arpruss 8 anni fa
parent
commit
a549eee2e1
1 ha cambiato i file con 272 aggiunte e 0 eliminazioni
  1. 272 0
      split.html

+ 272 - 0
split.html

@@ -0,0 +1,272 @@
+<html>
+<body>
+<input type="file" id="file" name="file" />
+<ul id="console">
+</ul>
+
+
+<script>
+
+var TRIANGLE_SIZE = (3+3*3)*4+2;
+var ASCII_MODE = true;
+var allSplitMeshes = [];
+var baseFilaname = "";
+
+function getString(view, position, length) {
+    var out = "";
+    
+    for (var i=0; i<length; i++) {
+        var b = view.getUint8(position + i);
+        out += String.fromCharCode(b);
+    }
+    
+    return out;
+}
+
+function getVector(view, position) {
+    if (ASCII_MODE) {
+        x = view.getUint32(position, true);
+        y = view.getUint32(position+4, true);
+        z = view.getUint32(position+8, true);
+        return x.toString(16)+":"+y.toString(16)+":"+z.toString(16);
+    }
+
+    x = view.getFloat32(position, true);
+    y = view.getFloat32(position+4, true);
+    z = view.getFloat32(position+8, true);
+    return [x,y,z]; // x.toString()+","+y.toString()+","+z.toString(); //[x,y,z];
+}
+
+function setVector(view, position, 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);
+        }
+    }
+    else {
+        view.setFloat32(position, vector[0], true);
+        view.setFloat32(position+4, vector[1], true);
+        view.setFloat32(position+8, vector[2], true);
+    }
+}
+
+function getVectorFromText(line, position) {
+    data = line.substr(position).split(/[\s,]+/);
+    if (data.length < 3)
+        throw 'Invalid vector';
+        
+    if (ASCII_MODE) {
+        return data[0]+","+data[1]+","+data[2];
+    }
+
+    return [parseFloat(data[0]), parseFloat(data[1]), parseFloat(data[2])];
+}
+
+function message(text) {
+    document.getElementById('console').innerHTML += '<li>'+text+'</li>';
+}
+
+function getASCIISTL(text) {
+    var triangles = [];
+    
+    var triangle = [];
+    var normal = [0,0,0];
+    
+    var lines = text.split(/[\r\n]+/);
+    
+    message(lines.length+" lines of data");
+    
+    for (var i = 0 ; i < lines.length ; i++ ) {
+        l = lines[i].trim().toLowerCase();
+        if (l == 'endfacet') {
+            if (triangle.length != 3) {
+                throw 'invalid triangle';
+            }
+            triangles.push([triangle[0],triangle[1],triangle[2],normal]);
+            triangle = [];
+            normal = [0,0,0];
+        }
+        else if (l.startsWith('facet')) {
+            if (l.length > 6) {
+                if (l.substr(6).startsWith('normal'))
+                    normal = getVectorFromText(l, 13);
+            }
+        }
+        else if (l.startsWith('vertex')) {
+            if (l.length > 7) 
+                triangle.push(getVectorFromText(l, 7));
+        }
+    }
+    
+    message(String(triangles.length) + " triangles");
+    
+    return triangles;
+}
+
+function getBinarySTL(view) {
+    var triangles = [];
+
+    var numTriangles = view.getUint32(80, true);
+    
+    message(String(numTriangles) + " triangles");
+    
+    for (var i = 0 ; i < numTriangles ; i++) {
+        position = 84 + TRIANGLE_SIZE*i;
+    
+        normal = getVector(view, position);
+        v1 = getVector(view, position+12);
+        v2 = getVector(view, position+12*2);
+        v3 = getVector(view, position+12*3);
+        triangles.push( [v1,v2,v3,normal] );
+    }
+    
+    return triangles;
+}
+
+function splitMesh(triangles) {
+    meshes = [];
+    
+    for (var i = 0; i<triangles.length; i++) {
+        var t = triangles[i];
+        var matches = [];
+        for (var j = 0 ; j < meshes.length; j++) {
+            for (var k = 0 ; k < 3 ; k++) {
+                if (t[k] in meshes[j].points) {
+                    matches.push(j);
+                    break;
+                }
+            }
+        }
+        var m;
+        if (matches.length == 0) {
+            m = {points:{}, triangles:[]};
+            meshes.push(m);
+        }
+        else {
+            m = meshes[matches[0]];
+            for (var j = matches.length - 1 ; j >= 1 ; j--) {
+                mm = meshes[matches[j]];
+                for (var key in mm.points) {
+                    if (mm.points.hasOwnProperty(key))
+                        m.points[key] = true;
+                }
+                for (var k = 0 ; k < mm.triangles.length; k++) {
+                    m.triangles.push(mm.triangles[k]);
+                }
+                meshes.splice(matches[j], 1);
+            }
+        }
+        for (var k = 0 ; k < 3 ; k++) {
+            m.points[t[k]] = true;
+        }
+        m.triangles.push(t);
+    }
+    
+    out = [];
+    
+    for (var i = 0 ; i < meshes.length ; i++) {
+        out.push(meshes[i].triangles);
+    }
+    
+    return out;
+}
+
+function downloadBlob(name,blob) {
+    var link = document.createElement('a');
+    link.download = name;
+    link.href = window.URL.createObjectURL(blob);
+    link.onclick = function(e) {
+        setTimeout(function() {
+            window.URL.revokeObjectURL(link.href);
+        }, 1600);
+    };
+    link.click();
+    link.remove();
+}
+
+function makeMeshByteArray(triangles) {
+    data = new ArrayBuffer(84 + triangles.length * TRIANGLE_SIZE);
+    view = new DataView(data);
+    view.setUint32(80, triangles.length, true);
+    for (var i=0; i<triangles.length; i++) {
+        var offset = 84 + i*TRIANGLE_SIZE;
+        setVector(view, offset, triangles[i][3]); // normal
+        setVector(view, offset+12, triangles[i][0]); // v1
+        setVector(view, offset+12*2, triangles[i][1]); // v2
+        setVector(view, offset+12*3, triangles[i][2]); // v3
+    }
+    return view.buffer;
+}
+
+function downloadMesh(i) {
+    downloadBlob(baseFilename+i+".stl", new Blob([makeMeshByteArray(allSplitMeshes[i])], {type: "application/octet-stream"}));
+}
+
+function processSTL(data) {
+    length = data.byteLength;
+    view = new DataView(data);
+    
+    var header = getString(view, 0, 5);
+    
+    var binary = true;
+    var text;
+    
+    if (header == "solid") {
+        // probably ASCII
+        text = getString(view, 0, length);
+        if (text.includes("endfacet")) {
+            binary = false;
+        }
+    }
+    
+    message(binary ? "binary STL" : "ASCII STL");
+    triangles = binary ? getBinarySTL(view) : getASCIISTL(text);
+    message("data successfully read");    
+    splitMeshes = splitMesh(triangles);
+    if (splitMeshes.length == 1) {
+        message("No splitting done: Only one mesh in file.");
+    }
+    else if (splitMeshes.length == 0) {
+        message("No mesh found in file.");
+    }
+    else {
+        message(String(splitMeshes.length)+" meshes extracted");
+        allSplitMeshes = splitMeshes;
+        for (var i=0; i<splitMeshes.length; i++) {
+            message("<a href='#' onclick='downloadMesh("+i+");'>Download mesh part "+i+"</a>");
+        }
+    }
+}
+
+function handleFileSelect(evt) {
+    var e = document.getElementById('file');
+    e.parentNode.removeChild(e);
+
+    var f = evt.target.files[0];
+    
+    message( escape(f.name) );
+    message( String(f.size) + ' bytes');
+    
+    var n = f.name.split(/[/\\]+/);
+    baseFilename = f.name.replace(/.*[/\\]/, "").replace(/\.[sS][tT][lL]$/, "");
+
+    var reader = new FileReader();
+    reader.onload = function(event) {
+        processSTL(event.target.result);
+    }
+    reader.readAsArrayBuffer(f);
+}
+
+document.getElementById('file').addEventListener('change', handleFileSelect, false);
+</script>
+</body>
+</html>