Vtk.js: Import multi STLs - javascript

I'm using Vtk.js to display 3D content on a web interface.
My problem happens when I try to load multiple models (STL format).
I'm using this logic:
PS: files is an array of attributes of my STLs, the 'url' attribute is the path of the STL
const fullScreenRenderer = vtk.Rendering.Misc.vtkFullScreenRenderWindow.newInstance();
for (var i = files.length - 1; i >= 0; i--)
{
var mapper = vtk.Rendering.Core.vtkMapper.newInstance({ scalarVisibility: false });
var actor = vtk.Rendering.Core.vtkActor.newInstance();
var reader = vtk.IO.Geometry.vtkSTLReader.newInstance();
actor.setMapper(mapper);
mapper.setInputConnection(reader.getOutputPort());
actor.getProperty().setColor( files[i].color );
actor.getProperty().setOpacity( files[i].opacity );
fullScreenRenderer.getRenderer().addActor(actor);
reader.setUrl( files[i].url , { binary: true }).then( update) ;
}
function update()
{
fullScreenRenderer.getRenderer().resetCamera();
fullScreenRenderer.getRenderer().setLayer(1);
fullScreenRenderer.getRenderWindow().render();
}
The problem is that every 3D model is black. If I remove the setLayer(1), the whole screen is black.
I think this happend because I'm not using the correct "pipeline". But I don't have that much experience with this library to know, the doc is still not complete, it is not helping.

This works for me (but I don't understand why at all...)
const fullScreenRenderer = vtk.Rendering.Misc.vtkFullScreenRenderWindow.newInstance();
var actors = [];
for (var i = files.length - 1; i >= 0; i--)
{
var mapper = vtk.Rendering.Core.vtkMapper.newInstance({ scalarVisibility: false });
actors[i] = vtk.Rendering.Core.vtkActor.newInstance();
var reader = vtk.IO.Geometry.vtkSTLReader.newInstance();
actors[i].setMapper(mapper);
mapper.setInputConnection(reader.getOutputPort());
actors[i].getProperty().setColor( files[i].color );
actors[i].getProperty().setOpacity( files[i].opacity );
fullScreenRenderer.getRenderer().addActor(actor);
reader.setUrl( files[i].url , { binary: true }).then( update(i) ) ;
}
function update(i)
{
actors[i].getProperty().setColor( files[i].color );
fullScreenRenderer.getRenderer().resetCamera();
fullScreenRenderer.getRenderWindow().render();
}

Related

Uncaught TypeError: Cannot read property 'dispatchEvent' of null

I am getting the above error when I run my function. The goal is when a user enters a number in a search box it should zoom to that number in the visualization. Below is my code -
function zoom1() {
var input1 = document.getElementById("myInput1").value; //value from searchbox
console.log("input from searchbox :"+input1);
d3.json("intervals.json", function(alldata) // entering json file to look for oid
{
// console.log("all data from json"+alldata);
var i=0;
for (i = 0; i < alldata.records.length; i++) //for loop for getting the "oid" alldata.records.length;
{
conceptid1 = alldata.records[i].eag; //saving all the oid in conceptid
console.log("conceptid1: "+conceptid1);
var conceptid2 = conceptid1.toString();
console.log("conceptid2: "+conceptid2);
if (conceptid2 === input1) //if the user input1 matches conceptid2
{
console.log("inside if conceptid2:"+conceptid2);
console.log(document.getElementById(conceptid2).dispatchEvent(new Event('click'))); // zoom
}
}
});
}
Can you share the console log for conceptid2?
By the way, use ES6 syntax. It's a newer and better way to write JS. Here is your code written in ES6:
const zoom = () => {
let value = document.querySelector("#myInput1").value;
console.log(`Input ${value}`);
d3.json("intervals.json", (alldata) => {
const { records } = alldata;
for (let i = 0; i < records.length; ++i) {
const conceptId = records[i].eag.toString();
console.log(`Concept ID: ${conceptId}`);
if (conceptId === value) {
// Your stuff
}
}
});
}
Anyways didn't want to come on too hard but I hope this helps :)

Can I reduce this javascript? (multiple image arrays and click Event Listeners)

https://jsfiddle.net/mr_antlers/ryLtwcbe/
I have put this together. I simple image swap on click. I've repeated the same block of code for each face element I want to swap. So this block repeats for eyes, then nose, mouth etc...
//eyes
var img_eyes = []
img_eyes[0] = "http://guildofone.com/makeneki-neko/img/SVG/eyes0.svg";
img_eyes[1] = "http://guildofone.com/makeneki-neko/img/SVG/eyes1.svg";
img_eyes[2] = "http://guildofone.com/makeneki-neko/img/SVG/eyes2.svg";
//Select all elements on the page with the name attribute equal to VCRImage
var eyes = document.querySelectorAll('[name=eyes]');
for(var i=0; i < eyes.length; i++)
{
var eyes = eyes[i];
eyes.addEventListener('click', eyesClicked(), false);
}
function eyesClicked()
{
var counter = 0;
return function(event)
{
counter++;
this.src = img_eyes[counter % img_eyes.length];
}
}
I'd like to cut down the repetition in the arrays and the click listeners...
Ideally I'd also like a button to toggle each face attribute.I haven't got to this yet. A random button would be nice too. Any help on these would be appreciated.
Many thanks in advance for guidance on improving this code.
Just combine all the similar logic into a function and the parts that differ pass in as parameters. In my example, I am passing in the images and the elements to bind an event too - the rest of the implementation within the functions are the same.
window.onload = function() {
//eyes
var img_eyes = []
img_eyes[0] = "http://guildofone.com/makeneki-neko/img/SVG/eyes0.svg";
img_eyes[1] = "http://guildofone.com/makeneki-neko/img/SVG/eyes1.svg";
img_eyes[2] = "http://guildofone.com/makeneki-neko/img/SVG/eyes2.svg";
//face
var img_face = []
img_face[0] = "http://guildofone.com/makeneki-neko/img/SVG/face0.svg";
img_face[1] = "http://guildofone.com/makeneki-neko/img/SVG/face1.svg";
img_face[2] = "http://guildofone.com/makeneki-neko/img/SVG/face2.svg";
//build the rest of the images
//add the features
addFeature( document.querySelectorAll( "[name=eyes]" ), img_eyes )
addFeature( document.querySelectorAll( "[name=face]" ), img_face )
}
function addFeature( features, imgs ) {
//add the feature
for( var i=0; i < features.length; i++ ) {
var feature = features[i];
feature.addEventListener( "click", featureClicked(), false )
}
function featureClicked() {
let counter = 0;
return function( event ) {
counter++;
this.src = imgs[counter % imgs.length];
}
}
}
A couple of opportunities:
Define features as a list
Populate list of feature values dynamically with new Array(3).fill().map()
Add a listener on the containing element of the image instead of the image itself
Maintain the state of the current index on the DOM element using a data attribute (e.g. data-index)
const features = [
{
element: document.querySelector('.eyes'),
values: new Array(3).fill().map((value, index) => `http://guildofone.com/makeneki-neko/img/SVG/eyes${index}.svg`),
},
{
element: document.querySelector('.noses'),
values: new Array(3).fill().map((value, index) => `http://guildofone.com/makeneki-neko/img/SVG/nose${index}.svg`),
}
];
function initialize() {
features.forEach(feature => {
feature.element.addEventListener('click', () => {
const current = parseInt(feature.element.getAttribute('data-index'), 10);
const nextIndex = (current + 1) % feature.values.length;
feature.element.setAttribute('data-index', nextIndex);
updateFeature(feature);
});
updateFeature(feature);
});
}
function updateFeature(feature) {
const index = feature.element.getAttribute('data-index');
const img = feature.element.querySelector('img');
img.src = feature.values[index];
}
initialize();
<div class="eyes" data-index="0">
<img />
</div>
<div class="noses" data-index="0">
<img />
</div>

Looping through layers and setting them to visible

I'm trying to loop through the layers in an InDesign doc and set all of them to visible. This is to ensure that file collection occurs correctly.
I put together the following
var myDocument = app.activeDocument;
//make all layers visable
for (i = 0; i < myDocument.layers.length; i++) {
if(myDocument.layers[i].visible = false) {
myDocument.layers[i].visible = true;
};
};
This is excerpted from a larger script that automates the file collect, this is just the routine for the layers.
For context here's the actual script.
function Left(str, n){
if (n <= 0)
return "";
else if (n > String(str).length)
return str;
else
return String(str).substring(0,n);
}
function Right(str, n){
if (n <= 0)
return "";
else if (n > String(str).length)
return str;
else {
var iLen = String(str).length;
return String(str).substring(iLen, iLen - n);
}
}
if (app.documents.length != 0){
var myDocument = app.activeDocument;
var docName = myDocument.name;
var docName = Left(docName, String(docName).length-5)
//alert(docName);
var myFolder = new Folder ("~/Desktop/"+docName+"/");
//myFolder.create("Bob");s
/*new Folder ("~/Desktop/Collected/Hi-Res PDF/");
new Folder ("~/Desktop/Collected/RELEASE INFO/");*/
//make all layers visable
for (i = 0; i < myDocument.layers.length; i++) {
if(myDocument.layers[i].visible = false) {
myDocument.layers[i].visible = true;
};
};
myDocument.packageForPrint (myFolder,1,1,0,1,0,0,0);
var newFolder = new Folder ("~/Desktop/"+docName+"/RELEASE INFO/");
newFolder.create();
var inddFolder = new Folder ("~/Desktop/"+docName+"/Indesign Files/");
inddFolder.create();
var newFolder = new Folder ("~/Desktop/"+docName+"/IDML Files/");
newFolder.create();
//Export IMDL File
myDocument.exportFile(ExportFormat.INDESIGN_MARKUP, File("~/Desktop/"+docName+"/IDML Files/"+docName+".idml"), false);
//Move INDD File
//var myInddfile = File("~/Desktop/"+docName+"/"+docName+".indd");
//myDocument.changePath(File(inddFolder),false);
//Rip Low Res PDFs
var myPDFExportPreset = app.pdfExportPresets.item("CP3 Low Rez");
app.activeDocument.exportFile(ExportFormat.pdfType,
File("~/Desktop/"+docName+"/RELEASE INFO/"+docName+"_LR.pdf"), false, myPDFExportPreset);
//Now export the document. You'll have to fill in your own file path.
//app.activeDocument.exportFile(ExportFormat.pdfType, File("~/Desktop/"+docName+"_FILM/RELEASE INFO/"+docName+"_LR.pdf"), false);
var newFolder = new Folder ("~/Desktop/"+docName+"/Hi-Res PDF/");
newFolder.create();
//Rip Hi-Res PDF
var myPDFExportPreset = app.pdfExportPresets.item("Kern Hi Rez Print");
app.activeDocument.exportFile(ExportFormat.pdfType,
File("~/Desktop/"+docName+"/Hi-Res PDF/"+docName+"_HiRes.pdf"), false, myPDFExportPreset);
//Now export the document. You'll have to fill in your own file path.
//app.activeDocument.exportFile(ExportFormat.pdfType, File("~/Desktop/"+docName+"_FILM/Hi-Res PDF/"+docName+"_HiRes.pdf"), false);
myFolder.execute();
}
else{
alert("Please open a document and try again.");
}
Hopefully, when the script executes, all the layers will be set to visible then the file collect will occur.
Use triple equals in your if statement for strict equality. For instance:
for (i = 0; i < myDocument.layers.length; i++) {
if(myDocument.layers[i].visible === false) { // <-- Note the `===` instead of `=`
myDocument.layers[i].visible = true;
};
};
Or even better, you can change it to utilize the Logical NOT ! operator
for (i = 0; i < myDocument.layers.length; i++) {
if (!myDocument.layers[i].visible) { // <-- Change to this.
myDocument.layers[i].visible = true;
};
};
Note: Given your example, the conditional if statement is not actually necessary. You could simply do this instead:
for (i = 0; i < myDocument.layers.length; i++) {
myDocument.layers[i].visible = true;
};
Set everything to be visible
If you actually want to make everything visible - including; InDesign document layers and all page items on the sub-layer(s), then you'll need to do something like this example:
var myDocument = app.activeDocument;
// ...
function makeAllVisible() {
for (i = 0, max = myDocument.layers.length; i < max; i++) {
var currentLayer = myDocument.layers[i];
currentLayer.visible = true; // Make the top level layer visible.
// Make all sub layers visible,
// i.e. make all page items on the current layer visible.
var currentLayerPageItems = currentLayer.allPageItems;
for (x = 0, len = currentLayerPageItems.length; x < len; x++) {
currentLayerPageItems[x].visible = true
}
}
}
makeAllVisible(); // Invoke the function.
// ...

Javascript array results returning undefined

I have been working on a simple math game and am having problems getting the overall answer results to return after the end of the game.
Here is what my return function looks like
function pShowResults() {
var pNumResults = document.getElementById("results");
for (var i = 0; i <= 10; i++) {
pNumStore.push(pNumGuess[i]);
var pNumTable = document.createElement("div");
pNumTable.innerHTML = (pNumGuess[i]);
pNumResults.appendChild(pNumTable);
}
}
Here is the full script
Pretty much need debugging help. I new to this so I'm guessing there is a ton that's off, but as long as I can get the results fed back I should be fine.
You are not passing the value of x in many placess
$(document).ready(function () {
//declare arrays and variables for use below
var pNum1 = [];
var pNum2 = [];
var pNumAns = [];
var pNumGuess = [];
var pNumStore = [];
var pNumCarry = 0;
var pNumTrack = 0;
var pNumMessageRight = ['Awesome Job!', 'Correct!', 'Great Job!'];
var pNumMessageWrong = ['Oh No! That Was Wrong!', 'Incorrect!', 'That\'s Wrong'];
$(".Play").click(function () {
$("#popup").attr("class", "on");
pNumTrack = 0;
pNumGen(pNumTrack);
});
$(".pNumSubmit").click(function () {
pNumCalc(pNumTrack-1);
});
$(".pNumNext").click(function () {
pNumGen(pNumTrack);
});
function pNumGen(x) {
pNum1[x] = (Math.round(Math.random() * 51));
pNum2[x] = (Math.round(Math.random() * 51));
pNumAns[x] = pNum1[x] + pNum2[x];
$(".pNum1").html(pNum1[x]);
$(".pNum2").html(pNum2[x]);
$(".pNumGuess").val("");
$(".pNum1").html(pNumTrack[x]);
if (pNumTrack == 2) {
$(".pNumNext").html("");
$(".pNumSubmit").html("Close");
pShowResults();
}
pNumTrack++;
}
function pNumCalc(x) {
pNumGuess[x] = $(".pNumGuess").val();
if (pNumGuess[x] == pNumAns[x]) {
$(".message").html(pNumMessageRight[Math.floor(Math.random() * pNumMessageRight.length)]);
$(".pNumNext").html("Next Question >")
} else {
$(".message").html(pNumMessageWrong[Math.floor(Math.random() * pNumMessageWrong.length)]);
$(".pNumNext").html("Maybe The Next Question >")
}
}
function pShowResults() {
var pNumResults = document.getElementById("results");
for (var i = 0; i < pNumGuess.length; i++) {
pNumStore.push(pNumGuess[i]);
var pNumTable = document.createElement("div");
pNumTable.innerHTML = (pNumGuess[i]);
pNumResults.appendChild(pNumTable);
}
}
});
Demo: Fiddle
There is a function called pNumCalc in your code which you have set to take in an argument, but you never pass one in. You use the argument to store the results in the pNumGuess array, but since the argument is never passed in, the guesses are never stored, and you end up with undefined as the answers the user gave.
Updated fiddle: http://jsfiddle.net/dwdX9/2/. Not sure how close this is to what you actually want though, but hopefully it gets you on the right track.
Because StackOverflow wants code to to be included when JSFiddle is...:
pNumCalc(pNumTrack)
You forget to define array before use it.
function pShowResults() {
var pNumStore = new Array();
var pNumResults = document.getElementById("results");
for (var i = 0; i <= 10; i++) {
pNumStore.push(pNumGuess[i]);
var pNumTable = document.createElement("div");
pNumTable.innerHTML = (pNumGuess[i]);
pNumResults.appendChild(pNumTable);
}
}
I must suggest you should use jquery instead.
After visiting your Fiddle seems like there are many problems with the code. and also your question is unclear.
for e.g.
$(".pNumSubmit").click(function () {
//why x value not passed?
pNumCalc();
});
function pNumCalc(x) {
pNumGuess[x] = $(".pNumGuess").val();
if (pNumGuess[x] == pNumAns[x]) {
$(".message").html(pNumMessageRight[Math.floor(Math.random() * pNumMessageRight.length)]);
$(".pNumNext").html("Next Question >")
} else {
$(".message").html(pNumMessageWrong[Math.floor(Math.random() * pNumMessageWrong.length)]);
$(".pNumNext").html("Maybe The Next Question >")
}
}
Please clear which array is returning undefined so that others can help you.

alert(line) alerts 'ac' and typeof(line) is 'string', but charAt is not a function

alert(line) alerts 'ac'
typeof(line) is 'string'
When I run line.charAt(0), charAt is not a function.
When line is 'http://www.google.com/', it works,
I think it's the UTF-8 encoding of the file that I opened...
How to make charAt work with UTF-8?
UPDATED:
http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/src/effective_tld_names.dat?raw=1 is in my extension's chrome folder as effective_tld_names.dat
To run the code:
authority = 'orkut.com.br';
lines = sc_geteffectivetldnames();
lines = sc_preparetouse(lines);
domainname = sc_extractdomainname(authority, lines);
The code:
function sc_geteffectivetldnames () {
var MY_ID = "my#email.com";
var em = Components.classes["#mozilla.org/extensions/manager;1"].
getService(Components.interfaces.nsIExtensionManager);
var file = em.getInstallLocation(MY_ID).getItemFile(MY_ID, "chrome/effective_tld_names.dat");
var istream = Components.classes["#mozilla.org/network/file-input-stream;1"].
createInstance(Components.interfaces.nsIFileInputStream);
istream.init(file, 0x01, 0444, 0);
istream.QueryInterface(Components.interfaces.nsILineInputStream);
var line = {}, lines = [], hasmore;
do {
hasmore = istream.readLine(line);
lines.push(line.value);
} while(hasmore);
istream.close();
return lines;
}
function sc_preparetouse(lines) {
lines = sc_notcomment(lines);
lines = sc_notempty(lines);
return lines;
}
function sc_notcomment(lines) {
var line;
var commentre;
var matchedcomment;
var replacedlines;
replacedlines = new Array();
var i = 0;
while (i < lines.length) {
line = lines[i];
commentre = new RegExp("^//", 'i');
matchedcomment = line.match(commentre);
if(matchedcomment) {
lines.splice(i, 1);
} else {
i++;
}
}
return lines;
}
function sc_notempty(lines) {
var line;
var emptyre;
var matchedempty;
var replacedlines;
replacedlines = new Array();
var i = 0;
while (i < lines.length) {
line = lines[i];
emptyre = new RegExp("^$", 'i');
matchedempty = line.match(emptyre);
if(matchedempty) {
lines.splice(i, 1);
} else {
i++;
}
}
return lines;
}
function sc_extractdomainname(authority, lines) {
for (var i = 0; i < lines.length; i++) {
line = lines[i];
alert(line);
alert(typeof(line));
if (line.chatAt(0) == '*') {
alert('test1');
continue;
}
if (line.chatAt(0) == '!') {
alert('test2');
line.chatAt(0) = '';
}
alert('test3');
checkline = sc_checknotasteriskline(authority, line);
if (checkline) {
domainname = checkline;
}
}
if (!domainname) {
for (var i = 0; i < lines.length; i++) {
line = lines[i];
alert(line);
if (line.chatAt(0) != '*') {
alert('test4');
continue;
}
if (line.chatAt(0) == '!') {
alert('test5');
line.chatAt(0) = '';
}
alert('test6');
checkline = sc_checkasteriskline(authority, line);
if (checkline) {
domainname = checkline;
}
}
}
return domainname;
}
It alerts 'ac', then 'string', then nothing.
UPDATED:
I'm thinking there is a difference between files opened with nsIExtensionManager and NSIIOService, because that real code doesn't work, but this test code works:
function makeURI(aURL, aOriginCharset, aBaseURI) {
var ioService = Components.classes["#mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
return ioService.newURI(aURL, aOriginCharset, aBaseURI);
}
URL = makeURI('file://C:/test/TLDs.dat');
// URL is a nsIURI; see nsIIOService::newURI for getting a string into a nsIURI.
var file = URL.QueryInterface(Components.interfaces.nsIFileURL).file;
// file is now a nsIFile
// open an input stream from file
var istream = Components.classes["#mozilla.org/network/file-input-stream;1"].
createInstance(Components.interfaces.nsIFileInputStream);
istream.init(file, 0x01, 0444, 0);
istream.QueryInterface(Components.interfaces.nsILineInputStream);
// read lines into array
var line = {}, lines = [], hasmore;
do {
hasmore = istream.readLine(line);
lines.push(line.value);
} while(hasmore);
istream.close();
// do something with read data
lines[0].charAt(0);
It's hard to tell what's going on without seeing any code, but remember that not all properties that evaluate as strings are really strings. A good example of this is the location object. Use of the object on its own will give you a string value, but you can't use any methods that are available to native strings on that string value.
// Although `window.location` returns a string, you cannot use String methods on it
alert(window.location.charAt(0)); // error
alert(window.location.href.charAt(0)); // no error
The same could be true of strings provided by external interfaces, such as plugins or ActiveX controls. The solution to this problem is to cast to a native string:
alert((""+window.location).charAt(0)); // auto casting with concatenation
alert(String(window.location).charAt(0)); // with the String() constructor
alert(window.location.toString().charAt(0)); // with toString()
At least the first two of those methods should solve your problem (replace window.location with your var). If not, try posting some code so we can get a better idea of what's happening.
Looking at your code, I can only assume that what I said above is correct. The readLine method returns a line object that contains the non-native string property value (which is rather odd, considering). I would suggest editing your code to look like this:
function sc_geteffectivetldnames () {
var MY_ID = "my#email.com";
var em = Components.classes["#mozilla.org/extensions/manager;1"].
getService(Components.interfaces.nsIExtensionManager);
var file = em.getInstallLocation(MY_ID).getItemFile(MY_ID, "chrome/effective_tld_names.dat");
var istream = Components.classes["#mozilla.org/network/file-input-stream;1"].
createInstance(Components.interfaces.nsIFileInputStream);
istream.init(file, 0x01, 0444, 0);
istream.QueryInterface(Components.interfaces.nsILineInputStream);
var line = {}, lines = [], hasmore;
do {
hasmore = istream.readLine(line);
lines.push(String(line.value)); // <--- or ""+line.value
} while(hasmore);
istream.close();
return lines;
}
I found URI Parsing for Firefox in MDC.
https://developer.mozilla.org/en/Code_snippets/URI_parsing
Somehow, it's not appearing on Google.

Categories