Electron, new BrowserWindow load values - json

I try load and pass from a json file the x,y position and width, height. Here is my code
const electron = require('electron')
const {app, BrowserWindow} = electron
var fs = require('fs');
var loadsttngs = JSON.parse(fs.readFileSync('settings.json', 'utf8'));
console.log(loadsttngs.width);
let win
function createWindow () {
win = new BrowserWindow({
x: loadsttngs.x,
y: loadsttngs.y,
width: loadsttngs.width,
height: loadsttngs.height,
frame: false})
win.setMenu(null)
win.loadURL(`file://${__dirname}/index.html`)
win.webContents.openDevTools()
// Emitted when the window is closed.
win.on('closed', () => {
//var bounds = win.getBounds();
win = null
})
}
the console.log(loadsttngs.width); return the right value, so there is no problem with reading the file but in the new BrowserWindow does not be used(like using some defaults values). If I write the values directly to new BrowserWindow works fine.
settings.json
{
"x" : "50",
"y" : "50",
"width" : "1200",
"height" : "200",
"maximized": "false"
}

Your x and y values are strings not numbers.
Should be:
"x":50
Maximized is also a string not a Boolean.

Related

Revit shared coordinates to Forge viewer

What is the correct process for getting a transform between Forge coordinates and Revit's shared coordinates? I know there is globalOffset, but does it reference the Revit project internal coordinate system or shared coordinates?
Update Jun 11th, 2021
Now my MultipleModelUtil.js supports the alignments I shared below. Also, we can easily tell Forge Viewer to use By shared coordinates to aggregate models. Here is the code snippet, and you can check out here to know supported alignments
const util = new MultipleModelUtil( viewer );
util.options = {
alignment: MultipleModelAlignmentType.ShareCoordinates
};
const models = [
{ name: '1.rvt', urn: 'urn:dXJuOmFkc2sud2lwcHJvZDpmcy5maWxlOnZmLlNpaHgxOTVuUVJDMHIyWXZUSVRuZFE_dmVyc2lvbj0x' },
{ name: '2.rvt', urn: 'urn:dXJuOmFkc2sud2lwcHJvZDpmcy5maWxlOnZmLldVRHJ4ajZ6UTBPLTRrbWZrZ3ZoLUE_dmVyc2lvbj0x' },
{ name: '3.rvt', urn: 'urn:dXJuOmFkc2sud2lwcHJvZDpmcy5maWxlOnZmLjRyZW5HRTNUU25xNHhYaW5xdWtyaWc_dmVyc2lvbj0x' }
];
util.processModels( models );
==================
First, Forge Viewer supports 3 kinds of Revit link methods as the below, and you can take a look at the 3rd one (By shared coordinates).
Origin to origin: Apply the globalOffset of the 1st model to others. Check MultipleModelUtil/MultipleModelUtil.js for the demo
Center to center: the default way of the viewer.
By shared coordinates: set up applyRefpoint: true and make the globalOffset to the refPoint. This method is the one you are looking for.
The refPoint is the Revit survey point location inside Revit internal coordinate system. It's accessible with the AecModelData. Meanwhile, you can take advantage of the AggregatedView to use this aligning option. Here is an example of telling how to use AggregatedView:
https://gist.github.com/yiskang/c404af571ba4d631b5929c777503891e
If you want to use this logic with the Viewer class directly, here is a code snippet for you:
let globalOffset = null;
const aecModelData = bubbleNode.getAecModelData();
const tf = aecModelData && aecModelData.refPointTransformation; // Matrix4x3 as array[12]
const refPoint = tf ? { x: tf[9], y: tf[10], z: 0.0 } : { x: 0, y: 0, z: 0 };
// Check if the current globalOffset is sufficiently close to the refPoint to avoid inaccuracies.
const MaxDistSqr = 4.0e6;
const distSqr = globalOffset && THREE.Vector3.prototype.distanceToSquared.call(refPoint, globalOffset);
if (!globalOffset || distSqr > MaxDistSqr) {
globalOffset = new THREE.Vector3().copy(refPoint);
}
viewer.loadDocumentNode(doc, bubbleNode, { applyRefpoint: true, globalOffset: globalOffset, keepCurrentModels: true });
The bubbleNode can be either of the following:
bubbleNode = doc.getRoot().getDefaultGeometry()
//Or
const viewables = viewerDocument.getRoot().search({'type':'geometry'});
bubbleNode = viewables[0];
To get AecModelData, please refer to my gist: https://gist.github.com/yiskang/c404af571ba4d631b5929c777503891e#file-index-html-L67
// Call this line before using AecModelData
await doc.downloadAecModelData();
// doc.downloadAecModelData(() => resolve(doc));
See here for details of the AecModelData: https://forge.autodesk.com/blog/consume-aec-data-which-are-model-derivative-api
I've also found success feeding the refPointTransformation into a matrix4.
This way, the orientation of the model is also taken into account. (This is based off Eason's Answer).
const bubbleNode = doc.getRoot().getDefaultGeometry();
await doc.downloadAecModelData();
const aecModelData = bubbleNode.getAecModelData();
const tf = aecModelData && aecModelData.refPointTransformation;
const matrix4 = new THREE.Matrix4()
.makeBasis(
new THREE.Vector3(tf[0], tf[1], tf[2]),
new THREE.Vector3(tf[3], tf[4], tf[5]),
new THREE.Vector3(tf[6], tf[7], tf[8])
)
.setPosition(new THREE.Vector3(tf[9], tf[10], tf[11]))
viewer.loadDocumentNode(doc, viewables, {
placementTransform: matrix4,
keepCurrentModels: true,
globalOffset: {
"x": 0,
"y": 0,
"z": 0
},
applyRefpoint: true,
applyScaling: 'ft',
})

Start model browser in Forge viewer collapsed when loading several models

I have tried to start the model browser with all nodes collapsed when loading several aggregated models, but it do no collapse all nodes. Is there any way to do this?
Try the code below on these model: https://wallabyway.github.io/federatedmodels-v7/
var ext = NOP_VIEWER.getExtension('Autodesk.ModelStructure')
ext._modelstructure.options.startCollapsed = true
Try to use this one instead. The ModelStructralPanel will read options in its constructor only.
var viewer = new Autodesk.Viewing.GuiViewer3D(container, {startCollapsed: true});
var ext = viewer.getExtension('Autodesk.ModelStructure');
// or
// viewer.unloadExtension('Autodesk.ModelStructure');
// var ext = await viewer.loadExtension('Autodesk.ModelStructure', {startCollapsed: true});
Workaround:
Add this code snippet before opening the modelstructure panel.
var ext = viewer.getExtension('Autodesk.ModelStructure');
ext._modelstructure.addVisibilityListener( show => {
if( show && (!ext._modelstructure.uiCreated) ) {
ext._modelstructure.tree.delegates.forEach( d => ext._modelstructure.tree.setAllCollapsed( d, true ) )
}
});
When creating the viewer, pass the following option to it:
var viewer = new Autodesk.Viewing.GuiViewer3D(container, {modelBrowserStartCollapsed: true});
It should cascade until reaching the model browser.
Background
The option "modelBrowserStartCollapsed" is passed on from the Viewer3D constructor up until the ModelStructureExtension, where it changes name to "startCollapsed" as it is passed to the ViewerModelStructurePanel.
proto.restoreDefaultPanel = function () {
var config = this.viewer.config;
var options = {
docStructureConfig: config.docStructureConfig,
hideSearch: (0, _src_compat__WEBPACK_IMPORTED_MODULE_2__.isMobileDevice)(),
excludeRoot: config.modelBrowserExcludeRoot,
startCollapsed: config.modelBrowserStartCollapsed // HERE
};
var modelTitle = config.defaultModelStructureTitle || 'Browser';
var panelInstance = new _src_gui_ViewerModelStructurePanel__WEBPACK_IMPORTED_MODULE_1__.ViewerModelStructurePanel(_objectSpread(_objectSpread({},
options),
(0, _src_gui_ViewerModelStructurePanel__WEBPACK_IMPORTED_MODULE_1__.generateDefaultViewerHandlerOptions)(this.viewer)),
modelTitle);
this.setModelStructurePanel(panelInstance);
};
The source for ViewerModelStructurePanel shows that it takes the option "startCollapsed" as stated, among other options.
function ViewerModelStructurePanel(viewer, userTitle, ops) {
...
options.startCollapsed = options.startCollapsed !== undefined ? options.startCollapsed : false;

Forge Viewer: Properties Window

The Properties window does not populate any properties even though the 2D view has properties info for the selected room
Here is the function that loads the model. what am I missing?
function loadModel() {
var initialViewable = viewables[indexViewable];
var svfUrl = lmvDoc.getViewablePath(initialViewable);
var modelOptions = {
sharedPropertyDbPath: lmvDoc.getFullPath(lmvDoc.getRoot().findPropertyDbPath())
};
viewer.loadModel(svfUrl, modelOptions, onLoadModelSuccess, onLoadModelError);
}
One line missing in your code, please try the following instead:
var sharedDbPath = initialViewable.findPropertyDbPath();
sharedDbPath = lmvDoc.getFullPath( sharedDbPath );
var modelOptions = {
sharedPropertyDbPath: sharedDbPath
};
However, you should not need to specify the sharedPropertyDbPath manually now. You can take advantage of the Viewer3D#loadDocumentNode to load the model directly. It will automatically determine the path for you. (started from v7 viewer)
const initialViewable = viewables[0];
viewer.loadDocumentNode( lmvDoc, initialViewable, loadOptions )
.then( onLoadModelSuccess )
.catch( onLoadModelError );

How to change the color of sphere objects dynamically (used SceneBuilder in Autodesk forge)

I am working on the example from Custom models in Forge Viewer blog by Petr Broz. I am facing issue in updating the color of sphere objects dynamically. I am getting the value of sphere's color from a json file like this "color": "#FF0000". I have created 3 spheres and I am getting the color of first sphere for the rest also. Why the color is not updating for the other spheres? If the problem is on using same material then I tried giving the sphereMaterial in array also as shown below. Is that wrong or how can i update the color?
var spherecolor='';
var sphereMaterial = [];
const button = document.getElementById('button-geometry');
button.addEventListener('click', async function () {
const sceneBuilder = await viewer.loadExtension('Autodesk.Viewing.SceneBuilder');
const modelBuilder = await sceneBuilder.addNewModel({ conserveMemory: true, modelNameOverride: 'My Custom Model' });
for (var i = 0; i < numOfSphere;i++) {
addGeometry(modelBuilder, jsonGeomConfig.geom[i].dbId, i);
}
});
function addGeometry(modelBuilder, dbId, i) {
const sphereGeometry = new THREE.BufferGeometry().fromGeometry(new THREE.SphereGeometry(0.05, 8, 10));
//Getting spherecolor from json file
spherecolor = jsonGeomConfig.geom[i].color;
sphereMaterial[i] = new THREE.MeshPhongMaterial({ color: spherecolor });
const sphereTransform = new THREE.Matrix4().compose(
new THREE.Vector3(jsonGeomConfig.geom[i].Position.posX, jsonGeomConfig.geom[i].Position.posY, jsonGeomConfig.geom[i].Position.posZ),
new THREE.Quaternion(0, 0, 0, 1),
new THREE.Vector3(2,2,2)
);
modelBuilder.addMaterial('MyCustomMaterial', sphereMaterial[i]);
const sphereGeomId = modelBuilder.addGeometry(sphereGeometry);
const sphereFragId = modelBuilder.addFragment(sphereGeomId, 'MyCustomMaterial', sphereTransform);
modelBuilder.changeFragmentsDbId(sphereFragId, dbId);
}
Be sure to give the materials with different colors different names ... otherwise it'd get overridden - see this live environment:
modelBuilder.addMaterial('MyCustomMaterial'+i, sphereMaterial[i]);
const sphereGeomId = modelBuilder.addGeometry(sphereGeometry);
const sphereFragId = modelBuilder.addFragment(sphereGeomId, 'MyCustomMaterial'+i, sphereTransform);

HTML Canvas - Updating the canvas periodically

I have a canvas which I use to draw a plot periodically. I have a function that receives data periodically, and it parses the data and plots it on the canvas. For the plotting I use Chart.js.
But I am not able to update the plot periodically. I have confirmed that the data are received correctly and parsed, but the plot is not updating. It updates when I click the page, or if I minimize the browser and maximize it again. The plot would briefly appear and the next time update is called, the plot dissapears.
Here is my code. I am using Firefox.
function start ()
{
// create a new websocket and connect
window.ws = new wsImpl('ws://localhost:8181/consoleappsample', 'my-protocol');
// when data is comming from the server, this metod is called
ws.onmessage = function (evt)
{
ParseIncomingData(evt.data);
};
// when the connection is established, this method is called
ws.onopen = function ()
{
inc.innerHTML = 'Connected<br/>';
textPanel.style.background = "#00FF00";
};
// when the connection is closed, this method is called
ws.onclose = function ()
{
inc.innerHTML = 'Connection closed<br/>';
textPanel.style.background = "#FF0000";
}
var periodicFuncID = setInterval( function() { ws.send(1); }, 2000);
}
function ParseIncomingData(data)
{
var splitContents = data.split(',');
var inc = document.getElementById('incomming');
var xaxis = new Array();
var yaxis = new Array();
yaxis = splitContents;
var dataType = yaxis.shift();
var data;
for(var i=1; i<=yaxis.length; i++)
{
xaxis.push(i);
}
data =
{
labels : xaxis,
datasets : [
{
//fillColor : "rgba(135,206,250,0.5)",
fillColor : "rgba(0,0,0,0.4)",
strokeColor : "rgba(220,220,220,1)",
pointColor : "rgba(255,165,0,1)",
pointStrokeColor : "#585858 ",
data : yaxis
}
]
}
var canvas= document.getElementById('Plot');
var ctx = canvas.getContext("2d");
var myLine = new Chart(ctx).Line(data);
}
window.onload = start;
Most of the code is unrelated to my problem but I just wanted to know if there is something wrong in the way I handle.
Thank you.