PixelCompare method issue - autodesk-forge

I have an issue with PixelCompare extension.
Here, i am loading it:
viewer1 = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer1'), { extensions: [ 'GoogleMapsLocator', 'Autodesk.AEC.Minimap3DExtension','Autodesk.AEC.LevelsExtension','Autodesk.DocumentBrowser','Autodesk.ToolbarExtension' ,'Autodesk.Viewing.PixelCompare'] });
Then im trying to use it :
viewer1.compareTwoModels(data[0],data[1]);
Data is an array containing the models.
I get a "viewer.compareTwoModels is not a function" error which means either there is a typo in the function name or it doesnt exist.
Without access to the extension repo, i cannot confirm this method indeed exists.
Im at loss as to what to do and will welcome any help.
EDIT:
This snippet loads the document in the viewer to display it.
Autodesk.Viewing.Document.load(`urn:${urns[index]}`, function(doc){
var viewables=doc.getRoot().getDefaultGeometry();
doc.downloadAecModelData();
viewer1.loadDocumentNode(doc, viewables, {
placementTransform: (new THREE.Matrix4()).setPosition({ x: increment, y: 0, z: 0 }),
keepCurrentModels: true,
globalOffset: { x: 0, y: 0, z: 0 }
}).then(i => {
if(urns.length > 1) {
$(viewer1.toolbar.container).find('#toolbarXLS').hide();
}
});
increment += parseInt(sessionStorage.getItem('padding1'));
});
Then, im using this to pixel compare it:
viewer1.loadModel('urn:dXJuOmFkc2sud2lwcHJvZDpmcy5maWxlOnZmLmwwLS10X0k5UkVhbnNWRXBuLXl5Zmc_dmVyc2lvbj0x', {}, (model1) => {
console.log('test load model :' + model1)
viewer1.loadModel('urn:dXJuOmFkc2sud2lwcHJvZDpmcy5maWxlOnZmLmxXX0dONUJNVDBxdDRuOGZmRWx4SkE_dmVyc2lvbj0x', {}, async (model2) => {
const pcExt = await viewer1.loadExtension('Autodesk.Viewing.PixelCompare');
pcExt.compareTwoModels(model1, model2);
console.log()
});
});
I get an instant "file extension unsupported" error, probably on the first argument the code does not reach console.log('test load model :' + model1).

The function compareTwoModels is part of the extension object, not the viewer - see PixelCompare extension
function launchViewer() {
var options = {
env: 'Local'
};
Autodesk.Viewing.Initializer(options, () => {
viewer = new Autodesk.Viewing.GuiViewer3D(
document.getElementById('forgeViewer'), {}
);
viewer.start();
// Load 2 sheets
viewer.loadModel('scissors1.pdf', {}, (model1) => {
viewer.loadModel('scissors2.pdf', {}, async (model2) => {
// Compare them
const pcExt = await viewer.loadExtension('Autodesk.Viewing.PixelCompare');
pcExt.compareTwoModels(model1, model2);
});
});
});
}

Related

onMount inside a function won't re-trigger when a reactive variable changes

I need to get google maps autocomplete suggestion when I type a word on input.
maps.svelte
function inputChange() {
onMount(() => {
loader
.load()
.then((google) => {
const map = new google.maps.Map(document.getElementById('map'), mapOptions);
const markerPickUp = new google.maps.Marker({
position: {
lat: 14.6012,
lng: 120.975
},
map: map
});
const displaySuggestions = function (predictions, status) {
if (status != google.maps.places.PlacesServiceStatus.OK || !predictions) {
predictionsArray = [];
return;
}
predictionsArray = predictions;
console.log(predictionsArray);
};
const service = new google.maps.places.AutocompleteService();
const sessionToken = new google.maps.places.AutocompleteSessionToken();
service.getPlacePredictions(
{ input: $bookDetails.dropOffLocation, sessionToken: sessionToken },
displaySuggestions
);
})
.catch((e) => {
console.log(e);
});
});
}
$: $bookDetails.dropOffLocation, inputChange();
I tried to log $bookDetails.dropOffLocation after inputChange() just to see if it's bind on the input and it is. Also, the code works well without the onMount() but it's giving me errors on my terminal. It says windows not defined and it has to do with google maps. I think it needs to load the dom first that's why it gives error. I'm using #googlemaps/js-api-loader.
onMount registers a callback that executes when the component is mounted. It is not intended to be called multiple times and only ever will invoke the callback once during the lifecycle of a component.
If you just want to make sure that the component is already mounted when executing some logic, you can set a flag and use that as a guard. E.g.
let mounted = false;
onMount(() => mounted = true);
$: {
$bookDetails.dropOffLocation;
if (mounted) inputChange();
}

Protractor cucumber html report is generating only after 2nd run?

When i try to run my code it is generating html report only after 2nd run.
In the first run it is generating the json file and then after the second run, by using the generated json file and creating the HTML report
Please tell me how to generate html report by running only once.
below is code i tried
hook.js
const {defineSupportCode} = require('cucumber');
defineSupportCode(function ({After}) {
After(function(scenario,done)
{
const world = this;
console.log('in after block')
if (scenario.result.status === 'failed') {
console.log('in after block inside')
browser.takeScreenshot().then(function (stream) {
let decodedImage = new Buffer(stream.replace(/^data:image\/(png|gif|jpeg);base64,/, ''), 'base64');
world.attach(decodedImage, 'image/png');
console.log('screenshot successful');
}).then(function () {
done();
});
}else {
done();
}
});
});
index.js
var reporter = require('cucumber-html-reporter');
var options = {
theme: 'bootstrap',
output: 'cucumber-report.html',
reportSuiteAsScenarios: true,
launchReport: true,
screenshotsDirectory: 'screenshots123',
takeScreenShotsOnlyForFailedSpecs: true,
//screenshotsSubfolder: 'images',
storeScreenshots: true,
};
reporter.generate(options);
Index.js
var reporter = require('cucumber-html-reporter');
var options = {
theme: 'bootstrap',
jsonFile: 'C:/Users/pc/ProtractorCucumber/htmlReport/cucumber_html_reporter/report.json',
// jsonFile: 'C:/Users/pc/ProtractorCucumber/htmlReport/cucumber_html_reporter/cucumber-report.json',
output: 'C:/Users/pc/ProtractorCucumber/htmlReport/cucumber_html_reporter/cucumber-report.html',
// output: 'report123.html',
reportSuiteAsScenarios: true,
launchReport: true,
screenshotsDirectory: 'screenshots123',
takeScreenShotsOnlyForFailedSpecs: true,
//screenshotsSubfolder: 'images',
storeScreenshots: true,
};
reporter.generate(options);
Cucumber-html-reporter will require the JSON file created by cucumber after the execution.
Please refer the following snippet which has exception handled before calling generate function of cucumber-html-report.
const Cucumber = require('cucumber');
import { browser } from 'protractor';
import * as fs from 'fs';
import { config } from '../config/config';
import { defineSupportCode } from "cucumber";
import * as reporter from 'cucumber-html-reporter';
import { mkdirp } from 'mkdirp';
defineSupportCode(function ({ registerHandler, registerListener, After, setDefaultTimeout }) {
setDefaultTimeout(10 * 1000);
let jsonReports = process.cwd() + "/reports/json";
let htmlReports = process.cwd() + "/reports/html";
let targetJson = jsonReports + "/cucumber_report.json";
//BeforeFeature
registerHandler('BeforeFeature', function (event, callback) {
browser.get(config.baseUrl);
callback();
});
After(function (scenario) {
let world = this;
if (scenario.isFailed()) {
return browser.takeScreenshot().then(function (screenShot) {
// screenShot is a base-64 encoded PNG
world.attach(screenShot, 'image/png');
});
}
})
let cucumberReporterOptions = {
theme: "bootstrap",
//theme: "foundation",
// theme: "simple",
jsonFile: targetJson,
output: htmlReports + "/cucumber_reporter.html",
reportSuiteAsScenarios: true,
launchReport: false
};
let logFn = string => {
if (!fs.existsSync(jsonReports)) {
mkdirp.sync(jsonReports);
}
try {
fs.writeFileSync(targetJson, string);
reporter.generate(cucumberReporterOptions); // invoke cucumber-html-reporter
} catch (err) {
if (err) {
console.log(`Failed to save cucumber test results to json file.
Failed to create html report.
`);
console.log(err);
}
}
};
let jsonformatter = new Cucumber.JsonFormatter({
log: logFn
});
registerListener(jsonformatter);
})

File extension not supported:null ErrorCode:13. when loading multiple models

I'm trying to load 2 models into Autodesk's Forge Viewer.
I'm trying with the following code:
const urn1 = <urn>
const urn2 = <urn>
Autodesk.Viewing.Initializer(
options,
() => {
const viewerDiv = document.getElementById('MyViewerDiv');
viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv);
this.loadDoc(this.props.urns[1], true);
window.setTimeout(e => {
this.loadDoc(this.props.urns[2], false);
}, 4000);
},
);
loadDoc(urn: string, initializeAndLoad: boolean) {
Autodesk.Viewing.Document.load(urn,
(doc) => {
const viewables = Autodesk.Viewing.Document
.getSubItemsWithProperties(doc.getRootItem(), {'type': 'geometry'}, true);
if (viewables.length === 0) {
return;
}
const initialViewable = viewables[0];
const svfUrl = doc.getViewablePath(initialViewable);
const modelOptions = {
globalOffset: {x: 0, y: 0, z: 0}, // to align the models
sharedPropertyDbPath: doc.getPropertyDbPath(),
};
if (initializeAndLoad) {
viewer.start(svfUrl, modelOptions,
() => {},
() => {console.log('load model error');},
);
} else {
viewer.loadModel(urn, modelOptions,
() => {},
(e) => {
console.warn(e);
});
}
},
() => {}
);
}
The rationale behind the timeout is to load the second model using loadModel after the first model has loaded. I've also tried loading the second model from the viewer.start's onSuccess callback.
No matter what, I get the File extension not supported:null ErrorCode:13. error message (both in the console and in a popup)
I'm pretty sure the message is misleading since both urns have valid SVF derivatives (I can switch between them, whichever one is loaded first displays just fine)
NB I'm using the following version:
'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.2/viewer3D.min.js'
As a side note, I've tried using Autodesk.Viewing.ViewingApplication and selectItem. With this I'm able to load multiple models but I don't seem to be able to set modelOptions (specifically globalOffset) with this approach.
The loadModel method expects a URL with some known file extension (e.g., .svf) but you're calling it with an URN (the base64-encoded identifier of a translated document). That's why it's failing to find the file extension.
Btw. if you want to postpone the loading of the second model after the first one is loaded completely, consider using the geometry-loaded-event instead of a timeout.

object keys are undefined in if conditional, but inside the if statement I can access it

As the title states, I have a variable which is a javascript object, i'm comparing it with another js object by stringifying them. The problem is that the variable is completely accessible without calling the keys, so these
if(JSON.stringify(response) == JSON.stringify(lastcmd))
if(JSON.stringify(response.id) == JSON.stringify(lastcmd))
work perfectly fine, but accessing lastcmd's id key will cause it to throw undefined.
if(JSON.stringify(response) == JSON.stringify(lastcmd.id))
full code link here
Edit: Here's the JSON
{ "id" : "001", "app": "msgbox", "contents": { "title": "Newpaste", "message": "I'm a edited paste!" } }
Edit2: Here's the code on the post
const { BrowserWindow, app, dialog, ClientRequest } = require("electron");
const axios = require("axios");
const url = require("url");
let win = null;
let lastcmd;
function grabCurrentInstructions(fetchurl) {
return axios
.get(fetchurl)
.then(response => {
// handle success
//console.log(response.data);
return response.data;
})
.catch(function(error) {
// handle error
console.log(error);
});
}
function boot() {
//console.log(process.type);
win = new BrowserWindow({
resizable: true,
show: false,
frame: false
});
win.loadURL(`file://${__dirname}/index.html`);
//Loop everything in here every 10 seconds
var requestLoop = setInterval(getLoop, 4000);
function getLoop() {
grabCurrentInstructions("https://pastebin.com/raw/i9cYsAt1").then(
response => {
//console.log(typeof lastcmd);
//console.log(typeof response);
if (JSON.stringify(response.app) == JSON.stringify(lastcmd.app)) {
console.log(lastcmd.app);
clearInterval(requestLoop);
requestLoop = setInterval(getLoop, 4000);
} else {
lastcmd = response;
switch (response.app) {
case "msgbox":
dialog.showMessageBox(response.contents);
//console.log(lastcmd);
clearInterval(requestLoop);
requestLoop = setInterval(getLoop, 1000);
}
}
}
);
}
}
app.on("ready", boot);
And here's the error:
(node:7036) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'id' of undefined
at grabCurrentInstructions.then.response (C:\Users\The Meme Machine\Desktop\nodejsprojects\electronrat\index.js:42:64)
at process._tickCallback (internal/process/next_tick.js:68:7)
Thanks to user str I saw that my lastcmd was undefined when I ran the comparison the first time, this would break it and thereby loop the same error over and over, by addding
grabCurrentInstructions("https://pastebin.com/raw/i9cYsAt1").then(
response => {
lastcmd = response;
}
);
below this line
win.loadURL(`file://${__dirname}/index.html`);
I made sure that the last command sent while the app was offline wouldn't be executed on launch and fixing my problem at the same time!

Chrome.storage.sync.get() seems to be duplicating keys?

I am saving some settings using the following sequence
var getSettings = async function() {
var settings;
try {
settings = await authenticatedGET(server_url + SETTINGS_ENDPOINT);
return settings;
} catch (error) {
console.log("Settings Fetch Failed: " + error);
throw new Error(error);
}
}
const setLocalSettings = function(settings) {
chrome.storage.sync.set({ 'LML_Settings': JSON.parse(settings) }, function() {
console.log("Settings saved locally");
});
}
At the line right after the setLocalSettings function definition, the 'settings' object logs out as
{"email_format":"individual","close_tab":true,"frequency":"DAILY"} (correctly as intended). When I go to fetch the settings using this sequence:
chrome.storage.sync.get('LML_Settings', function(LMLSettingsContainer) {
console.log(LMLSettingsContainer);
if (LMLSettingsContainer.LML_settings.close_tab == "true") {
closeCurrentTab();
}
})
LMLSettingsContainer logs out as
{
"LML_Settings": {
"close_tab": true,
"email_format": "individual",
"frequency": "DAILY"
}
}
accessing my settings with LMLSettingsContainer.LML_Settings["<setting>"] is a bit annoying (and its the whole reason I named the top variable LMLSettingsContainer).
Does anyone know if there's a way to have chrome save/get these values unwrapped?
chrome.storage.sync.get('LML_Settings', ({LML_settings}) => { ... }) works, per #wOxxOm