From 2c78e5e9cc25f4065a64c50545f29c63700f1b5d Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Mon, 6 Sep 2021 21:47:27 -0400 Subject: [PATCH] add heal option to context menu --- src/geo/mesh.js | 63 ++++++++++++++++++++++++++++++++++++++++----- src/kiri/init.js | 1 + src/kiri/main.js | 21 +++++++++++++++ src/kiri/widget.js | 22 ++++++++++++---- web/kiri/index.html | 1 + web/kiri/lang/en.js | 1 + 6 files changed, 97 insertions(+), 12 deletions(-) diff --git a/src/geo/mesh.js b/src/geo/mesh.js index 93edcbf2..9e74e746 100644 --- a/src/geo/mesh.js +++ b/src/geo/mesh.js @@ -67,6 +67,18 @@ return this; } + // return non-indexed vertex list (for compatibility) + unrolled() { + let out = []; + let vertices = this.vertices; + for (let face of this.faces) { + out.push(vertices[face]); + out.push(vertices[face+1]); + out.push(vertices[face+2]); + } + return out; + } + heal() { // construct ordered line map with array of connected lines // for each point pair, create ordered line @@ -90,6 +102,7 @@ if (this.faces.indexOf(face) < 0) { this.faces.push(face); } + return this; } unitVector() { @@ -151,10 +164,9 @@ // lines belonging to only one face or with only 2 peers // are on the edge of a hole - let edges = lines.filter(l => l.faces.length === 1); - console.log({edges}); - - let loops = []; + let edges = this.edges = lines.filter(l => l.faces.length === 1); + let loops = this.loops = []; + // console.log({edges}); // connect edge lines into closed loops for (let i=0, l=edges.length; i !l.del); - console.log({loop}); loops.push(loop); } - console.log({loops}); + // console.log({loops}); + + // emit loops + let faceCount = this.faces.length; + for (let loop of loops) { + while (loop.length > 2) { + // console.log({loop}); + let nuloop = []; + // proceed through line pairs + for (let i=0, l=loop.length; i { API.view.wireframe(true, 0, 0.5); }; $('render-solid').onclick = () => { API.view.wireframe(false, 0, 1); }; // context menu + $('context-heal-mesh').onclick = () => { API.widgets.heal() }; $('context-export-stl').onclick = () => { objectsExport() }; $('context-export-workspace').onclick = () => { profileExport(true) }; $('context-clear-workspace').onclick = () => { diff --git a/src/kiri/main.js b/src/kiri/main.js index 9a71786a..6d30f2d4 100644 --- a/src/kiri/main.js +++ b/src/kiri/main.js @@ -388,6 +388,7 @@ console.log/** Copyright Stewart Allen -- All Rights Reserved */ filter: (fn) => { WIDGETS = WIDGETS.filter(fn) }, for: forAllWidgets, load: Widget.loadFromCatalog, + heal: healWidgets, meshes: meshArray, opacity: setOpacity, annotate: (id) => { @@ -853,6 +854,26 @@ console.log/** Copyright Stewart Allen -- All Rights Reserved */ return out; } + function healWidgets() { + let widgets = API.widgets.all(); + if (widgets.length) { + API.show.alert("Analyzing objects"); + } else { + return; + } + let healed = 0; + for (let w of widgets) { + if (w.heal()) { + healed++; + } + } + if (healed) { + API.show.alert(`${healed} Object${healed ? 's':''} healed`); + } else { + API.show.alert('Nothing found to heal'); + } + } + function forAllWidgets(f) { WIDGETS.slice().forEach(function(widget) { f(widget); diff --git a/src/kiri/widget.js b/src/kiri/widget.js index d3fb29bd..470e2102 100644 --- a/src/kiri/widget.js +++ b/src/kiri/widget.js @@ -289,9 +289,12 @@ console.log/** Copyright Stewart Allen -- All Rights Reserved */ } } if (this.mesh) { - this.mesh.geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); - this.mesh.geometry.computeFaceNormals(); - this.mesh.geometry.computeVertexNormals(); + let geo = this.mesh.geometry; + geo.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); + geo.setAttribute('normal', undefined); + geo.attributes.position.needsUpdate = true; + geo.computeFaceNormals(); + geo.computeVertexNormals(); this.points = null; this.meta.vertices = vertices.length / 3; return this; @@ -303,9 +306,18 @@ console.log/** Copyright Stewart Allen -- All Rights Reserved */ } }; + PRO.heal = function() { + let mesh = this.debugMesh(); + mesh.heal(); + if (mesh.newFaces) { + this.loadVertices(mesh.unrolled().toFloat32()); + return this.modified = true; + } + return false; + }; + PRO.debugMesh = function(precision) { - let mesh = new base.Mesh({precision, vertices: this.getVertices().array}); - return mesh; + return new base.Mesh({precision, vertices: this.getVertices().array}); }; PRO.getVertices = function() { diff --git a/web/kiri/index.html b/web/kiri/index.html index a07f1f2f..6fd13c4f 100644 --- a/web/kiri/index.html +++ b/web/kiri/index.html @@ -458,6 +458,7 @@
+
diff --git a/web/kiri/lang/en.js b/web/kiri/lang/en.js index f0afa6fb..b4d2d923 100644 --- a/web/kiri/lang/en.js +++ b/web/kiri/lang/en.js @@ -54,6 +54,7 @@ kiri.lang['en-us'] = { rc_mirr: "mirror", rc_dupl: "duplicate", rc_focs: "set focus", + rc_heal: "heal meshes", rc_xstl: "export as STL", // DEVICE MENU and related dialogs