add jspoly and checkpoint thinwall v3
This commit is contained in:
parent
ad0b2c8fc0
commit
c76085f6f9
3 changed files with 7428 additions and 34 deletions
7295
src/ext/jspoly.js
Normal file
7295
src/ext/jspoly.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -257,32 +257,14 @@ export class Polygon {
|
|||
// including inner polys. return the noodle and the remainder
|
||||
// of the polygon with the noodle removed (for the next pass)
|
||||
noodle(width) {
|
||||
// inset outer polygon
|
||||
let inner = this.inner;
|
||||
let inset = this.clone().offset(width);
|
||||
let noodot = [ this.clone().setInner(inset) ];
|
||||
let noodin = [];
|
||||
// subtract inners from the inset
|
||||
if (inner) {
|
||||
noodot = POLY.subtract(noodot, inner, []);
|
||||
// for each inner, offset and subtract noodle + itself
|
||||
let nood = [];
|
||||
for (let innie of inner) {
|
||||
let inexp = innie.clone().offset(-width);
|
||||
let intrm = POLY.trimTo(inexp, [ this ]);
|
||||
let inood = POLY.subtract(intrm, [ ...noodot, innie ], []);
|
||||
nood.push(...inood);
|
||||
}
|
||||
noodin = POLY.union(nood, 0, true);
|
||||
}
|
||||
// unify inner noodles and outer noodle
|
||||
let noodle = POLY.union([ ...noodot, ...noodin ], 0, true);
|
||||
// subtract noodle from poly for next noodle calc
|
||||
let remain = POLY.subtract([ this ], noodle, []);
|
||||
return { noodle, remain };
|
||||
let clone = this.clone(true);
|
||||
let ins = clone.offset(width);
|
||||
let nood = POLY.nest(POLY.flatten([ clone, ...ins ], [], true));
|
||||
return { noodle: nood, remain: ins };
|
||||
}
|
||||
|
||||
// generate center crossing point cloud
|
||||
// only used for fdm thin-wall type 1 (fdm/post.js)
|
||||
centers(step, z, min, max, opt = {}) {
|
||||
let cloud = [],
|
||||
bounds = this.bounds,
|
||||
|
|
@ -555,6 +537,7 @@ export class Polygon {
|
|||
return this;
|
||||
}
|
||||
|
||||
// only used in fdm/slice.js for enclosing supports
|
||||
createConvexHull(points) {
|
||||
function removeMiddle(a, b, c) {
|
||||
let cross = (a.x - b.x) * (c.y - b.y) - (a.y - b.y) * (c.x - b.x);
|
||||
|
|
@ -886,6 +869,7 @@ export class Polygon {
|
|||
|
||||
/**
|
||||
* hint fill angle hinting from longest segment
|
||||
* only used in fdm/slice.js for projected infill orientation
|
||||
*/
|
||||
hintFillAngle() {
|
||||
let index = 0,
|
||||
|
|
@ -1217,6 +1201,8 @@ export class Polygon {
|
|||
* 2. ease-down starts, following the polygonal path, decreasing Z at a fixed slope until target Z is hit,
|
||||
* 3. then the rest of the path is completed and repeated at target Z until touchdown point is reached.
|
||||
* 4. this function should probably move to CAM prepare since it's only called from there
|
||||
*
|
||||
* possibly no longer used anywhere
|
||||
*/
|
||||
forEachPointEaseDown(fn, fromPoint, degrees = 45) {
|
||||
let index = this.findClosestPointTo(fromPoint).index,
|
||||
|
|
@ -1537,6 +1523,7 @@ export class Polygon {
|
|||
return this;
|
||||
}
|
||||
|
||||
// used in geo/slicer.js to free memory
|
||||
freeParentRefs() {
|
||||
if (this.inner && this.inner.length > 0) {
|
||||
for (let inner of this.inner) {
|
||||
|
|
@ -1549,6 +1536,7 @@ export class Polygon {
|
|||
}
|
||||
}
|
||||
|
||||
// possibly ununsed
|
||||
newUndeleted() {
|
||||
let poly = newPolygon();
|
||||
this.forEachPoint(p => {
|
||||
|
|
@ -1888,6 +1876,7 @@ export class Polygon {
|
|||
return out;
|
||||
}
|
||||
|
||||
// possibly unused
|
||||
shortestSegmentLength() {
|
||||
let len = Infinity;
|
||||
this.forEachSegment((p1, p2) => {
|
||||
|
|
@ -2362,6 +2351,8 @@ export class Polygon {
|
|||
return this;
|
||||
}
|
||||
|
||||
// only used by cam/op-pocket.js
|
||||
// for any poly points closer than `dist`, replace them with their midpoint
|
||||
midpoints(dist = 0.01) {
|
||||
const newp = [];
|
||||
const points = this.points;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
import '../../../ext/jspoly.js';
|
||||
import { base } from '../../../geo/base.js';
|
||||
import { Line } from '../../../geo/line.js';
|
||||
import { polygons as POLY, fillArea } from '../../../geo/polygons.js';
|
||||
import { getRangeParameters } from './driver.js';
|
||||
import { slicer } from '../../../geo/slicer.js';
|
||||
import { Point } from '../../../geo/point.js';
|
||||
|
||||
slicer.slicePost.FDM = slicePost;
|
||||
|
||||
|
|
@ -164,19 +167,124 @@ function thin_type_3(params) {
|
|||
top.thin_fill = [];
|
||||
top.fill_sparse = [];
|
||||
|
||||
let { noodle, remain } = top.poly.noodle(offsetN);
|
||||
let { noodle, remain } = top.poly.noodle(offsetN * 2);
|
||||
top.shells = noodle;
|
||||
top.gaps = remain;
|
||||
// top.fill_off = noodle;
|
||||
|
||||
// if (remain.length) {
|
||||
// top.gaps = [];
|
||||
// for (let poly of remain) {
|
||||
// let { noodle } = poly.noodle(offsetN);
|
||||
// console.log({ next_noodle: noodle });
|
||||
// top.gaps.push(...noodle);
|
||||
// }
|
||||
// }
|
||||
let thin = top.thin_fill;
|
||||
let scale = 5000;
|
||||
let minR = offsetN / 2;
|
||||
let minSpur = offsetN * 3;
|
||||
|
||||
let pointMap = new Map();
|
||||
let lineMap = new Map();
|
||||
|
||||
function pointToRec(point) {
|
||||
let key = `${(point.x*100)|0}|${(point.y*100)|0}`;
|
||||
let rec = pointMap.get(key);
|
||||
if (!rec) {
|
||||
rec = {
|
||||
key,
|
||||
count: 0,
|
||||
x: point.x/scale,
|
||||
y: point.y/scale,
|
||||
r: point.radius/scale,
|
||||
};
|
||||
pointMap.set(key, rec);
|
||||
}
|
||||
return rec;
|
||||
}
|
||||
|
||||
function pointsToLine(p0, p1) {
|
||||
p0 = pointToRec(p0);
|
||||
p1 = pointToRec(p1);
|
||||
let key = p0.key > p1.key ? `${p1.key}:${p0.key}` : `${p0.key}:${p1.key}`;
|
||||
let rec = lineMap.get(key);
|
||||
if (rec) {
|
||||
rec.count++;
|
||||
} else {
|
||||
rec = {
|
||||
p0,
|
||||
p1,
|
||||
key,
|
||||
count: 1,
|
||||
};
|
||||
p0.count++;
|
||||
p1.count++;
|
||||
lineMap.set(key, rec);
|
||||
}
|
||||
return rec;
|
||||
}
|
||||
|
||||
let chains = [];
|
||||
|
||||
for (let poly of noodle) {
|
||||
poly = poly.clone(true).scale({ x:scale, y:scale, z:scale });
|
||||
let out = poly.points.map(p => ({ x: p.x|0, y: p.y|0 }));
|
||||
let inr = (poly.inner ?? []).map(p => p.points.map(p => ({ x: p.x|0, y: p.y|0 })));
|
||||
let ma = JSPoly.construct_medial_axis(out, inr);
|
||||
for (let { point0, point1 } of ma) {
|
||||
pointsToLine(point0, point1);
|
||||
}
|
||||
for (let seg of lineMap.values()) {
|
||||
let { p0, p1 } = seg;
|
||||
let len = seg.len = Math.hypot(p0.x-p1.x, p0.y-p1.y);
|
||||
if (p0.r < minR || p1.r < minR) {
|
||||
if (p0.r > minR && len > minSpur) {
|
||||
// move p1 toward p0 until minR met
|
||||
let pct = (minR - p1.r) / (p0.r - p1.r);
|
||||
let dx = p1.x - p0.x;
|
||||
let dy = p1.y - p0.y;
|
||||
p1.x -= dx * pct;
|
||||
p1.y -= dy * pct;
|
||||
p1.r = minR;
|
||||
pointMap.delete(p1.key);
|
||||
} else if (p1.r > minR && len > minSpur) {
|
||||
// move p0 toward p1 until minR met
|
||||
let pct = (minR - p0.r) / (p1.r - p0.r);
|
||||
let dx = p0.x - p1.x;
|
||||
let dy = p0.y - p1.y;
|
||||
p0.x -= dx * pct;
|
||||
p0.y -= dy * pct;
|
||||
p0.r = minR;
|
||||
pointMap.delete(p0.key);
|
||||
} else {
|
||||
lineMap.delete(seg.key);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// thin.push(new Point(p0.x, p0.y));
|
||||
// thin.push(new Point(p1.x, p1.y));
|
||||
let add;
|
||||
for (let chain of chains) {
|
||||
if (p0.count === 2 && p0 === chain[0]) {
|
||||
chain.splice(0,0,p1);
|
||||
} else if (p0.count === 2 && p0 === chain.peek()) {
|
||||
chain.push(p1);
|
||||
add = true;
|
||||
} else if (p1.count === 2 && p1 === chain[0]) {
|
||||
chain.splice(0,0,p0);
|
||||
add = true;
|
||||
} else if (p1.count ===2 && p1 === chain.last) {
|
||||
chain.push(p0);
|
||||
add = true;
|
||||
}
|
||||
if (add) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!add) {
|
||||
chains.push([ p0, p1 ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let chain of chains) {
|
||||
for (let i=0; i<chain.length-1; i++) {
|
||||
thin.push(new Point(chain[i].x, chain[i].y));
|
||||
thin.push(new Point(chain[i+1].x, chain[i+1].y));
|
||||
}
|
||||
}
|
||||
|
||||
return { last, gaps };
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue