From e97eb9ad1db5f5cedb3f478c7ee53322c77ef659 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Wed, 8 Sep 2021 01:59:18 -0400 Subject: [PATCH] add merging of open loops --- src/geo/mesh.js | 132 ++++++++++++++++++++++++++++++++------------- src/kiri/widget.js | 23 ++++---- 2 files changed, 106 insertions(+), 49 deletions(-) diff --git a/src/geo/mesh.js b/src/geo/mesh.js index 6ca5c4da..3cb1c9a1 100644 --- a/src/geo/mesh.js +++ b/src/geo/mesh.js @@ -39,6 +39,8 @@ // when face/index data is missing, vertices need to be normalized if (!faces) { faces = []; + let fcac = {}; // seen face hash + let fnew = []; // accumulate vertex triplets let nuvt = []; // new vertex list let hash = {}; // find vertex matches let prec = this.precision; @@ -58,7 +60,22 @@ nuvt.push(y); nuvt.push(z); } - faces.push(vpos); + fnew.push(vpos); + if (fnew.length === 3) { + if (fnew[0] === fnew[1] || fnew[0] === fnew[2] || fnew[1] === fnew[2]) { + // console.log('invalid face', fnew); + fnew = []; + continue; + } + let key = fnew.slice().sort().join('-'); + if (!fcac[key]) { + faces.appendAll(fnew); + // } else { + // console.log('dup face', key); + } + fcac[key] = key; + fnew = []; + } } vertices = nuvt; } @@ -99,12 +116,31 @@ addFace(face) { if (this.faces.indexOf(face) < 0) { this.faces.push(face); - // } else { - // console.log('adding face to line twice', this, face); + } else { + console.log('adding face to line twice', this, face); } return this; } + adjacentUnused() { + return vmap[this.v1] + .concat(vmap[this.v2]) + .filter(l => l !== this && !l.used && l.faces.length === 1); + } + + adjacentUsed() { + return vmap[this.v1] + .concat(vmap[this.v2]) + .filter(l => l !== this && l.used && l.faces.length === 1); + } + + touches(line) { + return this.v1 === line.v1 || + this.v1 === line.v2 || + this.v2 === line.v1 || + this.v2 === line.v2; + } + unitVector() { if (this.unit !== undefined) { return this.unit; @@ -171,22 +207,27 @@ if (line.used) { continue; } + // cannot start on split + if (line.adjacentUnused().length > 2) { + console.log('cannot start on a split'); + continue; + } // line.used = true; - let loop = [ line ]; + let loop = [ ]; // build line through adjacent lines while (true) { - let adjacent = vmap[line.v1] - .concat(vmap[line.v2]) - .filter(l => l !== line && !l.used && l.faces.length === 1); + let adjacent = line.adjacentUnused(); if (adjacent.length === 0) { + let first = loop[0]; + let last = loop.last(); + loop.open = loop.length < 3 + || (first.v1 !== last.v1 + && first.v2 !== last.v2 + && first.v1 !== last.v2 + && first.v2 !== last.v1); + // console.log({term: line, adj: line.adjacentUsed(), open, loop}); break; - } - if (adjacent.length > 2) { - console.log('error adjacent', line, adjacent, loops.length, loop.length); - line.error = adjacent; - // break; - } - if (adjacent.length === 1) { + } else if (adjacent.length === 1) { if (line.v2 !== adjacent[0].v1) { let tmp = adjacent[0].v1; adjacent[0].v1 = adjacent[0].v2; @@ -194,41 +235,56 @@ // console.log('chirality mismatch fixed'); } line = adjacent[0]; - } else { + } else if (adjacent.length === 2) { // follow edges according to chirality line = adjacent[0].v1 === line.v2 ? adjacent[0] : adjacent[1] + } else { + // console.log('error adjacent', line, adjacent, loops.length, loop.length); + line.split = adjacent; + line = adjacent[0]; } loop.push(line); line.used = true; } - // drop co-linear points because they can't be connected into valid faces - // fixup remaining line by dropping common point and using dropped line's point - // todo: disabled until faces are fixed up, too. otherwise, problems - if (false) for (let j=0, jl=loop.length; j !l.del); loops.push(loop); } - // console.log({loops}); + // attempt to connect open loops + if (loops.length > 1) { + outer: for (let i=0; i l && l.length > 2); + console.log({loops}); // progressive boundary run algorithm function emitLoop1(loop) { diff --git a/src/kiri/widget.js b/src/kiri/widget.js index 97577515..d0a1f768 100644 --- a/src/kiri/widget.js +++ b/src/kiri/widget.js @@ -307,14 +307,14 @@ console.log/** Copyright Stewart Allen -- All Rights Reserved */ }; PRO.heal = function(debug) { - let mesh = this.debugMesh(); + let mesh = this.debugMesh(undefined); mesh.heal(); if (debug) { let verts = mesh.vertices; let edges = mesh.edges; - let error = mesh.edges.filter(l => l.error); + let split = mesh.edges.filter(l => l.split); let layrz = new KIRI.Layers(); - layrz.setLayer("edges", {line: 0xff0000}); + layrz.setLayer("edges", {line: 0}); for (let line of edges) { layrz.addLine( BASE.newPoint(verts[line.v1], verts[line.v1+1], verts[line.v1+2]), @@ -322,24 +322,25 @@ console.log/** Copyright Stewart Allen -- All Rights Reserved */ ); } for (let l=0; l