fix thin3 chain marking and shortening
This commit is contained in:
parent
046c071333
commit
32d4b7e62a
2 changed files with 86 additions and 39 deletions
|
|
@ -258,7 +258,7 @@ export class Polygon {
|
||||||
// of the polygon with the noodle removed (for the next pass)
|
// of the polygon with the noodle removed (for the next pass)
|
||||||
noodle(width) {
|
noodle(width) {
|
||||||
let clone = this.clone(true);
|
let clone = this.clone(true);
|
||||||
let ins = clone.offset(width);
|
let ins = clone.offset(width) ?? [];
|
||||||
let remain = ins.clone(true);
|
let remain = ins.clone(true);
|
||||||
let nood = POLY.nest(POLY.flatten([ clone, ...ins ], [], true));
|
let nood = POLY.nest(POLY.flatten([ clone, ...ins ], [], true));
|
||||||
return { noodle: nood, remain };
|
return { noodle: nood, remain };
|
||||||
|
|
|
||||||
|
|
@ -182,11 +182,13 @@ function thin_type_3(params) {
|
||||||
let mergeChains = true;
|
let mergeChains = true;
|
||||||
let interpolateShortSpur = true;
|
let interpolateShortSpur = true;
|
||||||
let showChainInterpPoints = true;
|
let showChainInterpPoints = true;
|
||||||
|
let showCross = false;
|
||||||
|
let showPoint = true;
|
||||||
let showChainRawPoints = false;
|
let showChainRawPoints = false;
|
||||||
let showNoodle = false;
|
let showNoodle = false;
|
||||||
let showMid = true;
|
let showMid = true;
|
||||||
let showCross = true;
|
|
||||||
let showRad = false;
|
let showRad = false;
|
||||||
|
let showNexus = false;
|
||||||
|
|
||||||
let pointMap = new Map();
|
let pointMap = new Map();
|
||||||
let lineMap = new Map();
|
let lineMap = new Map();
|
||||||
|
|
@ -354,37 +356,6 @@ function thin_type_3(params) {
|
||||||
chains = chains.filter(c => c.total >= minR);
|
chains = chains.filter(c => c.total >= minR);
|
||||||
chains.sort((c1,c2) => c2.total - c1.total);
|
chains.sort((c1,c2) => c2.total - c1.total);
|
||||||
|
|
||||||
// map chains to nexus via endpoints
|
|
||||||
let nexus = {};
|
|
||||||
function addEp(point, chain) {
|
|
||||||
let key = point.key;
|
|
||||||
let rec = nexus[key];
|
|
||||||
if (!rec) rec = nexus[key] = { point, chains: [] };
|
|
||||||
if (rec.chains.indexOf(chain) < 0) rec.chains.push(chain);
|
|
||||||
}
|
|
||||||
// since chains are sorted longest to shortest,
|
|
||||||
// they will appear in the nexus record longest to shortest
|
|
||||||
for (let chain of chains) {
|
|
||||||
addEp(chain[0], chain);
|
|
||||||
addEp(chain.peek(), chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
// mark spurs
|
|
||||||
for (let [key, rec] of Object.entries(nexus)) {
|
|
||||||
if (rec.chains.length === 1) {
|
|
||||||
rec.chains[0].spur = true;
|
|
||||||
delete nexus[key];
|
|
||||||
// console.log({ delete_nexus: key });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// detach spurs from nexus and shorten by ?
|
|
||||||
// for (let [key,val] of Object.entries(nexus)) {
|
|
||||||
// nexus[key].chains = val.chains.filter(c => !c.spur);
|
|
||||||
// }
|
|
||||||
|
|
||||||
console.log({ chains, nexus });
|
|
||||||
|
|
||||||
function merge1chain() {
|
function merge1chain() {
|
||||||
let clen = chains.length;
|
let clen = chains.length;
|
||||||
for (let i=0; i<clen; i++) {
|
for (let i=0; i<clen; i++) {
|
||||||
|
|
@ -423,6 +394,25 @@ function thin_type_3(params) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// console.log({ chains });
|
||||||
|
|
||||||
|
// map chains to nexus via endpoints
|
||||||
|
let nexus = {};
|
||||||
|
function addEp(point, chain) {
|
||||||
|
let key = point.key;
|
||||||
|
let rec = nexus[key];
|
||||||
|
if (!rec) rec = nexus[key] = { point, chains: [] };
|
||||||
|
if (rec.chains.indexOf(chain) < 0) rec.chains.push(chain);
|
||||||
|
}
|
||||||
|
// since chains are sorted longest to shortest,
|
||||||
|
// they will appear in the nexus record longest to shortest
|
||||||
|
for (let chain of chains) {
|
||||||
|
addEp(chain[0], chain);
|
||||||
|
addEp(chain.peek(), chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log({ chains, nexus, np: Object.values(nexus).length });
|
||||||
|
|
||||||
// connect chains end to end following nexus branches that result
|
// connect chains end to end following nexus branches that result
|
||||||
// in the longest final merged chain (open or closed)
|
// in the longest final merged chain (open or closed)
|
||||||
// map chain endpoints to nexus points
|
// map chain endpoints to nexus points
|
||||||
|
|
@ -432,13 +422,69 @@ function thin_type_3(params) {
|
||||||
console.log({ chains });
|
console.log({ chains });
|
||||||
|
|
||||||
// mark closed chains
|
// mark closed chains
|
||||||
|
// todo use exact point match by eliminating slice above
|
||||||
|
// then later removing repeated points in the resulting chain from merges
|
||||||
for (let chain of chains) {
|
for (let chain of chains) {
|
||||||
chain.closed = pointDist(chain[0], chain.peek()) <= offsetN;
|
chain.closed = pointDist(chain[0], chain.peek()) <= offsetN;
|
||||||
|
// console.log(chain.closed);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shorten(chain) {
|
||||||
|
for (let rem=0, i=chain.length-1; i>=1 && rem < minR; i--) {
|
||||||
|
let c1 = chain[i];
|
||||||
|
let c2 = chain[i-1];
|
||||||
|
let d = pointDist(c1,c2);
|
||||||
|
if (rem + d <= minR) {
|
||||||
|
chain.pop();
|
||||||
|
rem += d;
|
||||||
|
} else {
|
||||||
|
let diff = minR - rem;
|
||||||
|
// move c1 toward c2
|
||||||
|
let pct = diff / d;
|
||||||
|
let dx = c1.x - c2.x;
|
||||||
|
let dy = c1.y - c2.y;
|
||||||
|
chain[i] = {
|
||||||
|
x: c1.x - dx * pct,
|
||||||
|
y: c1.y - dy * pct,
|
||||||
|
r: c1.r
|
||||||
|
};
|
||||||
|
rem = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add chains
|
||||||
|
|
||||||
|
// shorten chains terminating at nexus by midR
|
||||||
|
for (let rec of Object.values(nexus)) {
|
||||||
|
let { point } = rec;
|
||||||
|
rec.shorts = 0;
|
||||||
|
if (rec.chains.length < 3) continue;
|
||||||
|
for (let chain of chains.filter(c => !c.closed)) {
|
||||||
|
if (pointDist(chain[0], point) < minR) {
|
||||||
|
chain.reverse();
|
||||||
|
shorten(chain);
|
||||||
|
chain.reverse();
|
||||||
|
rec.shorts++;
|
||||||
|
} else if (chain.peek() === point) {
|
||||||
|
shorten(chain);
|
||||||
|
rec.shorts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showNexus)
|
||||||
|
for (let rec of Object.values(nexus)) {
|
||||||
|
let { point, chains } = rec;
|
||||||
|
// console.log(rec);
|
||||||
|
top.shells.push(newPolygon().centerCircle(point, 0.2, 6 - rec.shorts));
|
||||||
}
|
}
|
||||||
|
|
||||||
// gather point offsets into shells
|
// gather point offsets into shells
|
||||||
// todo: order outer shell innersection to inner
|
let zi = z;
|
||||||
for (let chain of chains) {
|
for (let chain of chains) {
|
||||||
|
// zi += 0.1;
|
||||||
if (showChainRawPoints)
|
if (showChainRawPoints)
|
||||||
for (let pt of chain) {
|
for (let pt of chain) {
|
||||||
top.shells.push(newPolygon().centerCircle(pt, pt.r ?? 0.1, 10));
|
top.shells.push(newPolygon().centerCircle(pt, pt.r ?? 0.1, 10));
|
||||||
|
|
@ -447,8 +493,8 @@ function thin_type_3(params) {
|
||||||
for (let i=0; i<chain.length-1; i++) {
|
for (let i=0; i<chain.length-1; i++) {
|
||||||
// medial axis segment
|
// medial axis segment
|
||||||
if (showMid) {
|
if (showMid) {
|
||||||
thin.push(new Point(chain[i].x, chain[i].y));
|
thin.push(new Point(chain[i].x, chain[i].y, zi));
|
||||||
thin.push(new Point(chain[i+1].x, chain[i+1].y));
|
thin.push(new Point(chain[i+1].x, chain[i+1].y, zi));
|
||||||
}
|
}
|
||||||
// compute medial axis segment cross section
|
// compute medial axis segment cross section
|
||||||
let p0 = chain[i];
|
let p0 = chain[i];
|
||||||
|
|
@ -474,8 +520,8 @@ function thin_type_3(params) {
|
||||||
if (showCross) {
|
if (showCross) {
|
||||||
thin.push(new Point(cx + yo, cy - xo));
|
thin.push(new Point(cx + yo, cy - xo));
|
||||||
thin.push(new Point(cx - yo, cy + xo));
|
thin.push(new Point(cx - yo, cy + xo));
|
||||||
} else {
|
} else if (showPoint) {
|
||||||
top.shells.push(newPolygon().centerCircle({ x:cx, y:cy }, 0.15, 10));
|
top.shells.push(newPolygon().centerCircle({ x:cx, y:cy }, 0.05, 10));
|
||||||
}
|
}
|
||||||
if (showRad) {
|
if (showRad) {
|
||||||
const Sx = cx + ndy * cr;
|
const Sx = cx + ndy * cr;
|
||||||
|
|
@ -495,7 +541,8 @@ function thin_type_3(params) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
POLY.setZ([...thin, ...top.shells], z);
|
// POLY.setZ([...thin, ...top.shells], z);
|
||||||
|
POLY.setZ([...top.shells], z);
|
||||||
|
|
||||||
return { last, gaps };
|
return { last, gaps };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue