@tracespace/plotter
Version:
Plot @tracespace/parser ASTs into image trees.
665 lines (664 loc) • 18.4 kB
JavaScript
import { COMMENT as Ct, GRAPHIC as F, LEADING as B, TRAILING as j, COORDINATE_FORMAT as Pt, UNITS as Rt, IN as Tt, TOOL_MACRO as St, TOOL_DEFINITION as J, MACRO_SHAPE as Lt, TOOL_CHANGE as It, POLYGON as Nt, OBROUND as K, RECTANGLE as Gt, CIRCLE as vt, MACRO_VARIABLE as bt, MACRO_PRIMITIVE as Dt, MACRO_THERMAL as wt, MACRO_MOIRE_DEPRECATED as Ft, MACRO_POLYGON as Ht, MACRO_OUTLINE as zt, MACRO_LOWER_LEFT_LINE_DEPRECATED as Bt, MACRO_CENTER_LINE as jt, MACRO_VECTOR_LINE_DEPRECATED as Wt, MACRO_VECTOR_LINE as Vt, MACRO_CIRCLE as qt, DRILL as $t, SHAPE as I, SEGMENT as G, SLOT as kt, INTERPOLATE_MODE as st, QUADRANT_MODE as Yt, SINGLE as Ut, REGION_MODE as Z, DONE as Xt, MOVE as W, CW_ARC as ct, CCW_ARC as ot, LINE as Qt } from "@tracespace/parser";
const Jt = "image", v = "imageShape", it = "imagePath", Kt = "imageRegion", O = "line", g = "arc", S = "circle", H = "rectangle", M = "polygon", z = "outline", Y = "layeredShape", { PI: T } = Math, P = T / 2, at = 3 * P, A = 2 * T;
function V(t) {
return t >= 0 && t <= A ? t : t < 0 ? t + A : t > A ? t - A : V(t);
}
function tt(t) {
return t >= P ? t - P : t + at;
}
function ut(t) {
return t * Math.PI / 180;
}
function C(t, e, n = 0) {
const r = ut(n), [c, s] = [Math.sin(r), Math.cos(r)], [o, i] = t, a = o * s - i * c + e[0], p = o * c + i * s + e[1];
return [a, p];
}
function pt(t, e) {
return t[0] === e[0] && t[1] === e[1];
}
function q(t) {
return t.length === 0;
}
function ft() {
return [];
}
function yt(t, e) {
return q(t) ? e : q(e) ? t : [
Math.min(t[0], e[0]),
Math.min(t[1], e[1]),
Math.max(t[2], e[2]),
Math.max(t[3], e[3])
];
}
function N(t) {
return t.reduce(yt, ft());
}
function ht(t) {
return N(t.map(lt));
}
function lt(t) {
return t.type === v ? U(t.shape) : X(
t.segments,
t.type === it ? t.width : void 0
);
}
function U(t) {
switch (t.type) {
case S: {
const { cx: e, cy: n, r } = t;
return $([e, n], r);
}
case H: {
const { x: e, y: n, xSize: r, ySize: c } = t;
return [e, n, e + r, n + c];
}
case M:
return N(t.points.map((e) => $(e)));
case z:
return X(t.segments);
case Y:
return N(t.shapes.filter(({ erase: e }) => !e).map(U));
}
}
function X(t, e = 0) {
const n = e / 2, r = [];
for (const c of t)
if (r.push(c.start, c.end), c.type === g) {
const { start: s, end: o, center: i, radius: a } = c, p = Math.abs(o[2] - s[2]);
let [f, u] = o[2] > s[2] ? [s[2], o[2]] : [o[2], s[2]];
f = V(f), u = V(u);
const l = [
[i[0] + a, i[1]],
[i[0], i[1] + a],
[i[0] - a, i[1]],
[i[0], i[1] - a]
];
for (const y of l)
(f > u || p === A) && r.push(y), f = tt(f), u = tt(u);
}
return N(r.map((c) => $(c, n)));
}
function $(t, e = 0) {
return [
t[0] - e,
t[1] - e,
t[0] + e,
t[1] + e
];
}
const Ce = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
add: yt,
empty: ft,
fromGraphic: lt,
fromGraphics: ht,
fromPath: X,
fromShape: U,
isEmpty: q,
sum: N
}, Symbol.toStringTag, { value: "Module" })), Zt = /FORMAT={?(\d):(\d)/;
function te(t) {
const { children: e } = t;
let n = null, r = null, c = null, s = 0;
for (; s < e.length && (n === null || r === null || c === null); ) {
const o = e[s];
switch (o.type) {
case Rt: {
n = o.units;
break;
}
case Pt: {
r = o.format, c = o.zeroSuppression;
break;
}
case F: {
const { coordinates: i } = o;
for (const a of Object.values(i)) {
if (c !== null)
break;
a.endsWith("0") || a.includes(".") ? c = B : a.startsWith("0") && (c = j);
}
break;
}
case Ct: {
const { comment: i } = o, a = Zt.exec(i);
/suppress trailing/i.test(i) ? c = j : /(suppress leading|keep zeros)/i.test(i) && (c = B), a && (r = [Number(a[1]), Number(a[2])]);
break;
}
}
s += 1;
}
return {
units: n ?? Tt,
coordinateFormat: r ?? [2, 4],
zeroSuppression: c ?? B
};
}
const b = "simpleTool", dt = "macroTool";
function ee() {
return Object.create(ne);
}
const ne = {
_currentToolCode: void 0,
_toolsByCode: {},
_macrosByName: {},
use(t) {
if (t.type === St && (this._macrosByName[t.name] = t.children), t.type === J) {
const { shape: e, hole: n } = t, r = e.type === Lt ? {
type: dt,
macro: this._macrosByName[e.name] ?? [],
variableValues: e.variableValues
} : { type: b, shape: e, ...n && { hole: n } };
this._toolsByCode[t.code] = r;
}
return (t.type === J || t.type === It) && (this._currentToolCode = t.code), typeof this._currentToolCode == "string" ? this._toolsByCode[this._currentToolCode] : void 0;
}
};
function re() {
return Object.create(se);
}
const se = {
_DEFAULT_ARC_OFFSETS: { i: 0, j: 0, a: 0 },
_previousPoint: { x: 0, y: 0 },
use(t, e) {
let n = this._DEFAULT_ARC_OFFSETS, r = this._previousPoint, c = r;
if (t.type === F) {
const { coordinates: s } = t, o = R(s.x0, r.x, e), i = R(s.y0, r.y, e), a = R(s.x, o, e), p = R(s.y, i, e), f = R(s.i, 0, e), u = R(s.j, 0, e), l = R(s.a, 0, e);
(r.x !== o || r.y !== i) && (r = { x: o, y: i }), (c.x !== a || c.y !== p) && (c = { x: a, y: p }), (f !== 0 || u !== 0 || l !== 0) && (n = { i: f, j: u, a: l });
}
return this._previousPoint = c, { startPoint: r, endPoint: c, arcOffsets: n };
}
};
function R(t, e, n) {
if (typeof t != "string")
return e;
if (t.includes(".") || t === "0")
return Number(t);
const { coordinateFormat: r, zeroSuppression: c } = n, [s, o] = r, [i, a] = t.startsWith("+") || t.startsWith("-") ? [t[0], t.slice(1)] : ["+", t], p = s + o, f = c === j ? a.padEnd(p, "0") : a.padStart(p, "0"), u = f.slice(0, s), l = f.slice(s);
return Number(`${i}${u}.${l}`);
}
function et(t, e) {
const { x: n, y: r } = e;
switch (t.type) {
case vt: {
const { diameter: c } = t;
return { type: S, cx: n, cy: r, r: c / 2 };
}
case Gt:
case K: {
const { xSize: c, ySize: s } = t, o = c / 2, i = s / 2, a = {
type: H,
x: n - o,
y: r - i,
xSize: c,
ySize: s
};
return t.type === K && (a.r = Math.min(o, i)), a;
}
case Nt: {
const { diameter: c, rotation: s, vertices: o } = t, i = c / 2, a = ut(s ?? 0), p = A / o, f = Array.from({ length: o }).map(
(u, l) => {
const y = p * l + a, h = n + i * Math.cos(y), _ = r + i * Math.sin(y);
return [h, _];
}
);
return { type: M, points: f };
}
}
}
function k(t) {
if (t.type === S) {
const { cx: e, cy: n, r } = t;
return [
{
type: g,
start: [e + r, n, 0],
end: [e + r, n, A],
center: [e, n],
radius: r
}
];
}
if (t.type === H) {
const { x: e, y: n, xSize: r, ySize: c, r: s } = t;
return s === r / 2 ? [
{
type: O,
start: [e + r, n + s],
end: [e + r, n + c - s]
},
{
type: g,
start: [e + r, n + c - s, 0],
end: [e, n + c - s, T],
center: [e + s, n + c - s],
radius: s
},
{ type: O, start: [e, n + c - s], end: [e, n + s] },
{
type: g,
start: [e, n + s, T],
end: [e + r, n + s, A],
center: [e + s, n + s],
radius: s
}
] : s === c / 2 ? [
{ type: O, start: [e + s, n], end: [e + r - s, n] },
{
type: g,
start: [e + r - s, n, -P],
end: [e + r - s, n + c, P],
center: [e + r - s, n + s],
radius: s
},
{
type: O,
start: [e + r - s, n + c],
end: [e + s, n + c]
},
{
type: g,
start: [e + s, n + c, P],
end: [e + s, n, at],
center: [e + s, n + s],
radius: s
}
] : [
{ type: O, start: [e, n], end: [e + r, n] },
{ type: O, start: [e + r, n], end: [e + r, n + c] },
{ type: O, start: [e + r, n + c], end: [e, n + c] },
{ type: O, start: [e, n + c], end: [e, n] }
];
}
return t.type === M ? t.points.map((e, n) => {
const r = n < t.points.length - 1 ? n + 1 : 0;
return { type: O, start: e, end: t.points[r] };
}) : t.segments;
}
function ce(t, e) {
const { shape: n, hole: r } = t, c = et(n, e.endPoint), s = r ? et(r, e.endPoint) : void 0;
return s === void 0 ? c : {
type: z,
segments: [...k(c), ...k(s)]
};
}
function oe(t, e) {
const n = t.filter((r) => r.type === O).map((r) => ie(r, e));
return { type: v, shape: { type: Y, shapes: n } };
}
function ie(t, e) {
const { start: n, end: r } = t, [c, s] = n, [o, i] = r, [a, p] = [e.xSize / 2, e.ySize / 2], f = Math.atan2(i - s, o - i), [u, l] = [c - a, c + a], [y, h] = [s - p, s + p], [_, E] = [o - a, o + a], [m, x] = [i - p, i + p];
let d = [];
return pt(n, r) ? d = [
[u, y],
[l, y],
[E, m],
[E, x],
[_, x],
[u, h]
] : f >= 0 && f < P ? d = [
[u, y],
[l, y],
[E, m],
[E, x],
[_, x],
[u, h]
] : f >= P && f <= T ? d = [
[l, y],
[l, h],
[E, x],
[_, x],
[_, m],
[u, y]
] : f >= -T && f < -P ? d = [
[l, h],
[u, h],
[_, x],
[_, m],
[E, m],
[l, y]
] : d = [
[u, h],
[u, y],
[_, m],
[E, m],
[E, x],
[l, h]
], { type: M, points: d };
}
const _t = "cw", Q = "ccw";
function nt(t, e, n) {
return e === void 0 ? xt(t) : ae(t, e, n);
}
function rt(t, e, n = !1) {
if (t.length > 0) {
if (n)
return { type: Kt, segments: t };
if ((e == null ? void 0 : e.type) === b && e.shape.type === S)
return { type: it, width: e.shape.diameter, segments: t };
if ((e == null ? void 0 : e.type) === b && e.shape.type === H)
return oe(t, e.shape);
}
}
function xt(t) {
return {
type: O,
start: [t.startPoint.x, t.startPoint.y],
end: [t.endPoint.x, t.endPoint.y]
};
}
function ae(t, e, n = !1) {
const { startPoint: r, endPoint: c, arcOffsets: s } = t, o = s.a > 0 ? s.a : (s.i ** 2 + s.j ** 2) ** 0.5;
if (n || s.a > 0) {
if (r.x === c.x && r.y === c.y)
return xt(t);
const [u, l, y] = ue(t, o).map((h) => D(r, c, h, e)).sort(([h, _], [E, m]) => {
const x = Math.abs(_[2] - h[2]), d = Math.abs(m[2] - E[2]);
return x - d;
})[0];
return { type: g, start: u, end: l, center: y, radius: o };
}
const i = {
x: r.x + s.i,
y: r.y + s.j
}, [a, p, f] = D(
r,
c,
i,
e
);
return { type: g, start: a, end: p, center: f, radius: o };
}
function D(t, e, n, r) {
let c = Math.atan2(
t.y - n.y,
t.x - n.x
), s = Math.atan2(
e.y - n.y,
e.x - n.x
);
return r === Q ? s = s > c ? s : s + A : c = c > s ? c : c + A, [
[t.x, t.y, c],
[e.x, e.y, s],
[n.x, n.y]
];
}
function ue(t, e) {
const { x: n, y: r } = t.startPoint, { x: c, y: s } = t.endPoint, [o, i] = [c - n, s - r], [a, p] = [c + n, s + r], f = Math.sqrt(o ** 2 + i ** 2);
if (e <= f / 2)
return [{ x: n + o / 2, y: r + i / 2 }];
const u = Math.sqrt(4 * e ** 2 / f ** 2 - 1), [l, y] = [a / 2, p / 2], [h, _] = [i * u / 2, o * u / 2];
return [
{ x: l + h, y: y - _ },
{ x: l - h, y: y + _ }
];
}
function pe(t, e) {
const n = [], r = Object.fromEntries(
t.variableValues.map((c, s) => [`$${s + 1}`, c])
);
for (const c of t.macro)
if (c.type === bt && (r[c.name] = w(c.value, r)), c.type === Dt) {
const s = [e.endPoint.x, e.endPoint.y], o = c.parameters.map((i) => w(i, r));
n.push(...fe(c.code, s, o));
}
return { type: Y, shapes: n };
}
function w(t, e) {
if (typeof t == "number")
return t;
if (typeof t == "string")
return e[t];
const n = w(t.left, e), r = w(t.right, e);
switch (t.operator) {
case "+":
return n + r;
case "-":
return n - r;
case "x":
return n * r;
case "/":
return n / r;
}
}
function fe(t, e, n) {
switch (t) {
case qt:
return [ye(e, n)];
case Vt:
case Wt:
return [he(e, n)];
case jt:
return [le(e, n)];
case Bt:
return [de(e, n)];
case zt:
return [_e(e, n)];
case Ht:
return [xe(e, n)];
case Ft:
return me(e, n);
case wt:
return [Ee(e, n)];
}
return [];
}
function ye(t, e) {
const [n, r, c, s, o] = e, i = r / 2, [a, p] = C([c, s], t, o);
return { type: S, erase: n === 0, cx: a, cy: p, r: i };
}
function he(t, e) {
const [n, r, c, s, o, i, a] = e, [p, f] = [i - s, o - c], u = r / 2, l = Math.sqrt(p ** 2 + f ** 2), [y, h] = [u * f / l, u * p / l];
return {
type: M,
erase: n === 0,
points: [
[c + y, s - h],
[o + y, i - h],
[o - y, i + h],
[c - y, s + h]
].map((_) => C(_, t, a))
};
}
function le(t, e) {
const [n, r, c, s, o, i] = e, [a, p] = [r / 2, c / 2];
return {
type: M,
erase: n === 0,
points: [
[s - a, o - p],
[s + a, o - p],
[s + a, o + p],
[s - a, o + p]
].map((f) => C(f, t, i))
};
}
function de(t, e) {
const [n, r, c, s, o, i] = e;
return {
type: M,
erase: n === 0,
points: [
[s, o],
[s + r, o],
[s + r, o + c],
[s, o + c]
].map((a) => C(a, t, i))
};
}
function _e(t, e) {
const [n, , ...r] = e.slice(0, -1), c = e[e.length - 1];
return {
type: M,
erase: n === 0,
points: r.flatMap(
(s, o) => o % 2 === 1 ? [[r[o - 1], s]] : []
).map((s) => C(s, t, c))
};
}
function xe(t, e) {
const [n, r, c, s, o, i] = e, a = o / 2, p = 2 * T / r, f = [];
let u;
for (u = 0; u < r; u++) {
const l = p * u, y = c + a * Math.cos(l), h = s + a * Math.sin(l);
f.push(C([y, h], t, i));
}
return { type: M, erase: n === 0, points: f };
}
function me(t, e) {
const n = (x) => C(x, t, e[8]), [r, c, s, o, i, a, p, f] = e, [u, l] = n([r, c]), y = p / 2, h = f / 2, _ = [];
let E = 0, m = s;
for (; m >= 0 && E < a; ) {
const x = m / 2, d = x - o;
_.push(x), d > 0 && _.push(d), E += 1, m = 2 * (d - i);
}
return [
{
type: z,
segments: _.flatMap((x) => k({ type: S, cx: u, cy: l, r: x }))
},
// Vertical stroke
{
type: M,
points: [
[r - y, c - h],
[r + y, c - h],
[r + y, c + h],
[r - y, c + h]
].map(n)
},
// Horizontal stroke
{
type: M,
points: [
[r - h, c - y],
[r + h, c - y],
[r + h, c + y],
[r - h, c + y]
].map(n)
}
];
}
function Ee(t, e) {
const [n, r, c, s, o, i] = e, a = C([n, r], t, i), [p, f] = [c / 2, s / 2], u = o / 2, l = p ** 2 - u ** 2, y = f ** 2 - u ** 2, h = Math.sqrt(l), _ = y >= 0 ? Math.sqrt(y) : u, E = [0, 90, 180, 270], m = [];
for (const x of E) {
const d = [
[_, u],
[h, u],
[u, h],
[u, _]
].map((L) => C(L, [n, r], x)).map((L) => C(L, t, i)), [Et, Ot, Mt] = D(
{ x: d[1][0], y: d[1][1] },
{ x: d[2][0], y: d[2][1] },
{ x: a[0], y: a[1] },
Q
);
if (m.push(
{ type: O, start: d[0], end: d[1] },
{ type: g, start: Et, end: Ot, center: Mt, radius: p },
{ type: O, start: d[2], end: d[3] }
), !pt(d[0], d[3])) {
const [L, gt, At] = D(
{ x: d[3][0], y: d[3][1] },
{ x: d[0][0], y: d[0][1] },
{ x: a[0], y: a[1] },
_t
);
m.push({
type: g,
start: L,
end: gt,
center: At,
radius: f
});
}
}
return { type: z, segments: m };
}
function Oe(t) {
const e = Object.create(Me);
return t === $t ? Object.assign(e, ge) : e;
}
const Me = {
_currentPath: void 0,
_arcDirection: void 0,
_ambiguousArcCenter: !1,
_regionMode: !1,
_defaultGraphic: void 0,
plot(t, e, n) {
const r = [], c = this._setGraphicState(t), s = this._plotCurrentPath(t, e, c);
if (s && r.push(s), c === I && (e == null ? void 0 : e.type) === b && r.push({ type: v, shape: ce(e, n) }), c === I && (e == null ? void 0 : e.type) === dt && r.push({ type: v, shape: pe(e, n) }), c === G && (this._currentPath = this._currentPath ?? {
segments: [],
region: this._regionMode,
tool: e
}, this._currentPath.segments.push(
nt(n, this._arcDirection, this._ambiguousArcCenter)
)), c === kt) {
const o = rt([nt(n)], e);
o && r.push(o);
}
return r;
},
_setGraphicState(t) {
if (t.type === st && (this._arcDirection = mt(t.mode)), t.type === Yt && (this._ambiguousArcCenter = t.quadrant === Ut), t.type === Z && (this._regionMode = t.region), t.type === F)
return t.graphic === G ? this._defaultGraphic = G : t.graphic !== null && (this._defaultGraphic = void 0), t.graphic ?? this._defaultGraphic;
},
_plotCurrentPath(t, e, n) {
if (this._currentPath !== void 0 && (e !== this._currentPath.tool || t.type === Z || t.type === Xt || n === W && this._currentPath.region || n === I && this._currentPath !== void 0)) {
const r = rt(
this._currentPath.segments,
this._currentPath.tool,
this._currentPath.region
);
return this._currentPath = void 0, r;
}
}
}, ge = {
_defaultGraphic: I,
_ambiguousArcCenter: !0,
_setGraphicState(t) {
if (t.type === st) {
const { mode: e } = t;
this._arcDirection = mt(e), e === ct || e === ot || e === Qt ? this._defaultGraphic = G : e === W ? this._defaultGraphic = W : this._defaultGraphic = I;
}
if (t.type === F)
return t.graphic ?? this._defaultGraphic;
}
};
function mt(t) {
if (t === ot)
return Q;
if (t === ct)
return _t;
}
function Pe(t) {
const e = te(t), n = ee(), r = re(), c = Oe(t.filetype), s = [];
for (const o of t.children) {
const i = n.use(o), a = r.use(o, e), p = c.plot(o, i, a);
s.push(...p);
}
return {
type: Jt,
units: e.units,
size: ht(s),
children: s
};
}
export {
g as ARC,
Ce as BoundingBox,
S as CIRCLE,
Jt as IMAGE,
it as IMAGE_PATH,
Kt as IMAGE_REGION,
v as IMAGE_SHAPE,
Y as LAYERED_SHAPE,
O as LINE,
z as OUTLINE,
M as POLYGON,
H as RECTANGLE,
A as TWO_PI,
Pe as plot,
pt as positionsEqual
};
//# sourceMappingURL=tracespace-plotter.js.map