fixup more code broken by ai

This commit is contained in:
Stewart Allen 2025-07-05 17:06:38 -04:00
commit 76f9ce2c25
13 changed files with 161 additions and 351 deletions

View file

@ -401,6 +401,10 @@ function center2pr(p1, p2, r, clockwise) {
// find angle difference between 0 and 2pi from n1 to n2 (signed depending on clock direction)
function thetaDiff(n1, n2, clockwise) {
let diff = n2 - n1;
if(typeof n1 != 'number' || typeof n2 != 'number') {
throw ("n1 and n2 must be numbers");
// this check is here because this causes an infinite loop when other value are provided
}
while (diff < -Math.PI) diff += Math.PI * 2;
while (diff > Math.PI) diff -= Math.PI * 2;
if (clockwise && diff > 0) diff -= Math.PI * 2;
@ -516,333 +520,125 @@ function comma(v) {
return rt ? `${lt}.${rt}` : lt;
}
// Create the base namespace object
const base = {
config: {
// size of gcode debug arrow head
debug_arrow: 0.25,
// default # of decimal places in generated gcode
gcode_decimals: 4,
// heal disjoint polygons in slicing (experimental)
bridgeLineGapDistance: 0.05,
bridgeLineGapDistanceMax: 25,
// Bounds default margin nearTo
// Polygon.offset mindist2 offset precision
precision_offset: 0.05,
// Polygon.isEquivalent area() isCloseTo
precision_poly_area: 0.05,
// Polygon.isEquivalent bounds() equals value
precision_poly_bounds: 0.01,
// Polygon.isEquivalent point distance to other poly line
precision_poly_merge: 0.05,
// Polygon.traceIntersects mindist2
// Polygon.overlaps (bounds overlaps test precision)
// Polygon.isEquivalent circularity (is circle if 1-this < merge)
// Slope.isSame (vert/horiz w/in this value)
// isCloseTo() default for dist
// sliceIntersects point merge dist for non-fill
precision_merge: 0.005,
precision_slice_z: 0.0001,
// Point.isInPolygon nearPolygon value
// Point.isInPolygonNotNear nearPolygon value
// Point.isMergable2D distToSq2D value
// Point.isMergable3D distToSq2D value
// Polygon.isInside nearPolygon value
// Polygon.isOutside nearPolygon value
precision_merge_sq: sqr(0.005),
// Bound.isNested inflation value for potential parent
precision_bounds: 0.0001,
// Slope.isSame default precision
precision_slope: 0.02,
// Slope.isSame use to calculate precision
precision_slope_merge: 0.25,
// sliceIntersect point merge distance for fill
precision_fill_merge: 0.001,
// convertPoints point merge distance
// other values break cube-s9 (wtf)
precision_decimate: 0.05,
// decimate test over this many points
decimate_threshold: 500000,
// Point.onLine precision distance (endpoints in Polygon.intersect)
precision_point_on_line: 0.01,
// Polygon.isEquivalent value for determining similar enough to test
precision_circularity: 0.001,
// polygon fill hinting (settings override)
hint_len_min: sqr(3),
hint_len_max: sqr(20),
hint_min_circ: 0.15,
// tolerances to determine if a point is near a masking polygon
precision_mask_tolerance: 0.001,
// Polygon isInside,isOutside tolerance (accounts for midpoint skew)
precision_close_to_poly_sq: sqr(0.001),
// how long a segment has to be to trigger a midpoint check (inner/outer)
precision_midpoint_check_dist: 1,
precision_nested_sq: sqr(0.01),
// clipper multiplier
clipper: 100000,
// clipper poly clean
clipperClean: 250
},
key: {
NONE: "",
PROJECT: "project",
SEGINT: "segint",
RAYINT: "rayint",
PARALLEL: "parallel"
},
util: {
time,
lerp,
pwait,
ptimer,
numOrDefault,
doCombinations,
isClockwise,
isCounterClockwise,
pac,
area2,
isCloseTo,
inCloseRange,
sqr,
rotate,
toRadians,
toDegrees,
dist2D,
distSq,
distSqv2,
offsetPrecision,
inRange,
round,
clamp,
intersect,
intersectRayLine,
determinant,
zInPlane,
circleCenter,
determinant33,
center2d,
center2pr,
thetaDiff,
orderClosest,
triangulate,
flatten,
comma
},
paths: {
pointsToPath: function(points, offset, open, miter = 1.5) {
const absoff = Math.abs(offset);
// calculate segment normals which are used to calculate vertex normals
// next segment info is associated with the current point
const nupoints = [];
const length = points.length;
if (length === 2 && points[0].isEqual(points[1])) {
return { };
}
const dedup = (open && length > 2) || (!open && length > 3);
for (let i=0; i<length; i++) {
let p1 = points[i];
let p2 = points[(i + 1) % length];
p1.normal = calc_normal(p1, p2);
// drop next duplicate point if segment length is 0
// is possible there are 3 dups in a row and this is
// not handled. could make if a while, but that could
// end up in a loop without additional checks. ignore
// the case when the last and first point are the same
// which is valid when the line is an open path
if (dedup && p1.normal.len === 0 && i !== length - 1) {
p1.normal = calc_normal(p1, points[(i + 2) % length]);
i++;
}
nupoints.push(p1);
}
if (nupoints.length === 1) {
console.log({points, nupoints});
}
// when points are dropped, we need the new array
points = nupoints;
// generate left / right paths and triangle faces
const left = [];
const right = [];
const faces = [];
const normals = [];
const zn = -1;
// calculate vertex normals from segments normals
// vertex info is associated with the origin point
let fl, fr;
for (let i=0, l=points.length; i<l; i++) {
let n1 = points[(i+l-1)%l].normal;
let n2 = points[(i+l)%l].normal;
let vn = open && (i === 0 || i === l-1) ?
end_vertex(n1, n2, offset, i === 0) :
calc_vertex(n1, n2, offset);
let { p1, p2 } = n2;
let { io, vl } = vn;
if (offset < 0) {
io = -io;
}
let split_left = false, split_right = false;
if (io > 0) { // right
split_left = vl > absoff * miter;
split_right = vl > Math.min(n1.len, n2.len) + absoff;
} else { // left
split_right = vl > absoff * miter;
split_left = vl > Math.min(n1.len, n2.len) + absoff;
}
let l0 = left.peek(1);
let r0 = right.peek(1);
if (split_left || split_right) {
// shorten each leg and insert new point
let delta = 0.1;
let np1 = p1.clone().move({ x: n1.dy * delta, y: -n1.dx * delta, z: 0 });
let np2 = p1.clone().move({ x:-n2.dy * delta, y: n2.dx * delta, z: 0 });
let sn1 = np1.normal = calc_normal(np1, np2);
let sn2 = np2.normal = p1.normal;
let nv1 = calc_vertex(n1.p1.normal, sn1, offset, np1);
let nv2 = calc_vertex(sn1, sn2, offset, np2);
if (split_right) {
right.push(v2pr(nv1), v2pr(nv2));
} else {
right.push(v2pr(vn));
}
if (split_left) {
left.push(v2pl(nv1), v2pl(nv2));
} else {
left.push(v2pl(vn));
}
if (faces) {
let l1 = left.peek(1);
let r1 = right.peek(1);
let l2 = left.peek(2);
let r2 = right.peek(2);
faces.push([l0, r0, l1], [r0, r1, l1], [l1, r1, l2], [r1, r2, l2]);
}
} else {
if (split_right) {
right.push(v2pr(vn));
} else {
right.push(v2pr(vn));
}
if (split_left) {
left.push(v2pl(vn));
} else {
left.push(v2pl(vn));
}
if (faces) {
let l1 = left.peek(1);
let r1 = right.peek(1);
faces.push([l0, r0, l1], [r0, r1, l1]);
}
}
}
return { left, right, faces, normals };
},
pathTo3D: function(path, height, z) {
const { left, right, faces } = path;
const vertices = [];
const normals = [];
const uvs = [];
const indices = [];
let i, j, k, l, r, f, v, n, u;
// add left and right vertices
for (i = 0; i < left.length; i++) {
l = left[i];
r = right[i];
v = [l.x, l.y, z, r.x, r.y, z];
n = [0, 0, 1, 0, 0, 1];
u = [0, 0, 1, 0];
vertices.push(...v);
normals.push(...n);
uvs.push(...u);
}
// add top vertices
for (i = 0; i < left.length; i++) {
l = left[i];
r = right[i];
v = [l.x, l.y, z + height, r.x, r.y, z + height];
n = [0, 0, 1, 0, 0, 1];
u = [0, 1, 1, 1];
vertices.push(...v);
normals.push(...n);
uvs.push(...u);
}
// add faces
for (i = 0; i < faces.length; i++) {
f = faces[i];
indices.push(f[0], f[1], f[2]);
}
// add top faces
for (i = 0; i < faces.length; i++) {
f = faces[i];
indices.push(f[0] + left.length, f[1] + left.length, f[2] + left.length);
}
// add side faces
for (i = 0; i < left.length - 1; i++) {
j = i * 2;
k = j + 2;
indices.push(j, k, j + 1, j + 1, k, k + 1);
}
return { vertices, normals, uvs, indices };
}
},
newPoint
/** ******************************************************************
* Connect to base
******************************************************************* */
export const key = {
NONE: "",
PROJECT: "project",
SEGINT: "segint",
RAYINT: "rayint",
PARALLEL: "parallel"
};
// Helper functions for paths
function calc_normal(p1, p2) {
let dx = p2.x - p1.x;
let dy = p2.y - p1.y;
let len = Math.sqrt(dx * dx + dy * dy);
let mn = (1 / len);
dx *= mn;
dy *= mn;
return({ dx: dy, dy: -dx, p1, p2, len });
}
export const config = {
// size of gcode debug arrow head
debug_arrow: 0.25,
// default # of decimal places in generated gcode
gcode_decimals: 4,
// heal disjoint polygons in slicing (experimental)
bridgeLineGapDistance: 0.05,
bridgeLineGapDistanceMax: 25,
// Bounds default margin nearTo
// Polygon.offset mindist2 offset precision
precision_offset: 0.05,
// Polygon.isEquivalent area() isCloseTo
precision_poly_area: 0.05,
// Polygon.isEquivalent bounds() equals value
precision_poly_bounds: 0.01,
// Polygon.isEquivalent point distance to other poly line
precision_poly_merge: 0.05,
// Polygon.traceIntersects mindist2
// Polygon.overlaps (bounds overlaps test precision)
// Polygon.isEquivalent circularity (is circle if 1-this < merge)
// Slope.isSame (vert/horiz w/in this value)
// isCloseTo() default for dist
// sliceIntersects point merge dist for non-fill
precision_merge: 0.005,
precision_slice_z: 0.0001,
// Point.isInPolygon nearPolygon value
// Point.isInPolygonNotNear nearPolygon value
// Point.isMergable2D distToSq2D value
// Point.isMergable3D distToSq2D value
// Polygon.isInside nearPolygon value
// Polygon.isOutside nearPolygon value
precision_merge_sq: sqr(0.005),
// Bound.isNested inflation value for potential parent
precision_bounds: 0.0001,
// Slope.isSame default precision
precision_slope: 0.02,
// Slope.isSame use to calculate precision
precision_slope_merge: 0.25,
// sliceIntersect point merge distance for fill
precision_fill_merge: 0.001,
// convertPoints point merge distance
// other values break cube-s9 (wtf)
precision_decimate: 0.05,
// decimate test over this many points
decimate_threshold: 500000,
// Point.onLine precision distance (endpoints in Polygon.intersect)
precision_point_on_line: 0.01,
// Polygon.isEquivalent value for determining similar enough to test
precision_circularity: 0.001,
// polygon fill hinting (settings override)
hint_len_min: sqr(3),
hint_len_max: sqr(20),
hint_min_circ: 0.15,
// tolerances to determine if a point is near a masking polygon
precision_mask_tolerance: 0.001,
// Polygon isInside,isOutside tolerance (accounts for midpoint skew)
precision_close_to_poly_sq: sqr(0.001),
// how long a segment has to be to trigger a midpoint check (inner/outer)
precision_midpoint_check_dist: 1,
precision_nested_sq: sqr(0.01),
// clipper multiplier
clipper: 100000,
// clipper poly clean
clipperClean: 250
};
function end_vertex(n1, n2, off, start) {
let dx, dy;
if (start) {
dx = n2.dx * off;
dy = n2.dy * off;
} else {
dx = n1.dx * off;
dy = n1.dy * off;
}
return { dx, dy, vp: n1.p2 };
}
export const util = {
sqr,
lerp,
time,
clamp,
comma,
round,
area2,
pwait,
ptimer,
flatten,
rotate,
distSq,
dist2D,
distSqv2,
center2d,
center2pr,
determinant,
orderClosest,
doCombinations,
offsetPrecision,
circleCenter,
numOrDefault,
toRadians,
toDegrees,
thetaDiff,
intersect,
inRange,
isCloseTo,
inCloseRange,
isClockwise,
isCounterClockwise,
intersectRayLine,
triangulate,
zInPlane
};
function calc_vertex(n1, n2, off, vp) {
let dx, dy, io, vl, q, r;
r = 1 + (n1.dx * n2.dx + n1.dy * n2.dy);
q = off / r;
// handle spurs that switch back 180 degrees
if (q === Infinity) {
q = 0;
}
dx = (n1.dx + n2.dx) * q;
dy = (n1.dy + n2.dy) * q;
// io tells us whether we're turning left or right
io = (n1.dx * n2.dy - n2.dx * n1.dy);
// vertex length can be compared to the previons and next
// segment lengths to see if we're highly acute
vl = Math.sqrt(dx * dx + dy * dy);
return { dx, dy, vp: vp || n1.p2, io, vl };
}
export const base = {
config,
key,
util
};
function v2pl(rec) {
let p = rec.vp.clone();
p.x += rec.dx;
p.y += rec.dy;
p.vp = rec.vp;
return p;
}
function v2pr(rec) {
let p = rec.vp.clone();
p.x -= rec.dx;
p.y -= rec.dy;
p.vp = rec.vp;
return p;
}
export { base, earcut };
export const { config, key, util, paths } = base;
export { earcut };

View file

@ -1,11 +1,7 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
import { base } from './base.js';
const { util, config } = base;
const { sqr, numOrDefault } = util;
const DEG2RAD = Math.PI / 180;
import { newPoint } from './point.js';
/**
* emit each element in an array based on
@ -643,3 +639,12 @@ export class FloatPacker {
}
}
}
export const paths = {
tip2tipEmit,
poly2polyEmit,
shapeToPath,
pointsToPath,
pathTo3D,
FloatPacker
}

View file

@ -5,6 +5,7 @@
import { base, config, earcut, util } from './base.js';
import { ClipperLib } from '../ext/clip2.esm.js';
import { newBounds } from './bounds.js';
import { paths } from './paths.js';
import { newPoint, pointFromClipper } from './point.js';
import { polygons as POLY } from './polygons.js';
@ -70,11 +71,11 @@ export class Polygon {
}
toPath2D(offset) {
return base.paths.pointsToPath(this.points, offset, this.open);
return paths.pointsToPath(this.points, offset, this.open);
}
toPath3D(offset, height, z) {
return base.paths.pathTo3D(this.toPath2D(offset), height, z);
return paths.pathTo3D(this.toPath2D(offset), height, z);
}
toString(verbose) {
@ -461,7 +462,7 @@ export class Polygon {
return polys
.filter(poly => poly.length > 1)
.map(poly => {
let np = base.newPolygon().setOpen();
let np = newPolygon().setOpen();
for (let p of poly) {
np.push(p);
}

View file

@ -2,13 +2,15 @@
"use strict";
import { base, util, paths, config } from './base.js';
import { base, util, config } from './base.js';
import { newPoint, pointFromClipper } from './point.js';
import { newPolygon } from './polygon.js';
import { newSlope } from './slope.js';
import { paths } from './paths.js';
import { ClipperLib } from '../ext/clip2.esm.js';
const { sqr, numOrDefault } = util;
const geo = base;
const { numOrDefault } = util;
const DEG2RAD = Math.PI / 180,
SQRT = Math.sqrt,

View file

@ -2,11 +2,13 @@
import { base, util } from '../../geo/base.js';
import { poly2polyEmit, tip2tipEmit } from '../../geo/paths.js';
import { newBounds } from '../../geo/bounds.js';
import { newPoint } from '../../geo/point.js';
import { newPolygon, Polygon } from '../../geo/polygon.js';
import { polygons as POLY, fillArea } from '../../geo/polygons.js';
import { newPrint } from '../../kiri/print.js';
import { newSlice } from '../../kiri/slice.js';
import { newWidget } from '../../kiri/widget.js';
import { render } from '../../kiri/render.js';
import { getRangeParameters } from './driver.js';
@ -201,7 +203,7 @@ export async function fdm_prepare(widgets, settings, update) {
}
}
// recompute bounds for purge block offsets
let bbounds = base.newBounds();
let bbounds = newBounds();
brims.forEach(brim => {
bbounds.merge(brim.bounds);
});
@ -232,7 +234,7 @@ export async function fdm_prepare(widgets, settings, update) {
sslices.push(sslice);
}
if (sslices.length) {
let swidget = kiri.newWidget(null,widget.group);
let swidget = newWidget(null,widget.group);
swidget.slices = sslices;
swidget.support = true;
swidget.belt = widget.belt;

View file

@ -1510,7 +1510,8 @@ function doFillArea(fillQ, polys, angle, spacing, output, minLen, maxLen) {
* calculate external overhangs requiring support
*/
async function doSupport(slice, proc, shadow, opt = {}) {
let maxBridge = proc.sliceSupportSpan || 5,
let { minions } = self.kiri_worker,
maxBridge = proc.sliceSupportSpan || 5,
minArea = proc.supportMinArea || 0.1,
pillarSize = proc.sliceSupportSize,
offset = proc.sliceSupportOffset || 0,

View file

@ -695,7 +695,7 @@ dispatch.onmessage = self.onmessage = async function(e) {
msg = e.data || {},
run = dispatch[msg.task],
send = {
data : function(data,direct) {
data : function(data, direct) {
// if (direct && direct.length) {
// console.log( direct.map(z => z.byteLength).reduce((a,v) => a+v) );
// }

View file

@ -111,7 +111,7 @@ export const client = {
running = {};
worker = client.newWorker();
client.onmessage = worker.onmessage = function(e) {
client.onmessage = worker.onmessage = (e) => {
let now = time(),
reply = e.data,
record = running[reply.seq],

View file

@ -1,6 +1,6 @@
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
import { newPolygon } from '../geo/polygon.js';
import { newPolygon, Polygon } from '../geo/polygon.js';
import { polygons as POLY } from '../geo/polygons.js';
export class Layers {
@ -78,7 +78,7 @@ export class Layers {
options.open = true;
const polys = [];
for (let i=0; i<lines.length-1; i += 2) {
polys.push(new base.Polygon()
polys.push(new Polygon()
.append(lines[i])
.append(lines[i+1])
.setOpen());
@ -94,11 +94,14 @@ export class Layers {
// an open or closed polygon
addPoly(poly, options) {
return this.addPolys([poly], options);
return this.addPolys([ poly ], options);
}
// a polygon rendered as a webgl line
addPolys(polys, options) {
if (!Array.isArray(polys)) {
throw "polys must be an array";
}
if (polys.length === 0) {
return this;
}
@ -170,8 +173,7 @@ export class Layers {
p1.setZ(poly.z);
p2.setZ(poly.z);
}
this.addPolys(p1);
this.addPolys(p2);
this.addPolys([ p1, p2 ]);
}
const color = opts.color ?
(typeof(opts.color) === 'number' ? { line: opts.color, face: opts.color } : opts.color) :

View file

@ -129,6 +129,7 @@ async function path(levels, update, opts = {}) {
const lasers = [];
const sparks = [];
const output = new Layers();
layers.push(output);
const pushPrint = (toolid, poly) => {

View file

@ -752,12 +752,11 @@ class Widget {
*/
render(stack) {
const mark = Date.now();
if (this.slices)
this.slices.forEach(slice => {
for (let slice of this.slices || []) {
if (slice.layers) {
stack.add(slice.layers);
}
});
}
return Date.now() - mark;
}

View file

@ -2186,11 +2186,13 @@ details[open] summary::after {
}
#slider-zero {
z-index: 10;
min-width: 3em;
background-color: #bbb;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
#slider-max {
min-width: 3em;
background-color: #bbb;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;

View file

@ -24,7 +24,6 @@
<link href="../font/css/all.min.css" rel="stylesheet">
<!-- <script type="module" src="/v2/lib/kiri-run/worker.js"></script> -->
<!-- <script type="module" src="/v2/lib/kiri-run/minion.js"></script> -->
<!-- <script src="../lib/ext/earcut.js" type="module"></script> -->
<script src="../lib/ext/tween.js"></script>
<script src="../font/js/all.min.js" crossorigin="anonymous" defer></script>
<script src="../lib/main/kiri.js" type="module"></script>