move path utilities out of print
This commit is contained in:
parent
d8fc75026b
commit
36d3f6b0b6
4 changed files with 118 additions and 109 deletions
2
app.js
2
app.js
|
|
@ -361,7 +361,6 @@ const script = {
|
||||||
"kiri/stack",
|
"kiri/stack",
|
||||||
"kiri/stacks",
|
"kiri/stacks",
|
||||||
"kiri/widget",
|
"kiri/widget",
|
||||||
"kiri/print",
|
|
||||||
"kiri/codec",
|
"kiri/codec",
|
||||||
"kiri/conf",
|
"kiri/conf",
|
||||||
"kiri/main",
|
"kiri/main",
|
||||||
|
|
@ -384,6 +383,7 @@ const script = {
|
||||||
"add/three",
|
"add/three",
|
||||||
"add/class",
|
"add/class",
|
||||||
"geo/base",
|
"geo/base",
|
||||||
|
"geo/path",
|
||||||
"geo/wasm",
|
"geo/wasm",
|
||||||
"geo/point",
|
"geo/point",
|
||||||
"geo/points",
|
"geo/points",
|
||||||
|
|
|
||||||
111
src/geo/path.js
Normal file
111
src/geo/path.js
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
const base = self.base;
|
||||||
|
if (base.path) return;
|
||||||
|
|
||||||
|
const { util, config, newPoint } = base;
|
||||||
|
const { sqr, numOrDefault } = util;
|
||||||
|
|
||||||
|
const DEG2RAD = Math.PI / 180;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* emit each element in an array based on
|
||||||
|
* the next closest endpoint.
|
||||||
|
*/
|
||||||
|
function tip2tipEmit(array, startPoint, emitter) {
|
||||||
|
let mindist, dist, found, count = 0;
|
||||||
|
for (;;) {
|
||||||
|
found = null;
|
||||||
|
mindist = Infinity;
|
||||||
|
array.forEach(function(el) {
|
||||||
|
if (el.delete) return;
|
||||||
|
dist = startPoint.distTo2D(el.first);
|
||||||
|
if (dist < mindist) {
|
||||||
|
found = {el:el, first:el.first, last:el.last};
|
||||||
|
mindist = dist;
|
||||||
|
}
|
||||||
|
dist = startPoint.distTo2D(el.last);
|
||||||
|
if (dist < mindist) {
|
||||||
|
found = {el:el, first:el.last, last:el.first};
|
||||||
|
mindist = dist;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (found) {
|
||||||
|
found.el.delete = true;
|
||||||
|
startPoint = found.last;
|
||||||
|
emitter(found.el, found.first, ++count);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return startPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* like tip2tipEmit but accepts an array of polygons and the next closest
|
||||||
|
* point can be anywhere in the adjacent polygon. should be re-written
|
||||||
|
* to be more like outputOrderClosest() and have the option to account for
|
||||||
|
* depth in determining distance
|
||||||
|
*/
|
||||||
|
function poly2polyEmit(array, startPoint, emitter, opt = {}) {
|
||||||
|
let marker = opt.mark || 'delete';
|
||||||
|
let mindist, dist, found, count = 0;
|
||||||
|
for (;;) {
|
||||||
|
found = null;
|
||||||
|
mindist = Infinity;
|
||||||
|
for (let poly of array) {
|
||||||
|
if (poly[marker]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (poly.isOpen()) {
|
||||||
|
const d2f = startPoint.distTo2D(poly.first());
|
||||||
|
const d2l = startPoint.distTo2D(poly.last());
|
||||||
|
if (d2f > mindist && d2l > mindist) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (d2l < mindist && d2l < d2f && opt.swapdir !== false) {
|
||||||
|
poly.reverse();
|
||||||
|
found = {poly:poly, index:0, point:poly.first()};
|
||||||
|
mindist = d2l;
|
||||||
|
} else if (d2f < mindist) {
|
||||||
|
found = {poly:poly, index:0, point:poly.first()};
|
||||||
|
mindist = d2f;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let area = poly.open ? 1 : poly.area();
|
||||||
|
poly.forEachPoint(function(point, index) {
|
||||||
|
dist = opt.weight ?
|
||||||
|
startPoint.distTo3D(point) * area * area :
|
||||||
|
startPoint.distTo2D(point);
|
||||||
|
if (dist < mindist) {
|
||||||
|
found = {poly:poly, index:index, point:point};
|
||||||
|
mindist = dist;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!found || opt.term) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
found.poly[marker] = true;
|
||||||
|
startPoint = emitter(found.poly, found.index, ++count, startPoint) || found.point;
|
||||||
|
}
|
||||||
|
|
||||||
|
// undo delete marks
|
||||||
|
if (opt.perm !== true) {
|
||||||
|
array.forEach(function(poly) { poly[marker] = false });
|
||||||
|
}
|
||||||
|
|
||||||
|
return startPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.path = {
|
||||||
|
poly2polyEmit,
|
||||||
|
tip2tipEmit
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
@ -7,10 +7,10 @@
|
||||||
let KIRI = self.kiri,
|
let KIRI = self.kiri,
|
||||||
BASE = self.base,
|
BASE = self.base,
|
||||||
POLY = BASE.polygons,
|
POLY = BASE.polygons,
|
||||||
UTIL = BASE.util,
|
PATH = BASE.path,
|
||||||
CAM = KIRI.driver.CAM,
|
CAM = KIRI.driver.CAM,
|
||||||
PRO = CAM.process,
|
{ newPoint } = BASE,
|
||||||
newPoint = BASE.newPoint;
|
{ tip2tipEmit, poly2polyEmit } = PATH;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DRIVER PRINT CONTRACT
|
* DRIVER PRINT CONTRACT
|
||||||
|
|
@ -103,8 +103,6 @@
|
||||||
spindle = 0,
|
spindle = 0,
|
||||||
spindleMax = device.spindleMax,
|
spindleMax = device.spindleMax,
|
||||||
addOutput = print.addOutput,
|
addOutput = print.addOutput,
|
||||||
tip2tipEmit = print.tip2tipEmit,
|
|
||||||
poly2polyEmit = print.poly2polyEmit,
|
|
||||||
maxToolDiam = widget.maxToolDiam,
|
maxToolDiam = widget.maxToolDiam,
|
||||||
terrain = widget.terrain ? widget.terrain.map(data => {
|
terrain = widget.terrain ? widget.terrain.map(data => {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,15 @@
|
||||||
if (self.kiri.newPrint) return;
|
if (self.kiri.newPrint) return;
|
||||||
|
|
||||||
const KIRI = self.kiri,
|
const KIRI = self.kiri,
|
||||||
DRIVERS = KIRI.driver,
|
|
||||||
LASER = DRIVERS.LASER,
|
|
||||||
CAM = DRIVERS.CAM,
|
|
||||||
FDM = DRIVERS.FDM,
|
|
||||||
BASE = self.base,
|
BASE = self.base,
|
||||||
|
PATH = BASE.path,
|
||||||
UTIL = BASE.util,
|
UTIL = BASE.util,
|
||||||
POLY = BASE.polygons,
|
|
||||||
SQRT = Math.sqrt,
|
|
||||||
SQR = UTIL.sqr,
|
SQR = UTIL.sqr,
|
||||||
PI = Math.PI,
|
PI = Math.PI,
|
||||||
PRO = Print.prototype,
|
PRO = Print.prototype,
|
||||||
Polygon = BASE.Polygon,
|
Polygon = BASE.Polygon,
|
||||||
newPoint = BASE.newPoint;
|
newPoint = BASE.newPoint,
|
||||||
|
{ tip2tipEmit } = PATH;
|
||||||
|
|
||||||
let lastPoint = null,
|
let lastPoint = null,
|
||||||
lastEmit = null,
|
lastEmit = null,
|
||||||
|
|
@ -58,8 +54,6 @@
|
||||||
PRO.addOutput = addOutput;
|
PRO.addOutput = addOutput;
|
||||||
PRO.extrudePerMM = extrudePerMM;
|
PRO.extrudePerMM = extrudePerMM;
|
||||||
PRO.constReplace = constReplace;
|
PRO.constReplace = constReplace;
|
||||||
PRO.poly2polyEmit = poly2polyEmit;
|
|
||||||
PRO.tip2tipEmit = tip2tipEmit;
|
|
||||||
PRO.addPrintPoints = addPrintPoints;
|
PRO.addPrintPoints = addPrintPoints;
|
||||||
|
|
||||||
PRO.parseSVG = function(code, offset) {
|
PRO.parseSVG = function(code, offset) {
|
||||||
|
|
@ -1185,100 +1179,6 @@
|
||||||
output.appendAll(input);
|
output.appendAll(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* emit each element in an array based on
|
|
||||||
* the next closest endpoint.
|
|
||||||
*/
|
|
||||||
function tip2tipEmit(array, startPoint, emitter) {
|
|
||||||
let mindist, dist, found, count = 0;
|
|
||||||
for (;;) {
|
|
||||||
found = null;
|
|
||||||
mindist = Infinity;
|
|
||||||
array.forEach(function(el) {
|
|
||||||
if (el.delete) return;
|
|
||||||
dist = startPoint.distTo2D(el.first);
|
|
||||||
if (dist < mindist) {
|
|
||||||
found = {el:el, first:el.first, last:el.last};
|
|
||||||
mindist = dist;
|
|
||||||
}
|
|
||||||
dist = startPoint.distTo2D(el.last);
|
|
||||||
if (dist < mindist) {
|
|
||||||
found = {el:el, first:el.last, last:el.first};
|
|
||||||
mindist = dist;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (found) {
|
|
||||||
found.el.delete = true;
|
|
||||||
startPoint = found.last;
|
|
||||||
emitter(found.el, found.first, ++count);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return startPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
BASE.util.poly2polyEmit = poly2polyEmit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* like tip2tipEmit but accepts an array of polygons and the next closest
|
|
||||||
* point can be anywhere in the adjacent polygon. should be re-written
|
|
||||||
* to be more like outputOrderClosest() and have the option to account for
|
|
||||||
* depth in determining distance
|
|
||||||
*/
|
|
||||||
function poly2polyEmit(array, startPoint, emitter, opt = {}) {
|
|
||||||
let marker = opt.mark || 'delete';
|
|
||||||
let mindist, dist, found, count = 0;
|
|
||||||
for (;;) {
|
|
||||||
found = null;
|
|
||||||
mindist = Infinity;
|
|
||||||
for (let poly of array) {
|
|
||||||
if (poly[marker]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (poly.isOpen()) {
|
|
||||||
const d2f = startPoint.distTo2D(poly.first());
|
|
||||||
const d2l = startPoint.distTo2D(poly.last());
|
|
||||||
if (d2f > mindist && d2l > mindist) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (d2l < mindist && d2l < d2f && opt.swapdir !== false) {
|
|
||||||
poly.reverse();
|
|
||||||
found = {poly:poly, index:0, point:poly.first()};
|
|
||||||
mindist = d2l;
|
|
||||||
} else if (d2f < mindist) {
|
|
||||||
found = {poly:poly, index:0, point:poly.first()};
|
|
||||||
mindist = d2f;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let area = poly.open ? 1 : poly.area();
|
|
||||||
poly.forEachPoint(function(point, index) {
|
|
||||||
dist = opt.weight ?
|
|
||||||
startPoint.distTo3D(point) * area * area :
|
|
||||||
startPoint.distTo2D(point);
|
|
||||||
if (dist < mindist) {
|
|
||||||
found = {poly:poly, index:index, point:point};
|
|
||||||
mindist = dist;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!found || opt.term) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
found.poly[marker] = true;
|
|
||||||
startPoint = emitter(found.poly, found.index, ++count, startPoint) || found.point;
|
|
||||||
}
|
|
||||||
|
|
||||||
// undo delete marks
|
|
||||||
if (opt.perm !== true) {
|
|
||||||
array.forEach(function(poly) { poly[marker] = false });
|
|
||||||
}
|
|
||||||
|
|
||||||
return startPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* calculate mm of filament required for a given extrusion length and layer height.
|
* calculate mm of filament required for a given extrusion length and layer height.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue