Goal is to show multiple .stl-files in different divs on a webpage and get the model information per model (volume, area, xyz, etc.). Therefore I use https://www.viewstl.com/plugin/#params, which is based on three.js
I code the index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<main id="main"></main>
<script src="stl_viewer.min.js"></script>
<script src="tq_ini_stlviewer.js"></script>
</body>
</html>
The javascript code:
// Loop for 3 stl-files
for (var modelNo = 0; modelNo < 3; modelNo ) {
var orderPosition = document.createElement("div"); // Create div element
var createClass = "drag-area" modelNo; // Create class
orderPosition.classList.add(createClass); // Add class to element
var main = document.getElementById("main"); // Add element to DOM
main.appendChild(orderPosition);
var stlDatei = "./models/" modelNo ".stl"; // Create path
console.log("Model-No.: " modelNo);
console.log("STL-File: " stlDatei);
/* Create StlViewer object for each class and dedicate id and stl-file to it.
Wait for callback that file is loaded, then call function 'dimensions'*/
var stl_viewer = new StlViewer(document.querySelector("." createClass), {
models: [{ id: modelNo, filename: stlDatei }],
model_loaded_callback: dimensions,
});
}
function dimensions(modelNo) {
console.log("Dimensions for model: " modelNo);
var model_info = window.stl_viewer.get_model_info(modelNo);
var Volume = (model_info.volume / 1000).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
var BoundBox = (
(model_info.dims.x * model_info.dims.y * model_info.dims.z) /
1000
).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
var Area = (model_info.area / 1000).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
console.log(
"Model-ID: "
modelNo
"\n"
"Name: "
model_info.name
"\n"
"Volumen: "
Volume
" cm³\n"
"Bounding Box Volumen: "
BoundBox
" cm³\n"
"Oberfläche: "
Area
" cm²\n"
"Länge: "
model_info.dims.x.toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})
" mm\n"
"Breite: "
model_info.dims.y.toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})
" mm\n"
"Höhe: "
model_info.dims.z.toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})
" mm\n"
"Dreiecksfacetten: "
model_info.triangles.toLocaleString(undefined, {
minimumFractionDigits: 0,
maximumFractionDigits: 0,
})
);
}
Expected output in console
model information for stl-file 0, 1 and 2 like
- Model-ID: 0
- Name: ./models/0.stl
- Volumen: 23,76 cm³
- Bounding Box Volumen: 145,01 cm³
- etc.
Instead I get
- model information for stl-file 2 only and
- two error-messages for stl-file 0 and 1:
get_model_info - id not found: 0 "Uncaught TypeError: Cannot read properties of undefined (reading 'x') at StlViewer.dimensions [as model_loaded_callback]
get_model_info - id not found: 1 "Uncaught TypeError: Cannot read properties of undefined (reading 'x') at StlViewer.dimensions [as model_loaded_callback]
@trincot: this is the output of console.log(JSON.sstringify(model_info, null, 2))
:
{
"name": "./models/2.stl",
"orig_filename": null,
"position": {
"x": 0,
"y": 0,
"z": 0
},
"dims": {
"x": 102.5,
"y": 86,
"z": 16.450000762939453
},
"rotation": {
"x": 0,
"y": 0,
"z": 0
},
"display": "flat",
"color": null,
"scale": {
"x": 1,
"y": 1,
"z": 1
},
"volume": 23762.741633293106,
"area": 18429.489759870332,
"triangles": 6012,
"units": "mm",
"opacity": 1
}
It seems, that the model_loaded_callback
is an asynchrone process and the for-loop is not waiting.
How can I resolve the problem to get model information of all models?
Best regards Martin
CodePudding user response:
The problem is that you access stl_viewer
in the dimensions
callback, which by the time that function runs has already been overwritten by the last instance of StlViewer
. The references to the two previous instances have been lost.
There are several ways to avoid this loss of references. One is to store them in an array, using the model number as index.
Assuming that the dimensions
function gets the same modelNo value as argument as you have used in the loop, it should work like this:
var stl_viewer = []; // array to have access to ALL instances
for (var modelNo = 0; modelNo < 3; modelNo ) {
// ...etc...
// ADD to that array
stl_viewer.push(new StlViewer(document.querySelector("." createClass), {
models: [{ id: modelNo, filename: stlDatei }],
model_loaded_callback: dimensions,
}));
}
function dimensions(modelNo) {
console.log("Dimensions for model: " modelNo);
// Access the appropriate StlViewer instance:
var model_info = window.stl_viewer[modelNo].get_model_info(modelNo);
// ...etc...
}