|
@@ -23,6 +23,10 @@ function getString(view, position, length) {
|
|
|
return out;
|
|
|
}
|
|
|
|
|
|
+// For hashing during splitting, ASCII mode is used, where vectors are stored
|
|
|
+// as strings. From a binary STL, the vectors are stored as hex strings, and
|
|
|
+// from an ASCII STL, they are stored as directly extracted ASCII.
|
|
|
+
|
|
|
function getVector(view, position) {
|
|
|
if (ASCII_MODE) {
|
|
|
x = view.getUint32(position, true);
|
|
@@ -37,20 +41,28 @@ function getVector(view, position) {
|
|
|
return [x,y,z]; // x.toString()+","+y.toString()+","+z.toString(); //[x,y,z];
|
|
|
}
|
|
|
|
|
|
-function setVector(view, position, vector) {
|
|
|
+function parseVector(vector) {
|
|
|
if (typeof vector === "string") {
|
|
|
- if (vector.includes(":")) {
|
|
|
- data = vector.split(":");
|
|
|
- view.setUint32(position, parseInt(data[0],16), true);
|
|
|
- view.setUint32(position+4, parseInt(data[1],16), true);
|
|
|
- view.setUint32(position+8, parseInt(data[2],16), true);
|
|
|
- }
|
|
|
- else {
|
|
|
- data = vector.split(",");
|
|
|
- view.setFloat32(position, parseFloat(data[0]), true);
|
|
|
- view.setFloat32(position+4, parseFloat(data[1]), true);
|
|
|
- view.setFloat32(position+8, parseFloat(data[2]), true);
|
|
|
+ var data = vector.split(":");
|
|
|
+ var buf = new ArrayBuffer(4);
|
|
|
+ var view = new DataView(buf);
|
|
|
+ function parse(s) {
|
|
|
+ view.setUint32(0, parseInt(s,16));
|
|
|
+ return view.getFloat32(0);
|
|
|
}
|
|
|
+ return [parse(data[0]),parse(data[1]),parse(data[2])];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return vector;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function setVector(view, position, vector) {
|
|
|
+ if (typeof vector === "string") {
|
|
|
+ var data = vector.split(":");
|
|
|
+ view.setUint32(position, parseInt(data[0],16), true);
|
|
|
+ view.setUint32(position+4, parseInt(data[1],16), true);
|
|
|
+ view.setUint32(position+8, parseInt(data[2],16), true);
|
|
|
}
|
|
|
else {
|
|
|
view.setFloat32(position, vector[0], true);
|
|
@@ -60,12 +72,21 @@ function setVector(view, position, vector) {
|
|
|
}
|
|
|
|
|
|
function getVectorFromText(line, position) {
|
|
|
- data = line.substr(position).split(/[\s,]+/);
|
|
|
+ var data = line.substr(position).split(/[\s,]+/);
|
|
|
+
|
|
|
if (data.length < 3)
|
|
|
throw 'Invalid vector';
|
|
|
|
|
|
if (ASCII_MODE) {
|
|
|
- return data[0]+","+data[1]+","+data[2];
|
|
|
+ var buf = new ArrayBuffer(4);
|
|
|
+ var view = new DataView(buf);
|
|
|
+
|
|
|
+ function toHex32(number) {
|
|
|
+ view.setFloat32(0, parseFloat(number));
|
|
|
+ return view.getUint32(0).toString(16);
|
|
|
+ }
|
|
|
+
|
|
|
+ return toHex32(data[0])+":"+toHex32(data[1])+":"+toHex32(data[2]);
|
|
|
}
|
|
|
|
|
|
return [parseFloat(data[0]), parseFloat(data[1]), parseFloat(data[2])];
|
|
@@ -88,9 +109,8 @@ function getASCIISTL(text) {
|
|
|
for (var i = 0 ; i < lines.length ; i++ ) {
|
|
|
l = lines[i].trim().toLowerCase();
|
|
|
if (l == 'endfacet') {
|
|
|
- if (triangle.length != 3) {
|
|
|
+ if (triangle.length != 3)
|
|
|
throw 'invalid triangle';
|
|
|
- }
|
|
|
triangles.push([triangle[0],triangle[1],triangle[2],normal]);
|
|
|
triangle = [];
|
|
|
normal = [0,0,0];
|
|
@@ -171,13 +191,37 @@ function splitMesh(triangles) {
|
|
|
m.triangles.push(t);
|
|
|
}
|
|
|
|
|
|
- out = [];
|
|
|
-
|
|
|
for (var i = 0 ; i < meshes.length ; i++) {
|
|
|
- out.push(meshes[i].triangles);
|
|
|
+ var bounds = [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY,
|
|
|
+ Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY ];
|
|
|
+
|
|
|
+ for (var key in meshes[i].points) {
|
|
|
+ if (meshes[i].points.hasOwnProperty(key)) {
|
|
|
+ var v = parseVector(key);
|
|
|
+ for (var k=0; k<3; k++) {
|
|
|
+ bounds[k] = Math.min(bounds[k], v[k]);
|
|
|
+ bounds[3+k] = Math.max(bounds[3+k], v[k]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ meshes[i].bounds = bounds;
|
|
|
+ delete meshes[i].points;
|
|
|
}
|
|
|
|
|
|
- return out;
|
|
|
+ function compareByBounds(m,m) {
|
|
|
+ for (var i=0; i<6; i++) {
|
|
|
+ if (m.bounds[i] < m.bounds[i])
|
|
|
+ return -1;
|
|
|
+ else if (m.bounds[i] < m.bounds[i])
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ meshes.sort(compareByBounds);
|
|
|
+
|
|
|
+ return meshes;
|
|
|
}
|
|
|
|
|
|
function downloadBlob(name,blob) {
|
|
@@ -211,6 +255,11 @@ function downloadMesh(i) {
|
|
|
downloadBlob(baseFilename+i+".stl", new Blob([makeMeshByteArray(allSplitMeshes[i])], {type: "application/octet-stream"}));
|
|
|
}
|
|
|
|
|
|
+function describeBounds(bounds) {
|
|
|
+ return "("+bounds[0].toFixed(2)+", "+bounds[1].toFixed(2)+", "+bounds[2].toFixed(2)+") - ("+
|
|
|
+ bounds[3].toFixed(2)+", "+bounds[4].toFixed(2)+", "+bounds[5].toFixed(2)+")";
|
|
|
+}
|
|
|
+
|
|
|
function processSTL(data) {
|
|
|
length = data.byteLength;
|
|
|
view = new DataView(data);
|
|
@@ -240,20 +289,22 @@ function processSTL(data) {
|
|
|
}
|
|
|
else {
|
|
|
message(String(splitMeshes.length)+" meshes extracted");
|
|
|
- allSplitMeshes = splitMeshes;
|
|
|
+ allSplitMeshes = [];
|
|
|
+
|
|
|
for (var i=0; i<splitMeshes.length; i++) {
|
|
|
- message("<a href='#' onclick='downloadMesh("+i+");'>Download mesh part "+i+"</a>");
|
|
|
+ allSplitMeshes.push(splitMeshes[i].triangles);
|
|
|
+ message("<a href='#' onclick='downloadMesh("+i+");'>Download mesh part "+i+"</a> "+describeBounds(splitMeshes[i].bounds));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function handleFileSelect(evt) {
|
|
|
var e = document.getElementById('file');
|
|
|
- e.parentNode.removeChild(e);
|
|
|
+ e.disabled = true;
|
|
|
+ document.getElementById('console').innerHTML = '';
|
|
|
|
|
|
var f = evt.target.files[0];
|
|
|
|
|
|
- message( escape(f.name) );
|
|
|
message( String(f.size) + ' bytes');
|
|
|
|
|
|
var n = f.name.split(/[/\\]+/);
|
|
@@ -261,7 +312,14 @@ function handleFileSelect(evt) {
|
|
|
|
|
|
var reader = new FileReader();
|
|
|
reader.onload = function(event) {
|
|
|
- processSTL(event.target.result);
|
|
|
+ try {
|
|
|
+ processSTL(event.target.result);
|
|
|
+ }
|
|
|
+ catch(err) {
|
|
|
+ message( "Error: "+err);
|
|
|
+ }
|
|
|
+ var e = document.getElementById('file');
|
|
|
+ e.disabled = false;
|
|
|
}
|
|
|
reader.readAsArrayBuffer(f);
|
|
|
}
|