hrithik18k/metal-touch-panel
A PCB autorouting wrapper that corrects footprint-trace obstacle dimensions, solves routes with a preloaded trace-graph solver, and reports completed traces or routing errors.
- Version
- 1.0.0
- License
- unset
- Stars
- 0
dist/index.js
import { jsx, jsxs } from 'react/jsx-runtime';
import { Fragment } from 'react';
var __create = Object.create;
var __getProtoOf = Object.getPrototypeOf;
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
function __accessProp(key) {
return this[key];
}
var __toESMCache_node;
var __toESM = (mod, isNodeMode, target) => {
var canCache = mod != null && typeof mod === "object";
if (canCache) {
var cache = __toESMCache_node ??= new WeakMap ;
var cached = cache.get(mod);
if (cached)
return cached;
}
target = mod != null ? __create(__getProtoOf(mod)) : {};
const to = __defProp(target, "default", { value: mod, enumerable: true }) ;
for (let key of __getOwnPropNames(mod))
if (!__hasOwnProp.call(to, key))
__defProp(to, key, {
get: __accessProp.bind(mod, key),
enumerable: true
});
if (canCache)
cache.set(mod, to);
return to;
};
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
if (typeof require !== "undefined")
return require.apply(this, arguments);
throw Error('Dynamic require of "' + x + '" is not supported');
});
// node_modules/object-hash/dist/object_hash.js
var require_object_hash = __commonJS((exports, module) => {
(function(e) {
var t;
typeof exports == "object" ? module.exports = e() : typeof define == "function" && define.amd ? define(e) : (typeof window != "undefined" ? t = window : typeof global != "undefined" ? t = global : typeof self != "undefined" && (t = self), t.objectHash = e());
})(function() {
return function r(o, i, u) {
function s(n, e2) {
if (!i[n]) {
if (!o[n]) {
var t = __require;
if (!e2 && t)
return t(n, true);
if (a)
return a(n, true);
throw new Error("Cannot find module '" + n + "'");
}
e2 = i[n] = { exports: {} };
o[n][0].call(e2.exports, function(e3) {
var t2 = o[n][1][e3];
return s(t2 || e3);
}, e2, e2.exports, r, o, i, u);
}
return i[n].exports;
}
for (var a = __require, e = 0;e < u.length; e++)
s(u[e]);
return s;
}({ 1: [function(w, b, m) {
(function(e, n, s, c, d, h, p, g, y) {
var r = w("crypto");
function t(e2, t2) {
t2 = u(e2, t2);
var n2;
return (n2 = t2.algorithm !== "passthrough" ? r.createHash(t2.algorithm) : new l).write === undefined && (n2.write = n2.update, n2.end = n2.update), f(t2, n2).dispatch(e2), n2.update || n2.end(""), n2.digest ? n2.digest(t2.encoding === "buffer" ? undefined : t2.encoding) : (e2 = n2.read(), t2.encoding !== "buffer" ? e2.toString(t2.encoding) : e2);
}
(m = b.exports = t).sha1 = function(e2) {
return t(e2);
}, m.keys = function(e2) {
return t(e2, { excludeValues: true, algorithm: "sha1", encoding: "hex" });
}, m.MD5 = function(e2) {
return t(e2, { algorithm: "md5", encoding: "hex" });
}, m.keysMD5 = function(e2) {
return t(e2, { algorithm: "md5", encoding: "hex", excludeValues: true });
};
var o = r.getHashes ? r.getHashes().slice() : ["sha1", "md5"], i = (o.push("passthrough"), ["buffer", "hex", "binary", "base64"]);
function u(e2, t2) {
var n2 = {};
if (n2.algorithm = (t2 = t2 || {}).algorithm || "sha1", n2.encoding = t2.encoding || "hex", n2.excludeValues = !!t2.excludeValues, n2.algorithm = n2.algorithm.toLowerCase(), n2.encoding = n2.encoding.toLowerCase(), n2.ignoreUnknown = t2.ignoreUnknown === true, n2.respectType = t2.respectType !== false, n2.respectFunctionNames = t2.respectFunctionNames !== false, n2.respectFunctionProperties = t2.respectFunctionProperties !== false, n2.unorderedArrays = t2.unorderedArrays === true, n2.unorderedSets = t2.unorderedSets !== false, n2.unorderedObjects = t2.unorderedObjects !== false, n2.replacer = t2.replacer || undefined, n2.excludeKeys = t2.excludeKeys || undefined, e2 === undefined)
throw new Error("Object argument required.");
for (var r2 = 0;r2 < o.length; ++r2)
o[r2].toLowerCase() === n2.algorithm.toLowerCase() && (n2.algorithm = o[r2]);
if (o.indexOf(n2.algorithm) === -1)
throw new Error('Algorithm "' + n2.algorithm + '" not supported. supported values: ' + o.join(", "));
if (i.indexOf(n2.encoding) === -1 && n2.algorithm !== "passthrough")
throw new Error('Encoding "' + n2.encoding + '" not supported. supported values: ' + i.join(", "));
return n2;
}
function a(e2) {
if (typeof e2 == "function")
return /^function\s+\w*\s*\(\s*\)\s*{\s+\[native code\]\s+}$/i.exec(Function.prototype.toString.call(e2)) != null;
}
function f(o2, t2, i2) {
i2 = i2 || [];
function u2(e2) {
return t2.update ? t2.update(e2, "utf8") : t2.write(e2, "utf8");
}
return { dispatch: function(e2) {
return this["_" + ((e2 = o2.replacer ? o2.replacer(e2) : e2) === null ? "null" : typeof e2)](e2);
}, _object: function(t3) {
var n2, e2 = Object.prototype.toString.call(t3), r2 = /\[object (.*)\]/i.exec(e2);
r2 = (r2 = r2 ? r2[1] : "unknown:[" + e2 + "]").toLowerCase();
if (0 <= (e2 = i2.indexOf(t3)))
return this.dispatch("[CIRCULAR:" + e2 + "]");
if (i2.push(t3), s !== undefined && s.isBuffer && s.isBuffer(t3))
return u2("buffer:"), u2(t3);
if (r2 === "object" || r2 === "function" || r2 === "asyncfunction")
return e2 = Object.keys(t3), o2.unorderedObjects && (e2 = e2.sort()), o2.respectType === false || a(t3) || e2.splice(0, 0, "prototype", "__proto__", "constructor"), o2.excludeKeys && (e2 = e2.filter(function(e3) {
return !o2.excludeKeys(e3);
})), u2("object:" + e2.length + ":"), n2 = this, e2.forEach(function(e3) {
n2.dispatch(e3), u2(":"), o2.excludeValues || n2.dispatch(t3[e3]), u2(",");
});
if (!this["_" + r2]) {
if (o2.ignoreUnknown)
return u2("[" + r2 + "]");
throw new Error('Unknown object type "' + r2 + '"');
}
this["_" + r2](t3);
}, _array: function(e2, t3) {
t3 = t3 !== undefined ? t3 : o2.unorderedArrays !== false;
var n2 = this;
if (u2("array:" + e2.length + ":"), !t3 || e2.length <= 1)
return e2.forEach(function(e3) {
return n2.dispatch(e3);
});
var r2 = [], t3 = e2.map(function(e3) {
var t4 = new l, n3 = i2.slice();
return f(o2, t4, n3).dispatch(e3), r2 = r2.concat(n3.slice(i2.length)), t4.read().toString();
});
return i2 = i2.concat(r2), t3.sort(), this._array(t3, false);
}, _date: function(e2) {
return u2("date:" + e2.toJSON());
}, _symbol: function(e2) {
return u2("symbol:" + e2.toString());
}, _error: function(e2) {
return u2("error:" + e2.toString());
}, _boolean: function(e2) {
return u2("bool:" + e2.toString());
}, _string: function(e2) {
u2("string:" + e2.length + ":"), u2(e2.toString());
}, _function: function(e2) {
u2("fn:"), a(e2) ? this.dispatch("[native]") : this.dispatch(e2.toString()), o2.respectFunctionNames !== false && this.dispatch("function-name:" + String(e2.name)), o2.respectFunctionProperties && this._object(e2);
}, _number: function(e2) {
return u2("number:" + e2.toString());
}, _xml: function(e2) {
return u2("xml:" + e2.toString());
}, _null: function() {
return u2("Null");
}, _undefined: function() {
return u2("Undefined");
}, _regexp: function(e2) {
return u2("regex:" + e2.toString());
}, _uint8array: function(e2) {
return u2("uint8array:"), this.dispatch(Array.prototype.slice.call(e2));
}, _uint8clampedarray: function(e2) {
return u2("uint8clampedarray:"), this.dispatch(Array.prototype.slice.call(e2));
}, _int8array: function(e2) {
return u2("int8array:"), this.dispatch(Array.prototype.slice.call(e2));
}, _uint16array: function(e2) {
return u2("uint16array:"), this.dispatch(Array.prototype.slice.call(e2));
}, _int16array: function(e2) {
return u2("int16array:"), this.dispatch(Array.prototype.slice.call(e2));
}, _uint32array: function(e2) {
return u2("uint32array:"), this.dispatch(Array.prototype.slice.call(e2));
}, _int32array: function(e2) {
return u2("int32array:"), this.dispatch(Array.prototype.slice.call(e2));
}, _float32array: function(e2) {
return u2("float32array:"), this.dispatch(Array.prototype.slice.call(e2));
}, _float64array: function(e2) {
return u2("float64array:"), this.dispatch(Array.prototype.slice.call(e2));
}, _arraybuffer: function(e2) {
return u2("arraybuffer:"), this.dispatch(new Uint8Array(e2));
}, _url: function(e2) {
return u2("url:" + e2.toString());
}, _map: function(e2) {
u2("map:");
e2 = Array.from(e2);
return this._array(e2, o2.unorderedSets !== false);
}, _set: function(e2) {
u2("set:");
e2 = Array.from(e2);
return this._array(e2, o2.unorderedSets !== false);
}, _file: function(e2) {
return u2("file:"), this.dispatch([e2.name, e2.size, e2.type, e2.lastModfied]);
}, _blob: function() {
if (o2.ignoreUnknown)
return u2("[blob]");
throw Error(`Hashing Blob objects is currently not supported
(see https://github.com/puleos/object-hash/issues/26)
Use "options.replacer" or "options.ignoreUnknown"
`);
}, _domwindow: function() {
return u2("domwindow");
}, _bigint: function(e2) {
return u2("bigint:" + e2.toString());
}, _process: function() {
return u2("process");
}, _timer: function() {
return u2("timer");
}, _pipe: function() {
return u2("pipe");
}, _tcp: function() {
return u2("tcp");
}, _udp: function() {
return u2("udp");
}, _tty: function() {
return u2("tty");
}, _statwatcher: function() {
return u2("statwatcher");
}, _securecontext: function() {
return u2("securecontext");
}, _connection: function() {
return u2("connection");
}, _zlib: function() {
return u2("zlib");
}, _context: function() {
return u2("context");
}, _nodescript: function() {
return u2("nodescript");
}, _httpparser: function() {
return u2("httpparser");
}, _dataview: function() {
return u2("dataview");
}, _signal: function() {
return u2("signal");
}, _fsevent: function() {
return u2("fsevent");
}, _tlswrap: function() {
return u2("tlswrap");
} };
}
function l() {
return { buf: "", write: function(e2) {
this.buf += e2;
}, end: function(e2) {
this.buf += e2;
}, read: function() {
return this.buf;
} };
}
m.writeToStream = function(e2, t2, n2) {
return n2 === undefined && (n2 = t2, t2 = {}), f(t2 = u(e2, t2), n2).dispatch(e2);
};
}).call(this, w("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, w("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/fake_9a5aa49d.js", "/");
}, { buffer: 3, crypto: 5, lYpoI2: 11 }], 2: [function(e, t, f) {
(function(e2, t2, n, r, o, i, u, s, a) {
(function(e3) {
var a2 = typeof Uint8Array != "undefined" ? Uint8Array : Array, t3 = 43, n2 = 47, r2 = 48, o2 = 97, i2 = 65, u2 = 45, s2 = 95;
function f2(e4) {
e4 = e4.charCodeAt(0);
return e4 === t3 || e4 === u2 ? 62 : e4 === n2 || e4 === s2 ? 63 : e4 < r2 ? -1 : e4 < r2 + 10 ? e4 - r2 + 26 + 26 : e4 < i2 + 26 ? e4 - i2 : e4 < o2 + 26 ? e4 - o2 + 26 : undefined;
}
e3.toByteArray = function(e4) {
var t4, n3;
if (0 < e4.length % 4)
throw new Error("Invalid string. Length must be a multiple of 4");
var r3 = e4.length, r3 = e4.charAt(r3 - 2) === "=" ? 2 : e4.charAt(r3 - 1) === "=" ? 1 : 0, o3 = new a2(3 * e4.length / 4 - r3), i3 = 0 < r3 ? e4.length - 4 : e4.length, u3 = 0;
function s3(e5) {
o3[u3++] = e5;
}
for (t4 = 0;t4 < i3; t4 += 4, 0)
s3((16711680 & (n3 = f2(e4.charAt(t4)) << 18 | f2(e4.charAt(t4 + 1)) << 12 | f2(e4.charAt(t4 + 2)) << 6 | f2(e4.charAt(t4 + 3)))) >> 16), s3((65280 & n3) >> 8), s3(255 & n3);
return r3 == 2 ? s3(255 & (n3 = f2(e4.charAt(t4)) << 2 | f2(e4.charAt(t4 + 1)) >> 4)) : r3 == 1 && (s3((n3 = f2(e4.charAt(t4)) << 10 | f2(e4.charAt(t4 + 1)) << 4 | f2(e4.charAt(t4 + 2)) >> 2) >> 8 & 255), s3(255 & n3)), o3;
}, e3.fromByteArray = function(e4) {
var t4, n3, r3, o3, i3 = e4.length % 3, u3 = "";
function s3(e5) {
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(e5);
}
for (t4 = 0, r3 = e4.length - i3;t4 < r3; t4 += 3)
n3 = (e4[t4] << 16) + (e4[t4 + 1] << 8) + e4[t4 + 2], u3 += s3((o3 = n3) >> 18 & 63) + s3(o3 >> 12 & 63) + s3(o3 >> 6 & 63) + s3(63 & o3);
switch (i3) {
case 1:
u3 = (u3 += s3((n3 = e4[e4.length - 1]) >> 2)) + s3(n3 << 4 & 63) + "==";
break;
case 2:
u3 = (u3 = (u3 += s3((n3 = (e4[e4.length - 2] << 8) + e4[e4.length - 1]) >> 10)) + s3(n3 >> 4 & 63)) + s3(n3 << 2 & 63) + "=";
}
return u3;
};
})(f === undefined ? this.base64js = {} : f);
}).call(this, e("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, e("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/base64-js/lib/b64.js", "/node_modules/gulp-browserify/node_modules/base64-js/lib");
}, { buffer: 3, lYpoI2: 11 }], 3: [function(O, e, H) {
(function(e2, n, f, r, h, p, g, y, w) {
var a = O("base64-js"), i = O("ieee754");
function f(e3, t2, n2) {
if (!(this instanceof f))
return new f(e3, t2, n2);
var r2, o2, i2, u2, s2 = typeof e3;
if (t2 === "base64" && s2 == "string")
for (e3 = (u2 = e3).trim ? u2.trim() : u2.replace(/^\s+|\s+$/g, "");e3.length % 4 != 0; )
e3 += "=";
if (s2 == "number")
r2 = j(e3);
else if (s2 == "string")
r2 = f.byteLength(e3, t2);
else {
if (s2 != "object")
throw new Error("First argument needs to be a number, array or string.");
r2 = j(e3.length);
}
if (f._useTypedArrays ? o2 = f._augment(new Uint8Array(r2)) : ((o2 = this).length = r2, o2._isBuffer = true), f._useTypedArrays && typeof e3.byteLength == "number")
o2._set(e3);
else if (C(u2 = e3) || f.isBuffer(u2) || u2 && typeof u2 == "object" && typeof u2.length == "number")
for (i2 = 0;i2 < r2; i2++)
f.isBuffer(e3) ? o2[i2] = e3.readUInt8(i2) : o2[i2] = e3[i2];
else if (s2 == "string")
o2.write(e3, 0, t2);
else if (s2 == "number" && !f._useTypedArrays && !n2)
for (i2 = 0;i2 < r2; i2++)
o2[i2] = 0;
return o2;
}
function b(e3, t2, n2, r2) {
return f._charsWritten = c(function(e4) {
for (var t3 = [], n3 = 0;n3 < e4.length; n3++)
t3.push(255 & e4.charCodeAt(n3));
return t3;
}(t2), e3, n2, r2);
}
function m(e3, t2, n2, r2) {
return f._charsWritten = c(function(e4) {
for (var t3, n3, r3 = [], o2 = 0;o2 < e4.length; o2++)
n3 = e4.charCodeAt(o2), t3 = n3 >> 8, n3 = n3 % 256, r3.push(n3), r3.push(t3);
return r3;
}(t2), e3, n2, r2);
}
function v(e3, t2, n2) {
var r2 = "";
n2 = Math.min(e3.length, n2);
for (var o2 = t2;o2 < n2; o2++)
r2 += String.fromCharCode(e3[o2]);
return r2;
}
function o(e3, t2, n2, r2) {
r2 || (d(typeof n2 == "boolean", "missing or invalid endian"), d(t2 != null, "missing offset"), d(t2 + 1 < e3.length, "Trying to read beyond buffer length"));
var o2, r2 = e3.length;
if (!(r2 <= t2))
return n2 ? (o2 = e3[t2], t2 + 1 < r2 && (o2 |= e3[t2 + 1] << 8)) : (o2 = e3[t2] << 8, t2 + 1 < r2 && (o2 |= e3[t2 + 1])), o2;
}
function u(e3, t2, n2, r2) {
r2 || (d(typeof n2 == "boolean", "missing or invalid endian"), d(t2 != null, "missing offset"), d(t2 + 3 < e3.length, "Trying to read beyond buffer length"));
var o2, r2 = e3.length;
if (!(r2 <= t2))
return n2 ? (t2 + 2 < r2 && (o2 = e3[t2 + 2] << 16), t2 + 1 < r2 && (o2 |= e3[t2 + 1] << 8), o2 |= e3[t2], t2 + 3 < r2 && (o2 += e3[t2 + 3] << 24 >>> 0)) : (t2 + 1 < r2 && (o2 = e3[t2 + 1] << 16), t2 + 2 < r2 && (o2 |= e3[t2 + 2] << 8), t2 + 3 < r2 && (o2 |= e3[t2 + 3]), o2 += e3[t2] << 24 >>> 0), o2;
}
function _(e3, t2, n2, r2) {
if (r2 || (d(typeof n2 == "boolean", "missing or invalid endian"), d(t2 != null, "missing offset"), d(t2 + 1 < e3.length, "Trying to read beyond buffer length")), !(e3.length <= t2))
return r2 = o(e3, t2, n2, true), 32768 & r2 ? -1 * (65535 - r2 + 1) : r2;
}
function E(e3, t2, n2, r2) {
if (r2 || (d(typeof n2 == "boolean", "missing or invalid endian"), d(t2 != null, "missing offset"), d(t2 + 3 < e3.length, "Trying to read beyond buffer length")), !(e3.length <= t2))
return r2 = u(e3, t2, n2, true), 2147483648 & r2 ? -1 * (4294967295 - r2 + 1) : r2;
}
function I(e3, t2, n2, r2) {
return r2 || (d(typeof n2 == "boolean", "missing or invalid endian"), d(t2 + 3 < e3.length, "Trying to read beyond buffer length")), i.read(e3, t2, n2, 23, 4);
}
function A(e3, t2, n2, r2) {
return r2 || (d(typeof n2 == "boolean", "missing or invalid endian"), d(t2 + 7 < e3.length, "Trying to read beyond buffer length")), i.read(e3, t2, n2, 52, 8);
}
function s(e3, t2, n2, r2, o2) {
o2 || (d(t2 != null, "missing value"), d(typeof r2 == "boolean", "missing or invalid endian"), d(n2 != null, "missing offset"), d(n2 + 1 < e3.length, "trying to write beyond buffer length"), Y(t2, 65535));
o2 = e3.length;
if (!(o2 <= n2))
for (var i2 = 0, u2 = Math.min(o2 - n2, 2);i2 < u2; i2++)
e3[n2 + i2] = (t2 & 255 << 8 * (r2 ? i2 : 1 - i2)) >>> 8 * (r2 ? i2 : 1 - i2);
}
function l(e3, t2, n2, r2, o2) {
o2 || (d(t2 != null, "missing value"), d(typeof r2 == "boolean", "missing or invalid endian"), d(n2 != null, "missing offset"), d(n2 + 3 < e3.length, "trying to write beyond buffer length"), Y(t2, 4294967295));
o2 = e3.length;
if (!(o2 <= n2))
for (var i2 = 0, u2 = Math.min(o2 - n2, 4);i2 < u2; i2++)
e3[n2 + i2] = t2 >>> 8 * (r2 ? i2 : 3 - i2) & 255;
}
function B(e3, t2, n2, r2, o2) {
o2 || (d(t2 != null, "missing value"), d(typeof r2 == "boolean", "missing or invalid endian"), d(n2 != null, "missing offset"), d(n2 + 1 < e3.length, "Trying to write beyond buffer length"), F(t2, 32767, -32768)), e3.length <= n2 || s(e3, 0 <= t2 ? t2 : 65535 + t2 + 1, n2, r2, o2);
}
function L(e3, t2, n2, r2, o2) {
o2 || (d(t2 != null, "missing value"), d(typeof r2 == "boolean", "missing or invalid endian"), d(n2 != null, "missing offset"), d(n2 + 3 < e3.length, "Trying to write beyond buffer length"), F(t2, 2147483647, -2147483648)), e3.length <= n2 || l(e3, 0 <= t2 ? t2 : 4294967295 + t2 + 1, n2, r2, o2);
}
function U(e3, t2, n2, r2, o2) {
o2 || (d(t2 != null, "missing value"), d(typeof r2 == "boolean", "missing or invalid endian"), d(n2 != null, "missing offset"), d(n2 + 3 < e3.length, "Trying to write beyond buffer length"), D(t2, 340282346638528860000000000000000000000, -34028234663852886e22)), e3.length <= n2 || i.write(e3, t2, n2, r2, 23, 4);
}
function x(e3, t2, n2, r2, o2) {
o2 || (d(t2 != null, "missing value"), d(typeof r2 == "boolean", "missing or invalid endian"), d(n2 != null, "missing offset"), d(n2 + 7 < e3.length, "Trying to write beyond buffer length"), D(t2, 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, -17976931348623157e292)), e3.length <= n2 || i.write(e3, t2, n2, r2, 52, 8);
}
H.Buffer = f, H.SlowBuffer = f, H.INSPECT_MAX_BYTES = 50, f.poolSize = 8192, f._useTypedArrays = function() {
try {
var e3 = new ArrayBuffer(0), t2 = new Uint8Array(e3);
return t2.foo = function() {
return 42;
}, t2.foo() === 42 && typeof t2.subarray == "function";
} catch (e4) {
return false;
}
}(), f.isEncoding = function(e3) {
switch (String(e3).toLowerCase()) {
case "hex":
case "utf8":
case "utf-8":
case "ascii":
case "binary":
case "base64":
case "raw":
case "ucs2":
case "ucs-2":
case "utf16le":
case "utf-16le":
return true;
default:
return false;
}
}, f.isBuffer = function(e3) {
return !(e3 == null || !e3._isBuffer);
}, f.byteLength = function(e3, t2) {
var n2;
switch (e3 += "", t2 || "utf8") {
case "hex":
n2 = e3.length / 2;
break;
case "utf8":
case "utf-8":
n2 = T(e3).length;
break;
case "ascii":
case "binary":
case "raw":
n2 = e3.length;
break;
case "base64":
n2 = M(e3).length;
break;
case "ucs2":
case "ucs-2":
case "utf16le":
case "utf-16le":
n2 = 2 * e3.length;
break;
default:
throw new Error("Unknown encoding");
}
return n2;
}, f.concat = function(e3, t2) {
if (d(C(e3), `Usage: Buffer.concat(list, [totalLength])
list should be an Array.`), e3.length === 0)
return new f(0);
if (e3.length === 1)
return e3[0];
if (typeof t2 != "number")
for (o2 = t2 = 0;o2 < e3.length; o2++)
t2 += e3[o2].length;
for (var n2 = new f(t2), r2 = 0, o2 = 0;o2 < e3.length; o2++) {
var i2 = e3[o2];
i2.copy(n2, r2), r2 += i2.length;
}
return n2;
}, f.prototype.write = function(e3, t2, n2, r2) {
isFinite(t2) ? isFinite(n2) || (r2 = n2, n2 = undefined) : (a2 = r2, r2 = t2, t2 = n2, n2 = a2), t2 = Number(t2) || 0;
var o2, i2, u2, s2, a2 = this.length - t2;
switch ((!n2 || a2 < (n2 = Number(n2))) && (n2 = a2), r2 = String(r2 || "utf8").toLowerCase()) {
case "hex":
o2 = function(e4, t3, n3, r3) {
n3 = Number(n3) || 0;
var o3 = e4.length - n3;
(!r3 || o3 < (r3 = Number(r3))) && (r3 = o3), d((o3 = t3.length) % 2 == 0, "Invalid hex string"), o3 / 2 < r3 && (r3 = o3 / 2);
for (var i3 = 0;i3 < r3; i3++) {
var u3 = parseInt(t3.substr(2 * i3, 2), 16);
d(!isNaN(u3), "Invalid hex string"), e4[n3 + i3] = u3;
}
return f._charsWritten = 2 * i3, i3;
}(this, e3, t2, n2);
break;
case "utf8":
case "utf-8":
i2 = this, u2 = t2, s2 = n2, o2 = f._charsWritten = c(T(e3), i2, u2, s2);
break;
case "ascii":
case "binary":
o2 = b(this, e3, t2, n2);
break;
case "base64":
i2 = this, u2 = t2, s2 = n2, o2 = f._charsWritten = c(M(e3), i2, u2, s2);
break;
case "ucs2":
case "ucs-2":
case "utf16le":
case "utf-16le":
o2 = m(this, e3, t2, n2);
break;
default:
throw new Error("Unknown encoding");
}
return o2;
}, f.prototype.toString = function(e3, t2, n2) {
var r2, o2, i2, u2, s2 = this;
if (e3 = String(e3 || "utf8").toLowerCase(), t2 = Number(t2) || 0, (n2 = n2 !== undefined ? Number(n2) : s2.length) === t2)
return "";
switch (e3) {
case "hex":
r2 = function(e4, t3, n3) {
var r3 = e4.length;
(!t3 || t3 < 0) && (t3 = 0);
(!n3 || n3 < 0 || r3 < n3) && (n3 = r3);
for (var o3 = "", i3 = t3;i3 < n3; i3++)
o3 += k(e4[i3]);
return o3;
}(s2, t2, n2);
break;
case "utf8":
case "utf-8":
r2 = function(e4, t3, n3) {
var r3 = "", o3 = "";
n3 = Math.min(e4.length, n3);
for (var i3 = t3;i3 < n3; i3++)
e4[i3] <= 127 ? (r3 += N(o3) + String.fromCharCode(e4[i3]), o3 = "") : o3 += "%" + e4[i3].toString(16);
return r3 + N(o3);
}(s2, t2, n2);
break;
case "ascii":
case "binary":
r2 = v(s2, t2, n2);
break;
case "base64":
o2 = s2, u2 = n2, r2 = (i2 = t2) === 0 && u2 === o2.length ? a.fromByteArray(o2) : a.fromByteArray(o2.slice(i2, u2));
break;
case "ucs2":
case "ucs-2":
case "utf16le":
case "utf-16le":
r2 = function(e4, t3, n3) {
for (var r3 = e4.slice(t3, n3), o3 = "", i3 = 0;i3 < r3.length; i3 += 2)
o3 += String.fromCharCode(r3[i3] + 256 * r3[i3 + 1]);
return o3;
}(s2, t2, n2);
break;
default:
throw new Error("Unknown encoding");
}
return r2;
}, f.prototype.toJSON = function() {
return { type: "Buffer", data: Array.prototype.slice.call(this._arr || this, 0) };
}, f.prototype.copy = function(e3, t2, n2, r2) {
if (t2 = t2 || 0, (r2 = r2 || r2 === 0 ? r2 : this.length) !== (n2 = n2 || 0) && e3.length !== 0 && this.length !== 0) {
d(n2 <= r2, "sourceEnd < sourceStart"), d(0 <= t2 && t2 < e3.length, "targetStart out of bounds"), d(0 <= n2 && n2 < this.length, "sourceStart out of bounds"), d(0 <= r2 && r2 <= this.length, "sourceEnd out of bounds"), r2 > this.length && (r2 = this.length);
var o2 = (r2 = e3.length - t2 < r2 - n2 ? e3.length - t2 + n2 : r2) - n2;
if (o2 < 100 || !f._useTypedArrays)
for (var i2 = 0;i2 < o2; i2++)
e3[i2 + t2] = this[i2 + n2];
else
e3._set(this.subarray(n2, n2 + o2), t2);
}
}, f.prototype.slice = function(e3, t2) {
var n2 = this.length;
if (e3 = S(e3, n2, 0), t2 = S(t2, n2, n2), f._useTypedArrays)
return f._augment(this.subarray(e3, t2));
for (var r2 = t2 - e3, o2 = new f(r2, undefined, true), i2 = 0;i2 < r2; i2++)
o2[i2] = this[i2 + e3];
return o2;
}, f.prototype.get = function(e3) {
return console.log(".get() is deprecated. Access using array indexes instead."), this.readUInt8(e3);
}, f.prototype.set = function(e3, t2) {
return console.log(".set() is deprecated. Access using array indexes instead."), this.writeUInt8(e3, t2);
}, f.prototype.readUInt8 = function(e3, t2) {
if (t2 || (d(e3 != null, "missing offset"), d(e3 < this.length, "Trying to read beyond buffer length")), !(e3 >= this.length))
return this[e3];
}, f.prototype.readUInt16LE = function(e3, t2) {
return o(this, e3, true, t2);
}, f.prototype.readUInt16BE = function(e3, t2) {
return o(this, e3, false, t2);
}, f.prototype.readUInt32LE = function(e3, t2) {
return u(this, e3, true, t2);
}, f.prototype.readUInt32BE = function(e3, t2) {
return u(this, e3, false, t2);
}, f.prototype.readInt8 = function(e3, t2) {
if (t2 || (d(e3 != null, "missing offset"), d(e3 < this.length, "Trying to read beyond buffer length")), !(e3 >= this.length))
return 128 & this[e3] ? -1 * (255 - this[e3] + 1) : this[e3];
}, f.prototype.readInt16LE = function(e3, t2) {
return _(this, e3, true, t2);
}, f.prototype.readInt16BE = function(e3, t2) {
return _(this, e3, false, t2);
}, f.prototype.readInt32LE = function(e3, t2) {
return E(this, e3, true, t2);
}, f.prototype.readInt32BE = function(e3, t2) {
return E(this, e3, false, t2);
}, f.prototype.readFloatLE = function(e3, t2) {
return I(this, e3, true, t2);
}, f.prototype.readFloatBE = function(e3, t2) {
return I(this, e3, false, t2);
}, f.prototype.readDoubleLE = function(e3, t2) {
return A(this, e3, true, t2);
}, f.prototype.readDoubleBE = function(e3, t2) {
return A(this, e3, false, t2);
}, f.prototype.writeUInt8 = function(e3, t2, n2) {
n2 || (d(e3 != null, "missing value"), d(t2 != null, "missing offset"), d(t2 < this.length, "trying to write beyond buffer length"), Y(e3, 255)), t2 >= this.length || (this[t2] = e3);
}, f.prototype.writeUInt16LE = function(e3, t2, n2) {
s(this, e3, t2, true, n2);
}, f.prototype.writeUInt16BE = function(e3, t2, n2) {
s(this, e3, t2, false, n2);
}, f.prototype.writeUInt32LE = function(e3, t2, n2) {
l(this, e3, t2, true, n2);
}, f.prototype.writeUInt32BE = function(e3, t2, n2) {
l(this, e3, t2, false, n2);
}, f.prototype.writeInt8 = function(e3, t2, n2) {
n2 || (d(e3 != null, "missing value"), d(t2 != null, "missing offset"), d(t2 < this.length, "Trying to write beyond buffer length"), F(e3, 127, -128)), t2 >= this.length || (0 <= e3 ? this.writeUInt8(e3, t2, n2) : this.writeUInt8(255 + e3 + 1, t2, n2));
}, f.prototype.writeInt16LE = function(e3, t2, n2) {
B(this, e3, t2, true, n2);
}, f.prototype.writeInt16BE = function(e3, t2, n2) {
B(this, e3, t2, false, n2);
}, f.prototype.writeInt32LE = function(e3, t2, n2) {
L(this, e3, t2, true, n2);
}, f.prototype.writeInt32BE = function(e3, t2, n2) {
L(this, e3, t2, false, n2);
}, f.prototype.writeFloatLE = function(e3, t2, n2) {
U(this, e3, t2, true, n2);
}, f.prototype.writeFloatBE = function(e3, t2, n2) {
U(this, e3, t2, false, n2);
}, f.prototype.writeDoubleLE = function(e3, t2, n2) {
x(this, e3, t2, true, n2);
}, f.prototype.writeDoubleBE = function(e3, t2, n2) {
x(this, e3, t2, false, n2);
}, f.prototype.fill = function(e3, t2, n2) {
if (t2 = t2 || 0, n2 = n2 || this.length, d(typeof (e3 = typeof (e3 = e3 || 0) == "string" ? e3.charCodeAt(0) : e3) == "number" && !isNaN(e3), "value is not a number"), d(t2 <= n2, "end < start"), n2 !== t2 && this.length !== 0) {
d(0 <= t2 && t2 < this.length, "start out of bounds"), d(0 <= n2 && n2 <= this.length, "end out of bounds");
for (var r2 = t2;r2 < n2; r2++)
this[r2] = e3;
}
}, f.prototype.inspect = function() {
for (var e3 = [], t2 = this.length, n2 = 0;n2 < t2; n2++)
if (e3[n2] = k(this[n2]), n2 === H.INSPECT_MAX_BYTES) {
e3[n2 + 1] = "...";
break;
}
return "<Buffer " + e3.join(" ") + ">";
}, f.prototype.toArrayBuffer = function() {
if (typeof Uint8Array == "undefined")
throw new Error("Buffer.toArrayBuffer not supported in this browser");
if (f._useTypedArrays)
return new f(this).buffer;
for (var e3 = new Uint8Array(this.length), t2 = 0, n2 = e3.length;t2 < n2; t2 += 1)
e3[t2] = this[t2];
return e3.buffer;
};
var t = f.prototype;
function S(e3, t2, n2) {
return typeof e3 != "number" ? n2 : t2 <= (e3 = ~~e3) ? t2 : 0 <= e3 || 0 <= (e3 += t2) ? e3 : 0;
}
function j(e3) {
return (e3 = ~~Math.ceil(+e3)) < 0 ? 0 : e3;
}
function C(e3) {
return (Array.isArray || function(e4) {
return Object.prototype.toString.call(e4) === "[object Array]";
})(e3);
}
function k(e3) {
return e3 < 16 ? "0" + e3.toString(16) : e3.toString(16);
}
function T(e3) {
for (var t2 = [], n2 = 0;n2 < e3.length; n2++) {
var r2 = e3.charCodeAt(n2);
if (r2 <= 127)
t2.push(e3.charCodeAt(n2));
else
for (var o2 = n2, i2 = (55296 <= r2 && r2 <= 57343 && n2++, encodeURIComponent(e3.slice(o2, n2 + 1)).substr(1).split("%")), u2 = 0;u2 < i2.length; u2++)
t2.push(parseInt(i2[u2], 16));
}
return t2;
}
function M(e3) {
return a.toByteArray(e3);
}
function c(e3, t2, n2, r2) {
for (var o2 = 0;o2 < r2 && !(o2 + n2 >= t2.length || o2 >= e3.length); o2++)
t2[o2 + n2] = e3[o2];
return o2;
}
function N(e3) {
try {
return decodeURIComponent(e3);
} catch (e4) {
return String.fromCharCode(65533);
}
}
function Y(e3, t2) {
d(typeof e3 == "number", "cannot write a non-number as a number"), d(0 <= e3, "specified a negative value for writing an unsigned value"), d(e3 <= t2, "value is larger than maximum value for type"), d(Math.floor(e3) === e3, "value has a fractional component");
}
function F(e3, t2, n2) {
d(typeof e3 == "number", "cannot write a non-number as a number"), d(e3 <= t2, "value larger than maximum allowed value"), d(n2 <= e3, "value smaller than minimum allowed value"), d(Math.floor(e3) === e3, "value has a fractional component");
}
function D(e3, t2, n2) {
d(typeof e3 == "number", "cannot write a non-number as a number"), d(e3 <= t2, "value larger than maximum allowed value"), d(n2 <= e3, "value smaller than minimum allowed value");
}
function d(e3, t2) {
if (!e3)
throw new Error(t2 || "Failed assertion");
}
f._augment = function(e3) {
return e3._isBuffer = true, e3._get = e3.get, e3._set = e3.set, e3.get = t.get, e3.set = t.set, e3.write = t.write, e3.toString = t.toString, e3.toLocaleString = t.toString, e3.toJSON = t.toJSON, e3.copy = t.copy, e3.slice = t.slice, e3.readUInt8 = t.readUInt8, e3.readUInt16LE = t.readUInt16LE, e3.readUInt16BE = t.readUInt16BE, e3.readUInt32LE = t.readUInt32LE, e3.readUInt32BE = t.readUInt32BE, e3.readInt8 = t.readInt8, e3.readInt16LE = t.readInt16LE, e3.readInt16BE = t.readInt16BE, e3.readInt32LE = t.readInt32LE, e3.readInt32BE = t.readInt32BE, e3.readFloatLE = t.readFloatLE, e3.readFloatBE = t.readFloatBE, e3.readDoubleLE = t.readDoubleLE, e3.readDoubleBE = t.readDoubleBE, e3.writeUInt8 = t.writeUInt8, e3.writeUInt16LE = t.writeUInt16LE, e3.writeUInt16BE = t.writeUInt16BE, e3.writeUInt32LE = t.writeUInt32LE, e3.writeUInt32BE = t.writeUInt32BE, e3.writeInt8 = t.writeInt8, e3.writeInt16LE = t.writeInt16LE, e3.writeInt16BE = t.writeInt16BE, e3.writeInt32LE = t.writeInt32LE, e3.writeInt32BE = t.writeInt32BE, e3.writeFloatLE = t.writeFloatLE, e3.writeFloatBE = t.writeFloatBE, e3.writeDoubleLE = t.writeDoubleLE, e3.writeDoubleBE = t.writeDoubleBE, e3.fill = t.fill, e3.inspect = t.inspect, e3.toArrayBuffer = t.toArrayBuffer, e3;
};
}).call(this, O("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, O("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/buffer/index.js", "/node_modules/gulp-browserify/node_modules/buffer");
}, { "base64-js": 2, buffer: 3, ieee754: 10, lYpoI2: 11 }], 4: [function(c, d, e) {
(function(e2, t, a, n, r, o, i, u, s) {
var a = c("buffer").Buffer, f = 4, l = new a(f);
l.fill(0);
d.exports = { hash: function(e3, t2, n2, r2) {
for (var o2 = t2(function(e4, t3) {
e4.length % f != 0 && (n3 = e4.length + (f - e4.length % f), e4 = a.concat([e4, l], n3));
for (var n3, r3 = [], o3 = t3 ? e4.readInt32BE : e4.readInt32LE, i3 = 0;i3 < e4.length; i3 += f)
r3.push(o3.call(e4, i3));
return r3;
}(e3 = a.isBuffer(e3) ? e3 : new a(e3), r2), 8 * e3.length), t2 = r2, i2 = new a(n2), u2 = t2 ? i2.writeInt32BE : i2.writeInt32LE, s2 = 0;s2 < o2.length; s2++)
u2.call(i2, o2[s2], 4 * s2, true);
return i2;
} };
}).call(this, c("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, c("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/helpers.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
}, { buffer: 3, lYpoI2: 11 }], 5: [function(v, e, _) {
(function(l, c, u, d, h, p, g, y, w) {
var u = v("buffer").Buffer, e2 = v("./sha"), t = v("./sha256"), n = v("./rng"), b = { sha1: e2, sha256: t, md5: v("./md5") }, s = 64, a = new u(s);
function r(e3, n2) {
var r2 = b[e3 = e3 || "sha1"], o2 = [];
return r2 || i("algorithm:", e3, "is not yet supported"), { update: function(e4) {
return u.isBuffer(e4) || (e4 = new u(e4)), o2.push(e4), e4.length, this;
}, digest: function(e4) {
var t2 = u.concat(o2), t2 = n2 ? function(e5, t3, n3) {
u.isBuffer(t3) || (t3 = new u(t3)), u.isBuffer(n3) || (n3 = new u(n3)), t3.length > s ? t3 = e5(t3) : t3.length < s && (t3 = u.concat([t3, a], s));
for (var r3 = new u(s), o3 = new u(s), i2 = 0;i2 < s; i2++)
r3[i2] = 54 ^ t3[i2], o3[i2] = 92 ^ t3[i2];
return n3 = e5(u.concat([r3, n3])), e5(u.concat([o3, n3]));
}(r2, n2, t2) : r2(t2);
return o2 = null, e4 ? t2.toString(e4) : t2;
} };
}
function i() {
var e3 = [].slice.call(arguments).join(" ");
throw new Error([e3, "we accept pull requests", "http://github.com/dominictarr/crypto-browserify"].join(`
`));
}
a.fill(0), _.createHash = function(e3) {
return r(e3);
}, _.createHmac = r, _.randomBytes = function(e3, t2) {
if (!t2 || !t2.call)
return new u(n(e3));
try {
t2.call(this, undefined, new u(n(e3)));
} catch (e4) {
t2(e4);
}
};
var o, f = ["createCredentials", "createCipher", "createCipheriv", "createDecipher", "createDecipheriv", "createSign", "createVerify", "createDiffieHellman", "pbkdf2"], m = function(e3) {
_[e3] = function() {
i("sorry,", e3, "is not implemented yet");
};
};
for (o in f)
m(f[o]);
}).call(this, v("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, v("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/index.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
}, { "./md5": 6, "./rng": 7, "./sha": 8, "./sha256": 9, buffer: 3, lYpoI2: 11 }], 6: [function(w, b, e) {
(function(e2, r, o, i, u, a, f, l, y) {
var t = w("./helpers");
function n(e3, t2) {
e3[t2 >> 5] |= 128 << t2 % 32, e3[14 + (t2 + 64 >>> 9 << 4)] = t2;
for (var n2 = 1732584193, r2 = -271733879, o2 = -1732584194, i2 = 271733878, u2 = 0;u2 < e3.length; u2 += 16) {
var s2 = n2, a2 = r2, f2 = o2, l2 = i2, n2 = c(n2, r2, o2, i2, e3[u2 + 0], 7, -680876936), i2 = c(i2, n2, r2, o2, e3[u2 + 1], 12, -389564586), o2 = c(o2, i2, n2, r2, e3[u2 + 2], 17, 606105819), r2 = c(r2, o2, i2, n2, e3[u2 + 3], 22, -1044525330);
n2 = c(n2, r2, o2, i2, e3[u2 + 4], 7, -176418897), i2 = c(i2, n2, r2, o2, e3[u2 + 5], 12, 1200080426), o2 = c(o2, i2, n2, r2, e3[u2 + 6], 17, -1473231341), r2 = c(r2, o2, i2, n2, e3[u2 + 7], 22, -45705983), n2 = c(n2, r2, o2, i2, e3[u2 + 8], 7, 1770035416), i2 = c(i2, n2, r2, o2, e3[u2 + 9], 12, -1958414417), o2 = c(o2, i2, n2, r2, e3[u2 + 10], 17, -42063), r2 = c(r2, o2, i2, n2, e3[u2 + 11], 22, -1990404162), n2 = c(n2, r2, o2, i2, e3[u2 + 12], 7, 1804603682), i2 = c(i2, n2, r2, o2, e3[u2 + 13], 12, -40341101), o2 = c(o2, i2, n2, r2, e3[u2 + 14], 17, -1502002290), n2 = d(n2, r2 = c(r2, o2, i2, n2, e3[u2 + 15], 22, 1236535329), o2, i2, e3[u2 + 1], 5, -165796510), i2 = d(i2, n2, r2, o2, e3[u2 + 6], 9, -1069501632), o2 = d(o2, i2, n2, r2, e3[u2 + 11], 14, 643717713), r2 = d(r2, o2, i2, n2, e3[u2 + 0], 20, -373897302), n2 = d(n2, r2, o2, i2, e3[u2 + 5], 5, -701558691), i2 = d(i2, n2, r2, o2, e3[u2 + 10], 9, 38016083), o2 = d(o2, i2, n2, r2, e3[u2 + 15], 14, -660478335), r2 = d(r2, o2, i2, n2, e3[u2 + 4], 20, -405537848), n2 = d(n2, r2, o2, i2, e3[u2 + 9], 5, 568446438), i2 = d(i2, n2, r2, o2, e3[u2 + 14], 9, -1019803690), o2 = d(o2, i2, n2, r2, e3[u2 + 3], 14, -187363961), r2 = d(r2, o2, i2, n2, e3[u2 + 8], 20, 1163531501), n2 = d(n2, r2, o2, i2, e3[u2 + 13], 5, -1444681467), i2 = d(i2, n2, r2, o2, e3[u2 + 2], 9, -51403784), o2 = d(o2, i2, n2, r2, e3[u2 + 7], 14, 1735328473), n2 = h(n2, r2 = d(r2, o2, i2, n2, e3[u2 + 12], 20, -1926607734), o2, i2, e3[u2 + 5], 4, -378558), i2 = h(i2, n2, r2, o2, e3[u2 + 8], 11, -2022574463), o2 = h(o2, i2, n2, r2, e3[u2 + 11], 16, 1839030562), r2 = h(r2, o2, i2, n2, e3[u2 + 14], 23, -35309556), n2 = h(n2, r2, o2, i2, e3[u2 + 1], 4, -1530992060), i2 = h(i2, n2, r2, o2, e3[u2 + 4], 11, 1272893353), o2 = h(o2, i2, n2, r2, e3[u2 + 7], 16, -155497632), r2 = h(r2, o2, i2, n2, e3[u2 + 10], 23, -1094730640), n2 = h(n2, r2, o2, i2, e3[u2 + 13], 4, 681279174), i2 = h(i2, n2, r2, o2, e3[u2 + 0], 11, -358537222), o2 = h(o2, i2, n2, r2, e3[u2 + 3], 16, -722521979), r2 = h(r2, o2, i2, n2, e3[u2 + 6], 23, 76029189), n2 = h(n2, r2, o2, i2, e3[u2 + 9], 4, -640364487), i2 = h(i2, n2, r2, o2, e3[u2 + 12], 11, -421815835), o2 = h(o2, i2, n2, r2, e3[u2 + 15], 16, 530742520), n2 = p(n2, r2 = h(r2, o2, i2, n2, e3[u2 + 2], 23, -995338651), o2, i2, e3[u2 + 0], 6, -198630844), i2 = p(i2, n2, r2, o2, e3[u2 + 7], 10, 1126891415), o2 = p(o2, i2, n2, r2, e3[u2 + 14], 15, -1416354905), r2 = p(r2, o2, i2, n2, e3[u2 + 5], 21, -57434055), n2 = p(n2, r2, o2, i2, e3[u2 + 12], 6, 1700485571), i2 = p(i2, n2, r2, o2, e3[u2 + 3], 10, -1894986606), o2 = p(o2, i2, n2, r2, e3[u2 + 10], 15, -1051523), r2 = p(r2, o2, i2, n2, e3[u2 + 1], 21, -2054922799), n2 = p(n2, r2, o2, i2, e3[u2 + 8], 6, 1873313359), i2 = p(i2, n2, r2, o2, e3[u2 + 15], 10, -30611744), o2 = p(o2, i2, n2, r2, e3[u2 + 6], 15, -1560198380), r2 = p(r2, o2, i2, n2, e3[u2 + 13], 21, 1309151649), n2 = p(n2, r2, o2, i2, e3[u2 + 4], 6, -145523070), i2 = p(i2, n2, r2, o2, e3[u2 + 11], 10, -1120210379), o2 = p(o2, i2, n2, r2, e3[u2 + 2], 15, 718787259), r2 = p(r2, o2, i2, n2, e3[u2 + 9], 21, -343485551), n2 = g(n2, s2), r2 = g(r2, a2), o2 = g(o2, f2), i2 = g(i2, l2);
}
return Array(n2, r2, o2, i2);
}
function s(e3, t2, n2, r2, o2, i2) {
return g((t2 = g(g(t2, e3), g(r2, i2))) << o2 | t2 >>> 32 - o2, n2);
}
function c(e3, t2, n2, r2, o2, i2, u2) {
return s(t2 & n2 | ~t2 & r2, e3, t2, o2, i2, u2);
}
function d(e3, t2, n2, r2, o2, i2, u2) {
return s(t2 & r2 | n2 & ~r2, e3, t2, o2, i2, u2);
}
function h(e3, t2, n2, r2, o2, i2, u2) {
return s(t2 ^ n2 ^ r2, e3, t2, o2, i2, u2);
}
function p(e3, t2, n2, r2, o2, i2, u2) {
return s(n2 ^ (t2 | ~r2), e3, t2, o2, i2, u2);
}
function g(e3, t2) {
var n2 = (65535 & e3) + (65535 & t2);
return (e3 >> 16) + (t2 >> 16) + (n2 >> 16) << 16 | 65535 & n2;
}
b.exports = function(e3) {
return t.hash(e3, n, 16);
};
}).call(this, w("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, w("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/md5.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
}, { "./helpers": 4, buffer: 3, lYpoI2: 11 }], 7: [function(e, l, t) {
(function(e2, t2, n, r, o, i, u, s, f) {
l.exports = function(e3) {
for (var t3, n2 = new Array(e3), r2 = 0;r2 < e3; r2++)
(3 & r2) == 0 && (t3 = 4294967296 * Math.random()), n2[r2] = t3 >>> ((3 & r2) << 3) & 255;
return n2;
};
}).call(this, e("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, e("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/rng.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
}, { buffer: 3, lYpoI2: 11 }], 8: [function(c, d, e) {
(function(e2, t, n, r, o, s, a, f, l) {
var i = c("./helpers");
function u(l2, c2) {
l2[c2 >> 5] |= 128 << 24 - c2 % 32, l2[15 + (c2 + 64 >> 9 << 4)] = c2;
for (var e3, t2, n2, r2 = Array(80), o2 = 1732584193, i2 = -271733879, u2 = -1732584194, s2 = 271733878, d2 = -1009589776, h = 0;h < l2.length; h += 16) {
for (var p = o2, g = i2, y = u2, w = s2, b = d2, a2 = 0;a2 < 80; a2++) {
r2[a2] = a2 < 16 ? l2[h + a2] : v(r2[a2 - 3] ^ r2[a2 - 8] ^ r2[a2 - 14] ^ r2[a2 - 16], 1);
var f2 = m(m(v(o2, 5), (f2 = i2, t2 = u2, n2 = s2, (e3 = a2) < 20 ? f2 & t2 | ~f2 & n2 : !(e3 < 40) && e3 < 60 ? f2 & t2 | f2 & n2 | t2 & n2 : f2 ^ t2 ^ n2)), m(m(d2, r2[a2]), (e3 = a2) < 20 ? 1518500249 : e3 < 40 ? 1859775393 : e3 < 60 ? -1894007588 : -899497514)), d2 = s2, s2 = u2, u2 = v(i2, 30), i2 = o2, o2 = f2;
}
o2 = m(o2, p), i2 = m(i2, g), u2 = m(u2, y), s2 = m(s2, w), d2 = m(d2, b);
}
return Array(o2, i2, u2, s2, d2);
}
function m(e3, t2) {
var n2 = (65535 & e3) + (65535 & t2);
return (e3 >> 16) + (t2 >> 16) + (n2 >> 16) << 16 | 65535 & n2;
}
function v(e3, t2) {
return e3 << t2 | e3 >>> 32 - t2;
}
d.exports = function(e3) {
return i.hash(e3, u, 20, true);
};
}).call(this, c("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, c("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/sha.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
}, { "./helpers": 4, buffer: 3, lYpoI2: 11 }], 9: [function(c, d, e) {
(function(e2, t, n, r, u, s, a, f, l) {
function b(e3, t2) {
var n2 = (65535 & e3) + (65535 & t2);
return (e3 >> 16) + (t2 >> 16) + (n2 >> 16) << 16 | 65535 & n2;
}
function o(e3, l2) {
var c2, d2 = new Array(1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221, 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580, 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, 3516065817, 3600352804, 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298), t2 = new Array(1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225), n2 = new Array(64);
e3[l2 >> 5] |= 128 << 24 - l2 % 32, e3[15 + (l2 + 64 >> 9 << 4)] = l2;
for (var r2, o2, h = 0;h < e3.length; h += 16) {
for (var i2 = t2[0], u2 = t2[1], s2 = t2[2], p = t2[3], a2 = t2[4], g = t2[5], y = t2[6], w = t2[7], f2 = 0;f2 < 64; f2++)
n2[f2] = f2 < 16 ? e3[f2 + h] : b(b(b((o2 = n2[f2 - 2], m(o2, 17) ^ m(o2, 19) ^ v(o2, 10)), n2[f2 - 7]), (o2 = n2[f2 - 15], m(o2, 7) ^ m(o2, 18) ^ v(o2, 3))), n2[f2 - 16]), c2 = b(b(b(b(w, m(o2 = a2, 6) ^ m(o2, 11) ^ m(o2, 25)), a2 & g ^ ~a2 & y), d2[f2]), n2[f2]), r2 = b(m(r2 = i2, 2) ^ m(r2, 13) ^ m(r2, 22), i2 & u2 ^ i2 & s2 ^ u2 & s2), w = y, y = g, g = a2, a2 = b(p, c2), p = s2, s2 = u2, u2 = i2, i2 = b(c2, r2);
t2[0] = b(i2, t2[0]), t2[1] = b(u2, t2[1]), t2[2] = b(s2, t2[2]), t2[3] = b(p, t2[3]), t2[4] = b(a2, t2[4]), t2[5] = b(g, t2[5]), t2[6] = b(y, t2[6]), t2[7] = b(w, t2[7]);
}
return t2;
}
var i = c("./helpers"), m = function(e3, t2) {
return e3 >>> t2 | e3 << 32 - t2;
}, v = function(e3, t2) {
return e3 >>> t2;
};
d.exports = function(e3) {
return i.hash(e3, o, 32, true);
};
}).call(this, c("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, c("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/sha256.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
}, { "./helpers": 4, buffer: 3, lYpoI2: 11 }], 10: [function(e, t, f) {
(function(e2, t2, n, r, o, i, u, s, a) {
f.read = function(e3, t3, n2, r2, o2) {
var i2, u2, l = 8 * o2 - r2 - 1, c = (1 << l) - 1, d = c >> 1, s2 = -7, a2 = n2 ? o2 - 1 : 0, f2 = n2 ? -1 : 1, o2 = e3[t3 + a2];
for (a2 += f2, i2 = o2 & (1 << -s2) - 1, o2 >>= -s2, s2 += l;0 < s2; i2 = 256 * i2 + e3[t3 + a2], a2 += f2, s2 -= 8)
;
for (u2 = i2 & (1 << -s2) - 1, i2 >>= -s2, s2 += r2;0 < s2; u2 = 256 * u2 + e3[t3 + a2], a2 += f2, s2 -= 8)
;
if (i2 === 0)
i2 = 1 - d;
else {
if (i2 === c)
return u2 ? NaN : 1 / 0 * (o2 ? -1 : 1);
u2 += Math.pow(2, r2), i2 -= d;
}
return (o2 ? -1 : 1) * u2 * Math.pow(2, i2 - r2);
}, f.write = function(e3, t3, l, n2, r2, c) {
var o2, i2, u2 = 8 * c - r2 - 1, s2 = (1 << u2) - 1, a2 = s2 >> 1, d = r2 === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0, f2 = n2 ? 0 : c - 1, h = n2 ? 1 : -1, c = t3 < 0 || t3 === 0 && 1 / t3 < 0 ? 1 : 0;
for (t3 = Math.abs(t3), isNaN(t3) || t3 === 1 / 0 ? (i2 = isNaN(t3) ? 1 : 0, o2 = s2) : (o2 = Math.floor(Math.log(t3) / Math.LN2), t3 * (n2 = Math.pow(2, -o2)) < 1 && (o2--, n2 *= 2), 2 <= (t3 += 1 <= o2 + a2 ? d / n2 : d * Math.pow(2, 1 - a2)) * n2 && (o2++, n2 /= 2), s2 <= o2 + a2 ? (i2 = 0, o2 = s2) : 1 <= o2 + a2 ? (i2 = (t3 * n2 - 1) * Math.pow(2, r2), o2 += a2) : (i2 = t3 * Math.pow(2, a2 - 1) * Math.pow(2, r2), o2 = 0));8 <= r2; e3[l + f2] = 255 & i2, f2 += h, i2 /= 256, r2 -= 8)
;
for (o2 = o2 << r2 | i2, u2 += r2;0 < u2; e3[l + f2] = 255 & o2, f2 += h, o2 /= 256, u2 -= 8)
;
e3[l + f2 - h] |= 128 * c;
};
}).call(this, e("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, e("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/ieee754/index.js", "/node_modules/gulp-browserify/node_modules/ieee754");
}, { buffer: 3, lYpoI2: 11 }], 11: [function(e, h, t) {
(function(e2, t2, n, r, o, f, l, c, d) {
var i, u, s;
function a() {}
(e2 = h.exports = {}).nextTick = (u = typeof window != "undefined" && window.setImmediate, s = typeof window != "undefined" && window.postMessage && window.addEventListener, u ? function(e3) {
return window.setImmediate(e3);
} : s ? (i = [], window.addEventListener("message", function(e3) {
var t3 = e3.source;
t3 !== window && t3 !== null || e3.data !== "process-tick" || (e3.stopPropagation(), 0 < i.length && i.shift()());
}, true), function(e3) {
i.push(e3), window.postMessage("process-tick", "*");
}) : function(e3) {
setTimeout(e3, 0);
}), e2.title = "browser", e2.browser = true, e2.env = {}, e2.argv = [], e2.on = a, e2.addListener = a, e2.once = a, e2.off = a, e2.removeListener = a, e2.removeAllListeners = a, e2.emit = a, e2.binding = function(e3) {
throw new Error("process.binding is not supported");
}, e2.cwd = function() {
return "/";
}, e2.chdir = function(e3) {
throw new Error("process.chdir is not supported");
};
}).call(this, e("lYpoI2"), typeof self != "undefined" ? self : typeof window != "undefined" ? window : {}, e("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/process/browser.js", "/node_modules/gulp-browserify/node_modules/process");
}, { buffer: 3, lYpoI2: 11 }] }, {}, [1])(1);
});
});
// node_modules/@tscircuit/capacity-autorouter/dist/index.js
var import_object_hash = __toESM(require_object_hash());
__toESM(require_object_hash());
__toESM(require_object_hash());
var t = Object.create;
var e = Object.defineProperty;
var n = Object.getOwnPropertyDescriptor;
var o = Object.getOwnPropertyNames;
var i = Object.getPrototypeOf;
var r = Object.prototype.hasOwnProperty;
var s = (t2, e2) => function() {
return e2 || (0, t2[o(t2)[0]])((e2 = { exports: {} }).exports, e2), e2.exports;
};
var a = (t2, n2) => {
for (var o2 in n2)
e(t2, o2, { get: n2[o2], enumerable: true });
};
var c = (s2, a2, c2) => (c2 = s2 != null ? t(i(s2)) : {}, ((t2, i2, s3, a3) => {
if (i2 && typeof i2 == "object" || typeof i2 == "function")
for (let c3 of o(i2))
r.call(t2, c3) || c3 === s3 || e(t2, c3, { get: () => i2[c3], enumerable: !(a3 = n(i2, c3)) || a3.enumerable });
return t2;
})(!a2 && s2 && s2.__esModule ? c2 : e(c2, "default", { value: s2, enumerable: true }), s2));
var l = s({ "node_modules/is-buffer/index.js"(t2, e2) {
function n2(t3) {
return !!t3.constructor && typeof t3.constructor.isBuffer == "function" && t3.constructor.isBuffer(t3);
}
e2.exports = function(t3) {
return t3 != null && (n2(t3) || function(t4) {
return typeof t4.readFloatLE == "function" && typeof t4.slice == "function" && n2(t4.slice(0, 0));
}(t3) || !!t3._isBuffer);
};
} });
var h = s({ "node_modules/kind-of/index.js"(t2, e2) {
var n2 = l(), o2 = Object.prototype.toString;
e2.exports = function(t3) {
if (t3 === undefined)
return "undefined";
if (t3 === null)
return "null";
if (t3 === true || t3 === false || t3 instanceof Boolean)
return "boolean";
if (typeof t3 == "string" || t3 instanceof String)
return "string";
if (typeof t3 == "number" || t3 instanceof Number)
return "number";
if (typeof t3 == "function" || t3 instanceof Function)
return "function";
if (Array.isArray !== undefined && Array.isArray(t3))
return "array";
if (t3 instanceof RegExp)
return "regexp";
if (t3 instanceof Date)
return "date";
var e3 = o2.call(t3);
return e3 === "[object RegExp]" ? "regexp" : e3 === "[object Date]" ? "date" : e3 === "[object Arguments]" ? "arguments" : e3 === "[object Error]" ? "error" : n2(t3) ? "buffer" : e3 === "[object Set]" ? "set" : e3 === "[object WeakSet]" ? "weakset" : e3 === "[object Map]" ? "map" : e3 === "[object WeakMap]" ? "weakmap" : e3 === "[object Symbol]" ? "symbol" : e3 === "[object Int8Array]" ? "int8array" : e3 === "[object Uint8Array]" ? "uint8array" : e3 === "[object Uint8ClampedArray]" ? "uint8clampedarray" : e3 === "[object Int16Array]" ? "int16array" : e3 === "[object Uint16Array]" ? "uint16array" : e3 === "[object Int32Array]" ? "int32array" : e3 === "[object Uint32Array]" ? "uint32array" : e3 === "[object Float32Array]" ? "float32array" : e3 === "[object Float64Array]" ? "float64array" : "object";
};
} });
var d = s({ "node_modules/rename-keys/index.js"(t2, e2) {
(function() {
function t3(t4, e3) {
if (typeof e3 != "function")
return t4;
var n2 = {};
for (var o2 in t4)
Object.prototype.hasOwnProperty.call(t4, o2) && (n2[e3(o2, t4[o2]) || o2] = t4[o2]);
return n2;
}
e2 !== undefined && e2.exports ? e2.exports = t3 : typeof define == "function" && define.amd ? define([], function() {
return t3;
}) : window.rename = t3;
})();
} });
var u = s({ "node_modules/deep-rename-keys/index.js"(t2, e2) {
var n2 = h(), o2 = d();
e2.exports = function t3(e3, i2) {
var r2 = n2(e3);
if (r2 !== "object" && r2 !== "array")
throw new Error("expected an object");
var s2 = [];
for (var a2 in r2 === "object" && (e3 = o2(e3, i2), s2 = {}), e3)
if (e3.hasOwnProperty(a2)) {
var c2 = e3[a2];
n2(c2) === "object" || n2(c2) === "array" ? s2[a2] = t3(c2, i2) : s2[a2] = c2;
}
return s2;
};
} });
var p = s({ "node_modules/xml-reader/node_modules/eventemitter3/index.js"(t2, e2) {
var n2 = Object.prototype.hasOwnProperty, o2 = "~";
function i2() {}
function r2(t3, e3, n3) {
this.fn = t3, this.context = e3, this.once = n3 || false;
}
function s2() {
this._events = new i2, this._eventsCount = 0;
}
Object.create && (i2.prototype = Object.create(null), new i2().__proto__ || (o2 = false)), s2.prototype.eventNames = function() {
var t3, e3, i3 = [];
if (this._eventsCount === 0)
return i3;
for (e3 in t3 = this._events)
n2.call(t3, e3) && i3.push(o2 ? e3.slice(1) : e3);
return Object.getOwnPropertySymbols ? i3.concat(Object.getOwnPropertySymbols(t3)) : i3;
}, s2.prototype.listeners = function(t3, e3) {
var n3 = o2 ? o2 + t3 : t3, i3 = this._events[n3];
if (e3)
return !!i3;
if (!i3)
return [];
if (i3.fn)
return [i3.fn];
for (var r3 = 0, s3 = i3.length, a2 = new Array(s3);r3 < s3; r3++)
a2[r3] = i3[r3].fn;
return a2;
}, s2.prototype.emit = function(t3, e3, n3, i3, r3, s3) {
var a2 = o2 ? o2 + t3 : t3;
if (!this._events[a2])
return false;
var c2, l2, h2 = this._events[a2], d2 = arguments.length;
if (h2.fn) {
switch (h2.once && this.removeListener(t3, h2.fn, undefined, true), d2) {
case 1:
return h2.fn.call(h2.context), true;
case 2:
return h2.fn.call(h2.context, e3), true;
case 3:
return h2.fn.call(h2.context, e3, n3), true;
case 4:
return h2.fn.call(h2.context, e3, n3, i3), true;
case 5:
return h2.fn.call(h2.context, e3, n3, i3, r3), true;
case 6:
return h2.fn.call(h2.context, e3, n3, i3, r3, s3), true;
}
for (l2 = 1, c2 = new Array(d2 - 1);l2 < d2; l2++)
c2[l2 - 1] = arguments[l2];
h2.fn.apply(h2.context, c2);
} else {
var u2, p2 = h2.length;
for (l2 = 0;l2 < p2; l2++)
switch (h2[l2].once && this.removeListener(t3, h2[l2].fn, undefined, true), d2) {
case 1:
h2[l2].fn.call(h2[l2].context);
break;
case 2:
h2[l2].fn.call(h2[l2].context, e3);
break;
case 3:
h2[l2].fn.call(h2[l2].context, e3, n3);
break;
case 4:
h2[l2].fn.call(h2[l2].context, e3, n3, i3);
break;
default:
if (!c2)
for (u2 = 1, c2 = new Array(d2 - 1);u2 < d2; u2++)
c2[u2 - 1] = arguments[u2];
h2[l2].fn.apply(h2[l2].context, c2);
}
}
return true;
}, s2.prototype.on = function(t3, e3, n3) {
var i3 = new r2(e3, n3 || this), s3 = o2 ? o2 + t3 : t3;
return this._events[s3] ? this._events[s3].fn ? this._events[s3] = [this._events[s3], i3] : this._events[s3].push(i3) : (this._events[s3] = i3, this._eventsCount++), this;
}, s2.prototype.once = function(t3, e3, n3) {
var i3 = new r2(e3, n3 || this, true), s3 = o2 ? o2 + t3 : t3;
return this._events[s3] ? this._events[s3].fn ? this._events[s3] = [this._events[s3], i3] : this._events[s3].push(i3) : (this._events[s3] = i3, this._eventsCount++), this;
}, s2.prototype.removeListener = function(t3, e3, n3, r3) {
var s3 = o2 ? o2 + t3 : t3;
if (!this._events[s3])
return this;
if (!e3)
return --this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3], this;
var a2 = this._events[s3];
if (a2.fn)
a2.fn !== e3 || r3 && !a2.once || n3 && a2.context !== n3 || (--this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3]);
else {
for (var c2 = 0, l2 = [], h2 = a2.length;c2 < h2; c2++)
(a2[c2].fn !== e3 || r3 && !a2[c2].once || n3 && a2[c2].context !== n3) && l2.push(a2[c2]);
l2.length ? this._events[s3] = l2.length === 1 ? l2[0] : l2 : --this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3];
}
return this;
}, s2.prototype.removeAllListeners = function(t3) {
var e3;
return t3 ? (e3 = o2 ? o2 + t3 : t3, this._events[e3] && (--this._eventsCount === 0 ? this._events = new i2 : delete this._events[e3])) : (this._events = new i2, this._eventsCount = 0), this;
}, s2.prototype.off = s2.prototype.removeListener, s2.prototype.addListener = s2.prototype.on, s2.prototype.setMaxListeners = function() {
return this;
}, s2.prefixed = o2, s2.EventEmitter = s2, e2 !== undefined && (e2.exports = s2);
} });
var m = s({ "node_modules/xml-lexer/node_modules/eventemitter3/index.js"(t2, e2) {
var n2 = Object.prototype.hasOwnProperty, o2 = "~";
function i2() {}
function r2(t3, e3, n3) {
this.fn = t3, this.context = e3, this.once = n3 || false;
}
function s2() {
this._events = new i2, this._eventsCount = 0;
}
Object.create && (i2.prototype = Object.create(null), new i2().__proto__ || (o2 = false)), s2.prototype.eventNames = function() {
var t3, e3, i3 = [];
if (this._eventsCount === 0)
return i3;
for (e3 in t3 = this._events)
n2.call(t3, e3) && i3.push(o2 ? e3.slice(1) : e3);
return Object.getOwnPropertySymbols ? i3.concat(Object.getOwnPropertySymbols(t3)) : i3;
}, s2.prototype.listeners = function(t3, e3) {
var n3 = o2 ? o2 + t3 : t3, i3 = this._events[n3];
if (e3)
return !!i3;
if (!i3)
return [];
if (i3.fn)
return [i3.fn];
for (var r3 = 0, s3 = i3.length, a2 = new Array(s3);r3 < s3; r3++)
a2[r3] = i3[r3].fn;
return a2;
}, s2.prototype.emit = function(t3, e3, n3, i3, r3, s3) {
var a2 = o2 ? o2 + t3 : t3;
if (!this._events[a2])
return false;
var c2, l2, h2 = this._events[a2], d2 = arguments.length;
if (h2.fn) {
switch (h2.once && this.removeListener(t3, h2.fn, undefined, true), d2) {
case 1:
return h2.fn.call(h2.context), true;
case 2:
return h2.fn.call(h2.context, e3), true;
case 3:
return h2.fn.call(h2.context, e3, n3), true;
case 4:
return h2.fn.call(h2.context, e3, n3, i3), true;
case 5:
return h2.fn.call(h2.context, e3, n3, i3, r3), true;
case 6:
return h2.fn.call(h2.context, e3, n3, i3, r3, s3), true;
}
for (l2 = 1, c2 = new Array(d2 - 1);l2 < d2; l2++)
c2[l2 - 1] = arguments[l2];
h2.fn.apply(h2.context, c2);
} else {
var u2, p2 = h2.length;
for (l2 = 0;l2 < p2; l2++)
switch (h2[l2].once && this.removeListener(t3, h2[l2].fn, undefined, true), d2) {
case 1:
h2[l2].fn.call(h2[l2].context);
break;
case 2:
h2[l2].fn.call(h2[l2].context, e3);
break;
case 3:
h2[l2].fn.call(h2[l2].context, e3, n3);
break;
case 4:
h2[l2].fn.call(h2[l2].context, e3, n3, i3);
break;
default:
if (!c2)
for (u2 = 1, c2 = new Array(d2 - 1);u2 < d2; u2++)
c2[u2 - 1] = arguments[u2];
h2[l2].fn.apply(h2[l2].context, c2);
}
}
return true;
}, s2.prototype.on = function(t3, e3, n3) {
var i3 = new r2(e3, n3 || this), s3 = o2 ? o2 + t3 : t3;
return this._events[s3] ? this._events[s3].fn ? this._events[s3] = [this._events[s3], i3] : this._events[s3].push(i3) : (this._events[s3] = i3, this._eventsCount++), this;
}, s2.prototype.once = function(t3, e3, n3) {
var i3 = new r2(e3, n3 || this, true), s3 = o2 ? o2 + t3 : t3;
return this._events[s3] ? this._events[s3].fn ? this._events[s3] = [this._events[s3], i3] : this._events[s3].push(i3) : (this._events[s3] = i3, this._eventsCount++), this;
}, s2.prototype.removeListener = function(t3, e3, n3, r3) {
var s3 = o2 ? o2 + t3 : t3;
if (!this._events[s3])
return this;
if (!e3)
return --this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3], this;
var a2 = this._events[s3];
if (a2.fn)
a2.fn !== e3 || r3 && !a2.once || n3 && a2.context !== n3 || (--this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3]);
else {
for (var c2 = 0, l2 = [], h2 = a2.length;c2 < h2; c2++)
(a2[c2].fn !== e3 || r3 && !a2[c2].once || n3 && a2[c2].context !== n3) && l2.push(a2[c2]);
l2.length ? this._events[s3] = l2.length === 1 ? l2[0] : l2 : --this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3];
}
return this;
}, s2.prototype.removeAllListeners = function(t3) {
var e3;
return t3 ? (e3 = o2 ? o2 + t3 : t3, this._events[e3] && (--this._eventsCount === 0 ? this._events = new i2 : delete this._events[e3])) : (this._events = new i2, this._eventsCount = 0), this;
}, s2.prototype.off = s2.prototype.removeListener, s2.prototype.addListener = s2.prototype.on, s2.prototype.setMaxListeners = function() {
return this;
}, s2.prefixed = o2, s2.EventEmitter = s2, e2 !== undefined && (e2.exports = s2);
} });
var g = s({ "node_modules/xml-lexer/dist/lexer.js"(t2, e2) {
function n2(t3, e3, n3) {
return e3 in t3 ? Object.defineProperty(t3, e3, { value: n3, enumerable: true, configurable: true, writable: true }) : t3[e3] = n3, t3;
}
var o2 = m(), i2 = function() {}, r2 = { data: "state-data", cdata: "state-cdata", tagBegin: "state-tag-begin", tagName: "state-tag-name", tagEnd: "state-tag-end", attributeNameStart: "state-attribute-name-start", attributeName: "state-attribute-name", attributeNameEnd: "state-attribute-name-end", attributeValueBegin: "state-attribute-value-begin", attributeValue: "state-attribute-value" }, s2 = { lt: "action-lt", gt: "action-gt", space: "action-space", equal: "action-equal", quote: "action-quote", slash: "action-slash", char: "action-char", error: "action-error" }, a2 = { text: "text", openTag: "open-tag", closeTag: "close-tag", attributeName: "attribute-name", attributeValue: "attribute-value" }, c2 = { " ": s2.space, "\t": s2.space, "\n": s2.space, "\r": s2.space, "<": s2.lt, ">": s2.gt, '"': s2.quote, "'": s2.quote, "=": s2.equal, "/": s2.slash };
e2.exports = { State: r2, Action: s2, Type: a2, create: function(t3) {
var e3, l2, h2, d2, u2, p2, m2, g2, f, y;
t3 = Object.assign({ debug: false }, t3);
var _ = new o2, b = r2.data, x = "", v = "", I = "", S = "", C = "", P = "", M = function(e4, n3) {
if (v[0] !== "?" && v[0] !== "!") {
var o3 = { type: e4, value: n3 };
t3.debug && console.log("emit:", o3), _.emit("data", o3);
}
};
_.stateMachine = (n2(y = {}, r2.data, (n2(e3 = {}, s2.lt, function() {
x.trim() && M(a2.text, x), v = "", C = false, b = r2.tagBegin;
}), n2(e3, s2.char, function(t4) {
x += t4;
}), e3)), n2(y, r2.cdata, n2({}, s2.char, function(t4) {
(x += t4).substr(-3) === "]]>" && (M(a2.text, x.slice(0, -3)), x = "", b = r2.data);
})), n2(y, r2.tagBegin, (n2(l2 = {}, s2.space, i2), n2(l2, s2.char, function(t4) {
v = t4, b = r2.tagName;
}), n2(l2, s2.slash, function() {
v = "", C = true;
}), l2)), n2(y, r2.tagName, (n2(h2 = {}, s2.space, function() {
C ? b = r2.tagEnd : (b = r2.attributeNameStart, M(a2.openTag, v));
}), n2(h2, s2.gt, function() {
M(C ? a2.closeTag : a2.openTag, v), x = "", b = r2.data;
}), n2(h2, s2.slash, function() {
b = r2.tagEnd, M(a2.openTag, v);
}), n2(h2, s2.char, function(t4) {
(v += t4) === "![CDATA[" && (b = r2.cdata, x = "", v = "");
}), h2)), n2(y, r2.tagEnd, (n2(d2 = {}, s2.gt, function() {
M(a2.closeTag, v), x = "", b = r2.data;
}), n2(d2, s2.char, i2), d2)), n2(y, r2.attributeNameStart, (n2(u2 = {}, s2.char, function(t4) {
I = t4, b = r2.attributeName;
}), n2(u2, s2.gt, function() {
x = "", b = r2.data;
}), n2(u2, s2.space, i2), n2(u2, s2.slash, function() {
C = true, b = r2.tagEnd;
}), u2)), n2(y, r2.attributeName, (n2(p2 = {}, s2.space, function() {
b = r2.attributeNameEnd;
}), n2(p2, s2.equal, function() {
M(a2.attributeName, I), b = r2.attributeValueBegin;
}), n2(p2, s2.gt, function() {
S = "", M(a2.attributeName, I), M(a2.attributeValue, S), x = "", b = r2.data;
}), n2(p2, s2.slash, function() {
C = true, S = "", M(a2.attributeName, I), M(a2.attributeValue, S), b = r2.tagEnd;
}), n2(p2, s2.char, function(t4) {
I += t4;
}), p2)), n2(y, r2.attributeNameEnd, (n2(m2 = {}, s2.space, i2), n2(m2, s2.equal, function() {
M(a2.attributeName, I), b = r2.attributeValueBegin;
}), n2(m2, s2.gt, function() {
S = "", M(a2.attributeName, I), M(a2.attributeValue, S), x = "", b = r2.data;
}), n2(m2, s2.char, function(t4) {
S = "", M(a2.attributeName, I), M(a2.attributeValue, S), I = t4, b = r2.attributeName;
}), m2)), n2(y, r2.attributeValueBegin, (n2(g2 = {}, s2.space, i2), n2(g2, s2.quote, function(t4) {
P = t4, S = "", b = r2.attributeValue;
}), n2(g2, s2.gt, function() {
M(a2.attributeValue, S = ""), x = "", b = r2.data;
}), n2(g2, s2.char, function(t4) {
P = "", S = t4, b = r2.attributeValue;
}), g2)), n2(y, r2.attributeValue, (n2(f = {}, s2.space, function(t4) {
P ? S += t4 : (M(a2.attributeValue, S), b = r2.attributeNameStart);
}), n2(f, s2.quote, function(t4) {
P === t4 ? (M(a2.attributeValue, S), b = r2.attributeNameStart) : S += t4;
}), n2(f, s2.gt, function(t4) {
P ? S += t4 : (M(a2.attributeValue, S), x = "", b = r2.data);
}), n2(f, s2.slash, function(t4) {
P ? S += t4 : (M(a2.attributeValue, S), C = true, b = r2.tagEnd);
}), n2(f, s2.char, function(t4) {
S += t4;
}), f)), y);
var N = function(e4) {
t3.debug && console.log(b, e4);
var n3 = _.stateMachine[b], o3 = n3[function(t4) {
return c2[t4] || s2.char;
}(e4)] || n3[s2.error] || n3[s2.char];
o3(e4);
};
return _.write = function(t4) {
for (var e4 = t4.length, n3 = 0;n3 < e4; n3++)
N(t4[n3]);
}, _;
} };
} });
var f = s({ "node_modules/xml-reader/dist/reader.js"(t2, e2) {
var n2 = p(), o2 = g(), i2 = o2.Type, r2 = { element: "element", text: "text" }, s2 = function(t3) {
return Object.assign({ name: "", type: r2.element, value: "", parent: null, attributes: {}, children: [] }, t3);
}, a2 = function(t3) {
t3 = Object.assign({ stream: false, parentNodes: true, doneEvent: "done", tagPrefix: "tag:", emitTopLevelOnly: false, debug: false }, t3);
var e3 = undefined, a3 = undefined, c2 = undefined, l2 = undefined, h2 = new n2, d2 = function(n3) {
switch (n3.type) {
case i2.openTag:
if (c2 === null)
(c2 = a3).name = n3.value;
else {
var o3 = s2({ name: n3.value, parent: c2 });
c2.children.push(o3), c2 = o3;
}
break;
case i2.closeTag:
var d3 = c2.parent;
if (t3.parentNodes || (c2.parent = null), c2.name !== n3.value)
break;
t3.stream && d3 === a3 && (a3.children = [], c2.parent = null), t3.emitTopLevelOnly && d3 !== a3 || (h2.emit(t3.tagPrefix + c2.name, c2), h2.emit("tag", c2.name, c2)), c2 === a3 && (e3.removeAllListeners("data"), h2.emit(t3.doneEvent, c2), a3 = null), c2 = d3;
break;
case i2.text:
c2 && c2.children.push(s2({ type: r2.text, value: n3.value, parent: t3.parentNodes ? c2 : null }));
break;
case i2.attributeName:
l2 = n3.value, c2.attributes[l2] = "";
break;
case i2.attributeValue:
c2.attributes[l2] = n3.value;
}
};
return h2.reset = function() {
(e3 = o2.create({ debug: t3.debug })).on("data", d2), a3 = s2(), c2 = null, l2 = "", h2.parse = e3.write;
}, h2.reset(), h2;
};
e2.exports = { parseSync: function(t3, e3) {
e3 = Object.assign({}, e3, { stream: false, tagPrefix: ":" });
var n3 = a2(e3), o3 = undefined;
return n3.on("done", function(t4) {
o3 = t4;
}), n3.parse(t3), o3;
}, create: a2, NodeType: r2 };
} });
var y = s({ "node_modules/binary-search-bounds/search-bounds.js"(t2, e2) {
function n2(t3, e3, n3, o3, i3) {
for (var r3 = i3 + 1;o3 <= i3; ) {
var s3 = o3 + i3 >>> 1, a3 = t3[s3];
(n3 !== undefined ? n3(a3, e3) : a3 - e3) >= 0 ? (r3 = s3, i3 = s3 - 1) : o3 = s3 + 1;
}
return r3;
}
function o2(t3, e3, n3, o3, i3) {
for (var r3 = i3 + 1;o3 <= i3; ) {
var s3 = o3 + i3 >>> 1, a3 = t3[s3];
(n3 !== undefined ? n3(a3, e3) : a3 - e3) > 0 ? (r3 = s3, i3 = s3 - 1) : o3 = s3 + 1;
}
return r3;
}
function i2(t3, e3, n3, o3, i3) {
for (var r3 = o3 - 1;o3 <= i3; ) {
var s3 = o3 + i3 >>> 1, a3 = t3[s3];
(n3 !== undefined ? n3(a3, e3) : a3 - e3) < 0 ? (r3 = s3, o3 = s3 + 1) : i3 = s3 - 1;
}
return r3;
}
function r2(t3, e3, n3, o3, i3) {
for (var r3 = o3 - 1;o3 <= i3; ) {
var s3 = o3 + i3 >>> 1, a3 = t3[s3];
(n3 !== undefined ? n3(a3, e3) : a3 - e3) <= 0 ? (r3 = s3, o3 = s3 + 1) : i3 = s3 - 1;
}
return r3;
}
function s2(t3, e3, n3, o3, i3) {
for (;o3 <= i3; ) {
var r3 = o3 + i3 >>> 1, s3 = t3[r3], a3 = n3 !== undefined ? n3(s3, e3) : s3 - e3;
if (a3 === 0)
return r3;
a3 <= 0 ? o3 = r3 + 1 : i3 = r3 - 1;
}
return -1;
}
function a2(t3, e3, n3, o3, i3, r3) {
return typeof n3 == "function" ? r3(t3, e3, n3, o3 === undefined ? 0 : 0 | o3, i3 === undefined ? t3.length - 1 : 0 | i3) : r3(t3, e3, undefined, n3 === undefined ? 0 : 0 | n3, o3 === undefined ? t3.length - 1 : 0 | o3);
}
e2.exports = { ge: function(t3, e3, o3, i3, r3) {
return a2(t3, e3, o3, i3, r3, n2);
}, gt: function(t3, e3, n3, i3, r3) {
return a2(t3, e3, n3, i3, r3, o2);
}, lt: function(t3, e3, n3, o3, r3) {
return a2(t3, e3, n3, o3, r3, i2);
}, le: function(t3, e3, n3, o3, i3) {
return a2(t3, e3, n3, o3, i3, r2);
}, eq: function(t3, e3, n3, o3, i3) {
return a2(t3, e3, n3, o3, i3, s2);
} };
} });
var _ = s({ "node_modules/two-product/two-product.js"(t2, e2) {
e2.exports = function(t3, e3, o2) {
var i2 = t3 * e3, r2 = n2 * t3, s2 = r2 - (r2 - t3), a2 = t3 - s2, c2 = n2 * e3, l2 = c2 - (c2 - e3), h2 = e3 - l2, d2 = a2 * h2 - (i2 - s2 * l2 - a2 * l2 - s2 * h2);
if (o2)
return o2[0] = d2, o2[1] = i2, o2;
return [d2, i2];
};
var n2 = +(Math.pow(2, 27) + 1);
} });
var b = s({ "node_modules/robust-sum/robust-sum.js"(t2, e2) {
e2.exports = function(t3, e3) {
var n2 = 0 | t3.length, o2 = 0 | e3.length;
if (n2 === 1 && o2 === 1)
return function(t4, e4) {
var n3 = t4 + e4, o3 = n3 - t4, i3 = n3 - o3, r3 = e4 - o3, s3 = t4 - i3, a3 = s3 + r3;
if (a3)
return [a3, n3];
return [n3];
}(t3[0], e3[0]);
var i2, r2, s2 = new Array(n2 + o2), a2 = 0, c2 = 0, l2 = 0, h2 = Math.abs, d2 = t3[c2], u2 = h2(d2), p2 = e3[l2], m2 = h2(p2);
u2 < m2 ? (r2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t3[c2]))) : (r2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = e3[l2])));
c2 < n2 && u2 < m2 || l2 >= o2 ? (i2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t3[c2]))) : (i2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = e3[l2])));
var g2, f2, y2 = i2 + r2, _2 = y2 - i2, b2 = r2 - _2, x = b2, v = y2;
for (;c2 < n2 && l2 < o2; )
u2 < m2 ? (i2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t3[c2]))) : (i2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = e3[l2]))), (b2 = (r2 = x) - (_2 = (y2 = i2 + r2) - i2)) && (s2[a2++] = b2), x = v - ((g2 = v + y2) - (f2 = g2 - v)) + (y2 - f2), v = g2;
for (;c2 < n2; )
(b2 = (r2 = x) - (_2 = (y2 = (i2 = d2) + r2) - i2)) && (s2[a2++] = b2), x = v - ((g2 = v + y2) - (f2 = g2 - v)) + (y2 - f2), v = g2, (c2 += 1) < n2 && (d2 = t3[c2]);
for (;l2 < o2; )
(b2 = (r2 = x) - (_2 = (y2 = (i2 = p2) + r2) - i2)) && (s2[a2++] = b2), x = v - ((g2 = v + y2) - (f2 = g2 - v)) + (y2 - f2), v = g2, (l2 += 1) < o2 && (p2 = e3[l2]);
x && (s2[a2++] = x);
v && (s2[a2++] = v);
a2 || (s2[a2++] = 0);
return s2.length = a2, s2;
};
} });
var x = s({ "node_modules/two-sum/two-sum.js"(t2, e2) {
e2.exports = function(t3, e3, n2) {
var o2 = t3 + e3, i2 = o2 - t3, r2 = e3 - i2, s2 = t3 - (o2 - i2);
if (n2)
return n2[0] = s2 + r2, n2[1] = o2, n2;
return [s2 + r2, o2];
};
} });
var v = s({ "node_modules/robust-scale/robust-scale.js"(t2, e2) {
var n2 = _(), o2 = x();
e2.exports = function(t3, e3) {
var i2 = t3.length;
if (i2 === 1) {
var r2 = n2(t3[0], e3);
return r2[0] ? r2 : [r2[1]];
}
var s2 = new Array(2 * i2), a2 = [0.1, 0.1], c2 = [0.1, 0.1], l2 = 0;
n2(t3[0], e3, a2), a2[0] && (s2[l2++] = a2[0]);
for (var h2 = 1;h2 < i2; ++h2) {
n2(t3[h2], e3, c2);
var d2 = a2[1];
o2(d2, c2[0], a2), a2[0] && (s2[l2++] = a2[0]);
var u2 = c2[1], p2 = a2[1], m2 = u2 + p2, g2 = p2 - (m2 - u2);
a2[1] = m2, g2 && (s2[l2++] = g2);
}
a2[1] && (s2[l2++] = a2[1]);
l2 === 0 && (s2[l2++] = 0);
return s2.length = l2, s2;
};
} });
var I = s({ "node_modules/robust-subtract/robust-diff.js"(t2, e2) {
e2.exports = function(t3, e3) {
var n2 = 0 | t3.length, o2 = 0 | e3.length;
if (n2 === 1 && o2 === 1)
return function(t4, e4) {
var n3 = t4 + e4, o3 = n3 - t4, i3 = n3 - o3, r3 = e4 - o3, s3 = t4 - i3, a3 = s3 + r3;
if (a3)
return [a3, n3];
return [n3];
}(t3[0], -e3[0]);
var i2, r2, s2 = new Array(n2 + o2), a2 = 0, c2 = 0, l2 = 0, h2 = Math.abs, d2 = t3[c2], u2 = h2(d2), p2 = -e3[l2], m2 = h2(p2);
u2 < m2 ? (r2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t3[c2]))) : (r2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = -e3[l2])));
c2 < n2 && u2 < m2 || l2 >= o2 ? (i2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t3[c2]))) : (i2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = -e3[l2])));
var g2, f2, y2 = i2 + r2, _2 = y2 - i2, b2 = r2 - _2, x2 = b2, v2 = y2;
for (;c2 < n2 && l2 < o2; )
u2 < m2 ? (i2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t3[c2]))) : (i2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = -e3[l2]))), (b2 = (r2 = x2) - (_2 = (y2 = i2 + r2) - i2)) && (s2[a2++] = b2), x2 = v2 - ((g2 = v2 + y2) - (f2 = g2 - v2)) + (y2 - f2), v2 = g2;
for (;c2 < n2; )
(b2 = (r2 = x2) - (_2 = (y2 = (i2 = d2) + r2) - i2)) && (s2[a2++] = b2), x2 = v2 - ((g2 = v2 + y2) - (f2 = g2 - v2)) + (y2 - f2), v2 = g2, (c2 += 1) < n2 && (d2 = t3[c2]);
for (;l2 < o2; )
(b2 = (r2 = x2) - (_2 = (y2 = (i2 = p2) + r2) - i2)) && (s2[a2++] = b2), x2 = v2 - ((g2 = v2 + y2) - (f2 = g2 - v2)) + (y2 - f2), v2 = g2, (l2 += 1) < o2 && (p2 = -e3[l2]);
x2 && (s2[a2++] = x2);
v2 && (s2[a2++] = v2);
a2 || (s2[a2++] = 0);
return s2.length = a2, s2;
};
} });
var S = s({ "node_modules/robust-orientation/orientation.js"(t2, e2) {
var n2 = _(), o2 = b(), i2 = v(), r2 = I();
function s2(t3, e3, n3, o3) {
return function(n4, i3, r3) {
var s3 = t3(t3(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), t3(e3(n4[1], i3[0]), e3(-i3[1], n4[0]))), a3 = t3(e3(n4[1], r3[0]), e3(-r3[1], n4[0])), c3 = o3(s3, a3);
return c3[c3.length - 1];
};
}
function a2(t3, e3, n3, o3) {
return function(i3, r3, s3, a3) {
var c3 = t3(t3(n3(t3(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), r3[2]), t3(n3(t3(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), -s3[2]), n3(t3(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), a3[2]))), t3(n3(t3(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), i3[2]), t3(n3(t3(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -r3[2]), n3(t3(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), a3[2])))), l3 = t3(t3(n3(t3(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), i3[2]), t3(n3(t3(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -s3[2]), n3(t3(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), a3[2]))), t3(n3(t3(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), i3[2]), t3(n3(t3(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), -r3[2]), n3(t3(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), s3[2])))), h3 = o3(c3, l3);
return h3[h3.length - 1];
};
}
function c2(t3, e3, n3, o3) {
return function(i3, r3, s3, a3, c3) {
var l3 = t3(t3(t3(n3(t3(n3(t3(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), s3[2]), t3(n3(t3(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), -a3[2]), n3(t3(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), c3[2]))), r3[3]), t3(n3(t3(n3(t3(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), r3[2]), t3(n3(t3(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), -a3[2]), n3(t3(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), c3[2]))), -s3[3]), n3(t3(n3(t3(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), r3[2]), t3(n3(t3(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), -s3[2]), n3(t3(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), c3[2]))), a3[3]))), t3(n3(t3(n3(t3(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), r3[2]), t3(n3(t3(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), -s3[2]), n3(t3(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), a3[2]))), -c3[3]), t3(n3(t3(n3(t3(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), r3[2]), t3(n3(t3(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), -a3[2]), n3(t3(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), c3[2]))), i3[3]), n3(t3(n3(t3(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), i3[2]), t3(n3(t3(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -a3[2]), n3(t3(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), c3[2]))), -r3[3])))), t3(t3(n3(t3(n3(t3(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), i3[2]), t3(n3(t3(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -r3[2]), n3(t3(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), c3[2]))), a3[3]), t3(n3(t3(n3(t3(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), i3[2]), t3(n3(t3(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -r3[2]), n3(t3(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), a3[2]))), -c3[3]), n3(t3(n3(t3(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), r3[2]), t3(n3(t3(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), -s3[2]), n3(t3(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), a3[2]))), i3[3]))), t3(n3(t3(n3(t3(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), i3[2]), t3(n3(t3(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -s3[2]), n3(t3(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), a3[2]))), -r3[3]), t3(n3(t3(n3(t3(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), i3[2]), t3(n3(t3(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -r3[2]), n3(t3(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), a3[2]))), s3[3]), n3(t3(n3(t3(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), i3[2]), t3(n3(t3(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), -r3[2]), n3(t3(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), s3[2]))), -a3[3]))))), h3 = t3(t3(t3(n3(t3(n3(t3(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), s3[2]), t3(n3(t3(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), -a3[2]), n3(t3(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), c3[2]))), i3[3]), n3(t3(n3(t3(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), i3[2]), t3(n3(t3(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -a3[2]), n3(t3(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), c3[2]))), -s3[3])), t3(n3(t3(n3(t3(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), i3[2]), t3(n3(t3(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -s3[2]), n3(t3(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), c3[2]))), a3[3]), n3(t3(n3(t3(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), i3[2]), t3(n3(t3(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -s3[2]), n3(t3(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), a3[2]))), -c3[3]))), t3(t3(n3(t3(n3(t3(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), r3[2]), t3(n3(t3(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), -s3[2]), n3(t3(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), c3[2]))), i3[3]), n3(t3(n3(t3(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), i3[2]), t3(n3(t3(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -s3[2]), n3(t3(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), c3[2]))), -r3[3])), t3(n3(t3(n3(t3(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), i3[2]), t3(n3(t3(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -r3[2]), n3(t3(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), c3[2]))), s3[3]), n3(t3(n3(t3(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), i3[2]), t3(n3(t3(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), -r3[2]), n3(t3(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), s3[2]))), -c3[3])))), d3 = o3(l3, h3);
return d3[d3.length - 1];
};
}
function l2(t3) {
return (t3 === 3 ? s2 : t3 === 4 ? a2 : c2)(o2, n2, i2, r2);
}
var h2 = l2(3), d2 = l2(4), u2 = [function() {
return 0;
}, function() {
return 0;
}, function(t3, e3) {
return e3[0] - t3[0];
}, function(t3, e3, n3) {
var o3, i3 = (t3[1] - n3[1]) * (e3[0] - n3[0]), r3 = (t3[0] - n3[0]) * (e3[1] - n3[1]), s3 = i3 - r3;
if (i3 > 0) {
if (r3 <= 0)
return s3;
o3 = i3 + r3;
} else {
if (!(i3 < 0))
return s3;
if (r3 >= 0)
return s3;
o3 = -(i3 + r3);
}
var a3 = 0.00000000000000033306690738754716 * o3;
return s3 >= a3 || s3 <= -a3 ? s3 : h2(t3, e3, n3);
}, function(t3, e3, n3, o3) {
var i3 = t3[0] - o3[0], r3 = e3[0] - o3[0], s3 = n3[0] - o3[0], a3 = t3[1] - o3[1], c3 = e3[1] - o3[1], l3 = n3[1] - o3[1], h3 = t3[2] - o3[2], u3 = e3[2] - o3[2], p3 = n3[2] - o3[2], m3 = r3 * l3, g2 = s3 * c3, f2 = s3 * a3, y2 = i3 * l3, _2 = i3 * c3, b2 = r3 * a3, x2 = h3 * (m3 - g2) + u3 * (f2 - y2) + p3 * (_2 - b2), v2 = 0.0000000000000007771561172376103 * ((Math.abs(m3) + Math.abs(g2)) * Math.abs(h3) + (Math.abs(f2) + Math.abs(y2)) * Math.abs(u3) + (Math.abs(_2) + Math.abs(b2)) * Math.abs(p3));
return x2 > v2 || -x2 > v2 ? x2 : d2(t3, e3, n3, o3);
}];
function p2(t3) {
var e3 = u2[t3.length];
return e3 || (e3 = u2[t3.length] = l2(t3.length)), e3.apply(undefined, t3);
}
function m2(t3, e3, n3, o3, i3, r3, s3) {
return function(e4, n4, a3, c3, l3) {
switch (arguments.length) {
case 0:
case 1:
return 0;
case 2:
return o3(e4, n4);
case 3:
return i3(e4, n4, a3);
case 4:
return r3(e4, n4, a3, c3);
case 5:
return s3(e4, n4, a3, c3, l3);
}
for (var h3 = new Array(arguments.length), d3 = 0;d3 < arguments.length; ++d3)
h3[d3] = arguments[d3];
return t3(h3);
};
}
(function() {
for (;u2.length <= 5; )
u2.push(l2(u2.length));
e2.exports = m2.apply(undefined, [p2].concat(u2));
for (var t3 = 0;t3 <= 5; ++t3)
e2.exports[t3] = u2[t3];
})();
} });
var C = s({ "node_modules/cdt2d/lib/monotone.js"(t2, e2) {
var n2 = y(), o2 = S()[3];
function i2(t3, e3, n3, o3, i3) {
this.a = t3, this.b = e3, this.idx = n3, this.lowerIds = o3, this.upperIds = i3;
}
function r2(t3, e3, n3, o3) {
this.a = t3, this.b = e3, this.type = n3, this.idx = o3;
}
function s2(t3, e3) {
var n3 = t3.a[0] - e3.a[0] || t3.a[1] - e3.a[1] || t3.type - e3.type;
return n3 || (t3.type !== 0 && (n3 = o2(t3.a, t3.b, e3.b)) ? n3 : t3.idx - e3.idx);
}
function a2(t3, e3) {
return o2(t3.a, t3.b, e3);
}
function c2(t3, e3, i3, r3, s3) {
for (var c3 = n2.lt(e3, r3, a2), l3 = n2.gt(e3, r3, a2), h3 = c3;h3 < l3; ++h3) {
for (var d3 = e3[h3], u2 = d3.lowerIds, p2 = u2.length;p2 > 1 && o2(i3[u2[p2 - 2]], i3[u2[p2 - 1]], r3) > 0; )
t3.push([u2[p2 - 1], u2[p2 - 2], s3]), p2 -= 1;
u2.length = p2, u2.push(s3);
var m2 = d3.upperIds;
for (p2 = m2.length;p2 > 1 && o2(i3[m2[p2 - 2]], i3[m2[p2 - 1]], r3) < 0; )
t3.push([m2[p2 - 2], m2[p2 - 1], s3]), p2 -= 1;
m2.length = p2, m2.push(s3);
}
}
function l2(t3, e3) {
var n3;
return (n3 = t3.a[0] < e3.a[0] ? o2(t3.a, t3.b, e3.a) : o2(e3.b, e3.a, t3.a)) ? n3 : (n3 = e3.b[0] < t3.b[0] ? o2(t3.a, t3.b, e3.b) : o2(e3.b, e3.a, t3.b)) || t3.idx - e3.idx;
}
function h2(t3, e3, o3) {
var r3 = n2.le(t3, o3, l2), s3 = t3[r3], a3 = s3.upperIds, c3 = a3[a3.length - 1];
s3.upperIds = [c3], t3.splice(r3 + 1, 0, new i2(o3.a, o3.b, o3.idx, [c3], a3));
}
function d2(t3, e3, o3) {
var i3 = o3.a;
o3.a = o3.b, o3.b = i3;
var r3 = n2.eq(t3, o3, l2), s3 = t3[r3];
t3[r3 - 1].upperIds = s3.upperIds, t3.splice(r3, 1);
}
e2.exports = function(t3, e3) {
for (var n3 = t3.length, o3 = e3.length, a3 = [], l3 = 0;l3 < n3; ++l3)
a3.push(new r2(t3[l3], null, 0, l3));
for (l3 = 0;l3 < o3; ++l3) {
var u2 = e3[l3], p2 = t3[u2[0]], m2 = t3[u2[1]];
p2[0] < m2[0] ? a3.push(new r2(p2, m2, 2, l3), new r2(m2, p2, 1, l3)) : p2[0] > m2[0] && a3.push(new r2(m2, p2, 2, l3), new r2(p2, m2, 1, l3));
}
a3.sort(s2);
for (var g2 = a3[0].a[0] - (1 + Math.abs(a3[0].a[0])) * Math.pow(2, -52), f2 = [new i2([g2, 1], [g2, 0], -1, [], [])], y2 = [], _2 = (l3 = 0, a3.length);l3 < _2; ++l3) {
var b2 = a3[l3], x2 = b2.type;
x2 === 0 ? c2(y2, f2, t3, b2.a, b2.idx) : x2 === 2 ? h2(f2, t3, b2) : d2(f2, t3, b2);
}
return y2;
};
} });
var P = s({ "node_modules/cdt2d/lib/triangulation.js"(t2, e2) {
var n2 = y();
function o2(t3, e3) {
this.stars = t3, this.edges = e3;
}
e2.exports = function(t3, e3) {
for (var n3 = new Array(t3), i3 = 0;i3 < t3; ++i3)
n3[i3] = [];
return new o2(n3, e3);
};
var i2 = o2.prototype;
function r2(t3, e3, n3) {
for (var o3 = 1, i3 = t3.length;o3 < i3; o3 += 2)
if (t3[o3 - 1] === e3 && t3[o3] === n3)
return t3[o3 - 1] = t3[i3 - 2], t3[o3] = t3[i3 - 1], void (t3.length = i3 - 2);
}
i2.isConstraint = function() {
var t3 = [0, 0];
function e3(t4, e4) {
return t4[0] - e4[0] || t4[1] - e4[1];
}
return function(o3, i3) {
return t3[0] = Math.min(o3, i3), t3[1] = Math.max(o3, i3), n2.eq(this.edges, t3, e3) >= 0;
};
}(), i2.removeTriangle = function(t3, e3, n3) {
var o3 = this.stars;
r2(o3[t3], e3, n3), r2(o3[e3], n3, t3), r2(o3[n3], t3, e3);
}, i2.addTriangle = function(t3, e3, n3) {
var o3 = this.stars;
o3[t3].push(e3, n3), o3[e3].push(n3, t3), o3[n3].push(t3, e3);
}, i2.opposite = function(t3, e3) {
for (var n3 = this.stars[e3], o3 = 1, i3 = n3.length;o3 < i3; o3 += 2)
if (n3[o3] === t3)
return n3[o3 - 1];
return -1;
}, i2.flip = function(t3, e3) {
var n3 = this.opposite(t3, e3), o3 = this.opposite(e3, t3);
this.removeTriangle(t3, e3, n3), this.removeTriangle(e3, t3, o3), this.addTriangle(t3, o3, n3), this.addTriangle(e3, n3, o3);
}, i2.edges = function() {
for (var t3 = this.stars, e3 = [], n3 = 0, o3 = t3.length;n3 < o3; ++n3)
for (var i3 = t3[n3], r3 = 0, s2 = i3.length;r3 < s2; r3 += 2)
e3.push([i3[r3], i3[r3 + 1]]);
return e3;
}, i2.cells = function() {
for (var t3 = this.stars, e3 = [], n3 = 0, o3 = t3.length;n3 < o3; ++n3)
for (var i3 = t3[n3], r3 = 0, s2 = i3.length;r3 < s2; r3 += 2) {
var a2 = i3[r3], c2 = i3[r3 + 1];
n3 < Math.min(a2, c2) && e3.push([n3, a2, c2]);
}
return e3;
};
} });
var M = s({ "node_modules/robust-in-sphere/in-sphere.js"(t2, e2) {
var n2 = _(), o2 = b(), i2 = I(), r2 = v();
function s2(t3) {
return (t3 === 3 ? a2 : t3 === 4 ? c2 : t3 === 5 ? l2 : h2)(o2, i2, n2, r2);
}
function a2(t3, e3, n3, o3) {
return function(i3, r3, s3) {
var a3 = n3(i3[0], i3[0]), c3 = o3(a3, r3[0]), l3 = o3(a3, s3[0]), h3 = n3(r3[0], r3[0]), d3 = o3(h3, i3[0]), u3 = o3(h3, s3[0]), p3 = n3(s3[0], s3[0]), m2 = o3(p3, i3[0]), g2 = o3(p3, r3[0]), f2 = t3(e3(g2, u3), e3(d3, c3)), y2 = e3(m2, l3), _2 = e3(f2, y2);
return _2[_2.length - 1];
};
}
function c2(t3, e3, n3, o3) {
return function(i3, r3, s3, a3) {
var c3 = t3(n3(i3[0], i3[0]), n3(i3[1], i3[1])), l3 = o3(c3, r3[0]), h3 = o3(c3, s3[0]), d3 = o3(c3, a3[0]), u3 = t3(n3(r3[0], r3[0]), n3(r3[1], r3[1])), p3 = o3(u3, i3[0]), m2 = o3(u3, s3[0]), g2 = o3(u3, a3[0]), f2 = t3(n3(s3[0], s3[0]), n3(s3[1], s3[1])), y2 = o3(f2, i3[0]), _2 = o3(f2, r3[0]), b2 = o3(f2, a3[0]), x2 = t3(n3(a3[0], a3[0]), n3(a3[1], a3[1])), v2 = o3(x2, i3[0]), I2 = o3(x2, r3[0]), S2 = o3(x2, s3[0]), C2 = t3(t3(o3(e3(S2, b2), r3[1]), t3(o3(e3(I2, g2), -s3[1]), o3(e3(_2, m2), a3[1]))), t3(o3(e3(I2, g2), i3[1]), t3(o3(e3(v2, d3), -r3[1]), o3(e3(p3, l3), a3[1])))), P2 = t3(t3(o3(e3(S2, b2), i3[1]), t3(o3(e3(v2, d3), -s3[1]), o3(e3(y2, h3), a3[1]))), t3(o3(e3(_2, m2), i3[1]), t3(o3(e3(y2, h3), -r3[1]), o3(e3(p3, l3), s3[1])))), M2 = e3(C2, P2);
return M2[M2.length - 1];
};
}
function l2(t3, e3, n3, o3) {
return function(i3, r3, s3, a3, c3) {
var l3 = t3(n3(i3[0], i3[0]), t3(n3(i3[1], i3[1]), n3(i3[2], i3[2]))), h3 = o3(l3, r3[0]), d3 = o3(l3, s3[0]), u3 = o3(l3, a3[0]), p3 = o3(l3, c3[0]), m2 = t3(n3(r3[0], r3[0]), t3(n3(r3[1], r3[1]), n3(r3[2], r3[2]))), g2 = o3(m2, i3[0]), f2 = o3(m2, s3[0]), y2 = o3(m2, a3[0]), _2 = o3(m2, c3[0]), b2 = t3(n3(s3[0], s3[0]), t3(n3(s3[1], s3[1]), n3(s3[2], s3[2]))), x2 = o3(b2, i3[0]), v2 = o3(b2, r3[0]), I2 = o3(b2, a3[0]), S2 = o3(b2, c3[0]), C2 = t3(n3(a3[0], a3[0]), t3(n3(a3[1], a3[1]), n3(a3[2], a3[2]))), P2 = o3(C2, i3[0]), M2 = o3(C2, r3[0]), N = o3(C2, s3[0]), w = o3(C2, c3[0]), T = t3(n3(c3[0], c3[0]), t3(n3(c3[1], c3[1]), n3(c3[2], c3[2]))), R = o3(T, i3[0]), E = o3(T, r3[0]), A = o3(T, s3[0]), O = o3(T, a3[0]), k = t3(t3(t3(o3(t3(o3(e3(O, w), s3[1]), t3(o3(e3(A, S2), -a3[1]), o3(e3(N, I2), c3[1]))), r3[2]), t3(o3(t3(o3(e3(O, w), r3[1]), t3(o3(e3(E, _2), -a3[1]), o3(e3(M2, y2), c3[1]))), -s3[2]), o3(t3(o3(e3(A, S2), r3[1]), t3(o3(e3(E, _2), -s3[1]), o3(e3(v2, f2), c3[1]))), a3[2]))), t3(o3(t3(o3(e3(N, I2), r3[1]), t3(o3(e3(M2, y2), -s3[1]), o3(e3(v2, f2), a3[1]))), -c3[2]), t3(o3(t3(o3(e3(O, w), r3[1]), t3(o3(e3(E, _2), -a3[1]), o3(e3(M2, y2), c3[1]))), i3[2]), o3(t3(o3(e3(O, w), i3[1]), t3(o3(e3(R, p3), -a3[1]), o3(e3(P2, u3), c3[1]))), -r3[2])))), t3(t3(o3(t3(o3(e3(E, _2), i3[1]), t3(o3(e3(R, p3), -r3[1]), o3(e3(g2, h3), c3[1]))), a3[2]), t3(o3(t3(o3(e3(M2, y2), i3[1]), t3(o3(e3(P2, u3), -r3[1]), o3(e3(g2, h3), a3[1]))), -c3[2]), o3(t3(o3(e3(N, I2), r3[1]), t3(o3(e3(M2, y2), -s3[1]), o3(e3(v2, f2), a3[1]))), i3[2]))), t3(o3(t3(o3(e3(N, I2), i3[1]), t3(o3(e3(P2, u3), -s3[1]), o3(e3(x2, d3), a3[1]))), -r3[2]), t3(o3(t3(o3(e3(M2, y2), i3[1]), t3(o3(e3(P2, u3), -r3[1]), o3(e3(g2, h3), a3[1]))), s3[2]), o3(t3(o3(e3(v2, f2), i3[1]), t3(o3(e3(x2, d3), -r3[1]), o3(e3(g2, h3), s3[1]))), -a3[2]))))), D = t3(t3(t3(o3(t3(o3(e3(O, w), s3[1]), t3(o3(e3(A, S2), -a3[1]), o3(e3(N, I2), c3[1]))), i3[2]), o3(t3(o3(e3(O, w), i3[1]), t3(o3(e3(R, p3), -a3[1]), o3(e3(P2, u3), c3[1]))), -s3[2])), t3(o3(t3(o3(e3(A, S2), i3[1]), t3(o3(e3(R, p3), -s3[1]), o3(e3(x2, d3), c3[1]))), a3[2]), o3(t3(o3(e3(N, I2), i3[1]), t3(o3(e3(P2, u3), -s3[1]), o3(e3(x2, d3), a3[1]))), -c3[2]))), t3(t3(o3(t3(o3(e3(A, S2), r3[1]), t3(o3(e3(E, _2), -s3[1]), o3(e3(v2, f2), c3[1]))), i3[2]), o3(t3(o3(e3(A, S2), i3[1]), t3(o3(e3(R, p3), -s3[1]), o3(e3(x2, d3), c3[1]))), -r3[2])), t3(o3(t3(o3(e3(E, _2), i3[1]), t3(o3(e3(R, p3), -r3[1]), o3(e3(g2, h3), c3[1]))), s3[2]), o3(t3(o3(e3(v2, f2), i3[1]), t3(o3(e3(x2, d3), -r3[1]), o3(e3(g2, h3), s3[1]))), -c3[2])))), L = e3(k, D);
return L[L.length - 1];
};
}
function h2(t3, e3, n3, o3) {
return function(i3, r3, s3, a3, c3, l3) {
var h3 = t3(t3(n3(i3[0], i3[0]), n3(i3[1], i3[1])), t3(n3(i3[2], i3[2]), n3(i3[3], i3[3]))), d3 = o3(h3, r3[0]), u3 = o3(h3, s3[0]), p3 = o3(h3, a3[0]), m2 = o3(h3, c3[0]), g2 = o3(h3, l3[0]), f2 = t3(t3(n3(r3[0], r3[0]), n3(r3[1], r3[1])), t3(n3(r3[2], r3[2]), n3(r3[3], r3[3]))), y2 = o3(f2, i3[0]), _2 = o3(f2, s3[0]), b2 = o3(f2, a3[0]), x2 = o3(f2, c3[0]), v2 = o3(f2, l3[0]), I2 = t3(t3(n3(s3[0], s3[0]), n3(s3[1], s3[1])), t3(n3(s3[2], s3[2]), n3(s3[3], s3[3]))), S2 = o3(I2, i3[0]), C2 = o3(I2, r3[0]), P2 = o3(I2, a3[0]), M2 = o3(I2, c3[0]), N = o3(I2, l3[0]), w = t3(t3(n3(a3[0], a3[0]), n3(a3[1], a3[1])), t3(n3(a3[2], a3[2]), n3(a3[3], a3[3]))), T = o3(w, i3[0]), R = o3(w, r3[0]), E = o3(w, s3[0]), A = o3(w, c3[0]), O = o3(w, l3[0]), k = t3(t3(n3(c3[0], c3[0]), n3(c3[1], c3[1])), t3(n3(c3[2], c3[2]), n3(c3[3], c3[3]))), D = o3(k, i3[0]), L = o3(k, r3[0]), z = o3(k, s3[0]), B = o3(k, a3[0]), F = o3(k, l3[0]), j = t3(t3(n3(l3[0], l3[0]), n3(l3[1], l3[1])), t3(n3(l3[2], l3[2]), n3(l3[3], l3[3]))), $ = o3(j, i3[0]), Y = o3(j, r3[0]), X = o3(j, s3[0]), W = o3(j, a3[0]), V = o3(j, c3[0]), H = t3(t3(t3(o3(t3(t3(o3(t3(o3(e3(V, F), a3[1]), t3(o3(e3(W, O), -c3[1]), o3(e3(B, A), l3[1]))), s3[2]), o3(t3(o3(e3(V, F), s3[1]), t3(o3(e3(X, N), -c3[1]), o3(e3(z, M2), l3[1]))), -a3[2])), t3(o3(t3(o3(e3(W, O), s3[1]), t3(o3(e3(X, N), -a3[1]), o3(e3(E, P2), l3[1]))), c3[2]), o3(t3(o3(e3(B, A), s3[1]), t3(o3(e3(z, M2), -a3[1]), o3(e3(E, P2), c3[1]))), -l3[2]))), r3[3]), t3(o3(t3(t3(o3(t3(o3(e3(V, F), a3[1]), t3(o3(e3(W, O), -c3[1]), o3(e3(B, A), l3[1]))), r3[2]), o3(t3(o3(e3(V, F), r3[1]), t3(o3(e3(Y, v2), -c3[1]), o3(e3(L, x2), l3[1]))), -a3[2])), t3(o3(t3(o3(e3(W, O), r3[1]), t3(o3(e3(Y, v2), -a3[1]), o3(e3(R, b2), l3[1]))), c3[2]), o3(t3(o3(e3(B, A), r3[1]), t3(o3(e3(L, x2), -a3[1]), o3(e3(R, b2), c3[1]))), -l3[2]))), -s3[3]), o3(t3(t3(o3(t3(o3(e3(V, F), s3[1]), t3(o3(e3(X, N), -c3[1]), o3(e3(z, M2), l3[1]))), r3[2]), o3(t3(o3(e3(V, F), r3[1]), t3(o3(e3(Y, v2), -c3[1]), o3(e3(L, x2), l3[1]))), -s3[2])), t3(o3(t3(o3(e3(X, N), r3[1]), t3(o3(e3(Y, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), c3[2]), o3(t3(o3(e3(z, M2), r3[1]), t3(o3(e3(L, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), -l3[2]))), a3[3]))), t3(t3(o3(t3(t3(o3(t3(o3(e3(W, O), s3[1]), t3(o3(e3(X, N), -a3[1]), o3(e3(E, P2), l3[1]))), r3[2]), o3(t3(o3(e3(W, O), r3[1]), t3(o3(e3(Y, v2), -a3[1]), o3(e3(R, b2), l3[1]))), -s3[2])), t3(o3(t3(o3(e3(X, N), r3[1]), t3(o3(e3(Y, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), a3[2]), o3(t3(o3(e3(E, P2), r3[1]), t3(o3(e3(R, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), -l3[2]))), -c3[3]), o3(t3(t3(o3(t3(o3(e3(B, A), s3[1]), t3(o3(e3(z, M2), -a3[1]), o3(e3(E, P2), c3[1]))), r3[2]), o3(t3(o3(e3(B, A), r3[1]), t3(o3(e3(L, x2), -a3[1]), o3(e3(R, b2), c3[1]))), -s3[2])), t3(o3(t3(o3(e3(z, M2), r3[1]), t3(o3(e3(L, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), a3[2]), o3(t3(o3(e3(E, P2), r3[1]), t3(o3(e3(R, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), -c3[2]))), l3[3])), t3(o3(t3(t3(o3(t3(o3(e3(V, F), a3[1]), t3(o3(e3(W, O), -c3[1]), o3(e3(B, A), l3[1]))), r3[2]), o3(t3(o3(e3(V, F), r3[1]), t3(o3(e3(Y, v2), -c3[1]), o3(e3(L, x2), l3[1]))), -a3[2])), t3(o3(t3(o3(e3(W, O), r3[1]), t3(o3(e3(Y, v2), -a3[1]), o3(e3(R, b2), l3[1]))), c3[2]), o3(t3(o3(e3(B, A), r3[1]), t3(o3(e3(L, x2), -a3[1]), o3(e3(R, b2), c3[1]))), -l3[2]))), i3[3]), o3(t3(t3(o3(t3(o3(e3(V, F), a3[1]), t3(o3(e3(W, O), -c3[1]), o3(e3(B, A), l3[1]))), i3[2]), o3(t3(o3(e3(V, F), i3[1]), t3(o3(e3($, g2), -c3[1]), o3(e3(D, m2), l3[1]))), -a3[2])), t3(o3(t3(o3(e3(W, O), i3[1]), t3(o3(e3($, g2), -a3[1]), o3(e3(T, p3), l3[1]))), c3[2]), o3(t3(o3(e3(B, A), i3[1]), t3(o3(e3(D, m2), -a3[1]), o3(e3(T, p3), c3[1]))), -l3[2]))), -r3[3])))), t3(t3(t3(o3(t3(t3(o3(t3(o3(e3(V, F), r3[1]), t3(o3(e3(Y, v2), -c3[1]), o3(e3(L, x2), l3[1]))), i3[2]), o3(t3(o3(e3(V, F), i3[1]), t3(o3(e3($, g2), -c3[1]), o3(e3(D, m2), l3[1]))), -r3[2])), t3(o3(t3(o3(e3(Y, v2), i3[1]), t3(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), c3[2]), o3(t3(o3(e3(L, x2), i3[1]), t3(o3(e3(D, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), -l3[2]))), a3[3]), o3(t3(t3(o3(t3(o3(e3(W, O), r3[1]), t3(o3(e3(Y, v2), -a3[1]), o3(e3(R, b2), l3[1]))), i3[2]), o3(t3(o3(e3(W, O), i3[1]), t3(o3(e3($, g2), -a3[1]), o3(e3(T, p3), l3[1]))), -r3[2])), t3(o3(t3(o3(e3(Y, v2), i3[1]), t3(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), a3[2]), o3(t3(o3(e3(R, b2), i3[1]), t3(o3(e3(T, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), -l3[2]))), -c3[3])), t3(o3(t3(t3(o3(t3(o3(e3(B, A), r3[1]), t3(o3(e3(L, x2), -a3[1]), o3(e3(R, b2), c3[1]))), i3[2]), o3(t3(o3(e3(B, A), i3[1]), t3(o3(e3(D, m2), -a3[1]), o3(e3(T, p3), c3[1]))), -r3[2])), t3(o3(t3(o3(e3(L, x2), i3[1]), t3(o3(e3(D, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), a3[2]), o3(t3(o3(e3(R, b2), i3[1]), t3(o3(e3(T, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), -c3[2]))), l3[3]), o3(t3(t3(o3(t3(o3(e3(W, O), s3[1]), t3(o3(e3(X, N), -a3[1]), o3(e3(E, P2), l3[1]))), r3[2]), o3(t3(o3(e3(W, O), r3[1]), t3(o3(e3(Y, v2), -a3[1]), o3(e3(R, b2), l3[1]))), -s3[2])), t3(o3(t3(o3(e3(X, N), r3[1]), t3(o3(e3(Y, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), a3[2]), o3(t3(o3(e3(E, P2), r3[1]), t3(o3(e3(R, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), -l3[2]))), i3[3]))), t3(t3(o3(t3(t3(o3(t3(o3(e3(W, O), s3[1]), t3(o3(e3(X, N), -a3[1]), o3(e3(E, P2), l3[1]))), i3[2]), o3(t3(o3(e3(W, O), i3[1]), t3(o3(e3($, g2), -a3[1]), o3(e3(T, p3), l3[1]))), -s3[2])), t3(o3(t3(o3(e3(X, N), i3[1]), t3(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), a3[2]), o3(t3(o3(e3(E, P2), i3[1]), t3(o3(e3(T, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -l3[2]))), -r3[3]), o3(t3(t3(o3(t3(o3(e3(W, O), r3[1]), t3(o3(e3(Y, v2), -a3[1]), o3(e3(R, b2), l3[1]))), i3[2]), o3(t3(o3(e3(W, O), i3[1]), t3(o3(e3($, g2), -a3[1]), o3(e3(T, p3), l3[1]))), -r3[2])), t3(o3(t3(o3(e3(Y, v2), i3[1]), t3(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), a3[2]), o3(t3(o3(e3(R, b2), i3[1]), t3(o3(e3(T, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), -l3[2]))), s3[3])), t3(o3(t3(t3(o3(t3(o3(e3(X, N), r3[1]), t3(o3(e3(Y, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), i3[2]), o3(t3(o3(e3(X, N), i3[1]), t3(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), -r3[2])), t3(o3(t3(o3(e3(Y, v2), i3[1]), t3(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), s3[2]), o3(t3(o3(e3(C2, _2), i3[1]), t3(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -l3[2]))), -a3[3]), o3(t3(t3(o3(t3(o3(e3(E, P2), r3[1]), t3(o3(e3(R, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), i3[2]), o3(t3(o3(e3(E, P2), i3[1]), t3(o3(e3(T, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -r3[2])), t3(o3(t3(o3(e3(R, b2), i3[1]), t3(o3(e3(T, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), s3[2]), o3(t3(o3(e3(C2, _2), i3[1]), t3(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -a3[2]))), l3[3]))))), G = t3(t3(t3(o3(t3(t3(o3(t3(o3(e3(V, F), a3[1]), t3(o3(e3(W, O), -c3[1]), o3(e3(B, A), l3[1]))), s3[2]), o3(t3(o3(e3(V, F), s3[1]), t3(o3(e3(X, N), -c3[1]), o3(e3(z, M2), l3[1]))), -a3[2])), t3(o3(t3(o3(e3(W, O), s3[1]), t3(o3(e3(X, N), -a3[1]), o3(e3(E, P2), l3[1]))), c3[2]), o3(t3(o3(e3(B, A), s3[1]), t3(o3(e3(z, M2), -a3[1]), o3(e3(E, P2), c3[1]))), -l3[2]))), i3[3]), t3(o3(t3(t3(o3(t3(o3(e3(V, F), a3[1]), t3(o3(e3(W, O), -c3[1]), o3(e3(B, A), l3[1]))), i3[2]), o3(t3(o3(e3(V, F), i3[1]), t3(o3(e3($, g2), -c3[1]), o3(e3(D, m2), l3[1]))), -a3[2])), t3(o3(t3(o3(e3(W, O), i3[1]), t3(o3(e3($, g2), -a3[1]), o3(e3(T, p3), l3[1]))), c3[2]), o3(t3(o3(e3(B, A), i3[1]), t3(o3(e3(D, m2), -a3[1]), o3(e3(T, p3), c3[1]))), -l3[2]))), -s3[3]), o3(t3(t3(o3(t3(o3(e3(V, F), s3[1]), t3(o3(e3(X, N), -c3[1]), o3(e3(z, M2), l3[1]))), i3[2]), o3(t3(o3(e3(V, F), i3[1]), t3(o3(e3($, g2), -c3[1]), o3(e3(D, m2), l3[1]))), -s3[2])), t3(o3(t3(o3(e3(X, N), i3[1]), t3(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), c3[2]), o3(t3(o3(e3(z, M2), i3[1]), t3(o3(e3(D, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), -l3[2]))), a3[3]))), t3(t3(o3(t3(t3(o3(t3(o3(e3(W, O), s3[1]), t3(o3(e3(X, N), -a3[1]), o3(e3(E, P2), l3[1]))), i3[2]), o3(t3(o3(e3(W, O), i3[1]), t3(o3(e3($, g2), -a3[1]), o3(e3(T, p3), l3[1]))), -s3[2])), t3(o3(t3(o3(e3(X, N), i3[1]), t3(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), a3[2]), o3(t3(o3(e3(E, P2), i3[1]), t3(o3(e3(T, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -l3[2]))), -c3[3]), o3(t3(t3(o3(t3(o3(e3(B, A), s3[1]), t3(o3(e3(z, M2), -a3[1]), o3(e3(E, P2), c3[1]))), i3[2]), o3(t3(o3(e3(B, A), i3[1]), t3(o3(e3(D, m2), -a3[1]), o3(e3(T, p3), c3[1]))), -s3[2])), t3(o3(t3(o3(e3(z, M2), i3[1]), t3(o3(e3(D, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), a3[2]), o3(t3(o3(e3(E, P2), i3[1]), t3(o3(e3(T, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -c3[2]))), l3[3])), t3(o3(t3(t3(o3(t3(o3(e3(V, F), s3[1]), t3(o3(e3(X, N), -c3[1]), o3(e3(z, M2), l3[1]))), r3[2]), o3(t3(o3(e3(V, F), r3[1]), t3(o3(e3(Y, v2), -c3[1]), o3(e3(L, x2), l3[1]))), -s3[2])), t3(o3(t3(o3(e3(X, N), r3[1]), t3(o3(e3(Y, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), c3[2]), o3(t3(o3(e3(z, M2), r3[1]), t3(o3(e3(L, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), -l3[2]))), i3[3]), o3(t3(t3(o3(t3(o3(e3(V, F), s3[1]), t3(o3(e3(X, N), -c3[1]), o3(e3(z, M2), l3[1]))), i3[2]), o3(t3(o3(e3(V, F), i3[1]), t3(o3(e3($, g2), -c3[1]), o3(e3(D, m2), l3[1]))), -s3[2])), t3(o3(t3(o3(e3(X, N), i3[1]), t3(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), c3[2]), o3(t3(o3(e3(z, M2), i3[1]), t3(o3(e3(D, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), -l3[2]))), -r3[3])))), t3(t3(t3(o3(t3(t3(o3(t3(o3(e3(V, F), r3[1]), t3(o3(e3(Y, v2), -c3[1]), o3(e3(L, x2), l3[1]))), i3[2]), o3(t3(o3(e3(V, F), i3[1]), t3(o3(e3($, g2), -c3[1]), o3(e3(D, m2), l3[1]))), -r3[2])), t3(o3(t3(o3(e3(Y, v2), i3[1]), t3(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), c3[2]), o3(t3(o3(e3(L, x2), i3[1]), t3(o3(e3(D, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), -l3[2]))), s3[3]), o3(t3(t3(o3(t3(o3(e3(X, N), r3[1]), t3(o3(e3(Y, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), i3[2]), o3(t3(o3(e3(X, N), i3[1]), t3(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), -r3[2])), t3(o3(t3(o3(e3(Y, v2), i3[1]), t3(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), s3[2]), o3(t3(o3(e3(C2, _2), i3[1]), t3(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -l3[2]))), -c3[3])), t3(o3(t3(t3(o3(t3(o3(e3(z, M2), r3[1]), t3(o3(e3(L, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), i3[2]), o3(t3(o3(e3(z, M2), i3[1]), t3(o3(e3(D, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), -r3[2])), t3(o3(t3(o3(e3(L, x2), i3[1]), t3(o3(e3(D, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), s3[2]), o3(t3(o3(e3(C2, _2), i3[1]), t3(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -c3[2]))), l3[3]), o3(t3(t3(o3(t3(o3(e3(B, A), s3[1]), t3(o3(e3(z, M2), -a3[1]), o3(e3(E, P2), c3[1]))), r3[2]), o3(t3(o3(e3(B, A), r3[1]), t3(o3(e3(L, x2), -a3[1]), o3(e3(R, b2), c3[1]))), -s3[2])), t3(o3(t3(o3(e3(z, M2), r3[1]), t3(o3(e3(L, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), a3[2]), o3(t3(o3(e3(E, P2), r3[1]), t3(o3(e3(R, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), -c3[2]))), i3[3]))), t3(t3(o3(t3(t3(o3(t3(o3(e3(B, A), s3[1]), t3(o3(e3(z, M2), -a3[1]), o3(e3(E, P2), c3[1]))), i3[2]), o3(t3(o3(e3(B, A), i3[1]), t3(o3(e3(D, m2), -a3[1]), o3(e3(T, p3), c3[1]))), -s3[2])), t3(o3(t3(o3(e3(z, M2), i3[1]), t3(o3(e3(D, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), a3[2]), o3(t3(o3(e3(E, P2), i3[1]), t3(o3(e3(T, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -c3[2]))), -r3[3]), o3(t3(t3(o3(t3(o3(e3(B, A), r3[1]), t3(o3(e3(L, x2), -a3[1]), o3(e3(R, b2), c3[1]))), i3[2]), o3(t3(o3(e3(B, A), i3[1]), t3(o3(e3(D, m2), -a3[1]), o3(e3(T, p3), c3[1]))), -r3[2])), t3(o3(t3(o3(e3(L, x2), i3[1]), t3(o3(e3(D, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), a3[2]), o3(t3(o3(e3(R, b2), i3[1]), t3(o3(e3(T, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), -c3[2]))), s3[3])), t3(o3(t3(t3(o3(t3(o3(e3(z, M2), r3[1]), t3(o3(e3(L, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), i3[2]), o3(t3(o3(e3(z, M2), i3[1]), t3(o3(e3(D, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), -r3[2])), t3(o3(t3(o3(e3(L, x2), i3[1]), t3(o3(e3(D, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), s3[2]), o3(t3(o3(e3(C2, _2), i3[1]), t3(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -c3[2]))), -a3[3]), o3(t3(t3(o3(t3(o3(e3(E, P2), r3[1]), t3(o3(e3(R, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), i3[2]), o3(t3(o3(e3(E, P2), i3[1]), t3(o3(e3(T, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -r3[2])), t3(o3(t3(o3(e3(R, b2), i3[1]), t3(o3(e3(T, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), s3[2]), o3(t3(o3(e3(C2, _2), i3[1]), t3(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -a3[2]))), c3[3]))))), U = e3(H, G);
return U[U.length - 1];
};
}
var d2 = [function() {
return 0;
}, function() {
return 0;
}, function() {
return 0;
}];
function u2(t3) {
var e3 = d2[t3.length];
return e3 || (e3 = d2[t3.length] = s2(t3.length)), e3.apply(undefined, t3);
}
function p2(t3, e3, n3, o3, i3, r3, s3, a3) {
return function(e4, n4, c3, l3, h3, d3) {
switch (arguments.length) {
case 0:
case 1:
return 0;
case 2:
return o3(e4, n4);
case 3:
return i3(e4, n4, c3);
case 4:
return r3(e4, n4, c3, l3);
case 5:
return s3(e4, n4, c3, l3, h3);
case 6:
return a3(e4, n4, c3, l3, h3, d3);
}
for (var u3 = new Array(arguments.length), p3 = 0;p3 < arguments.length; ++p3)
u3[p3] = arguments[p3];
return t3(u3);
};
}
(function() {
for (;d2.length <= 6; )
d2.push(s2(d2.length));
e2.exports = p2.apply(undefined, [u2].concat(d2));
for (var t3 = 0;t3 <= 6; ++t3)
e2.exports[t3] = d2[t3];
})();
} });
var N = s({ "node_modules/cdt2d/lib/delaunay.js"(t2, e2) {
var n2 = M()[4];
y();
function o2(t3, e3, o3, i2, r2, s2) {
var a2 = e3.opposite(i2, r2);
if (!(a2 < 0)) {
if (r2 < i2) {
var c2 = i2;
i2 = r2, r2 = c2, c2 = s2, s2 = a2, a2 = c2;
}
e3.isConstraint(i2, r2) || n2(t3[i2], t3[r2], t3[s2], t3[a2]) < 0 && o3.push(i2, r2);
}
}
e2.exports = function(t3, e3) {
for (var i2 = [], r2 = t3.length, s2 = e3.stars, a2 = 0;a2 < r2; ++a2)
for (var c2 = s2[a2], l2 = 1;l2 < c2.length; l2 += 2) {
if (!((p2 = c2[l2]) < a2) && !e3.isConstraint(a2, p2)) {
for (var h2 = c2[l2 - 1], d2 = -1, u2 = 1;u2 < c2.length; u2 += 2)
if (c2[u2 - 1] === p2) {
d2 = c2[u2];
break;
}
d2 < 0 || n2(t3[a2], t3[p2], t3[h2], t3[d2]) < 0 && i2.push(a2, p2);
}
}
for (;i2.length > 0; ) {
for (var p2 = i2.pop(), m2 = (h2 = -1, d2 = -1, c2 = s2[a2 = i2.pop()], 1);m2 < c2.length; m2 += 2) {
var g2 = c2[m2 - 1], f2 = c2[m2];
g2 === p2 ? d2 = f2 : f2 === p2 && (h2 = g2);
}
h2 < 0 || d2 < 0 || (n2(t3[a2], t3[p2], t3[h2], t3[d2]) >= 0 || (e3.flip(a2, p2), o2(t3, e3, i2, h2, a2, d2), o2(t3, e3, i2, a2, d2, h2), o2(t3, e3, i2, d2, p2, h2), o2(t3, e3, i2, p2, h2, d2)));
}
};
} });
var w = s({ "node_modules/cdt2d/lib/filter.js"(t2, e2) {
var n2 = y();
function o2(t3, e3, n3, o3, i3, r2, s2) {
this.cells = t3, this.neighbor = e3, this.flags = o3, this.constraint = n3, this.active = i3, this.next = r2, this.boundary = s2;
}
function i2(t3, e3) {
return t3[0] - e3[0] || t3[1] - e3[1] || t3[2] - e3[2];
}
e2.exports = function(t3, e3, n3) {
var r2 = function(t4, e4) {
for (var n4 = t4.cells(), r3 = n4.length, s3 = 0;s3 < r3; ++s3) {
var a3 = (y3 = n4[s3])[0], c3 = y3[1], l3 = y3[2];
c3 < l3 ? c3 < a3 && (y3[0] = c3, y3[1] = l3, y3[2] = a3) : l3 < a3 && (y3[0] = l3, y3[1] = a3, y3[2] = c3);
}
n4.sort(i2);
var h3 = new Array(r3);
for (s3 = 0;s3 < h3.length; ++s3)
h3[s3] = 0;
var d3 = [], u3 = [], p3 = new Array(3 * r3), m3 = new Array(3 * r3), g3 = null;
e4 && (g3 = []);
var f3 = new o2(n4, p3, m3, h3, d3, u3, g3);
for (s3 = 0;s3 < r3; ++s3)
for (var y3 = n4[s3], _2 = 0;_2 < 3; ++_2) {
a3 = y3[_2], c3 = y3[(_2 + 1) % 3];
var b2 = p3[3 * s3 + _2] = f3.locate(c3, a3, t4.opposite(c3, a3)), x2 = m3[3 * s3 + _2] = t4.isConstraint(a3, c3);
b2 < 0 && (x2 ? u3.push(s3) : (d3.push(s3), h3[s3] = 1), e4 && g3.push([c3, a3, -1]));
}
return f3;
}(t3, n3);
if (e3 === 0)
return n3 ? r2.cells.concat(r2.boundary) : r2.cells;
var s2 = 1, a2 = r2.active, c2 = r2.next, l2 = r2.flags, h2 = r2.cells, d2 = r2.constraint, u2 = r2.neighbor;
for (;a2.length > 0 || c2.length > 0; ) {
for (;a2.length > 0; ) {
var p2 = a2.pop();
if (l2[p2] !== -s2) {
l2[p2] = s2;
h2[p2];
for (var m2 = 0;m2 < 3; ++m2) {
var g2 = u2[3 * p2 + m2];
g2 >= 0 && l2[g2] === 0 && (d2[3 * p2 + m2] ? c2.push(g2) : (a2.push(g2), l2[g2] = s2));
}
}
}
var f2 = c2;
c2 = a2, a2 = f2, c2.length = 0, s2 = -s2;
}
var y2 = function(t4, e4, n4) {
for (var o3 = 0, i3 = 0;i3 < t4.length; ++i3)
e4[i3] === n4 && (t4[o3++] = t4[i3]);
return t4.length = o3, t4;
}(h2, l2, e3);
if (n3)
return y2.concat(r2.boundary);
return y2;
}, o2.prototype.locate = function() {
var t3 = [0, 0, 0];
return function(e3, o3, r2) {
var s2 = e3, a2 = o3, c2 = r2;
return o3 < r2 ? o3 < e3 && (s2 = o3, a2 = r2, c2 = e3) : r2 < e3 && (s2 = r2, a2 = e3, c2 = o3), s2 < 0 ? -1 : (t3[0] = s2, t3[1] = a2, t3[2] = c2, n2.eq(this.cells, t3, i2));
};
}();
} });
var T = s({ "node_modules/cdt2d/cdt2d.js"(t2, e2) {
var n2 = C(), o2 = P(), i2 = N(), r2 = w();
function s2(t3) {
return [Math.min(t3[0], t3[1]), Math.max(t3[0], t3[1])];
}
function a2(t3, e3) {
return t3[0] - e3[0] || t3[1] - e3[1];
}
function c2(t3, e3, n3) {
return e3 in t3 ? t3[e3] : n3;
}
e2.exports = function(t3, e3, l2) {
Array.isArray(e3) ? (l2 = l2 || {}, e3 = e3 || []) : (l2 = e3 || {}, e3 = []);
var h2 = !!c2(l2, "delaunay", true), d2 = !!c2(l2, "interior", true), u2 = !!c2(l2, "exterior", true), p2 = !!c2(l2, "infinity", false);
if (!d2 && !u2 || t3.length === 0)
return [];
var m2 = n2(t3, e3);
if (h2 || d2 !== u2 || p2) {
for (var g2 = o2(t3.length, function(t4) {
return t4.map(s2).sort(a2);
}(e3)), f2 = 0;f2 < m2.length; ++f2) {
var y2 = m2[f2];
g2.addTriangle(y2[0], y2[1], y2[2]);
}
return h2 && i2(t3, g2), u2 ? d2 ? p2 ? r2(g2, 0, p2) : g2.cells() : r2(g2, 1, p2) : r2(g2, -1);
}
return m2;
};
} });
function R(t2, e2) {
return Array.isArray(e2) ? [t2.a * e2[0] + t2.c * e2[1] + t2.e, t2.b * e2[0] + t2.d * e2[1] + t2.f] : { x: t2.a * e2.x + t2.c * e2.y + t2.e, y: t2.b * e2.x + t2.d * e2.y + t2.f };
}
function E(t2, e2) {
return e2.map((e3) => R(t2, e3));
}
function A(t2) {
const { a: e2, b: n2, c: o2, d: i2, e: r2, f: s2 } = t2, a2 = e2 * i2 - n2 * o2;
return { a: i2 / a2, b: n2 / -a2, c: o2 / -a2, d: e2 / a2, e: (i2 * r2 - o2 * s2) / -a2, f: (n2 * r2 - e2 * s2) / a2 };
}
function O(t2) {
return t2 === undefined;
}
function k(t2, e2 = 0) {
return { a: 1, c: 0, e: t2, b: 0, d: 1, f: e2 };
}
function D(...t2) {
const e2 = (t3, e3) => ({ a: t3.a * e3.a + t3.c * e3.b, c: t3.a * e3.c + t3.c * e3.d, e: t3.a * e3.e + t3.c * e3.f + t3.e, b: t3.b * e3.a + t3.d * e3.b, d: t3.b * e3.c + t3.d * e3.d, f: t3.b * e3.e + t3.d * e3.f + t3.f });
switch ((t2 = Array.isArray(t2[0]) ? t2[0] : t2).length) {
case 0:
throw new Error("no matrices provided");
case 1:
return t2[0];
case 2:
return e2(t2[0], t2[1]);
default: {
const [n2, o2, ...i2] = t2;
return D(e2(n2, o2), ...i2);
}
}
}
function L(...t2) {
return D(...t2);
}
var { cos: z, sin: B, PI: F } = Math;
function j(t2, e2 = undefined, n2 = undefined) {
return function(t3, e3, n3) {
const o2 = z(t3), i2 = B(t3), r2 = { a: o2, c: -i2, e: 0, b: i2, d: o2, f: 0 };
return O(e3) || O(n3) ? r2 : D([k(e3, n3), r2, k(-e3, -n3)]);
}(t2 * F / 180, e2, n2);
}
(c(u()), c(f()), new TextEncoder, (() => {
const t2 = new Uint8Array(4);
new Uint32Array(t2.buffer)[0] = 1, t2[0];
})(), []);
var X = new Uint16Array([255]);
var W = (new Uint8Array(X.buffer)[0], new Uint16Array([255]));
new Uint8Array(W.buffer)[0], new TextDecoder("latin1");
function V() {
return V = Object.assign ? Object.assign.bind() : function(t2) {
for (var e2 = 1;e2 < arguments.length; e2++) {
var n2 = arguments[e2];
for (var o2 in n2)
({}).hasOwnProperty.call(n2, o2) && (t2[o2] = n2[o2]);
}
return t2;
}, V.apply(null, arguments);
}
function H(t2, e2) {
return (H = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function(t3, e3) {
return t3.__proto__ = e3, t3;
})(t2, e2);
}
function G(t2) {
return (G = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function(t3) {
return t3.__proto__ || Object.getPrototypeOf(t3);
})(t2);
}
function U() {
try {
var t2 = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
} catch (t3) {}
return (U = function() {
return !!t2;
})();
}
function Z(t2) {
var e2 = typeof Map == "function" ? new Map : undefined;
return Z = function(t3) {
if (t3 === null || !function(t4) {
try {
return Function.toString.call(t4).indexOf("[native code]") !== -1;
} catch (e3) {
return typeof t4 == "function";
}
}(t3))
return t3;
if (typeof t3 != "function")
throw new TypeError("Super expression must either be null or a function");
if (e2 !== undefined) {
if (e2.has(t3))
return e2.get(t3);
e2.set(t3, n2);
}
function n2() {
return function(t4, e3, n3) {
if (U())
return Reflect.construct.apply(null, arguments);
var o2 = [null];
o2.push.apply(o2, e3);
var i2 = new (t4.bind.apply(t4, o2));
return n3 && H(i2, n3.prototype), i2;
}(t3, arguments, G(this).constructor);
}
return n2.prototype = Object.create(t3.prototype, { constructor: { value: n2, enumerable: false, writable: true, configurable: true } }), H(n2, t3);
}, Z(t2);
}
var q = { 1: `Passed invalid arguments to hsl, please pass multiple numbers e.g. hsl(360, 0.75, 0.4) or an object e.g. rgb({ hue: 255, saturation: 0.4, lightness: 0.75 }).
`, 2: `Passed invalid arguments to hsla, please pass multiple numbers e.g. hsla(360, 0.75, 0.4, 0.7) or an object e.g. rgb({ hue: 255, saturation: 0.4, lightness: 0.75, alpha: 0.7 }).
`, 3: `Passed an incorrect argument to a color function, please pass a string representation of a color.
`, 4: `Couldn't generate valid rgb string from %s, it returned %s.
`, 5: `Couldn't parse the color string. Please provide the color as a string in hex, rgb, rgba, hsl or hsla notation.
`, 6: `Passed invalid arguments to rgb, please pass multiple numbers e.g. rgb(255, 205, 100) or an object e.g. rgb({ red: 255, green: 205, blue: 100 }).
`, 7: `Passed invalid arguments to rgba, please pass multiple numbers e.g. rgb(255, 205, 100, 0.75) or an object e.g. rgb({ red: 255, green: 205, blue: 100, alpha: 0.75 }).
`, 8: `Passed invalid argument to toColorString, please pass a RgbColor, RgbaColor, HslColor or HslaColor object.
`, 9: `Please provide a number of steps to the modularScale helper.
`, 10: `Please pass a number or one of the predefined scales to the modularScale helper as the ratio.
`, 11: `Invalid value passed as base to modularScale, expected number or em string but got "%s"
`, 12: `Expected a string ending in "px" or a number passed as the first argument to %s(), got "%s" instead.
`, 13: `Expected a string ending in "px" or a number passed as the second argument to %s(), got "%s" instead.
`, 14: `Passed invalid pixel value ("%s") to %s(), please pass a value like "12px" or 12.
`, 15: `Passed invalid base value ("%s") to %s(), please pass a value like "12px" or 12.
`, 16: `You must provide a template to this method.
`, 17: `You passed an unsupported selector state to this method.
`, 18: `minScreen and maxScreen must be provided as stringified numbers with the same units.
`, 19: `fromSize and toSize must be provided as stringified numbers with the same units.
`, 20: `expects either an array of objects or a single object with the properties prop, fromSize, and toSize.
`, 21: "expects the objects in the first argument array to have the properties `prop`, `fromSize`, and `toSize`.\n\n", 22: "expects the first argument object to have the properties `prop`, `fromSize`, and `toSize`.\n\n", 23: `fontFace expects a name of a font-family.
`, 24: `fontFace expects either the path to the font file(s) or a name of a local copy.
`, 25: `fontFace expects localFonts to be an array.
`, 26: `fontFace expects fileFormats to be an array.
`, 27: `radialGradient requries at least 2 color-stops to properly render.
`, 28: `Please supply a filename to retinaImage() as the first argument.
`, 29: `Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.
`, 30: "Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\n\n", 31: `The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation
`, 32: `To pass multiple animations please supply them in arrays, e.g. animation(['rotate', '2s'], ['move', '1s'])
To pass a single animation please supply them in simple values, e.g. animation('rotate', '2s')
`, 33: `The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation
`, 34: `borderRadius expects a radius value as a string or number as the second argument.
`, 35: `borderRadius expects one of "top", "bottom", "left" or "right" as the first argument.
`, 36: `Property must be a string value.
`, 37: `Syntax Error at %s.
`, 38: `Formula contains a function that needs parentheses at %s.
`, 39: `Formula is missing closing parenthesis at %s.
`, 40: `Formula has too many closing parentheses at %s.
`, 41: `All values in a formula must have the same unit or be unitless.
`, 42: `Please provide a number of steps to the modularScale helper.
`, 43: `Please pass a number or one of the predefined scales to the modularScale helper as the ratio.
`, 44: `Invalid value passed as base to modularScale, expected number or em/rem string but got %s.
`, 45: `Passed invalid argument to hslToColorString, please pass a HslColor or HslaColor object.
`, 46: `Passed invalid argument to rgbToColorString, please pass a RgbColor or RgbaColor object.
`, 47: `minScreen and maxScreen must be provided as stringified numbers with the same units.
`, 48: `fromSize and toSize must be provided as stringified numbers with the same units.
`, 49: `Expects either an array of objects or a single object with the properties prop, fromSize, and toSize.
`, 50: `Expects the objects in the first argument array to have the properties prop, fromSize, and toSize.
`, 51: `Expects the first argument object to have the properties prop, fromSize, and toSize.
`, 52: `fontFace expects either the path to the font file(s) or a name of a local copy.
`, 53: `fontFace expects localFonts to be an array.
`, 54: `fontFace expects fileFormats to be an array.
`, 55: `fontFace expects a name of a font-family.
`, 56: `linearGradient requries at least 2 color-stops to properly render.
`, 57: `radialGradient requries at least 2 color-stops to properly render.
`, 58: `Please supply a filename to retinaImage() as the first argument.
`, 59: `Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.
`, 60: "Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\n\n", 61: `Property must be a string value.
`, 62: `borderRadius expects a radius value as a string or number as the second argument.
`, 63: `borderRadius expects one of "top", "bottom", "left" or "right" as the first argument.
`, 64: `The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation.
`, 65: `To pass multiple animations please supply them in arrays, e.g. animation(['rotate', '2s'], ['move', '1s'])\\nTo pass a single animation please supply them in simple values, e.g. animation('rotate', '2s').
`, 66: `The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation.
`, 67: `You must provide a template to this method.
`, 68: `You passed an unsupported selector state to this method.
`, 69: `Expected a string ending in "px" or a number passed as the first argument to %s(), got %s instead.
`, 70: `Expected a string ending in "px" or a number passed as the second argument to %s(), got %s instead.
`, 71: `Passed invalid pixel value %s to %s(), please pass a value like "12px" or 12.
`, 72: `Passed invalid base value %s to %s(), please pass a value like "12px" or 12.
`, 73: `Please provide a valid CSS variable.
`, 74: `CSS variable not found and no default was provided.
`, 75: `important requires a valid style object, got a %s instead.
`, 76: `fromSize and toSize must be provided as stringified numbers with the same units as minScreen and maxScreen.
`, 77: `remToPx expects a value in "rem" but you provided it in "%s".
`, 78: `base must be set in "px" or "%" but you set it in "%s".
` };
function J() {
for (var t2 = arguments.length, e2 = new Array(t2), n2 = 0;n2 < t2; n2++)
e2[n2] = arguments[n2];
var o2, i2 = e2[0], r2 = [];
for (o2 = 1;o2 < e2.length; o2 += 1)
r2.push(e2[o2]);
return r2.forEach(function(t3) {
i2 = i2.replace(/%[a-z]/, t3);
}), i2;
}
var Q = function(t2) {
var e2, n2;
function o2(e3) {
var n3;
{
for (var o3 = arguments.length, i2 = new Array(o3 > 1 ? o3 - 1 : 0), r2 = 1;r2 < o3; r2++)
i2[r2 - 1] = arguments[r2];
n3 = t2.call(this, J.apply(undefined, [q[e3]].concat(i2))) || this;
}
return function(t3) {
if (t3 === undefined)
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
return t3;
}(n3);
}
return n2 = t2, (e2 = o2).prototype = Object.create(n2.prototype), e2.prototype.constructor = e2, H(e2, n2), o2;
}(Z(Error));
function ot(t2) {
return Math.round(255 * t2);
}
function it(t2, e2, n2) {
return ot(t2) + "," + ot(e2) + "," + ot(n2);
}
function rt(t2, e2, n2, o2) {
if (o2 === undefined && (o2 = it), e2 === 0)
return o2(n2, n2, n2);
var i2 = (t2 % 360 + 360) % 360 / 60, r2 = (1 - Math.abs(2 * n2 - 1)) * e2, s2 = r2 * (1 - Math.abs(i2 % 2 - 1)), a2 = 0, c2 = 0, l2 = 0;
i2 >= 0 && i2 < 1 ? (a2 = r2, c2 = s2) : i2 >= 1 && i2 < 2 ? (a2 = s2, c2 = r2) : i2 >= 2 && i2 < 3 ? (c2 = r2, l2 = s2) : i2 >= 3 && i2 < 4 ? (c2 = s2, l2 = r2) : i2 >= 4 && i2 < 5 ? (a2 = s2, l2 = r2) : i2 >= 5 && i2 < 6 && (a2 = r2, l2 = s2);
var h2 = n2 - r2 / 2;
return o2(a2 + h2, c2 + h2, l2 + h2);
}
var st = { aliceblue: "f0f8ff", antiquewhite: "faebd7", aqua: "00ffff", aquamarine: "7fffd4", azure: "f0ffff", beige: "f5f5dc", bisque: "ffe4c4", black: "000", blanchedalmond: "ffebcd", blue: "0000ff", blueviolet: "8a2be2", brown: "a52a2a", burlywood: "deb887", cadetblue: "5f9ea0", chartreuse: "7fff00", chocolate: "d2691e", coral: "ff7f50", cornflowerblue: "6495ed", cornsilk: "fff8dc", crimson: "dc143c", cyan: "00ffff", darkblue: "00008b", darkcyan: "008b8b", darkgoldenrod: "b8860b", darkgray: "a9a9a9", darkgreen: "006400", darkgrey: "a9a9a9", darkkhaki: "bdb76b", darkmagenta: "8b008b", darkolivegreen: "556b2f", darkorange: "ff8c00", darkorchid: "9932cc", darkred: "8b0000", darksalmon: "e9967a", darkseagreen: "8fbc8f", darkslateblue: "483d8b", darkslategray: "2f4f4f", darkslategrey: "2f4f4f", darkturquoise: "00ced1", darkviolet: "9400d3", deeppink: "ff1493", deepskyblue: "00bfff", dimgray: "696969", dimgrey: "696969", dodgerblue: "1e90ff", firebrick: "b22222", floralwhite: "fffaf0", forestgreen: "228b22", fuchsia: "ff00ff", gainsboro: "dcdcdc", ghostwhite: "f8f8ff", gold: "ffd700", goldenrod: "daa520", gray: "808080", green: "008000", greenyellow: "adff2f", grey: "808080", honeydew: "f0fff0", hotpink: "ff69b4", indianred: "cd5c5c", indigo: "4b0082", ivory: "fffff0", khaki: "f0e68c", lavender: "e6e6fa", lavenderblush: "fff0f5", lawngreen: "7cfc00", lemonchiffon: "fffacd", lightblue: "add8e6", lightcoral: "f08080", lightcyan: "e0ffff", lightgoldenrodyellow: "fafad2", lightgray: "d3d3d3", lightgreen: "90ee90", lightgrey: "d3d3d3", lightpink: "ffb6c1", lightsalmon: "ffa07a", lightseagreen: "20b2aa", lightskyblue: "87cefa", lightslategray: "789", lightslategrey: "789", lightsteelblue: "b0c4de", lightyellow: "ffffe0", lime: "0f0", limegreen: "32cd32", linen: "faf0e6", magenta: "f0f", maroon: "800000", mediumaquamarine: "66cdaa", mediumblue: "0000cd", mediumorchid: "ba55d3", mediumpurple: "9370db", mediumseagreen: "3cb371", mediumslateblue: "7b68ee", mediumspringgreen: "00fa9a", mediumturquoise: "48d1cc", mediumvioletred: "c71585", midnightblue: "191970", mintcream: "f5fffa", mistyrose: "ffe4e1", moccasin: "ffe4b5", navajowhite: "ffdead", navy: "000080", oldlace: "fdf5e6", olive: "808000", olivedrab: "6b8e23", orange: "ffa500", orangered: "ff4500", orchid: "da70d6", palegoldenrod: "eee8aa", palegreen: "98fb98", paleturquoise: "afeeee", palevioletred: "db7093", papayawhip: "ffefd5", peachpuff: "ffdab9", peru: "cd853f", pink: "ffc0cb", plum: "dda0dd", powderblue: "b0e0e6", purple: "800080", rebeccapurple: "639", red: "f00", rosybrown: "bc8f8f", royalblue: "4169e1", saddlebrown: "8b4513", salmon: "fa8072", sandybrown: "f4a460", seagreen: "2e8b57", seashell: "fff5ee", sienna: "a0522d", silver: "c0c0c0", skyblue: "87ceeb", slateblue: "6a5acd", slategray: "708090", slategrey: "708090", snow: "fffafa", springgreen: "00ff7f", steelblue: "4682b4", tan: "d2b48c", teal: "008080", thistle: "d8bfd8", tomato: "ff6347", turquoise: "40e0d0", violet: "ee82ee", wheat: "f5deb3", white: "fff", whitesmoke: "f5f5f5", yellow: "ff0", yellowgreen: "9acd32" };
var at = /^#[a-fA-F0-9]{6}$/;
var ct = /^#[a-fA-F0-9]{8}$/;
var lt = /^#[a-fA-F0-9]{3}$/;
var ht = /^#[a-fA-F0-9]{4}$/;
var dt = /^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i;
var ut = /^rgb(?:a)?\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i;
var pt = /^hsl\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*\)$/i;
var mt = /^hsl(?:a)?\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i;
function gt(t2) {
if (typeof t2 != "string")
throw new Q(3);
var e2 = function(t3) {
if (typeof t3 != "string")
return t3;
var e3 = t3.toLowerCase();
return st[e3] ? "#" + st[e3] : t3;
}(t2);
if (e2.match(at))
return { red: parseInt("" + e2[1] + e2[2], 16), green: parseInt("" + e2[3] + e2[4], 16), blue: parseInt("" + e2[5] + e2[6], 16) };
if (e2.match(ct)) {
var n2 = parseFloat((parseInt("" + e2[7] + e2[8], 16) / 255).toFixed(2));
return { red: parseInt("" + e2[1] + e2[2], 16), green: parseInt("" + e2[3] + e2[4], 16), blue: parseInt("" + e2[5] + e2[6], 16), alpha: n2 };
}
if (e2.match(lt))
return { red: parseInt("" + e2[1] + e2[1], 16), green: parseInt("" + e2[2] + e2[2], 16), blue: parseInt("" + e2[3] + e2[3], 16) };
if (e2.match(ht)) {
var o2 = parseFloat((parseInt("" + e2[4] + e2[4], 16) / 255).toFixed(2));
return { red: parseInt("" + e2[1] + e2[1], 16), green: parseInt("" + e2[2] + e2[2], 16), blue: parseInt("" + e2[3] + e2[3], 16), alpha: o2 };
}
var i2 = dt.exec(e2);
if (i2)
return { red: parseInt("" + i2[1], 10), green: parseInt("" + i2[2], 10), blue: parseInt("" + i2[3], 10) };
var r2 = ut.exec(e2.substring(0, 50));
if (r2)
return { red: parseInt("" + r2[1], 10), green: parseInt("" + r2[2], 10), blue: parseInt("" + r2[3], 10), alpha: parseFloat("" + r2[4]) > 1 ? parseFloat("" + r2[4]) / 100 : parseFloat("" + r2[4]) };
var s2 = pt.exec(e2);
if (s2) {
var a2 = "rgb(" + rt(parseInt("" + s2[1], 10), parseInt("" + s2[2], 10) / 100, parseInt("" + s2[3], 10) / 100) + ")", c2 = dt.exec(a2);
if (!c2)
throw new Q(4, e2, a2);
return { red: parseInt("" + c2[1], 10), green: parseInt("" + c2[2], 10), blue: parseInt("" + c2[3], 10) };
}
var l2 = mt.exec(e2.substring(0, 50));
if (l2) {
var h2 = "rgb(" + rt(parseInt("" + l2[1], 10), parseInt("" + l2[2], 10) / 100, parseInt("" + l2[3], 10) / 100) + ")", d2 = dt.exec(h2);
if (!d2)
throw new Q(4, e2, h2);
return { red: parseInt("" + d2[1], 10), green: parseInt("" + d2[2], 10), blue: parseInt("" + d2[3], 10), alpha: parseFloat("" + l2[4]) > 1 ? parseFloat("" + l2[4]) / 100 : parseFloat("" + l2[4]) };
}
throw new Q(5);
}
function ft(t2) {
return function(t3) {
var e2, n2 = t3.red / 255, o2 = t3.green / 255, i2 = t3.blue / 255, r2 = Math.max(n2, o2, i2), s2 = Math.min(n2, o2, i2), a2 = (r2 + s2) / 2;
if (r2 === s2)
return t3.alpha !== undefined ? { hue: 0, saturation: 0, lightness: a2, alpha: t3.alpha } : { hue: 0, saturation: 0, lightness: a2 };
var c2 = r2 - s2, l2 = a2 > 0.5 ? c2 / (2 - r2 - s2) : c2 / (r2 + s2);
switch (r2) {
case n2:
e2 = (o2 - i2) / c2 + (o2 < i2 ? 6 : 0);
break;
case o2:
e2 = (i2 - n2) / c2 + 2;
break;
default:
e2 = (n2 - o2) / c2 + 4;
}
return e2 *= 60, t3.alpha !== undefined ? { hue: e2, saturation: l2, lightness: a2, alpha: t3.alpha } : { hue: e2, saturation: l2, lightness: a2 };
}(gt(t2));
}
var yt = function(t2) {
return t2.length === 7 && t2[1] === t2[2] && t2[3] === t2[4] && t2[5] === t2[6] ? "#" + t2[1] + t2[3] + t2[5] : t2;
};
function _t(t2) {
var e2 = t2.toString(16);
return e2.length === 1 ? "0" + e2 : e2;
}
function bt(t2) {
return _t(Math.round(255 * t2));
}
function xt(t2, e2, n2) {
return yt("#" + bt(t2) + bt(e2) + bt(n2));
}
function vt(t2, e2, n2) {
return rt(t2, e2, n2, xt);
}
function It(t2, e2, n2) {
if (typeof t2 == "number" && typeof e2 == "number" && typeof n2 == "number")
return yt("#" + _t(t2) + _t(e2) + _t(n2));
if (typeof t2 == "object" && e2 === undefined && n2 === undefined)
return yt("#" + _t(t2.red) + _t(t2.green) + _t(t2.blue));
throw new Q(6);
}
function St(t2, e2, n2, o2) {
if (typeof t2 == "object" && e2 === undefined && n2 === undefined && o2 === undefined)
return t2.alpha >= 1 ? It(t2.red, t2.green, t2.blue) : "rgba(" + t2.red + "," + t2.green + "," + t2.blue + "," + t2.alpha + ")";
throw new Q(7);
}
function Ct(t2) {
if (typeof t2 != "object")
throw new Q(8);
if (function(t3) {
return typeof t3.red == "number" && typeof t3.green == "number" && typeof t3.blue == "number" && typeof t3.alpha == "number";
}(t2))
return St(t2);
if (function(t3) {
return typeof t3.red == "number" && typeof t3.green == "number" && typeof t3.blue == "number" && (typeof t3.alpha != "number" || t3.alpha === undefined);
}(t2))
return It(t2);
if (function(t3) {
return typeof t3.hue == "number" && typeof t3.saturation == "number" && typeof t3.lightness == "number" && typeof t3.alpha == "number";
}(t2))
return function(t3, e2, n2, o2) {
if (typeof t3 == "object" && e2 === undefined && n2 === undefined && o2 === undefined)
return t3.alpha >= 1 ? vt(t3.hue, t3.saturation, t3.lightness) : "rgba(" + rt(t3.hue, t3.saturation, t3.lightness) + "," + t3.alpha + ")";
throw new Q(2);
}(t2);
if (function(t3) {
return typeof t3.hue == "number" && typeof t3.saturation == "number" && typeof t3.lightness == "number" && (typeof t3.alpha != "number" || t3.alpha === undefined);
}(t2))
return function(t3, e2, n2) {
if (typeof t3 == "object" && e2 === undefined && n2 === undefined)
return vt(t3.hue, t3.saturation, t3.lightness);
throw new Q(1);
}(t2);
throw new Q(8);
}
function Pt(t2, e2, n2) {
return function() {
var o2 = n2.concat(Array.prototype.slice.call(arguments));
return o2.length >= e2 ? t2.apply(this, o2) : Pt(t2, e2, o2);
};
}
function Mt(t2) {
return Pt(t2, t2.length, []);
}
Mt(function(t2, e2) {
if (e2 === "transparent")
return e2;
var n2 = ft(e2);
return Ct(V({}, n2, { hue: n2.hue + parseFloat(t2) }));
});
function Nt(t2, e2, n2) {
return Math.max(t2, Math.min(e2, n2));
}
Mt(function(t2, e2) {
if (e2 === "transparent")
return e2;
var n2 = ft(e2);
return Ct(V({}, n2, { lightness: Nt(0, 1, n2.lightness - parseFloat(t2)) }));
});
Mt(function(t2, e2) {
if (e2 === "transparent")
return e2;
var n2 = ft(e2);
return Ct(V({}, n2, { saturation: Nt(0, 1, n2.saturation - parseFloat(t2)) }));
});
Mt(function(t2, e2) {
if (e2 === "transparent")
return e2;
var n2 = ft(e2);
return Ct(V({}, n2, { lightness: Nt(0, 1, n2.lightness + parseFloat(t2)) }));
});
var wt = Mt(function(t2, e2, n2) {
if (e2 === "transparent")
return n2;
if (n2 === "transparent")
return e2;
if (t2 === 0)
return n2;
var o2 = gt(e2), i2 = V({}, o2, { alpha: typeof o2.alpha == "number" ? o2.alpha : 1 }), r2 = gt(n2), s2 = V({}, r2, { alpha: typeof r2.alpha == "number" ? r2.alpha : 1 }), a2 = i2.alpha - s2.alpha, c2 = 2 * parseFloat(t2) - 1, l2 = ((c2 * a2 === -1 ? c2 : c2 + a2) / (1 + c2 * a2) + 1) / 2, h2 = 1 - l2;
return St({ red: Math.floor(i2.red * l2 + s2.red * h2), green: Math.floor(i2.green * l2 + s2.green * h2), blue: Math.floor(i2.blue * l2 + s2.blue * h2), alpha: i2.alpha * parseFloat(t2) + s2.alpha * (1 - parseFloat(t2)) });
});
Mt(function(t2, e2) {
if (e2 === "transparent")
return e2;
var n2 = gt(e2);
return St(V({}, n2, { alpha: Nt(0, 1, (100 * (typeof n2.alpha == "number" ? n2.alpha : 1) + 100 * parseFloat(t2)) / 100) }));
});
Mt(function(t2, e2) {
if (e2 === "transparent")
return e2;
var n2 = ft(e2);
return Ct(V({}, n2, { saturation: Nt(0, 1, n2.saturation + parseFloat(t2)) }));
});
Mt(function(t2, e2) {
return e2 === "transparent" ? e2 : Ct(V({}, ft(e2), { hue: parseFloat(t2) }));
});
Mt(function(t2, e2) {
return e2 === "transparent" ? e2 : Ct(V({}, ft(e2), { lightness: parseFloat(t2) }));
});
Mt(function(t2, e2) {
return e2 === "transparent" ? e2 : Ct(V({}, ft(e2), { saturation: parseFloat(t2) }));
});
Mt(function(t2, e2) {
return e2 === "transparent" ? e2 : wt(parseFloat(t2), "rgb(0, 0, 0)", e2);
});
Mt(function(t2, e2) {
return e2 === "transparent" ? e2 : wt(parseFloat(t2), "rgb(255, 255, 255)", e2);
});
var Tt = Mt(function(t2, e2) {
if (e2 === "transparent")
return e2;
var n2 = gt(e2);
return St(V({}, n2, { alpha: Nt(0, 1, +(100 * (typeof n2.alpha == "number" ? n2.alpha : 1) - 100 * parseFloat(t2)).toFixed(2) / 100) }));
});
var Rt = { 0: "M0.301025 0.257813 L0.206593 0.283385 L0.122042 0.361307 L0.075923 0.474441 L0.064942 0.642221 L0.091296 0.78289 L0.159376 0.899463 L0.257104 0.961214 L0.344948 0.961214 L0.442678 0.899463 L0.510757 0.78289 L0.537111 0.642221 L0.526131 0.474441 L0.480012 0.361307 L0.39546 0.283385 L0.301025 0.257813", 1: "M0.220426 0.40845 L0.381626 0.270996 L0.381626 0.948966", 2: "M0.110409 0.39212 L0.125621 0.342293 L0.170571 0.295823 L0.244237 0.26431 L0.291518 0.257813 L0.373319 0.263799 L0.434683 0.290705 L0.468239 0.331966 L0.480292 0.379913 L0.479492 0.411806 L0.465088 0.465192 L0.402571 0.568988 L0.245134 0.766438 L0.07959 0.948045 L0.522462 0.948045", 3: "M0.081606 0.345073 L0.119154 0.315633 L0.178996 0.284091 L0.255265 0.257813 L0.349133 0.263062 L0.43127 0.289348 L0.48994 0.336662 L0.525141 0.394491 L0.513407 0.457577 L0.466472 0.504892 L0.384334 0.541692 L0.290464 0.56272 L0.20833 0.573235 L0.290464 0.583749 L0.384334 0.610035 L0.466472 0.652092 L0.519274 0.709922 L0.531007 0.773007 L0.50754 0.841351 L0.454738 0.899179 L0.3726 0.946494 L0.310412 0.961214 L0.209503 0.959111 L0.127367 0.946494 L0.071046 0.929671", 4: "M0.418494 0.270996 L0.048828 0.724199 L0.553224 0.724199 M0.414181 0.578167 L0.414181 0.94897", 5: "M0.074951 0.270996 L0.074951 0.614701 L0.267655 0.5695 L0.405247 0.586502 L0.460002 0.617189 L0.498028 0.660731 L0.527101 0.779401 L0.513352 0.841049 L0.477274 0.889568 L0.406378 0.93463 L0.324445 0.958337 L0.247399 0.962139 L0.182516 0.949767 L0.130068 0.925508 L0.074951 0.875607 M0.074951 0.270996 L0.527101 0.270996", 6: "M0.428549 0.257813 L0.341433 0.285053 L0.26073 0.312099 L0.192188 0.360182 L0.138902 0.410969 L0.098219 0.500422 L0.070249 0.584267 L0.067264 0.670716 L0.065164 0.756863 L0.087163 0.820973 L0.108168 0.861042 L0.157916 0.913131 L0.210981 0.948192 L0.29279 0.961214 L0.384548 0.956206 L0.456409 0.924151 L0.507262 0.881077 L0.5349 0.821975 L0.537111 0.771889 L0.521634 0.718798 L0.498418 0.67372 L0.463042 0.636657 L0.414398 0.613617 L0.34696 0.598591 L0.28284 0.595587 L0.215403 0.605604 L0.145756 0.641665 L0.109274 0.678729 L0.064942 0.724006", 7: "M0.071534 0.270996 L0.530519 0.270996 L0.495935 0.291702 L0.477752 0.305407 L0.435186 0.346112 L0.412067 0.374136 L0.388565 0.40796 L0.365315 0.448098 L0.342943 0.495062 L0.322081 0.549366 L0.303364 0.611524 L0.287416 0.68205 L0.270077 0.80465 L0.26253 0.94897", 8: "M0.286761 0.257813 L0.210684 0.27162 L0.1414 0.305622 L0.092494 0.382125 L0.111513 0.450128 L0.16857 0.502193 L0.228345 0.539382 L0.377781 0.594635 L0.470161 0.645637 L0.52586 0.706203 L0.538087 0.792269 L0.506841 0.87621 L0.438915 0.927212 L0.339743 0.961214 L0.263666 0.959089 L0.174004 0.929337 L0.102003 0.881523 L0.063965 0.811395 L0.066682 0.741266 L0.102003 0.671139 L0.180797 0.608448 L0.259591 0.580822 L0.358762 0.548945 L0.456576 0.49688 L0.486463 0.446941 L0.487822 0.362999 L0.453859 0.302434 L0.384574 0.265245 L0.286761 0.257813", 9: "M0.511026 0.437812 L0.491026 0.347812 L0.451026 0.297812 L0.391026 0.267812 L0.311026 0.257813 L0.231026 0.267812 L0.161026 0.297812 L0.111026 0.347812 L0.091026 0.417812 L0.111026 0.487812 L0.161026 0.537812 L0.231026 0.567812 L0.311026 0.577812 L0.391026 0.557812 L0.451026 0.517812 L0.491026 0.477812 L0.511026 0.437812 M0.510026 0.438812 L0.434026 0.636812 L0.381026 0.777812 L0.337026 0.879812 L0.301026 0.957812", "!": "M0.301026 0.270996 L0.301026 0.749566 M0.251466 0.94897 L0.350587 0.94897", '"': "M0.16504 0.270996 L0.16504 0.523022 M0.437013 0.270996 L0.437013 0.523022", "#": "M0.20958 0.282227 L0.146515 0.949754 M0.461844 0.282227 L0.398779 0.949754 M0.032999 0.526969 L0.600587 0.452796 M0.001465 0.82366 L0.569055 0.749486", $: "M0.307121 0.240234 L0.307121 1.083502 M0.490031 0.415915 L0.404676 0.328075 L0.23396 0.310507 L0.136407 0.398347 L0.099828 0.521324 L0.124213 0.591596 L0.197379 0.644299 L0.429061 0.697003 L0.502224 0.749708 L0.526613 0.837547 L0.477836 0.960526 L0.355897 1.013228 L0.197379 0.99566 L0.112021 0.942957 L0.07544 0.837547", "'": "M0.301026 0.270996 L0.301026 0.523022", "(": "M0.413087 0.241211 L0.372337 0.28347 L0.331589 0.334184 L0.290838 0.393349 L0.25009 0.460965 L0.219528 0.528584 L0.199153 0.5962 L0.188966 0.655364 L0.199153 0.714529 L0.219528 0.782146 L0.25009 0.849764 L0.290838 0.91738 L0.331589 0.976544 L0.372337 1.027258 L0.413087 1.069491", ")": "M0.188966 0.241211 L0.229716 0.28347 L0.270466 0.334184 L0.311213 0.393349 L0.351964 0.460965 L0.382526 0.528584 L0.4029 0.5962 L0.413087 0.655364 L0.4029 0.714529 L0.382526 0.782146 L0.351964 0.849764 L0.311213 0.91738 L0.270466 0.976544 L0.229716 1.027258 L0.188966 1.069491", "*": "M0.301026 0.458702 L0.301026 0.681942 M0.301026 0.458702 L0.520997 0.536834 M0.301026 0.458702 L0.439954 0.257813 M0.301026 0.458702 L0.162098 0.257813 M0.301026 0.458702 L0.081055 0.536834", "+": "M0.042969 0.66845 L0.559083 0.66845 M0.301023 0.428223 L0.301023 0.908661", ",": "M0.38672 0.852051 L0.215333 1.030661 L0.301025 1.119971", "-": "M0.173829 0.686035 L0.428224 0.686035", ".": "M0.362549 0.851074 L0.239503 0.851074", "/": "M0.062501 1.035249 L0.539551 0.270996", "<": "M0.559083 0.441895 L0.042969 0.66939 L0.042969 0.66939 L0.559083 0.896902", "=": "M0.042969 0.545898 L0.559083 0.545898 M0.042969 0.80837 L0.559083 0.80837", ">": "M0.042969 0.441895 L0.559083 0.66939 L0.559083 0.66939 L0.042969 0.896902", A: "M0.018067 0.94897 L0.290179 0.270996 L0.583986 0.94897 M0.155303 0.684521 L0.433548 0.684521", B: "M0.063965 0.94897 L0.063965 0.278953 L0.209356 0.270996 L0.342486 0.294394 L0.432179 0.37292 L0.418224 0.48773 L0.312686 0.549166 L0.084728 0.575531 L0.306377 0.589434 L0.468877 0.647456 L0.538087 0.736658 L0.5324 0.85202 L0.501247 0.902983 L0.42355 0.944398 L0.063965 0.94897", C: "M0.529054 0.419847 L0.498425 0.345196 L0.442238 0.292341 L0.33583 0.257813 L0.257199 0.268357 L0.187906 0.303748 L0.120243 0.385432 L0.072998 0.599844 L0.110073 0.815385 L0.165381 0.902183 L0.222883 0.942801 L0.334904 0.961214 L0.43253 0.937679 L0.504816 0.868999 L0.529054 0.772065", D: "M0.064454 0.94897 L0.071838 0.285078 L0.171217 0.270996 L0.247348 0.272633 L0.37101 0.306078 L0.462461 0.378304 L0.514748 0.475555 L0.535591 0.576392 L0.537599 0.652313 L0.528065 0.717381 L0.508562 0.772419 L0.445948 0.855695 L0.362356 0.90871 L0.225203 0.945862 L0.064454 0.94897", E: "M0.080078 0.270996 L0.080078 0.94897 M0.080078 0.270996 L0.521974 0.270996 M0.080078 0.609981 L0.389405 0.609981 M0.080078 0.94897 L0.521974 0.94897", F: "M0.086426 0.270996 L0.086426 0.94897 M0.091304 0.275607 L0.515626 0.275607 M0.091304 0.607677 L0.447344 0.607677", G: "M0.498034 0.284943 L0.374621 0.257813 L0.244219 0.268648 L0.160577 0.311997 L0.094556 0.398116 L0.056397 0.58404 L0.076752 0.785532 L0.120865 0.858197 L0.188947 0.916734 L0.271008 0.953591 L0.357069 0.961214 L0.43715 0.932047 L0.501262 0.858539 L0.545656 0.648611 L0.329595 0.648131", H: "M0.066895 0.270996 L0.066895 0.94897 M0.066895 0.595658 L0.530009 0.595658 M0.535157 0.270996 L0.535157 0.94897", I: "M0.301026 0.270996 L0.301026 0.94897", J: "M0.506839 0.270996 L0.507814 0.782193 L0.498468 0.846168 L0.480733 0.880789 L0.455864 0.90832 L0.426095 0.929408 L0.360746 0.954812 L0.302508 0.962139 L0.223573 0.953638 L0.16538 0.930312 L0.137072 0.907715 L0.116428 0.880312 L0.102822 0.848819 L0.095633 0.813947 L0.094239 0.776413", K: "M0.035401 0.270996 L0.035401 0.94897 M0.502258 0.316194 L0.035401 0.687823 M0.212484 0.582361 L0.566652 0.933903", L: "M0.07544 0.270996 L0.07544 0.94897 L0.526613 0.94897", M: "M0.042481 0.94897 L0.042481 0.270996 L0.301027 0.712492 L0.559571 0.270996 L0.559571 0.94897", N: "M0.067871 0.94897 L0.067871 0.270996 L0.534181 0.94897 L0.525031 0.270996", O: "M0.287293 0.961214 L0.19843 0.933567 L0.1172 0.849451 L0.057129 0.563945 L0.114348 0.350255 L0.18455 0.289392 L0.306101 0.257813 L0.42054 0.29572 L0.487543 0.365003 L0.544923 0.625294 L0.516366 0.789624 L0.465476 0.884596 L0.375084 0.949287 L0.287293 0.961214", P: "M0.070557 0.94897 L0.070557 0.28379 L0.20704 0.270996 L0.329134 0.278993 L0.408525 0.300514 L0.444022 0.317908 L0.500637 0.368929 L0.525796 0.423728 L0.531496 0.50384 L0.508934 0.554205 L0.473724 0.582043 L0.417577 0.604365 L0.336375 0.620372 L0.226014 0.629268 L0.082368 0.630258", Q: "M0.282435 1.050813 L0.195447 1.019646 L0.115933 0.924817 L0.057129 0.602943 L0.113139 0.362034 L0.18186 0.293418 L0.300844 0.257813 L0.412868 0.300553 L0.478457 0.37866 L0.534625 0.672103 L0.506671 0.857367 L0.456855 0.964437 L0.368371 1.037368 L0.282435 1.050813 M0.341225 0.815559 L0.544923 1.070653", R: "M0.034912 0.944112 L0.034912 0.288556 L0.227127 0.270996 L0.362038 0.276867 L0.443423 0.294907 L0.477644 0.309614 L0.505809 0.328757 L0.526616 0.352817 L0.544963 0.418061 L0.543241 0.475921 L0.524463 0.517817 L0.49076 0.546518 L0.444265 0.564799 L0.355195 0.578739 L0.047653 0.589627 M0.303054 0.617306 L0.56714 0.94897", S: "M0.483037 0.364333 L0.407613 0.267477 L0.22883 0.257813 L0.128623 0.327565 L0.087712 0.455539 L0.104656 0.518727 L0.168054 0.573307 L0.41928 0.617318 L0.503796 0.669342 L0.535157 0.759324 L0.493846 0.900055 L0.367668 0.961214 L0.205436 0.956661 L0.116711 0.907038 L0.066895 0.790334", T: "M0.022949 0.270996 L0.579103 0.270996 M0.309284 0.270996 L0.309284 0.94897", U: "M0.072022 0.270996 L0.07308 0.648875 L0.080372 0.75167 L0.099024 0.827813 L0.134786 0.885729 L0.181571 0.924023 L0.251464 0.95168 L0.339655 0.962139 L0.401553 0.951668 L0.45232 0.924086 L0.482701 0.891771 L0.495745 0.870529 L0.515699 0.81637 L0.525014 0.744626 L0.530031 0.272017", V: "M0.027832 0.270996 L0.320083 0.94897 L0.57422 0.270996", W: "M0 0.270996 L0.079799 0.940377 L0.285198 0.472884 L0.505255 0.94897 L0.602052 0.270996", X: "M0.009034 0.270996 L0.586805 0.94897 M0.593019 0.270996 L0.015246 0.94897", Y: "M0.018067 0.270996 L0.293132 0.574135 M0.583986 0.271959 L0.294954 0.57606 L0.305277 0.94897", Z: "M0.053711 0.270996 L0.548341 0.270996 L0.053711 0.94897 L0.548341 0.94897", "[": "M0.404542 0.240234 L0.197511 0.240234 L0.197511 1.069424 L0.404542 1.069424", "\\": "M0.062501 0.270996 L0.539551 1.035249", "]": "M0.19751 0.240234 L0.404542 0.240234 L0.404542 1.069424 L0.19751 1.069424", "^": "M0.035156 0.523931 L0.301024 0.270996 L0.566896 0.523931", _: "M0 1.160601 L0.602052 1.160601", a: "M0.527101 0.439941 L0.527101 0.973965 M0.527101 0.553824 L0.451366 0.477535 L0.376759 0.439941 L0.263722 0.439941 L0.187989 0.477535 L0.112255 0.553824 L0.074951 0.66881 L0.074951 0.745099 L0.112255 0.85898 L0.187989 0.93527 L0.263722 0.973965 L0.376759 0.973965 L0.451366 0.93527 L0.527101 0.85898", b: "M0.07666 0.240234 L0.07666 0.959985 M0.07666 0.582737 L0.151822 0.514237 L0.225865 0.480483 L0.338045 0.480483 L0.413211 0.514237 L0.488374 0.582737 L0.525392 0.685983 L0.525392 0.754485 L0.488374 0.856739 L0.413211 0.92524 L0.338045 0.959985 L0.225865 0.959985 L0.151822 0.92524 L0.07666 0.856739", c: "M0.512452 0.553823 L0.441624 0.477535 L0.371854 0.439941 L0.26614 0.439941 L0.195312 0.477535 L0.124486 0.553823 L0.0896 0.668808 L0.0896 0.745099 L0.124486 0.858979 L0.195312 0.93527 L0.26614 0.973965 L0.371854 0.973965 L0.441624 0.93527 L0.512452 0.858979", d: "M0.525392 0.240234 L0.525392 0.959985 M0.525392 0.582737 L0.450232 0.514237 L0.376189 0.480483 L0.264006 0.480483 L0.188844 0.514237 L0.11368 0.582737 L0.076661 0.685983 L0.076661 0.754485 L0.11368 0.856739 L0.188844 0.92524 L0.264006 0.959985 L0.376189 0.959985 L0.450232 0.92524 L0.525392 0.856739", e: "M0.059571 0.668808 L0.542482 0.668808 M0.542482 0.592521 L0.502641 0.516231 L0.461594 0.477535 L0.381914 0.439941 L0.261186 0.439941 L0.180299 0.477535 L0.099412 0.553823 L0.059571 0.668808 L0.059571 0.745099 L0.099412 0.858979 L0.180299 0.93527 L0.261186 0.973965 L0.381914 0.973965 L0.461594 0.93527 L0.542482 0.858979", f: "M0.512941 0.240234 L0.406984 0.240234 L0.301026 0.274346 L0.248047 0.374731 L0.248047 0.946817 M0.089112 0.476088 L0.459965 0.476088", g: "M0.525392 0.439941 L0.525392 0.989395 L0.488373 1.091918 L0.45023 1.126757 L0.376189 1.160601 L0.264004 1.160601 L0.188844 1.126757 L0.113681 1.058075 L0.076661 0.954555 M0.525392 0.542467 L0.45023 0.473786 L0.376189 0.439941 L0.264004 0.439941 L0.188844 0.473786 L0.113681 0.542467 L0.076661 0.645988 L0.076661 0.714669 L0.113681 0.817193 L0.188844 0.885875 L0.264004 0.920713 L0.376189 0.920713 L0.45023 0.885875 L0.525392 0.817193", h: "M0.092041 0.240234 L0.092041 0.946817 M0.092041 0.61058 L0.205937 0.509225 L0.282214 0.476086 L0.396109 0.476086 L0.47187 0.509225 L0.510011 0.61058 L0.510011 0.946817", i: "M0.261026 0.240234 L0.341026 0.240234 M0.300978 0.476089 L0.300978 0.946817", j: "M0.3853 0.240234 L0.447023 0.240234 M0.416159 0.465708 L0.416159 1.011689 L0.383887 1.108586 L0.252832 1.140264 L0.15503 1.108586", k: "M0.065186 0.240234 L0.065186 0.946817 M0.493824 0.476086 L0.065186 0.812323 M0.236758 0.677829 L0.536867 0.946817", l: "M0.301026 0.234863 L0.301026 0.946441", m: "M0.050538 0.439941 L0.050538 0.960796 M0.050538 0.588758 L0.114405 0.476607 L0.157178 0.439941 L0.236864 0.439941 L0.279637 0.476607 L0.32241 0.588758 L0.32241 0.960796 M0.32241 0.588758 L0.386281 0.476607 L0.428467 0.439941 L0.50874 0.439941 L0.551515 0.476607 L0.551515 0.960796", n: "M0.092041 0.439941 L0.092041 0.960796 M0.092041 0.588758 L0.205936 0.476607 L0.282216 0.439941 L0.396113 0.439941 L0.471871 0.476607 L0.510011 0.588758 L0.510011 0.960796", o: "M0.247175 0.439941 L0.175178 0.477535 L0.103186 0.553823 L0.066895 0.668808 L0.066895 0.745099 L0.103186 0.858979 L0.175178 0.93527 L0.247175 0.973965 L0.354874 0.973965 L0.426872 0.93527 L0.498866 0.858979 L0.535157 0.745099 L0.535157 0.668808 L0.498866 0.553823 L0.426872 0.477535 L0.354874 0.439941 L0.247175 0.439941", p: "M0.076904 0.439941 L0.076904 1.154244 M0.076904 0.541563 L0.151986 0.473487 L0.225944 0.439941 L0.338005 0.439941 L0.413087 0.473487 L0.488166 0.541563 L0.525148 0.644169 L0.525148 0.712246 L0.488166 0.813866 L0.413087 0.881942 L0.338005 0.916471 L0.225944 0.916471 L0.151986 0.881942 L0.076904 0.813866", q: "M0.525148 0.441895 L0.525148 1.156195 M0.525148 0.5435 L0.450067 0.47544 L0.376106 0.441895 L0.264042 0.441895 L0.188966 0.47544 L0.113885 0.5435 L0.076905 0.646108 L0.076905 0.714187 L0.113885 0.815809 L0.188966 0.883886 L0.264042 0.918418 L0.376106 0.918418 L0.450067 0.883886 L0.525148 0.815809", r: "M0.107422 0.439941 L0.107422 0.960796 M0.107422 0.663164 L0.155824 0.551014 L0.252626 0.476607 L0.349428 0.439941 L0.49463 0.439941", s: "M0.475556 0.477535 L0.400757 0.439941 L0.276092 0.439941 L0.176361 0.477535 L0.101563 0.553823 L0.101563 0.630112 L0.176361 0.668808 L0.301024 0.668808 L0.425688 0.745099 L0.50049 0.821387 L0.50049 0.897677 L0.425688 0.93527 L0.325956 0.973965 L0.201295 0.973965 L0.126496 0.93527 L0.101563 0.858979", t: "M0.246032 0.297852 L0.246032 0.826549 L0.301023 0.919323 L0.411011 0.950848 L0.520997 0.950848 M0.081055 0.515799 L0.466004 0.515799", u: "M0.092041 0.454102 L0.092041 0.826134 L0.13018 0.937211 L0.205936 0.974954 L0.319832 0.974954 L0.396113 0.937211 L0.510011 0.826134 M0.510011 0.454102 L0.510011 0.974954", v: "M0.048828 0.453125 L0.301026 0.961719 M0.553224 0.453125 L0.301026 0.961719", w: "M0 0.453125 L0.150512 0.961719 M0.301024 0.453125 L0.150512 0.961719 M0.301024 0.453125 L0.451539 0.961719 M0.602052 0.453125 L0.451539 0.961719", x: "M0.03711 0.453125 L0.564943 0.961719 M0.564943 0.453125 L0.03711 0.961719", y: "M0.084618 0.453125 L0.320232 0.921476 M0.55713 0.453125 L0.320232 0.921476 L0.242119 1.055289 L0.163369 1.122196 L0.084618 1.155166 L0.044922 1.155166", z: "M0.505373 0.452148 L0.09668 0.961651 M0.09668 0.452148 L0.505373 0.452148 M0.09668 0.961651 L0.505373 0.961651" };
var Et = {};
for (const t2 in Rt) {
Et[t2] = [];
const e2 = Rt[t2].split("M").slice(1).map((t3) => t3.split("L").map((t4) => t4.trim().split(" ").map(parseFloat)));
for (const n2 of e2)
for (let e3 = 0;e3 < n2.length - 1; e3++)
Et[t2].push({ x1: n2[e3][0], y1: 1 - n2[e3][1], x2: n2[e3 + 1][0], y2: 1 - n2[e3 + 1][1] });
}
var At = (t2, e2) => ({ ...t2, rects: [...t2.rects ?? [], ...e2.rects ?? []], points: [...t2.points ?? [], ...e2.points ?? []], lines: [...t2.lines ?? [], ...e2.lines ?? []], infiniteLines: [...t2.infiniteLines ?? [], ...e2.infiniteLines ?? []], polygons: [...t2.polygons ?? [], ...e2.polygons ?? []], circles: [...t2.circles ?? [], ...e2.circles ?? []], arrows: [...t2.arrows ?? [], ...e2.arrows ?? []], texts: [...t2.texts ?? [], ...e2.texts ?? []] });
function Ot(t2, e2) {
if (t2.points)
for (const n2 of t2.points)
n2.step = e2;
if (t2.lines)
for (const n2 of t2.lines)
n2.step = e2;
if (t2.infiniteLines)
for (const n2 of t2.infiniteLines)
n2.step = e2;
if (t2.polygons)
for (const n2 of t2.polygons)
n2.step = e2;
if (t2.rects)
for (const n2 of t2.rects)
n2.step = e2;
if (t2.circles)
for (const n2 of t2.circles)
n2.step = e2;
if (t2.texts)
for (const n2 of t2.texts)
n2.step = e2;
if (t2.arrows)
for (const n2 of t2.arrows)
n2.step = e2;
return t2;
}
var kt = class {
MAX_ITERATIONS = 1e5;
solved = false;
failed = false;
iterations = 0;
progress = 0;
error = null;
activeSubSolver;
failedSubSolvers;
timeToSolve;
stats = {};
_setupDone = false;
getSolverName() {
return this.constructor.name;
}
setup() {
this._setupDone || (this._setup(), this._setupDone = true);
}
_setup() {}
step() {
if (this._setupDone || this.setup(), !this.solved && !this.failed) {
this.iterations++;
try {
this._step();
} catch (t2) {
throw this.error = `${this.getSolverName()} error: ${t2}`, this.failed = true, t2;
}
!this.solved && this.iterations >= this.MAX_ITERATIONS && this.tryFinalAcceptance(), !this.solved && this.iterations >= this.MAX_ITERATIONS && (this.error = `${this.getSolverName()} ran out of iterations`, this.failed = true), "computeProgress" in this && (this.progress = this.computeProgress());
}
}
_step() {}
getConstructorParams() {
throw new Error("getConstructorParams not implemented");
}
getOutput() {
return null;
}
solve() {
const t2 = Date.now();
for (;!this.solved && !this.failed; )
this.step();
const e2 = Date.now();
this.timeToSolve = e2 - t2;
}
visualize() {
return { lines: [], points: [], rects: [], circles: [] };
}
tryFinalAcceptance() {}
preview() {
return { lines: [], points: [], rects: [], circles: [] };
}
};
function Dt(t2, e2, n2, o2 = {}) {
return { solverName: t2, solverClass: e2, getConstructorParams: n2, onSolved: o2.onSolved };
}
var Lt = class extends kt {
startTimeOfStage = {};
endTimeOfStage = {};
timeSpentOnStage = {};
firstIterationOfStage = {};
currentPipelineStageIndex = 0;
inputProblem;
pipelineOutputs = {};
constructor(t2) {
super(), this.inputProblem = t2, this.MAX_ITERATIONS = 1e6;
}
_step() {
const t2 = this.pipelineDef[this.currentPipelineStageIndex];
if (!t2)
return void (this.solved = true);
if (this.activeSubSolver) {
if (this.activeSubSolver.step(), this.activeSubSolver.solved) {
this.endTimeOfStage[t2.solverName] = performance.now(), this.timeSpentOnStage[t2.solverName] = this.endTimeOfStage[t2.solverName] - this.startTimeOfStage[t2.solverName];
const e3 = this.activeSubSolver.getOutput();
e3 !== null && (this.pipelineOutputs[t2.solverName] = e3), t2.onSolved?.(this), this.activeSubSolver = null, this.currentPipelineStageIndex++;
} else
this.activeSubSolver.failed && (this.error = this.activeSubSolver?.error, this.failed = true, this.activeSubSolver = null);
return;
}
const e2 = t2.getConstructorParams(this);
this.activeSubSolver = new t2.solverClass(...e2), this[t2.solverName] = this.activeSubSolver, this.timeSpentOnStage[t2.solverName] = 0, this.startTimeOfStage[t2.solverName] = performance.now(), this.firstIterationOfStage[t2.solverName] = this.iterations;
}
solveUntilStage(t2) {
for (;this.getCurrentStageName().toLowerCase() !== t2.toLowerCase() && (this.step(), !this.failed && !this.solved); )
;
}
getCurrentStageName() {
return this.pipelineDef[this.currentPipelineStageIndex]?.solverName ?? "none";
}
getStageProgress() {
const t2 = this.pipelineDef.length;
if (t2 === 0)
return 1;
const e2 = this.activeSubSolver?.progress ?? 0;
return (this.currentPipelineStageIndex + e2) / t2;
}
getStageStats() {
const t2 = {};
for (const e2 of this.pipelineDef) {
const n2 = this.timeSpentOnStage[e2.solverName] || 0, o2 = this.firstIterationOfStage[e2.solverName] || 0, i2 = this.iterations, r2 = e2.solverName === this.getCurrentStageName() ? i2 - o2 : 0, s2 = this.currentPipelineStageIndex > this.pipelineDef.findIndex((t3) => t3.solverName === e2.solverName);
t2[e2.solverName] = { timeSpent: n2, iterations: r2, completed: s2 };
}
return t2;
}
initialVisualize() {
return null;
}
finalVisualize() {
return null;
}
visualize() {
if (!this.solved && this.activeSubSolver)
return this.activeSubSolver.visualize();
let t2 = 0;
const e2 = this.initialVisualize();
e2 && (Ot(e2, 0), t2 = 1);
let n2 = null;
this.solved && (n2 = this.finalVisualize());
const o2 = [e2].filter(Boolean).concat(this.pipelineDef.map((e3, n3) => {
const o3 = this[e3.solverName], i2 = o3?.visualize();
return i2 ? (Ot(i2, n3 + t2), i2) : null;
}).filter(Boolean));
return o2.length === 0 ? { points: [], rects: [], lines: [], circles: [], texts: [] } : (this.solved && n2 && (Ot(n2, o2.length + t2 + 1), o2.push(n2)), o2.length === 1 ? o2[0] : { points: o2.flatMap((t3) => t3.points || []), rects: o2.flatMap((t3) => t3.rects || []), lines: o2.flatMap((t3) => t3.lines || []), circles: o2.flatMap((t3) => t3.circles || []), texts: o2.flatMap((t3) => t3.texts || []) });
}
preview() {
return this.activeSubSolver ? this.activeSubSolver.preview() : super.preview();
}
computeProgress() {
return this.getStageProgress();
}
getStageOutput(t2) {
return this.pipelineOutputs[t2];
}
getAllOutputs() {
return { ...this.pipelineOutputs };
}
hasStageOutput(t2) {
return t2 in this.pipelineOutputs;
}
getSolver(t2) {
return this[t2];
}
};
var zt = class {
constructor(t2 = 1 / 0, e2 = Float64Array, n2 = Uint32Array) {
const o2 = t2 !== 1 / 0;
this.ids = o2 ? new n2(t2) : [], this.values = o2 ? new e2(t2) : [], this.capacity = t2, this.length = 0;
}
clear() {
this.length = 0;
}
push(t2, e2) {
if (this.length === this.capacity)
throw new RangeError("Queue is at capacity.");
let n2 = this.length++;
for (;n2 > 0; ) {
const t3 = n2 - 1 >> 1, o2 = this.values[t3];
if (e2 >= o2)
break;
this.ids[n2] = this.ids[t3], this.values[n2] = o2, n2 = t3;
}
this.ids[n2] = t2, this.values[n2] = e2;
}
pop() {
if (this.length === 0)
return;
const t2 = this.ids, e2 = this.values, n2 = t2[0], o2 = --this.length;
if (o2 > 0) {
const n3 = t2[o2], i2 = e2[o2];
let r2 = 0;
const s2 = o2 >> 1;
for (;r2 < s2; ) {
const n4 = 1 + (r2 << 1), s3 = n4 + 1, a2 = n4 + (+(s3 < o2) & +(e2[s3] < e2[n4]));
if (e2[a2] >= i2)
break;
t2[r2] = t2[a2], e2[r2] = e2[a2], r2 = a2;
}
t2[r2] = n3, e2[r2] = i2;
}
return n2;
}
peek() {
return this.length > 0 ? this.ids[0] : undefined;
}
peekValue() {
return this.length > 0 ? this.values[0] : undefined;
}
shrink() {
Array.isArray(this.ids) && (this.ids.length = this.length), Array.isArray(this.values) && (this.values.length = this.length);
}
};
var Bt = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array];
var Ft = class t2 {
static from(e2, n2 = 0) {
if (n2 % 8 != 0)
throw new Error("byteOffset must be 8-byte aligned.");
if (!e2 || e2.byteLength === undefined || "buffer" in e2)
throw new Error("Data must be an instance of ArrayBuffer or SharedArrayBuffer.");
const [o2, i2] = new Uint8Array(e2, n2 + 0, 2);
if (o2 !== 251)
throw new Error("Data does not appear to be in a Flatbush format.");
const r2 = i2 >> 4;
if (r2 !== 3)
throw new Error(`Got v${r2} data when expected v3.`);
const s2 = Bt[15 & i2];
if (!s2)
throw new Error("Unrecognized array type.");
const [a2] = new Uint16Array(e2, n2 + 2, 1), [c2] = new Uint32Array(e2, n2 + 4, 1);
return new t2(c2, a2, s2, undefined, e2, n2);
}
constructor(t3, e2 = 16, n2 = Float64Array, o2 = ArrayBuffer, i2, r2 = 0) {
if (t3 === undefined)
throw new Error("Missing required argument: numItems.");
if (isNaN(t3) || t3 <= 0)
throw new Error(`Unexpected numItems value: ${t3}.`);
this.numItems = +t3, this.nodeSize = Math.min(Math.max(+e2, 2), 65535), this.byteOffset = r2;
let s2 = t3, a2 = s2;
this._levelBounds = [4 * s2];
do {
s2 = Math.ceil(s2 / this.nodeSize), a2 += s2, this._levelBounds.push(4 * a2);
} while (s2 !== 1);
this.ArrayType = n2, this.IndexArrayType = a2 < 16384 ? Uint16Array : Uint32Array;
const c2 = Bt.indexOf(n2), l2 = 4 * a2 * n2.BYTES_PER_ELEMENT;
if (c2 < 0)
throw new Error(`Unexpected typed array class: ${n2}.`);
const h2 = n2, d2 = this.IndexArrayType;
if (i2)
this.data = i2, this._boxes = new h2(i2, r2 + 8, 4 * a2), this._indices = new d2(i2, r2 + 8 + l2, a2), this._pos = 4 * a2, this.minX = this._boxes[this._pos - 4], this.minY = this._boxes[this._pos - 3], this.maxX = this._boxes[this._pos - 2], this.maxY = this._boxes[this._pos - 1];
else {
const n3 = this.data = new o2(8 + l2 + a2 * this.IndexArrayType.BYTES_PER_ELEMENT);
this._boxes = new h2(n3, 8, 4 * a2), this._indices = new d2(n3, 8 + l2, a2), this._pos = 0, this.minX = 1 / 0, this.minY = 1 / 0, this.maxX = -1 / 0, this.maxY = -1 / 0, new Uint8Array(n3, 0, 2).set([251, 48 + c2]), new Uint16Array(n3, 2, 1)[0] = e2, new Uint32Array(n3, 4, 1)[0] = t3;
}
this._queue = new zt;
}
add(t3, e2, n2 = t3, o2 = e2) {
const i2 = this._pos, r2 = i2 >> 2, s2 = this._boxes;
return this._indices[r2] = r2, s2[i2] = t3, s2[i2 + 1] = e2, s2[i2 + 2] = n2, s2[i2 + 3] = o2, this._pos = i2 + 4, t3 < this.minX && (this.minX = t3), e2 < this.minY && (this.minY = e2), n2 > this.maxX && (this.maxX = n2), o2 > this.maxY && (this.maxY = o2), r2;
}
finish() {
if (this._pos >> 2 !== this.numItems)
throw new Error(`Added ${this._pos >> 2} items when expected ${this.numItems}.`);
const t3 = this._boxes;
if (this.numItems <= this.nodeSize)
return t3[this._pos++] = this.minX, t3[this._pos++] = this.minY, t3[this._pos++] = this.maxX, void (t3[this._pos++] = this.maxY);
const { numItems: e2, minX: n2, minY: o2, nodeSize: i2, _indices: r2, _levelBounds: s2 } = this, a2 = this.maxX - n2 || 1, c2 = this.maxY - o2 || 1, l2 = new Int32Array(e2), h2 = 65535 / a2, d2 = 65535 / c2;
for (let i3 = 0, r3 = 0;i3 < e2; i3++) {
const e3 = t3[r3++], s3 = t3[r3++], a3 = h2 * ((e3 + t3[r3++]) / 2 - n2) | 0, c3 = d2 * ((s3 + t3[r3++]) / 2 - o2) | 0;
l2[i3] = Yt(a3, c3);
}
(function(t4, e3, n3, o3, i3, r3) {
const s3 = [o3, i3];
for (;s3.length; ) {
const o4 = s3.pop() || 0, i4 = s3.pop() || 0;
if (o4 - i4 <= r3 && Math.floor(i4 / r3) >= Math.floor(o4 / r3))
continue;
const a3 = t4[i4], c3 = t4[i4 + o4 >> 1], l3 = t4[o4], h3 = a3 > c3 != a3 > l3 ? a3 : c3 < a3 != c3 < l3 ? c3 : l3;
let d3 = i4 - 1, u3 = o4 + 1;
for (;; ) {
do {
d3++;
} while (t4[d3] < h3);
do {
u3--;
} while (t4[u3] > h3);
if (d3 >= u3)
break;
$t(t4, e3, n3, d3, u3);
}
s3.push(i4, u3, u3 + 1, o4);
}
})(l2, t3, r2, 0, e2 - 1, i2);
let u2 = 4 * e2;
for (let e3 = 0, n3 = 0;e3 < s2.length - 1; e3++) {
const o3 = s2[e3];
for (;n3 < o3; ) {
const e4 = n3;
let s3 = t3[n3++], a3 = t3[n3++], c3 = t3[n3++], l3 = t3[n3++];
for (let e5 = 1;e5 < i2 && n3 < o3; e5++)
s3 = Math.min(s3, t3[n3++]), a3 = Math.min(a3, t3[n3++]), c3 = Math.max(c3, t3[n3++]), l3 = Math.max(l3, t3[n3++]);
r2[u2 >> 2] = e4, t3[u2++] = s3, t3[u2++] = a3, t3[u2++] = c3, t3[u2++] = l3;
}
}
this._pos = u2;
}
search(t3, e2, n2, o2, i2) {
if (this._pos !== this._boxes.length)
throw new Error("Data not yet indexed - call index.finish().");
const { _boxes: r2, _levelBounds: s2, _indices: a2, nodeSize: c2 } = this, l2 = 4 * this.numItems;
let h2 = r2.length - 4, d2 = s2.length - 1;
const u2 = [], p2 = [];
let m2 = false;
for (;h2 !== undefined; ) {
const g2 = Math.min(h2 + 4 * c2, s2[d2]), f2 = h2 >= l2;
if (m2)
this._collectContained(h2, g2, d2, l2, p2, i2);
else
for (let s3 = h2;s3 < g2; s3 += 4) {
const c3 = r2[s3];
if (n2 < c3)
continue;
const l3 = r2[s3 + 1];
if (o2 < l3)
continue;
const h3 = r2[s3 + 2];
if (t3 > h3)
continue;
const m3 = r2[s3 + 3];
if (e2 > m3)
continue;
const g3 = 0 | a2[s3 >> 2];
if (f2) {
const i3 = +(t3 <= c3 && e2 <= l3 && n2 >= h3 && o2 >= m3);
u2.push(g3 | i3, d2 - 1);
} else
(i2 === undefined || i2(g3, c3, l3, h3, m3)) && p2.push(g3);
}
d2 = u2.pop(), h2 = u2.pop(), h2 !== undefined && (m2 = !(1 & ~h2), h2 &= -2);
}
return p2;
}
_collectContained(t3, e2, n2, o2, i2, r2) {
const s2 = this._boxes, a2 = this._indices;
let c2 = t3;
for (let t4 = n2;t4 > 0; t4--)
c2 = a2[c2 >> 2];
const l2 = Math.min(c2 + (e2 - t3) * this.nodeSize ** n2, o2);
if (r2 === undefined)
for (;c2 < l2; c2 += 4)
i2.push(0 | a2[c2 >> 2]);
else
for (;c2 < l2; c2 += 4) {
const t4 = 0 | a2[c2 >> 2];
r2(t4, s2[c2], s2[c2 + 1], s2[c2 + 2], s2[c2 + 3]) && i2.push(t4);
}
}
neighbors(t3, e2, n2 = 1 / 0, o2 = 1 / 0, i2) {
if (this._pos !== this._boxes.length)
throw new Error("Data not yet indexed - call index.finish().");
const { _boxes: r2, _levelBounds: s2, _indices: a2, _queue: c2, nodeSize: l2 } = this, h2 = 4 * this.numItems, d2 = 4 * l2, u2 = [], p2 = n2 === 1;
let m2 = o2 * o2;
for (c2.push(r2.length - 4 << 1, 0);c2.length; ) {
const o3 = c2.ids[0];
if (1 & o3) {
if (c2.pop(), u2.push(o3 >> 1), u2.length === n2)
break;
continue;
}
c2.pop();
const l3 = o3 >> 1, g2 = l3 < h2, f2 = Math.min(l3 + d2, jt(l3, s2));
for (let n3 = l3;n3 < f2; n3 += 4) {
const o4 = r2[n3], s3 = r2[n3 + 1], l4 = r2[n3 + 2], h3 = r2[n3 + 3], d3 = Math.max(Math.max(o4 - t3, t3 - l4), 0), u3 = Math.max(Math.max(s3 - e2, e2 - h3), 0), f3 = d3 * d3 + u3 * u3;
if (f3 > m2)
continue;
const y2 = 0 | a2[n3 >> 2];
g2 ? (i2 === undefined || i2(y2)) && (c2.push(y2 << 1 | 1, f3), p2 && f3 < m2 && (m2 = f3)) : c2.push(y2 << 1, f3);
}
}
return c2.clear(), u2;
}
};
function jt(t3, e2) {
let n2 = 0, o2 = e2.length - 1;
for (;n2 < o2; ) {
const i2 = n2 + o2 >> 1;
e2[i2] > t3 ? o2 = i2 : n2 = i2 + 1;
}
return e2[n2];
}
function $t(t3, e2, n2, o2, i2) {
const r2 = t3[o2];
t3[o2] = t3[i2], t3[i2] = r2;
const s2 = 4 * o2, a2 = 4 * i2, c2 = e2[s2], l2 = e2[s2 + 1], h2 = e2[s2 + 2], d2 = e2[s2 + 3];
e2[s2] = e2[a2], e2[s2 + 1] = e2[a2 + 1], e2[s2 + 2] = e2[a2 + 2], e2[s2 + 3] = e2[a2 + 3], e2[a2] = c2, e2[a2 + 1] = l2, e2[a2 + 2] = h2, e2[a2 + 3] = d2;
const u2 = n2[o2];
n2[o2] = n2[i2], n2[i2] = u2;
}
function Yt(t3, e2) {
let n2 = t3 ^ e2, o2 = 65535 ^ n2, i2 = 65535 ^ (t3 | e2), r2 = t3 & (65535 ^ e2), s2 = n2 | o2 >> 1, a2 = n2 >> 1 ^ n2, c2 = i2 ^ i2 >> 1 ^ o2 & r2 >> 1, l2 = r2 ^ n2 & i2 >> 1 ^ r2 >> 1;
return n2 = s2 & s2 >> 2 ^ a2 & a2 >> 2, o2 = s2 & a2 >> 2 ^ a2 & (s2 ^ a2) >> 2, i2 = c2 ^ s2 & c2 >> 2 ^ a2 & l2 >> 2, r2 = l2 ^ a2 & c2 >> 2 ^ (s2 ^ a2) & l2 >> 2, s2 = n2 & n2 >> 4 ^ o2 & o2 >> 4, a2 = n2 & o2 >> 4 ^ o2 & (n2 ^ o2) >> 4, c2 = i2 ^ n2 & i2 >> 4 ^ o2 & r2 >> 4, l2 = r2 ^ o2 & i2 >> 4 ^ (n2 ^ o2) & r2 >> 4, i2 = c2 ^ s2 & c2 >> 8 ^ a2 & l2 >> 8, r2 = l2 ^ a2 & c2 >> 8 ^ (s2 ^ a2) & l2 >> 8, i2 ^= i2 >> 1, r2 ^= r2 >> 1, n2 = t3 ^ e2, o2 = r2 | 65535 ^ (n2 | i2), n2 = 16711935 & (n2 | n2 << 8), n2 = 252645135 & (n2 | n2 << 4), n2 = 858993459 & (n2 | n2 << 2), n2 = 1431655765 & (n2 | n2 << 1), o2 = 16711935 & (o2 | o2 << 8), o2 = 252645135 & (o2 | o2 << 4), o2 = 858993459 & (o2 | o2 << 2), o2 = 1431655765 & (o2 | o2 << 1), ((o2 << 1 | n2) >>> 0) - 2147483648;
}
var Xt = 0.0001;
var Wt = [{ facingDirection: "x-", dx: -1, dy: 0, startX: -0.5, startY: 0.5, endX: -0.5, endY: -0.5 }, { facingDirection: "x+", dx: 1, dy: 0, startX: 0.5, startY: 0.5, endX: 0.5, endY: -0.5 }, { facingDirection: "y-", dx: 0, dy: -1, startX: -0.5, startY: -0.5, endX: 0.5, endY: -0.5 }, { facingDirection: "y+", dx: 0, dy: 1, startX: 0.5, startY: 0.5, endX: -0.5, endY: 0.5 }];
var Vt = { "x-": Wt.find((t3) => t3.facingDirection === "x-"), "x+": Wt.find((t3) => t3.facingDirection === "x+"), "y-": Wt.find((t3) => t3.facingDirection === "y-"), "y+": Wt.find((t3) => t3.facingDirection === "y+") };
var Ht = { "x-": { x: -1, y: 0 }, "x+": { x: 1, y: 0 }, "y-": { x: 0, y: -1 }, "y+": { x: 0, y: 1 } };
var Gt = (t3, e2) => {
const { dir: n2, amt: o2 } = e2, i2 = Ht[n2];
return t3.map((t4) => ({ x: t4.x + i2.x * o2, y: t4.y + i2.y * o2 }));
};
var Ut = 0.0001;
function Zt(t3) {
const e2 = [];
for (const n2 of t3)
for (const t4 of Wt) {
let o2 = { x: n2.center.x + n2.width * t4.startX, y: n2.center.y + n2.height * t4.startY }, i2 = { x: n2.center.x + n2.width * t4.endX, y: n2.center.y + n2.height * t4.endY };
o2.x > i2.x && ([o2, i2] = [i2, o2]), Math.abs(o2.x - i2.x) < Ut && o2.y > i2.y && ([o2, i2] = [i2, o2]);
for (const r2 of n2.availableZ)
e2.push({ parent: n2, start: o2, end: i2, facingDirection: t4.facingDirection, z: r2 });
}
return e2;
}
var qt = class extends kt {
constructor(t3) {
super(), this.input = t3;
const e2 = this.input.targetMeshNodes ?? this.input.allMeshNodes, n2 = new Set(e2.map((t4) => t4.capacityMeshNodeId)), o2 = this.input.allMeshNodes.filter((t4) => !n2.has(t4.capacityMeshNodeId));
this.unprocessedEdges = Zt(e2), this.allEdges = [...this.unprocessedEdges, ...Zt(o2)], this.edgeSpatialIndex = new Ft(this.allEdges.length);
for (const t4 of this.allEdges)
this.edgeSpatialIndex.add(t4.start.x, t4.start.y, t4.end.x, t4.end.y);
this.edgeSpatialIndex.finish();
}
allEdges;
unprocessedEdges = [];
segmentsWithAdjacentEmptySpace = [];
edgeSpatialIndex;
lastCandidateEdge = null;
lastOverlappingEdges = null;
lastUncoveredSegments = null;
_step() {
if (this.unprocessedEdges.length === 0)
return this.solved = true, this.lastCandidateEdge = null, this.lastOverlappingEdges = null, void (this.lastUncoveredSegments = null);
const t3 = this.unprocessedEdges.shift();
this.lastCandidateEdge = t3;
const e2 = this.edgeSpatialIndex.search(t3.start.x - Ut, t3.start.y - Ut, t3.end.x + Ut, t3.end.y + Ut).map((t4) => this.allEdges[t4]).filter((e3) => e3.z === t3.z);
this.lastOverlappingEdges = e2;
const n2 = function(t4, e3) {
const n3 = Math.abs(t4.start.y - t4.end.y) < Xt, o2 = Math.abs(t4.start.x - t4.end.x) < Xt;
if (!n3 && !o2)
return [];
const i2 = n3 ? "x" : "y", r2 = n3 ? "y" : "x", s2 = t4.start[r2], a2 = t4.start[i2], c2 = t4.end[i2], l2 = Math.min(a2, c2), h2 = Math.max(a2, c2), d2 = (t5) => Math.max(l2, Math.min(h2, t5)), u2 = [];
for (const n4 of e3) {
if (n4 === t4)
continue;
const e4 = Math.abs(n4.start.y - n4.end.y) < Xt, o3 = Math.abs(n4.start.x - n4.end.x) < Xt;
if (i2 === "x" && !e4)
continue;
if (i2 === "y" && !o3)
continue;
if (Math.abs(n4.start[r2] - s2) > Xt)
continue;
const a3 = Math.min(n4.start[i2], n4.end[i2]), c3 = Math.max(n4.start[i2], n4.end[i2]), l3 = d2(a3), h3 = d2(c3);
h3 - l3 > Xt && u2.push({ s: l3, e: h3 });
}
if (u2.length === 0)
return [{ ...t4, start: { ...t4.start }, end: { ...t4.end } }];
u2.sort((t5, e4) => t5.s - e4.s);
const p2 = [];
for (const t5 of u2) {
const e4 = p2[p2.length - 1];
!e4 || t5.s > e4.e + Xt ? p2.push({ ...t5 }) : e4.e = Math.max(e4.e, t5.e);
}
const m2 = [];
let g2 = l2;
for (const t5 of p2)
if (t5.s > g2 + Xt && m2.push({ s: g2, e: t5.s }), g2 = Math.max(g2, t5.e), g2 >= h2 - Xt)
break;
return h2 > g2 + Xt && m2.push({ s: g2, e: h2 }), m2.length === 0 ? [] : m2.filter((t5) => t5.e - t5.s > Xt).map((e4) => {
const n4 = i2 === "x" ? { x: e4.s, y: s2 } : { x: s2, y: e4.s }, o3 = i2 === "x" ? { x: e4.e, y: s2 } : { x: s2, y: e4.e };
return { parent: t4.parent, facingDirection: t4.facingDirection, start: n4, end: o3, z: t4.z };
});
}(t3, e2);
this.lastUncoveredSegments = n2, this.segmentsWithAdjacentEmptySpace.push(...n2);
}
getOutput() {
return { segmentsWithAdjacentEmptySpace: this.segmentsWithAdjacentEmptySpace };
}
visualize() {
const t3 = { title: "FindSegmentsWithAdjacentEmptySpace", coordinateSystem: "cartesian", rects: [], points: [], lines: [], circles: [], infiniteLines: [], polygons: [], arrows: [], texts: [] };
for (const e2 of this.input.allMeshNodes)
t3.rects.push({ center: e2.center, width: e2.width, height: e2.height, stroke: "rgba(0, 0, 0, 0.1)" });
for (const e2 of this.unprocessedEdges)
t3.lines.push({ points: Gt([e2.start, e2.end], { dir: e2.facingDirection, amt: -0.1 }), strokeColor: "rgba(0, 0, 255, 0.5)", strokeDash: "5 5" });
for (const e2 of this.segmentsWithAdjacentEmptySpace)
t3.lines.push({ points: [e2.start, e2.end], strokeColor: "rgba(0,255,0, 0.5)" });
if (this.lastCandidateEdge && t3.lines.push({ points: [this.lastCandidateEdge.start, this.lastCandidateEdge.end], strokeColor: "blue" }), this.lastOverlappingEdges)
for (const e2 of this.lastOverlappingEdges)
t3.lines.push({ points: Gt([e2.start, e2.end], { dir: e2.facingDirection, amt: 0.05 }), strokeColor: "red", strokeDash: "2 2" });
if (this.lastUncoveredSegments)
for (const e2 of this.lastUncoveredSegments)
t3.lines.push({ points: Gt([e2.start, e2.end], { dir: e2.facingDirection, amt: -0.05 }), strokeColor: "green", strokeDash: "2 2" });
return t3;
}
};
function Jt(t3, e2, n2 = 0, o2 = t3.length - 1, i2 = Kt) {
for (;o2 > n2; ) {
if (o2 - n2 > 600) {
const r3 = o2 - n2 + 1, s3 = e2 - n2 + 1, a3 = Math.log(r3), c2 = 0.5 * Math.exp(2 * a3 / 3), l2 = 0.5 * Math.sqrt(a3 * c2 * (r3 - c2) / r3) * (s3 - r3 / 2 < 0 ? -1 : 1);
Jt(t3, e2, Math.max(n2, Math.floor(e2 - s3 * c2 / r3 + l2)), Math.min(o2, Math.floor(e2 + (r3 - s3) * c2 / r3 + l2)), i2);
}
const r2 = t3[e2];
let s2 = n2, a2 = o2;
for (Qt(t3, n2, e2), i2(t3[o2], r2) > 0 && Qt(t3, n2, o2);s2 < a2; ) {
for (Qt(t3, s2, a2), s2++, a2--;i2(t3[s2], r2) < 0; )
s2++;
for (;i2(t3[a2], r2) > 0; )
a2--;
}
i2(t3[n2], r2) === 0 ? Qt(t3, n2, a2) : (a2++, Qt(t3, a2, o2)), a2 <= e2 && (n2 = a2 + 1), e2 <= a2 && (o2 = a2 - 1);
}
}
function Qt(t3, e2, n2) {
const o2 = t3[e2];
t3[e2] = t3[n2], t3[n2] = o2;
}
function Kt(t3, e2) {
return t3 < e2 ? -1 : t3 > e2 ? 1 : 0;
}
var te = class {
constructor(t3 = 9) {
this._maxEntries = Math.max(4, t3), this._minEntries = Math.max(2, Math.ceil(0.4 * this._maxEntries)), this.clear();
}
all() {
return this._all(this.data, []);
}
search(t3) {
let e2 = this.data;
const n2 = [];
if (!ue(t3, e2))
return n2;
const o2 = this.toBBox, i2 = [];
for (;e2; ) {
for (let r2 = 0;r2 < e2.children.length; r2++) {
const s2 = e2.children[r2], a2 = e2.leaf ? o2(s2) : s2;
ue(t3, a2) && (e2.leaf ? n2.push(s2) : de(t3, a2) ? this._all(s2, n2) : i2.push(s2));
}
e2 = i2.pop();
}
return n2;
}
collides(t3) {
let e2 = this.data;
if (!ue(t3, e2))
return false;
const n2 = [];
for (;e2; ) {
for (let o2 = 0;o2 < e2.children.length; o2++) {
const i2 = e2.children[o2], r2 = e2.leaf ? this.toBBox(i2) : i2;
if (ue(t3, r2)) {
if (e2.leaf || de(t3, r2))
return true;
n2.push(i2);
}
}
e2 = n2.pop();
}
return false;
}
load(t3) {
if (!t3 || !t3.length)
return this;
if (t3.length < this._minEntries) {
for (let e3 = 0;e3 < t3.length; e3++)
this.insert(t3[e3]);
return this;
}
let e2 = this._build(t3.slice(), 0, t3.length - 1, 0);
if (this.data.children.length)
if (this.data.height === e2.height)
this._splitRoot(this.data, e2);
else {
if (this.data.height < e2.height) {
const t4 = this.data;
this.data = e2, e2 = t4;
}
this._insert(e2, this.data.height - e2.height - 1, true);
}
else
this.data = e2;
return this;
}
insert(t3) {
return t3 && this._insert(t3, this.data.height - 1), this;
}
clear() {
return this.data = pe([]), this;
}
remove(t3, e2) {
if (!t3)
return this;
let n2 = this.data;
const o2 = this.toBBox(t3), i2 = [], r2 = [];
let s2, a2, c2;
for (;n2 || i2.length; ) {
if (n2 || (n2 = i2.pop(), a2 = i2[i2.length - 1], s2 = r2.pop(), c2 = true), n2.leaf) {
const o3 = ee(t3, n2.children, e2);
if (o3 !== -1)
return n2.children.splice(o3, 1), i2.push(n2), this._condense(i2), this;
}
c2 || n2.leaf || !de(n2, o2) ? a2 ? (s2++, n2 = a2.children[s2], c2 = false) : n2 = null : (i2.push(n2), r2.push(s2), s2 = 0, a2 = n2, n2 = n2.children[0]);
}
return this;
}
toBBox(t3) {
return t3;
}
compareMinX(t3, e2) {
return t3.minX - e2.minX;
}
compareMinY(t3, e2) {
return t3.minY - e2.minY;
}
toJSON() {
return this.data;
}
fromJSON(t3) {
return this.data = t3, this;
}
_all(t3, e2) {
const n2 = [];
for (;t3; )
t3.leaf ? e2.push(...t3.children) : n2.push(...t3.children), t3 = n2.pop();
return e2;
}
_build(t3, e2, n2, o2) {
const i2 = n2 - e2 + 1;
let r2, s2 = this._maxEntries;
if (i2 <= s2)
return r2 = pe(t3.slice(e2, n2 + 1)), ne(r2, this.toBBox), r2;
o2 || (o2 = Math.ceil(Math.log(i2) / Math.log(s2)), s2 = Math.ceil(i2 / Math.pow(s2, o2 - 1))), r2 = pe([]), r2.leaf = false, r2.height = o2;
const a2 = Math.ceil(i2 / s2), c2 = a2 * Math.ceil(Math.sqrt(s2));
me(t3, e2, n2, c2, this.compareMinX);
for (let i3 = e2;i3 <= n2; i3 += c2) {
const e3 = Math.min(i3 + c2 - 1, n2);
me(t3, i3, e3, a2, this.compareMinY);
for (let n3 = i3;n3 <= e3; n3 += a2) {
const i4 = Math.min(n3 + a2 - 1, e3);
r2.children.push(this._build(t3, n3, i4, o2 - 1));
}
}
return ne(r2, this.toBBox), r2;
}
_chooseSubtree(t3, e2, n2, o2) {
for (;o2.push(e2), !e2.leaf && o2.length - 1 !== n2; ) {
let n3, o3 = 1 / 0, i2 = 1 / 0;
for (let r2 = 0;r2 < e2.children.length; r2++) {
const s2 = e2.children[r2], a2 = ae(s2), c2 = le(t3, s2) - a2;
c2 < i2 ? (i2 = c2, o3 = a2 < o3 ? a2 : o3, n3 = s2) : c2 === i2 && a2 < o3 && (o3 = a2, n3 = s2);
}
e2 = n3 || e2.children[0];
}
return e2;
}
_insert(t3, e2, n2) {
const o2 = n2 ? t3 : this.toBBox(t3), i2 = [], r2 = this._chooseSubtree(o2, this.data, e2, i2);
for (r2.children.push(t3), ie(r2, o2);e2 >= 0 && i2[e2].children.length > this._maxEntries; )
this._split(i2, e2), e2--;
this._adjustParentBBoxes(o2, i2, e2);
}
_split(t3, e2) {
const n2 = t3[e2], o2 = n2.children.length, i2 = this._minEntries;
this._chooseSplitAxis(n2, i2, o2);
const r2 = this._chooseSplitIndex(n2, i2, o2), s2 = pe(n2.children.splice(r2, n2.children.length - r2));
s2.height = n2.height, s2.leaf = n2.leaf, ne(n2, this.toBBox), ne(s2, this.toBBox), e2 ? t3[e2 - 1].children.push(s2) : this._splitRoot(n2, s2);
}
_splitRoot(t3, e2) {
this.data = pe([t3, e2]), this.data.height = t3.height + 1, this.data.leaf = false, ne(this.data, this.toBBox);
}
_chooseSplitIndex(t3, e2, n2) {
let o2, i2 = 1 / 0, r2 = 1 / 0;
for (let s2 = e2;s2 <= n2 - e2; s2++) {
const e3 = oe(t3, 0, s2, this.toBBox), a2 = oe(t3, s2, n2, this.toBBox), c2 = he(e3, a2), l2 = ae(e3) + ae(a2);
c2 < i2 ? (i2 = c2, o2 = s2, r2 = l2 < r2 ? l2 : r2) : c2 === i2 && l2 < r2 && (r2 = l2, o2 = s2);
}
return o2 || n2 - e2;
}
_chooseSplitAxis(t3, e2, n2) {
const o2 = t3.leaf ? this.compareMinX : re, i2 = t3.leaf ? this.compareMinY : se;
this._allDistMargin(t3, e2, n2, o2) < this._allDistMargin(t3, e2, n2, i2) && t3.children.sort(o2);
}
_allDistMargin(t3, e2, n2, o2) {
t3.children.sort(o2);
const i2 = this.toBBox, r2 = oe(t3, 0, e2, i2), s2 = oe(t3, n2 - e2, n2, i2);
let a2 = ce(r2) + ce(s2);
for (let o3 = e2;o3 < n2 - e2; o3++) {
const e3 = t3.children[o3];
ie(r2, t3.leaf ? i2(e3) : e3), a2 += ce(r2);
}
for (let o3 = n2 - e2 - 1;o3 >= e2; o3--) {
const e3 = t3.children[o3];
ie(s2, t3.leaf ? i2(e3) : e3), a2 += ce(s2);
}
return a2;
}
_adjustParentBBoxes(t3, e2, n2) {
for (let o2 = n2;o2 >= 0; o2--)
ie(e2[o2], t3);
}
_condense(t3) {
for (let e2, n2 = t3.length - 1;n2 >= 0; n2--)
t3[n2].children.length === 0 ? n2 > 0 ? (e2 = t3[n2 - 1].children, e2.splice(e2.indexOf(t3[n2]), 1)) : this.clear() : ne(t3[n2], this.toBBox);
}
};
function ee(t3, e2, n2) {
if (!n2)
return e2.indexOf(t3);
for (let o2 = 0;o2 < e2.length; o2++)
if (n2(t3, e2[o2]))
return o2;
return -1;
}
function ne(t3, e2) {
oe(t3, 0, t3.children.length, e2, t3);
}
function oe(t3, e2, n2, o2, i2) {
i2 || (i2 = pe(null)), i2.minX = 1 / 0, i2.minY = 1 / 0, i2.maxX = -1 / 0, i2.maxY = -1 / 0;
for (let r2 = e2;r2 < n2; r2++) {
const e3 = t3.children[r2];
ie(i2, t3.leaf ? o2(e3) : e3);
}
return i2;
}
function ie(t3, e2) {
return t3.minX = Math.min(t3.minX, e2.minX), t3.minY = Math.min(t3.minY, e2.minY), t3.maxX = Math.max(t3.maxX, e2.maxX), t3.maxY = Math.max(t3.maxY, e2.maxY), t3;
}
function re(t3, e2) {
return t3.minX - e2.minX;
}
function se(t3, e2) {
return t3.minY - e2.minY;
}
function ae(t3) {
return (t3.maxX - t3.minX) * (t3.maxY - t3.minY);
}
function ce(t3) {
return t3.maxX - t3.minX + (t3.maxY - t3.minY);
}
function le(t3, e2) {
return (Math.max(e2.maxX, t3.maxX) - Math.min(e2.minX, t3.minX)) * (Math.max(e2.maxY, t3.maxY) - Math.min(e2.minY, t3.minY));
}
function he(t3, e2) {
const n2 = Math.max(t3.minX, e2.minX), o2 = Math.max(t3.minY, e2.minY), i2 = Math.min(t3.maxX, e2.maxX), r2 = Math.min(t3.maxY, e2.maxY);
return Math.max(0, i2 - n2) * Math.max(0, r2 - o2);
}
function de(t3, e2) {
return t3.minX <= e2.minX && t3.minY <= e2.minY && e2.maxX <= t3.maxX && e2.maxY <= t3.maxY;
}
function ue(t3, e2) {
return e2.minX <= t3.maxX && e2.minY <= t3.maxY && e2.maxX >= t3.minX && e2.maxY >= t3.minY;
}
function pe(t3) {
return { children: t3, height: 1, leaf: true, minX: 1 / 0, minY: 1 / 0, maxX: -1 / 0, maxY: -1 / 0 };
}
function me(t3, e2, n2, o2, i2) {
const r2 = [e2, n2];
for (;r2.length; ) {
if ((n2 = r2.pop()) - (e2 = r2.pop()) <= o2)
continue;
const s2 = e2 + Math.ceil((n2 - e2) / o2 / 2) * o2;
Jt(t3, s2, e2, n2, i2), r2.push(e2, s2, s2, n2);
}
}
var ge = (t3) => ({ minX: Math.min(...t3.map((t4) => t4.x)), minY: Math.min(...t3.map((t4) => t4.y)), maxX: Math.max(...t3.map((t4) => t4.x)), maxY: Math.max(...t3.map((t4) => t4.y)) });
function fe(t3, e2, n2, o2) {
const i2 = ye(t3, e2, n2), r2 = ye(t3, e2, o2), s2 = ye(n2, o2, t3), a2 = ye(n2, o2, e2);
return i2 !== r2 && s2 !== a2 || (!(i2 !== 0 || !_e(t3, n2, e2)) || (!(r2 !== 0 || !_e(t3, o2, e2)) || (!(s2 !== 0 || !_e(n2, t3, o2)) || !(a2 !== 0 || !_e(n2, e2, o2)))));
}
function ye(t3, e2, n2) {
const o2 = (e2.y - t3.y) * (n2.x - e2.x) - (e2.x - t3.x) * (n2.y - e2.y);
return o2 === 0 ? 0 : o2 > 0 ? 1 : 2;
}
function _e(t3, e2, n2) {
return e2.x <= Math.max(t3.x, n2.x) && e2.x >= Math.min(t3.x, n2.x) && e2.y <= Math.max(t3.y, n2.y) && e2.y >= Math.min(t3.y, n2.y);
}
function be(t3, e2, n2) {
const o2 = (n2.x - e2.x) ** 2 + (n2.y - e2.y) ** 2;
if (o2 === 0)
return xe(t3, e2);
let i2 = ((t3.x - e2.x) * (n2.x - e2.x) + (t3.y - e2.y) * (n2.y - e2.y)) / o2;
i2 = Math.max(0, Math.min(1, i2));
return xe(t3, { x: e2.x + i2 * (n2.x - e2.x), y: e2.y + i2 * (n2.y - e2.y) });
}
function xe(t3, e2) {
const n2 = t3.x - e2.x, o2 = t3.y - e2.y;
return Math.sqrt(n2 * n2 + o2 * o2);
}
function ve(t3, e2, n2, o2) {
const i2 = e2.x - t3.x, r2 = e2.y - t3.y, s2 = o2.x - n2.x, a2 = o2.y - n2.y, c2 = t3.x - n2.x, l2 = t3.y - n2.y, h2 = i2 * a2 - r2 * s2;
if (Math.abs(h2) < 0.0000000001)
return null;
const d2 = (l2 * s2 - c2 * a2) / h2, u2 = (i2 * l2 - r2 * c2) / h2, p2 = 0.000000001;
if (d2 >= -1e-9 && d2 <= 1 + p2 && u2 >= -1e-9 && u2 <= 1 + p2) {
return { x: t3.x + d2 * i2, y: t3.y + d2 * r2 };
}
return null;
}
var Ie = (t3) => {
if ("minX" in t3)
return t3;
const e2 = t3.width / 2, n2 = t3.height / 2;
return { minX: t3.center.x - e2, minY: t3.center.y - n2, maxX: t3.center.x + e2, maxY: t3.center.y + n2 };
};
var Se = (t3) => [{ x: t3.minX, y: t3.minY }, { x: t3.maxX, y: t3.minY }, { x: t3.maxX, y: t3.maxY }, { x: t3.minX, y: t3.maxY }];
var Ce = (t3) => {
const e2 = [];
for (let n2 = 0;n2 < t3.length; n2++) {
const o2 = t3[n2], i2 = t3[(n2 + 1) % t3.length];
e2.push([o2, i2]);
}
return e2;
};
var Pe = (t3, e2, n2) => {
const o2 = (t3.y - e2.y) * (n2.x - e2.x) - (t3.x - e2.x) * (n2.y - e2.y);
if (Math.abs(o2) > 0.000000001)
return false;
const i2 = (t3.x - e2.x) * (n2.x - e2.x) + (t3.y - e2.y) * (n2.y - e2.y);
if (i2 < 0)
return false;
const r2 = (n2.x - e2.x) ** 2 + (n2.y - e2.y) ** 2;
return r2 !== 0 && !(i2 > r2);
};
var Me = (t3, e2) => t3.x >= e2.minX && t3.x <= e2.maxX && t3.y >= e2.minY && t3.y <= e2.maxY;
var Ne = (t3, e2) => {
if (e2.length < 3)
return false;
const n2 = Ce(e2);
for (const [e3, o3] of n2)
if (Pe(t3, e3, o3))
return true;
let o2 = false;
for (let n3 = 0, i2 = e2.length - 1;n3 < e2.length; i2 = n3++) {
const r2 = e2[n3].x, s2 = e2[n3].y, a2 = e2[i2].x, c2 = e2[i2].y;
s2 > t3.y != c2 > t3.y && t3.x < (a2 - r2) * (t3.y - s2) / (c2 - s2) + r2 && (o2 = !o2);
}
return o2;
};
var we = (t3, e2) => {
const n2 = Se(t3), o2 = [[n2[0], n2[1]], [n2[1], n2[2]], [n2[2], n2[3]], [n2[3], n2[0]]], i2 = Ce(e2);
for (const [t4, e3] of i2)
for (const [n3, i3] of o2)
if (fe(t4, e3, n3, i3))
return true;
return false;
};
var Te = (t3, e2) => ((t4, e3) => !(e3.length < 3) && (!!e3.some((e4) => Me(e4, t4)) || (!!Se(t4).some((t5) => Ne(t5, e3)) || we(t4, e3))))(Ie(t3), e2);
function Ee(t3) {
const e2 = t3.width / 2, n2 = t3.height / 2;
return { minX: t3.center.x - e2, maxX: t3.center.x + e2, minY: t3.center.y - n2, maxY: t3.center.y + n2 };
}
function Ae(t3, e2, n2) {
return Math.max(e2, Math.min(n2, t3));
}
function Oe(t3, e2, n2, o2) {
if (t3.x === e2.x && t3.y === e2.y)
return be(t3, n2, o2);
if (n2.x === o2.x && n2.y === o2.y)
return be(n2, t3, e2);
if (fe(t3, e2, n2, o2))
return 0;
const i2 = [be(t3, n2, o2), be(e2, n2, o2), be(n2, t3, e2), be(o2, t3, e2)];
return Math.min(...i2);
}
function ke(t3, e2, n2) {
const o2 = { x: n2.minX, y: n2.minY }, i2 = { x: n2.maxX, y: n2.minY }, r2 = { x: n2.minX, y: n2.maxY }, s2 = { x: n2.maxX, y: n2.maxY };
if (fe(t3, e2, o2, i2) || fe(t3, e2, i2, s2) || fe(t3, e2, s2, r2) || fe(t3, e2, r2, o2))
return 0;
if (t3.x >= n2.minX && t3.x <= n2.maxX && t3.y >= n2.minY && t3.y <= n2.maxY && e2.x >= n2.minX && e2.x <= n2.maxX && e2.y >= n2.minY && e2.y <= n2.maxY)
return 0;
const a2 = [be(o2, t3, e2), be(i2, t3, e2), be(r2, t3, e2), be(s2, t3, e2)];
if (t3.x >= n2.minX && t3.x <= n2.maxX && t3.y >= n2.minY && t3.y <= n2.maxY)
return 0;
if (e2.x >= n2.minX && e2.x <= n2.maxX && e2.y >= n2.minY && e2.y <= n2.maxY)
return 0;
if (t3.x < n2.minX || t3.x > n2.maxX || t3.y < n2.minY || t3.y > n2.maxY) {
const e3 = Ae(t3.x, n2.minX, n2.maxX), o3 = Ae(t3.y, n2.minY, n2.maxY);
a2.push(xe(t3, { x: e3, y: o3 }));
}
if (e2.x < n2.minX || e2.x > n2.maxX || e2.y < n2.minY || e2.y > n2.maxY) {
const t4 = Ae(e2.x, n2.minX, n2.maxX), o3 = Ae(e2.y, n2.minY, n2.maxY);
a2.push(xe(e2, { x: t4, y: o3 }));
}
return Math.min(...a2);
}
function De(t3, e2, n2) {
const o2 = n2.width / 2, i2 = n2.height / 2;
return ke(t3, e2, { minX: n2.center.x - o2, maxX: n2.center.x + o2, minY: n2.center.y - i2, maxY: n2.center.y + i2 });
}
function Le(t3, e2, n2) {
const o2 = { x: n2.x, y: n2.y };
if (t3.x === e2.x && t3.y === e2.y)
return Math.max(0, xe(t3, o2) - n2.radius);
const i2 = e2.x - t3.x, r2 = e2.y - t3.y, s2 = o2.x - t3.x, a2 = o2.y - t3.y, c2 = i2 * i2 + r2 * r2, l2 = Math.max(0, Math.min(1, (i2 * s2 + r2 * a2) / c2)), h2 = xe({ x: t3.x + l2 * i2, y: t3.y + l2 * r2 }, o2);
return Math.max(0, h2 - n2.radius);
}
function ze(t3, e2, n2) {
const o2 = n2.x - e2.x, i2 = n2.y - e2.y, r2 = o2 * o2 + i2 * i2;
if (r2 === 0)
return { x: e2.x, y: e2.y };
let s2 = ((t3.x - e2.x) * o2 + (t3.y - e2.y) * i2) / r2;
s2 = Math.max(0, Math.min(1, s2));
return { x: e2.x + s2 * o2, y: e2.y + s2 * i2 };
}
var Be = (t3, e2) => {
const n2 = e2.x - t3.x, o2 = e2.y - t3.y, i2 = Math.sqrt(n2 ** 2 + o2 ** 2);
return { x: n2 / i2, y: o2 / i2 };
};
function Fe(t3, e2) {
const n2 = e2.width / 2, o2 = e2.height / 2, i2 = e2.center.x - n2, r2 = e2.center.x + n2, s2 = e2.center.y - o2, a2 = e2.center.y + o2;
if (t3.x >= i2 && t3.x <= r2 && t3.y >= s2 && t3.y <= a2)
return 0;
return xe(t3, { x: Ae(t3.x, i2, r2), y: Ae(t3.y, s2, a2) });
}
function je(t3, e2) {
if (t3.x >= e2.minX && t3.x <= e2.maxX && t3.y >= e2.minY && t3.y <= e2.maxY)
return 0;
return xe(t3, { x: Ae(t3.x, e2.minX, e2.maxX), y: Ae(t3.y, e2.minY, e2.maxY) });
}
function $e(t3, e2) {
return { x: (t3.x + e2.x) / 2, y: (t3.y + e2.y) / 2 };
}
function Ye(t3, e2) {
const n2 = t3.x - e2.x, o2 = t3.y - e2.y;
return n2 * n2 + o2 * o2;
}
var Xe = (t3, e2) => !(t3.maxX < e2.minX || e2.maxX < t3.minX || t3.maxY < e2.minY || e2.maxY < t3.minY);
var We = (t3) => {
const { center: e2, width: n2, height: o2 } = t3, i2 = n2 / 2, r2 = o2 / 2;
return { minX: e2.x - i2, maxX: e2.x + i2, minY: e2.y - r2, maxY: e2.y + r2 };
};
var Ve = (t3) => {
if (t3.length === 0)
return null;
let e2 = t3[0].x, n2 = t3[0].y, o2 = t3[0].x, i2 = t3[0].y;
for (let r2 = 1;r2 < t3.length; r2++) {
const s2 = t3[r2];
s2.x < e2 && (e2 = s2.x), s2.y < n2 && (n2 = s2.y), s2.x > o2 && (o2 = s2.x), s2.y > i2 && (i2 = s2.y);
}
return { minX: e2, minY: n2, maxX: o2, maxY: i2 };
};
var He = 0.0001;
var Ge = class extends kt {
constructor(t3) {
super(), this.input = t3, this.unprocessedSegments = [...this.input.segmentsWithAdjacentEmptySpace], this.rectSpatialIndex = new te, this.rectSpatialIndex.load(this.input.boardVoid?.boardVoidRects.map((t4, e2) => ({ capacityMeshNodeId: `void-rect-${e2}`, center: { x: t4.x + t4.width / 2, y: t4.y + t4.height / 2 }, width: t4.width, height: t4.height, availableZ: Array.from({ length: this.input.boardVoid?.layerCount || 0 }, (t5, e3) => e3), layer: "void", minX: t4.x, minY: t4.y, maxX: t4.x + t4.width, maxY: t4.y + t4.height })) || []), this.rectSpatialIndex.load(this.input.inputMeshNodes.map((t4) => ({ ...t4, minX: t4.center.x - t4.width / 2, minY: t4.center.y - t4.height / 2, maxX: t4.center.x + t4.width / 2, maxY: t4.center.y + t4.height / 2 })));
}
unprocessedSegments = [];
expandedSegments = [];
lastSegment = null;
lastSearchBounds = null;
lastCollidingNodes = null;
lastSearchCorner1 = null;
lastSearchCorner2 = null;
lastExpandedSegment = null;
rectSpatialIndex;
_step() {
if (this.unprocessedSegments.length === 0)
return void (this.solved = true);
const t3 = this.unprocessedSegments.shift();
this.lastSegment = t3;
const { dx: e2, dy: n2 } = Vt[t3.facingDirection], o2 = t3.end.x - t3.start.x, i2 = t3.end.y - t3.start.y, r2 = Math.sqrt(o2 ** 2 + i2 ** 2), s2 = o2 / r2, a2 = i2 / r2;
let c2 = null, l2 = 1;
const h2 = { x: t3.start.x + e2 * He + s2 * He * 10, y: t3.start.y + n2 * He + a2 * He * 10 }, d2 = { x: t3.end.x + e2 * He - s2 * He * 10, y: t3.end.y + n2 * He - a2 * He * 10 };
for (this.lastSearchCorner1 = h2, this.lastSearchCorner2 = d2;(!c2 || c2.length === 0) && l2 < 1000; ) {
const o3 = ge([h2, d2, { x: h2.x + e2 * l2, y: h2.y + n2 * l2 }, { x: d2.x + e2 * l2, y: d2.y + n2 * l2 }]);
this.lastSearchBounds = o3, c2 = this.rectSpatialIndex.search(o3).filter((e3) => e3.availableZ.includes(t3.z)).filter((e3) => e3.capacityMeshNodeId !== t3.parent.capacityMeshNodeId), l2 *= 4;
}
if (!c2 || c2.length === 0)
return;
this.lastCollidingNodes = c2;
let u2 = 1 / 0;
for (const e3 of c2) {
const n3 = De(t3.start, t3.end, e3);
n3 < u2 && (u2 = n3);
}
const p2 = u2, m2 = ge([t3.start, t3.end, { x: t3.start.x + e2 * p2, y: t3.start.y + n2 * p2 }, { x: t3.end.x + e2 * p2, y: t3.end.y + n2 * p2 }]), g2 = { x: (m2.minX + m2.maxX) / 2, y: (m2.minY + m2.maxY) / 2 }, f2 = m2.maxX - m2.minX, y2 = m2.maxY - m2.minY, _2 = { segment: t3, newNode: { capacityMeshNodeId: `new-${t3.parent.capacityMeshNodeId}-${this.expandedSegments.length}`, center: g2, width: f2, height: y2, availableZ: [t3.z], layer: t3.parent.layer } };
this.lastExpandedSegment = _2, f2 < He || y2 < He || (this.expandedSegments.push(_2), this.rectSpatialIndex.insert({ ..._2.newNode, ...m2 }));
}
getOutput() {
return { expandedSegments: this.expandedSegments };
}
visualize() {
const t3 = { title: "ExpandEdgesToEmptySpace", coordinateSystem: "cartesian", rects: [], points: [], lines: [], circles: [], infiniteLines: [], polygons: [], arrows: [], texts: [] };
for (const e2 of this.input.inputMeshNodes)
t3.rects.push({ center: e2.center, width: e2.width, height: e2.height, stroke: "rgba(0, 0, 0, 0.1)", layer: `z${e2.availableZ.join(",")}`, label: [`node ${e2.capacityMeshNodeId}`, `z:${e2.availableZ.join(",")}`].join(`
`) });
for (const { newNode: e2 } of this.expandedSegments)
t3.rects.push({ center: e2.center, width: e2.width, height: e2.height, fill: "green", label: `expandedSegment (z=${e2.availableZ.join(",")})`, layer: `z${e2.availableZ.join(",")}` });
if (this.lastSegment && t3.lines.push({ points: [this.lastSegment.start, this.lastSegment.end], strokeColor: "rgba(0, 0, 255, 0.5)" }), this.lastSearchBounds && t3.rects.push({ center: { x: (this.lastSearchBounds.minX + this.lastSearchBounds.maxX) / 2, y: (this.lastSearchBounds.minY + this.lastSearchBounds.maxY) / 2 }, width: this.lastSearchBounds.maxX - this.lastSearchBounds.minX, height: this.lastSearchBounds.maxY - this.lastSearchBounds.minY, fill: "rgba(0, 0, 255, 0.25)" }), this.lastSearchCorner1 && this.lastSearchCorner2 && (t3.points.push({ x: this.lastSearchCorner1.x, y: this.lastSearchCorner1.y, color: "rgba(0, 0, 255, 0.5)", label: ["searchCorner1", `z=${this.lastSegment?.z}`].join(`
`) }), t3.points.push({ x: this.lastSearchCorner2.x, y: this.lastSearchCorner2.y, color: "rgba(0, 0, 255, 0.5)", label: ["searchCorner2", `z=${this.lastSegment?.z}`].join(`
`) })), this.lastExpandedSegment && t3.rects.push({ center: this.lastExpandedSegment.newNode.center, width: this.lastExpandedSegment.newNode.width, height: this.lastExpandedSegment.newNode.height, fill: "purple", label: `expandedSegment (z=${this.lastExpandedSegment.segment.z})` }), this.lastCollidingNodes)
for (const e2 of this.lastCollidingNodes)
t3.rects.push({ center: e2.center, width: e2.width, height: e2.height, fill: "rgba(255, 0, 0, 0.5)" });
return t3;
}
};
var Ue = class extends Lt {
findSegmentsWithAdjacentEmptySpaceSolver;
expandEdgesToEmptySpaceSolver;
outputNodes = [];
passExpandedCounts = [];
currentPassNodes = [];
currentTargetNodes = [];
currentPassIndex = 0;
expandedNodeIds = new Set;
maxGapFillPasses = 1;
pipelineDef = [Dt("findSegmentsWithAdjacentEmptySpaceSolver", qt, (t3) => [{ allMeshNodes: t3.currentPassNodes, targetMeshNodes: t3.currentTargetNodes }], { onSolved: () => {} }), Dt("expandEdgesToEmptySpaceSolver", Ge, (t3) => [{ inputMeshNodes: t3.currentPassNodes, segmentsWithAdjacentEmptySpace: t3.findSegmentsWithAdjacentEmptySpaceSolver.getOutput().segmentsWithAdjacentEmptySpace, boardVoid: t3.inputProblem.boardVoid }], { onSolved: (t3) => {
t3.completePass();
} })];
_setup() {
this.outputNodes = [...this.inputProblem.meshNodes], this.currentPassNodes = [...this.inputProblem.meshNodes], this.currentTargetNodes = [...this.inputProblem.meshNodes], this.passExpandedCounts = [], this.currentPassIndex = 0, this.expandedNodeIds.clear();
const t3 = this.inputProblem.maxGapFillPasses;
this.maxGapFillPasses = Number.isFinite(t3) ? Math.max(1, Math.floor(t3)) : 1;
}
completePass() {
const t3 = (this.expandEdgesToEmptySpaceSolver?.getOutput().expandedSegments ?? []).map((t4) => t4.newNode);
for (const e2 of t3)
this.expandedNodeIds.add(e2.capacityMeshNodeId);
this.passExpandedCounts.push(t3.length), this.currentPassNodes = [...this.currentPassNodes, ...t3], this.currentTargetNodes = t3, this.outputNodes = this.currentPassNodes, t3.length === 0 || this.currentPassIndex + 1 >= this.maxGapFillPasses || (this.currentPassIndex += 1, this.currentPipelineStageIndex = -1);
}
getOutput() {
return { outputNodes: this.outputNodes.length ? this.outputNodes : this.inputProblem.meshNodes };
}
initialVisualize() {
const t3 = { title: "GapFillSolverPipeline - Initial", coordinateSystem: "cartesian", rects: [], points: [], lines: [], circles: [], infiniteLines: [], polygons: [], arrows: [], texts: [] };
for (const e2 of this.inputProblem.meshNodes)
t3.rects.push({ center: e2.center, width: e2.width, height: e2.height, stroke: "rgba(0, 0, 0, 0.3)", fill: "rgba(100, 100, 100, 0.1)", layer: `z${e2.availableZ.join(",")}`, label: [`node ${e2.capacityMeshNodeId}`, `z:${e2.availableZ.join(",")}`].join(`
`) });
return t3;
}
finalVisualize() {
const t3 = { title: "GapFillSolverPipeline - Final", coordinateSystem: "cartesian", rects: [], points: [], lines: [], circles: [], infiniteLines: [], polygons: [], arrows: [], texts: [] }, { outputNodes: e2 } = this.getOutput();
for (const n2 of e2) {
const e3 = this.expandedNodeIds.has(n2.capacityMeshNodeId);
t3.rects.push({ center: n2.center, width: n2.width, height: n2.height, stroke: e3 ? "rgba(0, 128, 0, 0.8)" : "rgba(0, 0, 0, 0.3)", fill: e3 ? "rgba(0, 200, 0, 0.3)" : "rgba(100, 100, 100, 0.1)", layer: `z${n2.availableZ.join(",")}`, label: [`${e3 ? "[expanded] " : ""}node ${n2.capacityMeshNodeId}`, `z:${n2.availableZ.join(",")}`].join(`
`) });
}
return t3;
}
};
function Ze(t3) {
const e2 = t3.toLowerCase();
if (e2 === "top")
return -1e6;
if (e2 === "bottom")
return 1e6;
const n2 = /^inner(\d+)$/i.exec(e2);
return n2 ? parseInt(n2[1], 10) || 0 : 100 + e2.charCodeAt(0);
}
function qe(t3) {
const e2 = function(t4) {
return Array.from(new Set(t4)).sort((t5, e3) => {
const n3 = Ze(t5), o3 = Ze(e3);
return n3 !== o3 ? n3 - o3 : t5.localeCompare(e3);
});
}((t3.obstacles ?? []).flatMap((t4) => t4.layers ?? [])), n2 = Math.max(1, t3.layerCount || e2.length || 1), o2 = Array.from({ length: n2 }, (t4, e3) => e3 === 0 ? "top" : e3 === n2 - 1 ? "bottom" : `inner${e3}`), i2 = [], r2 = new Set, s2 = (t4) => {
const e3 = t4.toLowerCase();
r2.has(e3) || (r2.add(e3), i2.push(t4));
};
o2.forEach(s2), e2.forEach(s2);
const a2 = i2.slice(0, n2), c2 = new Map;
return a2.forEach((t4, e3) => c2.set(t4.toLowerCase(), e3)), i2.slice(a2.length).forEach((t4) => {
const e3 = t4.toLowerCase();
c2.set(e3, ((t5) => {
if (a2.length <= 1)
return 0;
if (t5 === "top")
return 0;
if (t5 === "bottom")
return a2.length - 1;
const e4 = /^inner(\d+)$/i.exec(t5);
if (e4) {
if (a2.length <= 2)
return a2.length - 1;
const t6 = parseInt(e4[1], 10), n3 = a2.length - 2;
return Math.min(n3, Math.max(1, Number.isFinite(t6) ? t6 : 1));
}
return 0;
})(e3));
}), { layerNames: a2, zIndexByName: c2 };
}
function Je(t3, e2) {
if (t3.zLayers?.length)
return Array.from(new Set(t3.zLayers)).sort((t4, e3) => t4 - e3);
const n2 = (t3.layers ?? []).map((t4) => e2.get(t4.toLowerCase())).filter((t4) => typeof t4 == "number");
return Array.from(new Set(n2)).sort((t4, e3) => t4 - e3);
}
function Qe(t3) {
const { width: e2, height: n2 } = t3;
return typeof e2 != "number" || typeof n2 != "number" ? null : { x: t3.center.x - e2 / 2, y: t3.center.y - n2 / 2, width: e2, height: n2 };
}
var Ke = (t3) => {
const e2 = [{ fill: "#dbeafe", stroke: "#3b82f6" }, { fill: "#fef3c7", stroke: "#f59e0b" }, { fill: "#d1fae5", stroke: "#10b981" }, { fill: "#e9d5ff", stroke: "#a855f7" }, { fill: "#fed7aa", stroke: "#f97316" }, { fill: "#fecaca", stroke: "#ef4444" }];
return e2[Math.min(...t3) % e2.length];
};
var tn = 0.000000001;
var en = (t3, e2) => t3 > e2 + tn;
var nn = (t3, e2) => t3 > e2 - tn;
var on = (t3, e2) => t3 < e2 - tn;
var rn = (t3, e2) => t3 < e2 + tn;
function sn(t3, e2) {
return !(t3.x + t3.width <= e2.x + tn || e2.x + e2.width <= t3.x + tn || t3.y + t3.height <= e2.y + tn || e2.y + e2.height <= t3.y + tn);
}
function an(t3, e2) {
const n2 = e2.x, o2 = e2.x + e2.width, i2 = e2.y, r2 = e2.y + e2.height;
if (t3.x >= n2 && t3.x <= o2 && t3.y >= i2 && t3.y <= r2)
return Math.min(t3.x - n2, o2 - t3.x, t3.y - i2, r2 - t3.y);
const s2 = t3.x < n2 ? n2 - t3.x : t3.x > o2 ? t3.x - o2 : 0, a2 = t3.y < i2 ? i2 - t3.y : t3.y > r2 ? t3.y - r2 : 0;
return s2 === 0 ? a2 : a2 === 0 ? s2 : Math.hypot(s2, a2);
}
function cn(t3, e2) {
const n2 = Math.max(t3[0], e2[0]), o2 = Math.min(t3[1], e2[1]);
return o2 > n2 + tn ? [n2, o2] : null;
}
function ln(t3, e2) {
if (!sn(t3, e2))
return [t3];
const n2 = cn([t3.x, t3.x + t3.width], [e2.x, e2.x + e2.width]), o2 = cn([t3.y, t3.y + t3.height], [e2.y, e2.y + e2.height]);
if (!n2 || !o2)
return [t3];
const [i2, r2] = n2, [s2, a2] = o2, c2 = [];
i2 > t3.x + tn && c2.push({ x: t3.x, y: t3.y, width: i2 - t3.x, height: t3.height }), t3.x + t3.width > r2 + tn && c2.push({ x: r2, y: t3.y, width: t3.x + t3.width - r2, height: t3.height });
const l2 = Math.max(0, r2 - i2);
return l2 > tn && s2 > t3.y + tn && c2.push({ x: i2, y: t3.y, width: l2, height: s2 - t3.y }), l2 > tn && t3.y + t3.height > a2 + tn && c2.push({ x: i2, y: a2, width: l2, height: t3.y + t3.height - a2 }), c2.filter((t4) => t4.width > tn && t4.height > tn);
}
var hn = (t3, e2) => !e2 || e2 <= 0 ? t3 : { x: t3.x - e2, y: t3.y - e2, width: t3.width + 2 * e2, height: t3.height + 2 * e2 };
var dn = (t3) => ({ x: t3.center.x - t3.width / 2, y: t3.center.y - t3.height / 2, width: t3.width, height: t3.height });
var un = (t3) => t3.width * t3.height;
var pn = (t3) => ({ ...t3, center: { ...t3.center }, availableZ: [...t3.availableZ] });
var mn = (t3, e2, n2) => ({ ...t3, capacityMeshNodeId: n2, center: { x: e2.x + e2.width / 2, y: e2.y + e2.height / 2 }, width: e2.width, height: e2.height, availableZ: [...t3.availableZ], layer: `z${t3.availableZ.join(",")}` });
var gn = (t3) => !t3._containsObstacle && !t3._containsTarget;
var fn = (t3, e2) => t3.availableZ.length === 1 && t3.availableZ[0] === e2;
var yn = (t3, e2) => Math.abs(t3.x - e2.x) <= tn && Math.abs(t3.y - e2.y) <= tn && Math.abs(t3.width - e2.width) <= tn && Math.abs(t3.height - e2.height) <= tn;
var _n = (t3, e2) => {
let n2 = [t3];
for (const t4 of e2) {
if (n2.length === 0)
return n2;
const e3 = [];
for (const o2 of n2)
e3.push(...ln(o2, t4));
n2 = e3;
}
return n2;
};
var bn = (t3, e2) => _n(t3, e2).length === 0;
var xn = class extends kt {
constructor(t3) {
super(), this.input = t3;
}
outputNodes = [];
promotedNodeIds = new Set;
residualNodeIds = new Set;
_setup() {
this.outputNodes = this.input.meshNodes.map(pn), this.promotedNodeIds.clear(), this.residualNodeIds.clear();
}
_step() {
this.outputNodes = this.processOuterLayerContainmentMerges(), this.solved = true;
}
processOuterLayerContainmentMerges() {
const t3 = this.input.simpleRouteJson, e2 = Math.max(1, t3.layerCount || 1);
if (e2 < 3)
return this.input.meshNodes.map(pn);
const n2 = e2 - 1, o2 = Math.max(t3.minViaDiameter ?? 0, t3.minTraceWidth || 0), i2 = this.input.meshNodes.map(pn), r2 = this.buildObstaclesByLayer(e2);
if (!r2.slice(1, -1).some((t4) => t4.some((t5) => t5.obstacle.isCopperPour)))
return i2;
const s2 = i2.filter((t4) => gn(t4) && (fn(t4, 0) || fn(t4, n2))), a2 = i2.filter((t4) => !gn(t4)), c2 = new Map;
c2.set(0, i2.filter((t4) => gn(t4) && t4.availableZ.includes(0))), c2.set(n2, i2.filter((t4) => gn(t4) && t4.availableZ.includes(n2)));
const l2 = [], h2 = [], d2 = s2.filter((t4) => t4.width + tn >= o2 && t4.height + tn >= o2).sort((t4, e3) => un(dn(e3)) - un(dn(t4)));
for (const t4 of d2) {
const e3 = t4.availableZ[0], i3 = e3 === 0 ? n2 : 0, s3 = dn(t4), a3 = (c2.get(i3) ?? []).filter((t5) => sn(s3, dn(t5))), d3 = a3[0]?.availableZ;
if (!d3)
continue;
if (h2.some((t5) => sn(s3, t5)))
continue;
if (!this.isTransitCompatibleAcrossIntermediateLayers({ rect: s3, fromZ: e3, toZ: i3, obstaclesByLayer: r2 }))
continue;
if (!bn(s3, a3.map(dn)))
continue;
const u3 = a3.every((t5) => t5.availableZ.length === d3.length && t5.availableZ.every((t6) => d3.includes(t6))) ? [{ rect: s3, availableZ: d3 }] : a3.map((t5) => {
const e4 = dn(t5), n3 = Math.max(s3.x, e4.x), o3 = Math.max(s3.y, e4.y);
return { rect: { x: n3, y: o3, width: Math.min(s3.x + s3.width, e4.x + e4.width) - n3, height: Math.min(s3.y + s3.height, e4.y + e4.height) - o3 }, availableZ: t5.availableZ };
});
for (const [n3, i4] of u3.entries()) {
if (i4.rect.width + tn < o2 || i4.rect.height + tn < o2)
continue;
const r3 = [...new Set([e3, ...i4.availableZ])].sort((t5, e4) => t5 - e4), s4 = n3 === 0 ? t4.capacityMeshNodeId : `${t4.capacityMeshNodeId}-outer-support-${n3}`;
l2.push(mn({ ...t4, availableZ: r3 }, i4.rect, s4)), h2.push(i4.rect), this.promotedNodeIds.add(s4);
}
}
if (l2.length === 0)
return i2;
let u2 = 0;
const p2 = [];
for (const t4 of i2.filter(gn)) {
const e3 = dn(t4);
if (t4.availableZ.filter((t5) => t5 === 0 || t5 === n2).length === 0) {
p2.push(t4);
continue;
}
const o3 = _n(e3, h2);
if (o3.length === 1 && yn(o3[0], e3))
p2.push(t4);
else
for (const e4 of o3) {
const n3 = mn(t4, e4, `${t4.capacityMeshNodeId}-outer-merge-${u2++}`);
p2.push(n3), this.residualNodeIds.add(n3.capacityMeshNodeId);
}
}
return [...a2, ...l2, ...p2];
}
buildObstaclesByLayer(t3) {
const e2 = Array.from({ length: t3 }, () => []);
for (const n2 of this.input.simpleRouteJson.obstacles ?? []) {
const o2 = Qe(n2);
if (!o2)
continue;
const i2 = hn(o2, this.input.obstacleClearance ?? 0), r2 = Je(n2, this.input.zIndexByName);
for (const o3 of r2)
o3 < 0 || o3 >= t3 || e2[o3].push({ obstacle: n2, rect: i2 });
}
return e2;
}
isTransitCompatibleAcrossIntermediateLayers(t3) {
const { rect: e2, fromZ: n2, toZ: o2, obstaclesByLayer: i2 } = t3, r2 = Math.min(n2, o2), s2 = Math.max(n2, o2);
if (s2 - r2 < 2)
return false;
let a2 = false;
for (let t4 = r2 + 1;t4 < s2; t4++) {
const n3 = (i2[t4] ?? []).filter((t5) => sn(t5.rect, e2));
if (n3.length === 0)
continue;
if (n3.some((t5) => !t5.obstacle.isCopperPour))
return false;
if (!bn(e2, n3.map((t5) => t5.rect)))
return false;
a2 = true;
}
return a2;
}
getOutput() {
return { outputNodes: this.outputNodes };
}
visualize() {
return { title: "OuterLayerContainmentMergeSolver", coordinateSystem: "cartesian", rects: this.outputNodes.map((t3) => {
const e2 = Ke(t3.availableZ), n2 = this.promotedNodeIds.has(t3.capacityMeshNodeId), o2 = this.residualNodeIds.has(t3.capacityMeshNodeId);
return { center: t3.center, width: t3.width, height: t3.height, stroke: n2 ? "rgba(22, 163, 74, 0.95)" : o2 ? "rgba(37, 99, 235, 0.95)" : e2.stroke, fill: t3._containsObstacle ? "rgba(239, 68, 68, 0.35)" : n2 ? "rgba(34, 197, 94, 0.28)" : o2 ? "rgba(59, 130, 246, 0.18)" : e2.fill, layer: `z${t3.availableZ.join(",")}`, label: [`node ${t3.capacityMeshNodeId}`, `z:${t3.availableZ.join(",")}`].join(`
`) };
}), points: [], lines: [], texts: [] };
}
};
var vn = 0.000000001;
var In = (t3) => Math.abs(t3.rect.x + t3.rect.width / 2 - t3.startX) < vn && Math.abs(t3.rect.y + t3.rect.height / 2 - t3.startY) < vn && Math.abs(t3.rect.width - t3.initialW) < vn && Math.abs(t3.rect.height - t3.initialH) < vn;
var Sn = ({ rect: t3, bounds: e2 }) => ({ x: t3.x, y: t3.y, width: e2.x + e2.width - t3.x, height: t3.height });
var Cn = ({ rect: t3, bounds: e2 }) => ({ x: t3.x, y: t3.y, width: t3.width, height: e2.y + e2.height - t3.y });
var Pn = ({ rect: t3, bounds: e2 }) => ({ x: e2.x, y: t3.y, width: t3.x - e2.x, height: t3.height });
var Mn = ({ rect: t3, bounds: e2 }) => ({ x: t3.x, y: e2.y, width: t3.width, height: t3.y - e2.y });
var Nn = (t3, e2 = 0.000001) => Math.round(t3 / e2) * e2;
var wn = (t3) => ({ x: Nn(t3.x), y: Nn(t3.y), width: Nn(t3.width), height: Nn(t3.height) });
function Tn(t3) {
const { r: e2, bounds: n2, blockers: o2, maxAspect: i2 } = t3;
let r2 = n2.x + n2.width - e2.x;
for (const t4 of o2) {
if (e2.y + e2.height > t4.y + tn && t4.y + t4.height > e2.y + tn) {
if (nn(t4.x, e2.x + e2.width))
r2 = Math.min(r2, t4.x - e2.x);
else if (t4.x + t4.width > e2.x + e2.width - tn && t4.x < e2.x + e2.width + tn)
return 0;
}
}
let s2 = Math.max(0, r2 - e2.width);
if (s2 <= 0)
return 0;
if (i2 != null) {
const { width: t4, height: n3 } = e2;
t4 >= n3 && (s2 = Math.min(s2, i2 * n3 - t4));
}
return Math.max(0, s2);
}
function Rn(t3) {
const { r: e2, bounds: n2, blockers: o2, maxAspect: i2 } = t3;
let r2 = n2.y + n2.height - e2.y;
for (const t4 of o2) {
if (e2.x + e2.width > t4.x + tn && t4.x + t4.width > e2.x + tn) {
if (nn(t4.y, e2.y + e2.height))
r2 = Math.min(r2, t4.y - e2.y);
else if (t4.y + t4.height > e2.y + e2.height - tn && t4.y < e2.y + e2.height + tn)
return 0;
}
}
let s2 = Math.max(0, r2 - e2.height);
if (s2 <= 0)
return 0;
if (i2 != null) {
const { width: t4, height: n3 } = e2;
n3 >= t4 && (s2 = Math.min(s2, i2 * t4 - n3));
}
return Math.max(0, s2);
}
function En(t3) {
const { r: e2, bounds: n2, blockers: o2, maxAspect: i2 } = t3;
let r2 = n2.x;
for (const t4 of o2) {
if (e2.y + e2.height > t4.y + tn && t4.y + t4.height > e2.y + tn) {
if (rn(t4.x + t4.width, e2.x))
r2 = Math.max(r2, t4.x + t4.width);
else if (t4.x < e2.x + tn && t4.x + t4.width > e2.x - tn)
return 0;
}
}
let s2 = Math.max(0, e2.x - r2);
if (s2 <= 0)
return 0;
if (i2 != null) {
const { width: t4, height: n3 } = e2;
t4 >= n3 && (s2 = Math.min(s2, i2 * n3 - t4));
}
return Math.max(0, s2);
}
function An(t3) {
const { r: e2, bounds: n2, blockers: o2, maxAspect: i2 } = t3;
let r2 = n2.y;
for (const t4 of o2) {
if (e2.x + e2.width > t4.x + tn && t4.x + t4.width > e2.x + tn) {
if (rn(t4.y + t4.height, e2.y))
r2 = Math.max(r2, t4.y + t4.height);
else if (t4.y < e2.y + tn && t4.y + t4.height > e2.y - tn)
return 0;
}
}
let s2 = Math.max(0, e2.y - r2);
if (s2 <= 0)
return 0;
if (i2 != null) {
const { width: t4, height: n3 } = e2;
n3 >= t4 && (s2 = Math.min(s2, i2 * t4 - n3));
}
return Math.max(0, s2);
}
var On = (t3) => {
const { rect: e2, seen: n2, blockers: o2 } = t3;
n2.has(e2) || (n2.add(e2), o2.push(e2));
};
function kn(t3) {
const { startX: e2, startY: n2, gridSize: o2, bounds: i2, obsticalIndexByLayer: r2, placedIndexByLayer: s2, initialCellRatio: a2, maxAspectRatio: c2, minReq: l2 } = t3, h2 = Math.max(0.000000001, o2 * a2), d2 = Math.max(h2, l2.width), u2 = Math.max(h2, l2.height), p2 = [], m2 = new Set, g2 = s2.length, f2 = (o3) => {
const a3 = ((t4) => {
const { bounds: e3, rect: n3 } = t4, o4 = Math.max(e3.x, n3.x), i3 = Math.max(e3.y, n3.y), r3 = Math.min(e3.x + e3.width, n3.x + n3.width), s3 = Math.min(e3.y + e3.height, n3.y + n3.height);
return r3 <= o4 + tn || s3 <= i3 + tn ? null : { minX: o4, minY: i3, maxX: r3, maxY: s3 };
})({ bounds: i2, rect: o3 });
if (a3)
for (const o4 of t3.zLayers) {
const t4 = r2[o4];
if (t4)
for (const e3 of t4.search(a3))
On({ rect: e3, seen: m2, blockers: p2 });
const i3 = s2[o4];
if (i3)
for (const t5 of i3.search(a3)) {
t5.zLayers.length >= g2 && (In({ rect: t5, startX: e2, startY: n2, initialW: d2, initialH: u2 }) || On({ rect: t5, seen: m2, blockers: p2 }));
}
}
}, y2 = [{ ox: 0, oy: 0 }, { ox: -d2, oy: 0 }, { ox: 0, oy: -u2 }, { ox: -d2, oy: -u2 }, { ox: -d2 / 2, oy: -u2 / 2 }];
let _2 = null, b2 = 0;
t:
for (const t4 of y2) {
let o3 = { x: e2 + t4.ox, y: n2 + t4.oy, width: d2, height: u2 };
if (f2(o3), on(o3.x, i2.x) || on(o3.y, i2.y) || en(o3.x + o3.width, i2.x + i2.width) || en(o3.y + o3.height, i2.y + i2.height))
continue;
for (const t5 of p2)
if (sn(o3, t5))
continue t;
const r3 = 0.000001, s3 = 1000;
let a3 = true, h3 = 0;
for (;a3 && h3 < s3; ) {
h3++, a3 = false;
const t5 = { bounds: i2, blockers: p2, maxAspect: c2 };
f2(Sn({ rect: o3, bounds: i2 }));
const e3 = Tn({ ...t5, r: o3 });
e3 > r3 && (o3 = { ...o3, width: o3.width + e3 }, f2(o3), a3 = true), f2(Cn({ rect: o3, bounds: i2 }));
const n3 = Rn({ ...t5, r: o3 });
n3 > r3 && (o3 = { ...o3, height: o3.height + n3 }, f2(o3), a3 = true), f2(Pn({ rect: o3, bounds: i2 }));
const s4 = En({ ...t5, r: o3 });
s4 > r3 && (o3 = { x: o3.x - s4, y: o3.y, width: o3.width + s4, height: o3.height }, f2(o3), a3 = true), f2(Mn({ rect: o3, bounds: i2 }));
const l3 = An({ ...t5, r: o3 });
l3 > r3 && (o3 = { x: o3.x, y: o3.y - l3, width: o3.width, height: o3.height + l3 }, f2(o3), a3 = true);
}
if (o3.width + tn >= l2.width && o3.height + tn >= l2.height) {
const t5 = o3.width * o3.height;
t5 > b2 && (_2 = wn(o3), b2 = t5);
}
}
return _2;
}
function Dn(t3) {
const e2 = Math.max(t3.width, t3.height);
return [e2 / 8, e2 / 16, e2 / 32];
}
function Ln(t3) {
const e2 = { minX: t3.point.x, minY: t3.point.y, maxX: t3.point.x, maxY: t3.point.y };
for (let n2 = 0;n2 < t3.layerCount; n2++) {
const o2 = t3.obstacleIndexByLayer[n2], i2 = !!o2 && o2.collides(e2), r2 = t3.placedIndexByLayer[n2], s2 = !!r2 && r2.collides(e2);
if (!i2 && !s2)
return false;
}
return true;
}
function zn(t3) {
const { x: e2, y: n2, z: o2, layerCount: i2, minSpan: r2, maxSpan: s2, obstacleIndexByLayer: a2, additionalBlockersByLayer: c2 } = t3, l2 = (t4) => {
const o3 = { minX: e2, minY: n2, maxX: e2, maxY: n2 }, i3 = a2[t4];
if (i3 && i3.collides(o3))
return false;
return !(c2?.[t4] ?? []).some((t5) => {
return (i4 = { x: e2, y: n2 }).x >= (o4 = t5).x - tn && i4.x <= o4.x + o4.width + tn && i4.y >= o4.y - tn && i4.y <= o4.y + o4.height + tn;
var o4, i4;
});
};
let h2 = o2, d2 = o2;
for (;h2 - 1 >= 0 && l2(h2 - 1); )
h2--;
for (;d2 + 1 < i2 && l2(d2 + 1); )
d2++;
if (typeof s2 == "number") {
const t4 = ((t5, e3, n3) => Math.max(e3, Math.min(n3, t5)))(s2, 1, i2);
for (;d2 - h2 + 1 > t4; )
o2 - h2 > d2 - o2 ? h2++ : d2--;
}
const u2 = [];
for (let t4 = h2;t4 <= d2; t4++)
u2.push(t4);
return u2.length >= r2 ? u2 : [];
}
var Bn = (t3, e2 = 0.000001) => Math.round(t3 / e2) * e2;
var Fn = (t3, e2 = 0.000001) => Math.round(t3 / e2) * e2;
var jn = (t3) => ("minX" in t3) ? { x: t3.minX, y: t3.minY, width: t3.maxX - t3.minX, height: t3.maxY - t3.minY } : t3;
function $n(t3) {
const { lineStart: e2, lineEnd: n2, coveringIntervals: o2, minSegmentLength: i2 } = t3, r2 = Fn(e2), s2 = Fn(n2), a2 = o2.map((t4) => {
const e3 = Fn(t4.start), n3 = Fn(t4.end);
return { start: Math.min(e3, n3), end: Math.max(e3, n3) };
}).filter((t4) => t4.end > t4.start + tn);
if (a2.length === 0) {
return [{ start: r2, end: s2, center: (r2 + s2) / 2 }];
}
const c2 = [...a2].sort((t4, e3) => t4.start - e3.start), l2 = [];
let h2 = { ...c2[0] };
for (let t4 = 1;t4 < c2.length; t4++) {
const e3 = c2[t4];
e3.start <= h2.end + tn ? h2.end = Math.max(h2.end, e3.end) : (l2.push(h2), h2 = { ...e3 });
}
l2.push(h2);
const d2 = [];
if (l2[0].start > r2 + tn) {
const t4 = r2, e3 = l2[0].start;
e3 - t4 >= i2 && d2.push({ start: t4, end: e3, center: (t4 + e3) / 2 });
}
for (let t4 = 0;t4 < l2.length - 1; t4++) {
const e3 = l2[t4].end, n3 = l2[t4 + 1].start;
n3 - e3 >= i2 && d2.push({ start: e3, end: n3, center: (e3 + n3) / 2 });
}
if (l2[l2.length - 1].end < s2 - tn) {
const t4 = l2[l2.length - 1].end, e3 = s2;
e3 - t4 >= i2 && d2.push({ start: t4, end: e3, center: (t4 + e3) / 2 });
}
return d2;
}
function Yn(t3) {
const { bounds: e2, minSize: n2, layerCount: o2, obstacleIndexByLayer: i2, placedIndexByLayer: r2, hardPlacedByLayer: s2 } = t3, a2 = [], c2 = Math.max(0.15 * n2, 3 * tn), l2 = new Set, h2 = Array.from({ length: o2 }, (t4, e3) => [...i2[e3]?.all() ?? [], ...s2[e3] ?? []].map(jn));
function d2(t4) {
const n3 = Fn(t4.x), c3 = Fn(t4.y), { z: d3 } = t4, u2 = n3, p2 = c3;
if (u2 < e2.x + tn || p2 < e2.y + tn || u2 > e2.x + e2.width - tn || p2 > e2.y + e2.height - tn)
return;
if (function(t5) {
return Ln({ layerCount: o2, obstacleIndexByLayer: i2, placedIndexByLayer: r2, point: t5 });
}({ x: u2, y: p2 }))
return;
const m2 = h2[d3] ?? [];
let g2 = an({ x: u2, y: p2 }, e2);
for (const t5 of m2)
g2 = Math.min(g2, an({ x: u2, y: p2 }, t5));
const f2 = Fn(g2), y2 = ((t5) => `${t5.z}|${t5.x.toFixed(6)}|${t5.y.toFixed(6)}`)({ x: u2, y: p2, z: d3 });
if (l2.has(y2))
return;
l2.add(y2);
const _2 = zn({ x: u2, y: p2, z: d3, layerCount: o2, minSpan: 1, maxSpan: undefined, obstacleIndexByLayer: i2, additionalBlockersByLayer: s2 });
a2.push({ x: u2, y: p2, z: d3, distance: f2, zSpanLen: _2.length, isEdgeSeed: true });
}
for (let t4 = 0;t4 < o2; t4++) {
const o3 = (h2[t4] ?? []).map((t5) => ({ x: Fn(t5.x), y: Fn(t5.y), width: Fn(t5.width), height: Fn(t5.height) })), i3 = [{ x: e2.x + c2, y: e2.y + c2 }, { x: e2.x + e2.width - c2, y: e2.y + c2 }, { x: e2.x + c2, y: e2.y + e2.height - c2 }, { x: e2.x + e2.width - c2, y: e2.y + e2.height - c2 }];
for (const e3 of i3)
d2({ x: e3.x, y: e3.y, z: t4 });
const r3 = e2.y + c2, s3 = o3.filter((t5) => t5.y <= r3 && t5.y + t5.height >= r3).map((t5) => ({ start: Math.max(e2.x, t5.x), end: Math.min(e2.x + e2.width, t5.x + t5.width) })), a3 = $n({ lineStart: e2.x + c2, lineEnd: e2.x + e2.width - c2, coveringIntervals: s3, minSegmentLength: 0.5 * n2 });
for (const e3 of a3) {
const o4 = e3.end - e3.start;
o4 >= n2 && (d2({ x: e3.center, y: r3, z: t4 }), o4 > 1.5 * n2 && (d2({ x: e3.start + 0.4 * n2, y: r3, z: t4 }), d2({ x: e3.end - 0.4 * n2, y: r3, z: t4 })));
}
const l3 = e2.y + e2.height - c2, u2 = o3.filter((t5) => t5.y <= l3 && t5.y + t5.height >= l3).map((t5) => ({ start: Math.max(e2.x, t5.x), end: Math.min(e2.x + e2.width, t5.x + t5.width) })), p2 = $n({ lineStart: e2.x + c2, lineEnd: e2.x + e2.width - c2, coveringIntervals: u2, minSegmentLength: 0.5 * n2 });
for (const e3 of p2) {
const o4 = e3.end - e3.start;
o4 >= n2 && (d2({ x: e3.center, y: l3, z: t4 }), o4 > 1.5 * n2 && (d2({ x: e3.start + 0.4 * n2, y: l3, z: t4 }), d2({ x: e3.end - 0.4 * n2, y: l3, z: t4 })));
}
const m2 = e2.x + c2, g2 = o3.filter((t5) => t5.x <= m2 && t5.x + t5.width >= m2).map((t5) => ({ start: Math.max(e2.y, t5.y), end: Math.min(e2.y + e2.height, t5.y + t5.height) })), f2 = $n({ lineStart: e2.y + c2, lineEnd: e2.y + e2.height - c2, coveringIntervals: g2, minSegmentLength: 0.5 * n2 });
for (const e3 of f2) {
const o4 = e3.end - e3.start;
o4 >= n2 && (d2({ x: m2, y: e3.center, z: t4 }), o4 > 1.5 * n2 && (d2({ x: m2, y: e3.start + 0.4 * n2, z: t4 }), d2({ x: m2, y: e3.end - 0.4 * n2, z: t4 })));
}
const y2 = e2.x + e2.width - c2, _2 = o3.filter((t5) => t5.x <= y2 && t5.x + t5.width >= y2).map((t5) => ({ start: Math.max(e2.y, t5.y), end: Math.min(e2.y + e2.height, t5.y + t5.height) })), b2 = $n({ lineStart: e2.y + c2, lineEnd: e2.y + e2.height - c2, coveringIntervals: _2, minSegmentLength: 0.5 * n2 });
for (const e3 of b2) {
const o4 = e3.end - e3.start;
o4 >= n2 && (d2({ x: y2, y: e3.center, z: t4 }), o4 > 1.5 * n2 && (d2({ x: y2, y: e3.start + 0.4 * n2, z: t4 }), d2({ x: y2, y: e3.end - 0.4 * n2, z: t4 })));
}
for (const i4 of o3) {
const r4 = i4.x - c2;
if (r4 > e2.x + tn && r4 < e2.x + e2.width - tn) {
const e3 = o3.filter((t5) => t5 !== i4 && t5.x <= r4 && t5.x + t5.width >= r4).map((t5) => ({ start: Math.max(i4.y, t5.y), end: Math.min(i4.y + i4.height, t5.y + t5.height) })), s5 = $n({ lineStart: i4.y, lineEnd: i4.y + i4.height, coveringIntervals: e3, minSegmentLength: 0.5 * n2 });
for (const e4 of s5)
d2({ x: r4, y: e4.center, z: t4 });
}
const s4 = i4.x + i4.width + c2;
if (s4 > e2.x + tn && s4 < e2.x + e2.width - tn) {
const e3 = o3.filter((t5) => t5 !== i4 && t5.x <= s4 && t5.x + t5.width >= s4).map((t5) => ({ start: Math.max(i4.y, t5.y), end: Math.min(i4.y + i4.height, t5.y + t5.height) })), r5 = $n({ lineStart: i4.y, lineEnd: i4.y + i4.height, coveringIntervals: e3, minSegmentLength: 0.5 * n2 });
for (const e4 of r5)
d2({ x: s4, y: e4.center, z: t4 });
}
const a4 = i4.y - c2;
if (a4 > e2.y + tn && a4 < e2.y + e2.height - tn) {
const e3 = o3.filter((t5) => t5 !== i4 && t5.y <= a4 && t5.y + t5.height >= a4).map((t5) => ({ start: Math.max(i4.x, t5.x), end: Math.min(i4.x + i4.width, t5.x + t5.width) })), r5 = $n({ lineStart: i4.x, lineEnd: i4.x + i4.width, coveringIntervals: e3, minSegmentLength: 0.5 * n2 });
for (const e4 of r5)
d2({ x: e4.center, y: a4, z: t4 });
}
const l4 = i4.y + i4.height + c2;
if (l4 > e2.y + tn && l4 < e2.y + e2.height - tn) {
const e3 = o3.filter((t5) => t5 !== i4 && t5.y <= l4 && t5.y + t5.height >= l4).map((t5) => ({ start: Math.max(i4.x, t5.x), end: Math.min(i4.x + i4.width, t5.x + t5.width) })), r5 = $n({ lineStart: i4.x, lineEnd: i4.x + i4.width, coveringIntervals: e3, minSegmentLength: 0.5 * n2 });
for (const e4 of r5)
d2({ x: e4.center, y: l4, z: t4 });
}
}
}
return a2.sort((t4, e3) => e3.zSpanLen - t4.zSpanLen || e3.distance - t4.distance || t4.z - e3.z || t4.x - e3.x || t4.y - e3.y), a2;
}
function Xn(t3) {
const e2 = Array.from({ length: t3.layerCount }, () => []);
for (const n2 of t3.placed)
if (n2.zLayers.length >= t3.layerCount)
for (const t4 of n2.zLayers)
e2[t4].push(n2.rect);
return e2;
}
var Wn = (t3, e2) => ({ ...t3, minX: t3.x, minY: t3.y, maxX: t3.x + t3.width, maxY: t3.y + t3.height, zLayers: e2.zLayers });
function Vn(t3, e2) {
const n2 = t3.placed[e2], { rect: o2, zLayers: i2 } = n2, r2 = t3.layerCount, s2 = [], a2 = [];
for (let n3 = 0;n3 < t3.placed.length; n3++) {
if (n3 === e2)
continue;
const c3 = t3.placed[n3];
if (c3.zLayers.length >= r2)
continue;
const l2 = c3.zLayers.filter((t4) => i2.includes(t4));
if (l2.length === 0)
continue;
if (!sn(c3.rect, o2))
continue;
const h2 = ln(c3.rect, o2);
s2.push(n3);
const d2 = c3.zLayers.filter((t4) => !i2.includes(t4));
d2.length > 0 && a2.push({ rect: c3.rect, zLayers: d2 });
const u2 = Math.min(t3.options.minSingle.width, t3.options.minMulti.width), p2 = Math.min(t3.options.minSingle.height, t3.options.minMulti.height);
for (const t4 of h2)
t4.width + tn >= u2 && t4.height + tn >= p2 && a2.push({ rect: t4, zLayers: l2.slice() });
}
const c2 = (t4, e3) => t4.minX === e3.minX && t4.minY === e3.minY && t4.maxX === e3.maxX && t4.maxY === e3.maxY;
s2.sort((t4, e3) => e3 - t4).forEach((e3) => {
const n3 = t3.placed.splice(e3, 1)[0];
if (t3.placedIndexByLayer)
for (const e4 of n3.zLayers) {
const o3 = t3.placedIndexByLayer[e4];
o3 && o3.remove(Wn(n3.rect, { zLayers: n3.zLayers }), c2);
}
});
for (const e3 of a2) {
t3.placed.push(e3);
for (const n3 of e3.zLayers)
if (t3.placedIndexByLayer) {
const o3 = t3.placedIndexByLayer[n3];
o3 && o3.insert(Wn(e3.rect, { zLayers: e3.zLayers.slice() }));
}
}
}
var Hn = class extends kt {
constructor(t3) {
super(), this.input = t3;
}
srj;
layerNames;
layerCount;
bounds;
options;
boardVoidRects;
gridIndex;
candidates;
placed;
placedIndexByLayer;
hardPlacedByLayer;
expansionIndex;
edgeAnalysisDone;
totalSeedsThisGrid;
consumedSeedsThisGrid;
_setup() {
const t3 = this.input.simpleRouteJson, e2 = this.input.gridOptions ?? {}, n2 = this.input.layerNames && this.input.zIndexByName, { layerNames: o2} = n2 ? { layerNames: this.input.layerNames, zIndexByName: this.input.zIndexByName } : qe({ obstacles: t3.obstacles, layerCount: t3.layerCount }), r2 = Math.max(1, o2.length, t3.layerCount || 1), s2 = { x: t3.bounds.minX, y: t3.bounds.minY, width: t3.bounds.maxX - t3.bounds.minX, height: t3.bounds.maxY - t3.bounds.minY }, a2 = Math.max(0.01, t3.minTraceWidth || 0.15), c2 = { ...{ gridSizes: [], initialCellRatio: 0.2, maxAspectRatio: 3, minSingle: { width: 2 * a2, height: 2 * a2 }, minMulti: { width: 4 * a2, height: 4 * a2, minLayers: Math.min(2, Math.max(1, t3.layerCount || 1)) }, preferMultiLayer: true, maxMultiLayerSpan: undefined }, ...e2, gridSizes: e2.gridSizes ?? Dn(s2) };
this.srj = t3, this.layerNames = o2, this.layerCount = r2, this.bounds = s2, this.options = c2, this.boardVoidRects = this.input.boardVoidRects, this.gridIndex = 0, this.candidates = [], this.placed = [], this.placedIndexByLayer = Array.from({ length: r2 }, () => new te), this.hardPlacedByLayer = Array.from({ length: r2 }, () => []), this.expansionIndex = 0, this.edgeAnalysisDone = false, this.totalSeedsThisGrid = 0, this.consumedSeedsThisGrid = 0, this.stats = { gridIndex: this.gridIndex };
}
_step() {
this._stepGrid(), this.stats.gridIndex = this.gridIndex, this.stats.placed = this.placed.length;
}
_stepGrid() {
const { gridSizes: t3, initialCellRatio: e2, maxAspectRatio: n2, minSingle: o2, minMulti: i2, preferMultiLayer: r2, maxMultiLayerSpan: s2 } = this.options, a2 = t3[this.gridIndex];
if (this.candidates.length === 0 && this.consumedSeedsThisGrid === 0 && (this.candidates = function(t4) {
const { bounds: e3, gridSize: n3, layerCount: o3, obstacleIndexByLayer: i3, placedIndexByLayer: r3, hardPlacedByLayer: s3 } = t4, a3 = new Map, c3 = Array.from({ length: o3 }, (t5, e4) => [...i3[e4]?.all() ?? [], ...s3[e4] ?? []]);
for (let t5 = e3.x;t5 < e3.x + e3.width; t5 += n3)
for (let l4 = e3.y;l4 < e3.y + e3.height; l4 += n3) {
if (Math.abs(t5 - e3.x) < tn || Math.abs(l4 - e3.y) < tn || t5 > e3.x + e3.width - n3 - tn || l4 > e3.y + e3.height - n3 - tn)
continue;
if (Ln({ layerCount: o3, obstacleIndexByLayer: i3, placedIndexByLayer: r3, point: { x: t5, y: l4 } }))
continue;
let h3 = [], d3 = 0;
for (let e4 = 0;e4 < o3; e4++) {
const n4 = zn({ x: t5, y: l4, z: e4, layerCount: o3, minSpan: 1, maxSpan: undefined, obstacleIndexByLayer: i3, additionalBlockersByLayer: s3 });
n4.length > h3.length && (h3 = n4, d3 = e4);
}
const u2 = h3.length ? h3[Math.floor(h3.length / 2)] : d3, p2 = c3[u2] ?? [];
let m2 = an({ x: t5, y: l4 }, e3);
for (const e4 of p2)
m2 = Math.min(m2, an({ x: t5, y: l4 }, e4));
const g2 = Bn(m2), f2 = `${t5.toFixed(6)}|${l4.toFixed(6)}`, y2 = { x: t5, y: l4, z: u2, distance: g2, zSpanLen: h3.length }, _2 = a3.get(f2);
(!_2 || y2.zSpanLen > (_2.zSpanLen ?? 0) || y2.zSpanLen === _2.zSpanLen && y2.distance > _2.distance) && a3.set(f2, y2);
}
const l3 = Array.from(a3.values());
return l3.sort((t5, e4) => e4.zSpanLen - t5.zSpanLen || e4.distance - t5.distance || t5.z - e4.z || t5.x - e4.x || t5.y - e4.y), l3;
}({ bounds: this.bounds, gridSize: a2, layerCount: this.layerCount, hardPlacedByLayer: this.hardPlacedByLayer, obstacleIndexByLayer: this.input.obstacleIndexByLayer, placedIndexByLayer: this.placedIndexByLayer }), this.totalSeedsThisGrid = this.candidates.length, this.consumedSeedsThisGrid = 0), this.consumedSeedsThisGrid >= this.candidates.length) {
if (this.gridIndex + 1 < t3.length)
return this.gridIndex += 1, this.candidates = [], this.totalSeedsThisGrid = 0, void (this.consumedSeedsThisGrid = 0);
if (!this.edgeAnalysisDone) {
const t4 = Math.min(o2.width, o2.height);
return this.candidates = Yn({ bounds: this.bounds, minSize: t4, layerCount: this.layerCount, obstacleIndexByLayer: this.input.obstacleIndexByLayer, placedIndexByLayer: this.placedIndexByLayer, hardPlacedByLayer: this.hardPlacedByLayer }), this.edgeAnalysisDone = true, this.totalSeedsThisGrid = this.candidates.length, void (this.consumedSeedsThisGrid = 0);
}
return this.candidates = [], this.solved = true, void (this.expansionIndex = 0);
}
const c2 = this.candidates[this.consumedSeedsThisGrid++];
if (Ln({ layerCount: this.layerCount, obstacleIndexByLayer: this.input.obstacleIndexByLayer, placedIndexByLayer: this.placedIndexByLayer, point: { x: c2.x, y: c2.y } }))
return;
const l2 = zn({ x: c2.x, y: c2.y, z: c2.z, layerCount: this.layerCount, minSpan: i2.minLayers, maxSpan: s2, obstacleIndexByLayer: this.input.obstacleIndexByLayer, additionalBlockersByLayer: this.hardPlacedByLayer }), h2 = [];
l2.length >= i2.minLayers && h2.push({ kind: "multi", layers: l2, minReq: { width: i2.width, height: i2.height } }), h2.push({ kind: "single", layers: [c2.z], minReq: { width: o2.width, height: o2.height } });
const d2 = r2 ? h2 : h2.reverse();
for (const t4 of d2) {
const o3 = kn({ startX: c2.x, startY: c2.y, gridSize: a2, bounds: this.bounds, obsticalIndexByLayer: this.input.obstacleIndexByLayer, placedIndexByLayer: this.placedIndexByLayer, initialCellRatio: e2, maxAspectRatio: n2, minReq: t4.minReq, zLayers: t4.layers });
if (!o3)
continue;
const i3 = { rect: o3, zLayers: [...t4.layers] }, r3 = this.placed.push(i3) - 1;
for (const e3 of t4.layers) {
const t5 = this.placedIndexByLayer[e3];
t5 && t5.insert(Wn(o3, { zLayers: i3.zLayers }));
}
return Vn({ layerCount: this.layerCount, placed: this.placed, options: this.options, placedIndexByLayer: this.placedIndexByLayer }, r3), void (this.hardPlacedByLayer = Xn({ layerCount: this.layerCount, placed: this.placed }));
}
}
computeProgress() {
if (this.solved)
return 1;
const t3 = this.options.gridSizes.length, e2 = this.gridIndex / (t3 + 1), n2 = Math.max(1, this.totalSeedsThisGrid), o2 = n2 ? this.consumedSeedsThisGrid / n2 : 1;
return Math.min(0.999, e2 + o2 * (1 / (t3 + 1)));
}
getOutput() {
return { layerNames: this.layerNames, layerCount: this.layerCount, bounds: this.bounds, options: this.options, boardVoidRects: this.boardVoidRects, gridIndex: this.gridIndex, candidates: this.candidates, placed: this.placed, expansionIndex: this.expansionIndex, edgeAnalysisDone: this.edgeAnalysisDone, totalSeedsThisGrid: this.totalSeedsThisGrid, consumedSeedsThisGrid: this.consumedSeedsThisGrid, obstacles: this.srj.obstacles, obstacleClearance: this.input.obstacleClearance };
}
visualize() {
const t3 = [], e2 = [], n2 = [], o2 = this.srj ?? this.input.simpleRouteJson, i2 = o2.bounds.minX, r2 = o2.bounds.maxX, s2 = o2.bounds.minY, a2 = o2.bounds.maxY;
o2.outline && o2.outline.length > 1 ? n2.push({ points: [...o2.outline, o2.outline[0]], strokeColor: "#111827", strokeWidth: 0.01, label: "outline" }) : t3.push({ center: { x: (i2 + r2) / 2, y: (s2 + a2) / 2 }, width: r2 - i2, height: a2 - s2, fill: "none", stroke: "#111827", label: "board" });
for (const e3 of o2.obstacles ?? [])
e3.type !== "rect" && e3.type !== "oval" || t3.push({ center: { x: e3.center.x, y: e3.center.y }, width: e3.width, height: e3.height, fill: "#fee2e2", stroke: "#ef4444", layer: "obstacle", label: "obstacle" });
if (this.boardVoidRects) {
let e3 = null;
if (o2.outline && o2.outline.length > 0) {
const t4 = o2.outline.map((t5) => t5.x), n3 = o2.outline.map((t5) => t5.y), i3 = Math.min(...t4), r3 = Math.min(...n3);
e3 = { x: i3, y: r3, width: Math.max(...t4) - i3, height: Math.max(...n3) - r3 };
}
for (const n3 of this.boardVoidRects)
e3 && !sn(n3, e3) || t3.push({ center: { x: n3.x + n3.width / 2, y: n3.y + n3.height / 2 }, width: n3.width, height: n3.height, fill: "rgba(0, 0, 0, 0.5)", stroke: "none", label: "void" });
}
if (this.candidates?.length)
for (const t4 of this.candidates)
e2.push({ x: t4.x, y: t4.y, label: `z:${t4.z}` });
if (this.placed?.length)
for (const e3 of this.placed) {
const n3 = Ke(e3.zLayers);
t3.push({ center: { x: e3.rect.x + e3.rect.width / 2, y: e3.rect.y + e3.rect.height / 2 }, width: e3.rect.width, height: e3.rect.height, fill: n3.fill, stroke: n3.stroke, layer: `z${e3.zLayers.join(",")}`, label: `free
z:${e3.zLayers.join(",")}` });
}
return { title: "RectDiff Grid", coordinateSystem: "cartesian", rects: t3, points: e2, lines: n2 };
}
};
var Gn = (t3, e2) => t3.minX === e2.minX && t3.minY === e2.minY && t3.maxX === e2.maxX && t3.maxY === e2.maxY;
var Un = class extends kt {
constructor(t3) {
super(), this.input = t3;
}
placedIndexByLayer = [];
_meshNodes = [];
_setup() {
this.stats = { gridIndex: this.input.gridIndex }, this.placedIndexByLayer = Array.from({ length: this.input.layerCount }, () => new te);
for (const t3 of this.input.placed)
for (const e2 of t3.zLayers) {
const n2 = this.placedIndexByLayer[e2];
n2 && n2.insert(Wn(t3.rect, { zLayers: t3.zLayers }));
}
}
_step() {
this.solved || (this._stepExpansion(), this.stats.gridIndex = this.input.gridIndex, this.stats.placed = this.input.placed.length, this.input.expansionIndex >= this.input.placed.length && this.finalizeIfNeeded());
}
_stepExpansion() {
if (this.input.expansionIndex >= this.input.placed.length)
return;
const t3 = this.input.expansionIndex, e2 = this.input.placed[t3], n2 = this.input.options.gridSizes[this.input.options.gridSizes.length - 1], o2 = e2.rect, i2 = kn({ startX: e2.rect.x + e2.rect.width / 2, startY: e2.rect.y + e2.rect.height / 2, gridSize: n2, bounds: this.input.bounds, obsticalIndexByLayer: this.input.obstacleIndexByLayer, placedIndexByLayer: this.placedIndexByLayer, initialCellRatio: 0, maxAspectRatio: null, minReq: { width: e2.rect.width, height: e2.rect.height }, zLayers: e2.zLayers });
if (i2) {
this.input.placed[t3] = { rect: i2, zLayers: e2.zLayers };
for (const t4 of e2.zLayers) {
const n3 = this.placedIndexByLayer[t4];
n3 && (n3.remove(Wn(o2, { zLayers: e2.zLayers }), Gn), n3.insert(Wn(i2, { zLayers: e2.zLayers })));
}
Vn({ layerCount: this.input.layerCount, placed: this.input.placed, options: this.input.options, placedIndexByLayer: this.placedIndexByLayer }, t3);
}
this.input.expansionIndex += 1;
}
finalizeIfNeeded() {
if (this.solved)
return;
const t3 = function(t4) {
const e2 = t4.placed.map((t5) => ({ minX: t5.rect.x, minY: t5.rect.y, maxX: t5.rect.x + t5.rect.width, maxY: t5.rect.y + t5.rect.height, zLayers: [...t5.zLayers].sort((t6, e3) => t6 - e3) }));
for (const n2 of t4.obstacles ?? []) {
const o2 = Qe(n2);
if (!o2)
continue;
const i2 = t4.obstacleClearance ? { x: o2.x - t4.obstacleClearance, y: o2.y - t4.obstacleClearance, width: o2.width + 2 * t4.obstacleClearance, height: o2.height + 2 * t4.obstacleClearance } : o2, r2 = n2.zLayers?.length && n2.zLayers.length > 0 ? n2.zLayers : Je(n2, t4.zIndexByName);
e2.push({ minX: i2.x, minY: i2.y, maxX: i2.x + i2.width, maxY: i2.y + i2.height, zLayers: [...new Set(r2)].sort((t5, e3) => t5 - e3), isObstacle: true, connectedTo: [...n2.connectedTo] });
}
return e2;
}({ placed: this.input.placed, obstacles: this.input.obstacles, zIndexByName: this.input.zIndexByName, boardVoidRects: this.input.boardVoidRects, obstacleClearance: this.input.obstacleClearance });
this._meshNodes = function(t4) {
let e2 = 0;
const n2 = [];
for (const o2 of t4) {
const t5 = Math.max(0, o2.maxX - o2.minX), i2 = Math.max(0, o2.maxY - o2.minY);
t5 <= 0 || i2 <= 0 || o2.zLayers.length === 0 || n2.push({ capacityMeshNodeId: "cmn_" + e2++, center: { x: (o2.minX + o2.maxX) / 2, y: (o2.minY + o2.maxY) / 2 }, width: t5, height: i2, layer: "top", availableZ: o2.zLayers.slice(), _containsObstacle: o2.isObstacle, _containsTarget: o2.isObstacle, ...o2.connectedTo?.length ? { _connectedTo: [...o2.connectedTo] } : {} });
}
return n2;
}(t3), this.solved = true;
}
computeProgress() {
if (this.solved)
return 1;
const t3 = this.input.options.gridSizes.length, e2 = t3 / (t3 + 1), n2 = Math.max(1, this.input.placed.length), o2 = n2 ? this.input.expansionIndex / n2 : 1;
return Math.min(0.999, e2 + o2 * (1 / (t3 + 1)));
}
getOutput() {
if (this.solved)
return { meshNodes: this._meshNodes };
return { meshNodes: this.input.placed.map((t3, e2) => ({ capacityMeshNodeId: `expand-preview-${e2}`, center: { x: t3.rect.x + t3.rect.width / 2, y: t3.rect.y + t3.rect.height / 2 }, width: t3.rect.width, height: t3.rect.height, availableZ: t3.zLayers.slice(), layer: `z${t3.zLayers.join(",")}` })) };
}
visualize() {
const t3 = [];
for (const e2 of this.input.placed ?? [])
t3.push({ center: { x: e2.rect.x + e2.rect.width / 2, y: e2.rect.y + e2.rect.height / 2 }, width: e2.rect.width, height: e2.rect.height, stroke: "rgba(37, 99, 235, 0.9)", fill: "rgba(191, 219, 254, 0.5)", layer: `z${e2.zLayers.join(",")}`, label: `expanded
z:${e2.zLayers.join(",")}` });
return { title: "RectDiff Expansion", coordinateSystem: "cartesian", rects: t3, points: [], lines: [] };
}
};
var Zn = class extends Lt {
rectDiffSeedingSolver;
rectDiffExpansionSolver;
obstacleIndexByLayer;
layerNames;
zIndexByName;
constructor(t3) {
super(t3);
const { obstacleIndexByLayer: e2, layerNames: n2, zIndexByName: o2 } = ((t4) => {
const { srj: e3, boardVoidRects: n3, obstacleClearance: o3 } = t4, { layerNames: i2, zIndexByName: r2 } = qe({ obstacles: e3.obstacles, layerCount: e3.layerCount }), s2 = Math.max(1, i2.length, e3.layerCount || 1), a2 = (e3.bounds.minX, e3.bounds.minY, e3.bounds.maxX, e3.bounds.minX, e3.bounds.maxY, e3.bounds.minY, Array.from({ length: s2 }, () => new te)), c2 = (t5, e4) => {
const n4 = { ...t5, minX: t5.x, minY: t5.y, maxX: t5.x + t5.width, maxY: t5.y + t5.height, zLayers: [e4] };
a2[e4]?.insert(n4);
};
if (e3.outline && e3.outline.length > 2)
for (const t5 of n3 ?? [])
for (let e4 = 0;e4 < s2; e4++)
c2(t5, e4);
for (const t5 of e3.obstacles ?? []) {
const e4 = Qe(t5);
if (!e4)
continue;
const n4 = hn(e4, o3 ?? 0), i3 = Je(t5, r2), a3 = i3.filter((t6) => t6 < 0 || t6 >= s2);
if (a3.length)
throw new Error(`RectDiff: obstacle uses z-layer indices ${a3.join(",")} outside 0-${s2 - 1}`);
t5.zLayers && t5.zLayers.length !== 0 || !i3.length || (t5.zLayers = i3);
for (const t6 of i3)
c2(n4, t6);
}
return { obstacleIndexByLayer: a2, layerNames: i2, zIndexByName: r2 };
})({ srj: { bounds: t3.bounds, obstacles: t3.obstacles, connections: t3.connections, outline: t3.outline?.outline, layerCount: t3.layerCount, minTraceWidth: t3.minTraceWidth }, boardVoidRects: t3.boardVoidRects, obstacleClearance: t3.obstacleClearance });
this.obstacleIndexByLayer = e2, this.layerNames = t3.layerNames ?? n2, this.zIndexByName = t3.zIndexByName ?? o2;
}
pipelineDef = [Dt("rectDiffSeedingSolver", Hn, (t3) => [{ simpleRouteJson: { bounds: t3.inputProblem.bounds, obstacles: t3.inputProblem.obstacles, connections: t3.inputProblem.connections, outline: t3.inputProblem.outline?.outline, layerCount: t3.inputProblem.layerCount, minTraceWidth: t3.inputProblem.minTraceWidth }, gridOptions: t3.inputProblem.gridOptions, obstacleIndexByLayer: t3.obstacleIndexByLayer, boardVoidRects: t3.inputProblem.boardVoidRects, layerNames: t3.layerNames, zIndexByName: t3.zIndexByName, obstacleClearance: t3.inputProblem.obstacleClearance }]), Dt("rectDiffExpansionSolver", Un, (t3) => {
const e2 = t3.rectDiffSeedingSolver?.getOutput();
if (!e2)
throw new Error("RectDiffSeedingSolver did not produce output");
return [{ layerNames: e2.layerNames ?? [], boardVoidRects: t3.inputProblem.boardVoidRects ?? [], layerCount: t3.inputProblem.layerCount, bounds: e2.bounds, candidates: e2.candidates, consumedSeedsThisGrid: e2.placed.length, totalSeedsThisGrid: e2.candidates.length, placed: e2.placed, edgeAnalysisDone: e2.edgeAnalysisDone, gridIndex: e2.gridIndex, expansionIndex: e2.expansionIndex, obstacleIndexByLayer: t3.obstacleIndexByLayer, options: e2.options, zIndexByName: t3.zIndexByName, layerNamesCanonical: t3.layerNames, obstacles: t3.inputProblem.obstacles, obstacleClearance: t3.inputProblem.obstacleClearance }];
})];
getConstructorParams() {
return [this.inputProblem];
}
getOutput() {
if (this.rectDiffExpansionSolver)
return this.rectDiffExpansionSolver.getOutput();
if (this.rectDiffSeedingSolver) {
return { meshNodes: this.rectDiffSeedingSolver.getOutput().placed.map((t3, e2) => ({ capacityMeshNodeId: `grid-${e2}`, center: { x: t3.rect.x + t3.rect.width / 2, y: t3.rect.y + t3.rect.height / 2 }, width: t3.rect.width, height: t3.rect.height, availableZ: t3.zLayers, layer: `z${t3.zLayers.join(",")}` })) };
}
return { meshNodes: [] };
}
visualize() {
return this.rectDiffExpansionSolver ? this.rectDiffExpansionSolver.visualize() : this.rectDiffSeedingSolver ? this.rectDiffSeedingSolver.visualize() : { title: "RectDiff Grid Pipeline", coordinateSystem: "cartesian", rects: [], points: [], lines: [] };
}
};
var qn = (t3) => {
const { srj: e2, clearance: n2 } = t3, o2 = n2 ?? 0;
if (o2 <= 0)
return { title: "Obstacle Clearance", coordinateSystem: "cartesian", rects: [] };
const i2 = [];
for (const t4 of e2.obstacles ?? []) {
if (t4.type !== "rect" && t4.type !== "oval")
continue;
const e3 = { x: t4.center.x - t4.width / 2 - o2, y: t4.center.y - t4.height / 2 - o2, width: t4.width + 2 * o2, height: t4.height + 2 * o2 };
i2.push({ center: { x: e3.x + e3.width / 2, y: e3.y + e3.height / 2 }, width: e3.width, height: e3.height, stroke: "rgba(202, 138, 4, 0.9)", fill: "rgba(234, 179, 8, 0.15)", layer: "obstacle-clearance", label: `clearance
z:${(t4.zLayers ?? []).join(",") || "all"}` });
}
return { title: "Obstacle Clearance", coordinateSystem: "cartesian", rects: i2 };
};
function Jn(t3, e2, n2 = {}) {
if (!e2 || e2.length < 3)
return [];
const o2 = e2.length > 120, i2 = o2 ? function(t4, e3) {
const n3 = (t5) => Math.round(t5 / e3) * e3, o3 = new Set, i3 = [];
for (const e4 of t4) {
const t5 = n3(e4.x), r3 = n3(e4.y), s3 = `${t5},${r3}`;
o3.has(s3) || (o3.add(s3), i3.push({ x: t5, y: r3 }));
}
return i3;
}(e2, Math.max(t3.width, t3.height) / 120) : e2, r2 = new Set([t3.x, t3.x + t3.width]), s2 = new Set([t3.y, t3.y + t3.height]);
for (const t4 of i2)
r2.add(t4.x), s2.add(t4.y);
(function({ polygon: t4, xs: e3, ys: n3, minGridSize: o3 }) {
const i3 = [];
let r3 = 0;
for (let e4 = 0;e4 < t4.length; e4++) {
const n4 = t4[e4], o4 = t4[(e4 + 1) % t4.length], s4 = Math.abs(o4.x - n4.x), a3 = Math.abs(o4.y - n4.y);
if (s4 <= tn || a3 <= tn)
continue;
const c3 = Math.max(s4, a3);
i3.push({ start: n4, end: o4, span: c3 }), r3 += c3;
}
if (i3.length === 0)
return;
const s3 = Math.max(o3, r3 / 256);
for (const { start: t5, end: o4, span: r4 } of i3) {
const i4 = Math.max(1, Math.ceil(r4 / s3));
for (let r5 = 1;r5 < i4; r5++) {
const s4 = r5 / i4;
e3.add(t5.x + (o4.x - t5.x) * s4), n3.add(t5.y + (o4.y - t5.y) * s4);
}
}
})({ polygon: i2, xs: r2, ys: s2, minGridSize: Math.max(tn, n2.minGridSize ?? Math.max(t3.width, t3.height) / 256) });
const a2 = Array.from(r2).sort((t4, e3) => t4 - e3), c2 = Array.from(s2).sort((t4, e3) => t4 - e3), l2 = [];
for (let n3 = 0;n3 < a2.length - 1; n3++)
for (let i3 = 0;i3 < c2.length - 1; i3++) {
const r3 = a2[n3], s3 = a2[n3 + 1], h3 = c2[i3], d3 = c2[i3 + 1], u3 = (r3 + s3) / 2, p2 = (h3 + d3) / 2;
if (u3 >= t3.x && u3 <= t3.x + t3.width && p2 >= t3.y && p2 <= t3.y + t3.height) {
(o2 ? [{ x: u3, y: p2 }] : [{ x: u3, y: p2 }, { x: r3, y: h3 }, { x: s3, y: h3 }, { x: r3, y: d3 }, { x: s3, y: d3 }]).every((t4) => Ne(t4, e2)) || l2.push({ x: r3, y: h3, width: s3 - r3, height: d3 - h3 });
}
}
const h2 = [];
l2.sort((t4, e3) => Math.abs(t4.y - e3.y) > tn ? t4.y - e3.y : t4.x - e3.x);
let d2 = null;
for (const t4 of l2) {
if (!d2) {
d2 = t4;
continue;
}
const e3 = Math.abs(d2.y - t4.y) < tn, n3 = Math.abs(d2.height - t4.height) < tn, o3 = Math.abs(d2.x + d2.width - t4.x) < tn;
e3 && n3 && o3 ? d2.width += t4.width : (h2.push(d2), d2 = t4);
}
d2 && h2.push(d2), h2.sort((t4, e3) => Math.abs(t4.x - e3.x) > tn ? t4.x - e3.x : t4.y - e3.y);
const u2 = [];
d2 = null;
for (const t4 of h2) {
if (!d2) {
d2 = t4;
continue;
}
const e3 = Math.abs(d2.x - t4.x) < tn, n3 = Math.abs(d2.width - t4.width) < tn, o3 = Math.abs(d2.y + d2.height - t4.y) < tn;
e3 && n3 && o3 ? d2.height += t4.height : (u2.push(d2), d2 = t4);
}
return d2 && u2.push(d2), u2;
}
var Qn = class extends Lt {
rectDiffGridSolverPipeline;
gapFillSolver;
outerLayerContainmentMergeSolver;
boardVoidRects;
zIndexByName;
layerNames;
pipelineDef = [Dt("rectDiffGridSolverPipeline", Zn, (t3) => [{ bounds: t3.inputProblem.simpleRouteJson.bounds, obstacles: t3.inputProblem.simpleRouteJson.obstacles, connections: t3.inputProblem.simpleRouteJson.connections, outline: t3.inputProblem.simpleRouteJson.outline ? { outline: t3.inputProblem.simpleRouteJson.outline } : undefined, layerCount: t3.inputProblem.simpleRouteJson.layerCount, gridOptions: t3.inputProblem.gridOptions, boardVoidRects: t3.boardVoidRects, layerNames: t3.layerNames, zIndexByName: t3.zIndexByName, minTraceWidth: t3.inputProblem.simpleRouteJson.minTraceWidth, obstacleClearance: t3.inputProblem.obstacleClearance }]), Dt("gapFillSolver", Ue, (t3) => [{ meshNodes: t3.rectDiffGridSolverPipeline?.getOutput().meshNodes ?? [], boardVoid: { boardVoidRects: t3.boardVoidRects || [], layerCount: t3.inputProblem.simpleRouteJson.layerCount || 0 }, maxGapFillPasses: t3.inputProblem.maxGapFillPasses }]), Dt("outerLayerContainmentMergeSolver", xn, (t3) => [{ meshNodes: t3.gapFillSolver?.getOutput().outputNodes ?? t3.rectDiffGridSolverPipeline?.getOutput().meshNodes ?? [], simpleRouteJson: t3.inputProblem.simpleRouteJson, zIndexByName: t3.zIndexByName ?? new Map, obstacleClearance: t3.inputProblem.obstacleClearance }])];
_setup() {
const { zIndexByName: t3, layerNames: e2 } = qe({ obstacles: this.inputProblem.simpleRouteJson.obstacles, layerCount: this.inputProblem.simpleRouteJson.layerCount });
if (this.zIndexByName = t3, this.layerNames = e2, this.inputProblem.simpleRouteJson.outline) {
const t4 = Math.max(0, this.inputProblem.simpleRouteJson.minBoardEdgeClearance ?? 0);
this.boardVoidRects = Jn({ x: this.inputProblem.simpleRouteJson.bounds.minX - t4, y: this.inputProblem.simpleRouteJson.bounds.minY - t4, width: this.inputProblem.simpleRouteJson.bounds.maxX - this.inputProblem.simpleRouteJson.bounds.minX + 2 * t4, height: this.inputProblem.simpleRouteJson.bounds.maxY - this.inputProblem.simpleRouteJson.bounds.minY + 2 * t4 }, this.inputProblem.simpleRouteJson.outline ?? [], { minGridSize: this.inputProblem.simpleRouteJson.minTraceWidth }).map((e3) => hn(e3, t4));
}
}
getConstructorParams() {
return [this.inputProblem];
}
getOutput() {
const t3 = this.outerLayerContainmentMergeSolver?.getOutput();
if (t3)
return { meshNodes: t3.outputNodes };
const e2 = this.gapFillSolver?.getOutput();
return e2 ? { meshNodes: e2.outputNodes } : this.rectDiffGridSolverPipeline ? this.rectDiffGridSolverPipeline.getOutput() : { meshNodes: [] };
}
initialVisualize() {
const t3 = function(t4, e3 = "RectDiff") {
const n3 = [], o2 = [], i2 = t4.bounds.minX, r2 = t4.bounds.maxX, s2 = t4.bounds.minY, a2 = t4.bounds.maxY;
t4.outline && t4.outline.length > 1 ? o2.push({ points: [...t4.outline, t4.outline[0]], strokeColor: "#111827", strokeWidth: 0.01, label: "outline" }) : n3.push({ center: { x: (i2 + r2) / 2, y: (s2 + a2) / 2 }, width: r2 - i2, height: a2 - s2, fill: "none", stroke: "#111827", label: "board" });
for (const e4 of t4.obstacles ?? [])
if (e4.type === "rect" || e4.type === "oval") {
const t5 = (e4.zLayers ?? []).join(",") || "all";
n3.push({ center: { x: e4.center.x, y: e4.center.y }, width: e4.width, height: e4.height, fill: "#fee2e2", stroke: "#ef4444", layer: "obstacle", label: `obstacle
z:${t5}` });
}
return { title: e3, coordinateSystem: "cartesian", rects: n3, points: [], lines: o2 };
}(this.inputProblem.simpleRouteJson, "RectDiffPipeline - Initial"), e2 = qn({ srj: this.inputProblem.simpleRouteJson, clearance: this.inputProblem.obstacleClearance }), n2 = { rects: (this.rectDiffGridSolverPipeline?.getOutput().meshNodes ?? []).map((t4) => ({ center: t4.center, width: t4.width, height: t4.height, stroke: "rgba(0, 0, 0, 0.3)", fill: "rgba(100, 100, 100, 0.1)", layer: `z${t4.availableZ.join(",")}`, label: [`node ${t4.capacityMeshNodeId}`, `z:${t4.availableZ.join(",")}`].join(`
`) })) };
return At(At(t3, e2), n2);
}
finalVisualize() {
return (({ srj: t3, meshNodes: e2, obstacleClearance: n2 }) => {
const o2 = (({ srj: t4 }) => ({ title: "SimpleRoute Outline", coordinateSystem: "cartesian", lines: t4.outline && t4.outline.length > 1 ? [{ points: [...t4.outline, t4.outline[0]], strokeColor: "#111827", strokeWidth: 0.1, label: "outline" }] : [{ points: [{ x: t4.bounds.minX, y: t4.bounds.minY }, { x: t4.bounds.maxX, y: t4.bounds.minY }, { x: t4.bounds.maxX, y: t4.bounds.maxY }, { x: t4.bounds.minX, y: t4.bounds.maxY }, { x: t4.bounds.minX, y: t4.bounds.minY }], strokeColor: "#111827", strokeWidth: 0.1, label: "bounds" }] }))({ srj: t3 }), i2 = qn({ srj: t3, clearance: n2 }), r2 = e2.map((t4) => ({ center: t4.center, width: t4.width, height: t4.height, stroke: Ke(t4.availableZ).stroke, fill: t4._containsObstacle ? "#fca5a5" : Ke(t4.availableZ).fill, layer: `z${t4.availableZ.join(",")}`, label: `node ${t4.capacityMeshNodeId}
z:${t4.availableZ.join(",")}` }));
return At(At({ title: "RectDiffPipeline - Final", coordinateSystem: "cartesian", rects: r2, lines: [], points: [], texts: [] }, o2), i2);
})({ srj: this.inputProblem.simpleRouteJson, meshNodes: this.getOutput().meshNodes, obstacleClearance: this.inputProblem.obstacleClearance });
}
};
var Kn = class {
cacheHitsByPrefix = {};
cacheMissesByPrefix = {};
isSyncCache = true;
cacheHits = 0;
cacheMisses = 0;
cache = new Map;
getCachedSolutionSync(t3) {
const e2 = this.cache.get(t3);
if (e2 !== undefined) {
this.cacheHits++;
const n2 = t3.split(":")[0];
return this.cacheHitsByPrefix[n2] = (this.cacheHitsByPrefix[n2] || 0) + 1, structuredClone(e2);
}
{
this.cacheMisses++;
const e3 = t3.split(":")[0];
return void (this.cacheMissesByPrefix[e3] = (this.cacheMissesByPrefix[e3] || 0) + 1);
}
}
async getCachedSolution(t3) {
return this.getCachedSolutionSync(t3);
}
setCachedSolutionSync(t3, e2) {
this.cache.set(t3, structuredClone(e2));
}
async setCachedSolution(t3, e2) {
this.setCachedSolutionSync(t3, e2);
}
clearCache() {
this.cache.clear(), this.cacheHits = 0, this.cacheMisses = 0, this.cacheHitsByPrefix = {}, this.cacheMissesByPrefix = {};
}
getAllCacheKeys() {
return Array.from(this.cache.keys());
}
};
var to = "tscircuit_autorouter_cache_";
var eo = class {
isSyncCache = true;
cacheHits = 0;
cacheMisses = 0;
cacheHitsByPrefix = {};
cacheMissesByPrefix = {};
constructor() {}
getKey(t3) {
return `${to}${t3}`;
}
getCachedSolutionSync(t3) {
if (typeof localStorage == "undefined")
return;
const e2 = this.getKey(t3);
try {
const n2 = localStorage.getItem(e2);
if (n2 !== null) {
const e3 = JSON.parse(n2);
this.cacheHits++;
const o2 = t3.split(":")[0];
return this.cacheHitsByPrefix[o2] = (this.cacheHitsByPrefix[o2] || 0) + 1, e3;
}
{
this.cacheMisses++;
const e3 = t3.split(":")[0];
return void (this.cacheMissesByPrefix[e3] = (this.cacheMissesByPrefix[e3] || 0) + 1);
}
} catch (n2) {
console.error(`Error getting cached solution sync for ${e2}:`, n2), this.cacheMisses++;
const o2 = t3.split(":")[0];
return void (this.cacheMissesByPrefix[o2] = (this.cacheMissesByPrefix[o2] || 0) + 1);
}
}
async getCachedSolution(t3) {
return this.getCachedSolutionSync(t3);
}
setCachedSolutionSync(t3, e2) {
if (typeof localStorage == "undefined")
return;
const n2 = this.getKey(t3);
try {
const t4 = JSON.stringify(e2);
localStorage.setItem(n2, t4);
} catch (t4) {
console.error(`Error setting cached solution sync for ${n2}:`, t4), t4 instanceof DOMException && (t4.name === "QuotaExceededError" || t4.name === "NS_ERROR_DOM_QUOTA_REACHED") && console.warn(`LocalStorage quota exceeded. Failed to cache solution for ${n2}. Consider clearing the cache.`);
}
}
async setCachedSolution(t3, e2) {
this.setCachedSolutionSync(t3, e2);
}
clearCache() {
if (typeof localStorage != "undefined")
try {
const t3 = [];
for (let e2 = 0;e2 < localStorage.length; e2++) {
const n2 = localStorage.key(e2);
n2?.startsWith(to) && t3.push(n2);
}
t3.forEach((t4) => localStorage.removeItem(t4)), console.log(`Cleared ${t3.length} items from LocalStorage cache.`);
} catch (t3) {
console.error("Error clearing LocalStorage cache:", t3);
} finally {
this.cacheHits = 0, this.cacheMisses = 0, this.cacheHitsByPrefix = {}, this.cacheMissesByPrefix = {};
}
}
getAllCacheKeys() {
const t3 = [];
for (let e2 = 0;e2 < 1e4; e2++) {
const n2 = localStorage.key(e2);
if (!n2)
break;
n2.includes(to) && t3.push(n2);
}
return t3;
}
};
function oo() {
return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE || io(), globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE;
}
function io() {
globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE ??= new eo, globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE ??= new Kn;
}
function ro(t3) {
const e2 = { minX: t3.center.x - t3.width / 2, maxX: t3.center.x + t3.width / 2, minY: t3.center.y - t3.height / 2, maxY: t3.center.y + t3.height / 2 };
for (const n2 of t3.portPoints)
n2.x < e2.minX && (e2.minX = n2.x), n2.x > e2.maxX && (e2.maxX = n2.x), n2.y < e2.minY && (e2.minY = n2.y), n2.y > e2.maxY && (e2.maxY = n2.y);
return e2;
}
var so = (t3, e2) => t3 <= e2 ? [t3, e2] : [e2, t3];
var ao = (t3) => `${t3[0]}|${t3[1]}`;
var co = ({ portPointId: t3, currentNodeId: e2, inputNodes: n2 }) => {
let o2;
if (t3)
for (const e3 of n2) {
const n3 = e3.portPoints.find((e4) => e4.portPointId === t3);
if (n3?.connectionNodeIds) {
o2 = n3.connectionNodeIds;
break;
}
}
if (!o2 || o2.length !== 2)
return [e2, e2];
const [i2, r2] = o2;
return i2 && r2 ? so(i2, r2) : [e2, e2];
};
var lo = 0.000001;
var ho = (t3, e2) => Math.abs(t3 - e2) <= lo;
var uo = ({ nodeAId: t3, nodeBId: e2, nodeBounds: n2 }) => {
if (t3 === e2)
return null;
const o2 = n2.get(t3), i2 = n2.get(e2);
if (!o2 || !i2)
return null;
const r2 = so(t3, e2), s2 = ao(r2);
if (ho(o2.maxX, i2.minX) || ho(i2.maxX, o2.minX)) {
const n3 = Math.max(o2.minY, i2.minY), a2 = Math.min(o2.maxY, i2.maxY), c2 = a2 - n3;
if (c2 > lo) {
const l2 = ho(o2.maxX, i2.minX) ? o2.maxX : o2.minX;
return { ownerNodeIds: r2, ownerPairKey: s2, orientation: "vertical", x1: l2, y1: n3, x2: l2, y2: a2, center: { x: l2, y: (n3 + a2) / 2 }, length: c2, nodeSideByOwnerId: ho(o2.maxX, i2.minX) ? { [t3]: "right", [e2]: "left" } : { [t3]: "left", [e2]: "right" } };
}
}
if (ho(o2.maxY, i2.minY) || ho(i2.maxY, o2.minY)) {
const n3 = Math.max(o2.minX, i2.minX), a2 = Math.min(o2.maxX, i2.maxX), c2 = a2 - n3;
if (c2 > lo) {
const l2 = ho(o2.maxY, i2.minY) ? o2.maxY : o2.minY;
return { ownerNodeIds: r2, ownerPairKey: s2, orientation: "horizontal", x1: n3, y1: l2, x2: a2, y2: l2, center: { x: (n3 + a2) / 2, y: l2 }, length: c2, nodeSideByOwnerId: ho(o2.maxY, i2.minY) ? { [t3]: "top", [e2]: "bottom" } : { [t3]: "bottom", [e2]: "top" } };
}
}
return null;
};
var po = ({ portPoint: t3, ownerNodeIds: e2, inputNodes: n2 }) => {
for (const o2 of e2) {
const e3 = n2.find((t4) => t4.capacityMeshNodeId === o2);
if (e3?._containsTarget)
return true;
const i2 = e3?.portPoints.find((e4) => e4.portPointId === t3.portPointId);
if (i2?.connectionNodeIds?.some((t4) => n2.find((e4) => e4.capacityMeshNodeId === t4)?._containsTarget))
return true;
}
return false;
};
var mo = (t3, e2) => t3 === "top" ? 0 : t3 === "bottom" ? e2 - 1 : parseInt(t3.slice(5));
function go(t3, e2) {
return [...new Set(t3)].filter((t4) => Number.isInteger(t4) && t4 >= 0 && t4 < e2).sort((t4, e3) => t4 - e3);
}
function fo(t3, e2) {
return go(t3.map((t4) => mo(t4, e2)), e2);
}
var yo = 0.000001;
var _o = ({ sharedEdge: t3, obstacles: e2, z: n2, layerCount: o2 }) => {
for (const i2 of e2) {
const e3 = i2.zLayers ?? (o2 === undefined ? undefined : i2.layers.map((t4) => mo(t4, o2)));
if (n2 !== undefined && e3 && !e3.includes(n2))
continue;
const r2 = i2.center.x - i2.width / 2, s2 = i2.center.x + i2.width / 2, a2 = i2.center.y - i2.height / 2, c2 = i2.center.y + i2.height / 2;
if (t3.orientation !== "vertical") {
if (Math.abs(t3.y1 - a2) < yo || Math.abs(t3.y1 - c2) < yo) {
const e4 = Math.max(t3.x1, r2);
if (Math.min(t3.x2, s2) - e4 > yo)
return true;
}
} else if (Math.abs(t3.x1 - r2) < yo || Math.abs(t3.x1 - s2) < yo) {
const e4 = Math.max(t3.y1, a2);
if (Math.min(t3.y2, c2) - e4 > yo)
return true;
}
}
return false;
};
var bo = class extends kt {
constructor(t3) {
super(), this.input = t3;
for (const e3 of t3.nodeWithPortPoints)
this.mapOfNodeIdToBounds.set(e3.capacityMeshNodeId, t3.useLayerAwareGeometry ? { minX: e3.center.x - e3.width / 2, maxX: e3.center.x + e3.width / 2, minY: e3.center.y - e3.height / 2, maxY: e3.center.y + e3.height / 2 } : ro(e3));
const e2 = new Map;
for (const n2 of t3.nodeWithPortPoints)
for (const o2 of n2.portPoints) {
if (!o2.portPointId)
continue;
const i2 = co({ portPointId: o2.portPointId, currentNodeId: n2.capacityMeshNodeId, inputNodes: t3.inputNodesWithPortPoints }), r2 = ao(i2), s2 = this.mapOfOwnerPairToPortPoints.get(r2) ?? [];
s2.some((t4) => t4.portPointId && t4.portPointId === o2.portPointId) || s2.push({ ...o2, ownerNodeIds: i2, ownerPairKey: r2 }), this.mapOfOwnerPairToPortPoints.set(r2, s2), e2.set(r2, i2);
}
this.mapOfOwnerPairToSharedEdge = (({ ownerPairs: t4, nodeBounds: e3 }) => {
const n2 = new Map;
for (const o2 of t4) {
const [t5, i2] = o2;
if (t5 === i2)
continue;
const r2 = uo({ nodeAId: t5, nodeBId: i2, nodeBounds: e3 });
r2 && n2.set(ao(o2), r2);
}
return n2;
})({ ownerPairs: Array.from(e2.values()), nodeBounds: this.mapOfNodeIdToBounds }), this.ownerPairsToProcess = Array.from(this.mapOfOwnerPairToSharedEdge.keys()), this.ownerPairsToProcess.sort((t4, e3) => {
const n2 = this.mapOfOwnerPairToSharedEdge.get(t4), o2 = this.mapOfOwnerPairToSharedEdge.get(e3);
return n2.center.x - o2.center.x || n2.center.y - o2.center.y;
});
}
getSolverName() {
return "UniformPortDistributionSolver";
}
mapOfNodeIdToBounds = new Map;
mapOfOwnerPairToPortPoints = new Map;
mapOfOwnerPairToSharedEdge = new Map;
ownerPairsToProcess = [];
currentOwnerPairBeingProcessed = null;
redistributedNodes = [];
step() {
if (this.ownerPairsToProcess.length === 0)
return this.rebuildNodes(), void (this.solved = true);
this.currentOwnerPairBeingProcessed = this.ownerPairsToProcess.shift();
const t3 = this.currentOwnerPairBeingProcessed, e2 = this.mapOfOwnerPairToSharedEdge.get(t3);
if (!e2)
return;
const n2 = this.mapOfOwnerPairToPortPoints.get(t3) ?? [], o2 = _o({ sharedEdge: e2, obstacles: this.input.obstacles });
if (!this.input.useLayerAwareGeometry && o2)
return;
const i2 = new Map;
for (const t4 of n2)
i2.set(t4.z, (i2.get(t4.z) ?? 0) + 1);
const r2 = [];
for (const t4 of n2)
this.input.preserveSolitaryPorts && o2 && i2.get(t4.z) === 1 || _o({ sharedEdge: e2, obstacles: this.input.obstacles, z: this.input.useLayerAwareGeometry ? t4.z : undefined, layerCount: this.input.layerCount }) || po({ portPoint: t4, ownerNodeIds: t4.ownerNodeIds, inputNodes: this.input.inputNodesWithPortPoints }) || r2.push(t4);
const s2 = (({ sharedEdge: t4, portPoints: e3 }) => {
if (e3.length === 0)
return [];
const n3 = new Map;
for (const t5 of e3) {
const e4 = t5.z ?? 0, o4 = n3.get(e4) ?? [];
o4.push(t5), n3.set(e4, o4);
}
const o3 = [], i3 = Array.from(n3.keys()).sort((t5, e4) => t5 - e4);
for (const e4 of i3) {
const i4 = n3.get(e4), r3 = i4.length;
i4.sort((e5, n4) => t4.orientation === "horizontal" ? e5.x - n4.x : e5.y - n4.y);
for (let e5 = 0;e5 < r3; e5++) {
const n4 = (2 * e5 + 1) / (2 * r3), s3 = t4.orientation === "horizontal" ? t4.x1 + t4.length * n4 : t4.x1, a2 = t4.orientation === "horizontal" ? t4.y1 : t4.y1 + t4.length * n4;
o3.push({ ...i4[e5], x: s3, y: a2 });
}
}
return o3;
})({ sharedEdge: e2, portPoints: r2 });
this.mapOfOwnerPairToPortPoints.set(t3, s2);
}
rebuildNodes() {
const t3 = new Map;
for (const e3 of this.mapOfOwnerPairToPortPoints.values())
for (const n2 of e3)
n2.portPointId && t3.set(n2.portPointId, { x: n2.x, y: n2.y });
const e2 = (e3) => {
if (e3.portPointId && t3.has(e3.portPointId)) {
const n2 = t3.get(e3.portPointId);
return { ...e3, x: n2.x, y: n2.y };
}
return e3;
};
this.redistributedNodes = this.input.nodeWithPortPoints.map((t4) => ({ ...t4, portPoints: t4.portPoints.map(e2), portPointsInPairs: t4.portPointsInPairs?.map(([t5, n2]) => [e2(t5), e2(n2)]) }));
}
getOutput = () => this.redistributedNodes;
visualize() {
return (({ obstacles: t3, nodeWithPortPoints: e2, mapOfOwnerPairToPortPoints: n2, mapOfOwnerPairToSharedEdge: o2, ownerPairsToProcess: i2, currentOwnerPairBeingProcessed: r2, mapOfNodeIdToBounds: s2 }) => {
const a2 = t3.filter((t4) => !t4.isCopperPour).map((t4) => ({ ...t4, fill: "#ec000070" })), c2 = [], l2 = [], h2 = new Map, d2 = new Map, u2 = new Map, p2 = (t4) => t4.portPointId ? h2.get(t4.portPointId) ?? { x: t4.x, y: t4.y } : { x: t4.x, y: t4.y };
for (const t4 of e2)
for (const e3 of t4.portPoints)
e3.portPointId && (h2.set(e3.portPointId, { x: e3.x, y: e3.y }), d2.set(e3.portPointId, e3.z ?? 0));
for (const t4 of n2.values())
for (const e3 of t4)
e3.portPointId && (h2.set(e3.portPointId, { x: e3.x, y: e3.y }), d2.set(e3.portPointId, e3.z ?? 0), u2.set(e3.portPointId, `${e3.ownerNodeIds[0]}&${e3.ownerNodeIds[1]}`));
e2.forEach((t4) => {
const e3 = s2.get(t4.capacityMeshNodeId);
if (e3) {
const n3 = (e3.minX + e3.maxX) / 2, o3 = (e3.minY + e3.maxY) / 2, i3 = e3.maxX - e3.minX, r3 = e3.maxY - e3.minY;
a2.push({ center: { x: n3, y: o3 }, width: i3, height: r3, fill: "#00000030", label: `${t4.capacityMeshNodeId}` });
}
t4.portPoints.forEach((e4) => {
if (!e4.portPointId)
return;
const n3 = h2.get(e4.portPointId), o3 = d2.get(e4.portPointId) ?? 0, i3 = u2.get(e4.portPointId) ?? `${t4.capacityMeshNodeId}&${t4.capacityMeshNodeId}`;
c2.push({ x: n3.x, y: n3.y, label: `z:${o3}
o:${i3}` }), t4.portPointsInPairs?.length || t4.portPoints.forEach((t5) => {
if (t5.portPointId && e4 !== t5 && e4.connectionName === t5.connectionName) {
const e5 = h2.get(t5.portPointId);
l2.push({ points: [n3, e5], strokeColor: "#fff822c9" });
}
});
}), t4.portPointsInPairs?.forEach(([t5, e4]) => {
l2.push({ points: [p2(t5), p2(e4)], strokeColor: "#fff822c9" });
});
});
for (const t4 of i2) {
const e3 = o2.get(t4);
e3 && l2.push({ points: [{ x: e3.x1, y: e3.y1 }, { x: e3.x2, y: e3.y2 }], strokeColor: "orange", strokeWidth: 0.01 });
}
if (r2) {
const t4 = o2.get(r2);
t4 && (l2.push({ points: [{ x: t4.x1, y: t4.y1 }, { x: t4.x2, y: t4.y2 }], strokeColor: "red", strokeWidth: 0.03 }), c2.push({ x: t4.center.x, y: t4.center.y, label: t4.ownerPairKey }));
}
for (const t4 of o2.values())
l2.push({ points: [{ x: t4.x1, y: t4.y1 }, { x: t4.x2, y: t4.y2 }], strokeColor: "#33b5ff80", strokeWidth: 0.006 });
return { rects: a2, lines: l2, points: c2 };
})({ obstacles: this.input.obstacles, nodeWithPortPoints: this.input.nodeWithPortPoints, mapOfOwnerPairToPortPoints: this.mapOfOwnerPairToPortPoints, mapOfOwnerPairToSharedEdge: this.mapOfOwnerPairToSharedEdge, ownerPairsToProcess: this.ownerPairsToProcess, currentOwnerPairBeingProcessed: this.currentOwnerPairBeingProcessed, mapOfNodeIdToBounds: this.mapOfNodeIdToBounds });
}
};
var xo = (t3, e2, n2) => t3.connectedTo.some((t4) => t4 === e2.connectionName || t4 === e2.rootConnectionName || (n2?.areIdsConnected(e2.connectionName, t4) ?? false) || e2.rootConnectionName !== undefined && (n2?.areIdsConnected(e2.rootConnectionName, t4) ?? false));
function vo(t3) {
return !("layers" in t3) && typeof t3.layer == "string";
}
function Io(t3) {
return So(t3)[0];
}
function So(t3) {
if (function(t4) {
return !("layer" in t4) && Array.isArray(t4.layers);
}(t3))
return t3.layers;
if (vo(t3))
return [t3.layer];
throw new Error("Connection point must specify either layer or layers, never both");
}
var Co = (t3, e2) => {
if (t3 === 1 && e2 === 1)
return "inner1";
if (t3 < 0 || t3 >= e2)
throw new Error(`Invalid z "${t3}" for layer count: ${e2}`);
return t3 === 0 ? "top" : t3 === e2 - 1 ? "bottom" : `inner${t3}`;
};
var Po = (t3, e2) => !!t3 && !!e2 && Math.abs(t3.x - e2.x) <= 0.000000000001 && Math.abs(t3.y - e2.y) <= 0.000000000001;
var Mo = (t3, e2) => Fe(t3, e2) <= 0.000001;
var No = (t3, e2, n2, o2) => e2.toNextSegmentType === "through_obstacle" || (o2.connectedMultilayerObstacles ? o2.connectedMultilayerObstacles.some((t4) => Mo(e2, t4) && Mo(n2, t4)) : o2.obstacles?.some((i2) => ((t4) => (t4.__zLayers?.length ?? t4.layers?.length ?? 0) > 1)(i2) && Mo(e2, i2) && Mo(n2, i2) && xo(i2, t3, o2.connMap)) ?? false);
var wo = ({ endpoint: t3, endpointLayer: e2, connectionPoints: n2, tolerance: o2 }) => {
let i2;
for (const r2 of n2) {
if (!vo(r2) || !r2.terminalVia)
continue;
if (r2.layer !== e2)
continue;
const n3 = xe(r2, t3);
n3 > o2 || (!i2 || n3 < i2.distance) && (i2 = { point: r2, distance: n3 });
}
return i2?.point;
};
var To = (t3, e2, n2 = {}) => {
const o2 = [];
if (t3.route.length === 0)
return o2;
let i2 = [], r2 = t3.route[0].z;
for (let s3 = 0;s3 < t3.route.length; s3++) {
const a2 = t3.route[s3];
if (a2.z !== r2) {
const s4 = i2[i2.length - 1], c2 = Co(r2, e2);
for (const e3 of i2)
o2.push({ route_type: "wire", x: e3.x, y: e3.y, width: e3.traceThickness ?? t3.traceThickness, layer: c2 });
const l2 = Co(a2.z, e2);
if (s4 && No(t3, s4, a2, n2))
o2.push({ route_type: "through_obstacle", start: { x: s4.x, y: s4.y }, end: { x: a2.x, y: a2.y }, from_layer: c2, to_layer: l2, width: s4.traceThickness ?? t3.traceThickness, ...s4.toNextSegmentCircuitJsonMetadata ? { circuitJsonMetadata: s4.toNextSegmentCircuitJsonMetadata } : {} });
else {
t3.vias.some((t4) => Math.abs(t4.x - a2.x) < 0.001 && Math.abs(t4.y - a2.y) < 0.001) && o2.push({ route_type: "via", x: a2.x, y: a2.y, from_layer: c2, to_layer: l2, via_diameter: t3.viaDiameter, ...n2.defaultViaHoleDiameter !== undefined ? { via_hole_diameter: n2.defaultViaHoleDiameter } : {} });
}
i2 = [a2], r2 = a2.z;
} else
Po(i2[i2.length - 1], a2) || i2.push(a2);
}
const s2 = Co(r2, e2);
for (const e3 of i2)
o2.push({ route_type: "wire", x: e3.x, y: e3.y, width: e3.traceThickness ?? t3.traceThickness, layer: s2 });
if (t3.jumpers && t3.jumpers.length > 0) {
const n3 = Co(t3.route[0]?.z ?? 0, e2);
for (const e3 of t3.jumpers)
o2.push({ route_type: "jumper", start: e3.start, end: e3.end, footprint: e3.footprint, layer: n3 });
}
return (({ route: t4, hdRoute: e3, layerCount: n3, connectionPoints: o3 = [], tolerance: i3 = 0.25, defaultViaHoleDiameter: r3 }) => {
if (t4.length === 0 || e3.route.length === 0 || !o3.length)
return t4;
if (!o3.some((t5) => vo(t5) && t5.terminalVia))
return t4;
const s3 = t4.filter((t5) => t5.route_type !== "jumper"), a2 = t4.filter((t5) => t5.route_type === "jumper");
if (s3.length === 0)
return t4;
const c2 = e3.route[0], l2 = e3.route[e3.route.length - 1], h2 = Co(c2.z, n3), d2 = Co(l2.z, n3), u2 = wo({ endpoint: c2, endpointLayer: h2, connectionPoints: o3, tolerance: i3 }), p2 = wo({ endpoint: l2, endpointLayer: d2, connectionPoints: o3, tolerance: i3 }), m2 = [], g2 = [], f2 = s3[0], y2 = s3[s3.length - 1], _2 = c2.traceThickness ?? e3.traceThickness, b2 = l2.traceThickness ?? e3.traceThickness;
return u2?.terminalVia && (m2.push({ route_type: "via", x: u2.x, y: u2.y, from_layer: u2.layer, to_layer: u2.terminalVia.toLayer, via_diameter: u2.terminalVia.viaDiameter ?? e3.viaDiameter, ...r3 !== undefined ? { via_hole_diameter: r3 } : {} }), f2?.route_type === "wire" && f2.layer === u2.layer && Po(f2, u2) || m2.push({ route_type: "wire", x: u2.x, y: u2.y, width: _2, layer: u2.layer })), p2?.terminalVia && (y2?.route_type === "wire" && y2.layer === p2.layer && Po(y2, p2) || g2.push({ route_type: "wire", x: p2.x, y: p2.y, width: b2, layer: p2.layer }), g2.push({ route_type: "via", x: p2.x, y: p2.y, from_layer: p2.layer, to_layer: p2.terminalVia.toLayer, via_diameter: p2.terminalVia.viaDiameter ?? e3.viaDiameter, ...r3 !== undefined ? { via_hole_diameter: r3 } : {} })), [...m2, ...s3, ...g2, ...a2];
})({ route: o2, hdRoute: t3, layerCount: e2, connectionPoints: n2.connectionPoints, tolerance: n2.terminalViaAttachTolerance, defaultViaHoleDiameter: n2.defaultViaHoleDiameter });
};
var Eo = (t3, e2) => {
const n2 = {};
for (let o2 = 0;o2 < t3.connections.length; o2++) {
const i2 = t3.connections[o2], r2 = e2?.getNetConnectedToId(i2.name);
r2 && !n2[r2] && (n2[r2] = `hsl(${300 * o2 / t3.connections.length}, 100%, 50%)`), n2[i2.name] = (r2 ? n2[r2] : null) ?? `hsl(${340 * o2 / t3.connections.length}, 100%, 50%)`;
}
return n2;
};
var Ao = (t3, e2) => {
try {
return Tt(e2, t3);
} catch (e3) {
return console.error(e3), t3;
}
};
var Oo = (t3, e2 = 1) => {
if (!t3)
return "rgba(0, 0, 0, 0.5)";
const n2 = 300 * t3.split("").reduce((t4, e3) => t4 + e3.charCodeAt(0), 0) / t3.length % 360;
return e2 < 1 ? `hsla(${n2}, 100%, 50%, ${e2})` : `hsl(${n2}, 100%, 50%)`;
};
var ko = (t3) => {
const e2 = new Set;
return t3.filter((t4) => !e2.has(t4) && (e2.add(t4), true));
};
var Do = (t3, e2, n2) => {
if (!e2)
return;
const o2 = t3.get(e2);
o2 ? o2.includes(n2) || o2.push(n2) : t3.set(e2, [n2]);
};
var Lo = (t3) => {
const e2 = new Map;
for (const n2 of t3.connections) {
const t4 = n2.__rootConnectionNames ?? [n2.name];
for (const o2 of t4) {
Do(e2, n2.name, o2), Do(e2, o2, o2), Do(e2, n2.__netConnectionName, o2);
for (const t5 of n2.pointsToConnect)
Do(e2, t5.pointId, o2), Do(e2, t5.pcb_port_id, o2);
}
}
return (t4) => ((t5, e3 = []) => {
const n2 = ko(e3).join(", ");
return t5.layers.map((t6) => n2 ? `${t6}
${n2}` : t6).join(`
`);
})(t4, ((t5, e3) => ko([...t5.connectedTo.flatMap((t6) => e3.get(t6) ?? []), ...(t5.offBoardConnectsTo ?? []).flatMap((t6) => e3.get(t6) ?? [])]))(t4, e2));
};
var zo = (t3, e2) => `z${fo(t3, e2).join(",")}`;
var Bo = (t3, e2) => zo(So(t3), e2);
var Fo = (t3, e2) => t3.__zLayers && t3.__zLayers.length > 0 ? go(t3.__zLayers, e2) : fo(t3.layers, e2);
var jo = (t3, e2) => `z${Fo(t3, e2).join(",")}`;
var $o = (...t3) => t3.find((t4) => typeof t4 == "number" && Number.isFinite(t4));
var Yo = (t3) => {
const e2 = $o(t3.min_via_hole_diameter, t3.minViaHoleDiameter), n2 = $o(t3.min_via_pad_diameter, t3.minViaPadDiameter, t3.minViaDiameter), o2 = Math.max(n2 ?? t3.minViaDiameter ?? 0.3, e2 ?? 0);
return { padDiameter: o2, holeDiameter: e2 ?? 0.5 * o2 };
};
var Xo = { "0603": { length: 1.65, width: 0.95, padLength: 0.8, padWidth: 0.95 }, 1206: { length: 3.2, width: 1.6, padLength: 0.6, padWidth: 1.6 }, "1206x4_pair": { length: 2.7, width: 0.5, padLength: 0.8, padWidth: 0.5 } };
var Wo = { top: "red", bottom: "blue", inner1: "green", inner2: "yellow", inner3: "orange", inner4: "purple", inner5: "cyan", inner6: "magenta", inner7: "lime", inner8: "brown" };
function Vo(t3) {
if (Object.hasOwn(Wo, t3))
return Wo[t3];
const e2 = /^inner([1-9]\d*)$/.exec(t3);
if (e2) {
return `hsl(${137 * Number(e2[1]) % 360}, 70%, 45%)`;
}
throw new Error(`No visualization color for layer "${t3}"`);
}
var Ho = (t3, e2 = {}) => {
const n2 = [], o2 = [], i2 = [], r2 = [], s2 = Eo(t3), a2 = e2.traceColorMode ?? "layer", c2 = t3.layerCount, l2 = Yo(t3), h2 = Lo(t3);
if (t3.connections)
for (const e3 of t3.connections)
for (const t4 of e3.pointsToConnect) {
const n3 = So(t4), o3 = e3.__rootConnectionNames ?? [e3.name];
i2.push({ x: t4.x, y: t4.y, color: s2[e3.name], layer: Bo(t4, c2), label: [e3.name, o3.join(", "), n3.join(",")].join(`
`) });
}
if (t3.traces)
for (const e3 of t3.traces) {
let i3 = t3.minTraceWidth;
const h3 = e3.route.filter((t4) => t4.route_type === "jumper"), d2 = (t4, e4) => {
const n3 = 0.01;
for (const o3 of h3) {
const i4 = Math.abs(t4.x - o3.start.x) < n3 && Math.abs(t4.y - o3.start.y) < n3 && Math.abs(e4.x - o3.end.x) < n3 && Math.abs(e4.y - o3.end.y) < n3, r3 = Math.abs(t4.x - o3.end.x) < n3 && Math.abs(t4.y - o3.end.y) < n3 && Math.abs(e4.x - o3.start.x) < n3 && Math.abs(e4.y - o3.start.y) < n3;
if (i4 || r3)
return true;
}
return false;
};
for (const t4 of e3.route)
if (t4.route_type === "via") {
const n3 = mo(t4.from_layer, c2), i4 = mo(t4.to_layer, c2), r3 = (t4.via_diameter ?? l2.padDiameter) / 2, h4 = Array.from({ length: Math.abs(i4 - n3) + 1 }, (t5, e4) => Math.min(n3, i4) + e4);
o2.push({ center: { x: t4.x, y: t4.y }, radius: r3, fill: a2 === "net" ? s2[e3.connection_name] : "blue", stroke: "none", layer: `z${h4.join(",")}` });
} else if (t4.route_type === "through_obstacle") {
const o3 = s2[e3.connection_name] ?? "purple";
n2.push({ points: [t4.start, t4.end], strokeColor: Ao(o3, 0.35), strokeWidth: t4.width, strokeDash: [0.1, 0.1], layer: zo([t4.from_layer, t4.to_layer], c2), label: `${e3.connection_name} through_obstacle` });
}
let u2;
for (let t4 = 0;t4 < e3.route.length - 1; t4++) {
const o3 = e3.route[t4], l3 = e3.route[t4 + 1];
if (o3.route_type === "jumper") {
u2 = undefined;
const t5 = s2[e3.connection_name] ?? "rgba(255, 165, 0, 0.8)", i4 = o3.footprint, a3 = Xo[i4 === "1206x4_pair" ? "1206x4_pair" : "0603"] ?? Xo["0603"], l4 = o3.end.x - o3.start.x, h4 = o3.end.y - o3.start.y, d3 = Math.abs(l4) > Math.abs(h4), p2 = d3 ? a3.padLength : a3.padWidth, m2 = d3 ? a3.padWidth : a3.padLength;
r2.push({ center: o3.start, width: p2, height: m2, fill: Ao(t5, 0.5), stroke: "rgba(0, 0, 0, 0.5)", layer: zo([o3.layer], c2) }), r2.push({ center: o3.end, width: p2, height: m2, fill: Ao(t5, 0.5), stroke: "rgba(0, 0, 0, 0.5)", layer: zo([o3.layer], c2) }), n2.push({ points: [o3.start, o3.end], strokeColor: "rgba(100, 100, 100, 0.8)", strokeWidth: 0.3 * a3.padWidth, layer: zo([o3.layer], c2) });
} else if (o3.route_type === "wire" && l3.route_type === "wire" && l3.layer === o3.layer) {
if (d2({ x: o3.x, y: o3.y }, { x: l3.x, y: l3.y })) {
u2 = undefined;
continue;
}
i3 = o3.width;
const t5 = o3.layer === "top", r3 = a2 === "net" ? s2[e3.connection_name] : Vo(o3.layer), h4 = `z${mo(o3.layer, c2)}`;
if (u2 && u2.layer === h4 && u2.strokeWidth === i3) {
u2.points.push({ x: l3.x, y: l3.y });
continue;
}
u2 = { points: [{ x: o3.x, y: o3.y }, { x: l3.x, y: l3.y }], layer: h4, strokeWidth: i3, strokeColor: t5 ? r3 : Ao(r3, 0.5), ...a2 === "net" ? { label: e3.connection_name } : {}, ...t5 ? {} : { strokeDash: [0.2, 0.2] } }, n2.push(u2);
} else
u2 = undefined;
}
}
for (const e3 of t3.obstacles) {
if (e3.isCopperPour)
continue;
const t4 = Fo(e3, c2);
if (t4.length === 0)
throw new Error(`Cannot visualize obstacle "${e3.obstacleId ?? "unknown"}" without a valid layer: layers=${e3.layers.join(",")}, __zLayers=${e3.__zLayers?.join(",") ?? "unset"}, layerCount=${c2}`);
const n3 = Vo((t4.length === 1 ? Co(t4[0], c2) : null) === "bottom" ? "bottom" : "top"), o3 = 0.5 ** t4.length;
r2.push({ center: e3.center, width: e3.width, height: e3.height, ccwRotationDegrees: e3.ccwRotationDegrees, fill: Ao(n3, o3), layer: jo(e3, c2), label: h2(e3) });
}
if (t3.jumpers)
for (const e3 of t3.jumpers)
for (const t4 of e3.pads)
r2.push({ center: t4.center, width: t4.width, height: t4.height, ccwRotationDegrees: t4.ccwRotationDegrees, fill: "rgba(255, 165, 0, 0.3)", stroke: "rgba(255, 165, 0, 0.8)", layer: jo(t4, c2) });
return { rects: r2, circles: o2, lines: n2, points: i2 };
};
function Go([t3, e2], [n2, o2], { lineThickness: i2 = 0 } = {}) {
if (i2 === 0)
return Uo(t3, e2, n2, o2);
const r2 = function(t4, e3, n3, o3) {
if (t4.x === e3.x && t4.y === e3.y)
return Jo(t4, n3, o3);
if (n3.x === o3.x && n3.y === o3.y)
return Jo(n3, t4, e3);
if (Uo(t4, e3, n3, o3))
return 0;
const i3 = [Jo(t4, n3, o3), Jo(e3, n3, o3), Jo(n3, t4, e3), Jo(o3, t4, e3)];
return Math.min(...i3);
}(t3, e2, n2, o2);
return r2 <= i2;
}
function Uo(t3, e2, n2, o2) {
const i2 = Zo(t3, e2, n2), r2 = Zo(t3, e2, o2), s2 = Zo(n2, o2, t3), a2 = Zo(n2, o2, e2);
return i2 !== r2 && s2 !== a2 || (!(i2 !== 0 || !qo(t3, n2, e2)) || (!(r2 !== 0 || !qo(t3, o2, e2)) || (!(s2 !== 0 || !qo(n2, t3, o2)) || !(a2 !== 0 || !qo(n2, e2, o2)))));
}
function Zo(t3, e2, n2) {
const o2 = (e2.y - t3.y) * (n2.x - e2.x) - (e2.x - t3.x) * (n2.y - e2.y);
return o2 === 0 ? 0 : o2 > 0 ? 1 : 2;
}
function qo(t3, e2, n2) {
return e2.x <= Math.max(t3.x, n2.x) && e2.x >= Math.min(t3.x, n2.x) && e2.y <= Math.max(t3.y, n2.y) && e2.y >= Math.min(t3.y, n2.y);
}
function Jo(t3, e2, n2) {
const o2 = (n2.x - e2.x) ** 2 + (n2.y - e2.y) ** 2;
if (o2 === 0)
return Qo(t3, e2);
let i2 = ((t3.x - e2.x) * (n2.x - e2.x) + (t3.y - e2.y) * (n2.y - e2.y)) / o2;
i2 = Math.max(0, Math.min(1, i2));
return Qo(t3, { x: e2.x + i2 * (n2.x - e2.x), y: e2.y + i2 * (n2.y - e2.y) });
}
function Qo(t3, e2) {
const n2 = t3.x - e2.x, o2 = t3.y - e2.y;
return Math.sqrt(n2 * n2 + o2 * o2);
}
function Ko(t3) {
const e2 = new Map;
let n2 = 0;
function o2(t4) {
for (const [, n3] of e2)
if (n3.has(t4))
return n3;
const o3 = new Set;
return e2.set("connectivity_net" + n2++, o3), o3;
}
for (const n3 of t3) {
let t4 = null;
for (const i2 of n3) {
if (t4) {
if (!t4.has(i2)) {
const n4 = o2(i2);
if (n4 !== t4) {
for (const e3 of n4)
t4.add(e3);
e2.delete(Array.from(e2.entries()).find(([, t5]) => t5 === n4)[0]);
}
}
} else
t4 = o2(i2);
t4.add(i2);
}
}
return Object.fromEntries(Array.from(e2.entries()).map(([t4, e3]) => [t4, Array.from(e3)]));
}
var ti = class {
netMap;
idToNetMap;
constructor(t3) {
this.netMap = t3, this.idToNetMap = {};
for (const [e2, n2] of Object.entries(t3))
for (const t4 of n2)
this.idToNetMap[t4] = e2;
}
addConnections(t3) {
for (const e2 of t3) {
const t4 = new Set;
for (const n3 of e2) {
const e3 = this.idToNetMap[n3];
e3 && t4.add(e3);
}
let n2;
if (t4.size === 0)
n2 = `connectivity_net${Object.keys(this.netMap).length}`, this.netMap[n2] = [];
else if (t4.size === 1)
n2 = t4.values().next().value ?? `connectivity_net${Object.keys(this.netMap).length}`;
else {
n2 = t4.values().next().value ?? `connectivity_net${Object.keys(this.netMap).length}`;
for (const e3 of t4)
if (e3 !== n2) {
this.netMap[n2].push(...this.netMap[e3]), this.netMap[e3] = this.netMap[n2];
for (const t5 of this.netMap[n2])
this.idToNetMap[t5] = n2;
}
}
for (const t5 of e2)
this.netMap[n2].includes(t5) || this.netMap[n2].push(t5), this.idToNetMap[t5] = n2;
}
}
getIdsConnectedToNet(t3) {
return this.netMap[t3] || [];
}
getNetConnectedToId(t3) {
return this.idToNetMap[t3];
}
areIdsConnected(t3, e2) {
if (t3 === e2)
return true;
const n2 = this.getNetConnectedToId(t3);
if (!n2)
return false;
const o2 = this.getNetConnectedToId(e2);
return !!o2 && (n2 === o2 || o2 === t3 || o2 === t3);
}
areAllIdsConnected(t3) {
const e2 = this.getNetConnectedToId(t3[0]);
for (const n2 of t3) {
const t4 = this.getNetConnectedToId(n2);
if (t4 === undefined)
return false;
if (t4 !== e2)
return false;
}
return true;
}
};
var ei = (t3) => {
const e2 = [];
for (const n3 of t3)
if (n3.type === "source_trace")
e2.push([n3.source_trace_id, ...n3.connected_source_port_ids ?? [], ...n3.connected_source_net_ids ?? []].filter(Boolean));
else if (n3.type === "pcb_port") {
const { pcb_port_id: t4, source_port_id: o2 } = n3;
o2 && t4 && e2.push([o2, t4]);
} else if (n3.type === "pcb_smtpad") {
const { pcb_smtpad_id: t4, pcb_port_id: o2 } = n3;
o2 && t4 && e2.push([t4, o2]);
} else if (n3.type === "pcb_plated_hole") {
const { pcb_plated_hole_id: t4, pcb_port_id: o2 } = n3;
o2 && t4 && e2.push([t4, o2]);
} else if (n3.type === "pcb_trace") {
const { pcb_trace_id: t4, source_trace_id: o2 } = n3;
o2 && t4 && e2.push([t4, o2]);
}
const n2 = Ko(e2);
return new ti(n2);
};
var ni = class {
circuitJson;
traceIdToElm;
portIdToElm;
connMap;
constructor(t3) {
this.circuitJson = t3 || [], this.traceIdToElm = new Map, this.portIdToElm = new Map, t3 ? (this._buildTraceMap(), this._buildPortMap(), this.connMap = this._buildTraceConnectivityMap()) : this.connMap = new ti({});
}
_buildPortMap() {
for (const t3 of this.circuitJson)
t3.type === "pcb_port" && this.portIdToElm.set(t3.pcb_port_id, t3);
}
_buildTraceMap() {
for (const t3 of this.circuitJson)
t3.type === "pcb_trace" && this.traceIdToElm.set(t3.pcb_trace_id, t3);
}
_buildTraceConnectivityMap() {
const t3 = [], e2 = Array.from(this.traceIdToElm.keys());
for (let n2 = 0;n2 < e2.length; n2++)
for (let o2 = n2 + 1;o2 < e2.length; o2++) {
const i2 = this.traceIdToElm.get(e2[n2]), r2 = this.traceIdToElm.get(e2[o2]);
this._arePcbTracesConnected(i2, r2) && t3.push([e2[n2], e2[o2]]);
}
for (const e3 of this.portIdToElm.values())
for (const n2 of this.traceIdToElm.values())
for (const o2 of n2.route)
o2.route_type === "wire" && (o2.start_pcb_port_id === e3.pcb_port_id ? t3.push([e3.pcb_port_id, n2.pcb_trace_id]) : o2.end_pcb_port_id === e3.pcb_port_id && t3.push([n2.pcb_trace_id, e3.pcb_port_id]));
return new ti(Ko(t3));
}
addTrace(t3) {
this.traceIdToElm.set(t3.pcb_trace_id, t3);
const e2 = [];
for (const n2 of t3.route)
n2.route_type === "wire" && (n2.start_pcb_port_id && e2.push([n2.start_pcb_port_id, t3.pcb_trace_id]), n2.end_pcb_port_id && e2.push([n2.end_pcb_port_id, t3.pcb_trace_id]));
this.connMap.addConnections(e2);
}
_arePcbTracesConnected(t3, e2) {
for (let n2 = 0;n2 < t3.route.length - 1; n2++) {
const o2 = t3.route[n2], i2 = t3.route[n2 + 1];
if (o2.route_type === "wire" && i2.route_type === "wire")
for (let t4 = 0;t4 < e2.route.length - 1; t4++) {
const n3 = e2.route[t4], r2 = e2.route[t4 + 1];
if (n3.route_type !== "wire")
continue;
if (r2.route_type !== "wire")
continue;
if (Go([o2, i2], [n3, r2], { lineThickness: (o2.width + n3.width) / 2 }))
return true;
}
}
return false;
}
areTracesConnected(t3, e2) {
return this.connMap.areIdsConnected(t3, e2);
}
getAllTracesConnectedToTrace(t3) {
const e2 = this.connMap.getNetConnectedToId(t3);
return e2 ? this.connMap.getIdsConnectedToNet(e2).filter((t4) => this.traceIdToElm.has(t4)).map((t4) => this.traceIdToElm.get(t4)) : [];
}
getAllTracesConnectedToPort(t3) {
const e2 = this.connMap.getNetConnectedToId(t3);
return e2 ? this.connMap.getIdsConnectedToNet(e2).filter((t4) => this.traceIdToElm.has(t4)).map((t4) => this.traceIdToElm.get(t4)) : [];
}
};
var oi = (t3) => `${Math.round(100 * t3.x)},${Math.round(100 * t3.y)}`;
var ii = (t3) => {
const e2 = new ti({});
for (const n2 of t3.connections) {
for (const t4 of n2.__rootConnectionNames ?? [])
e2.addConnections([[n2.name, t4]]);
n2.__netConnectionName && e2.addConnections([[n2.name, n2.__netConnectionName]]);
for (const o2 of n2.pointsToConnect)
e2.addConnections([[n2.name, `${oi(o2)}:${So(o2).map((e3) => mo(e3, t3.layerCount)).sort().join("-")}`]]), "pcb_port_id" in o2 && o2.pcb_port_id && e2.addConnections([[n2.name, o2.pcb_port_id]]), o2.pointId && e2.addConnections([[n2.name, o2.pointId]]);
}
for (const n2 of t3.obstacles) {
const o2 = n2.offBoardConnectsTo ?? [], i2 = Array.from(new Set([n2.obstacleId, ...n2.connectedTo, ...o2, `${oi(n2.center)}:${n2.layers.map((e3) => mo(e3, t3.layerCount)).sort().join("-")}`].filter(Boolean)));
i2.length > 0 && e2.addConnections([i2]);
}
for (const n2 of t3.traces ?? []) {
const t4 = Array.from(new Set([n2.pcb_trace_id, n2.connection_name, ...n2.connectsTo ?? []].filter(Boolean)));
t4.length > 0 && e2.addConnections([t4]);
}
return e2;
};
var ri = (t3) => {
const e2 = new ti({});
for (const n2 of t3.connections) {
const t4 = n2.externallyConnectedPointIds ?? [];
e2.addConnections(t4);
}
for (const n2 of t3.traces ?? []) {
const t4 = n2.connectsTo ?? [];
t4.length !== 0 && e2.addConnections([[n2.pcb_trace_id, ...t4]]);
}
return e2;
};
var si = class {
MAX_ITERATIONS = 1000;
solved = false;
failed = false;
iterations = 0;
progress = 0;
error = null;
activeSubSolver;
failedSubSolvers;
timeToSolve;
stats = {};
pendingEffects;
cacheHit;
cacheKey;
cacheToSolveSpaceTransform;
getSolverName() {
return this.constructor.name;
}
step() {
if (!this.solved && !this.failed) {
this.iterations++;
try {
this._step();
} catch (t3) {
throw this.error = `${this.getSolverName()} error: ${t3}`, console.error(this.error), this.failed = true, t3;
}
!this.solved && this.iterations > this.MAX_ITERATIONS && this.tryFinalAcceptance(), !this.solved && this.iterations > this.MAX_ITERATIONS && (this.error = `${this.getSolverName()} ran out of iterations (MAX_ITERATIONS=${this.MAX_ITERATIONS})`, this.failed = true), "computeProgress" in this && (this.progress = this.computeProgress());
}
}
_step() {}
getConstructorParams() {
throw new Error("getConstructorParams not implemented");
}
solve() {
const t3 = Date.now();
for (;!this.solved && !this.failed; )
this.step();
const e2 = Date.now();
this.timeToSolve = e2 - t3;
}
visualize() {
return { lines: [], points: [], rects: [], circles: [] };
}
tryFinalAcceptance() {}
preview() {
return { lines: [], points: [], rects: [], circles: [] };
}
};
function ai(t3) {
const e2 = new Map;
for (const n2 of t3)
for (const t4 of n2.nodeIds)
e2.set(t4, [...e2.get(t4) ?? [], n2]);
return e2;
}
var ci = class extends si {
getSolverName() {
return "AvailableSegmentPointSolver";
}
nodes;
edges;
traceWidth;
obstacleMargin;
minPortSpacing;
nodeMap;
nodeEdgeMap;
sharedEdgeSegments = [];
edgeSegmentMap = new Map;
portPointMap = new Map;
colorMap;
shouldReturnCrampedPortPoints;
constructor({ nodes: t3, edges: e2, traceWidth: n2, obstacleMargin: o2, colorMap: i2, shouldReturnCrampedPortPoints: r2 }) {
super(), this.nodes = t3, this.edges = e2, this.traceWidth = n2, this.obstacleMargin = o2 ?? 0.15, this.shouldReturnCrampedPortPoints = r2, this.minPortSpacing = this.traceWidth + this.obstacleMargin, this.colorMap = i2 ?? {}, this.nodeMap = new Map(t3.map((t4) => [t4.capacityMeshNodeId, t4])), this.nodeEdgeMap = ai(e2), this.MAX_ITERATIONS = 1;
}
_step() {
this.computeAllSharedEdgeSegments(), this.solved = true;
}
computeAllSharedEdgeSegments() {
for (const t3 of this.edges) {
const [e2, n2] = t3.nodeIds, o2 = this.nodeMap.get(e2), i2 = this.nodeMap.get(n2);
if (!o2 || !i2)
continue;
const r2 = this.computeSharedEdgeSegment(t3, o2, i2);
if (r2) {
this.sharedEdgeSegments.push(r2), this.edgeSegmentMap.set(t3.capacityMeshEdgeId, r2);
for (const t4 of r2.portPoints)
this.portPointMap.set(t4.segmentPortPointId, t4);
}
}
}
computeSharedEdgeSegment(t3, e2, n2) {
const o2 = this.findOverlappingSegment(e2, n2);
if (!o2)
return null;
const i2 = e2.availableZ.filter((t4) => n2.availableZ.includes(t4));
if (i2.length === 0)
return null;
const r2 = Math.sqrt((o2.end.x - o2.start.x) ** 2 + (o2.end.y - o2.start.y) ** 2), s2 = Boolean(e2._isNarrowQfpPadGap || n2._isNarrowQfpPadGap), a2 = 3 * this.minPortSpacing / 4, c2 = Math.max(0, r2 - 2 * a2);
if (c2 <= 0 && !e2._containsTarget && !n2._containsTarget) {
if (!this.shouldReturnCrampedPortPoints)
return null;
const r3 = [];
for (const s3 of i2)
r3.push({ segmentPortPointId: `${t3.capacityMeshEdgeId}_pp0_z${s3}_cramped`, x: (o2.start.x + o2.end.x) / 2, y: (o2.start.y + o2.end.y) / 2, availableZ: [s3], nodeIds: [e2.capacityMeshNodeId, n2.capacityMeshNodeId], edgeId: t3.capacityMeshEdgeId, connectionName: null, distToCentermostPortOnZ: 0, cramped: true });
return { edgeId: t3.capacityMeshEdgeId, nodeIds: [e2.capacityMeshNodeId, n2.capacityMeshNodeId], start: o2.start, end: o2.end, availableZ: i2, portPoints: r3 };
}
let l2 = Math.max(1, Math.floor(c2 / this.minPortSpacing) + 1);
if (e2._offBoardConnectionId || n2._offBoardConnectionId) {
if (e2._offBoardConnectionId && !n2._offBoardConnectionId) {
if (this.shouldSkipOffBoardPortPoint(e2, n2))
return null;
} else if (n2._offBoardConnectionId && !e2._offBoardConnectionId && this.shouldSkipOffBoardPortPoint(n2, e2))
return null;
l2 = 1;
}
const h2 = [], d2 = o2.end.x - o2.start.x, u2 = o2.end.y - o2.start.y, p2 = (o2.start.x + o2.end.x) / 2, m2 = (o2.start.y + o2.end.y) / 2;
l2 > 5 && (l2 = 5 + Math.floor(l2 / 4));
const g2 = [];
for (let t4 = 0;t4 < l2; t4++) {
let e3;
e3 = r2 === 0 || l2 === 1 ? 0.5 : (a2 + c2 * t4 / (l2 - 1)) / r2;
const n3 = o2.start.x + d2 * e3, i3 = o2.start.y + u2 * e3, s3 = Math.sqrt((n3 - p2) ** 2 + (i3 - m2) ** 2);
g2.push({ x: n3, y: i3, distToCenter: s3 });
}
const f2 = g2.reduce((t4, e3) => e3.distToCenter < t4.distToCenter ? e3 : t4);
for (let o3 = 0;o3 < l2; o3++) {
const { x: r3, y: a3 } = g2[o3], c3 = Math.sqrt((r3 - f2.x) ** 2 + (a3 - f2.y) ** 2);
for (const l3 of i2) {
const i3 = { segmentPortPointId: `${t3.capacityMeshEdgeId}_pp${o3}_z${l3}`, x: r3, y: a3, availableZ: [l3], nodeIds: [e2.capacityMeshNodeId, n2.capacityMeshNodeId], edgeId: t3.capacityMeshEdgeId, connectionName: null, distToCentermostPortOnZ: c3, cramped: s2 };
h2.push(i3);
}
}
return { edgeId: t3.capacityMeshEdgeId, nodeIds: [e2.capacityMeshNodeId, n2.capacityMeshNodeId], start: o2.start, end: o2.end, availableZ: i2, portPoints: h2 };
}
shouldSkipOffBoardPortPoint(t3, e2) {
const n2 = this.nodeEdgeMap.get(e2.capacityMeshNodeId) ?? [];
for (const o2 of n2) {
const n3 = o2.nodeIds[0] === e2.capacityMeshNodeId ? o2.nodeIds[1] : o2.nodeIds[0];
if (n3 === t3.capacityMeshNodeId)
continue;
const i2 = this.nodeMap.get(n3);
if (i2?._offBoardConnectionId !== t3._offBoardConnectionId)
continue;
if (this.nodes.filter((e3) => e3._offBoardConnectionId === t3._offBoardConnectionId).length !== 2)
continue;
const r2 = { x: (t3.center.x + i2.center.x) / 2, y: (t3.center.y + i2.center.y) / 2 };
if (r2.x >= e2.center.x - e2.width / 2 && r2.x <= e2.center.x + e2.width / 2 && r2.y >= e2.center.y - e2.height / 2 && r2.y <= e2.center.y + e2.height / 2)
return true;
}
return false;
}
findOverlappingSegment(t3, e2) {
const n2 = { start: Math.max(t3.center.x - t3.width / 2, e2.center.x - e2.width / 2), end: Math.min(t3.center.x + t3.width / 2, e2.center.x + e2.width / 2) }, o2 = { start: Math.max(t3.center.y - t3.height / 2, e2.center.y - e2.height / 2), end: Math.min(t3.center.y + t3.height / 2, e2.center.y + e2.height / 2) }, i2 = n2.end - n2.start, r2 = o2.end - o2.start;
if (i2 < -1e-4 || r2 < -1e-4)
return null;
if (i2 < r2) {
const t4 = (n2.start + n2.end) / 2;
return { start: { x: t4, y: o2.start }, end: { x: t4, y: o2.end } };
}
{
const t4 = (o2.start + o2.end) / 2;
return { start: { x: n2.start, y: t4 }, end: { x: n2.end, y: t4 } };
}
}
getAvailablePortPointsBetweenNodes(t3, e2) {
const n2 = this.edges.find((n3) => n3.nodeIds[0] === t3 && n3.nodeIds[1] === e2 || n3.nodeIds[0] === e2 && n3.nodeIds[1] === t3);
if (!n2)
return [];
const o2 = this.edgeSegmentMap.get(n2.capacityMeshEdgeId);
return o2 ? o2.portPoints.filter((t4) => t4.connectionName === null) : [];
}
getPortPointsForEdge(t3, e2) {
const n2 = this.edges.find((n3) => n3.nodeIds[0] === t3 && n3.nodeIds[1] === e2 || n3.nodeIds[0] === e2 && n3.nodeIds[1] === t3);
if (!n2)
return [];
const o2 = this.edgeSegmentMap.get(n2.capacityMeshEdgeId);
return o2?.portPoints ?? [];
}
assignPortPoint(t3, e2, n2) {
const o2 = this.portPointMap.get(t3);
return !!o2 && (o2.connectionName === null && (o2.connectionName = e2, o2.rootConnectionName = n2, true));
}
releasePortPoint(t3) {
const e2 = this.portPointMap.get(t3);
return !!e2 && (e2.connectionName = null, e2.rootConnectionName = undefined, true);
}
getAvailablePortCountForEdge(t3, e2) {
return this.getAvailablePortPointsBetweenNodes(t3, e2).length;
}
getOutput() {
return this.sharedEdgeSegments;
}
visualize() {
const t3 = { lines: [], points: [], rects: [], circles: [] };
for (const e2 of this.sharedEdgeSegments) {
t3.lines.push({ points: [e2.start, e2.end], strokeColor: "rgba(100, 100, 100, 0.5)" });
for (const n2 of e2.portPoints) {
const e3 = n2.connectionName ? this.colorMap[n2.connectionName] ?? "blue" : "rgba(0, 200, 0, 0.7)";
n2.cramped ? t3.rects.push({ center: { x: n2.x, y: n2.y }, width: 0.1, height: 0.1, fill: e3, layer: `z${n2.availableZ.join(",")}`, label: `cramped ${n2.segmentPortPointId}` }) : t3.circles.push({ center: { x: n2.x, y: n2.y }, radius: this.traceWidth / 2, fill: e3, layer: `z${n2.availableZ.join(",")}`, label: [n2.segmentPortPointId, n2.connectionName, n2.availableZ.join(","), `cd: ${n2.distToCentermostPortOnZ}`, `connects: ${n2.nodeIds.join(",")}`].filter(Boolean).join(`
`) });
}
}
return t3;
}
};
function li(t3, e2) {
const n2 = t3.center.x - t3.width / 2, o2 = t3.center.x + t3.width / 2, i2 = t3.center.y - t3.height / 2, r2 = t3.center.y + t3.height / 2, s2 = e2.center.x - e2.width / 2, a2 = e2.center.x + e2.width / 2, c2 = e2.center.y - e2.height / 2, l2 = e2.center.y + e2.height / 2, h2 = 0.001, d2 = (Math.abs(o2 - s2) < h2 || Math.abs(n2 - a2) < h2) && Math.min(r2, l2) - Math.max(i2, c2) >= h2, u2 = (Math.abs(r2 - c2) < h2 || Math.abs(i2 - l2) < h2) && Math.min(o2, a2) - Math.max(n2, s2) >= h2;
return d2 || u2;
}
var hi = class extends si {
constructor(t3) {
super(), this.nodes = t3, this.edges = [];
}
getSolverName() {
return "CapacityMeshEdgeSolver";
}
edges;
nodeMap;
getNextCapacityMeshEdgeId() {
return `ce${this.edges.length}`;
}
_step() {
this.edges = [];
for (let t3 = 0;t3 < this.nodes.length; t3++)
for (let e2 = t3 + 1;e2 < this.nodes.length; e2++) {
!(this.nodes[t3]._strawNode && this.nodes[e2]._strawNode && this.nodes[t3]._strawParentCapacityMeshNodeId === this.nodes[e2]._strawParentCapacityMeshNodeId) && li(this.nodes[t3], this.nodes[e2]) && this.doNodesHaveSharedLayer(this.nodes[t3], this.nodes[e2]) && this.edges.push({ capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(), nodeIds: [this.nodes[t3].capacityMeshNodeId, this.nodes[e2].capacityMeshNodeId] });
}
this.handleTargetNodes(), this.solved = true;
}
handleTargetNodes() {
const t3 = this.nodes.filter((t4) => t4._containsTarget), e2 = new Map(this.nodes.map((t4) => [t4.capacityMeshNodeId, t4]));
for (let e3 = 0;e3 < t3.length; e3++)
for (let n2 = e3 + 1;n2 < t3.length; n2++) {
const o2 = t3[e3], i2 = t3[n2];
this.doNodesHaveSharedLayer(o2, i2) && (this.doNodesTouchOrOverlap(o2, i2) && (this.hasEdgeBetween(o2, i2) || this.edges.push({ capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(), nodeIds: [o2.capacityMeshNodeId, i2.capacityMeshNodeId] })));
}
for (const n2 of t3) {
if (!n2._containsObstacle || !n2._targetConnectionName)
continue;
if (!this.edges.some((t4) => {
if (!t4.nodeIds.includes(n2.capacityMeshNodeId))
return false;
const o2 = t4.nodeIds[0] === n2.capacityMeshNodeId ? t4.nodeIds[1] : t4.nodeIds[0], i2 = e2.get(o2);
return !!i2 && (!i2._containsObstacle && !i2._containsTarget && this.doNodesHaveSharedLayer(n2, i2));
}))
throw new Error(`Target obstacle region "${n2.capacityMeshNodeId}" for connection "${n2._targetConnectionName}" has no bordering routing edge`);
}
}
doNodesHaveSharedLayer(t3, e2) {
return t3.availableZ.some((t4) => e2.availableZ.includes(t4));
}
hasEdgeBetween(t3, e2) {
return this.edges.some((n2) => n2.nodeIds.includes(t3.capacityMeshNodeId) && n2.nodeIds.includes(e2.capacityMeshNodeId));
}
doNodesTouchOrOverlap(t3, e2) {
const n2 = 0.001, o2 = t3.center.x - t3.width / 2, i2 = t3.center.x + t3.width / 2, r2 = t3.center.y - t3.height / 2, s2 = t3.center.y + t3.height / 2, a2 = e2.center.x - e2.width / 2, c2 = e2.center.x + e2.width / 2, l2 = e2.center.y - e2.height / 2, h2 = e2.center.y + e2.height / 2;
return o2 <= c2 + n2 && i2 + n2 >= a2 && r2 <= h2 + n2 && s2 + n2 >= l2;
}
visualize() {
const t3 = new Map;
for (const e3 of this.edges)
for (const n2 of e3.nodeIds)
t3.set(n2, 1 + (t3.get(n2) ?? 0));
const e2 = { lines: [], points: [], rects: this.nodes.map((e3) => {
const n2 = Math.min(...e3.availableZ);
return { width: Math.max(e3.width - 2, 0.8 * e3.width), height: Math.max(e3.height - 2, 0.8 * e3.height), center: { x: e3.center.x + n2 * e3.width * 0.05, y: e3.center.y - n2 * e3.width * 0.05 }, fill: e3._containsObstacle ? "rgba(255,0,0,0.1)" : { "0,1": "rgba(0,0,0,0.1)", 0: "rgba(0,200,200, 0.1)", 1: "rgba(0,0,200, 0.1)" }[e3.availableZ.join(",")] ?? "rgba(0,200,200,0.1)", label: [e3.capacityMeshNodeId, `availableZ: ${e3.availableZ.join(",")}`, `target? ${e3._containsTarget ?? false}`, `obs? ${e3._containsObstacle ?? false}`, `conn: ${t3.get(e3.capacityMeshNodeId) ?? 0}`].join(`
`), layer: `z${e3.availableZ.join(",")}` };
}), circles: [] };
if (!this.nodeMap) {
this.nodeMap = new Map;
for (const t4 of this.nodes)
this.nodeMap.set(t4.capacityMeshNodeId, t4);
}
for (const t4 of this.edges) {
const n2 = this.nodeMap.get(t4.nodeIds[0]), o2 = this.nodeMap.get(t4.nodeIds[1]);
if (n2?.center && o2?.center) {
const t5 = Math.min(...n2.availableZ), i2 = Math.min(...o2.availableZ), r2 = { x: n2.center.x + t5 * n2.width * 0.05, y: n2.center.y - t5 * n2.width * 0.05 }, s2 = { x: o2.center.x + i2 * o2.width * 0.05, y: o2.center.y - i2 * o2.width * 0.05 }, a2 = Array.from(new Set([...n2.availableZ, ...o2.availableZ])).sort();
e2.lines.push({ layer: `z${a2.join(",")}`, points: [r2, s2], strokeDash: n2.availableZ.join(",") === o2.availableZ.join(",") ? undefined : "10 5" });
}
}
return e2;
}
};
var di = class {
constructor(t3) {
this.nodes = t3, this.buckets = new Map;
for (const e2 of t3) {
const t4 = e2.center.x - e2.width / 2, n2 = e2.center.y - e2.height / 2, o2 = e2.center.x + e2.width / 2, i2 = e2.center.y + e2.height / 2, r2 = Math.floor(t4 / this.CELL_SIZE), s2 = Math.floor(o2 / this.CELL_SIZE), a2 = Math.floor(n2 / this.CELL_SIZE), c2 = Math.floor(i2 / this.CELL_SIZE);
for (let t5 = r2;t5 <= s2; t5++)
for (let n3 = a2;n3 <= c2; n3++) {
const o3 = `${t5}x${n3}`, i3 = this.buckets.get(o3);
i3 ? i3.push(e2) : this.buckets.set(o3, [e2]);
}
}
}
buckets;
CELL_SIZE = 0.4;
getBucketKey(t3, e2) {
return `${Math.floor(t3 / this.CELL_SIZE)}x${Math.floor(e2 / this.CELL_SIZE)}`;
}
getNodesInArea(t3, e2, n2, o2) {
const i2 = [], r2 = new Set, s2 = t3 - n2 / 2, a2 = e2 - o2 / 2, c2 = t3 + n2 / 2, l2 = e2 + o2 / 2, h2 = Math.floor(s2 / this.CELL_SIZE), d2 = Math.floor(c2 / this.CELL_SIZE), u2 = Math.floor(a2 / this.CELL_SIZE), p2 = Math.floor(l2 / this.CELL_SIZE);
for (let t4 = h2;t4 <= d2; t4++)
for (let e3 = u2;e3 <= p2; e3++) {
const n3 = `${t4}x${e3}`, o3 = this.buckets.get(n3) || [];
for (const t5 of o3)
r2.has(t5.capacityMeshNodeId) || (r2.add(t5.capacityMeshNodeId), i2.push(t5));
}
return i2;
}
};
var ui = class extends hi {
constructor(t3) {
super(t3), this.nodes = t3, this.MAX_ITERATIONS = 1e7, this.nodeTree = new di(this.nodes), this.currentNodeIndex = 0, this.edgeSet = new Set;
}
getSolverName() {
return "CapacityMeshEdgeSolver2_NodeTreeOptimization";
}
nodeTree;
currentNodeIndex;
edgeSet;
_step() {
if (this.currentNodeIndex >= this.nodes.length)
return this.handleTargetNodes(), void (this.solved = true);
const t3 = this.nodes[this.currentNodeIndex], e2 = this.nodeTree.getNodesInArea(t3.center.x, t3.center.y, 2 * t3.width, 2 * t3.height);
for (const n2 of e2) {
if (!li(t3, n2))
continue;
const e3 = t3._strawNode && n2._strawNode && t3._strawParentCapacityMeshNodeId === n2._strawParentCapacityMeshNodeId;
t3.capacityMeshNodeId === n2.capacityMeshNodeId || e3 || !this.doNodesHaveSharedLayer(t3, n2) || this.edgeSet.has(`${t3.capacityMeshNodeId}-${n2.capacityMeshNodeId}`) || (this.edgeSet.add(`${t3.capacityMeshNodeId}-${n2.capacityMeshNodeId}`), this.edgeSet.add(`${n2.capacityMeshNodeId}-${t3.capacityMeshNodeId}`), this.edges.push({ capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(), nodeIds: [t3.capacityMeshNodeId, n2.capacityMeshNodeId] }));
}
this.currentNodeIndex++;
}
};
var pi = (...t3) => {
const e2 = { points: [], lines: [], circles: [], rects: [], polygons: [], infiniteLines: [], arrows: [], texts: [] };
return t3.forEach((t4, n2) => {
t4 && (t4.lines && (e2.lines = [...e2.lines || [], ...t4.lines.map((t5) => ({ ...t5, step: n2 }))]), t4.points && (e2.points = [...e2.points || [], ...t4.points.map((t5) => ({ ...t5, step: n2 }))]), t4.circles && (e2.circles = [...e2.circles || [], ...t4.circles.map((t5) => ({ ...t5, step: n2 }))]), t4.rects && (e2.rects = [...e2.rects || [], ...t4.rects.map((t5) => ({ ...t5, step: n2 }))]), t4.polygons && (e2.polygons = [...e2.polygons || [], ...t4.polygons.map((t5) => ({ ...t5, step: n2 }))]), t4.infiniteLines && (e2.infiniteLines = [...e2.infiniteLines || [], ...t4.infiniteLines.map((t5) => ({ ...t5, step: n2 }))]), t4.arrows && (e2.arrows = [...e2.arrows || [], ...t4.arrows.map((t5) => ({ ...t5, step: n2 }))]), t4.texts && (e2.texts = [...e2.texts || [], ...t4.texts.map((t5) => ({ ...t5, step: n2 }))]));
}), e2;
};
function mi(t3, e2, n2) {
const o2 = [];
let i2 = null;
for (let r2 = 0;r2 < t3.length; r2++) {
const s2 = t3[r2];
i2 ? i2.z === s2.z ? i2.points.push({ x: s2.x, y: s2.y }) : (o2.push(i2), i2 = { points: [{ x: s2.x, y: s2.y }], z: s2.z, connectionName: e2, color: n2 }) : i2 = { points: [{ x: s2.x, y: s2.y }], z: s2.z, connectionName: e2, color: n2 }, r2 === t3.length - 1 && i2 && o2.push(i2);
}
return o2;
}
function gi(t3, e2) {
return { x: t3.a * e2.x + t3.b * e2.y + t3.c, y: t3.d * e2.x + t3.e * e2.y + t3.f };
}
var fi = (t3, e2, n2) => {
const [o2, i2] = t3;
if (o2 === i2)
return;
const r2 = ((t4, e3) => {
const n3 = t4.portPointId ?? `${t4.connectionName}:${t4.x}:${t4.y}:${t4.z}`, o3 = e3.portPointId ?? `${e3.connectionName}:${e3.x}:${e3.y}:${e3.z}`;
return n3 < o3 ? `${n3}|${o3}` : `${o3}|${n3}`;
})(o2, i2);
e2.has(r2) || (e2.add(r2), n2.push(t3));
};
var yi = (t3, e2, n2) => {
for (let o2 = 0;o2 < t3.length - 1; o2++)
fi([t3[o2], t3[o2 + 1]], e2, n2);
};
var _i = (t3) => {
const e2 = [], n2 = new Set, o2 = ((t4) => {
const e3 = new Map;
for (const n3 of t4)
n3.portPointId && e3.set(n3.portPointId, n3);
return e3;
})(t3);
for (const i3 of t3) {
if (i3.prevPortPointId) {
const t4 = o2.get(i3.prevPortPointId);
t4 && t4.connectionName === i3.connectionName && fi([t4, i3], n2, e2);
}
if (i3.nextPortPointId) {
const t4 = o2.get(i3.nextPortPointId);
t4 && t4.connectionName === i3.connectionName && fi([i3, t4], n2, e2);
}
}
if (e2.length === 0)
return yi(t3, n2, e2), e2;
const i2 = ((t4) => {
const e3 = new Set;
for (const [n3, o3] of t4)
n3.portPointId && e3.add(n3.portPointId), o3.portPointId && e3.add(o3.portPointId);
return e3;
})(e2), r2 = t3.filter((t4) => !t4.portPointId || !i2.has(t4.portPointId));
return yi(r2, n2, e2), e2;
};
function bi(t3, e2, n2) {
return Math.max(e2, Math.min(n2, t3));
}
function xi(t3) {
const e2 = t3.planeSize * t3.layers, n2 = t3.connectionCount, o2 = Math.sqrt(n2), i2 = Math.max(1, t3.maxIterations), r2 = bi(Math.round(e2 * (8 + 1.2 * o2)), 150000, 12000000), s2 = bi(Math.round(r2 * t3.effort), 150000, 12000000), a2 = bi(Math.round(0.2 * i2), 150000, 2000000);
return { maxIterationsIters: Math.max(1, Math.min(i2, Math.max(a2, s2))), baseSearchBudgetIters: bi(Math.round(e2 * (10 + 0.8 * o2) * t3.effort), 50000, 4000000) };
}
function vi(t3, e2) {
for (let n2 = t3;n2; n2 = n2.prev)
if (n2.id === e2)
return true;
return false;
}
var Ii = class {
f = [];
seq = [];
id = [];
n = 0;
push(t3, e2, n2) {
let o2 = this.n++;
for (this.f[o2] = t3, this.seq[o2] = e2, this.id[o2] = n2;o2 > 0; ) {
const t4 = o2 - 1 >> 1;
if (this.less(t4, o2))
break;
this.swap(o2, t4), o2 = t4;
}
}
pop() {
const t3 = this.id[0];
return this.n--, this.n > 0 && (this.f[0] = this.f[this.n], this.seq[0] = this.seq[this.n], this.id[0] = this.id[this.n], this.siftDown(0)), t3;
}
get size() {
return this.n;
}
clear() {
this.n = 0;
}
siftDown(t3) {
for (;; ) {
const e2 = 2 * t3 + 1, n2 = e2 + 1;
if (e2 >= this.n)
return;
let o2 = e2;
if (n2 < this.n && !this.less(e2, n2) && (o2 = n2), this.less(t3, o2))
return;
this.swap(t3, o2), t3 = o2;
}
}
less(t3, e2) {
const n2 = this.f[t3], o2 = this.f[e2];
return n2 !== o2 ? n2 < o2 : this.seq[t3] < this.seq[e2];
}
swap(t3, e2) {
const n2 = this.f[t3];
this.f[t3] = this.f[e2], this.f[e2] = n2;
const o2 = this.seq[t3];
this.seq[t3] = this.seq[e2], this.seq[e2] = o2;
const i2 = this.id[t3];
this.id[t3] = this.id[e2], this.id[e2] = i2;
}
};
var Si = [-1, -1, -1, 0, 0, 1, 1, 1];
var Ci = [-1, 0, 1, -1, 1, -1, 0, 1];
var Pi = class extends kt {
getSolverName() {
return "HighDensitySolverA01";
}
nodeWithPortPoints;
cellSizeMm;
viaDiameter;
MAX_RIPS;
maxCellCount;
traceThickness;
traceMargin;
viaMinDistFromBorder;
showPenaltyMap;
showUsedCellMap;
effort;
stepMultiplier;
hyperParameters;
initialPenaltyFn;
useExactViaTraceClearance = false;
ripHistoryCostMultiplier = 0;
rows;
cols;
layers;
gridOrigin;
gridToBoundsTransform;
availableZ;
zToLayer;
layerToZ;
connNameToId;
connIdToName;
connIdToRootNet;
overlapFriendlyRootNets;
planeSize;
usedCellsFlat;
portOwnerFlat;
usedDiagFlat;
penalty2d;
visitedStamp;
sharedCrossRootPortCells;
stamp = 0;
viaOccupantScanOffsetsDr;
viaOccupantScanOffsetsDc;
viaOccupantScanOffsetsLen;
viaOwnersByCell;
viaCenterIndicesByConn;
viaTraceClearanceMm;
outputCellStepX;
outputCellStepY;
minViaRow;
maxViaRow;
minViaCol;
maxViaCol;
usedIndicesByConn;
usedDiagIndicesByConn;
unsolvedSegs;
solvedRoutes;
activeConnSeg = null;
activeConnId = -1;
crossLayerSearch = false;
nodePool;
heap;
seqCounter = 0;
_viaOccs = [];
viaOccupantsByCell = new Map;
ripCount;
totalRipEvents = 0;
searchIterations = 0;
consecutiveSkips = 0;
penaltyCap;
baseSearchBudgetIters;
_moveCost = 0;
_moveRipped = null;
get unsolvedConnections() {
return this.unsolvedSegs;
}
get solvedConnectionsMap() {
return this.solvedRoutes;
}
get activeConnection() {
if (!this.activeConnSeg)
return null;
const t3 = this.activeConnSeg;
return { connectionName: this.connIdToName[t3.connId] ?? "", start: { row: t3.startRow, col: t3.startCol, z: t3.startZ, x: 0, y: 0 }, end: { row: t3.endRow, col: t3.endCol, z: t3.endZ, x: 0, y: 0 } };
}
get openSet() {
return { length: this.heap?.size ?? 0 };
}
get gridStats() {
return { cells: this.planeSize || 0, layers: this.layers || 0, states: (this.planeSize || 0) * (this.layers || 0) };
}
constructor(t3) {
super(), this.nodeWithPortPoints = t3.nodeWithPortPoints, this.cellSizeMm = t3.cellSizeMm, this.viaDiameter = t3.viaDiameter, this.maxCellCount = t3.maxCellCount, this.traceThickness = t3.traceThickness ?? 0.1, this.traceMargin = t3.traceMargin ?? 0.15, this.viaMinDistFromBorder = t3.viaMinDistFromBorder ?? 0.15, this.showPenaltyMap = t3.showPenaltyMap ?? false, this.showUsedCellMap = t3.showUsedCellMap ?? false, this.effort = t3.effort ?? 1, this.stepMultiplier = Math.max(1, Math.floor(t3.stepMultiplier ?? 1)), this.hyperParameters = { shuffleSeed: 0, ripCost: 10, ripTracePenalty: 0.5, ripViaPenalty: 0.75, viaBaseCost: 0.1, greedyMultiplier: 1.5, ...t3.hyperParameters }, this.MAX_ITERATIONS = 1e8, this.MAX_RIPS = 200, this.initialPenaltyFn = t3.initialPenaltyFn;
}
getConstructorParams() {
return [{ nodeWithPortPoints: this.nodeWithPortPoints, cellSizeMm: this.cellSizeMm, viaDiameter: this.viaDiameter, maxCellCount: this.maxCellCount, stepMultiplier: this.stepMultiplier, traceThickness: this.traceThickness, traceMargin: this.traceMargin, viaMinDistFromBorder: this.viaMinDistFromBorder, showPenaltyMap: this.showPenaltyMap, showUsedCellMap: this.showUsedCellMap, effort: this.effort, hyperParameters: this.hyperParameters, initialPenaltyFn: this.initialPenaltyFn }];
}
_setup() {
const { nodeWithPortPoints: t3, cellSizeMm: e2 } = this, { width: n2, height: o2, center: i2 } = t3;
this.availableZ = t3.availableZ ?? [...new Set(t3.portPoints.map((t4) => t4.z))].sort((t4, e3) => t4 - e3), this.rows = Math.floor(o2 / e2), this.cols = Math.floor(n2 / e2), this.layers = this.availableZ.length, this.planeSize = this.rows * this.cols;
const r2 = this.layers * this.planeSize;
if (this.maxCellCount !== undefined && r2 > this.maxCellCount)
return this.error = `Cell count ${r2} exceeds maxCellCount ${this.maxCellCount}`, void (this.failed = true);
const s2 = this.layers * Math.max(0, this.rows - 1) * Math.max(0, this.cols - 1) * 2;
this.zToLayer = new Map, this.layerToZ = new Map;
for (let t4 = 0;t4 < this.availableZ.length; t4++) {
const e3 = this.availableZ[t4];
this.zToLayer.set(e3, t4), this.layerToZ.set(t4, e3);
}
if (this.gridOrigin = { x: i2.x - n2 / 2, y: i2.y - o2 / 2 }, this.gridToBoundsTransform = function(t4) {
const { originX: e3, originY: n3, rows: o3, cols: i3, cellSizeMm: r3, width: s3, height: a3 } = t4;
let c3, l3, h2, d2;
return i3 > 1 ? (c3 = s3 / ((i3 - 1) * r3), l3 = e3 * (1 - c3) - 0.5 * r3 * c3) : (c3 = 1, l3 = e3 + s3 / 2 - (e3 + 0.5 * r3)), o3 > 1 ? (h2 = a3 / ((o3 - 1) * r3), d2 = n3 * (1 - h2) - 0.5 * r3 * h2) : (h2 = 1, d2 = n3 + a3 / 2 - (n3 + 0.5 * r3)), { a: c3, b: 0, c: l3, d: 0, e: h2, f: d2 };
}({ originX: this.gridOrigin.x, originY: this.gridOrigin.y, rows: this.rows, cols: this.cols, cellSizeMm: e2, width: n2, height: o2 }), this.outputCellStepX = this.cols > 1 ? n2 / (this.cols - 1) : n2, this.outputCellStepY = this.rows > 1 ? o2 / (this.rows - 1) : o2, this.connNameToId = new Map, this.connIdToName = [], this.connIdToRootNet = [], this.overlapFriendlyRootNets = new Set, this.penalty2d = new Float64Array(this.planeSize), this.initialPenaltyFn)
for (let t4 = 0;t4 < this.rows; t4++) {
const n3 = t4 * this.cols;
for (let o3 = 0;o3 < this.cols; o3++) {
const i3 = this.gridOrigin.x + (o3 + 0.5) * e2, r3 = this.gridOrigin.y + (t4 + 0.5) * e2, s3 = (o3 + 0.5) / this.cols, a3 = (t4 + 0.5) / this.rows;
this.penalty2d[n3 + o3] = this.initialPenaltyFn({ x: i3, y: r3, px: s3, py: a3, row: t4, col: o3 });
}
}
this.usedCellsFlat = new Int32Array(r2).fill(-1), this.portOwnerFlat = new Int32Array(r2).fill(-1), this.usedDiagFlat = new Int32Array(s2).fill(-1), this.visitedStamp = new Uint32Array(r2), this.stamp = 0;
const a2 = function(t4) {
const e3 = t4.radiusMm / t4.cellSizeMm, n3 = Math.round(e3), o3 = Math.abs(e3 - n3) <= 0.000000001 ? n3 : Math.ceil(e3), i3 = o3 * o3, r3 = [], s3 = [];
for (let t5 = -o3;t5 <= o3; t5++)
for (let e4 = -o3;e4 <= o3; e4++)
t5 * t5 + e4 * e4 <= i3 && (r3.push(t5), s3.push(e4));
return { rowOffsets: new Int32Array(r3), columnOffsets: new Int32Array(s3), length: r3.length };
}({ radiusMm: this.viaDiameter / 2, cellSizeMm: e2 });
if (this.viaOccupantScanOffsetsLen = a2.length, this.viaOccupantScanOffsetsDr = a2.rowOffsets, this.viaOccupantScanOffsetsDc = a2.columnOffsets, this.viaOwnersByCell = new Map, this.viaCenterIndicesByConn = [], this.viaTraceClearanceMm = this.viaDiameter / 2 + this.traceThickness / 2, this.viaMinDistFromBorder > 0) {
const t4 = Math.ceil(this.viaMinDistFromBorder / e2);
this.minViaRow = t4, this.maxViaRow = this.rows - 1 - t4, this.minViaCol = t4, this.maxViaCol = this.cols - 1 - t4;
} else
this.minViaRow = 0, this.maxViaRow = this.rows - 1, this.minViaCol = 0, this.maxViaCol = this.cols - 1;
this.unsolvedSegs = this.buildConnectionSegs(), this.sharedCrossRootPortCells = new Set;
const c2 = new Map;
for (const t4 of this.nodeWithPortPoints.portPoints) {
const e3 = this.connNameToId.get(t4.connectionName);
if (e3 === undefined)
continue;
const n3 = this.pointToCell(t4), o3 = (n3.z * this.rows + n3.row) * this.cols + n3.col, i3 = this.connIdToRootNet[e3], r3 = c2.get(o3);
r3 === undefined ? c2.set(o3, i3) : r3 !== i3 && this.sharedCrossRootPortCells.add(o3);
const s3 = this.portOwnerFlat[o3];
this.portOwnerFlat[o3] = s3 === -1 || s3 === e3 ? e3 : -2;
}
this.solvedRoutes = new Map, this.usedIndicesByConn = [], this.usedDiagIndicesByConn = [], this.ripCount = [], this.consecutiveSkips = 0, this.penaltyCap = 0.5 * this.hyperParameters.ripCost, this.shuffleConnections();
const l2 = xi({ planeSize: this.planeSize, layers: this.layers, connectionCount: this.unsolvedSegs.length, effort: this.effort, maxIterations: this.MAX_ITERATIONS });
this.baseSearchBudgetIters = l2.baseSearchBudgetIters, this.MAX_ITERATIONS = l2.maxIterationsIters, this.activeConnSeg = null, this.activeConnId = -1, this.nodePool = [], this.heap = new Ii, this.seqCounter = 0;
}
_step() {
for (let t3 = 0;t3 < this.stepMultiplier; t3++) {
if (this.solved || this.failed)
return;
this.stepOnce();
}
}
stepOnce() {
if (!this.activeConnSeg) {
if (this.unsolvedSegs.length === 0)
return void (this.solved = true);
const t4 = this.unsolvedSegs.shift();
this.activeConnSeg = t4, this.activeConnId = t4.connId, this.crossLayerSearch = t4.startZ !== t4.endZ, this.viaOccupantsByCell.clear(), this.nodePool = [], this.heap.clear(), this.seqCounter = 0, this.searchIterations = 0, this.nextStamp();
const e3 = this.computeH(t4.startZ, t4.startRow, t4.startCol, t4.endZ, t4.endRow, t4.endCol) * this.hyperParameters.greedyMultiplier;
return this.nodePool.push({ z: t4.startZ, row: t4.startRow, col: t4.startCol, g: 0, f: e3, parentIdx: -1, ripped: null }), void this.heap.push(e3, this.seqCounter++, 0);
}
this.searchIterations++;
const t3 = this.ripCount[this.activeConnId] ?? 0, e2 = Math.round(this.baseSearchBudgetIters * (1 + 0.25 * Math.min(t3, 10)));
if (this.searchIterations > e2) {
const t4 = this.penalty2d;
for (let e3 = 0;e3 < t4.length; e3++)
t4[e3] = 0.9 * t4[e3];
return this.unsolvedSegs.push(this.activeConnSeg), this.activeConnSeg = null, this.activeConnId = -1, this.heap.clear(), this.nodePool = [], this.consecutiveSkips++, void (this.consecutiveSkips >= 3 * this.unsolvedSegs.length && (this.error = `Convergence failure: ${this.unsolvedSegs.length} connections stuck`, this.failed = true));
}
if (this.heap.size === 0)
return this.error = `No path found for ${this.connIdToName[this.activeConnId]}`, void (this.failed = true);
const n2 = this.heap.pop(), o2 = this.nodePool[n2], { z: i2, row: r2, col: s2, g: a2, ripped: c2 } = o2, l2 = (i2 * this.rows + r2) * this.cols + s2;
if (this.visitedStamp[l2] === this.stamp)
return;
this.visitedStamp[l2] = this.stamp;
const h2 = this.activeConnSeg;
if (i2 === h2.endZ && r2 === h2.endRow && s2 === h2.endCol)
return this.finalizeRoute(n2), this.activeConnSeg = null, void (this.activeConnId = -1);
const { endZ: d2, endRow: u2, endCol: p2 } = h2, m2 = this.activeConnId, g2 = this.rows, f2 = this.cols, y2 = (this.cellSizeMm, this.visitedStamp), _2 = this.stamp;
for (let t4 = 0;t4 < 8; t4++) {
const e3 = r2 + Si[t4], o3 = s2 + Ci[t4];
if (e3 < 0 || e3 >= g2 || o3 < 0 || o3 >= f2)
continue;
if (y2[(i2 * g2 + e3) * f2 + o3] === _2)
continue;
if (this.computeMoveCostAndRips(m2, i2, r2, s2, i2, e3, o3, c2), this._moveCost < 0)
continue;
const l3 = a2 + this._moveCost, h3 = l3 + this.computeH(i2, e3, o3, d2, u2, p2) * this.hyperParameters.greedyMultiplier, b2 = this.nodePool.length;
this.nodePool.push({ z: i2, row: e3, col: o3, g: l3, f: h3, parentIdx: n2, ripped: this._moveRipped }), this.heap.push(h3, this.seqCounter++, b2);
}
if (r2 >= this.minViaRow && r2 <= this.maxViaRow && s2 >= this.minViaCol && s2 <= this.maxViaCol)
for (let t4 = 0;t4 < this.layers; t4++) {
if (t4 === i2)
continue;
if (y2[(t4 * g2 + r2) * f2 + s2] === _2)
continue;
if (this.computeMoveCostAndRips(m2, i2, r2, s2, t4, r2, s2, c2), this._moveCost < 0)
continue;
const e3 = a2 + this._moveCost, o3 = e3 + this.computeH(t4, r2, s2, d2, u2, p2) * this.hyperParameters.greedyMultiplier, l3 = this.nodePool.length;
this.nodePool.push({ z: t4, row: r2, col: s2, g: e3, f: o3, parentIdx: n2, ripped: this._moveRipped }), this.heap.push(o3, this.seqCounter++, l3);
}
}
getRipCost(t3) {
return this.hyperParameters.ripCost * (1 + this.ripHistoryCostMultiplier * (this.ripCount[t3] ?? 0));
}
computeMoveCostAndRips(t3, e2, n2, o2, i2, r2, s2, a2) {
let c2 = 0, l2 = a2;
const h2 = this.cols;
if (e2 !== i2) {
c2 += this.hyperParameters.viaBaseCost, c2 += Math.min(this.penalty2d[r2 * h2 + s2], this.penaltyCap);
const e3 = (i2 * this.rows + r2) * h2 + s2, n3 = this.portOwnerFlat[e3], o3 = this.connIdToRootNet[n3] === this.connIdToRootNet[t3] && this.overlapFriendlyRootNets.has(this.connIdToRootNet[t3]), a3 = this.activeConnSeg, d2 = !!a3 && i2 === a3.endZ && r2 === a3.endRow && s2 === a3.endCol;
if (n3 >= 0 && n3 !== t3 && !o3 && !d2)
return this._moveCost = -1, void (this._moveRipped = l2);
this.fillViaOccupants(r2, s2, t3);
const u2 = this._viaOccs;
for (let t4 = 0;t4 < u2.length; t4++) {
const e4 = u2[t4];
vi(l2, e4) || (c2 += this.getRipCost(e4), l2 = { id: e4, prev: l2 }), c2 += this.hyperParameters.ripViaPenalty;
}
} else {
const e3 = n2 > r2 ? n2 - r2 : r2 - n2, a3 = o2 > s2 ? o2 - s2 : s2 - o2;
c2 += (e3 + a3 > 1 ? Math.SQRT2 : 1) * this.cellSizeMm, c2 += Math.min(this.penalty2d[r2 * h2 + s2], this.penaltyCap);
const d2 = (i2 * this.rows + r2) * h2 + s2, u2 = this.portOwnerFlat[d2], p2 = this.connIdToRootNet[u2] === this.connIdToRootNet[t3] && this.overlapFriendlyRootNets.has(this.connIdToRootNet[t3]), m2 = this.activeConnSeg, g2 = !!m2 && i2 === m2.endZ && r2 === m2.endRow && s2 === m2.endCol;
if (u2 >= 0 && u2 !== t3 && !p2 && !g2)
return this._moveCost = -1, void (this._moveRipped = l2);
const f2 = this.usedCellsFlat[d2], y2 = this.connIdToRootNet[f2] === this.connIdToRootNet[t3] && this.overlapFriendlyRootNets.has(this.connIdToRootNet[t3]);
if (f2 === -1 || f2 === t3 || y2 || (vi(l2, f2) || (c2 += this.getRipCost(f2), l2 = { id: f2, prev: l2 }), c2 += this.hyperParameters.ripTracePenalty), this.viaOwnersByCell.size > 0) {
this.fillTraceSegmentViaOccupants(n2, o2, r2, s2, t3);
const e4 = this._viaOccs;
for (let t4 = 0;t4 < e4.length; t4++) {
const n3 = e4[t4];
vi(l2, n3) || (c2 += this.getRipCost(n3), l2 = { id: n3, prev: l2 }), c2 += this.hyperParameters.ripViaPenalty;
}
}
if (e3 === 1 && a3 === 1) {
const e4 = n2 < r2 ? n2 : r2, a4 = o2 < s2 ? o2 : s2, c3 = 1 ^ (n2 < r2 && o2 < s2 || n2 > r2 && o2 > s2 ? 0 : 1), h3 = this.cols - 1, d3 = 2 * ((i2 * (this.rows - 1) + e4) * h3 + a4), u3 = this.usedDiagFlat[d3 + c3], p3 = this.connIdToRootNet[u3] === this.connIdToRootNet[t3] && this.overlapFriendlyRootNets.has(this.connIdToRootNet[t3]);
if (u3 !== -1 && u3 !== t3 && !p3)
return this._moveCost = -1, void (this._moveRipped = l2);
}
}
this._moveCost = c2, this._moveRipped = l2;
}
fillViaOccupants(t3, e2, n2) {
const o2 = this._viaOccs;
o2.length = 0;
const i2 = t3 * this.cols + e2, r2 = this.viaOccupantsByCell.get(i2);
if (r2) {
for (const t4 of r2)
o2.push(t4);
return;
}
const s2 = this.rows, a2 = this.cols, c2 = this.viaOccupantScanOffsetsDr, l2 = this.viaOccupantScanOffsetsDc, h2 = this.viaOccupantScanOffsetsLen, d2 = this.usedCellsFlat;
for (let i3 = 0;i3 < this.layers; i3++) {
const r3 = i3 * this.planeSize;
for (let i4 = 0;i4 < h2; i4++) {
const h3 = t3 + c2[i4], u2 = e2 + l2[i4];
if (h3 < 0 || u2 < 0 || h3 >= s2 || u2 >= a2)
continue;
const p2 = d2[r3 + h3 * a2 + u2];
if (p2 === -1 || p2 === n2)
continue;
if (this.connIdToRootNet[p2] === this.connIdToRootNet[n2] && this.overlapFriendlyRootNets.has(this.connIdToRootNet[n2]))
continue;
let m2 = false;
for (let t4 = 0;t4 < o2.length; t4++)
if (o2[t4] === p2) {
m2 = true;
break;
}
m2 || o2.push(p2);
}
}
this.viaOccupantsByCell.set(i2, o2.slice());
}
fillTraceSegmentViaOccupants(t3, e2, n2, o2, i2) {
const r2 = this._viaOccs;
r2.length = 0;
const s2 = Math.min(t3, n2), a2 = Math.max(t3, n2), c2 = Math.min(e2, o2), l2 = Math.max(e2, o2), h2 = this.viaTraceClearanceMm / this.outputCellStepY, d2 = this.viaTraceClearanceMm / this.outputCellStepX, u2 = (o2 - e2) * this.outputCellStepX, p2 = (n2 - t3) * this.outputCellStepY, m2 = u2 * u2 + p2 * p2, g2 = this.viaTraceClearanceMm * this.viaTraceClearanceMm;
for (const [n3, o3] of this.viaOwnersByCell) {
const f2 = Math.floor(n3 / this.cols), y2 = n3 - f2 * this.cols;
if (f2 < s2 - h2 || f2 > a2 + h2 || y2 < c2 - d2 || y2 > l2 + d2)
continue;
const _2 = (y2 - e2) * this.outputCellStepX, b2 = (f2 - t3) * this.outputCellStepY, x2 = m2 === 0 ? 0 : Math.max(0, Math.min(1, (_2 * u2 + b2 * p2) / m2)), v2 = _2 - u2 * x2, I2 = b2 - p2 * x2;
if (!(v2 * v2 + I2 * I2 >= g2))
for (const t4 of o3) {
if (t4 === i2)
continue;
this.connIdToRootNet[t4] === this.connIdToRootNet[i2] && this.overlapFriendlyRootNets.has(this.connIdToRootNet[i2]) || (r2.includes(t4) || r2.push(t4));
}
}
}
shouldSkipFixedPortHalo(t3, e2) {
const n2 = this.portOwnerFlat[t3];
if (n2 === e2)
return false;
if (n2 === -2)
return true;
if (n2 < 0)
return false;
return !(this.connIdToRootNet[n2] === this.connIdToRootNet[e2] && this.overlapFriendlyRootNets.has(this.connIdToRootNet[e2]));
}
nextStamp() {
this.stamp = this.stamp + 1 >>> 0, this.stamp === 0 && (this.visitedStamp.fill(0), this.stamp = 1);
}
computeH(t3, e2, n2, o2, i2, r2) {
const s2 = Math.abs(e2 - i2) + Math.abs(n2 - r2);
if (t3 === o2)
return s2 * this.cellSizeMm;
if (!this.crossLayerSearch)
return s2 * this.cellSizeMm + this.hyperParameters.viaBaseCost;
const a2 = Math.max(this.minViaRow, Math.min(this.maxViaRow, e2)), c2 = Math.max(this.minViaCol, Math.min(this.maxViaCol, n2)), l2 = Math.max(this.minViaRow, Math.min(this.maxViaRow, i2)), h2 = Math.max(this.minViaCol, Math.min(this.maxViaCol, r2)), d2 = Math.abs(e2 - a2) + Math.abs(n2 - c2) + Math.abs(a2 - i2) + Math.abs(c2 - r2), u2 = Math.abs(e2 - l2) + Math.abs(n2 - h2) + Math.abs(l2 - i2) + Math.abs(h2 - r2);
return Math.max(Math.min(d2, u2), s2) * this.cellSizeMm + this.hyperParameters.viaBaseCost;
}
internConn(t3, e2) {
const n2 = this.connNameToId.get(t3);
if (n2 !== undefined)
return n2;
const o2 = this.connIdToName.length;
var i2;
return this.connIdToName.push(t3), this.connIdToRootNet.push((i2 = t3, e2 ?? i2.replace(/_mst\d+$/, ""))), this.connNameToId.set(t3, o2), o2;
}
buildConnectionSegs() {
const t3 = new Map;
for (const e3 of this.nodeWithPortPoints.portPoints) {
const n3 = e3.connectionName;
t3.has(n3) || t3.set(n3, { points: [], rootConnectionName: e3.rootConnectionName }), t3.get(n3).points.push(e3);
}
const e2 = [], n2 = new Set;
for (const [o2, i2] of t3) {
const t4 = i2.points, r2 = _i(t4);
if (r2.length === 0)
continue;
const s2 = this.internConn(o2, i2.rootConnectionName);
for (const [t5, a2] of r2) {
const r3 = this.pointToCell(t5), c2 = this.pointToCell(a2), l2 = `${r3.z}:${r3.row}:${r3.col}`, h2 = `${c2.z}:${c2.row}:${c2.col}`, d2 = l2 < h2 ? `${l2}|${h2}` : `${h2}|${l2}`, u2 = i2.rootConnectionName ?? o2, p2 = `${u2}|${d2}`;
n2.has(p2) ? this.overlapFriendlyRootNets.add(u2) : (n2.add(p2), e2.push({ connId: s2, startZ: r3.z, startRow: r3.row, startCol: r3.col, startPoint: t5, endZ: c2.z, endRow: c2.row, endCol: c2.col, endPoint: a2 }));
}
}
return e2;
}
pointToCell(t3) {
const e2 = Math.max(0, Math.min(this.cols - 1, Math.round((t3.x - this.gridOrigin.x) / this.cellSizeMm - 0.5))), n2 = Math.max(0, Math.min(this.rows - 1, Math.round((t3.y - this.gridOrigin.y) / this.cellSizeMm - 0.5)));
return { z: this.zToLayer.get(t3.z) ?? 0, row: n2, col: e2 };
}
shuffleConnections() {
const t3 = this.unsolvedSegs;
let e2 = this.hyperParameters.shuffleSeed;
const n2 = () => (e2 = 1664525 * e2 + 1013904223 & 4294967295, (e2 >>> 0) / 4294967295);
for (let e3 = t3.length - 1;e3 > 0; e3--) {
const o2 = Math.floor(n2() * (e3 + 1)), i2 = t3[e3];
t3[e3] = t3[o2], t3[o2] = i2;
}
}
finalizeRoute(t3) {
this.consecutiveSkips = Math.max(0, this.consecutiveSkips - 1);
const e2 = [];
let n2 = t3;
for (;n2 >= 0; ) {
const t4 = this.nodePool[n2];
e2.push({ z: t4.z, row: t4.row, col: t4.col }), n2 = t4.parentIdx;
}
for (e2.reverse();e2.length > 1; ) {
const t4 = e2[0], n3 = (t4.z * this.rows + t4.row) * this.cols + t4.col;
if (!this.sharedCrossRootPortCells.has(n3))
break;
e2.shift();
}
for (;e2.length > 1; ) {
const t4 = e2[e2.length - 1], n3 = (t4.z * this.rows + t4.row) * this.cols + t4.col;
if (!this.sharedCrossRootPortCells.has(n3))
break;
e2.pop();
}
const o2 = [];
for (let t4 = 1;t4 < e2.length; t4++)
e2[t4].z !== e2[t4 - 1].z && o2.push({ row: e2[t4].row, col: e2[t4].col });
const i2 = e2[0], r2 = e2[e2.length - 1], s2 = this.activeConnId, a2 = [];
for (let e3 = this.nodePool[t3].ripped;e3; e3 = e3.prev)
a2.push(e3.id);
for (let t4 = 0;t4 < a2.length; t4++)
if (this.ripTrace(a2[t4]), this.failed)
return;
const c2 = Math.ceil(this.traceMargin / this.cellSizeMm), l2 = [], h2 = this.rows, d2 = this.cols, u2 = this.usedCellsFlat;
for (let t4 = 0;t4 < e2.length; t4++) {
const n3 = e2[t4];
for (let t5 = -c2;t5 <= c2; t5++)
for (let e3 = -c2;e3 <= c2; e3++) {
const o3 = n3.row + t5, i3 = n3.col + e3;
if (o3 < 0 || o3 >= h2 || i3 < 0 || i3 >= d2)
continue;
const r3 = (n3.z * h2 + o3) * d2 + i3;
if ((o3 !== n3.row || i3 !== n3.col) && this.shouldSkipFixedPortHalo(r3, s2))
continue;
const a3 = u2[r3], c3 = this.connIdToRootNet[a3] === this.connIdToRootNet[s2] && this.overlapFriendlyRootNets.has(this.connIdToRootNet[s2]);
(a3 === -1 || a3 === s2 || c3) && (u2[r3] = s2, l2.push(r3));
}
}
const p2 = [], m2 = this.viaOccupantScanOffsetsDr, g2 = this.viaOccupantScanOffsetsDc, f2 = this.viaOccupantScanOffsetsLen;
for (let t4 = 0;t4 < o2.length; t4++) {
const e3 = o2[t4];
for (let t5 = 0;t5 < this.layers; t5++) {
const n3 = t5 * this.planeSize;
for (let t6 = 0;t6 < f2; t6++) {
const o3 = e3.row + m2[t6], i3 = e3.col + g2[t6];
if (o3 < 0 || o3 >= h2 || i3 < 0 || i3 >= d2)
continue;
const r3 = n3 + o3 * d2 + i3;
if ((o3 !== e3.row || i3 !== e3.col) && this.shouldSkipFixedPortHalo(r3, s2))
continue;
const a3 = u2[r3], c3 = this.connIdToRootNet[a3] === this.connIdToRootNet[s2] && this.overlapFriendlyRootNets.has(this.connIdToRootNet[s2]);
if (a3 !== -1 && a3 !== s2 && !c3) {
let t7 = false;
for (let e4 = 0;e4 < p2.length; e4++)
if (p2[e4] === a3) {
t7 = true;
break;
}
t7 || p2.push(a3);
}
u2[r3] = s2, l2.push(r3);
}
}
}
const y2 = [], _2 = this.cols - 1;
for (let t4 = 1;t4 < e2.length; t4++) {
const n3 = e2[t4 - 1], o3 = e2[t4];
if (n3.z !== o3.z)
continue;
const i3 = n3.row > o3.row ? n3.row - o3.row : o3.row - n3.row, r3 = n3.col > o3.col ? n3.col - o3.col : o3.col - n3.col;
if (i3 !== 1 || r3 !== 1)
continue;
const a3 = n3.row < o3.row ? n3.row : o3.row, c3 = n3.col < o3.col ? n3.col : o3.col, l3 = n3.row < o3.row && n3.col < o3.col || n3.row > o3.row && n3.col > o3.col ? 0 : 1, h3 = 1 ^ l3, d3 = 2 * ((n3.z * (this.rows - 1) + a3) * _2 + c3), u3 = d3 + h3, p3 = this.usedDiagFlat[u3], m3 = this.connIdToRootNet[p3] === this.connIdToRootNet[s2] && this.overlapFriendlyRootNets.has(this.connIdToRootNet[s2]);
if (p3 !== -1 && p3 !== s2 && !m3)
continue;
const g3 = d3 + l3;
this.usedDiagFlat[g3] = s2, y2.push(g3);
}
for (;this.usedIndicesByConn.length <= s2; )
this.usedIndicesByConn.push([]);
const b2 = this.usedIndicesByConn[s2] ?? [];
for (b2.push(...l2), this.usedIndicesByConn[s2] = b2;this.usedDiagIndicesByConn.length <= s2; )
this.usedDiagIndicesByConn.push([]);
const x2 = this.usedDiagIndicesByConn[s2] ?? [];
x2.push(...y2), this.usedDiagIndicesByConn[s2] = x2;
const v2 = this.solvedRoutes.get(s2) ?? [];
if (v2.push({ connId: s2, startZ: i2.z, startRow: i2.row, startCol: i2.col, startPoint: this.activeConnSeg.startPoint, endZ: r2.z, endRow: r2.row, endCol: r2.col, endPoint: this.activeConnSeg.endPoint, cells: e2, viaCells: o2 }), this.solvedRoutes.set(s2, v2), this.useExactViaTraceClearance) {
for (;this.viaCenterIndicesByConn.length <= s2; )
this.viaCenterIndicesByConn.push([]);
const t4 = this.viaCenterIndicesByConn[s2] ?? [];
for (const e3 of o2) {
const n3 = e3.row * this.cols + e3.col, o3 = this.viaOwnersByCell.get(n3) ?? new Set;
o3.has(s2) || (o3.add(s2), t4.push(n3)), this.viaOwnersByCell.set(n3, o3);
}
this.viaCenterIndicesByConn[s2] = t4;
}
for (let t4 = 0;t4 < p2.length; t4++)
if (this.ripTrace(p2[t4]), this.failed)
return;
if (a2.length > 0 || p2.length > 0) {
const t4 = this.penalty2d, e3 = this.penaltyCap;
if (this.totalRipEvents > 50)
for (let e4 = 0;e4 < t4.length; e4++)
t4[e4] = 0.99 * t4[e4];
else
for (let n3 = 0;n3 < t4.length; n3++)
t4[n3] > e3 && (t4[n3] = 0.5 * t4[n3]);
}
}
ripTrace(t3) {
for (;this.ripCount.length <= t3; )
this.ripCount.push(0);
if (this.ripCount[t3]++, this.totalRipEvents++, this.totalRipEvents >= this.MAX_RIPS)
return this.error = `Convergence failure: exceeded MAX_RIPS ${this.MAX_RIPS}`, void (this.failed = true);
const e2 = this.solvedRoutes.get(t3) ?? [];
if (e2.length > 0) {
const t4 = this.cols;
for (const n3 of e2) {
for (let e3 = 0;e3 < n3.cells.length; e3++) {
const o3 = n3.cells[e3], i3 = o3.row * t4 + o3.col;
this.penalty2d[i3] = this.penalty2d[i3] + this.hyperParameters.ripTracePenalty;
}
for (let e3 = 0;e3 < n3.viaCells.length; e3++) {
const o3 = n3.viaCells[e3], i3 = o3.row * t4 + o3.col;
this.penalty2d[i3] = this.penalty2d[i3] + this.hyperParameters.ripViaPenalty;
}
}
}
const n2 = this.usedIndicesByConn[t3];
if (n2) {
const e3 = this.usedCellsFlat;
for (let o3 = 0;o3 < n2.length; o3++) {
const i3 = n2[o3];
e3[i3] === t3 && (e3[i3] = -1);
}
this.usedIndicesByConn[t3] = [];
}
const o2 = this.usedDiagIndicesByConn[t3];
if (o2) {
const e3 = this.usedDiagFlat;
for (let n3 = 0;n3 < o2.length; n3++) {
const i3 = o2[n3];
e3[i3] === t3 && (e3[i3] = -1);
}
this.usedDiagIndicesByConn[t3] = [];
}
const i2 = this.viaCenterIndicesByConn[t3];
if (i2) {
for (const e3 of i2) {
const n3 = this.viaOwnersByCell.get(e3);
n3 && (n3.delete(t3), n3.size === 0 && this.viaOwnersByCell.delete(e3));
}
this.viaCenterIndicesByConn[t3] = [];
}
if (e2.length > 0) {
this.solvedRoutes.delete(t3);
for (const n3 of e2)
this.unsolvedSegs.push({ connId: t3, startZ: n3.startZ, startRow: n3.startRow, startCol: n3.startCol, startPoint: n3.startPoint, endZ: n3.endZ, endRow: n3.endRow, endCol: n3.endCol, endPoint: n3.endPoint });
}
}
visualize() {
const t3 = ["red", "blue", "orange", "green"], e2 = [], n2 = [], o2 = [], i2 = [], { width: r2, height: s2, center: a2 } = this.nodeWithPortPoints;
i2.push({ center: { x: a2.x, y: a2.y }, width: r2, height: s2, stroke: "gray" });
const c2 = this.gridToBoundsTransform;
if (this.showPenaltyMap && this.penalty2d) {
let t4 = 0;
for (let e3 = 0;e3 < this.penalty2d.length; e3++)
this.penalty2d[e3] > t4 && (t4 = this.penalty2d[e3]);
if (t4 > 0)
for (let e3 = 0;e3 < this.rows; e3++)
for (let n3 = 0;n3 < this.cols; n3++) {
const o3 = this.penalty2d[e3 * this.cols + n3];
if (o3 <= 0)
continue;
const r3 = Math.min(0.6, o3 / t4 * 0.6), s3 = gi(c2, { x: this.gridOrigin.x + (n3 + 0.5) * this.cellSizeMm, y: this.gridOrigin.y + (e3 + 0.5) * this.cellSizeMm });
i2.push({ center: s3, width: this.cellSizeMm * c2.a, height: this.cellSizeMm * c2.e, fill: `rgba(255,165,0,${r3.toFixed(3)})` });
}
}
if (this.showUsedCellMap && this.usedCellsFlat)
for (let t4 = 0;t4 < this.layers; t4++)
for (let e3 = 0;e3 < this.rows; e3++)
for (let n3 = 0;n3 < this.cols; n3++) {
if (this.usedCellsFlat[(t4 * this.rows + e3) * this.cols + n3] === -1)
continue;
const o3 = gi(c2, { x: this.gridOrigin.x + (n3 + 0.5) * this.cellSizeMm, y: this.gridOrigin.y + (e3 + 0.5) * this.cellSizeMm });
i2.push({ center: o3, width: this.cellSizeMm * c2.a, height: this.cellSizeMm * c2.e, fill: "rgba(0,0,255,0.5)" });
}
for (const n3 of this.nodeWithPortPoints.portPoints)
e2.push({ x: n3.x, y: n3.y, color: t3[n3.z] ?? "gray", label: n3.connectionName });
const l2 = ["rgba(255,0,0,0.75)", "rgba(0,0,255,0.75)", "rgba(255,165,0,0.75)", "rgba(0,128,0,0.75)"], h2 = this.getOutput();
for (const t4 of h2) {
if (t4.route.length < 2)
continue;
let e3 = 0;
for (let o3 = 1;o3 < t4.route.length; o3++) {
const i3 = t4.route[o3 - 1];
t4.route[o3].z !== i3.z && (o3 - e3 >= 2 && n2.push({ points: t4.route.slice(e3, o3).map((t5) => ({ x: t5.x, y: t5.y })), strokeColor: l2[i3.z] ?? "rgba(128,128,128,0.75)", strokeWidth: this.traceThickness }), e3 = o3);
}
if (t4.route.length - e3 >= 2) {
const o3 = t4.route[e3].z;
n2.push({ points: t4.route.slice(e3).map((t5) => ({ x: t5.x, y: t5.y })), strokeColor: l2[o3] ?? "rgba(128,128,128,0.75)", strokeWidth: this.traceThickness });
}
}
for (const t4 of h2)
for (const e3 of t4.vias)
o2.push({ center: { x: e3.x, y: e3.y }, radius: this.viaDiameter / 2, fill: "rgba(0,0,0,0.3)", stroke: "black" });
if (this.activeConnSeg && this.visitedStamp) {
const t4 = this.stamp;
for (let n3 = 0;n3 < this.layers; n3++)
for (let o3 = 0;o3 < this.rows; o3++)
for (let i3 = 0;i3 < this.cols; i3++) {
if (this.visitedStamp[(n3 * this.rows + o3) * this.cols + i3] !== t4)
continue;
const r3 = gi(c2, { x: this.gridOrigin.x + (i3 + 0.5) * this.cellSizeMm, y: this.gridOrigin.y + (o3 + 0.5) * this.cellSizeMm });
e2.push({ x: r3.x, y: r3.y, color: "rgba(0,0,255,0.2)" });
}
}
return { points: e2, lines: n2, circles: o2, rects: i2, coordinateSystem: "cartesian", title: `HighDensityA01 [${this.solvedRoutes?.size ?? 0} solved, ${this.unsolvedSegs?.length ?? 0} remaining]` };
}
getOutput() {
const t3 = this.gridToBoundsTransform, e2 = [];
for (const [n2, o2] of this.solvedRoutes ?? []) {
const i2 = this.connIdToName[n2];
for (const r2 of o2) {
const o3 = r2.cells.map((e3) => {
const n3 = this.gridOrigin.x + (e3.col + 0.5) * this.cellSizeMm, o4 = this.gridOrigin.y + (e3.row + 0.5) * this.cellSizeMm, i3 = gi(t3, { x: n3, y: o4 });
return { x: i3.x, y: i3.y, z: this.layerToZ.get(e3.z) ?? e3.z };
});
o3.length > 0 && (o3[0] = { ...r2.startPoint }, o3.length > 1 && (o3[o3.length - 1] = { ...r2.endPoint })), e2.push({ connectionName: i2, rootConnectionName: this.connIdToRootNet[n2], regionId: this.nodeWithPortPoints.capacityMeshNodeId, traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, route: o3, vias: r2.viaCells.map((e3) => {
const n3 = this.gridOrigin.x + (e3.col + 0.5) * this.cellSizeMm, o4 = this.gridOrigin.y + (e3.row + 0.5) * this.cellSizeMm;
return gi(t3, { x: n3, y: o4 });
}) });
}
}
return e2;
}
};
var Mi = ["left", "top", "right", "bottom", "middle"];
var Ni = class {
f = new Float64Array(1024);
seq = new Uint32Array(1024);
id = new Int32Array(1024);
n = 0;
push(t3, e2, n2) {
this.ensureCapacity(this.n + 1);
let o2 = this.n++;
for (this.f[o2] = t3, this.seq[o2] = e2, this.id[o2] = n2;o2 > 0; ) {
const t4 = o2 - 1 >> 1;
if (this.less(t4, o2))
break;
this.swap(o2, t4), o2 = t4;
}
}
pop() {
const t3 = this.id[0];
return this.n--, this.n > 0 && (this.f[0] = this.f[this.n], this.seq[0] = this.seq[this.n], this.id[0] = this.id[this.n], this.siftDown(0)), t3;
}
get size() {
return this.n;
}
clear() {
this.n = 0;
}
ensureCapacity(t3) {
if (t3 <= this.f.length)
return;
let e2 = this.f.length;
for (;e2 < t3; )
e2 *= 2;
const n2 = new Float64Array(e2);
n2.set(this.f), this.f = n2;
const o2 = new Uint32Array(e2);
o2.set(this.seq), this.seq = o2;
const i2 = new Int32Array(e2);
i2.set(this.id), this.id = i2;
}
siftDown(t3) {
for (;; ) {
const e2 = 2 * t3 + 1, n2 = e2 + 1;
if (e2 >= this.n)
return;
let o2 = e2;
if (n2 < this.n && !this.less(e2, n2) && (o2 = n2), this.less(t3, o2))
return;
this.swap(t3, o2), t3 = o2;
}
}
less(t3, e2) {
const n2 = this.f[t3], o2 = this.f[e2];
return n2 !== o2 ? n2 < o2 : this.seq[t3] < this.seq[e2];
}
swap(t3, e2) {
const n2 = this.f[t3];
this.f[t3] = this.f[e2], this.f[e2] = n2;
const o2 = this.seq[t3];
this.seq[t3] = this.seq[e2], this.seq[e2] = o2;
const i2 = this.id[t3];
this.id[t3] = this.id[e2], this.id[e2] = i2;
}
};
var wi = class {
z = new Int32Array(1024);
cellId = new Int32Array(1024);
g = new Float64Array(1024);
parent = new Int32Array(1024);
ripHead = new Int32Array(1024).fill(-1);
ripCount = new Int32Array(1024);
length = 0;
clear() {
this.length = 0;
}
push(t3, e2, n2, o2, i2, r2) {
this.ensureCapacity(this.length + 1);
const s2 = this.length++;
return this.z[s2] = t3, this.cellId[s2] = e2, this.g[s2] = n2, this.parent[s2] = o2, this.ripHead[s2] = i2, this.ripCount[s2] = r2, s2;
}
ensureCapacity(t3) {
if (t3 <= this.z.length)
return;
let e2 = this.z.length;
for (;e2 < t3; )
e2 *= 2;
const n2 = new Int32Array(e2);
n2.set(this.z), this.z = n2;
const o2 = new Int32Array(e2);
o2.set(this.cellId), this.cellId = o2;
const i2 = new Float64Array(e2);
i2.set(this.g), this.g = i2;
const r2 = new Int32Array(e2);
r2.set(this.parent), this.parent = r2;
const s2 = new Int32Array(e2);
s2.fill(-1), s2.set(this.ripHead.subarray(0, this.length)), this.ripHead = s2;
const a2 = new Int32Array(e2);
a2.set(this.ripCount.subarray(0, this.length)), this.ripCount = a2;
}
};
var Ti = class {
connId = new Int32Array(1024);
prev = new Int32Array(1024).fill(-1);
length = 0;
clear() {
this.length = 0;
}
append(t3, e2) {
this.ensureCapacity(this.length + 1);
const n2 = this.length++;
return this.connId[n2] = e2, this.prev[n2] = t3, n2;
}
contains(t3, e2) {
for (let n2 = t3;n2 >= 0; n2 = this.prev[n2])
if (this.connId[n2] === e2)
return true;
return false;
}
collect(t3, e2) {
e2.length = 0;
for (let n2 = t3;n2 >= 0; n2 = this.prev[n2])
e2.push(this.connId[n2]);
}
ensureCapacity(t3) {
if (t3 <= this.connId.length)
return;
let e2 = this.connId.length;
for (;e2 < t3; )
e2 *= 2;
const n2 = new Int32Array(e2);
n2.set(this.connId), this.connId = n2;
const o2 = new Int32Array(e2);
o2.fill(-1), o2.set(this.prev.subarray(0, this.length)), this.prev = o2;
}
};
function Ri(t3, e2, n2) {
return Math.max(e2, Math.min(n2, t3));
}
function Ei(t3, e2) {
for (let n2 = 0;n2 < t3.length; n2++)
if (t3[n2] === e2)
return;
t3.push(e2);
}
function Ai(t3, e2) {
for (let n2 = 0;n2 < t3.length; n2++)
if (t3[n2].cellId === e2.cellId)
return;
t3.push(e2);
}
function Oi(t3, e2, n2, o2, i2, r2, s2) {
const a2 = t3 - Ri(t3, o2, r2), c2 = e2 - Ri(e2, i2, s2);
return a2 * a2 + c2 * c2 <= n2 * n2;
}
var ki;
var Di = class extends kt {
getSolverName() {
return "HighDensitySolverA03";
}
nodeWithPortPoints;
highResolutionCellSize;
highResolutionCellThickness;
lowResolutionCellSize;
viaDiameter;
MAX_RIPS;
maxCellCount;
traceThickness;
traceMargin;
viaMinDistFromBorder;
showPenaltyMap;
showUsedCellMap;
effort;
enableDiagonalMoves;
stepMultiplier;
hyperParameters;
initialPenaltyFn;
boundsMinX;
boundsMaxX;
boundsMinY;
boundsMaxY;
gridToBoundsTransform;
availableZ;
zToLayer;
layerToZ;
layers;
fineRows;
fineCols;
lowScale;
bandRows;
bandCols;
regions;
planeSize;
cellCenterX;
cellCenterY;
cellMinX;
cellMinY;
cellMaxX;
cellMaxY;
cellWidth;
cellHeight;
cellRegion;
cellRow;
cellCol;
viaAllowed;
neighborOffset;
neighborIds;
neighborCosts;
usedCellsFlat;
sharedCellsFlat;
portOwnerFlat;
penalty2d;
ripStateBuckets;
visitedStamp;
bestGStamp;
bestGValue;
visitedFlatStamp;
sharedCrossRootPortFlat;
stamp = 0;
connNameToId;
connIdToName;
connIdToRootNet;
overlapFriendlyRootNets;
usedIndicesByConn;
unsolvedSegs;
solvedRoutes;
activeConnSeg = null;
activeConnId = -1;
nodePool;
heap;
ripChain;
seqCounter = 0;
_viaOccs = [];
viaOccupantsByCell = new Map;
_cellOccs = [];
_rippedIds = [];
ripCount;
totalRipEvents = 0;
searchIterations = 0;
consecutiveSkips = 0;
penaltyCap;
baseSearchBudgetIters;
_moveCost = 0;
_moveRippedHead = -1;
_moveRipCount = 0;
traceKeepoutRadius;
viaKeepoutRadius;
get unsolvedConnections() {
return this.unsolvedSegs;
}
get solvedConnectionsMap() {
const t3 = new Map;
for (let e2 = 0;e2 < this.solvedRoutes.length; e2++) {
const n2 = this.getSolvedRoutesForConn(e2);
n2.length > 0 && t3.set(e2, n2);
}
return t3;
}
get activeConnection() {
if (!this.activeConnSeg)
return null;
const t3 = this.activeConnSeg.startCellId, e2 = this.activeConnSeg.endCellId;
return { connectionName: this.connIdToName[this.activeConnSeg.connId] ?? "", start: { cellId: t3, region: Mi[this.cellRegion[t3]], row: this.cellRow[t3], col: this.cellCol[t3], x: this.cellCenterX[t3], y: this.cellCenterY[t3], z: this.activeConnSeg.startZ }, end: { cellId: e2, region: Mi[this.cellRegion[e2]], row: this.cellRow[e2], col: this.cellCol[e2], x: this.cellCenterX[e2], y: this.cellCenterY[e2], z: this.activeConnSeg.endZ } };
}
get openSet() {
return { length: this.heap?.size ?? 0 };
}
get gridStats() {
return { cells: this.planeSize || 0, layers: this.layers || 0, states: (this.planeSize || 0) * (this.layers || 0), ripStateBuckets: this.ripStateBuckets || 0, neighborEdges: this.neighborIds?.length ?? 0, regionCounts: this.regions ? Object.fromEntries(this.regions.map((t3) => [t3.name, t3.rows * t3.cols])) : {} };
}
constructor(t3) {
super(), this.nodeWithPortPoints = t3.nodeWithPortPoints, this.highResolutionCellSize = t3.highResolutionCellSize ?? 0.1, this.highResolutionCellThickness = Math.max(1, Math.floor(t3.highResolutionCellThickness ?? 8)), this.lowResolutionCellSize = t3.lowResolutionCellSize ?? 0.4, this.viaDiameter = t3.viaDiameter, this.maxCellCount = t3.maxCellCount, this.traceThickness = t3.traceThickness ?? 0.1, this.traceMargin = t3.traceMargin ?? 0.15, this.viaMinDistFromBorder = t3.viaMinDistFromBorder ?? 0.15, this.showPenaltyMap = t3.showPenaltyMap ?? false, this.showUsedCellMap = t3.showUsedCellMap ?? false, this.effort = t3.effort ?? 1, this.enableDiagonalMoves = t3.enableDiagonalMoves ?? false, this.stepMultiplier = Math.max(1, Math.floor(t3.stepMultiplier ?? 1)), this.hyperParameters = { shuffleSeed: 0, ripCost: 8, ripTracePenalty: 0.5, ripViaPenalty: 0.75, viaBaseCost: 0.1, greedyMultiplier: 1.5, ...t3.hyperParameters }, this.MAX_ITERATIONS = 1e8, this.MAX_RIPS = 200, this.initialPenaltyFn = t3.initialPenaltyFn;
}
getConstructorParams() {
return [{ nodeWithPortPoints: this.nodeWithPortPoints, highResolutionCellSize: this.highResolutionCellSize, highResolutionCellThickness: this.highResolutionCellThickness, lowResolutionCellSize: this.lowResolutionCellSize, viaDiameter: this.viaDiameter, maxCellCount: this.maxCellCount, stepMultiplier: this.stepMultiplier, traceThickness: this.traceThickness, traceMargin: this.traceMargin, viaMinDistFromBorder: this.viaMinDistFromBorder, showPenaltyMap: this.showPenaltyMap, showUsedCellMap: this.showUsedCellMap, effort: this.effort, enableDiagonalMoves: this.enableDiagonalMoves, hyperParameters: this.hyperParameters, initialPenaltyFn: this.initialPenaltyFn }];
}
_setup() {
const { nodeWithPortPoints: t3 } = this, { width: e2, height: n2, center: o2 } = t3, i2 = this.lowResolutionCellSize / this.highResolutionCellSize, r2 = Math.round(i2);
if (!Number.isFinite(i2) || i2 <= 0 || Math.abs(i2 - r2) > 0.000000001)
return this.error = "lowResolutionCellSize must be a positive integer multiple of highResolutionCellSize", void (this.failed = true);
this.lowScale = Math.max(1, r2), this.availableZ = t3.availableZ ?? [...new Set(t3.portPoints.map((t4) => t4.z))].sort((t4, e3) => t4 - e3), this.layers = this.availableZ.length, this.zToLayer = new Map, this.layerToZ = new Map;
for (let t4 = 0;t4 < this.availableZ.length; t4++) {
const e3 = this.availableZ[t4];
this.zToLayer.set(e3, t4), this.layerToZ.set(t4, e3);
}
this.boundsMinX = o2.x - e2 / 2, this.boundsMaxX = o2.x + e2 / 2, this.boundsMinY = o2.y - n2 / 2, this.boundsMaxY = o2.y + n2 / 2, this.traceKeepoutRadius = this.traceMargin + this.traceThickness / 2, this.viaKeepoutRadius = this.viaDiameter / 2 + this.traceKeepoutRadius, this.buildFiveRegionGrid(e2, n2), this.gridToBoundsTransform = this.computeGridToBoundsTransform();
const s2 = this.layers * this.planeSize;
if (this.maxCellCount !== undefined && s2 > this.maxCellCount)
return this.error = `Cell count ${s2} exceeds maxCellCount ${this.maxCellCount}`, void (this.failed = true);
this.connNameToId = new Map, this.connIdToName = [], this.connIdToRootNet = [], this.overlapFriendlyRootNets = new Set, this.unsolvedSegs = this.buildConnectionSegs(), this.penalty2d = new Float64Array(this.planeSize);
const a2 = e2 > 0 ? 1 / e2 : 0, c2 = n2 > 0 ? 1 / n2 : 0;
for (let t4 = 0;t4 < this.planeSize; t4++) {
let e3 = 0;
this.initialPenaltyFn && (e3 += this.initialPenaltyFn({ x: this.cellCenterX[t4], y: this.cellCenterY[t4], px: (this.cellCenterX[t4] - this.boundsMinX) * a2, py: (this.cellCenterY[t4] - this.boundsMinY) * c2, cellId: t4, region: Mi[this.cellRegion[t4]], row: this.cellRow[t4], col: this.cellCol[t4] })), this.penalty2d[t4] = e3;
}
this.usedCellsFlat = new Int32Array(s2).fill(-1), this.sharedCellsFlat = Array.from({ length: s2 }, () => {}), this.portOwnerFlat = new Int32Array(s2).fill(-1), this.sharedCrossRootPortFlat = new Uint8Array(s2), this.ripStateBuckets = 1;
const l2 = s2;
this.visitedStamp = new Uint32Array(l2), this.bestGStamp = new Uint32Array(l2), this.bestGValue = new Float64Array(l2), this.visitedFlatStamp = new Uint32Array(s2), this.stamp = 0;
const h2 = new Map;
for (const t4 of this.nodeWithPortPoints.portPoints) {
const e3 = this.connNameToId.get(t4.connectionName);
if (e3 === undefined)
continue;
const n3 = this.pointToCell(t4), o3 = n3.z * this.planeSize + n3.cellId, i3 = this.connIdToRootNet[e3], r3 = h2.get(o3);
r3 === undefined ? h2.set(o3, i3) : r3 !== i3 && (this.sharedCrossRootPortFlat[o3] = 1);
const s3 = this.portOwnerFlat[o3];
this.portOwnerFlat[o3] = s3 === -1 || s3 === e3 ? e3 : -2;
}
this.solvedRoutes = [], this.usedIndicesByConn = [], this.ripCount = [], this.consecutiveSkips = 0, this.penaltyCap = 0.5 * this.hyperParameters.ripCost, this.shuffleConnections();
const d2 = xi({ planeSize: this.planeSize, layers: this.layers, connectionCount: this.unsolvedSegs.length, effort: this.effort, maxIterations: this.MAX_ITERATIONS });
this.baseSearchBudgetIters = d2.baseSearchBudgetIters, this.MAX_ITERATIONS = d2.maxIterationsIters, this.activeConnSeg = null, this.activeConnId = -1, this.nodePool = new wi, this.heap = new Ni, this.ripChain = new Ti, this.seqCounter = 0;
}
_step() {
for (let t3 = 0;t3 < this.stepMultiplier; t3++) {
if (this.solved || this.failed)
return;
this.stepOnce();
}
}
buildFiveRegionGrid(t3, e2) {
this.fineCols = Math.max(1, Math.ceil(t3 / this.highResolutionCellSize)), this.fineRows = Math.max(1, Math.ceil(e2 / this.highResolutionCellSize)), this.bandCols = Math.min(this.highResolutionCellThickness, Math.floor(this.fineCols / 2)), this.bandRows = Math.min(this.highResolutionCellThickness, Math.floor(this.fineRows / 2));
const n2 = Math.max(0, this.fineCols - 2 * this.bandCols), o2 = Math.max(0, this.fineRows - 2 * this.bandRows), i2 = n2, r2 = n2;
this.regions = [{ id: 0, name: "left", fineOriginRow: 0, fineOriginCol: 0, fineRows: this.fineRows, fineCols: this.bandCols, cellScale: 1, rows: this.fineRows, cols: this.bandCols, offset: 0 }, { id: 1, name: "top", fineOriginRow: 0, fineOriginCol: this.bandCols, fineRows: this.bandRows, fineCols: i2, cellScale: 1, rows: this.bandRows, cols: i2, offset: 0 }, { id: 2, name: "right", fineOriginRow: 0, fineOriginCol: this.fineCols - this.bandCols, fineRows: this.fineRows, fineCols: this.bandCols, cellScale: 1, rows: this.fineRows, cols: this.bandCols, offset: 0 }, { id: 3, name: "bottom", fineOriginRow: this.fineRows - this.bandRows, fineOriginCol: this.bandCols, fineRows: this.bandRows, fineCols: r2, cellScale: 1, rows: this.bandRows, cols: r2, offset: 0 }, { id: 4, name: "middle", fineOriginRow: this.bandRows, fineOriginCol: this.bandCols, fineRows: o2, fineCols: n2, cellScale: this.lowScale, rows: o2 > 0 ? Math.ceil(o2 / this.lowScale) : 0, cols: n2 > 0 ? Math.ceil(n2 / this.lowScale) : 0, offset: 0 }];
let s2 = 0;
for (let t4 = 0;t4 < this.regions.length; t4++)
this.regions[t4].offset = s2, s2 += this.regions[t4].rows * this.regions[t4].cols;
this.planeSize = s2, this.cellCenterX = new Float64Array(this.planeSize), this.cellCenterY = new Float64Array(this.planeSize), this.cellMinX = new Float64Array(this.planeSize), this.cellMinY = new Float64Array(this.planeSize), this.cellMaxX = new Float64Array(this.planeSize), this.cellMaxY = new Float64Array(this.planeSize), this.cellWidth = new Float64Array(this.planeSize), this.cellHeight = new Float64Array(this.planeSize), this.cellRegion = new Uint8Array(this.planeSize), this.cellRow = new Int32Array(this.planeSize), this.cellCol = new Int32Array(this.planeSize), this.viaAllowed = new Uint8Array(this.planeSize);
for (let t4 = 0;t4 < this.regions.length; t4++) {
const e3 = this.regions[t4];
for (let t5 = 0;t5 < e3.rows; t5++) {
const n3 = e3.fineOriginRow + t5 * e3.cellScale, o3 = Math.min(e3.fineOriginRow + e3.fineRows, n3 + e3.cellScale), i3 = this.boundsMinY + n3 * this.highResolutionCellSize, r3 = Math.min(this.boundsMaxY, this.boundsMinY + o3 * this.highResolutionCellSize);
for (let n4 = 0;n4 < e3.cols; n4++) {
const o4 = e3.fineOriginCol + n4 * e3.cellScale, s3 = Math.min(e3.fineOriginCol + e3.fineCols, o4 + e3.cellScale), a3 = this.boundsMinX + o4 * this.highResolutionCellSize, c3 = Math.min(this.boundsMaxX, this.boundsMinX + s3 * this.highResolutionCellSize), l3 = this.cellIdFor(e3.id, t5, n4);
this.cellCenterX[l3] = (a3 + c3) / 2, this.cellCenterY[l3] = (i3 + r3) / 2, this.cellMinX[l3] = a3, this.cellMinY[l3] = i3, this.cellMaxX[l3] = c3, this.cellMaxY[l3] = r3, this.cellWidth[l3] = c3 - a3, this.cellHeight[l3] = r3 - i3, this.cellRegion[l3] = e3.id, this.cellRow[l3] = t5, this.cellCol[l3] = n4;
const h3 = Math.min(this.cellCenterX[l3] - this.boundsMinX, this.boundsMaxX - this.cellCenterX[l3], this.cellCenterY[l3] - this.boundsMinY, this.boundsMaxY - this.cellCenterY[l3]);
this.viaAllowed[l3] = h3 >= this.viaMinDistFromBorder ? 1 : 0;
}
}
}
const a2 = Array.from({ length: this.planeSize }, () => []), c2 = (t4, e3) => {
if (t4 === e3 || t4 < 0 || e3 < 0)
return;
const n3 = this.cellCenterX[t4] - this.cellCenterX[e3], o3 = this.cellCenterY[t4] - this.cellCenterY[e3], i3 = Math.hypot(n3, o3);
Ai(a2[t4], { cellId: e3, cost: i3 }), Ai(a2[e3], { cellId: t4, cost: i3 });
};
for (let t4 = 0;t4 < this.regions.length; t4++) {
const e3 = this.regions[t4];
for (let t5 = 0;t5 < e3.rows; t5++)
for (let n3 = 0;n3 < e3.cols; n3++) {
const o3 = this.cellIdFor(e3.id, t5, n3);
t5 + 1 < e3.rows && c2(o3, this.cellIdFor(e3.id, t5 + 1, n3)), n3 + 1 < e3.cols && c2(o3, this.cellIdFor(e3.id, t5, n3 + 1)), this.enableDiagonalMoves && t5 + 1 < e3.rows && (n3 + 1 < e3.cols && c2(o3, this.cellIdFor(e3.id, t5 + 1, n3 + 1)), n3 > 0 && c2(o3, this.cellIdFor(e3.id, t5 + 1, n3 - 1)));
}
}
const l2 = this.regions[0], h2 = this.regions[1], d2 = this.regions[2], u2 = this.regions[3], p2 = this.regions[4], m2 = l2.rows > 0 && l2.cols > 0, g2 = h2.rows > 0 && h2.cols > 0, f2 = d2.rows > 0 && d2.cols > 0, y2 = u2.rows > 0 && u2.cols > 0, _2 = p2.rows > 0 && p2.cols > 0;
if (m2 && g2)
for (let t4 = 0;t4 < this.bandRows; t4++)
c2(this.cellIdFor(0, t4, l2.cols - 1), this.cellIdFor(1, t4, 0));
if (g2 && f2)
for (let t4 = 0;t4 < this.bandRows; t4++)
c2(this.cellIdFor(1, t4, h2.cols - 1), this.cellIdFor(2, t4, 0));
if (m2 && y2)
for (let t4 = this.fineRows - this.bandRows;t4 < this.fineRows; t4++)
c2(this.cellIdFor(0, t4, l2.cols - 1), this.cellIdFor(3, t4 - (this.fineRows - this.bandRows), 0));
if (y2 && f2)
for (let t4 = this.fineRows - this.bandRows;t4 < this.fineRows; t4++)
c2(this.cellIdFor(3, t4 - (this.fineRows - this.bandRows), u2.cols - 1), this.cellIdFor(2, t4, 0));
if (m2 && _2)
for (let t4 = this.bandRows;t4 < this.fineRows - this.bandRows; t4++)
c2(this.cellIdFor(0, t4, l2.cols - 1), this.cellIdFor(4, Math.floor((t4 - this.bandRows) / this.lowScale), 0));
if (f2 && _2)
for (let t4 = this.bandRows;t4 < this.fineRows - this.bandRows; t4++)
c2(this.cellIdFor(4, Math.floor((t4 - this.bandRows) / this.lowScale), p2.cols - 1), this.cellIdFor(2, t4, 0));
if (g2 && _2)
for (let t4 = this.bandCols;t4 < this.fineCols - this.bandCols; t4++)
c2(this.cellIdFor(1, h2.rows - 1, t4 - this.bandCols), this.cellIdFor(4, 0, Math.floor((t4 - this.bandCols) / this.lowScale)));
if (y2 && _2)
for (let t4 = this.bandCols;t4 < this.fineCols - this.bandCols; t4++)
c2(this.cellIdFor(4, p2.rows - 1, Math.floor((t4 - this.bandCols) / this.lowScale)), this.cellIdFor(3, 0, t4 - this.bandCols));
if (!_2 && !g2 && !y2 && m2 && f2)
for (let t4 = 0;t4 < Math.min(l2.rows, d2.rows); t4++)
c2(this.cellIdFor(0, t4, l2.cols - 1), this.cellIdFor(2, t4, 0));
if (!_2 && !m2 && !f2 && g2 && y2)
for (let t4 = 0;t4 < Math.min(h2.cols, u2.cols); t4++)
c2(this.cellIdFor(1, h2.rows - 1, t4), this.cellIdFor(3, 0, t4));
const b2 = this.flattenNeighborLists(a2);
this.neighborOffset = b2.offset, this.neighborIds = b2.ids, this.neighborCosts = b2.costs;
}
cellIdFor(t3, e2, n2) {
const o2 = this.regions[t3];
return o2.offset + e2 * o2.cols + n2;
}
stepOnce() {
if (!this.activeConnSeg) {
if (this.unsolvedSegs.length === 0)
return void (this.solved = true);
const t4 = this.unsolvedSegs.shift();
this.activeConnSeg = t4, this.activeConnId = t4.connId, this.viaOccupantsByCell.clear(), this.nodePool.clear(), this.ripChain.clear(), this.heap.clear(), this.seqCounter = 0, this.searchIterations = 0, this.nextStamp();
const e3 = this.computeH(t4.startZ, t4.startCellId, t4.endZ, t4.endCellId) * this.hyperParameters.greedyMultiplier, n3 = this.nodePool.push(t4.startZ, t4.startCellId, 0, -1, -1, 0), o3 = t4.startZ * this.planeSize + t4.startCellId, i3 = this.getSearchStateIdx(o3, 0);
return this.bestGStamp[i3] = this.stamp, this.bestGValue[i3] = 0, void this.heap.push(e3, this.seqCounter++, n3);
}
this.searchIterations++;
const t3 = this.ripCount[this.activeConnId] ?? 0, e2 = Math.round(this.baseSearchBudgetIters * (1 + 0.25 * Math.min(t3, 10)));
if (this.searchIterations > e2) {
const t4 = this.penalty2d;
for (let e3 = 0;e3 < t4.length; e3++)
t4[e3] = 0.9 * t4[e3];
return this.unsolvedSegs.push(this.activeConnSeg), this.activeConnSeg = null, this.activeConnId = -1, this.heap.clear(), this.nodePool.clear(), this.consecutiveSkips++, void (this.consecutiveSkips >= Math.max(3, 3 * this.unsolvedSegs.length) && (this.error = `Convergence failure: ${this.unsolvedSegs.length} connections stuck`, this.failed = true));
}
if (this.heap.size === 0)
return this.error = `No path found for ${this.connIdToName[this.activeConnId]}`, void (this.failed = true);
const n2 = this.heap.pop(), o2 = this.nodePool.z[n2], i2 = this.nodePool.cellId[n2], r2 = this.nodePool.g[n2], s2 = this.nodePool.ripHead[n2], a2 = this.nodePool.ripCount[n2], c2 = o2 * this.planeSize + i2, l2 = this.getSearchStateIdx(c2, a2);
if (this.visitedStamp[l2] === this.stamp)
return;
this.visitedStamp[l2] = this.stamp, this.visitedFlatStamp[c2] = this.stamp;
const h2 = this.activeConnSeg;
if (o2 === h2.endZ && i2 === h2.endCellId)
return this.finalizeRoute(n2), this.activeConnSeg = null, void (this.activeConnId = -1);
const d2 = this.visitedStamp, u2 = this.stamp, p2 = this.activeConnId, m2 = h2.endZ, g2 = h2.endCellId, f2 = this.neighborOffset[i2], y2 = this.neighborOffset[i2 + 1];
for (let t4 = f2;t4 < y2; t4++) {
const e3 = this.neighborIds[t4], i3 = o2 * this.planeSize + e3;
if (this.computeMoveCostAndRips(p2, o2, e3, false, s2, a2, this.neighborCosts[t4]), this._moveCost < 0)
continue;
const c3 = this.getSearchStateIdx(i3, this._moveRipCount);
if (d2[c3] === u2)
continue;
const l3 = r2 + this._moveCost;
if (this.bestGStamp[c3] === u2 && l3 >= this.bestGValue[c3])
continue;
this.bestGStamp[c3] = u2, this.bestGValue[c3] = l3;
const h3 = l3 + this.computeH(o2, e3, m2, g2) * this.hyperParameters.greedyMultiplier, f3 = this.nodePool.push(o2, e3, l3, n2, this._moveRippedHead, this._moveRipCount);
this.heap.push(h3, this.seqCounter++, f3);
}
if (this.viaAllowed[i2])
for (let t4 = 0;t4 < this.layers; t4++) {
if (t4 === o2)
continue;
const e3 = t4 * this.planeSize + i2;
if (this.computeMoveCostAndRips(p2, t4, i2, true, s2, a2, 0), this._moveCost < 0)
continue;
const c3 = this.getSearchStateIdx(e3, this._moveRipCount);
if (d2[c3] === u2)
continue;
const l3 = r2 + this._moveCost;
if (this.bestGStamp[c3] === u2 && l3 >= this.bestGValue[c3])
continue;
this.bestGStamp[c3] = u2, this.bestGValue[c3] = l3;
const h3 = l3 + this.computeH(t4, i2, m2, g2) * this.hyperParameters.greedyMultiplier, f3 = this.nodePool.push(t4, i2, l3, n2, this._moveRippedHead, this._moveRipCount);
this.heap.push(h3, this.seqCounter++, f3);
}
}
computeMoveCostAndRips(t3, e2, n2, o2, i2, r2, s2) {
let a2 = 0, c2 = i2, l2 = r2;
const h2 = e2 * this.planeSize + n2;
if (o2) {
a2 += this.hyperParameters.viaBaseCost, a2 += Math.min(this.penalty2d[n2], this.penaltyCap);
const o3 = this.portOwnerFlat[h2], i3 = this.allowSharedUse(t3, o3), r3 = this.activeConnSeg, s3 = !!r3 && e2 === r3.endZ && n2 === r3.endCellId;
if (o3 >= 0 && o3 !== t3 && !i3 && !s3)
return this._moveCost = -1, void (this._moveRippedHead = c2);
this.fillViaOccupants(n2, t3);
const d2 = this._viaOccs;
for (let t4 = 0;t4 < d2.length; t4++) {
const e3 = d2[t4];
this.ripChain.contains(c2, e3) || (a2 += this.hyperParameters.ripCost, c2 = this.ripChain.append(c2, e3), l2++), a2 += this.hyperParameters.ripViaPenalty;
}
} else {
a2 += s2, a2 += Math.min(this.penalty2d[n2], this.penaltyCap);
const o3 = this.portOwnerFlat[h2], i3 = this.allowSharedUse(t3, o3), r3 = this.activeConnSeg, d2 = !!r3 && e2 === r3.endZ && n2 === r3.endCellId;
if (o3 >= 0 && o3 !== t3 && !i3 && !d2)
return this._moveCost = -1, void (this._moveRippedHead = c2);
this.fillTraceOccupants(h2, t3, this._cellOccs);
for (let t4 = 0;t4 < this._cellOccs.length; t4++) {
const e3 = this._cellOccs[t4];
this.ripChain.contains(c2, e3) || (a2 += this.hyperParameters.ripCost, c2 = this.ripChain.append(c2, e3), l2++), a2 += this.hyperParameters.ripTracePenalty;
}
}
this._moveCost = a2, this._moveRippedHead = c2, this._moveRipCount = l2;
}
fillViaOccupants(t3, e2) {
const n2 = this._viaOccs;
n2.length = 0;
const o2 = this.viaOccupantsByCell.get(t3);
if (o2) {
for (const t4 of o2)
n2.push(t4);
return;
}
const i2 = this.cellCenterX[t3], r2 = this.cellCenterY[t3];
this.forEachCellNearCircle(i2, r2, this.viaKeepoutRadius, (t4) => {
if (Oi(i2, r2, this.viaKeepoutRadius, this.cellMinX[t4], this.cellMinY[t4], this.cellMaxX[t4], this.cellMaxY[t4]))
for (let o3 = 0;o3 < this.layers; o3++)
this.pushFlatOccupants(o3 * this.planeSize + t4, e2, n2);
}), this.viaOccupantsByCell.set(t3, n2.slice());
}
fillTraceOccupants(t3, e2, n2) {
n2.length = 0, this.pushFlatOccupants(t3, e2, n2);
}
pushFlatOccupants(t3, e2, n2) {
const o2 = this.usedCellsFlat[t3];
o2 === -1 || o2 === e2 || this.allowSharedUse(e2, o2) || Ei(n2, o2);
const i2 = this.sharedCellsFlat[t3];
if (i2)
for (let t4 = 0;t4 < i2.length; t4++) {
const o3 = i2[t4];
o3 !== e2 && (this.allowSharedUse(e2, o3) || Ei(n2, o3));
}
}
addSharedOccupant(t3, e2) {
if (this.usedCellsFlat[t3] === e2)
return;
let n2 = this.sharedCellsFlat[t3];
n2 || (n2 = [], this.sharedCellsFlat[t3] = n2), Ei(n2, e2);
}
replaceOccupants(t3, e2) {
this.usedCellsFlat[t3] = e2, this.sharedCellsFlat[t3] = undefined;
}
removeOccupant(t3, e2) {
const n2 = this.sharedCellsFlat[t3];
if (this.usedCellsFlat[t3] === e2)
return void (n2 && n2.length > 0 ? (this.usedCellsFlat[t3] = n2.pop(), n2.length === 0 && (this.sharedCellsFlat[t3] = undefined)) : this.usedCellsFlat[t3] = -1);
if (!n2)
return;
const o2 = n2.indexOf(e2);
o2 !== -1 && (n2.splice(o2, 1), n2.length === 0 && (this.sharedCellsFlat[t3] = undefined));
}
allowSharedUse(t3, e2) {
if (e2 < 0)
return false;
return this.connIdToRootNet[e2] === this.connIdToRootNet[t3];
}
shouldSkipFixedPortHalo(t3, e2) {
const n2 = this.portOwnerFlat[t3];
return n2 !== e2 && (n2 === -2 || !(n2 < 0) && !this.allowSharedUse(e2, n2));
}
nextStamp() {
this.stamp = this.stamp + 1 >>> 0, this.stamp === 0 && (this.visitedStamp.fill(0), this.bestGStamp.fill(0), this.visitedFlatStamp.fill(0), this.stamp = 1);
}
getSearchStateIdx(t3, e2) {
return t3;
}
computeH(t3, e2, n2, o2) {
const i2 = Math.hypot(this.cellCenterX[e2] - this.cellCenterX[o2], this.cellCenterY[e2] - this.cellCenterY[o2]);
return t3 === n2 ? i2 : i2 + this.hyperParameters.viaBaseCost;
}
internConn(t3, e2) {
const n2 = this.connNameToId.get(t3);
if (n2 !== undefined)
return n2;
const o2 = this.connIdToName.length;
var i2;
return this.connIdToName.push(t3), this.connIdToRootNet.push((i2 = t3, e2 ?? i2.replace(/_mst\d+$/, ""))), this.connNameToId.set(t3, o2), o2;
}
buildConnectionSegs() {
const t3 = new Map;
for (const e3 of this.nodeWithPortPoints.portPoints) {
const n3 = e3.connectionName;
t3.has(n3) || t3.set(n3, { points: [], rootConnectionName: e3.rootConnectionName }), t3.get(n3).points.push(e3);
}
const e2 = [], n2 = new Set;
for (const [o2, i2] of t3) {
const t4 = i2.points, r2 = _i(t4);
if (r2.length === 0)
continue;
const s2 = this.internConn(o2, i2.rootConnectionName);
for (const [t5, a2] of r2) {
const r3 = this.pointToCell(t5), c2 = this.pointToCell(a2), l2 = `${r3.z}:${r3.cellId}`, h2 = `${c2.z}:${c2.cellId}`, d2 = l2 < h2 ? `${l2}|${h2}` : `${h2}|${l2}`, u2 = i2.rootConnectionName ?? o2, p2 = `${u2}|${d2}`;
n2.has(p2) ? this.overlapFriendlyRootNets.add(u2) : (n2.add(p2), e2.push({ connId: s2, startZ: r3.z, startCellId: r3.cellId, startPoint: t5, endZ: c2.z, endCellId: c2.cellId, endPoint: a2 }));
}
}
return e2;
}
pointToCell(t3) {
const e2 = Ri(Math.floor((t3.x - this.boundsMinX) / this.highResolutionCellSize), 0, this.fineCols - 1), n2 = Ri(Math.floor((t3.y - this.boundsMinY) / this.highResolutionCellSize), 0, this.fineRows - 1);
let o2 = 4;
e2 < this.bandCols ? o2 = 0 : e2 >= this.fineCols - this.bandCols ? o2 = 2 : n2 < this.bandRows ? o2 = 1 : n2 >= this.fineRows - this.bandRows && (o2 = 3);
const i2 = this.regions[o2], r2 = n2 - i2.fineOriginRow, s2 = e2 - i2.fineOriginCol, a2 = Ri(Math.floor(r2 / i2.cellScale), 0, Math.max(0, i2.rows - 1)), c2 = Ri(Math.floor(s2 / i2.cellScale), 0, Math.max(0, i2.cols - 1));
return { z: this.zToLayer.get(t3.z) ?? 0, cellId: this.cellIdFor(o2, a2, c2) };
}
shuffleConnections() {
const t3 = this.unsolvedSegs;
let e2 = this.hyperParameters.shuffleSeed >>> 0;
const n2 = () => (e2 = Math.imul(e2, 1664525) + 1013904223 >>> 0, e2 / 4294967295);
for (let e3 = t3.length - 1;e3 > 0; e3--) {
const o2 = Math.floor(n2() * (e3 + 1)), i2 = t3[e3];
t3[e3] = t3[o2], t3[o2] = i2;
}
}
finalizeRoute(t3) {
this.consecutiveSkips = Math.max(0, this.consecutiveSkips - 1);
const e2 = [];
let n2 = t3;
for (;n2 >= 0; ) {
const t4 = this.nodePool.z[n2], o3 = this.nodePool.cellId[n2];
e2.push(t4 * this.planeSize + o3), n2 = this.nodePool.parent[n2];
}
for (e2.reverse();e2.length > 1 && this.sharedCrossRootPortFlat[e2[0]]; )
e2.shift();
for (;e2.length > 1 && this.sharedCrossRootPortFlat[e2[e2.length - 1]]; )
e2.pop();
const o2 = this.extractViaCellIds(e2), i2 = this.activeConnId;
this.ripChain.collect(this.nodePool.ripHead[t3], this._rippedIds);
for (let t4 = 0;t4 < this._rippedIds.length; t4++)
if (this.ripTrace(this._rippedIds[t4]), this.failed)
return;
const r2 = [];
for (let t4 = 0;t4 < e2.length; t4++) {
const n3 = e2[t4], o3 = Math.floor(n3 / this.planeSize), s3 = n3 - o3 * this.planeSize;
this.markTraceFootprint(i2, o3, s3, r2);
}
const s2 = [];
for (let t4 = 0;t4 < o2.length; t4++)
this.markViaFootprint(i2, o2[t4], r2, s2);
for (;this.usedIndicesByConn.length <= i2; )
this.usedIndicesByConn.push(undefined);
const a2 = this.usedIndicesByConn[i2] ?? [];
for (a2.push(...r2), this.usedIndicesByConn[i2] = a2;this.solvedRoutes.length <= i2; )
this.solvedRoutes.push(undefined);
const c2 = this.solvedRoutes[i2] ?? [];
c2.push({ connId: i2, states: Int32Array.from(e2), viaCellIds: Int32Array.from(o2), startPoint: this.activeConnSeg.startPoint, endPoint: this.activeConnSeg.endPoint }), this.solvedRoutes[i2] = c2;
for (let t4 = 0;t4 < s2.length; t4++)
if (this.ripTrace(s2[t4]), this.failed)
return;
if (this._rippedIds.length > 0 || s2.length > 0) {
const t4 = this.penalty2d, e3 = this.penaltyCap;
if (this.totalRipEvents > 50)
for (let e4 = 0;e4 < t4.length; e4++)
t4[e4] = 0.99 * t4[e4];
else
for (let n3 = 0;n3 < t4.length; n3++)
t4[n3] > e3 && (t4[n3] = 0.5 * t4[n3]);
}
}
extractViaCellIds(t3) {
const e2 = [];
for (let n2 = 1;n2 < t3.length; n2++) {
const o2 = t3[n2 - 1], i2 = t3[n2], r2 = Math.floor(o2 / this.planeSize), s2 = Math.floor(i2 / this.planeSize);
r2 !== s2 && e2.push(i2 - s2 * this.planeSize);
}
return e2;
}
markTraceFootprint(t3, e2, n2, o2) {
const i2 = this.cellCenterX[n2], r2 = this.cellCenterY[n2];
this.forEachCellNearCircle(i2, r2, this.traceKeepoutRadius, (s2) => {
if (!Oi(i2, r2, this.traceKeepoutRadius, this.cellMinX[s2], this.cellMinY[s2], this.cellMaxX[s2], this.cellMaxY[s2]))
return;
const a2 = e2 * this.planeSize + s2;
if (s2 !== n2 && this.shouldSkipFixedPortHalo(a2, t3))
return;
const c2 = this.usedCellsFlat[a2], l2 = this.allowSharedUse(t3, c2);
(c2 === -1 || c2 === t3 || l2) && (c2 !== -1 && c2 !== t3 ? this.addSharedOccupant(a2, t3) : this.usedCellsFlat[a2] = t3, o2.push(a2));
});
}
markViaFootprint(t3, e2, n2, o2) {
const i2 = this.cellCenterX[e2], r2 = this.cellCenterY[e2];
this.forEachCellNearCircle(i2, r2, this.viaKeepoutRadius, (s2) => {
if (Oi(i2, r2, this.viaKeepoutRadius, this.cellMinX[s2], this.cellMinY[s2], this.cellMaxX[s2], this.cellMaxY[s2]))
for (let i3 = 0;i3 < this.layers; i3++) {
const r3 = i3 * this.planeSize + s2;
if (s2 !== e2 && this.shouldSkipFixedPortHalo(r3, t3))
continue;
if (this.fillTraceOccupants(r3, t3, this._cellOccs), this._cellOccs.length > 0) {
for (let t4 = 0;t4 < this._cellOccs.length; t4++)
Ei(o2, this._cellOccs[t4]);
this.replaceOccupants(r3, t3), n2.push(r3);
continue;
}
const a2 = this.usedCellsFlat[r3];
a2 !== -1 && a2 !== t3 ? this.addSharedOccupant(r3, t3) : this.usedCellsFlat[r3] = t3, n2.push(r3);
}
});
}
forEachCellNearCircle(t3, e2, n2, o2) {
const i2 = Ri(Math.floor((t3 - n2 - this.boundsMinX) / this.highResolutionCellSize), 0, this.fineCols - 1), r2 = Ri(Math.floor((t3 + n2 - this.boundsMinX) / this.highResolutionCellSize), 0, this.fineCols - 1), s2 = Ri(Math.floor((e2 - n2 - this.boundsMinY) / this.highResolutionCellSize), 0, this.fineRows - 1), a2 = Ri(Math.floor((e2 + n2 - this.boundsMinY) / this.highResolutionCellSize), 0, this.fineRows - 1);
for (let t4 = 0;t4 < this.regions.length; t4++) {
const e3 = this.regions[t4];
if (e3.rows === 0 || e3.cols === 0)
continue;
const n3 = Math.max(s2, e3.fineOriginRow), c2 = Math.min(a2, e3.fineOriginRow + e3.fineRows - 1), l2 = Math.max(i2, e3.fineOriginCol), h2 = Math.min(r2, e3.fineOriginCol + e3.fineCols - 1);
if (n3 > c2)
continue;
if (l2 > h2)
continue;
const d2 = Math.floor((n3 - e3.fineOriginRow) / e3.cellScale), u2 = Math.floor((c2 - e3.fineOriginRow) / e3.cellScale), p2 = Math.floor((l2 - e3.fineOriginCol) / e3.cellScale), m2 = Math.floor((h2 - e3.fineOriginCol) / e3.cellScale);
for (let t5 = d2;t5 <= u2; t5++)
for (let n4 = p2;n4 <= m2; n4++)
o2(this.cellIdFor(e3.id, t5, n4));
}
}
ripTrace(t3) {
for (;this.ripCount.length <= t3; )
this.ripCount.push(0);
if (this.ripCount[t3]++, this.totalRipEvents++, this.totalRipEvents >= this.MAX_RIPS)
return this.error = `Convergence failure: exceeded MAX_RIPS ${this.MAX_RIPS}`, void (this.failed = true);
const e2 = this.getSolvedRoutesForConn(t3);
if (e2.length > 0)
for (const t4 of e2) {
for (let e3 = 0;e3 < t4.states.length; e3++) {
const n3 = t4.states[e3] % this.planeSize;
this.penalty2d[n3] = this.penalty2d[n3] + this.hyperParameters.ripTracePenalty;
}
for (let e3 = 0;e3 < t4.viaCellIds.length; e3++) {
const n3 = t4.viaCellIds[e3];
this.penalty2d[n3] = this.penalty2d[n3] + this.hyperParameters.ripViaPenalty;
}
}
const n2 = this.usedIndicesByConn[t3];
if (n2) {
for (let e3 = 0;e3 < n2.length; e3++)
this.removeOccupant(n2[e3], t3);
this.usedIndicesByConn[t3] = undefined;
}
if (e2.length > 0) {
this.solvedRoutes[t3] = undefined;
for (const n3 of e2) {
const e3 = n3.states[0], o2 = n3.states[n3.states.length - 1], i2 = Math.floor(e3 / this.planeSize), r2 = Math.floor(o2 / this.planeSize);
this.unsolvedSegs.push({ connId: t3, startZ: i2, startCellId: e3 - i2 * this.planeSize, startPoint: n3.startPoint, endZ: r2, endCellId: o2 - r2 * this.planeSize, endPoint: n3.endPoint });
}
}
}
flattenNeighborLists(t3) {
const e2 = new Int32Array(t3.length + 1);
let n2 = 0;
for (let o3 = 0;o3 < t3.length; o3++)
e2[o3] = n2, n2 += t3[o3].length;
e2[t3.length] = n2;
const o2 = new Int32Array(n2), i2 = new Float32Array(n2);
let r2 = 0;
for (let e3 = 0;e3 < t3.length; e3++) {
const n3 = t3[e3];
for (let t4 = 0;t4 < n3.length; t4++) {
const e4 = n3[t4];
o2[r2] = e4.cellId, i2[r2] = e4.cost, r2++;
}
}
return { offset: e2, ids: o2, costs: i2 };
}
visualize() {
const t3 = ["red", "blue", "orange", "green"], e2 = this.gridToBoundsTransform, n2 = [], o2 = [], i2 = [], r2 = [];
if (r2.push({ center: { x: this.nodeWithPortPoints.center.x, y: this.nodeWithPortPoints.center.y }, width: this.nodeWithPortPoints.width, height: this.nodeWithPortPoints.height, stroke: "gray" }), this.showPenaltyMap && this.penalty2d) {
let t4 = 0;
for (let e3 = 0;e3 < this.penalty2d.length; e3++)
this.penalty2d[e3] > t4 && (t4 = this.penalty2d[e3]);
if (t4 > 0)
for (let n3 = 0;n3 < this.planeSize; n3++) {
const o3 = this.penalty2d[n3];
if (o3 <= 0)
continue;
const i3 = gi(e2, { x: this.cellCenterX[n3], y: this.cellCenterY[n3] }), s3 = Math.min(0.6, o3 / t4 * 0.6);
r2.push({ center: i3, width: this.cellWidth[n3] * e2.a, height: this.cellHeight[n3] * e2.e, fill: `rgba(255,165,0,${s3.toFixed(3)})` });
}
}
if (this.showUsedCellMap && this.usedCellsFlat)
for (let t4 = 0;t4 < this.layers; t4++) {
const n3 = t4 * this.planeSize;
for (let t5 = 0;t5 < this.planeSize; t5++) {
if (this.usedCellsFlat[n3 + t5] === -1)
continue;
const o3 = gi(e2, { x: this.cellCenterX[t5], y: this.cellCenterY[t5] });
r2.push({ center: o3, width: this.cellWidth[t5] * e2.a, height: this.cellHeight[t5] * e2.e, fill: "rgba(0,0,255,0.5)" });
}
}
for (const e3 of this.nodeWithPortPoints.portPoints)
n2.push({ x: e3.x, y: e3.y, color: t3[e3.z] ?? "gray", label: e3.connectionName });
const s2 = ["rgba(255,0,0,0.75)", "rgba(0,0,255,0.75)", "rgba(255,165,0,0.75)", "rgba(0,128,0,0.75)"], a2 = this.getOutput();
for (const t4 of a2) {
if (t4.route.length < 2)
continue;
let e3 = 0;
for (let n3 = 1;n3 < t4.route.length; n3++) {
const i3 = t4.route[n3 - 1];
t4.route[n3].z !== i3.z && (n3 - e3 >= 2 && o2.push({ points: t4.route.slice(e3, n3).map((t5) => ({ x: t5.x, y: t5.y })), strokeColor: s2[i3.z] ?? "rgba(128,128,128,0.75)", strokeWidth: this.traceThickness }), e3 = n3);
}
if (t4.route.length - e3 >= 2) {
const n3 = t4.route[e3].z;
o2.push({ points: t4.route.slice(e3).map((t5) => ({ x: t5.x, y: t5.y })), strokeColor: s2[n3] ?? "rgba(128,128,128,0.75)", strokeWidth: this.traceThickness });
}
}
for (const t4 of a2)
for (const e3 of t4.vias)
i2.push({ center: { x: e3.x, y: e3.y }, radius: this.viaDiameter / 2, fill: "rgba(0,0,0,0.3)", stroke: "black" });
if (this.activeConnSeg && this.visitedFlatStamp) {
const t4 = this.stamp;
for (let o3 = 0;o3 < this.layers; o3++) {
const i3 = o3 * this.planeSize;
for (let o4 = 0;o4 < this.planeSize; o4++) {
if (this.visitedFlatStamp[i3 + o4] !== t4)
continue;
const r3 = gi(e2, { x: this.cellCenterX[o4], y: this.cellCenterY[o4] });
n2.push({ x: r3.x, y: r3.y, color: "rgba(0,0,255,0.2)" });
}
}
}
return { points: n2, lines: o2, circles: i2, rects: r2, coordinateSystem: "cartesian", title: `${this.getSolverName()} [${this.getSolvedRouteCount()} solved, ${this.unsolvedSegs?.length ?? 0} remaining]` };
}
getOutput() {
const t3 = this.gridToBoundsTransform, e2 = [];
for (let n2 = 0;n2 < this.solvedRoutes.length; n2++) {
const o2 = this.getSolvedRoutesForConn(n2);
if (o2.length === 0)
continue;
const i2 = this.connIdToName[n2];
for (const r2 of o2) {
const o3 = Array.from(r2.states, (e3) => {
const n3 = Math.floor(e3 / this.planeSize), o4 = e3 - n3 * this.planeSize, i3 = gi(t3, { x: this.cellCenterX[o4], y: this.cellCenterY[o4] });
return { x: i3.x, y: i3.y, z: this.layerToZ.get(n3) ?? n3 };
});
o3.length === 1 ? (o3[0] = { ...r2.startPoint }, o3.push({ ...r2.endPoint })) : o3.length > 1 && (o3[0] = { ...r2.startPoint }, o3[o3.length - 1] = { ...r2.endPoint }), e2.push({ connectionName: i2, rootConnectionName: this.connIdToRootNet[n2], regionId: this.nodeWithPortPoints.capacityMeshNodeId, traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, route: o3, vias: Array.from(r2.viaCellIds, (e3) => gi(t3, { x: this.cellCenterX[e3], y: this.cellCenterY[e3] })) });
}
}
return e2;
}
getSolvedRoutesForConn(t3) {
const e2 = this.solvedRoutes[t3];
return e2 ? Array.isArray(e2) ? e2 : [e2] : [];
}
getSolvedRouteCount() {
let t3 = 0;
for (let e2 = 0;e2 < this.solvedRoutes.length; e2++)
t3 += this.getSolvedRoutesForConn(e2).length;
return t3;
}
computeGridToBoundsTransform() {
let t3 = 1 / 0, e2 = -1 / 0, n2 = 1 / 0, o2 = -1 / 0;
for (let i3 = 0;i3 < this.planeSize; i3++) {
const r3 = this.cellCenterX[i3], s3 = this.cellCenterY[i3];
r3 < t3 && (t3 = r3), r3 > e2 && (e2 = r3), s3 < n2 && (n2 = s3), s3 > o2 && (o2 = s3);
}
const i2 = e2 - t3, r2 = o2 - n2, s2 = this.boundsMaxX - this.boundsMinX, a2 = this.boundsMaxY - this.boundsMinY, c2 = i2 > 0 ? s2 / i2 : 1, l2 = r2 > 0 ? a2 / r2 : 1;
return { a: c2, b: 0, c: i2 > 0 ? this.boundsMinX - c2 * t3 : (this.boundsMinX + this.boundsMaxX) / 2 - t3, d: 0, e: l2, f: r2 > 0 ? this.boundsMinY - l2 * n2 : (this.boundsMinY + this.boundsMaxY) / 2 - n2 };
}
};
var Li = class {
begin;
run;
copyParents;
constructor(t3, e2, n2, o2, i2) {
const r2 = t3 * e2, s2 = r2 * n2, a2 = new Float64Array(s2), c2 = new Int32Array(s2), l2 = new Uint32Array(s2), h2 = new Int32Array(s2), d2 = new Uint8Array(s2);
let u2, p2, m2, g2, f2, y2, _2, b2, x2 = 0, v2 = 0, I2 = 0, S2 = 1024, C2 = new Float64Array(S2), P2 = new Int32Array(S2), M2 = new Uint32Array(S2);
for (let n3 = 0;n3 < s2; n3++) {
const o3 = n3 % r2, i3 = o3 % t3, s3 = Math.floor(o3 / t3), a3 = Math.floor(n3 / r2);
h2[n3] = o3, d2[n3] = Number(i3 > 0) | Number(i3 + 1 < t3) << 1 | Number(s3 > 0) << 2 | Number(s3 + 1 < e2) << 3 | a3 % 2 << 4;
}
function N2(t4, e3) {
let n3 = I2++;
for (;n3 > 0; ) {
const t5 = n3 - 1 >> 1;
if (C2[t5] <= e3)
break;
C2[n3] = C2[t5], P2[n3] = P2[t5], M2[n3] = M2[t5], n3 = t5;
}
C2[n3] = e3, P2[n3] = t4, l2[t4] = l2[t4] + 1 >>> 0, M2[n3] = l2[t4];
}
let w2 = 0, T2 = 0;
function R2() {
w2 = P2[0], T2 = M2[0];
const t4 = --I2;
if (!t4)
return;
const e3 = P2[t4], n3 = M2[t4], o3 = C2[t4];
let i3 = 0;
for (;2 * i3 + 1 < I2; ) {
let t5 = 2 * i3 + 1;
if (t5 + 1 < I2 && C2[t5 + 1] < C2[t5] && t5++, o3 <= C2[t5])
break;
C2[i3] = C2[t5], P2[i3] = P2[t5], M2[i3] = M2[t5], i3 = t5;
}
C2[i3] = o3, P2[i3] = e3, M2[i3] = n3;
}
function E2(t4, e3, n3, o3, i3, r3) {
const s3 = r3 + e3;
if (s3 >= a2[t4])
return;
if (m2[t4] && t4 !== x2)
return;
if (n3 && g2[o3])
return;
const l3 = n3 ? p2[o3] : u2[t4], h3 = n3 ? y2[o3] : f2[t4], d3 = s3 + v2 * l3 + h3;
d3 >= a2[t4] || (a2[t4] = d3, c2[t4] = i3, N2(t4, d3 + _2[t4]));
}
this.begin = (t4, e3, n3, o3) => {
(({ traceCost: u2, viaCost: p2, fixed: m2, fixedVia: g2, history: f2, viaHistory: y2, viaAllowed: b2 } = t4)), _2 = t4.heuristicCost, x2 = n3, v2 = o3, I2 = 0, a2.fill(1 / 0), c2.fill(-1), l2.fill(0), a2[e3] = 0, N2(e3, _2[e3]);
}, this.run = (e3, s3) => {
let c3 = 0, u3 = 0;
for (;u3 < e3; ) {
if (c3 >= s3)
return { status: 3, expansions: c3 };
if (!I2)
return { status: 2, expansions: c3 };
if (I2 + 4 + n2 > S2) {
S2 *= 2;
const t4 = new Float64Array(S2), e5 = new Int32Array(S2), n3 = new Uint32Array(S2);
t4.set(C2), e5.set(P2), n3.set(M2), C2 = t4, P2 = e5, M2 = n3;
continue;
}
R2(), u3++;
const e4 = w2;
if (T2 !== l2[e4])
continue;
const p3 = a2[e4];
if (c3++, e4 === x2)
return { status: 1, expansions: c3 };
const m3 = h2[e4], g3 = d2[e4], f3 = o2 * (16 & g3 ? 1.05 : 1), y3 = i2 * (16 & g3 ? 1 : 1.05);
if (1 & g3 && E2(e4 - 1, f3, false, 0, e4, p3), 2 & g3 && E2(e4 + 1, f3, false, 0, e4, p3), 4 & g3 && E2(e4 - t3, y3, false, 0, e4, p3), 8 & g3 && E2(e4 + t3, y3, false, 0, e4, p3), b2[m3])
for (let t4 = 0;t4 < n2; t4++) {
const n3 = t4 * r2 + m3;
n3 !== e4 && E2(n3, 0.8, true, m3, e4, p3);
}
}
return { status: 0, expansions: c3 };
}, this.copyParents = (t4) => t4.set(c2);
}
};
var zi = class {
exports;
offsets = [];
states;
heapCapacity = 1024;
constructor(t3, e2, n2, o2, i2) {
ki ??= new WebAssembly.Module(Uint8Array.from(atob("AGFzbQEAAAABHwVgB39/f3x8f38AYAF/AGAAAX9gA39/fABgAn9/AX8DBwYAAQICAwQFAwEAAgYPAn8BQYCABAt/AEGAgQQLB2kIBm1lbW9yeQIACWNvbmZpZ3VyZQAAEXNldF9oZWFwX2NhcGFjaXR5AAEOZ2V0X2V4cGFuc2lvbnMAAghnZXRfcG9wcwADDGJlZ2luX3NlYXJjaAAEA3J1bgAFC19faGVhcF9iYXNlAwEK0h8G8wcEBX8FewR/BHtBACEHQQAgAjYChICEgABBACAANgKAgISAAEEAIAY2AqCAhIAAQQAgASAAbCIINgKIgISAAEEAIAggAmwiCTYCjICEgABBACADOQOQgISAAEEAIAQ5A5iAhIAAQQAgBSgCBDYCqICEgABBACAFKAIINgKsgISAAEEAIAUoAgw2ArCAhIAAQQAgBSgCEDYCtICEgABBACAFKAIUNgK4gISAAEEAIAUoAgA2AqSAhIAAQQAgBSgCGDYCvICEgABBACAFKAIcNgLAgISAAEEAIAUoAiA2AsSAhIAAQQAgBSgCJDYCyICEgABBACAFKAIoIgo2AsyAhIAAQQAgBSgCLCILNgLQgISAAEEAIAUoAjA2AtSAhIAAQQAgBSgCNDYC2ICEgAACQCAJQQFIDQACQCAJQQhJDQAgCyACIAFsIABsQQJ0IgVqIgIgCksgCiAFaiIFIAtLcQ0AIApBhICEgABJIAVBgICEgABLcQ0AIAtBhICEgABJIAJBgICEgABLcQ0AIAH9ESEMIAD9ESENIAj9ESEOQQD9CQKAgISAACEP/QwAAAAAAQAAAAIAAAADAAAAIRAgCiEFIAshAiAJQfz///8HcSIHIQYDQCAFIBAgEP0bACAO/RsAbSIR/REgEP0bASAO/RsBbSIS/RwBIBD9GwIgDv0bAm0iE/0cAiAQ/RsDIA79GwNtIhT9HAMgDv21Af2xASIV/QsCACACIBX9GwAgDf0bAG39ESAV/RsBIA39GwFt/RwBIBX9GwIgDf0bAm39HAIgFf0bAyAN/RsDbf0cAyIW/QwAAAAAAAAAAAAAAAAAAAAAIhf9O/0MBAAAAAQAAAAEAAAABAAAACIY/U4gFSAWIA39tQH9sQEiFSAX/Tj9sQEgEUECb/0RIBJBAm/9HAEgE0ECb/0cAiAUQQJv/RwDQQT9qwH9UCAV/QwBAAAAAQAAAAEAAAABAAAAIhf9rgEgD/05/QwCAAAAAgAAAAIAAAACAAAA/U79UCAWIBf9rgEgDP05/QwIAAAACAAAAAgAAAAIAAAA/U79UP0LAgAgBUEQaiEFIAJBEGohAiAQIBj9rgEhECAGQXxqIgYNAAsgCSAHRg0BC0EAIAFrIRMgCiAHQQJ0IgJqIQUgCyACaiECQQAgCGshFANAIAUgByAUIAcgCG0iBmxqIhE2AgAgAkEEQQAgESAAbSIRQQBKGyAHIAAgEyAGbCARa2wiEmpBAEdyIAZBAm9BBHRyQQJBACAHQQFqIgYgEmpBACgCgICEgABIG3JBCEEAIBFBAWogAUgbcjYCACAFQQRqIQUgAkEEaiECIAYhByAJIAZHDQALCwsNAEEAIAA2AqCAhIAACwsAQQAoAtyAhIAACwsAQQAoAuCAhIAAC4gFAQl/QQAgAjkD6ICEgABBACABNgLkgISAAEEAKALUgISAACEDQQAoAsSAhIAAIQQCQEEAKAKMgISAACIFQQFIDQBBACgCyICEgAAhBkEAIQcCQCAFQQRJDQBBACEHIAMgBmtBCEkNACAEIQEgBiEIIAMhCSAFQf7///8HcSIHIQoDQCAIQn83AgAgAf0MAAAAAAAA8H8AAAAAAADwf/0LAwAgCUIANwIAIAFBEGohASAIQQhqIQggCUEIaiEJIApBfmoiCg0ACyAFIAdGDQELIAchCwJAIAUgB2tBA3EiCkUNACAHIApqIQsgBCAHQQN0aiEBIAYgB0ECdCIJaiEIIAMgCWohCQNAIAhBfzYCACABQoCAgICAgID4/wA3AwAgCUEANgIAIAFBCGohASAIQQRqIQggCUEEaiEJIApBf2oiCg0ACwsgByAFa0F8Sw0AIAtBAnQhByAFIAtrIQUgBCALQQN0aiEBIAMhCgNAIAYgB2oiCEF/NgIAIAogB2oiCUEANgIAIAhBBGpBfzYCACAJQQRqQQA2AgAgCEEIakF/NgIAIAlBCGpBADYCACAIQQxqQX82AgAgAUKAgICAgICA+P8ANwMAIAFBCGpCgICAgICAgPj/ADcDACABQRBqQoCAgICAgID4/wA3AwAgAUEYakKAgICAgICA+P8ANwMAIAlBDGpBADYCACABQSBqIQEgBkEQaiEGIApBEGohCiAFQXxqIgUNAAsLQQBBATYC8ICEgAAgBCAAQQN0IghqQgA3AwAgAyAAQQJ0aiIBIAEoAgBBAWoiCTYCAEEAKALYgISAACIBQQAoAryAhIAAIAhqKwMAOQMAIAEgCTYCDCABIAA2AggLqhIMC38BfAN/AnwNfwF+AXwDfwJ8AX8BfAN/QQAhAkEAQQA2AuCAhIAAQQBBADYC3ICEgAACQCAAQQFIDQBBACgChICEgAAiA0EEaiEEQQAoAriAhIAAIQVBACgCqICEgAAhBkEAKAKwgISAACEHQQAoAoiAhIAAIQhBACgCwICEgAAhCUEAKAKAgISAACEKQQAoAryAhIAAIQtBACgCyICEgAAhDEEAKwPogISAACENQQAoArSAhIAAIQ5BACgCpICEgAAhD0EAKAKsgISAACEQQQArA5iAhIAAIRFBACsDkICEgAAhEkEAKALQgISAACETQQAoAsyAhIAAIRRBACgC5ICEgAAhFUEAKALEgISAACEWQQAoAtSAhIAAIRdBACgC2ICEgAAhGEEAKAKggISAACEZQQAoAvCAhIAAIRpBACEbQQAhHANAAkAgHCABSA0AQQMPCwJAIBoNAEECDwsCQCAaIARqIBlMDQBBBA8LQQAgGkF/aiIdNgLwgISAACAYKAIMIR4gGCgCCCEfAkAgHUUNACAYIB1BBHRqIgIpAwghICACKwMAISFBACECAkAgGkEDSA0AQQAhIkEBISNBACEkA0ACQAJAICRBAmoiJCAdSA0AICMhAgwBCyAjIQIgGCAkQQR0aisDACAYICNBBHRqKwMAY0UNACAkIQILAkAgISAYIAJBBHRqIiMrAwBlRQ0AICIhAgwCCyAYICJBBHRqICP9AAMA/QsDACACISIgAkEBdCIkQQFyIiMgHUgNAAsLIBggAkEEdGoiAiAgNwMIIAIgITkDAAtBACAbQQFqIhs2AuCAhIAAAkACQCAeIBcgH0ECdCIjaigCAEYNACAdIRoMAQtBASECQQAgHEEBaiIcNgLcgISAACAfIBVGDQIgFiAfQQN0aisDACEhIBJEzczMzMzM8D9EAAAAAAAA8D8gEyAjaigCACICQRBxIiIboiElIBQgI2ooAgAhIwJAAkAgAkEBcQ0AIB0hGgwBCwJAICEgJaAiJiAWIB9Bf2oiHkEDdCIkaiInKwMAIihmRQ0AIB0hGgwBCwJAIB4gFUYNACAQIB5qLQAAQf8BcUUNACAdIRoMAQsCQCAOICRqKwMAICYgDSAPIB5BAXRqLwEAuKKgoCImIChmRQ0AIB0hGgwBCyAMIB5BAnQiKWogHzYCACAnICY5AwBBACAaNgLwgISAACAmIAsgJGorAwCgISYCQCAaQQJIDQADQCAYIB1Bf2pBAXYiJEEEdGoiJysDACAmZQ0BIBggHUEEdGogJ/0AAwD9CwMAICQhHSAkDQALQQAhHQsgFyApaiIkICQoAgBBAWoiJDYCACAYIB1BBHRqIh0gJjkDACAdICQ2AgwgHSAeNgIIC0QAAAAAAADwP0TNzMzMzMzwPyAiGyEmAkACQCACQQJxDQAgGiEdDAELAkAgISAloCIlIBYgH0EBaiIeQQN0IiJqIh0rAwAiKGZFDQAgGiEdDAELAkAgHiAVRg0AIBAgHmotAABB/wFxRQ0AIBohHQwBCwJAIA4gImorAwAgJSANIA8gHkEBdGovAQC4oqCgIiUgKGZFDQAgGiEdDAELIAwgHkECdCInaiAfNgIAIB0gJTkDAEEAIBpBAWoiHTYC8ICEgAAgJSALICJqKwMAoCElAkAgGkEBSA0AA0AgGCAaQX9qQQF2IiJBBHRqIiQrAwAgJWUNASAYIBpBBHRqICT9AAMA/QsDACAiIRogIg0AC0EAIRoLIBcgJ2oiIiAiKAIAQQFqIiI2AgAgGCAaQQR0aiIaICU5AwAgGiAiNgIMIBogHjYCCAsgESAmoiElAkACQCACQQRxDQAgHSEiDAELAkAgISAloCImIBYgHyAKayIeQQN0IhpqIiIrAwAiKGZFDQAgHSEiDAELAkAgHiAVRg0AIBAgHmotAABB/wFxRQ0AIB0hIgwBCwJAIA4gGmorAwAgJiANIA8gHkEBdGovAQC4oqCgIiYgKGZFDQAgHSEiDAELIAwgHkECdCInaiAfNgIAICIgJjkDAEEAIB1BAWoiIjYC8ICEgAAgJiALIBpqKwMAoCEmAkAgHUEBSA0AA0AgGCAdQX9qQQF2IhpBBHRqIiQrAwAgJmUNASAYIB1BBHRqICT9AAMA/QsDACAaIR0gGg0AC0EAIR0LIBcgJ2oiGiAaKAIAQQFqIho2AgAgGCAdQQR0aiIdICY5AwAgHSAaNgIMIB0gHjYCCAsCQAJAIAJBCHENACAiIRoMAQsCQCAhICWgIiUgFiAKIB9qIiRBA3QiAmoiHSsDACImZkUNACAiIRoMAQsCQCAkIBVGDQAgECAkai0AAEH/AXFFDQAgIiEaDAELAkAgDiACaisDACAlIA0gDyAkQQF0ai8BALiioKAiJSAmZkUNACAiIRoMAQsgDCAkQQJ0Ih5qIB82AgAgHSAlOQMAQQAgIkEBaiIaNgLwgISAACAlIAsgAmorAwCgISUCQCAiQQFIDQADQCAYICJBf2pBAXYiAkEEdGoiHSsDACAlZQ0BIBggIkEEdGogHf0AAwD9CwMAIAIhIiACDQALQQAhIgsgFyAeaiICIAIoAgBBAWoiHTYCACAYICJBBHRqIgIgJTkDACACIB02AgwgAiAkNgIICyAJICNqLQAARQ0AIANBAUgNACAHICNqIR4gIUSamZmZmZnpP6AhISAFICNBA3RqIScgBiAjQQF0aiEpQQAhAgNAAkAgCCACbCAjaiIdIB9GDQAgISAWIB1BA3QiImoiJCsDACIlZg0AAkAgHSAVRg0AIBAgHWotAABB/wFxDQELIB4tAAANACAnKwMAICEgDSApLwEAuKKgoCImICVmDQAgDCAdQQJ0IipqIB82AgAgJCAmOQMAQQAgGkEBaiIrNgLwgISAACAmIAsgImorAwCgISUCQCAaQQFIDQADQCAYIBpBf2pBAXYiIkEEdGoiJCsDACAlZQ0BIBggGkEEdGogJP0AAwD9CwMAICIhGiAiDQALQQAhGgsgFyAqaiIiICIoAgBBAWoiIjYCACAYIBpBBHRqIhogJTkDACAaICI2AgwgGiAdNgIIICshGgsgAkEBaiICIANHDQALCyAbIABHDQALQQAhAgsgAgsAdQRuYW1lAAwLa2VybmVsLndhc20BTAYACWNvbmZpZ3VyZQERc2V0X2hlYXBfY2FwYWNpdHkCDmdldF9leHBhbnNpb25zAwhnZXRfcG9wcwQMYmVnaW5fc2VhcmNoBQNydW4HEgEAD19fc3RhY2tfcG9pbnRlcgAvCXByb2R1Y2VycwEMcHJvY2Vzc2VkLWJ5AQ5Ib21lYnJldyBjbGFuZwYyMi4xLjgAnQEPdGFyZ2V0X2ZlYXR1cmVzCSsLYnVsay1tZW1vcnkrD2J1bGstbWVtb3J5LW9wdCsWY2FsbC1pbmRpcmVjdC1vdmVybG9uZysKbXVsdGl2YWx1ZSsPbXV0YWJsZS1nbG9iYWxzKxNub250cmFwcGluZy1mcHRvaW50Kw9yZWZlcmVuY2UtdHlwZXMrCHNpZ24tZXh0KwdzaW1kMTI4"), (t4) => t4.charCodeAt(0))), this.exports = new WebAssembly.Instance(ki).exports;
const r2 = t3 * e2;
this.states = r2 * n2;
let s2 = Number(this.exports.__heap_base.value);
const a2 = s2;
s2 += 56;
for (const t4 of [2 * this.states, 2 * r2, this.states, r2, 8 * this.states, 8 * r2, 8 * this.states, r2, 8 * this.states, 4 * this.states, 4 * this.states, 4 * this.states, 4 * this.states, 16 * this.heapCapacity])
s2 = 8 * Math.ceil(s2 / 8), this.offsets.push(s2), s2 += t4;
this.ensureMemory(s2), new Int32Array(this.exports.memory.buffer, a2, 14).set(this.offsets), this.exports.configure(t3, e2, n2, o2, i2, a2, this.heapCapacity);
}
ensureMemory(t3) {
const e2 = this.exports.memory;
t3 > e2.buffer.byteLength && e2.grow(Math.ceil((t3 - e2.buffer.byteLength) / 65536));
}
begin(t3, e2, n2, o2) {
const i2 = new Uint8Array(this.exports.memory.buffer), r2 = [t3.traceCost, t3.viaCost, t3.fixed, t3.fixedVia, t3.history, t3.viaHistory, t3.heuristicCost, t3.viaAllowed];
for (let t4 = 0;t4 < r2.length; t4++) {
const e3 = r2[t4];
i2.set(new Uint8Array(e3.buffer, e3.byteOffset, e3.byteLength), this.offsets[t4]);
}
this.exports.begin_search(e2, n2, o2);
}
run(t3, e2) {
let n2 = 0, o2 = 0, i2 = Math.ceil(t3);
for (;i2 > 0; )
if (o2 = this.exports.run(Math.min(i2, 1e6), Math.min(Math.ceil(e2 - n2), 2147483647)), i2 -= this.exports.get_pops(), n2 += this.exports.get_expansions(), o2 === 4)
this.heapCapacity *= 2, this.ensureMemory(this.offsets[13] + 16 * this.heapCapacity), this.exports.set_heap_capacity(this.heapCapacity);
else if (o2 !== 0)
break;
return { status: o2, expansions: n2 };
}
copyParents(t3) {
t3.set(new Int32Array(this.exports.memory.buffer, this.offsets[9], this.states));
}
};
var Bi = (t3, e2, n2) => {
const [o2, i2] = t3;
if (o2 === i2)
return;
const r2 = ((t4, e3) => {
const n3 = t4.portPointId ?? `${t4.connectionName}:${t4.x}:${t4.y}:${t4.z}`, o3 = e3.portPointId ?? `${e3.connectionName}:${e3.x}:${e3.y}:${e3.z}`;
return n3 < o3 ? `${n3}|${o3}` : `${o3}|${n3}`;
})(o2, i2);
e2.has(r2) || (e2.add(r2), n2.push(t3));
};
var Fi = (t3, e2, n2) => {
for (let o2 = 0;o2 < t3.length - 1; o2++)
Bi([t3[o2], t3[o2 + 1]], e2, n2);
};
var ji = (t3) => {
const e2 = [], n2 = new Set, o2 = ((t4) => {
const e3 = new Map;
for (const n3 of t4)
n3.portPointId && e3.set(n3.portPointId, n3);
return e3;
})(t3);
for (const i3 of t3) {
if (i3.prevPortPointId) {
const t4 = o2.get(i3.prevPortPointId);
t4 && t4.connectionName === i3.connectionName && Bi([t4, i3], n2, e2);
}
if (i3.nextPortPointId) {
const t4 = o2.get(i3.nextPortPointId);
t4 && t4.connectionName === i3.connectionName && Bi([i3, t4], n2, e2);
}
}
if (e2.length === 0)
return Fi(t3, n2, e2), e2;
const i2 = ((t4) => {
const e3 = new Set;
for (const [n3, o3] of t4)
n3.portPointId && e3.add(n3.portPointId), o3.portPointId && e3.add(o3.portPointId);
return e3;
})(e2), r2 = t3.filter((t4) => !t4.portPointId || !i2.has(t4.portPointId));
return Fi(r2, n2, e2), e2;
};
var $i = 0.000000001;
var Yi = 0.01;
var Xi = 0.000001;
function Wi(t3, e2, n2) {
return (e2.x - t3.x) * (n2.y - t3.y) - (e2.y - t3.y) * (n2.x - t3.x);
}
function Vi(t3, e2, n2, o2) {
const i2 = Wi(n2, o2, t3), r2 = Wi(n2, o2, e2), s2 = Wi(t3, e2, n2), a2 = Wi(t3, e2, o2);
if ((i2 > $i && r2 < -1e-9 || i2 < -1e-9 && r2 > $i) && (s2 > $i && a2 < -1e-9 || s2 < -1e-9 && a2 > $i)) {
const n3 = i2 / (i2 - r2);
return { x: t3.x + n3 * (e2.x - t3.x), y: t3.y + n3 * (e2.y - t3.y) };
}
return null;
}
function Hi(t3, e2) {
const n2 = [];
for (let o2 = 0;o2 < t3.route.length - 1; o2++) {
const i2 = t3.route[o2], r2 = t3.route[o2 + 1];
i2.z === e2 && r2.z === e2 && n2.push([{ x: i2.x, y: i2.y }, { x: r2.x, y: r2.y }]);
}
return n2;
}
function Gi(t3, e2) {
return t3.route.filter((t4) => t4.z === e2).map((t4) => ({ x: t4.x, y: t4.y }));
}
function Ui(t3, e2) {
return Math.hypot(t3.x - e2.x, t3.y - e2.y);
}
function Zi(t3, e2, n2 = 0.01) {
return Math.abs(t3.x - e2.x) < n2 && Math.abs(t3.y - e2.y) < n2;
}
function qi(t3, e2, n2) {
const o2 = new Set, i2 = [t3.route[0], t3.route[t3.route.length - 1]];
for (const t4 of i2)
t4 && t4.z === e2 && t4.portPointId && Zi(t4, n2) && o2.add(t4.portPointId);
return o2;
}
function Ji(t3, e2, n2, o2) {
const i2 = qi(t3, n2, o2);
if (i2.size === 0)
return false;
const r2 = qi(e2, n2, o2);
if (r2.size === 0)
return false;
for (const t4 of i2)
if (r2.has(t4))
return true;
return false;
}
function Qi(t3, e2, n2, o2) {
const i2 = [e2.a, e2.b], r2 = [o2.a, o2.b];
for (const o3 of i2)
for (const i3 of r2)
if (Zi(o3, i3) && Ji(t3, n2, e2.z, o3))
return true;
return false;
}
function Ki(t3, e2, n2) {
const o2 = n2.x - e2.x, i2 = n2.y - e2.y, r2 = o2 * o2 + i2 * i2;
if (r2 <= $i)
return Ui(t3, e2);
const s2 = t3.x - e2.x, a2 = t3.y - e2.y, c2 = Math.max(0, Math.min(1, (s2 * o2 + a2 * i2) / r2));
const l2 = e2.x + o2 * c2, h2 = e2.y + i2 * c2;
return Math.hypot(t3.x - l2, t3.y - h2);
}
function tr(t3, e2, n2, o2) {
return Vi(t3, e2, n2, o2) ? 0 : Math.min(Ki(t3, n2, o2), Ki(e2, n2, o2), Ki(n2, t3, e2), Ki(o2, t3, e2));
}
function er(t3) {
return t3.rootConnectionName ?? t3.connectionName.replace(/_mst\d+$/, "");
}
function nr(t3, e2) {
t3.push(e2);
}
function or(t3) {
const e2 = function(t4) {
const e3 = [], n3 = new Set;
for (const e4 of t4)
for (const t5 of e4.route)
n3.add(t5.z);
for (const o2 of n3) {
const n4 = t4.map((t5) => ({ points: Gi(t5, o2), segments: Hi(t5, o2), root: er(t5) }));
for (let i2 = 0;i2 < t4.length; i2++) {
const r2 = t4[i2], { points: s2, segments: a2, root: c2 } = n4[i2];
for (let l2 = i2 + 1;l2 < t4.length; l2++) {
const i3 = t4[l2], { points: h2, segments: d2, root: u2 } = n4[l2];
if (c2 === u2)
continue;
const p2 = new Set;
for (const t5 of s2)
for (const n5 of h2)
if (Zi(t5, n5)) {
if (Ji(r2, i3, o2, t5))
continue;
const n6 = `${t5.x.toFixed(2)},${t5.y.toFixed(2)}`;
if (p2.has(n6))
continue;
p2.add(n6), e3.push({ trace1: r2.connectionName, trace2: i3.connectionName, z: o2, point: t5, type: "shared_point" });
}
for (const [t5, n5] of a2)
for (const [s3, a3] of d2) {
const c3 = Vi(t5, n5, s3, a3);
c3 && e3.push({ trace1: r2.connectionName, trace2: i3.connectionName, z: o2, point: c3, type: "crossing", seg1: [t5, n5], seg2: [s3, a3] });
}
}
}
}
return e3;
}(t3).map((t4) => ({ trace1: t4.trace1, trace2: t4.trace2, type: t4.type, z: t4.z, point: t4.point, seg1: t4.seg1, seg2: t4.seg2, distance: 0, requiredDistance: 0 })), n2 = t3.map((t4) => {
const e3 = function(t5) {
const e4 = [];
for (let n4 = 0;n4 < t5.route.length - 1; n4++) {
const o3 = t5.route[n4], i3 = t5.route[n4 + 1];
o3.z === i3.z && e4.push({ minX: Math.min(o3.x, i3.x), maxX: Math.max(o3.x, i3.x), minY: Math.min(o3.y, i3.y), maxY: Math.max(o3.y, i3.y), z: o3.z, a: { x: o3.x, y: o3.y }, b: { x: i3.x, y: i3.y } });
}
return e4;
}(t4), n3 = new Set, o2 = new Map, i2 = new Map;
for (const e4 of t4.route) {
n3.add(e4.z);
const t5 = o2.get(e4.z) ?? [];
t5.push({ x: e4.x, y: e4.y }), o2.set(e4.z, t5);
}
for (const t5 of e3) {
const e4 = i2.get(t5.z) ?? [];
e4.push(t5), i2.set(t5.z, e4);
}
return { route: t4, rootNet: er(t4), pointsByLayer: o2, segmentsByLayer: i2, segments: e3, vias: t4.vias.map((t5) => ({ x: t5.x, y: t5.y })), traceRadius: t4.traceThickness / 2, viaRadius: t4.viaDiameter / 2, zLayers: n3 };
});
for (let t4 = 0;t4 < n2.length; t4++) {
const o2 = n2[t4];
for (let i2 = t4 + 1;i2 < n2.length; i2++) {
const t5 = n2[i2];
if (o2.rootNet === t5.rootNet)
continue;
const r2 = new Set([...o2.zLayers.values(), ...t5.zLayers.values()]);
for (const n3 of r2) {
const i3 = o2.segmentsByLayer.get(n3) ?? [], r3 = t5.segmentsByLayer.get(n3) ?? [], s3 = o2.pointsByLayer.get(n3) ?? [], a2 = t5.pointsByLayer.get(n3) ?? [], c2 = o2.traceRadius + t5.traceRadius;
for (const s4 of i3)
for (const i4 of r3) {
if (s4.minX - i4.maxX >= c2 || i4.minX - s4.maxX >= c2 || s4.minY - i4.maxY >= c2 || i4.minY - s4.maxY >= c2)
continue;
const r4 = tr(s4.a, s4.b, i4.a, i4.b);
r4 + Xi >= c2 || (r4 <= Yi && Qi(o2.route, s4, t5.route, i4) || nr(e2, { trace1: o2.route.connectionName, trace2: t5.route.connectionName, type: r4 <= Yi ? "shared_point" : "trace_clearance", z: n3, distance: r4, requiredDistance: c2, seg1: [s4.a, s4.b], seg2: [i4.a, i4.b] }));
}
for (const i4 of s3)
for (const r4 of a2) {
if (Math.abs(i4.x - r4.x) >= c2 || Math.abs(i4.y - r4.y) >= c2)
continue;
const s4 = Ui(i4, r4);
s4 + Xi >= c2 || (s4 <= Yi && Ji(o2.route, t5.route, n3, i4) || nr(e2, { trace1: o2.route.connectionName, trace2: t5.route.connectionName, type: s4 <= Yi ? "shared_point" : "trace_clearance", z: n3, distance: s4, requiredDistance: c2, point: i4, point2: r4 }));
}
}
const s2 = o2.viaRadius + t5.viaRadius;
for (const n3 of o2.vias)
for (const i3 of t5.vias) {
if (Math.abs(n3.x - i3.x) >= s2 || Math.abs(n3.y - i3.y) >= s2)
continue;
const r3 = Ui(n3, i3);
r3 + Xi >= s2 || nr(e2, { trace1: o2.route.connectionName, trace2: t5.route.connectionName, type: "via_via_clearance", z: null, distance: r3, requiredDistance: s2, point: n3, point2: i3 });
}
for (const n3 of o2.vias) {
const i3 = o2.viaRadius + t5.traceRadius;
for (const r3 of t5.segments) {
if (n3.x - r3.maxX >= i3 || r3.minX - n3.x >= i3 || n3.y - r3.maxY >= i3 || r3.minY - n3.y >= i3)
continue;
const s3 = Ki(n3, r3.a, r3.b);
s3 + Xi >= i3 || nr(e2, { trace1: o2.route.connectionName, trace2: t5.route.connectionName, type: "via_trace_clearance", z: r3.z, distance: s3, requiredDistance: i3, point: n3, seg2: [r3.a, r3.b] });
}
}
for (const n3 of t5.vias) {
const i3 = t5.viaRadius + o2.traceRadius;
for (const r3 of o2.segments) {
if (n3.x - r3.maxX >= i3 || r3.minX - n3.x >= i3 || n3.y - r3.maxY >= i3 || r3.minY - n3.y >= i3)
continue;
const s3 = Ki(n3, r3.a, r3.b);
s3 + Xi >= i3 || nr(e2, { trace1: o2.route.connectionName, trace2: t5.route.connectionName, type: "via_trace_clearance", z: r3.z, distance: s3, requiredDistance: i3, point: n3, seg1: [r3.a, r3.b] });
}
}
}
}
return e2;
}
var ir = class extends kt {
nodeWithPortPoints;
props;
traceThickness;
traceMargin;
viaDiameter;
hyperParameters;
phase = "routing";
round = 0;
routingIterations = 0;
routedCount = 0;
conflictCount = 0;
rerouteCount = 0;
bestConflictCount = 1 / 0;
broadNegotiations = 0;
stagnantRounds = 0;
violations = [];
connections = [];
activeConnectionIndex = -1;
rows = 0;
cols = 0;
plane = 0;
layers = [];
pitchX = 0;
pitchY = 0;
left = 0;
bottom = 0;
routes = new Map;
pairCache = new WeakMap;
queue = [];
traceCost;
viaCost;
fixed;
fixedVia;
history;
viaHistory;
parent;
searchKernel;
heuristicCost;
heuristicCache = new Map;
viaAllowed;
goal = 0;
presentCost = 0.5;
randomState = 1;
constructor(t3) {
super(), this.props = t3, this.nodeWithPortPoints = t3.nodeWithPortPoints, this.traceThickness = t3.traceThickness ?? 0.1, this.traceMargin = t3.traceMargin ?? 0.1, this.viaDiameter = t3.viaDiameter ?? 0.3, this.hyperParameters = { shuffleSeed: 0, greedyMultiplier: 1.1, ...t3.hyperParameters };
for (const e2 of [t3.cellSizeMm ?? 0.1, this.traceThickness, this.viaDiameter, t3.stepMultiplier ?? 1000, t3.maxRounds ?? 200, t3.maxSearchIterations ?? 50000000, this.hyperParameters.greedyMultiplier])
if (!Number.isFinite(e2) || e2 <= 0)
throw new Error("A13 dimensions and search limits must be positive and finite");
if (!Number.isFinite(this.traceMargin) || this.traceMargin < 0)
throw new Error("traceMargin must be nonnegative");
this.MAX_ITERATIONS = 1e8;
}
getSolverName() {
return "HighDensitySolverA13";
}
getConstructorParams() {
return [{ ...this.props }];
}
_setup() {
const t3 = this.nodeWithPortPoints;
if (t3.width <= 0 || t3.height <= 0)
throw new Error("Node dimensions must be positive");
this.cols = Math.ceil(t3.width / (this.props.cellSizeMm ?? 0.1)) + 1, this.rows = Math.ceil(t3.height / (this.props.cellSizeMm ?? 0.1)) + 1, this.pitchX = t3.width / (this.cols - 1), this.pitchY = t3.height / (this.rows - 1), this.left = t3.center.x - t3.width / 2, this.bottom = t3.center.y - t3.height / 2, this.layers = t3.availableZ ?? [...new Set(t3.portPoints.map((t4) => t4.z))].sort((t4, e3) => t4 - e3), this.plane = this.rows * this.cols;
const e2 = this.plane * this.layers.length;
if (e2 > 2000000)
throw new Error("A13 grid exceeds two million states");
this.traceCost = new Uint16Array(e2), this.viaCost = new Uint16Array(this.plane), this.fixed = new Uint8Array(e2), this.fixedVia = new Uint8Array(this.plane), this.history = new Float64Array(e2), this.viaHistory = new Float64Array(this.plane), this.heuristicCost = new Float64Array(e2), this.viaAllowed = new Uint8Array(this.plane);
const n2 = Math.max(this.viaDiameter / 2, this.props.viaMinDistFromBorder ?? this.viaDiameter / 2);
for (let e3 = 0;e3 < this.plane; e3++) {
const o3 = this.point(e3);
o3.x - this.left >= n2 && this.left + t3.width - o3.x >= n2 && o3.y - this.bottom >= n2 && this.bottom + t3.height - o3.y >= n2 && (this.viaAllowed[e3] = 1);
}
this.parent = new Int32Array(e2);
const o2 = this.props.searchBackend === "wasm" ? zi : Li;
this.searchKernel = new o2(this.cols, this.rows, this.layers.length, this.pitchX, this.pitchY);
const i2 = new Map;
for (const e3 of t3.portPoints) {
if (!this.layers.includes(e3.z))
throw new Error("Port is on an unavailable layer");
const t4 = i2.get(e3.connectionName) ?? [];
t4.push(e3), i2.set(e3.connectionName, t4);
}
for (const t4 of i2.values())
for (const [e3, n3] of ji(t4))
this.connections.push({ start: e3, end: n3, root: e3.rootConnectionName ?? e3.connectionName.replace(/_mst\d+$/, "") });
this.randomState = this.hyperParameters.shuffleSeed + 1 >>> 0, this.queue = this.shuffle(this.connections.map((t4, e3) => e3));
}
shuffle(t3) {
for (let e2 = t3.length - 1;e2 > 0; e2--) {
this.randomState = Math.imul(this.randomState, 1664525) + 1013904223 >>> 0;
const n2 = this.randomState % (e2 + 1);
[t3[e2], t3[n2]] = [t3[n2], t3[e2]];
}
return t3;
}
index(t3) {
const e2 = Math.max(0, Math.min(this.cols - 1, Math.round((t3.x - this.left) / this.pitchX))), n2 = Math.max(0, Math.min(this.rows - 1, Math.round((t3.y - this.bottom) / this.pitchY)));
return this.layers.indexOf(t3.z) * this.plane + n2 * this.cols + e2;
}
point(t3) {
const e2 = t3 % this.plane;
return { x: this.left + e2 % this.cols * this.pitchX, y: this.bottom + Math.floor(e2 / this.cols) * this.pitchY, z: this.layers[Math.floor(t3 / this.plane)] };
}
capsule(t3, e2, n2, o2) {
const i2 = Math.max(0, Math.floor((Math.min(t3.x, e2.x) - n2 - this.left) / this.pitchX)), r2 = Math.min(this.cols - 1, Math.ceil((Math.max(t3.x, e2.x) + n2 - this.left) / this.pitchX)), s2 = Math.max(0, Math.floor((Math.min(t3.y, e2.y) - n2 - this.bottom) / this.pitchY)), a2 = Math.min(this.rows - 1, Math.ceil((Math.max(t3.y, e2.y) + n2 - this.bottom) / this.pitchY)), c2 = e2.x - t3.x, l2 = e2.y - t3.y, h2 = c2 * c2 + l2 * l2;
for (let e3 = s2;e3 <= a2; e3++)
for (let s3 = i2;s3 <= r2; s3++) {
const i3 = this.left + s3 * this.pitchX, r3 = this.bottom + e3 * this.pitchY, a3 = h2 ? Math.max(0, Math.min(1, ((i3 - t3.x) * c2 + (r3 - t3.y) * l2) / h2)) : 0;
(i3 - t3.x - a3 * c2) ** 2 + (r3 - t3.y - a3 * l2) ** 2 < n2 * n2 - 0.000000000001 && o2(e3 * this.cols + s3);
}
}
prepareSearch(t3) {
this.activeConnectionIndex = t3;
const e2 = this.connections[t3];
this.traceCost.fill(0), this.viaCost.fill(0), this.fixed.fill(0), this.fixedVia.fill(0);
for (const [t4, n3] of this.routes)
if (this.connections[t4].root !== e2.root) {
for (const t5 of n3.traceFootprint)
this.traceCost[t5]++;
for (const t5 of n3.viaFootprint)
this.viaCost[t5]++;
}
for (const t4 of this.connections)
if (t4.root !== e2.root)
for (const e3 of [t4.start, t4.end])
this.capsule(e3, e3, this.traceThickness + this.traceMargin, (t5) => {
this.fixed[this.layers.indexOf(e3.z) * this.plane + t5] = 1;
}), this.capsule(e3, e3, (this.traceThickness + this.viaDiameter) / 2 + this.traceMargin, (t5) => {
this.fixedVia[t5] = 1;
});
const n2 = this.index(e2.start);
this.goal = this.index(e2.end);
const o2 = this.point(this.goal), i2 = this.heuristicCache.get(this.goal);
if (i2)
this.heuristicCost = i2;
else {
this.heuristicCost = new Float64Array(this.parent.length);
for (let t5 = 0;t5 < this.layers.length; t5++)
for (let e3 = 0;e3 < this.rows; e3++) {
const n3 = Math.abs(this.bottom + e3 * this.pitchY - o2.y);
for (let i3 = 0;i3 < this.cols; i3++)
this.heuristicCost[t5 * this.plane + e3 * this.cols + i3] = (Math.abs(this.left + i3 * this.pitchX - o2.x) + n3 + (this.layers[t5] === o2.z ? 0 : 0.8)) * this.hyperParameters.greedyMultiplier;
}
const t4 = Math.floor(8388608 / this.heuristicCost.byteLength);
t4 > 0 && (this.heuristicCache.size >= t4 && this.heuristicCache.delete(this.heuristicCache.keys().next().value), this.heuristicCache.set(this.goal, this.heuristicCost));
}
this.searchKernel.begin({ traceCost: this.traceCost, viaCost: this.viaCost, fixed: this.fixed, fixedVia: this.fixedVia, history: this.history, viaHistory: this.viaHistory, heuristicCost: this.heuristicCost, viaAllowed: this.viaAllowed }, n2, this.goal, this.presentCost);
}
_step() {
if (this.phase === "negotiating")
return void this.negotiate();
if (this.activeConnectionIndex < 0) {
const t4 = this.queue.shift();
if (t4 === undefined)
return void (this.phase = "negotiating");
this.prepareSearch(t4);
}
const { status: t3, expansions: e2 } = this.searchKernel.run(this.props.stepMultiplier ?? 1000, (this.props.maxSearchIterations ?? 50000000) - this.routingIterations);
this.routingIterations += e2, t3 === 1 ? (this.searchKernel.copyParents(this.parent), this.commit(this.goal)) : t3 === 2 ? (this.failed = true, this.error = `No path between fixed terminals of ${this.connections[this.activeConnectionIndex].start.connectionName}`) : t3 === 3 && (this.failed = true, this.error = "A13 exhausted its search budget");
}
commit(t3) {
const e2 = this.activeConnectionIndex, n2 = this.connections[e2], o2 = [];
for (let e3 = t3;e3 !== -1; e3 = this.parent[e3])
o2.push(e3);
o2.reverse();
const i2 = [{ ...n2.start }, ...o2.map((t4) => this.point(t4)), { ...n2.end }], r2 = [];
for (const t4 of i2) {
const e3 = r2.at(-1), n3 = r2.at(-2);
e3 && e3.x === t4.x && e3.y === t4.y && e3.z === t4.z || (n3 && e3 && n3.z === t4.z && e3.z === t4.z && (e3.x - n3.x) * (t4.y - e3.y) === (e3.y - n3.y) * (t4.x - e3.x) && r2.pop(), r2.push(t4));
}
r2[0] = { ...n2.start }, r2[r2.length - 1] = { ...n2.end };
const s2 = [], a2 = [];
for (let t4 = 1;t4 < o2.length; t4++)
if (Math.floor(o2[t4] / this.plane) !== Math.floor(o2[t4 - 1] / this.plane)) {
const e3 = this.point(o2[t4]);
s2.push({ x: e3.x, y: e3.y }), a2.push(o2[t4] % this.plane);
}
const c2 = { connectionName: n2.start.connectionName, rootConnectionName: n2.root, regionId: this.nodeWithPortPoints.capacityMeshNodeId, traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, route: r2, vias: s2 }, l2 = new Set, h2 = new Set, d2 = new Set;
for (let t4 = 1;t4 < r2.length; t4++) {
const e3 = r2[t4 - 1], n3 = r2[t4];
e3.z === n3.z && (this.capsule(e3, n3, 0.00001, (t5) => d2.add(this.layers.indexOf(e3.z) * this.plane + t5)), this.capsule(e3, n3, this.traceThickness + this.traceMargin, (t5) => l2.add(this.layers.indexOf(e3.z) * this.plane + t5)), this.capsule(e3, n3, (this.traceThickness + this.viaDiameter) / 2 + this.traceMargin, (t5) => h2.add(t5)));
}
for (const t4 of s2)
this.capsule(t4, t4, (this.viaDiameter + this.traceThickness) / 2 + this.traceMargin, (t5) => {
for (let e3 = 0;e3 < this.layers.length; e3++)
l2.add(e3 * this.plane + t5);
}), this.capsule(t4, t4, this.viaDiameter + this.traceMargin, (t5) => h2.add(t5));
this.routes.has(e2) && this.rerouteCount++, this.routes.set(e2, { output: c2, clearanceOutput: { ...c2, traceThickness: c2.traceThickness + this.traceMargin, viaDiameter: c2.viaDiameter + this.traceMargin }, traceFootprint: [...l2], traceFootprintSet: l2, viaFootprint: [...h2], viaFootprintSet: h2, cells: [...d2], viaCells: a2 }), this.routedCount = this.routes.size, this.activeConnectionIndex = -1;
}
getPair(t3, e2) {
let n2 = this.pairCache.get(t3);
n2 || (n2 = new WeakMap, this.pairCache.set(t3, n2));
let o2 = n2.get(e2);
return o2 || (o2 = { cells: [...t3.cells.filter((t4) => e2.traceFootprintSet.has(t4)), ...e2.cells.filter((e3) => t3.traceFootprintSet.has(e3))], vias: [...t3.viaCells.filter((t4) => e2.viaFootprintSet.has(t4)), ...e2.viaCells.filter((e3) => t3.viaFootprintSet.has(e3))], violations: or([t3.clearanceOutput, e2.clearanceOutput]) }, n2.set(e2, o2)), o2;
}
negotiate() {
this.round++;
const t3 = new Set, e2 = new Set, n2 = new Set;
for (const [o3, i3] of this.routes)
for (const [r3, s2] of this.routes) {
if (r3 <= o3 || this.connections[o3].root === this.connections[r3].root)
continue;
const a2 = this.getPair(i3, s2);
if (a2.cells.length || a2.vias.length) {
t3.add(o3), t3.add(r3);
for (const t4 of a2.cells)
e2.add(t4);
for (const t4 of a2.vias)
n2.add(t4);
}
}
const o2 = [...this.routes.entries()].sort(([t4], [e3]) => t4 - e3), i2 = new Map;
for (const [, t4] of o2)
for (const e3 of t4.output.route)
i2.has(e3.z) || i2.set(e3.z, []);
const r2 = [];
for (let t4 = 0;t4 < o2.length; t4++)
for (let e3 = t4 + 1;e3 < o2.length; e3++) {
const [n3, s2] = o2[t4], [a2, c2] = o2[e3];
if (this.connections[n3].root !== this.connections[a2].root)
for (const t5 of this.getPair(s2, c2).violations)
t5.requiredDistance === 0 ? i2.get(t5.z).push(t5) : r2.push(t5);
}
this.violations = [...i2.values()].flat().concat(r2);
for (const o3 of this.violations) {
for (let e3 = 0;e3 < this.connections.length; e3++)
[o3.trace1, o3.trace2].includes(this.connections[e3].start.connectionName) && t3.add(e3);
for (const t4 of [o3.point, o3.point2])
if (t4) {
const i3 = this.index({ ...t4, z: this.layers[0] }) % this.plane;
n2.add(i3), o3.z !== null && e2.add(this.layers.indexOf(o3.z) * this.plane + i3);
}
}
if (this.conflictCount = t3.size, this.stagnantRounds = this.conflictCount < this.bestConflictCount ? 0 : this.stagnantRounds + 1, this.bestConflictCount = Math.min(this.bestConflictCount, this.conflictCount), this.stats = { round: this.round, conflictedRoutes: this.conflictCount, geometryViolations: this.violations.length, reroutes: this.rerouteCount, searchExpansions: this.routingIterations }, !this.violations.length && this.routes.size === this.connections.length)
return this.solved = true, this.stats.conflictedRoutes = 0, this.conflictCount = 0, this.bestConflictCount = 0, void (this.phase = "complete");
if (this.round >= (this.props.maxRounds ?? 200))
return this.failed = true, void (this.error = `Negotiation exhausted ${this.round} rounds (${this.conflictCount} conflicted routes)`);
for (const t4 of e2)
this.history[t4] += 0.15;
for (const t4 of n2)
this.viaHistory[t4] += 0.15;
this.presentCost = Math.min(20, 1.08 * this.presentCost), this.stagnantRounds >= 8 ? (this.queue = this.shuffle(this.connections.map((t4, e3) => e3)), this.presentCost = Math.max(0.5, this.presentCost / 2), this.stagnantRounds = 0, this.broadNegotiations++) : this.queue = this.shuffle([...t3]), this.phase = "routing";
}
getOutput() {
return [...this.routes.entries()].sort(([t3], [e2]) => t3 - e2).map(([, t3]) => t3.output);
}
visualize() {
const t3 = this.nodeWithPortPoints, e2 = { title: `A13 negotiated congestion · round ${this.round} · ${this.conflictCount} conflicted routes`, rects: [{ center: t3.center, width: t3.width, height: t3.height, stroke: "#475569", fill: "transparent" }], points: t3.portPoints.map((t4) => ({ ...t4, color: t4.z === 0 ? "red" : "blue", layer: `z${t4.z}`, label: t4.connectionName })), lines: [], circles: [] };
for (const t4 of this.getOutput()) {
for (let n2 = 1;n2 < t4.route.length; n2++) {
const o2 = t4.route[n2 - 1], i2 = t4.route[n2];
o2.z === i2.z && e2.lines.push({ points: [o2, i2], strokeColor: o2.z === 0 ? "#ef4444" : "#3b82f6", strokeWidth: this.traceThickness, layer: `z${o2.z}` });
}
for (const n2 of t4.vias)
e2.circles.push({ center: n2, radius: this.viaDiameter / 2, fill: "#cbd5e1", stroke: "#334155", layer: `z${this.layers.join(",")}` });
}
for (const t4 of this.violations.slice(0, 50))
t4.point && e2.circles.push({ center: t4.point, radius: 0.2, stroke: "#f59e0b", fill: "transparent" });
return e2;
}
};
var sr = (t3) => ({ minX: Math.min(t3[0].x, t3[1].x), maxX: Math.max(t3[0].x, t3[1].x), minY: Math.min(t3[0].y, t3[1].y), maxY: Math.max(t3[0].y, t3[1].y) });
function ar(t3, e2) {
const n2 = t3.x - e2.x, o2 = t3.y - e2.y;
return n2 * n2 + o2 * o2;
}
function cr(t3, e2, n2) {
const o2 = ar(e2, n2);
if (o2 === 0)
return ar(t3, e2);
let i2 = ((t3.x - e2.x) * (n2.x - e2.x) + (t3.y - e2.y) * (n2.y - e2.y)) / o2;
i2 = Math.max(0, Math.min(1, i2));
return ar(t3, { x: e2.x + i2 * (n2.x - e2.x), y: e2.y + i2 * (n2.y - e2.y) });
}
function lr(t3, e2, n2, o2) {
if (fe(t3, e2, n2, o2))
return 0;
const i2 = { x: t3.x, y: t3.y }, r2 = { x: e2.x, y: e2.y }, s2 = { x: n2.x, y: n2.y }, a2 = { x: o2.x, y: o2.y };
return Math.min(cr(i2, s2, a2), cr(r2, s2, a2), cr(s2, i2, r2), cr(a2, i2, r2));
}
var hr = class {
segmentBuckets;
viaBuckets;
CELL_SIZE;
maximumCopperRadius = 0;
constructor(t3, e2 = 1) {
this.segmentBuckets = new Map, this.viaBuckets = new Map, this.CELL_SIZE = e2;
for (const e3 of t3)
if (e3 && e3.connectionName) {
if (this.maximumCopperRadius = Math.max(this.maximumCopperRadius, e3.traceThickness / 2, e3.viaDiameter / 2), e3.route && e3.route.length >= 2)
for (let t4 = 0;t4 < e3.route.length - 1; t4++) {
const n2 = e3.route[t4], o2 = e3.route[t4 + 1];
if (n2.x === o2.x && n2.y === o2.y)
continue;
if (n2.insideJumperPad && o2.insideJumperPad)
continue;
const i2 = [n2, o2], r2 = sr(i2), s2 = { segmentId: `${e3.connectionName}-seg-${t4}`, segment: i2, parentRoute: e3 }, a2 = Math.floor(r2.minX / this.CELL_SIZE), c2 = Math.floor((r2.maxX + 0.000000001) / this.CELL_SIZE), l2 = Math.floor(r2.minY / this.CELL_SIZE), h2 = Math.floor((r2.maxY + 0.000000001) / this.CELL_SIZE);
for (let t5 = a2;t5 <= c2; t5++)
for (let e4 = l2;e4 <= h2; e4++) {
const n3 = `${t5}x${e4}`;
let o3 = this.segmentBuckets.get(n3);
o3 || (o3 = [], this.segmentBuckets.set(n3, o3)), o3.push(s2);
}
}
if (e3.vias && e3.vias.length > 0)
for (let t4 = 0;t4 < e3.vias.length; t4++) {
const n2 = e3.vias[t4];
if (n2 == null)
continue;
const o2 = { viaId: `${e3.connectionName}-via-${t4}`, x: n2.x, y: n2.y, parentRoute: e3 }, i2 = `${Math.floor(n2.x / this.CELL_SIZE)}x${Math.floor(n2.y / this.CELL_SIZE)}`;
let r2 = this.viaBuckets.get(i2);
r2 || (r2 = [], this.viaBuckets.set(i2, r2)), r2.push(o2);
}
} else
console.warn("Skipping route with missing data:", e3);
}
getConflictingRoutesForSegment(t3, e2, n2) {
const o2 = sr([t3, e2]), i2 = n2 + this.maximumCopperRadius, r2 = o2.minX - i2, s2 = o2.minY - i2, a2 = o2.maxX + i2, c2 = o2.maxY + i2, l2 = Math.floor(r2 / this.CELL_SIZE), h2 = Math.floor((a2 + 0.000000001) / this.CELL_SIZE), d2 = Math.floor(s2 / this.CELL_SIZE), u2 = Math.floor((c2 + 0.000000001) / this.CELL_SIZE), p2 = new Map, m2 = new Set, g2 = new Set, f2 = { x: t3.x, y: t3.y }, y2 = { x: e2.x, y: e2.y };
for (let o3 = l2;o3 <= h2; o3++)
for (let i3 = d2;i3 <= u2; i3++) {
const r3 = `${o3}x${i3}`, s3 = this.segmentBuckets.get(r3);
if (s3)
for (const o4 of s3) {
if (m2.has(o4.segmentId))
continue;
m2.add(o4.segmentId);
const i4 = o4.parentRoute, [r4, s4] = o4.segment;
if (t3.z !== e2.z || r4.z !== s4.z || r4.z !== t3.z)
continue;
const a4 = n2 + i4.traceThickness / 2, c3 = a4 * a4, l3 = lr(t3, e2, r4, s4);
if (l3 < c3) {
const t4 = i4.connectionName, e3 = p2.get(t4);
(!e3 || l3 < e3.minDistSq) && p2.set(t4, { route: i4, minDistSq: l3 });
}
}
const a3 = this.viaBuckets.get(r3);
if (a3)
for (const t4 of a3) {
if (g2.has(t4.viaId))
continue;
g2.add(t4.viaId);
const e3 = t4.parentRoute, o4 = { x: t4.x, y: t4.y }, i4 = n2 + e3.viaDiameter / 2, r4 = i4 * i4, s4 = cr(o4, f2, y2);
if (s4 < r4) {
const t5 = e3.connectionName, n3 = p2.get(t5);
(!n3 || s4 < n3.minDistSq) && p2.set(t5, { route: e3, minDistSq: s4 });
}
}
}
const _2 = [];
for (const t4 of p2.values())
_2.push({ conflictingRoute: t4.route, distance: Math.sqrt(t4.minDistSq) });
return _2;
}
removeRoute(t3) {
for (const [e2, n2] of this.segmentBuckets) {
const o2 = n2.filter((e3) => e3.parentRoute.connectionName !== t3);
o2.length === 0 ? this.segmentBuckets.delete(e2) : o2.length !== n2.length && this.segmentBuckets.set(e2, o2);
}
for (const [e2, n2] of this.viaBuckets) {
const o2 = n2.filter((e3) => e3.parentRoute.connectionName !== t3);
o2.length === 0 ? this.viaBuckets.delete(e2) : o2.length !== n2.length && this.viaBuckets.set(e2, o2);
}
}
addRoute(t3) {
if (!t3 || !t3.connectionName)
return void console.warn("Skipping route with missing data:", t3);
this.maximumCopperRadius = Math.max(this.maximumCopperRadius, t3.traceThickness / 2, t3.viaDiameter / 2);
if (t3.route && t3.route.length >= 2)
for (let e2 = 0;e2 < t3.route.length - 1; e2++) {
const n2 = t3.route[e2], o2 = t3.route[e2 + 1];
if (n2.x === o2.x && n2.y === o2.y)
continue;
if (n2.insideJumperPad && o2.insideJumperPad)
continue;
const i2 = [n2, o2], r2 = sr(i2), s2 = { segmentId: `${t3.connectionName}-seg-${e2}`, segment: i2, parentRoute: t3 }, a2 = Math.floor(r2.minX / this.CELL_SIZE), c2 = Math.floor((r2.maxX + 0.000000001) / this.CELL_SIZE), l2 = Math.floor(r2.minY / this.CELL_SIZE), h2 = Math.floor((r2.maxY + 0.000000001) / this.CELL_SIZE);
for (let t4 = a2;t4 <= c2; t4++)
for (let e3 = l2;e3 <= h2; e3++) {
const n3 = `${t4}x${e3}`;
let o3 = this.segmentBuckets.get(n3);
o3 || (o3 = [], this.segmentBuckets.set(n3, o3)), o3.push(s2);
}
}
if (t3.vias && t3.vias.length > 0)
for (let e2 = 0;e2 < t3.vias.length; e2++) {
const n2 = t3.vias[e2];
if (n2 == null)
continue;
const o2 = { viaId: `${t3.connectionName}-via-${e2}`, x: n2.x, y: n2.y, parentRoute: t3 }, i2 = `${Math.floor(n2.x / this.CELL_SIZE)}x${Math.floor(n2.y / this.CELL_SIZE)}`;
let r2 = this.viaBuckets.get(i2);
r2 || (r2 = [], this.viaBuckets.set(i2, r2)), r2.push(o2);
}
}
getConflictingRoutesNearPoint(t3, e2) {
const n2 = e2 + this.maximumCopperRadius, o2 = t3.x - n2, i2 = t3.y - n2, r2 = t3.x + n2, s2 = t3.y + n2, a2 = Math.floor(o2 / this.CELL_SIZE), c2 = Math.floor((r2 + 0.000000001) / this.CELL_SIZE), l2 = Math.floor(i2 / this.CELL_SIZE), h2 = Math.floor((s2 + 0.000000001) / this.CELL_SIZE), d2 = new Map, u2 = new Set, p2 = new Set;
for (let n3 = a2;n3 <= c2; n3++)
for (let o3 = l2;o3 <= h2; o3++) {
const i3 = `${n3}x${o3}`, r3 = this.segmentBuckets.get(i3);
if (r3)
for (const n4 of r3) {
if (u2.has(n4.segmentId))
continue;
u2.add(n4.segmentId);
const o4 = n4.segment[0], i4 = n4.segment[1];
if (o4.z !== i4.z || o4.z !== t3.z)
continue;
const r4 = n4.parentRoute, s4 = { x: n4.segment[0].x, y: n4.segment[0].y }, a3 = { x: n4.segment[1].x, y: n4.segment[1].y }, c3 = e2 + r4.traceThickness / 2, l3 = c3 * c3, h3 = cr(t3, s4, a3);
if (h3 < l3) {
const t4 = r4.connectionName, e3 = d2.get(t4);
(!e3 || h3 < e3.minDistSq) && d2.set(t4, { route: r4, minDistSq: h3 });
}
}
const s3 = this.viaBuckets.get(i3);
if (s3)
for (const n4 of s3) {
if (p2.has(n4.viaId))
continue;
p2.add(n4.viaId);
const o4 = n4.parentRoute, i4 = { x: n4.x, y: n4.y }, r4 = e2 + o4.viaDiameter / 2, s4 = r4 * r4, a3 = ar(t3, i4);
if (a3 < s4) {
const t4 = o4.connectionName, e3 = d2.get(t4);
(!e3 || a3 < e3.minDistSq) && d2.set(t4, { route: o4, minDistSq: a3 });
}
}
}
const m2 = [];
for (const t4 of d2.values())
m2.push({ conflictingRoute: t4.route, distance: Math.sqrt(t4.minDistSq) });
return m2;
}
};
function dr(t3) {
let e2 = t3;
for (let t4 = 0;t4 < 10; t4++)
e2 = 16807 * e2 % 2147483647;
let n2 = e2;
e2 = (69069 * t3 + 1) % 2147483647;
for (let t4 = 0;t4 < 10; t4++)
e2 = 48271 * e2 % 2147483647;
let o2 = e2;
return () => {
let t4 = n2;
n2 = o2, t4 ^= t4 << 23, t4 ^= t4 >>> 17, t4 ^= o2, t4 ^= o2 >>> 26, o2 = t4;
const e3 = (n2 + o2) / 4294967296;
return e3 - Math.floor(e3);
};
}
var ur = { 1: [[0]], 2: [[0, 1], [1, 0]], 3: [[0, 1, 2], [2, 0, 1], [1, 0, 2], [0, 2, 1], [1, 2, 0], [2, 1, 0]], 4: [[0, 1, 2, 3], [2, 0, 1, 3], [1, 3, 2, 0], [3, 0, 1, 2], [0, 2, 1, 3], [2, 1, 3, 0], [3, 0, 2, 1], [1, 2, 0, 3], [3, 1, 0, 2], [0, 3, 2, 1], [2, 3, 0, 1], [2, 3, 1, 0], [1, 2, 3, 0], [3, 1, 2, 0], [0, 1, 3, 2], [0, 2, 3, 1], [0, 3, 1, 2], [1, 0, 2, 3], [1, 0, 3, 2], [1, 3, 0, 2], [2, 0, 3, 1], [2, 1, 0, 3], [3, 2, 0, 1], [3, 2, 1, 0]] };
function pr(t3, e2) {
if (e2 === 0)
return t3;
if (t3.length === 0)
return t3;
if (t3.length <= 4) {
const n3 = ur[t3.length];
return n3[e2 % n3.length].map((e3) => t3[e3]);
}
const n2 = dr(e2), o2 = t3.slice();
for (let t4 = 0;t4 < o2.length; t4++) {
const e3 = Math.floor(n2() * o2.length), i2 = Math.floor(n2() * (t4 + 1));
[o2[e3], o2[i2]] = [o2[i2], o2[e3]];
}
return o2;
}
var mr = (t3) => {
let e2 = 1 / 0;
const n2 = t3.portPoints;
for (let t4 = 0;t4 < n2.length; t4++)
for (let o2 = t4 + 1;o2 < n2.length; o2++) {
const i2 = n2[t4], r2 = n2[o2];
if (i2.z !== r2.z)
continue;
if (i2.rootConnectionName && i2.rootConnectionName === r2.rootConnectionName)
continue;
const s2 = Math.sqrt((i2.x - r2.x) ** 2 + (i2.y - r2.y) ** 2);
e2 = Math.min(e2, s2);
}
return e2 === 1 / 0 ? 0 : e2;
};
var gr = class {
heap = [];
constructor(t3) {
this.heap = [];
for (const e2 of t3)
this.enqueue(e2);
}
dequeue() {
if (this.heap.length === 0)
return null;
const t3 = this.heap[0];
return this.heap[0] = this.heap[this.heap.length - 1], this.heap.pop(), this.heapifyDown(), t3;
}
peek() {
return this.heap.length === 0 ? null : this.heap[0];
}
enqueue(t3) {
this.heap.push(t3), this.heapifyUp();
}
heapifyUp() {
let t3 = this.heap.length - 1;
const e2 = this.heap[t3];
for (;t3 > 0; ) {
const n2 = Math.floor((t3 - 1) / 2), o2 = this.heap[n2];
if (o2.f <= e2.f)
break;
this.heap[t3] = o2, t3 = n2;
}
this.heap[t3] = e2;
}
heapifyDown() {
let t3 = 0;
const e2 = this.heap.length, n2 = this.heap[t3];
if (n2) {
for (;; ) {
const o2 = 2 * t3 + 1;
if (o2 >= e2)
break;
const i2 = o2 + 1;
let r2 = o2;
if (i2 < e2 && this.heap[i2].f < this.heap[o2].f && (r2 = i2), n2.f < this.heap[r2].f)
break;
this.heap[t3] = this.heap[r2], t3 = r2;
}
this.heap[t3] = n2;
}
}
getTopN(t3) {
return [...this.heap].sort((t4, e2) => t4.f - e2.f).slice(0, t3);
}
};
var fr = (t3, e2, n2 = []) => [t3, e2 ? `rootConnectionName: ${e2}` : undefined, ...n2].filter(Boolean).join(`
`);
var yr = class extends si {
getSolverName() {
return "SingleHighDensityRouteSolver";
}
obstacleRoutes;
bounds;
boundsSize;
boundsCenter;
A;
B;
straightLineDistance;
viaDiameter;
traceThickness;
obstacleMargin;
layerCount;
availableZ;
minCellSize = 0.05;
cellStep = 0.05;
GREEDY_MULTIPLER = 1.1;
numRoutes;
VIA_PENALTY_FACTOR = 0.3;
CELL_SIZE_FACTOR;
NEARBY_SEGMENT_CLEARANCE;
exploredNodes;
viasInPathByNode = new WeakMap;
gridMinXIndex;
gridMinYIndex;
gridWidth;
gridHeight;
candidates;
connectionName;
rootConnectionName;
regionId;
solvedPath = null;
futureConnections;
hyperParameters;
connMap;
obstacleSegments = [];
obstacleSegmentIndex = null;
obstacleSegmentsByLayer = new Map;
obstacleSegmentIndexByLayer = new Map;
obstacleVias = [];
obstacleViaIndex = null;
debug_exploredNodesOrdered;
debug_nodesTooCloseToObstacle;
debug_nodePathToParentIntersectsObstacle;
debugEnabled;
initialNodeGridOffset;
constructor(t3) {
super(), this.bounds = t3.bounds, this.connMap = t3.connMap, this.hyperParameters = t3.hyperParameters ?? {}, this.CELL_SIZE_FACTOR = this.hyperParameters.CELL_SIZE_FACTOR ?? 1, this.boundsSize = { width: this.bounds.maxX - this.bounds.minX, height: this.bounds.maxY - this.bounds.minY }, this.boundsCenter = { x: (this.bounds.minX + this.bounds.maxX) / 2, y: (this.bounds.minY + this.bounds.maxY) / 2 }, this.connectionName = t3.connectionName, this.rootConnectionName = t3.rootConnectionName, this.regionId = t3.regionId, this.obstacleRoutes = t3.obstacleRoutes, this.A = t3.A, this.B = t3.B, this.viaDiameter = t3.viaDiameter ?? 0.3, this.traceThickness = t3.traceThickness ?? 0.15, this.obstacleMargin = t3.obstacleMargin ?? 0.15, this.layerCount = t3.layerCount ?? 2, this.availableZ = t3.availableZ && t3.availableZ.length > 0 ? [...new Set(t3.availableZ)].sort((t4, e3) => t4 - e3) : Array.from({ length: this.layerCount }, (t4, e3) => e3), this.exploredNodes = new Set, this.straightLineDistance = xe(this.A, this.B), this.futureConnections = t3.futureConnections ?? [], this.NEARBY_SEGMENT_CLEARANCE = t3.nearbySegmentClearance ?? 0.15, this.debugEnabled = t3.captureSearchDebug ?? true, this.MAX_ITERATIONS = 1e4, this.debug_exploredNodesOrdered = [], this.debug_nodesTooCloseToObstacle = new Set, this.debug_nodePathToParentIntersectsObstacle = new Set, this.numRoutes = this.obstacleRoutes.length + this.futureConnections.length, this.buildObstacleIndexes();
const e2 = Math.ceil(5 * (this.numRoutes + 1));
let n2 = this.boundsSize.width / this.cellStep, o2 = this.boundsSize.height / this.cellStep;
for (;n2 * o2 > e2 ** 2 && !(2 * this.cellStep > t3.minDistBetweenEnteringPoints); )
this.cellStep *= 2, n2 = this.boundsSize.width / this.cellStep, o2 = this.boundsSize.height / this.cellStep;
this.cellStep *= this.CELL_SIZE_FACTOR, this.gridMinXIndex = Math.round(this.bounds.minX / this.cellStep) - 1, this.gridMinYIndex = Math.round(this.bounds.minY / this.cellStep) - 1;
const i2 = Math.round(this.bounds.maxX / this.cellStep) + 1, r2 = Math.round(this.bounds.maxY / this.cellStep) + 1;
this.gridWidth = i2 - this.gridMinXIndex + 1, this.gridHeight = r2 - this.gridMinYIndex + 1;
const s2 = Math.abs(this.A.x - this.bounds.minX) < 0.001 && Math.abs(this.B.x - this.bounds.minX) < 0.001 || Math.abs(this.A.x - this.bounds.maxX) < 0.001 && Math.abs(this.B.x - this.bounds.maxX) < 0.001 || Math.abs(this.A.y - this.bounds.minY) < 0.001 && Math.abs(this.B.y - this.bounds.minY) < 0.001 || Math.abs(this.A.y - this.bounds.maxY) < 0.001 && Math.abs(this.B.y - this.bounds.maxY) < 0.001;
this.futureConnections && this.futureConnections.length === 0 && this.obstacleRoutes.length === 0 && !s2 && this.handleSimpleCases();
const a2 = { x: Math.round(t3.A.x / (this.cellStep / 2)) * (this.cellStep / 2), y: Math.round(t3.A.y / (this.cellStep / 2)) * (this.cellStep / 2) };
this.initialNodeGridOffset = { x: a2.x - Math.round(t3.A.x / this.cellStep) * this.cellStep, y: a2.y - Math.round(t3.A.y / this.cellStep) * this.cellStep };
const c2 = { ...t3.A, z: t3.A.z ?? 0, g: 0, h: 0, f: 0, parent: null }, l2 = { ...t3.A, ...a2, z: t3.A.z ?? 0, g: 0, h: 0, f: 0, parent: c2 }, h2 = (Math.abs(l2.x - t3.A.x) > 0.000000001 || Math.abs(l2.y - t3.A.y) > 0.000000001) && (this.isNodeTooCloseToObstacle(l2) || this.isNodeTooCloseToEdge(l2, false) || this.doesPathToParentIntersectObstacle(l2));
this.candidates = new gr([h2 ? c2 : l2]);
}
handleSimpleCases() {
this.solved = true;
const { A: t3, B: e2 } = this, n2 = t3.z === e2.z ? [t3, e2] : [t3, { ...this.boundsCenter, z: this.A.z }, { ...this.boundsCenter, z: e2.z }, e2];
this.solvedPath = { connectionName: this.connectionName, rootConnectionName: this.rootConnectionName, regionId: this.regionId, route: n2, traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, vias: this.A.z === this.B.z ? [] : [this.boundsCenter] };
}
get viaPenaltyDistance() {
return this.cellStep + this.straightLineDistance * this.VIA_PENALTY_FACTOR;
}
isNodeTooCloseToObstacle(t3, e2, n2, o2) {
if (e2 ??= this.obstacleMargin, n2 && t3.parent) {
const n3 = this.getViasInNodePath(t3.parent);
for (const o3 of n3)
if (xe(t3, o3) < this.viaDiameter / 2 + e2)
return true;
}
const i2 = this.traceThickness + e2, r2 = o2?.segments ?? (n2 ? this.obstacleSegments : this.obstacleSegmentsByLayer.get(t3.z)), s2 = o2?.segmentIds ?? (n2 ? this.obstacleSegmentIndex : this.obstacleSegmentIndexByLayer.get(t3.z))?.search(t3.x - i2, t3.y - i2, t3.x + i2, t3.y + i2) ?? [];
if (r2)
for (const e3 of s2) {
const s3 = r2[e3];
if (s3 && !s3.connectedToCurrentConnection && ((n2 || s3.z === t3.z) && (!o2 || !(t3.x + i2 < s3.minX || t3.y + i2 < s3.minY || t3.x - i2 > s3.maxX || t3.y - i2 > s3.maxY)) && be(t3, s3.A, s3.B) < i2))
return true;
}
const a2 = this.viaDiameter / 2 + this.traceThickness / 2 + e2;
if (this.obstacleViaIndex) {
const e3 = this.obstacleViaIndex.search(t3.x - a2, t3.y - a2, t3.x + a2, t3.y + a2);
for (const n3 of e3) {
const e4 = this.obstacleVias[n3];
if (e4 && xe(t3, e4) < a2)
return true;
}
}
return false;
}
isNodeTooCloseToEdge(t3, e2) {
const n2 = e2 ? this.viaDiameter / 2 + this.obstacleMargin / 2 : this.obstacleMargin / 2, o2 = t3.x < this.bounds.minX + n2 || t3.x > this.bounds.maxX - n2 || t3.y < this.bounds.minY + n2 || t3.y > this.bounds.maxY - n2;
return !(o2 && !e2 && (xe(t3, this.B) < 2 * n2 || xe(t3, this.A) < 2 * n2)) && o2;
}
doesPathToParentIntersectObstacle(t3, e2) {
const n2 = t3.parent;
if (!n2)
return false;
const o2 = e2?.segments ?? this.obstacleSegmentsByLayer.get(t3.z);
if (!o2)
return false;
const i2 = t3.z === n2.z && this.obstacleSegments.length > 0 ? this.NEARBY_SEGMENT_CLEARANCE : 0, r2 = Math.min(t3.x, n2.x), s2 = Math.max(t3.x, n2.x), a2 = Math.min(t3.y, n2.y), c2 = Math.max(t3.y, n2.y), l2 = e2?.segmentIds ?? this.obstacleSegmentIndexByLayer.get(t3.z)?.search(r2 - i2, a2 - i2, s2 + i2, c2 + i2) ?? [];
for (const h2 of l2) {
const l3 = o2[h2];
if (l3 && !l3.connectedToCurrentConnection && !(l3.z !== t3.z || e2 && (s2 + i2 < l3.minX || c2 + i2 < l3.minY || r2 - i2 > l3.maxX || a2 - i2 > l3.maxY))) {
if (fe(t3, n2, l3.A, l3.B))
return true;
if (i2 > 0 && xr(t3, n2, l3.A, l3.B) < i2)
return true;
}
}
return false;
}
getPlanarObstacleQuery(t3) {
const e2 = t3.parent;
if (!e2)
return;
const n2 = this.obstacleSegmentIndexByLayer.get(t3.z), o2 = this.obstacleSegmentsByLayer.get(t3.z);
if (!n2 || !o2)
return;
const i2 = this.traceThickness + this.obstacleMargin, r2 = t3.z === e2.z && this.obstacleSegments.length > 0 ? this.NEARBY_SEGMENT_CLEARANCE : 0;
return { segments: o2, segmentIds: n2.search(Math.min(t3.x - i2, e2.x - r2), Math.min(t3.y - i2, e2.y - r2), Math.max(t3.x + i2, e2.x + r2), Math.max(t3.y + i2, e2.y + r2)) };
}
buildObstacleIndexes() {
if (this.obstacleRoutes.length === 0)
return this.obstacleSegmentIndex = null, this.obstacleSegmentsByLayer.clear(), this.obstacleSegmentIndexByLayer.clear(), void (this.obstacleViaIndex = null);
const t3 = [], e2 = [];
for (const n2 of this.obstacleRoutes) {
const o2 = this.connMap?.areIdsConnected?.(this.connectionName, n2.connectionName) ?? false;
for (const e3 of _r(n2))
t3.push({ ...e3, minX: Math.min(e3.A.x, e3.B.x), minY: Math.min(e3.A.y, e3.B.y), maxX: Math.max(e3.A.x, e3.B.x), maxY: Math.max(e3.A.y, e3.B.y), connectedToCurrentConnection: o2 });
for (const t4 of n2.vias)
e2.push(t4);
}
if (this.obstacleSegments = t3, this.obstacleVias = e2, this.obstacleSegmentsByLayer.clear(), this.obstacleSegmentIndexByLayer.clear(), t3.length > 0) {
const e3 = new Ft(t3.length);
for (const n2 of t3)
e3.add(n2.minX, n2.minY, n2.maxX, n2.maxY);
e3.finish(), this.obstacleSegmentIndex = e3;
for (const e4 of t3) {
if (e4.connectedToCurrentConnection)
continue;
const t4 = this.obstacleSegmentsByLayer.get(e4.z);
t4 ? t4.push(e4) : this.obstacleSegmentsByLayer.set(e4.z, [e4]);
}
for (const [t4, e4] of this.obstacleSegmentsByLayer) {
const n2 = new Ft(e4.length);
for (const t5 of e4)
n2.add(t5.minX, t5.minY, t5.maxX, t5.maxY);
n2.finish(), this.obstacleSegmentIndexByLayer.set(t4, n2);
}
} else
this.obstacleSegmentIndex = null;
if (e2.length > 0) {
const t4 = new Ft(e2.length);
for (const n2 of e2)
t4.add(n2.x, n2.y, n2.x, n2.y);
t4.finish(), this.obstacleViaIndex = t4;
} else
this.obstacleViaIndex = null;
}
computeH(t3) {
return xe(t3, this.B) + (t3.z !== this.B.z ? this.viaPenaltyDistance : 0);
}
computeG(t3) {
return (t3.parent?.g ?? 0) + (t3.z === t3.parent?.z ? 0 : this.viaPenaltyDistance) + xe(t3, t3.parent);
}
computeF(t3, e2) {
return t3 + e2 * this.GREEDY_MULTIPLER;
}
setNodeCosts(t3) {
t3.g = this.computeG(t3), t3.h = this.computeH(t3), t3.f = this.computeF(t3.g, t3.h);
}
getNodeKey(t3) {
const e2 = Math.round(t3.x / this.cellStep) - this.gridMinXIndex, n2 = Math.round(t3.y / this.cellStep) - this.gridMinYIndex;
return (t3.z * this.gridHeight + n2) * this.gridWidth + e2;
}
getNeighbors(t3) {
const e2 = [], { maxX: n2, minX: o2, maxY: i2, minY: r2 } = this.bounds;
for (let s2 = -1;s2 <= 1; s2++)
for (let a2 = -1;a2 <= 1; a2++) {
if (s2 === 0 && a2 === 0)
continue;
const c2 = { x: br(t3.x + s2 * this.cellStep, o2, n2), y: br(t3.y + a2 * this.cellStep, r2, i2), z: t3.z, g: t3.g, h: t3.h, f: t3.f, parent: t3 }, l2 = this.getNodeKey(c2);
if (this.exploredNodes.has(l2))
continue;
const h2 = this.getPlanarObstacleQuery(c2);
this.isNodeTooCloseToObstacle(c2, undefined, false, h2) ? (this.debugEnabled && this.debug_nodesTooCloseToObstacle.add(l2), this.exploredNodes.add(l2)) : this.isNodeTooCloseToEdge(c2, false) ? this.exploredNodes.add(l2) : this.doesPathToParentIntersectObstacle(c2, h2) ? (this.debugEnabled && this.debug_nodePathToParentIntersectsObstacle.add(l2), this.exploredNodes.add(l2)) : (this.setNodeCosts(c2), e2.push(c2));
}
for (const n3 of this.availableZ) {
if (n3 === t3.z)
continue;
const o3 = { x: t3.x, y: t3.y, z: n3, g: t3.g, h: t3.h, f: t3.f, parent: t3 };
this.exploredNodes.has(this.getNodeKey(o3)) || this.isNodeTooCloseToObstacle(o3, this.viaDiameter / 2 + this.obstacleMargin / 2, true) || this.isNodeTooCloseToEdge(o3, true) || (this.setNodeCosts(o3), e2.push(o3));
}
return e2;
}
getNodePath(t3) {
const e2 = [];
for (;t3; )
e2.push(t3), t3 = t3.parent;
return e2;
}
getViasInNodePath(t3) {
const e2 = this.viasInPathByNode.get(t3);
if (e2)
return e2;
const n2 = t3.parent, o2 = n2 ? this.getViasInNodePath(n2) : [], i2 = n2 && t3.z !== n2.z ? [{ x: t3.x, y: t3.y }, ...o2] : o2;
return this.viasInPathByNode.set(t3, i2), i2;
}
setSolvedPath(t3) {
const e2 = this.getNodePath(t3);
e2.reverse();
const n2 = [];
for (let t4 = 0;t4 < e2.length - 1; t4++)
e2[t4].z !== e2[t4 + 1].z && n2.push({ x: e2[t4].x, y: e2[t4].y });
this.solvedPath = { connectionName: this.connectionName, rootConnectionName: this.rootConnectionName, regionId: this.regionId, traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, route: e2.map((t4) => ({ x: t4.x, y: t4.y, z: t4.z })).concat([this.B]), vias: n2 };
}
computeProgress(t3, e2, n2) {
if (e2 === undefined || n2 === undefined)
return Number.NaN;
n2 || (e2 += this.viaPenaltyDistance);
const o2 = 1 - e2 / this.straightLineDistance;
return Math.max(this.progress || 0, 2 / Math.PI * Math.atan(0.112 * o2 / (1 - o2)));
}
_step() {
let t3 = this.candidates.dequeue(), e2 = t3 ? this.getNodeKey(t3) : undefined;
for (;t3 && e2 && this.exploredNodes.has(e2); )
t3 = this.candidates.dequeue(), e2 = t3 ? this.getNodeKey(t3) : undefined;
if (!t3 || !e2)
return this.failed = true, void (this.error = "Ran out of candidate nodes to explore");
this.exploredNodes.add(e2), this.debugEnabled && this.debug_exploredNodesOrdered.push({ key: e2, x: Math.round(t3.x / this.cellStep) * this.cellStep + this.initialNodeGridOffset.x, y: Math.round(t3.y / this.cellStep) * this.cellStep + this.initialNodeGridOffset.y, z: t3.z });
const n2 = xe(t3, this.B);
this.progress = this.computeProgress(t3, n2, t3.z === this.B.z), n2 <= this.cellStep * Math.SQRT2 && t3.z === this.B.z && !this.doesPathToParentIntersectObstacle({ ...t3, parent: t3, x: this.B.x, y: this.B.y }) && (this.solved = true, this.setSolvedPath(t3));
const o2 = this.getNeighbors(t3);
for (const t4 of o2)
this.candidates.enqueue(t4);
}
visualize() {
const t3 = { lines: [], points: [], rects: [], circles: [] };
t3.points.push({ x: this.A.x, y: this.A.y, label: fr(this.connectionName, this.rootConnectionName, ["Input A", `z: ${this.A.z}`]), color: "orange" }), t3.points.push({ x: this.B.x, y: this.B.y, label: fr(this.connectionName, this.rootConnectionName, ["Input B", `z: ${this.B.z}`]), color: "orange" }), t3.lines.push({ points: [this.A, this.B], strokeColor: "rgba(255, 0, 0, 0.5)", label: fr(this.connectionName, this.rootConnectionName, ["Direct Input Connection"]) });
for (let e2 = 0;e2 < this.obstacleRoutes.length; e2++) {
const n2 = this.obstacleRoutes[e2];
for (let o2 = 0;o2 < n2.route.length - 1; o2++) {
const i2 = n2.route[o2].z;
t3.lines.push({ points: [n2.route[o2], n2.route[o2 + 1]], strokeColor: i2 === 0 ? "rgba(255, 0, 0, 0.75)" : "rgba(255, 128, 0, 0.25)", strokeWidth: n2.traceThickness, label: fr(n2.connectionName, n2.rootConnectionName, ["Obstacle Route"]), layer: `obstacle${e2.toString()}` });
}
}
for (let e2 = 0;e2 < this.debug_exploredNodesOrdered.length; e2++) {
const { key: n2, x: o2, y: i2, z: r2 } = this.debug_exploredNodesOrdered[e2];
this.debug_nodesTooCloseToObstacle.has(n2) || (this.debug_nodePathToParentIntersectsObstacle.has(n2) || t3.rects.push({ center: { x: o2 + r2 * this.cellStep / 20, y: i2 + r2 * this.cellStep / 20 }, fill: r2 === 0 ? `rgba(255,0,255,${0.3 - e2 / this.debug_exploredNodesOrdered.length * 0.2})` : `rgba(0,0,255,${0.3 - e2 / this.debug_exploredNodesOrdered.length * 0.2})`, width: 0.9 * this.cellStep, height: 0.9 * this.cellStep, label: `Explored (z=${r2})` }));
}
if (this.candidates.peek()) {
const e2 = this.candidates.peek();
t3.rects.push({ center: { x: e2.x + e2.z * this.cellStep / 20, y: e2.y + e2.z * this.cellStep / 20 }, fill: "rgba(0, 255, 0, 0.8)", width: 0.9 * this.cellStep, height: 0.9 * this.cellStep, label: `Next (z=${e2.z})` });
}
for (const e2 of this.obstacleRoutes)
for (const n2 of e2.vias)
t3.circles.push({ center: { x: n2.x, y: n2.y }, radius: this.viaDiameter / 2, fill: "rgba(255, 0, 0, 0.5)", label: "Via" });
if (this.solvedPath) {
t3.lines.push({ points: this.solvedPath.route, strokeColor: "green", label: fr(this.solvedPath.connectionName, this.solvedPath.rootConnectionName, ["Solved Route"]) });
for (const e2 of this.solvedPath.vias)
t3.circles.push({ center: e2, radius: this.viaDiameter / 2, fill: "green", label: fr(this.solvedPath.connectionName, this.solvedPath.rootConnectionName, ["Via"]) });
}
return t3;
}
};
function _r(t3) {
const e2 = [];
for (let n2 = 0;n2 < t3.route.length - 1; n2++)
t3.route[n2].z === t3.route[n2 + 1].z && e2.push({ z: t3.route[n2].z, A: t3.route[n2], B: t3.route[n2 + 1] });
return e2;
}
function br(t3, e2, n2) {
return Math.max(e2, Math.min(t3, n2));
}
function xr(t3, e2, n2, o2) {
return Math.min(be(t3, n2, o2), be(e2, n2, o2), be(n2, t3, e2), be(o2, t3, e2));
}
var vr = class extends yr {
FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR = 2;
FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR = 1;
FUTURE_CONNECTION_PROXIMITY_VD = 10;
MISALIGNED_DIST_PENALTY_FACTOR = 5;
VIA_PENALTY_FACTOR_2 = 1;
FLIP_TRACE_ALIGNMENT_DIRECTION = false;
FUTURE_CONNECTION_VIA_TRACE_CLEARANCE = 0.1;
futureConnectionPoints;
futureConnectionSegmentsCache = null;
constructor(t3) {
super({ ...t3, nearbySegmentClearance: t3.nearbySegmentClearance ?? (t3.traceThickness ?? 0.15) / 2 + (t3.obstacleMargin ?? 0.15) });
for (const e3 in t3.hyperParameters)
this[e3] = t3.hyperParameters[e3];
const e2 = this.boundsSize.width / this.viaDiameter, n2 = Math.max(1, this.numRoutes);
this.VIA_PENALTY_FACTOR = e2 / n2 * 0.3 * this.VIA_PENALTY_FACTOR_2, this.futureConnectionPoints = this.futureConnections.flatMap((t4) => t4.points);
}
getClosestFutureConnectionPoint(t3) {
let e2 = 1 / 0, n2 = null;
for (const o2 of this.futureConnectionPoints) {
const i2 = xe(t3, o2) + (t3.z !== o2.z ? this.viaPenaltyDistance : 0);
i2 < e2 && (e2 = i2, n2 = o2);
}
return n2;
}
getFutureConnectionSegments() {
if (this.futureConnectionSegmentsCache)
return this.futureConnectionSegmentsCache;
const t3 = [];
for (const e2 of this.futureConnections) {
if (e2.connectionName === this.connectionName || (this.connMap?.areIdsConnected?.(this.connectionName, e2.connectionName) ?? false))
continue;
const [n2, ...o2] = e2.points;
if (n2)
for (const i2 of o2)
Math.abs(n2.x - i2.x) < 0.000000001 && Math.abs(n2.y - i2.y) < 0.000000001 || t3.push({ connectionName: e2.connectionName, start: n2, end: i2 });
}
return this.futureConnectionSegmentsCache = t3, t3;
}
isViaTooCloseToFutureConnectionTrace(t3) {
const e2 = this.viaDiameter / 2 + this.traceThickness / 2 + this.FUTURE_CONNECTION_VIA_TRACE_CLEARANCE;
for (const n2 of this.getFutureConnectionSegments())
if (be(t3, n2.start, n2.end) < e2)
return true;
return false;
}
isNodeTooCloseToObstacle(t3, e2, n2, o2) {
return !!super.isNodeTooCloseToObstacle(t3, e2, n2, o2) || !(!n2 || !this.isViaTooCloseToFutureConnectionTrace(t3));
}
diminishCloseToGoal(t3) {
const e2 = xe(t3, this.B);
return 1 - Math.exp(-e2 / this.straightLineDistance * 5);
}
getFutureConnectionPenalty(t3, e2) {
let n2 = 0;
const o2 = this.getClosestFutureConnectionPoint(t3), i2 = xe(t3, this.B);
if (o2) {
const r2 = xe(t3, o2);
if (i2 <= r2)
return 0;
const s2 = r2 / (this.viaDiameter * this.FUTURE_CONNECTION_PROXIMITY_VD);
n2 = (e2 ? this.straightLineDistance * this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR : this.straightLineDistance * this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR) * Math.exp(5 * -s2);
}
return n2;
}
computeH(t3) {
const e2 = xe(t3, this.B) ** 1.6;
this.straightLineDistance;
return e2 + (t3.z !== this.B.z ? this.viaPenaltyDistance : 0) + this.getFutureConnectionPenalty(t3, t3.z !== t3.parent?.z);
}
computeG(t3) {
const e2 = Math.abs(t3.x - t3.parent.x), n2 = Math.abs(t3.y - t3.parent.y), o2 = Math.sqrt(e2 ** 2 + n2 ** 2), i2 = t3.z % 2 == 0, r2 = this.FLIP_TRACE_ALIGNMENT_DIRECTION ? i2 ? e2 : n2 : i2 ? n2 : e2;
return (t3.parent?.g ?? 0) + (t3.z === t3.parent?.z ? 0 : this.viaPenaltyDistance) + o2 + r2 * this.MISALIGNED_DIST_PENALTY_FACTOR + this.getFutureConnectionPenalty(t3, t3.z !== t3.parent?.z);
}
setNodeCosts(t3) {
const e2 = Math.abs(t3.x - t3.parent.x), n2 = Math.abs(t3.y - t3.parent.y), o2 = Math.sqrt(e2 ** 2 + n2 ** 2), i2 = t3.z % 2 == 0, r2 = this.FLIP_TRACE_ALIGNMENT_DIRECTION ? i2 ? e2 : n2 : i2 ? n2 : e2, s2 = (t3.parent?.g ?? 0) + (t3.z === t3.parent?.z ? 0 : this.viaPenaltyDistance) + o2 + r2 * this.MISALIGNED_DIST_PENALTY_FACTOR, a2 = xe(t3, this.B) ** 1.6 + (t3.z !== this.B.z ? this.viaPenaltyDistance : 0), c2 = this.getFutureConnectionPenalty(t3, t3.z !== t3.parent?.z);
t3.g = s2 + c2, t3.h = a2 + c2, t3.f = this.computeF(t3.g, t3.h);
}
};
var Ir = (t3, e2, n2 = []) => [t3, e2 ? `rootConnectionName: ${e2}` : undefined, ...n2].filter(Boolean).join(`
`);
var Sr = (t3) => `${t3.x.toFixed(6)},${t3.y.toFixed(6)},${t3.z}`;
var Cr = (t3) => {
const e2 = new Set, n2 = [];
for (const o2 of t3) {
const t4 = Sr(o2);
e2.has(t4) || (e2.add(t4), n2.push(o2));
}
return n2;
};
var Pr = class extends si {
getSolverName() {
return "IntraNodeRouteSolver";
}
nodeWithPortPoints;
colorMap;
unsolvedConnections;
originalConnectionPointsByName;
rootConnectionNameByConnectionName;
totalConnections;
solvedRoutes;
failedSubSolvers;
hyperParameters;
minDistBetweenEnteringPoints;
viaDiameter;
traceWidth;
obstacleMargin;
captureSearchDebug;
rerouteAttemptsByConnection;
POSTROUTE_VIA_TRACE_CLEARANCE = 0.1;
MAX_POSTROUTE_REPAIR_ATTEMPTS = 2;
activeSubSolver = null;
connMap;
get failedSolvers() {
return this.failedSubSolvers;
}
get activeSolver() {
return this.activeSubSolver;
}
constructor(t3) {
const { nodeWithPortPoints: e2, colorMap: n2 } = t3;
super(), this.nodeWithPortPoints = e2, this.colorMap = n2 ?? {}, this.solvedRoutes = [], this.hyperParameters = t3.hyperParameters ?? {}, this.failedSubSolvers = [], this.connMap = t3.connMap, this.viaDiameter = t3.viaDiameter ?? 0.3, this.traceWidth = t3.traceWidth ?? 0.15, this.obstacleMargin = t3.obstacleMargin ?? 0.15, this.captureSearchDebug = t3.captureSearchDebug ?? true;
const o2 = new Map;
this.rootConnectionNameByConnectionName = new Map;
for (const { connectionName: t4, rootConnectionName: n3, x: i2, y: r2, z: s2 } of e2.portPoints)
n3 && this.rootConnectionNameByConnectionName.set(t4, n3), o2.set(t4, [...o2.get(t4) ?? [], { x: i2, y: r2, z: s2 ?? 0 }]);
this.originalConnectionPointsByName = new Map(Array.from(o2.entries()).map(([t4, e3]) => [t4, Cr(e3)])), this.unsolvedConnections = Array.from(o2.entries().map(([t4, e3]) => ({ connectionName: t4, rootConnectionName: this.rootConnectionNameByConnectionName.get(t4), points: Cr(e3) }))), this.rerouteAttemptsByConnection = new Map, this.hyperParameters.SHUFFLE_SEED && (this.unsolvedConnections = pr(this.unsolvedConnections, this.hyperParameters.SHUFFLE_SEED ?? 0), this.unsolvedConnections = this.unsolvedConnections.map(({ points: t4, ...e3 }, n3) => ({ ...e3, points: pr(t4, 7117 * n3 + (this.hyperParameters.SHUFFLE_SEED ?? 0)) }))), this.totalConnections = this.unsolvedConnections.length, this.MAX_ITERATIONS = 1000 * this.totalConnections ** 1.5, this.minDistBetweenEnteringPoints = mr(this.nodeWithPortPoints);
}
computeProgress() {
return (this.solvedRoutes.length + (this.activeSubSolver?.progress || 0)) / this.totalConnections;
}
getSingleRouteSolverOpts(t3) {
const { connectionName: e2, rootConnectionName: n2, points: o2 } = t3;
return { connectionName: e2, rootConnectionName: n2, regionId: this.nodeWithPortPoints.capacityMeshNodeId, minDistBetweenEnteringPoints: this.minDistBetweenEnteringPoints, bounds: ro(this.nodeWithPortPoints), A: { x: o2[0].x, y: o2[0].y, z: o2[0].z }, B: { x: o2[o2.length - 1].x, y: o2[o2.length - 1].y, z: o2[o2.length - 1].z }, obstacleRoutes: this.connMap ? this.solvedRoutes.filter((t4) => !this.connMap.areIdsConnected(t4.connectionName, e2)) : this.solvedRoutes, futureConnections: this.unsolvedConnections, layerCount: this.nodeWithPortPoints.portPoints.reduce((t4, e3) => Math.max(t4, (e3.z ?? 0) + 1), 2), availableZ: this.nodeWithPortPoints.availableZ && this.nodeWithPortPoints.availableZ.length > 0 ? this.nodeWithPortPoints.availableZ : [...new Set(this.nodeWithPortPoints.portPoints.map((t4) => t4.z ?? 0))].sort((t4, e3) => t4 - e3), hyperParameters: this.hyperParameters, connMap: this.connMap, viaDiameter: this.viaDiameter, traceThickness: this.traceWidth, obstacleMargin: this.obstacleMargin, captureSearchDebug: this.captureSearchDebug };
}
trySolveSamePointLayerChange(t3) {
const e2 = this.getSingleRouteSolverOpts(t3), n2 = new vr(e2), { A: o2, B: i2 } = e2, r2 = { x: o2.x, y: o2.y };
if (!Mr(n2, r2, o2))
return false;
const s2 = [{ x: o2.x, y: o2.y, z: o2.z }, { ...r2, z: o2.z }, { ...r2, z: i2.z }, { x: i2.x, y: i2.y, z: i2.z }].filter((t4, e3, n3) => e3 === 0 || Math.abs(t4.x - n3[e3 - 1].x) > 0.000001 || Math.abs(t4.y - n3[e3 - 1].y) > 0.000001 || t4.z !== n3[e3 - 1].z);
return this.solvedRoutes.push({ connectionName: t3.connectionName, rootConnectionName: t3.rootConnectionName, regionId: this.nodeWithPortPoints.capacityMeshNodeId, traceThickness: this.traceWidth, viaDiameter: this.viaDiameter, route: s2, vias: [{ x: r2.x, y: r2.y }] }), true;
}
queueExtraBranchesForMultiPointConnection(t3) {
const [e2, ...n2] = Cr(t3.points);
if (!e2 || n2.length <= 1)
return false;
for (const o2 of n2)
this.unsolvedConnections.push({ connectionName: t3.connectionName, rootConnectionName: t3.rootConnectionName, points: [e2, o2] });
return true;
}
getAvailableZLayers() {
return this.nodeWithPortPoints.availableZ && this.nodeWithPortPoints.availableZ.length > 0 ? [...new Set(this.nodeWithPortPoints.availableZ)].sort((t3, e2) => t3 - e2) : [...new Set(this.nodeWithPortPoints.portPoints.map((t3) => t3.z ?? 0))].sort((t3, e2) => t3 - e2);
}
getFirstSolvedViaTraceConflict() {
if (this.solvedRoutes.length < 2)
return null;
const t3 = new hr(this.solvedRoutes), e2 = this.getAvailableZLayers();
for (const n2 of this.solvedRoutes) {
const o2 = n2.viaDiameter / 2 + this.POSTROUTE_VIA_TRACE_CLEARANCE;
for (const i2 of n2.vias)
for (const r2 of e2) {
const e3 = t3.getConflictingRoutesNearPoint({ x: i2.x, y: i2.y, z: r2 }, o2).filter(({ conflictingRoute: t4 }) => t4.connectionName !== n2.connectionName && !this.connMap?.areIdsConnected(n2.connectionName, t4.connectionName));
if (e3.length > 0)
return { route: n2, via: i2, conflictingRoute: e3[0].conflictingRoute };
}
}
return null;
}
queueConnectionForPostrouteRepair(t3) {
const e2 = this.originalConnectionPointsByName.get(t3);
return !(!e2 || e2.length < 2) && (this.solvedRoutes = this.solvedRoutes.filter((e3) => e3.connectionName !== t3), this.unsolvedConnections.push({ connectionName: t3, rootConnectionName: this.rootConnectionNameByConnectionName.get(t3), points: e2.map((t4) => ({ ...t4 })) }), this.rerouteAttemptsByConnection.set(t3, (this.rerouteAttemptsByConnection.get(t3) ?? 0) + 1), true);
}
_step() {
if (this.activeSubSolver)
return this.activeSubSolver.step(), this.progress = this.computeProgress(), void (this.activeSubSolver.solved ? (this.solvedRoutes.push(this.activeSubSolver.solvedPath), this.activeSubSolver = null) : this.activeSubSolver.failed && (this.failedSubSolvers.push(this.activeSubSolver), this.activeSubSolver = null, this.error = this.failedSubSolvers.map((t4) => t4.error).join(`
`), this.failed = true));
const t3 = this.unsolvedConnections.pop();
if (this.progress = this.computeProgress(), !t3) {
const t4 = this.getFirstSolvedViaTraceConflict();
if (t4) {
if ((this.rerouteAttemptsByConnection.get(t4.route.connectionName) ?? 0) >= this.MAX_POSTROUTE_REPAIR_ATTEMPTS)
return this.error = ["Post-route via/trace clearance repair exceeded retry budget", `route: ${t4.route.connectionName}`, `conflicts with: ${t4.conflictingRoute.connectionName}`, `via: (${t4.via.x.toFixed(3)}, ${t4.via.y.toFixed(3)})`].join(`
`), void (this.failed = true);
if (this.queueConnectionForPostrouteRepair(t4.route.connectionName))
return void (this.progress = this.computeProgress());
}
return void (this.solved = this.failedSubSolvers.length === 0);
}
if (t3.points.length !== 1 && !(t3.points.length > 2 && this.queueExtraBranchesForMultiPointConnection(t3))) {
if (t3.points.length === 2) {
const [e2, n2] = t3.points, o2 = Math.abs(e2.x - n2.x) < 0.000001, i2 = Math.abs(e2.y - n2.y) < 0.000001;
if (o2 && i2 && e2.z === n2.z)
return;
if (o2 && i2 && e2.z !== n2.z && this.trySolveSamePointLayerChange(t3))
return;
}
this.activeSubSolver = new vr(this.getSingleRouteSolverOpts(t3));
}
}
visualize() {
const t3 = { lines: [], points: [], rects: [], circles: [] };
for (const e3 of this.nodeWithPortPoints.portPoints)
t3.points.push({ x: e3.x, y: e3.y, label: Ir(e3.connectionName, e3.rootConnectionName, [`layer: ${e3.z}`]), color: this.colorMap[e3.connectionName] ?? "blue" });
for (let e3 = 0;e3 < this.solvedRoutes.length; e3++) {
const n3 = this.solvedRoutes[e3];
if (n3.route.length > 0) {
const o3 = this.colorMap[n3.connectionName] ?? "blue", i3 = n3.rootConnectionName ?? this.rootConnectionNameByConnectionName.get(n3.connectionName);
for (let r3 = 0;r3 < n3.route.length - 1; r3++) {
const s2 = n3.route[r3], a2 = n3.route[r3 + 1];
t3.lines.push({ points: [s2, a2], label: Ir(n3.connectionName, i3, [`layer: ${s2.z}`]), strokeColor: s2.z === 0 ? Ao(o3, 0.2) : Ao(o3, 0.8), layer: `route-layer-${s2.z}`, step: e3, strokeWidth: n3.traceThickness });
}
for (const r3 of n3.vias)
t3.circles.push({ center: { x: r3.x, y: r3.y }, radius: n3.viaDiameter / 2, fill: Ao(o3, 0.5), layer: "via", step: e3, label: Ir(n3.connectionName, i3, ["via"]) });
}
}
const e2 = ro(this.nodeWithPortPoints), { minX: n2, minY: o2, maxX: i2, maxY: r2 } = e2;
return t3.lines.push({ points: [{ x: n2, y: o2 }, { x: i2, y: o2 }, { x: i2, y: r2 }, { x: n2, y: r2 }, { x: n2, y: o2 }], strokeColor: "rgba(255, 0, 0, 0.25)", strokeDash: "4 4", layer: "border" }), t3;
}
};
var Mr = (t3, e2, n2, o2) => {
const i2 = { x: e2.x, y: e2.y, z: n2.z, parent: { x: n2.x, y: n2.y, z: n2.z, g: 0, h: 0, f: 0, parent: null }, g: 0, h: 0, f: 0 };
return !t3.isNodeTooCloseToObstacle(i2, t3.viaDiameter / 2 + t3.obstacleMargin / 2, true) && !t3.isNodeTooCloseToEdge(i2, true);
};
var Nr = (t3) => Math.round(200 * t3) / 200;
var wr = (t3) => typeof structuredClone == "function" ? structuredClone(t3) : JSON.parse(JSON.stringify(t3));
io();
var Tr = class extends Pr {
getSolverName() {
return "CachedIntraNodeRouteSolver";
}
cacheProvider;
cacheHit = false;
hasAttemptedToUseCache = false;
initialUnsolvedConnections;
constructor(t3) {
super(t3), this.cacheProvider = t3.cacheProvider === undefined ? oo() : t3.cacheProvider, this.initialUnsolvedConnections = wr(this.unsolvedConnections), (this.solved || this.failed) && this.cacheProvider && !this.cacheHit && this.saveToCacheSync();
}
_step() {
if (!this.hasAttemptedToUseCache && this.cacheProvider && this.attemptToUseCacheSync())
return;
const t3 = this.solved, e2 = this.failed;
super._step(), !this.cacheProvider || this.cacheHit || !this.solved && !this.failed || t3 || e2 || this.saveToCacheSync();
}
computeCacheKeyAndTransform() {
const t3 = this.nodeWithPortPoints.center, e2 = this.initialUnsolvedConnections.map(({ connectionName: e3, rootConnectionName: n3, points: o3 }) => ({ connectionName: e3, rootConnectionName: n3, points: o3.map((n4) => ({ connectionName: e3, x: Nr(n4.x - t3.x), y: Nr(n4.y - t3.y), z: n4.z ?? 0 })) })), n2 = [...this.nodeWithPortPoints.portPoints].sort((t4, e3) => t4.connectionName !== e3.connectionName ? t4.connectionName.localeCompare(e3.connectionName) : (t4.portPointId ?? "") !== (e3.portPointId ?? "") ? (t4.portPointId ?? "").localeCompare(e3.portPointId ?? "") : t4.x !== e3.x ? t4.x - e3.x : t4.y !== e3.y ? t4.y - e3.y : (t4.z ?? 0) - (e3.z ?? 0)).map((e3) => ({ connectionName: e3.connectionName, rootConnectionName: e3.rootConnectionName, portPointId: e3.portPointId, prevPortPointId: e3.prevPortPointId, nextPortPointId: e3.nextPortPointId, x: Nr(e3.x - t3.x), y: Nr(e3.y - t3.y), z: e3.z ?? 0 })), o2 = Object.fromEntries(Object.entries(this.hyperParameters ?? {}).filter(([, t4]) => t4 !== undefined).sort(([t4], [e3]) => t4.localeCompare(e3))), i2 = this.connMap ? this.initialUnsolvedConnections.map(({ connectionName: t4 }) => ({ connectionName: t4, connectedIds: [...new Set(this.connMap.getIdsConnectedToNet(t4) ?? [])].sort() })) : undefined, r2 = { cacheSchemaVersion: 4, node: { width: Nr(this.nodeWithPortPoints.width), height: Nr(this.nodeWithPortPoints.height), center: { x: Nr(this.nodeWithPortPoints.center.x), y: Nr(this.nodeWithPortPoints.center.y) }, availableZ: this.nodeWithPortPoints.availableZ ? [...this.nodeWithPortPoints.availableZ].sort() : undefined, portPoints: n2 }, normalizedConnections: e2, normalizedHyperParameters: o2, minDistBetweenEnteringPoints: Nr(this.minDistBetweenEnteringPoints), traceWidth: Nr(this.traceWidth), viaDiameter: Nr(this.viaDiameter), obstacleMargin: Nr(this.obstacleMargin), normalizedConnMap: i2 }, s2 = `intranode-solver:${import_object_hash.default(r2, { respectType: false, unorderedObjects: false })}`, a2 = {};
return this.cacheKey = s2, this.cacheToSolveSpaceTransform = a2, { cacheKey: s2, cacheToSolveSpaceTransform: a2 };
}
applyCachedSolution(t3) {
t3.success ? (this.solvedRoutes = wr(t3.solvedRoutes), this.solved = true, this.failed = false) : (this.solvedRoutes = [], this.failedSubSolvers = [], this.solved = false, this.failed = true, this.error = t3.error ?? this.error), this.unsolvedConnections = [], this.activeSubSolver = null, this.cacheHit = true, this.progress = 1;
}
attemptToUseCacheSync() {
if (this.hasAttemptedToUseCache = true, !this.cacheProvider?.isSyncCache)
return false;
if (!this.cacheKey)
try {
this.computeCacheKeyAndTransform();
} catch (t3) {
return console.error("Error computing cache key:", t3), false;
}
if (!this.cacheKey)
return console.error("Failed to compute cache key."), false;
try {
const t3 = this.cacheProvider.getCachedSolutionSync(this.cacheKey);
if (t3 != null)
return this.applyCachedSolution(t3), true;
} catch (t3) {
console.error("Error attempting to use cache:", t3);
}
return false;
}
saveToCacheSync() {
if (!this.cacheProvider?.isSyncCache)
return;
if (!this.cacheKey)
try {
this.computeCacheKeyAndTransform();
} catch (t4) {
return void console.error("Error computing cache key during save:", t4);
}
if (!this.cacheKey)
return void console.error("Failed to compute cache key before saving.");
const t3 = this.failed ? { success: false, error: this.error ?? undefined } : { success: true, solvedRoutes: wr(this.solvedRoutes) };
try {
this.cacheProvider.setCachedSolutionSync(this.cacheKey, t3);
} catch (t4) {
console.error("Error saving solution to cache:", t4);
}
}
};
var Rr = (t3, e2) => {
const n2 = {};
return t3.portPoints.forEach((e3, o2) => {
n2[e3.connectionName] = `hsl(${360 * o2 / t3.portPoints.length}, 100%, 50%)`;
}), n2;
};
var Er = class extends si {
getSolverName() {
return "ViaPossibilitiesSolver2";
}
bounds;
maxViaCount;
portPairMap;
colorMap;
nodeWidth;
availableZ;
hyperParameters;
VIA_INTERSECTION_BUFFER_DISTANCE = 0.05;
PLACEHOLDER_WALL_BUFFER_DISTANCE = 0.1;
NEW_HEAD_WALL_BUFFER_DISTANCE = 0.05;
viaDiameter;
unprocessedConnections;
completedPaths = new Map;
placeholderPaths = new Map;
currentHead;
currentConnectionName;
currentPath;
currentViaCount;
constructor({ nodeWithPortPoints: t3, colorMap: e2, hyperParameters: n2, viaDiameter: o2 }) {
super(), this.MAX_ITERATIONS = 1e5, this.colorMap = e2 ?? Rr(t3), this.maxViaCount = 5, this.bounds = ro(t3), this.nodeWidth = this.bounds.maxX - this.bounds.minX, this.portPairMap = ((t4) => {
const e3 = new Map;
return t4.portPoints.forEach((t5) => {
e3.has(t5.connectionName) ? e3.get(t5.connectionName).end = t5 : e3.set(t5.connectionName, { start: t5, end: null, connectionName: t5.connectionName });
}), e3;
})(t3), this.stats.solutionsFound = 0, this.availableZ = t3.availableZ ?? [0, 1], this.hyperParameters = n2 ?? { SHUFFLE_SEED: 0 }, this.viaDiameter = o2 ?? 0.3, this.unprocessedConnections = Array.from(this.portPairMap.keys()).sort(), n2?.SHUFFLE_SEED && (this.unprocessedConnections = pr(this.unprocessedConnections, n2.SHUFFLE_SEED));
for (const [t4, { start: e3, end: n3 }] of this.portPairMap.entries())
if (e3.z === n3.z) {
const o3 = Math.abs(e3.x - n3.x) < 0.000000001, i3 = Math.abs(e3.y - n3.y) < 0.000000001;
o3 || i3 ? this.placeholderPaths.set(t4, [e3, this._padByPlaceholderWallBuffer(e3), this._padByPlaceholderWallBuffer(n3), n3]) : this.placeholderPaths.set(t4, [e3, n3]);
} else {
const o3 = (e3.x + n3.x) / 2, i3 = (e3.y + n3.y) / 2, r2 = this._padByPlaceholderWallBuffer({ x: o3, y: i3, z: e3.z }), s2 = this._padByPlaceholderWallBuffer({ x: o3, y: i3, z: n3.z });
this.placeholderPaths.set(t4, [e3, this._padByPlaceholderWallBuffer(e3), r2, s2, this._padByPlaceholderWallBuffer(n3), n3]);
}
this.currentConnectionName = this.unprocessedConnections.pop();
const i2 = this.portPairMap.get(this.currentConnectionName).start;
this.currentHead = this._padByNewHeadWallBuffer(i2), this.currentPath = [i2, this.currentHead], this.currentViaCount = 0, this.placeholderPaths.delete(this.currentConnectionName);
}
_padByNewHeadWallBuffer(t3) {
return { x: Ae(t3.x, this.bounds.minX + this.NEW_HEAD_WALL_BUFFER_DISTANCE, this.bounds.maxX - this.NEW_HEAD_WALL_BUFFER_DISTANCE), y: Ae(t3.y, this.bounds.minY + this.NEW_HEAD_WALL_BUFFER_DISTANCE, this.bounds.maxY - this.NEW_HEAD_WALL_BUFFER_DISTANCE), z: t3.z };
}
_padByPlaceholderWallBuffer(t3) {
return { x: Ae(t3.x, this.bounds.minX + this.PLACEHOLDER_WALL_BUFFER_DISTANCE, this.bounds.maxX - this.PLACEHOLDER_WALL_BUFFER_DISTANCE), y: Ae(t3.y, this.bounds.minY + this.PLACEHOLDER_WALL_BUFFER_DISTANCE, this.bounds.maxY - this.PLACEHOLDER_WALL_BUFFER_DISTANCE), z: t3.z };
}
_step() {
if (this.solved)
return;
const t3 = this.portPairMap.get(this.currentConnectionName).end, e2 = [this.currentHead, t3];
let n2 = null, o2 = null;
const i2 = (t4) => {
for (const i3 of t4.values())
for (let t5 = 0;t5 < i3.length - 1; t5++) {
const r3 = [i3[t5], i3[t5 + 1]];
if (r3[0].x === r3[1].x && r3[0].y === r3[1].y)
continue;
if (r3[0].z !== this.currentHead.z)
continue;
const s2 = ve(e2[0], e2[1], r3[0], r3[1]);
if (s2) {
const t6 = xe(this.currentHead, s2);
if (t6 < 0.000001)
continue;
(!n2 || t6 < n2.dist) && (n2 = { point: s2, dist: t6 }, o2 = r3[0].z);
}
}
};
i2(this.completedPaths), i2(this.placeholderPaths);
const r2 = this.currentHead.z !== t3.z;
if ((n2 || r2) && (this.currentViaCount++, this.currentViaCount >= this.maxViaCount))
return this.failed = true, void (this.error = `Exceeded max via count of ${this.maxViaCount}`);
if (n2) {
let t4;
const e3 = n2.dist;
if (e3 <= this.VIA_INTERSECTION_BUFFER_DISTANCE + 0.000001)
t4 = $e(this.currentHead, n2.point);
else {
const o3 = n2.point, i4 = o3.x - this.currentHead.x, r4 = o3.y - this.currentHead.y, s3 = (e3 - this.VIA_INTERSECTION_BUFFER_DISTANCE) / e3;
t4 = { x: this.currentHead.x + i4 * s3, y: this.currentHead.y + r4 * s3 };
}
const i3 = this.availableZ.find((t5) => t5 !== o2);
if (i3 === undefined)
return this.error = "Could not determine next Z level for via placement!", void (this.failed = true);
const r3 = { ...t4, z: this.currentHead.z }, s2 = { ...t4, z: i3 };
this.currentPath.push(r3, s2), this.currentHead = s2;
} else if (r2) {
let e3;
const n3 = xe(this.currentHead, t3);
if (n3 < this.VIA_INTERSECTION_BUFFER_DISTANCE)
e3 = $e(this.currentHead, t3);
else {
const o4 = t3.x - this.currentHead.x, i4 = t3.y - this.currentHead.y, r4 = (n3 - this.VIA_INTERSECTION_BUFFER_DISTANCE) / n3;
e3 = { x: this.currentHead.x + o4 * r4, y: this.currentHead.y + i4 * r4 };
}
const o3 = t3.z, i3 = { ...e3, z: this.currentHead.z }, r3 = { ...e3, z: o3 };
this.currentPath.push(i3, r3), this.currentHead = r3;
} else if (this.currentPath.push(t3), this.completedPaths.set(this.currentConnectionName, this.currentPath), this.unprocessedConnections.length === 0)
this.solved = true, this.stats.solutionsFound = 1;
else {
this.currentConnectionName = this.unprocessedConnections.pop();
const { start: t4 } = this.portPairMap.get(this.currentConnectionName);
this.currentHead = this._padByNewHeadWallBuffer(t4), this.currentPath = [t4, this.currentHead], this.currentViaCount = 0, this.placeholderPaths.delete(this.currentConnectionName);
}
}
visualize() {
const t3 = { points: [], lines: [], circles: [], rects: [], title: "Via Possibilities Solver State", coordinateSystem: "cartesian" }, e2 = this.colorMap;
t3.lines.push({ points: [{ x: this.bounds.minX, y: this.bounds.minY }, { x: this.bounds.maxX, y: this.bounds.minY }, { x: this.bounds.maxX, y: this.bounds.maxY }, { x: this.bounds.minX, y: this.bounds.maxY }, { x: this.bounds.minX, y: this.bounds.minY }], strokeColor: "gray", strokeWidth: 0.01 });
for (const [e3, { start: n3, end: o2 }] of this.portPairMap.entries()) {
const i2 = this.colorMap[e3] ?? "black";
t3.points.push({ x: n3.x, y: n3.y, color: i2, label: `Port: ${e3} Start (z${n3.z})` }), t3.points.push({ x: o2.x, y: o2.y, color: i2, label: `Port: ${e3} End (z${o2.z})` });
}
const n2 = (n3, o2) => {
for (const [i2, r2] of n3.entries()) {
const n4 = e2[i2] ?? "black";
for (let e3 = 0;e3 < r2.length - 1; e3++) {
const s2 = r2[e3], a2 = r2[e3 + 1];
s2.x === a2.x && s2.y === a2.y && s2.z !== a2.z ? t3.circles.push({ center: { x: s2.x, y: s2.y }, radius: this.viaDiameter / 2, fill: Ao(n4, 0.5), label: `${o2}: ${i2} Via (z${s2.z}->z${a2.z})` }) : t3.lines.push({ points: [s2, a2], strokeColor: Ao(n4, 0.5), strokeDash: s2.z === 0 ? undefined : [0.1, 0.1], strokeWidth: 0.1, label: `${o2}: ${i2} (z${s2.z})` });
}
}
};
if (n2(this.placeholderPaths, "Placeholder"), n2(this.completedPaths, "Completed"), this.currentPath && this.currentPath.length > 0) {
const n3 = e2[this.currentConnectionName] ?? "orange";
for (let e3 = 0;e3 < this.currentPath.length - 1; e3++) {
const o2 = this.currentPath[e3], i2 = this.currentPath[e3 + 1];
o2.x === i2.x && o2.y === i2.y && o2.z !== i2.z ? t3.circles.push({ center: { x: o2.x, y: o2.y }, radius: this.viaDiameter / 2, fill: Ao(n3, 0.5), label: `Current: ${this.currentConnectionName} Via (z${o2.z}->z${i2.z})` }) : t3.lines.push({ points: [o2, i2], strokeColor: Ao(n3, 0.5), strokeWidth: 0.15, strokeDash: "2,2", label: `Current: ${this.currentConnectionName} (z${o2.z})` });
}
t3.points.push({ x: this.currentHead.x, y: this.currentHead.y, color: "green", label: `Current Head: ${this.currentConnectionName} (z${this.currentHead.z})` });
}
return t3;
}
};
var Ar = (t3) => Math.round(1e4 * t3);
var Or = (t3) => {
let e2 = 0, n2 = [];
const o2 = [];
for (const e3 of t3.portPoints) {
if (n2.some((t4) => t4.connectionName === e3.connectionName))
continue;
if (o2.some((t4) => t4.connectionName === e3.connectionName))
continue;
const i3 = { connectionName: e3.connectionName, z: e3.z, points: [{ x: Ar(e3.x), y: Ar(e3.y), z: e3.z }] };
for (const n3 of t3.portPoints)
e3.connectionName === n3.connectionName && (e3.x === n3.x && e3.y === n3.y || i3.points.push({ x: Ar(n3.x), y: Ar(n3.y), z: n3.z }));
i3.points.some((t4) => t4.z !== i3.z) ? o2.push(i3) : n2.push(i3);
}
n2 = n2.filter((t4) => t4.points.length > 1);
for (let t4 = 0;t4 < n2.length; t4++)
for (let o3 = t4 + 1;o3 < n2.length; o3++) {
const i3 = n2[t4], r2 = n2[o3];
i3.z === r2.z && fe(i3.points[0], i3.points[1], r2.points[0], r2.points[1]) && e2++;
}
let i2 = 0;
for (let t4 = 0;t4 < o2.length; t4++)
for (let e3 = t4 + 1;e3 < o2.length; e3++) {
const n3 = o2[t4], r2 = o2[e3];
fe(n3.points[0], n3.points[1], r2.points[0], r2.points[1]) && i2++;
}
return { numSameLayerCrossings: e2, numEntryExitLayerChanges: o2.length, numTransitionPairCrossings: i2 };
};
var kr = (t3) => {
const { start: e2, end: n2, segmentsPerPolyline: o2, viaPositions: i2, viaCount: r2, availableZ: s2 } = t3, a2 = function(t4, e3) {
const n3 = new Array(t4).fill(0);
if (e3 === 0)
return n3;
if (e3 === t4)
return n3.fill(1);
if (e3 <= t4 / 2) {
const o3 = Math.floor(t4 / e3), i3 = Math.floor((t4 - (o3 * (e3 - 1) + 1)) / 2);
for (let t5 = 0;t5 < e3; t5++)
n3[i3 + t5 * o3] = 1;
} else {
const o3 = t4 - e3, i3 = Math.floor(t4 / o3), r3 = Math.floor((t4 - (i3 * (o3 - 1) + 1)) / 2);
n3.fill(1);
for (let t5 = 0;t5 < o3; t5++)
n3[r3 + t5 * i3] = 0;
}
return n3;
}(o2, r2), c2 = a2.map(() => null);
let l2 = 0, h2 = e2.z1;
const d2 = s2.indexOf(e2.z1);
for (let t4 = 0;t4 < a2.length; t4++)
if (a2[t4] === 1) {
const e3 = s2[(d2 + l2 + 1) % s2.length];
c2[t4] = { ...i2[l2], z1: h2, z2: e3 }, h2 = e3, l2++;
}
let u2 = e2;
for (let t4 = 0;t4 < c2.length; t4++) {
if (c2[t4]) {
u2 = c2[t4];
continue;
}
let e3 = n2, o3 = c2.length;
for (let n3 = t4 + 1;n3 < c2.length; n3++)
if (c2[n3]) {
e3 = c2[n3], o3 = n3;
break;
}
const i3 = o3 - t4, r3 = e3.x - u2.x, s3 = e3.y - u2.y;
for (let e4 = 1 / (i3 + 1), n3 = 0;t4 + n3 !== o3; e4 += 1 / (i3 + 1), n3++)
c2[t4 + n3] = { x: u2.x + r3 * e4, y: u2.y + s3 * e4, z1: u2.z2, z2: u2.z2 };
}
return c2;
};
var Dr = 0.000000001;
function Lr(t3, e2) {
return Math.abs(t3 - e2) < Dr;
}
function zr(t3) {
return `${Math.round(t3.x / Dr)}:${Math.round(t3.y / Dr)}`;
}
function Br(t3, e2, n2, o2) {
return t3 * o2 - e2 * n2;
}
function Fr(t3, e2, n2, o2) {
const i2 = { x: e2.x - t3.x, y: e2.y - t3.y }, r2 = { x: o2.x - n2.x, y: o2.y - n2.y }, s2 = Br(i2.x, i2.y, r2.x, r2.y), a2 = { x: n2.x - t3.x, y: n2.y - t3.y };
if (Lr(s2, 0))
return null;
const c2 = Br(a2.x, a2.y, r2.x, r2.y) / s2, l2 = Br(a2.x, a2.y, i2.x, i2.y) / s2;
return c2 >= -1e-9 && c2 <= 1 + Dr && l2 >= -1e-9 && l2 <= 1 + Dr ? { x: t3.x + c2 * i2.x, y: t3.y + c2 * i2.y } : null;
}
function jr(t3, e2, n2) {
return Lr(Math.hypot(t3.x - e2.x, t3.y - e2.y) + Math.hypot(t3.x - n2.x, t3.y - n2.y), Math.hypot(e2.x - n2.x, e2.y - n2.y));
}
function $r(t3, e2) {
const n2 = [], o2 = new Map;
for (const e3 of t3) {
const t4 = [e3.start, ...e3.mPoints, e3.end];
for (let i4 = 0;i4 < t4.length - 1; i4++) {
const r3 = t4[i4], s3 = t4[i4 + 1], a3 = r3.z2;
if (n2.push({ start: { x: r3.x, y: r3.y }, end: { x: s3.x, y: s3.y }, connectionName: e3.connectionName, layer: a3 }), r3.z1 !== r3.z2) {
const t5 = zr(r3);
o2.has(t5) || o2.set(t5, { point: r3, connectionName: e3.connectionName });
}
}
const i3 = t4[t4.length - 1];
if (i3.z1 !== i3.z2) {
const t5 = zr(i3);
o2.has(t5) || o2.set(t5, { point: i3, connectionName: e3.connectionName });
}
}
const i2 = [{ start: { x: e2.minX, y: e2.minY }, end: { x: e2.maxX, y: e2.minY }, connectionName: null, layer: 0 }, { start: { x: e2.maxX, y: e2.minY }, end: { x: e2.maxX, y: e2.maxY }, connectionName: null, layer: 0 }, { start: { x: e2.maxX, y: e2.maxY }, end: { x: e2.minX, y: e2.maxY }, connectionName: null, layer: 0 }, { start: { x: e2.minX, y: e2.maxY }, end: { x: e2.minX, y: e2.minY }, connectionName: null, layer: 0 }];
n2.push(...i2);
const r2 = new Map;
let s2 = 0;
function a2(t4, e3) {
const n3 = zr(t4);
let i3 = r2.get(n3);
if (!i3) {
const e4 = o2.has(n3);
i3 = { id: s2++, x: t4.x, y: t4.y, isVia: e4, connectionNames: new Set, outgoingEdges: [] }, r2.set(n3, i3), e4 && o2.get(n3) && i3.connectionNames.add(o2.get(n3).connectionName);
}
return e3 && i3.connectionNames.add(e3), i3;
}
for (const t4 of n2)
a2(t4.start, t4.connectionName), a2(t4.end, t4.connectionName);
const c2 = new Map;
for (const t4 of n2)
c2.set(t4, []);
for (let t4 = 0;t4 < n2.length; t4++)
for (let e3 = t4 + 1;e3 < n2.length; e3++) {
if (n2[t4].layer !== n2[e3].layer)
continue;
const o3 = Fr(n2[t4].start, n2[t4].end, n2[e3].start, n2[e3].end);
o3 && (a2(o3), jr(o3, n2[t4].start, n2[t4].end) && c2.get(n2[t4]).push(o3), jr(o3, n2[e3].start, n2[e3].end) && c2.get(n2[e3]).push(o3));
}
const l2 = [];
let h2 = 0;
for (const t4 of n2) {
const e3 = [t4.start, ...c2.get(t4), t4.end];
e3.sort((e4, n4) => {
const o3 = t4.end.x - t4.start.x, i3 = t4.end.y - t4.start.y;
return Math.abs(o3) > Math.abs(i3) ? (e4.x - t4.start.x) / o3 - (n4.x - t4.start.x) / o3 : Math.abs(i3) < Dr ? 0 : (e4.y - t4.start.y) / i3 - (n4.y - t4.start.y) / i3;
});
const n3 = [];
if (e3.length > 0) {
n3.push(e3[0]);
for (let t5 = 1;t5 < e3.length; t5++)
Lr(e3[t5].x, e3[t5 - 1].x) && Lr(e3[t5].y, e3[t5 - 1].y) || n3.push(e3[t5]);
}
for (let e4 = 0;e4 < n3.length - 1; e4++) {
const o3 = n3[e4], i3 = n3[e4 + 1], r3 = a2(o3, t4.connectionName), s3 = a2(i3, t4.connectionName);
if (r3 === s3)
continue;
const c3 = { id: h2++, origin: r3, twin: null, next: null, face: null, connectionName: t4.connectionName, layer: t4.layer, visited: false }, d3 = { id: h2++, origin: s3, twin: c3, next: null, face: null, connectionName: t4.connectionName, layer: t4.layer, visited: false };
c3.twin = d3, l2.push(c3, d3), r3.outgoingEdges.push(c3), s3.outgoingEdges.push(d3);
}
}
for (const t4 of r2.values()) {
t4.outgoingEdges.sort((e4, n3) => {
const o3 = e4.twin.origin, i3 = n3.twin.origin;
return Math.atan2(o3.y - t4.y, o3.x - t4.x) - Math.atan2(i3.y - t4.y, i3.x - t4.x);
});
const e3 = t4.outgoingEdges.length;
for (let n3 = 0;n3 < e3; n3++) {
const o3 = t4.outgoingEdges[n3], i3 = t4.outgoingEdges[(n3 - 1 + e3) % e3];
o3.twin && (o3.twin.next = i3);
}
}
let u2 = 0, p2 = null, m2 = -1 / 0;
for (const t4 of l2) {
if (t4.visited)
continue;
const e3 = { id: u2++, outerComponent: t4, innerComponents: [], isOuterFace: false };
let n3 = t4;
const o3 = [], i3 = [], r3 = new Set;
let s3 = 0;
do {
if (!n3 || n3.visited) {
console.warn("Face traversal encountered visited edge or null, breaking loop.", e3.id), o3.length = 0;
break;
}
n3.visited = true, n3.face = e3, o3.push(n3), i3.push(n3.origin), n3.connectionName !== null && r3.add(n3.connectionName);
const t5 = n3.origin, a3 = n3.twin.origin;
s3 += t5.x * a3.y - a3.x * t5.y, n3 = n3.next;
} while (n3 !== t4 && n3 !== null);
if (n3 === t4) {
if (s3 = 0.5 * Math.abs(s3), s3 > m2 && (m2 = s3, p2 && (p2.isOuterFace = false), p2 = e3, e3.isOuterFace = true), !e3.isOuterFace && o3.length > 0) {
if ([...r3].filter((t5) => t5 !== null).length > 1) {
let t5 = false;
for (const e4 of i3)
if (e4.isVia) {
t5 = true;
break;
}
if (!t5)
return true;
}
}
} else
console.warn(`Face ${e3.id} did not close properly.`), u2--;
}
return false;
}
var Yr = (t3) => {
if (t3.length === 0)
return [[]];
const e2 = [];
for (let n2 = 0;n2 < t3.length; n2++) {
const o2 = t3[n2], i2 = [...t3.slice(0, n2), ...t3.slice(n2 + 1)], r2 = Yr(i2);
for (const t4 of r2)
e2.push([o2, ...t4]);
}
return e2;
};
var Xr = 0.000000001;
function Wr(t3, e2, n2 = 0.000000001) {
return Math.abs(t3 - e2) < n2;
}
function Vr(t3, e2, n2, o2) {
return t3 * o2 - e2 * n2;
}
function Hr(t3, e2, n2, o2) {
const i2 = { x: e2.x - t3.x, y: e2.y - t3.y }, r2 = { x: o2.x - n2.x, y: o2.y - n2.y }, s2 = Vr(i2.x, i2.y, r2.x, r2.y);
if (Wr(s2, 0))
return null;
const a2 = { x: n2.x - t3.x, y: n2.y - t3.y }, c2 = Vr(a2.x, a2.y, r2.x, r2.y) / s2, l2 = Vr(a2.x, a2.y, i2.x, i2.y) / s2;
return c2 < -1e-9 || c2 > 1 + Xr || l2 < -1e-9 || l2 > 1 + Xr ? null : { x: t3.x + c2 * i2.x, y: t3.y + c2 * i2.y };
}
function Gr(t3) {
let e2 = 0;
for (let n2 = 0, o2 = t3.length;n2 < o2; ++n2) {
const i2 = (n2 + 1) % o2;
e2 += t3[n2].x * t3[i2].y - t3[i2].x * t3[n2].y;
}
return 0.5 * e2;
}
function Ur(t3) {
let e2 = 0, n2 = 0, o2 = 0;
for (let i2 = 0, r2 = t3.length;i2 < r2; ++i2) {
const s2 = (i2 + 1) % r2, a2 = t3[i2].x * t3[s2].y - t3[s2].x * t3[i2].y;
e2 += a2, n2 += (t3[i2].x + t3[s2].x) * a2, o2 += (t3[i2].y + t3[s2].y) * a2;
}
return e2 *= 0.5, Wr(e2, 0) ? null : (n2 /= 6 * e2, o2 /= 6 * e2, { x: n2, y: o2 });
}
var Zr = class {
x;
y;
out;
connectionNames;
constructor(t3, e2) {
this.x = t3, this.y = e2, this.out = [], this.connectionNames = new Set;
}
};
var qr = class {
orig;
dest;
twin;
next;
visited;
constructor(t3, e2) {
this.orig = t3, this.dest = e2, this.twin = null, this.next = null, this.visited = false;
}
};
function Jr(t3, e2) {
const n2 = [...e2, ...[{ start: { x: t3.minX, y: t3.minY }, end: { x: t3.maxX, y: t3.minY } }, { start: { x: t3.maxX, y: t3.minY }, end: { x: t3.maxX, y: t3.maxY } }, { start: { x: t3.maxX, y: t3.maxY }, end: { x: t3.minX, y: t3.maxY } }, { start: { x: t3.minX, y: t3.maxY }, end: { x: t3.minX, y: t3.minY } }]], o2 = n2.map(() => []);
for (let t4 = 0;t4 < n2.length; ++t4) {
const e3 = n2[t4];
o2[t4].push(e3.start, e3.end);
}
for (let t4 = 0;t4 < n2.length; ++t4)
for (let e3 = t4 + 1;e3 < n2.length; ++e3) {
const i3 = Hr(n2[t4].start, n2[t4].end, n2[e3].start, n2[e3].end);
i3 && (o2[t4].push(i3), o2[e3].push(i3));
}
const i2 = new Map, r2 = [];
function s2(t4) {
const e3 = function(t5, e4 = 0.000000001) {
return `${Math.round(t5.x / e4)}:${Math.round(t5.y / e4)}`;
}(t4);
if (!i2.has(e3)) {
const n3 = r2.length;
return i2.set(e3, n3), r2.push(new Zr(t4.x, t4.y)), n3;
}
return i2.get(e3);
}
const a2 = [];
for (let t4 = 0;t4 < n2.length; ++t4) {
const e3 = n2[t4], i3 = o2[t4].slice();
i3.sort((t5, n3) => {
const o3 = e3.end.x - e3.start.x, i4 = e3.end.y - e3.start.y;
return (Wr(Math.abs(o3), 0) ? (t5.y - e3.start.y) / i4 : (t5.x - e3.start.x) / o3) - (Wr(Math.abs(o3), 0) ? (n3.y - e3.start.y) / i4 : (n3.x - e3.start.x) / o3);
});
for (let t5 = 0;t5 < i3.length - 1; ++t5) {
const n3 = i3[t5], o3 = i3[t5 + 1], c3 = s2(n3), l3 = s2(o3);
c3 !== l3 && (a2.push([c3, l3]), e3.connectionName && (r2[c3].connectionNames.add(e3.connectionName), r2[l3].connectionNames.add(e3.connectionName)));
}
}
const c2 = [];
for (const [t4, e3] of a2) {
const n3 = new qr(t4, e3), o3 = new qr(e3, t4);
n3.twin = c2.length + 1, o3.twin = c2.length;
const i3 = c2.length;
c2.push(n3, o3), r2[t4].out.push(i3), r2[e3].out.push(i3 + 1);
}
for (let t4 = 0;t4 < r2.length; ++t4) {
const e3 = r2[t4];
e3.out.sort((t5, n4) => {
const o3 = c2[t5], i3 = c2[n4], s3 = r2[o3.dest], a3 = r2[i3.dest];
return Math.atan2(s3.y - e3.y, s3.x - e3.x) - Math.atan2(a3.y - e3.y, a3.x - e3.x);
});
const n3 = e3.out.length;
for (let t5 = 0;t5 < n3; ++t5) {
const o3 = e3.out[t5], i3 = e3.out[(t5 - 1 + n3) % n3], r3 = c2[o3];
r3.twin !== null && (c2[r3.twin].next = i3);
}
}
const l2 = [], h2 = [];
for (let t4 = 0;t4 < c2.length; ++t4) {
if (c2[t4].visited)
continue;
let e3 = t4;
const n3 = [];
do {
if (e3 === null)
break;
const t5 = c2[e3];
t5.visited = true, n3.push(r2[t5.orig]), e3 = t5.next;
} while (e3 !== null && e3 !== t4 && !c2[e3].visited);
if (n3.length < 3)
continue;
if (Gr(n3) > Xr) {
const t5 = Ur(n3);
t5 && (l2.push(t5), h2.push({ vertices: n3.map((t6) => ({ x: t6.x, y: t6.y, connectionNames: t6.connectionNames.size > 0 ? t6.connectionNames : undefined })), centroid: t5 }));
}
}
return { centroids: l2, faces: h2, allVertices: r2 };
}
function Qr(t3, e2) {
if (t3 > e2)
throw new Error("oneCount cannot be greater than length");
if (t3 < 0 || e2 < 0)
throw new Error("oneCount and length must be non-negative");
const n2 = [];
return function t4(o2, i2, r2) {
r2 !== e2 ? (o2[r2] = 0, t4(o2, i2, r2 + 1), i2 > 0 && (o2[r2] = 1, t4(o2, i2 - 1, r2 + 1))) : i2 === 0 && n2.push([...o2]);
}(Array(e2).fill(0), t3, 0), n2;
}
var Kr = class extends si {
getSolverName() {
return "MultiHeadPolyLineIntraNodeSolver";
}
nodeWithPortPoints;
colorMap;
hyperParameters;
connMap;
candidates;
bounds;
solvedRoutes = [];
unsolvedConnections = [];
SEGMENTS_PER_POLYLINE;
cellSize;
MAX_CANDIDATES = 50000;
viaDiameter = 0.3;
obstacleMargin = 0.1;
traceWidth = 0.15;
availableZ = [];
uniqueConnections = 0;
BOUNDARY_PADDING;
lastCandidate = null;
maxViaCount;
minViaCount;
phase = "setup";
progress = 0;
constructor(t3) {
super(), this.MAX_ITERATIONS = 1e4, this.nodeWithPortPoints = t3.nodeWithPortPoints, this.colorMap = t3.colorMap ?? Rr(t3.nodeWithPortPoints), this.hyperParameters = t3.hyperParameters ?? {}, this.SEGMENTS_PER_POLYLINE = t3.hyperParameters?.SEGMENTS_PER_POLYLINE ?? 3, this.BOUNDARY_PADDING = t3.hyperParameters?.BOUNDARY_PADDING ?? 0.05, this.connMap = t3.connMap, this.viaDiameter = t3.viaDiameter ?? this.viaDiameter, this.cellSize = this.nodeWithPortPoints.width / 1024, this.candidates = [], this.availableZ = this.nodeWithPortPoints.availableZ ?? [0, 1], this.bounds = { minX: this.nodeWithPortPoints.center.x - this.nodeWithPortPoints.width / 2, maxX: this.nodeWithPortPoints.center.x + this.nodeWithPortPoints.width / 2, minY: this.nodeWithPortPoints.center.y - this.nodeWithPortPoints.height / 2, maxY: this.nodeWithPortPoints.center.y + this.nodeWithPortPoints.height / 2 };
const e2 = this.nodeWithPortPoints.width * this.nodeWithPortPoints.height, n2 = (this.viaDiameter + 2 * this.obstacleMargin + this.traceWidth / 2) ** 2, o2 = new Set(this.nodeWithPortPoints.portPoints.map((t4) => t4.connectionName)).size;
this.uniqueConnections = o2;
const { numSameLayerCrossings: i2, numEntryExitLayerChanges: r2 } = Or(this.nodeWithPortPoints);
if (this.minViaCount = 2 * i2 + r2, this.maxViaCount = Math.min(Math.floor(e2 / n2), Math.ceil(1.5 * o2)), this.minViaCount > this.SEGMENTS_PER_POLYLINE * (o2 / 2))
return this.failed = true, void (this.error = `Not possible to solve problem with given SEGMENTS_PER_POLYLINE (${this.SEGMENTS_PER_POLYLINE}), atleast ${this.minViaCount} vias are required`);
this.maxViaCount > this.SEGMENTS_PER_POLYLINE && (this.maxViaCount = this.SEGMENTS_PER_POLYLINE), this.maxViaCount < this.minViaCount && (this.maxViaCount = this.minViaCount);
}
computeMinGapBtwPolyLines(t3) {
const e2 = [], n2 = [], o2 = [];
for (let e3 = 0;e3 < t3.length; e3++) {
const i2 = t3[e3], r2 = [i2.start, ...i2.mPoints, i2.end], s2 = new Map(this.availableZ.map((t4) => [t4, []]));
for (let t4 = 0;t4 < r2.length - 1; t4++) {
const e4 = [r2[t4], r2[t4 + 1]], n3 = e4[0].z2;
s2.has(n3) || s2.set(n3, []), s2.get(n3).push(e4);
}
n2.push(s2), o2.push(r2.filter((t4) => t4.z1 !== t4.z2));
}
for (let i2 = 0;i2 < t3.length; i2++) {
const r2 = n2[i2], s2 = o2[i2];
for (let a2 = i2 + 1;a2 < t3.length; a2++) {
if (this.connMap?.areIdsConnected(t3[i2].connectionName, t3[a2].connectionName))
continue;
const c2 = n2[a2], l2 = o2[a2];
let h2 = 1;
for (const t4 of this.availableZ) {
const e3 = r2.get(t4) ?? [], n3 = c2.get(t4) ?? [];
for (const t5 of e3)
for (const e4 of n3)
h2 = Math.min(h2, Oe(t5[0], t5[1], e4[0], e4[1]) - this.traceWidth);
for (const t5 of s2)
for (const e4 of n3)
h2 = Math.min(h2, be(t5, e4[0], e4[1]) - this.traceWidth / 2 - this.viaDiameter / 2);
for (const t5 of l2)
for (const n4 of e3)
h2 = Math.min(h2, be(t5, n4[0], n4[1]) - this.traceWidth / 2 - this.viaDiameter / 2);
for (const t5 of s2)
for (const e4 of l2)
h2 = Math.min(h2, xe(t5, e4) - this.viaDiameter);
}
e2.push(h2);
}
}
return e2;
}
insertCandidate(t3) {
let e2 = 0, n2 = this.candidates.length - 1;
for (;e2 <= n2; ) {
const o2 = Math.floor((e2 + n2) / 2);
this.candidates[o2].f < t3.f ? e2 = o2 + 1 : n2 = o2 - 1;
}
this.candidates.splice(e2, 0, t3);
}
setupInitialPolyLines() {
const t3 = new Map;
this.nodeWithPortPoints.portPoints.forEach((e3) => {
t3.has(e3.connectionName) ? t3.get(e3.connectionName).end = { ...e3, z1: e3.z ?? 0, z2: e3.z ?? 0 } : t3.set(e3.connectionName, { start: { ...e3, z1: e3.z ?? 0, z2: e3.z ?? 0 }, end: null });
});
for (const [e3, n3] of t3.entries())
n3.end === null && t3.delete(e3);
if (t3.size === 0)
return this.failed = true, void (this.error = "No port pairs found, can't solve");
const e2 = Array.from(t3.entries()), n2 = ((t4, e3, n3, o3) => {
const i3 = [];
for (const [, n4] of t4) {
const t5 = n4.start.z1 !== n4.end.z1, o4 = [];
for (let n5 = 0;n5 <= e3; n5++) {
const e4 = n5 % 2 != 0;
t5 && e4 ? o4.push(n5) : t5 || e4 || o4.push(n5);
}
i3.push(o4);
}
if (i3.length === 0)
return [[]];
let r2 = ((t5) => {
if (!t5 || t5.length === 0)
return [[]];
let e4 = [[]];
for (const n4 of t5) {
const t6 = [];
for (const o4 of e4)
for (const e5 of n4)
t6.push([...o4, e5]);
e4 = t6;
}
return e4;
})(i3).filter((t5) => {
for (let e4 = 0;e4 < t5.length; e4++)
if (t5.reduce((t6, e5) => t6 + e5, 0) < o3)
return false;
return true;
});
return r2 = r2.filter((e4) => {
for (let n4 = 0;n4 < t4.length; n4++) {
const [, o4] = t4[n4];
if (o4.start.z1 !== o4.start.z2 && e4[n4] === 0)
return false;
}
return true;
}), r2 = r2.filter((e4) => {
for (let n4 = 0;n4 < t4.length; n4++) {
const [, o4] = t4[n4];
if (t4[n4][1].start.z1 === t4[n4][1].start.z2)
for (let i4 = n4 + 1;i4 < t4.length; i4++) {
if (t4[i4][1].start.z1 !== t4[i4][1].start.z2)
continue;
const [, r3] = t4[i4];
if (o4.start.z1 === o4.end.z1 && r3.start.z1 === r3.end.z1 && o4.start.z1 === r3.start.z1 && fe(o4.start, o4.end, r3.start, r3.end) && e4[n4] + e4[i4] < 2)
return false;
}
}
return true;
}), r2 = r2.filter((t5) => !(t5.reduce((t6, e4) => t6 + e4, 0) > n3)), r2;
})(e2, this.SEGMENTS_PER_POLYLINE, this.maxViaCount, this.minViaCount), o2 = ((t4) => {
const { bounds: e3, portPairsEntries: n3, viaCountVariants: o3 } = t4, { centroids: i3 } = Jr(e3, n3.map(([t5, e4]) => e4)), r2 = [];
for (const t5 of o3) {
const n4 = t5.reduce((t6, e4) => t6 + e4, 0);
let o4 = i3;
if (i3.length < n4) {
o4 = [];
const t6 = Math.ceil(Math.sqrt(n4)), i4 = t6;
for (let n5 = 0;n5 < t6; n5++)
for (let r3 = 0;r3 < i4; r3++)
o4.push({ x: e3.minX + (r3 + 1) / (i4 + 1) * (e3.maxX - e3.minX), y: e3.minY + (n5 + 1) / (t6 + 1) * (e3.maxY - e3.minY) });
}
const s2 = Qr(n4, o4.length);
for (const e4 of s2) {
const n5 = [];
for (let t6 = 0;t6 < e4.length; t6++)
e4[t6] === 1 && n5.push(o4[t6]);
r2.push({ viaPositions: n5, viaCountVariant: t5 });
}
}
return r2;
})({ portPairsEntries: e2, viaCountVariants: n2, bounds: this.bounds }), i2 = [];
for (const { viaCountVariant: t4, viaPositions: e3 } of o2) {
const n3 = Yr(e3);
for (const e4 of n3)
i2.push({ viaCountVariant: t4, viaPositions: e4 });
}
for (const { viaPositions: t4, viaCountVariant: n3 } of i2) {
const o3 = [];
let i3 = 0;
for (let r3 = 0;r3 < e2.length; r3++) {
const [s3, a3] = e2[r3], c2 = n3[r3], l2 = t4.slice(i3, i3 + c2), h2 = kr({ start: a3.start, end: a3.end, segmentsPerPolyline: this.SEGMENTS_PER_POLYLINE, viaPositions: l2, viaCount: c2, availableZ: this.availableZ });
i3 += c2, o3.push({ connectionName: s3, start: a3.start, end: a3.end, mPoints: h2 });
}
if ($r(o3, this.bounds))
continue;
const r2 = this.computeMinGapBtwPolyLines(o3), s2 = this.computeH({ minGaps: r2, forces: [] }), a2 = { polyLines: o3, g: 0, h: s2, f: s2, viaCount: n3.reduce((t5, e3) => t5 + e3, 0), minGaps: r2 };
if (this.checkIfSolved(a2))
return void (this.candidates = [a2]);
if (this.candidates.push(a2), this.candidates.length > this.MAX_CANDIDATES)
return;
}
this.candidates.sort((t4, e3) => t4.f - e3.f);
}
computeG(t3, e2) {
return e2.g + 0.000005 + 0.000005 * e2.viaCount * 100;
}
computeH(t3) {
let e2 = 0;
for (const n2 of t3.forces ?? [])
for (const t4 of n2)
for (const n3 of t4.values())
e2 += n3.fx * n3.fx + n3.fy * n3.fy;
return e2;
}
getNeighbors(t3) {
const { polyLines: e2 } = t3, n2 = e2.length, o2 = 0.02, i2 = 0.008, r2 = 0.000001, s2 = Array.from({ length: n2 }, (t4, n3) => Array.from({ length: e2[n3].mPoints.length }, () => new Map)), a2 = (t4, n3, o3, i3, r3) => {
if (n3 > 0 && n3 < e2[t4].mPoints.length + 1) {
const e3 = n3 - 1, a3 = s2[t4][e3], c3 = a3.get(o3) || { fx: 0, fy: 0 };
a3.set(o3, { fx: c3.fx + i3, fy: c3.fy + r3 });
}
};
for (let t4 = 0;t4 < n2; t4++)
for (let i3 = t4 + 1;i3 < n2; i3++) {
const n3 = e2[t4], s3 = e2[i3], c3 = [n3.start, ...n3.mPoints, n3.end], l3 = [s3.start, ...s3.mPoints, s3.end], h3 = [], d3 = [];
for (let t5 = 0;t5 < c3.length - 1; t5++)
h3.push({ p1: c3[t5], p2: c3[t5 + 1], layer: c3[t5].z2, p1Idx: t5, p2Idx: t5 + 1 });
c3.forEach((t5, e3) => {
t5.z1 !== t5.z2 && d3.push({ point: t5, layers: [t5.z1, t5.z2], index: e3 });
});
const u3 = [], p2 = [];
for (let t5 = 0;t5 < l3.length - 1; t5++)
u3.push({ p1: l3[t5], p2: l3[t5 + 1], layer: l3[t5].z2, p1Idx: t5, p2Idx: t5 + 1 });
l3.forEach((t5, e3) => {
t5.z1 !== t5.z2 && p2.push({ point: t5, layers: [t5.z1, t5.z2], index: e3 });
});
for (const e3 of h3)
for (const n4 of u3)
if (e3.layer === n4.layer) {
if (Oe(e3.p1, e3.p2, n4.p1, n4.p2) < r2)
continue;
const o3 = { x: (e3.p1.x + e3.p2.x) / 2, y: (e3.p1.y + e3.p2.y) / 2 }, s4 = { x: (n4.p1.x + n4.p2.x) / 2, y: (n4.p1.y + n4.p2.y) / 2 }, c4 = o3.x - s4.x, l4 = o3.y - s4.y, h4 = c4 * c4 + l4 * l4;
if (h4 > r2) {
const s5 = (`seg:${i3}:${n4.p1Idx}:${n4.p2Idx}`), c5 = `seg:${t4}:${e3.p1Idx}:${e3.p2Idx}`, l5 = (t5, e4, n5, o5, i4, s6, c6) => {
const l6 = ze(t5, n5.p1, n5.p2), h5 = t5.x - l6.x, d4 = t5.y - l6.y, u4 = h5 * h5 + d4 * d4;
if (u4 <= r2)
return;
const p3 = Math.sqrt(u4), m2 = 0.02 * Math.exp(-6 * p3), g2 = h5 / p3 * m2, f2 = d4 / p3 * m2;
a2(o5, e4, s6, g2, f2), a2(i4, n5.p1Idx, c6, -g2 / 2, -f2 / 2), a2(i4, n5.p2Idx, c6, -g2 / 2, -f2 / 2);
};
l5(e3.p1, e3.p1Idx, n4, t4, i3, s5, c5), l5(e3.p2, e3.p2Idx, n4, t4, i3, s5, c5), l5(n4.p1, n4.p1Idx, e3, i3, t4, c5, s5), l5(n4.p2, n4.p2Idx, e3, i3, t4, c5, s5);
}
}
for (const e3 of d3)
for (const n4 of u3)
if (e3.layers.includes(n4.layer)) {
const s4 = ze(e3.point, n4.p1, n4.p2), c4 = e3.point.x - s4.x, l4 = e3.point.y - s4.y, h4 = c4 * c4 + l4 * l4;
if (h4 > r2) {
const s5 = Math.sqrt(h4);
let d4 = 2, u4 = s5;
s5 < this.viaDiameter / 2 ? (d4 *= 4, u4 = Math.max(r2, s5)) : u4 = Math.max(r2, s5 - this.viaDiameter / 2);
const p3 = d4 * o2 * Math.exp(-6 * u4), m2 = c4 / s5 * p3, g2 = l4 / s5 * p3, f2 = `seg:${i3}:${n4.p1Idx}:${n4.p2Idx}`;
a2(t4, e3.index, f2, m2, g2);
const y2 = `via:${t4}:${e3.index}`;
a2(i3, n4.p1Idx, y2, -m2 / 2, -g2 / 2), a2(i3, n4.p2Idx, y2, -m2 / 2, -g2 / 2);
}
}
for (const e3 of p2)
for (const n4 of h3)
if (e3.layers.includes(n4.layer)) {
const s4 = ze(e3.point, n4.p1, n4.p2), c4 = e3.point.x - s4.x, l4 = e3.point.y - s4.y, h4 = c4 * c4 + l4 * l4;
if (h4 > r2) {
const s5 = Math.sqrt(h4);
let d4 = 2, u4 = s5;
s5 < this.viaDiameter / 2 ? (d4 *= 4, u4 = Math.max(r2, s5)) : u4 = Math.max(r2, s5 - this.viaDiameter / 2);
const p3 = d4 * o2 * Math.exp(-6 * u4), m2 = c4 / s5 * p3, g2 = l4 / s5 * p3, f2 = `seg:${t4}:${n4.p1Idx}:${n4.p2Idx}`;
a2(i3, e3.index, f2, m2, g2);
const y2 = `via:${i3}:${e3.index}`;
a2(t4, n4.p1Idx, y2, -m2 / 2, -g2 / 2), a2(t4, n4.p2Idx, y2, -m2 / 2, -g2 / 2);
}
}
for (const e3 of d3)
for (const n4 of p2) {
if (e3.layers.filter((t5) => n4.layers.includes(t5)).length > 0) {
const s4 = e3.point.x - n4.point.x, c4 = e3.point.y - n4.point.y, l4 = s4 * s4 + c4 * c4;
if (l4 > r2) {
const h4 = Math.sqrt(l4);
let d4 = 2, u4 = h4;
h4 < this.viaDiameter ? (d4 *= 4, u4 = Math.max(r2, h4)) : u4 = Math.max(r2, h4 - this.viaDiameter);
const p3 = d4 * o2 * Math.exp(-6 * u4), m2 = s4 / h4 * p3, g2 = c4 / h4 * p3, f2 = `via:${i3}:${n4.index}`, y2 = `via:${t4}:${e3.index}`;
a2(t4, e3.index, f2, m2, g2), a2(i3, n4.index, y2, -m2, -g2);
}
}
}
}
for (let t4 = 0;t4 < n2; t4++) {
const n3 = e2[t4], i3 = [n3.start, ...n3.mPoints, n3.end], s3 = [];
if (i3.forEach((t5, e3) => {
t5.z1 !== t5.z2 && s3.push({ point: t5, layers: [t5.z1, t5.z2], index: e3 });
}), !(s3.length < 2))
for (let e3 = 0;e3 < s3.length; e3++)
for (let n4 = e3 + 1;n4 < s3.length; n4++) {
const i4 = s3[e3], c3 = s3[n4], l3 = i4.point.x - c3.point.x, h3 = i4.point.y - c3.point.y, d3 = l3 * l3 + h3 * h3;
if (d3 > r2) {
const e4 = Math.sqrt(d3);
let n5 = 2, s4 = e4;
e4 < this.viaDiameter ? (n5 *= 4, s4 = Math.max(r2, e4)) : s4 = Math.max(r2, e4 - this.viaDiameter);
const u3 = n5 * o2 * Math.exp(-6 * s4), p2 = l3 / e4 * u3, m2 = h3 / e4 * u3, g2 = `via:${t4}:${c3.index}`, f2 = `via:${t4}:${i4.index}`;
a2(t4, i4.index, g2, p2, m2), a2(t4, c3.index, f2, -p2, -m2);
}
}
}
const c2 = e2.map((t4) => ({ ...t4, mPoints: t4.mPoints.map((t5) => ({ ...t5 })) }));
let l2 = false;
for (let t4 = 0;t4 < n2; t4++)
for (let e3 = 0;e3 < c2[t4].mPoints.length; e3++) {
const n3 = c2[t4].mPoints[e3], o3 = s2[t4][e3], a3 = { fx: 0, fy: 0 };
for (const t5 of o3.values())
a3.fx += t5.fx, a3.fy += t5.fy;
const h3 = n3.z1 !== n3.z2;
let d3 = n3.x + a3.fx, u3 = n3.y + a3.fy;
if (h3) {
const t5 = this.viaDiameter / 2;
let e4 = 0, o4 = 0;
const r3 = this.viaDiameter / 2 + this.BOUNDARY_PADDING, s3 = this.bounds.minX + r3, c3 = this.bounds.maxX - r3, l3 = this.bounds.minY + r3, h4 = this.bounds.maxY - r3, p2 = s3 + t5 - n3.x, m2 = n3.x - (c3 - t5), g2 = l3 + t5 - n3.y, f2 = n3.y - (h4 - t5);
p2 > 0 ? e4 = i2 * (Math.exp(p2 / (2 * this.obstacleMargin)) - 1) : m2 > 0 && (e4 = -8e-3 * (Math.exp(m2 / (2 * this.obstacleMargin)) - 1)), g2 > 0 ? o4 = i2 * (Math.exp(g2 / (2 * this.obstacleMargin)) - 1) : f2 > 0 && (o4 = -8e-3 * (Math.exp(f2 / (2 * this.obstacleMargin)) - 1)), a3.fx += e4, a3.fy += o4, d3 = n3.x + a3.fx, u3 = n3.y + a3.fy;
} else {
const t5 = this.traceWidth / 2 + this.BOUNDARY_PADDING;
d3 = Math.max(this.bounds.minX + t5, Math.min(this.bounds.maxX - t5, d3)), u3 = Math.max(this.bounds.minY + t5, Math.min(this.bounds.maxY - t5, u3));
}
Math.abs(a3.fx) < r2 && Math.abs(a3.fy) < r2 || (Math.abs(n3.x - d3) > r2 || Math.abs(n3.y - u3) > r2) && (n3.x = d3, n3.y = u3, l2 = true);
}
if (!l2)
return [];
const h2 = this.computeMinGapBtwPolyLines(c2), d2 = this.computeG(c2, t3), u2 = this.computeH({ minGaps: h2, forces: s2 });
return [{ polyLines: c2, g: d2, h: u2, f: Math.round(5 * d2) / 5 + u2, minGaps: h2, forces: s2, viaCount: t3.viaCount }];
}
checkIfSolved(t3) {
const e2 = t3.minGaps.every((t4) => t4 >= this.obstacleMargin), n2 = t3.polyLines.every((t4) => t4.mPoints.every((t5) => {
const e3 = (t5.z1 !== t5.z2 ? this.viaDiameter / 2 : this.traceWidth / 2) + this.BOUNDARY_PADDING;
return ((t6, e4, n3 = 0) => t6.x >= e4.minX + n3 && t6.x <= e4.maxX - n3 && t6.y >= e4.minY + n3 && t6.y <= e4.maxY - n3)(t5, this.bounds, e3);
}));
return e2 && n2;
}
tryFinalAcceptance() {
const t3 = this.hyperParameters?.MINIMUM_FINAL_ACCEPTANCE_GAP ?? undefined;
if (t3 === undefined || this.lastCandidate === null || this.lastCandidate.minGaps.length === 0)
return;
return Math.min(...this.lastCandidate.minGaps) >= t3 ? (this.solved = true, void this._setSolvedRoutes()) : undefined;
}
_step() {
if (this.phase === "setup")
return this.setupInitialPolyLines(), void (this.phase = "solving");
const t3 = this.candidates.shift();
if (!t3) {
if (this.tryFinalAcceptance(), this.solved)
return;
return this.failed = true, void (this.error = "No candidates left");
}
if (this.lastCandidate = t3, this.checkIfSolved(t3))
return this.solved = true, void this._setSolvedRoutes();
if (!t3)
return void (this.failed = true);
const e2 = this.getNeighbors(t3);
for (const t4 of e2)
this.insertCandidate(t4);
}
visualize() {
const t3 = { points: [], lines: [], rects: [], circles: [], coordinateSystem: "cartesian", title: "MultiHeadPolyLineIntraNodeSolver Visualization" };
t3.lines.push({ points: [{ x: this.bounds.minX, y: this.bounds.minY }, { x: this.bounds.maxX, y: this.bounds.minY }, { x: this.bounds.maxX, y: this.bounds.maxY }, { x: this.bounds.minX, y: this.bounds.maxY }, { x: this.bounds.minX, y: this.bounds.minY }], strokeColor: "gray" });
const e2 = this.lastCandidate ?? this.candidates[0];
if (e2?.hasClosedSameLayerFace) {
const e3 = 0.1 * (this.bounds.maxX - this.bounds.minX), n2 = 0.1 * (this.bounds.maxY - this.bounds.minY);
t3.rects.push({ center: { x: this.bounds.maxX + 0.6 * e3, y: this.bounds.maxY + 0.6 * n2 }, width: e3, height: n2, fill: "red", label: "HAS CLOSED FACE" });
}
for (const e3 of this.nodeWithPortPoints.portPoints)
t3.points.push({ x: e3.x, y: e3.y, label: `${e3.connectionName} (Port z=${e3.z ?? 0})`, color: this.colorMap[e3.connectionName] ?? "blue" });
return e2 && e2.polyLines.forEach((n2, o2) => {
const i2 = this.colorMap[n2.connectionName] ?? "purple", r2 = [n2.start, ...n2.mPoints, n2.end];
for (let e3 = 0;e3 < r2.length - 1; e3++) {
const o3 = r2[e3], s2 = r2[e3 + 1], a2 = o3.z2, c2 = a2 === 0, l2 = c2 ? i2 : Ao(i2, 0.5);
t3.lines.push({ points: [o3, s2], strokeColor: l2, strokeWidth: this.traceWidth, strokeDash: c2 ? undefined : [0.15, 0.15], label: `${n2.connectionName} segment (z=${a2})` });
}
r2.forEach((s2, a2) => {
const c2 = s2.z1 !== s2.z2, l2 = s2.z1, h2 = a2 > 0 && a2 < r2.length - 1;
let d2 = "", u2 = "";
if (h2) {
const i3 = a2 - 1, r3 = e2.forces?.[o2]?.[i3];
if (r3 && r3.size > 0) {
const o3 = { fx: 0, fy: 0 };
r3.forEach((r4, a3) => {
if (o3.fx += r4.fx, o3.fy += r4.fy, Math.abs(r4.fx) > 0.000001 || Math.abs(r4.fy) > 0.000001) {
const o4 = a3.split(":"), c3 = o4[0], l3 = parseInt(o4[1], 10), h3 = e2.polyLines[l3], d3 = this.colorMap[h3.connectionName] ?? "gray", u3 = 20, p2 = { x: s2.x + r4.fx * u3, y: s2.y + r4.fy * u3 };
let m2 = h3.connectionName;
if (c3 === "via") {
m2 += ` Via ${parseInt(o4[2], 10)}`;
} else if (c3 === "seg") {
m2 += ` Seg ${parseInt(o4[2], 10)}-${parseInt(o4[3], 10)}`;
}
t3.lines.push({ points: [s2, p2], strokeColor: d3, strokeWidth: 0.02, strokeDash: "2,2", label: `Force by ${m2} on ${n2.connectionName} mPoint ${i3}` });
}
}), (Math.abs(o3.fx) > 0.000001 || Math.abs(o3.fy) > 0.000001) && (u2 = `
Net Force: (${o3.fx.toFixed(3)}, ${o3.fy.toFixed(3)})`);
}
}
if (c2)
d2 = `Via (${n2.connectionName} z=${s2.z1} -> z=${s2.z2})${u2}`, t3.circles.push({ center: s2, radius: this.viaDiameter / 2, fill: Ao(i2, 0.5), label: d2 });
else if (h2) {
const e3 = l2 === 0 ? i2 : Ao(i2, 0.5);
d2 = `mPoint (${n2.connectionName} z=${l2})${u2}`, t3.circles.push({ center: s2, radius: this.cellSize / 8, fill: e3, label: d2 });
}
});
}), t3;
}
_setSolvedRoutes() {
if (!this.solved || !this.lastCandidate)
return [];
const t3 = [];
for (const e2 of this.lastCandidate.polyLines) {
const n2 = [], o2 = [], i2 = [e2.start, ...e2.mPoints, e2.end];
for (let t4 = 0;t4 < i2.length; t4++) {
const e3 = i2[t4];
n2.push({ x: e3.x, y: e3.y, z: e3.z1 }), e3.z1 !== e3.z2 && (o2.push({ x: e3.x, y: e3.y }), n2.push({ x: e3.x, y: e3.y, z: e3.z2 }));
}
t3.push({ connectionName: e2.connectionName, regionId: this.nodeWithPortPoints.capacityMeshNodeId, traceThickness: this.traceWidth, viaDiameter: this.viaDiameter, route: n2, vias: o2 });
}
this.solvedRoutes = t3;
}
};
var ts = class extends Kr {
getSolverName() {
return "MultiHeadPolyLineIntraNodeSolver2";
}
computeG(t3, e2) {
return e2.g + 0.000005 + 0.000005 * e2.viaCount * 100;
}
computeH(t3) {
const { minGaps: e2 } = t3;
let n2 = 0;
for (const t4 of e2)
t4 < 0 && (n2 += this.obstacleMargin), t4 < this.obstacleMargin && (n2 += this.obstacleMargin - t4);
return 0.011 * n2;
}
_step() {
if (this.phase === "setup")
return this.setupInitialPolyLines(), void (this.phase = "solving");
const t3 = this.candidates.shift();
if (!t3) {
if (this.tryFinalAcceptance(), this.solved)
return;
return void (this.failed = true);
}
if (this.lastCandidate = t3, this.checkIfSolved(t3))
return this.solved = true, void this._setSolvedRoutes();
let e2 = false, n2 = 0;
const o2 = t3.magForceApplied === undefined ? 1 : 10;
for (let i2 = 0;i2 < o2; i2++) {
const o3 = this.applyForcesToPolyLines(t3.polyLines);
if (n2 += o3.magForceApplied, e2 = o3.lastStepMoved, !o3.lastStepMoved)
break;
}
if (t3.magForceApplied = n2, t3.minGaps = this.computeMinGapBtwPolyLines(t3.polyLines), this.checkIfSolved(t3))
return this.solved = true, void this._setSolvedRoutes();
t3.g = this.computeG(t3.polyLines, t3), t3.h = this.computeH(t3), t3.f = t3.g + t3.h, e2 && this.insertCandidate(t3);
}
applyForcesToPolyLines(t3) {
let e2 = 0;
const n2 = t3.length, o2 = 0.02, i2 = 0.008, r2 = 0.000001, s2 = Array.from({ length: n2 }, (e3, n3) => Array.from({ length: t3[n3].mPoints.length }, () => ({ fx: 0, fy: 0 }))), a2 = (e3, n3, o3, i3) => {
if (n3 > 0 && n3 < t3[e3].mPoints.length + 1) {
const t4 = n3 - 1;
s2[e3][t4].fx += o3, s2[e3][t4].fy += i3;
}
}, c2 = (t4, e3, n3, o3, i3) => {
const s3 = ze(t4, n3.p1, n3.p2), c3 = t4.x - s3.x, l3 = t4.y - s3.y, h3 = c3 * c3 + l3 * l3;
if (h3 <= r2)
return;
const d2 = Math.sqrt(h3), u2 = 0.02 * Math.exp(-6 * d2), p2 = c3 / d2 * u2, m2 = l3 / d2 * u2;
a2(o3, e3, p2, m2), a2(i3, n3.p1Idx, -p2 / 2, -m2 / 2), a2(i3, n3.p2Idx, -p2 / 2, -m2 / 2);
}, l2 = t3.map((t4) => {
const e3 = [t4.start, ...t4.mPoints, t4.end];
return { segments: e3.slice(0, -1).map((t5, n3) => ({ p1: t5, p2: e3[n3 + 1], layer: t5.z2, p1Idx: n3, p2Idx: n3 + 1 })), vias: e3.flatMap((t5, e4) => t5.z1 === t5.z2 ? [] : [{ point: t5, layers: [t5.z1, t5.z2], index: e4 }]) };
});
for (let t4 = 0;t4 < n2; t4++)
for (let e3 = t4 + 1;e3 < n2; e3++) {
const { segments: n3, vias: i3 } = l2[t4], { segments: s3, vias: h3 } = l2[e3];
for (const o3 of n3)
for (const n4 of s3)
o3.layer === n4.layer && (c2(o3.p1, o3.p1Idx, n4, t4, e3), c2(o3.p2, o3.p2Idx, n4, t4, e3), c2(n4.p1, n4.p1Idx, o3, e3, t4), c2(n4.p2, n4.p2Idx, o3, e3, t4));
for (const n4 of i3)
for (const i4 of s3)
if (n4.layers.includes(i4.layer)) {
const s4 = ze(n4.point, i4.p1, i4.p2), c3 = n4.point.x - s4.x, l3 = n4.point.y - s4.y, h4 = c3 * c3 + l3 * l3;
if (h4 > r2) {
const s5 = Math.sqrt(h4);
let d2 = 2, u2 = s5;
s5 < this.viaDiameter / 2 ? (d2 *= 4, u2 = Math.max(r2, s5)) : u2 = Math.max(r2, s5 - this.viaDiameter / 2);
const p2 = d2 * o2 * Math.exp(-6 * u2), m2 = c3 / s5 * p2, g2 = l3 / s5 * p2;
a2(t4, n4.index, m2, g2), a2(e3, i4.p1Idx, -m2 / 2, -g2 / 2), a2(e3, i4.p2Idx, -m2 / 2, -g2 / 2);
}
}
for (const i4 of h3)
for (const s4 of n3)
if (i4.layers.includes(s4.layer)) {
const n4 = ze(i4.point, s4.p1, s4.p2), c3 = i4.point.x - n4.x, l3 = i4.point.y - n4.y, h4 = c3 * c3 + l3 * l3;
if (h4 > r2) {
const n5 = Math.sqrt(h4);
let d2 = 2, u2 = n5;
n5 < this.viaDiameter / 2 ? (d2 *= 4, u2 = Math.max(r2, n5)) : u2 = Math.max(r2, n5 - this.viaDiameter / 2);
const p2 = d2 * o2 * Math.exp(-6 * u2), m2 = c3 / n5 * p2, g2 = l3 / n5 * p2;
a2(e3, i4.index, m2, g2), a2(t4, s4.p1Idx, -m2 / 2, -g2 / 2), a2(t4, s4.p2Idx, -m2 / 2, -g2 / 2);
}
}
for (const n4 of i3)
for (const i4 of h3) {
if (n4.layers.filter((t5) => i4.layers.includes(t5)).length > 0) {
const s4 = n4.point.x - i4.point.x, c3 = n4.point.y - i4.point.y, l3 = s4 * s4 + c3 * c3;
if (l3 > r2) {
const h4 = Math.sqrt(l3);
let d2 = 2, u2 = h4;
h4 < this.viaDiameter ? (d2 *= 4, u2 = Math.max(r2, h4)) : u2 = Math.max(r2, h4 - this.viaDiameter);
const p2 = d2 * o2 * Math.exp(-6 * u2), m2 = s4 / h4 * p2, g2 = c3 / h4 * p2;
a2(t4, n4.index, m2, g2), a2(e3, i4.index, -m2, -g2);
}
}
}
}
for (let t4 = 0;t4 < n2; t4++) {
const { vias: e3 } = l2[t4];
if (!(e3.length < 2))
for (let n3 = 0;n3 < e3.length; n3++)
for (let i3 = n3 + 1;i3 < e3.length; i3++) {
const s3 = e3[n3], c3 = e3[i3], l3 = s3.point.x - c3.point.x, h3 = s3.point.y - c3.point.y, d2 = l3 * l3 + h3 * h3;
if (d2 > r2) {
const e4 = Math.sqrt(d2);
let n4 = 2, i4 = e4;
e4 < this.viaDiameter ? (n4 *= 4, i4 = Math.max(r2, e4)) : i4 = Math.max(r2, e4 - this.viaDiameter);
const u2 = n4 * o2 * Math.exp(-6 * i4), p2 = l3 / e4 * u2, m2 = h3 / e4 * u2;
a2(t4, s3.index, p2, m2), a2(t4, c3.index, -p2, -m2);
}
}
}
let h2 = false;
for (let o3 = 0;o3 < n2; o3++)
for (let n3 = 0;n3 < t3[o3].mPoints.length; n3++) {
const a3 = t3[o3].mPoints[n3], c3 = s2[o3][n3], l3 = a3.z1 !== a3.z2;
let { fx: d2, fy: u2 } = c3, p2 = a3.x + d2, m2 = a3.y + u2;
if (l3) {
const t4 = this.viaDiameter / 2;
let e3 = 0, n4 = 0;
const o4 = this.viaDiameter / 2 + this.BOUNDARY_PADDING, r3 = this.bounds.minX + o4, s3 = this.bounds.maxX - o4, c4 = this.bounds.minY + o4, l4 = this.bounds.maxY - o4, h3 = r3 + t4 - a3.x, g2 = a3.x - (s3 - t4), f2 = c4 + t4 - a3.y, y2 = a3.y - (l4 - t4);
h3 > 0 ? e3 = i2 * (Math.exp(h3 / (2 * this.obstacleMargin)) - 1) : g2 > 0 && (e3 = -8e-3 * (Math.exp(g2 / (2 * this.obstacleMargin)) - 1)), f2 > 0 ? n4 = i2 * (Math.exp(f2 / (2 * this.obstacleMargin)) - 1) : y2 > 0 && (n4 = -8e-3 * (Math.exp(y2 / (2 * this.obstacleMargin)) - 1)), d2 += e3, u2 += n4, p2 = a3.x + d2, m2 = a3.y + u2;
} else {
const t4 = this.traceWidth / 2 + this.BOUNDARY_PADDING;
p2 = Math.max(this.bounds.minX + t4, Math.min(this.bounds.maxX - t4, p2)), m2 = Math.max(this.bounds.minY + t4, Math.min(this.bounds.maxY - t4, m2));
}
if (Math.abs(d2) < r2 && Math.abs(u2) < r2)
continue;
e2 += Math.sqrt(d2 * d2 + u2 * u2), (Math.abs(a3.x - p2) > r2 || Math.abs(a3.y - m2) > r2) && (a3.x = p2, a3.y = m2, h2 = true);
}
return { lastStepMoved: h2, magForceApplied: e2 };
}
};
var es = (t3) => t3.flatMap((t4) => `${t4.connectionName}-${t4.mPoints.map((t5) => `${t5.x.toFixed(2)},${t5.y.toFixed(2)},${t5.z1},${t5.z2}`)}`).sort().join("|");
var ns = class extends ts {
getSolverName() {
return "MultiHeadPolyLineIntraNodeSolver3";
}
constructor(t3) {
super(t3), this.MAX_ITERATIONS = 1000;
}
createInitialCandidateFromSeed(t3) {
const e2 = new Er({ nodeWithPortPoints: this.nodeWithPortPoints, colorMap: this.colorMap, hyperParameters: { SHUFFLE_SEED: t3 }, viaDiameter: this.viaDiameter });
if (e2.solve(), e2.failed || !e2.solved)
return this.failed = true, this.error = `ViaPossibilitiesSolver2 failed with: ${e2.error}`, null;
const n2 = [];
let o2 = 0;
for (const [t4, i3] of e2.completedPaths.entries()) {
if (i3.length < 2) {
console.warn(`Skipping connection "${t4}" due to insufficient points (${i3.length}) in ViaPossibilitiesSolver2 path.`);
continue;
}
const e3 = i3[0], r3 = i3[i3.length - 1], s3 = i3.slice(1, -1), a2 = [];
let c2 = 0, l2 = e3.z;
for (let t5 = 0;t5 < s3.length; t5++) {
const e4 = s3[t5], n3 = t5 + 1 < s3.length ? s3[t5 + 1] : r3, o3 = l2, i4 = t5 + 1 < s3.length && e4.x === n3.x && e4.y === n3.y && e4.z !== n3.z ? n3.z : e4.z;
a2.push({ x: e4.x, y: e4.y, z1: o3, z2: i4 }), o3 !== i4 ? (c2++, t5++, l2 = i4) : l2 = e4.z;
}
o2 += c2;
const h2 = this.SEGMENTS_PER_POLYLINE;
let d2 = a2.length + 1;
for (;d2 < h2; ) {
let n3 = -1, o3 = -1, i4 = null, s4 = null;
const c3 = [{ ...e3, z1: e3.z, z2: e3.z, connectionName: t4 }, ...a2, { ...r3, z1: r3.z, z2: r3.z, connectionName: t4 }];
for (let t5 = 0;t5 < c3.length - 1; t5++) {
const e4 = c3[t5], r4 = c3[t5 + 1];
if (e4.x === r4.x && e4.y === r4.y)
continue;
const a3 = xe(e4, r4);
a3 > n3 && (n3 = a3, o3 = t5, i4 = e4, s4 = r4);
}
if (o3 === -1 || !i4 || !s4) {
console.warn(`Could not find longest segment for ${t4} while trying to reach ${h2} segments.`);
break;
}
const l3 = (i4.x + s4.x) / 2, u2 = (i4.y + s4.y) / 2, p2 = i4.z2, m2 = { x: l3, y: u2, z1: p2, z2: p2 };
a2.splice(o3, 0, m2), d2++;
}
n2.push({ connectionName: t4, start: { ...e3, z1: e3.z, z2: e3.z }, end: { ...r3, z1: r3.z, z2: r3.z }, mPoints: a2 });
}
if (n2.length === 0)
return this.failed = true, this.error = "No valid polylines generated from ViaPossibilitiesSolver2.", console.error(this.error), null;
const i2 = this.computeMinGapBtwPolyLines(n2), r2 = this.computeH({ minGaps: i2, forces: [] }), s2 = { polyLines: n2, g: 0, h: r2, f: 0 + r2, viaCount: o2, minGaps: i2 };
return s2.g = this.computeG(n2, s2), s2.f = s2.g + s2.h, s2;
}
setupInitialPolyLines() {
this.candidates = [];
const t3 = Math.min(2000, function(t4) {
if (!Number.isInteger(t4) || t4 < 0)
throw new RangeError("n must be a non-negative integer");
let e3 = 1;
for (let n2 = 2;n2 <= t4; n2++)
e3 *= n2;
return e3;
}(this.uniqueConnections)), e2 = new Set;
for (let n2 = 0;n2 < t3; n2++) {
const t4 = this.createInitialCandidateFromSeed(n2);
if (!t4)
continue;
const o2 = es(t4.polyLines);
e2.has(o2) || (e2.add(o2), this.candidates.push(t4));
}
this.candidates.sort((t4, e3) => t4.f - e3.f);
}
};
var os = (t3) => t3.portPointId ?? `${t3.connectionName}:${t3.x}:${t3.y}:${t3.z}`;
var is = (t3, e2) => {
const [n2, o2] = t3;
if (n2 === o2)
return false;
const i2 = ((t4) => {
const [e3, n3] = t4, o3 = os(e3), i3 = os(n3);
return o3 < i3 ? `${o3}|${i3}` : `${i3}|${o3}`;
})(t3);
return !e2.seenPairKeys.has(i2) && (e2.seenPairKeys.add(i2), e2.pairs.push(t3), true);
};
var rs = (t3, e2) => {
for (let n2 = 0;n2 < t3.length - 1; n2++)
is([t3[n2], t3[n2 + 1]], e2);
};
var ss = (t3) => {
const e2 = [], n2 = new Set, o2 = new Map(t3.filter((t4) => typeof t4.portPointId == "string").map((t4) => [t4.portPointId, t4])), i2 = { pairs: e2, seenPairKeys: n2 };
for (const e3 of t3) {
if (e3.prevPortPointId) {
const t4 = o2.get(e3.prevPortPointId);
t4 && t4.connectionName === e3.connectionName && is([t4, e3], i2);
}
if (e3.nextPortPointId) {
const t4 = o2.get(e3.nextPortPointId);
t4 && t4.connectionName === e3.connectionName && is([e3, t4], i2);
}
}
if (e2.length === 0)
return rs(t3, i2), e2;
const r2 = new Set(e2.flatMap(([t4, e3]) => [t4.portPointId, e3.portPointId]).filter(Boolean)), s2 = t3.filter((t4) => !t4.portPointId || !r2.has(t4.portPointId));
return rs(s2, i2), e2;
};
var as = 0.000001;
var cs = 0.02;
var ls = (t3) => `${t3.x.toFixed(6)},${t3.y.toFixed(6)}`;
var hs = (t3, e2) => Math.abs(t3.x - e2.x) < as && Math.abs(t3.y - e2.y) < as;
var ds = (t3) => ({ minX: t3.center.x - t3.width / 2, maxX: t3.center.x + t3.width / 2, minY: t3.center.y - t3.height / 2, maxY: t3.center.y + t3.height / 2 });
var us = (t3, e2) => t3.x >= e2.minX - as && t3.x <= e2.maxX + as && t3.y >= e2.minY - as && t3.y <= e2.maxY + as;
var ps = (t3, e2, n2) => {
for (const o2 of n2)
if (!hs(o2, t3) && !hs(o2, e2) && be(o2, t3, e2) < 0.0001)
return true;
return false;
};
var ms = (t3, e2, n2) => {
for (const o2 of n2)
if (!(hs(t3, o2.A) || hs(t3, o2.B) || hs(e2, o2.A) || hs(e2, o2.B)) && fe(t3, e2, o2.A, o2.B))
return true;
return false;
};
var gs = (t3, e2) => {
const n2 = [];
for (const o2 of t3) {
const t4 = o2.rootConnectionName ?? o2.connectionName;
if (t4 !== e2)
for (let e3 = 0;e3 < o2.route.length - 1; e3++) {
const i2 = o2.route[e3], r2 = o2.route[e3 + 1];
i2.z === r2.z && n2.push({ A: { x: i2.x, y: i2.y }, B: { x: r2.x, y: r2.y }, rootConnectionName: t4 });
}
}
return n2;
};
var fs = (t3, e2) => t3.portPoints.filter((t4) => (t4.rootConnectionName ?? t4.connectionName) !== e2).map((t4) => ({ x: t4.x, y: t4.y }));
function* ys(t3, e2 = t3.length) {
if (e2 <= 1)
yield t3.slice();
else
for (let n2 = 0;n2 < e2; n2++)
[t3[n2], t3[e2 - 1]] = [t3[e2 - 1], t3[n2]], yield* ys(t3, e2 - 1), [t3[n2], t3[e2 - 1]] = [t3[e2 - 1], t3[n2]];
}
var _s = ({ A: t3, B: e2, bounds: n2, obstacleSegments: o2, foreignPorts: i2 }) => {
const r2 = [{ x: t3.x, y: t3.y }, { x: e2.x, y: e2.y }, { x: (n2.minX + n2.maxX) / 2, y: (n2.minY + n2.maxY) / 2 }, { x: n2.minX, y: n2.minY }, { x: n2.maxX, y: n2.minY }, { x: n2.maxX, y: n2.maxY }, { x: n2.minX, y: n2.maxY }], s2 = [...o2.flatMap((t4) => [t4.A, t4.B]), ...i2, { x: t3.x, y: t3.y }, { x: e2.x, y: e2.y }];
for (const t4 of s2)
for (const e3 of [-0.02, 0, cs])
for (const o3 of [-0.02, 0, cs]) {
const i3 = { x: t4.x + e3, y: t4.y + o3 };
us(i3, n2) && r2.push(i3);
}
const a2 = ((t4) => {
const e3 = new Set, n3 = [];
for (const o3 of t4) {
const t5 = ls(o3);
e3.has(t5) || (e3.add(t5), n3.push(o3));
}
return n3;
})(r2), c2 = ls(t3), l2 = ls(e2), h2 = new Map(a2.map((t4) => [ls(t4), t4])), d2 = new Map, u2 = new Map, p2 = new Set;
for (const t4 of a2) {
const e3 = ls(t4);
d2.set(e3, e3 === c2 ? 0 : 1 / 0), u2.set(e3, null), p2.add(e3);
}
for (;p2.size > 0; ) {
let t4 = null, e3 = 1 / 0;
for (const n4 of p2) {
const o3 = d2.get(n4) ?? 1 / 0;
(o3 < e3 - as || Math.abs(o3 - e3) <= as && (t4 === null || n4 < t4)) && (e3 = o3, t4 = n4);
}
if (!t4 || e3 === 1 / 0)
break;
if (p2.delete(t4), t4 === l2)
break;
const n3 = h2.get(t4);
for (const r3 of p2) {
const s3 = h2.get(r3);
if (hs(n3, s3))
continue;
if (ms(n3, s3, o2))
continue;
if (ps(n3, s3, i2))
continue;
const a3 = e3 + xe(n3, s3), c3 = d2.get(r3) ?? 1 / 0, l3 = u2.get(r3);
(a3 < c3 - as || Math.abs(a3 - c3) <= as && (l3 == null || t4 < l3)) && (d2.set(r3, a3), u2.set(r3, t4));
}
}
if ((d2.get(l2) ?? 1 / 0) === 1 / 0)
return null;
const m2 = [];
let g2 = l2;
for (;g2; )
m2.push(h2.get(g2)), g2 = u2.get(g2) ?? null;
return m2.reverse(), m2.map((e3) => ({ x: e3.x, y: e3.y, z: t3.z }));
};
var bs = class extends si {
getSolverName() {
return "SingleLayerNoDifferentRootIntersectionsIntraNodeSolver";
}
nodeWithPortPoints;
traceWidth;
viaDiameter;
solvedRoutes = [];
constructor(t3) {
super(), this.nodeWithPortPoints = t3.nodeWithPortPoints, this.traceWidth = t3.traceWidth ?? 0.15, this.viaDiameter = t3.viaDiameter ?? 0.3, this.MAX_ITERATIONS = 1;
}
static isApplicable(t3) {
const e2 = ((t4) => t4.availableZ?.length ? [...new Set(t4.availableZ)].sort((t5, e3) => t5 - e3) : [...new Set(t4.portPoints.map((t5) => t5.z ?? 0))].sort((t5, e3) => t5 - e3))(t3);
if (e2.length !== 1)
return false;
if (t3.portPoints.length > 12)
return false;
const n2 = ds(t3);
if (t3.portPoints.some((t4) => ((t5, e3) => Math.abs(t5.y - e3.minY) < 0.001 ? "top" : Math.abs(t5.x - e3.maxX) < 0.001 ? "right" : Math.abs(t5.y - e3.maxY) < 0.001 ? "bottom" : Math.abs(t5.x - e3.minX) < 0.001 ? "left" : null)(t4, n2) === null))
return false;
const o2 = new Map;
for (const e3 of t3.portPoints)
o2.set(e3.connectionName, (o2.get(e3.connectionName) ?? 0) + 1);
return [...o2.values()].some((t4) => t4 > 2);
}
buildTaskGroups() {
const t3 = new Map;
for (const e2 of this.nodeWithPortPoints.portPoints) {
const n2 = t3.get(e2.connectionName) ?? [];
n2.push(e2), t3.set(e2.connectionName, n2);
}
return t3;
}
trySolveNode() {
const t3 = ds(this.nodeWithPortPoints), e2 = this.buildTaskGroups(), n2 = Array.from(e2.entries()).flatMap(([t4, e3]) => ss(e3).map(([e4, n3]) => ({ connectionName: t4, rootConnectionName: e4.rootConnectionName ?? n3.rootConnectionName ?? t4, A: e4, B: n3 }))), o2 = n2.length <= 6 ? ys(n2.slice()) : [n2];
for (const e3 of o2) {
const n3 = [];
let o3 = false;
for (const i2 of e3) {
const e4 = gs(n3, i2.rootConnectionName), r2 = fs(this.nodeWithPortPoints, i2.rootConnectionName), s2 = _s({ A: i2.A, B: i2.B, bounds: t3, obstacleSegments: e4, foreignPorts: r2 });
if (!s2 || s2.length < 2) {
o3 = true;
break;
}
n3.push({ connectionName: i2.connectionName, rootConnectionName: i2.rootConnectionName, regionId: this.nodeWithPortPoints.capacityMeshNodeId, traceThickness: this.traceWidth, viaDiameter: this.viaDiameter, route: s2, vias: [] });
}
if (!o3)
return n3;
}
return null;
}
_step() {
const t3 = this.trySolveNode();
if (!t3)
return this.failed = true, void (this.error = "Failed to find a single-layer route set without different-root intersections");
this.solvedRoutes = t3, this.stats = { routeCount: t3.length, distinctRoots: new Set(t3.map((t4) => t4.rootConnectionName ?? t4.connectionName)).size }, this.solved = true;
}
visualize() {
return { lines: this.solvedRoutes.map((t3) => ({ points: t3.route, strokeColor: "cyan", strokeWidth: t3.traceThickness, label: `${t3.connectionName}
root: ${t3.rootConnectionName ?? t3.connectionName}` })), points: this.nodeWithPortPoints.portPoints.map((t3) => ({ x: t3.x, y: t3.y, color: "blue", label: `${t3.connectionName}
root: ${t3.rootConnectionName ?? t3.connectionName}` })), rects: [], circles: [] };
}
};
var xs = (t3) => t3.min <= t3.max ? Ae(t3.value, t3.min, t3.max) : t3.value;
var vs = class extends si {
getSolverName() {
return "SingleTransitionIntraNodeSolver";
}
nodeWithPortPoints;
routes;
viaDiameter;
traceThickness;
obstacleMargin;
solvedRoutes = [];
bounds;
constructor(t3) {
if (super(), this.nodeWithPortPoints = t3.nodeWithPortPoints, this.viaDiameter = t3?.viaDiameter ?? 0.3, this.traceThickness = t3?.traceThickness ?? 0.15, this.obstacleMargin = t3?.obstacleMargin ?? 0.1, this.routes = this.extractRoutesFromNode(), this.bounds = this.calculateBounds(), this.routes.length !== 1)
return this.failed = true, void (this.error = `Expected 1 route, but got ${this.routes.length}`);
const e2 = this.routes[0];
if (e2.A.z === undefined || e2.B.z === undefined)
return this.failed = true, void (this.error = "Route points should have predefined z values");
if (e2.A.z === e2.B.z)
return this.failed = true, void (this.error = "Only one route provided, but it has no transition");
const n2 = this.viaDiameter / 2 + this.obstacleMargin, o2 = { x: xs({ value: (e2.A.x + e2.B.x) / 2, min: this.bounds.minX + n2, max: this.bounds.maxX - n2 }), y: xs({ value: (e2.A.y + e2.B.y) / 2, min: this.bounds.minY + n2, max: this.bounds.maxY - n2 }) };
this.solvedRoutes.push(this.createTransitionRoute({ start: e2.A, end: e2.B, via: o2, connectionName: e2.connectionName })), this.solved = true;
}
extractRoutesFromNode() {
const t3 = [], e2 = this.nodeWithPortPoints.portPoints, n2 = new Map;
for (const t4 of e2) {
const { connectionName: e3 } = t4;
n2.has(e3) || n2.set(e3, []), n2.get(e3).push(t4);
}
for (const [e3, o2] of n2.entries())
for (const [n3, i2] of ss(o2))
t3.push({ A: { ...n3 }, B: { ...i2 }, connectionName: e3 });
return t3;
}
calculateBounds() {
return { minX: this.nodeWithPortPoints.center.x - this.nodeWithPortPoints.width / 2, maxX: this.nodeWithPortPoints.center.x + this.nodeWithPortPoints.width / 2, minY: this.nodeWithPortPoints.center.y - this.nodeWithPortPoints.height / 2, maxY: this.nodeWithPortPoints.center.y + this.nodeWithPortPoints.height / 2 };
}
createTransitionRoute(t3) {
const { start: e2, end: n2, via: o2, connectionName: i2 } = t3, r2 = [{ x: e2.x, y: e2.y, z: e2.z }, { x: o2.x, y: o2.y, z: e2.z }, { x: o2.x, y: o2.y, z: n2.z }, { x: n2.x, y: n2.y, z: n2.z }];
return { connectionName: i2, regionId: this.nodeWithPortPoints.capacityMeshNodeId, route: r2, traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, vias: [o2] };
}
_step() {
this.solved = true;
}
visualize() {
const t3 = { lines: [], points: [], rects: [], circles: [] };
if (t3.rects.push({ center: { x: (this.bounds.minX + this.bounds.maxX) / 2, y: (this.bounds.minY + this.bounds.maxY) / 2 }, width: this.bounds.maxX - this.bounds.minX, height: this.bounds.maxY - this.bounds.minY, stroke: "rgba(0, 0, 0, 0.5)", fill: "rgba(240, 240, 240, 0.1)", label: "PCB Bounds" }), this.routes.length > 0)
for (const e2 of this.routes)
t3.points.push({ x: e2.A.x, y: e2.A.y, label: `${e2.connectionName} start (z=${e2.A.z})`, color: "orange" }), t3.points.push({ x: e2.B.x, y: e2.B.y, label: `${e2.connectionName} end (z=${e2.B.z})`, color: "orange" }), t3.lines.push({ points: [e2.A, e2.B], strokeColor: "rgba(255, 0, 0, 0.5)", label: `${e2.connectionName} direct` });
for (let e2 = 0;e2 < this.solvedRoutes.length; e2++) {
const n2 = this.solvedRoutes[e2], o2 = "rgba(0, 255, 0, 0.75)";
for (let e3 = 0;e3 < n2.route.length - 1; e3++) {
const i2 = n2.route[e3], r2 = n2.route[e3 + 1];
t3.lines.push({ points: [i2, r2], strokeColor: o2, strokeDash: i2.z !== n2.route[0].z ? [0.2, 0.2] : undefined, strokeWidth: n2.traceThickness, label: `${n2.connectionName} z=${i2.z}` });
}
for (const e3 of n2.vias)
t3.circles.push({ center: e3, radius: this.viaDiameter / 2, fill: "rgba(0, 0, 255, 0.8)", stroke: "black", label: "Solved Via" }), t3.circles.push({ center: e3, radius: this.viaDiameter / 2 + this.obstacleMargin, fill: "rgba(0, 0, 255, 0.3)", stroke: "black", label: "Via Margin" });
}
return t3;
}
};
var Is = (t3, e2 = 2) => {
const n2 = Array.from({ length: e2 }, (t4, e3) => e3);
return t3.map((t4) => {
const o2 = go(t4.__zLayers ?? (t4.layers ? fo(t4.layers, e2) : undefined) ?? n2, e2);
return { ...t4, __zLayers: o2.length > 0 ? o2 : n2 };
});
};
var Ss = 0.000001;
var Cs = (t3) => {
const { point: e2, obstacle: n2 } = t3, o2 = n2.width / 2 + Ss, i2 = n2.height / 2 + Ss;
return Math.abs(e2.x - n2.center.x) <= o2 && Math.abs(e2.y - n2.center.y) <= i2;
};
var Ps = class t3 extends si {
getSolverName() {
return "SingleTransitionThroughObstacleIntraNodeSolver";
}
nodeWithPortPoints;
routes;
obstacles;
viaDiameter;
traceThickness;
connMap;
solvedRoutes = [];
constructor(t4) {
if (super(), this.nodeWithPortPoints = t4.nodeWithPortPoints, this.obstacles = Is(t4.obstacles ?? [], t4.layerCount ?? 2), this.connMap = t4.connMap, this.viaDiameter = t4.viaDiameter ?? 0.3, this.traceThickness = t4.traceThickness ?? 0.15, this.routes = this.extractRoutesFromNode(), this.routes.length === 0)
return this.failed = true, void (this.error = "Expected at least 1 route");
if (this.routes.some((t5) => t5.A.z === undefined || t5.B.z === undefined))
return this.failed = true, void (this.error = "Route points should have predefined z values");
if (!this.routes.some((t5) => t5.A.z !== t5.B.z))
return this.failed = true, void (this.error = "No route transitions through an obstacle");
const e2 = this.routes.map((t5) => this.getContainingThroughObstacle(t5));
if (e2.some((t5) => !t5))
return this.failed = true, void (this.error = "No same-net multilayer obstacle contains every route");
this.solvedRoutes.push(...this.routes.map((t5, n2) => ({ connectionName: t5.connectionName, rootConnectionName: t5.rootConnectionName, regionId: this.nodeWithPortPoints.capacityMeshNodeId, route: [{ x: t5.A.x, y: t5.A.y, z: t5.A.z, ...t5.A.z !== t5.B.z ? { toNextSegmentType: "through_obstacle", ...e2[n2].circuitJsonMetadata ? { toNextSegmentCircuitJsonMetadata: e2[n2].circuitJsonMetadata } : {} } : {} }, { x: t5.B.x, y: t5.B.y, z: t5.B.z }], traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, vias: [] }))), this.solved = true;
}
static isApplicable(e2) {
return new t3(e2).solved;
}
extractRoutesFromNode() {
const t4 = [], e2 = new Map;
for (const t5 of this.nodeWithPortPoints.portPoints) {
const { connectionName: n2 } = t5;
e2.has(n2) || e2.set(n2, []), e2.get(n2).push(t5);
}
for (const [n2, o2] of e2.entries())
for (const [e3, i2] of ss(o2))
t4.push({ A: { ...e3 }, B: { ...i2 }, connectionName: n2, rootConnectionName: e3.rootConnectionName ?? i2.rootConnectionName });
return t4;
}
getContainingThroughObstacle(t4) {
const e2 = t4.A.z, n2 = t4.B.z;
return e2 === undefined || n2 === undefined ? null : this.obstacles.find((o2) => {
return !(o2.__zLayers.length < 2) && (!(!o2.__zLayers.includes(e2) || !o2.__zLayers.includes(n2)) && (!!(i2 = { obstacle: o2, connectionName: t4.connectionName, connMap: this.connMap }).obstacle.connectedTo.some((t5) => t5 === i2.connectionName || (i2.connMap?.areIdsConnected(i2.connectionName, t5) ?? false)) && (Cs({ point: t4.A, obstacle: o2 }) && Cs({ point: t4.B, obstacle: o2 }))));
var i2;
}) ?? null;
}
_step() {
this.solved = true;
}
visualize() {
const t4 = { lines: [], points: [], rects: [], circles: [] };
for (const e2 of this.obstacles)
t4.rects.push({ center: e2.center, width: e2.width, height: e2.height, fill: "rgba(128, 0, 128, 0.2)", stroke: "rgba(128, 0, 128, 0.6)", label: `through obstacle candidate
z: ${e2.__zLayers.join(",")}` });
for (const e2 of this.solvedRoutes) {
t4.lines.push({ points: e2.route, strokeColor: "rgba(0, 180, 0, 0.8)", strokeDash: "4, 3", strokeWidth: e2.traceThickness, label: `${e2.connectionName} through_obstacle` });
for (const n2 of e2.route)
t4.points.push({ x: n2.x, y: n2.y, color: "green", label: `${e2.connectionName}
z: ${n2.z}` });
}
return t4;
}
};
var Ms = 0.000001;
var Ns = ({ value: t4, min: e2, max: n2 }) => t4 >= e2 && t4 <= n2;
var ws = ({ value: t4, target: e2, epsilon: n2 }) => Math.abs(t4 - e2) <= n2;
var Ts = ({ point: t4, bounds: e2, epsilon: n2 = 0.000001 }) => {
if (![t4.x, t4.y, e2.minX, e2.maxX, e2.minY, e2.maxY].every((t5) => (({ value: t6 }) => Number.isFinite(t6))({ value: t5 })))
return "outside";
if (t4.x < e2.minX - n2 || t4.x > e2.maxX + n2 || t4.y < e2.minY - n2 || t4.y > e2.maxY + n2)
return "outside";
const o2 = ws({ value: t4.x, target: e2.minX, epsilon: n2 }), i2 = ws({ value: t4.x, target: e2.maxX, epsilon: n2 }), r2 = ws({ value: t4.y, target: e2.minY, epsilon: n2 }), s2 = ws({ value: t4.y, target: e2.maxY, epsilon: n2 }), a2 = o2 || i2, c2 = r2 || s2;
if (a2 && c2)
return "on-boundary";
const l2 = Ns({ value: t4.y, min: e2.minY, max: e2.maxY }), h2 = Ns({ value: t4.x, min: e2.minX, max: e2.maxX });
return a2 && l2 || c2 && h2 ? "on-boundary" : "inside";
};
function Rs(t4, e2, n2, o2, i2) {
const r2 = { x: (t4.x + e2.x + n2.x) / 3, y: (t4.y + e2.y + n2.y) / 3 }, s2 = (t5, e3) => Math.sqrt((e3.x - t5.x) ** 2 + (e3.y - t5.y) ** 2), a2 = (r3) => {
const a3 = s2(r3, t4), c3 = s2(r3, e2), l3 = s2(r3, n2), h3 = r3.x >= i2.minX && r3.x <= i2.maxX && r3.y >= i2.minY && r3.y <= i2.maxY;
return a3 >= o2 && c3 >= o2 && l3 >= o2 && h3;
};
if (a2(r2))
return r2;
const c2 = (t5, e3, n3) => {
const o3 = t5.x - e3.x, i3 = t5.y - e3.y, r3 = Math.sqrt(o3 * o3 + i3 * i3);
return r3 < 0.0000000001 ? { x: e3.x + n3, y: e3.y } : { x: e3.x + o3 / r3 * n3, y: e3.y + i3 / r3 * n3 };
}, l2 = (t5, e3, n3) => {
const o3 = e3.x - t5.x, i3 = e3.y - t5.y, r3 = Math.sqrt(o3 * o3 + i3 * i3);
if (r3 > 2 * n3 - 0.0000000001 || r3 < 0.0000000001)
return [];
const a3 = r3 * r3 / (2 * r3), c3 = Math.sqrt(Math.max(0, n3 * n3 - a3 * a3)), l3 = t5.x + o3 * a3 / r3, h3 = t5.y + i3 * a3 / r3, d3 = { x: l3 + c3 * i3 / r3, y: h3 - c3 * o3 / r3 }, u3 = { x: l3 - c3 * i3 / r3, y: h3 + c3 * o3 / r3 }, p3 = [], m3 = 0.000001;
return Math.abs(s2(d3, t5) - n3) < m3 && Math.abs(s2(d3, e3) - n3) < m3 && p3.push(d3), Math.abs(s2(u3, t5) - n3) < m3 && Math.abs(s2(u3, e3) - n3) < m3 && p3.push(u3), p3;
}, h2 = [c2(r2, t4, o2), c2(r2, e2, o2), c2(r2, n2, o2), ...l2(t4, e2, o2), ...l2(e2, n2, o2), ...l2(n2, t4, o2)], d2 = h2.filter(a2);
if (d2.length > 0) {
const t5 = d2.filter((t6) => !((t7) => {
const e3 = 0.000001;
return Math.abs(t7.x - i2.minX) < e3 || Math.abs(t7.x - i2.maxX) < e3 || Math.abs(t7.y - i2.minY) < e3 || Math.abs(t7.y - i2.maxY) < e3;
})(t6));
if (t5.length > 0)
return t5.sort((t6, e3) => s2(t6, r2) - s2(e3, r2)), t5[0];
}
let u2 = null, p2 = 1 / 0;
for (let t5 = i2.minX + 1;t5 < i2.maxX; t5 += 5)
for (let e3 = i2.minY + 1;e3 < i2.maxY; e3 += 5) {
const n3 = { x: t5, y: e3 };
if (a2(n3)) {
const t6 = s2(n3, r2);
t6 < p2 && (p2 = t6, u2 = n3);
}
}
if (u2 !== null)
return u2;
const m2 = [];
for (let t5 = 0;t5 <= 100; t5++) {
const e3 = t5 / 100;
m2.push({ x: i2.minX + e3 * (i2.maxX - i2.minX), y: i2.minY }), m2.push({ x: i2.maxX, y: i2.minY + e3 * (i2.maxY - i2.minY) }), m2.push({ x: i2.maxX - e3 * (i2.maxX - i2.minX), y: i2.maxY }), m2.push({ x: i2.minX, y: i2.maxY - e3 * (i2.maxY - i2.minY) });
}
const g2 = m2.filter(a2);
if (g2.length > 0)
return g2.sort((t5, e3) => s2(t5, r2) - s2(e3, r2)), g2[0];
let f2 = 1 / 0, y2 = { x: i2.minX, y: i2.minY };
for (const r3 of [...h2, ...m2])
if (r3.x >= i2.minX && r3.x <= i2.maxX && r3.y >= i2.minY && r3.y <= i2.maxY) {
const i3 = Math.max(0, o2 - s2(r3, t4)) + Math.max(0, o2 - s2(r3, e2)) + Math.max(0, o2 - s2(r3, n2));
i3 < f2 && (f2 = i3, y2 = r3);
}
return y2;
}
function Es(t4, e2, n2) {
const o2 = As(e2, t4, n2.center, n2.radius), i2 = As(t4, e2, n2.center, n2.radius), r2 = Os(o2, e2), s2 = Os(t4, i2), a2 = 0.000001;
let c2;
if (r2 > a2 && s2 > a2) {
c2 = { x: (o2.x + i2.x) / 2, y: (o2.y + i2.y) / 2 };
const r3 = Os(o2, c2), s3 = Os(i2, c2);
if (Math.abs(r3 - s3) > 0.5 * Math.min(r3, s3)) {
const n3 = Os(t4, o2), r4 = Os(e2, i2), s4 = n3 + r4;
if (s4 > a2) {
const t5 = r4 / s4, e3 = n3 / s4;
c2 = { x: o2.x * t5 + i2.x * e3, y: o2.y * t5 + i2.y * e3 };
}
}
const l2 = Os(c2, n2.center);
if (l2 < 1.05 * n2.radius) {
const t5 = { x: (c2.x - n2.center.x) / l2, y: (c2.y - n2.center.y) / l2 };
c2 = { x: n2.center.x + t5.x * n2.radius * 1.2, y: n2.center.y + t5.y * n2.radius * 1.2 };
}
} else {
const o3 = { x: (t4.x + e2.x) / 2, y: (t4.y + e2.y) / 2 }, i3 = Os(o3, n2.center);
if (i3 < 1.1 * n2.radius) {
const t5 = { x: (o3.x - n2.center.x) / i3, y: (o3.y - n2.center.y) / i3 };
c2 = { x: n2.center.x + t5.x * n2.radius * 1.2, y: n2.center.y + t5.y * n2.radius * 1.2 };
} else
c2 = o3;
}
return { B: o2, D: i2, E: c2 };
}
function As(t4, e2, n2, o2) {
const i2 = [n2.x - t4.x, n2.y - t4.y], r2 = Math.sqrt(i2[0] * i2[0] + i2[1] * i2[1]);
if (r2 <= o2) {
if (r2 < 0.00000001) {
const i3 = [e2.x - t4.x, e2.y - t4.y], r3 = Math.sqrt(i3[0] * i3[0] + i3[1] * i3[1]);
return r3 < 0.00000001 ? { x: n2.x + o2, y: n2.y } : { x: n2.x + i3[0] / r3 * o2, y: n2.y + i3[1] / r3 * o2 };
}
const s3 = [i2[0] / r2, i2[1] / r2];
return { x: n2.x - s3[0] * o2, y: n2.y - s3[1] * o2 };
}
const s2 = [e2.x - t4.x, e2.y - t4.y], a2 = Math.sqrt(r2 * r2 - o2 * o2), c2 = [i2[0] / r2, i2[1] / r2], l2 = [-c2[1], c2[0]], h2 = [c2[1], -c2[0]], d2 = s2[0] * l2[0] + s2[1] * l2[1] > s2[0] * h2[0] + s2[1] * h2[1] ? l2 : h2, u2 = o2 / r2, p2 = a2 / r2, m2 = [c2[0] * p2 + d2[0] * u2, c2[1] * p2 + d2[1] * u2];
return { x: t4.x + a2 * m2[0], y: t4.y + a2 * m2[1] };
}
function Os(t4, e2) {
const n2 = e2.x - t4.x, o2 = e2.y - t4.y;
return Math.sqrt(n2 * n2 + o2 * o2);
}
var ks = 0.000000001;
function Ds(t4, e2, n2, o2 = "cw") {
const i2 = Ls(t4, n2), r2 = Ls(e2, n2);
return Math.abs(r2 - i2) < ks ? { left: 0, top: 0, right: 0, bottom: 0 } : function(t5, e3, n3, o3) {
const i3 = n3.maxX - n3.minX, r3 = n3.maxY - n3.minY;
if (i3 < ks && r3 < ks)
return { left: 0, top: 0, right: 0, bottom: 0 };
const s2 = 2 * (i3 + r3);
if (s2 < ks)
return { left: 0, top: 0, right: 0, bottom: 0 };
const a2 = i3 / s2 * (2 * Math.PI), c2 = (i3 + r3) / s2 * (2 * Math.PI), l2 = (i3 + i3 + r3) / s2 * (2 * Math.PI), h2 = 2 * Math.PI, d2 = [{ name: "top", start: 0, end: a2, length: i3 }, { name: "right", start: a2, end: c2, length: r3 }, { name: "bottom", start: c2, end: l2, length: i3 }, { name: "left", start: l2, end: h2, length: r3 }], u2 = { left: 0, top: 0, right: 0, bottom: 0 }, p2 = (t6, e4, n4, o4, i4) => {
const r4 = e4 > 2 * Math.PI - ks ? 2 * Math.PI : e4;
if (r4 <= t6 + ks)
return 0;
if (i4) {
const e5 = Math.max(t6, n4), i5 = Math.min(r4, 2 * Math.PI), s3 = Math.max(0, i5 - e5), a3 = Math.max(t6, 0), c3 = Math.min(r4, o4);
return s3 + Math.max(0, c3 - a3);
}
{
const e5 = Math.max(t6, n4), i5 = Math.min(r4, o4);
return Math.max(0, i5 - e5);
}
};
for (const n4 of d2) {
const i4 = n4.end - n4.start;
if (i4 < ks || n4.length < ks)
continue;
let r4 = 0;
if (o3 === "cw") {
const o4 = t5 > e3 + ks;
r4 = p2(n4.start, n4.end, t5, e3, o4);
} else {
const o4 = e3 > t5 + ks;
r4 = p2(n4.start, n4.end, e3, t5, o4);
}
if (r4 > ks) {
const t6 = r4 / i4;
u2[n4.name] += Math.max(0, Number.isFinite(t6) ? t6 : 0);
}
}
for (const t6 in u2)
u2[t6] = Math.max(0, Math.min(1, u2[t6]));
return u2;
}(i2, r2, n2, o2);
}
function Ls(t4, e2) {
const n2 = e2.maxX - e2.minX, o2 = e2.maxY - e2.minY;
if (n2 < ks && o2 < ks)
return 0;
const i2 = 2 * (n2 + o2);
if (i2 < ks)
return 0;
let r2 = 0;
if (Math.abs(t4.y - e2.maxY) <= Ms && t4.x >= e2.minX - Ms && t4.x <= e2.maxX + Ms)
r2 = Math.max(0, Math.min(n2, t4.x - e2.minX));
else if (Math.abs(t4.x - e2.maxX) <= Ms && t4.y >= e2.minY - Ms && t4.y <= e2.maxY + Ms)
r2 = n2 + Math.max(0, Math.min(o2, e2.maxY - t4.y));
else if (Math.abs(t4.y - e2.minY) <= Ms && t4.x >= e2.minX - Ms && t4.x <= e2.maxX + Ms)
r2 = n2 + o2 + Math.max(0, Math.min(n2, e2.maxX - t4.x));
else {
if (!(Math.abs(t4.x - e2.minX) <= Ms && t4.y >= e2.minY - Ms && t4.y <= e2.maxY + Ms))
throw new Error(`Point (${t4.x}, ${t4.y}) does not lie on the boundary defined by ${JSON.stringify(e2)}`);
r2 = n2 + o2 + n2 + Math.max(0, Math.min(o2, t4.y - e2.minY));
}
return r2 = Math.max(0, Math.min(i2, r2)), i2 > ks ? r2 / i2 * (2 * Math.PI) : 0;
}
function zs(t4, e2, n2, o2) {
return function({ angleA: t5, angleB: e3, angleC: n3 }) {
const o3 = Math.cos(t5), i2 = Math.sin(t5), r2 = Math.cos(e3), s2 = Math.sin(e3), a2 = Math.cos(n3);
return (r2 - o3) * (Math.sin(n3) - i2) - (s2 - i2) * (a2 - o3) < 0 ? "ccw" : "cw";
}({ angleA: Ls(t4, o2), angleB: Ls(e2, o2), angleC: Ls(n2, o2) });
}
var Bs = class extends si {
getSolverName() {
return "SingleTransitionCrossingRouteSolver";
}
nodeWithPortPoints;
routes;
viaDiameter;
traceThickness;
obstacleMargin;
layerCount = 2;
debugViaPositions;
solvedRoutes = [];
bounds;
constructor(t4) {
if (super(), this.nodeWithPortPoints = t4.nodeWithPortPoints, this.viaDiameter = t4?.viaDiameter ?? 0.3, this.traceThickness = t4?.traceThickness ?? 0.15, this.obstacleMargin = t4?.obstacleMargin ?? 0.1, this.layerCount = t4?.layerCount ?? 2, this.debugViaPositions = [], this.routes = this.extractRoutesFromNode(), this.bounds = this.calculateBounds(), this.routes.length !== 2)
return this.failed = true, void (this.error = `Expected 2 routes, but got ${this.routes.length}`);
const e2 = this.routes.flatMap((t5) => [t5.A, t5.B]).map((t5) => this.getPortPointBoundsPosition(t5));
if (e2.includes("outside"))
return this.failed = true, void (this.error = "Invalid route input: SingleTransitionCrossingRouteSolver received port point(s) outside node bounds");
if (e2.includes("inside"))
return void (this.failed = true);
this.routes = this.routes.map((t5) => ({ ...t5, A: this.snapPortPointToBounds(t5.A), B: this.snapPortPointToBounds(t5.B) }));
const [n2, o2] = this.routes, i2 = n2.A.z !== n2.B.z, r2 = o2.A.z !== o2.B.z;
return i2 && r2 || !i2 && !r2 ? (this.failed = true, void (this.error = "Exactly one route must have a layer transition")) : undefined;
}
extractRoutesFromNode() {
const t4 = [], e2 = this.nodeWithPortPoints.portPoints, n2 = new Map;
for (const t5 of e2) {
const { connectionName: e3 } = t5;
n2.has(e3) || n2.set(e3, []), n2.get(e3)?.push(t5);
}
for (const [e3, o2] of n2.entries())
o2.length === 2 && t4.push({ A: { ...o2[0], z: o2[0].z ?? 0 }, B: { ...o2[1], z: o2[1].z ?? 0 }, connectionName: e3 });
return t4;
}
calculateBounds() {
return { minX: this.nodeWithPortPoints.center.x - this.nodeWithPortPoints.width / 2, maxX: this.nodeWithPortPoints.center.x + this.nodeWithPortPoints.width / 2, minY: this.nodeWithPortPoints.center.y - this.nodeWithPortPoints.height / 2, maxY: this.nodeWithPortPoints.center.y + this.nodeWithPortPoints.height / 2 };
}
getPortPointBoundsPosition(t4) {
return Ts({ point: t4, bounds: this.bounds });
}
snapPortPointToBounds(t4) {
const e2 = Ae(t4.x, this.bounds.minX, this.bounds.maxX), n2 = Ae(t4.y, this.bounds.minY, this.bounds.maxY);
return [{ distance: Math.abs(t4.y - this.bounds.maxY), point: { ...t4, x: e2, y: this.bounds.maxY } }, { distance: Math.abs(t4.x - this.bounds.maxX), point: { ...t4, x: this.bounds.maxX, y: n2 } }, { distance: Math.abs(t4.y - this.bounds.minY), point: { ...t4, x: e2, y: this.bounds.minY } }, { distance: Math.abs(t4.x - this.bounds.minX), point: { ...t4, x: this.bounds.minX, y: n2 } }].reduce((t5, e3) => e3.distance < t5.distance ? e3 : t5).point;
}
doRoutesCross(t4, e2) {
return fe(t4.A, t4.B, e2.A, e2.B);
}
calculateViaPosition(t4, e2) {
const n2 = e2.A.z, o2 = t4.A.z !== n2 ? t4.A : t4.B, i2 = 2 * this.obstacleMargin + this.viaDiameter / 2 + this.traceThickness, r2 = this.obstacleMargin + this.viaDiameter / 2, s2 = e2.A, a2 = o2, c2 = e2.B, l2 = zs(s2, a2, c2, this.bounds), h2 = function(t5, e3, n3, o3, i3) {
const r3 = Ds(t5, e3, o3, i3), s3 = Ds(e3, n3, o3, i3), a3 = { left: Math.min(1, r3.left + s3.left), top: Math.min(1, r3.top + s3.top), right: Math.min(1, r3.right + s3.right), bottom: Math.min(1, r3.bottom + s3.bottom) };
for (const t6 in a3)
Math.abs(a3[t6]) < ks && (a3[t6] = 0);
return a3;
}(s2, a2, c2, this.bounds, l2), d2 = { minX: this.bounds.minX + (h2.left > 0.5 ? i2 : r2), minY: this.bounds.minY + (h2.bottom > 0.5 ? i2 : r2), maxX: this.bounds.maxX - (h2.right > 0.5 ? i2 : r2), maxY: this.bounds.maxY - (h2.top > 0.5 ? i2 : r2) };
return d2.maxY < d2.minY && (d2.minY = (d2.minY + d2.maxY) / 2, d2.maxY = d2.minY), d2.maxX < d2.minX && (d2.minX = (d2.minX + d2.maxX) / 2, d2.maxX = d2.minX), Rs(s2, a2, c2, i2, d2);
}
createTransitionRoute(t4, e2, n2, o2) {
const i2 = [{ x: t4.x, y: t4.y, z: t4.z ?? 0 }, { x: n2.x, y: n2.y, z: t4.z ?? 0 }, { x: n2.x, y: n2.y, z: e2.z ?? 0 }, { x: e2.x, y: e2.y, z: e2.z ?? 0 }];
return { connectionName: o2, regionId: this.nodeWithPortPoints.capacityMeshNodeId, route: i2, traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, vias: [n2] };
}
createFlatRoute(t4, e2, n2, o2, i2, r2) {
o2.z, t4.z;
const s2 = this.viaDiameter / 2 + this.traceThickness / 2 + this.obstacleMargin, a2 = ((t5, e3, n3, o3) => {
const i3 = n3.x - t5.x, r3 = n3.y - t5.y;
return ((t6, e4) => ({ x: (t6.x + e4.x) / 2, y: (t6.y + e4.y) / 2 }))({ x: t5.x + i3 * e3, y: t5.y + r3 * e3 }, { x: n3.x - i3 * o3, y: n3.y - r3 * o3 });
})(n2, this.viaDiameter, o2.z !== t4.z ? o2 : i2, this.traceThickness), c2 = { center: { x: n2.x, y: n2.y }, radius: s2 }, l2 = Es(t4, a2, c2).E, h2 = Es(a2, e2, c2).E, d2 = Es(t4, l2, c2).E, u2 = Es(l2, a2, c2).E, p2 = Es(a2, h2, c2).E, m2 = Es(h2, e2, c2).E, g2 = Es(u2, p2, c2).E;
return { connectionName: r2, regionId: this.nodeWithPortPoints.capacityMeshNodeId, route: [{ x: t4.x, y: t4.y, z: t4.z ?? 0 }, { x: d2.x, y: d2.y, z: t4.z ?? 0 }, { x: l2.x, y: l2.y, z: t4.z ?? 0 }, { x: u2.x, y: u2.y, z: t4.z ?? 0 }, { x: g2.x, y: g2.y, z: t4.z ?? 0 }, { x: p2.x, y: p2.y, z: t4.z ?? 0 }, { x: h2.x, y: h2.y, z: t4.z ?? 0 }, { x: m2.x, y: m2.y, z: t4.z ?? 0 }, { x: e2.x, y: e2.y, z: e2.z ?? 0 }], traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, vias: [] };
}
trySolve() {
const [t4, e2] = this.routes, n2 = t4.A.z !== t4.B.z, o2 = n2 ? t4 : e2, i2 = n2 ? e2 : t4, r2 = this.calculateViaPosition(o2, i2);
if (!r2)
return false;
this.debugViaPositions.push({ via: r2 });
const s2 = this.createTransitionRoute(o2.A, o2.B, r2, o2.connectionName), a2 = this.createFlatRoute(i2.A, i2.B, r2, o2.A, o2.B, i2.connectionName);
return this.solvedRoutes.push(s2, a2), true;
}
_step() {
if (!this.doRoutesCross(this.routes[0], this.routes[1]))
return this.failed = true, void (this.error = "Can only solve routes that have a single transition crossing");
this.trySolve() ? this.solved = true : (this.failed = true, this.error = "Failed to find a valid via position and route path");
}
visualize() {
const t4 = { lines: [], points: [], rects: [], circles: [] };
t4.rects.push({ center: { x: (this.bounds.minX + this.bounds.maxX) / 2, y: (this.bounds.minY + this.bounds.maxY) / 2 }, width: this.bounds.maxX - this.bounds.minX, height: this.bounds.maxY - this.bounds.minY, stroke: "rgba(0, 0, 0, 0.5)", fill: "rgba(240, 240, 240, 0.1)", label: "PCB Bounds" });
for (const e2 of this.routes)
t4.points.push({ x: e2.A.x, y: e2.A.y, label: `${e2.connectionName} start (z=${e2.A.z})`, color: "orange" }), t4.points.push({ x: e2.B.x, y: e2.B.y, label: `${e2.connectionName} end (z=${e2.B.z})`, color: "orange" }), t4.lines.push({ points: [e2.A, e2.B], strokeColor: "rgba(255, 0, 0, 0.5)", label: `${e2.connectionName} direct` });
for (let e2 = 0;e2 < this.debugViaPositions.length; e2++) {
const { via: n2 } = this.debugViaPositions[e2];
t4.circles.push({ center: n2, radius: this.viaDiameter / 2, fill: "rgba(255, 165, 0, 0.7)", stroke: "rgba(0, 0, 0, 0.5)", label: `Computed Via (attempt ${e2 + 1})` });
const o2 = this.viaDiameter / 2 + this.obstacleMargin;
t4.circles.push({ center: n2, radius: o2, stroke: "rgba(255, 165, 0, 0.7)", fill: "rgba(0, 0, 0, 0)", label: "Safety Margin" });
}
for (let e2 = 0;e2 < this.solvedRoutes.length; e2++) {
const n2 = this.solvedRoutes[e2], o2 = e2 % 2 == 0 ? "rgba(0, 255, 0, 0.75)" : "rgba(255, 0, 255, 0.75)";
for (let e3 = 0;e3 < n2.route.length - 1; e3++) {
const i2 = n2.route[e3], r2 = n2.route[e3 + 1];
t4.lines.push({ points: [i2, r2], strokeColor: o2, strokeDash: i2.z !== n2.route[0].z ? [0.2, 0.2] : undefined, strokeWidth: n2.traceThickness, label: `${n2.connectionName} z=${i2.z}` });
}
for (const e3 of n2.vias)
t4.circles.push({ center: e3, radius: this.viaDiameter / 2, fill: "rgba(0, 0, 255, 0.8)", stroke: "black", label: "Solved Via" }), t4.circles.push({ center: e3, radius: this.viaDiameter / 2 + this.obstacleMargin, fill: "rgba(0, 0, 255, 0.3)", stroke: "black", label: "Via Margin" });
}
return t4;
}
getSolvedRoutes() {
return this.solvedRoutes;
}
};
function Fs({ A: t4, B: e2, C: n2, D: o2, E: i2, F: r2, radius: s2, margin: a2, subdivisions: c2 = 0 }) {
const l2 = (t5, e3) => ({ x: (t5.x + e3.x) / 2, y: (t5.y + e3.y) / 2 }), h2 = (t5, e3, n3) => {
const o3 = e3.x - t5.x, i3 = e3.y - t5.y, r3 = Math.sqrt(o3 * o3 + i3 * i3), s3 = o3 / r3, a3 = i3 / r3, c3 = -a3, l3 = s3;
return { midpoint: { x: (t5.x + e3.x) / 2, y: (t5.y + e3.y) / 2 }, A_Opp: { x: t5.x - s3 * n3, y: t5.y - a3 * n3 }, A_Right: { x: t5.x + c3 * n3, y: t5.y + l3 * n3 }, A_Left: { x: t5.x - c3 * n3, y: t5.y - l3 * n3 }, B_Opp: { x: e3.x + s3 * n3, y: e3.y + a3 * n3 }, B_Right: { x: e3.x + c3 * n3, y: e3.y + l3 * n3 }, B_Left: { x: e3.x - c3 * n3, y: e3.y - l3 * n3 } };
}, d2 = (t5, e3) => {
const n3 = xe(t5, e3.start), o3 = xe(t5, e3.end), i3 = xe(e3.start, e3.end);
return Math.abs(n3 + o3 - i3) < 0.0001;
}, u2 = (t5, e3) => {
const { start: n3, end: o3 } = t5, { start: i3, end: r3 } = e3;
if (d2(n3, e3) || d2(o3, e3) || d2(i3, t5) || d2(r3, t5))
return true;
const s3 = o3.x - n3.x, a3 = o3.y - n3.y, c3 = r3.x - i3.x, l3 = r3.y - i3.y, h3 = s3 * l3 - a3 * c3;
if (Math.abs(h3) < 0.0001)
return false;
const u3 = i3.x - n3.x, p3 = i3.y - n3.y, m3 = (u3 * l3 - p3 * c3) / h3, g3 = (u3 * a3 - p3 * s3) / h3;
return m3 > 0 && m3 < 1 && g3 > 0 && g3 < 1;
}, p2 = (t5, e3) => {
const n3 = [];
for (let e4 = 0;e4 < t5.length - 1; e4++)
n3.push({ start: t5[e4], end: t5[e4 + 1] });
const o3 = [];
for (let t6 = 0;t6 < e3.length - 1; t6++)
o3.push({ start: e3[t6], end: e3[t6 + 1] });
for (const t6 of n3)
for (const e4 of o3)
if (u2(t6, e4))
return true;
return false;
}, m2 = (t5) => {
let e3 = 0;
for (let n3 = 1;n3 < t5.length; n3++) {
const o3 = t5[n3].x - t5[n3 - 1].x, i3 = t5[n3].y - t5[n3 - 1].y;
e3 += Math.sqrt(o3 * o3 + i3 * i3);
}
return e3;
}, g2 = (t5, e3) => {
const { start: n3, end: o3 } = t5, i3 = o3.x - n3.x, r3 = o3.y - n3.y, s3 = i3 * i3 + r3 * r3;
if (s3 === 0)
return { ...n3, t: 0 };
const a3 = Math.max(0, Math.min(1, ((e3.x - n3.x) * i3 + (e3.y - n3.y) * r3) / s3));
return { x: n3.x + a3 * i3, y: n3.y + a3 * r3, t: a3 };
}, f2 = (e3, n3, o3) => {
const i3 = g2(e3, n3);
if (xe(i3, n3) >= o3)
return i3;
const r3 = i3.x - n3.x, s3 = i3.y - n3.y, a3 = Math.sqrt(r3 * r3 + s3 * s3);
if (a3 === 0) {
const r4 = e3.end.x - e3.start.x, s4 = e3.end.y - e3.start.y, a4 = Math.sqrt(r4 * r4 + s4 * s4);
return { x: n3.x + o3 * r4 / a4, y: n3.y + o3 * s4 / a4, t: i3.t, isSpecial: true, specialType: n3 === t4 ? "A" : "B" };
}
return { x: n3.x + o3 * r3 / a3, y: n3.y + o3 * s3 / a3, t: i3.t, isSpecial: true, specialType: n3 === t4 ? "A" : "B" };
}, y2 = h2(t4, e2, s2), _2 = h2(t4, e2, s2 + a2), b2 = (t5, e3, n3, o3, i3) => {
const r3 = t5.points;
if (r3.length < 2)
return r3;
const a3 = n3 + o3, c3 = [r3[0]];
for (let t6 = 0;t6 < r3.length - 1; t6++) {
const n4 = { start: r3[t6], end: r3[t6 + 1] };
if (be(e3, n4.start, n4.end) < a3) {
const t7 = g2(n4, e3), o4 = t7.x - e3.x, i4 = t7.y - e3.y, r4 = Math.sqrt(o4 * o4 + i4 * i4);
let l3 = null;
if (r4 > 0.000001)
l3 = { x: e3.x + a3 * o4 / r4, y: e3.y + a3 * i4 / r4 };
else {
const t8 = n4.end.x - n4.start.x, o5 = n4.end.y - n4.start.y, i5 = Math.sqrt(t8 * t8 + o5 * o5);
i5 > 0.000001 && (l3 = { x: e3.x + a3 * t8 / i5, y: e3.y + a3 * o5 / i5 });
}
l3 && xe(n4.start, l3) > s2 / 10 && c3.push(l3);
}
xe(c3[c3.length - 1], n4.end) > s2 / 10 && c3.push(n4.end);
}
if (c3.length > 1) {
const t6 = [c3[0]];
for (let e4 = 1;e4 < c3.length; e4++)
xe(t6[t6.length - 1], c3[e4]) > s2 / 10 && t6.push(c3[e4]);
return t6;
}
return c3;
}, x2 = (() => {
const t5 = [[n2, y2.B_Left, y2.B_Opp, y2.B_Right, l2(y2.midpoint, l2(y2.B_Right, y2.A_Right)), l2(y2.midpoint, l2(y2.A_Left, y2.B_Left)), y2.A_Left, y2.A_Opp, y2.A_Right, o2], [n2, y2.B_Right, y2.B_Opp, y2.B_Left, l2(y2.midpoint, l2(y2.A_Left, y2.B_Left)), l2(y2.midpoint, l2(y2.A_Right, y2.B_Right)), y2.A_Right, y2.A_Opp, y2.A_Left, o2], [o2, y2.B_Left, y2.B_Opp, y2.B_Right, l2(y2.midpoint, l2(y2.A_Right, y2.B_Right)), l2(y2.midpoint, l2(y2.A_Left, y2.B_Left)), y2.A_Left, y2.A_Opp, y2.A_Right, n2], [o2, y2.B_Right, y2.B_Opp, y2.B_Left, l2(y2.midpoint, l2(y2.A_Left, y2.B_Left)), l2(y2.midpoint, l2(y2.A_Right, y2.B_Right)), y2.A_Right, y2.A_Opp, y2.A_Left, n2]], e3 = [];
for (let n3 = 0;n3 < t5.length; n3++) {
const o3 = t5[n3], i4 = { start: o3[0], end: o3[1] }, r4 = { start: o3[o3.length - 2], end: o3[o3.length - 1] }, s4 = { start: o3[3], end: o3[4] };
u2(i4, r4) || u2(i4, s4) || u2(r4, s4) || e3.push({ index: n3 + 1, path: o3, length: m2(o3) });
}
if (e3.length === 0)
return { index: 0, path: [] };
const i3 = e3.sort((t6, e4) => t6.length - e4.length)[0], r3 = [...i3.path], s3 = r3[0], a3 = xe(s3, r3[2]), c3 = xe(s3, r3[3]), h3 = a3 < c3 ? 2 : 3;
(a3 < xe(s3, r3[1]) || c3 < xe(s3, r3[1])) && r3.splice(1, h3 - 1);
const d3 = r3[r3.length - 1], p3 = xe(d3, r3[r3.length - 3]), g3 = xe(d3, r3[r3.length - 4]), f3 = p3 < g3 ? r3.length - 3 : r3.length - 4;
return (p3 < xe(d3, r3[r3.length - 2]) || g3 < xe(d3, r3[r3.length - 2])) && r3.splice(f3 + 1, r3.length - f3 - 2), { index: i3.index, path: r3, startsAt: r3[0] === n2 ? "C" : "D", goesTo: r3[r3.length - 1] === n2 ? "C" : "D" };
})(), v2 = c2 > 0 ? ((n3, o3) => {
if (n3.length < 2)
return n3;
const i3 = [n3[0]];
for (let r3 = 0;r3 < n3.length - 1; r3++) {
const a3 = { start: n3[r3], end: n3[r3 + 1] }, c3 = { x: (a3.start.x + a3.end.x) / 2, y: (a3.start.y + a3.end.y) / 2 }, l3 = xe(c3, t4), h3 = xe(c3, e2);
if ((l3 <= s2 || h3 <= s2) && Math.abs(l3 - h3) > 0.0001) {
const n4 = g2(a3, t4), r4 = g2(a3, e2), c4 = xe(n4, t4), l4 = xe(r4, e2) < s2, h4 = c4 < s2 ? f2(a3, t4, s2) : null, d3 = l4 ? f2(a3, e2, s2) : null;
let u3 = [];
if (xe(a3.start, a3.end) > s2 / 2 && o3 > 0)
for (let n5 = 1;n5 <= o3; n5++) {
const i4 = n5 / (o3 + 1), r5 = { x: a3.start.x + i4 * (a3.end.x - a3.start.x), y: a3.start.y + i4 * (a3.end.y - a3.start.y), t: i4, isSpecial: false }, c5 = xe(r5, t4), l5 = xe(r5, e2);
c5 < s2 || l5 < s2 || (h4 && Math.abs(r5.t - h4.t) < 0.1 || d3 && Math.abs(r5.t - d3.t) < 0.1 || u3.push(r5));
}
if (h4 && u3.push(h4), d3 && u3.push(d3), u3.sort((t5, e3) => t5.t - e3.t), u3.length > 1) {
const t5 = [u3[0]];
for (let e3 = 1;e3 < u3.length; e3++) {
const n5 = t5[t5.length - 1], o4 = u3[e3];
xe(n5, o4) > s2 / 10 && t5.push(o4);
}
u3 = t5;
}
u3.forEach((t5) => i3.push(t5));
}
i3.push(n3[r3 + 1]);
}
if (i3.length > 1) {
const t5 = [i3[0]];
for (let e3 = 1;e3 < i3.length; e3++) {
const n4 = t5[t5.length - 1], o4 = i3[e3];
xe(n4, o4) > s2 / 10 && t5.push(o4);
}
return t5;
}
return i3;
})(x2.path, c2) : x2.path;
let I2 = (() => {
if (x2.path.length === 0)
return null;
const n3 = (() => {
const n4 = l2(y2.A_Right, y2.B_Right), o4 = l2(y2.B_Left, y2.A_Left);
return [{ startsAt: "E", goesTo: "B", points: [i2, e2] }, { startsAt: "E", goesTo: "A", points: [i2, t4] }, { startsAt: "F", goesTo: "B", points: [r2, e2] }, { startsAt: "F", goesTo: "A", points: [r2, t4] }, { startsAt: "E", goesTo: "B", points: [i2, n4, e2] }, { startsAt: "E", goesTo: "A", points: [i2, n4, t4] }, { startsAt: "F", goesTo: "B", points: [r2, n4, e2] }, { startsAt: "F", goesTo: "A", points: [r2, n4, t4] }, { startsAt: "E", goesTo: "B", points: [i2, o4, e2] }, { startsAt: "E", goesTo: "A", points: [i2, o4, t4] }, { startsAt: "F", goesTo: "B", points: [r2, o4, e2] }, { startsAt: "F", goesTo: "A", points: [r2, o4, t4] }, { startsAt: "E", goesTo: "B", points: [i2, _2.A_Right, n4, e2] }, { startsAt: "F", goesTo: "B", points: [r2, _2.B_Right, n4, e2] }, { startsAt: "E", goesTo: "A", points: [i2, _2.B_Left, o4, t4] }, { startsAt: "F", goesTo: "A", points: [r2, _2.A_Left, o4, t4] }, { startsAt: "E", goesTo: "B", points: [i2, _2.A_Left, o4, e2] }, { startsAt: "E", goesTo: "A", points: [i2, _2.B_Right, n4, t4] }, { startsAt: "E", goesTo: "B", points: [i2, _2.A_Opp, _2.A_Right, n4, e2] }, { startsAt: "E", goesTo: "A", points: [i2, _2.B_Opp, _2.B_Left, o4, t4] }, { startsAt: "F", goesTo: "B", points: [r2, _2.A_Opp, _2.A_Left, o4, e2] }, { startsAt: "F", goesTo: "A", points: [r2, _2.B_Opp, _2.B_Right, n4, t4] }, { startsAt: "F", goesTo: "A", points: [r2, _2.B_Opp, _2.B_Left, o4, t4] }, { startsAt: "E", goesTo: "B", points: [i2, _2.A_Opp, _2.A_Left, o4, e2] }, { startsAt: "E", goesTo: "A", points: [i2, _2.B_Opp, _2.B_Right, n4, t4] }, { startsAt: "E", goesTo: "B", points: [i2, _2.A_Left, _2.A_Opp, _2.A_Right, n4, e2] }, { startsAt: "E", goesTo: "A", points: [i2, _2.B_Right, _2.B_Opp, _2.B_Left, o4, t4] }, { startsAt: "F", goesTo: "B", points: [r2, _2.A_Right, _2.A_Opp, _2.A_Left, o4, e2] }, { startsAt: "F", goesTo: "A", points: [r2, _2.B_Left, _2.B_Opp, _2.B_Right, n4, t4] }, { startsAt: "F", goesTo: "A", points: [r2, _2.B_Right, _2.B_Opp, _2.B_Left, o4, t4] }, { startsAt: "E", goesTo: "B", points: [i2, _2.A_Right, _2.A_Opp, _2.A_Left, o4, e2] }, { startsAt: "E", goesTo: "A", points: [i2, _2.B_Left, _2.B_Opp, _2.B_Right, n4, t4] }].map((t5, e3) => ({ ...t5, index: e3 }));
})(), o3 = n3.filter((t5) => t5.startsAt === "E"), s3 = n3.filter((t5) => t5.startsAt === "F"), a3 = [], c3 = [];
for (const t5 of o3)
if (!p2(t5.points, x2.path)) {
a3.push(t5);
break;
}
for (const t5 of s3)
if (!p2(t5.points, x2.path)) {
c3.push(t5);
break;
}
return a3.length === 0 || c3.length === 0 ? null : { line1: a3[0], line2: c3[0] };
})();
if (I2) {
const n3 = I2.line1.goesTo === "A" ? e2 : t4, o3 = I2.line2.goesTo === "A" ? e2 : t4, i3 = b2(I2.line1, n3, s2, a2), r3 = b2(I2.line2, o3, s2, a2);
I2 = { line1: { ...I2.line1, points: i3 }, line2: { ...I2.line2, points: r3 } };
}
return { jPair: I2, optimalPath: { startsAt: x2.startsAt, goesTo: x2.goesTo, points: v2 } };
}
var js = class extends si {
getSolverName() {
return "TwoCrossingRoutesHighDensitySolver";
}
nodeWithPortPoints;
routes;
viaDiameter;
traceThickness;
obstacleMargin;
layerCount = 2;
debugViaPositions;
escapeLayer = 1;
solvedRoutes = [];
bounds;
constructor(t4) {
if (super(), this.nodeWithPortPoints = t4.nodeWithPortPoints, this.viaDiameter = t4?.viaDiameter ?? 0.3, this.traceThickness = t4?.traceThickness ?? 0.15, this.obstacleMargin = t4?.obstacleMargin ?? 0.1, this.layerCount = t4?.layerCount ?? 2, this.debugViaPositions = [], this.routes = this.extractRoutesFromNode(), this.bounds = this.calculateBounds(), this.routes.length !== 2)
return this.failed = true, void (this.error = `Expected 2 routes, but got ${this.routes.length}`);
const [e2, n2] = this.routes;
if (!(e2.startPort.z === e2.endPort.z))
return this.failed = true, void (this.error = "Route A must start and end on the same layer");
if (!(n2.startPort.z === n2.endPort.z))
return this.failed = true, void (this.error = "Route B must start and end on the same layer");
if (!(e2.startPort.z === n2.startPort.z))
return this.failed = true, void (this.error = "Both routes must be on the same layer");
e2.startPort.z === 0 ? this.escapeLayer = 1 : this.escapeLayer = 0;
}
extractRoutesFromNode() {
const t4 = [], e2 = this.nodeWithPortPoints.portPoints, n2 = new Map;
for (const t5 of e2) {
const { connectionName: e3 } = t5;
n2.has(e3) || n2.set(e3, []), n2.get(e3)?.push(t5);
}
for (const [e3, o2] of n2.entries())
o2.length === 2 && t4.push({ startPort: { ...o2[0], z: o2[0].z ?? 0 }, endPort: { ...o2[1], z: o2[1].z ?? 0 }, connectionName: e3 });
return t4;
}
calculateBounds() {
return { minX: this.nodeWithPortPoints.center.x - this.nodeWithPortPoints.width / 2, maxX: this.nodeWithPortPoints.center.x + this.nodeWithPortPoints.width / 2, minY: this.nodeWithPortPoints.center.y - this.nodeWithPortPoints.height / 2, maxY: this.nodeWithPortPoints.center.y + this.nodeWithPortPoints.height / 2 };
}
doRoutesCross(t4, e2) {
return fe(t4.startPort, t4.endPort, e2.startPort, e2.endPort);
}
calculateViaPositions(t4, e2) {
const n2 = this.bounds.maxX - this.bounds.minX, o2 = this.bounds.maxY - this.bounds.minY, i2 = this.bounds.minX, r2 = this.bounds.minY, s2 = { width: n2 - 2 * this.obstacleMargin - this.viaDiameter, height: o2 - 2 * this.obstacleMargin - this.viaDiameter, x: i2 + this.obstacleMargin + this.viaDiameter / 2, y: r2 + this.obstacleMargin + this.viaDiameter / 2 }, a2 = this.viaDiameter + this.obstacleMargin, c2 = e2.startPort, l2 = e2.endPort, h2 = [{ x: s2.x, y: s2.y }, { x: s2.x + s2.width, y: s2.y }, { x: s2.x + s2.width, y: s2.y + s2.height }, { x: s2.x, y: s2.y + s2.height }], d2 = (t5, e3) => xe(t5, e3), u2 = [];
h2.forEach((t5, e3) => {
d2(t5, c2) >= a2 && d2(t5, l2) >= a2 && u2.push({ ...t5, type: "corner", index: e3 });
});
const p2 = [{ p1: h2[0], p2: h2[1] }, { p1: h2[1], p2: h2[2] }, { p1: h2[2], p2: h2[3] }, { p1: h2[3], p2: h2[0] }];
if ([c2, l2].forEach((t5, e3) => {
p2.forEach((n3, o3) => {
((t6, e4) => {
const { x: n4, y: o4, r: i3 } = t6, r3 = e4.p1.x, s3 = e4.p1.y, a3 = e4.p2.x, c3 = e4.p2.y;
if (Math.abs(a3 - r3) < 0.001) {
const t7 = r3, e5 = i3 * i3 - (t7 - n4) ** 2;
if (e5 < 0)
return [];
if (Math.abs(e5) < 0.001) {
const e6 = o4;
return e6 >= Math.min(s3, c3) && e6 <= Math.max(s3, c3) ? [{ x: t7, y: e6 }] : [];
}
const a4 = o4 + Math.sqrt(e5), l4 = o4 - Math.sqrt(e5), h4 = [];
return a4 >= Math.min(s3, c3) && a4 <= Math.max(s3, c3) && h4.push({ x: t7, y: a4 }), l4 >= Math.min(s3, c3) && l4 <= Math.max(s3, c3) && h4.push({ x: t7, y: l4 }), h4;
}
const l3 = (c3 - s3) / (a3 - r3), h3 = s3 - l3 * r3, d3 = 1 + l3 * l3, u3 = 2 * (l3 * h3 - l3 * o4 - n4), p3 = u3 * u3 - 4 * d3 * (n4 * n4 + (h3 - o4) * (h3 - o4) - i3 * i3);
if (p3 < 0)
return [];
if (Math.abs(p3) < 0.001) {
const t7 = -u3 / (2 * d3), e5 = l3 * t7 + h3;
return t7 >= Math.min(r3, a3) && t7 <= Math.max(r3, a3) && e5 >= Math.min(s3, c3) && e5 <= Math.max(s3, c3) ? [{ x: t7, y: e5 }] : [];
}
const m3 = (-u3 + Math.sqrt(p3)) / (2 * d3), g3 = (-u3 - Math.sqrt(p3)) / (2 * d3), f3 = l3 * m3 + h3, y3 = l3 * g3 + h3, _3 = [];
return m3 >= Math.min(r3, a3) && m3 <= Math.max(r3, a3) && f3 >= Math.min(s3, c3) && f3 <= Math.max(s3, c3) && _3.push({ x: m3, y: f3 }), g3 >= Math.min(r3, a3) && g3 <= Math.max(r3, a3) && y3 >= Math.min(s3, c3) && y3 <= Math.max(s3, c3) && _3.push({ x: g3, y: y3 }), _3;
})({ ...t5, r: a2 }, n3).forEach((t6) => {
d2(t6, e3 === 0 ? l2 : c2) >= a2 && u2.push({ ...t6, type: "intersection", circle: e3, edge: o3 });
});
});
}), u2.length < 2) {
const t5 = 0.8 * a2;
if (h2.forEach((e3, n3) => {
d2(e3, c2) >= t5 && d2(e3, l2) >= t5 && !u2.some((t6) => t6.x === e3.x && t6.y === e3.y) && u2.push({ ...e3, type: "relaxed_corner", index: n3 });
}), u2.length < 2) {
const t6 = [...h2].sort((t7, e3) => {
const n3 = Math.min(d2(t7, c2), d2(t7, l2));
return Math.min(d2(e3, c2), d2(e3, l2)) - n3;
});
for (const e3 of t6)
if (!u2.some((t7) => t7.x === e3.x && t7.y === e3.y) && (u2.push({ ...e3, type: "forced_corner" }), u2.length >= 2))
break;
}
}
if (u2.length < 2)
return null;
let m2 = 0, g2 = [u2[0], u2[u2.length > 1 ? 1 : 0]];
for (let t5 = 0;t5 < u2.length; t5++)
for (let e3 = t5 + 1;e3 < u2.length; e3++) {
const n3 = d2(u2[t5], u2[e3]);
n3 > m2 && (m2 = n3, g2 = [u2[t5], u2[e3]]);
}
let f2 = { x: g2[0].x, y: g2[0].y }, y2 = { x: g2[1].x, y: g2[1].y };
const _2 = xe(f2, t4.startPort);
return xe(y2, t4.startPort) < _2 && ([f2, y2] = [y2, f2]), { via1: f2, via2: y2 };
}
trySolveAOverB(t4, e2, n2 = false) {
const o2 = n2 ? this.calculateViaPositions(t4, e2) : this.calculateViaPositions(e2, t4);
if (!o2)
return false;
this.debugViaPositions.push(o2);
const { via1: i2, via2: r2 } = this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(o2));
this.debugViaPositions.push({ via1: i2, via2: r2 });
const { jPair: s2, optimalPath: a2 } = Fs({ A: i2, B: r2, C: t4.startPort, D: t4.endPort, E: e2.startPort, F: e2.endPort, radius: this.viaDiameter / 2 + this.obstacleMargin + this.traceThickness / 2 * 1.5, margin: 2 * this.obstacleMargin + this.traceThickness / 2 * 1.5, subdivisions: 1 });
if (!s2)
return false;
const c2 = { connectionName: t4.connectionName, regionId: this.nodeWithPortPoints.capacityMeshNodeId, route: a2.points.map((e3) => ({ x: e3.x, y: e3.y, z: t4.startPort.z ?? 0 })), traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, vias: [] };
s2.line2.points.reverse();
const l2 = { connectionName: e2.connectionName, regionId: this.nodeWithPortPoints.capacityMeshNodeId, route: [...s2.line1.points.map((t5) => ({ x: t5.x, y: t5.y, z: e2.startPort.z ?? 0 })), { ...s2.line1.points[s2.line1.points.length - 1], z: this.escapeLayer }, { ...s2.line2.points[0], z: this.escapeLayer }, ...s2.line2.points.map((t5) => ({ x: t5.x, y: t5.y, z: e2.startPort.z ?? 0 }))], traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, vias: [i2, r2] };
return this.solvedRoutes.push(c2, l2), true;
}
pushViasFromEndpoints(t4) {
const e2 = { ...t4.via1 }, n2 = { ...t4.via2 }, o2 = [this.routes[0].startPort, this.routes[0].endPort, this.routes[1].startPort, this.routes[1].endPort], i2 = this.getMinDistanceBetweenViaCenters(), r2 = this.viaDiameter / 2 + 2 * this.traceThickness + 2 * this.obstacleMargin;
for (let t5 = 0;t5 < 10; t5++) {
let s3 = false, a2 = false;
const c2 = 0.9 ** t5;
for (const t6 of o2) {
const o3 = xe(e2, t6);
if (o3 < r2) {
const n3 = (r2 - o3) * c2, i4 = e2.x - t6.x, a3 = e2.y - t6.y, l3 = Math.sqrt(i4 * i4 + a3 * a3);
l3 > 0.000001 && (e2.x += i4 / l3 * n3, e2.y += a3 / l3 * n3, s3 = true);
}
const i3 = xe(n2, t6);
if (i3 < r2) {
const e3 = (r2 - i3) * c2, o4 = n2.x - t6.x, s4 = n2.y - t6.y, l3 = Math.sqrt(o4 * o4 + s4 * s4);
l3 > 0.000001 && (n2.x += o4 / l3 * e3, n2.y += s4 / l3 * e3, a2 = true);
}
}
const l2 = xe(e2, n2);
if (l2 < i2) {
const t6 = (i2 - l2) / 2, o3 = n2.x - e2.x, r3 = n2.y - e2.y, c3 = Math.sqrt(o3 * o3 + r3 * r3);
c3 > 0.000001 ? (e2.x -= o3 / c3 * t6, e2.y -= r3 / c3 * t6, n2.x += o3 / c3 * t6, n2.y += r3 / c3 * t6, s3 = true, a2 = true) : (e2.x -= t6, n2.x += t6, s3 = true, a2 = true);
}
if (!s3 && !a2)
break;
}
const s2 = xe(e2, n2);
if (s2 < i2) {
const t5 = (i2 - s2) / 2, o3 = n2.x - e2.x, r3 = n2.y - e2.y, a2 = Math.sqrt(o3 * o3 + r3 * r3);
a2 > 0.000001 ? (e2.x -= o3 / a2 * t5, e2.y -= r3 / a2 * t5, n2.x += o3 / a2 * t5, n2.y += r3 / a2 * t5) : (e2.x -= t5, n2.x += t5);
}
return { via1: e2, via2: n2 };
}
getMinDistanceBetweenViaCenters() {
return this.viaDiameter + this.traceThickness + 2 * this.obstacleMargin;
}
moveViasAsCloseAsPossible(t4) {
const { via1: e2, via2: n2 } = t4, o2 = this.getMinDistanceBetweenViaCenters(), i2 = xe(e2, n2);
if (i2 <= o2)
return t4;
const r2 = n2.x - e2.x, s2 = n2.y - e2.y, a2 = Math.sqrt(r2 * r2 + s2 * s2), c2 = r2 / a2, l2 = s2 / a2, h2 = (e2.x, n2.x, e2.y, n2.y, (i2 - o2) / 2);
return { via1: { x: e2.x + c2 * h2, y: e2.y + l2 * h2 }, via2: { x: n2.x - c2 * h2, y: n2.y - l2 * h2 } };
}
handleRoutesDontCross() {
const [t4, e2] = this.routes, n2 = { connectionName: t4.connectionName, regionId: this.nodeWithPortPoints.capacityMeshNodeId, route: [{ x: t4.startPort.x, y: t4.startPort.y, z: t4.startPort.z ?? 0 }, { x: t4.endPort.x, y: t4.endPort.y, z: t4.endPort.z ?? 0 }], traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, vias: [] }, o2 = { connectionName: e2.connectionName, regionId: this.nodeWithPortPoints.capacityMeshNodeId, route: [{ x: e2.startPort.x, y: e2.startPort.y, z: e2.startPort.z ?? 0 }, { x: e2.endPort.x, y: e2.endPort.y, z: e2.endPort.z ?? 0 }], traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, vias: [] };
this.solvedRoutes.push(n2, o2), this.solved = true;
}
_step() {
if (this.routes.length !== 2)
return void (this.failed = true);
const [t4, e2] = this.routes;
this.doRoutesCross(t4, e2) ? this.trySolveAOverB(t4, e2) || this.trySolveAOverB(e2, t4) || this.trySolveAOverB(t4, e2, true) || this.trySolveAOverB(e2, t4, true) ? this.solved = true : (this.failed = true, this.error = "All crossover strategies failed") : this.handleRoutesDontCross();
}
visualize() {
const t4 = { lines: [], points: [], rects: [], circles: [] };
t4.rects.push({ center: { x: (this.bounds.minX + this.bounds.maxX) / 2, y: (this.bounds.minY + this.bounds.maxY) / 2 }, width: this.bounds.maxX - this.bounds.minX, height: this.bounds.maxY - this.bounds.minY, stroke: "rgba(0, 0, 0, 0.5)", fill: "rgba(240, 240, 240, 0.1)" });
for (const [e2, n2] of [["Route A", this.routes[0]], ["Route B", this.routes[1]]])
t4.points.push({ x: n2.startPort.x, y: n2.startPort.y, label: `${e2}
${n2.connectionName} start`, color: "orange" }), t4.points.push({ x: n2.endPort.x, y: n2.endPort.y, label: `${e2}
${n2.connectionName} end`, color: "orange" }), t4.lines.push({ points: [n2.startPort, n2.endPort], strokeColor: "rgba(255, 0, 0, 0.5)", label: `${e2}
${n2.connectionName} direct` });
for (let e2 = 0;e2 < this.debugViaPositions.length; e2++) {
const { via1: n2, via2: o2 } = this.debugViaPositions[e2], i2 = ["rgba(255, 165, 0, 0.3)", "rgba(128, 0, 128, 0.3)"], r2 = i2[e2 % i2.length];
t4.circles.push({ center: n2, radius: this.viaDiameter / 2, fill: r2, stroke: "rgba(0, 0, 0, 0.3)", label: `Computed Via A (attempt ${e2 + 1})` }), t4.circles.push({ center: o2, radius: this.viaDiameter / 2, fill: r2, stroke: "rgba(0, 0, 0, 0.3)", label: `Computed Via B (attempt ${e2 + 1})` });
const s2 = this.viaDiameter / 2 + this.obstacleMargin;
t4.circles.push({ center: n2, radius: s2, stroke: r2, fill: "rgba(0, 0, 0, 0)", label: `Debug Via 1 Safety Margin (attempt ${e2 + 1})` }), t4.circles.push({ center: o2, radius: s2, stroke: r2, fill: "rgba(0, 0, 0, 0)", label: `Debug Via 2 Safety Margin (attempt ${e2 + 1})` }), t4.lines.push({ points: [this.routes[e2 % 2].startPort, n2, o2, this.routes[e2 % 2].endPort], strokeColor: `${r2.substring(0, r2.lastIndexOf(","))}, 0.3)`, strokeDash: [5, 5], label: `Potential Route (attempt ${e2 + 1})` });
}
for (let e2 = 0;e2 < this.solvedRoutes.length; e2++) {
const n2 = this.solvedRoutes[e2], o2 = e2 % 2 == 0 ? "rgba(0, 255, 0, 0.75)" : "rgba(255, 0, 255, 0.75)";
for (let e3 = 0;e3 < n2.route.length - 1; e3++) {
const i2 = n2.route[e3], r2 = n2.route[e3 + 1];
t4.lines.push({ points: [i2, r2], strokeColor: o2, strokeDash: i2.z === 1 ? [0.2, 0.2] : undefined, strokeWidth: n2.traceThickness, label: `${n2.connectionName} z=${i2.z}` }), i2._label && t4.points.push({ x: i2.x, y: i2.y, label: i2._label });
}
for (const e3 of n2.vias)
t4.circles.push({ center: e3, radius: this.viaDiameter / 2, fill: "rgba(0, 0, 255, 0.8)", stroke: "black", label: "Solved Via" }), t4.circles.push({ center: e3, radius: this.viaDiameter / 2 + this.obstacleMargin, fill: "rgba(0, 0, 255, 0.3)", stroke: "black", label: "Solved Via Margin" });
}
return t4;
}
getSolvedRoutes() {
return this.solvedRoutes;
}
};
var $s = class extends si {
getSolverName() {
return "HyperParameterSupervisorSolver";
}
GREEDY_MULTIPLIER = 1.2;
MIN_SUBSTEPS = 1;
supervisedSolvers;
winningSolver;
getHyperParameterDefs() {
throw new Error("Not implemented");
}
getCombinationDefs() {
return null;
}
getHyperParameterCombinations(t4) {
t4 || (t4 = this.getHyperParameterDefs());
const e2 = [];
if (t4.length === 0)
return [{}];
const [n2, ...o2] = t4, i2 = this.getHyperParameterCombinations(o2);
return n2.possibleValues.forEach((t5) => {
i2.forEach((n3) => {
e2.push({ ...n3, ...t5 });
});
}), e2;
}
initializeSolvers() {
const t4 = this.getHyperParameterDefs(), e2 = this.getCombinationDefs() ?? [t4.map((t5) => t5.name)];
this.supervisedSolvers = [];
for (const n2 of e2) {
const e3 = this.getHyperParameterCombinations(t4.filter((t5) => n2.includes(t5.name)));
for (const t5 of e3) {
const e4 = this.generateSolver(t5), n3 = this.computeG(e4);
this.supervisedSolvers.push({ hyperParameters: t5, solver: e4, h: 0, g: n3, f: n3 });
}
}
}
generateSolver(t4) {
throw new Error("Not implemented");
}
computeG(t4) {
return t4.iterations / t4.MAX_ITERATIONS;
}
computeH(t4) {
return 1 - (t4.progress || 0);
}
computeF(t4, e2) {
return t4 + e2 * this.GREEDY_MULTIPLIER;
}
getSupervisedSolverWithBestFitness() {
let t4 = 1 / 0, e2 = null;
for (const n2 of this.supervisedSolvers ?? []) {
if (n2.solver.solved)
return n2;
if (n2.solver.failed)
continue;
const o2 = n2.f;
o2 < t4 && (t4 = o2, e2 = n2);
}
return e2;
}
getFailureMessage() {
return `All solvers failed in hyper solver. Example failures: ${this.supervisedSolvers?.sort((t4, e2) => e2.f - t4.f)?.slice(0, 5).map((t4) => t4.solver.error).join(", ")}`;
}
_step() {
this.supervisedSolvers || this.initializeSolvers();
const t4 = this.getSupervisedSolverWithBestFitness();
if (!t4)
return this.failed = true, void (this.error = this.getFailureMessage());
for (let e2 = 0;e2 < this.MIN_SUBSTEPS; e2++)
t4.solver.step();
this.activeSubSolver = t4.solver, t4.g = this.computeG(t4.solver), t4.h = this.computeH(t4.solver), t4.f = this.computeF(t4.g, t4.h), t4.solver.solved && (this.solved = true, this.winningSolver = t4.solver, this.onSolve?.(t4));
}
onSolve(t4) {}
visualize() {
const t4 = this.getSupervisedSolverWithBestFitness();
let e2 = { lines: [], circles: [], points: [], rects: [] };
return t4 && (e2 = t4.solver.visualize()), e2;
}
};
function Ys(t4, e2, n2) {
const o2 = e2.z !== n2.z && t4.allowBlindAndBuriedVias !== true;
return { minZ: o2 ? 0 : Math.min(e2.z, n2.z), maxZ: o2 ? t4.layerCount - 1 : Math.max(e2.z, n2.z) };
}
var Xs = class {
values = [];
positions;
constructor(t4) {
if (t4 === undefined)
this.positions = new Map;
else {
if (!Number.isSafeInteger(t4) || t4 <= 0)
throw new Error("repair04: dense path queue requires a positive grid size");
const e2 = new Int32Array(t4);
this.positions = { get: (t5) => e2[t5] === 0 ? undefined : e2[t5] - 1, set: (t5, n2) => {
e2[t5] = n2 + 1;
}, delete: (t5) => {
e2[t5] = 0;
} };
}
}
get length() {
return this.values.length;
}
push(t4) {
let e2 = this.positions.get(t4.id);
if (e2 === undefined)
e2 = this.values.length, this.values.push(t4);
else if (t4.priority > this.values[e2].priority)
throw new Error("repair04: queued path priorities may only decrease");
for (;e2 > 0; ) {
const n2 = Math.floor((e2 - 1) / 2), o2 = this.values[n2];
if (o2.priority <= t4.priority)
break;
this.values[e2] = o2, this.positions.set(o2.id, e2), e2 = n2;
}
this.values[e2] = t4, this.positions.set(t4.id, e2);
}
pop() {
const t4 = this.values[0];
if (!t4)
throw new Error("repair04: cannot pop an empty path queue");
const e2 = this.values.pop();
if (this.positions.delete(t4.id), this.values.length) {
let t5 = 0;
for (;2 * t5 + 1 < this.values.length; ) {
let n2 = 2 * t5 + 1;
n2 + 1 < this.values.length && this.values[n2 + 1].priority < this.values[n2].priority && n2++;
const o2 = this.values[n2];
if (o2.priority >= e2.priority)
break;
this.values[t5] = o2, this.positions.set(o2.id, t5), t5 = n2;
}
this.values[t5] = e2, this.positions.set(e2.id, t5);
}
return t4;
}
};
var Ws = (t4, e2) => {
const n2 = [];
for (let o2 = 0;o2 < t4.route.length; o2 += 1) {
const i2 = t4.route[o2];
if (i2.route_type !== "via") {
n2.push(structuredClone(i2));
continue;
}
const r2 = n2[n2.length - 1], s2 = t4.route[o2 + 1], a2 = r2?.route_type === "wire" ? r2.width : s2?.route_type === "wire" ? s2.width : e2, c2 = s2?.route_type === "wire" ? s2.width : a2;
r2?.route_type === "wire" && r2.x === i2.x && r2.y === i2.y && r2.layer === i2.from_layer || n2.push({ route_type: "wire", x: i2.x, y: i2.y, layer: i2.from_layer, width: a2 }), n2.push(structuredClone(i2)), s2?.route_type === "wire" && s2.x === i2.x && s2.y === i2.y && s2.layer === i2.to_layer || n2.push({ route_type: "wire", x: i2.x, y: i2.y, layer: i2.to_layer, width: c2 });
}
return { ...structuredClone(t4), route: n2 };
};
function Vs(t4, e2, n2) {
return Math.max(n2 ? 0 : e2, t4.defaultObstacleMargin ?? 0, t4.minViaEdgeToPadEdgeClearance ?? 0);
}
var Hs = 0.00000001;
var Gs = (t4, e2, n2 = 0) => t4.x >= e2.minX + n2 - Hs && t4.x <= e2.maxX - n2 + Hs && t4.y >= e2.minY + n2 - Hs && t4.y <= e2.maxY - n2 + Hs;
var Us = (t4, e2, n2) => {
let o2 = 0, i2 = 1;
for (const [r2, s2, a2, c2] of [[t4.x, e2.x - t4.x, n2.minX, n2.maxX], [t4.y, e2.y - t4.y, n2.minY, n2.maxY]]) {
if (r2 === undefined || s2 === undefined || a2 === undefined || c2 === undefined)
throw new Error("Invalid segment clipping axis");
if (Math.abs(s2) <= Hs) {
if (r2 < a2 - Hs || r2 > c2 + Hs)
return;
continue;
}
const t5 = (a2 - r2) / s2, e3 = (c2 - r2) / s2;
if (o2 = Math.max(o2, Math.min(t5, e3)), i2 = Math.min(i2, Math.max(t5, e3)), i2 < o2 - Hs)
return;
}
return [Math.max(0, o2), Math.min(1, i2)];
};
var Zs = (t4, e2, n2) => {
if (n2 <= Hs)
return structuredClone(t4);
if (n2 >= 0.99999999)
return structuredClone(e2);
const o2 = { ...structuredClone(t4), x: t4.x + (e2.x - t4.x) * n2, y: t4.y + (e2.y - t4.y) * n2 };
return delete o2.pcb_port_id, o2;
};
var qs = (t4, e2) => Math.abs(t4.x - e2.x) <= Hs && Math.abs(t4.y - e2.y) <= Hs && t4.z === e2.z;
var Js = (t4) => Array.isArray(t4) ? `[${t4.map(Js).join(",")}]` : t4 !== null && typeof t4 == "object" ? `{${Object.keys(t4).filter((e2) => t4[e2] !== undefined).sort().map((e2) => `${JSON.stringify(e2)}:${Js(t4[e2])}`).join(",")}}` : JSON.stringify(t4) ?? "undefined";
var Qs = (t4, e2, n2) => {
if (t4.route.length === 1)
return structuredClone(t4.route);
const o2 = (e3) => {
const n3 = Math.min(Math.floor(e3), t4.route.length - 2);
return Zs(t4.route[n3], t4.route[n3 + 1], e3 - n3);
}, i2 = [o2(e2)];
for (let o3 = Math.floor(e2) + 1;o3 < n2 - Hs; o3 += 1)
i2.push(structuredClone(t4.route[o3]));
return n2 > e2 + Hs && i2.push(o2(n2)), i2;
};
var Ks = (t4, e2, n2) => {
const o2 = Qs(t4, e2, n2), i2 = Object.fromEntries(Object.entries(t4).filter(([t5]) => t5 !== "route" && t5 !== "vias")), r2 = t4.vias.filter((t5) => o2.some((e3) => Math.hypot(e3.x - t5.x, e3.y - t5.y) <= Hs));
return Js({ metadata: i2, points: o2, vias: r2 });
};
function ta(t4) {
const { srj: e2, routes: n2, routeIndex: o2, start: i2, end: r2, bounds: s2, traceThickness: a2 } = t4, c2 = t4.heuristicWeight ?? 1;
if (!Number.isFinite(c2) || c2 < 1)
throw new Error("repair04: heuristic weight must be finite and at least one");
const l2 = (e3, n3) => {
const o3 = t4.getAdditionalEdgeCost?.(e3, n3) ?? 0;
if (Number.isNaN(o3) || o3 < 0)
throw new Error("repair04: additional edge costs must be nonnegative");
return o3;
};
if (t4.maxNodes !== undefined && (!Number.isSafeInteger(t4.maxNodes) || t4.maxNodes < 1))
throw new Error("repair04: maxNodes must be a positive safe integer");
if (t4.stats && (t4.stats.nodesPopped = 0, t4.stats.completionReason = "no-path"), t4.allowLayerChanges === false && i2.z !== r2.z)
return null;
const h2 = n2[o2], d2 = t4.viaHoleDiameter ?? h2.viaDiameter;
if (!Number.isFinite(d2) || d2 <= 0 || d2 > h2.viaDiameter)
throw new Error("repair04: via hole diameter must be positive and fit the copper");
const u2 = d2 + t4.viaClearance, p2 = (t5, e3) => {
for (let n3 = e3;n3; n3 = n3.previous)
if ((t5.x !== n3.x || t5.y !== n3.y) && Math.hypot(t5.x - n3.x, t5.y - n3.y) + Hs < u2)
return false;
return true;
}, m2 = (t5) => {
let e3;
for (let n3 = 1;n3 < t5.length; n3++) {
const o3 = t5[n3 - 1], i3 = t5[n3];
if (o3.z !== i3.z && o3.toNextSegmentType !== "through_obstacle") {
if (!p2(o3, e3))
return false;
o3.x === e3?.x && o3.y === e3?.y || (e3 = { x: o3.x, y: o3.y, previous: e3 });
}
}
return true;
}, g2 = new Map, f2 = (t5) => {
const e3 = g2.get(t5);
if (e3 === undefined || e3 === t5)
return t5;
const n3 = f2(e3);
return g2.set(t5, n3), n3;
}, y2 = (t5) => {
const e3 = t5.filter((t6) => Boolean(t6));
if (!e3.length)
return;
const n3 = f2(e3[0]);
for (const t6 of e3)
g2.set(f2(t6), n3);
};
for (const t5 of e2.connections) {
const e3 = t5;
y2([e3.name, e3.rootConnectionName, e3.netConnectionName, e3.__netConnectionName, ...e3.mergedConnectionNames ?? [], ...e3.__rootConnectionNames ?? [], ...e3.pointsToConnect.flatMap((t6) => [t6.pcb_port_id, t6.pointId])]);
}
for (const t5 of e2.obstacles)
y2(t5.connectedTo);
for (const t5 of n2)
y2([t5.connectionName, t5.rootConnectionName]);
const _2 = f2(h2.connectionName), b2 = (t5) => t5 === "top" ? 0 : t5 === "bottom" ? e2.layerCount - 1 : Number(t5.slice(5)), x2 = [s2.minX, s2.maxX, s2.minY, s2.maxY, i2.x, i2.y, r2.x, r2.y, a2, h2.viaDiameter, t4.traceClearance, t4.viaClearance, e2.defaultObstacleMargin ?? 0, e2.minTraceToPadEdgeClearance ?? 0, e2.minViaEdgeToPadEdgeClearance ?? 0].every((t5) => Number.isFinite(t5) && Math.abs(t5) <= 1e4), v2 = [], I2 = (t5, n3, o3, i3, r3 = false, s3 = false) => {
const a3 = i3 ? Math.hypot(i3.width, i3.height) / 2 : o3, c3 = i3 ? Math.cos(i3.rotation) : 1, l3 = i3 ? Math.sin(i3.rotation) : 0, h3 = { minX: Math.min(t5.x, n3.x) - a3, maxX: Math.max(t5.x, n3.x) + a3, minY: Math.min(t5.y, n3.y) - a3, maxY: Math.max(t5.y, n3.y) + a3 }, d3 = i3 && x2 ? ((t6, e3, n4, o4, i4, r4) => {
if (t6.x !== e3.x || t6.y !== e3.y || !Number.isFinite(n4.rotation) || n4.width <= 0 || n4.height <= 0 || ![t6.x, t6.y, n4.width, n4.height, r4.minX, r4.maxX, r4.minY, r4.maxY].every((t7) => Number.isFinite(t7) && Math.abs(t7) <= 1e4))
return r4;
const s4 = o4 * o4 + i4 * i4;
if (!Number.isFinite(s4) || Math.abs(s4 - 1) > 0.000000000001)
return r4;
const a4 = n4.width / 2, c4 = n4.height / 2, l4 = (Math.abs(o4) * a4 + Math.abs(i4) * c4) / s4 + 0.00000001, h4 = (Math.abs(i4) * a4 + Math.abs(o4) * c4) / s4 + 0.00000001, d4 = { minX: t6.x - l4, maxX: t6.x + l4, minY: t6.y - h4, maxY: t6.y + h4 };
return d4.minX < r4.minX || d4.maxX > r4.maxX || d4.minY < r4.minY || d4.maxY > r4.maxY ? r4 : d4;
})(t5, n3, i3, c3, l3, h3) : h3;
v2.push({ a: t5, b: n3, radius: o3, rect: i3, viaOnly: r3, pad: s3, rectCos: c3, rectSin: l3, rectBounds: i3 ? { minX: -i3.width / 2, maxX: i3.width / 2, minY: -i3.height / 2, maxY: i3.height / 2 } : undefined, visitedQuery: 0, ...d3, ...Ys(e2, t5, n3) });
};
for (const t5 of e2.obstacles) {
const e3 = t5.connectedTo.some((t6) => f2(t6) === _2), n3 = t5.__zLayers ?? t5.zLayers ?? t5.layers.map(b2), o3 = t5.type === "oval" && t5.width === t5.height && t5.ccwRotationDegrees === undefined && n3.length > 1;
for (const i3 of n3) {
const n4 = { ...t5.center, z: i3 };
I2(n4, n4, o3 ? t5.width / 2 : 0, o3 ? undefined : { width: t5.width, height: t5.height, rotation: (t5.ccwRotationDegrees ?? 0) * Math.PI / 180 }, e3, o3);
}
}
for (const t5 of n2)
if (f2(t5.connectionName) !== _2)
for (let e3 = 1;e3 < t5.route.length; e3++) {
const n3 = t5.route[e3 - 1], o3 = t5.route[e3];
n3.toNextSegmentType !== "through_obstacle" && I2(n3, o3, n3.z !== o3.z ? t5.viaDiameter / 2 : Math.max(n3.traceThickness ?? t5.traceThickness, o3.traceThickness ?? t5.traceThickness) / 2);
}
for (const t5 of e2.traces ?? []) {
if (f2(t5.connection_name) === _2)
continue;
const n3 = Ws(t5, e2.minTraceWidth);
for (let t6 = 1;t6 < n3.route.length; t6++) {
const e3 = n3.route[t6 - 1], o3 = n3.route[t6];
e3.route_type === "wire" && o3.route_type === "wire" && e3.layer === o3.layer && I2({ x: e3.x, y: e3.y, z: b2(e3.layer) }, { x: o3.x, y: o3.y, z: b2(o3.layer) }, Math.max(e3.width, o3.width) / 2), o3.route_type === "via" && I2({ x: o3.x, y: o3.y, z: b2(o3.from_layer) }, { x: o3.x, y: o3.y, z: b2(o3.to_layer) }, (o3.via_diameter ?? h2.viaDiameter) / 2);
}
}
const S2 = new Map, C2 = Math.max(h2.viaDiameter, a2) / 2 + Math.max(t4.traceClearance, t4.viaClearance, e2.defaultObstacleMargin ?? 0, e2.minTraceToPadEdgeClearance ?? 0, e2.minViaEdgeToPadEdgeClearance ?? 0) + 0.00001;
for (const t5 of v2)
for (let e3 = Math.floor(Math.max(t5.minX, s2.minX - C2));e3 <= Math.floor(Math.min(t5.maxX, s2.maxX + C2)); e3++) {
let n3 = S2.get(e3);
for (let o3 = Math.floor(Math.max(t5.minY, s2.minY - C2));o3 <= Math.floor(Math.min(t5.maxY, s2.maxY + C2)); o3++) {
n3 || (n3 = new Map, S2.set(e3, n3));
const i3 = n3.get(o3);
i3 ? i3.push(t5) : n3.set(o3, [t5]);
}
}
let P2 = 0;
const M2 = { x: 0, y: 0 }, N2 = { x: 0, y: 0 }, w2 = (n3, o3) => {
const i3 = n3.z !== o3.z, r3 = i3 ? h2.viaDiameter / 2 : a2 / 2, s3 = Math.max(i3 ? t4.viaClearance : t4.traceClearance, e2.defaultObstacleMargin ?? 0, i3 ? e2.minViaEdgeToPadEdgeClearance ?? 0 : e2.minTraceToPadEdgeClearance ?? 0), c3 = r3 + s3 + 0.00001, l3 = ++P2, d3 = Math.min(n3.x, o3.x), u3 = Math.max(n3.x, o3.x), p3 = Math.min(n3.y, o3.y), m3 = Math.max(n3.y, o3.y), { minZ: g3, maxZ: f3 } = Ys(e2, n3, o3);
for (let a3 = Math.floor(d3 - c3);a3 <= Math.floor(u3 + c3); a3++) {
const h3 = S2.get(a3);
if (h3)
for (let a4 = Math.floor(p3 - c3);a4 <= Math.floor(m3 + c3); a4++) {
const c4 = h3.get(a4);
if (c4)
for (const a5 of c4) {
if (a5.viaOnly && !i3)
continue;
if (a5.visitedQuery === l3)
continue;
if (a5.visitedQuery = l3, a5.maxZ < g3 || a5.minZ > f3)
continue;
const c5 = r3 + (a5.viaOnly ? Vs(e2, t4.viaClearance, true) : a5.rect || a5.pad ? s3 : i3 && a5.minZ !== a5.maxZ ? t4.viaClearance : t4.traceClearance);
if (u3 + c5 < a5.minX || d3 - c5 > a5.maxX || m3 + c5 < a5.minY || p3 - c5 > a5.maxY)
continue;
let h4;
if (a5.rect ? (M2.x = (n3.x - a5.a.x) * a5.rectCos + (n3.y - a5.a.y) * a5.rectSin, M2.y = -(n3.x - a5.a.x) * a5.rectSin + (n3.y - a5.a.y) * a5.rectCos, N2.x = (o3.x - a5.a.x) * a5.rectCos + (o3.y - a5.a.y) * a5.rectSin, N2.y = -(o3.x - a5.a.x) * a5.rectSin + (o3.y - a5.a.y) * a5.rectCos, h4 = ke(M2, N2, a5.rectBounds)) : h4 = Oe(n3, o3, a5.a, a5.b) - a5.radius, h4 + Hs < c5)
return false;
}
}
}
return true;
};
if (!w2(i2, i2) || !w2(r2, r2))
return null;
if (t4.existingPath) {
const e3 = t4.existingPath, n3 = e3[0], o3 = e3.at(-1);
if (!n3 || !o3 || n3.x !== i2.x || n3.y !== i2.y || n3.z !== i2.z || o3.x !== r2.x || o3.y !== r2.y || o3.z !== r2.z)
throw new Error("repair04: existing clearance path must match its anchors");
if (e3.some((t5, n4) => {
const o4 = e3[n4 - 1];
return Boolean(o4 && o4.z !== t5.z && (o4.x !== t5.x || o4.y !== t5.y));
}))
throw new Error("repair04: existing clearance path has a non-colocated layer transition");
if (m2(e3) && (t4.allowLayerChanges !== false || e3.every((t5) => t5.z === i2.z)) && e3.slice(1).every((t5, n4) => w2(e3[n4], t5) && l2(e3[n4], t5) === 0))
return t4.stats && (t4.stats.completionReason = "found"), e3.map((t5) => ({ ...t5 }));
}
const T2 = t4.gridSize ?? 0.1;
if (!Number.isFinite(T2) || T2 <= 0)
throw new Error("repair04: clearance grid size must be positive and finite");
const R2 = Math.floor((s2.maxX - s2.minX) / T2), E2 = Math.floor((s2.maxY - s2.minY) / T2), A2 = (t5) => ({ x: s2.minX + (t5 % R2 + 0.5) * T2, y: s2.minY + (Math.floor(t5 / R2) % E2 + 0.5) * T2, z: Math.floor(t5 / (R2 * E2)), traceThickness: a2 }), O2 = (t5, e3, n3) => (n3 * E2 + e3) * R2 + t5, k2 = (t5) => Math.hypot(t5.x - r2.x, t5.y - r2.y) + (t5.z === r2.z ? 0 : 1), D2 = R2 * E2 * e2.layerCount, L2 = R2 > 0 && E2 > 0 && Number.isSafeInteger(e2.layerCount) && Number.isSafeInteger(D2) && D2 > 0 && D2 <= 1e6 && Number.isInteger(i2.z) && i2.z >= 0 && i2.z < e2.layerCount, z2 = new Xs(L2 ? D2 : undefined), B2 = new Map, F2 = new Map, j2 = new Map, $ = (W2 = i2, O2(Math.max(0, Math.min(R2 - 1, Math.floor((W2.x - s2.minX) / T2))), Math.max(0, Math.min(E2 - 1, Math.floor((W2.y - s2.minY) / T2))), W2.z)), Y2 = $ % R2, X2 = Math.floor($ / R2) % E2;
var W2;
for (let t5 = -2;t5 <= 2; t5++)
for (let e3 = -2;e3 <= 2; e3++) {
const n3 = Y2 + t5, o3 = X2 + e3;
if (n3 < 0 || n3 >= R2 || o3 < 0 || o3 >= E2)
continue;
const r3 = O2(n3, o3, i2.z), s3 = A2(r3);
if (!w2(i2, s3))
continue;
const a3 = Math.hypot(s3.x - i2.x, s3.y - i2.y) + l2(i2, s3);
Number.isFinite(a3) && (B2.set(r3, a3), F2.set(r3, -1), z2.push({ id: r3, cost: a3, priority: a3 + c2 * k2(s3) }));
}
const V2 = R2 * E2 * e2.layerCount, H2 = R2 > 0 && E2 > 0 && Number.isSafeInteger(e2.layerCount) && Number.isSafeInteger(V2) && V2 > 0 && Number.isSafeInteger(V2 * V2 - 1) && Number.isInteger(i2.z) && i2.z >= 0 && i2.z < e2.layerCount, G2 = c2 > 1 ? new Set : undefined, U2 = new Map, Z2 = new Map;
let q2 = 0;
for (;z2.length && q2 < (t4.maxNodes ?? 30000); ) {
const n3 = z2.pop();
if (q2++, t4.stats && (t4.stats.nodesPopped = q2), n3.cost !== B2.get(n3.id))
continue;
G2?.add(n3.id);
const o3 = A2(n3.id), s3 = j2.get(n3.id);
if (o3.z === r2.z && Math.hypot(o3.x - r2.x, o3.y - r2.y) < 3 * T2 && w2(o3, r2) && Number.isFinite(l2(o3, r2))) {
const e3 = [r2];
for (let t5 = n3.id;t5 !== -1; t5 = F2.get(t5))
e3.push(A2(t5));
e3.push(i2);
const o4 = e3.reverse(), s4 = [i2], a4 = [0];
for (let e4 = 1;t4.getAdditionalEdgeCost && e4 < o4.length; e4++) {
const t5 = o4[e4 - 1], n4 = o4[e4];
a4.push(a4[e4 - 1] + (t5.z === n4.z ? Math.hypot(t5.x - n4.x, t5.y - n4.y) : 1) + l2(t5, n4));
}
let c3 = 0;
for (let e4 = 1;e4 < o4.length; ) {
let n4 = e4;
if (o4[e4].z === s4.at(-1).z)
for (let i3 = e4 + 1;i3 < o4.length && o4[i3].z === o4[e4].z; i3++)
w2(s4.at(-1), o4[i3]) && (!t4.getAdditionalEdgeCost || Math.hypot(o4[i3].x - o4[c3].x, o4[i3].y - o4[c3].y) + l2(o4[c3], o4[i3]) <= a4[i3] - a4[c3] + Hs) && (n4 = i3);
s4.push(o4[n4]), c3 = n4, e4 = n4 + 1;
}
if (!m2(s4))
throw new Error("repair04: search generated conflicting drill sites");
return t4.stats && (t4.stats.completionReason = "found"), s4;
}
const a3 = n3.id % R2, h3 = Math.floor(n3.id / R2) % E2, d3 = [];
for (let t5 = -1;t5 <= 1; t5++)
for (let e3 = -1;e3 <= 1; e3++)
t5 === 0 && e3 === 0 || a3 + t5 < 0 || a3 + t5 >= R2 || h3 + e3 < 0 || h3 + e3 >= E2 || d3.push(O2(a3 + t5, h3 + e3, o3.z));
if (t4.allowLayerChanges !== false && p2(o3, s3))
for (let t5 = 0;t5 < e2.layerCount; t5++)
t5 !== o3.z && d3.push(O2(a3, h3, t5));
for (const t5 of d3) {
if (G2?.has(t5))
continue;
const i3 = A2(t5), r3 = n3.cost + (o3.z === i3.z ? Math.hypot(o3.x - i3.x, o3.y - i3.y) : 1), a4 = B2.get(t5) ?? 1 / 0;
if (r3 >= a4)
continue;
const h4 = Math.min(n3.id, t5), d4 = Math.max(n3.id, t5), u3 = H2 ? h4 * V2 + d4 : `${h4},${d4}`, p3 = H2 && o3.z !== i3.z && e2.allowBlindAndBuriedVias !== true ? n3.id % (R2 * E2) : undefined;
let m3 = p3 === undefined ? U2.get(u3) : Z2.get(p3);
if (m3 === undefined && (m3 = w2(o3, i3), p3 === undefined ? U2.set(u3, m3) : Z2.set(p3, m3)), !m3)
continue;
const g3 = r3 + l2(o3, i3);
g3 >= a4 || (o3.z === i3.z || o3.x === s3?.x && o3.y === s3?.y ? s3 ? j2.set(t5, s3) : j2.delete(t5) : j2.set(t5, { x: o3.x, y: o3.y, previous: s3 }), B2.set(t5, g3), F2.set(t5, n3.id), z2.push({ id: t5, cost: g3, priority: g3 + c2 * k2(i3) }));
}
}
return t4.stats && (t4.stats.completionReason = z2.length ? "node-limit" : "no-path"), null;
}
var ea = {};
a(ea, { all_layers: () => Cd, any_circuit_element: () => qm, any_soup_element: () => Jm, any_source_component: () => gd, asset: () => hh, base_circuit_json_error: () => Mh, battery_capacity: () => eh, brep_shape: () => gu, cadModelDefaultDirectionMap: () => Mm, cad_component: () => Nm, cad_model_axis_directions: () => Pm, cad_model_formats: () => Cm, capacitance: () => Xl, circuit_json_footprint_load_error: () => qp, current: () => Zl, distance: () => Ul, duration_ms: () => ql, experiment_type: () => zm, external_footprint_load_error: () => Zp, frequency: () => Gl, getZodPrefixedIdWithDefault: () => ah, inductance: () => Wl, kicadAt: () => dh, kicadEffects: () => ph, kicadFont: () => uh, kicadFootprintAttributes: () => fh, kicadFootprintMetadata: () => bh, kicadFootprintModel: () => _h, kicadFootprintPad: () => yh, kicadFootprintProperties: () => gh, kicadProperty: () => mh, kicadSymbolEffects: () => Ih, kicadSymbolMetadata: () => Ph, kicadSymbolPinNames: () => vh, kicadSymbolPinNumbers: () => xh, kicadSymbolProperties: () => Ch, kicadSymbolProperty: () => Sh, layer_ref: () => Md, layer_string: () => Pd, length: () => Hl, manufacturing_drc_properties: () => bu, ms: () => Ql, ninePointAnchor: () => ch, parseAndConvertSiUnit: () => ca, pcbRenderLayer: () => lh, pcb_autorouting_error: () => Qp, pcb_board: () => gp, pcb_breakout_point: () => om, pcb_component: () => xu, pcb_component_invalid_layer_error: () => mm, pcb_component_not_on_board_edge_error: () => pm, pcb_component_outside_board_error: () => um, pcb_connector_not_in_accessible_orientation_warning: () => em, pcb_copper_pour: () => dm, pcb_copper_pour_brep: () => lm, pcb_copper_pour_polygon: () => hm, pcb_copper_pour_rect: () => cm, pcb_copper_text: () => Sp, pcb_courtyard_circle: () => Im, pcb_courtyard_outline: () => xm, pcb_courtyard_overlap_error: () => jp, pcb_courtyard_pill: () => Sm, pcb_courtyard_polygon: () => vm, pcb_courtyard_rect: () => bm, pcb_cutout: () => Gp, pcb_cutout_circle: () => Wp, pcb_cutout_path: () => Hp, pcb_cutout_polygon: () => Vp, pcb_cutout_rect: () => Xp, pcb_fabrication_note_dimension: () => Op, pcb_fabrication_note_path: () => Ep, pcb_fabrication_note_rect: () => Ap, pcb_fabrication_note_text: () => Rp, pcb_footprint_overlap_error: () => Fp, pcb_ground_plane: () => im, pcb_ground_plane_region: () => rm, pcb_group: () => Jp, pcb_hole: () => Ou, pcb_hole_circle_or_square_shape: () => Mu, pcb_hole_circle_shape: () => Iu, pcb_hole_oval_shape: () => wu, pcb_hole_pill_shape: () => Ru, pcb_hole_rect_shape: () => Cu, pcb_hole_rotated_pill_shape: () => Au, pcb_keepout: () => $p, pcb_manual_edit_conflict_warning: () => Kp, pcb_missing_footprint_error: () => Up, pcb_net: () => pp, pcb_note_dimension: () => Bp, pcb_note_line: () => zp, pcb_note_path: () => Lp, pcb_note_rect: () => Dp, pcb_note_text: () => kp, pcb_pad_pad_clearance_error: () => ym, pcb_pad_trace_clearance_error: () => _m, pcb_panel: () => fp, pcb_panelization_placement_error: () => _p, pcb_placement_error: () => yp, pcb_plated_hole: () => ju, pcb_port: () => $u, pcb_port_not_connected_error: () => up, pcb_port_not_matched_error: () => dp, pcb_route_hint: () => fu, pcb_route_hints: () => yu, pcb_silkscreen_circle: () => Pp, pcb_silkscreen_graphic: () => wp, pcb_silkscreen_graphic_brep: () => Np, pcb_silkscreen_line: () => xp, pcb_silkscreen_oval: () => Mp, pcb_silkscreen_path: () => vp, pcb_silkscreen_pill: () => Tp, pcb_silkscreen_rect: () => Cp, pcb_silkscreen_text: () => Ip, pcb_smtpad: () => Uu, pcb_smtpad_pill: () => Vu, pcb_solder_paste: () => tp, pcb_text: () => ep, pcb_thermal_spoke: () => sm, pcb_trace: () => sp, pcb_trace_error: () => lp, pcb_trace_hint: () => bp, pcb_trace_missing_error: () => hp, pcb_trace_route_point: () => rp, pcb_trace_route_point_through_pad: () => ip, pcb_trace_route_point_via: () => op, pcb_trace_route_point_wire: () => np, pcb_trace_too_long_warning: () => cp, pcb_trace_warning: () => ap, pcb_via: () => mp, pcb_via_clearance_error: () => gm, pcb_via_trace_clearance_error: () => fm, point: () => nh, point3: () => ih, point_with_bulge: () => pu, port_arrangement: () => $d, position: () => oh, position3: () => rh, resistance: () => Yl, ring: () => mu, rotation: () => th, route_hint_point: () => _u, schematic_arc: () => Ud, schematic_box: () => Ld, schematic_circle: () => Gd, schematic_component: () => Yd, schematic_component_port_arrangement_by_sides: () => jd, schematic_component_port_arrangement_by_size: () => Fd, schematic_debug_line: () => iu, schematic_debug_object: () => su, schematic_debug_object_base: () => nu, schematic_debug_point: () => ru, schematic_debug_rect: () => ou, schematic_error: () => tu, schematic_group: () => lu, schematic_layout_error: () => eu, schematic_line: () => Vd, schematic_manual_edit_conflict_warning: () => cu, schematic_net_label: () => Kd, schematic_path: () => zd, schematic_pin_styles: () => Bd, schematic_port: () => Qd, schematic_rect: () => Hd, schematic_sheet: () => uu, schematic_symbol: () => Wd, schematic_table: () => hu, schematic_table_cell: () => du, schematic_text: () => Jd, schematic_trace: () => Zd, schematic_voltage_probe: () => au, simulation_ac_current_source: () => Dm, simulation_ac_voltage_source: () => Em, simulation_current_probe: () => Wm, simulation_current_source: () => Lm, simulation_dc_current_source: () => km, simulation_dc_voltage_source: () => Rm, simulation_experiment: () => Fm, simulation_op_amp: () => Hm, simulation_oscilloscope_trace: () => Zm, simulation_spice_subcircuit: () => Gm, simulation_switch: () => Ym, simulation_transient_current_graph: () => $m, simulation_transient_voltage_graph: () => jm, simulation_unknown_experiment_error: () => Vm, simulation_voltage_probe: () => Xm, simulation_voltage_source: () => Am, size: () => sh, source_ambiguous_port_reference: () => Id, source_board: () => vd, source_component_base: () => wh, source_component_internal_connection: () => yd, source_component_misconfigured_error: () => pd, source_component_pins_underspecified_warning: () => Ad, source_failed_to_create_component_error: () => od, source_group: () => bd, source_i2c_misconfigured_error: () => ud, source_interconnect: () => dd, source_invalid_component_property_error: () => id, source_manually_placed_via: () => wd, source_missing_manufacturer_part_number_warning: () => cd, source_missing_property_error: () => nd, source_net: () => xd, source_no_ground_pin_defined_warning: () => Ed, source_no_power_pin_defined_warning: () => Rd, source_part_not_found_warning: () => Dd, source_pcb_ground_plane: () => Sd, source_pin_attributes: () => jh, source_pin_missing_trace_warning: () => ad, source_pin_must_be_connected_error: () => Od, source_port: () => fd, source_project_metadata: () => ed, source_property_ignored_warning: () => sd, source_refdes_convention_warning: () => ld, source_simple_ammeter: () => Fh, source_simple_battery: () => $h, source_simple_capacitor: () => Th, source_simple_chip: () => Dh, source_simple_connector: () => Gh, source_simple_crystal: () => Vh, source_simple_current_source: () => zh, source_simple_diode: () => Eh, source_simple_fiducial: () => Ah, source_simple_fuse: () => Bh, source_simple_ground: () => kh, source_simple_inductor: () => Yh, source_simple_led: () => Oh, source_simple_mosfet: () => Qh, source_simple_op_amp: () => Kh, source_simple_pin_header: () => Hh, source_simple_pinout: () => Uh, source_simple_potentiometer: () => Wh, source_simple_power_source: () => Lh, source_simple_push_button: () => Xh, source_simple_resistor: () => Rh, source_simple_resonator: () => Zh, source_simple_switch: () => td, source_simple_test_point: () => Jh, source_simple_transistor: () => qh, source_simple_voltage_probe: () => hd, source_simple_voltage_source: () => md, source_trace: () => _d, source_trace_not_connected_error: () => rd, source_unnamed_trace_warning: () => Td, spice_simulation_options: () => Bm, supplier_footprint_mismatch_warning: () => nm, supplier_name: () => Nh, time: () => Jl, timestamp: () => Kl, unknown_error_finding_part: () => kd, visible_layer: () => Nd, voltage: () => Vl, wave_shape: () => wm });
var na = (t4) => {
const e2 = Math.round(1000 * t4) / 1000;
return `${Number(e2.toFixed(3))}mm`;
};
var oa = new Map([["T", 1000000000000], ["G", 1e9], ["M", 1e6], ["K", 1000], ["k", 1000], ["", 1], ["m", 0.001], ["µ", 0.000001], ["μ", 0.000001], ["u", 0.000001], ["n", 0.000000001], ["p", 0.000000000001], ["f", 0.000000000000001]]);
var ia = [...oa.keys()];
function ra(t4) {
return oa.get(t4);
}
var sa = { Hz: { baseUnit: "Hz", variants: { MHz: 1e6, kHz: 1000, Hz: 1 } }, g: { baseUnit: "g", variants: { kg: 1000, g: 1 } }, "Ω": { baseUnit: "Ω", variants: { "mΩ": 0.001, mohm: 0.001, mOhm: 0.001, milliohm: 0.001, "Ω": 1, ohm: 1, Ohm: 1, "kΩ": 1000, "KΩ": 1000, kohm: 1000, kOhm: 1000, KOhm: 1000, Kohm: 1000, "MΩ": 1e6, Mohm: 1e6, MOhm: 1e6, megohm: 1e6, Megohm: 1e6, "GΩ": 1e9, Gohm: 1e9, GOhm: 1e9, "TΩ": 1000000000000, Tohm: 1000000000000, TOhm: 1000000000000 } }, V: { baseUnit: "V", variants: { mV: 0.001, V: 1, kV: 1000, KV: 1000, MV: 1e6, GV: 1e9, TV: 1000000000000 } }, A: { baseUnit: "A", variants: { "µA": 0.000001, "μA": 0.000001, mA: 0.001, ma: 0.001, A: 1, kA: 1000, MA: 1e6 } }, F: { baseUnit: "F", variants: { pF: 0.000000000001, nF: 0.000000001, "µF": 0.000001, "μF": 0.000001, uF: 0.000001, mF: 0.001, F: 1, kF: 1000, KF: 1000, MF: 1e6 } }, H: { baseUnit: "H", variants: { pH: 0.000000000001, nH: 0.000000001, "µH": 0.000001, "μH": 0.000001, uH: 0.000001, mH: 0.001, H: 1, kH: 1000, KH: 1000, MH: 1e6 } }, ml: { baseUnit: "ml", variants: { ml: 1, mL: 1, l: 1000, L: 1000 } }, deg: { baseUnit: "deg", variants: { rad: 180 / Math.PI } }, ms: { baseUnit: "ms", variants: { fs: 0.000000000001, ps: 0.000000001, ns: 0.000001, us: 0.001, "µs": 0.001, "μs": 0.001, ms: 1, s: 1000 } }, mm: { baseUnit: "mm", variants: { nm: 0.000001, "µm": 0.001, "μm": 0.001, um: 0.001, mm: 1, cm: 10, dm: 100, m: 1000, km: 1e6, in: 25.4, ft: 304.8, IN: 25.4, FT: 304.8, yd: 914.4, mi: 1609344, mil: 0.0254 } } };
var aa = new Set;
for (const [t4, e2] of Object.entries(sa)) {
aa.add(t4);
for (const t5 of Object.keys(e2.variants))
aa.add(t5);
}
function ca(t4, e2) {
if (t4 == null)
return { parsedUnit: null, unitOfValue: null, value: null };
if (typeof t4 == "string" && t4.match(/^-?[\d.]+$/))
return { value: Number.parseFloat(t4), parsedUnit: null, unitOfValue: null };
if (typeof t4 == "number")
return { value: t4, parsedUnit: null, unitOfValue: null };
if (typeof t4 == "object" && "x" in t4 && "y" in t4) {
const n3 = ca(t4.x, e2), o3 = ca(t4.x, e2), i3 = ca(t4.y, e2);
return o3.value === null || i3.value === null ? { parsedUnit: null, unitOfValue: null, value: null } : { parsedUnit: n3.parsedUnit, unitOfValue: n3.unitOfValue, value: { x: o3.value, y: i3.value } };
}
const n2 = t4.toString().split("").reverse().join(""), o2 = n2.match(/[^\d\s]+/)?.[0];
if (!o2)
throw new Error(`Could not determine unit: "${t4}"`);
const i2 = o2.split("").reverse().join(""), r2 = t4.slice(0, -i2.length), s2 = ra(i2);
if (e2 && s2 != null)
return { parsedUnit: null, unitOfValue: e2, value: Number.parseFloat(r2) * s2 };
if (s2 != null && !aa.has(i2))
return { parsedUnit: null, unitOfValue: null, value: Number.parseFloat(r2) * s2 };
const { baseUnit: a2, conversionFactor: c2 } = function(t5) {
for (const e3 of Object.values(sa)) {
if (t5 in e3.variants)
return { baseUnit: e3.baseUnit, conversionFactor: e3.variants[t5] };
for (const [n3, o3] of Object.entries(e3.variants)) {
if (!t5.endsWith(n3))
continue;
const i3 = ra(t5.slice(0, -n3.length));
if (i3 != null)
return { baseUnit: e3.baseUnit, conversionFactor: i3 * o3 };
}
}
return { baseUnit: t5, conversionFactor: 1 };
}(i2);
return { parsedUnit: i2, unitOfValue: a2, value: c2 * Number.parseFloat(r2) };
}
var la;
var ha;
var da;
ia.filter((t4) => t4 !== "").sort((t4, e2) => e2.length - t4.length).map((t4) => t4.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
var pa = ({});
a(pa, { BRAND: () => Gc, DIRTY: () => Ra, EMPTY_PATH: () => Ca, INVALID: () => Ta, NEVER: () => $l, OK: () => Ea, ParseStatus: () => wa, Schema: () => ja, ZodAny: () => _c, ZodArray: () => Ic, ZodBigInt: () => uc, ZodBoolean: () => pc, ZodBranded: () => Uc, ZodCatch: () => Vc, ZodDate: () => mc, ZodDefault: () => Wc, ZodDiscriminatedUnion: () => Nc, ZodEffects: () => $c, ZodEnum: () => Bc, ZodError: () => _a, ZodFirstPartyTypeKind: () => Kc, ZodFunction: () => kc, ZodIntersection: () => Tc, ZodIssueCode: () => fa, ZodLazy: () => Dc, ZodLiteral: () => Lc, ZodMap: () => Ac, ZodNaN: () => Hc, ZodNativeEnum: () => Fc, ZodNever: () => xc, ZodNull: () => yc, ZodNullable: () => Xc, ZodNumber: () => dc, ZodObject: () => Cc, ZodOptional: () => Yc, ZodParsedType: () => ma, ZodPipeline: () => Zc, ZodPromise: () => jc, ZodReadonly: () => qc, ZodRecord: () => Ec, ZodSchema: () => ja, ZodSet: () => Oc, ZodString: () => lc, ZodSymbol: () => gc, ZodTransformer: () => $c, ZodTuple: () => Rc, ZodType: () => ja, ZodUndefined: () => fc, ZodUnion: () => Pc, ZodUnknown: () => bc, ZodVoid: () => vc, addIssueToContext: () => Pa, any: () => ul, array: () => fl, bigint: () => sl, boolean: () => al, coerce: () => jl, custom: () => Qc, date: () => cl, datetimeRegex: () => rc, defaultErrorMap: () => ba, discriminatedUnion: () => xl, effect: () => Al, enum: () => Tl, function: () => Ml, getErrorMap: () => Ia, getParsedType: () => ga, instanceof: () => nl, intersection: () => vl, isAborted: () => Aa, isAsync: () => Da, isDirty: () => Oa, isValid: () => ka, late: () => el, lazy: () => Nl, literal: () => wl, makeIssue: () => Sa, map: () => Cl, nan: () => rl, nativeEnum: () => Rl, never: () => ml, null: () => dl, nullable: () => kl, number: () => il, object: () => yl, objectUtil: () => da, oboolean: () => Fl, onumber: () => Bl, optional: () => Ol, ostring: () => zl, pipeline: () => Ll, preprocess: () => Dl, promise: () => El, quotelessJson: () => ya, record: () => Sl, set: () => Pl, setErrorMap: () => va, strictObject: () => _l, string: () => ol, symbol: () => ll, transformer: () => Al, tuple: () => Il, undefined: () => hl, union: () => bl, unknown: () => pl, util: () => la, void: () => gl }), (ha = la || (la = {})).assertEqual = (t4) => {}, ha.assertIs = function(t4) {}, ha.assertNever = function(t4) {
throw new Error;
}, ha.arrayToEnum = (t4) => {
const e2 = {};
for (const n2 of t4)
e2[n2] = n2;
return e2;
}, ha.getValidEnumValues = (t4) => {
const e2 = ha.objectKeys(t4).filter((e3) => typeof t4[t4[e3]] != "number"), n2 = {};
for (const o2 of e2)
n2[o2] = t4[o2];
return ha.objectValues(n2);
}, ha.objectValues = (t4) => ha.objectKeys(t4).map(function(e2) {
return t4[e2];
}), ha.objectKeys = typeof Object.keys == "function" ? (t4) => Object.keys(t4) : (t4) => {
const e2 = [];
for (const n2 in t4)
Object.prototype.hasOwnProperty.call(t4, n2) && e2.push(n2);
return e2;
}, ha.find = (t4, e2) => {
for (const n2 of t4)
if (e2(n2))
return n2;
}, ha.isInteger = typeof Number.isInteger == "function" ? (t4) => Number.isInteger(t4) : (t4) => typeof t4 == "number" && Number.isFinite(t4) && Math.floor(t4) === t4, ha.joinValues = function(t4, e2 = " | ") {
return t4.map((t5) => typeof t5 == "string" ? `'${t5}'` : t5).join(e2);
}, ha.jsonStringifyReplacer = (t4, e2) => typeof e2 == "bigint" ? e2.toString() : e2, (da || (da = {})).mergeShapes = (t4, e2) => ({ ...t4, ...e2 });
var ma = la.arrayToEnum(["string", "nan", "number", "integer", "float", "boolean", "date", "bigint", "symbol", "function", "undefined", "null", "array", "object", "unknown", "promise", "void", "never", "map", "set"]);
var ga = (t4) => {
switch (typeof t4) {
case "undefined":
return ma.undefined;
case "string":
return ma.string;
case "number":
return Number.isNaN(t4) ? ma.nan : ma.number;
case "boolean":
return ma.boolean;
case "function":
return ma.function;
case "bigint":
return ma.bigint;
case "symbol":
return ma.symbol;
case "object":
return Array.isArray(t4) ? ma.array : t4 === null ? ma.null : t4.then && typeof t4.then == "function" && t4.catch && typeof t4.catch == "function" ? ma.promise : typeof Map != "undefined" && t4 instanceof Map ? ma.map : typeof Set != "undefined" && t4 instanceof Set ? ma.set : typeof Date != "undefined" && t4 instanceof Date ? ma.date : ma.object;
default:
return ma.unknown;
}
};
var fa = la.arrayToEnum(["invalid_type", "invalid_literal", "custom", "invalid_union", "invalid_union_discriminator", "invalid_enum_value", "unrecognized_keys", "invalid_arguments", "invalid_return_type", "invalid_date", "invalid_string", "too_small", "too_big", "invalid_intersection_types", "not_multiple_of", "not_finite"]);
var ya = (t4) => JSON.stringify(t4, null, 2).replace(/"([^"]+)":/g, "$1:");
var _a = class t4 extends Error {
get errors() {
return this.issues;
}
constructor(t5) {
super(), this.issues = [], this.addIssue = (t6) => {
this.issues = [...this.issues, t6];
}, this.addIssues = (t6 = []) => {
this.issues = [...this.issues, ...t6];
};
const e2 = new.target.prototype;
Object.setPrototypeOf ? Object.setPrototypeOf(this, e2) : this.__proto__ = e2, this.name = "ZodError", this.issues = t5;
}
format(t5) {
const e2 = t5 || function(t6) {
return t6.message;
}, n2 = { _errors: [] }, o2 = (t6) => {
for (const i2 of t6.issues)
if (i2.code === "invalid_union")
i2.unionErrors.map(o2);
else if (i2.code === "invalid_return_type")
o2(i2.returnTypeError);
else if (i2.code === "invalid_arguments")
o2(i2.argumentsError);
else if (i2.path.length === 0)
n2._errors.push(e2(i2));
else {
let t7 = n2, o3 = 0;
for (;o3 < i2.path.length; ) {
const n3 = i2.path[o3];
o3 === i2.path.length - 1 ? (t7[n3] = t7[n3] || { _errors: [] }, t7[n3]._errors.push(e2(i2))) : t7[n3] = t7[n3] || { _errors: [] }, t7 = t7[n3], o3++;
}
}
};
return o2(this), n2;
}
static assert(e2) {
if (!(e2 instanceof t4))
throw new Error(`Not a ZodError: ${e2}`);
}
toString() {
return this.message;
}
get message() {
return JSON.stringify(this.issues, la.jsonStringifyReplacer, 2);
}
get isEmpty() {
return this.issues.length === 0;
}
flatten(t5 = (t6) => t6.message) {
const e2 = {}, n2 = [];
for (const o2 of this.issues)
if (o2.path.length > 0) {
const n3 = o2.path[0];
e2[n3] = e2[n3] || [], e2[n3].push(t5(o2));
} else
n2.push(t5(o2));
return { formErrors: n2, fieldErrors: e2 };
}
get formErrors() {
return this.flatten();
}
};
_a.create = (t5) => new _a(t5);
var ba = (t5, e2) => {
let n2;
switch (t5.code) {
case fa.invalid_type:
n2 = t5.received === ma.undefined ? "Required" : `Expected ${t5.expected}, received ${t5.received}`;
break;
case fa.invalid_literal:
n2 = `Invalid literal value, expected ${JSON.stringify(t5.expected, la.jsonStringifyReplacer)}`;
break;
case fa.unrecognized_keys:
n2 = `Unrecognized key(s) in object: ${la.joinValues(t5.keys, ", ")}`;
break;
case fa.invalid_union:
n2 = "Invalid input";
break;
case fa.invalid_union_discriminator:
n2 = `Invalid discriminator value. Expected ${la.joinValues(t5.options)}`;
break;
case fa.invalid_enum_value:
n2 = `Invalid enum value. Expected ${la.joinValues(t5.options)}, received '${t5.received}'`;
break;
case fa.invalid_arguments:
n2 = "Invalid function arguments";
break;
case fa.invalid_return_type:
n2 = "Invalid function return type";
break;
case fa.invalid_date:
n2 = "Invalid date";
break;
case fa.invalid_string:
typeof t5.validation == "object" ? "includes" in t5.validation ? (n2 = `Invalid input: must include "${t5.validation.includes}"`, typeof t5.validation.position == "number" && (n2 = `${n2} at one or more positions greater than or equal to ${t5.validation.position}`)) : ("startsWith" in t5.validation) ? n2 = `Invalid input: must start with "${t5.validation.startsWith}"` : ("endsWith" in t5.validation) ? n2 = `Invalid input: must end with "${t5.validation.endsWith}"` : la.assertNever(t5.validation) : n2 = t5.validation !== "regex" ? `Invalid ${t5.validation}` : "Invalid";
break;
case fa.too_small:
n2 = t5.type === "array" ? `Array must contain ${t5.exact ? "exactly" : t5.inclusive ? "at least" : "more than"} ${t5.minimum} element(s)` : t5.type === "string" ? `String must contain ${t5.exact ? "exactly" : t5.inclusive ? "at least" : "over"} ${t5.minimum} character(s)` : t5.type === "number" || t5.type === "bigint" ? `Number must be ${t5.exact ? "exactly equal to " : t5.inclusive ? "greater than or equal to " : "greater than "}${t5.minimum}` : t5.type === "date" ? `Date must be ${t5.exact ? "exactly equal to " : t5.inclusive ? "greater than or equal to " : "greater than "}${new Date(Number(t5.minimum))}` : "Invalid input";
break;
case fa.too_big:
n2 = t5.type === "array" ? `Array must contain ${t5.exact ? "exactly" : t5.inclusive ? "at most" : "less than"} ${t5.maximum} element(s)` : t5.type === "string" ? `String must contain ${t5.exact ? "exactly" : t5.inclusive ? "at most" : "under"} ${t5.maximum} character(s)` : t5.type === "number" ? `Number must be ${t5.exact ? "exactly" : t5.inclusive ? "less than or equal to" : "less than"} ${t5.maximum}` : t5.type === "bigint" ? `BigInt must be ${t5.exact ? "exactly" : t5.inclusive ? "less than or equal to" : "less than"} ${t5.maximum}` : t5.type === "date" ? `Date must be ${t5.exact ? "exactly" : t5.inclusive ? "smaller than or equal to" : "smaller than"} ${new Date(Number(t5.maximum))}` : "Invalid input";
break;
case fa.custom:
n2 = "Invalid input";
break;
case fa.invalid_intersection_types:
n2 = "Intersection results could not be merged";
break;
case fa.not_multiple_of:
n2 = `Number must be a multiple of ${t5.multipleOf}`;
break;
case fa.not_finite:
n2 = "Number must be finite";
break;
default:
n2 = e2.defaultError, la.assertNever(t5);
}
return { message: n2 };
};
var xa = ba;
function va(t5) {
xa = t5;
}
function Ia() {
return xa;
}
var Sa = (t5) => {
const { data: e2, path: n2, errorMaps: o2, issueData: i2 } = t5, r2 = [...n2, ...i2.path || []], s2 = { ...i2, path: r2 };
if (i2.message !== undefined)
return { ...i2, path: r2, message: i2.message };
let a2 = "";
const c2 = o2.filter((t6) => !!t6).slice().reverse();
for (const t6 of c2)
a2 = t6(s2, { data: e2, defaultError: a2 }).message;
return { ...i2, path: r2, message: a2 };
};
var Ca = [];
function Pa(t5, e2) {
const n2 = Ia(), o2 = Sa({ issueData: e2, data: t5.data, path: t5.path, errorMaps: [t5.common.contextualErrorMap, t5.schemaErrorMap, n2, n2 === ba ? undefined : ba].filter((t6) => !!t6) });
t5.common.issues.push(o2);
}
var Ma;
var Na;
var wa = class t5 {
constructor() {
this.value = "valid";
}
dirty() {
this.value === "valid" && (this.value = "dirty");
}
abort() {
this.value !== "aborted" && (this.value = "aborted");
}
static mergeArray(t6, e2) {
const n2 = [];
for (const o2 of e2) {
if (o2.status === "aborted")
return Ta;
o2.status === "dirty" && t6.dirty(), n2.push(o2.value);
}
return { status: t6.value, value: n2 };
}
static async mergeObjectAsync(e2, n2) {
const o2 = [];
for (const t6 of n2) {
const e3 = await t6.key, n3 = await t6.value;
o2.push({ key: e3, value: n3 });
}
return t5.mergeObjectSync(e2, o2);
}
static mergeObjectSync(t6, e2) {
const n2 = {};
for (const o2 of e2) {
const { key: e3, value: i2 } = o2;
if (e3.status === "aborted")
return Ta;
if (i2.status === "aborted")
return Ta;
e3.status === "dirty" && t6.dirty(), i2.status === "dirty" && t6.dirty(), e3.value === "__proto__" || i2.value === undefined && !o2.alwaysSet || (n2[e3.value] = i2.value);
}
return { status: t6.value, value: n2 };
}
};
var Ta = Object.freeze({ status: "aborted" });
var Ra = (t6) => ({ status: "dirty", value: t6 });
var Ea = (t6) => ({ status: "valid", value: t6 });
var Aa = (t6) => t6.status === "aborted";
var Oa = (t6) => t6.status === "dirty";
var ka = (t6) => t6.status === "valid";
var Da = (t6) => typeof Promise != "undefined" && t6 instanceof Promise;
(Na = Ma || (Ma = {})).errToObj = (t6) => typeof t6 == "string" ? { message: t6 } : t6 || {}, Na.toString = (t6) => typeof t6 == "string" ? t6 : t6?.message;
var La = class {
constructor(t6, e2, n2, o2) {
this._cachedPath = [], this.parent = t6, this.data = e2, this._path = n2, this._key = o2;
}
get path() {
return this._cachedPath.length || (Array.isArray(this._key) ? this._cachedPath.push(...this._path, ...this._key) : this._cachedPath.push(...this._path, this._key)), this._cachedPath;
}
};
var za = (t6, e2) => {
if (ka(e2))
return { success: true, data: e2.value };
if (!t6.common.issues.length)
throw new Error("Validation failed but no issues detected.");
return { success: false, get error() {
if (this._error)
return this._error;
const e3 = new _a(t6.common.issues);
return this._error = e3, this._error;
} };
};
function Ba(t6) {
if (!t6)
return {};
const { errorMap: e2, invalid_type_error: n2, required_error: o2, description: i2 } = t6;
if (e2 && (n2 || o2))
throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`);
if (e2)
return { errorMap: e2, description: i2 };
return { errorMap: (e3, i3) => {
const { message: r2 } = t6;
return e3.code === "invalid_enum_value" ? { message: r2 ?? i3.defaultError } : i3.data === undefined ? { message: r2 ?? o2 ?? i3.defaultError } : e3.code !== "invalid_type" ? { message: i3.defaultError } : { message: r2 ?? n2 ?? i3.defaultError };
}, description: i2 };
}
var Fa;
var ja = class {
get description() {
return this._def.description;
}
_getType(t6) {
return ga(t6.data);
}
_getOrReturnCtx(t6, e2) {
return e2 || { common: t6.parent.common, data: t6.data, parsedType: ga(t6.data), schemaErrorMap: this._def.errorMap, path: t6.path, parent: t6.parent };
}
_processInputParams(t6) {
return { status: new wa, ctx: { common: t6.parent.common, data: t6.data, parsedType: ga(t6.data), schemaErrorMap: this._def.errorMap, path: t6.path, parent: t6.parent } };
}
_parseSync(t6) {
const e2 = this._parse(t6);
if (Da(e2))
throw new Error("Synchronous parse encountered promise.");
return e2;
}
_parseAsync(t6) {
const e2 = this._parse(t6);
return Promise.resolve(e2);
}
parse(t6, e2) {
const n2 = this.safeParse(t6, e2);
if (n2.success)
return n2.data;
throw n2.error;
}
safeParse(t6, e2) {
const n2 = { common: { issues: [], async: e2?.async ?? false, contextualErrorMap: e2?.errorMap }, path: e2?.path || [], schemaErrorMap: this._def.errorMap, parent: null, data: t6, parsedType: ga(t6) }, o2 = this._parseSync({ data: t6, path: n2.path, parent: n2 });
return za(n2, o2);
}
"~validate"(t6) {
const e2 = { common: { issues: [], async: !!this["~standard"].async }, path: [], schemaErrorMap: this._def.errorMap, parent: null, data: t6, parsedType: ga(t6) };
if (!this["~standard"].async)
try {
const n2 = this._parseSync({ data: t6, path: [], parent: e2 });
return ka(n2) ? { value: n2.value } : { issues: e2.common.issues };
} catch (t7) {
t7?.message?.toLowerCase()?.includes("encountered") && (this["~standard"].async = true), e2.common = { issues: [], async: true };
}
return this._parseAsync({ data: t6, path: [], parent: e2 }).then((t7) => ka(t7) ? { value: t7.value } : { issues: e2.common.issues });
}
async parseAsync(t6, e2) {
const n2 = await this.safeParseAsync(t6, e2);
if (n2.success)
return n2.data;
throw n2.error;
}
async safeParseAsync(t6, e2) {
const n2 = { common: { issues: [], contextualErrorMap: e2?.errorMap, async: true }, path: e2?.path || [], schemaErrorMap: this._def.errorMap, parent: null, data: t6, parsedType: ga(t6) }, o2 = this._parse({ data: t6, path: n2.path, parent: n2 }), i2 = await (Da(o2) ? o2 : Promise.resolve(o2));
return za(n2, i2);
}
refine(t6, e2) {
const n2 = (t7) => typeof e2 == "string" || e2 === undefined ? { message: e2 } : typeof e2 == "function" ? e2(t7) : e2;
return this._refinement((e3, o2) => {
const i2 = t6(e3), r2 = () => o2.addIssue({ code: fa.custom, ...n2(e3) });
return typeof Promise != "undefined" && i2 instanceof Promise ? i2.then((t7) => !!t7 || (r2(), false)) : !!i2 || (r2(), false);
});
}
refinement(t6, e2) {
return this._refinement((n2, o2) => !!t6(n2) || (o2.addIssue(typeof e2 == "function" ? e2(n2, o2) : e2), false));
}
_refinement(t6) {
return new $c({ schema: this, typeName: Kc.ZodEffects, effect: { type: "refinement", refinement: t6 } });
}
superRefine(t6) {
return this._refinement(t6);
}
constructor(t6) {
this.spa = this.safeParseAsync, this._def = t6, this.parse = this.parse.bind(this), this.safeParse = this.safeParse.bind(this), this.parseAsync = this.parseAsync.bind(this), this.safeParseAsync = this.safeParseAsync.bind(this), this.spa = this.spa.bind(this), this.refine = this.refine.bind(this), this.refinement = this.refinement.bind(this), this.superRefine = this.superRefine.bind(this), this.optional = this.optional.bind(this), this.nullable = this.nullable.bind(this), this.nullish = this.nullish.bind(this), this.array = this.array.bind(this), this.promise = this.promise.bind(this), this.or = this.or.bind(this), this.and = this.and.bind(this), this.transform = this.transform.bind(this), this.brand = this.brand.bind(this), this.default = this.default.bind(this), this.catch = this.catch.bind(this), this.describe = this.describe.bind(this), this.pipe = this.pipe.bind(this), this.readonly = this.readonly.bind(this), this.isNullable = this.isNullable.bind(this), this.isOptional = this.isOptional.bind(this), this["~standard"] = { version: 1, vendor: "zod", validate: (t7) => this["~validate"](t7) };
}
optional() {
return Yc.create(this, this._def);
}
nullable() {
return Xc.create(this, this._def);
}
nullish() {
return this.nullable().optional();
}
array() {
return Ic.create(this);
}
promise() {
return jc.create(this, this._def);
}
or(t6) {
return Pc.create([this, t6], this._def);
}
and(t6) {
return Tc.create(this, t6, this._def);
}
transform(t6) {
return new $c({ ...Ba(this._def), schema: this, typeName: Kc.ZodEffects, effect: { type: "transform", transform: t6 } });
}
default(t6) {
const e2 = typeof t6 == "function" ? t6 : () => t6;
return new Wc({ ...Ba(this._def), innerType: this, defaultValue: e2, typeName: Kc.ZodDefault });
}
brand() {
return new Uc({ typeName: Kc.ZodBranded, type: this, ...Ba(this._def) });
}
catch(t6) {
const e2 = typeof t6 == "function" ? t6 : () => t6;
return new Vc({ ...Ba(this._def), innerType: this, catchValue: e2, typeName: Kc.ZodCatch });
}
describe(t6) {
return new (this.constructor)({ ...this._def, description: t6 });
}
pipe(t6) {
return Zc.create(this, t6);
}
readonly() {
return qc.create(this);
}
isOptional() {
return this.safeParse(undefined).success;
}
isNullable() {
return this.safeParse(null).success;
}
};
var $a = /^c[^\s-]{8,}$/i;
var Ya = /^[0-9a-z]+$/;
var Xa = /^[0-9A-HJKMNP-TV-Z]{26}$/i;
var Wa = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
var Va = /^[a-z0-9_-]{21}$/i;
var Ha = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/;
var Ga = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
var Ua = /^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i;
var Za = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
var qa = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/;
var Ja = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
var Qa = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
var Ka = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
var tc = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/;
var ec = "((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))";
var nc = new RegExp(`^${ec}$`);
function oc(t6) {
let e2 = "[0-5]\\d";
t6.precision ? e2 = `${e2}\\.\\d{${t6.precision}}` : t6.precision == null && (e2 = `${e2}(\\.\\d+)?`);
return `([01]\\d|2[0-3]):[0-5]\\d(:${e2})${t6.precision ? "+" : "?"}`;
}
function ic(t6) {
return new RegExp(`^${oc(t6)}$`);
}
function rc(t6) {
let e2 = `${ec}T${oc(t6)}`;
const n2 = [];
return n2.push(t6.local ? "Z?" : "Z"), t6.offset && n2.push("([+-]\\d{2}:?\\d{2})"), e2 = `${e2}(${n2.join("|")})`, new RegExp(`^${e2}$`);
}
function sc(t6, e2) {
return !(e2 !== "v4" && e2 || !Za.test(t6)) || !(e2 !== "v6" && e2 || !Ja.test(t6));
}
function ac(t6, e2) {
if (!Ha.test(t6))
return false;
try {
const [n2] = t6.split(".");
if (!n2)
return false;
const o2 = n2.replace(/-/g, "+").replace(/_/g, "/").padEnd(n2.length + (4 - n2.length % 4) % 4, "="), i2 = JSON.parse(atob(o2));
return typeof i2 == "object" && i2 !== null && ((!("typ" in i2) || i2?.typ === "JWT") && (!!i2.alg && (!e2 || i2.alg === e2)));
} catch {
return false;
}
}
function cc(t6, e2) {
return !(e2 !== "v4" && e2 || !qa.test(t6)) || !(e2 !== "v6" && e2 || !Qa.test(t6));
}
var lc = class t6 extends ja {
_parse(t7) {
this._def.coerce && (t7.data = String(t7.data));
if (this._getType(t7) !== ma.string) {
const e3 = this._getOrReturnCtx(t7);
return Pa(e3, { code: fa.invalid_type, expected: ma.string, received: e3.parsedType }), Ta;
}
const e2 = new wa;
let n2;
for (const o2 of this._def.checks)
if (o2.kind === "min")
t7.data.length < o2.value && (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { code: fa.too_small, minimum: o2.value, type: "string", inclusive: true, exact: false, message: o2.message }), e2.dirty());
else if (o2.kind === "max")
t7.data.length > o2.value && (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { code: fa.too_big, maximum: o2.value, type: "string", inclusive: true, exact: false, message: o2.message }), e2.dirty());
else if (o2.kind === "length") {
const i2 = t7.data.length > o2.value, r2 = t7.data.length < o2.value;
(i2 || r2) && (n2 = this._getOrReturnCtx(t7, n2), i2 ? Pa(n2, { code: fa.too_big, maximum: o2.value, type: "string", inclusive: true, exact: true, message: o2.message }) : r2 && Pa(n2, { code: fa.too_small, minimum: o2.value, type: "string", inclusive: true, exact: true, message: o2.message }), e2.dirty());
} else if (o2.kind === "email")
Ua.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "email", code: fa.invalid_string, message: o2.message }), e2.dirty());
else if (o2.kind === "emoji")
Fa || (Fa = new RegExp("^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$", "u")), Fa.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "emoji", code: fa.invalid_string, message: o2.message }), e2.dirty());
else if (o2.kind === "uuid")
Wa.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "uuid", code: fa.invalid_string, message: o2.message }), e2.dirty());
else if (o2.kind === "nanoid")
Va.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "nanoid", code: fa.invalid_string, message: o2.message }), e2.dirty());
else if (o2.kind === "cuid")
$a.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "cuid", code: fa.invalid_string, message: o2.message }), e2.dirty());
else if (o2.kind === "cuid2")
Ya.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "cuid2", code: fa.invalid_string, message: o2.message }), e2.dirty());
else if (o2.kind === "ulid")
Xa.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "ulid", code: fa.invalid_string, message: o2.message }), e2.dirty());
else if (o2.kind === "url")
try {
new URL(t7.data);
} catch {
n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "url", code: fa.invalid_string, message: o2.message }), e2.dirty();
}
else if (o2.kind === "regex") {
o2.regex.lastIndex = 0;
o2.regex.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "regex", code: fa.invalid_string, message: o2.message }), e2.dirty());
} else if (o2.kind === "trim")
t7.data = t7.data.trim();
else if (o2.kind === "includes")
t7.data.includes(o2.value, o2.position) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { code: fa.invalid_string, validation: { includes: o2.value, position: o2.position }, message: o2.message }), e2.dirty());
else if (o2.kind === "toLowerCase")
t7.data = t7.data.toLowerCase();
else if (o2.kind === "toUpperCase")
t7.data = t7.data.toUpperCase();
else if (o2.kind === "startsWith")
t7.data.startsWith(o2.value) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { code: fa.invalid_string, validation: { startsWith: o2.value }, message: o2.message }), e2.dirty());
else if (o2.kind === "endsWith")
t7.data.endsWith(o2.value) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { code: fa.invalid_string, validation: { endsWith: o2.value }, message: o2.message }), e2.dirty());
else if (o2.kind === "datetime") {
rc(o2).test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { code: fa.invalid_string, validation: "datetime", message: o2.message }), e2.dirty());
} else if (o2.kind === "date") {
nc.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { code: fa.invalid_string, validation: "date", message: o2.message }), e2.dirty());
} else if (o2.kind === "time") {
ic(o2).test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { code: fa.invalid_string, validation: "time", message: o2.message }), e2.dirty());
} else
o2.kind === "duration" ? Ga.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "duration", code: fa.invalid_string, message: o2.message }), e2.dirty()) : o2.kind === "ip" ? sc(t7.data, o2.version) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "ip", code: fa.invalid_string, message: o2.message }), e2.dirty()) : o2.kind === "jwt" ? ac(t7.data, o2.alg) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "jwt", code: fa.invalid_string, message: o2.message }), e2.dirty()) : o2.kind === "cidr" ? cc(t7.data, o2.version) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "cidr", code: fa.invalid_string, message: o2.message }), e2.dirty()) : o2.kind === "base64" ? Ka.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "base64", code: fa.invalid_string, message: o2.message }), e2.dirty()) : o2.kind === "base64url" ? tc.test(t7.data) || (n2 = this._getOrReturnCtx(t7, n2), Pa(n2, { validation: "base64url", code: fa.invalid_string, message: o2.message }), e2.dirty()) : la.assertNever(o2);
return { status: e2.value, value: t7.data };
}
_regex(t7, e2, n2) {
return this.refinement((e3) => t7.test(e3), { validation: e2, code: fa.invalid_string, ...Ma.errToObj(n2) });
}
_addCheck(e2) {
return new t6({ ...this._def, checks: [...this._def.checks, e2] });
}
email(t7) {
return this._addCheck({ kind: "email", ...Ma.errToObj(t7) });
}
url(t7) {
return this._addCheck({ kind: "url", ...Ma.errToObj(t7) });
}
emoji(t7) {
return this._addCheck({ kind: "emoji", ...Ma.errToObj(t7) });
}
uuid(t7) {
return this._addCheck({ kind: "uuid", ...Ma.errToObj(t7) });
}
nanoid(t7) {
return this._addCheck({ kind: "nanoid", ...Ma.errToObj(t7) });
}
cuid(t7) {
return this._addCheck({ kind: "cuid", ...Ma.errToObj(t7) });
}
cuid2(t7) {
return this._addCheck({ kind: "cuid2", ...Ma.errToObj(t7) });
}
ulid(t7) {
return this._addCheck({ kind: "ulid", ...Ma.errToObj(t7) });
}
base64(t7) {
return this._addCheck({ kind: "base64", ...Ma.errToObj(t7) });
}
base64url(t7) {
return this._addCheck({ kind: "base64url", ...Ma.errToObj(t7) });
}
jwt(t7) {
return this._addCheck({ kind: "jwt", ...Ma.errToObj(t7) });
}
ip(t7) {
return this._addCheck({ kind: "ip", ...Ma.errToObj(t7) });
}
cidr(t7) {
return this._addCheck({ kind: "cidr", ...Ma.errToObj(t7) });
}
datetime(t7) {
return typeof t7 == "string" ? this._addCheck({ kind: "datetime", precision: null, offset: false, local: false, message: t7 }) : this._addCheck({ kind: "datetime", precision: t7?.precision === undefined ? null : t7?.precision, offset: t7?.offset ?? false, local: t7?.local ?? false, ...Ma.errToObj(t7?.message) });
}
date(t7) {
return this._addCheck({ kind: "date", message: t7 });
}
time(t7) {
return typeof t7 == "string" ? this._addCheck({ kind: "time", precision: null, message: t7 }) : this._addCheck({ kind: "time", precision: t7?.precision === undefined ? null : t7?.precision, ...Ma.errToObj(t7?.message) });
}
duration(t7) {
return this._addCheck({ kind: "duration", ...Ma.errToObj(t7) });
}
regex(t7, e2) {
return this._addCheck({ kind: "regex", regex: t7, ...Ma.errToObj(e2) });
}
includes(t7, e2) {
return this._addCheck({ kind: "includes", value: t7, position: e2?.position, ...Ma.errToObj(e2?.message) });
}
startsWith(t7, e2) {
return this._addCheck({ kind: "startsWith", value: t7, ...Ma.errToObj(e2) });
}
endsWith(t7, e2) {
return this._addCheck({ kind: "endsWith", value: t7, ...Ma.errToObj(e2) });
}
min(t7, e2) {
return this._addCheck({ kind: "min", value: t7, ...Ma.errToObj(e2) });
}
max(t7, e2) {
return this._addCheck({ kind: "max", value: t7, ...Ma.errToObj(e2) });
}
length(t7, e2) {
return this._addCheck({ kind: "length", value: t7, ...Ma.errToObj(e2) });
}
nonempty(t7) {
return this.min(1, Ma.errToObj(t7));
}
trim() {
return new t6({ ...this._def, checks: [...this._def.checks, { kind: "trim" }] });
}
toLowerCase() {
return new t6({ ...this._def, checks: [...this._def.checks, { kind: "toLowerCase" }] });
}
toUpperCase() {
return new t6({ ...this._def, checks: [...this._def.checks, { kind: "toUpperCase" }] });
}
get isDatetime() {
return !!this._def.checks.find((t7) => t7.kind === "datetime");
}
get isDate() {
return !!this._def.checks.find((t7) => t7.kind === "date");
}
get isTime() {
return !!this._def.checks.find((t7) => t7.kind === "time");
}
get isDuration() {
return !!this._def.checks.find((t7) => t7.kind === "duration");
}
get isEmail() {
return !!this._def.checks.find((t7) => t7.kind === "email");
}
get isURL() {
return !!this._def.checks.find((t7) => t7.kind === "url");
}
get isEmoji() {
return !!this._def.checks.find((t7) => t7.kind === "emoji");
}
get isUUID() {
return !!this._def.checks.find((t7) => t7.kind === "uuid");
}
get isNANOID() {
return !!this._def.checks.find((t7) => t7.kind === "nanoid");
}
get isCUID() {
return !!this._def.checks.find((t7) => t7.kind === "cuid");
}
get isCUID2() {
return !!this._def.checks.find((t7) => t7.kind === "cuid2");
}
get isULID() {
return !!this._def.checks.find((t7) => t7.kind === "ulid");
}
get isIP() {
return !!this._def.checks.find((t7) => t7.kind === "ip");
}
get isCIDR() {
return !!this._def.checks.find((t7) => t7.kind === "cidr");
}
get isBase64() {
return !!this._def.checks.find((t7) => t7.kind === "base64");
}
get isBase64url() {
return !!this._def.checks.find((t7) => t7.kind === "base64url");
}
get minLength() {
let t7 = null;
for (const e2 of this._def.checks)
e2.kind === "min" && (t7 === null || e2.value > t7) && (t7 = e2.value);
return t7;
}
get maxLength() {
let t7 = null;
for (const e2 of this._def.checks)
e2.kind === "max" && (t7 === null || e2.value < t7) && (t7 = e2.value);
return t7;
}
};
function hc(t7, e2) {
const n2 = (t7.toString().split(".")[1] || "").length, o2 = (e2.toString().split(".")[1] || "").length, i2 = n2 > o2 ? n2 : o2;
return Number.parseInt(t7.toFixed(i2).replace(".", "")) % Number.parseInt(e2.toFixed(i2).replace(".", "")) / 10 ** i2;
}
lc.create = (t7) => new lc({ checks: [], typeName: Kc.ZodString, coerce: t7?.coerce ?? false, ...Ba(t7) });
var dc = class t7 extends ja {
constructor() {
super(...arguments), this.min = this.gte, this.max = this.lte, this.step = this.multipleOf;
}
_parse(t8) {
this._def.coerce && (t8.data = Number(t8.data));
if (this._getType(t8) !== ma.number) {
const e3 = this._getOrReturnCtx(t8);
return Pa(e3, { code: fa.invalid_type, expected: ma.number, received: e3.parsedType }), Ta;
}
let e2;
const n2 = new wa;
for (const o2 of this._def.checks)
if (o2.kind === "int")
la.isInteger(t8.data) || (e2 = this._getOrReturnCtx(t8, e2), Pa(e2, { code: fa.invalid_type, expected: "integer", received: "float", message: o2.message }), n2.dirty());
else if (o2.kind === "min") {
(o2.inclusive ? t8.data < o2.value : t8.data <= o2.value) && (e2 = this._getOrReturnCtx(t8, e2), Pa(e2, { code: fa.too_small, minimum: o2.value, type: "number", inclusive: o2.inclusive, exact: false, message: o2.message }), n2.dirty());
} else if (o2.kind === "max") {
(o2.inclusive ? t8.data > o2.value : t8.data >= o2.value) && (e2 = this._getOrReturnCtx(t8, e2), Pa(e2, { code: fa.too_big, maximum: o2.value, type: "number", inclusive: o2.inclusive, exact: false, message: o2.message }), n2.dirty());
} else
o2.kind === "multipleOf" ? hc(t8.data, o2.value) !== 0 && (e2 = this._getOrReturnCtx(t8, e2), Pa(e2, { code: fa.not_multiple_of, multipleOf: o2.value, message: o2.message }), n2.dirty()) : o2.kind === "finite" ? Number.isFinite(t8.data) || (e2 = this._getOrReturnCtx(t8, e2), Pa(e2, { code: fa.not_finite, message: o2.message }), n2.dirty()) : la.assertNever(o2);
return { status: n2.value, value: t8.data };
}
gte(t8, e2) {
return this.setLimit("min", t8, true, Ma.toString(e2));
}
gt(t8, e2) {
return this.setLimit("min", t8, false, Ma.toString(e2));
}
lte(t8, e2) {
return this.setLimit("max", t8, true, Ma.toString(e2));
}
lt(t8, e2) {
return this.setLimit("max", t8, false, Ma.toString(e2));
}
setLimit(e2, n2, o2, i2) {
return new t7({ ...this._def, checks: [...this._def.checks, { kind: e2, value: n2, inclusive: o2, message: Ma.toString(i2) }] });
}
_addCheck(e2) {
return new t7({ ...this._def, checks: [...this._def.checks, e2] });
}
int(t8) {
return this._addCheck({ kind: "int", message: Ma.toString(t8) });
}
positive(t8) {
return this._addCheck({ kind: "min", value: 0, inclusive: false, message: Ma.toString(t8) });
}
negative(t8) {
return this._addCheck({ kind: "max", value: 0, inclusive: false, message: Ma.toString(t8) });
}
nonpositive(t8) {
return this._addCheck({ kind: "max", value: 0, inclusive: true, message: Ma.toString(t8) });
}
nonnegative(t8) {
return this._addCheck({ kind: "min", value: 0, inclusive: true, message: Ma.toString(t8) });
}
multipleOf(t8, e2) {
return this._addCheck({ kind: "multipleOf", value: t8, message: Ma.toString(e2) });
}
finite(t8) {
return this._addCheck({ kind: "finite", message: Ma.toString(t8) });
}
safe(t8) {
return this._addCheck({ kind: "min", inclusive: true, value: Number.MIN_SAFE_INTEGER, message: Ma.toString(t8) })._addCheck({ kind: "max", inclusive: true, value: Number.MAX_SAFE_INTEGER, message: Ma.toString(t8) });
}
get minValue() {
let t8 = null;
for (const e2 of this._def.checks)
e2.kind === "min" && (t8 === null || e2.value > t8) && (t8 = e2.value);
return t8;
}
get maxValue() {
let t8 = null;
for (const e2 of this._def.checks)
e2.kind === "max" && (t8 === null || e2.value < t8) && (t8 = e2.value);
return t8;
}
get isInt() {
return !!this._def.checks.find((t8) => t8.kind === "int" || t8.kind === "multipleOf" && la.isInteger(t8.value));
}
get isFinite() {
let t8 = null, e2 = null;
for (const n2 of this._def.checks) {
if (n2.kind === "finite" || n2.kind === "int" || n2.kind === "multipleOf")
return true;
n2.kind === "min" ? (e2 === null || n2.value > e2) && (e2 = n2.value) : n2.kind === "max" && (t8 === null || n2.value < t8) && (t8 = n2.value);
}
return Number.isFinite(e2) && Number.isFinite(t8);
}
};
dc.create = (t8) => new dc({ checks: [], typeName: Kc.ZodNumber, coerce: t8?.coerce || false, ...Ba(t8) });
var uc = class t8 extends ja {
constructor() {
super(...arguments), this.min = this.gte, this.max = this.lte;
}
_parse(t9) {
if (this._def.coerce)
try {
t9.data = BigInt(t9.data);
} catch {
return this._getInvalidInput(t9);
}
if (this._getType(t9) !== ma.bigint)
return this._getInvalidInput(t9);
let e2;
const n2 = new wa;
for (const o2 of this._def.checks)
if (o2.kind === "min") {
(o2.inclusive ? t9.data < o2.value : t9.data <= o2.value) && (e2 = this._getOrReturnCtx(t9, e2), Pa(e2, { code: fa.too_small, type: "bigint", minimum: o2.value, inclusive: o2.inclusive, message: o2.message }), n2.dirty());
} else if (o2.kind === "max") {
(o2.inclusive ? t9.data > o2.value : t9.data >= o2.value) && (e2 = this._getOrReturnCtx(t9, e2), Pa(e2, { code: fa.too_big, type: "bigint", maximum: o2.value, inclusive: o2.inclusive, message: o2.message }), n2.dirty());
} else
o2.kind === "multipleOf" ? t9.data % o2.value !== BigInt(0) && (e2 = this._getOrReturnCtx(t9, e2), Pa(e2, { code: fa.not_multiple_of, multipleOf: o2.value, message: o2.message }), n2.dirty()) : la.assertNever(o2);
return { status: n2.value, value: t9.data };
}
_getInvalidInput(t9) {
const e2 = this._getOrReturnCtx(t9);
return Pa(e2, { code: fa.invalid_type, expected: ma.bigint, received: e2.parsedType }), Ta;
}
gte(t9, e2) {
return this.setLimit("min", t9, true, Ma.toString(e2));
}
gt(t9, e2) {
return this.setLimit("min", t9, false, Ma.toString(e2));
}
lte(t9, e2) {
return this.setLimit("max", t9, true, Ma.toString(e2));
}
lt(t9, e2) {
return this.setLimit("max", t9, false, Ma.toString(e2));
}
setLimit(e2, n2, o2, i2) {
return new t8({ ...this._def, checks: [...this._def.checks, { kind: e2, value: n2, inclusive: o2, message: Ma.toString(i2) }] });
}
_addCheck(e2) {
return new t8({ ...this._def, checks: [...this._def.checks, e2] });
}
positive(t9) {
return this._addCheck({ kind: "min", value: BigInt(0), inclusive: false, message: Ma.toString(t9) });
}
negative(t9) {
return this._addCheck({ kind: "max", value: BigInt(0), inclusive: false, message: Ma.toString(t9) });
}
nonpositive(t9) {
return this._addCheck({ kind: "max", value: BigInt(0), inclusive: true, message: Ma.toString(t9) });
}
nonnegative(t9) {
return this._addCheck({ kind: "min", value: BigInt(0), inclusive: true, message: Ma.toString(t9) });
}
multipleOf(t9, e2) {
return this._addCheck({ kind: "multipleOf", value: t9, message: Ma.toString(e2) });
}
get minValue() {
let t9 = null;
for (const e2 of this._def.checks)
e2.kind === "min" && (t9 === null || e2.value > t9) && (t9 = e2.value);
return t9;
}
get maxValue() {
let t9 = null;
for (const e2 of this._def.checks)
e2.kind === "max" && (t9 === null || e2.value < t9) && (t9 = e2.value);
return t9;
}
};
uc.create = (t9) => new uc({ checks: [], typeName: Kc.ZodBigInt, coerce: t9?.coerce ?? false, ...Ba(t9) });
var pc = class extends ja {
_parse(t9) {
this._def.coerce && (t9.data = Boolean(t9.data));
if (this._getType(t9) !== ma.boolean) {
const e2 = this._getOrReturnCtx(t9);
return Pa(e2, { code: fa.invalid_type, expected: ma.boolean, received: e2.parsedType }), Ta;
}
return Ea(t9.data);
}
};
pc.create = (t9) => new pc({ typeName: Kc.ZodBoolean, coerce: t9?.coerce || false, ...Ba(t9) });
var mc = class t9 extends ja {
_parse(t10) {
this._def.coerce && (t10.data = new Date(t10.data));
if (this._getType(t10) !== ma.date) {
const e3 = this._getOrReturnCtx(t10);
return Pa(e3, { code: fa.invalid_type, expected: ma.date, received: e3.parsedType }), Ta;
}
if (Number.isNaN(t10.data.getTime())) {
return Pa(this._getOrReturnCtx(t10), { code: fa.invalid_date }), Ta;
}
const e2 = new wa;
let n2;
for (const o2 of this._def.checks)
o2.kind === "min" ? t10.data.getTime() < o2.value && (n2 = this._getOrReturnCtx(t10, n2), Pa(n2, { code: fa.too_small, message: o2.message, inclusive: true, exact: false, minimum: o2.value, type: "date" }), e2.dirty()) : o2.kind === "max" ? t10.data.getTime() > o2.value && (n2 = this._getOrReturnCtx(t10, n2), Pa(n2, { code: fa.too_big, message: o2.message, inclusive: true, exact: false, maximum: o2.value, type: "date" }), e2.dirty()) : la.assertNever(o2);
return { status: e2.value, value: new Date(t10.data.getTime()) };
}
_addCheck(e2) {
return new t9({ ...this._def, checks: [...this._def.checks, e2] });
}
min(t10, e2) {
return this._addCheck({ kind: "min", value: t10.getTime(), message: Ma.toString(e2) });
}
max(t10, e2) {
return this._addCheck({ kind: "max", value: t10.getTime(), message: Ma.toString(e2) });
}
get minDate() {
let t10 = null;
for (const e2 of this._def.checks)
e2.kind === "min" && (t10 === null || e2.value > t10) && (t10 = e2.value);
return t10 != null ? new Date(t10) : null;
}
get maxDate() {
let t10 = null;
for (const e2 of this._def.checks)
e2.kind === "max" && (t10 === null || e2.value < t10) && (t10 = e2.value);
return t10 != null ? new Date(t10) : null;
}
};
mc.create = (t10) => new mc({ checks: [], coerce: t10?.coerce || false, typeName: Kc.ZodDate, ...Ba(t10) });
var gc = class extends ja {
_parse(t10) {
if (this._getType(t10) !== ma.symbol) {
const e2 = this._getOrReturnCtx(t10);
return Pa(e2, { code: fa.invalid_type, expected: ma.symbol, received: e2.parsedType }), Ta;
}
return Ea(t10.data);
}
};
gc.create = (t10) => new gc({ typeName: Kc.ZodSymbol, ...Ba(t10) });
var fc = class extends ja {
_parse(t10) {
if (this._getType(t10) !== ma.undefined) {
const e2 = this._getOrReturnCtx(t10);
return Pa(e2, { code: fa.invalid_type, expected: ma.undefined, received: e2.parsedType }), Ta;
}
return Ea(t10.data);
}
};
fc.create = (t10) => new fc({ typeName: Kc.ZodUndefined, ...Ba(t10) });
var yc = class extends ja {
_parse(t10) {
if (this._getType(t10) !== ma.null) {
const e2 = this._getOrReturnCtx(t10);
return Pa(e2, { code: fa.invalid_type, expected: ma.null, received: e2.parsedType }), Ta;
}
return Ea(t10.data);
}
};
yc.create = (t10) => new yc({ typeName: Kc.ZodNull, ...Ba(t10) });
var _c = class extends ja {
constructor() {
super(...arguments), this._any = true;
}
_parse(t10) {
return Ea(t10.data);
}
};
_c.create = (t10) => new _c({ typeName: Kc.ZodAny, ...Ba(t10) });
var bc = class extends ja {
constructor() {
super(...arguments), this._unknown = true;
}
_parse(t10) {
return Ea(t10.data);
}
};
bc.create = (t10) => new bc({ typeName: Kc.ZodUnknown, ...Ba(t10) });
var xc = class extends ja {
_parse(t10) {
const e2 = this._getOrReturnCtx(t10);
return Pa(e2, { code: fa.invalid_type, expected: ma.never, received: e2.parsedType }), Ta;
}
};
xc.create = (t10) => new xc({ typeName: Kc.ZodNever, ...Ba(t10) });
var vc = class extends ja {
_parse(t10) {
if (this._getType(t10) !== ma.undefined) {
const e2 = this._getOrReturnCtx(t10);
return Pa(e2, { code: fa.invalid_type, expected: ma.void, received: e2.parsedType }), Ta;
}
return Ea(t10.data);
}
};
vc.create = (t10) => new vc({ typeName: Kc.ZodVoid, ...Ba(t10) });
var Ic = class t10 extends ja {
_parse(t11) {
const { ctx: e2, status: n2 } = this._processInputParams(t11), o2 = this._def;
if (e2.parsedType !== ma.array)
return Pa(e2, { code: fa.invalid_type, expected: ma.array, received: e2.parsedType }), Ta;
if (o2.exactLength !== null) {
const t12 = e2.data.length > o2.exactLength.value, i3 = e2.data.length < o2.exactLength.value;
(t12 || i3) && (Pa(e2, { code: t12 ? fa.too_big : fa.too_small, minimum: i3 ? o2.exactLength.value : undefined, maximum: t12 ? o2.exactLength.value : undefined, type: "array", inclusive: true, exact: true, message: o2.exactLength.message }), n2.dirty());
}
if (o2.minLength !== null && e2.data.length < o2.minLength.value && (Pa(e2, { code: fa.too_small, minimum: o2.minLength.value, type: "array", inclusive: true, exact: false, message: o2.minLength.message }), n2.dirty()), o2.maxLength !== null && e2.data.length > o2.maxLength.value && (Pa(e2, { code: fa.too_big, maximum: o2.maxLength.value, type: "array", inclusive: true, exact: false, message: o2.maxLength.message }), n2.dirty()), e2.common.async)
return Promise.all([...e2.data].map((t12, n3) => o2.type._parseAsync(new La(e2, t12, e2.path, n3)))).then((t12) => wa.mergeArray(n2, t12));
const i2 = [...e2.data].map((t12, n3) => o2.type._parseSync(new La(e2, t12, e2.path, n3)));
return wa.mergeArray(n2, i2);
}
get element() {
return this._def.type;
}
min(e2, n2) {
return new t10({ ...this._def, minLength: { value: e2, message: Ma.toString(n2) } });
}
max(e2, n2) {
return new t10({ ...this._def, maxLength: { value: e2, message: Ma.toString(n2) } });
}
length(e2, n2) {
return new t10({ ...this._def, exactLength: { value: e2, message: Ma.toString(n2) } });
}
nonempty(t11) {
return this.min(1, t11);
}
};
function Sc(t11) {
if (t11 instanceof Cc) {
const e2 = {};
for (const n2 in t11.shape) {
const o2 = t11.shape[n2];
e2[n2] = Yc.create(Sc(o2));
}
return new Cc({ ...t11._def, shape: () => e2 });
}
return t11 instanceof Ic ? new Ic({ ...t11._def, type: Sc(t11.element) }) : t11 instanceof Yc ? Yc.create(Sc(t11.unwrap())) : t11 instanceof Xc ? Xc.create(Sc(t11.unwrap())) : t11 instanceof Rc ? Rc.create(t11.items.map((t12) => Sc(t12))) : t11;
}
Ic.create = (t11, e2) => new Ic({ type: t11, minLength: null, maxLength: null, exactLength: null, typeName: Kc.ZodArray, ...Ba(e2) });
var Cc = class t11 extends ja {
constructor() {
super(...arguments), this._cached = null, this.nonstrict = this.passthrough, this.augment = this.extend;
}
_getCached() {
if (this._cached !== null)
return this._cached;
const t12 = this._def.shape(), e2 = la.objectKeys(t12);
return this._cached = { shape: t12, keys: e2 }, this._cached;
}
_parse(t12) {
if (this._getType(t12) !== ma.object) {
const e3 = this._getOrReturnCtx(t12);
return Pa(e3, { code: fa.invalid_type, expected: ma.object, received: e3.parsedType }), Ta;
}
const { status: e2, ctx: n2 } = this._processInputParams(t12), { shape: o2, keys: i2 } = this._getCached(), r2 = [];
if (!(this._def.catchall instanceof xc && this._def.unknownKeys === "strip"))
for (const t13 in n2.data)
i2.includes(t13) || r2.push(t13);
const s2 = [];
for (const t13 of i2) {
const e3 = o2[t13], i3 = n2.data[t13];
s2.push({ key: { status: "valid", value: t13 }, value: e3._parse(new La(n2, i3, n2.path, t13)), alwaysSet: t13 in n2.data });
}
if (this._def.catchall instanceof xc) {
const t13 = this._def.unknownKeys;
if (t13 === "passthrough")
for (const t14 of r2)
s2.push({ key: { status: "valid", value: t14 }, value: { status: "valid", value: n2.data[t14] } });
else if (t13 === "strict")
r2.length > 0 && (Pa(n2, { code: fa.unrecognized_keys, keys: r2 }), e2.dirty());
else if (t13 !== "strip")
throw new Error("Internal ZodObject error: invalid unknownKeys value.");
} else {
const t13 = this._def.catchall;
for (const e3 of r2) {
const o3 = n2.data[e3];
s2.push({ key: { status: "valid", value: e3 }, value: t13._parse(new La(n2, o3, n2.path, e3)), alwaysSet: e3 in n2.data });
}
}
return n2.common.async ? Promise.resolve().then(async () => {
const t13 = [];
for (const e3 of s2) {
const n3 = await e3.key, o3 = await e3.value;
t13.push({ key: n3, value: o3, alwaysSet: e3.alwaysSet });
}
return t13;
}).then((t13) => wa.mergeObjectSync(e2, t13)) : wa.mergeObjectSync(e2, s2);
}
get shape() {
return this._def.shape();
}
strict(e2) {
return Ma.errToObj, new t11({ ...this._def, unknownKeys: "strict", ...e2 !== undefined ? { errorMap: (t12, n2) => {
const o2 = this._def.errorMap?.(t12, n2).message ?? n2.defaultError;
return t12.code === "unrecognized_keys" ? { message: Ma.errToObj(e2).message ?? o2 } : { message: o2 };
} } : {} });
}
strip() {
return new t11({ ...this._def, unknownKeys: "strip" });
}
passthrough() {
return new t11({ ...this._def, unknownKeys: "passthrough" });
}
extend(e2) {
return new t11({ ...this._def, shape: () => ({ ...this._def.shape(), ...e2 }) });
}
merge(e2) {
return new t11({ unknownKeys: e2._def.unknownKeys, catchall: e2._def.catchall, shape: () => ({ ...this._def.shape(), ...e2._def.shape() }), typeName: Kc.ZodObject });
}
setKey(t12, e2) {
return this.augment({ [t12]: e2 });
}
catchall(e2) {
return new t11({ ...this._def, catchall: e2 });
}
pick(e2) {
const n2 = {};
for (const t12 of la.objectKeys(e2))
e2[t12] && this.shape[t12] && (n2[t12] = this.shape[t12]);
return new t11({ ...this._def, shape: () => n2 });
}
omit(e2) {
const n2 = {};
for (const t12 of la.objectKeys(this.shape))
e2[t12] || (n2[t12] = this.shape[t12]);
return new t11({ ...this._def, shape: () => n2 });
}
deepPartial() {
return Sc(this);
}
partial(e2) {
const n2 = {};
for (const t12 of la.objectKeys(this.shape)) {
const o2 = this.shape[t12];
e2 && !e2[t12] ? n2[t12] = o2 : n2[t12] = o2.optional();
}
return new t11({ ...this._def, shape: () => n2 });
}
required(e2) {
const n2 = {};
for (const t12 of la.objectKeys(this.shape))
if (e2 && !e2[t12])
n2[t12] = this.shape[t12];
else {
let e3 = this.shape[t12];
for (;e3 instanceof Yc; )
e3 = e3._def.innerType;
n2[t12] = e3;
}
return new t11({ ...this._def, shape: () => n2 });
}
keyof() {
return zc(la.objectKeys(this.shape));
}
};
Cc.create = (t12, e2) => new Cc({ shape: () => t12, unknownKeys: "strip", catchall: xc.create(), typeName: Kc.ZodObject, ...Ba(e2) }), Cc.strictCreate = (t12, e2) => new Cc({ shape: () => t12, unknownKeys: "strict", catchall: xc.create(), typeName: Kc.ZodObject, ...Ba(e2) }), Cc.lazycreate = (t12, e2) => new Cc({ shape: t12, unknownKeys: "strip", catchall: xc.create(), typeName: Kc.ZodObject, ...Ba(e2) });
var Pc = class extends ja {
_parse(t12) {
const { ctx: e2 } = this._processInputParams(t12), n2 = this._def.options;
if (e2.common.async)
return Promise.all(n2.map(async (t13) => {
const n3 = { ...e2, common: { ...e2.common, issues: [] }, parent: null };
return { result: await t13._parseAsync({ data: e2.data, path: e2.path, parent: n3 }), ctx: n3 };
})).then(function(t13) {
for (const e3 of t13)
if (e3.result.status === "valid")
return e3.result;
for (const n4 of t13)
if (n4.result.status === "dirty")
return e2.common.issues.push(...n4.ctx.common.issues), n4.result;
const n3 = t13.map((t14) => new _a(t14.ctx.common.issues));
return Pa(e2, { code: fa.invalid_union, unionErrors: n3 }), Ta;
});
{
let t13;
const o2 = [];
for (const i3 of n2) {
const n3 = { ...e2, common: { ...e2.common, issues: [] }, parent: null }, r2 = i3._parseSync({ data: e2.data, path: e2.path, parent: n3 });
if (r2.status === "valid")
return r2;
r2.status !== "dirty" || t13 || (t13 = { result: r2, ctx: n3 }), n3.common.issues.length && o2.push(n3.common.issues);
}
if (t13)
return e2.common.issues.push(...t13.ctx.common.issues), t13.result;
const i2 = o2.map((t14) => new _a(t14));
return Pa(e2, { code: fa.invalid_union, unionErrors: i2 }), Ta;
}
}
get options() {
return this._def.options;
}
};
Pc.create = (t12, e2) => new Pc({ options: t12, typeName: Kc.ZodUnion, ...Ba(e2) });
var Mc = (t12) => t12 instanceof Dc ? Mc(t12.schema) : t12 instanceof $c ? Mc(t12.innerType()) : t12 instanceof Lc ? [t12.value] : t12 instanceof Bc ? t12.options : t12 instanceof Fc ? la.objectValues(t12.enum) : t12 instanceof Wc ? Mc(t12._def.innerType) : t12 instanceof fc ? [undefined] : t12 instanceof yc ? [null] : t12 instanceof Yc ? [undefined, ...Mc(t12.unwrap())] : t12 instanceof Xc ? [null, ...Mc(t12.unwrap())] : t12 instanceof Uc || t12 instanceof qc ? Mc(t12.unwrap()) : t12 instanceof Vc ? Mc(t12._def.innerType) : [];
var Nc = class t12 extends ja {
_parse(t13) {
const { ctx: e2 } = this._processInputParams(t13);
if (e2.parsedType !== ma.object)
return Pa(e2, { code: fa.invalid_type, expected: ma.object, received: e2.parsedType }), Ta;
const n2 = this.discriminator, o2 = e2.data[n2], i2 = this.optionsMap.get(o2);
return i2 ? e2.common.async ? i2._parseAsync({ data: e2.data, path: e2.path, parent: e2 }) : i2._parseSync({ data: e2.data, path: e2.path, parent: e2 }) : (Pa(e2, { code: fa.invalid_union_discriminator, options: Array.from(this.optionsMap.keys()), path: [n2] }), Ta);
}
get discriminator() {
return this._def.discriminator;
}
get options() {
return this._def.options;
}
get optionsMap() {
return this._def.optionsMap;
}
static create(e2, n2, o2) {
const i2 = new Map;
for (const t13 of n2) {
const n3 = Mc(t13.shape[e2]);
if (!n3.length)
throw new Error(`A discriminator value for key \`${e2}\` could not be extracted from all schema options`);
for (const o3 of n3) {
if (i2.has(o3))
throw new Error(`Discriminator property ${String(e2)} has duplicate value ${String(o3)}`);
i2.set(o3, t13);
}
}
return new t12({ typeName: Kc.ZodDiscriminatedUnion, discriminator: e2, options: n2, optionsMap: i2, ...Ba(o2) });
}
};
function wc(t13, e2) {
const n2 = ga(t13), o2 = ga(e2);
if (t13 === e2)
return { valid: true, data: t13 };
if (n2 === ma.object && o2 === ma.object) {
const n3 = la.objectKeys(e2), o3 = la.objectKeys(t13).filter((t14) => n3.indexOf(t14) !== -1), i2 = { ...t13, ...e2 };
for (const n4 of o3) {
const o4 = wc(t13[n4], e2[n4]);
if (!o4.valid)
return { valid: false };
i2[n4] = o4.data;
}
return { valid: true, data: i2 };
}
if (n2 === ma.array && o2 === ma.array) {
if (t13.length !== e2.length)
return { valid: false };
const n3 = [];
for (let o3 = 0;o3 < t13.length; o3++) {
const i2 = wc(t13[o3], e2[o3]);
if (!i2.valid)
return { valid: false };
n3.push(i2.data);
}
return { valid: true, data: n3 };
}
return n2 === ma.date && o2 === ma.date && +t13 === +e2 ? { valid: true, data: t13 } : { valid: false };
}
var Tc = class extends ja {
_parse(t13) {
const { status: e2, ctx: n2 } = this._processInputParams(t13), o2 = (t14, o3) => {
if (Aa(t14) || Aa(o3))
return Ta;
const i2 = wc(t14.value, o3.value);
return i2.valid ? ((Oa(t14) || Oa(o3)) && e2.dirty(), { status: e2.value, value: i2.data }) : (Pa(n2, { code: fa.invalid_intersection_types }), Ta);
};
return n2.common.async ? Promise.all([this._def.left._parseAsync({ data: n2.data, path: n2.path, parent: n2 }), this._def.right._parseAsync({ data: n2.data, path: n2.path, parent: n2 })]).then(([t14, e3]) => o2(t14, e3)) : o2(this._def.left._parseSync({ data: n2.data, path: n2.path, parent: n2 }), this._def.right._parseSync({ data: n2.data, path: n2.path, parent: n2 }));
}
};
Tc.create = (t13, e2, n2) => new Tc({ left: t13, right: e2, typeName: Kc.ZodIntersection, ...Ba(n2) });
var Rc = class t13 extends ja {
_parse(t14) {
const { status: e2, ctx: n2 } = this._processInputParams(t14);
if (n2.parsedType !== ma.array)
return Pa(n2, { code: fa.invalid_type, expected: ma.array, received: n2.parsedType }), Ta;
if (n2.data.length < this._def.items.length)
return Pa(n2, { code: fa.too_small, minimum: this._def.items.length, inclusive: true, exact: false, type: "array" }), Ta;
!this._def.rest && n2.data.length > this._def.items.length && (Pa(n2, { code: fa.too_big, maximum: this._def.items.length, inclusive: true, exact: false, type: "array" }), e2.dirty());
const o2 = [...n2.data].map((t15, e3) => {
const o3 = this._def.items[e3] || this._def.rest;
return o3 ? o3._parse(new La(n2, t15, n2.path, e3)) : null;
}).filter((t15) => !!t15);
return n2.common.async ? Promise.all(o2).then((t15) => wa.mergeArray(e2, t15)) : wa.mergeArray(e2, o2);
}
get items() {
return this._def.items;
}
rest(e2) {
return new t13({ ...this._def, rest: e2 });
}
};
Rc.create = (t14, e2) => {
if (!Array.isArray(t14))
throw new Error("You must pass an array of schemas to z.tuple([ ... ])");
return new Rc({ items: t14, typeName: Kc.ZodTuple, rest: null, ...Ba(e2) });
};
var Ec = class t14 extends ja {
get keySchema() {
return this._def.keyType;
}
get valueSchema() {
return this._def.valueType;
}
_parse(t15) {
const { status: e2, ctx: n2 } = this._processInputParams(t15);
if (n2.parsedType !== ma.object)
return Pa(n2, { code: fa.invalid_type, expected: ma.object, received: n2.parsedType }), Ta;
const o2 = [], i2 = this._def.keyType, r2 = this._def.valueType;
for (const t16 in n2.data)
o2.push({ key: i2._parse(new La(n2, t16, n2.path, t16)), value: r2._parse(new La(n2, n2.data[t16], n2.path, t16)), alwaysSet: t16 in n2.data });
return n2.common.async ? wa.mergeObjectAsync(e2, o2) : wa.mergeObjectSync(e2, o2);
}
get element() {
return this._def.valueType;
}
static create(e2, n2, o2) {
return new t14(n2 instanceof ja ? { keyType: e2, valueType: n2, typeName: Kc.ZodRecord, ...Ba(o2) } : { keyType: lc.create(), valueType: e2, typeName: Kc.ZodRecord, ...Ba(n2) });
}
};
var Ac = class extends ja {
get keySchema() {
return this._def.keyType;
}
get valueSchema() {
return this._def.valueType;
}
_parse(t15) {
const { status: e2, ctx: n2 } = this._processInputParams(t15);
if (n2.parsedType !== ma.map)
return Pa(n2, { code: fa.invalid_type, expected: ma.map, received: n2.parsedType }), Ta;
const o2 = this._def.keyType, i2 = this._def.valueType, r2 = [...n2.data.entries()].map(([t16, e3], r3) => ({ key: o2._parse(new La(n2, t16, n2.path, [r3, "key"])), value: i2._parse(new La(n2, e3, n2.path, [r3, "value"])) }));
if (n2.common.async) {
const t16 = new Map;
return Promise.resolve().then(async () => {
for (const n3 of r2) {
const o3 = await n3.key, i3 = await n3.value;
if (o3.status === "aborted" || i3.status === "aborted")
return Ta;
o3.status !== "dirty" && i3.status !== "dirty" || e2.dirty(), t16.set(o3.value, i3.value);
}
return { status: e2.value, value: t16 };
});
}
{
const t16 = new Map;
for (const n3 of r2) {
const { key: o3, value: i3 } = n3;
if (o3.status === "aborted" || i3.status === "aborted")
return Ta;
o3.status !== "dirty" && i3.status !== "dirty" || e2.dirty(), t16.set(o3.value, i3.value);
}
return { status: e2.value, value: t16 };
}
}
};
Ac.create = (t15, e2, n2) => new Ac({ valueType: e2, keyType: t15, typeName: Kc.ZodMap, ...Ba(n2) });
var Oc = class t15 extends ja {
_parse(t16) {
const { status: e2, ctx: n2 } = this._processInputParams(t16);
if (n2.parsedType !== ma.set)
return Pa(n2, { code: fa.invalid_type, expected: ma.set, received: n2.parsedType }), Ta;
const o2 = this._def;
o2.minSize !== null && n2.data.size < o2.minSize.value && (Pa(n2, { code: fa.too_small, minimum: o2.minSize.value, type: "set", inclusive: true, exact: false, message: o2.minSize.message }), e2.dirty()), o2.maxSize !== null && n2.data.size > o2.maxSize.value && (Pa(n2, { code: fa.too_big, maximum: o2.maxSize.value, type: "set", inclusive: true, exact: false, message: o2.maxSize.message }), e2.dirty());
const i2 = this._def.valueType;
function r2(t17) {
const n3 = new Set;
for (const o3 of t17) {
if (o3.status === "aborted")
return Ta;
o3.status === "dirty" && e2.dirty(), n3.add(o3.value);
}
return { status: e2.value, value: n3 };
}
const s2 = [...n2.data.values()].map((t17, e3) => i2._parse(new La(n2, t17, n2.path, e3)));
return n2.common.async ? Promise.all(s2).then((t17) => r2(t17)) : r2(s2);
}
min(e2, n2) {
return new t15({ ...this._def, minSize: { value: e2, message: Ma.toString(n2) } });
}
max(e2, n2) {
return new t15({ ...this._def, maxSize: { value: e2, message: Ma.toString(n2) } });
}
size(t16, e2) {
return this.min(t16, e2).max(t16, e2);
}
nonempty(t16) {
return this.min(1, t16);
}
};
Oc.create = (t16, e2) => new Oc({ valueType: t16, minSize: null, maxSize: null, typeName: Kc.ZodSet, ...Ba(e2) });
var kc = class t16 extends ja {
constructor() {
super(...arguments), this.validate = this.implement;
}
_parse(t17) {
const { ctx: e2 } = this._processInputParams(t17);
if (e2.parsedType !== ma.function)
return Pa(e2, { code: fa.invalid_type, expected: ma.function, received: e2.parsedType }), Ta;
function n2(t18, n3) {
return Sa({ data: t18, path: e2.path, errorMaps: [e2.common.contextualErrorMap, e2.schemaErrorMap, Ia(), ba].filter((t19) => !!t19), issueData: { code: fa.invalid_arguments, argumentsError: n3 } });
}
function o2(t18, n3) {
return Sa({ data: t18, path: e2.path, errorMaps: [e2.common.contextualErrorMap, e2.schemaErrorMap, Ia(), ba].filter((t19) => !!t19), issueData: { code: fa.invalid_return_type, returnTypeError: n3 } });
}
const i2 = { errorMap: e2.common.contextualErrorMap }, r2 = e2.data;
if (this._def.returns instanceof jc) {
const t18 = this;
return Ea(async function(...e3) {
const s2 = new _a([]), a2 = await t18._def.args.parseAsync(e3, i2).catch((t19) => {
throw s2.addIssue(n2(e3, t19)), s2;
}), c2 = await Reflect.apply(r2, this, a2);
return await t18._def.returns._def.type.parseAsync(c2, i2).catch((t19) => {
throw s2.addIssue(o2(c2, t19)), s2;
});
});
}
{
const t18 = this;
return Ea(function(...e3) {
const s2 = t18._def.args.safeParse(e3, i2);
if (!s2.success)
throw new _a([n2(e3, s2.error)]);
const a2 = Reflect.apply(r2, this, s2.data), c2 = t18._def.returns.safeParse(a2, i2);
if (!c2.success)
throw new _a([o2(a2, c2.error)]);
return c2.data;
});
}
}
parameters() {
return this._def.args;
}
returnType() {
return this._def.returns;
}
args(...e2) {
return new t16({ ...this._def, args: Rc.create(e2).rest(bc.create()) });
}
returns(e2) {
return new t16({ ...this._def, returns: e2 });
}
implement(t17) {
return this.parse(t17);
}
strictImplement(t17) {
return this.parse(t17);
}
static create(e2, n2, o2) {
return new t16({ args: e2 || Rc.create([]).rest(bc.create()), returns: n2 || bc.create(), typeName: Kc.ZodFunction, ...Ba(o2) });
}
};
var Dc = class extends ja {
get schema() {
return this._def.getter();
}
_parse(t17) {
const { ctx: e2 } = this._processInputParams(t17);
return this._def.getter()._parse({ data: e2.data, path: e2.path, parent: e2 });
}
};
Dc.create = (t17, e2) => new Dc({ getter: t17, typeName: Kc.ZodLazy, ...Ba(e2) });
var Lc = class extends ja {
_parse(t17) {
if (t17.data !== this._def.value) {
const e2 = this._getOrReturnCtx(t17);
return Pa(e2, { received: e2.data, code: fa.invalid_literal, expected: this._def.value }), Ta;
}
return { status: "valid", value: t17.data };
}
get value() {
return this._def.value;
}
};
function zc(t17, e2) {
return new Bc({ values: t17, typeName: Kc.ZodEnum, ...Ba(e2) });
}
Lc.create = (t17, e2) => new Lc({ value: t17, typeName: Kc.ZodLiteral, ...Ba(e2) });
var Bc = class t17 extends ja {
_parse(t18) {
if (typeof t18.data != "string") {
const e2 = this._getOrReturnCtx(t18), n2 = this._def.values;
return Pa(e2, { expected: la.joinValues(n2), received: e2.parsedType, code: fa.invalid_type }), Ta;
}
if (this._cache || (this._cache = new Set(this._def.values)), !this._cache.has(t18.data)) {
const e2 = this._getOrReturnCtx(t18), n2 = this._def.values;
return Pa(e2, { received: e2.data, code: fa.invalid_enum_value, options: n2 }), Ta;
}
return Ea(t18.data);
}
get options() {
return this._def.values;
}
get enum() {
const t18 = {};
for (const e2 of this._def.values)
t18[e2] = e2;
return t18;
}
get Values() {
const t18 = {};
for (const e2 of this._def.values)
t18[e2] = e2;
return t18;
}
get Enum() {
const t18 = {};
for (const e2 of this._def.values)
t18[e2] = e2;
return t18;
}
extract(e2, n2 = this._def) {
return t17.create(e2, { ...this._def, ...n2 });
}
exclude(e2, n2 = this._def) {
return t17.create(this.options.filter((t18) => !e2.includes(t18)), { ...this._def, ...n2 });
}
};
Bc.create = zc;
var Fc = class extends ja {
_parse(t18) {
const e2 = la.getValidEnumValues(this._def.values), n2 = this._getOrReturnCtx(t18);
if (n2.parsedType !== ma.string && n2.parsedType !== ma.number) {
const t19 = la.objectValues(e2);
return Pa(n2, { expected: la.joinValues(t19), received: n2.parsedType, code: fa.invalid_type }), Ta;
}
if (this._cache || (this._cache = new Set(la.getValidEnumValues(this._def.values))), !this._cache.has(t18.data)) {
const t19 = la.objectValues(e2);
return Pa(n2, { received: n2.data, code: fa.invalid_enum_value, options: t19 }), Ta;
}
return Ea(t18.data);
}
get enum() {
return this._def.values;
}
};
Fc.create = (t18, e2) => new Fc({ values: t18, typeName: Kc.ZodNativeEnum, ...Ba(e2) });
var jc = class extends ja {
unwrap() {
return this._def.type;
}
_parse(t18) {
const { ctx: e2 } = this._processInputParams(t18);
if (e2.parsedType !== ma.promise && e2.common.async === false)
return Pa(e2, { code: fa.invalid_type, expected: ma.promise, received: e2.parsedType }), Ta;
const n2 = e2.parsedType === ma.promise ? e2.data : Promise.resolve(e2.data);
return Ea(n2.then((t19) => this._def.type.parseAsync(t19, { path: e2.path, errorMap: e2.common.contextualErrorMap })));
}
};
jc.create = (t18, e2) => new jc({ type: t18, typeName: Kc.ZodPromise, ...Ba(e2) });
var $c = class extends ja {
innerType() {
return this._def.schema;
}
sourceType() {
return this._def.schema._def.typeName === Kc.ZodEffects ? this._def.schema.sourceType() : this._def.schema;
}
_parse(t18) {
const { status: e2, ctx: n2 } = this._processInputParams(t18), o2 = this._def.effect || null, i2 = { addIssue: (t19) => {
Pa(n2, t19), t19.fatal ? e2.abort() : e2.dirty();
}, get path() {
return n2.path;
} };
if (i2.addIssue = i2.addIssue.bind(i2), o2.type === "preprocess") {
const t19 = o2.transform(n2.data, i2);
if (n2.common.async)
return Promise.resolve(t19).then(async (t20) => {
if (e2.value === "aborted")
return Ta;
const o3 = await this._def.schema._parseAsync({ data: t20, path: n2.path, parent: n2 });
return o3.status === "aborted" ? Ta : o3.status === "dirty" || e2.value === "dirty" ? Ra(o3.value) : o3;
});
{
if (e2.value === "aborted")
return Ta;
const o3 = this._def.schema._parseSync({ data: t19, path: n2.path, parent: n2 });
return o3.status === "aborted" ? Ta : o3.status === "dirty" || e2.value === "dirty" ? Ra(o3.value) : o3;
}
}
if (o2.type === "refinement") {
const t19 = (t20) => {
const e3 = o2.refinement(t20, i2);
if (n2.common.async)
return Promise.resolve(e3);
if (e3 instanceof Promise)
throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead.");
return t20;
};
if (n2.common.async === false) {
const o3 = this._def.schema._parseSync({ data: n2.data, path: n2.path, parent: n2 });
return o3.status === "aborted" ? Ta : (o3.status === "dirty" && e2.dirty(), t19(o3.value), { status: e2.value, value: o3.value });
}
return this._def.schema._parseAsync({ data: n2.data, path: n2.path, parent: n2 }).then((n3) => n3.status === "aborted" ? Ta : (n3.status === "dirty" && e2.dirty(), t19(n3.value).then(() => ({ status: e2.value, value: n3.value }))));
}
if (o2.type === "transform") {
if (n2.common.async === false) {
const t19 = this._def.schema._parseSync({ data: n2.data, path: n2.path, parent: n2 });
if (!ka(t19))
return Ta;
const r2 = o2.transform(t19.value, i2);
if (r2 instanceof Promise)
throw new Error("Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.");
return { status: e2.value, value: r2 };
}
return this._def.schema._parseAsync({ data: n2.data, path: n2.path, parent: n2 }).then((t19) => ka(t19) ? Promise.resolve(o2.transform(t19.value, i2)).then((t20) => ({ status: e2.value, value: t20 })) : Ta);
}
la.assertNever(o2);
}
};
$c.create = (t18, e2, n2) => new $c({ schema: t18, typeName: Kc.ZodEffects, effect: e2, ...Ba(n2) }), $c.createWithPreprocess = (t18, e2, n2) => new $c({ schema: e2, effect: { type: "preprocess", transform: t18 }, typeName: Kc.ZodEffects, ...Ba(n2) });
var Yc = class extends ja {
_parse(t18) {
return this._getType(t18) === ma.undefined ? Ea(undefined) : this._def.innerType._parse(t18);
}
unwrap() {
return this._def.innerType;
}
};
Yc.create = (t18, e2) => new Yc({ innerType: t18, typeName: Kc.ZodOptional, ...Ba(e2) });
var Xc = class extends ja {
_parse(t18) {
return this._getType(t18) === ma.null ? Ea(null) : this._def.innerType._parse(t18);
}
unwrap() {
return this._def.innerType;
}
};
Xc.create = (t18, e2) => new Xc({ innerType: t18, typeName: Kc.ZodNullable, ...Ba(e2) });
var Wc = class extends ja {
_parse(t18) {
const { ctx: e2 } = this._processInputParams(t18);
let n2 = e2.data;
return e2.parsedType === ma.undefined && (n2 = this._def.defaultValue()), this._def.innerType._parse({ data: n2, path: e2.path, parent: e2 });
}
removeDefault() {
return this._def.innerType;
}
};
Wc.create = (t18, e2) => new Wc({ innerType: t18, typeName: Kc.ZodDefault, defaultValue: typeof e2.default == "function" ? e2.default : () => e2.default, ...Ba(e2) });
var Vc = class extends ja {
_parse(t18) {
const { ctx: e2 } = this._processInputParams(t18), n2 = { ...e2, common: { ...e2.common, issues: [] } }, o2 = this._def.innerType._parse({ data: n2.data, path: n2.path, parent: { ...n2 } });
return Da(o2) ? o2.then((t19) => ({ status: "valid", value: t19.status === "valid" ? t19.value : this._def.catchValue({ get error() {
return new _a(n2.common.issues);
}, input: n2.data }) })) : { status: "valid", value: o2.status === "valid" ? o2.value : this._def.catchValue({ get error() {
return new _a(n2.common.issues);
}, input: n2.data }) };
}
removeCatch() {
return this._def.innerType;
}
};
Vc.create = (t18, e2) => new Vc({ innerType: t18, typeName: Kc.ZodCatch, catchValue: typeof e2.catch == "function" ? e2.catch : () => e2.catch, ...Ba(e2) });
var Hc = class extends ja {
_parse(t18) {
if (this._getType(t18) !== ma.nan) {
const e2 = this._getOrReturnCtx(t18);
return Pa(e2, { code: fa.invalid_type, expected: ma.nan, received: e2.parsedType }), Ta;
}
return { status: "valid", value: t18.data };
}
};
Hc.create = (t18) => new Hc({ typeName: Kc.ZodNaN, ...Ba(t18) });
var Gc = Symbol("zod_brand");
var Uc = class extends ja {
_parse(t18) {
const { ctx: e2 } = this._processInputParams(t18), n2 = e2.data;
return this._def.type._parse({ data: n2, path: e2.path, parent: e2 });
}
unwrap() {
return this._def.type;
}
};
var Zc = class t18 extends ja {
_parse(t19) {
const { status: e2, ctx: n2 } = this._processInputParams(t19);
if (n2.common.async) {
return (async () => {
const t20 = await this._def.in._parseAsync({ data: n2.data, path: n2.path, parent: n2 });
return t20.status === "aborted" ? Ta : t20.status === "dirty" ? (e2.dirty(), Ra(t20.value)) : this._def.out._parseAsync({ data: t20.value, path: n2.path, parent: n2 });
})();
}
{
const t20 = this._def.in._parseSync({ data: n2.data, path: n2.path, parent: n2 });
return t20.status === "aborted" ? Ta : t20.status === "dirty" ? (e2.dirty(), { status: "dirty", value: t20.value }) : this._def.out._parseSync({ data: t20.value, path: n2.path, parent: n2 });
}
}
static create(e2, n2) {
return new t18({ in: e2, out: n2, typeName: Kc.ZodPipeline });
}
};
var qc = class extends ja {
_parse(t19) {
const e2 = this._def.innerType._parse(t19), n2 = (t20) => (ka(t20) && (t20.value = Object.freeze(t20.value)), t20);
return Da(e2) ? e2.then((t20) => n2(t20)) : n2(e2);
}
unwrap() {
return this._def.innerType;
}
};
function Jc(t19, e2) {
const n2 = typeof t19 == "function" ? t19(e2) : typeof t19 == "string" ? { message: t19 } : t19;
return typeof n2 == "string" ? { message: n2 } : n2;
}
function Qc(t19, e2 = {}, n2) {
return t19 ? _c.create().superRefine((o2, i2) => {
const r2 = t19(o2);
if (r2 instanceof Promise)
return r2.then((t20) => {
if (!t20) {
const t21 = Jc(e2, o2), r3 = t21.fatal ?? n2 ?? true;
i2.addIssue({ code: "custom", ...t21, fatal: r3 });
}
});
if (!r2) {
const t20 = Jc(e2, o2), r3 = t20.fatal ?? n2 ?? true;
i2.addIssue({ code: "custom", ...t20, fatal: r3 });
}
}) : _c.create();
}
qc.create = (t19, e2) => new qc({ innerType: t19, typeName: Kc.ZodReadonly, ...Ba(e2) });
var Kc;
var tl;
var el = { object: Cc.lazycreate };
(tl = Kc || (Kc = {})).ZodString = "ZodString", tl.ZodNumber = "ZodNumber", tl.ZodNaN = "ZodNaN", tl.ZodBigInt = "ZodBigInt", tl.ZodBoolean = "ZodBoolean", tl.ZodDate = "ZodDate", tl.ZodSymbol = "ZodSymbol", tl.ZodUndefined = "ZodUndefined", tl.ZodNull = "ZodNull", tl.ZodAny = "ZodAny", tl.ZodUnknown = "ZodUnknown", tl.ZodNever = "ZodNever", tl.ZodVoid = "ZodVoid", tl.ZodArray = "ZodArray", tl.ZodObject = "ZodObject", tl.ZodUnion = "ZodUnion", tl.ZodDiscriminatedUnion = "ZodDiscriminatedUnion", tl.ZodIntersection = "ZodIntersection", tl.ZodTuple = "ZodTuple", tl.ZodRecord = "ZodRecord", tl.ZodMap = "ZodMap", tl.ZodSet = "ZodSet", tl.ZodFunction = "ZodFunction", tl.ZodLazy = "ZodLazy", tl.ZodLiteral = "ZodLiteral", tl.ZodEnum = "ZodEnum", tl.ZodEffects = "ZodEffects", tl.ZodNativeEnum = "ZodNativeEnum", tl.ZodOptional = "ZodOptional", tl.ZodNullable = "ZodNullable", tl.ZodDefault = "ZodDefault", tl.ZodCatch = "ZodCatch", tl.ZodPromise = "ZodPromise", tl.ZodBranded = "ZodBranded", tl.ZodPipeline = "ZodPipeline", tl.ZodReadonly = "ZodReadonly";
var nl = (t19, e2 = { message: `Input not instance of ${t19.name}` }) => Qc((e3) => e3 instanceof t19, e2);
var ol = lc.create;
var il = dc.create;
var rl = Hc.create;
var sl = uc.create;
var al = pc.create;
var cl = mc.create;
var ll = gc.create;
var hl = fc.create;
var dl = yc.create;
var ul = _c.create;
var pl = bc.create;
var ml = xc.create;
var gl = vc.create;
var fl = Ic.create;
var yl = Cc.create;
var _l = Cc.strictCreate;
var bl = Pc.create;
var xl = Nc.create;
var vl = Tc.create;
var Il = Rc.create;
var Sl = Ec.create;
var Cl = Ac.create;
var Pl = Oc.create;
var Ml = kc.create;
var Nl = Dc.create;
var wl = Lc.create;
var Tl = Bc.create;
var Rl = Fc.create;
var El = jc.create;
var Al = $c.create;
var Ol = Yc.create;
var kl = Xc.create;
var Dl = $c.createWithPreprocess;
var Ll = Zc.create;
var zl = () => ol().optional();
var Bl = () => il().optional();
var Fl = () => al().optional();
var jl = { string: (t19) => lc.create({ ...t19, coerce: true }), number: (t19) => dc.create({ ...t19, coerce: true }), boolean: (t19) => pc.create({ ...t19, coerce: true }), bigint: (t19) => uc.create({ ...t19, coerce: true }), date: (t19) => mc.create({ ...t19, coerce: true }) };
var $l = Ta;
var Yl = pa.string().or(pa.number()).transform((t19) => ca(t19, "Ω").value);
var Xl = pa.string().or(pa.number()).transform((t19) => ca(t19, "F").value).transform((t19) => Number.parseFloat(t19.toPrecision(12)));
var Wl = pa.string().or(pa.number()).transform((t19) => ca(t19, "H").value);
var Vl = pa.string().or(pa.number()).transform((t19) => ca(t19, "V").value);
var Hl = pa.string().or(pa.number()).transform((t19) => ca(t19).value);
var Gl = pa.string().or(pa.number()).transform((t19) => ca(t19, "Hz").value);
var Ul = Hl;
var Zl = pa.string().or(pa.number()).transform((t19) => ca(t19, "A").value);
var ql = pa.string().or(pa.number()).transform((t19) => ca(t19).value);
var Jl = ql;
var Ql = ql;
var Kl = pa.string().datetime();
var th = pa.string().or(pa.number()).transform((t19) => typeof t19 == "number" ? t19 : t19.endsWith("deg") ? Number.parseFloat(t19.split("deg")[0]) : t19.endsWith("rad") ? 180 * Number.parseFloat(t19.split("rad")[0]) / Math.PI : Number.parseFloat(t19));
var eh = pa.number().or(pa.string().endsWith("mAh")).transform((t19) => {
if (typeof t19 == "string") {
const e2 = t19.replace("mAh", ""), n2 = Number.parseFloat(e2);
if (Number.isNaN(n2))
throw new Error("Invalid capacity");
return n2;
}
return t19;
}).describe("Battery capacity in mAh");
var nh = pa.object({ x: Ul, y: Ul });
var oh = nh;
var ih = pa.object({ x: Ul, y: Ul, z: Ul });
var rh = ih;
var sh = pa.object({ width: pa.number(), height: pa.number() });
var ah = (t19) => pa.string().optional().default(() => `${t19}_${((t20) => {
const e2 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return Array.from({ length: t20 }, () => e2[Math.floor(62 * Math.random())]).join("");
})(10)}`);
var ch = pa.enum(["top_left", "top_center", "top_right", "center_left", "center", "center_right", "bottom_left", "bottom_center", "bottom_right"]);
var lh = pa.enum(["top_silkscreen", "bottom_silkscreen", "top_copper", "bottom_copper", "top_soldermask", "bottom_soldermask", "top_fabrication_note", "bottom_fabrication_note", "top_user_note", "bottom_user_note", "top_courtyard", "bottom_courtyard", "inner1_copper", "inner2_copper", "inner3_copper", "inner4_copper", "inner5_copper", "inner6_copper", "inner7_copper", "inner8_copper", "edge_cuts", "drill"]);
var hh = pa.object({ project_relative_path: pa.string(), url: pa.string(), mimetype: pa.string() });
var dh = nh.extend({ rotation: th.optional() });
var uh = pa.object({ size: nh.optional(), thickness: Ul.optional() });
var ph = pa.object({ font: uh.optional() });
var mh = pa.object({ value: pa.string(), at: dh.optional(), layer: pa.string().optional(), uuid: pa.string().optional(), hide: pa.boolean().optional(), effects: ph.optional() });
var gh = pa.object({ Reference: mh.optional(), Value: mh.optional(), Datasheet: mh.optional(), Description: mh.optional() });
var fh = pa.object({ through_hole: pa.boolean().optional(), smd: pa.boolean().optional(), exclude_from_pos_files: pa.boolean().optional(), exclude_from_bom: pa.boolean().optional() });
var yh = pa.object({ name: pa.string(), type: pa.string(), shape: pa.string().optional(), at: dh.optional(), size: nh.optional(), drill: Ul.optional(), layers: pa.array(pa.string()).optional(), removeUnusedLayers: pa.boolean().optional(), uuid: pa.string().optional() });
var _h = pa.object({ path: pa.string(), offset: ih.optional(), scale: ih.optional(), rotate: ih.optional() });
var bh = pa.object({ footprintName: pa.string().optional(), version: pa.union([pa.number(), pa.string()]).optional(), generator: pa.string().optional(), generatorVersion: pa.union([pa.number(), pa.string()]).optional(), layer: pa.string().optional(), properties: gh.optional(), attributes: fh.optional(), pads: pa.array(yh).optional(), embeddedFonts: pa.boolean().optional(), model: _h.optional() });
var xh = pa.object({ hide: pa.boolean().optional() });
var vh = pa.object({ offset: Ul.optional(), hide: pa.boolean().optional() });
var Ih = pa.object({ font: uh.optional(), justify: pa.union([pa.string(), pa.array(pa.string())]).optional(), hide: pa.boolean().optional() });
var Sh = pa.object({ value: pa.string(), id: pa.union([pa.number(), pa.string()]).optional(), at: dh.optional(), effects: Ih.optional() });
var Ch = pa.object({ Reference: Sh.optional(), Value: Sh.optional(), Footprint: Sh.optional(), Datasheet: Sh.optional(), Description: Sh.optional(), ki_keywords: Sh.optional(), ki_fp_filters: Sh.optional() });
var Ph = pa.object({ symbolName: pa.string().optional(), extends: pa.string().optional(), pinNumbers: xh.optional(), pinNames: vh.optional(), excludeFromSim: pa.boolean().optional(), inBom: pa.boolean().optional(), onBoard: pa.boolean().optional(), properties: Ch.optional(), embeddedFonts: pa.boolean().optional() });
var Mh = pa.object({ error_type: pa.string(), message: pa.string(), is_fatal: pa.boolean().optional() });
var Nh = pa.enum(["jlcpcb", "macrofab", "pcbway", "digikey", "mouser", "lcsc"]);
var wh = pa.object({ type: pa.literal("source_component"), ftype: pa.string().optional(), source_component_id: pa.string(), name: pa.string(), manufacturer_part_number: pa.string().optional(), supplier_part_numbers: pa.record(Nh, pa.array(pa.string())).optional(), display_value: pa.string().optional(), display_name: pa.string().optional(), are_pins_interchangeable: pa.boolean().optional(), internally_connected_source_port_ids: pa.array(pa.array(pa.string())).optional(), source_group_id: pa.string().optional(), subcircuit_id: pa.string().optional() });
var Th = wh.extend({ ftype: pa.literal("simple_capacitor"), capacitance: Xl, max_voltage_rating: Vl.optional(), display_capacitance: pa.string().optional(), max_decoupling_trace_length: Ul.optional() });
var Rh = wh.extend({ ftype: pa.literal("simple_resistor"), resistance: Yl, display_resistance: pa.string().optional() });
var Eh = wh.extend({ ftype: pa.literal("simple_diode") });
var Ah = wh.extend({ ftype: pa.literal("simple_fiducial") });
var Oh = Eh.extend({ ftype: pa.literal("simple_led"), color: pa.string().optional(), wavelength: pa.string().optional() });
var kh = wh.extend({ ftype: pa.literal("simple_ground") });
var Dh = wh.extend({ ftype: pa.literal("simple_chip") });
var Lh = wh.extend({ ftype: pa.literal("simple_power_source"), voltage: Vl });
var zh = wh.extend({ ftype: pa.literal("simple_current_source"), current: Zl, frequency: Gl.optional(), peak_to_peak_current: Zl.optional(), wave_shape: pa.enum(["sine", "square", "triangle", "sawtooth", "dc"]).optional().default("dc"), phase: pa.number().optional(), duty_cycle: pa.number().min(0).max(1).optional() });
var Bh = wh.extend({ ftype: pa.literal("simple_fuse"), current_rating_amps: pa.number().describe("Nominal current in amps the fuse is rated for"), voltage_rating_volts: pa.number().describe("Voltage rating in volts, e.g. ±5V would be 5") });
var Fh = wh.extend({ ftype: pa.literal("simple_ammeter") });
var jh = pa.object({ must_be_connected: pa.boolean().optional(), provides_power: pa.boolean().optional(), requires_power: pa.boolean().optional(), provides_ground: pa.boolean().optional(), requires_ground: pa.boolean().optional(), provides_voltage: pa.union([pa.string(), pa.number()]).optional(), requires_voltage: pa.union([pa.string(), pa.number()]).optional(), do_not_connect: pa.boolean().optional(), include_in_board_pinout: pa.boolean().optional(), can_use_internal_pullup: pa.boolean().optional(), is_using_internal_pullup: pa.boolean().optional(), needs_external_pullup: pa.boolean().optional(), can_use_internal_pulldown: pa.boolean().optional(), is_using_internal_pulldown: pa.boolean().optional(), needs_external_pulldown: pa.boolean().optional(), can_use_open_drain: pa.boolean().optional(), is_using_open_drain: pa.boolean().optional(), can_use_push_pull: pa.boolean().optional(), is_using_push_pull: pa.boolean().optional(), should_have_decoupling_capacitor: pa.boolean().optional(), recommended_decoupling_capacitor_capacitance: pa.union([pa.string(), pa.number()]).optional(), is_configured_for_i2c_sda: pa.boolean().optional(), is_configured_for_i2c_scl: pa.boolean().optional(), is_configured_for_spi_mosi: pa.boolean().optional(), is_configured_for_spi_miso: pa.boolean().optional(), is_configured_for_spi_sck: pa.boolean().optional(), is_configured_for_spi_cs: pa.boolean().optional(), is_configured_for_uart_tx: pa.boolean().optional(), is_configured_for_uart_rx: pa.boolean().optional(), supports_i2c_sda: pa.boolean().optional(), supports_i2c_scl: pa.boolean().optional(), supports_spi_mosi: pa.boolean().optional(), supports_spi_miso: pa.boolean().optional(), supports_spi_sck: pa.boolean().optional(), supports_spi_cs: pa.boolean().optional(), supports_uart_tx: pa.boolean().optional(), supports_uart_rx: pa.boolean().optional() });
var $h = wh.extend({ ftype: pa.literal("simple_battery"), capacity: eh });
var Yh = wh.extend({ ftype: pa.literal("simple_inductor"), inductance: Wl, display_inductance: pa.string().optional(), max_current_rating: pa.number().optional() });
var Xh = wh.extend({ ftype: pa.literal("simple_push_button") });
var Wh = wh.extend({ ftype: pa.literal("simple_potentiometer"), max_resistance: Yl, display_max_resistance: pa.string().optional() });
var Vh = wh.extend({ ftype: pa.literal("simple_crystal"), frequency: pa.number().describe("Frequency in Hz"), load_capacitance: pa.number().optional().describe("Load capacitance in pF"), pin_variant: pa.enum(["two_pin", "four_pin"]).optional() });
var Hh = wh.extend({ ftype: pa.literal("simple_pin_header"), pin_count: pa.number(), gender: pa.enum(["male", "female"]).optional().default("male") });
var Gh = wh.extend({ ftype: pa.literal("simple_connector"), standard: pa.enum(["usb_c", "m2"]).optional() });
var Uh = wh.extend({ ftype: pa.literal("simple_pinout") });
var Zh = wh.extend({ ftype: pa.literal("simple_resonator"), load_capacitance: Xl, equivalent_series_resistance: Yl.optional(), frequency: Gl });
var qh = wh.extend({ ftype: pa.literal("simple_transistor"), transistor_type: pa.enum(["npn", "pnp"]) });
var Jh = wh.extend({ ftype: pa.literal("simple_test_point"), footprint_variant: pa.enum(["pad", "through_hole"]).optional(), pad_shape: pa.enum(["rect", "circle"]).optional(), pad_diameter: pa.union([pa.number(), pa.string()]).optional(), hole_diameter: pa.union([pa.number(), pa.string()]).optional(), width: pa.union([pa.number(), pa.string()]).optional(), height: pa.union([pa.number(), pa.string()]).optional() });
var Qh = wh.extend({ ftype: pa.literal("simple_mosfet"), channel_type: pa.enum(["n", "p"]), mosfet_mode: pa.enum(["enhancement", "depletion"]) });
var Kh = wh.extend({ ftype: pa.literal("simple_op_amp") });
var td = wh.extend({ ftype: pa.literal("simple_switch") });
var ed = pa.object({ type: pa.literal("source_project_metadata"), name: pa.string().optional(), software_used_string: pa.string().optional(), project_url: pa.string().optional(), source_filesystem_md5_hash: pa.string().optional(), created_at: Kl.optional() });
var nd = Mh.extend({ type: pa.literal("source_missing_property_error"), source_missing_property_error_id: ah("source_missing_property_error"), source_component_id: pa.string(), property_name: pa.string(), subcircuit_id: pa.string().optional(), error_type: pa.literal("source_missing_property_error").default("source_missing_property_error") }).describe("The source code is missing a property");
var od = Mh.extend({ type: pa.literal("source_failed_to_create_component_error"), source_failed_to_create_component_error_id: ah("source_failed_to_create_component_error"), error_type: pa.literal("source_failed_to_create_component_error").default("source_failed_to_create_component_error"), component_name: pa.string().optional(), subcircuit_id: pa.string().optional(), parent_source_component_id: pa.string().optional(), pcb_center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), schematic_center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional() }).describe("Error emitted when a component fails to be constructed");
var id = Mh.extend({ type: pa.literal("source_invalid_component_property_error"), source_invalid_component_property_error_id: ah("source_invalid_component_property_error"), source_component_id: pa.string(), property_name: pa.string(), property_value: pa.unknown().optional(), expected_format: pa.string().optional(), subcircuit_id: pa.string().optional(), error_type: pa.literal("source_invalid_component_property_error").default("source_invalid_component_property_error") }).describe("The source component property is invalid");
var rd = Mh.extend({ type: pa.literal("source_trace_not_connected_error"), source_trace_not_connected_error_id: ah("source_trace_not_connected_error"), error_type: pa.literal("source_trace_not_connected_error").default("source_trace_not_connected_error"), subcircuit_id: pa.string().optional(), source_group_id: pa.string().optional(), source_trace_id: pa.string().optional(), connected_source_port_ids: pa.array(pa.string()).optional(), selectors_not_found: pa.array(pa.string()).optional() }).describe("Occurs when a source trace selector does not match any ports");
var sd = pa.object({ type: pa.literal("source_property_ignored_warning"), source_property_ignored_warning_id: ah("source_property_ignored_warning"), source_component_id: pa.string(), property_name: pa.string(), subcircuit_id: pa.string().optional(), error_type: pa.literal("source_property_ignored_warning").default("source_property_ignored_warning"), message: pa.string() }).describe("The source property was ignored");
var ad = pa.object({ type: pa.literal("source_pin_missing_trace_warning"), source_pin_missing_trace_warning_id: ah("source_pin_missing_trace_warning"), warning_type: pa.literal("source_pin_missing_trace_warning").default("source_pin_missing_trace_warning"), message: pa.string(), source_component_id: pa.string(), source_port_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a source component pin is missing a trace connection");
var cd = pa.object({ type: pa.literal("source_missing_manufacturer_part_number_warning"), source_missing_manufacturer_part_number_warning_id: ah("source_missing_manufacturer_part_number_warning"), warning_type: pa.literal("source_missing_manufacturer_part_number_warning").default("source_missing_manufacturer_part_number_warning"), message: pa.string(), source_component_id: pa.string(), standard: pa.string(), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a standard connector is missing manufacturer part number");
var ld = pa.object({ type: pa.literal("source_refdes_convention_warning"), source_refdes_convention_warning_id: ah("source_refdes_convention_warning"), warning_type: pa.literal("source_refdes_convention_warning").default("source_refdes_convention_warning"), message: pa.string(), source_component_id: pa.string(), refdes: pa.string(), source_component_ftype: pa.string(), expected_prefixes: pa.array(pa.string()), actual_prefix: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a source component reference designator does not match the component type convention");
var hd = wh.extend({ ftype: pa.literal("simple_voltage_probe") });
var dd = wh.extend({ ftype: pa.literal("interconnect") });
var ud = Mh.extend({ type: pa.literal("source_i2c_misconfigured_error"), source_i2c_misconfigured_error_id: ah("source_i2c_misconfigured_error"), error_type: pa.literal("source_i2c_misconfigured_error").default("source_i2c_misconfigured_error"), source_port_ids: pa.array(pa.string()) }).describe("Error emitted when incompatible I2C pins (e.g. SDA and SCL) are connected to the same net");
var pd = Mh.extend({ type: pa.literal("source_component_misconfigured_error"), source_component_misconfigured_error_id: ah("source_component_misconfigured_error"), error_type: pa.literal("source_component_misconfigured_error").default("source_component_misconfigured_error"), source_component_ids: pa.array(pa.string()), source_port_ids: pa.array(pa.string()).optional() }).describe("Error emitted when one or more source components have an invalid or conflicting configuration");
var md = wh.extend({ ftype: pa.literal("simple_voltage_source"), voltage: Vl, frequency: Gl.optional(), peak_to_peak_voltage: Vl.optional(), wave_shape: pa.enum(["sinewave", "square", "triangle", "sawtooth"]).optional(), phase: th.optional(), duty_cycle: pa.number().optional().describe("Duty cycle as a fraction (0 to 1)"), pulse_delay: Ql.optional(), rise_time: Ql.optional(), fall_time: Ql.optional(), pulse_width: Ql.optional(), period: Ql.optional() });
var gd = pa.union([Rh, Th, Eh, Ah, Oh, kh, Dh, Lh, zh, Fh, $h, Yh, Xh, Wh, Vh, Hh, Gh, Uh, Zh, td, qh, Jh, Qh, Kh, Bh, hd, dd, md, ed, nd, id, od, rd, sd, ad, cd, ld, ud, pd]);
var fd = pa.object({ type: pa.literal("source_port"), pin_number: pa.number().optional(), port_hints: pa.array(pa.string()).optional(), name: pa.string(), source_port_id: pa.string(), source_component_id: pa.string().optional(), source_group_id: pa.string().optional(), most_frequently_referenced_by_name: pa.string().optional(), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional() }).merge(jh);
var yd = pa.object({ type: pa.literal("source_component_internal_connection"), source_component_internal_connection_id: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() });
var _d = pa.object({ type: pa.literal("source_trace"), source_trace_id: pa.string(), connected_source_port_ids: pa.array(pa.string()), connected_source_net_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional(), max_length: pa.number().optional(), name: pa.string().optional(), min_trace_thickness: pa.number().optional(), display_name: pa.string().optional() });
var bd = pa.object({ type: pa.literal("source_group"), source_group_id: pa.string(), subcircuit_id: pa.string().optional(), parent_subcircuit_id: pa.string().optional(), parent_source_group_id: pa.string().optional(), is_subcircuit: pa.boolean().optional(), show_as_schematic_box: pa.boolean().optional(), name: pa.string().optional(), was_automatically_named: pa.boolean().optional() });
var xd = pa.object({ type: pa.literal("source_net"), source_net_id: pa.string(), name: pa.string(), member_source_group_ids: pa.array(pa.string()), is_power: pa.boolean().optional(), is_ground: pa.boolean().optional(), is_digital_signal: pa.boolean().optional(), is_analog_signal: pa.boolean().optional(), is_positive_voltage_source: pa.boolean().optional(), trace_width: pa.number().optional(), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional() });
var vd = pa.object({ type: pa.literal("source_board"), source_board_id: pa.string(), source_group_id: pa.string(), title: pa.string().optional() }).describe("Defines a board in the source domain");
var Id = Mh.extend({ type: pa.literal("source_ambiguous_port_reference"), source_ambiguous_port_reference_id: ah("source_ambiguous_port_reference"), error_type: pa.literal("source_ambiguous_port_reference").default("source_ambiguous_port_reference"), source_port_id: pa.string().optional(), source_component_id: pa.string().optional() }).describe("Error emitted when a port hint matches multiple non-overlapping pads, making the port reference ambiguous");
var Sd = pa.object({ type: pa.literal("source_pcb_ground_plane"), source_pcb_ground_plane_id: pa.string(), source_group_id: pa.string(), source_net_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Defines a ground plane in the source domain");
var Cd = ["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6", "inner7", "inner8"];
var Pd = pa.enum(Cd);
var Md = Pd.or(pa.object({ name: Pd })).transform((t19) => typeof t19 == "string" ? t19 : t19.name);
var Nd = pa.enum(["top", "bottom"]);
var wd = pa.object({ type: pa.literal("source_manually_placed_via"), source_manually_placed_via_id: pa.string(), source_group_id: pa.string(), source_net_id: pa.string(), subcircuit_id: pa.string().optional(), source_trace_id: pa.string().optional() }).describe("Defines a via that is manually placed in the source domain");
var Td = pa.object({ type: pa.literal("source_unnamed_trace_warning"), source_unnamed_trace_warning_id: ah("source_unnamed_trace_warning"), warning_type: pa.literal("source_unnamed_trace_warning").default("source_unnamed_trace_warning"), message: pa.string(), source_trace_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a source trace is missing a name");
var Rd = pa.object({ type: pa.literal("source_no_power_pin_defined_warning"), source_no_power_pin_defined_warning_id: ah("source_no_power_pin_defined_warning"), warning_type: pa.literal("source_no_power_pin_defined_warning").default("source_no_power_pin_defined_warning"), message: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a chip has no source ports with requires_power=true");
var Ed = pa.object({ type: pa.literal("source_no_ground_pin_defined_warning"), source_no_ground_pin_defined_warning_id: ah("source_no_ground_pin_defined_warning"), warning_type: pa.literal("source_no_ground_pin_defined_warning").default("source_no_ground_pin_defined_warning"), message: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a chip has no source ports marked as ground pins");
var Ad = pa.object({ type: pa.literal("source_component_pins_underspecified_warning"), source_component_pins_underspecified_warning_id: ah("source_component_pins_underspecified_warning"), warning_type: pa.literal("source_component_pins_underspecified_warning").default("source_component_pins_underspecified_warning"), message: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Warning emitted when all ports on a source component are underspecified");
var Od = Mh.extend({ type: pa.literal("source_pin_must_be_connected_error"), source_pin_must_be_connected_error_id: ah("source_pin_must_be_connected_error"), error_type: pa.literal("source_pin_must_be_connected_error").default("source_pin_must_be_connected_error"), source_component_id: pa.string(), source_port_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a pin with mustBeConnected attribute is not connected to any trace");
var kd = Mh.extend({ type: pa.literal("unknown_error_finding_part"), unknown_error_finding_part_id: ah("unknown_error_finding_part"), error_type: pa.literal("unknown_error_finding_part").default("unknown_error_finding_part"), source_component_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when an unexpected error occurs while finding a part");
var Dd = pa.object({ type: pa.literal("source_part_not_found_warning"), source_part_not_found_warning_id: ah("source_part_not_found_warning"), warning_type: pa.literal("source_part_not_found_warning").default("source_part_not_found_warning"), message: pa.string(), source_component_id: pa.string().optional(), subcircuit_id: pa.string().optional(), supplier_name: Nh.optional(), manufacturer_part_number: pa.string().optional(), supplier_part_number: pa.string().optional(), part_name: pa.string().optional() }).describe("Warning emitted when a requested part can not be found");
var Ld = pa.object({ type: pa.literal("schematic_box"), schematic_sheet_id: pa.string().optional(), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), width: Ul, height: Ul, is_dashed: pa.boolean().default(false), x: Ul, y: Ul, subcircuit_id: pa.string().optional() }).describe("Draws a box on the schematic");
var zd = pa.object({ type: pa.literal("schematic_path"), schematic_path_id: ah("schematic_path"), schematic_sheet_id: pa.string().optional(), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), fill_color: pa.string().optional(), is_filled: pa.boolean().optional(), is_dashed: pa.boolean().default(false), stroke_width: Ul.nullable().optional(), stroke_color: pa.string().optional(), dash_length: Ul.optional(), dash_gap: Ul.optional(), points: pa.array(nh), subcircuit_id: pa.string().optional() });
var Bd = pa.record(pa.object({ left_margin: Hl.optional(), right_margin: Hl.optional(), top_margin: Hl.optional(), bottom_margin: Hl.optional() }));
var Fd = pa.object({ left_size: pa.number(), right_size: pa.number(), top_size: pa.number().optional(), bottom_size: pa.number().optional() });
var jd = pa.object({ left_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["top-to-bottom", "bottom-to-top"]).optional() }).optional(), right_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["top-to-bottom", "bottom-to-top"]).optional() }).optional(), top_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["left-to-right", "right-to-left"]).optional() }).optional(), bottom_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["left-to-right", "right-to-left"]).optional() }).optional() });
var $d = pa.union([Fd, jd]);
var Yd = pa.object({ type: pa.literal("schematic_component"), size: sh, center: nh, source_component_id: pa.string().optional(), schematic_component_id: pa.string(), schematic_sheet_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), pin_spacing: Hl.optional(), pin_styles: Bd.optional(), box_width: Hl.optional(), symbol_name: pa.string().optional(), port_arrangement: $d.optional(), port_labels: pa.record(pa.string()).optional(), symbol_display_value: pa.string().optional(), subcircuit_id: pa.string().optional(), schematic_group_id: pa.string().optional(), is_schematic_group: pa.boolean().optional(), source_group_id: pa.string().optional(), is_box_with_pins: pa.boolean().optional().default(true) });
var Xd = pa.object({ kicad_symbol: Ph.optional() }).catchall(pa.unknown());
var Wd = pa.object({ type: pa.literal("schematic_symbol"), schematic_symbol_id: pa.string(), name: pa.string().optional(), metadata: Xd.optional() }).describe("Defines a named schematic symbol that can be referenced by components.");
var Vd = pa.object({ type: pa.literal("schematic_line"), schematic_line_id: ah("schematic_line"), schematic_sheet_id: pa.string().optional(), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), x1: Ul, y1: Ul, x2: Ul, y2: Ul, stroke_width: Ul.nullable().optional(), color: pa.string().default("#000000"), is_dashed: pa.boolean().default(false), dash_length: Ul.optional(), dash_gap: Ul.optional(), subcircuit_id: pa.string().optional() }).describe("Draws a styled line on the schematic");
var Hd = pa.object({ type: pa.literal("schematic_rect"), schematic_rect_id: ah("schematic_rect"), schematic_sheet_id: pa.string().optional(), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), center: nh, width: Ul, height: Ul, rotation: th.default(0), stroke_width: Ul.nullable().optional(), color: pa.string().default("#000000"), is_filled: pa.boolean().default(false), fill_color: pa.string().optional(), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled rectangle on the schematic");
var Gd = pa.object({ type: pa.literal("schematic_circle"), schematic_circle_id: ah("schematic_circle"), schematic_sheet_id: pa.string().optional(), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), center: nh, radius: Ul, stroke_width: Ul.nullable().optional(), color: pa.string().default("#000000"), is_filled: pa.boolean().default(false), fill_color: pa.string().optional(), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled circle on the schematic");
var Ud = pa.object({ type: pa.literal("schematic_arc"), schematic_arc_id: ah("schematic_arc"), schematic_sheet_id: pa.string().optional(), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), center: nh, radius: Ul, start_angle_degrees: th, end_angle_degrees: th, direction: pa.enum(["clockwise", "counterclockwise"]).default("counterclockwise"), stroke_width: Ul.nullable().optional(), color: pa.string().default("#000000"), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled arc on the schematic");
var Zd = pa.object({ type: pa.literal("schematic_trace"), schematic_trace_id: pa.string(), schematic_sheet_id: pa.string().optional(), source_trace_id: pa.string().optional(), junctions: pa.array(pa.object({ x: pa.number(), y: pa.number() })), edges: pa.array(pa.object({ from: pa.object({ x: pa.number(), y: pa.number() }), to: pa.object({ x: pa.number(), y: pa.number() }), is_crossing: pa.boolean().optional(), from_schematic_port_id: pa.string().optional(), to_schematic_port_id: pa.string().optional() })), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional() });
var qd = pa.enum(["center", "left", "right", "top", "bottom"]);
var Jd = pa.object({ type: pa.literal("schematic_text"), schematic_sheet_id: pa.string().optional(), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), schematic_text_id: pa.string(), text: pa.string(), font_size: pa.number().default(0.18), position: pa.object({ x: Ul, y: Ul }), rotation: pa.number().default(0), anchor: pa.union([qd.describe("legacy"), ch]).default("center"), color: pa.string().default("#000000"), subcircuit_id: pa.string().optional() });
var Qd = pa.object({ type: pa.literal("schematic_port"), schematic_port_id: pa.string(), source_port_id: pa.string(), schematic_sheet_id: pa.string().optional(), schematic_component_id: pa.string().optional(), center: nh, facing_direction: pa.enum(["up", "down", "left", "right"]).optional(), distance_from_component_edge: pa.number().optional(), side_of_component: pa.enum(["top", "bottom", "left", "right"]).optional(), true_ccw_index: pa.number().optional(), pin_number: pa.number().optional(), display_pin_label: pa.string().optional(), subcircuit_id: pa.string().optional(), is_connected: pa.boolean().optional(), has_input_arrow: pa.boolean().optional(), has_output_arrow: pa.boolean().optional(), is_drawn_with_inversion_circle: pa.boolean().optional() }).describe("Defines a port on a schematic component");
var Kd = pa.object({ type: pa.literal("schematic_net_label"), schematic_net_label_id: ah("schematic_net_label"), schematic_sheet_id: pa.string().optional(), schematic_trace_id: pa.string().optional(), source_trace_id: pa.string().optional(), source_net_id: pa.string(), center: nh, anchor_position: nh.optional(), anchor_side: pa.enum(["top", "bottom", "left", "right"]), text: pa.string(), symbol_name: pa.string().optional(), is_movable: pa.boolean().optional(), subcircuit_id: pa.string().optional() });
var tu = Mh.extend({ type: pa.literal("schematic_error"), schematic_error_id: pa.string(), error_type: pa.literal("schematic_port_not_found").default("schematic_port_not_found"), subcircuit_id: pa.string().optional() }).describe("Defines a schematic error on the schematic");
var eu = Mh.extend({ type: pa.literal("schematic_layout_error"), schematic_layout_error_id: ah("schematic_layout_error"), error_type: pa.literal("schematic_layout_error").default("schematic_layout_error"), source_group_id: pa.string(), schematic_group_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Error emitted when schematic layout fails for a group");
var nu = pa.object({ type: pa.literal("schematic_debug_object"), label: pa.string().optional(), subcircuit_id: pa.string().optional() });
var ou = nu.extend({ shape: pa.literal("rect"), center: nh, size: sh });
var iu = nu.extend({ shape: pa.literal("line"), start: nh, end: nh });
var ru = nu.extend({ shape: pa.literal("point"), center: nh });
var su = pa.discriminatedUnion("shape", [ou, iu, ru]);
var au = pa.object({ type: pa.literal("schematic_voltage_probe"), schematic_voltage_probe_id: pa.string(), schematic_sheet_id: pa.string().optional(), source_component_id: pa.string().optional(), name: pa.string().optional(), position: nh, schematic_trace_id: pa.string(), voltage: Vl.optional(), subcircuit_id: pa.string().optional(), color: pa.string().optional(), label_alignment: ch.optional() }).describe("Defines a voltage probe measurement point on a schematic trace");
var cu = pa.object({ type: pa.literal("schematic_manual_edit_conflict_warning"), schematic_manual_edit_conflict_warning_id: ah("schematic_manual_edit_conflict_warning"), warning_type: pa.literal("schematic_manual_edit_conflict_warning").default("schematic_manual_edit_conflict_warning"), message: pa.string(), schematic_component_id: pa.string(), schematic_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), source_component_id: pa.string() }).describe("Warning emitted when a component has both manual placement and explicit schX/schY coordinates");
var lu = pa.object({ type: pa.literal("schematic_group"), schematic_group_id: ah("schematic_group"), schematic_sheet_id: pa.string().optional(), source_group_id: pa.string(), is_subcircuit: pa.boolean().optional(), subcircuit_id: pa.string().optional(), width: Hl, height: Hl, center: nh, schematic_component_ids: pa.array(pa.string()), show_as_schematic_box: pa.boolean().optional(), name: pa.string().optional(), description: pa.string().optional() }).describe("Defines a group of components on the schematic");
var hu = pa.object({ type: pa.literal("schematic_table"), schematic_table_id: ah("schematic_table"), schematic_sheet_id: pa.string().optional(), anchor_position: nh, column_widths: pa.array(Ul), row_heights: pa.array(Ul), cell_padding: Ul.optional(), border_width: Ul.optional(), subcircuit_id: pa.string().optional(), schematic_component_id: pa.string().optional(), anchor: ch.optional() }).describe("Defines a table on the schematic");
var du = pa.object({ type: pa.literal("schematic_table_cell"), schematic_table_cell_id: ah("schematic_table_cell"), schematic_sheet_id: pa.string().optional(), schematic_table_id: pa.string(), start_row_index: pa.number(), end_row_index: pa.number(), start_column_index: pa.number(), end_column_index: pa.number(), text: pa.string().optional(), center: nh, width: Ul, height: Ul, horizontal_align: pa.enum(["left", "center", "right"]).optional(), vertical_align: pa.enum(["top", "middle", "bottom"]).optional(), font_size: Ul.optional(), subcircuit_id: pa.string().optional() }).describe("Defines a cell within a schematic_table");
var uu = pa.object({ type: pa.literal("schematic_sheet"), schematic_sheet_id: ah("schematic_sheet"), name: pa.string().optional(), sheet_index: pa.number().optional(), subcircuit_id: pa.string().optional(), outline_color: pa.string().optional() }).describe("Defines a schematic sheet or page that components can be placed on");
var pu = pa.object({ x: Ul, y: Ul, bulge: pa.number().optional() });
var mu = pa.object({ vertices: pa.array(pu) });
var gu = pa.object({ outer_ring: mu, inner_rings: pa.array(mu).default([]) });
var fu = pa.object({ x: Ul, y: Ul, via: pa.boolean().optional(), via_to_layer: Md.optional() });
var yu = pa.array(fu);
var _u = pa.object({ x: Ul, y: Ul, via: pa.boolean().optional(), to_layer: Md.optional(), trace_width: Ul.optional() });
var bu = pa.object({ min_trace_width: Hl.optional(), min_board_edge_clearance: Hl.optional(), min_via_hole_edge_to_via_hole_edge_clearance: Hl.optional(), min_plated_hole_drill_edge_to_drill_edge_clearance: Hl.optional(), min_trace_to_pad_edge_clearance: Hl.optional(), min_pad_edge_to_pad_edge_clearance: Hl.optional(), min_same_net_trace_edge_to_trace_edge_clearance: Hl.optional(), min_different_net_trace_edge_to_trace_edge_clearance: Hl.optional(), min_via_edge_to_pad_edge_clearance: Hl.optional(), min_via_hole_diameter: Hl.optional(), min_via_pad_diameter: Hl.optional() });
var xu = pa.object({ type: pa.literal("pcb_component"), pcb_component_id: ah("pcb_component"), source_component_id: pa.string(), center: nh, layer: Md, rotation: th, display_offset_x: pa.string().optional().describe("How to display the x offset for this part, usually corresponding with how the user specified it"), display_offset_y: pa.string().optional().describe("How to display the y offset for this part, usually corresponding with how the user specified it"), width: Hl, height: Hl, do_not_place: pa.boolean().optional(), is_allowed_to_be_off_board: pa.boolean().optional(), subcircuit_id: pa.string().optional(), pcb_group_id: pa.string().optional(), position_mode: pa.enum(["packed", "relative_to_group_anchor", "relative_to_another_component", "none"]).optional(), anchor_position: nh.optional(), anchor_alignment: ch.optional(), positioned_relative_to_pcb_group_id: pa.string().optional(), positioned_relative_to_pcb_board_id: pa.string().optional(), cable_insertion_center: nh.optional(), insertion_direction: pa.enum(["from_above", "from_left", "from_right", "from_front", "from_back"]).optional(), metadata: pa.object({ kicad_footprint: bh.optional() }).optional(), obstructs_within_bounds: pa.boolean().default(true).describe("Does this component take up all the space within its bounds on a layer. This is generally true except for when separated pin headers are being represented by a single component (in which case, chips can be placed between the pin headers) or for tall modules where chips fit underneath") }).describe("Defines a component on the PCB");
var vu = pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: ah("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("circle"), hole_diameter: pa.number(), x: Ul, y: Ul, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var Iu = vu.describe("Defines a circular hole on the PCB");
var Su = pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: ah("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("rect"), hole_width: pa.number(), hole_height: pa.number(), x: Ul, y: Ul, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var Cu = Su.describe("Defines a rectangular (square-capable) hole on the PCB. Use equal width/height for square.");
var Pu = pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: ah("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.enum(["circle", "square"]), hole_diameter: pa.number(), x: Ul, y: Ul, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var Mu = Pu.describe("Defines a circular or square hole on the PCB");
var Nu = pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: ah("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("oval"), hole_width: pa.number(), hole_height: pa.number(), x: Ul, y: Ul, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var wu = Nu.describe("Defines an oval hole on the PCB");
var Tu = pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: ah("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("pill"), hole_width: pa.number(), hole_height: pa.number(), x: Ul, y: Ul, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var Ru = Tu.describe("Defines a pill-shaped hole on the PCB");
var Eu = pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: ah("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("rotated_pill"), hole_width: pa.number(), hole_height: pa.number(), x: Ul, y: Ul, ccw_rotation: th, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var Au = Eu.describe("Defines a rotated pill-shaped hole on the PCB");
var Ou = Pu.or(Nu).or(Tu).or(Eu).or(vu).or(Su);
var ku = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("circle"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), outer_diameter: pa.number(), hole_diameter: pa.number(), is_covered_with_solder_mask: pa.boolean().optional(), x: Ul, y: Ul, layers: pa.array(Md), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: ah("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var Du = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.enum(["oval", "pill"]), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), outer_width: pa.number(), outer_height: pa.number(), hole_width: pa.number(), hole_height: pa.number(), is_covered_with_solder_mask: pa.boolean().optional(), x: Ul, y: Ul, ccw_rotation: th, layers: pa.array(Md), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: ah("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var Lu = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("circular_hole_with_rect_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.literal("circle"), pad_shape: pa.literal("rect"), hole_diameter: pa.number(), rect_pad_width: pa.number(), rect_pad_height: pa.number(), rect_border_radius: pa.number().optional(), hole_offset_x: Ul.default(0), hole_offset_y: Ul.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: Ul, y: Ul, layers: pa.array(Md), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: ah("pcb_plated_hole"), soldermask_margin: pa.number().optional(), rect_ccw_rotation: th.optional() });
var zu = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("pill_hole_with_rect_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.literal("pill"), pad_shape: pa.literal("rect"), hole_width: pa.number(), hole_height: pa.number(), rect_pad_width: pa.number(), rect_pad_height: pa.number(), rect_border_radius: pa.number().optional(), hole_offset_x: Ul.default(0), hole_offset_y: Ul.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: Ul, y: Ul, layers: pa.array(Md), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: ah("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var Bu = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("rotated_pill_hole_with_rect_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.literal("rotated_pill"), pad_shape: pa.literal("rect"), hole_width: pa.number(), hole_height: pa.number(), hole_ccw_rotation: th, rect_pad_width: pa.number(), rect_pad_height: pa.number(), rect_border_radius: pa.number().optional(), rect_ccw_rotation: th, hole_offset_x: Ul.default(0), hole_offset_y: Ul.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: Ul, y: Ul, layers: pa.array(Md), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: ah("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var Fu = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("hole_with_polygon_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.enum(["circle", "oval", "pill", "rotated_pill"]), hole_diameter: pa.number().optional(), hole_width: pa.number().optional(), hole_height: pa.number().optional(), pad_outline: pa.array(pa.object({ x: Ul, y: Ul })).min(3), hole_offset_x: Ul.default(0), hole_offset_y: Ul.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: Ul, y: Ul, layers: pa.array(Md), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: ah("pcb_plated_hole"), soldermask_margin: pa.number().optional(), ccw_rotation: th.optional() });
var ju = pa.union([ku, Du, Lu, zu, Bu, Fu]);
var $u = pa.object({ type: pa.literal("pcb_port"), pcb_port_id: ah("pcb_port"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), source_port_id: pa.string(), pcb_component_id: pa.string().optional(), x: Ul, y: Ul, layers: pa.array(Md), is_board_pinout: pa.boolean().optional() }).describe("Defines a port on the PCB");
var Yu = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("circle"), pcb_smtpad_id: ah("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ul, y: Ul, radius: pa.number(), layer: Md, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var Xu = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("rect"), pcb_smtpad_id: ah("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ul, y: Ul, width: pa.number(), height: pa.number(), rect_border_radius: pa.number().optional(), corner_radius: pa.number().optional(), layer: Md, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional(), soldermask_margin_left: pa.number().optional(), soldermask_margin_top: pa.number().optional(), soldermask_margin_right: pa.number().optional(), soldermask_margin_bottom: pa.number().optional() });
var Wu = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("rotated_rect"), pcb_smtpad_id: ah("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ul, y: Ul, width: pa.number(), height: pa.number(), rect_border_radius: pa.number().optional(), corner_radius: pa.number().optional(), ccw_rotation: th, layer: Md, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional(), soldermask_margin_left: pa.number().optional(), soldermask_margin_top: pa.number().optional(), soldermask_margin_right: pa.number().optional(), soldermask_margin_bottom: pa.number().optional() });
var Vu = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("pill"), pcb_smtpad_id: ah("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ul, y: Ul, width: pa.number(), height: pa.number(), radius: pa.number(), layer: Md, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var Hu = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("rotated_pill"), pcb_smtpad_id: ah("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ul, y: Ul, width: pa.number(), height: pa.number(), radius: pa.number(), ccw_rotation: th, layer: Md, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var Gu = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("polygon"), pcb_smtpad_id: ah("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), points: pa.array(nh), layer: Md, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var Uu = pa.discriminatedUnion("shape", [Yu, Xu, Wu, Hu, Vu, Gu]).describe("Defines an SMT pad on the PCB");
var Zu = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("circle"), pcb_solder_paste_id: ah("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ul, y: Ul, radius: pa.number(), layer: Md, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var qu = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("rect"), pcb_solder_paste_id: ah("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ul, y: Ul, width: pa.number(), height: pa.number(), layer: Md, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var Ju = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("pill"), pcb_solder_paste_id: ah("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ul, y: Ul, width: pa.number(), height: pa.number(), radius: pa.number(), layer: Md, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var Qu = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("rotated_rect"), pcb_solder_paste_id: ah("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ul, y: Ul, width: pa.number(), height: pa.number(), ccw_rotation: Ul, layer: Md, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var Ku = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("oval"), pcb_solder_paste_id: ah("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ul, y: Ul, width: pa.number(), height: pa.number(), layer: Md, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var tp = pa.union([Zu, qu, Ju, Qu, Ku]).describe("Defines solderpaste on the PCB");
var ep = pa.object({ type: pa.literal("pcb_text"), pcb_text_id: ah("pcb_text"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), text: pa.string(), center: nh, layer: Md, width: Hl, height: Hl, lines: pa.number(), align: pa.enum(["bottom-left"]) }).describe("Defines text on the PCB");
var np = pa.object({ route_type: pa.literal("wire"), x: Ul, y: Ul, width: Ul, copper_pour_id: pa.string().optional(), is_inside_copper_pour: pa.boolean().optional(), start_pcb_port_id: pa.string().optional(), end_pcb_port_id: pa.string().optional(), layer: Md });
var op = pa.object({ route_type: pa.literal("via"), x: Ul, y: Ul, copper_pour_id: pa.string().optional(), is_inside_copper_pour: pa.boolean().optional(), hole_diameter: Ul.optional(), outer_diameter: Ul.optional(), from_layer: Md, to_layer: Md });
var ip = pa.object({ route_type: pa.literal("through_pad"), start: nh, end: nh, width: Ul, start_layer: Md, end_layer: Md, pcb_smtpad_id: pa.string().optional(), pcb_plated_hole_id: pa.string().optional() });
var rp = pa.union([np, op, ip]);
var sp = pa.object({ type: pa.literal("pcb_trace"), source_trace_id: pa.string().optional(), pcb_component_id: pa.string().optional(), pcb_trace_id: ah("pcb_trace"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), route_thickness_mode: pa.enum(["constant", "interpolated"]).default("constant").optional(), route_order_index: pa.number().optional(), should_round_corners: pa.boolean().optional(), trace_length: pa.number().optional(), highlight_color: pa.string().optional(), route: pa.array(rp) }).describe("Defines a trace on the PCB");
var ap = pa.object({ type: pa.literal("pcb_trace_warning"), pcb_trace_warning_id: ah("pcb_trace_warning"), warning_type: pa.literal("pcb_trace_warning").default("pcb_trace_warning"), message: pa.string(), center: nh.optional(), pcb_trace_id: pa.string(), source_trace_id: pa.string(), pcb_component_ids: pa.array(pa.string()), pcb_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines a trace warning on the PCB");
var cp = pa.object({ type: pa.literal("pcb_trace_too_long_warning"), pcb_trace_too_long_warning_id: ah("pcb_trace_too_long_warning"), warning_type: pa.literal("pcb_trace_too_long_warning").default("pcb_trace_too_long_warning"), message: pa.string(), pcb_trace_id: pa.string(), source_net_id: pa.string().optional(), source_trace_id: pa.string().optional(), actual_trace_length: Ul, maximum_trace_length: Ul, subcircuit_id: pa.string().optional() }).describe("Warning emitted when a PCB trace is longer than its maximum allowed length");
var lp = Mh.extend({ type: pa.literal("pcb_trace_error"), pcb_trace_error_id: ah("pcb_trace_error"), error_type: pa.literal("pcb_trace_error").default("pcb_trace_error"), center: nh.optional(), pcb_trace_id: pa.string(), source_trace_id: pa.string(), pcb_component_ids: pa.array(pa.string()), pcb_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines a trace error on the PCB");
var hp = Mh.extend({ type: pa.literal("pcb_trace_missing_error"), pcb_trace_missing_error_id: ah("pcb_trace_missing_error"), error_type: pa.literal("pcb_trace_missing_error").default("pcb_trace_missing_error"), center: nh.optional(), source_trace_id: pa.string(), pcb_component_ids: pa.array(pa.string()), pcb_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines an error when a source trace has no corresponding PCB trace");
var dp = Mh.extend({ type: pa.literal("pcb_port_not_matched_error"), pcb_error_id: ah("pcb_error"), error_type: pa.literal("pcb_port_not_matched_error").default("pcb_port_not_matched_error"), pcb_component_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines a trace error on the PCB where a port is not matched");
var up = Mh.extend({ type: pa.literal("pcb_port_not_connected_error"), pcb_port_not_connected_error_id: ah("pcb_port_not_connected_error"), error_type: pa.literal("pcb_port_not_connected_error").default("pcb_port_not_connected_error"), pcb_port_ids: pa.array(pa.string()), pcb_component_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines an error when a pcb port is not connected to any trace");
var pp = pa.object({ type: pa.literal("pcb_net"), pcb_net_id: ah("pcb_net"), source_net_id: pa.string().optional(), highlight_color: pa.string().optional() }).describe("Defines a net on the PCB");
var mp = pa.object({ type: pa.literal("pcb_via"), pcb_via_id: ah("pcb_via"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional(), x: Ul, y: Ul, outer_diameter: Ul.default("0.6mm"), hole_diameter: Ul.default("0.25mm"), from_layer: Md.optional(), to_layer: Md.optional(), layers: pa.array(Md), pcb_trace_id: pa.string().optional(), net_is_assignable: pa.boolean().optional(), net_assigned: pa.boolean().optional(), is_tented: pa.boolean().optional() }).describe("Defines a via on the PCB");
var gp = pa.object({ type: pa.literal("pcb_board"), pcb_board_id: ah("pcb_board"), pcb_panel_id: pa.string().optional(), carrier_pcb_board_id: pa.string().optional(), is_subcircuit: pa.boolean().optional(), subcircuit_id: pa.string().optional(), is_mounted_to_carrier_board: pa.boolean().optional(), width: Hl.optional(), height: Hl.optional(), center: nh, display_offset_x: pa.string().optional().describe("How to display the x offset for this board, usually corresponding with how the user specified it"), display_offset_y: pa.string().optional().describe("How to display the y offset for this board, usually corresponding with how the user specified it"), thickness: Hl.optional().default(1.4), num_layers: pa.number().optional().default(4), outline: pa.array(nh).optional(), shape: pa.enum(["rect", "polygon"]).optional(), material: pa.enum(["fr4", "fr1"]).default("fr4"), solder_mask_color: pa.string().optional(), silkscreen_color: pa.string().optional(), anchor_position: nh.optional(), anchor_alignment: ch.optional(), position_mode: pa.enum(["relative_to_panel_anchor", "none"]).optional() }).merge(bu).describe("Defines the board outline of the PCB");
var fp = pa.object({ type: pa.literal("pcb_panel"), pcb_panel_id: ah("pcb_panel"), width: Hl, height: Hl, center: nh, thickness: Hl.optional().default(1.4), covered_with_solder_mask: pa.boolean().optional().default(true) }).describe("Defines a PCB panel that can contain multiple boards");
var yp = Mh.extend({ type: pa.literal("pcb_placement_error"), pcb_placement_error_id: ah("pcb_placement_error"), error_type: pa.literal("pcb_placement_error").default("pcb_placement_error"), subcircuit_id: pa.string().optional() }).describe("Defines a placement error on the PCB");
var _p = Mh.extend({ type: pa.literal("pcb_panelization_placement_error"), pcb_panelization_placement_error_id: ah("pcb_panelization_placement_error"), error_type: pa.literal("pcb_panelization_placement_error").default("pcb_panelization_placement_error"), pcb_panel_id: pa.string().optional(), pcb_board_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Defines a panelization placement error on the PCB");
var bp = pa.object({ type: pa.literal("pcb_trace_hint"), pcb_trace_hint_id: ah("pcb_trace_hint"), pcb_port_id: pa.string(), pcb_component_id: pa.string(), route: pa.array(_u), subcircuit_id: pa.string().optional() }).describe("A hint that can be used during generation of a PCB trace");
var xp = pa.object({ type: pa.literal("pcb_silkscreen_line"), pcb_silkscreen_line_id: ah("pcb_silkscreen_line"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), stroke_width: Ul.default("0.1mm"), x1: Ul, y1: Ul, x2: Ul, y2: Ul, layer: Nd }).describe("Defines a silkscreen line on the PCB");
var vp = pa.object({ type: pa.literal("pcb_silkscreen_path"), pcb_silkscreen_path_id: ah("pcb_silkscreen_path"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Nd, route: pa.array(nh), stroke_width: Hl }).describe("Defines a silkscreen path on the PCB");
var Ip = pa.object({ type: pa.literal("pcb_silkscreen_text"), pcb_silkscreen_text_id: ah("pcb_silkscreen_text"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: Ul.default("0.2mm"), pcb_component_id: pa.string(), text: pa.string(), is_knockout: pa.boolean().default(false).optional(), knockout_padding: pa.object({ left: Hl, top: Hl, bottom: Hl, right: Hl }).default({ left: "0.2mm", top: "0.2mm", bottom: "0.2mm", right: "0.2mm" }).optional(), ccw_rotation: pa.number().optional(), layer: Md, is_mirrored: pa.boolean().default(false).optional(), anchor_position: nh.default({ x: 0, y: 0 }), anchor_alignment: ch.default("center") }).describe("Defines silkscreen text on the PCB");
var Sp = pa.object({ type: pa.literal("pcb_copper_text"), pcb_copper_text_id: ah("pcb_copper_text"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: Ul.default("0.2mm"), pcb_component_id: pa.string(), text: pa.string(), is_knockout: pa.boolean().default(false).optional(), knockout_padding: pa.object({ left: Hl, top: Hl, bottom: Hl, right: Hl }).default({ left: "0.2mm", top: "0.2mm", bottom: "0.2mm", right: "0.2mm" }).optional(), ccw_rotation: pa.number().optional(), layer: Md, is_mirrored: pa.boolean().default(false).optional(), anchor_position: nh.default({ x: 0, y: 0 }), anchor_alignment: ch.default("center") }).describe("Defines copper text on the PCB");
var Cp = pa.object({ type: pa.literal("pcb_silkscreen_rect"), pcb_silkscreen_rect_id: ah("pcb_silkscreen_rect"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: nh, width: Hl, height: Hl, layer: Md, stroke_width: Hl.default("1mm"), corner_radius: Hl.optional(), is_filled: pa.boolean().default(true).optional(), has_stroke: pa.boolean().optional(), is_stroke_dashed: pa.boolean().optional(), ccw_rotation: pa.number().optional() }).describe("Defines a silkscreen rect on the PCB");
var Pp = pa.object({ type: pa.literal("pcb_silkscreen_circle"), pcb_silkscreen_circle_id: ah("pcb_silkscreen_circle"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: nh, radius: Hl, layer: Nd, stroke_width: Hl.default("1mm"), is_filled: pa.boolean().optional() }).describe("Defines a silkscreen circle on the PCB");
var Mp = pa.object({ type: pa.literal("pcb_silkscreen_oval"), pcb_silkscreen_oval_id: ah("pcb_silkscreen_oval"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: nh, radius_x: Ul, radius_y: Ul, layer: Nd, ccw_rotation: th.optional() }).describe("Defines a silkscreen oval on the PCB");
var Np = pa.object({ type: pa.literal("pcb_silkscreen_graphic"), pcb_silkscreen_graphic_id: ah("pcb_silkscreen_graphic"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Nd, image_asset: hh.optional() }).extend({ shape: pa.literal("brep"), brep_shape: gu }).describe("Defines a BRep silkscreen graphic on the PCB");
var wp = pa.discriminatedUnion("shape", [Np]).describe("Defines a silkscreen graphic on the PCB");
var Tp = pa.object({ type: pa.literal("pcb_silkscreen_pill"), pcb_silkscreen_pill_id: ah("pcb_silkscreen_pill"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: nh, width: Hl, height: Hl, layer: Md, ccw_rotation: pa.number().optional() }).describe("Defines a silkscreen pill on the PCB");
var Rp = pa.object({ type: pa.literal("pcb_fabrication_note_text"), pcb_fabrication_note_text_id: ah("pcb_fabrication_note_text"), subcircuit_id: pa.string().optional(), pcb_group_id: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: Ul.default("1mm"), pcb_component_id: pa.string(), text: pa.string(), ccw_rotation: pa.number().optional(), layer: Nd, anchor_position: nh.default({ x: 0, y: 0 }), anchor_alignment: pa.enum(["center", "top_left", "top_right", "bottom_left", "bottom_right"]).default("center"), color: pa.string().optional() }).describe("Defines a fabrication note in text on the PCB, useful for leaving notes for assemblers or fabricators");
var Ep = pa.object({ type: pa.literal("pcb_fabrication_note_path"), pcb_fabrication_note_path_id: ah("pcb_fabrication_note_path"), pcb_component_id: pa.string(), subcircuit_id: pa.string().optional(), layer: Md, route: pa.array(nh), stroke_width: Hl, color: pa.string().optional() }).describe("Defines a fabrication path on the PCB for fabricators or assemblers");
var Ap = pa.object({ type: pa.literal("pcb_fabrication_note_rect"), pcb_fabrication_note_rect_id: ah("pcb_fabrication_note_rect"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: nh, width: Hl, height: Hl, layer: Nd, stroke_width: Hl.default("0.1mm"), corner_radius: Hl.optional(), is_filled: pa.boolean().optional(), has_stroke: pa.boolean().optional(), is_stroke_dashed: pa.boolean().optional(), color: pa.string().optional() }).describe("Defines a fabrication note rectangle on the PCB");
var Op = pa.object({ type: pa.literal("pcb_fabrication_note_dimension"), pcb_fabrication_note_dimension_id: ah("pcb_fabrication_note_dimension"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Nd, from: nh, to: nh, text: pa.string().optional(), text_ccw_rotation: pa.number().optional(), offset: Hl.optional(), offset_distance: Hl.optional(), offset_direction: pa.object({ x: pa.number(), y: pa.number() }).optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: Hl.default("1mm"), color: pa.string().optional(), arrow_size: Hl.default("1mm") }).describe("Defines a measurement annotation within PCB fabrication notes");
var kp = pa.object({ type: pa.literal("pcb_note_text"), pcb_note_text_id: ah("pcb_note_text"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: Ul.default("1mm"), text: pa.string().optional(), anchor_position: nh.default({ x: 0, y: 0 }), anchor_alignment: pa.enum(["center", "top_left", "top_right", "bottom_left", "bottom_right"]).default("center"), layer: Nd.default("top"), is_mirrored_from_top_view: pa.boolean().optional(), color: pa.string().optional() }).describe("Defines a documentation note in text on the PCB");
var Dp = pa.object({ type: pa.literal("pcb_note_rect"), pcb_note_rect_id: ah("pcb_note_rect"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), text: pa.string().optional(), center: nh, width: Hl, height: Hl, layer: Nd.default("top"), stroke_width: Hl.default("0.1mm"), corner_radius: Hl.optional(), is_filled: pa.boolean().optional(), has_stroke: pa.boolean().optional(), is_stroke_dashed: pa.boolean().optional(), color: pa.string().optional() }).describe("Defines a rectangular documentation note on the PCB");
var Lp = pa.object({ type: pa.literal("pcb_note_path"), pcb_note_path_id: ah("pcb_note_path"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), text: pa.string().optional(), route: pa.array(nh), layer: Nd.default("top"), stroke_width: Hl.default("0.1mm"), color: pa.string().optional() }).describe("Defines a polyline documentation note on the PCB");
var zp = pa.object({ type: pa.literal("pcb_note_line"), pcb_note_line_id: ah("pcb_note_line"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), text: pa.string().optional(), x1: Ul, y1: Ul, x2: Ul, y2: Ul, layer: Nd.default("top"), stroke_width: Ul.default("0.1mm"), color: pa.string().optional(), is_dashed: pa.boolean().optional() }).describe("Defines a straight documentation note line on the PCB");
var Bp = pa.object({ type: pa.literal("pcb_note_dimension"), pcb_note_dimension_id: ah("pcb_note_dimension"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), from: nh, to: nh, text: pa.string().optional(), text_ccw_rotation: pa.number().optional(), offset_distance: Hl.optional(), offset_direction: pa.object({ x: pa.number(), y: pa.number() }).optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: Hl.default("1mm"), layer: Nd.default("top"), color: pa.string().optional(), arrow_size: Hl.default("1mm") }).describe("Defines a measurement annotation within PCB documentation notes");
var Fp = Mh.extend({ type: pa.literal("pcb_footprint_overlap_error"), pcb_error_id: ah("pcb_error"), error_type: pa.literal("pcb_footprint_overlap_error").default("pcb_footprint_overlap_error"), pcb_smtpad_ids: pa.array(pa.string()).optional(), pcb_plated_hole_ids: pa.array(pa.string()).optional(), pcb_hole_ids: pa.array(pa.string()).optional(), pcb_keepout_ids: pa.array(pa.string()).optional() }).describe("Error emitted when a pcb footprint overlaps with another element");
var jp = Mh.extend({ type: pa.literal("pcb_courtyard_overlap_error"), pcb_error_id: ah("pcb_error"), error_type: pa.literal("pcb_courtyard_overlap_error").default("pcb_courtyard_overlap_error"), pcb_component_ids: pa.tuple([pa.string(), pa.string()]) }).describe("Error emitted when the courtyard (CrtYd) of one PCB component overlaps with the courtyard of another");
var $p = pa.object({ type: pa.literal("pcb_keepout"), shape: pa.literal("rect"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: nh, width: Ul, height: Ul, pcb_keepout_id: pa.string(), layers: pa.array(pa.string()), description: pa.string().optional() }).or(pa.object({ type: pa.literal("pcb_keepout"), shape: pa.literal("circle"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: nh, radius: Ul, pcb_keepout_id: pa.string(), layers: pa.array(pa.string()), description: pa.string().optional() }));
var Yp = pa.object({ type: pa.literal("pcb_cutout"), pcb_cutout_id: ah("pcb_cutout"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_board_id: pa.string().optional(), pcb_panel_id: pa.string().optional() });
var Xp = Yp.extend({ shape: pa.literal("rect"), center: nh, width: Hl, height: Hl, rotation: th.optional(), corner_radius: Hl.optional() });
var Wp = Yp.extend({ shape: pa.literal("circle"), center: nh, radius: Hl });
var Vp = Yp.extend({ shape: pa.literal("polygon"), points: pa.array(nh) });
var Hp = Yp.extend({ shape: pa.literal("path"), route: pa.array(nh), slot_width: Hl, slot_length: Hl.optional(), space_between_slots: Hl.optional(), slot_corner_radius: Hl.optional() });
var Gp = pa.discriminatedUnion("shape", [Xp, Wp, Vp, Hp]).describe("Defines a cutout on the PCB, removing board material.");
var Up = Mh.extend({ type: pa.literal("pcb_missing_footprint_error"), pcb_missing_footprint_error_id: ah("pcb_missing_footprint_error"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), error_type: pa.literal("pcb_missing_footprint_error").default("pcb_missing_footprint_error"), source_component_id: pa.string() }).describe("Defines a missing footprint error on the PCB");
var Zp = Mh.extend({ type: pa.literal("external_footprint_load_error"), external_footprint_load_error_id: ah("external_footprint_load_error"), pcb_component_id: pa.string(), source_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), footprinter_string: pa.string().optional(), error_type: pa.literal("external_footprint_load_error").default("external_footprint_load_error") }).describe("Defines an error when an external footprint fails to load");
var qp = Mh.extend({ type: pa.literal("circuit_json_footprint_load_error"), circuit_json_footprint_load_error_id: ah("circuit_json_footprint_load_error"), pcb_component_id: pa.string(), source_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), error_type: pa.literal("circuit_json_footprint_load_error").default("circuit_json_footprint_load_error"), circuit_json: pa.array(pa.any()).optional() }).describe("Defines an error when a circuit JSON footprint fails to load");
var Jp = pa.object({ type: pa.literal("pcb_group"), pcb_group_id: ah("pcb_group"), source_group_id: pa.string(), is_subcircuit: pa.boolean().optional(), subcircuit_id: pa.string().optional(), width: Hl.optional(), height: Hl.optional(), center: nh, display_offset_x: pa.string().optional().describe("How to display the x offset for this group, usually corresponding with how the user specified it"), display_offset_y: pa.string().optional().describe("How to display the y offset for this group, usually corresponding with how the user specified it"), outline: pa.array(nh).optional(), anchor_position: nh.optional(), anchor_alignment: ch.default("center"), position_mode: pa.enum(["packed", "relative_to_group_anchor", "none"]).optional(), positioned_relative_to_pcb_group_id: pa.string().optional(), positioned_relative_to_pcb_board_id: pa.string().optional(), pcb_component_ids: pa.array(pa.string()), child_layout_mode: pa.enum(["packed", "none"]).optional(), name: pa.string().optional(), description: pa.string().optional(), layout_mode: pa.string().optional(), autorouter_configuration: pa.object({ trace_clearance: Hl }).optional(), autorouter_used_string: pa.string().optional() }).describe("Defines a group of components on the PCB");
var Qp = Mh.extend({ type: pa.literal("pcb_autorouting_error"), pcb_error_id: ah("pcb_autorouting_error"), error_type: pa.literal("pcb_autorouting_error").default("pcb_autorouting_error"), subcircuit_id: pa.string().optional() }).describe("The autorouting has failed to route a portion of the board");
var Kp = pa.object({ type: pa.literal("pcb_manual_edit_conflict_warning"), pcb_manual_edit_conflict_warning_id: ah("pcb_manual_edit_conflict_warning"), warning_type: pa.literal("pcb_manual_edit_conflict_warning").default("pcb_manual_edit_conflict_warning"), message: pa.string(), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), source_component_id: pa.string() }).describe("Warning emitted when a component has both manual placement and explicit pcbX/pcbY coordinates");
var tm = pa.enum(["x-", "x+", "y+", "y-"]);
var em = pa.object({ type: pa.literal("pcb_connector_not_in_accessible_orientation_warning"), pcb_connector_not_in_accessible_orientation_warning_id: ah("pcb_connector_not_in_accessible_orientation_warning"), warning_type: pa.literal("pcb_connector_not_in_accessible_orientation_warning").default("pcb_connector_not_in_accessible_orientation_warning"), message: pa.string(), pcb_component_id: pa.string(), source_component_id: pa.string().optional(), pcb_board_id: pa.string().optional(), facing_direction: tm, recommended_facing_direction: tm, subcircuit_id: pa.string().optional() }).describe("Warning emitted when a connector PCB component is facing inward toward the board and should be reoriented to an outward-facing direction");
var nm = pa.object({ type: pa.literal("supplier_footprint_mismatch_warning"), supplier_footprint_mismatch_warning_id: ah("supplier_footprint_mismatch_warning"), warning_type: pa.literal("supplier_footprint_mismatch_warning").default("supplier_footprint_mismatch_warning"), message: pa.string(), source_component_id: pa.string(), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), supplier_name: Nh.optional(), supplier_part_number: pa.string().optional(), supplier_footprint_url: pa.string().optional(), footprint_copper_intersection_over_union: pa.number() }).describe("Warning emitted when a supplier part footprint does not match the expected footprint");
var om = pa.object({ type: pa.literal("pcb_breakout_point"), pcb_breakout_point_id: ah("pcb_breakout_point"), pcb_group_id: pa.string(), subcircuit_id: pa.string().optional(), source_trace_id: pa.string().optional(), source_port_id: pa.string().optional(), source_net_id: pa.string().optional(), x: Ul, y: Ul }).describe("Defines a routing target within a pcb_group for a source_trace or source_net");
var im = pa.object({ type: pa.literal("pcb_ground_plane"), pcb_ground_plane_id: ah("pcb_ground_plane"), source_pcb_ground_plane_id: pa.string(), source_net_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Defines a ground plane on the PCB");
var rm = pa.object({ type: pa.literal("pcb_ground_plane_region"), pcb_ground_plane_region_id: ah("pcb_ground_plane_region"), pcb_ground_plane_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Md, points: pa.array(nh) }).describe("Defines a polygon region of a ground plane");
var sm = pa.object({ type: pa.literal("pcb_thermal_spoke"), pcb_thermal_spoke_id: ah("pcb_thermal_spoke"), pcb_ground_plane_id: pa.string(), shape: pa.string(), spoke_count: pa.number(), spoke_thickness: Ul, spoke_inner_diameter: Ul, spoke_outer_diameter: Ul, pcb_plated_hole_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Pattern for connecting a ground plane to a plated hole");
var am = pa.object({ type: pa.literal("pcb_copper_pour"), pcb_copper_pour_id: ah("pcb_copper_pour"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Md, source_net_id: pa.string().optional(), covered_with_solder_mask: pa.boolean().optional().default(true) });
var cm = am.extend({ shape: pa.literal("rect"), center: nh, width: Hl, height: Hl, rotation: th.optional() });
var lm = am.extend({ shape: pa.literal("brep"), brep_shape: gu });
var hm = am.extend({ shape: pa.literal("polygon"), points: pa.array(nh) });
var dm = pa.discriminatedUnion("shape", [cm, lm, hm]).describe("Defines a copper pour on the PCB.");
var um = Mh.extend({ type: pa.literal("pcb_component_outside_board_error"), pcb_component_outside_board_error_id: ah("pcb_component_outside_board_error"), error_type: pa.literal("pcb_component_outside_board_error").default("pcb_component_outside_board_error"), pcb_component_id: pa.string(), pcb_board_id: pa.string(), component_center: nh, component_bounds: pa.object({ min_x: pa.number(), max_x: pa.number(), min_y: pa.number(), max_y: pa.number() }), subcircuit_id: pa.string().optional(), source_component_id: pa.string().optional() }).describe("Error emitted when a PCB component is placed outside the board boundaries");
var pm = Mh.extend({ type: pa.literal("pcb_component_not_on_board_edge_error"), pcb_component_not_on_board_edge_error_id: ah("pcb_component_not_on_board_edge_error"), error_type: pa.literal("pcb_component_not_on_board_edge_error").default("pcb_component_not_on_board_edge_error"), pcb_component_id: pa.string(), pcb_board_id: pa.string(), component_center: nh, pad_to_nearest_board_edge_distance: pa.number(), source_component_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a component that must be placed on the board edge is centered away from the edge");
var mm = Mh.extend({ type: pa.literal("pcb_component_invalid_layer_error"), pcb_component_invalid_layer_error_id: ah("pcb_component_invalid_layer_error"), error_type: pa.literal("pcb_component_invalid_layer_error").default("pcb_component_invalid_layer_error"), pcb_component_id: pa.string().optional(), source_component_id: pa.string(), layer: Md, subcircuit_id: pa.string().optional() }).describe("Error emitted when a component is placed on an invalid layer (components can only be on 'top' or 'bottom' layers)");
var gm = Mh.extend({ type: pa.literal("pcb_via_clearance_error"), pcb_error_id: ah("pcb_error"), error_type: pa.literal("pcb_via_clearance_error").default("pcb_via_clearance_error"), pcb_via_ids: pa.array(pa.string()).min(2), minimum_clearance: Ul.optional(), actual_clearance: Ul.optional(), pcb_center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when vias are closer than the allowed clearance");
var fm = Mh.extend({ type: pa.literal("pcb_via_trace_clearance_error"), pcb_via_trace_clearance_error_id: ah("pcb_via_trace_clearance_error"), error_type: pa.literal("pcb_via_trace_clearance_error").default("pcb_via_trace_clearance_error"), pcb_via_id: pa.string(), pcb_trace_id: pa.string(), minimum_clearance: Ul.optional(), actual_clearance: Ul.optional(), center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a via and trace are closer than the allowed clearance");
var ym = Mh.extend({ type: pa.literal("pcb_pad_pad_clearance_error"), pcb_pad_pad_clearance_error_id: ah("pcb_pad_pad_clearance_error"), error_type: pa.literal("pcb_pad_pad_clearance_error").default("pcb_pad_pad_clearance_error"), pcb_pad_ids: pa.array(pa.string()).min(2), minimum_clearance: Ul.optional(), actual_clearance: Ul.optional(), center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when pads are closer than the allowed clearance");
var _m = Mh.extend({ type: pa.literal("pcb_pad_trace_clearance_error"), pcb_pad_trace_clearance_error_id: ah("pcb_pad_trace_clearance_error"), error_type: pa.literal("pcb_pad_trace_clearance_error").default("pcb_pad_trace_clearance_error"), pcb_pad_id: pa.string(), pcb_trace_id: pa.string(), minimum_clearance: Ul.optional(), actual_clearance: Ul.optional(), center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a pad and trace are closer than allowed clearance");
var bm = pa.object({ type: pa.literal("pcb_courtyard_rect"), pcb_courtyard_rect_id: ah("pcb_courtyard_rect"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: nh, width: Hl, height: Hl, layer: Nd, ccw_rotation: th.optional(), color: pa.string().optional() }).describe("Defines a courtyard rectangle on the PCB");
var xm = pa.object({ type: pa.literal("pcb_courtyard_outline"), pcb_courtyard_outline_id: ah("pcb_courtyard_outline"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Nd, outline: pa.array(nh).min(2) }).describe("Defines a courtyard outline on the PCB");
var vm = pa.object({ type: pa.literal("pcb_courtyard_polygon"), pcb_courtyard_polygon_id: ah("pcb_courtyard_polygon"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Nd, points: pa.array(nh).min(3), color: pa.string().optional() }).describe("Defines a courtyard polygon on the PCB");
var Im = pa.object({ type: pa.literal("pcb_courtyard_circle"), pcb_courtyard_circle_id: ah("pcb_courtyard_circle"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: nh, radius: Hl, layer: Nd, color: pa.string().optional() }).describe("Defines a courtyard circle on the PCB");
var Sm = pa.object({ type: pa.literal("pcb_courtyard_pill"), pcb_courtyard_pill_id: ah("pcb_courtyard_pill"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: nh, width: Hl, height: Hl, radius: Hl, layer: Nd, color: pa.string().optional() }).describe("Defines a courtyard pill on the PCB");
var Cm = ["obj", "stl", "3mf", "gltf", "glb", "step", "wrl"];
var Pm = ["x+", "x-", "y+", "y-", "z+", "z-"];
var Mm = { obj: "z+", stl: "z+", "3mf": "z+", gltf: "y+", glb: "y+", step: "z+", wrl: "y+" };
var Nm = pa.object({ type: pa.literal("cad_component"), cad_component_id: pa.string(), pcb_component_id: pa.string(), source_component_id: pa.string(), position: ih, rotation: ih.optional(), size: ih.optional(), layer: Md.optional(), subcircuit_id: pa.string().optional(), footprinter_string: pa.string().optional(), model_obj_url: pa.string().optional(), model_stl_url: pa.string().optional(), model_3mf_url: pa.string().optional(), model_gltf_url: pa.string().optional(), model_glb_url: pa.string().optional(), model_step_url: pa.string().optional(), model_wrl_url: pa.string().optional(), model_asset: hh.optional(), model_unit_to_mm_scale_factor: pa.number().optional(), model_board_normal_direction: pa.enum(Pm).optional().describe(`The direction in the model's coordinate space that is considered "up" or "coming out of the board surface"`), model_origin_position: ih.optional(), model_origin_alignment: pa.enum(["unknown", "center", "center_of_component_on_board_surface", "bottom_center_of_component"]).optional(), model_object_fit: pa.enum(["contain_within_bounds", "fill_bounds"]).optional().default("contain_within_bounds"), model_jscad: pa.any().optional(), show_as_translucent_model: pa.boolean().optional(), show_as_bounding_box: pa.boolean().optional(), anchor_alignment: pa.enum(["center", "center_of_component_on_board_surface"]).optional().default("center") }).describe("Defines a component on the PCB");
var wm = pa.enum(["sinewave", "square", "triangle", "sawtooth"]);
var Tm = pa.union([pa.string(), pa.number()]).transform((t19) => typeof t19 == "string" ? t19.endsWith("%") ? parseFloat(t19.slice(0, -1)) / 100 : parseFloat(t19) : t19).pipe(pa.number().min(0, "Duty cycle must be non-negative").max(1, "Duty cycle cannot be greater than 100%"));
var Rm = pa.object({ type: pa.literal("simulation_voltage_source"), simulation_voltage_source_id: ah("simulation_voltage_source"), is_dc_source: pa.literal(true).optional().default(true), positive_source_port_id: pa.string().optional(), negative_source_port_id: pa.string().optional(), positive_source_net_id: pa.string().optional(), negative_source_net_id: pa.string().optional(), voltage: Vl }).describe("Defines a DC voltage source for simulation");
var Em = pa.object({ type: pa.literal("simulation_voltage_source"), simulation_voltage_source_id: ah("simulation_voltage_source"), is_dc_source: pa.literal(false), terminal1_source_port_id: pa.string().optional(), terminal2_source_port_id: pa.string().optional(), terminal1_source_net_id: pa.string().optional(), terminal2_source_net_id: pa.string().optional(), voltage: Vl.optional(), frequency: Gl.optional(), peak_to_peak_voltage: Vl.optional(), wave_shape: wm.optional(), phase: th.optional(), duty_cycle: Tm.optional(), pulse_delay: Ql.optional(), rise_time: Ql.optional(), fall_time: Ql.optional(), pulse_width: Ql.optional(), period: Ql.optional() }).describe("Defines an AC voltage source for simulation");
var Am = pa.union([Rm, Em]).describe("Defines a voltage source for simulation");
var Om = pa.union([pa.string(), pa.number()]).transform((t19) => typeof t19 == "string" ? t19.endsWith("%") ? parseFloat(t19.slice(0, -1)) / 100 : parseFloat(t19) : t19).pipe(pa.number().min(0, "Duty cycle must be non-negative").max(1, "Duty cycle cannot be greater than 100%"));
var km = pa.object({ type: pa.literal("simulation_current_source"), simulation_current_source_id: ah("simulation_current_source"), is_dc_source: pa.literal(true).optional().default(true), positive_source_port_id: pa.string().optional(), negative_source_port_id: pa.string().optional(), positive_source_net_id: pa.string().optional(), negative_source_net_id: pa.string().optional(), current: Zl }).describe("Defines a DC current source for simulation");
var Dm = pa.object({ type: pa.literal("simulation_current_source"), simulation_current_source_id: ah("simulation_current_source"), is_dc_source: pa.literal(false), terminal1_source_port_id: pa.string().optional(), terminal2_source_port_id: pa.string().optional(), terminal1_source_net_id: pa.string().optional(), terminal2_source_net_id: pa.string().optional(), current: Zl.optional(), frequency: Gl.optional(), peak_to_peak_current: Zl.optional(), wave_shape: wm.optional(), phase: th.optional(), duty_cycle: Om.optional() }).describe("Defines an AC current source for simulation");
var Lm = pa.union([km, Dm]).describe("Defines a current source for simulation");
var zm = pa.union([pa.literal("spice_dc_sweep"), pa.literal("spice_dc_operating_point"), pa.literal("spice_transient_analysis"), pa.literal("spice_ac_analysis")]);
var Bm = pa.object({ method: pa.enum(["trap", "gear"]).optional(), reltol: pa.union([pa.number(), pa.string()]).optional(), abstol: pa.union([pa.number(), pa.string()]).optional(), vntol: pa.union([pa.number(), pa.string()]).optional() }).describe("SPICE solver options for a simulation experiment");
var Fm = pa.object({ type: pa.literal("simulation_experiment"), simulation_experiment_id: ah("simulation_experiment"), name: pa.string(), experiment_type: zm, time_per_step: ql.optional(), start_time_ms: Ql.optional(), end_time_ms: Ql.optional(), spice_options: Bm.optional() }).describe("Defines a simulation experiment configuration");
var jm = pa.object({ type: pa.literal("simulation_transient_voltage_graph"), simulation_transient_voltage_graph_id: ah("simulation_transient_voltage_graph"), simulation_experiment_id: pa.string(), timestamps_ms: pa.array(pa.number()).optional(), voltage_levels: pa.array(pa.number()), source_component_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional(), time_per_step: ql, start_time_ms: Ql, end_time_ms: Ql, name: pa.string().optional(), color: pa.string().optional() }).describe("Stores voltage measurements over time for a simulation");
var $m = pa.object({ type: pa.literal("simulation_transient_current_graph"), simulation_transient_current_graph_id: ah("simulation_transient_current_graph"), simulation_experiment_id: pa.string(), timestamps_ms: pa.array(pa.number()).optional(), current_levels: pa.array(pa.number()), source_component_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional(), time_per_step: ql, start_time_ms: Ql, end_time_ms: Ql, name: pa.string().optional(), color: pa.string().optional() }).describe("Stores current measurements over time for a simulation");
var Ym = pa.object({ type: pa.literal("simulation_switch"), simulation_switch_id: ah("simulation_switch"), source_component_id: pa.string().optional(), closes_at: Ql.optional(), opens_at: Ql.optional(), starts_closed: pa.boolean().optional(), switching_frequency: Gl.optional() }).describe("Defines a switch for simulation timing control");
var Xm = pa.object({ type: pa.literal("simulation_voltage_probe"), simulation_voltage_probe_id: ah("simulation_voltage_probe"), source_component_id: pa.string().optional(), name: pa.string().optional(), signal_input_source_port_id: pa.string().optional(), signal_input_source_net_id: pa.string().optional(), reference_input_source_port_id: pa.string().optional(), reference_input_source_net_id: pa.string().optional(), subcircuit_id: pa.string().optional(), color: pa.string().optional() }).describe("Defines a voltage probe for simulation. If a reference input is not provided, it measures against ground. If a reference input is provided, it measures the differential voltage between two points.").superRefine((t19, e2) => {
if (t19.reference_input_source_port_id || t19.reference_input_source_net_id) {
const n2 = !!t19.signal_input_source_port_id || !!t19.reference_input_source_port_id, o2 = !!t19.signal_input_source_net_id || !!t19.reference_input_source_net_id;
n2 && o2 ? e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Cannot mix port and net connections in a differential probe." }) : n2 ? t19.signal_input_source_port_id && t19.reference_input_source_port_id || e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Differential port probe requires both signal_input_source_port_id and reference_input_source_port_id." }) : o2 && (t19.signal_input_source_net_id && t19.reference_input_source_net_id || e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Differential net probe requires both signal_input_source_net_id and reference_input_source_net_id." }));
} else
!!t19.signal_input_source_port_id == !!t19.signal_input_source_net_id && e2.addIssue({ code: pa.ZodIssueCode.custom, message: "A voltage probe must have exactly one of signal_input_source_port_id or signal_input_source_net_id." });
});
var Wm = pa.object({ type: pa.literal("simulation_current_probe"), simulation_current_probe_id: ah("simulation_current_probe"), source_component_id: pa.string().optional(), name: pa.string().optional(), positive_source_port_id: pa.string().optional(), negative_source_port_id: pa.string().optional(), positive_source_net_id: pa.string().optional(), negative_source_net_id: pa.string().optional(), subcircuit_id: pa.string().optional(), color: pa.string().optional() }).describe("Defines a current probe for simulation. It measures current flowing from the positive endpoint to the negative endpoint.").superRefine((t19, e2) => {
const n2 = !!t19.positive_source_port_id, o2 = !!t19.negative_source_port_id, i2 = !!t19.positive_source_net_id, r2 = !!t19.negative_source_net_id, s2 = n2 || o2, a2 = i2 || r2;
s2 && a2 ? e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Cannot mix port and net connections in a current probe." }) : s2 ? n2 && o2 || e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Current probe using source ports requires both positive_source_port_id and negative_source_port_id." }) : a2 ? i2 && r2 || e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Current probe using source nets requires both positive_source_net_id and negative_source_net_id." }) : e2.addIssue({ code: pa.ZodIssueCode.custom, message: "A current probe must have either positive/negative source port ids or positive/negative source net ids." });
});
var Vm = Mh.extend({ type: pa.literal("simulation_unknown_experiment_error"), simulation_unknown_experiment_error_id: ah("simulation_unknown_experiment_error"), error_type: pa.literal("simulation_unknown_experiment_error").default("simulation_unknown_experiment_error"), simulation_experiment_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("An unknown error occurred during the simulation experiment.");
var Hm = pa.object({ type: pa.literal("simulation_op_amp"), simulation_op_amp_id: ah("simulation_op_amp"), source_component_id: pa.string().optional(), inverting_input_source_port_id: pa.string(), non_inverting_input_source_port_id: pa.string(), output_source_port_id: pa.string(), positive_supply_source_port_id: pa.string(), negative_supply_source_port_id: pa.string() }).describe("Defines a simple ideal operational amplifier for simulation");
var Gm = pa.object({ type: pa.literal("simulation_spice_subcircuit"), simulation_spice_subcircuit_id: ah("simulation_spice_subcircuit"), source_component_id: pa.string(), spice_pin_to_source_port_map: pa.record(pa.string(), pa.string()), subcircuit_source: pa.string() }).describe("Defines a custom SPICE subcircuit model for simulation");
var Um = (t19) => t19 !== undefined;
var Zm = pa.object({ type: pa.literal("simulation_oscilloscope_trace"), simulation_oscilloscope_trace_id: ah("simulation_oscilloscope_trace"), simulation_transient_voltage_graph_id: pa.string().optional(), simulation_transient_current_graph_id: pa.string().optional(), simulation_voltage_probe_id: pa.string().optional(), simulation_current_probe_id: pa.string().optional(), display_name: pa.string().optional(), color: pa.string().optional(), display_center_value: pa.number().optional(), display_center_offset_divs: pa.number().optional(), volts_per_div: pa.number().positive().optional(), amps_per_div: pa.number().positive().optional() }).describe("Defines how a simulation measurement is rendered as an oscilloscope-style trace.").superRefine((t19, e2) => {
const n2 = [t19.simulation_transient_voltage_graph_id, t19.simulation_voltage_probe_id].filter(Um).length, o2 = [t19.simulation_transient_current_graph_id, t19.simulation_current_probe_id].filter(Um).length;
n2 + o2 !== 1 && e2.addIssue({ code: pa.ZodIssueCode.custom, message: "An oscilloscope trace must reference exactly one voltage graph, current graph, voltage probe, or current probe." }), n2 > 0 && t19.amps_per_div !== undefined && e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Voltage oscilloscope traces must use volts_per_div, not amps_per_div." }), o2 > 0 && t19.volts_per_div !== undefined && e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Current oscilloscope traces must use amps_per_div, not volts_per_div." });
});
var qm = pa.union([_d, fd, yd, gd, xd, bd, Dh, Th, Eh, Oh, Rh, Lh, $h, Yh, Hh, Uh, Zh, td, qh, Jh, Qh, Kh, Wh, Xh, Sd, wd, vd, ed, id, rd, ad, Td, cd, ld, Rd, Ed, Ad, Od, kd, Dd, ud, pd, Id, xu, Ou, Up, Zp, qp, Kp, em, nm, ju, $p, $u, pp, ep, sp, ap, cp, mp, Uu, tp, gp, fp, Jp, bp, xp, vp, Ip, Tp, Sp, Cp, Pp, Mp, wp, lp, hp, yp, _p, dp, up, gm, fm, ym, _m, Ep, Rp, Ap, Op, kp, Dp, Lp, zp, Bp, Qp, Fp, jp, om, Gp, im, rm, sm, dm, um, pm, mm, bm, xm, vm, Im, Sm, Ld, Jd, Vd, Hd, Gd, Ud, Yd, Wd, Qd, Zd, zd, tu, eu, Kd, su, au, cu, lu, uu, hu, du, Nm, Am, Lm, Fm, jm, $m, Ym, Xm, Wm, Zm, Vm, Hm, Gm]);
var Jm = qm;
function Qm(t19, e2, n2) {
if (!e2 || !n2)
return;
let o2 = t19.get(e2);
o2 || (o2 = new Set, t19.set(e2, o2)), o2.add(n2);
let i2 = t19.get(n2);
i2 || (i2 = new Set, t19.set(n2, i2)), i2.add(e2);
}
var Km = (t19, e2 = {}) => {
const n2 = t19;
let o2 = n2._internal_store;
if (!o2) {
o2 = { counts: {}, editCount: 0 }, n2._internal_store = o2;
for (const t20 of n2) {
const e3 = t20.type, n3 = t20[`${e3}_id`];
if (!n3)
continue;
const i3 = Number.parseInt(n3.split("_").pop());
Number.isNaN(i3) || (o2.counts[e3] = Math.max(o2.counts[e3] ?? 0, i3));
}
}
const i2 = new Proxy({}, { get: (t20, r2) => {
if (r2 === "toArray")
return () => (n2.editCount = o2.editCount, n2);
if (r2 === "editCount")
return o2.editCount;
if (r2 === "subtree")
return (t21) => Km(function(t22, e3) {
if (!e3.subcircuit_id && !e3.source_group_id)
return [...t22];
let n3 = e3;
if (e3.subcircuit_id) {
const o4 = new Set([e3.subcircuit_id]), i4 = new Map, r4 = new Map;
for (const e4 of t22)
if (e4.type === "source_group") {
const { source_group_id: t23, subcircuit_id: n4 } = e4;
n4 && r4.set(t23, n4);
const o5 = e4.parent_source_group_id;
o5 && (i4.has(o5) || i4.set(o5, []), i4.get(o5).push(t23));
}
let s4;
for (const [t23, n4] of r4)
if (n4 === e3.subcircuit_id) {
s4 = t23;
break;
}
if (s4) {
const t23 = (e4) => {
const n4 = i4.get(e4) || [];
for (const e5 of n4) {
const n5 = r4.get(e5);
n5 && o4.add(n5), t23(e5);
}
};
t23(s4), n3 = { ...e3, subcircuit_ids: Array.from(o4) };
}
}
const o3 = new Map;
for (const e4 of t22) {
const t23 = e4[`${e4.type}_id`];
typeof t23 == "string" && o3.set(t23, e4);
}
const i3 = new Map;
for (const e4 of t22) {
const t23 = Object.entries(e4);
for (const [n4, r4] of t23)
if (n4 !== "parent_source_group_id") {
if (n4.endsWith("_id") && typeof r4 == "string")
Qm(i3, e4, o3.get(r4));
else if (n4.endsWith("_ids") && Array.isArray(r4))
for (const t24 of r4)
typeof t24 == "string" && Qm(i3, e4, o3.get(t24));
}
}
const r3 = [], s3 = new Set;
for (const e4 of t22) {
let t23 = false;
(n3.subcircuit_id && ("subcircuit_id" in e4) && e4.subcircuit_id === n3.subcircuit_id || n3.subcircuit_ids && ("subcircuit_id" in e4) && e4.subcircuit_id && n3.subcircuit_ids.includes(e4.subcircuit_id) || n3.source_group_id && ("source_group_id" in e4) && e4.source_group_id === n3.source_group_id || n3.source_group_id && ("member_source_group_ids" in e4) && Array.isArray(e4.member_source_group_ids) && e4.member_source_group_ids.includes(n3.source_group_id)) && (t23 = true), t23 && (r3.push(e4), s3.add(e4));
}
for (;r3.length > 0; ) {
const t23 = r3.shift(), e4 = i3.get(t23);
if (e4)
for (const t24 of e4)
s3.has(t24) || (s3.add(t24), r3.push(t24));
}
return t22.filter((t23) => s3.has(t23));
}(n2, t21), e2);
if (r2 === "insert")
return (t21) => {
const i3 = t21.type;
if (!i3)
throw new Error("insert requires an element with a type");
o2.counts[i3] ??= -1, o2.counts[i3]++;
const r3 = o2.counts[i3], s3 = { ...t21, type: i3, [`${i3}_id`]: `${i3}_${r3}` };
if (e2.validateInserts) {
(ea[i3] ?? Jm).parse(s3);
}
return n2.push(s3), o2.editCount++, s3;
};
if (r2 === "insertAll")
return (t21) => t21.map((t22) => i2.insert(t22));
const s2 = r2;
return { get: (t21) => n2.find((e3) => e3.type === s2 && e3[`${s2}_id`] === t21), getUsing: (t21) => {
const e3 = Object.keys(t21);
if (e3.length !== 1)
throw new Error("getUsing requires exactly one key, e.g. { pcb_component_id }");
const o3 = e3[0], i3 = o3.replace("_id", ""), r3 = n2.find((e4) => e4.type === i3 && e4[o3] === t21[o3]);
return r3 ? n2.find((t22) => t22.type === s2 && t22[`${s2}_id`] === r3[`${s2}_id`]) : null;
}, getWhere: (t21) => {
const e3 = Object.keys(t21);
return n2.find((n3) => n3.type === s2 && e3.every((e4) => n3[e4] === t21[e4]));
}, list: (t21) => {
const e3 = t21 ? Object.keys(t21) : [];
return n2.filter((n3) => n3.type === s2 && e3.every((e4) => n3[e4] === t21[e4]));
}, insert: (t21) => {
o2.counts[s2] ??= -1, o2.counts[s2]++;
const i3 = o2.counts[s2], r3 = { type: s2, [`${s2}_id`]: `${s2}_${i3}`, ...t21 };
if (e2.validateInserts) {
(ea[s2] ?? Jm).parse(r3);
}
return n2.push(r3), o2.editCount++, r3;
}, delete: (t21) => {
const e3 = n2.find((e4) => e4[`${s2}_id`] === t21);
e3 && (n2.splice(n2.indexOf(e3), 1), o2.editCount++);
}, update: (t21, e3) => {
const i3 = n2.find((e4) => e4.type === s2 && e4[`${s2}_id`] === t21);
return i3 ? (Object.assign(i3, e3), o2.editCount++, i3) : null;
}, select: (t21) => {
if (s2 === "source_component")
return n2.find((e3) => e3.type === "source_component" && e3.name === t21.replace(/\./g, ""));
if (s2 === "pcb_port" || s2 === "source_port" || s2 === "schematic_port") {
const [e3, o3] = t21.replace(/\./g, "").split(/[\s\>]+/), i3 = n2.find((t22) => t22.type === "source_component" && t22.name === e3);
if (!i3)
return null;
const r3 = n2.find((t22) => t22.type === "source_port" && t22.source_component_id === i3.source_component_id && (t22.name === o3 || (t22.port_hints ?? []).includes(o3)));
if (!r3)
return null;
if (s2 === "source_port")
return r3;
if (s2 === "pcb_port")
return n2.find((t22) => t22.type === "pcb_port" && t22.source_port_id === r3.source_port_id);
if (s2 === "schematic_port")
return n2.find((t22) => t22.type === "schematic_port" && t22.source_port_id === r3.source_port_id);
}
} };
} });
return i2;
};
Km.unparsed = Km;
var tg = Km;
function eg(t19) {
const e2 = t19.type;
return `${e2}:${t19[`${e2}_id`]}`;
}
var ng = (t19, e2 = {}) => {
let n2 = t19._internal_store_indexed;
if (!n2) {
n2 = { counts: {}, editCount: 0, indexes: {} };
for (const e3 of t19) {
const t20 = e3.type, o3 = e3[`${t20}_id`];
if (!o3)
continue;
const i3 = Number.parseInt(o3.split("_").pop() || "");
Number.isNaN(i3) || (n2.counts[t20] = Math.max(n2.counts[t20] ?? 0, i3));
}
const o2 = e2.indexConfig || {}, i2 = n2.indexes;
if (o2.byId && (i2.byId = new Map), o2.byType && (i2.byType = new Map), o2.byRelation && (i2.byRelation = new Map), o2.bySubcircuit && (i2.bySubcircuit = new Map), o2.byCustomField && o2.byCustomField.length > 0) {
i2.byCustomField = new Map;
for (const t20 of o2.byCustomField)
i2.byCustomField.set(t20, new Map);
}
for (const e3 of t19) {
if (o2.byId) {
const t20 = eg(e3);
i2.byId.set(t20, e3);
}
if (o2.byType) {
const t20 = i2.byType.get(e3.type) || [];
t20.push(e3), i2.byType.set(e3.type, t20);
}
if (o2.byRelation) {
const t20 = Object.entries(e3);
for (const [n3, o3] of t20)
if (n3.endsWith("_id") && n3 !== `${e3.type}_id` && typeof o3 == "string") {
const t21 = i2.byRelation.get(n3) || new Map, r2 = t21.get(o3) || [];
r2.push(e3), t21.set(o3, r2), i2.byRelation.set(n3, t21);
}
}
if (o2.bySubcircuit && "subcircuit_id" in e3) {
const t20 = e3.subcircuit_id;
if (t20 && typeof t20 == "string") {
const n3 = i2.bySubcircuit.get(t20) || [];
n3.push(e3), i2.bySubcircuit.set(t20, n3);
}
}
if (o2.byCustomField && i2.byCustomField) {
for (const t20 of o2.byCustomField)
if (t20 in e3) {
const n3 = e3[t20];
if (n3 !== undefined && (typeof n3 == "string" || typeof n3 == "number")) {
const o3 = String(n3), r2 = i2.byCustomField.get(t20), s2 = r2.get(o3) || [];
s2.push(e3), r2.set(o3, s2);
}
}
}
}
t19._internal_store_indexed = n2;
}
return new Proxy({}, { get: (o2, i2) => {
if (i2 === "toArray")
return () => (t19.editCount = n2.editCount, t19);
if (i2 === "editCount")
return n2.editCount;
const r2 = i2;
return { get: (o3) => {
const i3 = e2.indexConfig || {};
if (i3.byId && n2.indexes.byId)
return n2.indexes.byId.get(`${r2}:${o3}`) || null;
if (i3.byType && n2.indexes.byType) {
return (n2.indexes.byType.get(r2) || []).find((t20) => t20[`${r2}_id`] === o3) || null;
}
return t19.find((t20) => t20.type === r2 && t20[`${r2}_id`] === o3) || null;
}, getUsing: (o3) => {
const i3 = e2.indexConfig || {}, s2 = Object.keys(o3);
if (s2.length !== 1)
throw new Error("getUsing requires exactly one key, e.g. { pcb_component_id }");
const a2 = s2[0], c2 = a2.replace("_id", "");
if (i3.byRelation && n2.indexes.byRelation) {
const e3 = n2.indexes.byRelation.get(a2);
if (e3) {
const s3 = (e3.get(o3[a2]) || []).find((t20) => t20.type === c2);
if (!s3)
return null;
const l3 = s3[`${r2}_id`];
if (i3.byId && n2.indexes.byId)
return n2.indexes.byId.get(`${r2}:${l3}`) || null;
if (i3.byType && n2.indexes.byType) {
return (n2.indexes.byType.get(r2) || []).find((t20) => t20[`${r2}_id`] === l3) || null;
}
return t19.find((t20) => t20.type === r2 && t20[`${r2}_id`] === l3) || null;
}
}
const l2 = t19.find((t20) => t20.type === c2 && t20[a2] === o3[a2]);
return l2 && t19.find((t20) => t20.type === r2 && t20[`${r2}_id`] === l2[`${r2}_id`]) || null;
}, getWhere: (o3) => {
const i3 = e2.indexConfig || {}, s2 = Object.keys(o3);
if (s2.length === 1 && i3.byCustomField && n2.indexes.byCustomField) {
const t20 = s2[0], e3 = n2.indexes.byCustomField.get(t20);
if (e3) {
const n3 = String(o3[t20]);
return (e3.get(n3) || []).find((t21) => t21.type === r2) || null;
}
}
if ("subcircuit_id" in o3 && i3.bySubcircuit && n2.indexes.bySubcircuit) {
const t20 = o3.subcircuit_id;
return (n2.indexes.bySubcircuit.get(t20) || []).find((t21) => t21.type === r2 && s2.every((e3) => t21[e3] === o3[e3])) || null;
}
if (i3.byType && n2.indexes.byType) {
return (n2.indexes.byType.get(r2) || []).find((t20) => s2.every((e3) => t20[e3] === o3[e3])) || null;
}
return t19.find((t20) => t20.type === r2 && s2.every((e3) => t20[e3] === o3[e3])) || null;
}, list: (o3) => {
const i3 = e2.indexConfig || {}, s2 = o3 ? Object.keys(o3) : [];
if (s2.length === 0 && i3.byType && n2.indexes.byType)
return n2.indexes.byType.get(r2) || [];
if (s2.length === 1 && s2[0] === "subcircuit_id" && i3.bySubcircuit && n2.indexes.bySubcircuit) {
const t20 = o3.subcircuit_id;
return (n2.indexes.bySubcircuit.get(t20) || []).filter((t21) => t21.type === r2);
}
let a2;
return a2 = i3.byType && n2.indexes.byType ? n2.indexes.byType.get(r2) || [] : t19.filter((t20) => t20.type === r2), s2.length > 0 ? a2.filter((t20) => s2.every((e3) => t20[e3] === o3[e3])) : a2;
}, insert: (o3) => {
n2.counts[r2] ??= -1, n2.counts[r2]++;
const i3 = n2.counts[r2], s2 = { type: r2, [`${r2}_id`]: `${r2}_${i3}`, ...o3 };
if (e2.validateInserts) {
(ea[r2] ?? Jm).parse(s2);
}
t19.push(s2), n2.editCount++;
const a2 = e2.indexConfig || {};
if (a2.byId && n2.indexes.byId) {
const t20 = eg(s2);
n2.indexes.byId.set(t20, s2);
}
if (a2.byType && n2.indexes.byType) {
const t20 = n2.indexes.byType.get(r2) || [];
t20.push(s2), n2.indexes.byType.set(r2, t20);
}
if (a2.byRelation && n2.indexes.byRelation) {
const t20 = Object.entries(s2);
for (const [e3, o4] of t20)
if (e3.endsWith("_id") && e3 !== `${s2.type}_id` && typeof o4 == "string") {
const t21 = n2.indexes.byRelation.get(e3) || new Map, i4 = t21.get(o4) || [];
i4.push(s2), t21.set(o4, i4), n2.indexes.byRelation.set(e3, t21);
}
}
if (a2.bySubcircuit && n2.indexes.bySubcircuit && "subcircuit_id" in s2) {
const t20 = s2.subcircuit_id;
if (t20 && typeof t20 == "string") {
const e3 = n2.indexes.bySubcircuit.get(t20) || [];
e3.push(s2), n2.indexes.bySubcircuit.set(t20, e3);
}
}
if (a2.byCustomField && n2.indexes.byCustomField) {
for (const t20 of a2.byCustomField)
if (t20 in s2) {
const e3 = s2[t20];
if (e3 !== undefined && (typeof e3 == "string" || typeof e3 == "number")) {
const o4 = String(e3), i4 = n2.indexes.byCustomField.get(t20), r3 = i4.get(o4) || [];
r3.push(s2), i4.set(o4, r3);
}
}
}
return s2;
}, delete: (o3) => {
const i3 = e2.indexConfig || {};
let s2;
if (i3.byId && n2.indexes.byId)
s2 = n2.indexes.byId.get(`${r2}:${o3}`);
else if (i3.byType && n2.indexes.byType) {
const t20 = n2.indexes.byType.get(r2) || [];
s2 = t20.find((t21) => t21[`${r2}_id`] === o3);
} else
s2 = t19.find((t20) => t20[`${r2}_id`] === o3);
if (!s2)
return;
const a2 = t19.indexOf(s2);
if (a2 >= 0 && (t19.splice(a2, 1), n2.editCount++), i3.byId && n2.indexes.byId) {
const t20 = eg(s2);
n2.indexes.byId.delete(t20);
}
if (i3.byType && n2.indexes.byType) {
const t20 = (n2.indexes.byType.get(r2) || []).filter((t21) => t21[`${r2}_id`] !== o3);
n2.indexes.byType.set(r2, t20);
}
if (i3.byRelation && n2.indexes.byRelation)
for (const [t20, e3] of n2.indexes.byRelation.entries())
for (const [t21, n3] of e3.entries()) {
const o4 = n3.filter((t22) => t22 !== s2);
o4.length === 0 ? e3.delete(t21) : e3.set(t21, o4);
}
if (i3.bySubcircuit && n2.indexes.bySubcircuit && "subcircuit_id" in s2) {
const t20 = s2.subcircuit_id;
if (t20) {
const e3 = (n2.indexes.bySubcircuit.get(t20) || []).filter((t21) => t21 !== s2);
e3.length === 0 ? n2.indexes.bySubcircuit.delete(t20) : n2.indexes.bySubcircuit.set(t20, e3);
}
}
if (i3.byCustomField && n2.indexes.byCustomField)
for (const t20 of n2.indexes.byCustomField.values())
for (const [e3, n3] of t20.entries()) {
const o4 = n3.filter((t21) => t21 !== s2);
o4.length === 0 ? t20.delete(e3) : t20.set(e3, o4);
}
}, update: (o3, i3) => {
const s2 = e2.indexConfig || {};
let a2;
if (s2.byId && n2.indexes.byId)
a2 = n2.indexes.byId.get(`${r2}:${o3}`);
else if (s2.byType && n2.indexes.byType) {
const t20 = n2.indexes.byType.get(r2) || [];
a2 = t20.find((t21) => t21[`${r2}_id`] === o3);
} else
a2 = t19.find((t20) => t20.type === r2 && t20[`${r2}_id`] === o3);
if (!a2)
return null;
if (s2.byRelation && n2.indexes.byRelation) {
const t20 = Object.entries(a2);
for (const [e3, o4] of t20)
if (e3.endsWith("_id") && e3 !== `${a2.type}_id` && typeof o4 == "string" && e3 in i3 && i3[e3] !== o4) {
const t21 = n2.indexes.byRelation.get(e3);
if (t21) {
const e4 = (t21.get(o4) || []).filter((t22) => t22 !== a2);
e4.length === 0 ? t21.delete(o4) : t21.set(o4, e4);
}
}
}
if (s2.bySubcircuit && n2.indexes.bySubcircuit && "subcircuit_id" in a2 && "subcircuit_id" in i3) {
const t20 = a2.subcircuit_id;
if (t20 !== i3.subcircuit_id) {
const e3 = (n2.indexes.bySubcircuit.get(t20) || []).filter((t21) => t21 !== a2);
e3.length === 0 ? n2.indexes.bySubcircuit.delete(t20) : n2.indexes.bySubcircuit.set(t20, e3);
}
}
if (s2.byCustomField && n2.indexes.byCustomField) {
for (const t20 of s2.byCustomField)
if (t20 in a2 && t20 in i3 && a2[t20] !== i3[t20]) {
const e3 = n2.indexes.byCustomField.get(t20);
if (e3) {
const n3 = String(a2[t20]), o4 = (e3.get(n3) || []).filter((t21) => t21 !== a2);
o4.length === 0 ? e3.delete(n3) : e3.set(n3, o4);
}
}
}
if (Object.assign(a2, i3), n2.editCount++, s2.byRelation && n2.indexes.byRelation) {
const t20 = Object.entries(a2);
for (const [e3, o4] of t20)
if (e3.endsWith("_id") && e3 !== `${a2.type}_id` && typeof o4 == "string" && e3 in i3) {
const t21 = n2.indexes.byRelation.get(e3) || new Map, i4 = t21.get(o4) || [];
i4.includes(a2) || (i4.push(a2), t21.set(o4, i4), n2.indexes.byRelation.set(e3, t21));
}
}
if (s2.bySubcircuit && n2.indexes.bySubcircuit && "subcircuit_id" in a2 && "subcircuit_id" in i3) {
const t20 = a2.subcircuit_id;
if (t20 && typeof t20 == "string") {
const e3 = n2.indexes.bySubcircuit.get(t20) || [];
e3.includes(a2) || (e3.push(a2), n2.indexes.bySubcircuit.set(t20, e3));
}
}
if (s2.byCustomField && n2.indexes.byCustomField) {
for (const t20 of s2.byCustomField)
if (t20 in a2 && t20 in i3) {
const e3 = a2[t20];
if (e3 !== undefined && (typeof e3 == "string" || typeof e3 == "number")) {
const o4 = String(e3), i4 = n2.indexes.byCustomField.get(t20), r3 = i4.get(o4) || [];
r3.includes(a2) || (r3.push(a2), i4.set(o4, r3));
}
}
}
return a2;
}, select: (e3) => {
if (r2 === "source_component")
return t19.find((t20) => t20.type === "source_component" && t20.name === e3.replace(/\./g, "")) || null;
if (r2 === "pcb_port" || r2 === "source_port" || r2 === "schematic_port") {
const [n3, o3] = e3.replace(/\./g, "").split(/[\s\>]+/), i3 = t19.find((t20) => t20.type === "source_component" && t20.name === n3);
if (!i3)
return null;
const s2 = t19.find((t20) => t20.type === "source_port" && t20.source_component_id === i3.source_component_id && (t20.name === o3 || (t20.port_hints ?? []).includes(o3)));
if (!s2)
return null;
if (r2 === "source_port")
return s2;
if (r2 === "pcb_port")
return t19.find((t20) => t20.type === "pcb_port" && t20.source_port_id === s2.source_port_id) || null;
if (r2 === "schematic_port")
return t19.find((t20) => t20.type === "schematic_port" && t20.source_port_id === s2.source_port_id) || null;
}
return null;
} };
} });
};
ng.unparsed = ng;
var og = (t19) => t19[`${t19.type}_id`];
function ig(t19, e2) {
const n2 = Km(t19).pcb_trace.get(e2);
if (!n2)
return `trace[${e2}]`;
const o2 = n2.route.flatMap((t20) => [t20.start_pcb_port_id, t20.end_pcb_port_id]).filter(Boolean);
if (o2.length === 0)
return `trace[${e2}]`;
return `trace[${o2.map((e3) => {
const n3 = function(e4) {
const n4 = Km(t19).pcb_port.get(e4);
if (!n4)
return null;
const o3 = n4.pcb_component_id ? Km(t19).pcb_component.get(n4.pcb_component_id) : undefined;
if (!o3)
return null;
const i2 = Km(t19).source_component.get(o3.source_component_id);
if (!i2)
return null;
const r2 = Km(t19).source_port.get(n4.source_port_id), s2 = r2?.port_hints ? r2.port_hints[1] : "";
return { componentName: i2.name, portHint: s2 };
}(e3);
return n3 ? `.${n3.componentName} > port.${n3.portHint}` : `port[${e3}]`;
}).join(", ")}]`;
}
var rg = (t19, e2) => {
const n2 = Km(t19).pcb_port.get(e2);
if (!n2)
return `pcb_port[#${e2}]`;
const o2 = n2.pcb_component_id ? Km(t19).pcb_component.get(n2.pcb_component_id) : undefined;
if (!o2)
return `pcb_port[#${e2}]`;
const i2 = Km(t19).source_component.get(o2.source_component_id);
if (!i2)
return `pcb_port[#${e2}]`;
const r2 = Km(t19).source_port.get(n2.source_port_id);
if (!r2)
return `pcb_port[#${e2}]`;
let s2;
return s2 = r2?.port_hints && r2.port_hints.length > 0 || r2.port_hints && r2.port_hints.length > 0 ? r2.port_hints[0] : e2, `pcb_port[.${i2.name} > .${s2}]`;
};
var sg = (t19, e2) => {
if (typeof e2 == "string") {
const n2 = ((t20, e3) => t20.find((t21) => og(t21) === e3) ?? null)(t19, e2);
return sg(t19, n2);
}
switch (e2.type) {
case "pcb_port":
return rg(t19, e2.pcb_port_id);
case "pcb_smtpad":
return function(t20, e3) {
const n2 = Km(t20).pcb_smtpad.get(e3);
return n2 && n2.pcb_port_id ? rg(t20, n2.pcb_port_id) : `smtpad[${e3}]`;
}(t19, e2.pcb_smtpad_id);
case "pcb_trace":
return ig(t19, e2.pcb_trace_id);
case "source_component":
return `source_component[${e2.name}]`;
default:
return `${e2.type}[#${og(e2)}]`;
}
};
var ag = (t19, e2) => ({ minX: Math.min(t19.minX, e2.minX), minY: Math.min(t19.minY, e2.minY), maxX: Math.max(t19.maxX, e2.maxX), maxY: Math.max(t19.maxY, e2.maxY) });
var cg = (t19, e2, n2) => {
const o2 = n2 / 2;
return { minX: t19 - o2, minY: e2 - o2, maxX: t19 + o2, maxY: e2 + o2 };
};
var lg = (t19, e2, n2, o2, i2) => {
const r2 = n2 / 2, s2 = o2 / 2, a2 = i2 * Math.PI / 180, c2 = Math.cos(a2), l2 = Math.sin(a2), h2 = [{ x: -r2, y: -s2 }, { x: r2, y: -s2 }, { x: r2, y: s2 }, { x: -r2, y: s2 }].map((n3) => ({ x: t19 + n3.x * c2 - n3.y * l2, y: e2 + n3.x * l2 + n3.y * c2 }));
return { minX: Math.min(...h2.map((t20) => t20.x)), minY: Math.min(...h2.map((t20) => t20.y)), maxX: Math.max(...h2.map((t20) => t20.x)), maxY: Math.max(...h2.map((t20) => t20.y)) };
};
var hg = (t19) => {
let { POSITIVE_INFINITY: e2, POSITIVE_INFINITY: n2, NEGATIVE_INFINITY: o2, NEGATIVE_INFINITY: i2 } = Number;
for (const r2 of t19) {
if (!r2.type.startsWith("pcb_"))
continue;
if (r2.type === "pcb_smtpad" && r2.shape === "polygon" && Array.isArray(r2.points)) {
for (const t21 of r2.points)
e2 = Math.min(e2, t21.x), n2 = Math.min(n2, t21.y), o2 = Math.max(o2, t21.x), i2 = Math.max(i2, t21.y);
continue;
}
if (r2.type === "pcb_hole" && r2.hole_shape === "circle") {
const t21 = cg(r2.x, r2.y, r2.hole_diameter);
e2 = Math.min(e2, t21.minX), n2 = Math.min(n2, t21.minY), o2 = Math.max(o2, t21.maxX), i2 = Math.max(i2, t21.maxY);
continue;
}
if (r2.type === "pcb_plated_hole") {
let t21;
if ("outer_diameter" in r2 && typeof r2.outer_diameter == "number" ? t21 = cg(r2.x, r2.y, r2.outer_diameter) : ("hole_diameter" in r2) && typeof r2.hole_diameter == "number" && (t21 = cg(r2.x, r2.y, r2.hole_diameter)), "rect_pad_width" in r2 && typeof r2.rect_pad_width == "number" && "rect_pad_height" in r2 && typeof r2.rect_pad_height == "number") {
const e3 = lg(r2.x, r2.y, r2.rect_pad_width, r2.rect_pad_height, "rect_ccw_rotation" in r2 ? r2.rect_ccw_rotation ?? 0 : 0);
t21 = t21 ? ag(t21, e3) : e3;
}
if ("hole_diameter" in r2 && typeof r2.hole_diameter == "number") {
const e3 = cg(r2.x + ("hole_offset_x" in r2 ? r2.hole_offset_x ?? 0 : 0), r2.y + ("hole_offset_y" in r2 ? r2.hole_offset_y ?? 0 : 0), r2.hole_diameter);
t21 = t21 ? ag(t21, e3) : e3;
}
if (t21) {
e2 = Math.min(e2, t21.minX), n2 = Math.min(n2, t21.minY), o2 = Math.max(o2, t21.maxX), i2 = Math.max(i2, t21.maxY);
continue;
}
}
let t20, s2, a2, c2;
if ("x" in r2 && "y" in r2 && (t20 = Number(r2.x), s2 = Number(r2.y)), "outer_diameter" in r2 && (a2 = Number(r2.outer_diameter), c2 = Number(r2.outer_diameter)), "width" in r2 && (a2 = Number(r2.width)), "height" in r2 && (c2 = Number(r2.height)), "center" in r2 && (t20 = r2.center.x, s2 = r2.center.y), t20 !== undefined && s2 !== undefined)
e2 = Math.min(e2, t20), n2 = Math.min(n2, s2), o2 = Math.max(o2, t20), i2 = Math.max(i2, s2), a2 !== undefined && c2 !== undefined && (e2 = Math.min(e2, t20 - a2 / 2), n2 = Math.min(n2, s2 - c2 / 2), o2 = Math.max(o2, t20 + a2 / 2), i2 = Math.max(i2, s2 + c2 / 2)), "radius" in r2 && (e2 = Math.min(e2, t20 - r2.radius), n2 = Math.min(n2, s2 - r2.radius), o2 = Math.max(o2, t20 + r2.radius), i2 = Math.max(i2, s2 + r2.radius));
else if (r2.type === "pcb_trace")
for (const t21 of r2.route)
e2 = Math.min(e2, t21.x), n2 = Math.min(n2, t21.y), o2 = Math.max(o2, t21.x), i2 = Math.max(i2, t21.y);
else if (r2.type === "pcb_courtyard_outline")
for (const t21 of r2.outline)
e2 = Math.min(e2, t21.x), n2 = Math.min(n2, t21.y), o2 = Math.max(o2, t21.x), i2 = Math.max(i2, t21.y);
else if (r2.type === "pcb_courtyard_polygon")
for (const t21 of r2.points)
e2 = Math.min(e2, t21.x), n2 = Math.min(n2, t21.y), o2 = Math.max(o2, t21.x), i2 = Math.max(i2, t21.y);
}
return { minX: e2, minY: n2, maxX: o2, maxY: i2 };
};
var dg = (t19) => t19[`${t19.type}_id`];
var ug = { Hz: { baseUnit: "Hz", variants: { MHz: 1e6, kHz: 1000, Hz: 1 } }, g: { baseUnit: "g", variants: { kg: 1000, g: 1 } }, "Ω": { baseUnit: "Ω", variants: { "mΩ": 0.001, "Ω": 1, "kΩ": 1000, "KΩ": 1000, kohm: 1000, "MΩ": 1e6, "GΩ": 1e9, "TΩ": 1000000000000 } }, V: { baseUnit: "V", variants: { mV: 0.001, V: 1, kV: 1000, KV: 1000, MV: 1e6, GV: 1e9, TV: 1000000000000 } }, A: { baseUnit: "A", variants: { "µA": 0.000001, mA: 0.001, ma: 0.001, A: 1, kA: 1000, MA: 1e6 } }, F: { baseUnit: "F", variants: { pF: 0.000000000001, nF: 0.000000001, "µF": 0.000001, uF: 0.000001, mF: 0.001, F: 1 } }, ml: { baseUnit: "ml", variants: { ml: 1, mL: 1, l: 1000, L: 1000 } }, deg: { baseUnit: "deg", variants: { rad: 180 / Math.PI } }, ms: { baseUnit: "ms", variants: { fs: 0.000000000001, ps: 0.000000001, ns: 0.000001, us: 0.001, "µs": 0.001, ms: 1, s: 1000 } }, mm: { baseUnit: "mm", variants: { nm: 0.000001, "µm": 0.001, um: 0.001, mm: 1, cm: 10, dm: 100, m: 1000, km: 1e6, in: 25.4, ft: 304.8, IN: 25.4, FT: 304.8, yd: 914.4, mi: 1609344, mil: 0.0254 } } };
var pg = new Set;
for (const [t19, e2] of Object.entries(ug)) {
pg.add(t19);
for (const t20 of Object.keys(e2.variants))
pg.add(t20);
}
var mg = { tera: 1000000000000, T: 1000000000000, giga: 1e9, G: 1e9, mega: 1e6, M: 1e6, kilo: 1000, k: 1000, deci: 0.1, d: 0.1, centi: 0.01, c: 0.01, milli: 0.001, m: 0.001, micro: 0.000001, u: 0.000001, "µ": 0.000001, nano: 0.000000001, n: 0.000000001, pico: 0.000000000001, p: 0.000000000001 };
function gg(t19) {
if (t19 == null)
return { parsedUnit: null, unitOfValue: null, value: null };
if (typeof t19 == "string" && t19.match(/^-?[\d\.]+$/))
return { value: Number.parseFloat(t19), parsedUnit: null, unitOfValue: null };
if (typeof t19 == "number")
return { value: t19, parsedUnit: null, unitOfValue: null };
if (typeof t19 == "object" && "x" in t19 && "y" in t19) {
const { parsedUnit: e3, unitOfValue: n3 } = gg(t19.x), o3 = gg(t19.x), i3 = gg(t19.y);
return o3.value === null || i3.value === null ? { parsedUnit: null, unitOfValue: null, value: null } : { parsedUnit: e3, unitOfValue: n3, value: { x: o3.value, y: i3.value } };
}
const e2 = t19.toString().split("").reverse().join(""), n2 = e2.match(/[^\d\s]+/)?.[0];
if (!n2)
throw new Error(`Could not determine unit: "${t19}"`);
const o2 = n2.split("").reverse().join(""), i2 = t19.slice(0, -o2.length);
if (o2 in mg && !pg.has(o2)) {
const t20 = mg[o2];
return { parsedUnit: null, unitOfValue: null, value: Number.parseFloat(i2) * t20 };
}
const { baseUnit: r2, conversionFactor: s2 } = function(t20) {
for (const [e3, n3] of Object.entries(ug))
if (t20 in n3.variants)
return { baseUnit: n3.baseUnit, conversionFactor: n3.variants[t20] };
return { baseUnit: t20, conversionFactor: 1 };
}(o2);
return { parsedUnit: o2, unitOfValue: r2, value: s2 * Number.parseFloat(i2) };
}
var fg = pa.string().or(pa.number()).transform((t19) => gg(t19).value);
var yg = pa.string().or(pa.number()).transform((t19) => gg(t19).value).transform((t19) => Number.parseFloat(t19.toPrecision(12)));
var _g = pa.string().or(pa.number()).transform((t19) => gg(t19).value);
var bg = pa.string().or(pa.number()).transform((t19) => gg(t19).value);
var xg = pa.string().or(pa.number()).transform((t19) => gg(t19).value);
var vg = pa.string().or(pa.number()).transform((t19) => gg(t19).value);
var Ig = xg;
var Sg = pa.string().or(pa.number()).transform((t19) => gg(t19).value);
var Cg = pa.string().or(pa.number()).transform((t19) => gg(t19).value);
var Pg = Cg;
var Mg = pa.string().datetime();
var Ng = pa.string().or(pa.number()).transform((t19) => typeof t19 == "number" ? t19 : t19.endsWith("deg") ? Number.parseFloat(t19.split("deg")[0]) : t19.endsWith("rad") ? 180 * Number.parseFloat(t19.split("rad")[0]) / Math.PI : Number.parseFloat(t19));
var wg = pa.number().or(pa.string().endsWith("mAh")).transform((t19) => {
if (typeof t19 == "string") {
const e2 = t19.replace("mAh", ""), n2 = Number.parseFloat(e2);
if (Number.isNaN(n2))
throw new Error("Invalid capacity");
return n2;
}
return t19;
}).describe("Battery capacity in mAh");
var Tg = pa.object({ x: Ig, y: Ig });
var Rg = pa.object({ x: Ig, y: Ig, z: Ig });
var Eg = pa.object({ width: pa.number(), height: pa.number() });
var Ag = (t19) => pa.string().optional().default(() => `${t19}_${((t20) => {
const e2 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return Array.from({ length: t20 }, () => e2[Math.floor(62 * Math.random())]).join("");
})(10)}`);
var Og = pa.enum(["top_left", "top_center", "top_right", "center_left", "center", "center_right", "bottom_left", "bottom_center", "bottom_right"]);
var kg = (pa.enum(["top_silkscreen", "bottom_silkscreen", "top_copper", "bottom_copper", "top_soldermask", "bottom_soldermask", "top_fabrication_note", "bottom_fabrication_note", "top_user_note", "bottom_user_note", "top_courtyard", "bottom_courtyard", "inner1_copper", "inner2_copper", "inner3_copper", "inner4_copper", "inner5_copper", "inner6_copper", "edge_cuts", "drill"]), pa.object({ project_relative_path: pa.string(), url: pa.string(), mimetype: pa.string() }));
var Dg = Tg.extend({ rotation: Ng.optional() });
var Lg = pa.object({ size: Tg.optional(), thickness: Ig.optional() });
var zg = pa.object({ font: Lg.optional() });
var Bg = pa.object({ value: pa.string(), at: Dg.optional(), layer: pa.string().optional(), uuid: pa.string().optional(), hide: pa.boolean().optional(), effects: zg.optional() });
var Fg = pa.object({ Reference: Bg.optional(), Value: Bg.optional(), Datasheet: Bg.optional(), Description: Bg.optional() });
var jg = pa.object({ through_hole: pa.boolean().optional(), smd: pa.boolean().optional(), exclude_from_pos_files: pa.boolean().optional(), exclude_from_bom: pa.boolean().optional() });
var $g = pa.object({ name: pa.string(), type: pa.string(), shape: pa.string().optional(), at: Dg.optional(), size: Tg.optional(), drill: Ig.optional(), layers: pa.array(pa.string()).optional(), removeUnusedLayers: pa.boolean().optional(), uuid: pa.string().optional() });
var Yg = pa.object({ path: pa.string(), offset: Rg.optional(), scale: Rg.optional(), rotate: Rg.optional() });
var Xg = pa.object({ footprintName: pa.string().optional(), version: pa.union([pa.number(), pa.string()]).optional(), generator: pa.string().optional(), generatorVersion: pa.union([pa.number(), pa.string()]).optional(), layer: pa.string().optional(), properties: Fg.optional(), attributes: jg.optional(), pads: pa.array($g).optional(), embeddedFonts: pa.boolean().optional(), model: Yg.optional() });
var Wg = pa.object({ hide: pa.boolean().optional() });
var Vg = pa.object({ offset: Ig.optional(), hide: pa.boolean().optional() });
var Hg = pa.object({ font: Lg.optional(), justify: pa.union([pa.string(), pa.array(pa.string())]).optional(), hide: pa.boolean().optional() });
var Gg = pa.object({ value: pa.string(), id: pa.union([pa.number(), pa.string()]).optional(), at: Dg.optional(), effects: Hg.optional() });
var Ug = pa.object({ Reference: Gg.optional(), Value: Gg.optional(), Footprint: Gg.optional(), Datasheet: Gg.optional(), Description: Gg.optional(), ki_keywords: Gg.optional(), ki_fp_filters: Gg.optional() });
var Zg = pa.object({ symbolName: pa.string().optional(), extends: pa.string().optional(), pinNumbers: Wg.optional(), pinNames: Vg.optional(), excludeFromSim: pa.boolean().optional(), inBom: pa.boolean().optional(), onBoard: pa.boolean().optional(), properties: Ug.optional(), embeddedFonts: pa.boolean().optional() });
var qg = pa.object({ error_type: pa.string(), message: pa.string(), is_fatal: pa.boolean().optional() });
var Jg = pa.enum(["jlcpcb", "macrofab", "pcbway", "digikey", "mouser", "lcsc"]);
var Qg = pa.object({ type: pa.literal("source_component"), ftype: pa.string().optional(), source_component_id: pa.string(), name: pa.string(), manufacturer_part_number: pa.string().optional(), supplier_part_numbers: pa.record(Jg, pa.array(pa.string())).optional(), display_value: pa.string().optional(), display_name: pa.string().optional(), are_pins_interchangeable: pa.boolean().optional(), internally_connected_source_port_ids: pa.array(pa.array(pa.string())).optional(), source_group_id: pa.string().optional(), subcircuit_id: pa.string().optional() });
var Kg = Qg.extend({ ftype: pa.literal("simple_capacitor"), capacitance: yg, max_voltage_rating: bg.optional(), display_capacitance: pa.string().optional(), max_decoupling_trace_length: Ig.optional() });
var tf = Qg.extend({ ftype: pa.literal("simple_resistor"), resistance: fg, display_resistance: pa.string().optional() });
var ef = Qg.extend({ ftype: pa.literal("simple_diode") });
var nf = Qg.extend({ ftype: pa.literal("simple_fiducial") });
var of = ef.extend({ ftype: pa.literal("simple_led"), color: pa.string().optional(), wavelength: pa.string().optional() });
var rf = Qg.extend({ ftype: pa.literal("simple_ground") });
var sf = Qg.extend({ ftype: pa.literal("simple_chip") });
var af = Qg.extend({ ftype: pa.literal("simple_power_source"), voltage: bg });
var cf = Qg.extend({ ftype: pa.literal("simple_current_source"), current: Sg, frequency: vg.optional(), peak_to_peak_current: Sg.optional(), wave_shape: pa.enum(["sine", "square", "triangle", "sawtooth", "dc"]).optional().default("dc"), phase: pa.number().optional(), duty_cycle: pa.number().min(0).max(1).optional() });
var lf = pa.object({ must_be_connected: pa.boolean().optional(), provides_power: pa.boolean().optional(), requires_power: pa.boolean().optional(), provides_ground: pa.boolean().optional(), requires_ground: pa.boolean().optional(), provides_voltage: pa.union([pa.string(), pa.number()]).optional(), requires_voltage: pa.union([pa.string(), pa.number()]).optional(), do_not_connect: pa.boolean().optional(), include_in_board_pinout: pa.boolean().optional(), can_use_internal_pullup: pa.boolean().optional(), is_using_internal_pullup: pa.boolean().optional(), needs_external_pullup: pa.boolean().optional(), can_use_internal_pulldown: pa.boolean().optional(), is_using_internal_pulldown: pa.boolean().optional(), needs_external_pulldown: pa.boolean().optional(), can_use_open_drain: pa.boolean().optional(), is_using_open_drain: pa.boolean().optional(), can_use_push_pull: pa.boolean().optional(), is_using_push_pull: pa.boolean().optional(), should_have_decoupling_capacitor: pa.boolean().optional(), recommended_decoupling_capacitor_capacitance: pa.union([pa.string(), pa.number()]).optional(), is_configured_for_i2c_sda: pa.boolean().optional(), is_configured_for_i2c_scl: pa.boolean().optional(), is_configured_for_spi_mosi: pa.boolean().optional(), is_configured_for_spi_miso: pa.boolean().optional(), is_configured_for_spi_sck: pa.boolean().optional(), is_configured_for_spi_cs: pa.boolean().optional(), is_configured_for_uart_tx: pa.boolean().optional(), is_configured_for_uart_rx: pa.boolean().optional(), supports_i2c_sda: pa.boolean().optional(), supports_i2c_scl: pa.boolean().optional(), supports_spi_mosi: pa.boolean().optional(), supports_spi_miso: pa.boolean().optional(), supports_spi_sck: pa.boolean().optional(), supports_spi_cs: pa.boolean().optional(), supports_uart_tx: pa.boolean().optional(), supports_uart_rx: pa.boolean().optional() });
var hf = Qg.extend({ ftype: pa.literal("simple_fuse"), current_rating_amps: pa.number().describe("Nominal current in amps the fuse is rated for"), voltage_rating_volts: pa.number().describe("Voltage rating in volts, e.g. ±5V would be 5") });
var df = Qg.extend({ ftype: pa.literal("simple_battery"), capacity: wg });
var uf = Qg.extend({ ftype: pa.literal("simple_inductor"), inductance: _g, display_inductance: pa.string().optional(), max_current_rating: pa.number().optional() });
var pf = Qg.extend({ ftype: pa.literal("simple_push_button") });
var mf = Qg.extend({ ftype: pa.literal("simple_potentiometer"), max_resistance: fg, display_max_resistance: pa.string().optional() });
var gf = Qg.extend({ ftype: pa.literal("simple_crystal"), frequency: pa.number().describe("Frequency in Hz"), load_capacitance: pa.number().optional().describe("Load capacitance in pF"), pin_variant: pa.enum(["two_pin", "four_pin"]).optional() });
var ff = Qg.extend({ ftype: pa.literal("simple_pin_header"), pin_count: pa.number(), gender: pa.enum(["male", "female"]).optional().default("male") });
var yf = Qg.extend({ ftype: pa.literal("simple_connector"), standard: pa.enum(["usb_c", "m2"]).optional() });
var _f = Qg.extend({ ftype: pa.literal("simple_pinout") });
var bf = Qg.extend({ ftype: pa.literal("simple_resonator"), load_capacitance: yg, equivalent_series_resistance: fg.optional(), frequency: vg });
var xf = Qg.extend({ ftype: pa.literal("simple_transistor"), transistor_type: pa.enum(["npn", "pnp"]) });
var vf = Qg.extend({ ftype: pa.literal("simple_test_point"), footprint_variant: pa.enum(["pad", "through_hole"]).optional(), pad_shape: pa.enum(["rect", "circle"]).optional(), pad_diameter: pa.union([pa.number(), pa.string()]).optional(), hole_diameter: pa.union([pa.number(), pa.string()]).optional(), width: pa.union([pa.number(), pa.string()]).optional(), height: pa.union([pa.number(), pa.string()]).optional() });
var If = Qg.extend({ ftype: pa.literal("simple_mosfet"), channel_type: pa.enum(["n", "p"]), mosfet_mode: pa.enum(["enhancement", "depletion"]) });
var Sf = Qg.extend({ ftype: pa.literal("simple_op_amp") });
var Cf = Qg.extend({ ftype: pa.literal("simple_switch") });
var Pf = pa.object({ type: pa.literal("source_project_metadata"), name: pa.string().optional(), software_used_string: pa.string().optional(), project_url: pa.string().optional(), created_at: Mg.optional() });
var Mf = qg.extend({ type: pa.literal("source_missing_property_error"), source_missing_property_error_id: Ag("source_missing_property_error"), source_component_id: pa.string(), property_name: pa.string(), subcircuit_id: pa.string().optional(), error_type: pa.literal("source_missing_property_error").default("source_missing_property_error") }).describe("The source code is missing a property");
var Nf = qg.extend({ type: pa.literal("source_failed_to_create_component_error"), source_failed_to_create_component_error_id: Ag("source_failed_to_create_component_error"), error_type: pa.literal("source_failed_to_create_component_error").default("source_failed_to_create_component_error"), component_name: pa.string().optional(), subcircuit_id: pa.string().optional(), parent_source_component_id: pa.string().optional(), pcb_center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), schematic_center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional() }).describe("Error emitted when a component fails to be constructed");
var wf = qg.extend({ type: pa.literal("source_invalid_component_property_error"), source_invalid_component_property_error_id: Ag("source_invalid_component_property_error"), source_component_id: pa.string(), property_name: pa.string(), property_value: pa.unknown().optional(), expected_format: pa.string().optional(), subcircuit_id: pa.string().optional(), error_type: pa.literal("source_invalid_component_property_error").default("source_invalid_component_property_error") }).describe("The source component property is invalid");
var Tf = qg.extend({ type: pa.literal("source_trace_not_connected_error"), source_trace_not_connected_error_id: Ag("source_trace_not_connected_error"), error_type: pa.literal("source_trace_not_connected_error").default("source_trace_not_connected_error"), subcircuit_id: pa.string().optional(), source_group_id: pa.string().optional(), source_trace_id: pa.string().optional(), connected_source_port_ids: pa.array(pa.string()).optional(), selectors_not_found: pa.array(pa.string()).optional() }).describe("Occurs when a source trace selector does not match any ports");
var Rf = pa.object({ type: pa.literal("source_property_ignored_warning"), source_property_ignored_warning_id: Ag("source_property_ignored_warning"), source_component_id: pa.string(), property_name: pa.string(), subcircuit_id: pa.string().optional(), error_type: pa.literal("source_property_ignored_warning").default("source_property_ignored_warning"), message: pa.string() }).describe("The source property was ignored");
var Ef = pa.object({ type: pa.literal("source_pin_missing_trace_warning"), source_pin_missing_trace_warning_id: Ag("source_pin_missing_trace_warning"), warning_type: pa.literal("source_pin_missing_trace_warning").default("source_pin_missing_trace_warning"), message: pa.string(), source_component_id: pa.string(), source_port_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a source component pin is missing a trace connection");
var Af = pa.object({ type: pa.literal("source_missing_manufacturer_part_number_warning"), source_missing_manufacturer_part_number_warning_id: Ag("source_missing_manufacturer_part_number_warning"), warning_type: pa.literal("source_missing_manufacturer_part_number_warning").default("source_missing_manufacturer_part_number_warning"), message: pa.string(), source_component_id: pa.string(), standard: pa.string(), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a standard connector is missing manufacturer part number");
var Of = Qg.extend({ ftype: pa.literal("simple_voltage_probe") });
var kf = Qg.extend({ ftype: pa.literal("interconnect") });
var Df = qg.extend({ type: pa.literal("source_i2c_misconfigured_error"), source_i2c_misconfigured_error_id: Ag("source_i2c_misconfigured_error"), error_type: pa.literal("source_i2c_misconfigured_error").default("source_i2c_misconfigured_error"), source_port_ids: pa.array(pa.string()) }).describe("Error emitted when incompatible I2C pins (e.g. SDA and SCL) are connected to the same net");
var Lf = Qg.extend({ ftype: pa.literal("simple_voltage_source"), voltage: bg, frequency: vg.optional(), peak_to_peak_voltage: bg.optional(), wave_shape: pa.enum(["sinewave", "square", "triangle", "sawtooth"]).optional(), phase: Ng.optional(), duty_cycle: pa.number().optional().describe("Duty cycle as a fraction (0 to 1)") });
var zf = pa.union([tf, Kg, ef, nf, of, rf, sf, af, cf, df, uf, pf, mf, gf, ff, yf, _f, bf, Cf, xf, vf, If, Sf, hf, Of, kf, Lf, Pf, Mf, wf, Nf, Tf, Rf, Ef, Af, Df]);
var Bf = pa.object({ type: pa.literal("source_port"), pin_number: pa.number().optional(), port_hints: pa.array(pa.string()).optional(), name: pa.string(), source_port_id: pa.string(), source_component_id: pa.string().optional(), source_group_id: pa.string().optional(), most_frequently_referenced_by_name: pa.string().optional(), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional() }).merge(lf);
var Ff = pa.object({ type: pa.literal("source_component_internal_connection"), source_component_internal_connection_id: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() });
var jf = pa.object({ type: pa.literal("source_trace"), source_trace_id: pa.string(), connected_source_port_ids: pa.array(pa.string()), connected_source_net_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional(), max_length: pa.number().optional(), min_trace_thickness: pa.number().optional(), display_name: pa.string().optional() });
var $f = pa.object({ type: pa.literal("source_group"), source_group_id: pa.string(), subcircuit_id: pa.string().optional(), parent_subcircuit_id: pa.string().optional(), parent_source_group_id: pa.string().optional(), is_subcircuit: pa.boolean().optional(), show_as_schematic_box: pa.boolean().optional(), name: pa.string().optional(), was_automatically_named: pa.boolean().optional() });
var Yf = pa.object({ type: pa.literal("source_net"), source_net_id: pa.string(), name: pa.string(), member_source_group_ids: pa.array(pa.string()), is_power: pa.boolean().optional(), is_ground: pa.boolean().optional(), is_digital_signal: pa.boolean().optional(), is_analog_signal: pa.boolean().optional(), is_positive_voltage_source: pa.boolean().optional(), trace_width: pa.number().optional(), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional() });
var Xf = pa.object({ type: pa.literal("source_board"), source_board_id: pa.string(), source_group_id: pa.string(), title: pa.string().optional() }).describe("Defines a board in the source domain");
var Wf = qg.extend({ type: pa.literal("source_ambiguous_port_reference"), source_ambiguous_port_reference_id: Ag("source_ambiguous_port_reference"), error_type: pa.literal("source_ambiguous_port_reference").default("source_ambiguous_port_reference"), source_port_id: pa.string().optional(), source_component_id: pa.string().optional() }).describe("Error emitted when a port hint matches multiple non-overlapping pads, making the port reference ambiguous");
var Vf = pa.object({ type: pa.literal("source_pcb_ground_plane"), source_pcb_ground_plane_id: pa.string(), source_group_id: pa.string(), source_net_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Defines a ground plane in the source domain");
var Hf = pa.enum(["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6"]);
var Gf = Hf.or(pa.object({ name: Hf })).transform((t19) => typeof t19 == "string" ? t19 : t19.name);
var Uf = pa.enum(["top", "bottom"]);
var Zf = pa.object({ type: pa.literal("source_manually_placed_via"), source_manually_placed_via_id: pa.string(), source_group_id: pa.string(), source_net_id: pa.string(), subcircuit_id: pa.string().optional(), source_trace_id: pa.string().optional() }).describe("Defines a via that is manually placed in the source domain");
var qf = pa.object({ type: pa.literal("source_no_power_pin_defined_warning"), source_no_power_pin_defined_warning_id: Ag("source_no_power_pin_defined_warning"), warning_type: pa.literal("source_no_power_pin_defined_warning").default("source_no_power_pin_defined_warning"), message: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a chip has no source ports with requires_power=true");
var Jf = pa.object({ type: pa.literal("source_no_ground_pin_defined_warning"), source_no_ground_pin_defined_warning_id: Ag("source_no_ground_pin_defined_warning"), warning_type: pa.literal("source_no_ground_pin_defined_warning").default("source_no_ground_pin_defined_warning"), message: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a chip has no source ports marked as ground pins");
var Qf = pa.object({ type: pa.literal("source_component_pins_underspecified_warning"), source_component_pins_underspecified_warning_id: Ag("source_component_pins_underspecified_warning"), warning_type: pa.literal("source_component_pins_underspecified_warning").default("source_component_pins_underspecified_warning"), message: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Warning emitted when all ports on a source component are underspecified");
var Kf = qg.extend({ type: pa.literal("source_pin_must_be_connected_error"), source_pin_must_be_connected_error_id: Ag("source_pin_must_be_connected_error"), error_type: pa.literal("source_pin_must_be_connected_error").default("source_pin_must_be_connected_error"), source_component_id: pa.string(), source_port_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a pin with mustBeConnected attribute is not connected to any trace");
var ty = qg.extend({ type: pa.literal("unknown_error_finding_part"), unknown_error_finding_part_id: Ag("unknown_error_finding_part"), error_type: pa.literal("unknown_error_finding_part").default("unknown_error_finding_part"), source_component_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when an unexpected error occurs while finding a part");
var ey = pa.object({ type: pa.literal("schematic_box"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), width: Ig, height: Ig, is_dashed: pa.boolean().default(false), x: Ig, y: Ig, subcircuit_id: pa.string().optional() }).describe("Draws a box on the schematic");
var ny = pa.object({ type: pa.literal("schematic_path"), schematic_path_id: Ag("schematic_path"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), fill_color: pa.string().optional(), is_filled: pa.boolean().optional(), stroke_width: Ig.nullable().optional(), stroke_color: pa.string().optional(), points: pa.array(Tg), subcircuit_id: pa.string().optional() });
var oy = pa.record(pa.object({ left_margin: xg.optional(), right_margin: xg.optional(), top_margin: xg.optional(), bottom_margin: xg.optional() }));
var iy = pa.object({ left_size: pa.number(), right_size: pa.number(), top_size: pa.number().optional(), bottom_size: pa.number().optional() });
var ry = pa.object({ left_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["top-to-bottom", "bottom-to-top"]).optional() }).optional(), right_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["top-to-bottom", "bottom-to-top"]).optional() }).optional(), top_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["left-to-right", "right-to-left"]).optional() }).optional(), bottom_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["left-to-right", "right-to-left"]).optional() }).optional() });
var sy = pa.union([iy, ry]);
var ay = pa.object({ type: pa.literal("schematic_component"), size: Eg, center: Tg, source_component_id: pa.string().optional(), schematic_component_id: pa.string(), schematic_symbol_id: pa.string().optional(), pin_spacing: xg.optional(), pin_styles: oy.optional(), box_width: xg.optional(), symbol_name: pa.string().optional(), port_arrangement: sy.optional(), port_labels: pa.record(pa.string()).optional(), symbol_display_value: pa.string().optional(), subcircuit_id: pa.string().optional(), schematic_group_id: pa.string().optional(), is_schematic_group: pa.boolean().optional(), source_group_id: pa.string().optional(), is_box_with_pins: pa.boolean().optional().default(true) });
var cy = pa.object({ kicad_symbol: Zg.optional() }).catchall(pa.unknown());
var ly = pa.object({ type: pa.literal("schematic_symbol"), schematic_symbol_id: pa.string(), name: pa.string().optional(), metadata: cy.optional() }).describe("Defines a named schematic symbol that can be referenced by components.");
var hy = pa.object({ type: pa.literal("schematic_line"), schematic_line_id: Ag("schematic_line"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), x1: Ig, y1: Ig, x2: Ig, y2: Ig, stroke_width: Ig.nullable().optional(), color: pa.string().default("#000000"), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled line on the schematic");
var dy = pa.object({ type: pa.literal("schematic_rect"), schematic_rect_id: Ag("schematic_rect"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), center: Tg, width: Ig, height: Ig, rotation: Ng.default(0), stroke_width: Ig.nullable().optional(), color: pa.string().default("#000000"), is_filled: pa.boolean().default(false), fill_color: pa.string().optional(), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled rectangle on the schematic");
var uy = pa.object({ type: pa.literal("schematic_circle"), schematic_circle_id: Ag("schematic_circle"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), center: Tg, radius: Ig, stroke_width: Ig.nullable().optional(), color: pa.string().default("#000000"), is_filled: pa.boolean().default(false), fill_color: pa.string().optional(), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled circle on the schematic");
var py = pa.object({ type: pa.literal("schematic_arc"), schematic_arc_id: Ag("schematic_arc"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), center: Tg, radius: Ig, start_angle_degrees: Ng, end_angle_degrees: Ng, direction: pa.enum(["clockwise", "counterclockwise"]).default("counterclockwise"), stroke_width: Ig.nullable().optional(), color: pa.string().default("#000000"), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled arc on the schematic");
var my = pa.object({ type: pa.literal("schematic_trace"), schematic_trace_id: pa.string(), source_trace_id: pa.string().optional(), junctions: pa.array(pa.object({ x: pa.number(), y: pa.number() })), edges: pa.array(pa.object({ from: pa.object({ x: pa.number(), y: pa.number() }), to: pa.object({ x: pa.number(), y: pa.number() }), is_crossing: pa.boolean().optional(), from_schematic_port_id: pa.string().optional(), to_schematic_port_id: pa.string().optional() })), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional() });
var gy = pa.enum(["center", "left", "right", "top", "bottom"]);
var fy = pa.object({ type: pa.literal("schematic_text"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), schematic_text_id: pa.string(), text: pa.string(), font_size: pa.number().default(0.18), position: pa.object({ x: Ig, y: Ig }), rotation: pa.number().default(0), anchor: pa.union([gy.describe("legacy"), Og]).default("center"), color: pa.string().default("#000000"), subcircuit_id: pa.string().optional() });
var yy = pa.object({ type: pa.literal("schematic_port"), schematic_port_id: pa.string(), source_port_id: pa.string(), schematic_component_id: pa.string().optional(), center: Tg, facing_direction: pa.enum(["up", "down", "left", "right"]).optional(), distance_from_component_edge: pa.number().optional(), side_of_component: pa.enum(["top", "bottom", "left", "right"]).optional(), true_ccw_index: pa.number().optional(), pin_number: pa.number().optional(), display_pin_label: pa.string().optional(), subcircuit_id: pa.string().optional(), is_connected: pa.boolean().optional(), has_input_arrow: pa.boolean().optional(), has_output_arrow: pa.boolean().optional(), is_drawn_with_inversion_circle: pa.boolean().optional() }).describe("Defines a port on a schematic component");
var _y = pa.object({ type: pa.literal("schematic_net_label"), schematic_net_label_id: Ag("schematic_net_label"), schematic_trace_id: pa.string().optional(), source_trace_id: pa.string().optional(), source_net_id: pa.string(), center: Tg, anchor_position: Tg.optional(), anchor_side: pa.enum(["top", "bottom", "left", "right"]), text: pa.string(), symbol_name: pa.string().optional(), is_movable: pa.boolean().optional(), subcircuit_id: pa.string().optional() });
var by = qg.extend({ type: pa.literal("schematic_error"), schematic_error_id: pa.string(), error_type: pa.literal("schematic_port_not_found").default("schematic_port_not_found"), subcircuit_id: pa.string().optional() }).describe("Defines a schematic error on the schematic");
var xy = qg.extend({ type: pa.literal("schematic_layout_error"), schematic_layout_error_id: Ag("schematic_layout_error"), error_type: pa.literal("schematic_layout_error").default("schematic_layout_error"), source_group_id: pa.string(), schematic_group_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Error emitted when schematic layout fails for a group");
var vy = pa.object({ type: pa.literal("schematic_debug_object"), label: pa.string().optional(), subcircuit_id: pa.string().optional() });
var Iy = vy.extend({ shape: pa.literal("rect"), center: Tg, size: Eg });
var Sy = vy.extend({ shape: pa.literal("line"), start: Tg, end: Tg });
var Cy = vy.extend({ shape: pa.literal("point"), center: Tg });
var Py = pa.discriminatedUnion("shape", [Iy, Sy, Cy]);
var My = pa.object({ type: pa.literal("schematic_voltage_probe"), schematic_voltage_probe_id: pa.string(), source_component_id: pa.string().optional(), name: pa.string().optional(), position: Tg, schematic_trace_id: pa.string(), voltage: bg.optional(), subcircuit_id: pa.string().optional(), color: pa.string().optional(), label_alignment: Og.optional() }).describe("Defines a voltage probe measurement point on a schematic trace");
var Ny = pa.object({ type: pa.literal("schematic_manual_edit_conflict_warning"), schematic_manual_edit_conflict_warning_id: Ag("schematic_manual_edit_conflict_warning"), warning_type: pa.literal("schematic_manual_edit_conflict_warning").default("schematic_manual_edit_conflict_warning"), message: pa.string(), schematic_component_id: pa.string(), schematic_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), source_component_id: pa.string() }).describe("Warning emitted when a component has both manual placement and explicit schX/schY coordinates");
var wy = pa.object({ type: pa.literal("schematic_group"), schematic_group_id: Ag("schematic_group"), source_group_id: pa.string(), is_subcircuit: pa.boolean().optional(), subcircuit_id: pa.string().optional(), width: xg, height: xg, center: Tg, schematic_component_ids: pa.array(pa.string()), show_as_schematic_box: pa.boolean().optional(), name: pa.string().optional(), description: pa.string().optional() }).describe("Defines a group of components on the schematic");
var Ty = pa.object({ type: pa.literal("schematic_table"), schematic_table_id: Ag("schematic_table"), anchor_position: Tg, column_widths: pa.array(Ig), row_heights: pa.array(Ig), cell_padding: Ig.optional(), border_width: Ig.optional(), subcircuit_id: pa.string().optional(), schematic_component_id: pa.string().optional(), anchor: Og.optional() }).describe("Defines a table on the schematic");
var Ry = pa.object({ type: pa.literal("schematic_table_cell"), schematic_table_cell_id: Ag("schematic_table_cell"), schematic_table_id: pa.string(), start_row_index: pa.number(), end_row_index: pa.number(), start_column_index: pa.number(), end_column_index: pa.number(), text: pa.string().optional(), center: Tg, width: Ig, height: Ig, horizontal_align: pa.enum(["left", "center", "right"]).optional(), vertical_align: pa.enum(["top", "middle", "bottom"]).optional(), font_size: Ig.optional(), subcircuit_id: pa.string().optional() }).describe("Defines a cell within a schematic_table");
var Ey = pa.object({ type: pa.literal("schematic_sheet"), schematic_sheet_id: Ag("schematic_sheet"), name: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Defines a schematic sheet or page that components can be placed on");
var Ay = pa.object({ x: Ig, y: Ig, bulge: pa.number().optional() });
var Oy = pa.object({ vertices: pa.array(Ay) });
var ky = pa.object({ outer_ring: Oy, inner_rings: pa.array(Oy).default([]) });
var Dy = pa.object({ x: Ig, y: Ig, via: pa.boolean().optional(), via_to_layer: Gf.optional() });
var Ly = (pa.array(Dy), pa.object({ x: Ig, y: Ig, via: pa.boolean().optional(), to_layer: Gf.optional(), trace_width: Ig.optional() }));
var zy = pa.object({ min_trace_width: xg.optional(), min_board_edge_clearance: xg.optional(), min_via_hole_edge_to_via_hole_edge_clearance: xg.optional(), min_plated_hole_drill_edge_to_drill_edge_clearance: xg.optional(), min_trace_to_pad_edge_clearance: xg.optional(), min_pad_edge_to_pad_edge_clearance: xg.optional(), min_same_net_trace_edge_to_trace_edge_clearance: xg.optional(), min_different_net_trace_edge_to_trace_edge_clearance: xg.optional(), min_via_hole_diameter: xg.optional(), min_via_pad_diameter: xg.optional() });
var By = pa.object({ type: pa.literal("pcb_component"), pcb_component_id: Ag("pcb_component"), source_component_id: pa.string(), center: Tg, layer: Gf, rotation: Ng, display_offset_x: pa.string().optional().describe("How to display the x offset for this part, usually corresponding with how the user specified it"), display_offset_y: pa.string().optional().describe("How to display the y offset for this part, usually corresponding with how the user specified it"), width: xg, height: xg, do_not_place: pa.boolean().optional(), is_allowed_to_be_off_board: pa.boolean().optional(), subcircuit_id: pa.string().optional(), pcb_group_id: pa.string().optional(), position_mode: pa.enum(["packed", "relative_to_group_anchor", "relative_to_another_component", "none"]).optional(), anchor_position: Tg.optional(), anchor_alignment: Og.optional(), positioned_relative_to_pcb_group_id: pa.string().optional(), positioned_relative_to_pcb_board_id: pa.string().optional(), cable_insertion_center: Tg.optional(), insertion_direction: pa.enum(["from_above", "from_left", "from_right", "from_front", "from_back"]).optional(), metadata: pa.object({ kicad_footprint: Xg.optional() }).optional(), obstructs_within_bounds: pa.boolean().default(true).describe("Does this component take up all the space within its bounds on a layer. This is generally true except for when separated pin headers are being represented by a single component (in which case, chips can be placed between the pin headers) or for tall modules where chips fit underneath") }).describe("Defines a component on the PCB");
var Fy = pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: Ag("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("circle"), hole_diameter: pa.number(), x: Ig, y: Ig, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var jy = (Fy.describe("Defines a circular hole on the PCB"), pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: Ag("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("rect"), hole_width: pa.number(), hole_height: pa.number(), x: Ig, y: Ig, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() }));
var $y = (jy.describe("Defines a rectangular (square-capable) hole on the PCB. Use equal width/height for square."), pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: Ag("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.enum(["circle", "square"]), hole_diameter: pa.number(), x: Ig, y: Ig, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() }));
var Yy = ($y.describe("Defines a circular or square hole on the PCB"), pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: Ag("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("oval"), hole_width: pa.number(), hole_height: pa.number(), x: Ig, y: Ig, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() }));
var Xy = (Yy.describe("Defines an oval hole on the PCB"), pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: Ag("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("pill"), hole_width: pa.number(), hole_height: pa.number(), x: Ig, y: Ig, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() }));
var Wy = (Xy.describe("Defines a pill-shaped hole on the PCB"), pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: Ag("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("rotated_pill"), hole_width: pa.number(), hole_height: pa.number(), x: Ig, y: Ig, ccw_rotation: Ng, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() }));
var Vy = (Wy.describe("Defines a rotated pill-shaped hole on the PCB"), $y.or(Yy).or(Xy).or(Wy).or(Fy).or(jy));
var Hy = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("circle"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), outer_diameter: pa.number(), hole_diameter: pa.number(), is_covered_with_solder_mask: pa.boolean().optional(), x: Ig, y: Ig, layers: pa.array(Gf), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: Ag("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var Gy = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.enum(["oval", "pill"]), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), outer_width: pa.number(), outer_height: pa.number(), hole_width: pa.number(), hole_height: pa.number(), is_covered_with_solder_mask: pa.boolean().optional(), x: Ig, y: Ig, ccw_rotation: Ng, layers: pa.array(Gf), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: Ag("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var Uy = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("circular_hole_with_rect_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.literal("circle"), pad_shape: pa.literal("rect"), hole_diameter: pa.number(), rect_pad_width: pa.number(), rect_pad_height: pa.number(), rect_border_radius: pa.number().optional(), hole_offset_x: Ig.default(0), hole_offset_y: Ig.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: Ig, y: Ig, layers: pa.array(Gf), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: Ag("pcb_plated_hole"), soldermask_margin: pa.number().optional(), rect_ccw_rotation: Ng.optional() });
var Zy = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("pill_hole_with_rect_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.literal("pill"), pad_shape: pa.literal("rect"), hole_width: pa.number(), hole_height: pa.number(), rect_pad_width: pa.number(), rect_pad_height: pa.number(), rect_border_radius: pa.number().optional(), hole_offset_x: Ig.default(0), hole_offset_y: Ig.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: Ig, y: Ig, layers: pa.array(Gf), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: Ag("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var qy = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("rotated_pill_hole_with_rect_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.literal("rotated_pill"), pad_shape: pa.literal("rect"), hole_width: pa.number(), hole_height: pa.number(), hole_ccw_rotation: Ng, rect_pad_width: pa.number(), rect_pad_height: pa.number(), rect_border_radius: pa.number().optional(), rect_ccw_rotation: Ng, hole_offset_x: Ig.default(0), hole_offset_y: Ig.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: Ig, y: Ig, layers: pa.array(Gf), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: Ag("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var Jy = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("hole_with_polygon_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.enum(["circle", "oval", "pill", "rotated_pill"]), hole_diameter: pa.number().optional(), hole_width: pa.number().optional(), hole_height: pa.number().optional(), pad_outline: pa.array(pa.object({ x: Ig, y: Ig })).min(3), hole_offset_x: Ig.default(0), hole_offset_y: Ig.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: Ig, y: Ig, layers: pa.array(Gf), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: Ag("pcb_plated_hole"), soldermask_margin: pa.number().optional(), ccw_rotation: Ng.optional() });
var Qy = pa.union([Hy, Gy, Uy, Zy, qy, Jy]);
var Ky = pa.object({ type: pa.literal("pcb_port"), pcb_port_id: Ag("pcb_port"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), source_port_id: pa.string(), pcb_component_id: pa.string().optional(), x: Ig, y: Ig, layers: pa.array(Gf), is_board_pinout: pa.boolean().optional() }).describe("Defines a port on the PCB");
var t_ = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("circle"), pcb_smtpad_id: Ag("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ig, y: Ig, radius: pa.number(), layer: Gf, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var e_ = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("rect"), pcb_smtpad_id: Ag("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ig, y: Ig, width: pa.number(), height: pa.number(), rect_border_radius: pa.number().optional(), corner_radius: pa.number().optional(), layer: Gf, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional(), soldermask_margin_left: pa.number().optional(), soldermask_margin_top: pa.number().optional(), soldermask_margin_right: pa.number().optional(), soldermask_margin_bottom: pa.number().optional() });
var n_ = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("rotated_rect"), pcb_smtpad_id: Ag("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ig, y: Ig, width: pa.number(), height: pa.number(), rect_border_radius: pa.number().optional(), corner_radius: pa.number().optional(), ccw_rotation: Ng, layer: Gf, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional(), soldermask_margin_left: pa.number().optional(), soldermask_margin_top: pa.number().optional(), soldermask_margin_right: pa.number().optional(), soldermask_margin_bottom: pa.number().optional() });
var o_ = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("pill"), pcb_smtpad_id: Ag("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ig, y: Ig, width: pa.number(), height: pa.number(), radius: pa.number(), layer: Gf, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var i_ = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("rotated_pill"), pcb_smtpad_id: Ag("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ig, y: Ig, width: pa.number(), height: pa.number(), radius: pa.number(), ccw_rotation: Ng, layer: Gf, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var r_ = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("polygon"), pcb_smtpad_id: Ag("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), points: pa.array(Tg), layer: Gf, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var s_ = pa.discriminatedUnion("shape", [t_, e_, n_, i_, o_, r_]).describe("Defines an SMT pad on the PCB");
var a_ = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("circle"), pcb_solder_paste_id: Ag("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ig, y: Ig, radius: pa.number(), layer: Gf, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var c_ = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("rect"), pcb_solder_paste_id: Ag("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ig, y: Ig, width: pa.number(), height: pa.number(), layer: Gf, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var l_ = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("pill"), pcb_solder_paste_id: Ag("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ig, y: Ig, width: pa.number(), height: pa.number(), radius: pa.number(), layer: Gf, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var h_ = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("rotated_rect"), pcb_solder_paste_id: Ag("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ig, y: Ig, width: pa.number(), height: pa.number(), ccw_rotation: Ig, layer: Gf, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var d_ = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("oval"), pcb_solder_paste_id: Ag("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: Ig, y: Ig, width: pa.number(), height: pa.number(), layer: Gf, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var u_ = pa.union([a_, c_, l_, h_, d_]).describe("Defines solderpaste on the PCB");
var p_ = pa.object({ type: pa.literal("pcb_text"), pcb_text_id: Ag("pcb_text"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), text: pa.string(), center: Tg, layer: Gf, width: xg, height: xg, lines: pa.number(), align: pa.enum(["bottom-left"]) }).describe("Defines text on the PCB");
var m_ = pa.object({ route_type: pa.literal("wire"), x: Ig, y: Ig, width: Ig, copper_pour_id: pa.string().optional(), is_inside_copper_pour: pa.boolean().optional(), start_pcb_port_id: pa.string().optional(), end_pcb_port_id: pa.string().optional(), layer: Gf });
var g_ = pa.object({ route_type: pa.literal("via"), x: Ig, y: Ig, copper_pour_id: pa.string().optional(), is_inside_copper_pour: pa.boolean().optional(), hole_diameter: Ig.optional(), outer_diameter: Ig.optional(), from_layer: Gf, to_layer: Gf });
var f_ = pa.union([m_, g_]);
var y_ = pa.object({ type: pa.literal("pcb_trace"), source_trace_id: pa.string().optional(), pcb_component_id: pa.string().optional(), pcb_trace_id: Ag("pcb_trace"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), route_thickness_mode: pa.enum(["constant", "interpolated"]).default("constant").optional(), route_order_index: pa.number().optional(), should_round_corners: pa.boolean().optional(), trace_length: pa.number().optional(), highlight_color: pa.string().optional(), route: pa.array(f_) }).describe("Defines a trace on the PCB");
var __ = pa.object({ type: pa.literal("pcb_trace_warning"), pcb_trace_warning_id: Ag("pcb_trace_warning"), warning_type: pa.literal("pcb_trace_warning").default("pcb_trace_warning"), message: pa.string(), center: Tg.optional(), pcb_trace_id: pa.string(), source_trace_id: pa.string(), pcb_component_ids: pa.array(pa.string()), pcb_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines a trace warning on the PCB");
var b_ = qg.extend({ type: pa.literal("pcb_trace_error"), pcb_trace_error_id: Ag("pcb_trace_error"), error_type: pa.literal("pcb_trace_error").default("pcb_trace_error"), center: Tg.optional(), pcb_trace_id: pa.string(), source_trace_id: pa.string(), pcb_component_ids: pa.array(pa.string()), pcb_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines a trace error on the PCB");
var x_ = qg.extend({ type: pa.literal("pcb_trace_missing_error"), pcb_trace_missing_error_id: Ag("pcb_trace_missing_error"), error_type: pa.literal("pcb_trace_missing_error").default("pcb_trace_missing_error"), center: Tg.optional(), source_trace_id: pa.string(), pcb_component_ids: pa.array(pa.string()), pcb_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines an error when a source trace has no corresponding PCB trace");
var v_ = qg.extend({ type: pa.literal("pcb_port_not_matched_error"), pcb_error_id: Ag("pcb_error"), error_type: pa.literal("pcb_port_not_matched_error").default("pcb_port_not_matched_error"), pcb_component_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines a trace error on the PCB where a port is not matched");
var I_ = qg.extend({ type: pa.literal("pcb_port_not_connected_error"), pcb_port_not_connected_error_id: Ag("pcb_port_not_connected_error"), error_type: pa.literal("pcb_port_not_connected_error").default("pcb_port_not_connected_error"), pcb_port_ids: pa.array(pa.string()), pcb_component_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines an error when a pcb port is not connected to any trace");
var S_ = pa.object({ type: pa.literal("pcb_net"), pcb_net_id: Ag("pcb_net"), source_net_id: pa.string().optional(), highlight_color: pa.string().optional() }).describe("Defines a net on the PCB");
var C_ = pa.object({ type: pa.literal("pcb_via"), pcb_via_id: Ag("pcb_via"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional(), x: Ig, y: Ig, outer_diameter: Ig.default("0.6mm"), hole_diameter: Ig.default("0.25mm"), from_layer: Gf.optional(), to_layer: Gf.optional(), layers: pa.array(Gf), pcb_trace_id: pa.string().optional(), net_is_assignable: pa.boolean().optional(), net_assigned: pa.boolean().optional(), is_tented: pa.boolean().optional() }).describe("Defines a via on the PCB");
var P_ = pa.object({ type: pa.literal("pcb_board"), pcb_board_id: Ag("pcb_board"), pcb_panel_id: pa.string().optional(), carrier_pcb_board_id: pa.string().optional(), is_subcircuit: pa.boolean().optional(), subcircuit_id: pa.string().optional(), is_mounted_to_carrier_board: pa.boolean().optional(), width: xg.optional(), height: xg.optional(), center: Tg, display_offset_x: pa.string().optional().describe("How to display the x offset for this board, usually corresponding with how the user specified it"), display_offset_y: pa.string().optional().describe("How to display the y offset for this board, usually corresponding with how the user specified it"), thickness: xg.optional().default(1.4), num_layers: pa.number().optional().default(4), outline: pa.array(Tg).optional(), shape: pa.enum(["rect", "polygon"]).optional(), material: pa.enum(["fr4", "fr1"]).default("fr4"), anchor_position: Tg.optional(), anchor_alignment: Og.optional(), position_mode: pa.enum(["relative_to_panel_anchor", "none"]).optional() }).merge(zy).describe("Defines the board outline of the PCB");
var M_ = pa.object({ type: pa.literal("pcb_panel"), pcb_panel_id: Ag("pcb_panel"), width: xg, height: xg, center: Tg, thickness: xg.optional().default(1.4), covered_with_solder_mask: pa.boolean().optional().default(true) }).describe("Defines a PCB panel that can contain multiple boards");
var N_ = qg.extend({ type: pa.literal("pcb_placement_error"), pcb_placement_error_id: Ag("pcb_placement_error"), error_type: pa.literal("pcb_placement_error").default("pcb_placement_error"), subcircuit_id: pa.string().optional() }).describe("Defines a placement error on the PCB");
var w_ = qg.extend({ type: pa.literal("pcb_panelization_placement_error"), pcb_panelization_placement_error_id: Ag("pcb_panelization_placement_error"), error_type: pa.literal("pcb_panelization_placement_error").default("pcb_panelization_placement_error"), pcb_panel_id: pa.string().optional(), pcb_board_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Defines a panelization placement error on the PCB");
var T_ = pa.object({ type: pa.literal("pcb_trace_hint"), pcb_trace_hint_id: Ag("pcb_trace_hint"), pcb_port_id: pa.string(), pcb_component_id: pa.string(), route: pa.array(Ly), subcircuit_id: pa.string().optional() }).describe("A hint that can be used during generation of a PCB trace");
var R_ = pa.object({ type: pa.literal("pcb_silkscreen_line"), pcb_silkscreen_line_id: Ag("pcb_silkscreen_line"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), stroke_width: Ig.default("0.1mm"), x1: Ig, y1: Ig, x2: Ig, y2: Ig, layer: Uf }).describe("Defines a silkscreen line on the PCB");
var E_ = pa.object({ type: pa.literal("pcb_silkscreen_path"), pcb_silkscreen_path_id: Ag("pcb_silkscreen_path"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Uf, route: pa.array(Tg), stroke_width: xg }).describe("Defines a silkscreen path on the PCB");
var A_ = pa.object({ type: pa.literal("pcb_silkscreen_text"), pcb_silkscreen_text_id: Ag("pcb_silkscreen_text"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: Ig.default("0.2mm"), pcb_component_id: pa.string(), text: pa.string(), is_knockout: pa.boolean().default(false).optional(), knockout_padding: pa.object({ left: xg, top: xg, bottom: xg, right: xg }).default({ left: "0.2mm", top: "0.2mm", bottom: "0.2mm", right: "0.2mm" }).optional(), ccw_rotation: pa.number().optional(), layer: Gf, is_mirrored: pa.boolean().default(false).optional(), anchor_position: Tg.default({ x: 0, y: 0 }), anchor_alignment: Og.default("center") }).describe("Defines silkscreen text on the PCB");
var O_ = pa.object({ type: pa.literal("pcb_copper_text"), pcb_copper_text_id: Ag("pcb_copper_text"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: Ig.default("0.2mm"), pcb_component_id: pa.string(), text: pa.string(), is_knockout: pa.boolean().default(false).optional(), knockout_padding: pa.object({ left: xg, top: xg, bottom: xg, right: xg }).default({ left: "0.2mm", top: "0.2mm", bottom: "0.2mm", right: "0.2mm" }).optional(), ccw_rotation: pa.number().optional(), layer: Gf, is_mirrored: pa.boolean().default(false).optional(), anchor_position: Tg.default({ x: 0, y: 0 }), anchor_alignment: Og.default("center") }).describe("Defines copper text on the PCB");
var k_ = pa.object({ type: pa.literal("pcb_silkscreen_rect"), pcb_silkscreen_rect_id: Ag("pcb_silkscreen_rect"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: Tg, width: xg, height: xg, layer: Gf, stroke_width: xg.default("1mm"), corner_radius: xg.optional(), is_filled: pa.boolean().default(true).optional(), has_stroke: pa.boolean().optional(), is_stroke_dashed: pa.boolean().optional(), ccw_rotation: pa.number().optional() }).describe("Defines a silkscreen rect on the PCB");
var D_ = pa.object({ type: pa.literal("pcb_silkscreen_circle"), pcb_silkscreen_circle_id: Ag("pcb_silkscreen_circle"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: Tg, radius: xg, layer: Uf, stroke_width: xg.default("1mm"), is_filled: pa.boolean().optional() }).describe("Defines a silkscreen circle on the PCB");
var L_ = pa.object({ type: pa.literal("pcb_silkscreen_oval"), pcb_silkscreen_oval_id: Ag("pcb_silkscreen_oval"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: Tg, radius_x: Ig, radius_y: Ig, layer: Uf, ccw_rotation: Ng.optional() }).describe("Defines a silkscreen oval on the PCB");
var z_ = pa.object({ type: pa.literal("pcb_silkscreen_pill"), pcb_silkscreen_pill_id: Ag("pcb_silkscreen_pill"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: Tg, width: xg, height: xg, layer: Gf, ccw_rotation: pa.number().optional() }).describe("Defines a silkscreen pill on the PCB");
var B_ = pa.object({ type: pa.literal("pcb_fabrication_note_text"), pcb_fabrication_note_text_id: Ag("pcb_fabrication_note_text"), subcircuit_id: pa.string().optional(), pcb_group_id: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: Ig.default("1mm"), pcb_component_id: pa.string(), text: pa.string(), layer: Uf, anchor_position: Tg.default({ x: 0, y: 0 }), anchor_alignment: pa.enum(["center", "top_left", "top_right", "bottom_left", "bottom_right"]).default("center"), color: pa.string().optional() }).describe("Defines a fabrication note in text on the PCB, useful for leaving notes for assemblers or fabricators");
var F_ = pa.object({ type: pa.literal("pcb_fabrication_note_path"), pcb_fabrication_note_path_id: Ag("pcb_fabrication_note_path"), pcb_component_id: pa.string(), subcircuit_id: pa.string().optional(), layer: Gf, route: pa.array(Tg), stroke_width: xg, color: pa.string().optional() }).describe("Defines a fabrication path on the PCB for fabricators or assemblers");
var j_ = pa.object({ type: pa.literal("pcb_fabrication_note_rect"), pcb_fabrication_note_rect_id: Ag("pcb_fabrication_note_rect"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: Tg, width: xg, height: xg, layer: Uf, stroke_width: xg.default("0.1mm"), corner_radius: xg.optional(), is_filled: pa.boolean().optional(), has_stroke: pa.boolean().optional(), is_stroke_dashed: pa.boolean().optional(), color: pa.string().optional() }).describe("Defines a fabrication note rectangle on the PCB");
var $_ = pa.object({ type: pa.literal("pcb_fabrication_note_dimension"), pcb_fabrication_note_dimension_id: Ag("pcb_fabrication_note_dimension"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Uf, from: Tg, to: Tg, text: pa.string().optional(), text_ccw_rotation: pa.number().optional(), offset: xg.optional(), offset_distance: xg.optional(), offset_direction: pa.object({ x: pa.number(), y: pa.number() }).optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: xg.default("1mm"), color: pa.string().optional(), arrow_size: xg.default("1mm") }).describe("Defines a measurement annotation within PCB fabrication notes");
var Y_ = pa.object({ type: pa.literal("pcb_note_text"), pcb_note_text_id: Ag("pcb_note_text"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: Ig.default("1mm"), text: pa.string().optional(), anchor_position: Tg.default({ x: 0, y: 0 }), anchor_alignment: pa.enum(["center", "top_left", "top_right", "bottom_left", "bottom_right"]).default("center"), layer: Uf.default("top"), is_mirrored_from_top_view: pa.boolean().optional(), color: pa.string().optional() }).describe("Defines a documentation note in text on the PCB");
var X_ = pa.object({ type: pa.literal("pcb_note_rect"), pcb_note_rect_id: Ag("pcb_note_rect"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), text: pa.string().optional(), center: Tg, width: xg, height: xg, layer: Uf.default("top"), stroke_width: xg.default("0.1mm"), corner_radius: xg.optional(), is_filled: pa.boolean().optional(), has_stroke: pa.boolean().optional(), is_stroke_dashed: pa.boolean().optional(), color: pa.string().optional() }).describe("Defines a rectangular documentation note on the PCB");
var W_ = pa.object({ type: pa.literal("pcb_note_path"), pcb_note_path_id: Ag("pcb_note_path"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), text: pa.string().optional(), route: pa.array(Tg), layer: Uf.default("top"), stroke_width: xg.default("0.1mm"), color: pa.string().optional() }).describe("Defines a polyline documentation note on the PCB");
var V_ = pa.object({ type: pa.literal("pcb_note_line"), pcb_note_line_id: Ag("pcb_note_line"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), text: pa.string().optional(), x1: Ig, y1: Ig, x2: Ig, y2: Ig, layer: Uf.default("top"), stroke_width: Ig.default("0.1mm"), color: pa.string().optional(), is_dashed: pa.boolean().optional() }).describe("Defines a straight documentation note line on the PCB");
var H_ = pa.object({ type: pa.literal("pcb_note_dimension"), pcb_note_dimension_id: Ag("pcb_note_dimension"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), from: Tg, to: Tg, text: pa.string().optional(), text_ccw_rotation: pa.number().optional(), offset_distance: xg.optional(), offset_direction: pa.object({ x: pa.number(), y: pa.number() }).optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: xg.default("1mm"), layer: Uf.default("top"), color: pa.string().optional(), arrow_size: xg.default("1mm") }).describe("Defines a measurement annotation within PCB documentation notes");
var G_ = qg.extend({ type: pa.literal("pcb_footprint_overlap_error"), pcb_error_id: Ag("pcb_error"), error_type: pa.literal("pcb_footprint_overlap_error").default("pcb_footprint_overlap_error"), pcb_smtpad_ids: pa.array(pa.string()).optional(), pcb_plated_hole_ids: pa.array(pa.string()).optional(), pcb_hole_ids: pa.array(pa.string()).optional(), pcb_keepout_ids: pa.array(pa.string()).optional() }).describe("Error emitted when a pcb footprint overlaps with another element");
var U_ = qg.extend({ type: pa.literal("pcb_courtyard_overlap_error"), pcb_error_id: Ag("pcb_error"), error_type: pa.literal("pcb_courtyard_overlap_error").default("pcb_courtyard_overlap_error"), pcb_component_ids: pa.tuple([pa.string(), pa.string()]) }).describe("Error emitted when the courtyard (CrtYd) of one PCB component overlaps with the courtyard of another");
var Z_ = pa.object({ type: pa.literal("pcb_keepout"), shape: pa.literal("rect"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: Tg, width: Ig, height: Ig, pcb_keepout_id: pa.string(), layers: pa.array(pa.string()), description: pa.string().optional() }).or(pa.object({ type: pa.literal("pcb_keepout"), shape: pa.literal("circle"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: Tg, radius: Ig, pcb_keepout_id: pa.string(), layers: pa.array(pa.string()), description: pa.string().optional() }));
var q_ = pa.object({ type: pa.literal("pcb_cutout"), pcb_cutout_id: Ag("pcb_cutout"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_board_id: pa.string().optional(), pcb_panel_id: pa.string().optional() });
var J_ = q_.extend({ shape: pa.literal("rect"), center: Tg, width: xg, height: xg, rotation: Ng.optional(), corner_radius: xg.optional() });
var Q_ = q_.extend({ shape: pa.literal("circle"), center: Tg, radius: xg });
var K_ = q_.extend({ shape: pa.literal("polygon"), points: pa.array(Tg) });
var tb = q_.extend({ shape: pa.literal("path"), route: pa.array(Tg), slot_width: xg, slot_length: xg.optional(), space_between_slots: xg.optional(), slot_corner_radius: xg.optional() });
var eb = pa.discriminatedUnion("shape", [J_, Q_, K_, tb]).describe("Defines a cutout on the PCB, removing board material.");
var nb = qg.extend({ type: pa.literal("pcb_missing_footprint_error"), pcb_missing_footprint_error_id: Ag("pcb_missing_footprint_error"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), error_type: pa.literal("pcb_missing_footprint_error").default("pcb_missing_footprint_error"), source_component_id: pa.string() }).describe("Defines a missing footprint error on the PCB");
var ob = qg.extend({ type: pa.literal("external_footprint_load_error"), external_footprint_load_error_id: Ag("external_footprint_load_error"), pcb_component_id: pa.string(), source_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), footprinter_string: pa.string().optional(), error_type: pa.literal("external_footprint_load_error").default("external_footprint_load_error") }).describe("Defines an error when an external footprint fails to load");
var ib = qg.extend({ type: pa.literal("circuit_json_footprint_load_error"), circuit_json_footprint_load_error_id: Ag("circuit_json_footprint_load_error"), pcb_component_id: pa.string(), source_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), error_type: pa.literal("circuit_json_footprint_load_error").default("circuit_json_footprint_load_error"), circuit_json: pa.array(pa.any()).optional() }).describe("Defines an error when a circuit JSON footprint fails to load");
var rb = pa.object({ type: pa.literal("pcb_group"), pcb_group_id: Ag("pcb_group"), source_group_id: pa.string(), is_subcircuit: pa.boolean().optional(), subcircuit_id: pa.string().optional(), width: xg.optional(), height: xg.optional(), center: Tg, display_offset_x: pa.string().optional().describe("How to display the x offset for this group, usually corresponding with how the user specified it"), display_offset_y: pa.string().optional().describe("How to display the y offset for this group, usually corresponding with how the user specified it"), outline: pa.array(Tg).optional(), anchor_position: Tg.optional(), anchor_alignment: Og.default("center"), position_mode: pa.enum(["packed", "relative_to_group_anchor", "none"]).optional(), positioned_relative_to_pcb_group_id: pa.string().optional(), positioned_relative_to_pcb_board_id: pa.string().optional(), pcb_component_ids: pa.array(pa.string()), child_layout_mode: pa.enum(["packed", "none"]).optional(), name: pa.string().optional(), description: pa.string().optional(), layout_mode: pa.string().optional(), autorouter_configuration: pa.object({ trace_clearance: xg }).optional(), autorouter_used_string: pa.string().optional() }).describe("Defines a group of components on the PCB");
var sb = qg.extend({ type: pa.literal("pcb_autorouting_error"), pcb_error_id: Ag("pcb_autorouting_error"), error_type: pa.literal("pcb_autorouting_error").default("pcb_autorouting_error"), subcircuit_id: pa.string().optional() }).describe("The autorouting has failed to route a portion of the board");
var ab = pa.object({ type: pa.literal("pcb_manual_edit_conflict_warning"), pcb_manual_edit_conflict_warning_id: Ag("pcb_manual_edit_conflict_warning"), warning_type: pa.literal("pcb_manual_edit_conflict_warning").default("pcb_manual_edit_conflict_warning"), message: pa.string(), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), source_component_id: pa.string() }).describe("Warning emitted when a component has both manual placement and explicit pcbX/pcbY coordinates");
var cb = pa.enum(["x-", "x+", "y+", "y-"]);
var lb = pa.object({ type: pa.literal("pcb_connector_not_in_accessible_orientation_warning"), pcb_connector_not_in_accessible_orientation_warning_id: Ag("pcb_connector_not_in_accessible_orientation_warning"), warning_type: pa.literal("pcb_connector_not_in_accessible_orientation_warning").default("pcb_connector_not_in_accessible_orientation_warning"), message: pa.string(), pcb_component_id: pa.string(), source_component_id: pa.string().optional(), pcb_board_id: pa.string().optional(), facing_direction: cb, recommended_facing_direction: cb, subcircuit_id: pa.string().optional() }).describe("Warning emitted when a connector PCB component is facing inward toward the board and should be reoriented to an outward-facing direction");
var hb = pa.object({ type: pa.literal("supplier_footprint_mismatch_warning"), supplier_footprint_mismatch_warning_id: Ag("supplier_footprint_mismatch_warning"), warning_type: pa.literal("supplier_footprint_mismatch_warning").default("supplier_footprint_mismatch_warning"), message: pa.string(), source_component_id: pa.string(), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), supplier_name: Jg.optional(), supplier_part_number: pa.string().optional(), supplier_footprint_url: pa.string().optional(), footprint_copper_intersection_over_union: pa.number() }).describe("Warning emitted when a supplier part footprint does not match the expected footprint");
var db = pa.object({ type: pa.literal("pcb_breakout_point"), pcb_breakout_point_id: Ag("pcb_breakout_point"), pcb_group_id: pa.string(), subcircuit_id: pa.string().optional(), source_trace_id: pa.string().optional(), source_port_id: pa.string().optional(), source_net_id: pa.string().optional(), x: Ig, y: Ig }).describe("Defines a routing target within a pcb_group for a source_trace or source_net");
var ub = pa.object({ type: pa.literal("pcb_ground_plane"), pcb_ground_plane_id: Ag("pcb_ground_plane"), source_pcb_ground_plane_id: pa.string(), source_net_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Defines a ground plane on the PCB");
var pb = pa.object({ type: pa.literal("pcb_ground_plane_region"), pcb_ground_plane_region_id: Ag("pcb_ground_plane_region"), pcb_ground_plane_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Gf, points: pa.array(Tg) }).describe("Defines a polygon region of a ground plane");
var mb = pa.object({ type: pa.literal("pcb_thermal_spoke"), pcb_thermal_spoke_id: Ag("pcb_thermal_spoke"), pcb_ground_plane_id: pa.string(), shape: pa.string(), spoke_count: pa.number(), spoke_thickness: Ig, spoke_inner_diameter: Ig, spoke_outer_diameter: Ig, pcb_plated_hole_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Pattern for connecting a ground plane to a plated hole");
var gb = pa.object({ type: pa.literal("pcb_copper_pour"), pcb_copper_pour_id: Ag("pcb_copper_pour"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Gf, source_net_id: pa.string().optional(), covered_with_solder_mask: pa.boolean().optional().default(true) });
var fb = gb.extend({ shape: pa.literal("rect"), center: Tg, width: xg, height: xg, rotation: Ng.optional() });
var yb = gb.extend({ shape: pa.literal("brep"), brep_shape: ky });
var _b = gb.extend({ shape: pa.literal("polygon"), points: pa.array(Tg) });
var bb = pa.discriminatedUnion("shape", [fb, yb, _b]).describe("Defines a copper pour on the PCB.");
var xb = qg.extend({ type: pa.literal("pcb_component_outside_board_error"), pcb_component_outside_board_error_id: Ag("pcb_component_outside_board_error"), error_type: pa.literal("pcb_component_outside_board_error").default("pcb_component_outside_board_error"), pcb_component_id: pa.string(), pcb_board_id: pa.string(), component_center: Tg, component_bounds: pa.object({ min_x: pa.number(), max_x: pa.number(), min_y: pa.number(), max_y: pa.number() }), subcircuit_id: pa.string().optional(), source_component_id: pa.string().optional() }).describe("Error emitted when a PCB component is placed outside the board boundaries");
var vb = qg.extend({ type: pa.literal("pcb_component_not_on_board_edge_error"), pcb_component_not_on_board_edge_error_id: Ag("pcb_component_not_on_board_edge_error"), error_type: pa.literal("pcb_component_not_on_board_edge_error").default("pcb_component_not_on_board_edge_error"), pcb_component_id: pa.string(), pcb_board_id: pa.string(), component_center: Tg, pad_to_nearest_board_edge_distance: pa.number(), source_component_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a component that must be placed on the board edge is centered away from the edge");
var Ib = qg.extend({ type: pa.literal("pcb_component_invalid_layer_error"), pcb_component_invalid_layer_error_id: Ag("pcb_component_invalid_layer_error"), error_type: pa.literal("pcb_component_invalid_layer_error").default("pcb_component_invalid_layer_error"), pcb_component_id: pa.string().optional(), source_component_id: pa.string(), layer: Gf, subcircuit_id: pa.string().optional() }).describe("Error emitted when a component is placed on an invalid layer (components can only be on 'top' or 'bottom' layers)");
var Sb = qg.extend({ type: pa.literal("pcb_via_clearance_error"), pcb_error_id: Ag("pcb_error"), error_type: pa.literal("pcb_via_clearance_error").default("pcb_via_clearance_error"), pcb_via_ids: pa.array(pa.string()).min(2), minimum_clearance: Ig.optional(), actual_clearance: Ig.optional(), pcb_center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when vias are closer than the allowed clearance");
var Cb = qg.extend({ type: pa.literal("pcb_via_trace_clearance_error"), pcb_via_trace_clearance_error_id: Ag("pcb_via_trace_clearance_error"), error_type: pa.literal("pcb_via_trace_clearance_error").default("pcb_via_trace_clearance_error"), pcb_via_id: pa.string(), pcb_trace_id: pa.string(), minimum_clearance: Ig.optional(), actual_clearance: Ig.optional(), center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a via and trace are closer than the allowed clearance");
var Pb = qg.extend({ type: pa.literal("pcb_pad_pad_clearance_error"), pcb_pad_pad_clearance_error_id: Ag("pcb_pad_pad_clearance_error"), error_type: pa.literal("pcb_pad_pad_clearance_error").default("pcb_pad_pad_clearance_error"), pcb_pad_ids: pa.array(pa.string()).min(2), minimum_clearance: Ig.optional(), actual_clearance: Ig.optional(), center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when pads are closer than the allowed clearance");
var Mb = qg.extend({ type: pa.literal("pcb_pad_trace_clearance_error"), pcb_pad_trace_clearance_error_id: Ag("pcb_pad_trace_clearance_error"), error_type: pa.literal("pcb_pad_trace_clearance_error").default("pcb_pad_trace_clearance_error"), pcb_pad_id: pa.string(), pcb_trace_id: pa.string(), minimum_clearance: Ig.optional(), actual_clearance: Ig.optional(), center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a pad and trace are closer than allowed clearance");
var Nb = pa.object({ type: pa.literal("pcb_courtyard_rect"), pcb_courtyard_rect_id: Ag("pcb_courtyard_rect"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: Tg, width: xg, height: xg, layer: Uf, ccw_rotation: Ng.optional(), color: pa.string().optional() }).describe("Defines a courtyard rectangle on the PCB");
var wb = pa.object({ type: pa.literal("pcb_courtyard_outline"), pcb_courtyard_outline_id: Ag("pcb_courtyard_outline"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Uf, outline: pa.array(Tg).min(2) }).describe("Defines a courtyard outline on the PCB");
var Tb = pa.object({ type: pa.literal("pcb_courtyard_polygon"), pcb_courtyard_polygon_id: Ag("pcb_courtyard_polygon"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: Uf, points: pa.array(Tg).min(3), color: pa.string().optional() }).describe("Defines a courtyard polygon on the PCB");
var Rb = pa.object({ type: pa.literal("pcb_courtyard_circle"), pcb_courtyard_circle_id: Ag("pcb_courtyard_circle"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: Tg, radius: xg, layer: Uf, color: pa.string().optional() }).describe("Defines a courtyard circle on the PCB");
var Eb = pa.object({ type: pa.literal("cad_component"), cad_component_id: pa.string(), pcb_component_id: pa.string(), source_component_id: pa.string(), position: Rg, rotation: Rg.optional(), size: Rg.optional(), layer: Gf.optional(), subcircuit_id: pa.string().optional(), footprinter_string: pa.string().optional(), model_obj_url: pa.string().optional(), model_stl_url: pa.string().optional(), model_3mf_url: pa.string().optional(), model_gltf_url: pa.string().optional(), model_glb_url: pa.string().optional(), model_step_url: pa.string().optional(), model_wrl_url: pa.string().optional(), model_asset: kg.optional(), model_unit_to_mm_scale_factor: pa.number().optional(), model_board_normal_direction: pa.enum(["x+", "x-", "y+", "y-", "z+", "z-"]).optional().describe(`The direction in the model's coordinate space that is considered "up" or "coming out of the board surface"`), model_origin_position: Rg.optional(), model_origin_alignment: pa.enum(["unknown", "center", "center_of_component_on_board_surface", "bottom_center_of_component"]).optional(), model_object_fit: pa.enum(["contain_within_bounds", "fill_bounds"]).optional().default("contain_within_bounds"), model_jscad: pa.any().optional(), show_as_translucent_model: pa.boolean().optional(), anchor_alignment: pa.enum(["center", "center_of_component_on_board_surface"]).optional().default("center") }).describe("Defines a component on the PCB");
var Ab = pa.enum(["sinewave", "square", "triangle", "sawtooth"]);
var Ob = pa.union([pa.string(), pa.number()]).transform((t19) => typeof t19 == "string" ? t19.endsWith("%") ? parseFloat(t19.slice(0, -1)) / 100 : parseFloat(t19) : t19).pipe(pa.number().min(0, "Duty cycle must be non-negative").max(1, "Duty cycle cannot be greater than 100%"));
var kb = pa.object({ type: pa.literal("simulation_voltage_source"), simulation_voltage_source_id: Ag("simulation_voltage_source"), is_dc_source: pa.literal(true).optional().default(true), positive_source_port_id: pa.string().optional(), negative_source_port_id: pa.string().optional(), positive_source_net_id: pa.string().optional(), negative_source_net_id: pa.string().optional(), voltage: bg }).describe("Defines a DC voltage source for simulation");
var Db = pa.object({ type: pa.literal("simulation_voltage_source"), simulation_voltage_source_id: Ag("simulation_voltage_source"), is_dc_source: pa.literal(false), terminal1_source_port_id: pa.string().optional(), terminal2_source_port_id: pa.string().optional(), terminal1_source_net_id: pa.string().optional(), terminal2_source_net_id: pa.string().optional(), voltage: bg.optional(), frequency: vg.optional(), peak_to_peak_voltage: bg.optional(), wave_shape: Ab.optional(), phase: Ng.optional(), duty_cycle: Ob.optional() }).describe("Defines an AC voltage source for simulation");
var Lb = pa.union([kb, Db]).describe("Defines a voltage source for simulation");
var zb = pa.union([pa.string(), pa.number()]).transform((t19) => typeof t19 == "string" ? t19.endsWith("%") ? parseFloat(t19.slice(0, -1)) / 100 : parseFloat(t19) : t19).pipe(pa.number().min(0, "Duty cycle must be non-negative").max(1, "Duty cycle cannot be greater than 100%"));
var Bb = pa.object({ type: pa.literal("simulation_current_source"), simulation_current_source_id: Ag("simulation_current_source"), is_dc_source: pa.literal(true).optional().default(true), positive_source_port_id: pa.string().optional(), negative_source_port_id: pa.string().optional(), positive_source_net_id: pa.string().optional(), negative_source_net_id: pa.string().optional(), current: Sg }).describe("Defines a DC current source for simulation");
var Fb = pa.object({ type: pa.literal("simulation_current_source"), simulation_current_source_id: Ag("simulation_current_source"), is_dc_source: pa.literal(false), terminal1_source_port_id: pa.string().optional(), terminal2_source_port_id: pa.string().optional(), terminal1_source_net_id: pa.string().optional(), terminal2_source_net_id: pa.string().optional(), current: Sg.optional(), frequency: vg.optional(), peak_to_peak_current: Sg.optional(), wave_shape: Ab.optional(), phase: Ng.optional(), duty_cycle: zb.optional() }).describe("Defines an AC current source for simulation");
var jb = pa.union([Bb, Fb]).describe("Defines a current source for simulation");
var $b = pa.union([pa.literal("spice_dc_sweep"), pa.literal("spice_dc_operating_point"), pa.literal("spice_transient_analysis"), pa.literal("spice_ac_analysis")]);
var Yb = pa.object({ type: pa.literal("simulation_experiment"), simulation_experiment_id: Ag("simulation_experiment"), name: pa.string(), experiment_type: $b, time_per_step: Cg.optional(), start_time_ms: Pg.optional(), end_time_ms: Pg.optional() }).describe("Defines a simulation experiment configuration");
var Xb = pa.object({ type: pa.literal("simulation_transient_voltage_graph"), simulation_transient_voltage_graph_id: Ag("simulation_transient_voltage_graph"), simulation_experiment_id: pa.string(), timestamps_ms: pa.array(pa.number()).optional(), voltage_levels: pa.array(pa.number()), source_component_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional(), time_per_step: Cg, start_time_ms: Pg, end_time_ms: Pg, name: pa.string().optional(), color: pa.string().optional() }).describe("Stores voltage measurements over time for a simulation");
var Wb = pa.object({ type: pa.literal("simulation_switch"), simulation_switch_id: Ag("simulation_switch"), source_component_id: pa.string().optional(), closes_at: Pg.optional(), opens_at: Pg.optional(), starts_closed: pa.boolean().optional(), switching_frequency: vg.optional() }).describe("Defines a switch for simulation timing control");
var Vb = pa.object({ type: pa.literal("simulation_voltage_probe"), simulation_voltage_probe_id: Ag("simulation_voltage_probe"), source_component_id: pa.string().optional(), name: pa.string().optional(), signal_input_source_port_id: pa.string().optional(), signal_input_source_net_id: pa.string().optional(), reference_input_source_port_id: pa.string().optional(), reference_input_source_net_id: pa.string().optional(), subcircuit_id: pa.string().optional(), color: pa.string().optional() }).describe("Defines a voltage probe for simulation. If a reference input is not provided, it measures against ground. If a reference input is provided, it measures the differential voltage between two points.").superRefine((t19, e2) => {
if (t19.reference_input_source_port_id || t19.reference_input_source_net_id) {
const n2 = !!t19.signal_input_source_port_id || !!t19.reference_input_source_port_id, o2 = !!t19.signal_input_source_net_id || !!t19.reference_input_source_net_id;
n2 && o2 ? e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Cannot mix port and net connections in a differential probe." }) : n2 ? t19.signal_input_source_port_id && t19.reference_input_source_port_id || e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Differential port probe requires both signal_input_source_port_id and reference_input_source_port_id." }) : o2 && (t19.signal_input_source_net_id && t19.reference_input_source_net_id || e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Differential net probe requires both signal_input_source_net_id and reference_input_source_net_id." }));
} else
!!t19.signal_input_source_port_id == !!t19.signal_input_source_net_id && e2.addIssue({ code: pa.ZodIssueCode.custom, message: "A voltage probe must have exactly one of signal_input_source_port_id or signal_input_source_net_id." });
});
var Hb = qg.extend({ type: pa.literal("simulation_unknown_experiment_error"), simulation_unknown_experiment_error_id: Ag("simulation_unknown_experiment_error"), error_type: pa.literal("simulation_unknown_experiment_error").default("simulation_unknown_experiment_error"), simulation_experiment_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("An unknown error occurred during the simulation experiment.");
var Gb = pa.object({ type: pa.literal("simulation_op_amp"), simulation_op_amp_id: Ag("simulation_op_amp"), source_component_id: pa.string().optional(), inverting_input_source_port_id: pa.string(), non_inverting_input_source_port_id: pa.string(), output_source_port_id: pa.string(), positive_supply_source_port_id: pa.string(), negative_supply_source_port_id: pa.string() }).describe("Defines a simple ideal operational amplifier for simulation");
var Ub = (pa.union([jf, Bf, Ff, zf, Yf, $f, sf, Kg, ef, of, tf, af, df, uf, ff, _f, bf, Cf, xf, vf, If, Sf, mf, pf, Vf, Zf, Xf, Pf, wf, Tf, Ef, Af, qf, Jf, Qf, Kf, ty, Df, Wf, By, Vy, nb, ob, ib, ab, lb, hb, Qy, Z_, Ky, S_, p_, y_, __, C_, s_, u_, P_, M_, rb, T_, R_, E_, A_, z_, O_, k_, D_, L_, b_, x_, N_, w_, v_, I_, Sb, Cb, Pb, Mb, F_, B_, j_, $_, Y_, X_, W_, V_, H_, sb, G_, U_, db, eb, ub, pb, mb, bb, xb, vb, Ib, Nb, wb, Tb, Rb, ey, fy, hy, dy, uy, py, ay, ly, yy, my, ny, by, xy, _y, Py, My, Ny, wy, Ey, Ty, Ry, Eb, Lb, jb, Yb, Xb, Wb, Vb, Hb, Gb]), true);
var Zb = { CCW: -1, CW: 1, NOT_ORIENTABLE: 0 };
var qb = 2 * Math.PI;
var Jb = Object.freeze({ __proto__: null, BOUNDARY: 2, CCW: Ub, CONTAINS: 3, CW: false, END_VERTEX: 2, INSIDE: 1, INTERLACE: 4, NOT_VERTEX: 0, ORIENTATION: Zb, OUTSIDE: 0, OVERLAP_OPPOSITE: 2, OVERLAP_SAME: 1, PIx2: qb, START_VERTEX: 1 });
var Qb = 0.000001;
function Kb(t19) {
Qb = t19;
}
function tx() {
return Qb;
}
function ex(t19) {
return t19 < Qb && t19 > -Qb;
}
function nx(t19, e2) {
return t19 - e2 < Qb && t19 - e2 > -Qb;
}
function ox(t19, e2) {
return t19 - e2 > Qb;
}
function ix(t19, e2) {
return t19 - e2 < -Qb;
}
var rx = { Utils: Object.freeze({ __proto__: null, DECIMALS: 3, EQ: nx, EQ_0: ex, GE: function(t19, e2) {
return t19 - e2 > -Qb;
}, GT: ox, LE: function(t19, e2) {
return t19 - e2 < Qb;
}, LT: ix, getTolerance: tx, setTolerance: Kb }), Errors: undefined, Matrix: undefined, Planar_set: undefined, Point: undefined, Vector: undefined, Line: undefined, Circle: undefined, Segment: undefined, Arc: undefined, Box: undefined, Edge: undefined, Face: undefined, Ray: undefined, Ray_shooting: undefined, Multiline: undefined, Polygon: undefined, Distance: undefined, Inversion: undefined };
for (let t19 in Jb)
rx[t19] = Jb[t19];
Object.defineProperty(rx, "DP_TOL", { get: function() {
return tx();
}, set: function(t19) {
Kb(t19);
} });
var sx = class {
static get ILLEGAL_PARAMETERS() {
return new ReferenceError("Illegal Parameters");
}
static get ZERO_DIVISION() {
return new Error("Zero division");
}
static get UNRESOLVED_BOUNDARY_CONFLICT() {
return new Error("Unresolved boundary conflict in boolean operation");
}
static get INFINITE_LOOP() {
return new Error("Infinite loop");
}
static get CANNOT_COMPLETE_BOOLEAN_OPERATION() {
return new Error("Cannot complete boolean operation");
}
static get CANNOT_INVOKE_ABSTRACT_METHOD() {
return new Error("Abstract method cannot be invoked");
}
static get OPERATION_IS_NOT_SUPPORTED() {
return new Error("Operation is not supported");
}
static get UNSUPPORTED_SHAPE_TYPE() {
return new Error("Unsupported shape type");
}
};
rx.Errors = sx;
var ax = class {
constructor(t19, e2) {
this.first = t19, this.last = e2 || this.first;
}
[Symbol.iterator]() {
let t19;
return { next: () => (t19 = t19 ? t19.next : this.first, { value: t19, done: t19 === undefined }) };
}
get size() {
let t19 = 0;
for (let e2 of this)
t19++;
return t19;
}
toArray(t19 = undefined, e2 = undefined) {
let n2 = [], o2 = t19 || this.first, i2 = e2 || this.last, r2 = o2;
if (r2 === undefined)
return n2;
do {
n2.push(r2), r2 = r2.next;
} while (r2 !== i2.next);
return n2;
}
append(t19) {
return this.isEmpty() ? this.first = t19 : (t19.prev = this.last, this.last.next = t19), this.last = t19, this.last.next = undefined, this.first.prev = undefined, this;
}
insert(t19, e2) {
if (this.isEmpty())
this.first = t19, this.last = t19;
else if (e2 == null)
t19.next = this.first, this.first.prev = t19, this.first = t19;
else {
let n2 = e2.next;
e2.next = t19, n2 && (n2.prev = t19), t19.prev = e2, t19.next = n2, this.last === e2 && (this.last = t19);
}
return this.last.next = undefined, this.first.prev = undefined, this;
}
remove(t19) {
return t19 === this.first && t19 === this.last ? (this.first = undefined, this.last = undefined) : (t19.prev && (t19.prev.next = t19.next), t19.next && (t19.next.prev = t19.prev), t19 === this.first && (this.first = t19.next), t19 === this.last && (this.last = t19.prev)), this;
}
isEmpty() {
return this.first === undefined;
}
static testInfiniteLoop(t19) {
let e2 = t19, n2 = t19;
do {
if (e2 != t19 && e2 === n2)
throw sx.INFINITE_LOOP;
e2 = e2.next, n2 = n2.next.next;
} while (e2 != t19);
}
};
var cx = { stroke: "black" };
var lx = class {
constructor(t19 = cx) {
for (const e2 in t19)
this[e2] = t19[e2];
this.stroke = t19.stroke ?? cx.stroke;
}
toAttributesString() {
return Object.keys(this).reduce((t19, e2) => t19 + (this[e2] !== undefined ? this.toAttrString(e2, this[e2]) : ""), "");
}
toAttrString(t19, e2) {
const n2 = t19 === "className" ? "class" : this.convertCamelToKebabCase(t19);
return e2 === null ? `${n2} ` : `${n2}="${e2.toString()}" `;
}
convertCamelToKebabCase(t19) {
return t19.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).join("-").toLowerCase();
}
};
function hx(t19) {
return new lx(t19).toAttributesString();
}
function dx(t19, e2) {
let n2 = [], [o2, i2, r2] = t19.standard, [s2, a2, c2] = e2.standard, l2 = o2 * a2 - i2 * s2, h2 = r2 * a2 - i2 * c2, d2 = o2 * c2 - r2 * s2;
if (!rx.Utils.EQ_0(l2)) {
let t20, e3;
i2 === 0 ? (t20 = r2 / o2, e3 = d2 / l2) : a2 === 0 ? (t20 = c2 / s2, e3 = d2 / l2) : o2 === 0 ? (t20 = h2 / l2, e3 = r2 / i2) : s2 === 0 ? (t20 = h2 / l2, e3 = c2 / a2) : (t20 = h2 / l2, e3 = d2 / l2), n2.push(new rx.Point(t20, e3));
}
return n2;
}
function ux(t19, e2) {
let n2 = [], o2 = e2.pc.projectionOn(t19), i2 = e2.pc.distanceTo(o2)[0];
if (rx.Utils.EQ(i2, e2.r))
n2.push(o2);
else if (rx.Utils.LT(i2, e2.r)) {
let r2, s2, a2 = Math.sqrt(e2.r * e2.r - i2 * i2);
r2 = t19.norm.rotate90CCW().multiply(a2), s2 = o2.translate(r2), n2.push(s2), r2 = t19.norm.rotate90CW().multiply(a2), s2 = o2.translate(r2), n2.push(s2);
}
return n2;
}
function px(t19, e2) {
let n2 = [];
for (let o2 of e2.toSegments()) {
let e3 = gx(o2, t19);
for (let t20 of e3)
kx(t20, n2) || n2.push(t20);
}
return n2;
}
function mx(t19, e2) {
let n2 = [];
if (px(t19, e2.box).length === 0)
return n2;
let o2 = ux(t19, new rx.Circle(e2.pc, e2.r));
for (let t20 of o2)
t20.on(e2) && n2.push(t20);
return n2;
}
function gx(t19, e2) {
let n2 = [];
return t19.ps.on(e2) && n2.push(t19.ps), t19.pe.on(e2) && !t19.isZeroLength() && n2.push(t19.pe), n2.length > 0 || t19.isZeroLength() || t19.ps.leftTo(e2) && t19.pe.leftTo(e2) || !t19.ps.leftTo(e2) && !t19.pe.leftTo(e2) ? n2 : dx(new rx.Line(t19.ps, t19.pe), e2);
}
function fx(t19, e2) {
let n2 = [];
if (t19.isZeroLength())
return t19.ps.on(e2) && n2.push(t19.ps), n2;
if (e2.isZeroLength())
return e2.ps.on(t19) && n2.push(e2.ps), n2;
let o2 = new rx.Line(t19.ps, t19.pe), i2 = new rx.Line(e2.ps, e2.pe);
if (o2.incidentTo(i2))
t19.ps.on(e2) && n2.push(t19.ps), t19.pe.on(e2) && n2.push(t19.pe), !e2.ps.on(t19) || e2.ps.equalTo(t19.ps) || e2.ps.equalTo(t19.pe) || n2.push(e2.ps), !e2.pe.on(t19) || e2.pe.equalTo(t19.ps) || e2.pe.equalTo(t19.pe) || n2.push(e2.pe);
else if (o2.parallelTo(i2)) {
const o3 = new rx.Vector(t19.ps, t19.pe), i3 = new rx.Vector(e2.ps, e2.pe), r2 = new rx.Vector(t19.ps, e2.ps), s2 = o3.cross(i3);
if (!rx.Utils.EQ_0(s2)) {
const a2 = r2.cross(i3) / s2, c2 = r2.cross(o3) / s2;
rx.Utils.GE(a2, 0) && rx.Utils.LE(a2, 1) && rx.Utils.GE(c2, 0) && rx.Utils.LE(c2, 1) && n2.push(yx(t19.ps.translate(o3.multiply(a2)), t19, e2));
}
} else {
let r2 = dx(o2, i2);
r2.length > 0 && _x(r2[0], t19) && _x(r2[0], e2) && n2.push(yx(r2[0], t19, e2));
}
return n2;
}
function yx(t19, e2, n2) {
for (const o2 of [e2.ps, e2.pe, n2.ps, n2.pe])
if (t19.equalTo(o2))
return o2;
return t19;
}
function _x(t19, e2) {
const n2 = e2.box;
return rx.Utils.LE(t19.x, n2.xmax) && rx.Utils.GE(t19.x, n2.xmin) && rx.Utils.LE(t19.y, n2.ymax) && rx.Utils.GE(t19.y, n2.ymin);
}
function bx(t19, e2) {
let n2 = [];
if (t19.isZeroLength()) {
let [o3, i2] = t19.ps.distanceTo(e2.pc);
return rx.Utils.EQ(o3, e2.r) && n2.push(t19.ps), n2;
}
let o2 = ux(new rx.Line(t19.ps, t19.pe), e2);
for (let e3 of o2)
e3.on(t19) && n2.push(e3);
return n2;
}
function xx(t19, e2) {
let n2 = [];
if (t19.isZeroLength())
return t19.ps.on(e2) && n2.push(t19.ps), n2;
let o2 = ux(new rx.Line(t19.ps, t19.pe), new rx.Circle(e2.pc, e2.r));
for (let i2 of o2)
i2.on(t19) && i2.on(e2) && n2.push(i2);
return n2;
}
function vx(t19, e2) {
let n2 = [], o2 = new rx.Vector(t19.pc, e2.pc), i2 = t19.r, r2 = e2.r;
if (rx.Utils.EQ_0(i2) || rx.Utils.EQ_0(r2))
return n2;
if (rx.Utils.EQ_0(o2.x) && rx.Utils.EQ_0(o2.y) && rx.Utils.EQ(i2, r2))
return n2.push(t19.pc.translate(-i2, 0)), n2;
let s2, a2 = t19.pc.distanceTo(e2.pc)[0];
if (rx.Utils.GT(a2, i2 + r2))
return n2;
if (rx.Utils.LT(a2, Math.abs(i2 - r2)))
return n2;
if (o2.x /= a2, o2.y /= a2, rx.Utils.EQ(a2, i2 + r2) || rx.Utils.EQ(a2, Math.abs(i2 - r2)))
return s2 = t19.pc.translate(i2 * o2.x, i2 * o2.y), n2.push(s2), n2;
let c2 = i2 * i2 / (2 * a2) - r2 * r2 / (2 * a2) + a2 / 2, l2 = t19.pc.translate(c2 * o2.x, c2 * o2.y), h2 = Math.sqrt(i2 * i2 - c2 * c2);
return s2 = l2.translate(o2.rotate90CCW().multiply(h2)), n2.push(s2), s2 = l2.translate(o2.rotate90CW().multiply(h2)), n2.push(s2), n2;
}
function Ix(t19, e2) {
let n2 = [];
if (t19.pc.equalTo(e2.pc) && rx.Utils.EQ(t19.r, e2.r)) {
let o3;
return o3 = t19.start, o3.on(e2) && n2.push(o3), o3 = t19.end, o3.on(e2) && n2.push(o3), o3 = e2.start, o3.on(t19) && n2.push(o3), o3 = e2.end, o3.on(t19) && n2.push(o3), n2;
}
let o2 = new rx.Circle(t19.pc, t19.r), i2 = new rx.Circle(e2.pc, e2.r), r2 = o2.intersect(i2);
for (let o3 of r2)
o3.on(t19) && o3.on(e2) && n2.push(o3);
return n2;
}
function Sx(t19, e2) {
let n2 = [];
if (e2.pc.equalTo(t19.pc) && rx.Utils.EQ(e2.r, t19.r))
return n2.push(t19.start), n2.push(t19.end), n2;
let o2 = vx(e2, new rx.Circle(t19.pc, t19.r));
for (let e3 of o2)
e3.on(t19) && n2.push(e3);
return n2;
}
function Cx(t19, e2) {
return t19.isSegment ? fx(t19.shape, e2) : xx(e2, t19.shape);
}
function Px(t19, e2) {
return t19.isSegment ? xx(t19.shape, e2) : Ix(t19.shape, e2);
}
function Mx(t19, e2) {
return t19.isSegment ? gx(t19.shape, e2) : mx(e2, t19.shape);
}
function Nx(t19, e2) {
return t19.isSegment ? bx(t19.shape, e2) : Sx(t19.shape, e2);
}
function wx(t19, e2) {
let n2 = [];
for (let o2 of e2.edges)
for (let e3 of Cx(o2, t19))
n2.push(e3);
return n2;
}
function Tx(t19, e2) {
let n2 = [];
for (let o2 of e2.edges)
for (let e3 of Px(o2, t19))
n2.push(e3);
return n2;
}
function Rx(t19, e2) {
let n2 = [];
if (e2.isEmpty())
return n2;
for (let o2 of e2.edges)
for (let e3 of Mx(o2, t19))
kx(e3, n2) || n2.push(e3);
return t19.sortPoints(n2);
}
function Ex(t19, e2) {
let n2 = [];
if (e2.isEmpty())
return n2;
for (let o2 of e2.edges)
for (let e3 of Nx(o2, t19))
n2.push(e3);
return n2;
}
function Ax(t19, e2) {
return t19.isSegment ? Cx(e2, t19.shape) : t19.isArc ? Px(e2, t19.shape) : t19.isLine ? Mx(e2, t19.shape) : t19.isRay ? (n2 = e2, o2 = t19.shape, n2.isSegment ? Lx(o2, n2.shape) : zx(o2, n2.shape)) : [];
var n2, o2;
}
function Ox(t19, e2) {
let n2 = [];
if (e2.isEmpty() || t19.shape.box.not_intersect(e2.box))
return n2;
let o2 = e2.edges.search(t19.shape.box);
for (let e3 of o2)
n2 = [...n2, ...Ax(t19, e3)];
return n2;
}
function kx(t19, e2) {
return e2.some((e3) => e3.equalTo(t19));
}
function Dx(t19) {
return new rx.Line(t19.start, t19.norm);
}
function Lx(t19, e2) {
return gx(e2, Dx(t19)).filter((e3) => t19.contains(e3));
}
function zx(t19, e2) {
return mx(Dx(t19), e2).filter((e3) => t19.contains(e3));
}
function Bx(t19, e2) {
return ux(Dx(t19), e2).filter((e3) => t19.contains(e3));
}
function Fx(t19, e2) {
return dx(Dx(t19), e2).filter((e3) => t19.contains(e3));
}
function jx(t19, e2) {
return Rx(Dx(t19), e2).filter((e3) => t19.contains(e3));
}
function $x(t19, e2) {
if (t19.intersect && t19.intersect instanceof Function)
return t19.intersect(e2);
throw sx.UNSUPPORTED_SHAPE_TYPE;
}
function Yx(t19, e2) {
let n2 = [];
for (let o2 of e2)
n2 = [...n2, ...$x(t19, o2.shape)];
return n2;
}
var Xx = class t19 extends ax {
constructor(...t20) {
if (super(), this.isInfinite = false, t20.length === 1 && t20[0] instanceof Array && t20[0].length > 0) {
const e2 = t20[0], n2 = e2.length, o2 = (t21) => t21 instanceof rx.Segment || t21 instanceof rx.Arc || t21 instanceof rx.Ray, i2 = (t21) => t21 instanceof rx.Segment || t21 instanceof rx.Arc;
if (!(n2 === 1 && ((t21) => t21 instanceof rx.Segment || t21 instanceof rx.Arc || t21 instanceof rx.Ray || t21 instanceof rx.Line)(e2[0]) || n2 > 1 && o2(e2[0]) && o2(e2[n2 - 1]) && e2.slice(1, n2 - 1).every(i2)))
throw rx.Errors.ILLEGAL_PARAMETERS;
this.isInfinite = e2.some((t21) => t21 instanceof rx.Ray || t21 instanceof rx.Line);
for (let t21 of e2) {
let e3 = new rx.Edge(t21);
this.append(e3);
}
this.setArcLength();
}
}
get edges() {
return [...this];
}
get box() {
return this.edges.reduce((t20, e2) => t20.merge(e2.box), new rx.Box);
}
get vertices() {
let t20 = this.edges.map((t21) => t21.start);
return t20.push(this.last.end), t20;
}
get length() {
if (this.isEmpty())
return 0;
if (this.isInfinite)
return Number.POSITIVE_INFINITY;
let t20 = 0;
for (let e2 of this)
t20 += e2.length;
return t20;
}
clone() {
return new t19(this.toShapes());
}
setArcLength() {
for (let t20 of this)
this.setOneEdgeArcLength(t20);
}
setOneEdgeArcLength(t20) {
t20 === this.first ? t20.arc_length = 0 : t20.arc_length = t20.prev.arc_length + t20.prev.length;
}
pointAtLength(t20) {
if (t20 > this.length || t20 < 0)
return null;
if (this.isInfinite)
return null;
let e2 = null;
for (let n2 of this)
if (t20 >= n2.arc_length && (n2 === this.last || t20 < n2.next.arc_length)) {
e2 = n2.pointAtLength(t20 - n2.arc_length);
break;
}
return e2;
}
addVertex(t20, e2) {
let n2 = e2.shape.split(t20);
if (n2[0] === null)
return e2.prev;
if (n2[1] === null)
return e2;
let o2 = new rx.Edge(n2[0]), i2 = e2.prev;
return this.insert(o2, i2), e2.shape = n2[1], o2;
}
getChain(t20, e2) {
let n2 = [];
for (let o2 = t20;o2 !== e2.next; o2 = o2.next)
n2.push(o2);
return n2;
}
split(t20) {
for (let e2 of t20) {
let t21 = this.findEdgeByPoint(e2);
this.addVertex(e2, t21);
}
return this;
}
findEdgeByPoint(t20) {
let e2;
for (let n2 of this)
if (n2.shape.contains(t20)) {
e2 = n2;
break;
}
return e2;
}
distanceTo(t20) {
if (t20 instanceof rx.Point) {
const [e2, n2] = rx.Distance.shape2multiline(t20, this);
return [e2, n2.reverse()];
}
if (t20 instanceof rx.Line) {
const [e2, n2] = rx.Distance.shape2multiline(t20, this);
return [e2, n2.reverse()];
}
if (t20 instanceof rx.Circle) {
const [e2, n2] = rx.Distance.shape2multiline(t20, this);
return [e2, n2.reverse()];
}
if (t20 instanceof rx.Segment) {
const [e2, n2] = rx.Distance.shape2multiline(t20, this);
return [e2, n2.reverse()];
}
if (t20 instanceof rx.Arc) {
const [e2, n2] = rx.Distance.shape2multiline(t20, this);
return [e2, n2.reverse()];
}
if (t20 instanceof rx.Box) {
const [e2, n2] = rx.Distance.shape2multiline(new rx.Polygon(t20), this);
return [e2, n2.reverse()];
}
if (t20 instanceof rx.Multiline)
return rx.Distance.multiline2multiline(this, t20);
throw rx.Errors.UNSUPPORTED_SHAPE_TYPE;
}
intersect(t20) {
return t20 instanceof rx.Multiline ? function(t21, e2) {
let n2 = [];
for (let o2 of t21)
for (let t22 of e2)
n2 = [...n2, ...$x(o2.shape, t22.shape)];
return n2;
}(this, t20) : Yx(t20, this);
}
contains(t20) {
if (t20 instanceof rx.Point)
return this.edges.some((e2) => e2.shape.contains(t20));
throw rx.Errors.UNSUPPORTED_SHAPE_TYPE;
}
translate(e2) {
return new t19(this.edges.map((t20) => t20.shape.translate(e2)));
}
rotate(e2 = 0, n2 = new rx.Point) {
return new t19(this.edges.map((t20) => t20.shape.rotate(e2, n2)));
}
transform(e2 = new rx.Matrix) {
return new t19(this.edges.map((t20) => t20.shape.transform(e2)));
}
toShapes() {
return this.edges.map((t20) => t20.shape.clone());
}
toJSON() {
return this.edges.map((t20) => t20.toJSON());
}
svgPoints() {
return this.vertices.map((t20) => `${t20.x},${t20.y}`).join(" ");
}
dpath() {
let t20 = `M${this.first.start.x},${this.first.start.y}`;
for (let e2 of this)
t20 += e2.svg();
return t20;
}
svg(t20 = {}) {
let e2 = `
<path ${hx({ fill: "none", ...t20 })} d="`;
e2 += `
M${this.first.start.x},${this.first.start.y}`;
for (let t21 of this)
e2 += t21.svg();
return e2 += `" >
</path>`, e2;
}
};
rx.Multiline = Xx;
function Wx(t20, e2, n2) {
let o2 = n2.length, i2 = t20.shape.split(e2);
if (i2.length === 0)
return;
let r2 = 0;
r2 = i2[0] === null ? 0 : i2[1] === null ? t20.shape.length : i2[0].length;
let s2, a2 = 0;
nx(r2, 0) && (a2 |= 1), nx(r2, t20.shape.length) && (a2 |= 2), s2 = r2 === 1 / 0 ? i2[0].coord(e2) : 2 & a2 && t20.next && t20.next.arc_length === 0 ? 0 : t20.arc_length + r2, n2.push({ id: o2, pt: e2, arc_length: s2, edge_before: t20, edge_after: undefined, face: t20.face, is_vertex: a2 });
}
function Vx(t20) {
t20.int_points1_sorted = Hx(t20.int_points1), t20.int_points2_sorted = Hx(t20.int_points2);
}
function Hx(t20) {
let e2 = new Map, n2 = 0;
for (let o2 of t20)
e2.has(o2.face) || (e2.set(o2.face, n2), n2++);
for (let n3 of t20)
n3.faceId = e2.get(n3.face);
return t20.slice().sort(Gx);
}
function Gx(t20, e2) {
return t20.faceId < e2.faceId ? -1 : t20.faceId > e2.faceId ? 1 : t20.arc_length < e2.arc_length ? -1 : t20.arc_length > e2.arc_length ? 1 : 0;
}
function Ux(t20) {
if (t20.int_points1.length < 2)
return;
let e2, n2, o2, i2, r2 = false;
for (let s2 = 0;s2 < t20.int_points1_sorted.length; s2++)
if (t20.int_points1_sorted[s2].id !== -1) {
e2 = t20.int_points1_sorted[s2], n2 = t20.int_points2[e2.id];
for (let a2 = s2 + 1;a2 < t20.int_points1_sorted.length && (o2 = t20.int_points1_sorted[a2], nx(o2.arc_length, e2.arc_length)); a2++)
o2.id !== -1 && (i2 = t20.int_points2[o2.id], i2.id !== -1 && o2.edge_before === e2.edge_before && o2.edge_after === e2.edge_after && i2.edge_before === n2.edge_before && i2.edge_after === n2.edge_after && (o2.id = -1, i2.id = -1, r2 = true));
}
n2 = t20.int_points2_sorted[0], e2 = t20.int_points1[n2.id];
for (let o3 = 1;o3 < t20.int_points2_sorted.length; o3++) {
let i3 = t20.int_points2_sorted[o3];
if (i3.id === -1)
continue;
if (n2.id === -1 || !nx(i3.arc_length, n2.arc_length)) {
n2 = i3, e2 = t20.int_points1[n2.id];
continue;
}
let s2 = t20.int_points1[i3.id];
s2.edge_before === e2.edge_before && s2.edge_after === e2.edge_after && i3.edge_before === n2.edge_before && i3.edge_after === n2.edge_after && (s2.id = -1, i3.id = -1, r2 = true);
}
r2 && (t20.int_points1 = t20.int_points1.filter((t21) => t21.id >= 0), t20.int_points2 = t20.int_points2.filter((t21) => t21.id >= 0), t20.int_points1.forEach((t21, e3) => t21.id = e3), t20.int_points2.forEach((t21, e3) => t21.id = e3));
}
function Zx(t20) {
for (let e2 of t20)
e2.edge_before && (e2.edge_before.bvStart = undefined, e2.edge_before.bvEnd = undefined, e2.edge_before.bv = undefined, e2.edge_before.overlap = undefined), e2.edge_after && (e2.edge_after.bvStart = undefined, e2.edge_after.bvEnd = undefined, e2.edge_after.bv = undefined, e2.edge_after.overlap = undefined);
for (let e2 of t20)
e2.edge_before && (e2.edge_before.bvEnd = 2), e2.edge_after && (e2.edge_after.bvStart = 2);
}
function qx(t20, e2) {
for (let n2 of t20)
n2.edge_before && n2.edge_before.setInclusion(e2), n2.edge_after && n2.edge_after.setInclusion(e2);
}
function Jx(t20, e2, n2) {
let o2, i2, r2 = 1;
if (t20.length === 1)
return 1;
o2 = t20[e2];
for (let s2 = e2 + 1;s2 < t20.length && o2.face === n2 && (i2 = t20[s2], i2.pt.equalTo(o2.pt) && i2.edge_before === o2.edge_before && i2.edge_after === o2.edge_after); s2++)
r2++;
return r2;
}
function Qx(t20, e2) {
if (e2) {
for (let n2 of e2) {
let e3 = n2.edge_before;
if (n2.is_vertex = 0, e3.shape.start && e3.shape.start.equalTo(n2.pt) && (n2.is_vertex |= 1), e3.shape.end && e3.shape.end.equalTo(n2.pt) && (n2.is_vertex |= 2), 1 & n2.is_vertex) {
n2.edge_before = e3.prev, e3.prev && (n2.is_vertex = 2);
continue;
}
if (2 & n2.is_vertex)
continue;
let o2 = t20.addVertex(n2.pt, e3);
n2.edge_before = o2;
}
for (let n2 of e2)
n2.edge_before ? n2.edge_after = n2.edge_before.next : t20 instanceof Xx && 1 & n2.is_vertex && (n2.edge_after = t20.first);
}
}
function Kx(t20, e2, n2) {
const o2 = t20.edge_before, i2 = e2.edge_after, r2 = n2.length;
o2.next = n2[0], n2[0].prev = o2, n2[r2 - 1].next = i2, i2.prev = n2[r2 - 1];
}
rx.multiline = (...t20) => new rx.Multiline(...t20);
var { INSIDE: tv, OUTSIDE: ev, BOUNDARY: nv, OVERLAP_SAME: ov, OVERLAP_OPPOSITE: iv } = Jb;
var { NOT_VERTEX: rv, START_VERTEX: sv, END_VERTEX: av } = Jb;
function cv(t20, e2) {
let n2 = e2.clone().reverse(), [o2] = mv(t20, n2, 3, true);
return o2;
}
function lv(t20, e2) {
let [n2] = mv(t20, e2, 2, true);
return n2;
}
function hv(t20, e2) {
let [n2, o2] = mv(t20, e2, 2, false), i2 = [];
for (let t21 of n2.faces)
i2 = [...i2, ...[...t21.edges].map((t22) => t22.shape)];
let r2 = [];
for (let t21 of o2.faces)
r2 = [...r2, ...[...t21.edges].map((t22) => t22.shape)];
return [i2, r2];
}
function dv(t20, e2) {
let [n2] = mv(t20, e2, 3, false), i2 = [];
for (let t21 of n2.faces)
i2 = [...i2, ...[...t21.edges].map((t22) => t22.shape)];
return i2;
}
function uv(t20, e2) {
let n2 = t20.clone(), o2 = e2.clone(), i2 = gv(n2, o2);
return Vx(i2), Qx(n2, i2.int_points1_sorted), Qx(o2, i2.int_points2_sorted), Ux(i2), Vx(i2), [i2.int_points1_sorted.map((t21) => t21.pt), i2.int_points2_sorted.map((t21) => t21.pt)];
}
function pv(t20, e2, n2, o2) {
let i2 = fv(t20, n2.int_points1), r2 = fv(e2, n2.int_points2);
for (yv(i2, e2), yv(r2, t20), Zx(n2.int_points1), Zx(n2.int_points2), qx(n2.int_points1, e2), qx(n2.int_points2, t20);_v(t20, e2, n2.int_points1, n2.int_points1_sorted, n2.int_points2, n2); )
;
((function(t21) {
let e3, n3, o3, i3 = t21.int_points1.length;
for (let r3 = 0;r3 < i3; r3++) {
let s2 = t21.int_points1_sorted[r3];
s2.face !== e3 && (n3 = r3, e3 = s2.face);
let a2, c2 = r3, l2 = Jx(t21.int_points1_sorted, r3, e3);
a2 = c2 + l2 < i3 && t21.int_points1_sorted[c2 + l2].face === e3 ? c2 + l2 : n3;
let h2 = Jx(t21.int_points1_sorted, a2, e3);
o3 = null;
for (let n4 = a2;n4 < a2 + h2; n4++) {
let i4 = t21.int_points1_sorted[n4];
if (i4.face === e3 && t21.int_points2[i4.id].face === t21.int_points2[s2.id].face) {
o3 = i4;
break;
}
}
if (o3 === null)
continue;
let d2 = s2.edge_after, u2 = o3.edge_before;
if (d2.bv !== 2 || u2.bv !== 2)
continue;
if (d2 !== u2)
continue;
let p2 = t21.int_points2[s2.id], m2 = t21.int_points2[o3.id], g2 = p2.edge_after, f2 = m2.edge_before;
g2.bv === 2 && f2.bv === 2 && g2 === f2 || (p2 = t21.int_points2[o3.id], m2 = t21.int_points2[s2.id], g2 = p2.edge_after, f2 = m2.edge_before), g2.bv === 2 && f2.bv === 2 && g2 === f2 && d2.setOverlap(g2);
}
}))(n2), bv(t20, o2, n2.int_points1_sorted, true), bv(e2, o2, n2.int_points2_sorted, false), Iv(t20, i2, o2, true), Iv(e2, r2, o2, false);
}
function mv(t20, e2, n2, o2) {
let i2 = t20.clone(), r2 = e2.clone(), s2 = gv(i2, r2);
return Vx(s2), Qx(i2, s2.int_points1_sorted), Qx(r2, s2.int_points2_sorted), Ux(s2), Vx(s2), pv(i2, r2, s2, n2), o2 && function(t21, e3, n3) {
((function(t22, e4, n4, o3) {
for (let n5 of e4.faces) {
for (let e5 of n5)
t22.edges.add(e5);
o3.find((t23) => t23.face === n5) === undefined && t22.addFace(n5.first, n5.last);
}
}))(t21, e3, 0, n3.int_points2), function(t22, e4, n4) {
if (n4.int_points1.length !== 0)
for (let t23 = 0;t23 < n4.int_points1.length; t23++) {
let e5 = n4.int_points1[t23], o3 = n4.int_points2[t23];
if (e5.edge_before !== undefined && e5.edge_after === undefined && o3.edge_before === undefined && o3.edge_after !== undefined && (e5.edge_before.next = o3.edge_after, o3.edge_after.prev = e5.edge_before, e5.edge_after = o3.edge_after, o3.edge_before = e5.edge_before), o3.edge_before !== undefined && o3.edge_after === undefined && e5.edge_before === undefined && e5.edge_after !== undefined && (o3.edge_before.next = e5.edge_after, e5.edge_after.prev = o3.edge_before, o3.edge_after = e5.edge_after, e5.edge_before = o3.edge_before), e5.edge_before !== undefined && e5.edge_after === undefined)
for (let t24 of n4.int_points1_sorted)
t24 !== e5 && t24.edge_before === undefined && t24.edge_after !== undefined && t24.pt.equalTo(e5.pt) && (e5.edge_before.next = t24.edge_after, t24.edge_after.prev = e5.edge_before, e5.edge_after = t24.edge_after, t24.edge_before = e5.edge_before);
if (o3.edge_before !== undefined && o3.edge_after === undefined)
for (let t24 of n4.int_points2_sorted)
t24 !== o3 && t24.edge_before === undefined && t24.edge_after !== undefined && t24.pt.equalTo(o3.pt) && (o3.edge_before.next = t24.edge_after, t24.edge_after.prev = o3.edge_before, o3.edge_after = t24.edge_after, t24.edge_before = o3.edge_before);
}
}(0, 0, n3), xv(t21, n3.int_points1), xv(e3, n3.int_points2), vv(t21, n3.int_points1, n3.int_points2), vv(t21, n3.int_points2, n3.int_points1), Sv(t21), Sv(e3);
}(i2, r2, s2), [i2, r2];
}
function gv(t20, e2) {
let n2 = { int_points1: [], int_points2: [] };
for (let o2 of t20.edges) {
let t21 = e2.edges.search(o2.box);
for (let e3 of t21) {
let t22 = o2.shape.intersect(e3.shape);
for (let i2 of t22)
Wx(o2, i2, n2.int_points1), Wx(e3, i2, n2.int_points2);
}
}
return n2;
}
function fv(t20, e2) {
let n2 = [];
for (let o2 of t20.faces)
e2.find((t21) => t21.face === o2) || n2.push(o2);
return n2;
}
function yv(t20, e2) {
for (let n2 of t20)
n2.first.bv = n2.first.bvStart = n2.first.bvEnd = undefined, n2.first.setInclusion(e2);
}
function _v(t20, e2, n2, o2, i2, r2) {
let s2, a2, c2, l2 = o2.length, h2 = false;
for (let d2 = 0;d2 < l2; d2++) {
let u2 = o2[d2];
u2.face !== s2 && (a2 = d2, s2 = u2.face);
let p2, m2 = d2, g2 = Jx(o2, d2, s2);
p2 = m2 + g2 < l2 && o2[m2 + g2].face === s2 ? m2 + g2 : a2;
let f2 = Jx(o2, p2, s2);
c2 = null;
for (let t21 = p2;t21 < p2 + f2; t21++) {
let e3 = o2[t21];
if (e3.face === s2 && i2[e3.id].face === i2[u2.id].face) {
c2 = e3;
break;
}
}
if (c2 === null)
continue;
let y2 = u2.edge_after, _2 = c2.edge_before;
if (y2.bv !== nv || _2.bv == nv)
if (y2.bv == nv || _2.bv !== nv) {
if (y2.bv === nv && _2.bv === nv && y2 != _2 || y2.bv === tv && _2.bv === ev || y2.bv === ev && _2.bv === tv) {
let t21 = y2.next;
for (;t21 != _2; )
t21.bvStart = undefined, t21.bvEnd = undefined, t21.bv = undefined, t21.setInclusion(e2), t21 = t21.next;
}
if (y2.bv === nv && _2.bv === nv && y2 != _2) {
let t21, e3 = y2.next;
for (;e3 != _2; ) {
if (e3.bv != nv) {
if (t21 === undefined)
t21 = e3.bv;
else if (e3.bv != t21)
throw sx.UNRESOLVED_BOUNDARY_CONFLICT;
}
e3 = e3.next;
}
t21 != null && (y2.bv = t21, _2.bv = t21);
continue;
}
if (y2.bv === tv && _2.bv === ev || y2.bv === ev && _2.bv === tv) {
let o3 = y2;
for (;o3 != _2; ) {
if (o3.bvStart === y2.bv && o3.bvEnd === _2.bv) {
let [s3, a3] = o3.shape.distanceTo(e2);
if (s3 < 10 * rx.DP_TOL) {
Wx(o3, a3.ps, n2);
let s4 = n2[n2.length - 1];
if (s4.is_vertex & sv)
s4.edge_after = o3, s4.edge_before = o3.prev, o3.bvStart = nv, o3.bv = undefined, o3.setInclusion(e2);
else if (s4.is_vertex & av)
s4.edge_after = o3.next, o3.bvEnd = nv, o3.bv = undefined, o3.setInclusion(e2);
else {
let t21 = e2.addVertex(s4.pt, o3);
s4.edge_before = t21, s4.edge_after = t21.next, t21.setInclusion(e2), t21.next.bvStart = nv, t21.next.bvEnd = undefined, t21.next.bv = undefined, t21.next.setInclusion(e2);
}
let c3 = e2.findEdgeByPoint(a3.pe);
Wx(c3, a3.pe, i2);
let l3 = i2[i2.length - 1];
if (l3.is_vertex & sv)
l3.edge_after = c3, l3.edge_before = c3.prev;
else if (l3.is_vertex & av)
l3.edge_after = c3.next;
else {
let n3 = i2.find((t21) => t21.edge_after === c3), o4 = e2.addVertex(l3.pt, c3);
l3.edge_before = o4, l3.edge_after = o4.next, n3 && (n3.edge_after = o4), o4.bvStart = undefined, o4.bvEnd = nv, o4.bv = undefined, o4.setInclusion(t20), o4.next.bvStart = nv, o4.next.bvEnd = undefined, o4.next.bv = undefined, o4.next.setInclusion(t20);
}
Vx(r2), h2 = true;
break;
}
}
o3 = o3.next;
}
if (h2)
break;
throw sx.UNRESOLVED_BOUNDARY_CONFLICT;
}
} else
_2.bv = y2.bv;
else
y2.bv = _2.bv;
}
return h2;
}
function bv(t20, e2, n2, o2) {
if (!n2)
return;
let i2, r2, s2, a2;
for (let c2 = 0;c2 < n2.length; c2++) {
if (s2 = n2[c2], s2.face !== i2 && (r2 = c2, i2 = s2.face), i2.isEmpty())
continue;
let l2, h2 = c2, d2 = Jx(n2, c2, i2);
l2 = h2 + d2 < n2.length && n2[h2 + d2].face === s2.face ? h2 + d2 : r2, a2 = n2[l2];
let u2 = l2, p2 = Jx(n2, u2, i2), m2 = s2.edge_after, g2 = a2.edge_before;
if (m2.bv === tv && g2.bv === tv && e2 === 1 || m2.bv === ev && g2.bv === ev && e2 === 2 || (m2.bv === ev || g2.bv === ev) && e2 === 3 && !o2 || (m2.bv === tv || g2.bv === tv) && e2 === 3 && o2 || m2.bv === nv && g2.bv === nv && m2.overlap & ov && o2 || m2.bv === nv && g2.bv === nv && m2.overlap & iv) {
t20.removeChain(i2, m2, g2);
for (let t21 = h2;t21 < h2 + d2; t21++)
n2[t21].edge_after = undefined;
for (let t21 = u2;t21 < u2 + p2; t21++)
n2[t21].edge_before = undefined;
}
c2 += d2 - 1;
}
}
function xv(t20, e2) {
for (let n2 of e2)
t20.faces.delete(n2.face), n2.face = undefined, n2.edge_before && (n2.edge_before.face = undefined), n2.edge_after && (n2.edge_after.face = undefined);
}
function vv(t20, e2, n2) {
for (let o2 of e2) {
if (o2.edge_before === undefined || o2.edge_after === undefined)
continue;
if (o2.face)
continue;
if (o2.edge_after.face || o2.edge_before.face)
continue;
let { edge_after: i2, edge_before: r2 } = o2;
try {
ax.testInfiniteLoop(i2);
} catch (t21) {
throw sx.CANNOT_COMPLETE_BOOLEAN_OPERATION;
}
let s2 = t20.addFace(i2, r2);
for (let t21 of e2)
t21.edge_before && t21.edge_after && t21.edge_before.face === s2 && t21.edge_after.face === s2 && (t21.face = s2);
for (let t21 of n2)
t21.edge_before && t21.edge_after && t21.edge_before.face === s2 && t21.edge_after.face === s2 && (t21.face = s2);
}
}
function Iv(t20, e2, n2, o2) {
for (let i2 of e2) {
let e3 = i2.first.bv;
(n2 === 1 && e3 === tv || n2 === 3 && e3 === tv && o2 || n2 === 3 && e3 === ev && !o2 || n2 === 2 && e3 === ev) && t20.deleteFace(i2);
}
}
function Sv(t20) {
const e2 = [];
for (const n2 of t20.edges)
n2.face && t20.faces.has(n2.face) || e2.push(n2);
for (const n2 of e2)
t20.edges.delete(n2);
}
var Cv = Object.freeze({ __proto__: null, BOOLEAN_INTERSECT: 2, BOOLEAN_SUBTRACT: 3, BOOLEAN_UNION: 1, calculateIntersections: uv, innerClip: hv, intersect: lv, outerClip: dv, removeNotRelevantChains: bv, removeOldFaces: xv, restoreFaces: vv, subtract: cv, unify: function(t20, e2) {
let [n2] = mv(t20, e2, 1, true);
return n2;
} });
var Pv = RegExp("T.F..FFF.|T.F...F..");
var Mv = RegExp("T........|.T.......|...T.....|....T....");
var Nv = RegExp("FT.......|F..T.....|F...T....");
var wv = RegExp("T.F..F...");
var Tv = RegExp("T.F..F...|.TF..F...|..FT.F...|..F.TF...");
var Rv = class {
constructor() {
this.m = new Array(9).fill(undefined);
}
get I2I() {
return this.m[0];
}
set I2I(t20) {
this.m[0] = t20;
}
get I2B() {
return this.m[1];
}
set I2B(t20) {
this.m[1] = t20;
}
get I2E() {
return this.m[2];
}
set I2E(t20) {
this.m[2] = t20;
}
get B2I() {
return this.m[3];
}
set B2I(t20) {
this.m[3] = t20;
}
get B2B() {
return this.m[4];
}
set B2B(t20) {
this.m[4] = t20;
}
get B2E() {
return this.m[5];
}
set B2E(t20) {
this.m[5] = t20;
}
get E2I() {
return this.m[6];
}
set E2I(t20) {
this.m[6] = t20;
}
get E2B() {
return this.m[7];
}
set E2B(t20) {
this.m[7] = t20;
}
get E2E() {
return this.m[8];
}
set E2E(t20) {
this.m[8] = t20;
}
toString() {
return this.m.map((t20) => t20 instanceof Array && t20.length > 0 ? "T" : t20 instanceof Array && t20.length === 0 ? "F" : "*").join("");
}
equal() {
return Pv.test(this.toString());
}
intersect() {
return Mv.test(this.toString());
}
touch() {
return Nv.test(this.toString());
}
inside() {
return wv.test(this.toString());
}
covered() {
return Tv.test(this.toString());
}
};
function Ev(t20, e2) {
let n2, o2 = new rx.Ray(e2), i2 = new rx.Line(o2.pt, o2.norm);
const r2 = new rx.Box(o2.box.xmin - rx.DP_TOL, o2.box.ymin - rx.DP_TOL, o2.box.xmax + rx.DP_TOL, o2.box.ymax + rx.DP_TOL);
if (t20.box.not_intersect(r2))
return rx.OUTSIDE;
let s2 = t20.edges.search(r2);
if (s2.length === 0)
return rx.OUTSIDE;
for (let t21 of s2)
if (t21.shape.contains(e2))
return rx.BOUNDARY;
let a2 = [...t20.faces], c2 = [];
for (let t21 of s2)
for (let n3 of o2.intersect(t21.shape)) {
if (n3.equalTo(e2))
return rx.BOUNDARY;
c2.push({ pt: n3, edge: t21, face_index: a2.indexOf(t21.face) });
}
c2.sort((t21, e3) => ix(t21.pt.x, e3.pt.x) ? -1 : ox(t21.pt.x, e3.pt.x) ? 1 : t21.face_index < e3.face_index ? -1 : t21.face_index > e3.face_index ? 1 : t21.edge.arc_length < e3.edge.arc_length ? -1 : t21.edge.arc_length > e3.edge.arc_length ? 1 : 0);
let l2 = 0;
for (let t21 = 0;t21 < c2.length; t21++) {
let e3 = c2[t21];
if (e3.pt.equalTo(e3.edge.shape.start)) {
if (t21 > 0 && e3.pt.equalTo(c2[t21 - 1].pt) && e3.face_index === c2[t21 - 1].face_index && e3.edge.prev === c2[t21 - 1].edge)
continue;
let n3 = e3.edge.prev;
for (;ex(n3.length); )
n3 = n3.prev;
let o3 = n3.shape.tangentInEnd(), r3 = e3.pt.translate(o3), s3 = e3.edge.shape.tangentInStart(), a3 = e3.pt.translate(s3), h2 = r3.leftTo(i2), d2 = a3.leftTo(i2);
(h2 && !d2 || !h2 && d2) && l2++;
} else if (e3.pt.equalTo(e3.edge.shape.end)) {
if (t21 > 0 && e3.pt.equalTo(c2[t21 - 1].pt) && e3.face_index === c2[t21 - 1].face_index && e3.edge.next === c2[t21 - 1].edge)
continue;
let n3 = e3.edge.next;
for (;ex(n3.length); )
n3 = n3.next;
let o3 = n3.shape.tangentInStart(), r3 = e3.pt.translate(o3), s3 = e3.edge.shape.tangentInEnd(), a3 = e3.pt.translate(s3), h2 = r3.leftTo(i2), d2 = a3.leftTo(i2);
(h2 && !d2 || !h2 && d2) && l2++;
} else if (e3.edge.shape instanceof rx.Segment)
l2++;
else {
let t22 = e3.edge.shape.box;
nx(e3.pt.y, t22.ymin) || nx(e3.pt.y, t22.ymax) || l2++;
}
}
return n2 = l2 % 2 == 1 ? 1 : 0, n2;
}
function Av(t20, e2) {
return Lv(t20, e2).intersect();
}
function Ov(t20, e2) {
return Lv(t20, e2).inside();
}
function kv(t20, e2) {
return Lv(t20, e2).covered();
}
function Dv(t20, e2) {
return kv(e2, t20);
}
function Lv(t20, e2) {
return t20 instanceof rx.Line && e2 instanceof rx.Line ? function(t21, e3) {
let n2 = new Rv, o2 = dx(t21, e3);
o2.length === 0 ? t21.contains(e3.pt) && e3.contains(t21.pt) ? (n2.I2I = [t21], n2.I2E = [], n2.E2I = []) : (n2.I2I = [], n2.I2E = [t21], n2.E2I = [e3]) : (n2.I2I = o2, n2.I2E = t21.split(o2), n2.E2I = e3.split(o2));
return n2;
}(t20, e2) : t20 instanceof rx.Line && e2 instanceof rx.Circle ? function(t21, e3) {
let n2 = new Rv, o2 = ux(t21, e3);
if (o2.length === 0)
n2.I2I = [], n2.I2B = [], n2.I2E = [t21], n2.E2I = [e3];
else if (o2.length === 1)
n2.I2I = [], n2.I2B = o2, n2.I2E = t21.split(o2), n2.E2I = [e3];
else {
let i2 = new Xx([t21]), r2 = t21.sortPoints(o2);
i2.split(r2);
let s2 = i2.toShapes();
n2.I2I = [s2[1]], n2.I2B = r2, n2.I2E = [s2[0], s2[2]], n2.E2I = new rx.Polygon([e3.toArc()]).cutWithLine(t21);
}
return n2;
}(t20, e2) : t20 instanceof rx.Line && e2 instanceof rx.Box ? function(t21, e3) {
let n2 = new Rv, o2 = px(t21, e3);
if (o2.length === 0)
n2.I2I = [], n2.I2B = [], n2.I2E = [t21], n2.E2I = [e3];
else if (o2.length === 1)
n2.I2I = [], n2.I2B = o2, n2.I2E = t21.split(o2), n2.E2I = [e3];
else {
let i2 = new Xx([t21]), r2 = t21.sortPoints(o2);
i2.split(r2);
let s2 = i2.toShapes();
e3.toSegments().some((t22) => t22.contains(o2[0]) && t22.contains(o2[1])) ? (n2.I2I = [], n2.I2B = [s2[1]], n2.I2E = [s2[0], s2[2]], n2.E2I = [e3]) : (n2.I2I = [s2[1]], n2.I2B = r2, n2.I2E = [s2[0], s2[2]], n2.E2I = new rx.Polygon(e3.toSegments()).cutWithLine(t21));
}
return n2;
}(t20, e2) : t20 instanceof rx.Line && e2 instanceof rx.Polygon ? function(t21, e3) {
let n2 = new Rv, o2 = Rx(t21, e3), i2 = new Xx([t21]), r2 = o2.length > 0 ? o2.slice() : t21.sortPoints(o2);
return i2.split(r2), [...i2].forEach((t22) => t22.setInclusion(e3)), n2.I2I = [...i2].filter((t22) => t22.bv === rx.INSIDE).map((t22) => t22.shape), n2.I2B = [...i2].slice(1).map((t22) => t22.bv === rx.BOUNDARY ? t22.shape : t22.shape.start), n2.I2E = [...i2].filter((t22) => t22.bv === rx.OUTSIDE).map((t22) => t22.shape), n2.E2I = e3.cutWithLine(t21), n2;
}(t20, e2) : (t20 instanceof rx.Segment || t20 instanceof rx.Arc) && e2 instanceof rx.Polygon ? zv(t20, e2) : (t20 instanceof rx.Segment || t20 instanceof rx.Arc) && (e2 instanceof rx.Circle || e2 instanceof rx.Box) ? zv(t20, new rx.Polygon(e2)) : t20 instanceof rx.Polygon && e2 instanceof rx.Polygon ? Bv(t20, e2) : (t20 instanceof rx.Circle || t20 instanceof rx.Box) && (e2 instanceof rx.Circle || e2 instanceof rx.Box) ? Bv(new rx.Polygon(t20), new rx.Polygon(e2)) : (t20 instanceof rx.Circle || t20 instanceof rx.Box) && e2 instanceof rx.Polygon ? Bv(new rx.Polygon(t20), e2) : t20 instanceof rx.Polygon && (e2 instanceof rx.Circle || e2 instanceof rx.Box) ? Bv(t20, new rx.Polygon(e2)) : undefined;
}
function zv(t20, e2) {
let n2 = new Rv, o2 = function(t21, e3) {
return t21 instanceof rx.Line ? Rx(t21, e3) : t21 instanceof rx.Segment ? wx(t21, e3) : t21 instanceof rx.Arc ? Tx(t21, e3) : [];
}(t20, e2), i2 = o2.length > 0 ? o2.slice() : t20.sortPoints(o2), r2 = new Xx([t20]);
r2.split(i2), [...r2].forEach((t21) => t21.setInclusion(e2)), n2.I2I = [...r2].filter((t21) => t21.bv === rx.INSIDE).map((t21) => t21.shape), n2.I2B = [...r2].slice(1).map((t21) => t21.bv === rx.BOUNDARY ? t21.shape : t21.shape.start), n2.I2E = [...r2].filter((t21) => t21.bv === rx.OUTSIDE).map((t21) => t21.shape), n2.B2I = [], n2.B2B = [], n2.B2E = [];
for (let o3 of [t20.start, t20.end])
switch (Ev(e2, o3)) {
case rx.INSIDE:
n2.B2I.push(o3);
break;
case rx.BOUNDARY:
n2.B2B.push(o3);
break;
case rx.OUTSIDE:
n2.B2E.push(o3);
}
return n2;
}
function Bv(t20, e2) {
let n2 = new Rv, [o2, i2] = uv(t20, e2), r2 = lv(t20, e2), s2 = cv(t20, e2), a2 = cv(e2, t20), [c2, l2] = hv(t20, e2), h2 = dv(t20, e2), d2 = dv(e2, t20);
return n2.I2I = r2.isEmpty() ? [] : [r2], n2.I2B = l2, n2.I2E = s2.isEmpty() ? [] : [s2], n2.B2I = c2, n2.B2B = o2, n2.B2E = h2, n2.E2I = a2.isEmpty() ? [] : [a2], n2.E2B = d2, n2;
}
var Fv = Object.freeze({ __proto__: null, contain: function(t20, e2) {
return Ov(e2, t20);
}, cover: Dv, covered: kv, disjoint: function(t20, e2) {
return !Av(t20, e2);
}, equal: function(t20, e2) {
return Lv(t20, e2).equal();
}, inside: Ov, intersect: Av, relate: Lv, touch: function(t20, e2) {
return Lv(t20, e2).touch();
} });
var jv = class t20 {
constructor(t21 = 1, e2 = 0, n2 = 0, o2 = 1, i2 = 0, r2 = 0) {
this.a = t21, this.b = e2, this.c = n2, this.d = o2, this.tx = i2, this.ty = r2;
}
fromMatrix3x3(e2) {
const [n2, o2, i2] = e2[0], [r2, s2, a2] = e2[1];
return new t20(n2, r2, o2, s2, i2, a2);
}
toMatrix3x3() {
return [[this.a, this.c, this.tx], [this.b, this.d, this.ty], [0, 0, 1]];
}
clone() {
return new t20(this.a, this.b, this.c, this.d, this.tx, this.ty);
}
transform(t21) {
return [t21[0] * this.a + t21[1] * this.c + this.tx, t21[0] * this.b + t21[1] * this.d + this.ty];
}
multiply(e2) {
return new t20(this.a * e2.a + this.c * e2.b, this.b * e2.a + this.d * e2.b, this.a * e2.c + this.c * e2.d, this.b * e2.c + this.d * e2.d, this.a * e2.tx + this.c * e2.ty + this.tx, this.b * e2.tx + this.d * e2.ty + this.ty);
}
translate(...e2) {
let n2, o2;
if (e2.length != 1 || isNaN(e2[0].x) || isNaN(e2[0].y)) {
if (e2.length !== 2 || typeof e2[0] != "number" || typeof e2[1] != "number")
throw sx.ILLEGAL_PARAMETERS;
n2 = e2[0], o2 = e2[1];
} else
n2 = e2[0].x, o2 = e2[0].y;
return this.multiply(new t20(1, 0, 0, 1, n2, o2));
}
rotate(e2, n2 = 0, o2 = 0) {
let i2 = Math.cos(e2), r2 = Math.sin(e2);
return this.translate(n2, o2).multiply(new t20(i2, r2, -r2, i2, 0, 0)).translate(-n2, -o2);
}
scale(e2, n2) {
return this.multiply(new t20(e2, 0, 0, n2, 0, 0));
}
equalTo(t21) {
return !!rx.Utils.EQ(this.tx, t21.tx) && (!!rx.Utils.EQ(this.ty, t21.ty) && (!!rx.Utils.EQ(this.a, t21.a) && (!!rx.Utils.EQ(this.b, t21.b) && (!!rx.Utils.EQ(this.c, t21.c) && !!rx.Utils.EQ(this.d, t21.d)))));
}
};
rx.Matrix = jv;
rx.matrix = (...t21) => new rx.Matrix(...t21);
var $v = class {
constructor(t21, e2) {
this.low = t21, this.high = e2;
}
get max() {
return this.clone();
}
less_than(t21) {
return this.low < t21.low || this.low === t21.low && this.high < t21.high;
}
equal_to(t21) {
return this.low === t21.low && this.high === t21.high;
}
intersect(t21) {
return !this.not_intersect(t21);
}
not_intersect(t21) {
return this.high < t21.low || t21.high < this.low;
}
merge(t21) {
const e2 = this.low === undefined ? t21.low : this.low < t21.low ? this.low : t21.low, n2 = this.high === undefined ? t21.high : this.high > t21.high ? this.high : t21.high, o2 = this.clone();
return o2.low = e2, o2.high = n2, o2;
}
output() {
return [this.low, this.high];
}
comparable_less_than(t21, e2) {
return t21 < e2;
}
};
var Yv = class t21 extends $v {
clone() {
return new t21(this.low, this.high);
}
};
var Xv = class {
constructor(t22, e2, n2 = null, o2 = null, i2 = null, r2 = 0) {
if (this.left = n2, this.right = o2, this.parent = i2, this.color = r2, this.item = { key: undefined, values: [] }, e2 !== undefined && this.item.values.push(e2), t22 !== undefined)
if (Array.isArray(t22)) {
const [e3, n3] = t22;
if (!Number.isNaN(e3) && !Number.isNaN(n3)) {
let t23 = e3, o3 = n3;
t23 > o3 && ([t23, o3] = [o3, t23]), this.item.key = new Yv(t23, o3);
}
} else
this.item.key = t22;
this.max = this.item.key ? this.item.key.max : undefined;
}
isNil() {
return this.item.key === undefined && this.item.values.length === 0 && this.left === null && this.right === null && this.color === 0;
}
requireKey() {
if (!this.item.key)
throw new Error("Node key is undefined (nil/sentinel). Operation is not applicable.");
return this.item.key;
}
less_than(t22) {
const e2 = this.requireKey(), n2 = t22.requireKey();
return e2.less_than(n2);
}
_value_equal(t22) {
const e2 = this.item.values[0], n2 = t22.item.values[0];
return e2 && n2 && e2.equal_to ? e2.equal_to(n2) : e2 === n2;
}
equal_to(t22) {
const e2 = this.requireKey(), n2 = t22.requireKey();
return e2.equal_to(n2);
}
intersect(t22) {
const e2 = this.requireKey(), n2 = t22.requireKey();
return e2.intersect(n2);
}
copy_data(t22) {
this.item.key = t22.item.key, this.item.values = t22.item.values.slice();
}
update_max() {
this.max = this.item.key ? this.item.key.max : undefined, this.right && this.right.max && (this.max = this.max ? this.max.merge(this.right.max) : this.right.max), this.left && this.left.max && (this.max = this.max ? this.max.merge(this.left.max) : this.left.max);
}
not_intersect_left_subtree(t22) {
if (!this.left)
return true;
const e2 = this.left.max ? this.left.max.high : this.left.item.key.high, n2 = this.requireKey(), o2 = t22.requireKey();
return n2.comparable_less_than(e2, o2.low);
}
not_intersect_right_subtree(t22) {
if (!this.right)
return true;
const e2 = this.right.max ? this.right.max.low : this.right.item.key.low, n2 = this.requireKey(), o2 = t22.requireKey();
return n2.comparable_less_than(o2.high, e2);
}
};
var Wv = class t22 {
constructor() {
this.root = null, this.nil_node = new Xv;
}
get size() {
let t23 = 0;
return this.tree_walk(this.root, (e2) => t23 += e2.item.values.length), t23;
}
get keys() {
const t23 = [];
return this.tree_walk(this.root, (e2) => t23.push(e2.item.key.output())), t23;
}
get values() {
const t23 = [];
return this.tree_walk(this.root, (e2) => {
for (const n2 of e2.item.values)
t23.push(n2);
}), t23;
}
get items() {
const t23 = [];
return this.tree_walk(this.root, (e2) => {
const n2 = e2.item.key.output();
for (const o2 of e2.item.values)
t23.push({ key: n2, value: o2 });
}), t23;
}
isEmpty() {
return this.root == null || this.root === this.nil_node;
}
clear() {
this.root = null;
}
insert(t23, e2 = t23) {
if (t23 === undefined)
return;
const n2 = this.tree_search(this.root, new Xv(t23));
if (n2)
return n2.item.values.push(e2), n2;
const o2 = new Xv(t23, e2, this.nil_node, this.nil_node, null, 1);
return this.tree_insert(o2), this.recalc_max(o2), o2;
}
exist(t23, e2 = t23) {
const n2 = this.tree_search(this.root, new Xv(t23));
return !!n2 && (arguments.length < 2 || e2 === t23 || n2.item.values.some((t24) => t24 && t24.equal_to ? t24.equal_to(e2) : t24 === e2));
}
remove(t23, e2 = t23) {
const n2 = this.tree_search(this.root, new Xv(t23));
if (!n2)
return;
if (arguments.length < 2)
return this.tree_delete(n2), n2;
const o2 = n2.item.values.findIndex((t24) => t24 && t24.equal_to ? t24.equal_to(e2) : t24 === e2);
return o2 >= 0 ? (n2.item.values.splice(o2, 1), n2.item.values.length === 0 && this.tree_delete(n2), n2) : undefined;
}
search(t23, e2 = (t24, e3) => t24 === e3 ? e3.output() : t24) {
const n2 = new Xv(t23), o2 = [];
this.tree_search_interval(this.root, n2, o2);
const i2 = [];
for (const t24 of o2)
for (const n3 of t24.item.values)
i2.push(e2(n3, t24.item.key));
return i2;
}
intersect_any(t23) {
const e2 = new Xv(t23);
return this.tree_find_any_interval(this.root, e2);
}
forEach(t23) {
this.tree_walk(this.root, (e2) => {
for (const n2 of e2.item.values)
t23(e2.item.key, n2);
});
}
map(e2) {
const n2 = new t22;
return this.tree_walk(this.root, (t23) => {
for (const o2 of t23.item.values)
n2.insert(t23.item.key, e2(o2, t23.item.key));
}), n2;
}
*iterate(t23, e2 = (t24, e3) => t24 === e3 ? e3.output() : t24) {
let n2 = null;
for (t23 ? n2 = this.tree_search_nearest_forward(this.root, new Xv(t23)) : this.root && (n2 = this.local_minimum(this.root));n2; ) {
for (const t24 of n2.item.values)
yield e2(t24, n2.item.key);
n2 = this.tree_successor(n2);
}
}
recalc_max(t23) {
let e2 = t23;
for (;e2.parent != null; )
e2.parent.update_max(), e2 = e2.parent;
}
tree_insert(t23) {
let e2 = this.root, n2 = null;
if (this.root == null || this.root === this.nil_node)
this.root = t23;
else {
for (;e2 !== this.nil_node; )
n2 = e2, e2 = t23.less_than(e2) ? e2.left : e2.right;
t23.parent = n2, t23.less_than(n2) ? n2.left = t23 : n2.right = t23;
}
this.insert_fixup(t23);
}
insert_fixup(t23) {
let e2, n2;
for (e2 = t23;e2 !== this.root && e2.parent.color === 1; )
e2.parent === e2.parent.parent.left ? (n2 = e2.parent.parent.right, n2.color === 1 ? (e2.parent.color = 0, n2.color = 0, e2.parent.parent.color = 1, e2 = e2.parent.parent) : (e2 === e2.parent.right && (e2 = e2.parent, this.rotate_left(e2)), e2.parent.color = 0, e2.parent.parent.color = 1, this.rotate_right(e2.parent.parent))) : (n2 = e2.parent.parent.left, n2.color === 1 ? (e2.parent.color = 0, n2.color = 0, e2.parent.parent.color = 1, e2 = e2.parent.parent) : (e2 === e2.parent.left && (e2 = e2.parent, this.rotate_right(e2)), e2.parent.color = 0, e2.parent.parent.color = 1, this.rotate_left(e2.parent.parent)));
this.root.color = 0;
}
tree_delete(t23) {
let e2, n2;
e2 = t23.left === this.nil_node || t23.right === this.nil_node ? t23 : this.tree_successor(t23), n2 = e2.left !== this.nil_node ? e2.left : e2.right, n2.parent = e2.parent, e2 === this.root ? this.root = n2 : (e2 === e2.parent.left ? e2.parent.left = n2 : e2.parent.right = n2, e2.parent.update_max()), this.recalc_max(n2), e2 !== t23 && (t23.copy_data(e2), t23.update_max(), this.recalc_max(t23)), e2.color === 0 && this.delete_fixup(n2);
}
delete_fixup(t23) {
let e2, n2 = t23;
for (;n2 !== this.root && n2.parent != null && n2.color === 0; )
n2 === n2.parent.left ? (e2 = n2.parent.right, e2.color === 1 && (e2.color = 0, n2.parent.color = 1, this.rotate_left(n2.parent), e2 = n2.parent.right), e2.left.color === 0 && e2.right.color === 0 ? (e2.color = 1, n2 = n2.parent) : (e2.right.color === 0 && (e2.color = 1, e2.left.color = 0, this.rotate_right(e2), e2 = n2.parent.right), e2.color = n2.parent.color, n2.parent.color = 0, e2.right.color = 0, this.rotate_left(n2.parent), n2 = this.root)) : (e2 = n2.parent.left, e2.color === 1 && (e2.color = 0, n2.parent.color = 1, this.rotate_right(n2.parent), e2 = n2.parent.left), e2.left.color === 0 && e2.right.color === 0 ? (e2.color = 1, n2 = n2.parent) : (e2.left.color === 0 && (e2.color = 1, e2.right.color = 0, this.rotate_left(e2), e2 = n2.parent.left), e2.color = n2.parent.color, n2.parent.color = 0, e2.left.color = 0, this.rotate_right(n2.parent), n2 = this.root));
n2.color = 0;
}
tree_search(t23, e2) {
if (t23 != null && t23 !== this.nil_node)
return e2.equal_to(t23) ? t23 : e2.less_than(t23) ? this.tree_search(t23.left, e2) : this.tree_search(t23.right, e2);
}
tree_search_nearest_forward(t23, e2) {
let n2 = null, o2 = t23;
for (;o2 && o2 !== this.nil_node; )
o2.less_than(e2) ? o2.intersect(e2) ? (n2 = o2, o2 = o2.left) : o2 = o2.right : (n2 && !o2.less_than(n2) || (n2 = o2), o2 = o2.left);
return n2 || null;
}
tree_search_interval(t23, e2, n2) {
t23 != null && t23 !== this.nil_node && (t23.left === this.nil_node || t23.not_intersect_left_subtree(e2) || this.tree_search_interval(t23.left, e2, n2), t23.intersect(e2) && n2.push(t23), t23.right === this.nil_node || t23.not_intersect_right_subtree(e2) || this.tree_search_interval(t23.right, e2, n2));
}
tree_find_any_interval(t23, e2) {
let n2 = false;
return t23 != null && t23 !== this.nil_node && (t23.left === this.nil_node || t23.not_intersect_left_subtree(e2) || (n2 = this.tree_find_any_interval(t23.left, e2)), n2 || (n2 = t23.intersect(e2)), n2 || t23.right === this.nil_node || t23.not_intersect_right_subtree(e2) || (n2 = this.tree_find_any_interval(t23.right, e2))), n2;
}
local_minimum(t23) {
let e2 = t23;
for (;e2.left != null && e2.left !== this.nil_node; )
e2 = e2.left;
return e2;
}
local_maximum(t23) {
let e2 = t23;
for (;e2.right != null && e2.right !== this.nil_node; )
e2 = e2.right;
return e2;
}
tree_successor(t23) {
let e2, n2, o2;
if (t23.right !== this.nil_node)
e2 = this.local_minimum(t23.right);
else {
for (n2 = t23, o2 = t23.parent;o2 != null && o2.right === n2; )
n2 = o2, o2 = o2.parent;
e2 = o2;
}
return e2;
}
rotate_left(t23) {
const e2 = t23.right;
t23.right = e2.left, e2.left !== this.nil_node && (e2.left.parent = t23), e2.parent = t23.parent, t23 === this.root ? this.root = e2 : t23 === t23.parent.left ? t23.parent.left = e2 : t23.parent.right = e2, e2.left = t23, t23.parent = e2, t23 !== null && t23 !== this.nil_node && t23.update_max(), e2 != null && e2 !== this.nil_node && e2.update_max();
}
rotate_right(t23) {
const e2 = t23.left;
t23.left = e2.right, e2.right !== this.nil_node && (e2.right.parent = t23), e2.parent = t23.parent, t23 === this.root ? this.root = e2 : t23 === t23.parent.left ? t23.parent.left = e2 : t23.parent.right = e2, e2.right = t23, t23.parent = e2, t23 !== null && t23 !== this.nil_node && t23.update_max(), e2 != null && e2 !== this.nil_node && e2.update_max();
}
tree_walk(t23, e2) {
t23 != null && t23 !== this.nil_node && (this.tree_walk(t23.left, e2), e2(t23), this.tree_walk(t23.right, e2));
}
testRedBlackProperty() {
let t23 = true;
return this.tree_walk(this.root, function(e2) {
e2.color === 1 && (e2.left.color === 0 && e2.right.color === 0 || (t23 = false));
}), t23;
}
testBlackHeightProperty(t23) {
let e2 = 0, n2 = 0, o2 = 0;
if (t23.color === 0 && e2++, n2 = t23.left !== this.nil_node ? this.testBlackHeightProperty(t23.left) : 1, o2 = t23.right !== this.nil_node ? this.testBlackHeightProperty(t23.right) : 1, n2 !== o2)
throw new Error("Red-black height property violated");
return e2 += n2, e2;
}
};
var Vv = class extends Set {
constructor(t23) {
super(t23), this.index = new Wv, this.forEach((t24) => this.index.insert(t24));
}
add(t23) {
let e2 = this.size;
const { key: n2, value: o2 } = t23, i2 = n2 || t23.box, r2 = o2 || t23;
return super.add(r2), this.size > e2 && this.index.insert(i2, r2), this;
}
delete(t23) {
const { key: e2, value: n2 } = t23, o2 = e2 || t23.box, i2 = n2 || t23;
let r2 = super.delete(i2);
return r2 && this.index.remove(o2, i2), r2;
}
clear() {
super.clear(), this.index = new Wv;
}
search(t23) {
return this.index.search(t23);
}
hit(t23) {
let e2 = new rx.Box(t23.x - 1, t23.y - 1, t23.x + 1, t23.y + 1);
return this.index.search(e2).filter((e3) => t23.on(e3));
}
svg() {
return [...this].reduce((t23, e2) => t23 + e2.svg(), "");
}
};
rx.PlanarSet = Vv;
var Hv = class {
get name() {
throw sx.CANNOT_INVOKE_ABSTRACT_METHOD;
}
get box() {
throw sx.CANNOT_INVOKE_ABSTRACT_METHOD;
}
clone() {
throw sx.CANNOT_INVOKE_ABSTRACT_METHOD;
}
translate(...t23) {
return this.transform(new jv().translate(...t23));
}
rotate(t23, e2 = new rx.Point) {
return this.transform(new jv().rotate(t23, e2.x, e2.y));
}
scale(t23, e2) {
return this.transform(new jv().scale(t23, e2));
}
transform(...t23) {
throw sx.CANNOT_INVOKE_ABSTRACT_METHOD;
}
toJSON() {
return Object.assign({}, this, { name: this.name });
}
svg(t23 = {}) {
throw sx.CANNOT_INVOKE_ABSTRACT_METHOD;
}
};
rx.Point = class t23 extends Hv {
constructor(...t24) {
if (super(), this.x = 0, this.y = 0, t24.length !== 0) {
if (t24.length === 1 && t24[0] instanceof Array && t24[0].length === 2) {
let e2 = t24[0];
if (typeof e2[0] == "number" && typeof e2[1] == "number")
return this.x = e2[0], void (this.y = e2[1]);
}
if (t24.length === 1 && t24[0] instanceof Object && t24[0].name === "point") {
let { x: e2, y: n2 } = t24[0];
return this.x = e2, void (this.y = n2);
}
if (t24.length === 2 && typeof t24[0] == "number" && typeof t24[1] == "number")
return this.x = t24[0], void (this.y = t24[1]);
throw sx.ILLEGAL_PARAMETERS;
}
}
get box() {
return new rx.Box(this.x, this.y, this.x, this.y);
}
clone() {
return new rx.Point(this.x, this.y);
}
get vertices() {
return [this.clone()];
}
equalTo(t24) {
return rx.Utils.EQ(this.x, t24.x) && rx.Utils.EQ(this.y, t24.y);
}
lessThan(t24) {
return !!rx.Utils.LT(this.y, t24.y) || !(!rx.Utils.EQ(this.y, t24.y) || !rx.Utils.LT(this.x, t24.x));
}
transform(t24) {
return new rx.Point(t24.transform([this.x, this.y]));
}
projectionOn(t24) {
if (this.equalTo(t24.pt))
return this.clone();
let e2 = new rx.Vector(this, t24.pt);
if (rx.Utils.EQ_0(e2.cross(t24.norm)))
return t24.pt.clone();
let n2 = e2.dot(t24.norm), o2 = t24.norm.multiply(n2);
return this.translate(o2);
}
leftTo(t24) {
let e2 = new rx.Vector(t24.pt, this);
return rx.Utils.GT(e2.dot(t24.norm), 0);
}
distanceTo(e2) {
if (e2 instanceof t23) {
let t24 = e2.x - this.x, n2 = e2.y - this.y;
return [Math.sqrt(t24 * t24 + n2 * n2), new rx.Segment(this, e2)];
}
return e2 instanceof rx.Line ? rx.Distance.point2line(this, e2) : e2 instanceof rx.Circle ? rx.Distance.point2circle(this, e2) : e2 instanceof rx.Segment ? rx.Distance.point2segment(this, e2) : e2 instanceof rx.Arc ? rx.Distance.point2arc(this, e2) : e2 instanceof rx.Box ? rx.Distance.point2polygon(this, new rx.Polygon(e2)) : e2 instanceof rx.Polygon ? rx.Distance.point2polygon(this, e2) : e2 instanceof rx.PlanarSet ? rx.Distance.shape2planarSet(this, e2) : e2 instanceof rx.Multiline ? rx.Distance.shape2multiline(this, e2) : undefined;
}
on(t24) {
if (t24 instanceof rx.Point)
return this.equalTo(t24);
if (t24.contains && t24.contains instanceof Function)
return t24.contains(this);
throw rx.Errors.UNSUPPORTED_SHAPE_TYPE;
}
get name() {
return "point";
}
svg(t24 = {}) {
const e2 = t24.r ?? 3;
return `
<circle cx="${this.x}" cy="${this.y}" r="${e2}"
${hx({ fill: "red", ...t24 })} />`;
}
};
var Gv = (...t24) => new rx.Point(...t24);
rx.point = Gv;
rx.Vector = class extends Hv {
constructor(...t24) {
if (super(), this.x = 0, this.y = 0, t24.length !== 0) {
if (t24.length === 1 && t24[0] instanceof Array && t24[0].length === 2) {
let e2 = t24[0];
if (typeof e2[0] == "number" && typeof e2[1] == "number")
return this.x = e2[0], void (this.y = e2[1]);
}
if (t24.length === 1 && t24[0] instanceof Object && t24[0].name === "vector") {
let { x: e2, y: n2 } = t24[0];
return this.x = e2, void (this.y = n2);
}
if (t24.length === 1 && t24[0] instanceof Object && t24[0].name === "segment") {
let { start: e2, end: n2 } = t24[0];
return this.x = n2.x - e2.x, void (this.y = n2.y - e2.y);
}
if (t24.length === 2) {
let e2 = t24[0], n2 = t24[1];
if (typeof e2 == "number" && typeof n2 == "number")
return this.x = e2, void (this.y = n2);
if (e2 instanceof rx.Point && n2 instanceof rx.Point)
return this.x = n2.x - e2.x, void (this.y = n2.y - e2.y);
}
throw sx.ILLEGAL_PARAMETERS;
}
}
clone() {
return new rx.Vector(this.x, this.y);
}
get slope() {
let t24 = Math.atan2(this.y, this.x);
return t24 < 0 && (t24 = 2 * Math.PI + t24), t24;
}
get length() {
return Math.sqrt(this.dot(this));
}
isZeroLength() {
return rx.Utils.EQ_0(this.length);
}
equalTo(t24) {
return rx.Utils.EQ(this.x, t24.x) && rx.Utils.EQ(this.y, t24.y);
}
multiply(t24) {
return new rx.Vector(t24 * this.x, t24 * this.y);
}
dot(t24) {
return this.x * t24.x + this.y * t24.y;
}
cross(t24) {
return this.x * t24.y - this.y * t24.x;
}
normalize() {
if (this.isZeroLength())
throw sx.ZERO_DIVISION;
return new rx.Vector(this.x / this.length, this.y / this.length);
}
rotate(t24, e2 = new rx.Point) {
if (e2.x === 0 && e2.y === 0)
return this.transform(new jv().rotate(t24));
throw sx.OPERATION_IS_NOT_SUPPORTED;
}
transform(t24) {
return new rx.Vector(t24.transform([this.x, this.y]));
}
rotate90CCW() {
return new rx.Vector(-this.y, this.x);
}
rotate90CW() {
return new rx.Vector(this.y, -this.x);
}
invert() {
return new rx.Vector(-this.x, -this.y);
}
add(t24) {
return new rx.Vector(this.x + t24.x, this.y + t24.y);
}
subtract(t24) {
return new rx.Vector(this.x - t24.x, this.y - t24.y);
}
angleTo(t24) {
let e2 = this.normalize(), n2 = t24.normalize(), o2 = Math.atan2(e2.cross(n2), e2.dot(n2));
return o2 < 0 && (o2 += 2 * Math.PI), o2;
}
projectionOn(t24) {
let e2 = t24.normalize(), n2 = this.dot(e2);
return e2.multiply(n2);
}
get name() {
return "vector";
}
};
var Uv = (...t24) => new rx.Vector(...t24);
rx.vector = Uv;
rx.Segment = class t24 extends Hv {
constructor(...t25) {
if (super(), this.ps = new rx.Point, this.pe = new rx.Point, t25.length !== 0) {
if (t25.length === 1 && t25[0] instanceof Array && t25[0].length === 4) {
let e2 = t25[0];
return this.ps = new rx.Point(e2[0], e2[1]), void (this.pe = new rx.Point(e2[2], e2[3]));
}
if (t25.length === 1 && t25[0] instanceof Object && t25[0].name === "segment") {
let { ps: e2, pe: n2 } = t25[0];
return this.ps = new rx.Point(e2.x, e2.y), void (this.pe = new rx.Point(n2.x, n2.y));
}
if (!(t25.length === 1 && t25[0] instanceof rx.Point)) {
if (t25.length === 2 && t25[0] instanceof rx.Point && t25[1] instanceof rx.Point)
return this.ps = t25[0].clone(), void (this.pe = t25[1].clone());
if (t25.length === 4)
return this.ps = new rx.Point(t25[0], t25[1]), void (this.pe = new rx.Point(t25[2], t25[3]));
throw sx.ILLEGAL_PARAMETERS;
}
this.ps = t25[0].clone();
}
}
clone() {
return new rx.Segment(this.start, this.end);
}
get start() {
return this.ps;
}
get end() {
return this.pe;
}
get vertices() {
return [this.ps.clone(), this.pe.clone()];
}
get length() {
return this.start.distanceTo(this.end)[0];
}
get slope() {
return new rx.Vector(this.start, this.end).slope;
}
get box() {
return new rx.Box(Math.min(this.start.x, this.end.x), Math.min(this.start.y, this.end.y), Math.max(this.start.x, this.end.x), Math.max(this.start.y, this.end.y));
}
equalTo(t25) {
return this.ps.equalTo(t25.ps) && this.pe.equalTo(t25.pe);
}
contains(t25) {
return rx.Utils.EQ_0(this.distanceToPoint(t25));
}
intersect(t25) {
return t25 instanceof rx.Point ? this.contains(t25) ? [t25] : [] : t25 instanceof rx.Line ? gx(this, t25) : t25 instanceof rx.Ray ? Lx(t25, this) : t25 instanceof rx.Segment ? fx(this, t25) : t25 instanceof rx.Circle ? bx(this, t25) : t25 instanceof rx.Box ? function(t26, e2) {
let n2 = [];
for (let o2 of e2.toSegments()) {
let e3 = fx(o2, t26);
for (let t27 of e3)
n2.push(t27);
}
return n2;
}(this, t25) : t25 instanceof rx.Arc ? xx(this, t25) : t25 instanceof rx.Polygon ? wx(this, t25) : t25 instanceof rx.Multiline ? Yx(this, t25) : undefined;
}
distanceTo(t25) {
if (t25 instanceof rx.Point) {
let [e2, n2] = rx.Distance.point2segment(t25, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t25 instanceof rx.Circle) {
let [e2, n2] = rx.Distance.segment2circle(this, t25);
return [e2, n2];
}
if (t25 instanceof rx.Line) {
let [e2, n2] = rx.Distance.segment2line(this, t25);
return [e2, n2];
}
if (t25 instanceof rx.Segment) {
let [e2, n2] = rx.Distance.segment2segment(this, t25);
return [e2, n2];
}
if (t25 instanceof rx.Arc) {
let [e2, n2] = rx.Distance.segment2arc(this, t25);
return [e2, n2];
}
if (t25 instanceof rx.Box) {
let [e2, n2] = rx.Distance.shape2polygon(this, new rx.Polygon(t25));
return [e2, n2];
}
if (t25 instanceof rx.Polygon) {
let [e2, n2] = rx.Distance.shape2polygon(this, t25);
return [e2, n2];
}
if (t25 instanceof rx.PlanarSet) {
let [e2, n2] = rx.Distance.shape2planarSet(this, t25);
return [e2, n2];
}
if (t25 instanceof rx.Multiline)
return rx.Distance.shape2multiline(this, t25);
}
tangentInStart() {
return new rx.Vector(this.start, this.end).normalize();
}
tangentInEnd() {
return new rx.Vector(this.end, this.start).normalize();
}
reverse() {
return new t24(this.end, this.start);
}
split(t25) {
return this.start.equalTo(t25) ? [null, this.clone()] : this.end.equalTo(t25) ? [this.clone(), null] : [new rx.Segment(this.start, t25), new rx.Segment(t25, this.end)];
}
middle() {
return new rx.Point((this.start.x + this.end.x) / 2, (this.start.y + this.end.y) / 2);
}
pointAtLength(t25) {
if (t25 > this.length || t25 < 0)
return null;
if (t25 == 0)
return this.start;
if (t25 == this.length)
return this.end;
let e2 = t25 / this.length;
return new rx.Point((this.end.x - this.start.x) * e2 + this.start.x, (this.end.y - this.start.y) * e2 + this.start.y);
}
distanceToPoint(t25) {
let [e2, ...n2] = rx.Distance.point2segment(t25, this);
return e2;
}
definiteIntegral(t25 = 0) {
return (this.end.x - this.start.x) * (this.start.y - t25 + (this.end.y - t25)) / 2;
}
transform(e2 = new rx.Matrix) {
return new t24(this.ps.transform(e2), this.pe.transform(e2));
}
isZeroLength() {
return this.ps.equalTo(this.pe);
}
sortPoints(t25) {
return new rx.Line(this.start, this.end).sortPoints(t25);
}
get name() {
return "segment";
}
svg(t25 = {}) {
return `
<line x1="${this.start.x}" y1="${this.start.y}" x2="${this.end.x}" y2="${this.end.y}" ${hx(t25)} />`;
}
};
var Zv = (...t25) => new rx.Segment(...t25);
rx.segment = Zv;
var { vector: qv } = rx;
rx.Line = class t25 extends Hv {
constructor(...e2) {
if (super(), this.pt = new rx.Point, this.norm = new rx.Vector(0, 1), e2.length !== 0) {
if (e2.length === 1 && e2[0] instanceof Object && e2[0].name === "line") {
let { pt: t26, norm: n2 } = e2[0];
return this.pt = new rx.Point(t26), void (this.norm = new rx.Vector(n2));
}
if (e2.length === 2) {
let n2 = e2[0], o2 = e2[1];
if (n2 instanceof rx.Point && o2 instanceof rx.Point)
return this.pt = n2, this.norm = t25.points2norm(n2, o2), void (this.norm.dot(qv(this.pt.x, this.pt.y)) >= 0 && this.norm.invert());
if (n2 instanceof rx.Point && o2 instanceof rx.Vector) {
if (rx.Utils.EQ_0(o2.x) && rx.Utils.EQ_0(o2.y))
throw sx.ILLEGAL_PARAMETERS;
return this.pt = n2.clone(), this.norm = o2.clone(), this.norm = this.norm.normalize(), void (this.norm.dot(qv(this.pt.x, this.pt.y)) >= 0 && this.norm.invert());
}
if (n2 instanceof rx.Vector && o2 instanceof rx.Point) {
if (rx.Utils.EQ_0(n2.x) && rx.Utils.EQ_0(n2.y))
throw sx.ILLEGAL_PARAMETERS;
return this.pt = o2.clone(), this.norm = n2.clone(), this.norm = this.norm.normalize(), void (this.norm.dot(qv(this.pt.x, this.pt.y)) >= 0 && this.norm.invert());
}
}
throw sx.ILLEGAL_PARAMETERS;
}
}
clone() {
return new rx.Line(this.pt, this.norm);
}
get start() {}
get end() {}
get length() {
return Number.POSITIVE_INFINITY;
}
get box() {
return new rx.Box(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
}
get middle() {}
get slope() {
return new rx.Vector(this.norm.y, -this.norm.x).slope;
}
get standard() {
return [this.norm.x, this.norm.y, this.norm.dot(qv(this.pt.x, this.pt.y))];
}
parallelTo(t26) {
return rx.Utils.EQ_0(this.norm.cross(t26.norm));
}
incidentTo(t26) {
return this.parallelTo(t26) && this.pt.on(t26);
}
contains(t26) {
if (this.pt.equalTo(t26))
return true;
let e2 = new rx.Vector(this.pt, t26);
return rx.Utils.EQ_0(this.norm.dot(e2));
}
coord(t26) {
return qv(t26.x, t26.y).cross(this.norm);
}
intersect(t26) {
return t26 instanceof rx.Point ? this.contains(t26) ? [t26] : [] : t26 instanceof rx.Line ? dx(this, t26) : t26 instanceof rx.Ray ? Fx(t26, this) : t26 instanceof rx.Circle ? ux(this, t26) : t26 instanceof rx.Box ? px(this, t26) : t26 instanceof rx.Segment ? gx(t26, this) : t26 instanceof rx.Arc ? mx(this, t26) : t26 instanceof rx.Polygon ? Rx(this, t26) : t26 instanceof rx.Multiline ? Yx(this, t26) : undefined;
}
distanceTo(t26) {
if (t26 instanceof rx.Point) {
let [e2, n2] = rx.Distance.point2line(t26, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t26 instanceof rx.Circle) {
let [e2, n2] = rx.Distance.circle2line(t26, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t26 instanceof rx.Segment) {
let [e2, n2] = rx.Distance.segment2line(t26, this);
return [e2, n2.reverse()];
}
if (t26 instanceof rx.Arc) {
let [e2, n2] = rx.Distance.arc2line(t26, this);
return [e2, n2.reverse()];
}
if (t26 instanceof rx.Box) {
let [e2, n2] = rx.Distance.shape2polygon(this, new rx.Polygon(t26));
return [e2, n2];
}
if (t26 instanceof rx.Polygon) {
let [e2, n2] = rx.Distance.shape2polygon(this, t26);
return [e2, n2];
}
}
split(t26) {
if (t26 instanceof rx.Point)
return [new rx.Ray(t26, this.norm), new rx.Ray(t26, this.norm)];
{
let e2 = new rx.Multiline([this]), n2 = this.sortPoints(t26);
return e2.split(n2), e2.toShapes();
}
}
rotate(t26, e2 = new rx.Point) {
return new rx.Line(this.pt.rotate(t26, e2), this.norm.rotate(t26));
}
transform(t26) {
return new rx.Line(this.pt.transform(t26), this.norm.clone());
}
sortPoints(t26) {
return t26.slice().sort((t27, e2) => this.coord(t27) < this.coord(e2) ? -1 : this.coord(t27) > this.coord(e2) ? 1 : 0);
}
get name() {
return "line";
}
svg(t26, e2 = {}) {
let n2 = px(this, t26);
if (n2.length === 0)
return "";
let o2 = n2[0], i2 = n2.length === 2 ? n2[1] : n2.find((t27) => !t27.equalTo(o2));
return i2 === undefined && (i2 = o2), new rx.Segment(o2, i2).svg(e2);
}
static points2norm(t26, e2) {
if (t26.equalTo(e2))
throw sx.ILLEGAL_PARAMETERS;
return new rx.Vector(t26, e2).normalize().rotate90CCW();
}
};
var Jv = (...t26) => new rx.Line(...t26);
rx.line = Jv;
rx.Circle = class extends Hv {
constructor(...t26) {
if (super(), this.pc = new rx.Point, this.r = 1, t26.length === 1 && t26[0] instanceof Object && t26[0].name === "circle") {
let { pc: e2, r: n2 } = t26[0];
this.pc = new rx.Point(e2), this.r = n2;
} else {
let [e2, n2] = [...t26];
e2 && e2 instanceof rx.Point && (this.pc = e2.clone()), n2 !== undefined && (this.r = n2);
}
}
clone() {
return new rx.Circle(this.pc.clone(), this.r);
}
get center() {
return this.pc;
}
get box() {
return new rx.Box(this.pc.x - this.r, this.pc.y - this.r, this.pc.x + this.r, this.pc.y + this.r);
}
contains(t26) {
return t26 instanceof rx.Point ? rx.Utils.LE(t26.distanceTo(this.center)[0], this.r) : t26 instanceof rx.Segment ? rx.Utils.LE(t26.start.distanceTo(this.center)[0], this.r) && rx.Utils.LE(t26.end.distanceTo(this.center)[0], this.r) : t26 instanceof rx.Arc ? this.intersect(t26).length === 0 && rx.Utils.LE(t26.start.distanceTo(this.center)[0], this.r) && rx.Utils.LE(t26.end.distanceTo(this.center)[0], this.r) : t26 instanceof rx.Circle ? this.intersect(t26).length === 0 && rx.Utils.LE(t26.r, this.r) && rx.Utils.LE(t26.center.distanceTo(this.center)[0], this.r) : undefined;
}
toArc(t26 = true) {
return new rx.Arc(this.center, this.r, Math.PI, -Math.PI, t26);
}
scale(t26, e2) {
if (t26 !== e2)
throw sx.OPERATION_IS_NOT_SUPPORTED;
if (this.pc.x !== 0 || this.pc.y !== 0)
throw sx.OPERATION_IS_NOT_SUPPORTED;
return new rx.Circle(this.pc, this.r * t26);
}
transform(t26 = new rx.Matrix) {
return new rx.Circle(this.pc.transform(t26), this.r);
}
intersect(t26) {
return t26 instanceof rx.Point ? this.contains(t26) ? [t26] : [] : t26 instanceof rx.Line ? ux(t26, this) : t26 instanceof rx.Ray ? Bx(t26, this) : t26 instanceof rx.Segment ? bx(t26, this) : t26 instanceof rx.Circle ? vx(t26, this) : t26 instanceof rx.Box ? function(t27, e2) {
let n2 = [];
for (let o2 of e2.toSegments()) {
let e3 = bx(o2, t27);
for (let t28 of e3)
n2.push(t28);
}
return n2;
}(this, t26) : t26 instanceof rx.Arc ? Sx(t26, this) : t26 instanceof rx.Polygon ? Ex(this, t26) : t26 instanceof rx.Multiline ? Yx(this, t26) : undefined;
}
distanceTo(t26) {
if (t26 instanceof rx.Point) {
let [e2, n2] = rx.Distance.point2circle(t26, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t26 instanceof rx.Circle) {
let [e2, n2] = rx.Distance.circle2circle(this, t26);
return [e2, n2];
}
if (t26 instanceof rx.Line) {
let [e2, n2] = rx.Distance.circle2line(this, t26);
return [e2, n2];
}
if (t26 instanceof rx.Segment) {
let [e2, n2] = rx.Distance.segment2circle(t26, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t26 instanceof rx.Arc) {
let [e2, n2] = rx.Distance.arc2circle(t26, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t26 instanceof rx.Box) {
let [e2, n2] = rx.Distance.shape2polygon(this, new rx.Polygon(t26));
return [e2, n2];
}
if (t26 instanceof rx.Polygon) {
let [e2, n2] = rx.Distance.shape2polygon(this, t26);
return [e2, n2];
}
if (t26 instanceof rx.PlanarSet) {
let [e2, n2] = rx.Distance.shape2planarSet(this, t26);
return [e2, n2];
}
if (t26 instanceof rx.Multiline) {
let [e2, n2] = rx.Distance.shape2multiline(this, t26);
return [e2, n2];
}
}
get name() {
return "circle";
}
svg(t26 = {}) {
return `
<circle cx="${this.pc.x}" cy="${this.pc.y}" r="${this.r}"
${hx({ fill: "none", ...t26 })} />`;
}
};
rx.circle = (...t26) => new rx.Circle(...t26);
rx.Arc = class extends Hv {
constructor(...t26) {
if (super(), this.pc = new rx.Point, this.r = 1, this.startAngle = 0, this.endAngle = 2 * Math.PI, this.counterClockwise = true, t26.length !== 0)
if (t26.length === 1 && t26[0] instanceof Object && t26[0].name === "arc") {
let { pc: e2, r: n2, startAngle: o2, endAngle: i2, counterClockwise: r2 } = t26[0];
this.pc = new rx.Point(e2.x, e2.y), this.r = n2, this.startAngle = o2, this.endAngle = i2, this.counterClockwise = r2;
} else {
let [e2, n2, o2, i2, r2] = [...t26];
e2 && e2 instanceof rx.Point && (this.pc = e2.clone()), n2 !== undefined && (this.r = n2), o2 !== undefined && (this.startAngle = o2), i2 !== undefined && (this.endAngle = i2), r2 !== undefined && (this.counterClockwise = r2);
}
}
clone() {
return new rx.Arc(this.pc.clone(), this.r, this.startAngle, this.endAngle, this.counterClockwise);
}
get sweep() {
let t26 = this.startAngle, e2 = this.endAngle;
if (rx.Utils.EQ(Math.abs(t26 - e2), rx.PIx2))
return rx.PIx2;
Math.abs(t26) > rx.PIx2 && (t26 -= Math.trunc(t26 / rx.PIx2) * rx.PIx2), t26 < 0 && (t26 += rx.PIx2), Math.abs(e2) > rx.PIx2 && (e2 -= Math.trunc(e2 / rx.PIx2) * rx.PIx2), e2 < 0 && (e2 += rx.PIx2);
let n2 = this.counterClockwise ? e2 - t26 : t26 - e2;
return n2 < 0 && (n2 += rx.PIx2), n2;
}
get start() {
return new rx.Point(this.pc.x + this.r, this.pc.y).rotate(this.startAngle, this.pc);
}
get end() {
return new rx.Point(this.pc.x + this.r, this.pc.y).rotate(this.endAngle, this.pc);
}
get center() {
return this.pc.clone();
}
get vertices() {
return [this.start.clone(), this.end.clone()];
}
get length() {
return Math.abs(this.sweep * this.r);
}
get box() {
let t26 = this.breakToFunctional().reduce((t27, e2) => t27.merge(e2.start.box), new rx.Box);
return t26 = t26.merge(this.end.box), t26;
}
contains(t26) {
if (!rx.Utils.EQ(this.pc.distanceTo(t26)[0], this.r))
return false;
if (t26.equalTo(this.start))
return true;
let e2 = new rx.Vector(this.pc, t26).slope, n2 = new rx.Arc(this.pc, this.r, this.startAngle, e2, this.counterClockwise);
return rx.Utils.LE(n2.length, this.length);
}
split(t26) {
if (this.start.equalTo(t26))
return [null, this.clone()];
if (this.end.equalTo(t26))
return [this.clone(), null];
let e2 = new rx.Vector(this.pc, t26).slope;
return [new rx.Arc(this.pc, this.r, this.startAngle, e2, this.counterClockwise), new rx.Arc(this.pc, this.r, e2, this.endAngle, this.counterClockwise)];
}
middle() {
let t26 = this.counterClockwise ? this.startAngle + this.sweep / 2 : this.startAngle - this.sweep / 2;
return new rx.Arc(this.pc, this.r, this.startAngle, t26, this.counterClockwise).end;
}
pointAtLength(t26) {
if (t26 > this.length || t26 < 0)
return null;
if (t26 === 0)
return this.start;
if (t26 === this.length)
return this.end;
let e2 = t26 / this.length, n2 = this.counterClockwise ? this.startAngle + this.sweep * e2 : this.startAngle - this.sweep * e2;
return new rx.Arc(this.pc, this.r, this.startAngle, n2, this.counterClockwise).end;
}
chordHeight() {
return (1 - Math.cos(Math.abs(this.sweep / 2))) * this.r;
}
intersect(t26) {
return t26 instanceof rx.Point ? this.contains(t26) ? [t26] : [] : t26 instanceof rx.Line ? mx(t26, this) : t26 instanceof rx.Ray ? zx(t26, this) : t26 instanceof rx.Circle ? Sx(this, t26) : t26 instanceof rx.Segment ? xx(t26, this) : t26 instanceof rx.Box ? function(t27, e2) {
let n2 = [];
for (let o2 of e2.toSegments()) {
let e3 = xx(o2, t27);
for (let t28 of e3)
n2.push(t28);
}
return n2;
}(this, t26) : t26 instanceof rx.Arc ? Ix(this, t26) : t26 instanceof rx.Polygon ? Tx(this, t26) : t26 instanceof rx.Multiline ? Yx(this, t26) : undefined;
}
distanceTo(t26) {
if (t26 instanceof rx.Point) {
let [e2, n2] = rx.Distance.point2arc(t26, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t26 instanceof rx.Circle) {
let [e2, n2] = rx.Distance.arc2circle(this, t26);
return [e2, n2];
}
if (t26 instanceof rx.Line) {
let [e2, n2] = rx.Distance.arc2line(this, t26);
return [e2, n2];
}
if (t26 instanceof rx.Segment) {
let [e2, n2] = rx.Distance.segment2arc(t26, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t26 instanceof rx.Arc) {
let [e2, n2] = rx.Distance.arc2arc(this, t26);
return [e2, n2];
}
if (t26 instanceof rx.Box) {
let [e2, n2] = rx.Distance.shape2polygon(this, new rx.Polygon(t26));
return [e2, n2];
}
if (t26 instanceof rx.Polygon) {
let [e2, n2] = rx.Distance.shape2polygon(this, t26);
return [e2, n2];
}
if (t26 instanceof rx.PlanarSet) {
let [e2, n2] = rx.Distance.shape2planarSet(this, t26);
return [e2, n2];
}
if (t26 instanceof rx.Multiline)
return rx.Distance.shape2multiline(this, t26);
}
breakToFunctional() {
let t26 = [], e2 = [0, Math.PI / 2, Math.PI, 3 * Math.PI / 2], n2 = this.startAngle, o2 = this.endAngle;
rx.Utils.EQ(Math.abs(n2 - o2), rx.PIx2) && (o2 = n2), Math.abs(n2) > rx.PIx2 && (n2 -= Math.trunc(n2 / rx.PIx2) * rx.PIx2), n2 < 0 && (n2 += rx.PIx2), Math.abs(o2) > rx.PIx2 && (o2 -= Math.trunc(o2 / rx.PIx2) * rx.PIx2), o2 < 0 && (o2 += rx.PIx2);
let i2, r2, s2, a2 = n2;
this.counterClockwise ? (r2 = Math.ceil(n2 / (Math.PI / 2)) % 4, s2 = 1) : (r2 = Math.floor(n2 / (Math.PI / 2)) % 4, s2 = -1);
for (let o3 = 0, c2 = r2;o3 < 4; o3++, c2 = (c2 + s2 + 4) % 4) {
if (i2 = e2[c2], i2 === a2)
continue;
let o4 = this.counterClockwise ? i2 - n2 : n2 - i2;
if (o4 < 0 && (o4 += rx.PIx2), o4 > this.sweep)
break;
t26.push(new rx.Arc(this.pc, this.r, a2, i2, this.counterClockwise)), a2 = i2;
}
return t26.length === 0 ? (t26.push(this), t26) : (i2 = o2, a2 !== i2 && t26.push(new rx.Arc(this.pc, this.r, a2, i2, this.counterClockwise)), t26);
}
tangentInStart() {
let t26 = new rx.Vector(this.pc, this.start), e2 = this.counterClockwise ? Math.PI / 2 : -Math.PI / 2;
return t26.rotate(e2).normalize();
}
tangentInEnd() {
let t26 = new rx.Vector(this.pc, this.end), e2 = this.counterClockwise ? -Math.PI / 2 : Math.PI / 2;
return t26.rotate(e2).normalize();
}
reverse() {
return new rx.Arc(this.pc, this.r, this.endAngle, this.startAngle, !this.counterClockwise);
}
transform(t26 = new rx.Matrix) {
let e2 = this.start.transform(t26), n2 = this.end.transform(t26), o2 = this.pc.transform(t26), i2 = this.counterClockwise;
return t26.a * t26.d < 0 && (i2 = !i2), rx.Arc.arcSE(o2, e2, n2, i2);
}
static arcSE(t26, e2, n2, o2) {
let { vector: i2 } = rx, r2 = i2(t26, e2).slope, s2 = i2(t26, n2).slope;
rx.Utils.EQ(r2, s2) && (s2 += 2 * Math.PI, o2 = true);
let a2 = i2(t26, e2).length;
return new rx.Arc(t26, a2, r2, s2, o2);
}
definiteIntegral(t26 = 0) {
return this.breakToFunctional().reduce((e2, n2) => e2 + n2.circularSegmentDefiniteIntegral(t26), 0);
}
circularSegmentDefiniteIntegral(t26) {
let e2 = new rx.Segment(this.start, this.end).definiteIntegral(t26), n2 = rx.Utils.EQ(this.sweep, rx.PIx2) ? 0 : this.circularSegmentArea();
return this.counterClockwise ? e2 - n2 : e2 + n2;
}
circularSegmentArea() {
return 0.5 * this.r * this.r * (this.sweep - Math.sin(this.sweep));
}
sortPoints(t26) {
let { vector: e2 } = rx;
return t26.slice().sort((t27, n2) => {
let o2 = e2(this.pc, t27).slope, i2 = e2(this.pc, n2).slope;
return o2 < i2 ? -1 : o2 > i2 ? 1 : 0;
});
}
get name() {
return "arc";
}
svg(t26 = {}) {
let e2 = this.sweep <= Math.PI ? "0" : "1", n2 = this.counterClockwise ? "1" : "0";
if (rx.Utils.EQ(this.sweep, 2 * Math.PI)) {
return new rx.Circle(this.pc, this.r).svg(t26);
}
return `
<path d="M${this.start.x},${this.start.y}
A${this.r},${this.r} 0 ${e2},${n2} ${this.end.x},${this.end.y}"
${hx({ fill: "none", ...t26 })} />`;
}
};
rx.arc = (...t26) => new rx.Arc(...t26);
rx.Box = class t26 extends Hv {
constructor(t27 = undefined, e2 = undefined, n2 = undefined, o2 = undefined) {
super(), this.xmin = t27, this.ymin = e2, this.xmax = n2, this.ymax = o2;
}
clone() {
return new t26(this.xmin, this.ymin, this.xmax, this.ymax);
}
get low() {
return new rx.Point(this.xmin, this.ymin);
}
get high() {
return new rx.Point(this.xmax, this.ymax);
}
get max() {
return this.clone();
}
get center() {
return new rx.Point((this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2);
}
get width() {
return Math.abs(this.xmax - this.xmin);
}
get height() {
return Math.abs(this.ymax - this.ymin);
}
get box() {
return this.clone();
}
not_intersect(t27) {
return this.xmax < t27.xmin || this.xmin > t27.xmax || this.ymax < t27.ymin || this.ymin > t27.ymax;
}
intersect(t27) {
return !this.not_intersect(t27);
}
merge(e2) {
return new t26(this.xmin === undefined ? e2.xmin : Math.min(this.xmin, e2.xmin), this.ymin === undefined ? e2.ymin : Math.min(this.ymin, e2.ymin), this.xmax === undefined ? e2.xmax : Math.max(this.xmax, e2.xmax), this.ymax === undefined ? e2.ymax : Math.max(this.ymax, e2.ymax));
}
less_than(t27) {
return !!this.low.lessThan(t27.low) || !(!this.low.equalTo(t27.low) || !this.high.lessThan(t27.high));
}
equal_to(t27) {
return this.low.equalTo(t27.low) && this.high.equalTo(t27.high);
}
output() {
return this.clone();
}
comparable_less_than(t27, e2) {
return t27.lessThan(e2);
}
set(t27, e2, n2, o2) {
this.xmin = t27, this.ymin = e2, this.xmax = n2, this.ymax = o2;
}
extend(e2) {
return e2 <= 0 ? this.clone() : new t26(this.xmin - e2, this.ymin - e2, this.xmax + e2, this.ymax + e2);
}
toPoints() {
return [new rx.Point(this.xmin, this.ymin), new rx.Point(this.xmax, this.ymin), new rx.Point(this.xmax, this.ymax), new rx.Point(this.xmin, this.ymax)];
}
toSegments() {
let t27 = this.toPoints();
return [new rx.Segment(t27[0], t27[1]), new rx.Segment(t27[1], t27[2]), new rx.Segment(t27[2], t27[3]), new rx.Segment(t27[3], t27[0])];
}
rotate(t27, e2 = new rx.Point) {
throw sx.OPERATION_IS_NOT_SUPPORTED;
}
transform(e2 = new rx.Matrix) {
return this.toPoints().map((t27) => t27.transform(e2)).reduce((t27, e3) => t27.merge(e3.box), new t26);
}
contains(t27) {
return t27 instanceof rx.Point ? t27.x >= this.xmin && t27.x <= this.xmax && t27.y >= this.ymin && t27.y <= this.ymax : t27 instanceof rx.Segment ? t27.vertices.every((t28) => this.contains(t28)) : t27 instanceof rx.Box ? t27.toSegments().every((t28) => this.contains(t28)) : t27 instanceof rx.Circle ? this.contains(t27.box) : t27 instanceof rx.Arc ? t27.vertices.every((t28) => this.contains(t28)) && this.toSegments().every((e2) => xx(e2, t27).length === 0) : !(t27 instanceof rx.Line || t27 instanceof rx.Ray) && (t27 instanceof rx.Multiline ? t27.toShapes().every((t28) => this.contains(t28)) : t27 instanceof rx.Polygon ? this.contains(t27.box) : undefined);
}
distanceTo(t27) {
const e2 = this.toSegments().map((e3) => e3.distanceTo(t27));
let n2 = [Number.MAX_SAFE_INTEGER, null];
return e2.forEach((t28) => {
t28[0] < n2[0] && (n2 = t28);
}), n2;
}
get name() {
return "box";
}
svg(t27 = {}) {
const e2 = this.xmax - this.xmin, n2 = this.ymax - this.ymin;
return `
<rect x="${this.xmin}" y="${this.ymin}" width="${e2}" height="${n2}"
${hx({ fill: "none", ...t27 })} />`;
}
};
rx.box = (...t27) => new rx.Box(...t27);
rx.Edge = class {
constructor(t27) {
this.shape = t27, this.next = undefined, this.prev = undefined, this.face = undefined, this.arc_length = 0, this.bvStart = undefined, this.bvEnd = undefined, this.bv = undefined, this.overlap = undefined;
}
get start() {
return this.shape.start;
}
get end() {
return this.shape.end;
}
get length() {
return this.shape.length;
}
get box() {
return this.shape.box;
}
get isSegment() {
return this.shape instanceof rx.Segment;
}
get isArc() {
return this.shape instanceof rx.Arc;
}
get isLine() {
return this.shape instanceof rx.Line;
}
get isRay() {
return this.shape instanceof rx.Ray;
}
middle() {
return this.shape.middle();
}
pointAtLength(t27) {
return this.shape.pointAtLength(t27);
}
contains(t27) {
return this.shape.contains(t27);
}
setInclusion(t27) {
if (this.bv !== undefined)
return this.bv;
if (this.shape instanceof rx.Line || this.shape instanceof rx.Ray)
return this.bv = rx.OUTSIDE, this.bv;
if (this.bvStart === undefined && (this.bvStart = Ev(t27, this.start)), this.bvEnd === undefined && (this.bvEnd = Ev(t27, this.end)), this.bvStart === rx.OUTSIDE || this.bvEnd == rx.OUTSIDE)
this.bv = rx.OUTSIDE;
else if (this.bvStart === rx.INSIDE || this.bvEnd == rx.INSIDE)
this.bv = rx.INSIDE;
else {
let e2 = Ev(t27, this.middle());
this.bv = e2;
}
return this.bv;
}
setOverlap(t27) {
let e2, n2 = this.shape, o2 = t27.shape;
n2 instanceof rx.Segment && o2 instanceof rx.Segment ? n2.start.equalTo(o2.start) && n2.end.equalTo(o2.end) ? e2 = rx.OVERLAP_SAME : n2.start.equalTo(o2.end) && n2.end.equalTo(o2.start) && (e2 = rx.OVERLAP_OPPOSITE) : (n2 instanceof rx.Arc && o2 instanceof rx.Arc || n2 instanceof rx.Segment && o2 instanceof rx.Arc || n2 instanceof rx.Arc && o2 instanceof rx.Segment) && (n2.start.equalTo(o2.start) && n2.end.equalTo(o2.end) && n2.middle().equalTo(o2.middle()) ? e2 = rx.OVERLAP_SAME : n2.start.equalTo(o2.end) && n2.end.equalTo(o2.start) && n2.middle().equalTo(o2.middle()) && (e2 = rx.OVERLAP_OPPOSITE)), this.overlap === undefined && (this.overlap = e2), t27.overlap === undefined && (t27.overlap = e2);
}
svg() {
if (this.shape instanceof rx.Segment)
return ` L${this.shape.end.x},${this.shape.end.y}`;
if (this.shape instanceof rx.Arc) {
let t27, e2 = this.shape, n2 = e2.counterClockwise ? "1" : "0";
if (rx.Utils.EQ(e2.sweep, 2 * Math.PI)) {
let o2 = e2.counterClockwise ? 1 : -1, i2 = new rx.Arc(e2.pc, e2.r, e2.startAngle, e2.startAngle + o2 * Math.PI, e2.counterClockwise), r2 = new rx.Arc(e2.pc, e2.r, e2.startAngle + o2 * Math.PI, e2.endAngle, e2.counterClockwise);
return t27 = "0", ` A${i2.r},${i2.r} 0 ${t27},${n2} ${i2.end.x},${i2.end.y}
A${r2.r},${r2.r} 0 ${t27},${n2} ${r2.end.x},${r2.end.y}`;
}
return t27 = e2.sweep <= Math.PI ? "0" : "1", ` A${e2.r},${e2.r} 0 ${t27},${n2} ${e2.end.x},${e2.end.y}`;
}
}
toJSON() {
return this.shape.toJSON();
}
};
var Qv = class extends ax {
constructor(t27, e2) {
super(t27, e2), this.setCircularLinks();
}
setCircularLinks() {
this.isEmpty() || (this.last.next = this.first, this.first.prev = this.last);
}
[Symbol.iterator]() {
let t27;
return { next: () => {
let e2 = t27 || this.first, n2 = !this.first || !!t27 && t27 === this.first;
return t27 = e2 ? e2.next : undefined, { value: e2, done: n2 };
} };
}
append(t27) {
return super.append(t27), this.setCircularLinks(), this;
}
insert(t27, e2) {
return super.insert(t27, e2), this.setCircularLinks(), this;
}
remove(t27) {
return super.remove(t27), this;
}
};
rx.Face = class t27 extends Qv {
constructor(e2, ...n2) {
if (super(), this._box = undefined, this._orientation = undefined, n2.length !== 0) {
if (n2.length === 1) {
if (n2[0] instanceof Array) {
let o2 = n2[0];
if (o2.length === 0)
return;
if (o2.every((t28) => t28 instanceof rx.Point)) {
let n3 = t27.points2segments(o2);
this.shapes2face(e2.edges, n3);
} else if (o2.every((t28) => t28 instanceof Array && t28.length === 2)) {
let n3 = o2.map((t28) => new rx.Point(t28[0], t28[1])), i2 = t27.points2segments(n3);
this.shapes2face(e2.edges, i2);
} else if (o2.every((t28) => t28 instanceof rx.Segment || t28 instanceof rx.Arc))
this.shapes2face(e2.edges, o2);
else if (o2.every((t28) => t28.name === "segment" || t28.name === "arc")) {
let t28 = [];
for (let e3 of o2) {
let n3;
n3 = e3.name === "segment" ? new rx.Segment(e3) : new rx.Arc(e3), t28.push(n3);
}
this.shapes2face(e2.edges, t28);
}
} else if (n2[0] instanceof t27) {
let t28 = n2[0];
this.first = t28.first, this.last = t28.last;
for (let n3 of t28)
e2.edges.add(n3);
} else if (n2[0] instanceof rx.Circle)
this.shapes2face(e2.edges, [n2[0].toArc(Ub)]);
else if (n2[0] instanceof rx.Box) {
let t28 = n2[0];
this.shapes2face(e2.edges, [new rx.Segment(new rx.Point(t28.xmin, t28.ymin), new rx.Point(t28.xmax, t28.ymin)), new rx.Segment(new rx.Point(t28.xmax, t28.ymin), new rx.Point(t28.xmax, t28.ymax)), new rx.Segment(new rx.Point(t28.xmax, t28.ymax), new rx.Point(t28.xmin, t28.ymax)), new rx.Segment(new rx.Point(t28.xmin, t28.ymax), new rx.Point(t28.xmin, t28.ymin))]);
}
}
n2.length === 2 && n2[0] instanceof rx.Edge && n2[1] instanceof rx.Edge && (this.first = n2[0], this.last = n2[1], this.last.next = this.first, this.first.prev = this.last, this.setArcLength());
}
}
get edges() {
return this.toArray();
}
get vertices() {
return this.edges.map((t28) => t28.shape.start.clone());
}
get shapes() {
return this.edges.map((t28) => t28.shape.clone());
}
get box() {
if (this._box === undefined) {
let t28 = new rx.Box;
for (let e2 of this)
t28 = t28.merge(e2.box);
this._box = t28;
}
return this._box;
}
get perimeter() {
return this.last.arc_length + this.last.length;
}
pointAtLength(t28) {
if (t28 > this.perimeter || t28 < 0)
return null;
let e2 = null;
for (let n2 of this)
if (t28 >= n2.arc_length && (n2 === this.last || t28 < n2.next.arc_length)) {
e2 = n2.pointAtLength(t28 - n2.arc_length);
break;
}
return e2;
}
static points2segments(t28) {
let e2 = [];
for (let n2 = 0;n2 < t28.length; n2++)
t28[n2].equalTo(t28[(n2 + 1) % t28.length]) || e2.push(new rx.Segment(t28[n2], t28[(n2 + 1) % t28.length]));
return e2;
}
shapes2face(t28, e2) {
for (let n2 of e2) {
let e3 = new rx.Edge(n2);
this.append(e3), t28.add(e3);
}
}
append(t28) {
return super.append(t28), this.setOneEdgeArcLength(t28), t28.face = this, this;
}
insert(t28, e2) {
return super.insert(t28, e2), this.setOneEdgeArcLength(t28), t28.face = this, this;
}
remove(t28) {
return super.remove(t28), this.setArcLength(), this;
}
merge_with_next_edge(t28) {
return t28.shape.end.x = t28.next.shape.end.x, t28.shape.end.y = t28.next.shape.end.y, this.remove(t28.next), this;
}
reverse() {
let t28 = [], e2 = this.last;
do {
e2.shape = e2.shape.reverse(), t28.push(e2), e2 = e2.prev;
} while (e2 !== this.last);
this.first = undefined, this.last = undefined;
for (let e3 of t28)
this.first === undefined ? (e3.prev = e3, e3.next = e3, this.first = e3, this.last = e3) : (e3.prev = this.last, this.last.next = e3, this.last = e3, this.last.next = this.first, this.first.prev = this.last), this.setOneEdgeArcLength(e3);
this._orientation !== undefined && (this._orientation = undefined, this._orientation = this.orientation());
}
setArcLength() {
for (let t28 of this)
this.setOneEdgeArcLength(t28), t28.face = this;
}
setOneEdgeArcLength(t28) {
t28 === this.first ? t28.arc_length = 0 : t28.arc_length = t28.prev.arc_length + t28.prev.length;
}
area() {
return Math.abs(this.signedArea());
}
signedArea() {
let t28 = 0, e2 = this.box.ymin;
for (let n2 of this)
t28 += n2.shape.definiteIntegral(e2);
return t28;
}
orientation() {
if (this._orientation === undefined) {
let t28 = this.signedArea();
rx.Utils.EQ_0(t28) ? this._orientation = Zb.NOT_ORIENTABLE : rx.Utils.LT(t28, 0) ? this._orientation = Zb.CCW : this._orientation = Zb.CW;
}
return this._orientation;
}
isSimple(e2) {
return t27.getSelfIntersections(this, e2, true).length === 0;
}
static getSelfIntersections(t28, e2, n2 = false) {
let o2 = [];
for (let i2 of t28) {
let r2 = e2.search(i2.box);
for (let e3 of r2) {
if (i2 === e3)
continue;
if (e3.face !== t28)
continue;
if (i2.shape instanceof rx.Segment && e3.shape instanceof rx.Segment && (i2.next === e3 || i2.prev === e3))
continue;
let r3 = i2.shape.intersect(e3.shape);
for (let t29 of r3)
if ((!t29.equalTo(i2.start) || !t29.equalTo(e3.end) || e3 !== i2.prev) && (!t29.equalTo(i2.end) || !t29.equalTo(e3.start) || e3 !== i2.next) && (o2.push(t29), n2))
break;
if (o2.length > 0 && n2)
break;
}
if (o2.length > 0 && n2)
break;
}
return o2;
}
findEdgeByPoint(t28) {
let e2;
for (let n2 of this)
if (!t28.equalTo(n2.shape.start) && (t28.equalTo(n2.shape.end) || n2.shape.contains(t28))) {
e2 = n2;
break;
}
return e2;
}
toPolygon() {
return new rx.Polygon(this.shapes);
}
toJSON() {
return this.edges.map((t28) => t28.toJSON());
}
svg() {
let t28 = `M${this.first.start.x},${this.first.start.y}`;
for (let e2 of this)
t28 += e2.svg();
return t28 += " z", t28;
}
};
rx.Ray = class t28 extends Hv {
constructor(...t29) {
if (super(), this.pt = new rx.Point, this.norm = new rx.Vector(0, 1), t29.length !== 0 && (t29.length >= 1 && t29[0] instanceof rx.Point && (this.pt = t29[0].clone()), t29.length !== 1)) {
if (!(t29.length === 2 && t29[1] instanceof rx.Vector))
throw sx.ILLEGAL_PARAMETERS;
this.norm = t29[1].clone();
}
}
clone() {
return new t28(this.pt, this.norm);
}
get slope() {
return new rx.Vector(this.norm.y, -this.norm.x).slope;
}
get box() {
let t29 = this.slope;
return new rx.Box(t29 > Math.PI / 2 && t29 < 3 * Math.PI / 2 ? Number.NEGATIVE_INFINITY : this.pt.x, t29 >= 0 && t29 <= Math.PI ? this.pt.y : Number.NEGATIVE_INFINITY, t29 >= Math.PI / 2 && t29 <= 3 * Math.PI / 2 ? this.pt.x : Number.POSITIVE_INFINITY, t29 >= Math.PI && t29 <= 2 * Math.PI || t29 === 0 ? this.pt.y : Number.POSITIVE_INFINITY);
}
get start() {
return this.pt;
}
get end() {}
get length() {
return Number.POSITIVE_INFINITY;
}
contains(t29) {
if (this.pt.equalTo(t29))
return true;
let e2 = new rx.Vector(this.pt, t29);
return rx.Utils.EQ_0(this.norm.dot(e2)) && rx.Utils.GE(e2.cross(this.norm), 0);
}
coord(t29) {
return Uv(t29.x, t29.y).cross(this.norm);
}
split(t29) {
return this.contains(t29) ? this.pt.equalTo(t29) ? [this] : [new rx.Segment(this.pt, t29), new rx.Ray(t29, this.norm)] : [];
}
intersect(t29) {
return t29 instanceof rx.Point ? this.contains(t29) ? [t29] : [] : t29 instanceof rx.Segment ? Lx(this, t29) : t29 instanceof rx.Arc ? zx(this, t29) : t29 instanceof rx.Line ? Fx(this, t29) : t29 instanceof rx.Ray ? (n2 = t29, dx(Dx(e2 = this), Dx(n2)).filter((t30) => e2.contains(t30)).filter((t30) => n2.contains(t30))) : t29 instanceof rx.Circle ? Bx(this, t29) : t29 instanceof rx.Box ? (i2 = t29, px(Dx(o2 = this), i2).filter((t30) => o2.contains(t30))) : t29 instanceof rx.Polygon ? jx(this, t29) : t29 instanceof rx.Multiline ? Yx(this, t29) : undefined;
var e2, n2, o2, i2;
}
rotate(t29, e2 = new rx.Point) {
return new rx.Ray(this.pt.rotate(t29, e2), this.norm.rotate(t29));
}
transform(t29) {
return new rx.Ray(this.pt.transform(t29), this.norm.clone());
}
get name() {
return "ray";
}
svg(t29, e2 = {}) {
let n2 = px(new rx.Line(this.pt, this.norm), t29);
return n2 = n2.filter((t30) => this.contains(t30)), n2.length === 0 || n2.length === 2 ? "" : new rx.Segment(this.pt, n2[0]).svg(e2);
}
};
rx.ray = (...t29) => new rx.Ray(...t29);
var Kv = class t29 {
constructor() {
this.faces = new rx.PlanarSet, this.edges = new rx.PlanarSet;
let t30 = [...arguments];
if (t30.length === 1 && (t30[0] instanceof Array && t30[0].length > 0 || t30[0] instanceof rx.Circle || t30[0] instanceof rx.Box)) {
let e2 = t30[0];
if (t30[0] instanceof Array && t30[0].every((t31) => t31 instanceof Array))
if (e2.every((t31) => t31 instanceof Array && t31.length === 2 && typeof t31[0] == "number" && typeof t31[1] == "number"))
this.faces.add(new rx.Face(this, e2));
else
for (let t31 of e2)
if (t31 instanceof Array && t31[0] instanceof Array && t31[0].every((t32) => t32 instanceof Array && t32.length === 2 && typeof t32[0] == "number" && typeof t32[1] == "number"))
for (let e3 of t31)
this.faces.add(new rx.Face(this, e3));
else
this.faces.add(new rx.Face(this, t31));
else
this.faces.add(new rx.Face(this, e2));
}
}
get box() {
return [...this.faces].reduce((t30, e2) => t30.merge(e2.box), new rx.Box);
}
get vertices() {
return [...this.faces].flatMap((t30) => t30.vertices);
}
clone() {
let e2 = new t29;
for (let t30 of this.faces)
e2.addFace(t30.shapes);
return e2;
}
createFromArray(e2) {
const n2 = new t29;
return e2.forEach((t30) => [...t30.faces].forEach((t31) => n2.addFace(t31.shapes))), n2;
}
isEmpty() {
return this.edges.size === 0 || this.faces.size === 0;
}
isValid() {
let t30 = true;
for (let e2 of this.faces)
if (!e2.isSimple(this.edges)) {
t30 = false;
break;
}
return t30;
}
area() {
let t30 = [...this.faces].reduce((t31, e2) => t31 + e2.signedArea(), 0);
return Math.abs(t30);
}
addFace(...t30) {
let e2 = new rx.Face(this, ...t30);
return this.faces.add(e2), e2;
}
deleteFace(t30) {
for (let e2 of t30)
this.edges.delete(e2);
return this.faces.delete(t30);
}
recreateFaces() {
this.faces.clear();
for (let t31 of this.edges)
t31.face = null;
let t30, e2 = true;
for (;e2; ) {
e2 = false;
for (let n2 of this.edges)
if (n2.face === null) {
t30 = n2, e2 = true;
break;
}
if (e2) {
let e3 = t30;
do {
e3 = e3.next;
} while (e3.next !== t30);
this.addFace(t30, e3);
}
}
}
removeChain(t30, e2, n2) {
if (n2.next !== e2) {
for (let o2 = e2;o2 !== n2.next; o2 = o2.next)
if (t30.remove(o2), this.edges.delete(o2), t30.isEmpty()) {
this.deleteFace(t30);
break;
}
} else
this.deleteFace(t30);
}
addVertex(t30, e2) {
let n2 = e2.shape.split(t30);
if (n2[0] === null)
return e2.prev;
if (n2[1] === null)
return e2;
let o2 = new rx.Edge(n2[0]), i2 = e2.prev;
return e2.face.insert(o2, i2), this.edges.delete(e2), this.edges.add(o2), e2.shape = n2[1], this.edges.add(e2), o2;
}
removeEndVertex(t30) {
const e2 = t30.next;
e2 !== t30 && (t30.face.merge_with_next_edge(t30), this.edges.delete(e2));
}
cut(t30) {
const e2 = this.splitToIslands().flatMap((e3) => e3._cutSingleIsland(t30)).filter((t31) => t31.isValid() && t31.isEmpty() === false);
return this.createFromArray(e2);
}
_cutSingleIsland(t30) {
let e2 = this.clone();
const n2 = t30.clone();
let o2, i2, r2 = { int_points1: [], int_points2: [], int_points1_sorted: [], int_points2_sorted: [] };
for (let t31 of n2.edges)
for (let n3 of e2.edges) {
let e3 = Ax(t31, n3);
for (let o3 of e3)
Wx(t31, o3, r2.int_points1), Wx(n3, o3, r2.int_points2);
}
if (r2.int_points1.length === 0)
return e2;
r2.int_points1_sorted = Hx(r2.int_points1), r2.int_points2_sorted = Hx(r2.int_points2), Qx(n2, r2.int_points1_sorted), Qx(e2, r2.int_points2_sorted), Ux(r2), r2.int_points1_sorted = Hx(r2.int_points1), r2.int_points2_sorted = Hx(r2.int_points2), Zx(r2.int_points1), qx(r2.int_points1, e2);
for (let t31 of r2.int_points1_sorted)
t31.edge_before && t31.edge_after && t31.edge_before.bv === t31.edge_after.bv && (r2.int_points2[t31.id] = -1, t31.id = -1);
if (r2.int_points1 = r2.int_points1.filter((t31) => t31.id >= 0), r2.int_points2 = r2.int_points2.filter((t31) => t31.id >= 0), r2.int_points1.forEach((t31, e3) => {
t31.id = e3;
}), r2.int_points2.forEach((t31, e3) => {
t31.id = e3;
}), r2.int_points1.length === 0)
return e2;
r2.int_points1_sorted = Hx(r2.int_points1), r2.int_points2_sorted = Hx(r2.int_points2);
for (let t31 = 1;t31 < r2.int_points1_sorted.length; t31++)
if (i2 = r2.int_points1_sorted[t31], o2 = r2.int_points1_sorted[t31 - 1], i2.edge_before && i2.edge_before.bv === 1) {
let t32 = o2.edge_after, s2 = i2.edge_before, a2 = n2.getChain(t32, s2);
Kx(r2.int_points2[o2.id], r2.int_points2[i2.id], a2), a2.forEach((t33) => e2.edges.add(t33)), a2 = a2.reverse().map((t33) => new rx.Edge(t33.shape.reverse()));
for (let t33 = 0;t33 < a2.length - 1; t33++)
a2[t33].next = a2[t33 + 1], a2[t33 + 1].prev = a2[t33];
Kx(r2.int_points2[i2.id], r2.int_points2[o2.id], a2), a2.forEach((t33) => e2.edges.add(t33));
}
return e2.recreateFaces(), e2;
}
cutWithLine(t30) {
let e2 = new Xx([t30]);
return this.cut(e2);
}
findEdgeByPoint(t30) {
let e2;
for (let n2 of this.faces)
if (e2 = n2.findEdgeByPoint(t30), e2 !== undefined)
break;
return e2;
}
splitToIslands() {
if (this.isEmpty())
return [];
let t30 = this.toArray();
t30.sort((t31, e3) => e3.area() - t31.area());
let e2 = [...t30[0].faces][0].orientation(), n2 = t30.filter((t31) => [...t31.faces][0].orientation() === e2);
for (let o2 of t30) {
let t31 = [...o2.faces][0];
if (t31.orientation() !== e2) {
for (let e3 of n2)
if (t31.shapes.every((t32) => e3.contains(t32))) {
e3.addFace(t31.shapes);
break;
}
}
}
return n2;
}
rearrange() {
if (this.faces.size <= 1)
return this.clone();
const e2 = this.splitToIslands(), n2 = new t29;
return e2.forEach((t30) => {
t30.faces.forEach((t31) => n2.addFace(t31.shapes));
}), n2;
}
orientation() {
return this.isEmpty() ? Zb.NOT_ORIENTABLE : [...this.faces][0].orientation();
}
isOuter(t30) {
return t30.orientation() === this.orientation();
}
isMultiPolygon() {
let t30 = 0;
return this.faces.forEach((e2) => {
this.isOuter(e2) && t30++;
}), t30 > 1;
}
reverse() {
for (let t30 of this.faces)
t30.reverse();
return this;
}
contains(t30) {
if (t30 instanceof rx.Point) {
let e2 = Ev(this, t30);
return e2 === 1 || e2 === 2;
}
return Dv(this, t30);
}
distanceTo(t30) {
if (t30 instanceof rx.Point) {
let [e2, n2] = rx.Distance.point2polygon(t30, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t30 instanceof rx.Circle || t30 instanceof rx.Line || t30 instanceof rx.Segment || t30 instanceof rx.Arc) {
let [e2, n2] = rx.Distance.shape2polygon(t30, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t30 instanceof rx.Box)
return this.distanceTo(new rx.Polygon(t30));
if (t30 instanceof rx.Polygon) {
let e2, n2, o2 = [Number.POSITIVE_INFINITY, new rx.Segment];
for (let i2 of this.edges) {
let r2 = o2[0];
[e2, n2] = rx.Distance.shape2planarSet(i2.shape, t30.edges, r2), rx.Utils.LT(e2, r2) && (o2 = [e2, n2]);
}
return o2;
}
}
intersect(t30) {
return t30 instanceof rx.Point ? this.contains(t30) ? [t30] : [] : t30 instanceof rx.Line ? Rx(t30, this) : t30 instanceof rx.Ray ? jx(t30, this) : t30 instanceof rx.Circle ? Ex(t30, this) : t30 instanceof rx.Segment ? wx(t30, this) : t30 instanceof rx.Arc ? Tx(t30, this) : t30 instanceof rx.Polygon ? function(t31, e2) {
let n2 = [];
if (t31.isEmpty() || e2.isEmpty())
return n2;
if (t31.box.not_intersect(e2.box))
return n2;
for (let o2 of t31.edges)
n2 = [...n2, ...Ox(o2, e2)];
return n2;
}(t30, this) : t30 instanceof rx.Multiline ? function(t31, e2) {
let n2 = [];
if (e2.isEmpty() || t31.size === 0)
return n2;
for (let o2 of t31)
n2 = [...n2, ...Ox(o2, e2)];
return n2;
}(t30, this) : undefined;
}
translate(e2) {
let n2 = new t29;
for (let t30 of this.faces)
n2.addFace(t30.shapes.map((t31) => t31.translate(e2)));
return n2;
}
rotate(e2 = 0, n2 = new rx.Point) {
let o2 = new t29;
for (let t30 of this.faces)
o2.addFace(t30.shapes.map((t31) => t31.rotate(e2, n2)));
return o2;
}
scale(e2, n2) {
let o2 = new t29;
for (let t30 of this.faces)
o2.addFace(t30.shapes.map((t31) => t31.scale(e2, n2)));
return o2;
}
transform(e2 = new rx.Matrix) {
let n2 = new t29;
for (let t30 of this.faces)
n2.addFace(t30.shapes.map((t31) => t31.transform(e2)));
return n2;
}
toJSON() {
return [...this.faces].map((t30) => t30.toJSON());
}
toArray() {
return [...this.faces].map((t30) => t30.toPolygon());
}
dpath() {
return [...this.faces].reduce((t30, e2) => t30 + e2.svg(), "");
}
svg(t30 = {}) {
let e2 = `
<path ${hx({ fillRule: "evenodd", fill: "lightcyan", ...t30 })} d="`;
for (let t31 of this.faces)
e2 += `
${t31.svg()}`;
return e2 += `" >
</path>`, e2;
}
};
rx.Polygon = Kv;
rx.polygon = (...t30) => new rx.Polygon(...t30);
var { Circle: tI, Line: eI, Point: nI, Vector: oI, Utils: iI } = rx;
rx.Inversion = class t30 {
constructor(t31) {
this.circle = t31;
}
get inversion_circle() {
return this.circle;
}
static inversePoint(t31, e2) {
const n2 = new oI(t31.pc, e2), o2 = t31.r * t31.r, i2 = n2.dot(n2);
return iI.EQ_0(i2) ? new nI(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY) : t31.pc.translate(n2.multiply(o2 / i2));
}
static inverseCircle(t31, e2) {
const n2 = t31.pc.distanceTo(e2.pc)[0];
if (iI.EQ(n2, e2.r)) {
let n3 = t31.r * t31.r / (2 * e2.r), o2 = new oI(t31.pc, e2.pc);
o2 = o2.normalize();
let i2 = t31.pc.translate(o2.multiply(n3));
return new eI(i2, o2);
}
{
let n3 = new oI(t31.pc, e2.pc), o2 = t31.r * t31.r / (n3.dot(n3) - e2.r * e2.r), i2 = t31.pc.translate(n3.multiply(o2)), r2 = Math.abs(o2) * e2.r;
return new tI(i2, r2);
}
}
static inverseLine(t31, e2) {
const [n2, o2] = t31.pc.distanceTo(e2);
if (iI.EQ_0(n2))
return e2.clone();
{
let e3 = t31.r * t31.r / (2 * n2), i2 = new oI(t31.pc, o2.end);
return i2 = i2.multiply(e3 / n2), new tI(t31.pc.translate(i2), e3);
}
}
inverse(e2) {
return e2 instanceof nI ? t30.inversePoint(this.circle, e2) : e2 instanceof tI ? t30.inverseCircle(this.circle, e2) : e2 instanceof eI ? t30.inverseLine(this.circle, e2) : undefined;
}
};
rx.inversion = (t31) => new rx.Inversion(t31);
rx.Distance = class t31 {
static point2point(t32, e2) {
return t32.distanceTo(e2);
}
static point2line(t32, e2) {
let n2 = t32.projectionOn(e2);
return [new rx.Vector(t32, n2).length, new rx.Segment(t32, n2)];
}
static point2circle(t32, e2) {
let [n2, o2] = t32.distanceTo(e2.center);
if (rx.Utils.EQ_0(n2))
return [e2.r, new rx.Segment(t32, e2.toArc().start)];
{
let o3 = Math.abs(n2 - e2.r), i2 = new rx.Vector(e2.pc, t32).normalize().multiply(e2.r), r2 = e2.pc.translate(i2);
return [o3, new rx.Segment(t32, r2)];
}
}
static point2segment(e2, n2) {
if (n2.start.equalTo(n2.end))
return t31.point2point(e2, n2.start);
let o2, i2, r2 = new rx.Vector(n2.start, n2.end), s2 = new rx.Vector(n2.start, e2), a2 = new rx.Vector(n2.end, e2), c2 = r2.dot(s2), l2 = -r2.dot(a2);
if (rx.Utils.GE(c2, 0) && rx.Utils.GE(l2, 0)) {
let t32 = n2.tangentInStart();
return o2 = Math.abs(t32.cross(s2)), i2 = n2.start.translate(t32.multiply(t32.dot(s2))), [o2, new rx.Segment(e2, i2)];
}
return c2 < 0 ? e2.distanceTo(n2.start) : e2.distanceTo(n2.end);
}
static point2arc(e2, n2) {
let o2, i2, r2 = new rx.Circle(n2.pc, n2.r), s2 = [];
return [o2, i2] = t31.point2circle(e2, r2), i2.end.on(n2) && s2.push(t31.point2circle(e2, r2)), s2.push(t31.point2point(e2, n2.start)), s2.push(t31.point2point(e2, n2.end)), t31.sort(s2), s2[0];
}
static point2edge(e2, n2) {
return n2.shape instanceof rx.Segment ? t31.point2segment(e2, n2.shape) : t31.point2arc(e2, n2.shape);
}
static segment2line(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new rx.Segment(o2[0], o2[0])];
let i2 = [];
return i2.push(t31.point2line(e2.start, n2)), i2.push(t31.point2line(e2.end, n2)), t31.sort(i2), i2[0];
}
static segment2segment(e2, n2) {
let o2 = fx(e2, n2);
if (o2.length > 0)
return [0, new rx.Segment(o2[0], o2[0])];
let i2, r2, s2 = [];
return [i2, r2] = t31.point2segment(n2.start, e2), s2.push([i2, r2.reverse()]), [i2, r2] = t31.point2segment(n2.end, e2), s2.push([i2, r2.reverse()]), s2.push(t31.point2segment(e2.start, n2)), s2.push(t31.point2segment(e2.end, n2)), t31.sort(s2), s2[0];
}
static segment2circle(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new rx.Segment(o2[0], o2[0])];
let i2 = new rx.Line(e2.ps, e2.pe), [r2, s2] = t31.point2line(n2.center, i2);
if (rx.Utils.GE(r2, n2.r) && s2.end.on(e2))
return t31.point2circle(s2.end, n2);
{
let [o3, i3] = t31.point2circle(e2.start, n2), [r3, s3] = t31.point2circle(e2.end, n2);
return rx.Utils.LT(o3, r3) ? [o3, i3] : [r3, s3];
}
}
static segment2arc(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new rx.Segment(o2[0], o2[0])];
let i2 = new rx.Line(e2.ps, e2.pe), r2 = new rx.Circle(n2.pc, n2.r), [s2, a2] = t31.point2line(r2.center, i2);
if (rx.Utils.GE(s2, r2.r) && a2.end.on(e2)) {
let [e3, o3] = t31.point2circle(a2.end, r2);
if (o3.end.on(n2))
return [e3, o3];
}
let c2, l2, h2 = [];
return h2.push(t31.point2arc(e2.start, n2)), h2.push(t31.point2arc(e2.end, n2)), [c2, l2] = t31.point2segment(n2.start, e2), h2.push([c2, l2.reverse()]), [c2, l2] = t31.point2segment(n2.end, e2), h2.push([c2, l2.reverse()]), t31.sort(h2), h2[0];
}
static circle2circle(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new rx.Segment(o2[0], o2[0])];
if (e2.center.equalTo(n2.center)) {
let o3 = e2.toArc(), i2 = n2.toArc();
return t31.point2point(o3.start, i2.start);
}
{
let o3 = new rx.Line(e2.center, n2.center), i2 = o3.intersect(e2), r2 = o3.intersect(n2), s2 = [];
return s2.push(t31.point2point(i2[0], r2[0])), s2.push(t31.point2point(i2[0], r2[1])), s2.push(t31.point2point(i2[1], r2[0])), s2.push(t31.point2point(i2[1], r2[1])), t31.sort(s2), s2[0];
}
}
static circle2line(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new rx.Segment(o2[0], o2[0])];
let [i2, r2] = t31.point2line(e2.center, n2), [s2, a2] = t31.point2circle(r2.end, e2);
return a2 = a2.reverse(), [s2, a2];
}
static arc2line(e2, n2) {
let o2 = n2.intersect(e2);
if (o2.length > 0)
return [0, new rx.Segment(o2[0], o2[0])];
let i2 = new rx.Circle(e2.center, e2.r), [r2, s2] = t31.point2line(i2.center, n2);
if (!rx.Utils.GE(r2, i2.r)) {
let o3 = [];
return o3.push(t31.point2line(e2.start, n2)), o3.push(t31.point2line(e2.end, n2)), t31.sort(o3), o3[0];
}
{
let [n3, o3] = t31.point2circle(s2.end, i2);
if (o3.end.on(e2))
return [n3, o3];
}
}
static arc2circle(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new rx.Segment(o2[0], o2[0])];
let i2 = new rx.Circle(e2.center, e2.r), [r2, s2] = t31.circle2circle(i2, n2);
if (s2.start.on(e2))
return [r2, s2];
{
let o3 = [];
return o3.push(t31.point2circle(e2.start, n2)), o3.push(t31.point2circle(e2.end, n2)), t31.sort(o3), o3[0];
}
}
static arc2arc(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new rx.Segment(o2[0], o2[0])];
let i2 = new rx.Circle(e2.center, e2.r), r2 = new rx.Circle(n2.center, n2.r), [s2, a2] = t31.circle2circle(i2, r2);
if (a2.start.on(e2) && a2.end.on(n2))
return [s2, a2];
{
let o3, i3, r3 = [];
return [o3, i3] = t31.point2arc(e2.start, n2), i3.end.on(n2) && r3.push([o3, i3]), [o3, i3] = t31.point2arc(e2.end, n2), i3.end.on(n2) && r3.push([o3, i3]), [o3, i3] = t31.point2arc(n2.start, e2), i3.end.on(e2) && r3.push([o3, i3.reverse()]), [o3, i3] = t31.point2arc(n2.end, e2), i3.end.on(e2) && r3.push([o3, i3.reverse()]), [o3, i3] = t31.point2point(e2.start, n2.start), r3.push([o3, i3]), [o3, i3] = t31.point2point(e2.start, n2.end), r3.push([o3, i3]), [o3, i3] = t31.point2point(e2.end, n2.start), r3.push([o3, i3]), [o3, i3] = t31.point2point(e2.end, n2.end), r3.push([o3, i3]), t31.sort(r3), r3[0];
}
}
static point2polygon(e2, n2) {
let o2 = [Number.POSITIVE_INFINITY, new rx.Segment];
for (let i2 of n2.edges) {
let [n3, r2] = t31.point2edge(e2, i2);
rx.Utils.LT(n3, o2[0]) && (o2 = [n3, r2]);
}
return o2;
}
static shape2polygon(t32, e2) {
let n2 = [Number.POSITIVE_INFINITY, new rx.Segment];
for (let o2 of e2.edges) {
let [e3, i2] = t32.distanceTo(o2.shape);
rx.Utils.LT(e3, n2[0]) && (n2 = [e3, i2]);
}
return n2;
}
static polygon2polygon(t32, e2) {
let n2 = [Number.POSITIVE_INFINITY, new rx.Segment];
for (let o2 of t32.edges)
for (let t33 of e2.edges) {
let [e3, i2] = o2.shape.distanceTo(t33.shape);
rx.Utils.LT(e3, n2[0]) && (n2 = [e3, i2]);
}
return n2;
}
static box2box_minmax(t32, e2) {
let n2 = Math.max(Math.max(t32.xmin - e2.xmax, 0), Math.max(e2.xmin - t32.xmax, 0)), o2 = Math.max(Math.max(t32.ymin - e2.ymax, 0), Math.max(e2.ymin - t32.ymax, 0)), i2 = n2 * n2 + o2 * o2, r2 = t32.merge(e2), s2 = r2.xmax - r2.xmin, a2 = r2.ymax - r2.ymin;
return [i2, s2 * s2 + a2 * a2];
}
static minmax_tree_process_level(e2, n2, o2, i2) {
let r2, s2;
for (let a3 of n2) {
[r2, s2] = t31.box2box_minmax(e2.box, a3.item.key);
for (let t32 of a3.item.values)
t32 instanceof rx.Edge ? i2.insert([r2, s2], t32.shape) : i2.insert([r2, s2], t32);
rx.Utils.LT(s2, o2) && (o2 = s2);
}
if (n2.length === 0)
return o2;
let a2 = [...n2.map((t32) => t32.left.isNil() ? undefined : t32.left).filter((t32) => t32 !== undefined), ...n2.map((t32) => t32.right.isNil() ? undefined : t32.right).filter((t32) => t32 !== undefined)].filter((n3) => {
let [i3, r3] = t31.box2box_minmax(e2.box, n3.max);
return rx.Utils.LE(i3, o2);
});
return o2 = t31.minmax_tree_process_level(e2, a2, o2, i2);
}
static minmax_tree(e2, n2, o2) {
let i2 = new Wv, r2 = [n2.index.root], s2 = o2 < Number.POSITIVE_INFINITY ? o2 * o2 : Number.POSITIVE_INFINITY;
return s2 = t31.minmax_tree_process_level(e2, r2, s2, i2), i2;
}
static minmax_tree_calc_distance(e2, n2, o2) {
let i2, r2;
if (n2 != null && !n2.isNil()) {
if ([i2, r2] = t31.minmax_tree_calc_distance(e2, n2.left, o2), r2)
return [i2, r2];
if (rx.Utils.LT(i2[0], Math.sqrt(n2.item.key.low)))
return [i2, true];
let [s2, a2] = t31.distanceToArray(e2, n2.item.values);
return rx.Utils.LT(s2, i2[0]) && (i2 = [s2, a2]), [i2, r2] = t31.minmax_tree_calc_distance(e2, n2.right, i2), [i2, r2];
}
return [o2, false];
}
static shape2planarSet(e2, n2, o2 = Number.POSITIVE_INFINITY) {
let i2 = [o2, new rx.Segment], r2 = false;
if (n2 instanceof rx.PlanarSet) {
let s2 = t31.minmax_tree(e2, n2, o2);
[i2, r2] = t31.minmax_tree_calc_distance(e2, s2.root, i2);
}
return i2;
}
static sort(t32) {
t32.sort((t33, e2) => rx.Utils.LT(t33[0], e2[0]) ? -1 : rx.Utils.GT(t33[0], e2[0]) ? 1 : 0);
}
static distance(t32, e2) {
return t32.distanceTo(e2);
}
static distanceToArray(t32, e2) {
let n2 = [Number.POSITIVE_INFINITY, new rx.Segment];
for (let o2 of e2) {
let [e3, i2] = t32.distanceTo(o2);
rx.Utils.LT(e3, n2[0]) && (n2 = [e3, i2]);
}
return n2;
}
static shape2multiline(e2, n2) {
let o2 = [Number.POSITIVE_INFINITY, new rx.Segment];
for (let i2 of n2) {
let [n3, r2] = t31.distance(e2, i2.shape);
rx.Utils.LT(n3, o2[0]) && (o2 = [n3, r2]);
}
return o2;
}
static multiline2multiline(e2, n2) {
let o2 = [Number.POSITIVE_INFINITY, new rx.Segment];
for (let i2 of e2)
for (let e3 of n2) {
let [n3, r2] = t31.distance(i2.shape, e3.shape);
rx.Utils.LT(n3, o2[0]) && (o2 = [n3, r2]);
}
return o2;
}
};
var { Multiline: rI, Point: sI, Segment: aI, Polygon: cI } = rx;
function lI(t32) {
return new sI(t32.split(" ").map(Number));
}
function hI(t32) {
return t32.split(", ").map(lI);
}
function dI(t32) {
const e2 = hI(t32);
let n2 = [];
for (let t33 = 0;t33 < e2.length - 1; t33++)
n2.push(new aI(e2[t33], e2[t33 + 1]));
return new rI(n2);
}
function uI(t32) {
const e2 = t32.replace(/\(\(/, "").replace(/\)\)$/, "").split("), ("), n2 = new cI;
let o2;
return e2.forEach((t33, e3) => {
let i2 = t33.split(", ").map((t34) => new sI(t34.split(" ").map(Number)));
const r2 = n2.addFace(i2);
e3 === 0 ? o2 = r2.orientation() : r2.orientation() === o2 && r2.reverse();
}), n2;
}
function pI(t32) {
if (t32.startsWith("POLYGON")) {
return uI(t32.replace(/^POLYGON /, ""));
}
return function(t33) {
const e2 = t33.split(/\)\), \(\(/).map((t34) => "((" + t34 + "))").map(uI), n2 = new cI;
return e2.reduce((t34, e3) => [...t34, ...e3?.faces], []).forEach((t34) => n2.addFace([...t34?.shapes])), n2;
}(t32.replace(/^MULTIPOLYGON \(\(\((.*)\)\)\)$/, "$1"));
}
function mI(t32) {
return t32.split(`
`)?.every((t33) => t33.includes("POINT"));
}
function gI(t32) {
return t32.split(`
`)?.every((t33) => t33.includes("LINESTRING"));
}
rx.isWktString = function(t33) {
return t33.startsWith("POINT") || mI(t33) || t33.startsWith("LINESTRING") || gI(t33) || t33.startsWith("MULTILINESTRING") || t33.startsWith("POLYGON") || t33.startsWith("MULTIPOINT") || t33.startsWith("MULTIPOLYGON") || t33.startsWith("GEOMETRYCOLLECTION");
}, rx.parseWKT = function t32(e2) {
if (e2.startsWith("POINT")) {
return lI(e2.replace(/^POINT \(/, "").replace(/\)$/, ""));
}
if (e2.startsWith("MULTIPOINT")) {
return hI(e2.replace(/^MULTIPOINT \(/, "").replace(/\)$/, ""));
}
if (e2.startsWith("LINESTRING")) {
return dI(e2.replace(/^LINESTRING \(/, "").replace(/\)$/, ""));
}
if (e2.startsWith("MULTILINESTRING")) {
return function(t33) {
return t33.replace(/\(\(/, "").replace(/\)\)$/, "").split("), (").map(dI);
}(e2.replace(/^MULTILINESTRING /, ""));
}
if (e2.startsWith("POLYGON") || e2.startsWith("MULTIPOLYGON"))
return pI(e2);
if (e2.startsWith("GEOMETRYCOLLECTION")) {
const n2 = /(?<type>POINT|LINESTRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON) \((?:[^\(\)]|\([^\)]*\))*\)/g, o2 = e2.match(n2);
o2[0].startsWith("GEOMETRYCOLLECTION") && (o2[0] = o2[0].replace("GEOMETRYCOLLECTION (", ""));
return o2.map(t32).map((t33) => t33 instanceof Array ? t33 : [t33]).reduce((t33, e3) => [...t33, ...e3], []);
}
return mI(e2) ? function(t33) {
return t33.split(`
`).map((t34) => t34.match(/\(([^)]+)\)/)[1]).map(lI);
}(e2) : gI(e2) ? function(t33) {
return t33.split(`
`).map((t34) => t34.match(/\(([^)]+)\)/)[1]).map(dI).reduce((t34, e3) => [...t34, ...e3], []);
}(e2) : [];
}, rx.BooleanOperations = Cv, rx.Relations = Fv;
var fI = [0, 1, -1, 2, -2, 3, -3, 4];
(fI.flatMap((t33) => fI.map((e2) => [t33, e2])).sort(([t33, e2], [n2, o2]) => Math.abs(t33) + Math.abs(e2) - Math.abs(n2) - Math.abs(o2)).length, [0.2, 0.4, 0.8, 1.2].flatMap((t33) => [0.2, 0.3, 0.45, 0.6].flatMap((e2) => [-1, 1].map((n2) => ({ halfSpan: t33, offset: e2, directionSign: n2 })))).flatMap((t33) => [0, 1].map((e2) => ({ kind: "segment", routeSide: e2, ...t33 }))));
[{ dx: -2.4, dy: -0.4 }, { dx: -2.4, dy: 0.4 }, { dx: 2.4, dy: -0.4 }, { dx: 2.4, dy: 0.4 }, { dx: -0.4, dy: -2.4 }, { dx: -0.4, dy: 2.4 }, { dx: 0.4, dy: -2.4 }, { dx: 0.4, dy: 2.4 }].flatMap((t33) => [0, 1].map((e2) => ({ kind: "waypoint", routeSide: e2, spanExpansion: 2, ...t33 }))), [{ dx: -0.17, dy: 0 }, { dx: 0.17, dy: 0 }, { dx: 0, dy: -0.17 }, { dx: 0, dy: 0.17 }].flatMap((t33) => [0, 1].map((e2) => ({ kind: "waypoint", routeSide: e2, spanExpansion: 0, ...t33 })));
function _I(t33) {
if (t33.type === "rect")
return { type: "rect", bounds: { minX: -t33.width / 2, maxX: t33.width / 2, minY: -t33.height / 2, maxY: t33.height / 2 } };
if (t33.type !== "oval")
throw new Error("repair04 found an unsupported obstacle shape");
const e2 = Math.abs(t33.width - t33.height) / 2, n2 = t33.width >= t33.height ? e2 : 0, o2 = t33.height > t33.width ? e2 : 0;
return { type: "oval", a: { x: -n2, y: -o2 }, b: { x: n2, y: o2 }, radius: Math.min(t33.width, t33.height) / 2 };
}
function bI(t33, e2, n2) {
return n2.type === "rect" ? ke(t33, e2, n2.bounds) : Math.max(0, Oe(t33, e2, n2.a, n2.b) - n2.radius);
}
var xI = (t33, e2) => {
const n2 = new Map, o2 = (t34) => {
const e3 = n2.get(t34);
if (e3 === undefined)
return n2.set(t34, t34), t34;
if (e3 === t34)
return t34;
const i3 = o2(e3);
return n2.set(t34, i3), i3;
}, i2 = (t34) => {
const e3 = t34.filter((t35) => typeof t35 == "string" && t35.length > 0);
if (e3.length === 0)
return;
const i3 = o2(e3[0]);
for (const t35 of e3)
n2.set(o2(t35), i3);
};
for (const e3 of t33.connections) {
const t34 = e3;
i2([t34.name, t34.rootConnectionName, t34.netConnectionName, t34.__netConnectionName, ...t34.mergedConnectionNames ?? [], ...t34.__rootConnectionNames ?? [], ...t34.pointsToConnect.flatMap((t35) => [t35.pointId, t35.pcb_port_id])]);
}
for (const e3 of t33.obstacles)
i2(e3.connectedTo);
for (const t34 of e2)
i2([t34.connectionName, t34.rootConnectionName]);
for (const t34 of n2.keys())
n2.set(t34, o2(t34));
return n2;
};
var vI = (t33, e2) => {
const n2 = t33.__zLayers;
if (n2)
return new Set(n2);
if (t33.zLayers)
return new Set(t33.zLayers);
const o2 = new Set;
for (const n3 of t33.layers) {
const t34 = n3 === "top" ? 0 : n3 === "bottom" ? e2 - 1 : /^inner\d+$/.test(n3) ? Number(n3.slice(5)) : -1;
if (t34 < 0 || t34 >= e2)
throw new Error(`repair04 obstacle has an unknown layer: ${n3}`);
o2.add(t34);
}
return o2;
};
var II = ({ srj: t33, routes: e2, traceClearance: n2 = 0.1, viaClearance: o2 = 0.1 }) => {
let i2;
const r2 = new Map, s2 = [];
let a2 = false;
return (c2) => {
const l2 = i2 ??= xI(t33, e2), h2 = new Map, d2 = a2 ? s2 : function* (e3) {
for (let i3 = 0;i3 < t33.obstacles.length; i3++) {
if (r2.has(i3)) {
const t34 = r2.get(i3);
t34 && (yield t34);
continue;
}
const a3 = t33.obstacles[i3], c3 = a3.connectedTo.some((t34) => /^(pcb_smtpad_|pcb_plated_hole_|pcb_port_)/.test(t34)), l3 = Math.abs((a3.ccwRotationDegrees ?? 0) % 180) > 0.00000001, h3 = a3.type === "rect" && a3.layers.length > 1 && Math.abs(a3.width - a3.height) < 0.001;
if (c3 && !l3 && !h3) {
r2.set(i3, null);
continue;
}
if (![a3.center.x, a3.center.y, a3.width, a3.height, a3.ccwRotationDegrees ?? 0].every(Number.isFinite) || a3.width < 0 || a3.height < 0)
throw new Error("repair04 fixed obstacle geometry must be finite and nonnegative");
const d3 = vI(a3, t33.layerCount), u2 = new Set(a3.connectedTo.map((t34) => e3.get(t34) ?? t34)), p2 = _I(a3), m2 = (a3.ccwRotationDegrees ?? 0) * Math.PI / 180, g2 = Math.cos(m2), f2 = Math.sin(m2), y2 = Math.hypot(a3.width, a3.height) / 2, _2 = (t34) => {
const e4 = t34.x - a3.center.x, n3 = t34.y - a3.center.y;
return { x: e4 * g2 + n3 * f2, y: -e4 * f2 + n3 * g2 };
}, b2 = (t34, e4, n3) => Math.max(t34.x, e4.x) + n3 < a3.center.x - y2 || Math.min(t34.x, e4.x) - n3 > a3.center.x + y2 || Math.max(t34.y, e4.y) + n3 < a3.center.y - y2 || Math.min(t34.y, e4.y) - n3 > a3.center.y + y2, x2 = a3.obstacleId?.startsWith("repair04_board_edge_") === true, v2 = x2 ? 0 : Math.max(n2, t33.defaultObstacleMargin ?? 0, t33.minTraceToPadEdgeClearance ?? 0), I2 = x2 ? 0 : Math.max(o2, t33.defaultObstacleMargin ?? 0, t33.minViaEdgeToPadEdgeClearance ?? 0), S2 = { obstacleIndex: i3, obstacle: a3, zLayers: d3, obstacleNets: u2, shape: p2, toLocal: _2, separated: b2, wireGap: v2, viaGap: I2 };
r2.set(i3, S2), s2.push(S2), yield S2;
}
a2 = true;
}(l2);
for (const { obstacleIndex: e3, obstacle: n3, zLayers: o3, obstacleNets: i3, shape: r3, toLocal: s3, separated: a3, wireGap: u2, viaGap: p2 } of d2)
for (let d3 = 0;d3 < c2.length; d3 += 1) {
const m2 = c2[d3];
if (!(m2.route.length < 2) && ![m2.connectionName, m2.rootConnectionName].some((t34) => t34 !== undefined && i3.has(l2.get(t34) ?? t34)))
for (let i4 = 1;i4 < m2.route.length; i4 += 1) {
const c3 = m2.route[i4 - 1], l3 = m2.route[i4];
if (c3.toNextSegmentType === "through_obstacle")
continue;
if (c3.z !== l3.z) {
const n4 = Ys(t33, c3, l3);
if (!Array.from(o3).some((t34) => t34 >= n4.minZ && t34 <= n4.maxZ))
continue;
if (Math.abs(c3.x - l3.x) > 0.00000001 || Math.abs(c3.y - l3.y) > 0.00000001)
throw new Error("repair04 found a non-colocated via transition");
if (a3(c3, c3, m2.viaDiameter / 2 + p2 + 0.00000001))
continue;
const i5 = s3(c3), u3 = bI(i5, i5, r3), g3 = m2.viaDiameter / 2 + p2 - u3;
if (g3 <= 0.00000001)
continue;
const f3 = `fixed-obstacle:${d3}:${e3}:via`;
(h2.get(f3)?.severity ?? -1 / 0) < g3 && h2.set(f3, { key: f3, center: { x: c3.x, y: c3.y }, routeIndex: d3, obstacleIndex: e3, kind: "via", severity: g3 });
continue;
}
if (!o3.has(c3.z))
continue;
const g2 = Math.max(c3.traceThickness ?? m2.traceThickness, l3.traceThickness ?? m2.traceThickness) / 2;
if (a3(c3, l3, g2 + u2 + 0.00000001))
continue;
const f2 = g2 + u2 - bI(s3(c3), s3(l3), r3);
if (f2 <= 0.00000001)
continue;
const y2 = `fixed-obstacle:${d3}:${e3}:wire`;
(h2.get(y2)?.severity ?? -1 / 0) < f2 && h2.set(y2, { key: y2, center: ze(n3.center, c3, l3), routeIndex: d3, obstacleIndex: e3, kind: "wire", severity: f2 });
}
}
return Array.from(h2.values());
};
};
var SI = (t33) => II(t33)(t33.routes);
var CI = (t33, e2) => {
const n2 = [];
for (let o2 = 1;o2 < t33.route.length; o2++) {
const i2 = t33.route[o2 - 1], r2 = t33.route[o2];
if (i2.z === r2.z || i2.toNextSegmentType === "through_obstacle")
continue;
if (i2.x !== r2.x || i2.y !== r2.y || ![i2.x, i2.y, i2.z, r2.z, t33.viaDiameter].every(Number.isFinite) || !Number.isInteger(i2.z) || !Number.isInteger(r2.z) || Math.min(i2.z, r2.z) < 0 || Math.max(i2.z, r2.z) >= e2 || t33.viaDiameter <= 0)
throw new Error("repair04 new-via guard requires valid colocated vias");
const s2 = o2 - 1, a2 = [i2.z, r2.z];
let c2 = Math.min(i2.z, r2.z), l2 = Math.max(i2.z, r2.z);
for (;o2 + 1 < t33.route.length && t33.route[o2].toNextSegmentType !== "through_obstacle"; ) {
const n3 = t33.route[o2 + 1];
if (n3.x !== r2.x || n3.y !== r2.y)
break;
if (!Number.isInteger(n3.z) || n3.z < 0 || n3.z >= e2)
throw new Error("repair04 new-via guard found an invalid layer span");
n3.z !== a2.at(-1) && a2.push(n3.z), c2 = Math.min(c2, n3.z), l2 = Math.max(l2, n3.z), o2++;
}
n2.push({ pointIndices: Array.from({ length: o2 - s2 + 1 }, (t34, e3) => s2 + e3), layerSequence: a2, x: r2.x, y: r2.y, minZ: c2, maxZ: l2, diameter: t33.viaDiameter, identity: JSON.stringify([r2.x, r2.y, c2, l2, t33.viaDiameter]) });
}
return n2;
};
var PI = (t33) => (({ srj: t34, viaClearance: e2 = 0.1 }) => {
const n2 = new Map, o2 = new Map, i2 = [e2, t34.defaultObstacleMargin ?? 0, t34.minViaEdgeToPadEdgeClearance ?? 0], r2 = Math.max(...i2), s2 = Vs(t34, e2, true);
let a2, c2 = [];
const l2 = (e3) => {
const i3 = o2.get(e3.identity);
if (i3)
return i3;
const s3 = [], a3 = Ys(t34, { z: e3.minZ }, { z: e3.maxZ });
for (let o3 = 0;o3 < t34.obstacles.length; o3++) {
const i4 = t34.obstacles[o3];
let c3 = n2.get(o3);
if (!c3) {
const e4 = i4.__zLayers ?? i4.zLayers ?? i4.layers.map((e5) => e5 === "top" ? 0 : e5 === "bottom" ? t34.layerCount - 1 : /^inner\d+$/.test(e5) ? Number(e5.slice(5)) : -1);
if (e4.some((e5) => !Number.isInteger(e5) || e5 < 0 || e5 >= t34.layerCount))
throw new Error("repair04 new-via guard found an unknown obstacle layer");
c3 = { zs: e4 }, n2.set(o3, c3);
}
if (!c3.zs.some((t35) => t35 >= a3.minZ && t35 <= a3.maxZ))
continue;
if (!c3.geometry) {
if (![i4.center.x, i4.center.y, i4.width, i4.height, i4.ccwRotationDegrees ?? 0].every(Number.isFinite) || i4.width < 0 || i4.height < 0)
throw new Error("repair04 new-via guard found invalid obstacle geometry");
const t35 = (i4.ccwRotationDegrees ?? 0) * Math.PI / 180;
c3.geometry = { x: i4.center.x, y: i4.center.y, cosine: Math.cos(t35), sine: Math.sin(t35), extent: Math.hypot(i4.width, i4.height) / 2, shape: _I(i4) };
}
const l3 = c3.geometry, h2 = l3.extent + e3.diameter / 2 + r2 + 0.00000001;
if (Math.abs(e3.x - l3.x) > h2 || Math.abs(e3.y - l3.y) > h2)
continue;
const d2 = e3.x - l3.x, u2 = e3.y - l3.y, p2 = { x: d2 * l3.cosine + u2 * l3.sine, y: -d2 * l3.sine + u2 * l3.cosine }, m2 = bI(p2, p2, l3.shape), g2 = e3.diameter / 2 + r2 - m2;
g2 <= 0.00000001 || s3.push({ obstacleIndex: o3, severity: g2 });
}
return o2.set(e3.identity, s3), s3;
};
return ({ previousRoutes: e3, routes: n3, includeExistingVias: o3 = [] }) => {
if (e3.length !== n3.length)
throw new Error("repair04 new-via guard requires matching route ordering");
if (i2.some((t35) => !Number.isFinite(t35) || t35 < 0))
throw new Error("repair04 new-via guard requires nonnegative finite margins");
const h2 = [];
a2 && c2.length === n3.length && !c2.some((t35, e4) => t35.connectionName !== n3[e4].connectionName || t35.rootConnectionName !== n3[e4].rootConnectionName) || (a2 = xI(t34, n3), c2 = n3.map((t35) => ({ connectionName: t35.connectionName, rootConnectionName: t35.rootConnectionName })));
for (let i3 = 0;i3 < n3.length; i3++) {
const c3 = n3[i3], d2 = e3[i3], u2 = a2.get(c3.connectionName) ?? c3.connectionName, p2 = (e4) => l2(e4).flatMap((e5) => {
const n4 = t34.obstacles[e5.obstacleIndex].connectedTo.some((t35) => (a2.get(t35) ?? t35) === u2), o4 = e5.severity - (n4 ? r2 - s2 : 0);
return o4 > 0.00000001 ? [{ obstacleIndex: e5.obstacleIndex, severity: o4 }] : [];
}), m2 = CI(d2, t34.layerCount), g2 = c3.connectionName === d2.connectionName && c3.rootConnectionName === d2.rootConnectionName, f2 = new Set(g2 ? m2.map((t35) => t35.identity) : []), y2 = CI(c3, t34.layerCount), _2 = g2 && c3.route.length === d2.route.length && c3.route.every((t35, e4) => {
const n4 = d2.route[e4];
return (!(e4 === 0 || e4 === c3.route.length - 1 || t35.pcb_port_id || t35.insideJumperPad || t35.toNextSegmentType) || t35.x === n4.x && t35.y === n4.y) && t35.z === n4.z && t35.pcb_port_id === n4.pcb_port_id && t35.toNextSegmentType === n4.toNextSegmentType && t35.insideJumperPad === n4.insideJumperPad;
}) && y2.length === m2.length && new Set(y2.map((t35) => t35.identity)).size === y2.length && y2.every((t35, e4) => {
const n4 = m2[e4];
return t35.diameter === n4.diameter && t35.pointIndices.length === n4.pointIndices.length && t35.pointIndices.every((t36, e5) => t36 === n4.pointIndices[e5]) && t35.layerSequence.length === n4.layerSequence.length && t35.layerSequence.every((t36, e5) => t36 === n4.layerSequence[e5]) && !m2.some((n5, o4) => o4 !== e4 && n5.identity === t35.identity);
});
for (let t35 = 0;t35 < y2.length; t35++) {
const e4 = y2[t35];
if (f2.has(e4.identity) && !o3.some((e5) => e5.routeIndex === i3 && e5.viaIndex === t35))
continue;
const n4 = _2 && !o3.some((e5) => e5.routeIndex === i3 && e5.viaIndex === t35) ? new Map(p2(m2[t35]).map((t36) => [t36.obstacleIndex, t36.severity])) : undefined;
for (const o4 of p2(e4)) {
const r3 = n4?.get(o4.obstacleIndex);
r3 !== undefined && o4.severity <= r3 + 0.00000001 || h2.push({ key: `new-via-pad:${i3}:${o4.obstacleIndex}:${t35}`, routeIndex: i3, obstacleIndex: o4.obstacleIndex, center: { x: e4.x, y: e4.y }, kind: "via", severity: o4.severity });
}
}
}
return h2;
};
})(t33)(t33);
var MI = (t33, e2, n2) => {
if (n2 <= Hs)
return structuredClone(t33);
if (n2 >= 0.99999999)
return structuredClone(e2);
const o2 = { ...structuredClone(t33), x: t33.x + (e2.x - t33.x) * n2, y: t33.y + (e2.y - t33.y) * n2 };
return delete o2.start_pcb_port_id, delete o2.end_pcb_port_id, o2;
};
var NI = (t33, e2) => {
const n2 = t33.end.x - t33.start.x, o2 = t33.end.y - t33.start.y, i2 = e2.end.x - e2.start.x, r2 = e2.end.y - e2.start.y, s2 = e2.start.x - t33.start.x, a2 = e2.start.y - t33.start.y, c2 = n2 * r2 - o2 * i2, l2 = (t34, e3) => ({ x: t34.start.x + (t34.end.x - t34.start.x) * e3, y: t34.start.y + (t34.end.y - t34.start.y) * e3 }), h2 = (t34, e3) => {
const n3 = e3.end.x - e3.start.x, o3 = e3.end.y - e3.start.y, i3 = n3 * n3 + o3 * o3, r3 = i3 > 0.00000000000000010000000000000001 ? Math.max(0, Math.min(1, ((t34.x - e3.start.x) * n3 + (t34.y - e3.start.y) * o3) / i3)) : 0;
return l2(e3, r3);
};
if (Math.abs(c2) > Hs) {
const e3 = (s2 * r2 - a2 * i2) / c2, h3 = (s2 * o2 - a2 * n2) / c2;
if (e3 >= 0 && e3 <= 1 && h3 >= 0 && h3 <= 1) {
const n3 = l2(t33, e3);
return [n3, n3];
}
} else {
const i3 = n2 * n2 + o2 * o2;
if (i3 > 0.00000000000000010000000000000001) {
const r3 = (s2 * n2 + a2 * o2) / i3, c3 = ((e2.end.x - t33.start.x) * n2 + (e2.end.y - t33.start.y) * o2) / i3, d3 = Math.max(0, Math.min(r3, c3)), u2 = Math.min(1, Math.max(r3, c3));
if (d3 <= u2) {
const n3 = l2(t33, (d3 + u2) / 2);
return [n3, h2(n3, e2)];
}
}
}
const d2 = [[t33.start, h2(t33.start, e2)], [t33.end, h2(t33.end, e2)], [h2(e2.start, t33), e2.start], [h2(e2.end, t33), e2.end]];
return d2.sort((t34, e3) => Math.hypot(t34[0].x - t34[1].x, t34[0].y - t34[1].y) - Math.hypot(e3[0].x - e3[1].x, e3[0].y - e3[1].y)), d2[0];
};
var wI = (t33, e2) => {
const n2 = t33 === "top" ? 0 : t33 === "bottom" ? e2 - 1 : /^inner\d+$/.test(t33) ? Number(t33.slice(5)) : -1;
if (!Number.isInteger(n2) || n2 < 0 || n2 >= e2)
throw new Error(`repair04 preload has an unknown layer: ${t33}`);
return n2;
};
var TI = (t33, e2, n2) => {
const o2 = ((t34, e3) => {
const n3 = new Map, o3 = (t35) => {
const e4 = n3.get(t35);
if (e4 === undefined || e4 === t35)
return t35;
const i4 = o3(e4);
return n3.set(t35, i4), i4;
}, i3 = (t35) => {
const e4 = t35.filter((t36) => typeof t36 == "string" && t36.length > 0);
if (e4.length === 0)
return;
const i4 = o3(e4[0]);
for (const t36 of e4)
n3.set(o3(t36), i4);
};
for (const e4 of t34.connections) {
const t35 = e4;
i3([t35.name, t35.rootConnectionName, t35.netConnectionName, t35.__netConnectionName, ...t35.mergedConnectionNames ?? [], ...t35.__rootConnectionNames ?? []]);
}
for (const t35 of e3)
i3([t35.connectionName, t35.rootConnectionName]);
for (const e4 of t34.traces ?? [])
i3([e4.connection_name, ...e4.connectsTo ?? []]);
return o3;
})(t33, e2), i2 = e2.map((t34, e3) => e3), r2 = (t34) => {
const e3 = i2[t34];
if (e3 === t34)
return t34;
const n3 = r2(e3);
return i2[t34] = n3, n3;
}, s2 = new Map, a2 = new Map;
for (let e3 = 0;e3 < t33.obstacles.length; e3 += 1)
for (const n3 of t33.obstacles[e3].connectedTo) {
const t34 = a2.get(n3) ?? [];
t34.push(e3), a2.set(n3, t34);
}
for (let n3 = 0;n3 < e2.length; n3 += 1) {
const c3 = e2[n3];
for (const e3 of [c3.route[0], c3.route.at(-1)]) {
if (!e3)
continue;
const l3 = o2(c3.connectionName), h3 = [JSON.stringify([l3, "point", e3.x, e3.y, e3.z])], d3 = e3.pcb_port_id ? a2.get(e3.pcb_port_id) ?? [] : [];
for (const n4 of d3) {
const o3 = t33.obstacles[n4];
if (!(o3.zLayers ?? o3.layers.map((e4) => wI(e4, t33.layerCount))).includes(e3.z))
continue;
const i3 = (o3.ccwRotationDegrees ?? 0) * Math.PI / 180, r3 = e3.x - o3.center.x, s3 = e3.y - o3.center.y, a3 = { x: r3 * Math.cos(i3) + s3 * Math.sin(i3), y: -r3 * Math.sin(i3) + s3 * Math.cos(i3) };
bI(a3, a3, _I(o3)) > Hs || h3.push(JSON.stringify([l3, "pad", n4]));
}
for (const t34 of h3) {
const e4 = s2.get(t34);
e4 === undefined ? s2.set(t34, n3) : i2[r2(n3)] = r2(e4);
}
}
}
const c2 = (t34, e3) => !(!t34.startsWith("route:") || !e3.startsWith("route:")) && r2(Number(t34.slice(6))) === r2(Number(e3.slice(6))), l2 = [], h2 = [], d2 = [], u2 = e2.map(() => ({ segmentTimes: new Map, viaPositions: [] })), p2 = (t34) => {
if (Gs(t34, n2)) {
d2.push(t34);
for (let e3 = t34.minZ;e3 <= t34.maxZ; e3 += 1)
l2.push({ x: t34.x, y: t34.y, z: e3, radius: t34.radius, net: t34.net, source: t34.source, ...t34.routeIndex !== undefined ? { viaOwner: t34.routeIndex } : {} });
}
};
for (let t34 = 0;t34 < e2.length; t34 += 1) {
const i3 = e2[t34], r3 = o2(i3.connectionName), s3 = `route:${t34}`;
for (let e3 = 0;e3 < i3.route.length; e3 += 1) {
const o3 = i3.route[e3];
if ((e3 === 0 || e3 === i3.route.length - 1 || o3.pcb_port_id) && Gs(o3, n2) && l2.push({ x: o3.x, y: o3.y, z: o3.z, radius: (o3.traceThickness ?? i3.traceThickness) / 2, net: r3, source: s3 }), e3 === 0)
continue;
const a3 = i3.route[e3 - 1];
a3.toNextSegmentType !== "through_obstacle" && (a3.z === o3.z ? h2.push({ start: a3, end: o3, z: o3.z, radius: Math.max(a3.traceThickness ?? i3.traceThickness, o3.traceThickness ?? i3.traceThickness) / 2, net: r3, source: s3, routeIndex: t34, segmentIndex: e3 - 1 }) : p2({ x: o3.x, y: o3.y, minZ: Math.min(a3.z, o3.z), maxZ: Math.max(a3.z, o3.z), radius: i3.viaDiameter / 2, net: r3, source: s3, routeIndex: t34 }));
}
}
for (let e3 = 0;e3 < (t33.traces ?? []).length; e3 += 1) {
const i3 = Ws(t33.traces[e3], t33.minTraceWidth), r3 = o2(i3.connection_name), s3 = `fixed:${e3}`;
for (let e4 = 0;e4 < i3.route.length; e4 += 1) {
const o3 = i3.route[e4], a3 = i3.route[e4 - 1];
if (o3.route_type === "wire") {
const c3 = wI(o3.layer, t33.layerCount);
(e4 === 0 || e4 === i3.route.length - 1 || o3.start_pcb_port_id || o3.end_pcb_port_id) && Gs(o3, n2) && l2.push({ x: o3.x, y: o3.y, z: c3, radius: o3.width / 2, net: r3, source: s3 }), a3?.route_type === "wire" && a3.layer === o3.layer && h2.push({ start: a3, end: o3, z: c3, radius: Math.max(a3.width, o3.width) / 2, net: r3, source: s3 });
} else if (o3.route_type === "via") {
const e5 = wI(o3.from_layer, t33.layerCount), n3 = wI(o3.to_layer, t33.layerCount);
p2({ x: o3.x, y: o3.y, minZ: Math.min(e5, n3), maxZ: Math.max(e5, n3), radius: (o3.via_diameter ?? t33.minViaDiameter ?? 0.3) / 2, net: r3, source: s3 });
}
}
}
const m2 = new Map;
for (const t34 of l2) {
const e3 = JSON.stringify([t34.net, t34.z]), n3 = m2.get(e3) ?? [];
n3.push(t34), m2.set(e3, n3);
}
const g2 = (t34, e3) => {
if (t34 === undefined)
return;
const n3 = u2[t34].viaPositions;
n3.some((t35) => Math.hypot(t35.x - e3.x, t35.y - e3.y) <= Hs) || n3.push({ x: e3.x, y: e3.y });
};
for (const t34 of h2) {
if (!Us(t34.start, t34.end, n2))
continue;
const e3 = t34.end.x - t34.start.x, o3 = t34.end.y - t34.start.y, i3 = e3 * e3 + o3 * o3;
if (!(i3 <= 0.00000000000000010000000000000001))
for (const r3 of m2.get(JSON.stringify([t34.net, t34.z])) ?? []) {
if (r3.source === t34.source || c2(r3.source, t34.source))
continue;
const s3 = Math.max(0, Math.min(1, ((r3.x - t34.start.x) * e3 + (r3.y - t34.start.y) * o3) / i3)), a3 = { x: t34.start.x + e3 * s3, y: t34.start.y + o3 * s3 };
if (Gs(a3, n2) && !(Math.hypot(a3.x - r3.x, a3.y - r3.y) > t34.radius + r3.radius + Hs)) {
if (t34.routeIndex !== undefined && t34.segmentIndex !== undefined) {
const e4 = u2[t34.routeIndex].segmentTimes.get(t34.segmentIndex) ?? [];
e4.some((t35) => Math.abs(t35 - s3) <= Hs) || e4.push(s3), u2[t34.routeIndex].segmentTimes.set(t34.segmentIndex, e4);
}
g2(r3.viaOwner, r3);
}
}
}
for (const t34 of d2)
for (let e3 = t34.minZ;e3 <= t34.maxZ; e3 += 1)
for (const n3 of m2.get(JSON.stringify([t34.net, e3])) ?? [])
n3.source === t34.source || c2(n3.source, t34.source) || Math.hypot(t34.x - n3.x, t34.y - n3.y) > t34.radius + n3.radius + Hs || (g2(t34.routeIndex, t34), g2(n3.viaOwner, n3));
return ((t34, e3, n3, o3) => {
const i3 = new Map, r3 = new Set, s3 = [], a3 = (t35, e4) => {
if (t35.routeIndex === undefined || t35.segmentIndex === undefined)
return;
const o4 = t35.end.x - t35.start.x, i4 = t35.end.y - t35.start.y, r4 = o4 * o4 + i4 * i4;
if (r4 <= 0.00000000000000010000000000000001)
return;
const s4 = Math.max(0, Math.min(1, ((e4.x - t35.start.x) * o4 + (e4.y - t35.start.y) * i4) / r4)), a4 = n3[t35.routeIndex].segmentTimes.get(t35.segmentIndex) ?? [];
a4.some((t36) => Math.abs(t36 - s4) <= Hs) || a4.push(s4), n3[t35.routeIndex].segmentTimes.set(t35.segmentIndex, a4);
};
for (const n4 of t34) {
const t35 = Us(n4.start, n4.end, e3);
if (!t35 || t35[1] - t35[0] <= Hs)
continue;
const c3 = (t36) => ({ x: n4.start.x + (n4.end.x - n4.start.x) * t36, y: n4.start.y + (n4.end.y - n4.start.y) * t36 }), l3 = { ...n4, start: c3(t35[0]), end: c3(t35[1]) }, h3 = s3.length;
s3.push({ original: n4, clipped: l3 });
const d3 = Math.floor((Math.min(l3.start.x, l3.end.x) - l3.radius) / 2), u3 = Math.floor((Math.max(l3.start.x, l3.end.x) + l3.radius) / 2), p3 = Math.floor((Math.min(l3.start.y, l3.end.y) - l3.radius) / 2), m3 = Math.floor((Math.max(l3.start.y, l3.end.y) + l3.radius) / 2);
for (let t36 = d3;t36 <= u3; t36 += 1)
for (let e4 = p3;e4 <= m3; e4 += 1) {
const c4 = JSON.stringify([l3.net, l3.z, t36, e4]), d4 = i3.get(c4) ?? [];
for (const t37 of d4) {
const e5 = s3[t37];
if (e5.original.source === n4.source || o3(e5.original.source, n4.source) || e5.original.routeIndex === undefined && n4.routeIndex === undefined)
continue;
const i4 = `${t37}:${h3}`;
if (r3.has(i4))
continue;
r3.add(i4);
const [c5, d5] = NI(l3, e5.clipped);
Math.hypot(c5.x - d5.x, c5.y - d5.y) > l3.radius + e5.clipped.radius + Hs || (a3(n4, c5), a3(e5.original, d5));
}
d4.push(h3), i3.set(c4, d4);
}
}
})(h2, n2, u2, c2), u2;
};
var RI = (t33, e2) => ({ minX: t33.minX - e2, maxX: t33.maxX + e2, minY: t33.minY - e2, maxY: t33.maxY + e2 });
var EI = (t33, e2, n2, o2) => {
const i2 = [];
let r2;
const s2 = t33.route, a2 = (t34) => t34 === 0 || t34 === s2.length - 1 || s2[t34]?.pcb_port_id !== undefined, c2 = () => {
r2 !== undefined && r2.points.length > 0 && (r2.locks[0] = true, r2.locks[r2.points.length - 1] = true, i2.push(r2)), r2 = undefined;
};
if (s2.length === 1 && s2[0] && Gs(s2[0], e2))
return [{ points: structuredClone(s2), locks: [true], start: { segmentIndex: 0, t: 0 }, end: { segmentIndex: 0, t: 0 } }];
for (let i3 = 0;i3 < s2.length - 1; i3 += 1) {
const l2 = s2[i3], h2 = s2[i3 + 1];
if (!l2 || !h2)
throw new Error("repair04 found a missing route point");
if (![l2.x, l2.y, l2.z, h2.x, h2.y, h2.z].every(Number.isFinite))
throw new Error("repair04 route coordinates must be finite");
if (l2.z !== h2.z && !qs({ x: l2.x, y: l2.y }, { x: h2.x, y: h2.y }) && l2.toNextSegmentType !== "through_obstacle")
throw new Error("repair04 requires colocated points at a via transition");
const d2 = Us(l2, h2, e2);
if (!d2) {
c2();
continue;
}
const [u2, p2] = d2;
if (p2 - u2 <= Hs && !qs(l2, h2)) {
c2();
continue;
}
const m2 = Us(l2, h2, n2), g2 = [u2, p2], f2 = o2.segmentTimes.get(i3) ?? [];
for (const t34 of f2)
t34 >= u2 - Hs && t34 <= p2 + Hs && g2.push(Math.max(u2, Math.min(p2, t34)));
if (m2 && l2.z === h2.z)
for (const t34 of m2)
t34 > u2 + Hs && t34 < p2 - Hs && g2.push(t34);
g2.sort((t34, e3) => t34 - e3);
const y2 = g2.filter((t34, e3) => e3 === 0 || Math.abs(t34 - g2[e3 - 1]) > Hs), _2 = Zs(l2, h2, u2);
r2 && !qs(r2.points[r2.points.length - 1], _2) && c2(), r2 || (r2 = { points: [], locks: [], start: { segmentIndex: i3, t: u2 }, end: { segmentIndex: i3, t: p2 } });
for (const e3 of y2) {
const s3 = Zs(l2, h2, e3), c3 = e3 <= Hs ? i3 : e3 >= 0.99999999 ? i3 + 1 : undefined, d3 = !Gs(s3, n2, 0.00000004) || f2.some((t34) => Math.abs(t34 - e3) <= Hs) || o2.viaPositions.some((t34) => Math.hypot(t34.x - s3.x, t34.y - s3.y) <= Hs) || c3 !== undefined && a2(c3) || l2.toNextSegmentType === "through_obstacle" || s3.toNextSegmentType === "through_obstacle" || l2.insideJumperPad === true || h2.insideJumperPad === true || (t33.jumpers ?? []).some((t34) => qs(s3, { ...t34.start, z: s3.z }) || qs(s3, { ...t34.end, z: s3.z })), u3 = r2.points[r2.points.length - 1];
u3 && u3.x === s3.x && u3.y === s3.y && u3.z === s3.z ? r2.locks[r2.locks.length - 1] = r2.locks[r2.locks.length - 1] || d3 : (r2.points.push(s3), r2.locks.push(d3));
}
r2.end = { segmentIndex: i3, t: p2 }, p2 < 0.99999999 && c2();
}
c2();
for (const t34 of i2)
for (let e3 = 1;e3 < t34.points.length; e3 += 1) {
const n3 = t34.points[e3 - 1], o3 = t34.points[e3];
if (n3.z !== o3.z && (t34.locks[e3 - 1] || t34.locks[e3])) {
let n4 = e3 - 1, i3 = e3;
for (;n4 > 0 && qs({ x: t34.points[n4 - 1].x, y: t34.points[n4 - 1].y }, { x: o3.x, y: o3.y }); )
n4 -= 1;
for (;i3 + 1 < t34.points.length && qs({ x: t34.points[i3 + 1].x, y: t34.points[i3 + 1].y }, { x: o3.x, y: o3.y }); )
i3 += 1;
for (let e4 = n4;e4 <= i3; e4 += 1)
t34.locks[e4] = true;
}
}
return i2;
};
var AI = (t33, e2) => {
const n2 = t33.bounds, o2 = t33.outline && t33.outline.length >= 3 ? t33.outline : [{ x: n2.minX, y: n2.minY }, { x: n2.maxX, y: n2.minY }, { x: n2.maxX, y: n2.maxY }, { x: n2.minX, y: n2.maxY }], i2 = [];
for (let n3 = 0;n3 < o2.length; n3 += 1) {
const r2 = o2[n3], s2 = o2[(n3 + 1) % o2.length], a2 = Us(r2, s2, e2);
if (!a2)
continue;
const c2 = s2.x - r2.x, l2 = s2.y - r2.y, h2 = Math.hypot(c2, l2);
if (h2 <= Hs)
continue;
const d2 = (a2[0] + a2[1]) / 2;
i2.push({ obstacleId: `repair04_board_edge_${n3}`, type: "rect", center: { x: r2.x + c2 * d2, y: r2.y + l2 * d2 }, width: h2 * (a2[1] - a2[0]), height: Math.max(2 * (t33.minBoardEdgeClearance ?? 0), Hs), ccwRotationDegrees: 180 * Math.atan2(l2, c2) / Math.PI, layers: Array.from({ length: t33.layerCount }, (e3, n4) => n4 === 0 ? "top" : n4 === t33.layerCount - 1 ? "bottom" : `inner${n4}`), zLayers: Array.from({ length: t33.layerCount }, (t34, e3) => e3), connectedTo: [] });
}
return i2;
};
var OI = ({ srj: t33, routes: e2, bounds: n2, boundaryMargin: o2 = 0.5, clearanceHalo: i2 }) => {
if (((t34) => {
if (!Object.values(t34).every(Number.isFinite))
throw new Error("repair04 bounds must contain finite coordinates");
if (t34.maxX - t34.minX < 9.99999999 || t34.maxY - t34.minY < 9.99999999)
throw new Error("repair04 requires bounds at least 10 mm by 10 mm");
})(n2), !Number.isFinite(o2) || o2 < 0 || i2 !== undefined && (!Number.isFinite(i2) || i2 < 0))
throw new Error("repair04 collar and halo must be finite and nonnegative");
const r2 = Math.max(t33.defaultObstacleMargin ?? 0.2, t33.minTraceToPadEdgeClearance ?? 0, t33.minViaEdgeToPadEdgeClearance ?? 0);
let s2 = Math.max(t33.minTraceWidth, t33.minViaDiameter ?? 0);
for (const t34 of e2) {
s2 = Math.max(s2, t34.traceThickness, t34.viaDiameter);
for (const e3 of t34.route)
s2 = Math.max(s2, e3.traceThickness ?? 0);
}
for (const e3 of t33.traces ?? [])
for (const n3 of e3.route)
n3.route_type === "wire" && (s2 = Math.max(s2, n3.width)), n3.route_type === "via" && (s2 = Math.max(s2, n3.via_diameter ?? t33.minViaDiameter ?? 0.3));
if (!Number.isFinite(s2) || s2 <= 0)
throw new Error("repair04 requires finite positive copper widths");
const a2 = Math.max(o2, s2 + r2);
if (2 * a2 >= Math.min(n2.maxX - n2.minX, n2.maxY - n2.minY))
throw new Error("repair04 bounds are too small for their required copper safety collar");
const c2 = RI(n2, Math.max(i2 ?? a2, r2 + s2)), l2 = RI(n2, -a2), h2 = TI(t33, e2, c2), d2 = ((t34, e3, n3) => {
const o3 = [];
for (const i3 of t34) {
const t35 = Ws(i3, n3), r3 = [];
let s3 = [];
const a3 = () => {
s3.length > 0 && r3.push(s3), s3 = [];
}, c3 = (t36) => {
Js(s3[s3.length - 1]) !== Js(t36) && s3.push(structuredClone(t36));
};
for (let n4 = 0;n4 < t35.route.length; n4 += 1) {
const o4 = t35.route[n4], i4 = t35.route[n4 - 1];
if (o4.route_type === "wire" && i4?.route_type === "wire" && o4.layer === i4.layer) {
const t36 = Us(i4, o4, e3);
if (!t36) {
a3();
continue;
}
const n5 = MI(i4, o4, t36[0]), r4 = MI(i4, o4, t36[1]), l3 = s3[s3.length - 1];
l3?.route_type === "wire" && (l3.layer !== n5.layer || Math.hypot(l3.x - n5.x, l3.y - n5.y) > Hs) && a3(), c3(n5), c3(r4), t36[1] < 0.99999999 && a3();
} else if (o4.route_type === "via") {
if (!Gs(o4, e3)) {
a3();
continue;
}
if (i4?.route_type !== "wire")
throw new Error("repair04 normalized preload via has no incoming wire");
c3(i4), c3(o4);
const r4 = t35.route[n4 + 1];
if (r4?.route_type !== "wire")
throw new Error("repair04 normalized preload via has no outgoing wire");
c3(r4);
} else if (o4.route_type === "wire")
Gs(o4, e3) && c3(o4);
else if ("start" in o4 && "end" in o4) {
const t36 = Us(o4.start, o4.end, e3);
if (!t36) {
a3();
continue;
}
const n5 = (t37) => ({ x: o4.start.x + (o4.end.x - o4.start.x) * t37, y: o4.start.y + (o4.end.y - o4.start.y) * t37 });
c3({ ...structuredClone(o4), start: n5(t36[0]), end: n5(t36[1]) }), t36[1] < 0.99999999 && a3();
}
}
a3();
for (let t36 = 0;t36 < r3.length; t36 += 1)
o3.push({ ...structuredClone(i3), pcb_trace_id: r3.length === 1 ? i3.pcb_trace_id : `${i3.pcb_trace_id}__repair04_fixed_${t36}`, route: r3[t36] });
}
return o3;
})(t33.traces ?? [], c2, t33.minTraceWidth), u2 = [], p2 = [], m2 = [];
for (let t34 = 0;t34 < e2.length; t34 += 1) {
const n3 = e2[t34];
for (const e3 of EI(n3, c2, l2, h2[t34])) {
const o3 = { ...structuredClone(Object.fromEntries(Object.entries(n3).filter(([t35]) => t35 !== "route" && t35 !== "vias" && t35 !== "jumpers"))), connectionName: n3.connectionName, traceThickness: n3.traceThickness, viaDiameter: n3.viaDiameter, route: e3.points, vias: n3.vias.filter((t35) => e3.points.some((e4) => Math.abs(e4.x - t35.x) <= Hs && Math.abs(e4.y - t35.y) <= Hs)).map((t35) => structuredClone(t35)), ...n3.jumpers !== undefined ? { jumpers: n3.jumpers.filter((t35) => Us(t35.start, t35.end, c2) !== undefined).map((t35) => structuredClone(t35)) } : {} };
u2.push(o3), p2.push(e3.locks), m2.push({ sourceRouteIndex: t34, start: e3.start, end: e3.end, sourceGeometryKey: Ks(n3, e3.start.segmentIndex + e3.start.t, e3.end.segmentIndex + e3.end.t), originalFragment: structuredClone(o3) });
}
}
const g2 = new Set([...u2.flatMap((t34) => [t34.connectionName, ...t34.rootConnectionName ? [t34.rootConnectionName] : []]), ...d2.map((t34) => t34.connection_name)]), f2 = t33.connections.filter((t34) => g2.has(t34.name) || t34.pointsToConnect.some((t35) => Gs(t35, c2))).map((t34) => ({ ...structuredClone(Object.fromEntries(Object.entries(t34).filter(([t35]) => t35 !== "pointsToConnect"))), name: t34.name, pointsToConnect: t34.pointsToConnect.filter((t35) => Gs(t35, c2)).map((t35) => structuredClone(t35)) }));
for (let e3 = 0;e3 < u2.length; e3 += 1) {
const n3 = u2[e3];
let o3 = f2.find((t34) => t34.name === n3.connectionName);
o3 || (o3 = { name: n3.connectionName, ...n3.rootConnectionName ? { rootConnectionName: n3.rootConnectionName } : {}, pointsToConnect: [] }, f2.push(o3));
for (const [i3, r3] of [["start", n3.route[0]], ["end", n3.route[n3.route.length - 1]]]) {
if (!r3)
continue;
const n4 = r3.z === 0 ? "top" : r3.z === t33.layerCount - 1 ? "bottom" : `inner${r3.z}`;
o3.pointsToConnect.some((t34) => Math.abs(t34.x - r3.x) <= Hs && Math.abs(t34.y - r3.y) <= Hs && ("layer" in t34 ? t34.layer === n4 : t34.layers.includes(n4))) || o3.pointsToConnect.push({ x: r3.x, y: r3.y, layer: n4, pointId: `repair04_${e3}_${i3}`, ...r3.pcb_port_id ? { pcb_port_id: r3.pcb_port_id } : {} });
}
}
const y2 = { ...Object.fromEntries(Object.entries(t33).filter(([t34, e3]) => t34 !== "sourceCircuitJson" && t34 !== "sourceKicadPcb" && (typeof e3 == "number" || typeof e3 == "boolean" || typeof e3 == "string"))), layerCount: t33.layerCount, minTraceWidth: t33.minTraceWidth, bounds: structuredClone(c2), obstacles: [...t33.obstacles.filter((t34) => ((t35, e3) => {
const n3 = (t35.ccwRotationDegrees ?? 0) * Math.PI / 180, o3 = (Math.abs(t35.width * Math.cos(n3)) + Math.abs(t35.height * Math.sin(n3))) / 2, i3 = (Math.abs(t35.width * Math.sin(n3)) + Math.abs(t35.height * Math.cos(n3))) / 2;
return t35.center.x + o3 >= e3.minX && t35.center.x - o3 <= e3.maxX && t35.center.y + i3 >= e3.minY && t35.center.y - i3 <= e3.maxY;
})(t34, c2)).map((t34) => structuredClone(t34)), ...AI(t33, c2)], connections: f2, ...t33.traces !== undefined ? { traces: d2 } : {}, ...t33.allowJumpers !== undefined ? { allowJumpers: t33.allowJumpers } : {}, ...t33.availableJumperTypes ? { availableJumperTypes: structuredClone(t33.availableJumperTypes) } : {} };
return { srj: y2, routes: u2, bounds: structuredClone(n2), contextBounds: c2, mutableBounds: l2, boundaryMargin: a2, lockedPointIndices: p2, routeMappings: m2 };
};
var kI = (t33) => Js(Object.fromEntries(Object.entries(t33).filter(([t34]) => t34 !== "route" && t34 !== "vias")));
var DI = (t33, e2) => {
const n2 = [];
for (let o2 = 1;o2 < t33.route.length; o2 += 1) {
const i2 = t33.route[o2 - 1], r2 = t33.route[o2], s2 = Us(i2, r2, e2), a2 = s2 ? [...s2[0] > Hs ? [[0, s2[0]]] : [], ...s2[1] < 0.99999999 ? [[s2[1], 1]] : []] : [[0, 1]];
s2 && !Gs(Zs(i2, r2, 0.5), e2, 0.00000004) && a2.length === 0 && a2.push([0, 1]);
for (const [t34, e3] of a2)
n2.push(Js([Zs(i2, r2, t34), Zs(i2, r2, e3)]));
}
return n2;
};
var LI = (t33, e2, n2, o2, i2, r2) => {
if (kI(t33) !== kI(e2))
throw new Error("repair04 merge rejected changed net, width, jumper, or route metadata");
if (n2.length !== t33.route.length)
throw new Error("repair04 merge received an invalid lock mask");
if (e2.route.length === 0)
throw new Error("repair04 merge rejected an empty replacement route");
if (Js(t33.route[0]) !== Js(e2.route[0]) || Js(t33.route[t33.route.length - 1]) !== Js(e2.route[e2.route.length - 1]))
throw new Error("repair04 merge rejected a moved fragment endpoint");
let s2 = 0;
for (let o3 = 0;o3 < t33.route.length; o3 += 1) {
if (!n2[o3])
continue;
const i3 = Js(t33.route[o3]);
for (;s2 < e2.route.length && Js(e2.route[s2]) !== i3; )
s2 += 1;
if (s2 === e2.route.length)
throw new Error("repair04 merge rejected a moved or removed locked point");
s2 += 1;
}
if (Js(DI(t33, o2)) !== Js(DI(e2, o2)))
throw new Error("repair04 merge rejected modified geometry in the fixed boundary collar");
for (let n3 = 1;n3 < t33.route.length; n3 += 1) {
const o3 = t33.route[n3 - 1], i3 = t33.route[n3];
if (!(o3.toNextSegmentType === "through_obstacle" || o3.insideJumperPad === true || i3.insideJumperPad === true || (t33.jumpers ?? []).some((t34) => qs(o3, { ...t34.start, z: o3.z }) && qs(i3, { ...t34.end, z: i3.z }) || qs(o3, { ...t34.end, z: o3.z }) && qs(i3, { ...t34.start, z: i3.z }))))
continue;
const r3 = Js([o3, i3]);
if (!e2.route.some((t34, n4) => n4 + 1 < e2.route.length && Js([t34, e2.route[n4 + 1]]) === r3))
throw new Error("repair04 merge rejected a changed atomic jumper or through-obstacle span");
}
for (const n3 of e2.route) {
if (![n3.x, n3.y, n3.z].every(Number.isFinite) || !Number.isInteger(n3.z) || n3.z < 0 || n3.z >= r2 || !Gs(n3, i2))
throw new Error("repair04 merge rejected invalid or out-of-region geometry");
if ((n3.pcb_port_id !== undefined || n3.insideJumperPad === true || n3.toNextSegmentCircuitJsonMetadata !== undefined) && !t33.route.some((t34) => Js(t34) === Js(n3)))
throw new Error("repair04 merge rejected invented or moved terminal/circuit metadata");
if (n3.traceThickness !== undefined && (!Number.isFinite(n3.traceThickness) || n3.traceThickness <= 0 || n3.traceThickness > Math.max(t33.traceThickness, ...t33.route.map((t34) => t34.traceThickness ?? 0)) + Hs))
throw new Error("repair04 merge rejected increased per-point copper width");
}
for (let n3 = 1;n3 < e2.route.length; n3 += 1) {
const o3 = e2.route[n3 - 1], i3 = e2.route[n3];
if (o3.toNextSegmentType === "through_obstacle" && !t33.route.some((e3, n4) => n4 + 1 < t33.route.length && Js([e3, t33.route[n4 + 1]]) === Js([o3, i3])))
throw new Error("repair04 merge rejected an invented through-obstacle span");
if (o3.z !== i3.z && o3.toNextSegmentType !== "through_obstacle" && (Math.abs(o3.x - i3.x) > Hs || Math.abs(o3.y - i3.y) > Hs || !e2.vias.some((t34) => Math.abs(t34.x - o3.x) <= Hs && Math.abs(t34.y - o3.y) <= Hs)))
throw new Error("repair04 merge rejected a disconnected or missing via");
}
for (const n3 of e2.vias) {
if (!(Number.isFinite(n3.x) && Number.isFinite(n3.y) && Gs(n3, i2) && e2.route.some((t34) => Math.abs(t34.x - n3.x) <= Hs && Math.abs(t34.y - n3.y) <= Hs)))
throw new Error("repair04 merge rejected an invalid via position");
if (!Gs(n3, o2, 0.00000004) && !t33.vias.some((t34) => Js(t34) === Js(n3)))
throw new Error("repair04 merge rejected a new via in the boundary collar");
}
for (const n3 of t33.vias)
if (!Gs(n3, o2, 0.00000004) && !e2.vias.some((t34) => Js(t34) === Js(n3)))
throw new Error("repair04 merge rejected a changed via in the boundary collar");
};
var zI = (t33, e2) => {
for (const n2 of e2) {
const e3 = t33[t33.length - 1];
e3 && qs(e3, n2) && Js(e3) === Js(n2) || t33.push(structuredClone(n2));
}
};
var BI = (t33, e2, n2) => {
const o2 = new Set(e2.route.map(Js)), i2 = new Set(n2.flatMap((t34) => t34.originalFragment.route.map(Js)).filter((t34) => !o2.has(t34))), r2 = [];
for (const e3 of t33)
for (r2.push(e3);r2.length >= 3; ) {
const t34 = r2[r2.length - 3], e4 = r2[r2.length - 2], n3 = r2[r2.length - 1];
if (!i2.has(Js(e4)))
break;
if (t34.z !== e4.z || e4.z !== n3.z && t34.toNextSegmentType !== "through_obstacle")
break;
if (t34.toNextSegmentType !== e4.toNextSegmentType || t34.insideJumperPad !== e4.insideJumperPad || t34.traceThickness !== e4.traceThickness || Js(t34.toNextSegmentCircuitJsonMetadata) !== Js(e4.toNextSegmentCircuitJsonMetadata))
break;
const o3 = n3.x - t34.x, s2 = n3.y - t34.y, a2 = o3 * o3 + s2 * s2;
if (a2 <= 0.00000000000000010000000000000001)
break;
const c2 = (e4.x - t34.x) * s2 - (e4.y - t34.y) * o3, l2 = ((e4.x - t34.x) * o3 + (e4.y - t34.y) * s2) / a2;
if (Math.abs(c2) > Hs * Math.sqrt(a2) || l2 < 0 || l2 > 1)
break;
r2.splice(r2.length - 2, 1);
}
return r2;
};
var FI = (t33) => {
if (!Number.isInteger(t33.segmentIndex) || t33.segmentIndex < 0 || !Number.isFinite(t33.t) || t33.t < 0 || t33.t > 1)
throw new Error("repair04 merge received invalid fragment provenance");
return t33.segmentIndex + t33.t;
};
var jI = ({ routes: t33, region: e2, repairedRoutes: n2 }) => {
if (n2.length !== e2.routeMappings.length || e2.lockedPointIndices.length !== n2.length)
throw new Error("repair04 merge requires exactly one replacement for every extracted fragment");
const o2 = new Map;
for (let i2 = 0;i2 < n2.length; i2 += 1) {
const r2 = e2.routeMappings[i2], s2 = n2[i2];
if (!t33[r2.sourceRouteIndex])
throw new Error("repair04 merge source route no longer exists");
if (LI(r2.originalFragment, s2, e2.lockedPointIndices[i2], e2.mutableBounds, e2.contextBounds, e2.srj.layerCount), Js(r2.originalFragment) === Js(s2))
continue;
const a2 = o2.get(r2.sourceRouteIndex) ?? [];
a2.push({ mapping: r2, repaired: s2 }), o2.set(r2.sourceRouteIndex, a2);
}
return t33.map((t34, e3) => {
const n3 = o2.get(e3);
if (!n3)
return t34;
n3.sort((t35, e4) => FI(t35.mapping.start) - FI(e4.mapping.start));
const i2 = [];
let r2 = 0;
for (const { mapping: e4, repaired: o3 } of n3) {
const n4 = FI(e4.start), s3 = FI(e4.end);
if (n4 < r2 - Hs || s3 < n4 || s3 > t34.route.length - 1 + Hs)
throw new Error("repair04 merge received overlapping or stale fragment provenance");
if (Ks(t34, n4, s3) !== e4.sourceGeometryKey)
throw new Error("repair04 merge rejected stale source geometry");
zI(i2, Qs(t34, r2, n4)), zI(i2, o3.route), r2 = s3;
}
zI(i2, Qs(t34, r2, t34.route.length - 1));
const s2 = new Set(n3.flatMap(({ mapping: t35 }) => t35.originalFragment.vias.map((t36) => `${t36.x},${t36.y}`))), a2 = t34.vias.filter((t35) => !s2.has(`${t35.x},${t35.y}`)).map((t35) => structuredClone(t35));
for (const { repaired: t35 } of n3)
for (const e4 of t35.vias)
a2.some((t36) => Math.abs(t36.x - e4.x) <= Hs && Math.abs(t36.y - e4.y) <= Hs) || a2.push(structuredClone(e4));
return { ...t34, route: BI(i2, t34, n3.map(({ mapping: t35 }) => t35)), vias: a2 };
});
};
function $I(t33, e2, n2) {
return t33.minX - n2 - Hs > e2.maxX || t33.maxX + n2 + Hs < e2.minX || t33.minY - n2 - Hs > e2.maxY || t33.maxY + n2 + Hs < e2.minY;
}
var YI = 0.25;
function XI(t33, e2, n2, o2) {
const i2 = e2.x - t33.x, r2 = e2.y - t33.y, s2 = o2.x - n2.x, a2 = o2.y - n2.y, c2 = t33.x - n2.x, l2 = t33.y - n2.y, h2 = i2 * i2 + r2 * r2, d2 = i2 * s2 + r2 * a2, u2 = s2 * s2 + a2 * a2, p2 = i2 * c2 + r2 * l2, m2 = s2 * c2 + a2 * l2, g2 = h2 * u2 - d2 * d2;
let f2 = g2 > 0.000000000000001 ? Math.max(0, Math.min(1, (d2 * m2 - u2 * p2) / g2)) : 0;
u2 < 0.000000000000001 && (f2 = h2 > 0.000000000000001 ? Math.max(0, Math.min(1, -p2 / h2)) : 0);
let y2 = u2 > 0.000000000000001 ? (d2 * f2 + m2) / u2 : 0;
y2 < 0 ? (y2 = 0, f2 = h2 > 0.000000000000001 ? Math.max(0, Math.min(1, -p2 / h2)) : 0) : y2 > 1 && (y2 = 1, f2 = h2 > 0.000000000000001 ? Math.max(0, Math.min(1, (d2 - p2) / h2)) : 0);
const _2 = t33.x + f2 * i2 - n2.x - y2 * s2, b2 = t33.y + f2 * r2 - n2.y - y2 * a2;
return { s: f2, t: y2, x: _2, y: b2, distance: Math.hypot(_2, b2) };
}
function WI(t33, e2) {
let n2 = { x: 0, y: 0, depth: 1 / 0 };
for (let o2 = 0;o2 < e2.length; o2++) {
const i2 = e2[o2], r2 = e2[(o2 + 1) % e2.length], s2 = r2.x - i2.x, a2 = r2.y - i2.y, c2 = Math.hypot(s2, a2), l2 = a2 / c2, h2 = -s2 / c2, d2 = -((t33.x - i2.x) * l2 + (t33.y - i2.y) * h2);
if (d2 < 0)
return null;
d2 < n2.depth && (n2 = { x: l2, y: h2, depth: d2 });
}
return n2;
}
function VI(t33, e2) {
const n2 = [];
for (let t34 = 1;t34 < e2.length; t34++) {
const o2 = e2[t34 - 1], i2 = e2[t34];
if (o2.z !== i2.z && o2.toNextSegmentType !== "through_obstacle") {
if (o2.x !== i2.x || o2.y !== i2.y)
throw new Error("repair04: negotiated via endpoints must coincide");
n2.some((t35) => t35.x === i2.x && t35.y === i2.y) || n2.push({ x: i2.x, y: i2.y });
}
}
return { ...t33, route: e2, vias: n2 };
}
function HI(t33) {
for (const e3 of [t33.maxPathSearchNodes, t33.maxPathSearchCalls])
if (!Number.isSafeInteger(e3) || e3 < 0)
throw new Error("repair04: negotiated work budgets must be nonnegative integers");
if (t33.maxPathSearchNodesPerCall !== undefined && (!Number.isSafeInteger(t33.maxPathSearchNodesPerCall) || t33.maxPathSearchNodesPerCall < 1))
throw new Error("repair04: per-path work budget must be a positive integer");
if (t33.pathHeuristicWeight !== undefined && (!Number.isFinite(t33.pathHeuristicWeight) || t33.pathHeuristicWeight < 1))
throw new Error("repair04: heuristic weight must be finite and at least one");
if (t33.pathGridSizeScale !== undefined && (!Number.isFinite(t33.pathGridSizeScale) || t33.pathGridSizeScale <= 0))
throw new Error("repair04: path grid scale must be positive and finite");
if (t33.viaHoleDiameter !== undefined && (!Number.isFinite(t33.viaHoleDiameter) || t33.viaHoleDiameter <= 0 || t33.routes.some((e3) => t33.viaHoleDiameter > e3.viaDiameter)))
throw new Error("repair04: via hole diameter must be positive and fit the copper");
const e2 = (e3) => e3.x >= t33.bounds.minX - Hs && e3.x <= t33.bounds.maxX + Hs && e3.y >= t33.bounds.minY - Hs && e3.y <= t33.bounds.maxY + Hs, n2 = [], o2 = t33.routes.map(() => []);
for (let i3 = 0;i3 < t33.routes.length; i3++) {
const r3 = t33.routes[i3], s3 = r3.route, a3 = s3.flatMap((e3, n3) => {
const o3 = s3[n3 - 1], a4 = s3[n3 + 1], c3 = e3.traceThickness ?? r3.traceThickness, l3 = o3 && (o3.traceThickness ?? r3.traceThickness) !== c3 || a4 && (a4.traceThickness ?? r3.traceThickness) !== c3, h3 = o3 && o3.z !== e3.z && (!t33.allowLayerChanges || t33.isLocked(i3, n3) || t33.isLocked(i3, n3 - 1)) || a4 && a4.z !== e3.z && (!t33.allowLayerChanges || t33.isLocked(i3, n3) || t33.isLocked(i3, n3 + 1));
return n3 === 0 || n3 === s3.length - 1 || t33.isLocked(i3, n3) || e3.pcb_port_id || e3.toNextSegmentType || e3.insideJumperPad || l3 || h3 ? [n3] : [];
});
for (let c3 = 1;c3 < a3.length; c3++) {
const l3 = s3.slice(a3[c3 - 1], a3[c3] + 1), h3 = l3[0].traceThickness ?? r3.traceThickness, d3 = l3.slice(1).every((e3, n3) => {
const o3 = l3[n3], i4 = (o3.x + e3.x) / 2, r4 = (o3.y + e3.y) / 2;
return i4 > t33.bounds.minX + 0.00000004 && i4 < t33.bounds.maxX - 0.00000004 && r4 > t33.bounds.minY + 0.00000004 && r4 < t33.bounds.maxY - 0.00000004;
}), u3 = l3.slice(1).every((e3, n3) => {
const o3 = l3[n3], r4 = a3[c3 - 1] + n3;
return o3.z === e3.z || !t33.isLocked(i3, r4) && !t33.isLocked(i3, r4 + 1);
}), p3 = l3.every(e2) && d3 && u3 && !r3.jumpers?.length && l3.every((t34) => !t34.toNextSegmentType && !t34.insideJumperPad && (t34.traceThickness ?? r3.traceThickness) === h3) && (t33.allowLayerChanges || l3.every((t34) => t34.z === l3[0].z));
o2[i3].push(n2.length), n2.push({ routeIndex: i3, mutable: Boolean(p3), route: VI({ ...r3, traceThickness: h3 }, l3) });
}
}
const i2 = n2.map((t34) => t34.route), r2 = n2.filter((t34) => !t34.mutable).map((t34) => t34.route), s2 = xI(t33.srj, t33.routes), a2 = (t34) => s2.get(t34.connectionName) ?? t34.connectionName, c2 = new Set;
for (const t34 of n2)
for (const e3 of [t34.route.route[0], t34.route.route.at(-1)]) {
const n3 = e3.traceThickness ?? t34.route.traceThickness, o3 = `${a2(t34.route)}|${e3.x}|${e3.y}|${e3.z}|${n3}`;
if (c2.has(o3))
continue;
c2.add(o3);
const i3 = { x: e3.x, y: e3.y, z: e3.z };
r2.push({ ...t34.route, traceThickness: n3, route: [i3, i3], vias: [] });
}
const l2 = n2.map(({ route: t34 }) => {
let e3 = 0;
for (let n3 = 1;n3 < t34.route.length; n3++) {
const o3 = t34.route[n3 - 1], i3 = t34.route[n3];
e3 += o3.z === i3.z ? Math.hypot(o3.x - i3.x, o3.y - i3.y) : 1;
}
return e3;
}), h2 = new Set, d2 = new Set(t33.dirtyRouteIndices), u2 = [], p2 = new Set, m2 = (t34) => {
p2.has(t34) || h2.has(t34) || !n2[t34].mutable || (p2.add(t34), u2.push(t34));
};
n2.forEach((t34, e3) => {
d2.has(t34.routeIndex) && m2(e3);
});
let g2 = 0, f2 = 0, y2 = 0;
for (;y2 < u2.length && g2 < t33.maxPathSearchNodes && f2 < t33.maxPathSearchCalls; ) {
const e3 = u2[y2++];
p2.delete(e3);
const o3 = i2[e3], s3 = a2(o3), c3 = [];
for (let o4 = 0;o4 < n2.length; o4++) {
if (o4 === e3)
continue;
const r3 = i2[o4], l3 = a2(r3);
for (let e4 = 1;e4 < r3.route.length; e4++) {
const i3 = r3.route[e4 - 1], a3 = r3.route[e4];
if (i3.toNextSegmentType === "through_obstacle")
continue;
const d4 = !n2[o4].mutable || h2.has(o4);
if (i3.z === a3.z && (l3 === s3 || d4))
continue;
const u3 = (i3.z !== a3.z ? r3.viaDiameter : Math.max(i3.traceThickness ?? r3.traceThickness, a3.traceThickness ?? r3.traceThickness)) / 2, p3 = { a: i3, b: a3, radius: u3, minX: Math.min(i3.x, a3.x), maxX: Math.max(i3.x, a3.x), minY: Math.min(i3.y, a3.y), maxY: Math.max(i3.y, a3.y), ...Ys(t33.srj, i3, a3), spanIndex: o4, owner: l3, index: c3.length, cellX: Math.floor(Math.min(i3.x, a3.x) - u3), cellY: Math.floor(Math.min(i3.y, a3.y) - u3), immutable: d4 };
c3.push(p3);
}
}
const d3 = (t34) => {
if (!t34.length)
return;
const e4 = new Ft(t34.length);
for (const n3 of t34)
e4.add(n3.minX - n3.radius - Hs, n3.minY - n3.radius - Hs, n3.maxX + n3.radius + Hs, n3.maxY + n3.radius + Hs);
return e4.finish(), { index: e4, copper: t34 };
}, _2 = d3(c3), b2 = new Map;
for (let e4 = 0;e4 < t33.srj.layerCount; e4++)
b2.set(e4, d3(c3.filter((t34) => t34.minZ <= e4 && t34.maxZ >= e4)));
const x2 = (e4, n3) => {
const i3 = e4.z !== n3.z, r3 = Math.min(e4.x, n3.x), a3 = Math.max(e4.x, n3.x), c4 = Math.min(e4.y, n3.y), l3 = Math.max(e4.y, n3.y), h3 = (i3 ? o3.viaDiameter : o3.traceThickness) / 2 + Math.max(t33.traceClearance, t33.viaClearance), d4 = [], u3 = Ys(t33.srj, e4, n3), p3 = i3 ? _2 : b2.get(e4.z), m3 = p3?.index.search(r3 - h3 - Hs, c4 - h3 - Hs, a3 + h3 + Hs, l3 + h3 + Hs) ?? [];
for (const h4 of m3) {
const m4 = p3.copper[h4], g4 = i3 && m4.minZ !== m4.maxZ, f4 = m4.minZ <= u3.maxZ && m4.maxZ >= u3.minZ;
if (!f4 && !g4)
continue;
if (m4.immutable && !g4)
continue;
if (m4.owner === s3 && (!g4 || e4.x === m4.a.x && e4.y === m4.a.y))
continue;
const y3 = (i3 ? o3.viaDiameter : o3.traceThickness) / 2 + (g4 ? t33.viaClearance : t33.traceClearance) + m4.radius, _3 = (t33.viaHoleDiameter ?? o3.viaDiameter) / 2 + (t33.viaHoleDiameter ?? 2 * m4.radius) / 2 + t33.viaClearance, b3 = g4 ? f4 && m4.owner !== s3 ? Math.max(y3, _3) : _3 : y3;
if (r3 - b3 - Hs > m4.maxX || a3 + b3 + Hs < m4.minX || c4 - b3 - Hs > m4.maxY || l3 + b3 + Hs < m4.minY)
continue;
const x3 = Oe(e4, n3, m4.a, m4.b);
x3 < b3 - Hs && d4.push({ copper: m4, ratio: (b3 - x3) / (b3 * b3) });
}
const g3 = Math.floor(r3 - h3), f3 = Math.floor(c4 - h3);
return d4.sort((t34, e5) => {
const n4 = Math.max(g3, t34.copper.cellX) - Math.max(g3, e5.copper.cellX);
if (n4 !== 0)
return n4;
return Math.max(f3, t34.copper.cellY) - Math.max(f3, e5.copper.cellY) || t34.copper.index - e5.copper.index;
}), d4;
}, v2 = (e4, n3) => {
const o4 = (e4.x + n3.x) / 2, i3 = (e4.y + n3.y) / 2;
if (o4 <= t33.bounds.minX + 0.00000004 || o4 >= t33.bounds.maxX - 0.00000004 || i3 <= t33.bounds.minY + 0.00000004 || i3 >= t33.bounds.maxY - 0.00000004)
return 1 / 0;
const r3 = new Map;
for (const { copper: t34, ratio: o5 } of x2(e4, n3)) {
if (t34.owner === s3 || t34.immutable)
return 1 / 0;
r3.set(t34.owner, Math.max(r3.get(t34.owner) ?? 0, o5 * l2[t34.spanIndex]));
}
let a3 = 0;
for (const t34 of r3.values())
a3 += t34;
return (e4.z === n3.z ? Math.hypot(e4.x - n3.x, e4.y - n3.y) : 1) * a3;
}, I2 = new Map, S2 = (e4, n3) => {
if (e4.z === n3.z || t33.srj.allowBlindAndBuriedVias === true || e4.x !== n3.x || e4.y !== n3.y)
return v2(e4, n3);
let o4 = I2.get(e4.x);
const i3 = o4?.get(e4.y);
if (i3 !== undefined)
return i3;
const r3 = v2(e4, n3);
return o4 || (o4 = new Map, I2.set(e4.x, o4)), o4.set(e4.y, r3), r3;
}, C2 = { nodesPopped: 0, completionReason: "no-path" }, P2 = ta({ srj: t33.srj, routes: [...r2, o3], routeIndex: r2.length, start: o3.route[0], end: o3.route.at(-1), bounds: t33.bounds, traceThickness: o3.traceThickness, traceClearance: t33.traceClearance, viaClearance: t33.viaClearance, gridSize: Math.min(0.1, o3.traceThickness * (t33.pathGridSizeScale ?? 1) / 2), allowLayerChanges: t33.allowLayerChanges, maxNodes: Math.min(t33.maxPathSearchNodesPerCall ?? t33.maxPathSearchNodes, t33.maxPathSearchNodes - g2), heuristicWeight: t33.pathHeuristicWeight, stats: C2, getAdditionalEdgeCost: S2, existingPath: o3.route, viaHoleDiameter: t33.viaHoleDiameter });
if (f2++, g2 += C2.nodesPopped, t33.onSearch?.(C2), !P2) {
h2.add(e3), r2.push(o3);
continue;
}
i2[e3] = VI(o3, P2);
const M2 = new Set;
for (let t34 = 1;t34 < P2.length; t34++)
for (const { copper: e4 } of x2(P2[t34 - 1], P2[t34]))
M2.add(e4.spanIndex);
for (const t34 of [...M2].sort((t35, e4) => t35 - e4))
l2[t34]++, m2(t34);
M2.size && (l2[e3]++, m2(e3));
}
return { routes: t33.routes.map((t34, e3) => {
if (!o2[e3].length)
return t34;
return VI(t34, o2[e3].flatMap((t35, e4) => e4 === 0 ? i2[t35].route : i2[t35].route.slice(1)));
}), pathSearchNodes: g2, pathSearchCalls: f2, unresolvedSpanCount: p2.size + h2.size };
}
var GI = (t33, e2) => {
const n2 = e2 * Math.PI / 180;
return { x: t33.x * Math.cos(n2) - t33.y * Math.sin(n2), y: t33.x * Math.sin(n2) + t33.y * Math.cos(n2) };
};
var UI = ({ x: t33, y: e2, width: n2, height: o2, ccwRotation: i2 }) => {
const r2 = n2 / 2, s2 = o2 / 2;
return [{ x: -r2, y: -s2 }, { x: r2, y: -s2 }, { x: r2, y: s2 }, { x: -r2, y: s2 }].map((n3) => {
const o3 = GI(n3, i2);
return { x: t33 + o3.x, y: e2 + o3.y };
});
};
var ZI = (t33) => {
const e2 = t33.shape === "rotated_pill" ? t33.ccw_rotation : 0, n2 = Math.max(Math.max(t33.width, t33.height) / 2 - t33.radius, 0), o2 = t33.width >= t33.height ? { x: n2, y: 0 } : { x: 0, y: n2 }, i2 = GI(o2, e2);
return { start: { x: t33.x - i2.x, y: t33.y - i2.y }, end: { x: t33.x + i2.x, y: t33.y + i2.y }, radius: t33.radius };
};
var qI = (t33) => {
if (t33.type === "pcb_smtpad") {
if (t33.shape === "polygon")
return t33.points;
if (t33.shape === "rotated_rect")
return UI({ x: t33.x, y: t33.y, width: t33.width, height: t33.height, ccwRotation: t33.ccw_rotation });
}
if (t33.type === "pcb_plated_hole" && "rect_pad_width" in t33 && "rect_pad_height" in t33)
return UI({ x: t33.x, y: t33.y, width: t33.rect_pad_width, height: t33.rect_pad_height, ccwRotation: "rect_ccw_rotation" in t33 && typeof t33.rect_ccw_rotation == "number" ? t33.rect_ccw_rotation : 0 });
throw new Error(`Expected polygonal pad geometry, got ${t33.type} with shape "${t33.shape}"`);
};
var JI = (t33) => t33.map((e2, n2) => [e2, t33[(n2 + 1) % t33.length]]);
var QI = (t33, e2, n2, o2) => {
const i2 = ve(t33, e2, n2, o2);
if (i2)
return { distance: 0, pointOnA: i2, pointOnB: i2, center: i2 };
const r2 = [{ pointOnA: t33, pointOnB: ze(t33, n2, o2) }, { pointOnA: e2, pointOnB: ze(e2, n2, o2) }, { pointOnA: ze(n2, t33, e2), pointOnB: n2 }, { pointOnA: ze(o2, t33, e2), pointOnB: o2 }];
let s2 = r2[0], a2 = Ye(s2.pointOnA, s2.pointOnB);
for (const t34 of r2.slice(1)) {
const e3 = Ye(t34.pointOnA, t34.pointOnB);
e3 < a2 && (s2 = t34, a2 = e3);
}
return { distance: Oe(t33, e2, n2, o2), pointOnA: s2.pointOnA, pointOnB: s2.pointOnB, center: { x: (s2.pointOnA.x + s2.pointOnB.x) / 2, y: (s2.pointOnA.y + s2.pointOnB.y) / 2 } };
};
function KI(t33, e2) {
return Math.sqrt((e2.x - t33.x) ** 2 + (e2.y - t33.y) ** 2);
}
var tS = 0.000000001;
var eS = 0.000000001;
function nS(t33, e2) {
const n2 = (t33.y - e2.start.y) * (e2.end.x - e2.start.x) - (t33.x - e2.start.x) * (e2.end.y - e2.start.y);
if (Math.abs(n2) > tS)
return false;
const o2 = (t33.x - e2.start.x) * (e2.end.x - e2.start.x) + (t33.y - e2.start.y) * (e2.end.y - e2.start.y);
if (o2 < -1e-9)
return false;
return o2 <= (e2.end.x - e2.start.x) ** 2 + (e2.end.y - e2.start.y) ** 2 + tS;
}
function oS(t33, e2) {
let n2 = false;
for (let o2 = 0, i2 = e2.length - 1;o2 < e2.length; i2 = o2++) {
const r2 = e2[o2], s2 = e2[i2];
if (nS(t33, { start: r2, end: s2 }))
return true;
r2.y > t33.y != s2.y > t33.y && t33.x < (s2.x - r2.x) * (t33.y - r2.y) / (s2.y - r2.y) + r2.x && (n2 = !n2);
}
return n2;
}
function iS(t33, e2) {
if (e2.type === "pcb_smtpad") {
if (e2.shape === "circle")
return KI(t33, e2) <= e2.radius + eS;
if (e2.shape === "rect") {
const n2 = e2.width / 2, o2 = e2.height / 2;
return Math.abs(t33.x - e2.x) <= n2 + eS && Math.abs(t33.y - e2.y) <= o2 + eS;
}
if (e2.shape === "rotated_rect")
return oS(t33, qI(e2));
if (e2.shape === "pill" || e2.shape === "rotated_pill") {
if (e2.shape === "rotated_pill") {
const n3 = ZI(e2);
return be(t33, n3.start, n3.end) <= n3.radius + eS;
}
const n2 = e2.width / 2, o2 = e2.height / 2, i2 = e2.radius;
if (Math.abs(t33.x - e2.x) <= n2 - i2 + eS && Math.abs(t33.y - e2.y) <= o2 + eS)
return true;
const r2 = Math.max(Math.abs(t33.x - e2.x) - (n2 - i2), 0), s2 = Math.max(Math.abs(t33.y - e2.y) - (o2 - i2), 0), a2 = i2 + eS;
return r2 * r2 + s2 * s2 <= a2 * a2;
}
if (e2.shape === "polygon")
return oS(t33, e2.points);
}
if (e2.type === "pcb_plated_hole") {
if (e2.shape === "circle")
return KI(t33, e2) <= e2.outer_diameter / 2 + eS;
if ("rect_pad_width" in e2 && "rect_pad_height" in e2)
return oS(t33, qI(e2));
if (e2.shape === "oval" || e2.shape === "pill")
return Math.abs(t33.x - e2.x) <= e2.outer_width / 2 + eS && Math.abs(t33.y - e2.y) <= e2.outer_height / 2 + eS;
}
return false;
}
function rS(t33, e2, n2, o2) {
return Math.sqrt((n2 - t33) ** 2 + (o2 - e2) ** 2);
}
var sS = 0.1;
var aS = 0.1;
var cS = 0.2;
var lS = 0.1;
var hS = 0.005;
var dS = (t33) => t33.find((t34) => t34.type === "pcb_board");
var uS = (t33, e2) => t33?.[e2];
var pS = (t33) => hg([t33]);
var mS = (t33) => {
const e2 = pS(t33);
return Math.min(e2.maxX - e2.minX, e2.maxY - e2.minY) / 2;
};
var gS = (t33) => {
const e2 = ((t34) => {
const e3 = pS(t34);
return $e({ x: e3.minX, y: e3.minY }, { x: e3.maxX, y: e3.maxY });
})(t33);
return { kind: "circle", x: e2.x, y: e2.y, radius: mS(t33) };
};
var fS = (t33) => tg(t33).pcb_trace.list().flatMap((t34) => {
const e2 = [];
for (let n2 = 0;n2 < t34.route.length - 1; n2++) {
const o2 = t34.route[n2], i2 = t34.route[n2 + 1];
o2.route_type === "wire" && (i2.route_type === "wire" && o2.layer === i2.layer && e2.push({ type: "pcb_trace_segment", pcb_trace_id: t34.pcb_trace_id, _pcbTrace: t34, thickness: "width" in o2 ? o2.width : ("width" in i2) ? i2.width : lS, layer: o2.layer, x1: o2.x, y1: o2.y, x2: i2.x, y2: i2.y }));
}
return e2;
});
var yS = (t33) => {
const e2 = t33._pcbTrace.route.flatMap((t34) => t34.route_type === "through_pad" ? [t34.start, t34.end] : [{ x: t34.x, y: t34.y }]), n2 = e2[0], o2 = e2[e2.length - 1];
return n2 && o2 ? $e(n2, o2) : $e({ x: t33.x1, y: t33.y1 }, { x: t33.x2, y: t33.y2 });
};
var _S = ({ tracePoint: t33, obstaclePoint: e2, traceRadius: n2, obstacleRadius: o2 }) => {
const i2 = e2.x - t33.x, r2 = e2.y - t33.y, s2 = Math.hypot(i2, r2);
if (s2 === 0)
return $e(t33, e2);
const a2 = i2 / s2, c2 = r2 / s2;
return $e({ x: t33.x + a2 * n2, y: t33.y + c2 * n2 }, { x: e2.x - a2 * o2, y: e2.y - c2 * o2 });
};
var bS = (t33, e2) => {
const n2 = { x: t33.x1, y: t33.y1 }, o2 = { x: t33.x2, y: t33.y2 }, i2 = t33.thickness / 2;
if (e2.type === "pcb_via" || ((r2 = e2).type === "pcb_via" || r2.shape === "circle")) {
const t34 = e2.type === "pcb_via" ? { x: e2.x, y: e2.y, radius: e2.outer_diameter / 2 } : gS(e2), r3 = ze(t34, n2, o2);
return { gap: Le(n2, o2, t34) - i2, center: _S({ tracePoint: r3, obstaclePoint: t34, traceRadius: i2, obstacleRadius: t34.radius }) };
}
var r2;
if (((t34) => t34.type === "pcb_smtpad" && (t34.shape === "pill" || t34.shape === "rotated_pill"))(e2)) {
const n3 = ((t34, e3) => {
const n4 = ZI(e3), o3 = QI({ x: t34.x1, y: t34.y1 }, { x: t34.x2, y: t34.y2 }, n4.start, n4.end);
return { distance: o3.distance, center: o3.center, radius: n4.radius, tracePoint: o3.pointOnA, obstaclePoint: o3.pointOnB };
})(t33, e2);
return { gap: n3.distance - i2 - n3.radius, center: _S({ tracePoint: n3.tracePoint, obstaclePoint: n3.obstaclePoint, traceRadius: i2, obstacleRadius: n3.radius }) };
}
const s2 = ((t34, e3, n3) => {
if (n3.length < 3)
return { distance: Number.POSITIVE_INFINITY, center: t34, tracePoint: t34, obstaclePoint: t34 };
const o3 = JI(n3).map(([n4, o4]) => ve(t34, e3, n4, o4)).filter((t35) => t35 !== null);
if (o3.length > 0) {
const n4 = e3.x - t34.x, i4 = e3.y - t34.y, r3 = n4 * n4 + i4 * i4;
return o3.sort((e4, o4) => ((e4.x - t34.x) * n4 + (e4.y - t34.y) * i4) / r3 - ((o4.x - t34.x) * n4 + (o4.y - t34.y) * i4) / r3), { distance: 0, center: o3[0], tracePoint: o3[0], obstaclePoint: o3[0] };
}
if (Ne(t34, n3) || Ne(e3, n3)) {
const n4 = { x: (t34.x + e3.x) / 2, y: (t34.y + e3.y) / 2 };
return { distance: 0, center: n4, tracePoint: n4, obstaclePoint: n4 };
}
let i3 = QI(t34, e3, n3[0], n3[1]);
for (const [o4, r3] of JI(n3).slice(1)) {
const n4 = QI(t34, e3, o4, r3);
n4.distance < i3.distance && (i3 = n4);
}
return { distance: i3.distance, center: i3.center, tracePoint: i3.pointOnA, obstaclePoint: i3.pointOnB };
})(n2, o2, ((t34) => {
if (t34.type === "pcb_smtpad" && (t34.shape === "polygon" || t34.shape === "rotated_rect"))
return { kind: "polygon", points: qI(t34) };
if (t34.type === "pcb_plated_hole" && "rect_pad_width" in t34 && "rect_pad_height" in t34)
return { kind: "polygon", points: qI(t34) };
const e3 = pS(t34);
return { kind: "polygon", points: [{ x: e3.minX, y: e3.minY }, { x: e3.maxX, y: e3.minY }, { x: e3.maxX, y: e3.maxY }, { x: e3.minX, y: e3.maxY }] };
})(e2).points);
return { gap: s2.distance - i2, center: _S({ tracePoint: s2.tracePoint, obstaclePoint: s2.obstaclePoint, traceRadius: i2, obstacleRadius: 0 }) };
};
var xS = (t33) => t33 <= 0;
var vS = class {
buckets;
objectsById;
getBounds;
getId;
CELL_SIZE = 0.4;
constructor({ objects: t33, getBounds: e2, getId: n2, CELL_SIZE: o2 }) {
this.buckets = new Map, this.objectsById = new Map, this.getBounds = e2, this.getId = n2 ?? (() => this._getNextId()), this.CELL_SIZE = o2 ?? this.CELL_SIZE;
for (const e3 of t33)
this.addObject(e3);
}
_idCounter = 0;
_getNextId() {
return "" + this._idCounter++;
}
addObject(t33) {
const e2 = this.getBounds(t33), n2 = this.getId(t33), o2 = { ...t33, spatialIndexId: n2 };
this.objectsById.set(n2, o2);
const i2 = Math.floor(e2.minX / this.CELL_SIZE), r2 = Math.floor(e2.minY / this.CELL_SIZE), s2 = Math.floor(e2.maxX / this.CELL_SIZE), a2 = Math.floor(e2.maxY / this.CELL_SIZE);
for (let t34 = i2;t34 <= s2; t34++)
for (let e3 = r2;e3 <= a2; e3++) {
const n3 = `${t34}x${e3}`, i3 = this.buckets.get(n3);
i3 ? i3.push(o2) : this.buckets.set(n3, [o2]);
}
}
removeObject(t33) {
const e2 = this.objectsById.get(t33);
if (!e2)
return false;
this.objectsById.delete(t33);
const n2 = this.getBounds(e2), o2 = Math.floor(n2.minX / this.CELL_SIZE), i2 = Math.floor(n2.minY / this.CELL_SIZE), r2 = Math.floor(n2.maxX / this.CELL_SIZE), s2 = Math.floor(n2.maxY / this.CELL_SIZE);
for (let e3 = o2;e3 <= r2; e3++)
for (let n3 = i2;n3 <= s2; n3++) {
const o3 = `${e3}x${n3}`, i3 = this.buckets.get(o3);
if (i3) {
const e4 = i3.findIndex((e5) => e5.spatialIndexId === t33);
e4 !== -1 && (i3.splice(e4, 1), i3.length === 0 && this.buckets.delete(o3));
}
}
return true;
}
getBucketKey(t33, e2) {
return `${Math.floor(t33 / this.CELL_SIZE)}x${Math.floor(e2 / this.CELL_SIZE)}`;
}
getObjectsInBounds(t33, e2 = 0) {
const n2 = [], o2 = new Set, i2 = Math.floor((t33.minX - e2) / this.CELL_SIZE), r2 = Math.floor((t33.minY - e2) / this.CELL_SIZE), s2 = Math.floor((t33.maxX + e2) / this.CELL_SIZE), a2 = Math.floor((t33.maxY + e2) / this.CELL_SIZE);
for (let t34 = i2;t34 <= s2; t34++)
for (let e3 = r2;e3 <= a2; e3++) {
const i3 = `${t34}x${e3}`, r3 = this.buckets.get(i3) || [];
for (const t35 of r3) {
const e4 = t35.spatialIndexId;
o2.has(e4) || (o2.add(e4), n2.push(t35));
}
}
return n2;
}
};
function IS(t33) {
return t33.type === "pcb_trace_segment" || t33.type === "pcb_smtpad" ? [t33.layer] : t33.type === "pcb_plated_hole" ? Array.isArray(t33.layers) ? t33.layers : [...Cd] : t33.type === "pcb_hole" ? [...Cd] : t33.type === "pcb_via" ? Array.isArray(t33.layers) ? t33.layers : [...Cd] : t33.type === "pcb_keepout" && Array.isArray(t33.layers) ? t33.layers : [];
}
var SS = (t33, e2) => {
const n2 = { x: t33.x1, y: t33.y1 }, o2 = { x: t33.x2, y: t33.y2 }, i2 = e2.minX, r2 = e2.minY, s2 = e2.maxX, a2 = e2.maxY;
if (n2.x === o2.x && n2.y === o2.y) {
const t34 = Math.max(i2, Math.min(s2, n2.x)), e3 = Math.max(r2, Math.min(a2, n2.y));
return t34 === n2.x && e3 === n2.y ? { x: n2.x, y: n2.y } : { x: t34, y: e3 };
}
const c2 = o2.x - n2.x, l2 = o2.y - n2.y, h2 = c2 !== 0 ? (i2 - n2.x) / c2 : Number.NEGATIVE_INFINITY, d2 = c2 !== 0 ? (s2 - n2.x) / c2 : Number.POSITIVE_INFINITY, u2 = l2 !== 0 ? (r2 - n2.y) / l2 : Number.NEGATIVE_INFINITY, p2 = l2 !== 0 ? (a2 - n2.y) / l2 : Number.POSITIVE_INFINITY, m2 = Math.max(Math.min(h2, d2), Math.min(u2, p2)), g2 = Math.min(Math.max(h2, d2), Math.max(u2, p2));
if (m2 <= g2 && g2 >= 0 && m2 <= 1) {
const t34 = Math.max(0, Math.min(1, m2));
return { x: n2.x + t34 * c2, y: n2.y + t34 * l2 };
}
const f2 = { x: Math.max(i2, Math.min(s2, n2.x)), y: Math.max(r2, Math.min(a2, n2.y)) }, y2 = { x: Math.max(i2, Math.min(s2, o2.x)), y: Math.max(r2, Math.min(a2, o2.y)) }, _2 = (f2.x - n2.x) ** 2 + (f2.y - n2.y) ** 2, b2 = (y2.x - o2.x) ** 2 + (y2.y - o2.y) ** 2, x2 = [{ start: { x: i2, y: r2 }, end: { x: s2, y: r2 } }, { start: { x: s2, y: r2 }, end: { x: s2, y: a2 } }, { start: { x: s2, y: a2 }, end: { x: i2, y: a2 } }, { start: { x: i2, y: a2 }, end: { x: i2, y: r2 } }];
let v2 = Math.min(_2, b2), I2 = _2 <= b2 ? f2 : y2;
const S2 = (t34, e3, n3) => Math.max(e3, Math.min(n3, t34));
for (const t34 of x2) {
const e3 = { x: o2.x - n2.x, y: o2.y - n2.y }, i3 = { x: t34.end.x - t34.start.x, y: t34.end.y - t34.start.y }, r3 = { x: n2.x - t34.start.x, y: n2.y - t34.start.y }, s3 = e3.x * e3.x + e3.y * e3.y, a3 = e3.x * i3.x + e3.y * i3.y, c3 = e3.x * r3.x + e3.y * r3.y, l3 = i3.x * i3.x + i3.y * i3.y, h3 = i3.x * r3.x + i3.y * r3.y, d3 = s3 * l3 - a3 * a3;
if (Math.abs(d3) < 0.0000000001)
continue;
let u3 = (a3 * h3 - l3 * c3) / d3, p3 = (s3 * h3 - a3 * c3) / d3;
u3 = S2(u3, 0, 1), p3 = S2(p3, 0, 1);
const m3 = { x: n2.x + u3 * e3.x, y: n2.y + u3 * e3.y }, g3 = { x: t34.start.x + p3 * i3.x, y: t34.start.y + p3 * i3.y }, f3 = m3.x - g3.x, y3 = m3.y - g3.y, _3 = f3 * f3 + y3 * y3;
_3 < v2 && (v2 = _3, I2 = { x: (m3.x + g3.x) / 2, y: (m3.y + g3.y) / 2 });
}
return I2;
};
var CS = (t33, e2) => {
const n2 = { x: t33.x1, y: t33.y1 }, o2 = { x: t33.x2, y: t33.y2 }, i2 = { x: e2.x1, y: e2.y1 }, r2 = { x: e2.x2, y: e2.y2 }, s2 = { x: o2.x - n2.x, y: o2.y - n2.y }, a2 = { x: r2.x - i2.x, y: r2.y - i2.y }, c2 = s2.x * s2.x + s2.y * s2.y, l2 = a2.x * a2.x + a2.y * a2.y;
if (c2 === 0 || l2 === 0) {
if (c2 === 0 && l2 === 0)
return { x: (n2.x + i2.x) / 2, y: (n2.y + i2.y) / 2 };
if (c2 === 0) {
const t35 = MS(((n2.x - i2.x) * a2.x + (n2.y - i2.y) * a2.y) / l2, 0, 1), e4 = { x: i2.x + t35 * a2.x, y: i2.y + t35 * a2.y };
return { x: (n2.x + e4.x) / 2, y: (n2.y + e4.y) / 2 };
}
const t34 = MS(((i2.x - n2.x) * s2.x + (i2.y - n2.y) * s2.y) / c2, 0, 1), e3 = { x: n2.x + t34 * s2.x, y: n2.y + t34 * s2.y };
return { x: (e3.x + i2.x) / 2, y: (e3.y + i2.y) / 2 };
}
const h2 = n2.x - i2.x, d2 = n2.y - i2.y, u2 = s2.x * s2.x + s2.y * s2.y, p2 = s2.x * a2.x + s2.y * a2.y, m2 = s2.x * h2 + s2.y * d2, g2 = a2.x * a2.x + a2.y * a2.y, f2 = a2.x * h2 + a2.y * d2, y2 = u2 * g2 - p2 * p2;
if (y2 < 0.0000000001)
return PS(n2, o2, i2, r2, s2, a2, c2, l2);
let _2 = (p2 * f2 - g2 * m2) / y2, b2 = (u2 * f2 - p2 * m2) / y2;
_2 = MS(_2, 0, 1), b2 = MS(b2, 0, 1), b2 = (_2 * p2 + f2) / g2, b2 = MS(b2, 0, 1), _2 = (b2 * p2 - m2) / u2, _2 = MS(_2, 0, 1);
const x2 = n2.x + _2 * s2.x, v2 = n2.y + _2 * s2.y, I2 = i2.x + b2 * a2.x, S2 = i2.y + b2 * a2.y;
return { x: (x2 + I2) / 2, y: (v2 + S2) / 2 };
};
var PS = (t33, e2, n2, o2, i2, r2, s2, a2) => {
let c2 = ((n2.x - t33.x) * i2.x + (n2.y - t33.y) * i2.y) / s2;
c2 = MS(c2, 0, 1);
const l2 = { x: t33.x + c2 * i2.x, y: t33.y + c2 * i2.y };
let h2 = ((o2.x - t33.x) * i2.x + (o2.y - t33.y) * i2.y) / s2;
h2 = MS(h2, 0, 1);
const d2 = { x: t33.x + h2 * i2.x, y: t33.y + h2 * i2.y };
let u2 = ((t33.x - n2.x) * r2.x + (t33.y - n2.y) * r2.y) / a2;
u2 = MS(u2, 0, 1);
const p2 = { x: n2.x + u2 * r2.x, y: n2.y + u2 * r2.y };
let m2 = ((e2.x - n2.x) * r2.x + (e2.y - n2.y) * r2.y) / a2;
m2 = MS(m2, 0, 1);
const g2 = { x: n2.x + m2 * r2.x, y: n2.y + m2 * r2.y }, f2 = [{ pointA: l2, pointB: n2, distance: Math.sqrt((l2.x - n2.x) ** 2 + (l2.y - n2.y) ** 2) }, { pointA: d2, pointB: o2, distance: Math.sqrt((d2.x - o2.x) ** 2 + (d2.y - o2.y) ** 2) }, { pointA: t33, pointB: p2, distance: Math.sqrt((t33.x - p2.x) ** 2 + (t33.y - p2.y) ** 2) }, { pointA: e2, pointB: g2, distance: Math.sqrt((e2.x - g2.x) ** 2 + (e2.y - g2.y) ** 2) }].reduce((t34, e3) => e3.distance < t34.distance ? e3 : t34);
return { x: (f2.pointA.x + f2.pointB.x) / 2, y: (f2.pointA.y + f2.pointB.y) / 2 };
};
var MS = (t33, e2, n2) => Math.max(e2, Math.min(n2, t33));
var NS = (t33) => {
if (t33.type === "pcb_trace_segment")
return { minX: Math.min(t33.x1, t33.x2), minY: Math.min(t33.y1, t33.y2), maxX: Math.max(t33.x1, t33.x2), maxY: Math.max(t33.y1, t33.y2) };
if (t33.type === "pcb_smtpad" || t33.type === "pcb_plated_hole") {
if (t33.type === "pcb_smtpad" && (t33.shape === "rotated_rect" || t33.shape === "polygon") || t33.type === "pcb_plated_hole" && "rect_pad_width" in t33 && "rect_pad_height" in t33) {
const e2 = qI(t33);
return { minX: Math.min(...e2.map((t34) => t34.x)), minY: Math.min(...e2.map((t34) => t34.y)), maxX: Math.max(...e2.map((t34) => t34.x)), maxY: Math.max(...e2.map((t34) => t34.y)) };
}
if (t33.type === "pcb_smtpad" && t33.shape === "rotated_pill") {
const e2 = ZI(t33);
return { minX: Math.min(e2.start.x, e2.end.x) - e2.radius, minY: Math.min(e2.start.y, e2.end.y) - e2.radius, maxX: Math.max(e2.start.x, e2.end.x) + e2.radius, maxY: Math.max(e2.start.y, e2.end.y) + e2.radius };
}
}
return hg([t33]);
};
function wS(t33) {
return t33.route_type !== "wire" ? [] : [t33.start_pcb_port_id, t33.end_pcb_port_id].filter((t34) => Boolean(t34));
}
function TS(t33) {
const e2 = new Set;
for (const n2 of t33.route)
for (const t34 of wS(n2))
e2.add(t34);
return Array.from(e2);
}
function RS(t33) {
const e2 = new Set;
for (const n2 of t33)
for (const t34 of TS(n2))
e2.add(t34);
return Array.from(e2);
}
var ES = (t33) => {
if (t33.type === "pcb_via")
return t33.outer_diameter / 2;
if (t33.type === "pcb_plated_hole" && t33.shape === "circle")
return t33.outer_diameter / 2;
if (t33.type === "pcb_hole" && t33.hole_shape === "circle")
return t33.hole_diameter / 2;
if (t33.type === "pcb_smtpad" && t33.shape === "circle")
return t33.radius;
throw new Error(`Could not determine radius of element: ${JSON.stringify(t33)}`);
};
var AS = (t33) => t33.type === "pcb_port" ? t33.pcb_port_id : t33.type === "pcb_smtpad" ? t33.pcb_smtpad_id : t33.pcb_plated_hole_id;
function OS(t33, { connMap: e2, minClearance: n2 } = {}) {
const o2 = [];
((t34) => {
const e3 = t34.filter((t35) => t35.type === "pcb_port"), n3 = t34.filter((t35) => t35.type === "pcb_smtpad"), o3 = t34.filter((t35) => t35.type === "pcb_trace");
function i3(t35, o4 = {}) {
const i4 = o4.traceWidth || 0, r3 = e3.find((e4) => rS(e4.x, e4.y, t35.x, t35.y) < 0.01);
if (r3)
return r3.pcb_port_id;
if (o4.isFirstOrLastPoint) {
const e4 = n3.find((e5) => e5.shape === "rect" ? Math.abs(t35.x - e5.x) < e5.width / 2 + i4 / 2 && Math.abs(t35.y - e5.y) < e5.height / 2 + i4 / 2 : e5.shape === "circle" ? rS(t35.x, t35.y, e5.x, e5.y) < e5.radius : e5.shape === "pill" || e5.shape === "rotated_pill" ? iS(t35, e5) : undefined);
if (e4)
return e4.pcb_port_id ?? null;
}
return null;
}
for (const t35 of o3)
for (let e4 = 0;e4 < t35.route.length; e4++) {
const n4 = t35.route[e4], o4 = e4 === 0 || e4 === t35.route.length - 1;
if (n4.route_type === "wire") {
if (!n4.start_pcb_port_id && e4 === 0) {
const t36 = i3(n4, { isFirstOrLastPoint: o4, traceWidth: n4.width });
t36 && (n4.start_pcb_port_id = t36);
}
if (!n4.end_pcb_port_id && e4 === t35.route.length - 1) {
const t36 = i3(n4, { isFirstOrLastPoint: o4, traceWidth: n4.width });
t36 && (n4.end_pcb_port_id = t36);
}
}
}
})(t33), e2 ??= ei(t33);
const i2 = dS(t33);
n2 ??= uS(i2, "min_trace_to_pad_edge_clearance") ?? 0.1;
const r2 = tg(t33).pcb_trace.list().flatMap((t34) => {
const e3 = [];
for (let n3 = 0;n3 < t34.route.length - 1; n3++) {
const o3 = t34.route[n3], i3 = t34.route[n3 + 1];
o3.route_type === "wire" && (i3.route_type === "wire" && o3.layer === i3.layer && e3.push({ type: "pcb_trace_segment", pcb_trace_id: t34.pcb_trace_id, _pcbTrace: t34, thickness: "width" in o3 ? o3.width : ("width" in i3) ? i3.width : lS, layer: o3.layer, x1: o3.x, y1: o3.y, x2: i3.x, y2: i3.y }));
}
return e3;
}), s2 = tg(t33).pcb_smtpad.list(), a2 = tg(t33).pcb_plated_hole.list(), c2 = tg(t33).pcb_port.list(), l2 = tg(t33).pcb_hole.list(), h2 = tg(t33).pcb_via.list(), d2 = tg(t33).pcb_keepout.list(), u2 = [...c2, ...s2, ...a2], p2 = new Map;
for (const t34 of d2) {
const e3 = new Set(t34.excluded_pcb_component_ids ?? []);
e3.size !== 0 && p2.set(t34.pcb_keepout_id, u2.filter((t35) => t35.pcb_component_id && e3.has(t35.pcb_component_id)).map(AS));
}
const m2 = [...r2, ...s2, ...a2, ...l2, ...h2, ...d2], g2 = new vS({ objects: m2, getBounds: NS }), f2 = (e3) => sg(t33, e3), y2 = (t34, e3, n3) => xS(n3) ? `PCB trace ${t34} overlaps with ${e3} (accidental contact)` : `PCB trace ${t34} is too close to ${e3} (gap: ${n3.toFixed(3)}mm)`, _2 = new Set;
for (const t34 of r2) {
const i3 = n2, r3 = NS(t34), s3 = g2.getObjectsInBounds(r3, i3 + t34.thickness / 2);
if (t34.x1 !== t34.x2 || t34.y1 !== t34.y2)
for (const r4 of s3) {
if (!IS(r4).includes(t34.layer))
continue;
if (r4.type === "pcb_keepout" && (p2.get(r4.pcb_keepout_id) ?? []).some((n3) => e2.areIdsConnected(t34.pcb_trace_id, n3)))
continue;
if (r4.type === "pcb_trace_segment") {
const i4 = r4;
if (t34.layer !== i4.layer)
continue;
if (e2.areIdsConnected(t34.pcb_trace_id, i4.pcb_trace_id))
continue;
const s5 = Oe({ x: t34.x1, y: t34.y1 }, { x: t34.x2, y: t34.y2 }, { x: i4.x1, y: i4.y1 }, { x: i4.x2, y: i4.y2 }) - t34.thickness / 2 - i4.thickness / 2;
if (s5 > n2 - hS)
continue;
const a4 = `overlap_${t34.pcb_trace_id}_${i4.pcb_trace_id}`, c3 = `overlap_${i4.pcb_trace_id}_${t34.pcb_trace_id}`;
if (_2.has(a4))
continue;
if (_2.has(c3))
continue;
_2.add(a4), o2.push({ type: "pcb_trace_error", error_type: "pcb_trace_error", message: y2(f2(t34.pcb_trace_id), f2(i4.pcb_trace_id), s5), pcb_trace_id: t34.pcb_trace_id, source_trace_id: "", pcb_trace_error_id: a4, pcb_component_ids: [], center: CS(t34, i4), pcb_port_ids: RS([t34._pcbTrace, i4._pcbTrace]) });
continue;
}
const s4 = dg(r4);
if (e2.areIdsConnected(t34.pcb_trace_id, "pcb_trace_id" in r4 ? r4.pcb_trace_id : s4))
continue;
if (r4.type === "pcb_smtpad" || r4.type === "pcb_plated_hole" || r4.type === "pcb_via") {
const { gap: e3, center: n3 } = bS(t34, r4);
if (!xS(e3))
continue;
const i4 = `overlap_${t34.pcb_trace_id}_${s4}`;
if (_2.has(i4))
continue;
_2.add(i4), o2.push({ type: "pcb_trace_error", error_type: "pcb_trace_error", message: y2(f2(t34.pcb_trace_id), `${r4.type} "${f2(s4)}"`, e3), pcb_trace_id: t34.pcb_trace_id, center: n3, source_trace_id: "", pcb_trace_error_id: i4, pcb_component_ids: ["pcb_component_id" in r4 ? r4.pcb_component_id : undefined].filter(Boolean), pcb_port_ids: [...RS([t34._pcbTrace]), "pcb_port_id" in r4 ? r4.pcb_port_id : undefined].filter(Boolean) });
continue;
}
if (r4.type === "pcb_hole") {
const e3 = ES(r4), i4 = Le({ x: t34.x1, y: t34.y1 }, { x: t34.x2, y: t34.y2 }, { x: r4.x, y: r4.y, radius: e3 }) - t34.thickness / 2;
if (i4 > n2 - hS)
continue;
const a4 = `overlap_${t34.pcb_trace_id}_${s4}`;
if (_2.has(a4))
continue;
_2.add(a4), o2.push({ type: "pcb_trace_error", error_type: "pcb_trace_error", message: y2(f2(t34.pcb_trace_id), `${r4.type} "${f2(dg(r4))}"`, i4), pcb_trace_id: t34.pcb_trace_id, center: SS(t34, NS(r4)), source_trace_id: "", pcb_trace_error_id: a4, pcb_component_ids: ["pcb_component_id" in r4 ? r4.pcb_component_id : undefined].filter(Boolean), pcb_port_ids: [...RS([t34._pcbTrace]), "pcb_port_id" in r4 ? r4.pcb_port_id : undefined].filter(Boolean) });
}
const a3 = ke({ x: t34.x1, y: t34.y1 }, { x: t34.x2, y: t34.y2 }, NS(r4)) - t34.thickness / 2;
if (a3 + hS < i3) {
const e3 = `overlap_${t34.pcb_trace_id}_${s4}`;
if (_2.has(e3))
continue;
_2.add(e3), o2.push({ type: "pcb_trace_error", error_type: "pcb_trace_error", message: y2(f2(t34.pcb_trace_id), `${r4.type} "${f2(dg(r4))}"`, a3), pcb_trace_id: t34.pcb_trace_id, source_trace_id: "", pcb_trace_error_id: e3, pcb_component_ids: ["pcb_component_id" in r4 ? r4.pcb_component_id : undefined].filter(Boolean), center: SS(t34, NS(r4)), pcb_port_ids: [...RS([t34._pcbTrace]), "pcb_port_id" in r4 ? r4.pcb_port_id : undefined].filter(Boolean) });
}
}
}
return o2;
}
function kS(t33, e2) {
return Math.hypot(t33.x - e2.x, t33.y - e2.y);
}
function DS(t33, e2) {
return kS(t33, e2) <= hS;
}
function LS(t33, { connMap: e2, minClearance: n2 } = {}) {
const o2 = t33.filter((t34) => t34.type === "pcb_via");
if (o2.length < 2)
return [];
const i2 = dS(t33);
n2 ??= uS(i2, "min_via_hole_edge_to_via_hole_edge_clearance") ?? sS, e2 ??= ei(t33);
const r2 = [], s2 = new Set;
for (let i3 = 0;i3 < o2.length; i3++)
for (let a2 = i3 + 1;a2 < o2.length; a2++) {
const c2 = o2[i3], l2 = o2[a2];
if (DS(c2, l2))
continue;
if (!e2.areIdsConnected(c2.pcb_via_id, l2.pcb_via_id))
continue;
const h2 = kS(c2, l2) - c2.hole_diameter / 2 - l2.hole_diameter / 2;
if (h2 + hS >= n2)
continue;
const d2 = [c2.pcb_via_id, l2.pcb_via_id].sort().join("_");
s2.has(d2) || (s2.add(d2), r2.push({ type: "pcb_via_clearance_error", pcb_error_id: `same_net_vias_close_${d2}`, message: `Vias ${sg(t33, c2.pcb_via_id)} and ${sg(t33, l2.pcb_via_id)} are too close together (gap: ${h2.toFixed(3)}mm)`, error_type: "pcb_via_clearance_error", pcb_via_ids: [c2.pcb_via_id, l2.pcb_via_id], minimum_clearance: n2, actual_clearance: h2, pcb_center: { x: (c2.x + l2.x) / 2, y: (c2.y + l2.y) / 2 } }));
}
return r2;
}
function zS(t33, { connMap: e2, minClearance: n2 } = {}) {
const o2 = t33.filter((t34) => t34.type === "pcb_via");
if (o2.length < 2)
return [];
const i2 = dS(t33);
n2 ??= uS(i2, "min_via_hole_edge_to_via_hole_edge_clearance") ?? sS, e2 ??= ei(t33);
const r2 = [], s2 = new Set;
for (let i3 = 0;i3 < o2.length; i3++)
for (let a2 = i3 + 1;a2 < o2.length; a2++) {
const c2 = o2[i3], l2 = o2[a2];
if (DS(c2, l2))
continue;
if (e2.areIdsConnected(c2.pcb_via_id, l2.pcb_via_id))
continue;
const h2 = kS(c2, l2) - c2.hole_diameter / 2 - l2.hole_diameter / 2;
if (h2 + hS >= n2)
continue;
const d2 = [c2.pcb_via_id, l2.pcb_via_id].sort().join("_");
s2.has(d2) || (s2.add(d2), r2.push({ type: "pcb_via_clearance_error", pcb_error_id: `different_net_vias_close_${d2}`, message: `Vias ${sg(t33, c2.pcb_via_id)} and ${sg(t33, l2.pcb_via_id)} from different nets are too close together (gap: ${h2.toFixed(3)}mm)`, error_type: "pcb_via_clearance_error", pcb_via_ids: [c2.pcb_via_id, l2.pcb_via_id], minimum_clearance: n2, actual_clearance: h2, pcb_center: { x: (c2.x + l2.x) / 2, y: (c2.y + l2.y) / 2 } }));
}
return r2;
}
function BS(t33) {
return t33.route_type === "through_pad" ? { x: (t33.start.x + t33.end.x) / 2, y: (t33.start.y + t33.end.y) / 2 } : { x: t33.x, y: t33.y };
}
function FS(t33, e2, n2, o2) {
return t33.route_type === "wire" && e2.some((e3) => {
if (!e3.pcb_port_id || e3.pcb_port_id === n2)
return false;
const i2 = o2.get(e3.pcb_port_id);
return i2?.some((e4) => iS({ x: t33.x, y: t33.y }, e4)) ?? false;
});
}
function jS({ firstPoint: t33, lastPoint: e2, port: n2, expectedPorts: o2, padMap: i2 }) {
let r2;
const s2 = t33.route_type === "wire" ? t33 : undefined, a2 = e2.route_type === "wire" ? e2 : undefined, c2 = wS(t33).includes(n2.pcb_port_id), l2 = wS(e2).includes(n2.pcb_port_id);
c2 && s2 ? r2 = s2 : l2 && a2 || FS(t33, o2, n2.pcb_port_id, i2) && a2 ? r2 = a2 : FS(e2, o2, n2.pcb_port_id, i2) && s2 ? r2 = s2 : s2 && a2 ? r2 = kS(s2, n2) <= kS(a2, n2) ? s2 : a2 : s2 ? r2 = s2 : a2 && (r2 = a2);
const h2 = BS(t33), d2 = BS(e2);
return r2 ? { x: r2.x, y: r2.y } : { x: (h2.x + d2.x) / 2, y: (h2.y + d2.y) / 2 };
}
function $S(t33) {
const e2 = [], n2 = t33.filter((t34) => t34.type === "pcb_port"), o2 = t33.filter((t34) => t34.type === "pcb_trace"), i2 = t33.filter((t34) => t34.type === "source_trace"), r2 = t33.filter((t34) => t34.type === "pcb_smtpad"), s2 = t33.filter((t34) => t34.type === "pcb_plated_hole"), a2 = new Map, c2 = new ni(t33), l2 = new Set;
for (const t34 of r2)
t34.pcb_port_id && a2.set(t34.pcb_port_id, [...a2.get(t34.pcb_port_id) ?? [], t34]);
for (const t34 of s2)
t34.pcb_port_id && a2.set(t34.pcb_port_id, [...a2.get(t34.pcb_port_id) ?? [], t34]);
for (const r3 of o2) {
if (r3.route.length === 0)
continue;
const s3 = r3.route[0], h2 = r3.route[r3.route.length - 1], d2 = i2.find((t34) => t34.source_trace_id === r3.source_trace_id), u2 = d2 ? n2.filter((t34) => d2.connected_source_port_ids?.includes(t34.source_port_id)) : [];
for (let n3 = 1;n3 < r3.route.length - 1; n3++) {
const o3 = r3.route[n3 - 1], i3 = r3.route[n3], s4 = r3.route[n3 + 1];
if (i3.route_type === "via") {
const a3 = o3.route_type === "wire", c3 = s4.route_type === "wire";
if (a3 && c3) {
const a4 = Math.abs(o3.x - i3.x) < 0.01 && Math.abs(o3.y - i3.y) < 0.01, c4 = Math.abs(s4.x - i3.x) < 0.01 && Math.abs(s4.y - i3.y) < 0.01;
if (!a4 || !c4) {
const o4 = ig(t33, r3.pcb_trace_id);
e2.push({ type: "pcb_trace_error", message: `Via in trace [${o4}] is misaligned at position {x: ${i3.x}, y: ${i3.y}}.`, source_trace_id: d2?.source_trace_id || r3.source_trace_id || `!${r3.pcb_trace_id}`, error_type: "pcb_trace_error", pcb_trace_id: r3.pcb_trace_id, pcb_trace_error_id: `misaligned_via_${r3.pcb_trace_id}_${n3}`, pcb_component_ids: [], pcb_port_ids: [] });
}
}
}
}
const p2 = ig(t33, r3.pcb_trace_id);
if (d2 && u2.length > 0) {
if (l2.has(d2.source_trace_id))
continue;
l2.add(d2.source_trace_id);
}
for (const n3 of u2) {
if (!n3.pcb_port_id)
continue;
const l3 = a2.get(n3.pcb_port_id);
if (!l3?.length)
continue;
let m2 = false;
const g2 = [...c2.getAllTracesConnectedToTrace(r3.pcb_trace_id), ...o2.filter((t34) => t34.source_trace_id === d2?.source_trace_id)];
for (const t34 of g2) {
if (t34.pcb_trace_id === r3.pcb_trace_id)
continue;
if (!t34.source_trace_id)
continue;
const e3 = i2.find((e4) => e4.source_trace_id === t34.source_trace_id);
if (!d2 || t34.source_trace_id !== d2.source_trace_id && !e3?.connected_source_port_ids.includes(n3.source_port_id))
continue;
const o3 = t34.route[0], s4 = t34.route.at(-1);
if (TS(t34).includes(n3.pcb_port_id) || o3?.route_type === "wire" && l3.some((t35) => iS(o3, t35)) || s4?.route_type === "wire" && l3.some((t35) => iS(s4, t35))) {
m2 = true;
break;
}
}
if (m2)
continue;
const f2 = s3.route_type === "wire" && l3.some((t34) => iS({ x: s3.x, y: s3.y }, t34)), y2 = h2.route_type === "wire" && l3.some((t34) => iS({ x: h2.x, y: h2.y }, t34));
if (!f2 && !y2) {
const o3 = rg(t33, n3.pcb_port_id).replace("pcb_port", ""), i3 = l3[0].type.replace(/pcb_/, ""), c3 = jS({ firstPoint: s3, lastPoint: h2, port: n3, expectedPorts: u2, padMap: a2 });
e2.push({ type: "pcb_trace_error", message: `Trace [${p2}] is missing a connection to ${i3}${o3}`, source_trace_id: d2?.source_trace_id || r3.source_trace_id || `!${r3.pcb_trace_id}`, error_type: "pcb_trace_error", pcb_trace_id: r3.pcb_trace_id, pcb_trace_error_id: `missing_connection_${r3.pcb_trace_id}_${n3.pcb_port_id}`, center: c3, pcb_component_ids: [], pcb_port_ids: [n3.pcb_port_id] });
}
}
if (u2.length === 0) {
let t34 = false, n3 = false;
const o3 = s3.route_type === "wire" && h2.route_type === "wire" && Math.abs(s3.x - h2.x) < 0.01 && Math.abs(s3.y - h2.y) < 0.01;
for (const e3 of a2.values())
s3.route_type === "wire" && e3.some((t35) => iS({ x: s3.x, y: s3.y }, t35)) && (t34 = true), h2.route_type === "wire" && e3.some((t35) => iS({ x: h2.x, y: h2.y }, t35)) && (n3 = true);
t34 || s3.route_type !== "wire" || e2.push({ type: "pcb_trace_error", message: `Trace [${p2}] has disconnected endpoint at (${s3.x.toFixed(2)}, ${s3.y.toFixed(2)})`, source_trace_id: d2?.source_trace_id || r3.source_trace_id || `!${r3.pcb_trace_id}`, error_type: "pcb_trace_error", pcb_trace_id: r3.pcb_trace_id, pcb_trace_error_id: `disconnected_endpoint_${r3.pcb_trace_id}_start`, center: { x: s3.x, y: s3.y }, pcb_component_ids: [], pcb_port_ids: [] }), n3 || h2.route_type !== "wire" || o3 && !t34 || e2.push({ type: "pcb_trace_error", message: `Trace [${p2}] has disconnected endpoint at (${h2.x.toFixed(2)}, ${h2.y.toFixed(2)})`, source_trace_id: d2?.source_trace_id || r3.source_trace_id || `!${r3.pcb_trace_id}`, error_type: "pcb_trace_error", pcb_trace_id: r3.pcb_trace_id, pcb_trace_error_id: `disconnected_endpoint_${r3.pcb_trace_id}_end`, center: { x: h2.x, y: h2.y }, pcb_component_ids: [], pcb_port_ids: [] });
}
}
return e2;
}
function YS(t33, e2 = {}) {
const n2 = [], o2 = dS(t33);
if (!o2)
return n2;
const i2 = e2.margin ?? uS(o2, "min_board_edge_clearance") ?? cS, r2 = function(t34) {
if (t34.outline && t34.outline.length > 0)
return t34.outline.map((t35) => ({ x: t35.x, y: t35.y }));
if (t34.center && typeof t34.width == "number" && typeof t34.height == "number") {
const e3 = t34.center.x, n3 = t34.center.y, o3 = t34.width / 2, i3 = t34.height / 2;
return [{ x: e3 - o3, y: n3 - i3 }, { x: e3 + o3, y: n3 - i3 }, { x: e3 + o3, y: n3 + i3 }, { x: e3 - o3, y: n3 + i3 }];
}
return null;
}(o2);
if (!r2)
return n2;
const s2 = tg(t33).pcb_trace.list();
for (const t34 of s2)
if (!(t34.route.length < 2))
for (let e3 = 0;e3 < t34.route.length - 1; e3++) {
const o3 = t34.route[e3], s3 = t34.route[e3 + 1];
if (o3.route_type !== "wire" || s3.route_type !== "wire")
continue;
const a2 = "width" in o3 ? o3.width : ("width" in s3) ? s3.width : 0.1, c2 = { x: o3.x, y: o3.y }, l2 = { x: s3.x, y: s3.y };
let h2 = Number.POSITIVE_INFINITY;
for (let t35 = 0;t35 < r2.length; t35++) {
const e4 = Oe(c2, l2, r2[t35], r2[(t35 + 1) % r2.length]);
e4 < h2 && (h2 = e4);
}
const d2 = a2 / 2 + i2;
if (h2 < d2) {
const o4 = { type: "pcb_trace_error", error_type: "pcb_trace_error", pcb_trace_error_id: `trace_too_close_to_board_${t34.pcb_trace_id}_segment_${e3}`, message: `Trace too close to board edge (${h2.toFixed(3)}mm < ${d2.toFixed(3)}mm required, margin: ${i2}mm)`, pcb_trace_id: t34.pcb_trace_id, source_trace_id: t34.source_trace_id || "", center: { x: (c2.x + l2.x) / 2, y: (c2.y + l2.y) / 2 }, pcb_component_ids: [], pcb_port_ids: [] };
n2.push(o4);
}
}
return n2;
}
function XS(t33, { connMap: e2, minClearance: n2 } = {}) {
const o2 = ((t34) => [...tg(t34).pcb_smtpad.list(), ...tg(t34).pcb_plated_hole.list()])(t33), i2 = fS(t33);
if (o2.length === 0 || i2.length === 0)
return [];
const r2 = dS(t33);
n2 ??= uS(r2, "min_trace_to_pad_edge_clearance") ?? aS, e2 ??= ei(t33);
const s2 = new vS({ objects: o2, getBounds: pS, getId: (t34) => dg(t34) }), a2 = new Map, c2 = new Set;
for (const o3 of i2) {
const i3 = s2.getObjectsInBounds(NS(o3), n2 + o3.thickness / 2);
for (const r3 of i3) {
const i4 = dg(r3);
if (!IS(r3).includes(o3.layer))
continue;
if (e2.areIdsConnected(o3.pcb_trace_id, i4))
continue;
const s3 = `${i4}_${o3.pcb_trace_id}`, { gap: l2 } = bS(o3, r3);
if (xS(l2)) {
a2.delete(s3), c2.add(s3);
continue;
}
if (c2.has(s3))
continue;
if (l2 + hS >= n2)
continue;
const h2 = { type: "pcb_pad_trace_clearance_error", pcb_pad_trace_clearance_error_id: `pad_trace_clearance_${s3}`, error_type: "pcb_pad_trace_clearance_error", message: `Pad ${sg(t33, i4)} and trace ${sg(t33, o3.pcb_trace_id)} are too close (clearance: ${na(l2)}, minimum: ${na(n2)})`, pcb_pad_id: i4, pcb_trace_id: o3.pcb_trace_id, minimum_clearance: n2, actual_clearance: l2, center: yS(o3) }, d2 = a2.get(s3);
(!d2 || l2 < d2.gap) && a2.set(s3, { error: h2, gap: l2 });
}
}
return Array.from(a2.values()).map(({ error: t34 }) => t34);
}
function WS(t33, { connMap: e2, minClearance: n2 } = {}) {
const o2 = t33.filter((t34) => t34.type === "pcb_via"), i2 = fS(t33);
if (o2.length === 0 || i2.length === 0)
return [];
const r2 = dS(t33);
n2 ??= uS(r2, "min_trace_to_pad_edge_clearance") ?? aS, e2 ??= ei(t33);
const s2 = new Map, a2 = new Set;
for (const r3 of o2)
for (const o3 of i2) {
if (!IS(r3).includes(o3.layer))
continue;
if (e2.areIdsConnected(o3.pcb_trace_id, r3.pcb_via_id))
continue;
const i3 = `${r3.pcb_via_id}_${o3.pcb_trace_id}`, { gap: c2 } = bS(o3, r3);
if (xS(c2)) {
s2.delete(i3), a2.add(i3);
continue;
}
if (a2.has(i3))
continue;
if (c2 + hS >= n2)
continue;
const l2 = { type: "pcb_via_trace_clearance_error", pcb_via_trace_clearance_error_id: `via_trace_clearance_${i3}`, error_type: "pcb_via_trace_clearance_error", message: `Via ${sg(t33, r3.pcb_via_id)} and trace ${sg(t33, o3.pcb_trace_id)} are too close (clearance: ${na(c2)}, minimum: ${na(n2)})`, pcb_via_id: r3.pcb_via_id, pcb_trace_id: o3.pcb_trace_id, minimum_clearance: n2, actual_clearance: c2, center: yS(o3) }, h2 = s2.get(i3);
(!h2 || c2 < h2.gap) && s2.set(i3, { error: l2, gap: c2 });
}
return Array.from(s2.values()).map(({ error: t34 }) => t34);
}
var VS = (t33, e2 = {}) => {
const n2 = ((t34) => {
const e3 = ei(t34), n3 = t34.filter((t35) => t35.type === "pcb_via" && typeof t35.pcb_trace_id == "string").map((t35) => [t35.pcb_via_id, t35.pcb_trace_id]);
return e3.addConnections(n3), e3;
})(t33), o2 = Math.max(e2.viaClearance ?? 0.1, 0.1), i2 = OS(t33, { connMap: n2, minClearance: e2.traceClearance }), r2 = e2.includeTypedTraceClearance !== false, s2 = r2 ? WS(t33, { connMap: n2, minClearance: e2.traceClearance }) : [], a2 = r2 ? XS(t33, { connMap: n2, minClearance: e2.traceClearance }) : [], c2 = [...LS(t33, { connMap: n2, minClearance: o2 }), ...zS(t33, { connMap: n2, minClearance: o2 })], l2 = [...i2, ...YS(t33), ...e2.includeTraceContinuity === false ? [] : $S(t33), ...s2, ...a2, ...c2], h2 = t33.filter((t34) => t34.type === "pcb_via"), d2 = new Map(h2.map((t34) => [t34.pcb_via_id, t34])), u2 = l2.map((t34) => {
if (t34.type === "pcb_via_trace_clearance_error" && typeof t34.pcb_via_id == "string") {
const e3 = d2.get(t34.pcb_via_id);
if (e3)
return { ...t34, center: { x: e3.x, y: e3.y } };
}
if ("center" in t34 && t34.center)
return t34;
if ("pcb_center" in t34 && t34.pcb_center)
return { ...t34, center: t34.pcb_center };
if ("pcb_via_ids" in t34 && Array.isArray(t34.pcb_via_ids)) {
const [e3, n3] = t34.pcb_via_ids, o3 = d2.get(e3), i3 = d2.get(n3);
if (o3 && i3)
return { ...t34, center: { x: (o3.x + i3.x) / 2, y: (o3.y + i3.y) / 2 } };
}
if ("pcb_error_id" in t34 && typeof t34.pcb_error_id == "string" && (t34.pcb_error_id.startsWith("same_net_vias_close_") || t34.pcb_error_id.startsWith("different_net_vias_close_"))) {
const e3 = t34.pcb_error_id.replace("same_net_vias_close_", "").replace("different_net_vias_close_", "").split("_").filter(Boolean);
if (e3.length === 2) {
const n3 = d2.get(e3[0]), o3 = d2.get(e3[1]);
if (n3 && o3)
return { ...t34, center: { x: (n3.x + o3.x) / 2, y: (n3.y + o3.y) / 2 } };
}
}
return t34;
}), p2 = u2.filter((t34) => Boolean(t34.center));
return { errors: l2, errorsWithCenters: u2, locationAwareErrors: p2 };
};
var HS = (t33, e2) => t33 === 0 ? "top" : t33 === e2 - 1 ? "bottom" : `inner${t33}`;
var GS = (t33, e2) => {
if (!Number.isInteger(e2) || e2 < 1)
throw new Error(`Invalid board layer count: ${e2}`);
const n2 = Array.from({ length: e2 }, (t34, n3) => HS(n3, e2)), o2 = n2.findIndex((e3) => e3 === t33.from_layer), i2 = n2.findIndex((e3) => e3 === t33.to_layer);
if (o2 < 0 || i2 < 0)
throw new Error(`Via span ${t33.from_layer} -> ${t33.to_layer} is outside the board`);
return n2.slice(Math.min(o2, i2), Math.max(o2, i2) + 1);
};
var US = 0.005;
var ZS = 0.000001;
var qS = (t33, e2) => ({ minX: t33.minX - e2, minY: t33.minY - e2, maxX: t33.maxX + e2, maxY: t33.maxY + e2 });
var JS = (t33) => qS({ minX: Math.min(t33.start.x, t33.end.x), minY: Math.min(t33.start.y, t33.end.y), maxX: Math.max(t33.start.x, t33.end.x), maxY: Math.max(t33.start.y, t33.end.y) }, t33.width / 2);
var QS = (t33) => {
const e2 = t33.diameter / 2;
return { minX: t33.x - e2, minY: t33.y - e2, maxX: t33.x + e2, maxY: t33.y + e2 };
};
var KS = (t33) => Ve(E(t33.localToWorld, [{ x: -t33.width / 2, y: -t33.height / 2 }, { x: t33.width / 2, y: -t33.height / 2 }, { x: t33.width / 2, y: t33.height / 2 }, { x: -t33.width / 2, y: t33.height / 2 }]));
var tC = (t33) => ({ minX: -t33.width / 2, minY: -t33.height / 2, maxX: t33.width / 2, maxY: t33.height / 2 });
var eC = (t33, e2) => `${t33}:${e2}`;
var nC = class {
constructor(t33) {
this.cellSize = t33;
}
cells = new Map;
insert(t33, e2) {
const n2 = Math.floor(e2.minX / this.cellSize), o2 = Math.floor(e2.maxX / this.cellSize), i2 = Math.floor(e2.minY / this.cellSize), r2 = Math.floor(e2.maxY / this.cellSize);
for (let e3 = n2;e3 <= o2; e3 += 1)
for (let n3 = i2;n3 <= r2; n3 += 1) {
const o3 = eC(e3, n3), i3 = this.cells.get(o3);
i3 ? i3.push(t33) : this.cells.set(o3, [t33]);
}
}
query(t33) {
const e2 = Math.floor(t33.minX / this.cellSize), n2 = Math.floor(t33.maxX / this.cellSize), o2 = Math.floor(t33.minY / this.cellSize), i2 = Math.floor(t33.maxY / this.cellSize), r2 = new Set;
for (let t34 = e2;t34 <= n2; t34 += 1)
for (let e3 = o2;e3 <= i2; e3 += 1) {
const n3 = this.cells.get(eC(t34, e3));
if (n3)
for (const t35 of n3)
r2.add(t35);
}
return [...r2];
}
};
var oC = (t33, e2) => {
const n2 = ve(t33.start, t33.end, e2.start, e2.end);
if (n2)
return n2;
const o2 = [{ left: t33.start, right: ze(t33.start, e2.start, e2.end) }, { left: t33.end, right: ze(t33.end, e2.start, e2.end) }, { left: ze(e2.start, t33.start, t33.end), right: e2.start }, { left: ze(e2.end, t33.start, t33.end), right: e2.end }];
let i2 = { left: t33.start, right: e2.start }, r2 = Number.POSITIVE_INFINITY;
for (const t34 of o2) {
const e3 = Math.hypot(t34.left.x - t34.right.x, t34.left.y - t34.right.y);
e3 < r2 && (i2 = t34, r2 = e3);
}
return { x: (i2.left.x + i2.right.x) / 2, y: (i2.left.y + i2.right.y) / 2 };
};
var iC = (t33, e2) => {
const n2 = ze(e2, t33.start, t33.end);
return { x: (n2.x + e2.x) / 2, y: (n2.y + e2.y) / 2 };
};
var rC = (t33, e2) => {
const n2 = ze({ x: (e2.minX + e2.maxX) / 2, y: (e2.minY + e2.maxY) / 2 }, t33.start, t33.end), o2 = Math.max(e2.minX, Math.min(e2.maxX, n2.x)), i2 = Math.max(e2.minY, Math.min(e2.maxY, n2.y));
return { x: (n2.x + o2) / 2, y: (n2.y + i2) / 2 };
};
var sC = (t33) => {
const e2 = new Set;
for (const n2 of t33.route)
n2.route_type === "wire" && (n2.start_pcb_port_id && e2.add(n2.start_pcb_port_id), n2.end_pcb_port_id && e2.add(n2.end_pcb_port_id));
return [...e2];
};
var aC = (t33, e2, n2) => n2 < 0 ? `PCB trace ${t33} overlaps with ${e2} (accidental contact)` : `PCB trace ${t33} is too close to ${e2} (gap: ${n2.toFixed(3)}mm)`;
var cC = class {
constructor(t33, e2 = {}) {
if (this.srj = t33, this.traceClearance = e2.traceClearance ?? 0.1, this.viaClearance = Math.max(e2.viaClearance ?? 0.1, 0.1), this.viaToPadClearance = e2.viaToPadClearance ?? this.srj.minViaEdgeToPadEdgeClearance ?? 0.1, this.connMap = e2.connMap, this.includeTraceViaOwnerMetadata = e2.includeTraceViaOwnerMetadata ?? false, this.cellSize = e2.spatialCellSize ?? this.getDefaultSpatialCellSize(), !Number.isFinite(this.traceClearance) || this.traceClearance < 0)
throw new Error("traceClearance must be a non-negative finite number");
if (!Number.isFinite(this.viaClearance))
throw new Error("viaClearance must be a finite number");
if (!Number.isFinite(this.viaToPadClearance) || this.viaToPadClearance < 0)
throw new Error("viaToPadClearance must be a non-negative finite number");
if (!Number.isFinite(this.cellSize) || this.cellSize <= 0)
throw new Error("spatialCellSize must be a positive finite number");
this.compileConnectionAliases(), this.obstacles = this.compileStaticObstacles(), this.indexStaticObstacles();
}
obstacleConnectivityCache = new Map;
traceClearance;
viaClearance;
viaToPadClearance;
cellSize;
connMap;
includeTraceViaOwnerMetadata;
canonicalNetByAlias = new Map;
connMapNetByCanonicalNet = new Map;
obstacles;
obstacleIndexesByLayer = new Map;
lastRunStats = { traceCount: 0, segmentCount: 0, viaCount: 0, obstacleCount: 0, broadPhaseCandidateCount: 0, exactCheckCount: 0 };
getDefaultSpatialCellSize() {
const t33 = Math.max(0, this.srj.bounds.maxX - this.srj.bounds.minX), e2 = Math.max(0, this.srj.bounds.maxY - this.srj.bounds.minY);
return Math.max(0.25, Math.max(t33, e2) / 64, (this.srj.minViaDiameter ?? 0.3) + Math.max(this.traceClearance, this.viaToPadClearance));
}
compileConnectionAliases() {
const t33 = new Map;
for (const e2 of this.srj.connections) {
const n2 = e2.netConnectionName ?? e2.rootConnectionName ?? e2.name, o2 = [e2.name, e2.rootConnectionName, e2.netConnectionName, ...e2.mergedConnectionNames ?? [], ...e2.pointsToConnect.flatMap((t34) => [t34.pointId, t34.pcb_port_id])];
for (const e3 of o2) {
if (!e3)
continue;
this.canonicalNetByAlias.set(e3, n2);
const o3 = this.connMap?.getNetConnectedToId(e3);
if (!o3)
continue;
let i2 = t33.get(n2);
i2 || (i2 = new Set, t33.set(n2, i2)), i2.add(o3);
}
this.canonicalNetByAlias.set(n2, n2);
}
for (const [e2, n2] of t33)
n2.size === 1 && this.connMapNetByCanonicalNet.set(e2, n2.values().next().value);
}
resolveNetId(t33) {
const e2 = this.connMap?.getNetConnectedToId(t33);
if (e2)
return e2;
const n2 = this.canonicalNetByAlias.get(t33);
return n2 ? this.connMapNetByCanonicalNet.get(n2) ?? n2 : t33;
}
areConnected(t33, e2) {
return t33 === e2 || (!!this.connMap?.areIdsConnected(t33, e2) || this.resolveNetId(t33) === this.resolveNetId(e2));
}
compileStaticObstacles() {
const t33 = [], e2 = new Set, n2 = new Set;
for (const o2 of this.srj.obstacles) {
if (o2.layers.length === 0)
continue;
const i2 = o2.connectedTo.find((t34) => t34.startsWith("pcb_smtpad_")), r2 = o2.connectedTo.find((t34) => t34.startsWith("pcb_plated_hole_")), s2 = o2.connectedTo.find((t34) => t34.startsWith("pcb_port_"));
if (!i2 && !r2 && !s2)
continue;
const a2 = o2.layers.length > 1, c2 = a2 ? "pcb_plated_hole" : "pcb_smtpad", l2 = a2 ? r2 ?? `pcb_plated_hole_${o2.center.x.toFixed(3)}_${o2.center.y.toFixed(3)}` : i2 ?? `pcb_smtpad_${o2.center.x.toFixed(3)}_${o2.center.y.toFixed(3)}`, h2 = a2 ? n2 : e2;
if (h2.has(l2))
continue;
h2.add(l2);
const d2 = typeof o2.ccwRotationDegrees == "number" && Number.isFinite(o2.ccwRotationDegrees), u2 = L(k(o2.center.x, o2.center.y), j(d2 ? o2.ccwRotationDegrees : 0)), p2 = !d2 && a2 && Math.abs(o2.width - o2.height) < 0.001;
t33.push({ kind: "obstacle", obstacleType: c2, obstacleId: l2, connectedTo: o2.connectedTo, x: o2.center.x, y: o2.center.y, width: o2.width, height: o2.height, localToWorld: u2, worldToLocal: A(u2), ...p2 ? { radius: Math.max(o2.width, o2.height) / 2 } : {}, layers: o2.layers, ...s2 ? { pcbPortId: s2 } : {} });
}
return t33;
}
indexStaticObstacles() {
for (const t33 of this.obstacles) {
const e2 = qS(KS(t33), Math.max(this.traceClearance, this.viaToPadClearance));
for (const n2 of t33.layers) {
let o2 = this.obstacleIndexesByLayer.get(n2);
o2 || (o2 = new nC(this.cellSize), this.obstacleIndexesByLayer.set(n2, o2)), o2.insert(t33, e2);
}
}
}
collectDynamicGeometry(t33) {
const e2 = [], n2 = [], o2 = new Set;
for (const i2 of t33) {
const t34 = this.resolveNetId(i2.connection_name), r2 = sC(i2);
for (let n3 = 0;n3 < i2.route.length - 1; n3 += 1) {
const o3 = i2.route[n3], s2 = i2.route[n3 + 1];
o3?.route_type === "wire" && s2?.route_type === "wire" && o3.layer === s2.layer && (Math.abs(o3.x - s2.x) <= ZS && Math.abs(o3.y - s2.y) <= ZS || e2.push({ kind: "trace_segment", order: e2.length, traceId: i2.pcb_trace_id, netId: t34, start: { x: o3.x, y: o3.y }, end: { x: s2.x, y: s2.y }, width: lC(o3, s2), layer: o3.layer, pcbPortIds: r2 }));
}
for (const e3 of i2.route) {
if (e3.route_type !== "via")
continue;
const r3 = `${e3.x},${e3.y},${e3.from_layer},${e3.to_layer}`;
o2.has(r3) || (o2.add(r3), n2.push({ kind: "via", order: n2.length, viaId: `via_${n2.length}`, traceId: i2.pcb_trace_id, netId: t34, x: e3.x, y: e3.y, diameter: e3.via_diameter ?? this.srj.minViaDiameter ?? 0.3, layers: GS(e3, this.srj.layerCount) }));
}
}
return { segments: e2, vias: n2 };
}
buildDynamicIndexes(t33, e2) {
const n2 = new Map, o2 = (t34, e3, o3) => {
let i2 = n2.get(t34);
i2 || (i2 = new nC(this.cellSize), n2.set(t34, i2)), i2.insert(e3, qS(o3, this.traceClearance));
};
for (const e3 of t33)
o2(e3.layer, e3, JS(e3));
for (const t34 of e2)
for (const e3 of t34.layers)
o2(e3, t34, QS(t34));
return n2;
}
obstacleSharesNet(t33, e2) {
let n2 = this.obstacleConnectivityCache.get(e2);
n2 || (n2 = new Map, this.obstacleConnectivityCache.set(e2, n2));
const o2 = n2.get(t33);
if (o2 !== undefined)
return o2;
const i2 = e2.connectedTo.some((e3) => this.areConnected(t33, e3));
return n2.set(t33, i2), i2;
}
checkTracePair(t33, e2) {
if (this.areConnected(t33.netId, e2.netId))
return;
this.lastRunStats.exactCheckCount += 1;
const n2 = Oe(t33.start, t33.end, e2.start, e2.end) - t33.width / 2 - e2.width / 2;
if (n2 > this.traceClearance - US)
return;
const o2 = `overlap_${t33.traceId}_${e2.traceId}`;
return { type: "pcb_trace_error", error_type: "pcb_trace_error", message: aC(t33.traceId, `PCB trace ${e2.traceId}`, n2), pcb_trace_id: t33.traceId, source_trace_id: "", pcb_trace_error_id: o2, minimum_clearance: this.traceClearance, actual_clearance: n2, pcb_component_ids: [], pcb_port_ids: [...new Set([...t33.pcbPortIds, ...e2.pcbPortIds])], center: oC(t33, e2) };
}
checkTraceVia(t33, e2) {
if (this.areConnected(t33.netId, e2.netId))
return;
this.lastRunStats.exactCheckCount += 1;
const n2 = Le(t33.start, t33.end, { x: e2.x, y: e2.y, radius: e2.diameter / 2 }) - t33.width / 2;
if (n2 > this.traceClearance - US)
return;
const o2 = `overlap_${t33.traceId}_${e2.viaId}`;
return { type: "pcb_trace_error", error_type: "pcb_trace_error", message: aC(t33.traceId, `pcb_via "${e2.viaId}"`, n2), pcb_trace_id: t33.traceId, ...this.includeTraceViaOwnerMetadata ? { pcb_trace_ids: [t33.traceId, e2.traceId], pcb_via_id: e2.viaId, pcb_via_ids: [e2.viaId] } : {}, source_trace_id: "", pcb_trace_error_id: o2, minimum_clearance: this.traceClearance, actual_clearance: n2, pcb_component_ids: [], pcb_port_ids: t33.pcbPortIds, center: iC(t33, e2) };
}
checkTraceObstacle(t33, e2) {
if (this.obstacleSharesNet(t33.netId, e2))
return;
this.lastRunStats.exactCheckCount += 1;
const n2 = tC(e2), o2 = { ...t33, start: R(e2.worldToLocal, t33.start), end: R(e2.worldToLocal, t33.end) }, i2 = (e2.radius === undefined ? ke(o2.start, o2.end, n2) : Le(t33.start, t33.end, { x: e2.x, y: e2.y, radius: e2.radius })) - t33.width / 2;
if (i2 + US >= this.traceClearance)
return;
const r2 = `overlap_${t33.traceId}_${e2.obstacleId}`;
return { type: "pcb_trace_error", error_type: "pcb_trace_error", message: aC(t33.traceId, `${e2.obstacleType} "${e2.obstacleId}"`, i2), pcb_trace_id: t33.traceId, source_trace_id: "", pcb_trace_error_id: r2, minimum_clearance: this.traceClearance, actual_clearance: i2, pcb_component_ids: [], pcb_port_ids: [...new Set([...t33.pcbPortIds, ...e2.pcbPortId ? [e2.pcbPortId] : []])], center: e2.radius === undefined ? R(e2.localToWorld, rC(o2, n2)) : iC(t33, e2) };
}
checkViaObstacle(t33, e2) {
if (this.obstacleSharesNet(t33.netId, e2))
return;
this.lastRunStats.exactCheckCount += 1;
const n2 = tC(e2), o2 = R(e2.worldToLocal, t33), i2 = (e2.radius === undefined ? Math.hypot(Math.max(n2.minX - o2.x, 0, o2.x - n2.maxX), Math.max(n2.minY - o2.y, 0, o2.y - n2.maxY)) : Math.hypot(t33.x - e2.x, t33.y - e2.y) - e2.radius) - t33.diameter / 2;
if (i2 + US >= this.viaToPadClearance)
return;
const r2 = `via_pad_clearance_${t33.viaId}_${e2.obstacleId}`, s2 = { x: (t33.x + e2.x) / 2, y: (t33.y + e2.y) / 2 };
return { type: "pcb_pad_pad_clearance_error", error_type: "pcb_pad_pad_clearance_error", pcb_pad_pad_clearance_error_id: r2, message: `pcb_via "${t33.viaId}" and ${e2.obstacleType} "${e2.obstacleId}" are too close (gap: ${i2.toFixed(3)}mm)`, pcb_trace_id: t33.traceId, pcb_pad_ids: [t33.viaId, e2.obstacleId], pcb_via_ids: [t33.viaId], minimum_clearance: this.viaToPadClearance, actual_clearance: i2, center: s2 };
}
checkViaPairs(t33) {
if (t33.length < 2)
return [];
const e2 = [], n2 = new nC(this.cellSize);
for (const e3 of t33)
n2.insert(e3, qS(QS(e3), this.viaClearance));
for (const o2 of t33)
for (const t34 of n2.query(QS(o2))) {
if (this.lastRunStats.broadPhaseCandidateCount += 1, t34.order <= o2.order)
continue;
this.lastRunStats.exactCheckCount += 1;
const n3 = Math.hypot(o2.x - t34.x, o2.y - t34.y);
if (n3 <= ZS)
continue;
const i2 = n3 - o2.diameter / 2 - t34.diameter / 2;
if (i2 + US >= this.viaClearance)
continue;
const r2 = this.areConnected(o2.netId, t34.netId), s2 = [o2.viaId, t34.viaId].sort().join("_"), a2 = { x: (o2.x + t34.x) / 2, y: (o2.y + t34.y) / 2 };
e2.push({ type: "pcb_via_clearance_error", error_type: "pcb_via_clearance_error", pcb_error_id: `${r2 ? "same_net" : "different_net"}_vias_close_${s2}`, message: `Vias ${o2.viaId} and ${t34.viaId}${r2 ? "" : " from different nets"} are too close together (gap: ${i2.toFixed(3)}mm)`, pcb_via_ids: [o2.viaId, t34.viaId], ...this.includeTraceViaOwnerMetadata ? { pcb_trace_ids: [o2.traceId, t34.traceId] } : {}, pcb_via_pair_net_relation: r2 ? "same_net" : "different_net", minimum_clearance: this.viaClearance, actual_clearance: i2, pcb_center: a2, center: a2 });
}
return e2;
}
evaluate(t33) {
return this.evaluateInternal(t33, true);
}
evaluateLegacy(t33) {
return this.evaluateInternal(t33, false);
}
evaluateInternal(t33, e2) {
this.obstacleConnectivityCache.clear();
const { segments: n2, vias: o2 } = this.collectDynamicGeometry(t33), i2 = this.buildDynamicIndexes(n2, o2), r2 = [], s2 = [];
this.lastRunStats = { traceCount: t33.length, segmentCount: n2.length, viaCount: o2.length, obstacleCount: this.obstacles.length, broadPhaseCandidateCount: 0, exactCheckCount: 0 };
for (const t34 of n2) {
const e3 = JS(t34), n3 = i2.get(t34.layer)?.query(e3) ?? [], o3 = this.obstacleIndexesByLayer.get(t34.layer)?.query(e3) ?? [];
for (const e4 of n3) {
if (this.lastRunStats.broadPhaseCandidateCount += 1, e4.kind === "trace_segment" && e4.order <= t34.order)
continue;
const n4 = e4.kind === "trace_segment" ? this.checkTracePair(t34, e4) : this.checkTraceVia(t34, e4);
n4 && r2.push(n4);
}
for (const e4 of o3) {
this.lastRunStats.broadPhaseCandidateCount += 1;
const n4 = this.checkTraceObstacle(t34, e4);
n4 && r2.push(n4);
}
}
const a2 = this.checkViaPairs(o2);
if (e2)
for (const t34 of o2) {
const e3 = new Set;
for (const n3 of t34.layers) {
const o3 = this.obstacleIndexesByLayer.get(n3)?.query(QS(t34)) ?? [];
for (const n4 of o3) {
if (e3.has(n4))
continue;
e3.add(n4), this.lastRunStats.broadPhaseCandidateCount += 1;
const o4 = this.checkViaObstacle(t34, n4);
o4 && s2.push(o4);
}
}
}
const c2 = new Map;
for (const t34 of r2) {
const e3 = String(t34.pcb_trace_error_id), n3 = c2.get(e3), o3 = Number(t34.actual_clearance);
if (!n3) {
c2.set(e3, { ...t34, first_contact_center: t34.center, first_contact_message: t34.message, first_actual_clearance: o3, worst_contact_center: t34.center, worst_contact_message: t34.message, worst_actual_clearance: o3 });
continue;
}
const i3 = Number(n3.worst_actual_clearance);
(o3 < i3 || !Number.isFinite(i3)) && (n3.worst_contact_center = t34.center, n3.worst_contact_message = t34.message, n3.worst_actual_clearance = o3);
}
const l2 = [...c2.values()].map((t34) => ({ ...t34, center: typeof t34.worst_contact_center == "object" ? t34.worst_contact_center : t34.center, message: typeof t34.worst_contact_message == "string" ? t34.worst_contact_message : t34.message, actual_clearance: typeof t34.worst_actual_clearance == "number" ? t34.worst_actual_clearance : t34.actual_clearance }));
l2.push(...s2), l2.push(...a2);
const h2 = l2.filter((t34) => t34.center);
return { errors: l2, errorsWithCenters: h2, locationAwareErrors: h2 };
}
};
var lC = (t33, e2) => t33.width ?? e2.width ?? 0.1;
var hC = [1, 1.75, -1];
var dC = [1, 1.75, -1];
var uC = 8 / 3;
var pC = 0.000001;
var mC = 0.001;
var gC = 0.14;
var fC = 0.035;
var yC = 0.015;
var _C = (t33) => t33.minTraceToPadEdgeClearance ?? 0.16;
var bC = (t33) => t33.minViaEdgeToPadEdgeClearance ?? 0.1;
var xC = (t33) => Math.max(48, Math.round(48 * Math.max(1, t33)));
var vC = (t33) => t33 >= 2 ? hC : dC;
var IC = class {
netMap;
idToNetMap;
constructor(t33) {
this.netMap = t33, this.idToNetMap = {};
for (const [e2, n2] of Object.entries(t33))
for (const t34 of n2)
this.idToNetMap[t34] = e2;
}
addConnections(t33) {
for (const e2 of t33) {
const t34 = new Set;
for (const n3 of e2) {
const e3 = this.idToNetMap[n3];
e3 && t34.add(e3);
}
let n2;
if (t34.size === 0)
n2 = `connectivity_net${Object.keys(this.netMap).length}`, this.netMap[n2] = [];
else if (t34.size === 1)
n2 = t34.values().next().value ?? `connectivity_net${Object.keys(this.netMap).length}`;
else {
n2 = t34.values().next().value ?? `connectivity_net${Object.keys(this.netMap).length}`;
for (const e3 of t34)
if (e3 !== n2) {
this.netMap[n2].push(...this.netMap[e3]), this.netMap[e3] = this.netMap[n2];
for (const t35 of this.netMap[n2])
this.idToNetMap[t35] = n2;
}
}
for (const t35 of e2)
this.netMap[n2].includes(t35) || this.netMap[n2].push(t35), this.idToNetMap[t35] = n2;
}
}
getIdsConnectedToNet(t33) {
return this.netMap[t33] || [];
}
getNetConnectedToId(t33) {
return this.idToNetMap[t33];
}
areIdsConnected(t33, e2) {
if (t33 === e2)
return true;
const n2 = this.getNetConnectedToId(t33);
if (!n2)
return false;
const o2 = this.getNetConnectedToId(e2);
return !!o2 && (n2 === o2 || o2 === t33 || o2 === t33);
}
areAllIdsConnected(t33) {
const e2 = this.getNetConnectedToId(t33[0]);
for (const n2 of t33) {
const t34 = this.getNetConnectedToId(n2);
if (t34 === undefined)
return false;
if (t34 !== e2)
return false;
}
return true;
}
};
var SC = (t33) => {
const e2 = [];
for (const n3 of t33)
if (n3.type === "source_trace")
e2.push([n3.source_trace_id, ...n3.connected_source_port_ids ?? [], ...n3.connected_source_net_ids ?? []].filter(Boolean));
else if (n3.type === "pcb_port") {
const { pcb_port_id: t34, source_port_id: o2 } = n3;
o2 && t34 && e2.push([o2, t34]);
} else if (n3.type === "pcb_smtpad") {
const { pcb_smtpad_id: t34, pcb_port_id: o2 } = n3;
o2 && t34 && e2.push([t34, o2]);
} else if (n3.type === "pcb_plated_hole") {
const { pcb_plated_hole_id: t34, pcb_port_id: o2 } = n3;
o2 && t34 && e2.push([t34, o2]);
} else if (n3.type === "pcb_trace") {
const { pcb_trace_id: t34, source_trace_id: o2 } = n3, i2 = Array.isArray(n3.route) ? n3.route.filter((t35) => t35 && t35.route_type === "wire") : [];
if (o2 && t34 && e2.push([t34, o2]), Array.isArray(i2)) {
const n4 = i2.find((t35) => t35?.start_pcb_port_id)?.start_pcb_port_id, o3 = i2.find((t35) => t35?.end_pcb_port_id)?.end_pcb_port_id;
n4 && t34 && o3 && e2.push([n4, t34, o3]);
}
} else if (n3.type === "pcb_via") {
const { pcb_via_id: t34, pcb_trace_id: o2 } = n3;
o2 && t34 && e2.push([t34, o2]);
} else if (n3.type === "source_component" && n3.internally_connected_source_port_ids)
for (const t34 of n3.internally_connected_source_port_ids)
e2.push(t34);
const n2 = function(t34) {
const e3 = new Map;
let n3 = 0;
function o2(t35) {
for (const [, n4] of e3)
if (n4.has(t35))
return n4;
const o3 = new Set;
return e3.set("connectivity_net" + n3++, o3), o3;
}
for (const n4 of t34) {
let t35 = null;
for (const i2 of n4) {
if (t35) {
if (!t35.has(i2)) {
const n5 = o2(i2);
if (n5 !== t35) {
for (const e4 of n5)
t35.add(e4);
e3.delete(Array.from(e3.entries()).find(([, t36]) => t36 === n5)[0]);
}
}
} else
t35 = o2(i2);
t35.add(i2);
}
}
return Object.fromEntries(Array.from(e3.entries()).map(([t35, e4]) => [t35, Array.from(e4)]));
}(e2);
return new IC(n2);
};
var CC = { Hz: { baseUnit: "Hz", variants: { MHz: 1e6, kHz: 1000, Hz: 1 } }, g: { baseUnit: "g", variants: { kg: 1000, g: 1 } }, "Ω": { baseUnit: "Ω", variants: { "mΩ": 0.001, "Ω": 1, "kΩ": 1000, "KΩ": 1000, kohm: 1000, "MΩ": 1e6, "GΩ": 1e9, "TΩ": 1000000000000 } }, V: { baseUnit: "V", variants: { mV: 0.001, V: 1, kV: 1000, KV: 1000, MV: 1e6, GV: 1e9, TV: 1000000000000 } }, A: { baseUnit: "A", variants: { "µA": 0.000001, mA: 0.001, ma: 0.001, A: 1, kA: 1000, MA: 1e6 } }, F: { baseUnit: "F", variants: { pF: 0.000000000001, nF: 0.000000001, "µF": 0.000001, uF: 0.000001, mF: 0.001, F: 1 } }, ml: { baseUnit: "ml", variants: { ml: 1, mL: 1, l: 1000, L: 1000 } }, deg: { baseUnit: "deg", variants: { rad: 180 / Math.PI } }, ms: { baseUnit: "ms", variants: { fs: 0.000000000001, ps: 0.000000001, ns: 0.000001, us: 0.001, "µs": 0.001, ms: 1, s: 1000 } }, mm: { baseUnit: "mm", variants: { nm: 0.000001, "µm": 0.001, um: 0.001, mm: 1, cm: 10, dm: 100, m: 1000, km: 1e6, in: 25.4, ft: 304.8, IN: 25.4, FT: 304.8, yd: 914.4, mi: 1609344, mil: 0.0254 } } };
var PC = new Set;
for (const [t33, e2] of Object.entries(CC)) {
PC.add(t33);
for (const t34 of Object.keys(e2.variants))
PC.add(t34);
}
var MC = { tera: 1000000000000, T: 1000000000000, giga: 1e9, G: 1e9, mega: 1e6, M: 1e6, kilo: 1000, k: 1000, deci: 0.1, d: 0.1, centi: 0.01, c: 0.01, milli: 0.001, m: 0.001, micro: 0.000001, u: 0.000001, "µ": 0.000001, nano: 0.000000001, n: 0.000000001, pico: 0.000000000001, p: 0.000000000001 };
function NC(t33) {
if (t33 == null)
return { parsedUnit: null, unitOfValue: null, value: null };
if (typeof t33 == "string" && t33.match(/^-?[\d\.]+$/))
return { value: Number.parseFloat(t33), parsedUnit: null, unitOfValue: null };
if (typeof t33 == "number")
return { value: t33, parsedUnit: null, unitOfValue: null };
if (typeof t33 == "object" && "x" in t33 && "y" in t33) {
const { parsedUnit: e3, unitOfValue: n3 } = NC(t33.x), o3 = NC(t33.x), i3 = NC(t33.y);
return o3.value === null || i3.value === null ? { parsedUnit: null, unitOfValue: null, value: null } : { parsedUnit: e3, unitOfValue: n3, value: { x: o3.value, y: i3.value } };
}
const e2 = t33.toString().split("").reverse().join(""), n2 = e2.match(/[^\d\s]+/)?.[0];
if (!n2)
throw new Error(`Could not determine unit: "${t33}"`);
const o2 = n2.split("").reverse().join(""), i2 = t33.slice(0, -o2.length);
if (o2 in MC && !PC.has(o2)) {
const t34 = MC[o2];
return { parsedUnit: null, unitOfValue: null, value: Number.parseFloat(i2) * t34 };
}
const { baseUnit: r2, conversionFactor: s2 } = function(t34) {
for (const [e3, n3] of Object.entries(CC))
if (t34 in n3.variants)
return { baseUnit: n3.baseUnit, conversionFactor: n3.variants[t34] };
return { baseUnit: t34, conversionFactor: 1 };
}(o2);
return { parsedUnit: o2, unitOfValue: r2, value: s2 * Number.parseFloat(i2) };
}
var wC = pa.string().or(pa.number()).transform((t33) => NC(t33).value);
var TC = pa.string().or(pa.number()).transform((t33) => NC(t33).value).transform((t33) => Number.parseFloat(t33.toPrecision(12)));
var RC = pa.string().or(pa.number()).transform((t33) => NC(t33).value);
var EC = pa.string().or(pa.number()).transform((t33) => NC(t33).value);
var AC = pa.string().or(pa.number()).transform((t33) => NC(t33).value);
var OC = pa.string().or(pa.number()).transform((t33) => NC(t33).value);
var kC = AC;
var DC = pa.string().or(pa.number()).transform((t33) => NC(t33).value);
var LC = pa.string().or(pa.number()).transform((t33) => NC(t33).value);
var zC = LC;
var BC = pa.string().datetime();
var FC = pa.string().or(pa.number()).transform((t33) => typeof t33 == "number" ? t33 : t33.endsWith("deg") ? Number.parseFloat(t33.split("deg")[0]) : t33.endsWith("rad") ? 180 * Number.parseFloat(t33.split("rad")[0]) / Math.PI : Number.parseFloat(t33));
var jC = pa.number().or(pa.string().endsWith("mAh")).transform((t33) => {
if (typeof t33 == "string") {
const e2 = t33.replace("mAh", ""), n2 = Number.parseFloat(e2);
if (Number.isNaN(n2))
throw new Error("Invalid capacity");
return n2;
}
return t33;
}).describe("Battery capacity in mAh");
var $C = pa.object({ x: kC, y: kC });
var YC = pa.object({ x: kC, y: kC, z: kC });
var XC = pa.object({ width: pa.number(), height: pa.number() });
var WC = (t33) => pa.string().optional().default(() => `${t33}_${((t34) => {
const e2 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return Array.from({ length: t34 }, () => e2[Math.floor(62 * Math.random())]).join("");
})(10)}`);
var VC = pa.enum(["top_left", "top_center", "top_right", "center_left", "center", "center_right", "bottom_left", "bottom_center", "bottom_right"]);
var HC = (pa.enum(["top_silkscreen", "bottom_silkscreen", "top_copper", "bottom_copper", "top_soldermask", "bottom_soldermask", "top_fabrication_note", "bottom_fabrication_note", "top_user_note", "bottom_user_note", "top_courtyard", "bottom_courtyard", "inner1_copper", "inner2_copper", "inner3_copper", "inner4_copper", "inner5_copper", "inner6_copper", "edge_cuts", "drill"]), pa.object({ project_relative_path: pa.string(), url: pa.string(), mimetype: pa.string() }));
var GC = $C.extend({ rotation: FC.optional() });
var UC = pa.object({ size: $C.optional(), thickness: kC.optional() });
var ZC = pa.object({ font: UC.optional() });
var qC = pa.object({ value: pa.string(), at: GC.optional(), layer: pa.string().optional(), uuid: pa.string().optional(), hide: pa.boolean().optional(), effects: ZC.optional() });
var JC = pa.object({ Reference: qC.optional(), Value: qC.optional(), Datasheet: qC.optional(), Description: qC.optional() });
var QC = pa.object({ through_hole: pa.boolean().optional(), smd: pa.boolean().optional(), exclude_from_pos_files: pa.boolean().optional(), exclude_from_bom: pa.boolean().optional() });
var KC = pa.object({ name: pa.string(), type: pa.string(), shape: pa.string().optional(), at: GC.optional(), size: $C.optional(), drill: kC.optional(), layers: pa.array(pa.string()).optional(), removeUnusedLayers: pa.boolean().optional(), uuid: pa.string().optional() });
var tP = pa.object({ path: pa.string(), offset: YC.optional(), scale: YC.optional(), rotate: YC.optional() });
var eP = pa.object({ footprintName: pa.string().optional(), version: pa.union([pa.number(), pa.string()]).optional(), generator: pa.string().optional(), generatorVersion: pa.union([pa.number(), pa.string()]).optional(), layer: pa.string().optional(), properties: JC.optional(), attributes: QC.optional(), pads: pa.array(KC).optional(), embeddedFonts: pa.boolean().optional(), model: tP.optional() });
var nP = pa.object({ hide: pa.boolean().optional() });
var oP = pa.object({ offset: kC.optional(), hide: pa.boolean().optional() });
var iP = pa.object({ font: UC.optional(), justify: pa.union([pa.string(), pa.array(pa.string())]).optional(), hide: pa.boolean().optional() });
var rP = pa.object({ value: pa.string(), id: pa.union([pa.number(), pa.string()]).optional(), at: GC.optional(), effects: iP.optional() });
var sP = pa.object({ Reference: rP.optional(), Value: rP.optional(), Footprint: rP.optional(), Datasheet: rP.optional(), Description: rP.optional(), ki_keywords: rP.optional(), ki_fp_filters: rP.optional() });
var aP = pa.object({ symbolName: pa.string().optional(), extends: pa.string().optional(), pinNumbers: nP.optional(), pinNames: oP.optional(), excludeFromSim: pa.boolean().optional(), inBom: pa.boolean().optional(), onBoard: pa.boolean().optional(), properties: sP.optional(), embeddedFonts: pa.boolean().optional() });
var cP = pa.object({ error_type: pa.string(), message: pa.string(), is_fatal: pa.boolean().optional() });
var lP = pa.enum(["jlcpcb", "macrofab", "pcbway", "digikey", "mouser", "lcsc"]);
var hP = pa.object({ type: pa.literal("source_component"), ftype: pa.string().optional(), source_component_id: pa.string(), name: pa.string(), manufacturer_part_number: pa.string().optional(), supplier_part_numbers: pa.record(lP, pa.array(pa.string())).optional(), display_value: pa.string().optional(), display_name: pa.string().optional(), are_pins_interchangeable: pa.boolean().optional(), internally_connected_source_port_ids: pa.array(pa.array(pa.string())).optional(), source_group_id: pa.string().optional(), subcircuit_id: pa.string().optional() });
var dP = hP.extend({ ftype: pa.literal("simple_capacitor"), capacitance: TC, max_voltage_rating: EC.optional(), display_capacitance: pa.string().optional(), max_decoupling_trace_length: kC.optional() });
var uP = hP.extend({ ftype: pa.literal("simple_resistor"), resistance: wC, display_resistance: pa.string().optional() });
var pP = hP.extend({ ftype: pa.literal("simple_diode") });
var mP = hP.extend({ ftype: pa.literal("simple_fiducial") });
var gP = pP.extend({ ftype: pa.literal("simple_led"), color: pa.string().optional(), wavelength: pa.string().optional() });
var fP = hP.extend({ ftype: pa.literal("simple_ground") });
var yP = hP.extend({ ftype: pa.literal("simple_chip") });
var _P = hP.extend({ ftype: pa.literal("simple_power_source"), voltage: EC });
var bP = hP.extend({ ftype: pa.literal("simple_current_source"), current: DC, frequency: OC.optional(), peak_to_peak_current: DC.optional(), wave_shape: pa.enum(["sine", "square", "triangle", "sawtooth", "dc"]).optional().default("dc"), phase: pa.number().optional(), duty_cycle: pa.number().min(0).max(1).optional() });
var xP = pa.object({ must_be_connected: pa.boolean().optional(), provides_power: pa.boolean().optional(), requires_power: pa.boolean().optional(), provides_ground: pa.boolean().optional(), requires_ground: pa.boolean().optional(), provides_voltage: pa.union([pa.string(), pa.number()]).optional(), requires_voltage: pa.union([pa.string(), pa.number()]).optional(), do_not_connect: pa.boolean().optional(), include_in_board_pinout: pa.boolean().optional(), can_use_internal_pullup: pa.boolean().optional(), is_using_internal_pullup: pa.boolean().optional(), needs_external_pullup: pa.boolean().optional(), can_use_internal_pulldown: pa.boolean().optional(), is_using_internal_pulldown: pa.boolean().optional(), needs_external_pulldown: pa.boolean().optional(), can_use_open_drain: pa.boolean().optional(), is_using_open_drain: pa.boolean().optional(), can_use_push_pull: pa.boolean().optional(), is_using_push_pull: pa.boolean().optional(), should_have_decoupling_capacitor: pa.boolean().optional(), recommended_decoupling_capacitor_capacitance: pa.union([pa.string(), pa.number()]).optional(), is_configured_for_i2c_sda: pa.boolean().optional(), is_configured_for_i2c_scl: pa.boolean().optional(), is_configured_for_spi_mosi: pa.boolean().optional(), is_configured_for_spi_miso: pa.boolean().optional(), is_configured_for_spi_sck: pa.boolean().optional(), is_configured_for_spi_cs: pa.boolean().optional(), is_configured_for_uart_tx: pa.boolean().optional(), is_configured_for_uart_rx: pa.boolean().optional(), supports_i2c_sda: pa.boolean().optional(), supports_i2c_scl: pa.boolean().optional(), supports_spi_mosi: pa.boolean().optional(), supports_spi_miso: pa.boolean().optional(), supports_spi_sck: pa.boolean().optional(), supports_spi_cs: pa.boolean().optional(), supports_uart_tx: pa.boolean().optional(), supports_uart_rx: pa.boolean().optional() });
var vP = hP.extend({ ftype: pa.literal("simple_fuse"), current_rating_amps: pa.number().describe("Nominal current in amps the fuse is rated for"), voltage_rating_volts: pa.number().describe("Voltage rating in volts, e.g. ±5V would be 5") });
var IP = hP.extend({ ftype: pa.literal("simple_battery"), capacity: jC });
var SP = hP.extend({ ftype: pa.literal("simple_inductor"), inductance: RC, display_inductance: pa.string().optional(), max_current_rating: pa.number().optional() });
var CP = hP.extend({ ftype: pa.literal("simple_push_button") });
var PP = hP.extend({ ftype: pa.literal("simple_potentiometer"), max_resistance: wC, display_max_resistance: pa.string().optional() });
var MP = hP.extend({ ftype: pa.literal("simple_crystal"), frequency: pa.number().describe("Frequency in Hz"), load_capacitance: pa.number().optional().describe("Load capacitance in pF"), pin_variant: pa.enum(["two_pin", "four_pin"]).optional() });
var NP = hP.extend({ ftype: pa.literal("simple_pin_header"), pin_count: pa.number(), gender: pa.enum(["male", "female"]).optional().default("male") });
var wP = hP.extend({ ftype: pa.literal("simple_connector"), standard: pa.enum(["usb_c", "m2"]).optional() });
var TP = hP.extend({ ftype: pa.literal("simple_pinout") });
var RP = hP.extend({ ftype: pa.literal("simple_resonator"), load_capacitance: TC, equivalent_series_resistance: wC.optional(), frequency: OC });
var EP = hP.extend({ ftype: pa.literal("simple_transistor"), transistor_type: pa.enum(["npn", "pnp"]) });
var AP = hP.extend({ ftype: pa.literal("simple_test_point"), footprint_variant: pa.enum(["pad", "through_hole"]).optional(), pad_shape: pa.enum(["rect", "circle"]).optional(), pad_diameter: pa.union([pa.number(), pa.string()]).optional(), hole_diameter: pa.union([pa.number(), pa.string()]).optional(), width: pa.union([pa.number(), pa.string()]).optional(), height: pa.union([pa.number(), pa.string()]).optional() });
var OP = hP.extend({ ftype: pa.literal("simple_mosfet"), channel_type: pa.enum(["n", "p"]), mosfet_mode: pa.enum(["enhancement", "depletion"]) });
var kP = hP.extend({ ftype: pa.literal("simple_op_amp") });
var DP = hP.extend({ ftype: pa.literal("simple_switch") });
var LP = pa.object({ type: pa.literal("source_project_metadata"), name: pa.string().optional(), software_used_string: pa.string().optional(), project_url: pa.string().optional(), created_at: BC.optional() });
var zP = cP.extend({ type: pa.literal("source_missing_property_error"), source_missing_property_error_id: WC("source_missing_property_error"), source_component_id: pa.string(), property_name: pa.string(), subcircuit_id: pa.string().optional(), error_type: pa.literal("source_missing_property_error").default("source_missing_property_error") }).describe("The source code is missing a property");
var BP = cP.extend({ type: pa.literal("source_failed_to_create_component_error"), source_failed_to_create_component_error_id: WC("source_failed_to_create_component_error"), error_type: pa.literal("source_failed_to_create_component_error").default("source_failed_to_create_component_error"), component_name: pa.string().optional(), subcircuit_id: pa.string().optional(), parent_source_component_id: pa.string().optional(), pcb_center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), schematic_center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional() }).describe("Error emitted when a component fails to be constructed");
var FP = cP.extend({ type: pa.literal("source_invalid_component_property_error"), source_invalid_component_property_error_id: WC("source_invalid_component_property_error"), source_component_id: pa.string(), property_name: pa.string(), property_value: pa.unknown().optional(), expected_format: pa.string().optional(), subcircuit_id: pa.string().optional(), error_type: pa.literal("source_invalid_component_property_error").default("source_invalid_component_property_error") }).describe("The source component property is invalid");
var jP = cP.extend({ type: pa.literal("source_trace_not_connected_error"), source_trace_not_connected_error_id: WC("source_trace_not_connected_error"), error_type: pa.literal("source_trace_not_connected_error").default("source_trace_not_connected_error"), subcircuit_id: pa.string().optional(), source_group_id: pa.string().optional(), source_trace_id: pa.string().optional(), connected_source_port_ids: pa.array(pa.string()).optional(), selectors_not_found: pa.array(pa.string()).optional() }).describe("Occurs when a source trace selector does not match any ports");
var $P = pa.object({ type: pa.literal("source_property_ignored_warning"), source_property_ignored_warning_id: WC("source_property_ignored_warning"), source_component_id: pa.string(), property_name: pa.string(), subcircuit_id: pa.string().optional(), error_type: pa.literal("source_property_ignored_warning").default("source_property_ignored_warning"), message: pa.string() }).describe("The source property was ignored");
var YP = pa.object({ type: pa.literal("source_pin_missing_trace_warning"), source_pin_missing_trace_warning_id: WC("source_pin_missing_trace_warning"), warning_type: pa.literal("source_pin_missing_trace_warning").default("source_pin_missing_trace_warning"), message: pa.string(), source_component_id: pa.string(), source_port_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a source component pin is missing a trace connection");
var XP = pa.object({ type: pa.literal("source_missing_manufacturer_part_number_warning"), source_missing_manufacturer_part_number_warning_id: WC("source_missing_manufacturer_part_number_warning"), warning_type: pa.literal("source_missing_manufacturer_part_number_warning").default("source_missing_manufacturer_part_number_warning"), message: pa.string(), source_component_id: pa.string(), standard: pa.string(), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a standard connector is missing manufacturer part number");
var WP = hP.extend({ ftype: pa.literal("simple_voltage_probe") });
var VP = hP.extend({ ftype: pa.literal("interconnect") });
var HP = cP.extend({ type: pa.literal("source_i2c_misconfigured_error"), source_i2c_misconfigured_error_id: WC("source_i2c_misconfigured_error"), error_type: pa.literal("source_i2c_misconfigured_error").default("source_i2c_misconfigured_error"), source_port_ids: pa.array(pa.string()) }).describe("Error emitted when incompatible I2C pins (e.g. SDA and SCL) are connected to the same net");
var GP = hP.extend({ ftype: pa.literal("simple_voltage_source"), voltage: EC, frequency: OC.optional(), peak_to_peak_voltage: EC.optional(), wave_shape: pa.enum(["sinewave", "square", "triangle", "sawtooth"]).optional(), phase: FC.optional(), duty_cycle: pa.number().optional().describe("Duty cycle as a fraction (0 to 1)") });
var UP = pa.union([uP, dP, pP, mP, gP, fP, yP, _P, bP, IP, SP, CP, PP, MP, NP, wP, TP, RP, DP, EP, AP, OP, kP, vP, WP, VP, GP, LP, zP, FP, BP, jP, $P, YP, XP, HP]);
var ZP = pa.object({ type: pa.literal("source_port"), pin_number: pa.number().optional(), port_hints: pa.array(pa.string()).optional(), name: pa.string(), source_port_id: pa.string(), source_component_id: pa.string().optional(), source_group_id: pa.string().optional(), most_frequently_referenced_by_name: pa.string().optional(), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional() }).merge(xP);
var qP = pa.object({ type: pa.literal("source_component_internal_connection"), source_component_internal_connection_id: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() });
var JP = pa.object({ type: pa.literal("source_trace"), source_trace_id: pa.string(), connected_source_port_ids: pa.array(pa.string()), connected_source_net_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional(), max_length: pa.number().optional(), min_trace_thickness: pa.number().optional(), display_name: pa.string().optional() });
var QP = pa.object({ type: pa.literal("source_group"), source_group_id: pa.string(), subcircuit_id: pa.string().optional(), parent_subcircuit_id: pa.string().optional(), parent_source_group_id: pa.string().optional(), is_subcircuit: pa.boolean().optional(), show_as_schematic_box: pa.boolean().optional(), name: pa.string().optional(), was_automatically_named: pa.boolean().optional() });
var KP = pa.object({ type: pa.literal("source_net"), source_net_id: pa.string(), name: pa.string(), member_source_group_ids: pa.array(pa.string()), is_power: pa.boolean().optional(), is_ground: pa.boolean().optional(), is_digital_signal: pa.boolean().optional(), is_analog_signal: pa.boolean().optional(), is_positive_voltage_source: pa.boolean().optional(), trace_width: pa.number().optional(), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional() });
var tM = pa.object({ type: pa.literal("source_board"), source_board_id: pa.string(), source_group_id: pa.string(), title: pa.string().optional() }).describe("Defines a board in the source domain");
var eM = cP.extend({ type: pa.literal("source_ambiguous_port_reference"), source_ambiguous_port_reference_id: WC("source_ambiguous_port_reference"), error_type: pa.literal("source_ambiguous_port_reference").default("source_ambiguous_port_reference"), source_port_id: pa.string().optional(), source_component_id: pa.string().optional() }).describe("Error emitted when a port hint matches multiple non-overlapping pads, making the port reference ambiguous");
var nM = pa.object({ type: pa.literal("source_pcb_ground_plane"), source_pcb_ground_plane_id: pa.string(), source_group_id: pa.string(), source_net_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Defines a ground plane in the source domain");
var oM = ["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6"];
var iM = pa.enum(oM);
var rM = iM.or(pa.object({ name: iM })).transform((t33) => typeof t33 == "string" ? t33 : t33.name);
var sM = pa.enum(["top", "bottom"]);
var aM = pa.object({ type: pa.literal("source_manually_placed_via"), source_manually_placed_via_id: pa.string(), source_group_id: pa.string(), source_net_id: pa.string(), subcircuit_id: pa.string().optional(), source_trace_id: pa.string().optional() }).describe("Defines a via that is manually placed in the source domain");
var cM = pa.object({ type: pa.literal("source_no_power_pin_defined_warning"), source_no_power_pin_defined_warning_id: WC("source_no_power_pin_defined_warning"), warning_type: pa.literal("source_no_power_pin_defined_warning").default("source_no_power_pin_defined_warning"), message: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a chip has no source ports with requires_power=true");
var lM = pa.object({ type: pa.literal("source_no_ground_pin_defined_warning"), source_no_ground_pin_defined_warning_id: WC("source_no_ground_pin_defined_warning"), warning_type: pa.literal("source_no_ground_pin_defined_warning").default("source_no_ground_pin_defined_warning"), message: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Warning emitted when a chip has no source ports marked as ground pins");
var hM = pa.object({ type: pa.literal("source_component_pins_underspecified_warning"), source_component_pins_underspecified_warning_id: WC("source_component_pins_underspecified_warning"), warning_type: pa.literal("source_component_pins_underspecified_warning").default("source_component_pins_underspecified_warning"), message: pa.string(), source_component_id: pa.string(), source_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Warning emitted when all ports on a source component are underspecified");
var dM = cP.extend({ type: pa.literal("source_pin_must_be_connected_error"), source_pin_must_be_connected_error_id: WC("source_pin_must_be_connected_error"), error_type: pa.literal("source_pin_must_be_connected_error").default("source_pin_must_be_connected_error"), source_component_id: pa.string(), source_port_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a pin with mustBeConnected attribute is not connected to any trace");
var uM = cP.extend({ type: pa.literal("unknown_error_finding_part"), unknown_error_finding_part_id: WC("unknown_error_finding_part"), error_type: pa.literal("unknown_error_finding_part").default("unknown_error_finding_part"), source_component_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when an unexpected error occurs while finding a part");
var pM = pa.object({ type: pa.literal("schematic_box"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), width: kC, height: kC, is_dashed: pa.boolean().default(false), x: kC, y: kC, subcircuit_id: pa.string().optional() }).describe("Draws a box on the schematic");
var mM = pa.object({ type: pa.literal("schematic_path"), schematic_path_id: WC("schematic_path"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), fill_color: pa.string().optional(), is_filled: pa.boolean().optional(), stroke_width: kC.nullable().optional(), stroke_color: pa.string().optional(), points: pa.array($C), subcircuit_id: pa.string().optional() });
var gM = pa.record(pa.object({ left_margin: AC.optional(), right_margin: AC.optional(), top_margin: AC.optional(), bottom_margin: AC.optional() }));
var fM = pa.object({ left_size: pa.number(), right_size: pa.number(), top_size: pa.number().optional(), bottom_size: pa.number().optional() });
var yM = pa.object({ left_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["top-to-bottom", "bottom-to-top"]).optional() }).optional(), right_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["top-to-bottom", "bottom-to-top"]).optional() }).optional(), top_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["left-to-right", "right-to-left"]).optional() }).optional(), bottom_side: pa.object({ pins: pa.array(pa.number()), direction: pa.enum(["left-to-right", "right-to-left"]).optional() }).optional() });
var _M = pa.union([fM, yM]);
var bM = pa.object({ type: pa.literal("schematic_component"), size: XC, center: $C, source_component_id: pa.string().optional(), schematic_component_id: pa.string(), schematic_symbol_id: pa.string().optional(), pin_spacing: AC.optional(), pin_styles: gM.optional(), box_width: AC.optional(), symbol_name: pa.string().optional(), port_arrangement: _M.optional(), port_labels: pa.record(pa.string()).optional(), symbol_display_value: pa.string().optional(), subcircuit_id: pa.string().optional(), schematic_group_id: pa.string().optional(), is_schematic_group: pa.boolean().optional(), source_group_id: pa.string().optional(), is_box_with_pins: pa.boolean().optional().default(true) });
var xM = pa.object({ kicad_symbol: aP.optional() }).catchall(pa.unknown());
var vM = pa.object({ type: pa.literal("schematic_symbol"), schematic_symbol_id: pa.string(), name: pa.string().optional(), metadata: xM.optional() }).describe("Defines a named schematic symbol that can be referenced by components.");
var IM = pa.object({ type: pa.literal("schematic_line"), schematic_line_id: WC("schematic_line"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), x1: kC, y1: kC, x2: kC, y2: kC, stroke_width: kC.nullable().optional(), color: pa.string().default("#000000"), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled line on the schematic");
var SM = pa.object({ type: pa.literal("schematic_rect"), schematic_rect_id: WC("schematic_rect"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), center: $C, width: kC, height: kC, rotation: FC.default(0), stroke_width: kC.nullable().optional(), color: pa.string().default("#000000"), is_filled: pa.boolean().default(false), fill_color: pa.string().optional(), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled rectangle on the schematic");
var CM = pa.object({ type: pa.literal("schematic_circle"), schematic_circle_id: WC("schematic_circle"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), center: $C, radius: kC, stroke_width: kC.nullable().optional(), color: pa.string().default("#000000"), is_filled: pa.boolean().default(false), fill_color: pa.string().optional(), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled circle on the schematic");
var PM = pa.object({ type: pa.literal("schematic_arc"), schematic_arc_id: WC("schematic_arc"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), center: $C, radius: kC, start_angle_degrees: FC, end_angle_degrees: FC, direction: pa.enum(["clockwise", "counterclockwise"]).default("counterclockwise"), stroke_width: kC.nullable().optional(), color: pa.string().default("#000000"), is_dashed: pa.boolean().default(false), subcircuit_id: pa.string().optional() }).describe("Draws a styled arc on the schematic");
var MM = pa.object({ type: pa.literal("schematic_trace"), schematic_trace_id: pa.string(), source_trace_id: pa.string().optional(), junctions: pa.array(pa.object({ x: pa.number(), y: pa.number() })), edges: pa.array(pa.object({ from: pa.object({ x: pa.number(), y: pa.number() }), to: pa.object({ x: pa.number(), y: pa.number() }), is_crossing: pa.boolean().optional(), from_schematic_port_id: pa.string().optional(), to_schematic_port_id: pa.string().optional() })), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional() });
var NM = pa.enum(["center", "left", "right", "top", "bottom"]);
var wM = pa.object({ type: pa.literal("schematic_text"), schematic_component_id: pa.string().optional(), schematic_symbol_id: pa.string().optional(), schematic_text_id: pa.string(), text: pa.string(), font_size: pa.number().default(0.18), position: pa.object({ x: kC, y: kC }), rotation: pa.number().default(0), anchor: pa.union([NM.describe("legacy"), VC]).default("center"), color: pa.string().default("#000000"), subcircuit_id: pa.string().optional() });
var TM = pa.object({ type: pa.literal("schematic_port"), schematic_port_id: pa.string(), source_port_id: pa.string(), schematic_component_id: pa.string().optional(), center: $C, facing_direction: pa.enum(["up", "down", "left", "right"]).optional(), distance_from_component_edge: pa.number().optional(), side_of_component: pa.enum(["top", "bottom", "left", "right"]).optional(), true_ccw_index: pa.number().optional(), pin_number: pa.number().optional(), display_pin_label: pa.string().optional(), subcircuit_id: pa.string().optional(), is_connected: pa.boolean().optional(), has_input_arrow: pa.boolean().optional(), has_output_arrow: pa.boolean().optional(), is_drawn_with_inversion_circle: pa.boolean().optional() }).describe("Defines a port on a schematic component");
var RM = pa.object({ type: pa.literal("schematic_net_label"), schematic_net_label_id: WC("schematic_net_label"), schematic_trace_id: pa.string().optional(), source_trace_id: pa.string().optional(), source_net_id: pa.string(), center: $C, anchor_position: $C.optional(), anchor_side: pa.enum(["top", "bottom", "left", "right"]), text: pa.string(), symbol_name: pa.string().optional(), is_movable: pa.boolean().optional(), subcircuit_id: pa.string().optional() });
var EM = cP.extend({ type: pa.literal("schematic_error"), schematic_error_id: pa.string(), error_type: pa.literal("schematic_port_not_found").default("schematic_port_not_found"), subcircuit_id: pa.string().optional() }).describe("Defines a schematic error on the schematic");
var AM = cP.extend({ type: pa.literal("schematic_layout_error"), schematic_layout_error_id: WC("schematic_layout_error"), error_type: pa.literal("schematic_layout_error").default("schematic_layout_error"), source_group_id: pa.string(), schematic_group_id: pa.string(), subcircuit_id: pa.string().optional() }).describe("Error emitted when schematic layout fails for a group");
var OM = pa.object({ type: pa.literal("schematic_debug_object"), label: pa.string().optional(), subcircuit_id: pa.string().optional() });
var kM = OM.extend({ shape: pa.literal("rect"), center: $C, size: XC });
var DM = OM.extend({ shape: pa.literal("line"), start: $C, end: $C });
var LM = OM.extend({ shape: pa.literal("point"), center: $C });
var zM = pa.discriminatedUnion("shape", [kM, DM, LM]);
var BM = pa.object({ type: pa.literal("schematic_voltage_probe"), schematic_voltage_probe_id: pa.string(), source_component_id: pa.string().optional(), name: pa.string().optional(), position: $C, schematic_trace_id: pa.string(), voltage: EC.optional(), subcircuit_id: pa.string().optional(), color: pa.string().optional(), label_alignment: VC.optional() }).describe("Defines a voltage probe measurement point on a schematic trace");
var FM = pa.object({ type: pa.literal("schematic_manual_edit_conflict_warning"), schematic_manual_edit_conflict_warning_id: WC("schematic_manual_edit_conflict_warning"), warning_type: pa.literal("schematic_manual_edit_conflict_warning").default("schematic_manual_edit_conflict_warning"), message: pa.string(), schematic_component_id: pa.string(), schematic_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), source_component_id: pa.string() }).describe("Warning emitted when a component has both manual placement and explicit schX/schY coordinates");
var jM = pa.object({ type: pa.literal("schematic_group"), schematic_group_id: WC("schematic_group"), source_group_id: pa.string(), is_subcircuit: pa.boolean().optional(), subcircuit_id: pa.string().optional(), width: AC, height: AC, center: $C, schematic_component_ids: pa.array(pa.string()), show_as_schematic_box: pa.boolean().optional(), name: pa.string().optional(), description: pa.string().optional() }).describe("Defines a group of components on the schematic");
var $M = pa.object({ type: pa.literal("schematic_table"), schematic_table_id: WC("schematic_table"), anchor_position: $C, column_widths: pa.array(kC), row_heights: pa.array(kC), cell_padding: kC.optional(), border_width: kC.optional(), subcircuit_id: pa.string().optional(), schematic_component_id: pa.string().optional(), anchor: VC.optional() }).describe("Defines a table on the schematic");
var YM = pa.object({ type: pa.literal("schematic_table_cell"), schematic_table_cell_id: WC("schematic_table_cell"), schematic_table_id: pa.string(), start_row_index: pa.number(), end_row_index: pa.number(), start_column_index: pa.number(), end_column_index: pa.number(), text: pa.string().optional(), center: $C, width: kC, height: kC, horizontal_align: pa.enum(["left", "center", "right"]).optional(), vertical_align: pa.enum(["top", "middle", "bottom"]).optional(), font_size: kC.optional(), subcircuit_id: pa.string().optional() }).describe("Defines a cell within a schematic_table");
var XM = pa.object({ type: pa.literal("schematic_sheet"), schematic_sheet_id: WC("schematic_sheet"), name: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Defines a schematic sheet or page that components can be placed on");
var WM = pa.object({ x: kC, y: kC, bulge: pa.number().optional() });
var VM = pa.object({ vertices: pa.array(WM) });
var HM = pa.object({ outer_ring: VM, inner_rings: pa.array(VM).default([]) });
var GM = pa.object({ x: kC, y: kC, via: pa.boolean().optional(), via_to_layer: rM.optional() });
var UM = (pa.array(GM), pa.object({ x: kC, y: kC, via: pa.boolean().optional(), to_layer: rM.optional(), trace_width: kC.optional() }));
var ZM = pa.object({ min_trace_width: AC.optional(), min_board_edge_clearance: AC.optional(), min_via_hole_edge_to_via_hole_edge_clearance: AC.optional(), min_plated_hole_drill_edge_to_drill_edge_clearance: AC.optional(), min_trace_to_pad_edge_clearance: AC.optional(), min_pad_edge_to_pad_edge_clearance: AC.optional(), min_same_net_trace_edge_to_trace_edge_clearance: AC.optional(), min_different_net_trace_edge_to_trace_edge_clearance: AC.optional(), min_via_hole_diameter: AC.optional(), min_via_pad_diameter: AC.optional() });
var qM = pa.object({ type: pa.literal("pcb_component"), pcb_component_id: WC("pcb_component"), source_component_id: pa.string(), center: $C, layer: rM, rotation: FC, display_offset_x: pa.string().optional().describe("How to display the x offset for this part, usually corresponding with how the user specified it"), display_offset_y: pa.string().optional().describe("How to display the y offset for this part, usually corresponding with how the user specified it"), width: AC, height: AC, do_not_place: pa.boolean().optional(), is_allowed_to_be_off_board: pa.boolean().optional(), subcircuit_id: pa.string().optional(), pcb_group_id: pa.string().optional(), position_mode: pa.enum(["packed", "relative_to_group_anchor", "relative_to_another_component", "none"]).optional(), anchor_position: $C.optional(), anchor_alignment: VC.optional(), positioned_relative_to_pcb_group_id: pa.string().optional(), positioned_relative_to_pcb_board_id: pa.string().optional(), cable_insertion_center: $C.optional(), insertion_direction: pa.enum(["from_above", "from_left", "from_right", "from_front", "from_back"]).optional(), metadata: pa.object({ kicad_footprint: eP.optional() }).optional(), obstructs_within_bounds: pa.boolean().default(true).describe("Does this component take up all the space within its bounds on a layer. This is generally true except for when separated pin headers are being represented by a single component (in which case, chips can be placed between the pin headers) or for tall modules where chips fit underneath") }).describe("Defines a component on the PCB");
var JM = pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: WC("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("circle"), hole_diameter: pa.number(), x: kC, y: kC, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var QM = (JM.describe("Defines a circular hole on the PCB"), pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: WC("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("rect"), hole_width: pa.number(), hole_height: pa.number(), x: kC, y: kC, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() }));
var KM = (QM.describe("Defines a rectangular (square-capable) hole on the PCB. Use equal width/height for square."), pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: WC("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.enum(["circle", "square"]), hole_diameter: pa.number(), x: kC, y: kC, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() }));
var tN = (KM.describe("Defines a circular or square hole on the PCB"), pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: WC("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("oval"), hole_width: pa.number(), hole_height: pa.number(), x: kC, y: kC, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() }));
var eN = (tN.describe("Defines an oval hole on the PCB"), pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: WC("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("pill"), hole_width: pa.number(), hole_height: pa.number(), x: kC, y: kC, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() }));
var nN = (eN.describe("Defines a pill-shaped hole on the PCB"), pa.object({ type: pa.literal("pcb_hole"), pcb_hole_id: WC("pcb_hole"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_component_id: pa.string().optional(), hole_shape: pa.literal("rotated_pill"), hole_width: pa.number(), hole_height: pa.number(), x: kC, y: kC, ccw_rotation: FC, is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() }));
var oN = (nN.describe("Defines a rotated pill-shaped hole on the PCB"), KM.or(tN).or(eN).or(nN).or(JM).or(QM));
var iN = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("circle"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), outer_diameter: pa.number(), hole_diameter: pa.number(), is_covered_with_solder_mask: pa.boolean().optional(), x: kC, y: kC, layers: pa.array(rM), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: WC("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var rN = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.enum(["oval", "pill"]), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), outer_width: pa.number(), outer_height: pa.number(), hole_width: pa.number(), hole_height: pa.number(), is_covered_with_solder_mask: pa.boolean().optional(), x: kC, y: kC, ccw_rotation: FC, layers: pa.array(rM), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: WC("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var sN = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("circular_hole_with_rect_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.literal("circle"), pad_shape: pa.literal("rect"), hole_diameter: pa.number(), rect_pad_width: pa.number(), rect_pad_height: pa.number(), rect_border_radius: pa.number().optional(), hole_offset_x: kC.default(0), hole_offset_y: kC.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: kC, y: kC, layers: pa.array(rM), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: WC("pcb_plated_hole"), soldermask_margin: pa.number().optional(), rect_ccw_rotation: FC.optional() });
var aN = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("pill_hole_with_rect_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.literal("pill"), pad_shape: pa.literal("rect"), hole_width: pa.number(), hole_height: pa.number(), rect_pad_width: pa.number(), rect_pad_height: pa.number(), rect_border_radius: pa.number().optional(), hole_offset_x: kC.default(0), hole_offset_y: kC.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: kC, y: kC, layers: pa.array(rM), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: WC("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var cN = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("rotated_pill_hole_with_rect_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.literal("rotated_pill"), pad_shape: pa.literal("rect"), hole_width: pa.number(), hole_height: pa.number(), hole_ccw_rotation: FC, rect_pad_width: pa.number(), rect_pad_height: pa.number(), rect_border_radius: pa.number().optional(), rect_ccw_rotation: FC, hole_offset_x: kC.default(0), hole_offset_y: kC.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: kC, y: kC, layers: pa.array(rM), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: WC("pcb_plated_hole"), soldermask_margin: pa.number().optional() });
var lN = pa.object({ type: pa.literal("pcb_plated_hole"), shape: pa.literal("hole_with_polygon_pad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), hole_shape: pa.enum(["circle", "oval", "pill", "rotated_pill"]), hole_diameter: pa.number().optional(), hole_width: pa.number().optional(), hole_height: pa.number().optional(), pad_outline: pa.array(pa.object({ x: kC, y: kC })).min(3), hole_offset_x: kC.default(0), hole_offset_y: kC.default(0), is_covered_with_solder_mask: pa.boolean().optional(), x: kC, y: kC, layers: pa.array(rM), port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), pcb_plated_hole_id: WC("pcb_plated_hole"), soldermask_margin: pa.number().optional(), ccw_rotation: FC.optional() });
var hN = pa.union([iN, rN, sN, aN, cN, lN]);
var dN = pa.object({ type: pa.literal("pcb_port"), pcb_port_id: WC("pcb_port"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), source_port_id: pa.string(), pcb_component_id: pa.string().optional(), x: kC, y: kC, layers: pa.array(rM), is_board_pinout: pa.boolean().optional() }).describe("Defines a port on the PCB");
var uN = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("circle"), pcb_smtpad_id: WC("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: kC, y: kC, radius: pa.number(), layer: rM, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var pN = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("rect"), pcb_smtpad_id: WC("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: kC, y: kC, width: pa.number(), height: pa.number(), rect_border_radius: pa.number().optional(), corner_radius: pa.number().optional(), layer: rM, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional(), soldermask_margin_left: pa.number().optional(), soldermask_margin_top: pa.number().optional(), soldermask_margin_right: pa.number().optional(), soldermask_margin_bottom: pa.number().optional() });
var mN = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("rotated_rect"), pcb_smtpad_id: WC("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: kC, y: kC, width: pa.number(), height: pa.number(), rect_border_radius: pa.number().optional(), corner_radius: pa.number().optional(), ccw_rotation: FC, layer: rM, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional(), soldermask_margin_left: pa.number().optional(), soldermask_margin_top: pa.number().optional(), soldermask_margin_right: pa.number().optional(), soldermask_margin_bottom: pa.number().optional() });
var gN = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("pill"), pcb_smtpad_id: WC("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: kC, y: kC, width: pa.number(), height: pa.number(), radius: pa.number(), layer: rM, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var fN = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("rotated_pill"), pcb_smtpad_id: WC("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: kC, y: kC, width: pa.number(), height: pa.number(), radius: pa.number(), ccw_rotation: FC, layer: rM, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var yN = pa.object({ type: pa.literal("pcb_smtpad"), shape: pa.literal("polygon"), pcb_smtpad_id: WC("pcb_smtpad"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), points: pa.array($C), layer: rM, port_hints: pa.array(pa.string()).optional(), pcb_component_id: pa.string().optional(), pcb_port_id: pa.string().optional(), is_covered_with_solder_mask: pa.boolean().optional(), soldermask_margin: pa.number().optional() });
var _N = pa.discriminatedUnion("shape", [uN, pN, mN, fN, gN, yN]).describe("Defines an SMT pad on the PCB");
var bN = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("circle"), pcb_solder_paste_id: WC("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: kC, y: kC, radius: pa.number(), layer: rM, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var xN = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("rect"), pcb_solder_paste_id: WC("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: kC, y: kC, width: pa.number(), height: pa.number(), layer: rM, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var vN = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("pill"), pcb_solder_paste_id: WC("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: kC, y: kC, width: pa.number(), height: pa.number(), radius: pa.number(), layer: rM, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var IN = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("rotated_rect"), pcb_solder_paste_id: WC("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: kC, y: kC, width: pa.number(), height: pa.number(), ccw_rotation: kC, layer: rM, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var SN = pa.object({ type: pa.literal("pcb_solder_paste"), shape: pa.literal("oval"), pcb_solder_paste_id: WC("pcb_solder_paste"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), x: kC, y: kC, width: pa.number(), height: pa.number(), layer: rM, pcb_component_id: pa.string().optional(), pcb_smtpad_id: pa.string().optional() });
var CN = pa.union([bN, xN, vN, IN, SN]).describe("Defines solderpaste on the PCB");
var PN = pa.object({ type: pa.literal("pcb_text"), pcb_text_id: WC("pcb_text"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), text: pa.string(), center: $C, layer: rM, width: AC, height: AC, lines: pa.number(), align: pa.enum(["bottom-left"]) }).describe("Defines text on the PCB");
var MN = pa.object({ route_type: pa.literal("wire"), x: kC, y: kC, width: kC, copper_pour_id: pa.string().optional(), is_inside_copper_pour: pa.boolean().optional(), start_pcb_port_id: pa.string().optional(), end_pcb_port_id: pa.string().optional(), layer: rM });
var NN = pa.object({ route_type: pa.literal("via"), x: kC, y: kC, copper_pour_id: pa.string().optional(), is_inside_copper_pour: pa.boolean().optional(), hole_diameter: kC.optional(), outer_diameter: kC.optional(), from_layer: rM, to_layer: rM });
var wN = pa.union([MN, NN]);
var TN = pa.object({ type: pa.literal("pcb_trace"), source_trace_id: pa.string().optional(), pcb_component_id: pa.string().optional(), pcb_trace_id: WC("pcb_trace"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), route_thickness_mode: pa.enum(["constant", "interpolated"]).default("constant").optional(), route_order_index: pa.number().optional(), should_round_corners: pa.boolean().optional(), trace_length: pa.number().optional(), highlight_color: pa.string().optional(), route: pa.array(wN) }).describe("Defines a trace on the PCB");
var RN = pa.object({ type: pa.literal("pcb_trace_warning"), pcb_trace_warning_id: WC("pcb_trace_warning"), warning_type: pa.literal("pcb_trace_warning").default("pcb_trace_warning"), message: pa.string(), center: $C.optional(), pcb_trace_id: pa.string(), source_trace_id: pa.string(), pcb_component_ids: pa.array(pa.string()), pcb_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines a trace warning on the PCB");
var EN = cP.extend({ type: pa.literal("pcb_trace_error"), pcb_trace_error_id: WC("pcb_trace_error"), error_type: pa.literal("pcb_trace_error").default("pcb_trace_error"), center: $C.optional(), pcb_trace_id: pa.string(), source_trace_id: pa.string(), pcb_component_ids: pa.array(pa.string()), pcb_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines a trace error on the PCB");
var AN = cP.extend({ type: pa.literal("pcb_trace_missing_error"), pcb_trace_missing_error_id: WC("pcb_trace_missing_error"), error_type: pa.literal("pcb_trace_missing_error").default("pcb_trace_missing_error"), center: $C.optional(), source_trace_id: pa.string(), pcb_component_ids: pa.array(pa.string()), pcb_port_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines an error when a source trace has no corresponding PCB trace");
var ON = cP.extend({ type: pa.literal("pcb_port_not_matched_error"), pcb_error_id: WC("pcb_error"), error_type: pa.literal("pcb_port_not_matched_error").default("pcb_port_not_matched_error"), pcb_component_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines a trace error on the PCB where a port is not matched");
var kN = cP.extend({ type: pa.literal("pcb_port_not_connected_error"), pcb_port_not_connected_error_id: WC("pcb_port_not_connected_error"), error_type: pa.literal("pcb_port_not_connected_error").default("pcb_port_not_connected_error"), pcb_port_ids: pa.array(pa.string()), pcb_component_ids: pa.array(pa.string()), subcircuit_id: pa.string().optional() }).describe("Defines an error when a pcb port is not connected to any trace");
var DN = pa.object({ type: pa.literal("pcb_net"), pcb_net_id: WC("pcb_net"), source_net_id: pa.string().optional(), highlight_color: pa.string().optional() }).describe("Defines a net on the PCB");
var LN = pa.object({ type: pa.literal("pcb_via"), pcb_via_id: WC("pcb_via"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional(), x: kC, y: kC, outer_diameter: kC.default("0.6mm"), hole_diameter: kC.default("0.25mm"), from_layer: rM.optional(), to_layer: rM.optional(), layers: pa.array(rM), pcb_trace_id: pa.string().optional(), net_is_assignable: pa.boolean().optional(), net_assigned: pa.boolean().optional(), is_tented: pa.boolean().optional() }).describe("Defines a via on the PCB");
var zN = pa.object({ type: pa.literal("pcb_board"), pcb_board_id: WC("pcb_board"), pcb_panel_id: pa.string().optional(), carrier_pcb_board_id: pa.string().optional(), is_subcircuit: pa.boolean().optional(), subcircuit_id: pa.string().optional(), is_mounted_to_carrier_board: pa.boolean().optional(), width: AC.optional(), height: AC.optional(), center: $C, display_offset_x: pa.string().optional().describe("How to display the x offset for this board, usually corresponding with how the user specified it"), display_offset_y: pa.string().optional().describe("How to display the y offset for this board, usually corresponding with how the user specified it"), thickness: AC.optional().default(1.4), num_layers: pa.number().optional().default(4), outline: pa.array($C).optional(), shape: pa.enum(["rect", "polygon"]).optional(), material: pa.enum(["fr4", "fr1"]).default("fr4"), anchor_position: $C.optional(), anchor_alignment: VC.optional(), position_mode: pa.enum(["relative_to_panel_anchor", "none"]).optional() }).merge(ZM).describe("Defines the board outline of the PCB");
var BN = pa.object({ type: pa.literal("pcb_panel"), pcb_panel_id: WC("pcb_panel"), width: AC, height: AC, center: $C, thickness: AC.optional().default(1.4), covered_with_solder_mask: pa.boolean().optional().default(true) }).describe("Defines a PCB panel that can contain multiple boards");
var FN = cP.extend({ type: pa.literal("pcb_placement_error"), pcb_placement_error_id: WC("pcb_placement_error"), error_type: pa.literal("pcb_placement_error").default("pcb_placement_error"), subcircuit_id: pa.string().optional() }).describe("Defines a placement error on the PCB");
var jN = cP.extend({ type: pa.literal("pcb_panelization_placement_error"), pcb_panelization_placement_error_id: WC("pcb_panelization_placement_error"), error_type: pa.literal("pcb_panelization_placement_error").default("pcb_panelization_placement_error"), pcb_panel_id: pa.string().optional(), pcb_board_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Defines a panelization placement error on the PCB");
var $N = pa.object({ type: pa.literal("pcb_trace_hint"), pcb_trace_hint_id: WC("pcb_trace_hint"), pcb_port_id: pa.string(), pcb_component_id: pa.string(), route: pa.array(UM), subcircuit_id: pa.string().optional() }).describe("A hint that can be used during generation of a PCB trace");
var YN = pa.object({ type: pa.literal("pcb_silkscreen_line"), pcb_silkscreen_line_id: WC("pcb_silkscreen_line"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), stroke_width: kC.default("0.1mm"), x1: kC, y1: kC, x2: kC, y2: kC, layer: sM }).describe("Defines a silkscreen line on the PCB");
var XN = pa.object({ type: pa.literal("pcb_silkscreen_path"), pcb_silkscreen_path_id: WC("pcb_silkscreen_path"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: sM, route: pa.array($C), stroke_width: AC }).describe("Defines a silkscreen path on the PCB");
var WN = pa.object({ type: pa.literal("pcb_silkscreen_text"), pcb_silkscreen_text_id: WC("pcb_silkscreen_text"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: kC.default("0.2mm"), pcb_component_id: pa.string(), text: pa.string(), is_knockout: pa.boolean().default(false).optional(), knockout_padding: pa.object({ left: AC, top: AC, bottom: AC, right: AC }).default({ left: "0.2mm", top: "0.2mm", bottom: "0.2mm", right: "0.2mm" }).optional(), ccw_rotation: pa.number().optional(), layer: rM, is_mirrored: pa.boolean().default(false).optional(), anchor_position: $C.default({ x: 0, y: 0 }), anchor_alignment: VC.default("center") }).describe("Defines silkscreen text on the PCB");
var VN = pa.object({ type: pa.literal("pcb_copper_text"), pcb_copper_text_id: WC("pcb_copper_text"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: kC.default("0.2mm"), pcb_component_id: pa.string(), text: pa.string(), is_knockout: pa.boolean().default(false).optional(), knockout_padding: pa.object({ left: AC, top: AC, bottom: AC, right: AC }).default({ left: "0.2mm", top: "0.2mm", bottom: "0.2mm", right: "0.2mm" }).optional(), ccw_rotation: pa.number().optional(), layer: rM, is_mirrored: pa.boolean().default(false).optional(), anchor_position: $C.default({ x: 0, y: 0 }), anchor_alignment: VC.default("center") }).describe("Defines copper text on the PCB");
var HN = pa.object({ type: pa.literal("pcb_silkscreen_rect"), pcb_silkscreen_rect_id: WC("pcb_silkscreen_rect"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: $C, width: AC, height: AC, layer: rM, stroke_width: AC.default("1mm"), corner_radius: AC.optional(), is_filled: pa.boolean().default(true).optional(), has_stroke: pa.boolean().optional(), is_stroke_dashed: pa.boolean().optional(), ccw_rotation: pa.number().optional() }).describe("Defines a silkscreen rect on the PCB");
var GN = pa.object({ type: pa.literal("pcb_silkscreen_circle"), pcb_silkscreen_circle_id: WC("pcb_silkscreen_circle"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: $C, radius: AC, layer: sM, stroke_width: AC.default("1mm"), is_filled: pa.boolean().optional() }).describe("Defines a silkscreen circle on the PCB");
var UN = pa.object({ type: pa.literal("pcb_silkscreen_oval"), pcb_silkscreen_oval_id: WC("pcb_silkscreen_oval"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: $C, radius_x: kC, radius_y: kC, layer: sM, ccw_rotation: FC.optional() }).describe("Defines a silkscreen oval on the PCB");
var ZN = pa.object({ type: pa.literal("pcb_silkscreen_pill"), pcb_silkscreen_pill_id: WC("pcb_silkscreen_pill"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: $C, width: AC, height: AC, layer: rM, ccw_rotation: pa.number().optional() }).describe("Defines a silkscreen pill on the PCB");
var qN = pa.object({ type: pa.literal("pcb_fabrication_note_text"), pcb_fabrication_note_text_id: WC("pcb_fabrication_note_text"), subcircuit_id: pa.string().optional(), pcb_group_id: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: kC.default("1mm"), pcb_component_id: pa.string(), text: pa.string(), layer: sM, anchor_position: $C.default({ x: 0, y: 0 }), anchor_alignment: pa.enum(["center", "top_left", "top_right", "bottom_left", "bottom_right"]).default("center"), color: pa.string().optional() }).describe("Defines a fabrication note in text on the PCB, useful for leaving notes for assemblers or fabricators");
var JN = pa.object({ type: pa.literal("pcb_fabrication_note_path"), pcb_fabrication_note_path_id: WC("pcb_fabrication_note_path"), pcb_component_id: pa.string(), subcircuit_id: pa.string().optional(), layer: rM, route: pa.array($C), stroke_width: AC, color: pa.string().optional() }).describe("Defines a fabrication path on the PCB for fabricators or assemblers");
var QN = pa.object({ type: pa.literal("pcb_fabrication_note_rect"), pcb_fabrication_note_rect_id: WC("pcb_fabrication_note_rect"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: $C, width: AC, height: AC, layer: sM, stroke_width: AC.default("0.1mm"), corner_radius: AC.optional(), is_filled: pa.boolean().optional(), has_stroke: pa.boolean().optional(), is_stroke_dashed: pa.boolean().optional(), color: pa.string().optional() }).describe("Defines a fabrication note rectangle on the PCB");
var KN = pa.object({ type: pa.literal("pcb_fabrication_note_dimension"), pcb_fabrication_note_dimension_id: WC("pcb_fabrication_note_dimension"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: sM, from: $C, to: $C, text: pa.string().optional(), text_ccw_rotation: pa.number().optional(), offset: AC.optional(), offset_distance: AC.optional(), offset_direction: pa.object({ x: pa.number(), y: pa.number() }).optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: AC.default("1mm"), color: pa.string().optional(), arrow_size: AC.default("1mm") }).describe("Defines a measurement annotation within PCB fabrication notes");
var tw = pa.object({ type: pa.literal("pcb_note_text"), pcb_note_text_id: WC("pcb_note_text"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: kC.default("1mm"), text: pa.string().optional(), anchor_position: $C.default({ x: 0, y: 0 }), anchor_alignment: pa.enum(["center", "top_left", "top_right", "bottom_left", "bottom_right"]).default("center"), layer: sM.default("top"), is_mirrored_from_top_view: pa.boolean().optional(), color: pa.string().optional() }).describe("Defines a documentation note in text on the PCB");
var ew = pa.object({ type: pa.literal("pcb_note_rect"), pcb_note_rect_id: WC("pcb_note_rect"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), text: pa.string().optional(), center: $C, width: AC, height: AC, layer: sM.default("top"), stroke_width: AC.default("0.1mm"), corner_radius: AC.optional(), is_filled: pa.boolean().optional(), has_stroke: pa.boolean().optional(), is_stroke_dashed: pa.boolean().optional(), color: pa.string().optional() }).describe("Defines a rectangular documentation note on the PCB");
var nw = pa.object({ type: pa.literal("pcb_note_path"), pcb_note_path_id: WC("pcb_note_path"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), text: pa.string().optional(), route: pa.array($C), layer: sM.default("top"), stroke_width: AC.default("0.1mm"), color: pa.string().optional() }).describe("Defines a polyline documentation note on the PCB");
var ow = pa.object({ type: pa.literal("pcb_note_line"), pcb_note_line_id: WC("pcb_note_line"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), text: pa.string().optional(), x1: kC, y1: kC, x2: kC, y2: kC, layer: sM.default("top"), stroke_width: kC.default("0.1mm"), color: pa.string().optional(), is_dashed: pa.boolean().optional() }).describe("Defines a straight documentation note line on the PCB");
var iw = pa.object({ type: pa.literal("pcb_note_dimension"), pcb_note_dimension_id: WC("pcb_note_dimension"), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), name: pa.string().optional(), from: $C, to: $C, text: pa.string().optional(), text_ccw_rotation: pa.number().optional(), offset_distance: AC.optional(), offset_direction: pa.object({ x: pa.number(), y: pa.number() }).optional(), font: pa.literal("tscircuit2024").default("tscircuit2024"), font_size: AC.default("1mm"), layer: sM.default("top"), color: pa.string().optional(), arrow_size: AC.default("1mm") }).describe("Defines a measurement annotation within PCB documentation notes");
var rw = cP.extend({ type: pa.literal("pcb_footprint_overlap_error"), pcb_error_id: WC("pcb_error"), error_type: pa.literal("pcb_footprint_overlap_error").default("pcb_footprint_overlap_error"), pcb_smtpad_ids: pa.array(pa.string()).optional(), pcb_plated_hole_ids: pa.array(pa.string()).optional(), pcb_hole_ids: pa.array(pa.string()).optional(), pcb_keepout_ids: pa.array(pa.string()).optional() }).describe("Error emitted when a pcb footprint overlaps with another element");
var sw = cP.extend({ type: pa.literal("pcb_courtyard_overlap_error"), pcb_error_id: WC("pcb_error"), error_type: pa.literal("pcb_courtyard_overlap_error").default("pcb_courtyard_overlap_error"), pcb_component_ids: pa.tuple([pa.string(), pa.string()]) }).describe("Error emitted when the courtyard (CrtYd) of one PCB component overlaps with the courtyard of another");
var aw = pa.object({ type: pa.literal("pcb_keepout"), shape: pa.literal("rect"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: $C, width: kC, height: kC, pcb_keepout_id: pa.string(), layers: pa.array(pa.string()), description: pa.string().optional() }).or(pa.object({ type: pa.literal("pcb_keepout"), shape: pa.literal("circle"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: $C, radius: kC, pcb_keepout_id: pa.string(), layers: pa.array(pa.string()), description: pa.string().optional() }));
var cw = pa.object({ type: pa.literal("pcb_cutout"), pcb_cutout_id: WC("pcb_cutout"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), pcb_board_id: pa.string().optional(), pcb_panel_id: pa.string().optional() });
var lw = cw.extend({ shape: pa.literal("rect"), center: $C, width: AC, height: AC, rotation: FC.optional(), corner_radius: AC.optional() });
var hw = cw.extend({ shape: pa.literal("circle"), center: $C, radius: AC });
var dw = cw.extend({ shape: pa.literal("polygon"), points: pa.array($C) });
var uw = cw.extend({ shape: pa.literal("path"), route: pa.array($C), slot_width: AC, slot_length: AC.optional(), space_between_slots: AC.optional(), slot_corner_radius: AC.optional() });
var pw = pa.discriminatedUnion("shape", [lw, hw, dw, uw]).describe("Defines a cutout on the PCB, removing board material.");
var mw = cP.extend({ type: pa.literal("pcb_missing_footprint_error"), pcb_missing_footprint_error_id: WC("pcb_missing_footprint_error"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), error_type: pa.literal("pcb_missing_footprint_error").default("pcb_missing_footprint_error"), source_component_id: pa.string() }).describe("Defines a missing footprint error on the PCB");
var gw = cP.extend({ type: pa.literal("external_footprint_load_error"), external_footprint_load_error_id: WC("external_footprint_load_error"), pcb_component_id: pa.string(), source_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), footprinter_string: pa.string().optional(), error_type: pa.literal("external_footprint_load_error").default("external_footprint_load_error") }).describe("Defines an error when an external footprint fails to load");
var fw = cP.extend({ type: pa.literal("circuit_json_footprint_load_error"), circuit_json_footprint_load_error_id: WC("circuit_json_footprint_load_error"), pcb_component_id: pa.string(), source_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), error_type: pa.literal("circuit_json_footprint_load_error").default("circuit_json_footprint_load_error"), circuit_json: pa.array(pa.any()).optional() }).describe("Defines an error when a circuit JSON footprint fails to load");
var yw = pa.object({ type: pa.literal("pcb_group"), pcb_group_id: WC("pcb_group"), source_group_id: pa.string(), is_subcircuit: pa.boolean().optional(), subcircuit_id: pa.string().optional(), width: AC.optional(), height: AC.optional(), center: $C, display_offset_x: pa.string().optional().describe("How to display the x offset for this group, usually corresponding with how the user specified it"), display_offset_y: pa.string().optional().describe("How to display the y offset for this group, usually corresponding with how the user specified it"), outline: pa.array($C).optional(), anchor_position: $C.optional(), anchor_alignment: VC.default("center"), position_mode: pa.enum(["packed", "relative_to_group_anchor", "none"]).optional(), positioned_relative_to_pcb_group_id: pa.string().optional(), positioned_relative_to_pcb_board_id: pa.string().optional(), pcb_component_ids: pa.array(pa.string()), child_layout_mode: pa.enum(["packed", "none"]).optional(), name: pa.string().optional(), description: pa.string().optional(), layout_mode: pa.string().optional(), autorouter_configuration: pa.object({ trace_clearance: AC }).optional(), autorouter_used_string: pa.string().optional() }).describe("Defines a group of components on the PCB");
var _w = cP.extend({ type: pa.literal("pcb_autorouting_error"), pcb_error_id: WC("pcb_autorouting_error"), error_type: pa.literal("pcb_autorouting_error").default("pcb_autorouting_error"), subcircuit_id: pa.string().optional() }).describe("The autorouting has failed to route a portion of the board");
var bw = pa.object({ type: pa.literal("pcb_manual_edit_conflict_warning"), pcb_manual_edit_conflict_warning_id: WC("pcb_manual_edit_conflict_warning"), warning_type: pa.literal("pcb_manual_edit_conflict_warning").default("pcb_manual_edit_conflict_warning"), message: pa.string(), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), source_component_id: pa.string() }).describe("Warning emitted when a component has both manual placement and explicit pcbX/pcbY coordinates");
var xw = pa.enum(["x-", "x+", "y+", "y-"]);
var vw = pa.object({ type: pa.literal("pcb_connector_not_in_accessible_orientation_warning"), pcb_connector_not_in_accessible_orientation_warning_id: WC("pcb_connector_not_in_accessible_orientation_warning"), warning_type: pa.literal("pcb_connector_not_in_accessible_orientation_warning").default("pcb_connector_not_in_accessible_orientation_warning"), message: pa.string(), pcb_component_id: pa.string(), source_component_id: pa.string().optional(), pcb_board_id: pa.string().optional(), facing_direction: xw, recommended_facing_direction: xw, subcircuit_id: pa.string().optional() }).describe("Warning emitted when a connector PCB component is facing inward toward the board and should be reoriented to an outward-facing direction");
var Iw = pa.object({ type: pa.literal("supplier_footprint_mismatch_warning"), supplier_footprint_mismatch_warning_id: WC("supplier_footprint_mismatch_warning"), warning_type: pa.literal("supplier_footprint_mismatch_warning").default("supplier_footprint_mismatch_warning"), message: pa.string(), source_component_id: pa.string(), pcb_component_id: pa.string().optional(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), supplier_name: lP.optional(), supplier_part_number: pa.string().optional(), supplier_footprint_url: pa.string().optional(), footprint_copper_intersection_over_union: pa.number() }).describe("Warning emitted when a supplier part footprint does not match the expected footprint");
var Sw = pa.object({ type: pa.literal("pcb_breakout_point"), pcb_breakout_point_id: WC("pcb_breakout_point"), pcb_group_id: pa.string(), subcircuit_id: pa.string().optional(), source_trace_id: pa.string().optional(), source_port_id: pa.string().optional(), source_net_id: pa.string().optional(), x: kC, y: kC }).describe("Defines a routing target within a pcb_group for a source_trace or source_net");
var Cw = pa.object({ type: pa.literal("pcb_ground_plane"), pcb_ground_plane_id: WC("pcb_ground_plane"), source_pcb_ground_plane_id: pa.string(), source_net_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Defines a ground plane on the PCB");
var Pw = pa.object({ type: pa.literal("pcb_ground_plane_region"), pcb_ground_plane_region_id: WC("pcb_ground_plane_region"), pcb_ground_plane_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: rM, points: pa.array($C) }).describe("Defines a polygon region of a ground plane");
var Mw = pa.object({ type: pa.literal("pcb_thermal_spoke"), pcb_thermal_spoke_id: WC("pcb_thermal_spoke"), pcb_ground_plane_id: pa.string(), shape: pa.string(), spoke_count: pa.number(), spoke_thickness: kC, spoke_inner_diameter: kC, spoke_outer_diameter: kC, pcb_plated_hole_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Pattern for connecting a ground plane to a plated hole");
var Nw = pa.object({ type: pa.literal("pcb_copper_pour"), pcb_copper_pour_id: WC("pcb_copper_pour"), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: rM, source_net_id: pa.string().optional(), covered_with_solder_mask: pa.boolean().optional().default(true) });
var ww = Nw.extend({ shape: pa.literal("rect"), center: $C, width: AC, height: AC, rotation: FC.optional() });
var Tw = Nw.extend({ shape: pa.literal("brep"), brep_shape: HM });
var Rw = Nw.extend({ shape: pa.literal("polygon"), points: pa.array($C) });
var Ew = pa.discriminatedUnion("shape", [ww, Tw, Rw]).describe("Defines a copper pour on the PCB.");
var Aw = cP.extend({ type: pa.literal("pcb_component_outside_board_error"), pcb_component_outside_board_error_id: WC("pcb_component_outside_board_error"), error_type: pa.literal("pcb_component_outside_board_error").default("pcb_component_outside_board_error"), pcb_component_id: pa.string(), pcb_board_id: pa.string(), component_center: $C, component_bounds: pa.object({ min_x: pa.number(), max_x: pa.number(), min_y: pa.number(), max_y: pa.number() }), subcircuit_id: pa.string().optional(), source_component_id: pa.string().optional() }).describe("Error emitted when a PCB component is placed outside the board boundaries");
var Ow = cP.extend({ type: pa.literal("pcb_component_not_on_board_edge_error"), pcb_component_not_on_board_edge_error_id: WC("pcb_component_not_on_board_edge_error"), error_type: pa.literal("pcb_component_not_on_board_edge_error").default("pcb_component_not_on_board_edge_error"), pcb_component_id: pa.string(), pcb_board_id: pa.string(), component_center: $C, pad_to_nearest_board_edge_distance: pa.number(), source_component_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a component that must be placed on the board edge is centered away from the edge");
var kw = cP.extend({ type: pa.literal("pcb_component_invalid_layer_error"), pcb_component_invalid_layer_error_id: WC("pcb_component_invalid_layer_error"), error_type: pa.literal("pcb_component_invalid_layer_error").default("pcb_component_invalid_layer_error"), pcb_component_id: pa.string().optional(), source_component_id: pa.string(), layer: rM, subcircuit_id: pa.string().optional() }).describe("Error emitted when a component is placed on an invalid layer (components can only be on 'top' or 'bottom' layers)");
var Dw = cP.extend({ type: pa.literal("pcb_via_clearance_error"), pcb_error_id: WC("pcb_error"), error_type: pa.literal("pcb_via_clearance_error").default("pcb_via_clearance_error"), pcb_via_ids: pa.array(pa.string()).min(2), minimum_clearance: kC.optional(), actual_clearance: kC.optional(), pcb_center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when vias are closer than the allowed clearance");
var Lw = cP.extend({ type: pa.literal("pcb_via_trace_clearance_error"), pcb_via_trace_clearance_error_id: WC("pcb_via_trace_clearance_error"), error_type: pa.literal("pcb_via_trace_clearance_error").default("pcb_via_trace_clearance_error"), pcb_via_id: pa.string(), pcb_trace_id: pa.string(), minimum_clearance: kC.optional(), actual_clearance: kC.optional(), center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a via and trace are closer than the allowed clearance");
var zw = cP.extend({ type: pa.literal("pcb_pad_pad_clearance_error"), pcb_pad_pad_clearance_error_id: WC("pcb_pad_pad_clearance_error"), error_type: pa.literal("pcb_pad_pad_clearance_error").default("pcb_pad_pad_clearance_error"), pcb_pad_ids: pa.array(pa.string()).min(2), minimum_clearance: kC.optional(), actual_clearance: kC.optional(), center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when pads are closer than the allowed clearance");
var Bw = cP.extend({ type: pa.literal("pcb_pad_trace_clearance_error"), pcb_pad_trace_clearance_error_id: WC("pcb_pad_trace_clearance_error"), error_type: pa.literal("pcb_pad_trace_clearance_error").default("pcb_pad_trace_clearance_error"), pcb_pad_id: pa.string(), pcb_trace_id: pa.string(), minimum_clearance: kC.optional(), actual_clearance: kC.optional(), center: pa.object({ x: pa.number().optional(), y: pa.number().optional() }).optional(), subcircuit_id: pa.string().optional() }).describe("Error emitted when a pad and trace are closer than allowed clearance");
var Fw = pa.object({ type: pa.literal("pcb_courtyard_rect"), pcb_courtyard_rect_id: WC("pcb_courtyard_rect"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: $C, width: AC, height: AC, layer: sM, ccw_rotation: FC.optional(), color: pa.string().optional() }).describe("Defines a courtyard rectangle on the PCB");
var jw = pa.object({ type: pa.literal("pcb_courtyard_outline"), pcb_courtyard_outline_id: WC("pcb_courtyard_outline"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: sM, outline: pa.array($C).min(2) }).describe("Defines a courtyard outline on the PCB");
var $w = pa.object({ type: pa.literal("pcb_courtyard_polygon"), pcb_courtyard_polygon_id: WC("pcb_courtyard_polygon"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), layer: sM, points: pa.array($C).min(3), color: pa.string().optional() }).describe("Defines a courtyard polygon on the PCB");
var Yw = pa.object({ type: pa.literal("pcb_courtyard_circle"), pcb_courtyard_circle_id: WC("pcb_courtyard_circle"), pcb_component_id: pa.string(), pcb_group_id: pa.string().optional(), subcircuit_id: pa.string().optional(), center: $C, radius: AC, layer: sM, color: pa.string().optional() }).describe("Defines a courtyard circle on the PCB");
var Xw = pa.object({ type: pa.literal("cad_component"), cad_component_id: pa.string(), pcb_component_id: pa.string(), source_component_id: pa.string(), position: YC, rotation: YC.optional(), size: YC.optional(), layer: rM.optional(), subcircuit_id: pa.string().optional(), footprinter_string: pa.string().optional(), model_obj_url: pa.string().optional(), model_stl_url: pa.string().optional(), model_3mf_url: pa.string().optional(), model_gltf_url: pa.string().optional(), model_glb_url: pa.string().optional(), model_step_url: pa.string().optional(), model_wrl_url: pa.string().optional(), model_asset: HC.optional(), model_unit_to_mm_scale_factor: pa.number().optional(), model_board_normal_direction: pa.enum(["x+", "x-", "y+", "y-", "z+", "z-"]).optional().describe(`The direction in the model's coordinate space that is considered "up" or "coming out of the board surface"`), model_origin_position: YC.optional(), model_origin_alignment: pa.enum(["unknown", "center", "center_of_component_on_board_surface", "bottom_center_of_component"]).optional(), model_object_fit: pa.enum(["contain_within_bounds", "fill_bounds"]).optional().default("contain_within_bounds"), model_jscad: pa.any().optional(), show_as_translucent_model: pa.boolean().optional(), anchor_alignment: pa.enum(["center", "center_of_component_on_board_surface"]).optional().default("center") }).describe("Defines a component on the PCB");
var Ww = pa.enum(["sinewave", "square", "triangle", "sawtooth"]);
var Vw = pa.union([pa.string(), pa.number()]).transform((t33) => typeof t33 == "string" ? t33.endsWith("%") ? parseFloat(t33.slice(0, -1)) / 100 : parseFloat(t33) : t33).pipe(pa.number().min(0, "Duty cycle must be non-negative").max(1, "Duty cycle cannot be greater than 100%"));
var Hw = pa.object({ type: pa.literal("simulation_voltage_source"), simulation_voltage_source_id: WC("simulation_voltage_source"), is_dc_source: pa.literal(true).optional().default(true), positive_source_port_id: pa.string().optional(), negative_source_port_id: pa.string().optional(), positive_source_net_id: pa.string().optional(), negative_source_net_id: pa.string().optional(), voltage: EC }).describe("Defines a DC voltage source for simulation");
var Gw = pa.object({ type: pa.literal("simulation_voltage_source"), simulation_voltage_source_id: WC("simulation_voltage_source"), is_dc_source: pa.literal(false), terminal1_source_port_id: pa.string().optional(), terminal2_source_port_id: pa.string().optional(), terminal1_source_net_id: pa.string().optional(), terminal2_source_net_id: pa.string().optional(), voltage: EC.optional(), frequency: OC.optional(), peak_to_peak_voltage: EC.optional(), wave_shape: Ww.optional(), phase: FC.optional(), duty_cycle: Vw.optional() }).describe("Defines an AC voltage source for simulation");
var Uw = pa.union([Hw, Gw]).describe("Defines a voltage source for simulation");
var Zw = pa.union([pa.string(), pa.number()]).transform((t33) => typeof t33 == "string" ? t33.endsWith("%") ? parseFloat(t33.slice(0, -1)) / 100 : parseFloat(t33) : t33).pipe(pa.number().min(0, "Duty cycle must be non-negative").max(1, "Duty cycle cannot be greater than 100%"));
var qw = pa.object({ type: pa.literal("simulation_current_source"), simulation_current_source_id: WC("simulation_current_source"), is_dc_source: pa.literal(true).optional().default(true), positive_source_port_id: pa.string().optional(), negative_source_port_id: pa.string().optional(), positive_source_net_id: pa.string().optional(), negative_source_net_id: pa.string().optional(), current: DC }).describe("Defines a DC current source for simulation");
var Jw = pa.object({ type: pa.literal("simulation_current_source"), simulation_current_source_id: WC("simulation_current_source"), is_dc_source: pa.literal(false), terminal1_source_port_id: pa.string().optional(), terminal2_source_port_id: pa.string().optional(), terminal1_source_net_id: pa.string().optional(), terminal2_source_net_id: pa.string().optional(), current: DC.optional(), frequency: OC.optional(), peak_to_peak_current: DC.optional(), wave_shape: Ww.optional(), phase: FC.optional(), duty_cycle: Zw.optional() }).describe("Defines an AC current source for simulation");
var Qw = pa.union([qw, Jw]).describe("Defines a current source for simulation");
var Kw = pa.union([pa.literal("spice_dc_sweep"), pa.literal("spice_dc_operating_point"), pa.literal("spice_transient_analysis"), pa.literal("spice_ac_analysis")]);
var tT = pa.object({ type: pa.literal("simulation_experiment"), simulation_experiment_id: WC("simulation_experiment"), name: pa.string(), experiment_type: Kw, time_per_step: LC.optional(), start_time_ms: zC.optional(), end_time_ms: zC.optional() }).describe("Defines a simulation experiment configuration");
var eT = pa.object({ type: pa.literal("simulation_transient_voltage_graph"), simulation_transient_voltage_graph_id: WC("simulation_transient_voltage_graph"), simulation_experiment_id: pa.string(), timestamps_ms: pa.array(pa.number()).optional(), voltage_levels: pa.array(pa.number()), source_component_id: pa.string().optional(), subcircuit_connectivity_map_key: pa.string().optional(), time_per_step: LC, start_time_ms: zC, end_time_ms: zC, name: pa.string().optional(), color: pa.string().optional() }).describe("Stores voltage measurements over time for a simulation");
var nT = pa.object({ type: pa.literal("simulation_switch"), simulation_switch_id: WC("simulation_switch"), source_component_id: pa.string().optional(), closes_at: zC.optional(), opens_at: zC.optional(), starts_closed: pa.boolean().optional(), switching_frequency: OC.optional() }).describe("Defines a switch for simulation timing control");
var oT = pa.object({ type: pa.literal("simulation_voltage_probe"), simulation_voltage_probe_id: WC("simulation_voltage_probe"), source_component_id: pa.string().optional(), name: pa.string().optional(), signal_input_source_port_id: pa.string().optional(), signal_input_source_net_id: pa.string().optional(), reference_input_source_port_id: pa.string().optional(), reference_input_source_net_id: pa.string().optional(), subcircuit_id: pa.string().optional(), color: pa.string().optional() }).describe("Defines a voltage probe for simulation. If a reference input is not provided, it measures against ground. If a reference input is provided, it measures the differential voltage between two points.").superRefine((t33, e2) => {
if (t33.reference_input_source_port_id || t33.reference_input_source_net_id) {
const n2 = !!t33.signal_input_source_port_id || !!t33.reference_input_source_port_id, o2 = !!t33.signal_input_source_net_id || !!t33.reference_input_source_net_id;
n2 && o2 ? e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Cannot mix port and net connections in a differential probe." }) : n2 ? t33.signal_input_source_port_id && t33.reference_input_source_port_id || e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Differential port probe requires both signal_input_source_port_id and reference_input_source_port_id." }) : o2 && (t33.signal_input_source_net_id && t33.reference_input_source_net_id || e2.addIssue({ code: pa.ZodIssueCode.custom, message: "Differential net probe requires both signal_input_source_net_id and reference_input_source_net_id." }));
} else
!!t33.signal_input_source_port_id == !!t33.signal_input_source_net_id && e2.addIssue({ code: pa.ZodIssueCode.custom, message: "A voltage probe must have exactly one of signal_input_source_port_id or signal_input_source_net_id." });
});
var iT = cP.extend({ type: pa.literal("simulation_unknown_experiment_error"), simulation_unknown_experiment_error_id: WC("simulation_unknown_experiment_error"), error_type: pa.literal("simulation_unknown_experiment_error").default("simulation_unknown_experiment_error"), simulation_experiment_id: pa.string().optional(), subcircuit_id: pa.string().optional() }).describe("An unknown error occurred during the simulation experiment.");
var rT = pa.object({ type: pa.literal("simulation_op_amp"), simulation_op_amp_id: WC("simulation_op_amp"), source_component_id: pa.string().optional(), inverting_input_source_port_id: pa.string(), non_inverting_input_source_port_id: pa.string(), output_source_port_id: pa.string(), positive_supply_source_port_id: pa.string(), negative_supply_source_port_id: pa.string() }).describe("Defines a simple ideal operational amplifier for simulation");
pa.union([JP, ZP, qP, UP, KP, QP, yP, dP, pP, gP, uP, _P, IP, SP, NP, TP, RP, DP, EP, AP, OP, kP, PP, CP, nM, aM, tM, LP, FP, jP, YP, XP, cM, lM, hM, dM, uM, HP, eM, qM, oN, mw, gw, fw, bw, vw, Iw, hN, aw, dN, DN, PN, TN, RN, LN, _N, CN, zN, BN, yw, $N, YN, XN, WN, ZN, VN, HN, GN, UN, EN, AN, FN, jN, ON, kN, Dw, Lw, zw, Bw, JN, qN, QN, KN, tw, ew, nw, ow, iw, _w, rw, sw, Sw, pw, Cw, Pw, Mw, Ew, Aw, Ow, kw, Fw, jw, $w, Yw, pM, wM, IM, SM, CM, PM, bM, vM, TM, MM, mM, EM, AM, RM, zM, BM, FM, jM, XM, $M, YM, Xw, Uw, Qw, tT, eT, nT, oT, iT, rT]);
function sT(t33, e2, n2, o2) {
return Math.sqrt((n2 - t33) ** 2 + (o2 - e2) ** 2);
}
var aT = class {
buckets;
objectsById;
getBounds;
getId;
CELL_SIZE = 0.4;
constructor({ objects: t33, getBounds: e2, getId: n2, CELL_SIZE: o2 }) {
this.buckets = new Map, this.objectsById = new Map, this.getBounds = e2, this.getId = n2 ?? (() => this._getNextId()), this.CELL_SIZE = o2 ?? this.CELL_SIZE;
for (const e3 of t33)
this.addObject(e3);
}
_idCounter = 0;
_getNextId() {
return "" + this._idCounter++;
}
addObject(t33) {
const e2 = this.getBounds(t33), n2 = this.getId(t33), o2 = { ...t33, spatialIndexId: n2 };
this.objectsById.set(n2, o2);
const i2 = Math.floor(e2.minX / this.CELL_SIZE), r2 = Math.floor(e2.minY / this.CELL_SIZE), s2 = Math.floor(e2.maxX / this.CELL_SIZE), a2 = Math.floor(e2.maxY / this.CELL_SIZE);
for (let t34 = i2;t34 <= s2; t34++)
for (let e3 = r2;e3 <= a2; e3++) {
const n3 = `${t34}x${e3}`, i3 = this.buckets.get(n3);
i3 ? i3.push(o2) : this.buckets.set(n3, [o2]);
}
}
removeObject(t33) {
const e2 = this.objectsById.get(t33);
if (!e2)
return false;
this.objectsById.delete(t33);
const n2 = this.getBounds(e2), o2 = Math.floor(n2.minX / this.CELL_SIZE), i2 = Math.floor(n2.minY / this.CELL_SIZE), r2 = Math.floor(n2.maxX / this.CELL_SIZE), s2 = Math.floor(n2.maxY / this.CELL_SIZE);
for (let e3 = o2;e3 <= r2; e3++)
for (let n3 = i2;n3 <= s2; n3++) {
const o3 = `${e3}x${n3}`, i3 = this.buckets.get(o3);
if (i3) {
const e4 = i3.findIndex((e5) => e5.spatialIndexId === t33);
e4 !== -1 && (i3.splice(e4, 1), i3.length === 0 && this.buckets.delete(o3));
}
}
return true;
}
getBucketKey(t33, e2) {
return `${Math.floor(t33 / this.CELL_SIZE)}x${Math.floor(e2 / this.CELL_SIZE)}`;
}
getObjectsInBounds(t33, e2 = 0) {
const n2 = [], o2 = new Set, i2 = Math.floor((t33.minX - e2) / this.CELL_SIZE), r2 = Math.floor((t33.minY - e2) / this.CELL_SIZE), s2 = Math.floor((t33.maxX + e2) / this.CELL_SIZE), a2 = Math.floor((t33.maxY + e2) / this.CELL_SIZE);
for (let t34 = i2;t34 <= s2; t34++)
for (let e3 = r2;e3 <= a2; e3++) {
const i3 = `${t34}x${e3}`, r3 = this.buckets.get(i3) || [];
for (const t35 of r3) {
const e4 = t35.spatialIndexId;
o2.has(e4) || (o2.add(e4), n2.push(t35));
}
}
return n2;
}
};
var cT = 0.1;
var lT = 0.1;
var hT = cT;
var dT = cT;
var uT = 0.005;
function pT(t33) {
return t33.type === "pcb_trace_segment" || t33.type === "pcb_smtpad" ? [t33.layer] : t33.type === "pcb_plated_hole" ? Array.isArray(t33.layers) ? t33.layers : [...oM] : t33.type === "pcb_hole" ? [...oM] : t33.type === "pcb_via" ? Array.isArray(t33.layers) ? t33.layers : [...oM] : t33.type === "pcb_keepout" && Array.isArray(t33.layers) ? t33.layers : [];
}
var mT = (t33, e2) => {
const n2 = { x: t33.x1, y: t33.y1 }, o2 = { x: t33.x2, y: t33.y2 }, i2 = e2.minX, r2 = e2.minY, s2 = e2.maxX, a2 = e2.maxY;
if (n2.x === o2.x && n2.y === o2.y) {
const t34 = Math.max(i2, Math.min(s2, n2.x)), e3 = Math.max(r2, Math.min(a2, n2.y));
return t34 === n2.x && e3 === n2.y ? { x: n2.x, y: n2.y } : { x: t34, y: e3 };
}
const c2 = o2.x - n2.x, l2 = o2.y - n2.y, h2 = c2 !== 0 ? (i2 - n2.x) / c2 : Number.NEGATIVE_INFINITY, d2 = c2 !== 0 ? (s2 - n2.x) / c2 : Number.POSITIVE_INFINITY, u2 = l2 !== 0 ? (r2 - n2.y) / l2 : Number.NEGATIVE_INFINITY, p2 = l2 !== 0 ? (a2 - n2.y) / l2 : Number.POSITIVE_INFINITY, m2 = Math.max(Math.min(h2, d2), Math.min(u2, p2)), g2 = Math.min(Math.max(h2, d2), Math.max(u2, p2));
if (m2 <= g2 && g2 >= 0 && m2 <= 1) {
const t34 = Math.max(0, Math.min(1, m2));
return { x: n2.x + t34 * c2, y: n2.y + t34 * l2 };
}
const f2 = { x: Math.max(i2, Math.min(s2, n2.x)), y: Math.max(r2, Math.min(a2, n2.y)) }, y2 = { x: Math.max(i2, Math.min(s2, o2.x)), y: Math.max(r2, Math.min(a2, o2.y)) }, _2 = (f2.x - n2.x) ** 2 + (f2.y - n2.y) ** 2, b2 = (y2.x - o2.x) ** 2 + (y2.y - o2.y) ** 2, x2 = [{ start: { x: i2, y: r2 }, end: { x: s2, y: r2 } }, { start: { x: s2, y: r2 }, end: { x: s2, y: a2 } }, { start: { x: s2, y: a2 }, end: { x: i2, y: a2 } }, { start: { x: i2, y: a2 }, end: { x: i2, y: r2 } }];
let v2 = Math.min(_2, b2), I2 = _2 <= b2 ? f2 : y2;
const S2 = (t34, e3, n3) => Math.max(e3, Math.min(n3, t34));
for (const t34 of x2) {
const e3 = { x: o2.x - n2.x, y: o2.y - n2.y }, i3 = { x: t34.end.x - t34.start.x, y: t34.end.y - t34.start.y }, r3 = { x: n2.x - t34.start.x, y: n2.y - t34.start.y }, s3 = e3.x * e3.x + e3.y * e3.y, a3 = e3.x * i3.x + e3.y * i3.y, c3 = e3.x * r3.x + e3.y * r3.y, l3 = i3.x * i3.x + i3.y * i3.y, h3 = i3.x * r3.x + i3.y * r3.y, d3 = s3 * l3 - a3 * a3;
if (Math.abs(d3) < 0.0000000001)
continue;
let u3 = (a3 * h3 - l3 * c3) / d3, p3 = (s3 * h3 - a3 * c3) / d3;
u3 = S2(u3, 0, 1), p3 = S2(p3, 0, 1);
const m3 = { x: n2.x + u3 * e3.x, y: n2.y + u3 * e3.y }, g3 = { x: t34.start.x + p3 * i3.x, y: t34.start.y + p3 * i3.y }, f3 = m3.x - g3.x, y3 = m3.y - g3.y, _3 = f3 * f3 + y3 * y3;
_3 < v2 && (v2 = _3, I2 = { x: (m3.x + g3.x) / 2, y: (m3.y + g3.y) / 2 });
}
return I2;
};
var gT = (t33, e2) => {
const n2 = { x: t33.x1, y: t33.y1 }, o2 = { x: t33.x2, y: t33.y2 }, i2 = { x: e2.x1, y: e2.y1 }, r2 = { x: e2.x2, y: e2.y2 }, s2 = { x: o2.x - n2.x, y: o2.y - n2.y }, a2 = { x: r2.x - i2.x, y: r2.y - i2.y }, c2 = s2.x * s2.x + s2.y * s2.y, l2 = a2.x * a2.x + a2.y * a2.y;
if (c2 === 0 || l2 === 0) {
if (c2 === 0 && l2 === 0)
return { x: (n2.x + i2.x) / 2, y: (n2.y + i2.y) / 2 };
if (c2 === 0) {
const t35 = yT(((n2.x - i2.x) * a2.x + (n2.y - i2.y) * a2.y) / l2, 0, 1), e4 = { x: i2.x + t35 * a2.x, y: i2.y + t35 * a2.y };
return { x: (n2.x + e4.x) / 2, y: (n2.y + e4.y) / 2 };
}
const t34 = yT(((i2.x - n2.x) * s2.x + (i2.y - n2.y) * s2.y) / c2, 0, 1), e3 = { x: n2.x + t34 * s2.x, y: n2.y + t34 * s2.y };
return { x: (e3.x + i2.x) / 2, y: (e3.y + i2.y) / 2 };
}
const h2 = n2.x - i2.x, d2 = n2.y - i2.y, u2 = s2.x * s2.x + s2.y * s2.y, p2 = s2.x * a2.x + s2.y * a2.y, m2 = s2.x * h2 + s2.y * d2, g2 = a2.x * a2.x + a2.y * a2.y, f2 = a2.x * h2 + a2.y * d2, y2 = u2 * g2 - p2 * p2;
if (y2 < 0.0000000001)
return fT(n2, o2, i2, r2, s2, a2, c2, l2);
let _2 = (p2 * f2 - g2 * m2) / y2, b2 = (u2 * f2 - p2 * m2) / y2;
_2 = yT(_2, 0, 1), b2 = yT(b2, 0, 1), b2 = (_2 * p2 + f2) / g2, b2 = yT(b2, 0, 1), _2 = (b2 * p2 - m2) / u2, _2 = yT(_2, 0, 1);
const x2 = n2.x + _2 * s2.x, v2 = n2.y + _2 * s2.y, I2 = i2.x + b2 * a2.x, S2 = i2.y + b2 * a2.y;
return { x: (x2 + I2) / 2, y: (v2 + S2) / 2 };
};
var fT = (t33, e2, n2, o2, i2, r2, s2, a2) => {
let c2 = ((n2.x - t33.x) * i2.x + (n2.y - t33.y) * i2.y) / s2;
c2 = yT(c2, 0, 1);
const l2 = { x: t33.x + c2 * i2.x, y: t33.y + c2 * i2.y };
let h2 = ((o2.x - t33.x) * i2.x + (o2.y - t33.y) * i2.y) / s2;
h2 = yT(h2, 0, 1);
const d2 = { x: t33.x + h2 * i2.x, y: t33.y + h2 * i2.y };
let u2 = ((t33.x - n2.x) * r2.x + (t33.y - n2.y) * r2.y) / a2;
u2 = yT(u2, 0, 1);
const p2 = { x: n2.x + u2 * r2.x, y: n2.y + u2 * r2.y };
let m2 = ((e2.x - n2.x) * r2.x + (e2.y - n2.y) * r2.y) / a2;
m2 = yT(m2, 0, 1);
const g2 = { x: n2.x + m2 * r2.x, y: n2.y + m2 * r2.y }, f2 = [{ pointA: l2, pointB: n2, distance: Math.sqrt((l2.x - n2.x) ** 2 + (l2.y - n2.y) ** 2) }, { pointA: d2, pointB: o2, distance: Math.sqrt((d2.x - o2.x) ** 2 + (d2.y - o2.y) ** 2) }, { pointA: t33, pointB: p2, distance: Math.sqrt((t33.x - p2.x) ** 2 + (t33.y - p2.y) ** 2) }, { pointA: e2, pointB: g2, distance: Math.sqrt((e2.x - g2.x) ** 2 + (e2.y - g2.y) ** 2) }].reduce((t34, e3) => e3.distance < t34.distance ? e3 : t34);
return { x: (f2.pointA.x + f2.pointB.x) / 2, y: (f2.pointA.y + f2.pointB.y) / 2 };
};
var yT = (t33, e2, n2) => Math.max(e2, Math.min(n2, t33));
var _T = (t33) => t33.type === "pcb_trace_segment" ? { minX: Math.min(t33.x1, t33.x2), minY: Math.min(t33.y1, t33.y2), maxX: Math.max(t33.x1, t33.x2), maxY: Math.max(t33.y1, t33.y2) } : hg([t33]);
function bT(t33) {
const e2 = new Set;
for (const n2 of t33.route)
n2.route_type === "wire" && (n2.start_pcb_port_id && e2.add(n2.start_pcb_port_id), n2.end_pcb_port_id && e2.add(n2.end_pcb_port_id));
return Array.from(e2);
}
function xT(t33) {
const e2 = new Set;
for (const n2 of t33)
for (const t34 of bT(n2))
e2.add(t34);
return Array.from(e2);
}
var vT = (t33) => {
if (t33.type === "pcb_via")
return t33.outer_diameter / 2;
if (t33.type === "pcb_plated_hole" && t33.shape === "circle")
return t33.outer_diameter / 2;
if (t33.type === "pcb_hole" && t33.hole_shape === "circle")
return t33.hole_diameter / 2;
if (t33.type === "pcb_smtpad" && t33.shape === "circle")
return t33.radius;
throw new Error(`Could not determine radius of element: ${JSON.stringify(t33)}`);
};
function IT(t33, { connMap: e2, minClearance: n2 = 0.1 } = {}) {
const o2 = [];
((t34) => {
const e3 = t34.filter((t35) => t35.type === "pcb_port"), n3 = t34.filter((t35) => t35.type === "pcb_smtpad"), o3 = t34.filter((t35) => t35.type === "pcb_trace");
function i3(t35, o4 = {}) {
const i4 = o4.traceWidth || 0, r3 = e3.find((e4) => sT(e4.x, e4.y, t35.x, t35.y) < 0.01);
if (r3)
return r3.pcb_port_id;
if (o4.isFirstOrLastPoint) {
const e4 = n3.find((e5) => e5.shape === "rect" ? Math.abs(t35.x - e5.x) < e5.width / 2 + i4 / 2 && Math.abs(t35.y - e5.y) < e5.height / 2 + i4 / 2 : e5.shape === "circle" ? sT(t35.x, t35.y, e5.x, e5.y) < e5.radius : undefined);
if (e4)
return e4.pcb_port_id ?? null;
}
return null;
}
for (const t35 of o3)
for (let e4 = 0;e4 < t35.route.length; e4++) {
const n4 = t35.route[e4], o4 = e4 === 0 || e4 === t35.route.length - 1;
if (n4.route_type === "wire") {
if (!n4.start_pcb_port_id && e4 === 0) {
const t36 = i3(n4, { isFirstOrLastPoint: o4, traceWidth: n4.width });
t36 && (n4.start_pcb_port_id = t36);
}
if (!n4.end_pcb_port_id && e4 === t35.route.length - 1) {
const t36 = i3(n4, { isFirstOrLastPoint: o4, traceWidth: n4.width });
t36 && (n4.end_pcb_port_id = t36);
}
}
}
})(t33), e2 ??= SC(t33);
const i2 = tg(t33).pcb_trace.list().flatMap((t34) => {
const e3 = [];
for (let n3 = 0;n3 < t34.route.length - 1; n3++) {
const o3 = t34.route[n3], i3 = t34.route[n3 + 1];
o3.route_type === "wire" && (i3.route_type === "wire" && o3.layer === i3.layer && e3.push({ type: "pcb_trace_segment", pcb_trace_id: t34.pcb_trace_id, _pcbTrace: t34, thickness: "width" in o3 ? o3.width : ("width" in i3) ? i3.width : lT, layer: o3.layer, x1: o3.x, y1: o3.y, x2: i3.x, y2: i3.y }));
}
return e3;
}), r2 = tg(t33).pcb_smtpad.list(), s2 = tg(t33).pcb_plated_hole.list(), a2 = tg(t33).pcb_hole.list(), c2 = tg(t33).pcb_via.list(), l2 = tg(t33).pcb_keepout.list(), h2 = [...i2, ...r2, ...s2, ...a2, ...c2, ...l2], d2 = new aT({ objects: h2, getBounds: _T }), u2 = (e3) => sg(t33, e3), p2 = (t34, e3, n3) => n3 < 0 ? `PCB trace ${t34} overlaps with ${e3} (accidental contact)` : `PCB trace ${t34} is too close to ${e3} (gap: ${n3.toFixed(3)}mm)`, m2 = new Set;
for (const t34 of i2) {
const i3 = n2, r3 = _T(t34), s3 = d2.getObjectsInBounds(r3, i3 + t34.thickness / 2);
if (t34.x1 !== t34.x2 || t34.y1 !== t34.y2)
for (const r4 of s3) {
if (!pT(r4).includes(t34.layer))
continue;
if (r4.type === "pcb_trace_segment") {
const i4 = r4;
if (t34.layer !== i4.layer)
continue;
if (e2.areIdsConnected(t34.pcb_trace_id, i4.pcb_trace_id))
continue;
const s5 = Oe({ x: t34.x1, y: t34.y1 }, { x: t34.x2, y: t34.y2 }, { x: i4.x1, y: i4.y1 }, { x: i4.x2, y: i4.y2 }) - t34.thickness / 2 - i4.thickness / 2;
if (s5 > n2 - uT)
continue;
const a4 = `overlap_${t34.pcb_trace_id}_${i4.pcb_trace_id}`, c3 = `overlap_${i4.pcb_trace_id}_${t34.pcb_trace_id}`;
if (m2.has(a4))
continue;
if (m2.has(c3))
continue;
m2.add(a4), o2.push({ type: "pcb_trace_error", error_type: "pcb_trace_error", message: p2(u2(t34.pcb_trace_id), u2(i4.pcb_trace_id), s5), pcb_trace_id: t34.pcb_trace_id, source_trace_id: "", pcb_trace_error_id: a4, pcb_component_ids: [], center: gT(t34, i4), pcb_port_ids: xT([t34._pcbTrace, i4._pcbTrace]) });
continue;
}
const s4 = dg(r4);
if (e2.areIdsConnected(t34.pcb_trace_id, "pcb_trace_id" in r4 ? r4.pcb_trace_id : s4))
continue;
if (r4.type === "pcb_via" || r4.type === "pcb_plated_hole" && r4.shape === "circle" || r4.type === "pcb_hole" || r4.type === "pcb_smtpad" && r4.shape === "circle") {
const e3 = vT(r4), i4 = Le({ x: t34.x1, y: t34.y1 }, { x: t34.x2, y: t34.y2 }, { x: r4.x, y: r4.y, radius: e3 }) - t34.thickness / 2;
if (i4 > n2 - uT)
continue;
const a4 = `overlap_${t34.pcb_trace_id}_${s4}`;
if (m2.has(a4))
continue;
m2.add(a4), o2.push({ type: "pcb_trace_error", error_type: "pcb_trace_error", message: p2(u2(t34.pcb_trace_id), `${r4.type} "${u2(dg(r4))}"`, i4), pcb_trace_id: t34.pcb_trace_id, center: mT(t34, _T(r4)), source_trace_id: "", pcb_trace_error_id: a4, pcb_component_ids: ["pcb_component_id" in r4 ? r4.pcb_component_id : undefined].filter(Boolean), pcb_port_ids: [...xT([t34._pcbTrace]), "pcb_port_id" in r4 ? r4.pcb_port_id : undefined].filter(Boolean) });
}
const a3 = ke({ x: t34.x1, y: t34.y1 }, { x: t34.x2, y: t34.y2 }, _T(r4)) - t34.thickness / 2;
if (a3 + uT < i3) {
const e3 = `overlap_${t34.pcb_trace_id}_${s4}`;
if (m2.has(e3))
continue;
m2.add(e3), o2.push({ type: "pcb_trace_error", error_type: "pcb_trace_error", message: p2(u2(t34.pcb_trace_id), `${r4.type} "${u2(dg(r4))}"`, a3), pcb_trace_id: t34.pcb_trace_id, source_trace_id: "", pcb_trace_error_id: e3, pcb_component_ids: ["pcb_component_id" in r4 ? r4.pcb_component_id : undefined].filter(Boolean), center: mT(t34, _T(r4)), pcb_port_ids: [...xT([t34._pcbTrace]), "pcb_port_id" in r4 ? r4.pcb_port_id : undefined].filter(Boolean) });
}
}
}
return o2;
}
function ST(t33, e2) {
return Math.hypot(t33.x - e2.x, t33.y - e2.y);
}
function CT(t33, e2) {
return ST(t33, e2) <= uT;
}
function PT(t33, { connMap: e2, minClearance: n2 = hT } = {}) {
const o2 = t33.filter((t34) => t34.type === "pcb_via");
if (o2.length < 2)
return [];
e2 ??= SC(t33);
const i2 = [], r2 = new Set;
for (let s2 = 0;s2 < o2.length; s2++)
for (let a2 = s2 + 1;a2 < o2.length; a2++) {
const c2 = o2[s2], l2 = o2[a2];
if (CT(c2, l2))
continue;
if (!e2.areIdsConnected(c2.pcb_via_id, l2.pcb_via_id))
continue;
const h2 = ST(c2, l2) - c2.outer_diameter / 2 - l2.outer_diameter / 2;
if (h2 + uT >= n2)
continue;
const d2 = [c2.pcb_via_id, l2.pcb_via_id].sort().join("_");
r2.has(d2) || (r2.add(d2), i2.push({ type: "pcb_via_clearance_error", pcb_error_id: `same_net_vias_close_${d2}`, message: `Vias ${sg(t33, c2.pcb_via_id)} and ${sg(t33, l2.pcb_via_id)} are too close together (gap: ${h2.toFixed(3)}mm)`, error_type: "pcb_via_clearance_error", pcb_via_ids: [c2.pcb_via_id, l2.pcb_via_id], minimum_clearance: n2, actual_clearance: h2, pcb_center: { x: (c2.x + l2.x) / 2, y: (c2.y + l2.y) / 2 } }));
}
return i2;
}
function MT(t33, { connMap: e2, minClearance: n2 = dT } = {}) {
const o2 = t33.filter((t34) => t34.type === "pcb_via");
if (o2.length < 2)
return [];
e2 ??= SC(t33);
const i2 = [], r2 = new Set;
for (let s2 = 0;s2 < o2.length; s2++)
for (let a2 = s2 + 1;a2 < o2.length; a2++) {
const c2 = o2[s2], l2 = o2[a2];
if (CT(c2, l2))
continue;
if (e2.areIdsConnected(c2.pcb_via_id, l2.pcb_via_id))
continue;
const h2 = ST(c2, l2) - c2.outer_diameter / 2 - l2.outer_diameter / 2;
if (h2 + uT >= n2)
continue;
const d2 = [c2.pcb_via_id, l2.pcb_via_id].sort().join("_");
r2.has(d2) || (r2.add(d2), i2.push({ type: "pcb_via_clearance_error", pcb_error_id: `different_net_vias_close_${d2}`, message: `Vias ${sg(t33, c2.pcb_via_id)} and ${sg(t33, l2.pcb_via_id)} from different nets are too close together (gap: ${h2.toFixed(3)}mm)`, error_type: "pcb_via_clearance_error", pcb_via_ids: [c2.pcb_via_id, l2.pcb_via_id], minimum_clearance: n2, actual_clearance: h2, pcb_center: { x: (c2.x + l2.x) / 2, y: (c2.y + l2.y) / 2 } }));
}
return i2;
}
var NT = (t33) => ({ minSpacing: t33, minClearance: t33 });
var wT = { traceClearance: 0.1, viaClearance: 0.1 };
var TT = (t33) => ((t34) => ("layer" in t34))(t33) ? [t33.layer] : t33.layers;
function RT(t33, e2, n2) {
let o2, i2 = Number.POSITIVE_INFINITY;
for (const r2 of e2) {
const e3 = n2.get(r2);
if (!e3)
continue;
const s2 = Math.hypot(e3.x - t33.x, e3.y - t33.y);
s2 < i2 && (i2 = s2, o2 = r2);
}
return o2 ?? e2[0];
}
function ET(t33) {
const e2 = [], n2 = new Set, o2 = new Set, i2 = function(t34) {
const e3 = new Map;
for (const n3 of t34.connections)
for (const t35 of n3.pointsToConnect)
t35.pcb_port_id && e3.set(t35.pcb_port_id, { x: t35.x, y: t35.y });
return e3;
}(t33);
for (const r2 of t33.obstacles) {
const t34 = r2.connectedTo, s2 = t34.find((t35) => t35.startsWith("pcb_smtpad_")), a2 = t34.find((t35) => t35.startsWith("pcb_plated_hole_")), c2 = t34.filter((t35) => t35.startsWith("pcb_port_")), l2 = RT(r2.center, c2, i2);
if (!s2 && !a2 && !l2)
continue;
const h2 = r2.layers;
if (h2.length === 0)
continue;
const { width: d2, height: u2 } = r2, p2 = r2.center.x, m2 = r2.center.y, g2 = r2.ccwRotationDegrees, f2 = typeof g2 == "number" && Number.isFinite(g2);
if (h2.length > 1) {
const t35 = a2 ?? `pcb_plated_hole_${p2.toFixed(3)}_${m2.toFixed(3)}`;
if (o2.has(t35))
continue;
if (o2.add(t35), f2) {
const n3 = Math.max(0.5 * Math.min(d2, u2), 0.1);
e2.push({ type: "pcb_plated_hole", pcb_plated_hole_id: t35, shape: "rotated_pill_hole_with_rect_pad", hole_shape: "rotated_pill", pad_shape: "rect", hole_width: n3, hole_height: n3, hole_ccw_rotation: g2, rect_pad_width: d2, rect_pad_height: u2, rect_ccw_rotation: g2, hole_offset_x: 0, hole_offset_y: 0, x: p2, y: m2, layers: h2, ...l2 ? { pcb_port_id: l2 } : {} });
continue;
}
if (Math.abs(d2 - u2) < 0.001) {
e2.push({ type: "pcb_plated_hole", pcb_plated_hole_id: t35, shape: "circle", outer_diameter: Math.max(d2, u2), hole_diameter: Math.max(0.5 * Math.min(d2, u2), 0.1), x: p2, y: m2, layers: h2, ...l2 ? { pcb_port_id: l2 } : {} });
continue;
}
e2.push({ type: "pcb_plated_hole", pcb_plated_hole_id: t35, shape: "circular_hole_with_rect_pad", hole_shape: "circle", hole_diameter: Math.max(0.5 * Math.min(d2, u2), 0.1), rect_pad_width: d2, rect_pad_height: u2, hole_offset_x: 0, hole_offset_y: 0, x: p2, y: m2, layers: h2, ...l2 ? { pcb_port_id: l2 } : {} });
continue;
}
const y2 = s2 ?? `pcb_smtpad_${p2.toFixed(3)}_${m2.toFixed(3)}`;
n2.has(y2) || (n2.add(y2), f2 ? e2.push({ type: "pcb_smtpad", pcb_smtpad_id: y2, layer: h2[0], shape: "rotated_rect", x: p2, y: m2, width: d2, height: u2, ccw_rotation: g2, ...l2 ? { pcb_port_id: l2 } : {} }) : e2.push({ type: "pcb_smtpad", pcb_smtpad_id: y2, layer: h2[0], shape: "rect", width: d2, height: u2, x: p2, y: m2, ...l2 ? { pcb_port_id: l2 } : {} }));
}
return e2;
}
function AT(t33, e2, n2 = 0.1, o2 = t33.minViaDiameter ?? 0.3) {
const i2 = [];
i2.push(...function(t34, e3) {
const n3 = [];
return t34.connections.forEach((o3) => {
const i3 = o3.pointsToConnect.filter((t35) => t35.pcb_port_id).map((t35) => t35.pcb_port_id).filter(Boolean), r3 = o3.netConnectionName || o3.rootConnectionName || o3.name, s2 = [], a2 = e3.find((t35) => (t35.connection_name ?? t35.connectionName) === o3.name);
if (a2) {
const e4 = (t35) => ("route_type" in t35) && t35.route_type === "jumper" ? t35.start : ("x" in t35) && ("y" in t35) ? { x: t35.x, y: t35.y } : { x: 0, y: 0 }, n4 = [e4(a2.route[0]), e4(a2.route[a2.route.length - 1])];
for (const e5 of n4)
for (const n5 of t34.obstacles)
Fe(e5, n5) <= 0 && s2.push(n5);
}
const c2 = n3.find((t35) => t35.type === "source_trace" && t35.source_trace_id === r3);
if (c2) {
const t35 = c2;
t35.connected_source_port_ids = [...new Set([...t35.connected_source_port_ids, ...i3])];
} else
n3.push({ type: "source_trace", source_trace_id: r3, connected_source_port_ids: i3.concat(s2.flatMap((t35) => [`obstacle_${t35.center.x.toFixed(3)}_${t35.center.y.toFixed(3)}_${t35.layers.join(".")}`, ...t35.connectedTo])), connected_source_net_ids: [] });
}), n3;
}(t33, e2)), i2.push(...function(t34) {
const e3 = new Map;
return t34.connections.forEach((t35) => {
t35.pointsToConnect.forEach((t36) => {
t36.pcb_port_id && e3.set(t36.pcb_port_id, { type: "pcb_port", pcb_port_id: t36.pcb_port_id, source_port_id: t36.pcb_port_id, x: t36.x, y: t36.y, layers: TT(t36) });
});
}), Array.from(e3.values());
}(t33)), i2.push(...ET(t33)), i2.push(...function(t34, e3, n3 = 0.3) {
const o3 = [], i3 = new Set;
return t34.length > 0 && ("type" in t34[0] && t34[0].type === "pcb_trace" ? t34.forEach((t35) => {
t35.route.forEach((r3) => {
if (r3.route_type === "via") {
const s2 = r3.via_diameter ?? n3, a2 = `${r3.x},${r3.y},${r3.from_layer},${r3.to_layer}`;
i3.has(a2) || (o3.push({ type: "pcb_via", pcb_via_id: `via_${o3.length}`, pcb_trace_id: t35.pcb_trace_id, x: r3.x, y: r3.y, outer_diameter: s2, hole_diameter: 0.5 * s2, layers: GS(r3, e3) }), i3.add(a2));
}
});
}) : t34.forEach((t35, r3) => {
const s2 = `trace_${r3}`, a2 = t35.viaDiameter ?? n3;
for (let n4 = 1;n4 < t35.route.length; n4++) {
const r4 = t35.route[n4 - 1], c2 = t35.route[n4];
if (r4.z !== c2.z && Math.abs(r4.x - c2.x) < 0.01 && Math.abs(r4.y - c2.y) < 0.01) {
const t36 = HS(r4.z, e3), n5 = HS(c2.z, e3), l2 = `${c2.x},${c2.y},${t36},${n5}`;
i3.has(l2) || (o3.push({ type: "pcb_via", pcb_via_id: `via_${o3.length}`, pcb_trace_id: s2, x: c2.x, y: c2.y, outer_diameter: a2, hole_diameter: 0.5 * a2, layers: GS({ from_layer: t36, to_layer: n5 }, e3) }), i3.add(l2));
}
}
})), o3;
}(e2, t33.layerCount, o2));
const r2 = new Map;
return t33.connections.forEach((t34) => {
r2.set(t34.name, t34.netConnectionName || t34.rootConnectionName || t34.name);
}), e2.length > 0 && ("type" in e2[0] && e2[0].type === "pcb_trace" ? e2.forEach((t34) => {
const e3 = t34.connection_name;
i2.push(function(t35, e4) {
return { type: "pcb_trace", pcb_trace_id: t35.pcb_trace_id, source_trace_id: e4, route: t35.route.map((t36) => t36.route_type === "wire" ? { route_type: "wire", x: t36.x, y: t36.y, width: t36.width, layer: t36.layer, start_pcb_port_id: t36.start_pcb_port_id, end_pcb_port_id: t36.end_pcb_port_id } : t36.route_type === "via" ? { route_type: "via", x: t36.x, y: t36.y, from_layer: t36.from_layer, to_layer: t36.to_layer } : null).filter((t36) => t36 !== null) };
}(t34, r2.get(e3) || e3));
}) : e2.forEach((e3, o3) => {
const s2 = e3.connectionName, a2 = function(t34, e4, n3, o4 = 0.1, i3) {
const r3 = [];
if (!t34.jumpers || t34.jumpers.length === 0)
return [{ type: "pcb_trace", pcb_trace_id: e4, source_trace_id: n3, route: t34.route.map((e5, n4) => {
const r4 = n4 === 0, s4 = n4 === t34.route.length - 1;
return { route_type: "wire", x: e5.x, y: e5.y, width: o4, layer: HS(e5.z, i3), ...r4 && e5.pcb_port_id ? { start_pcb_port_id: e5.pcb_port_id } : {}, ...s4 && e5.pcb_port_id ? { end_pcb_port_id: e5.pcb_port_id } : {} };
}) }];
const s3 = [];
for (const e5 of t34.jumpers) {
let n4 = -1, o5 = -1;
for (let i4 = 0;i4 < t34.route.length; i4++) {
const r4 = t34.route[i4];
Math.abs(r4.x - e5.start.x) < 0.01 && Math.abs(r4.y - e5.start.y) < 0.01 && (n4 = i4), Math.abs(r4.x - e5.end.x) < 0.01 && Math.abs(r4.y - e5.end.y) < 0.01 && (o5 = i4);
}
n4 !== -1 && o5 !== -1 && (n4 > o5 && ([n4, o5] = [o5, n4]), s3.push({ startIdx: n4, endIdx: o5 }));
}
s3.sort((t35, e5) => t35.startIdx - e5.startIdx);
let a3 = 0, c2 = 0;
for (const { startIdx: l2, endIdx: h2 } of s3) {
if (l2 >= a3) {
const s4 = t34.route.slice(a3, l2 + 1);
s4.length > 0 && (r3.push({ type: "pcb_trace", pcb_trace_id: `${e4}_${c2}`, source_trace_id: n3, route: s4.map((t35, e5) => {
const n4 = e5 === 0 && a3 === 0;
return { route_type: "wire", x: t35.x, y: t35.y, width: o4, layer: HS(t35.z, i3), ...n4 && t35.pcb_port_id ? { start_pcb_port_id: t35.pcb_port_id } : {} };
}) }), c2++);
}
a3 = h2;
}
if (a3 < t34.route.length) {
const s4 = t34.route.slice(a3);
if (s4.length > 0) {
r3.push({ type: "pcb_trace", pcb_trace_id: `${e4}_${c2}`, source_trace_id: n3, route: s4.map((e5, n4) => {
const r4 = n4 === s4.length - 1;
return { route_type: "wire", x: e5.x, y: e5.y, width: o4, layer: HS(e5.z, i3), ...r4 && e5.pcb_port_id ? { end_pcb_port_id: e5.pcb_port_id } : {} };
}) });
}
}
return r3;
}(e3, `trace_${o3}`, r2.get(s2) || s2, n2, t33.layerCount);
i2.push(...a2);
})), i2;
}
var OT = (t33) => t33.rootConnectionName ?? t33.connectionName;
var kT = (t33, e2) => {
if (t33 && e2)
return t33.getNetConnectedToId(e2);
};
var DT = (t33, e2, n2) => {
if (!e2)
return false;
if (t33 === e2)
return true;
const o2 = n2?.getNetConnectedToId(t33), i2 = n2?.getNetConnectedToId(e2);
return !(!o2 || !(o2 === i2 || t33 && o2 === e2)) || !(!i2 || i2 !== t33);
};
var LT = (t33, e2, n2) => e2.connectedTo?.some((e3) => DT(t33, e3, n2)) ?? false;
var zT = (t33, e2, n2) => Math.max(e2, Math.min(t33, n2));
var BT = (t33, e2) => {
t33.x = zT(t33.x, e2.minX, e2.maxX), t33.y = zT(t33.y, e2.minY, e2.maxY);
};
var FT = (t33, e2) => ({ minX: t33.minX - e2, minY: t33.minY - e2, maxX: t33.maxX + e2, maxY: t33.maxY + e2 });
var jT = (t33, e2) => ({ minCellX: Math.floor(t33.minX / e2), maxCellX: Math.floor(t33.maxX / e2), minCellY: Math.floor(t33.minY / e2), maxCellY: Math.floor(t33.maxY / e2) });
var $T = (t33, e2) => `${t33}:${e2}`;
var YT = (t33, e2, n2) => {
const o2 = new Map;
for (let i2 = 0;i2 < t33.length; i2 += 1) {
const r2 = t33[i2];
if (!r2)
continue;
const s2 = jT(e2(r2), n2);
for (let t34 = s2.minCellX;t34 <= s2.maxCellX; t34 += 1)
for (let e3 = s2.minCellY;e3 <= s2.maxCellY; e3 += 1) {
const n3 = $T(t34, e3), r3 = o2.get(n3);
r3 ? r3.push(i2) : o2.set(n3, [i2]);
}
}
return o2;
};
var XT = (t33, e2, n2) => {
const o2 = new Set, i2 = jT(e2, n2);
for (let e3 = i2.minCellX;e3 <= i2.maxCellX; e3 += 1)
for (let n3 = i2.minCellY;n3 <= i2.maxCellY; n3 += 1) {
const i3 = t33.get($T(e3, n3));
if (i3)
for (const t34 of i3)
o2.add(t34);
}
return [...o2].sort((t34, e3) => t34 - e3);
};
var WT = 0.000001;
var VT = (t33, e2, n2) => {
if (t33.length === 0)
return [];
const o2 = n2?.traceThickness ?? 0.1, i2 = t33[0], r2 = t33.at(-1), s2 = (t34) => {
if (t34.pcb_port_id)
return t34.pcb_port_id;
const o3 = HS(t34.z, e2);
return n2?.connectionPoints?.find((e3) => {
return e3.pcb_port_id && (n3 = e3, i3 = t34, Math.abs(n3.x - i3.x) <= WT && Math.abs(n3.y - i3.y) <= WT) && TT(e3).includes(o3);
var n3, i3;
})?.pcb_port_id;
}, a2 = s2(i2), c2 = s2(r2), l2 = [{ route_type: "wire", x: i2.x, y: i2.y, width: o2, layer: HS(i2.z, e2), ...a2 ? { start_pcb_port_id: a2 } : {}, ...t33.length === 1 && c2 ? { end_pcb_port_id: c2 } : {} }];
for (let i3 = 1;i3 < t33.length; i3 += 1) {
const r3 = t33[i3 - 1], s3 = t33[i3];
r3 && s3 && (r3.z !== s3.z && r3.x === s3.x && r3.y === s3.y && l2.push({ route_type: "via", x: s3.x, y: s3.y, from_layer: HS(r3.z, e2), to_layer: HS(s3.z, e2), ...n2?.viaDiameter ? { via_diameter: n2.viaDiameter } : {} }), l2.push({ route_type: "wire", x: s3.x, y: s3.y, width: o2, layer: HS(s3.z, e2), ...i3 === t33.length - 1 && c2 ? { end_pcb_port_id: c2 } : {} }));
}
return l2;
};
var HT = (t33, e2) => ({ x: Ae(t33.x, e2.minX, e2.maxX), y: Ae(t33.y, e2.minY, e2.maxY) });
var GT = (t33, e2) => {
const n2 = t33.x - e2.center.x, o2 = t33.y - e2.center.y;
return e2.circular ? Math.max(0, Math.hypot(n2, o2) - e2.halfWidth) : je(R(e2.worldToLocal, t33), { minX: -e2.halfWidth, maxX: e2.halfWidth, minY: -e2.halfHeight, maxY: e2.halfHeight });
};
var UT = (t33, e2) => ({ kind: "line", start: t33, end: e2, bounds: Ve([t33, e2]) });
var ZT = (t33, e2) => ({ kind: "circle", center: t33, radius: e2, bounds: We({ center: t33, width: 2 * e2, height: 2 * e2 }) });
var qT = (t33) => {
const e2 = t33.clearance + pC;
if (t33.circular)
return [ZT(t33.center, t33.halfWidth + e2)];
const n2 = (e3, n3) => R(t33.localToWorld, { x: e3, y: n3 }), { halfWidth: o2, halfHeight: i2 } = t33;
return [UT(n2(-o2, -i2 - e2), n2(o2, -i2 - e2)), UT(n2(o2 + e2, -i2), n2(o2 + e2, i2)), UT(n2(o2, i2 + e2), n2(-o2, i2 + e2)), UT(n2(-o2 - e2, i2), n2(-o2 - e2, -i2)), ZT(n2(-o2, -i2), e2), ZT(n2(o2, -i2), e2), ZT(n2(o2, i2), e2), ZT(n2(-o2, i2), e2)];
};
var JT = (t33, e2) => {
if (e2.kind === "circle") {
const n2 = t33.x - e2.center.x, o2 = t33.y - e2.center.y, i2 = Math.hypot(n2, o2);
return i2 === 0 ? [{ x: e2.center.x + e2.radius, y: e2.center.y }, { x: e2.center.x - e2.radius, y: e2.center.y }, { x: e2.center.x, y: e2.center.y + e2.radius }, { x: e2.center.x, y: e2.center.y - e2.radius }] : [{ x: e2.center.x + n2 * e2.radius / i2, y: e2.center.y + o2 * e2.radius / i2 }];
}
return [e2.start, e2.end, ze(t33, e2.start, e2.end)];
};
var QT = (t33, e2) => {
const n2 = t33.end.x - t33.start.x, o2 = t33.end.y - t33.start.y, i2 = t33.start.x - e2.center.x, r2 = t33.start.y - e2.center.y, s2 = n2 * n2 + o2 * o2;
if (s2 === 0)
return [];
const a2 = 2 * (i2 * n2 + r2 * o2), c2 = a2 * a2 - 4 * s2 * (i2 * i2 + r2 * r2 - e2.radius * e2.radius);
if (c2 < 0)
return [];
const l2 = Math.sqrt(c2);
return [(-a2 - l2) / (2 * s2), (-a2 + l2) / (2 * s2)].filter((t34) => t34 >= 0 && t34 <= 1).map((e3) => ({ x: t33.start.x + n2 * e3, y: t33.start.y + o2 * e3 }));
};
var KT = (t33, e2) => {
if (t33.kind === "line" && e2.kind === "circle")
return QT(t33, e2);
if (t33.kind === "circle" && e2.kind === "line")
return QT(e2, t33);
if (t33.kind === "line" && e2.kind === "line") {
const n3 = ve(t33.start, t33.end, e2.start, e2.end);
return n3 ? [n3] : [];
}
if (t33.kind !== "circle" || e2.kind !== "circle")
return [];
const n2 = e2.center.x - t33.center.x, o2 = e2.center.y - t33.center.y, i2 = Math.hypot(n2, o2);
if (i2 === 0 || i2 > t33.radius + e2.radius || i2 < Math.abs(t33.radius - e2.radius))
return [];
const r2 = (t33.radius ** 2 - e2.radius ** 2 + i2 ** 2) / (2 * i2), s2 = Math.sqrt(Math.max(0, t33.radius ** 2 - r2 ** 2)), a2 = t33.center.x + n2 * r2 / i2, c2 = t33.center.y + o2 * r2 / i2;
return [{ x: a2 - o2 * s2 / i2, y: c2 + n2 * s2 / i2 }, { x: a2 + o2 * s2 / i2, y: c2 - n2 * s2 / i2 }];
};
var tR = (t33, e2, n2, o2, i2) => {
const r2 = new Set(function(t34, e3, n3 = 1) {
if (n3 === 0)
throw new Error("step cannot be 0");
let o3, i3;
e3 === undefined ? (o3 = 0, i3 = t34) : (o3 = t34, i3 = e3);
const r3 = [];
if (n3 > 0)
for (let t35 = o3;t35 < i3; t35 += n3)
r3.push(t35);
else
for (let t35 = o3;t35 > i3; t35 += n3)
r3.push(t35);
return r3;
}(Math.min(...o2), Math.max(...o2) + 1).map((e3) => HS(e3, t33.layerCount)));
return t33.obstacles.filter((t34) => !t34.isCopperPour && t34.layers.some((t35) => r2.has(t35))).map((o3) => {
const r3 = typeof o3.ccwRotationDegrees == "number" && Number.isFinite(o3.ccwRotationDegrees), s2 = !r3 && o3.layers.length > 1 && Math.abs(o3.width - o3.height) < 0.001, a2 = L(k(o3.center.x, o3.center.y), j(r3 ? o3.ccwRotationDegrees : 0)), c2 = s2 ? Math.max(o3.width, o3.height) / 2 : o3.width / 2, l2 = s2 ? c2 : o3.height / 2, h2 = LT(OT(e2), o3, i2) || LT(e2.connectionName, o3, i2), d2 = n2 + (h2 ? 0 : bC(t33)), u2 = Ve(E(a2, [{ x: -c2, y: -l2 }, { x: c2, y: -l2 }, { x: c2, y: l2 }, { x: -c2, y: l2 }])), p2 = d2 + pC;
return { center: o3.center, halfWidth: c2, halfHeight: l2, localToWorld: a2, worldToLocal: A(a2), circular: s2, clearance: d2, bounds: { minX: u2.minX - p2, maxX: u2.maxX + p2, minY: u2.minY - p2, maxY: u2.maxY + p2 } };
});
};
var eR = (t33, e2, n2, o2) => {
const i2 = Math.min(...t33.zLayers), r2 = Math.max(...t33.zLayers), s2 = e2.filter((e3) => e3.z >= i2 && e3.z <= r2 && !DT(t33.rootConnectionName, e3.rootConnectionName, o2)).map((e3) => ({ segment: e3, required: t33.radius + e3.radius + n2 })).filter(({ segment: e3, required: n3 }) => be(t33, e3.start, e3.end) <= n3 + gC), a2 = s2.flatMap(({ segment: t34, required: e3 }) => {
const { start: n3, end: o3 } = t34, i3 = Math.sqrt(Ye(n3, o3));
if (i3 <= pC)
return [];
const r3 = e3 + pC, s3 = (o3.y - n3.y) / i3 * r3, a3 = (n3.x - o3.x) / i3 * r3;
return [UT({ x: n3.x + s3, y: n3.y + a3 }, { x: o3.x + s3, y: o3.y + a3 }), UT({ x: n3.x - s3, y: n3.y - a3 }, { x: o3.x - s3, y: o3.y - a3 }), ZT(n3, r3), ZT(o3, r3)];
}).filter((e3) => je(t33, e3.bounds) <= gC), c2 = [], l2 = (e3) => {
Ye(e3, t33) > gC ** 2 || c2.some((t34) => Ye(t34, e3) < 0.000000000001) || s2.some(({ segment: t34, required: n3 }) => be(e3, t34.start, t34.end) < n3) || c2.push(e3);
};
l2(t33);
for (let e3 = 0;e3 < a2.length; e3 += 1) {
const n3 = a2[e3];
for (const e4 of JT(t33, n3))
l2(e4);
for (let t34 = e3 + 1;t34 < a2.length; t34 += 1) {
const e4 = a2[t34];
if (Xe(n3.bounds, e4.bounds))
for (const t35 of KT(n3, e4))
l2(t35);
}
}
return c2.sort((e3, n3) => Ye(e3, t33) - Ye(n3, t33));
};
var nR = (t33) => ({ ...t33, route: t33.route.map((t34) => ({ ...t34 })), vias: t33.vias.map((t34) => ({ ...t34 })) });
var oR = (t33) => t33.map(nR);
var iR = (t33, e2) => {
const n2 = new Set(e2);
return t33.map((t34, e3) => n2.has(e3) ? nR(t34) : t34);
};
var rR = (t33, e2) => Math.abs(t33.x - e2.x) <= mC && Math.abs(t33.y - e2.y) <= mC;
var sR = ["pcb_smtpad", "pcb_plated_hole", "pcb_hole", "pcb_keepout"];
var aR = (t33) => typeof t33.type == "string" ? t33.type : typeof t33.error_type == "string" ? t33.error_type : undefined;
var cR = (t33) => {
if (aR(t33) === "pcb_pad_trace_clearance_error")
return true;
const e2 = typeof t33.message == "string" ? t33.message.toLowerCase() : "";
return (e2.includes("pcb_trace") || e2.includes("pcb trace")) && sR.some((t34) => e2.includes(t34));
};
var lR = (t33) => {
const e2 = typeof t33.message == "string" ? t33.message : "", n2 = e2.match(/gap: (-?\d+(?:\.\d+)?)mm/), o2 = e2.match(/required: (-?\d+(?:\.\d+)?)mm/);
if (n2 && o2) {
const t34 = Number.parseFloat(n2[1]), e3 = Number.parseFloat(o2[1]);
if (Number.isFinite(t34) && Number.isFinite(e3))
return Math.max(0, e3 - t34);
}
if (n2) {
const t34 = Number.parseFloat(n2[1]), e3 = wT.traceClearance;
if (Number.isFinite(t34))
return Math.max(0, e3 - t34);
}
return 1;
};
var hR = { projectEngineError: (t33) => ({ ...t33, center: typeof t33.first_contact_center == "object" ? t33.first_contact_center : t33.center, message: typeof t33.first_contact_message == "string" ? t33.first_contact_message : t33.message, actual_clearance: typeof t33.first_actual_clearance == "number" ? t33.first_actual_clearance : t33.actual_clearance }), getErrorSeverity: lR };
var dR = { projectEngineError: (t33) => t33, getErrorSeverity: (t33) => {
const e2 = Number(t33.minimum_clearance), n2 = Number(t33.worst_actual_clearance);
return Number.isFinite(e2) && Number.isFinite(n2) ? Math.max(0, e2 - n2) : lR(t33);
} };
var uR = (t33, e2 = lR) => t33.reduce((t34, n2) => t34 + e2(n2), 0);
var pR = (t33, e2, n2, o2, i2, r2 = hR) => {
const s2 = i2 && !n2 ? t33 : ((t34, e3) => e3 ? { ...t34, connections: t34.connections.map((t35) => {
const n3 = kT(e3, t35.name) ?? kT(e3, t35.rootConnectionName) ?? t35.netConnectionName;
return n3 ? { ...t35, netConnectionName: n3 } : t35;
}), obstacles: t34.obstacles.map((t35) => {
const n3 = new Set(t35.connectedTo);
for (const o3 of t35.connectedTo) {
const t36 = kT(e3, o3);
t36 && n3.add(t36);
}
return { ...t35, connectedTo: [...n3] };
}) } : t34)(t33, o2), { traces: a2, traceRouteIndexById: c2 } = ((t34, e3) => {
const n3 = [], o3 = new Map, i3 = new Map;
for (let t35 = 0;t35 < e3.length; t35 += 1) {
const n4 = e3[t35];
if (!n4)
continue;
const o4 = i3.get(n4.connectionName);
o4 ? o4.push({ route: n4, routeIndex: t35 }) : i3.set(n4.connectionName, [{ route: n4, routeIndex: t35 }]);
}
for (const e4 of t34.connections) {
const r3 = i3.get(e4.name) ?? [];
for (let i4 = 0;i4 < r3.length; i4 += 1) {
const s3 = r3[i4];
if (!s3)
continue;
const a3 = `${e4.name}_${i4}`;
n3.push({ type: "pcb_trace", pcb_trace_id: a3, connection_name: e4.netConnectionName ?? e4.rootConnectionName ?? e4.name, route: VT(s3.route.route, t34.layerCount, { traceThickness: s3.route.traceThickness ?? e4.nominalTraceWidth ?? t34.nominalTraceWidth ?? t34.minTraceWidth, viaDiameter: s3.route.viaDiameter ?? t34.minViaDiameter, connectionPoints: e4.pointsToConnect }) }), o3.set(a3, s3.routeIndex);
}
}
return { traces: n3, traceRouteIndexById: o3 };
})(s2, e2), l2 = n2?.({ srj: s2, routes: e2, traces: a2 });
if (l2) {
const t34 = Array.isArray(l2) ? l2 : l2.errors, e3 = Array.isArray(l2) ? l2 : l2.errorsWithCenters ?? l2.errors;
return { errors: e3, count: t34.length, issueScore: uR(e3, r2.getErrorSeverity), legacyIssueScore: uR(e3.filter((t35) => !DE(t35)), r2.getErrorSeverity), traceRouteIndexById: c2 };
}
const h2 = i2?.evaluate(a2) ?? ((t34, e3 = {}) => {
const n3 = Math.max(e3.viaClearance ?? 0.1, 0.1), o3 = [...IT(t34, NT(e3.traceClearance)), ...PT(t34, NT(n3)), ...MT(t34, NT(n3))], i3 = t34.filter((t35) => t35.type === "pcb_via"), r3 = new Map(i3.map((t35) => [t35.pcb_via_id, t35])), s3 = o3.map((t35) => {
if ("center" in t35 && t35.center)
return t35;
if ("pcb_center" in t35 && t35.pcb_center)
return { ...t35, center: t35.pcb_center };
if ("pcb_via_ids" in t35 && Array.isArray(t35.pcb_via_ids)) {
const [e4, n4] = t35.pcb_via_ids;
if (typeof e4 != "string" || typeof n4 != "string")
return t35;
const o4 = r3.get(e4), i4 = r3.get(n4);
if (o4 && i4)
return { ...t35, center: { x: (o4.x + i4.x) / 2, y: (o4.y + i4.y) / 2 } };
}
if ("pcb_error_id" in t35 && typeof t35.pcb_error_id == "string" && (t35.pcb_error_id.startsWith("same_net_vias_close_") || t35.pcb_error_id.startsWith("different_net_vias_close_"))) {
const e4 = t35.pcb_error_id.replace("same_net_vias_close_", "").replace("different_net_vias_close_", "").split("_").filter(Boolean);
if (e4.length === 2) {
const n4 = e4[0], o4 = e4[1];
if (!n4 || !o4)
return t35;
const i4 = r3.get(n4), s4 = r3.get(o4);
if (i4 && s4)
return { ...t35, center: { x: (i4.x + s4.x) / 2, y: (i4.y + s4.y) / 2 } };
}
}
return t35;
}), a3 = s3.filter((t35) => Boolean(t35.center));
return { errors: o3, errorsWithCenters: s3, locationAwareErrors: a3 };
})(AT(s2, a2, s2.minTraceWidth, s2.minViaDiameter), { traceClearance: s2.minTraceToPadEdgeClearance ?? wT.traceClearance, viaClearance: s2.minTraceToPadEdgeClearance ?? wT.viaClearance }), d2 = h2.errors, u2 = (h2.errorsWithCenters.length > 0 ? h2.errorsWithCenters : h2.errors).map((t34) => r2.projectEngineError(t34));
return { errors: u2, count: d2.length, issueScore: uR(u2, r2.getErrorSeverity), legacyIssueScore: uR(u2.filter((t34) => !DE(t34)), r2.getErrorSeverity), traceRouteIndexById: c2 };
};
var mR = (t33, e2, n2, o2, i2) => pR(t33, e2, n2, o2, i2, hR);
var gR = (t33, e2, n2, o2, i2) => pR(t33, e2, n2, o2, i2, dR);
var fR = (t33, e2 = 0.3) => {
const n2 = [];
for (let o2 = 0;o2 < t33.length; o2 += 1) {
const i2 = t33[o2];
if (!i2)
continue;
const r2 = new Set;
for (let t34 = 0;t34 < i2.route.length - 1; t34 += 1) {
const s2 = i2.route[t34], a2 = i2.route[t34 + 1];
if (!s2 || !a2)
continue;
if (s2.z === a2.z || !rR(s2, a2))
continue;
const c2 = [t34, t34 + 1];
for (let e3 = t34 - 1;e3 >= 0; e3 -= 1) {
const t35 = i2.route[e3];
if (!t35 || !rR(t35, s2))
break;
c2.push(e3);
}
for (let e3 = t34 + 2;e3 < i2.route.length; e3 += 1) {
const t35 = i2.route[e3];
if (!t35 || !rR(t35, s2))
break;
c2.push(e3);
}
const l2 = [...new Set(c2)];
if (l2.some((t35) => r2.has(t35)))
continue;
for (const t35 of l2)
r2.add(t35);
const h2 = l2.filter((t35) => t35 === 0 || t35 === i2.route.length - 1), d2 = h2.some((t35) => Boolean(i2.route[t35]?.pcb_port_id));
n2.push({ routeIndex: o2, rootConnectionName: OT(i2), pointIndexes: l2, zLayers: [...new Set(l2.map((t35) => i2.route[t35].z))], x: s2.x, y: s2.y, radius: (i2.viaDiameter ?? e2) / 2, movable: h2.length === 0, canCanonicalize: h2.length === 0 || !d2 });
}
}
return n2;
};
var yR = (t33, e2) => {
const n2 = [];
for (let o2 = 0;o2 < t33.route.length - 1; o2 += 1) {
const i2 = t33.route[o2], r2 = t33.route[o2 + 1];
i2 && r2 && (i2.z !== r2.z || rR(i2, r2) || n2.push({ routeIndex: e2, rootConnectionName: OT(t33), startIndex: o2, endIndex: o2 + 1, start: i2, end: r2, z: i2.z, radius: (t33.traceThickness ?? 0.1) / 2 }));
}
return n2;
};
var _R = (t33) => t33.flatMap((t34, e2) => yR(t34, e2));
var bR = (t33) => ({ minX: t33.x, minY: t33.y, maxX: t33.x, maxY: t33.y });
var xR = (t33) => ({ minX: Math.min(t33.start.x, t33.end.x), minY: Math.min(t33.start.y, t33.end.y), maxX: Math.max(t33.start.x, t33.end.x), maxY: Math.max(t33.start.y, t33.end.y) });
var vR = (t33) => ({ minX: t33.center.x - t33.width / 2, minY: t33.center.y - t33.height / 2, maxX: t33.center.x + t33.width / 2, maxY: t33.center.y + t33.height / 2 });
var IR = (t33, e2) => {
if (t33.zLayers && t33.zLayers.length > 0)
return t33.zLayers;
const n2 = Array.from({ length: e2 }, (t34, e3) => e3).filter((n3) => t33.layers.includes(HS(n3, e2)));
return n2.length > 0 ? n2 : Array.from({ length: e2 }, (t34, e3) => e3);
};
var SR = (t33, e2, n2) => {
const o2 = e2.reduce((t34, e3) => Math.max(t34, e3.radius), (t33.minViaDiameter ?? 0.3) / 2), i2 = n2.reduce((t34, e3) => Math.max(t34, e3.radius), t33.minTraceWidth / 2), r2 = (wT.traceClearance) + yC;
return Math.max(2 * o2 + 0.2 + yC, o2 + i2 + r2, 2 * i2 + r2, i2 + _C(t33) + yC, o2 + bC(t33) + yC);
};
var CR = (t33, e2, n2) => {
const o2 = n2.x - e2.x, i2 = n2.y - e2.y, r2 = o2 * o2 + i2 * i2;
if (r2 <= pC)
return { x: e2.x, y: e2.y, t: 0 };
const s2 = zT(((t33.x - e2.x) * o2 + (t33.y - e2.y) * i2) / r2, 0, 1);
return { x: e2.x + o2 * s2, y: e2.y + i2 * s2, t: s2 };
};
var PR = (t33, e2) => CR(t33, e2.start, e2.end);
var MR = (t33, e2) => {
const n2 = e2.width / 2, o2 = e2.height / 2, i2 = Math.max(Math.abs(t33.x - e2.center.x) - n2, 0), r2 = Math.max(Math.abs(t33.y - e2.center.y) - o2, 0);
return Math.hypot(i2, r2);
};
var NR = (t33, e2) => t33.x >= e2.center.x - e2.width / 2 - mC && t33.x <= e2.center.x + e2.width / 2 + mC && t33.y >= e2.center.y - e2.height / 2 - mC && t33.y <= e2.center.y + e2.height / 2 + mC;
var wR = (t33, e2, n2, o2) => t33.obstacles.find((i2) => LT(OT(e2), i2, o2) && IR(i2, t33.layerCount).includes(n2.z) && NR(n2, i2));
var TR = (t33, e2, n2 = 0.6, o2) => {
let i2;
for (const r2 of t33.obstacles) {
if (o2 && !o2(r2))
continue;
const t34 = MR(e2, r2);
t34 > n2 || (!i2 || t34 < i2.distance) && (i2 = { obstacle: r2, distance: t34 });
}
return i2?.obstacle;
};
var RR = (t33, e2, n2) => {
const o2 = e2.width / 2, i2 = e2.height / 2, r2 = zT(t33.x, e2.center.x - o2, e2.center.x + o2), s2 = zT(t33.y, e2.center.y - i2, e2.center.y + i2);
let a2 = t33.x - r2, c2 = t33.y - s2, l2 = Math.hypot(a2, c2);
if (l2 <= pC) {
o2 - Math.abs(t33.x - e2.center.x) < i2 - Math.abs(t33.y - e2.center.y) ? (a2 = t33.x >= e2.center.x ? 1 : -1, c2 = 0, l2 = 0) : (a2 = 0, c2 = t33.y >= e2.center.y ? 1 : -1, l2 = 0);
}
const h2 = n2 - l2;
if (h2 <= 0)
return;
const d2 = Math.hypot(a2, c2);
return { direction: { x: d2 > pC ? a2 / d2 : 1, y: d2 > pC ? c2 / d2 : 0 }, penetration: h2 };
};
var ER = (t33, e2, n2, o2) => {
const i2 = e2.message;
if (typeof i2 != "string" || !i2.includes("pcb_"))
return n2;
const r2 = Array.isArray(e2.pcb_pad_ids) ? e2.pcb_pad_ids.filter((t34) => typeof t34 == "string") : [], s2 = t33.obstacles.find((t34) => r2.some((e3) => t34.connectedTo.includes(e3)) && (true));
return s2 ? s2.center : TR(t33, n2, 0.6, o2)?.center ?? n2;
};
var AR = (t33, e2) => {
const n2 = t33.route[e2];
if (!n2)
return [];
const o2 = [e2];
for (let i2 = e2 - 1;i2 >= 0; i2 -= 1) {
const e3 = t33.route[i2];
if (!e3 || !rR(e3, n2))
break;
o2.push(i2);
}
for (let i2 = e2 + 1;i2 < t33.route.length; i2 += 1) {
const e3 = t33.route[i2];
if (!e3 || !rR(e3, n2))
break;
o2.push(i2);
}
return [...new Set(o2)];
};
var OR = (t33, e2) => {
if (e2 <= 0 || e2 >= t33.route.length - 1)
return;
const n2 = AR(t33, e2);
return n2.includes(0) || n2.includes(t33.route.length - 1) ? undefined : n2;
};
var kR = (t33, e2) => t33.x >= e2.minX - mC && t33.x <= e2.maxX + mC && t33.y >= e2.minY - mC && t33.y <= e2.maxY + mC;
var DR = (t33, e2) => Math.min(t33.x - e2.minX, e2.maxX - t33.x, t33.y - e2.minY, e2.maxY - t33.y);
var LR = (t33, e2, n2) => {
const o2 = n2.x - e2.x, i2 = n2.y - e2.y, r2 = t33.x - e2.x, s2 = o2 * (t33.y - e2.y) - i2 * r2;
if (Math.abs(s2) > mC)
return false;
const a2 = Math.min(e2.x, n2.x) - mC, c2 = Math.max(e2.x, n2.x) + mC, l2 = Math.min(e2.y, n2.y) - mC, h2 = Math.max(e2.y, n2.y) + mC;
return t33.x >= a2 && t33.x <= c2 && t33.y >= l2 && t33.y <= h2;
};
var zR = (t33, e2) => {
if (e2.length < 3)
return true;
for (let n3 = 0;n3 < e2.length; n3 += 1) {
const o2 = e2[n3], i2 = e2[(n3 + 1) % e2.length];
if (o2 && i2 && LR(t33, o2, i2))
return true;
}
let n2 = false;
for (let o2 = 0, i2 = e2.length - 1;o2 < e2.length; i2 = o2, o2 += 1) {
const r2 = e2[o2], s2 = e2[i2];
if (!r2 || !s2)
continue;
r2.y > t33.y != s2.y > t33.y && t33.x < (s2.x - r2.x) * (t33.y - r2.y) / (s2.y - r2.y) + r2.x && (n2 = !n2);
}
return n2;
};
var BR = (t33, e2) => {
const n2 = Math.hypot(t33, e2);
if (!(n2 <= pC))
return { x: t33 / n2, y: e2 / n2 };
};
var FR = (t33, e2) => t33.outline && t33.outline.length >= 3 ? ((t34, e3) => {
const n2 = zR(t34, e3);
let o2;
for (let n3 = 0;n3 < e3.length; n3 += 1) {
const i3 = e3[n3], r3 = e3[(n3 + 1) % e3.length];
if (!i3 || !r3)
continue;
const s3 = CR(t34, i3, r3), a3 = Math.hypot(t34.x - s3.x, t34.y - s3.y);
(!o2 || a3 < o2.distance) && (o2 = { projection: s3, start: i3, end: r3, distance: a3 });
}
if (!o2)
return;
const i2 = BR(n2 ? t34.x - o2.projection.x : o2.projection.x - t34.x, n2 ? t34.y - o2.projection.y : o2.projection.y - t34.y);
if (i2)
return i2;
const r2 = o2.end.x - o2.start.x, s2 = o2.end.y - o2.start.y, a2 = Math.hypot(r2, s2);
if (a2 <= pC)
return;
const c2 = ((t35) => {
let e4 = 0;
for (let n3 = 0;n3 < t35.length; n3 += 1) {
const o3 = t35[n3], i3 = t35[(n3 + 1) % t35.length];
o3 && i3 && (e4 += o3.x * i3.y - i3.x * o3.y);
}
return e4 / 2;
})(e3) >= 0;
return { x: c2 ? -s2 / a2 : s2 / a2, y: c2 ? r2 / a2 : -r2 / a2 };
})(e2, t33.outline) : ((t34, e3) => {
const n2 = t34.x - e3.minX, o2 = e3.maxX - t34.x, i2 = t34.y - e3.minY, r2 = e3.maxY - t34.y, s2 = Math.min(n2, o2, i2, r2);
let a2 = 0, c2 = 0;
return n2 <= s2 + mC && (a2 += 1), o2 <= s2 + mC && (a2 -= 1), i2 <= s2 + mC && (c2 += 1), r2 <= s2 + mC && (c2 -= 1), BR(a2, c2);
})(e2, t33.bounds);
var jR = (t33, e2) => t33.outline && t33.outline.length >= 3 ? zR(e2, t33.outline) : kR(e2, t33.bounds);
var $R = (t33, e2) => {
if (t33.outline && t33.outline.length >= 3) {
const n2 = ((t34, e3) => {
let n3 = Number.POSITIVE_INFINITY;
for (let o2 = 0;o2 < e3.length; o2 += 1) {
const i2 = e3[o2], r2 = e3[(o2 + 1) % e3.length];
i2 && r2 && (n3 = Math.min(n3, be(t34, i2, r2)));
}
return n3;
})(e2, t33.outline);
return zR(e2, t33.outline) ? n2 : -n2;
}
return DR(e2, t33.bounds);
};
var YR = (t33, e2, n2) => {
if (Math.abs(e2.x - n2.x) <= mC && Math.abs(e2.y - n2.y) <= mC)
return Math.min($R(t33, e2), $R(t33, n2));
if (t33.outline && t33.outline.length >= 3) {
if (!zR(e2, t33.outline) || !zR(n2, t33.outline))
return Math.min($R(t33, e2), $R(t33, n2));
let o2 = Number.POSITIVE_INFINITY;
for (let i2 = 0;i2 < t33.outline.length; i2 += 1) {
const r2 = t33.outline[i2], s2 = t33.outline[(i2 + 1) % t33.outline.length];
r2 && s2 && (o2 = Math.min(o2, Oe(e2, n2, r2, s2)));
}
return o2;
}
return kR(e2, t33.bounds) && kR(n2, t33.bounds) ? Math.min(DR(e2, t33.bounds), DR(n2, t33.bounds)) : Math.min($R(t33, e2), $R(t33, n2));
};
var XR = (t33, e2) => e2 + Math.max(0.16, t33.defaultObstacleMargin ?? 0, wT.traceClearance);
var WR = (t33, e2, n2) => e2 < t33 - mC && Math.min(t33, e2) <= n2 + mC;
var VR = (t33, e2, n2, o2, i2) => {
const r2 = t33 * n2.x + e2 * n2.y, s2 = -Math.max(0, o2 - i2);
if (r2 >= s2 - mC)
return { x: t33, y: e2 };
const a2 = s2 - r2;
return { x: t33 + n2.x * a2, y: e2 + n2.y * a2 };
};
var HR = (t33, e2, n2, o2, i2) => {
const r2 = FR(t33, e2);
return r2 ? VR(n2, o2, r2, $R(t33, e2), XR(t33, i2)) : { x: n2, y: o2 };
};
var GR = (t33, e2, n2, o2) => {
const i2 = [...new Set(n2)].sort((t34, e3) => t34 - e3);
if (i2.length === 0)
return Number.POSITIVE_INFINITY;
const r2 = new Set(i2), s2 = (t34) => o2?.get(t34) ?? e2.route[t34];
let a2 = Number.POSITIVE_INFINITY;
for (const e3 of i2) {
const n3 = s2(e3);
n3 && (a2 = Math.min(a2, $R(t33, n3)));
}
for (let n3 = 0;n3 < e2.route.length - 1; n3 += 1) {
if (!r2.has(n3) && !r2.has(n3 + 1))
continue;
const e3 = s2(n3), o3 = s2(n3 + 1);
e3 && o3 && (a2 = Math.min(a2, YR(t33, e3, o3)));
}
return a2;
};
var UR = (t33, e2, n2, o2, i2, r2) => {
const s2 = [...new Set(n2)].sort((t34, e3) => t34 - e3);
if (s2.length === 0)
return;
const a2 = ((t34, e3, n3, o3, i3, r3) => {
const s3 = [...new Set(n3)].sort((t35, e4) => t35 - e4);
let a3 = { x: o3, y: i3 };
const c3 = XR(t34, r3);
for (let n4 = 0;n4 < Math.max(1, s3.length); n4 += 1) {
let n5 = false;
for (const o4 of s3) {
const i4 = e3.route[o4];
if (!i4)
continue;
const r4 = FR(t34, i4);
if (!r4)
continue;
const s4 = VR(a3.x, a3.y, r4, $R(t34, i4), c3);
(Math.abs(s4.x - a3.x) > pC || Math.abs(s4.y - a3.y) > pC) && (a3 = s4, n5 = true);
}
if (!n5)
break;
}
return a3;
})(t33, e2, s2, o2, i2, r2);
if (Math.abs(a2.x) <= pC && Math.abs(a2.y) <= pC)
return;
const c2 = new Map;
for (const t34 of s2) {
const n3 = e2.route[t34];
if (!n3)
continue;
const o3 = { x: n3.x + a2.x, y: n3.y + a2.y };
c2.set(t34, o3);
}
const l2 = GR(t33, e2, s2), h2 = GR(t33, e2, s2, c2);
if (h2 < r2 - mC)
return;
const d2 = XR(t33, r2);
return WR(l2, h2, d2) ? undefined : a2;
};
var ZR = (t33, e2, n2, o2, i2, r2, s2) => {
const a2 = t33[e2];
if (!a2)
return false;
const c2 = OR(a2, n2);
if (!c2)
return false;
const l2 = UR(r2, a2, c2, o2, i2, s2);
if (!l2)
return false;
let h2 = false;
for (const t34 of c2) {
const e3 = a2.route[t34];
e3 && (e3.x += l2.x, e3.y += l2.y, BT(e3, r2.bounds), h2 = true);
}
return h2;
};
var qR = (t33, e2, n2, o2, i2, r2) => OR(e2, n2) ?? ((t34, e3, n3, o3, i3, r3) => {
const s2 = e3.route[n3];
if (!s2 || s2.pcb_port_id || n3 !== 0 && n3 !== e3.route.length - 1)
return;
const a2 = wR(t34, e3, s2, r3);
if (!a2)
return;
const c2 = { ...s2, x: s2.x + o3, y: s2.y + i3 };
return jR(t34, c2) && NR(c2, a2) ? AR(e3, n3) : undefined;
})(t33, e2, n2, o2, i2, r2);
var JR = (t33, e2, n2, o2, i2, r2) => {
const s2 = UR(i2, t33, e2, n2, o2, r2);
if (!s2)
return false;
let a2 = false;
for (const n3 of e2) {
const e3 = t33.route[n3];
e3 && (e3.x += s2.x, e3.y += s2.y, BT(e3, i2.bounds), a2 = true);
}
return a2;
};
var QR = (t33, e2, n2, o2, i2, r2) => {
const s2 = e2.route[n2];
if (!s2)
return false;
if (s2.pcb_port_id)
return false;
const a2 = wR(t33, e2, s2, r2);
return !!a2 && NR({ ...s2, x: s2.x + o2, y: s2.y + i2 }, a2);
};
var KR = (t33, e2, n2, o2) => {
const i2 = e2.route[n2];
if (i2 && !i2.pcb_port_id)
return wR(t33, e2, i2, o2);
};
var tE = (t33, e2, n2, o2, i2, r2, s2) => {
const a2 = t33[e2];
if (!a2 || a2.route.length === 0)
return false;
const c2 = ((t34, e3, n3, o3, i3) => {
let { NEGATIVE_INFINITY: r3, POSITIVE_INFINITY: s3, NEGATIVE_INFINITY: a3, POSITIVE_INFINITY: c3 } = Number;
for (const n4 of [0, e3.route.length - 1]) {
const o4 = e3.route[n4], l3 = KR(t34, e3, n4, i3);
if (!o4 || !l3)
return;
r3 = Math.max(r3, l3.center.x - l3.width / 2 - o4.x), s3 = Math.min(s3, l3.center.x + l3.width / 2 - o4.x), a3 = Math.max(a3, l3.center.y - l3.height / 2 - o4.y), c3 = Math.min(c3, l3.center.y + l3.height / 2 - o4.y);
}
if (!(r3 > s3 || a3 > c3))
return { x: zT(n3, r3, s3), y: zT(o3, a3, c3) };
})(i2, a2, n2, o2, s2);
if (!c2)
return false;
const l2 = a2.route.map((t34, e3) => e3), h2 = UR(i2, a2, l2, c2.x, c2.y, r2);
if (!h2)
return false;
const d2 = a2.route.length - 1;
if (!QR(i2, a2, 0, h2.x, h2.y, s2) || !QR(i2, a2, d2, h2.x, h2.y, s2))
return false;
let u2 = false;
for (const t34 of a2.route)
t34.x += h2.x, t34.y += h2.y, BT(t34, i2.bounds), u2 = true;
return u2;
};
var eE = (t33, e2, n2) => {
const o2 = e2.x - t33.x, i2 = e2.y - t33.y, r2 = n2.x - e2.x, s2 = n2.y - e2.y;
return Math.abs(o2 * s2 - i2 * r2) <= mC;
};
var nE = (t33, e2) => {
if (t33.z !== e2.z)
return false;
const n2 = e2.end.x - e2.start.x, o2 = e2.end.y - e2.start.y, i2 = t33.x - e2.start.x, r2 = t33.y - e2.start.y;
return Math.abs(n2 * r2 - o2 * i2) <= mC;
};
var oE = (t33, e2) => {
const n2 = ((t34, e3) => {
const n3 = e3.end.x - e3.start.x, o3 = e3.end.y - e3.start.y, i2 = Math.max(mC, 0.12 * (t34.traceThickness ?? 0.1)), r2 = Math.abs(o3) <= i2, s2 = Math.abs(n3) <= i2;
let { startIndex: a2, endIndex: c2 } = e3;
if (r2 || s2) {
const n4 = r2 ? (e3.start.y + e3.end.y) / 2 : (e3.start.x + e3.end.x) / 2;
for (;a2 > 0; ) {
const o4 = t34.route[a2 - 1];
if (!o4 || o4.z !== e3.z || Math.abs((r2 ? o4.y : o4.x) - n4) > i2)
break;
a2 -= 1;
}
for (;c2 < t34.route.length - 1; ) {
const o4 = t34.route[c2 + 1];
if (!o4 || o4.z !== e3.z || Math.abs((r2 ? o4.y : o4.x) - n4) > i2)
break;
c2 += 1;
}
return Array.from({ length: c2 - a2 + 1 }, (t35, e4) => a2 + e4);
}
for (;a2 > 0; ) {
const n4 = t34.route[a2 - 1], o4 = t34.route[a2], i3 = t34.route[a2 + 1];
if (!(n4 && o4 && i3 && n4.z === e3.z && nE(n4, e3) && eE(n4, o4, i3)))
break;
a2 -= 1;
}
for (;c2 < t34.route.length - 1; ) {
const n4 = t34.route[c2 - 1], o4 = t34.route[c2], i3 = t34.route[c2 + 1];
if (!(n4 && o4 && i3 && i3.z === e3.z && nE(i3, e3) && eE(n4, o4, i3)))
break;
c2 += 1;
}
return Array.from({ length: c2 - a2 + 1 }, (t35, e4) => a2 + e4);
})(t33, e2);
if (n2.length <= 2)
return;
const o2 = [];
for (const e3 of n2) {
const n3 = OR(t33, e3);
if (!n3)
return;
o2.push(...n3);
}
return [...new Set(o2)];
};
var iE = (t33, e2) => e2 > 0 && e2 < t33.route.length - 1 && !((t34, e3) => {
const n2 = t34.route[e3];
if (!n2)
return false;
const o2 = t34.route[e3 - 1], i2 = t34.route[e3 + 1];
return o2 && o2.z !== n2.z && rR(o2, n2) || i2 && i2.z !== n2.z && rR(i2, n2);
})(t33, e2);
var rE = (t33, e2, n2) => {
const o2 = t33.route[e2.startIndex], i2 = t33.route[e2.endIndex];
return !(!o2 || !i2) && (o2.z === e2.z && i2.z === e2.z && (!!((t34, e3) => xR(t34).maxX >= e3.minX - mC && xR(t34).minX <= e3.maxX + mC && xR(t34).maxY >= e3.minY - mC && xR(t34).minY <= e3.maxY + mC)(e2, n2) && (iE(t33, e2.startIndex) || iE(t33, e2.endIndex))));
};
var sE = (t33, e2, n2, o2, i2, r2, s2) => {
const a2 = t33[e2.routeIndex];
if (!a2)
return false;
const c2 = ((t34, e3, n3, o3) => {
const i3 = FT(vR(n3), o3);
let { startIndex: r3, startIndex: s3 } = e3;
for (;r3 > 0; ) {
const n4 = { ...e3, startIndex: r3 - 1, endIndex: r3, start: t34.route[r3 - 1], end: t34.route[r3] };
if (!t34.route[r3 - 1] || !rE(t34, n4, i3))
break;
r3 -= 1;
}
for (;s3 < t34.route.length - 2; ) {
const n4 = { ...e3, startIndex: s3 + 1, endIndex: s3 + 2, start: t34.route[s3 + 1], end: t34.route[s3 + 2] };
if (!t34.route[s3 + 2] || !rE(t34, n4, i3))
break;
s3 += 1;
}
const a3 = [];
for (let e4 = r3;e4 <= s3 + 1; e4 += 1)
iE(t34, e4) && a3.push(e4);
return [...new Set(a3)];
})(a2, e2, n2, o2);
return !(c2.length <= 2) && JR(a2, c2, i2, r2, s2, e2.radius);
};
var aE = (t33, e2) => {
const n2 = PR(e2, t33), o2 = n2.x - e2.x, i2 = n2.y - e2.y, r2 = Math.hypot(o2, i2), s2 = t33.end.x - t33.start.x, a2 = t33.end.y - t33.start.y, c2 = Math.hypot(s2, a2), l2 = t33.routeIndex % 2 == 0 ? 1 : -1;
return { projection: n2, direction: r2 > pC ? { x: o2 / r2, y: i2 / r2 } : c2 > pC ? { x: -a2 / c2 * l2, y: s2 / c2 * l2 } : { x: 1, y: 0 } };
};
var cE = (t33, e2, n2, o2, i2) => {
const r2 = t33[e2.routeIndex];
if (!r2)
return false;
const s2 = HR(i2, e2, n2, o2, e2.radius);
if (Math.abs(s2.x) <= pC && Math.abs(s2.y) <= pC)
return false;
const a2 = { x: e2.x + s2.x, y: e2.y + s2.y }, c2 = $R(i2, e2), l2 = $R(i2, a2);
if (l2 < e2.radius - mC)
return false;
const h2 = XR(i2, e2.radius);
if (WR(c2, l2, h2))
return false;
e2.x += s2.x, e2.y += s2.y, BT(e2, i2.bounds);
for (const t34 of e2.pointIndexes) {
const n3 = r2.route[t34];
n3 && (n3.x = e2.x, n3.y = e2.y);
}
return true;
};
var lE = (t33, e2) => {
const n2 = fR(t33), o2 = n2.find((t34) => t34.routeIndex === e2.routeIndex && t34.pointIndexes.some((t35) => e2.pointIndexes.includes(t35)));
return o2 ? n2.filter((t34) => t34.rootConnectionName === o2.rootConnectionName && Math.hypot(t34.x - o2.x, t34.y - o2.y) <= mC) : [];
};
var hE = (t33, e2, n2, o2, i2) => e2.movable && lE(t33, e2).length <= 1 && cE(t33, e2, n2, o2, i2);
var dE = (t33, e2, n2, o2, i2 = 1) => {
const { projection: r2, direction: s2 } = aE(e2, n2), a2 = gC * i2, c2 = 1 - r2.t, l2 = r2.t, h2 = ZR(t33, e2.routeIndex, e2.startIndex, s2.x * a2 * c2, s2.y * a2 * c2, o2, e2.radius), d2 = ZR(t33, e2.routeIndex, e2.endIndex, s2.x * a2 * l2, s2.y * a2 * l2, o2, e2.radius);
return !(!h2 && !d2) || ((t34, e3, n3, o3, i3) => {
const r3 = t34[e3.routeIndex];
if (!r3)
return false;
const { projection: s3, direction: a3 } = aE(e3, n3), c3 = HR(o3, s3, a3.x * gC * i3, a3.y * gC * i3, e3.radius);
if (Math.abs(c3.x) <= pC && Math.abs(c3.y) <= pC)
return false;
const l3 = { ...r3.route[e3.startIndex], x: s3.x + c3.x, y: s3.y + c3.y };
if (BT(l3, o3.bounds), be(l3, e3.start, e3.end) <= mC)
return false;
const h3 = r3.route[e3.startIndex], d3 = r3.route[e3.endIndex];
if (!h3 || !d3)
return false;
const u2 = YR(o3, h3, d3), p2 = Math.min($R(o3, l3), YR(o3, h3, l3), YR(o3, l3, d3));
if (p2 < e3.radius - mC)
return false;
const m2 = XR(o3, e3.radius);
return !WR(u2, p2, m2) && (r3.route.splice(e3.endIndex, 0, l3), true);
})(t33, e2, n2, o2, i2);
};
var uE = (t33, e2, n2, o2, i2, r2 = 1) => {
const s2 = e2.radius + _C(o2) + yC, a2 = PE(e2, n2, s2);
if (!a2)
return false;
const c2 = Math.min(0.3 * Math.abs(r2), a2.penetration + yC), l2 = a2.direction.x * c2, h2 = a2.direction.y * c2, d2 = t33[e2.routeIndex];
if (!d2)
return false;
const u2 = !((t34) => {
for (let e3 = 0;e3 < t34.route.length - 1; e3 += 1) {
const n3 = t34.route[e3], o3 = t34.route[e3 + 1];
if (n3 && o3 && n3.z !== o3.z && rR(n3, o3))
return true;
}
return false;
})(d2);
if (u2 && tE(t33, e2.routeIndex, l2, h2, o2, e2.radius, i2))
return true;
const p2 = sE(t33, e2, n2, s2, l2, h2, o2) || ((t34, e3, n3, o3, i3) => {
const r3 = t34[e3.routeIndex];
if (!r3)
return false;
const s3 = oE(r3, e3);
return !!s3 && JR(r3, s3, n3, o3, i3, e3.radius);
})(t33, e2, l2, h2, o2) || ((t34, e3, n3, o3, i3, r3) => {
const s3 = t34[e3.routeIndex];
if (!s3)
return false;
const a3 = qR(i3, s3, e3.startIndex, n3, o3, r3), c3 = qR(i3, s3, e3.endIndex, n3, o3, r3);
if (!a3 || !c3)
return false;
const l3 = [...new Set([...a3, ...c3])], h3 = UR(i3, s3, l3, n3, o3, e3.radius);
if (!h3)
return false;
let d3 = false;
for (const t35 of l3) {
const e4 = s3.route[t35];
e4 && (e4.x += h3.x, e4.y += h3.y, BT(e4, i3.bounds), d3 = true);
}
return d3;
})(t33, e2, l2, h2, o2, i2);
if (p2)
return true;
if (!u2 && tE(t33, e2.routeIndex, l2, h2, o2, e2.radius, i2))
return true;
const m2 = n2.width / 2, g2 = n2.height / 2, f2 = (Math.abs(a2.direction.y) >= Math.abs(a2.direction.x) ? [{ ...d2.route[e2.startIndex], x: n2.center.x - m2 - s2, y: n2.center.y + a2.direction.y * (g2 + s2) }, { ...d2.route[e2.startIndex], x: n2.center.x + m2 + s2, y: n2.center.y + a2.direction.y * (g2 + s2) }] : [{ ...d2.route[e2.startIndex], x: n2.center.x + a2.direction.x * (m2 + s2), y: n2.center.y - g2 - s2 }, { ...d2.route[e2.startIndex], x: n2.center.x + a2.direction.x * (m2 + s2), y: n2.center.y + g2 + s2 }]).map((t34) => {
const { t: n3 } = PR(t34, e2), i3 = { x: e2.start.x + (e2.end.x - e2.start.x) * n3, y: e2.start.y + (e2.end.y - e2.start.y) * n3 }, r3 = HR(o2, i3, t34.x - i3.x, t34.y - i3.y, e2.radius);
return t34.x = i3.x + r3.x, t34.y = i3.y + r3.y, BT(t34, o2.bounds), { point: t34, t: n3, moved: Math.abs(r3.x) > pC || Math.abs(r3.y) > pC, awayFromObstacleMotion: r3.x * a2.direction.x + r3.y * a2.direction.y };
}).sort((t34, e3) => t34.t - e3.t);
if (!f2.some(({ moved: t34 }) => t34))
return false;
if (!f2.some(({ awayFromObstacleMotion: t34 }) => t34 > mC))
return false;
const y2 = f2.map(({ point: t34 }) => t34);
if (y2.every((t34) => be(t34, e2.start, e2.end) <= mC))
return false;
if (y2.some((t34) => !jR(o2, t34)))
return false;
const _2 = d2.route[e2.startIndex], b2 = d2.route[e2.endIndex], x2 = y2[0], v2 = y2[1];
if (!(_2 && b2 && x2 && v2))
return false;
const I2 = YR(o2, _2, b2), S2 = Math.min($R(o2, x2), $R(o2, v2), YR(o2, _2, x2), YR(o2, x2, v2), YR(o2, v2, b2));
if (S2 < e2.radius - mC)
return false;
const C2 = XR(o2, e2.radius);
return !WR(I2, S2, C2) && (d2.route.splice(e2.endIndex, 0, ...y2), true);
};
var pE = (t33, e2, n2) => {
let o2;
for (const i2 of t33) {
if (n2 !== undefined && i2.routeIndex !== n2)
continue;
const t34 = PR(e2, i2), r2 = Math.hypot(t34.x - e2.x, t34.y - e2.y);
(!o2 || r2 < o2.distance) && (o2 = { segment: i2, distance: r2 });
}
return o2?.segment;
};
var mE = (t33, e2, n2) => {
let o2;
for (const i2 of t33) {
if (n2 !== undefined && i2.routeIndex !== n2)
continue;
const t34 = Math.hypot(i2.x - e2.x, i2.y - e2.y);
(!o2 || t34 < o2.distance) && (o2 = { via: i2, distance: t34 });
}
return o2?.via;
};
var gE = (t33, e2) => {
const n2 = t33.map((t34) => ({ via: t34, distance: Math.hypot(t34.x - e2.x, t34.y - e2.y) })).sort((t34, e3) => t34.distance - e3.distance).slice(0, 2).map(({ via: t34 }) => t34);
return n2.length === 2 ? n2 : undefined;
};
var fE = (t33, e2, n2, o2) => {
const i2 = e2.x - n2.x, r2 = e2.y - n2.y, s2 = Math.hypot(i2, r2);
return hE(t33, e2, (s2 > pC ? i2 / s2 : 1) * gC, (s2 > pC ? r2 / s2 : 0) * gC, o2);
};
var yE = (t33, e2) => {
const n2 = PR(t33.start, e2), o2 = PR(t33.end, e2), i2 = PR(e2.start, t33), r2 = PR(e2.end, t33);
return [{ leftT: 0, rightT: n2.t, leftPoint: t33.start, rightPoint: n2 }, { leftT: 1, rightT: o2.t, leftPoint: t33.end, rightPoint: o2 }, { leftT: i2.t, rightT: 0, leftPoint: i2, rightPoint: e2.start }, { leftT: r2.t, rightT: 1, leftPoint: r2, rightPoint: e2.end }].sort((t34, e3) => Math.hypot(t34.leftPoint.x - t34.rightPoint.x, t34.leftPoint.y - t34.rightPoint.y) - Math.hypot(e3.leftPoint.x - e3.rightPoint.x, e3.leftPoint.y - e3.rightPoint.y));
};
var _E = (t33, e2, n2, o2, i2, r2) => {
const s2 = zT(r2, 0, 1), a2 = 1 - s2, c2 = s2, l2 = ZR(t33, e2.routeIndex, e2.startIndex, n2 * a2, o2 * a2, i2, e2.radius), h2 = ZR(t33, e2.routeIndex, e2.endIndex, n2 * c2, o2 * c2, i2, e2.radius);
return l2 || h2;
};
var bE = (t33, e2, n2, o2, i2, r2 = 0.035, s2 = false) => {
if (!s2 && DT(e2.rootConnectionName, n2.rootConnectionName, i2))
return false;
const a2 = e2.radius + n2.radius + 0.2 + yC, c2 = e2.x - n2.x, l2 = e2.y - n2.y, h2 = Math.hypot(c2, l2), d2 = a2 - h2;
if (d2 <= 0)
return false;
const u2 = 1.618 * (97 * e2.routeIndex + 13 * n2.routeIndex), p2 = h2 > pC ? c2 / h2 : Math.cos(u2), m2 = h2 > pC ? l2 / h2 : Math.sin(u2), g2 = Number(e2.movable) + Number(n2.movable);
if (g2 === 0)
return false;
const f2 = Math.min(r2, d2 / g2), y2 = hE(t33, e2, p2 * f2, m2 * f2, o2), _2 = hE(t33, n2, -p2 * f2, -m2 * f2, o2);
return y2 || _2;
};
var xE = (t33, e2, n2, o2, i2) => {
if (!DT(e2.rootConnectionName, n2.rootConnectionName, i2))
return false;
const [r2, s2] = e2.canCanonicalize ? n2.canCanonicalize && e2.routeIndex <= n2.routeIndex ? [e2, n2] : [n2, e2] : [e2, n2];
return ((t34, e3, n3, o3) => {
if (!n3.canCanonicalize)
return false;
const i3 = e3.x - n3.x, r3 = e3.y - n3.y;
if (!n3.movable && Math.hypot(i3, r3) > n3.radius + mC)
return false;
const s3 = t34[n3.routeIndex];
if (!s3)
return false;
const a2 = { x: n3.x, y: n3.y }, c2 = n3.pointIndexes.map((t35) => {
const e4 = s3.route[t35];
return e4 ? { pointIndex: t35, x: e4.x, y: e4.y } : undefined;
});
if (cE(t34, n3, i3, r3, o3) && rR(n3, e3))
return true;
n3.x = a2.x, n3.y = a2.y;
for (const t35 of c2) {
if (!t35)
continue;
const e4 = s3.route[t35.pointIndex];
e4 && (e4.x = t35.x, e4.y = t35.y);
}
return false;
})(t33, r2, s2, o2);
};
var vE = (t33, e2, n2, o2, i2, r2 = 0.035, s2 = 2, a2 = false) => {
if (DT(e2.rootConnectionName, n2.rootConnectionName, i2))
return false;
const c2 = PR(e2, n2), l2 = e2.x - c2.x, h2 = e2.y - c2.y, d2 = Math.hypot(l2, h2), u2 = e2.radius + n2.radius + (wT.traceClearance) + yC - d2;
if (u2 <= 0)
return false;
const p2 = n2.end.x - n2.start.x, m2 = n2.end.y - n2.start.y, g2 = Math.hypot(p2, m2), f2 = e2.routeIndex % 2 == 0 ? 1 : -1, y2 = d2 > pC ? l2 / d2 : g2 > pC ? -m2 / g2 * f2 : 1, _2 = d2 > pC ? h2 / d2 : g2 > pC ? p2 / g2 * f2 : 0, b2 = Math.min(r2, u2 / s2), x2 = a2 ? ((t34, e3, n3, o3, i3) => {
const r3 = lE(t34, e3);
if (r3.length === 0 || r3.some((e4) => !e4.movable || t34[e4.routeIndex] === undefined))
return false;
const s3 = r3.reduce((t35, e4) => e4.radius > t35.radius ? e4 : t35);
if (!cE(t34, s3, n3, o3, i3))
return false;
for (const e4 of r3) {
if (e4 === s3)
continue;
e4.x = s3.x, e4.y = s3.y;
const n4 = t34[e4.routeIndex];
for (const t35 of e4.pointIndexes) {
const e5 = n4.route[t35];
e5 && (e5.x = s3.x, e5.y = s3.y);
}
}
return true;
})(t33, e2, y2 * b2, _2 * b2, o2) : hE(t33, e2, y2 * b2, _2 * b2, o2), v2 = _E(t33, n2, -y2 * b2, -_2 * b2, o2, c2.t);
return x2 || v2;
};
var IE = (t33, e2, n2, o2, i2) => {
if (e2.z !== n2.z || DT(e2.rootConnectionName, n2.rootConnectionName, i2))
return false;
const [r2] = yE(e2, n2);
if (!r2)
return false;
const s2 = r2.leftPoint.x - r2.rightPoint.x, a2 = r2.leftPoint.y - r2.rightPoint.y, c2 = Math.hypot(s2, a2), l2 = e2.radius + n2.radius + (wT.traceClearance) + yC - c2;
if (l2 <= 0)
return false;
const h2 = e2.end.x - e2.start.x, d2 = e2.end.y - e2.start.y, u2 = Math.hypot(h2, d2), p2 = (e2.routeIndex + n2.routeIndex) % 2 == 0 ? 1 : -1, m2 = c2 > pC ? s2 / c2 : u2 > pC ? -d2 / u2 * p2 : 1, g2 = c2 > pC ? a2 / c2 : u2 > pC ? h2 / u2 * p2 : 0, f2 = Math.min(fC, l2 / 2), y2 = _E(t33, e2, m2 * f2, g2 * f2, o2, r2.leftT), _2 = _E(t33, n2, -m2 * f2, -g2 * f2, o2, r2.rightT);
return y2 || _2;
};
var SE = (t33, e2, n2) => IR(t33, n2).includes(e2.z);
var CE = (t33, e2, n2, o2, i2) => {
const r2 = e2[n2];
if (!r2)
return;
const s2 = yR(r2, n2);
if (s2.length === 0)
return;
const a2 = OT(r2), c2 = pE(s2, o2);
if (!c2)
return;
const l2 = TR(t33, o2, 0.6, (e3) => !LT(a2, e3, i2) && SE(e3, c2, t33.layerCount));
if (l2)
return { obstacle: l2, segment: c2 };
const h2 = TR(t33, o2, 0.6, (e3) => !LT(a2, e3, i2) && s2.some((n3) => SE(e3, n3, t33.layerCount)));
if (!h2)
return;
const d2 = pE(s2.filter((e3) => SE(h2, e3, t33.layerCount)), o2);
return d2 ? { obstacle: h2, segment: d2 } : undefined;
};
var PE = (t33, e2, n2) => {
const o2 = e2.width / 2, i2 = e2.height / 2, r2 = [{ x: e2.center.x - o2, y: e2.center.y - i2 }, { x: e2.center.x + o2, y: e2.center.y - i2 }, { x: e2.center.x + o2, y: e2.center.y + i2 }, { x: e2.center.x - o2, y: e2.center.y + i2 }], s2 = [e2.center, ...r2].map((e3) => PR(e3, t33)), a2 = [{ point: t33.start, t: 0 }, { point: t33.end, t: 1 }, { point: { x: (t33.start.x + t33.end.x) / 2, y: (t33.start.y + t33.end.y) / 2 }, t: 0.5 }, ...s2.map((t34) => ({ point: { x: t34.x, y: t34.y }, t: t34.t }))];
let c2;
const l2 = Math.hypot(t33.end.x - t33.start.x, t33.end.y - t33.start.y);
for (const o3 of a2) {
const i3 = RR(o3.point, e2, n2);
if (!i3)
continue;
const r3 = l2 > pC ? Math.abs(((t33.end.x - t33.start.x) * i3.direction.y - (t33.end.y - t33.start.y) * i3.direction.x) / l2) : 0;
(!c2 || i3.penetration > c2.penetration + pC || Math.abs(i3.penetration - c2.penetration) <= pC && r3 > c2.normality) && (c2 = { ...i3, normality: r3, t: o3.t });
}
return c2;
};
var ME = (t33, e2, n2, o2 = false) => {
let i2 = false;
const r2 = fR(e2), s2 = _R(e2), a2 = SR(t33, r2, s2), c2 = Math.max(1, 2 * a2), l2 = YT(r2, bR, c2), h2 = YT(s2, xR, c2);
for (let s3 = 0;s3 < r2.length; s3 += 1) {
const h3 = r2[s3];
if (!h3)
continue;
const d2 = XT(l2, FT(bR(h3), a2), c2);
for (const a3 of d2) {
if (a3 <= s3)
continue;
const c3 = r2[a3];
c3 && (i2 = bE(e2, h3, c3, t33, n2, fC, o2) || i2);
}
}
for (let o3 = 0;o3 < r2.length; o3 += 1) {
const l3 = r2[o3];
if (!l3)
continue;
const d2 = XT(h2, FT(bR(l3), a2), c2);
for (const o4 of d2) {
const r3 = s2[o4];
r3 && (i2 = vE(e2, l3, r3, t33, n2) || i2);
}
}
for (let o3 = 0;o3 < s2.length; o3 += 1) {
const r3 = s2[o3];
if (!r3)
continue;
const l3 = XT(h2, FT(xR(r3), a2), c2);
for (const a3 of l3) {
if (a3 <= o3)
continue;
const c3 = s2[a3];
c3 && (i2 = IE(e2, r3, c3, t33, n2) || i2);
}
}
return ((t34, e3, n3, o3, i3, r3, s3, a3) => {
let c3 = false;
const l3 = _C(t34), h3 = o3.reduce((t35, e4) => Math.max(t35, e4.radius), 0) + l3 + yC, d2 = (t34.minViaDiameter ?? 0.3) / 2 + bC(t34) + yC;
for (const u2 of t34.obstacles) {
if (u2.isCopperPour)
continue;
const p2 = vR(u2), m2 = XT(i3, FT(p2, d2), s3);
for (const o4 of m2) {
const i4 = n3[o4];
if (!i4)
continue;
if (LT(i4.rootConnectionName, u2, a3))
continue;
const r4 = RR(i4, u2, d2);
if (!r4)
continue;
const s4 = Math.min(fC, r4.penetration);
c3 = hE(e3, i4, r4.direction.x * s4, r4.direction.y * s4, t34) || c3;
}
const g2 = XT(r3, FT(p2, h3), s3);
for (const n4 of g2) {
const i4 = o3[n4];
if (!i4)
continue;
if (LT(i4.rootConnectionName, u2, a3) || !SE(u2, i4, t34.layerCount))
continue;
const r4 = PE(i4, u2, i4.radius + l3 + yC);
if (!r4)
continue;
const s4 = Math.min(fC, r4.penetration);
c3 = _E(e3, i4, r4.direction.x * s4, r4.direction.y * s4, t34, r4.t) || c3;
}
}
return c3;
})(t33, e2, r2, s2, l2, h2, c2, n2) || i2;
};
var NE = (t33, e2, n2, o2 = 1, i2, r2 = false, s2 = true) => {
const a2 = oR(e2), c2 = Math.max(2, Math.round(12 * Math.max(1, n2) * o2));
let l2 = false;
for (let e3 = 0;e3 < c2; e3 += 1) {
if (!ME(t33, a2, i2, r2))
break;
l2 = true;
}
return l2 && s2 && ((t34, e3, n3) => {
let o3 = false;
const i3 = fR(e3), r3 = _R(e3), s3 = SR(t34, i3, r3), a3 = Math.max(1, 2 * s3), c3 = YT(r3, xR, a3);
for (const l3 of i3) {
const i4 = XT(c3, FT(bR(l3), s3), a3);
for (const s4 of i4) {
const i5 = r3[s4];
i5 && (o3 = vE(e3, l3, i5, t34, n3, fC, 1.75) || o3);
}
}
})(t33, a2, i2), l2 ? RE(a2) : e2;
};
var wE = (t33) => {
const e2 = [];
for (let n2 = 0;n2 < t33.route.length - 1; n2 += 1) {
const o2 = t33.route[n2], i2 = t33.route[n2 + 1];
if (!o2 || !i2)
continue;
if (o2.toNextSegmentType === "through_obstacle")
continue;
if (o2.z === i2.z || !rR(o2, i2))
continue;
const r2 = { x: o2.x, y: o2.y }, s2 = e2.at(-1);
s2 && rR(s2, r2) || e2.push(r2);
}
return e2;
};
var TE = (t33) => ({ ...t33, vias: wE(t33) });
var RE = (t33) => t33.map(TE);
var EE = (t33, e2) => {
const n2 = new Set(e2);
return t33.map((t34, e3) => n2.has(e3) ? TE(t34) : t34);
};
var AE = (t33) => {
const e2 = t33.pcb_trace_id;
if (typeof e2 != "string")
return;
const n2 = e2.match(/^trace_(\d+)/);
return n2 ? Number.parseInt(n2[1], 10) : undefined;
};
var OE = (t33) => {
const e2 = t33.center ?? t33.pcb_center;
if (!e2 || typeof e2 != "object")
return;
const n2 = e2;
return typeof n2.x == "number" && typeof n2.y == "number" ? { x: n2.x, y: n2.y } : undefined;
};
var kE = (t33, e2 = true) => t33.errors.filter((t34) => ((t35) => aR(t35) === "pcb_via_clearance_error" || Array.isArray(t35.pcb_via_ids))(t34) && (e2 || !DE(t34))).length;
var DE = (t33) => aR(t33) === "pcb_pad_pad_clearance_error" && Array.isArray(t33.pcb_via_ids) && t33.pcb_via_ids.length === 1;
var LE = (t33) => {
const e2 = Object.entries(t33).filter(([t34, e3]) => t34 !== "source_trace_id" && (t34.endsWith("_id") || t34.endsWith("_ids")) && e3 !== undefined && e3 !== "").sort(([t34], [e3]) => t34.localeCompare(e3)), n2 = typeof t33.message == "string" ? t33.message.replace(/-?\d+\.\d+/g, "#") : "";
return JSON.stringify([aR(t33), e2, n2]);
};
var zE = (t33) => Math.max(t33.errors.filter((t34) => !DE(t34)).length, t33.count - t33.errors.filter(DE).length);
var BE = (t33) => {
const e2 = zE(t33);
return e2 > 0 ? e2 : t33.count;
};
var FE = (t33) => {
if (zE(t33) === 0)
return t33.issueScore;
const e2 = t33.errors.filter((t34) => !DE(t34));
return t33.errors.some(DE) ? uR(e2) : t33.legacyIssueScore ?? uR(e2);
};
var jE = (t33, e2) => {
const n2 = zE(t33), o2 = zE(e2);
return n2 !== o2 ? n2 < o2 : !(n2 > 0) && t33.count < e2.count;
};
var $E = (t33) => {
const e2 = t33.filter((t34) => !DE(t34));
return e2.length > 0 ? e2 : t33;
};
var YE = (t33, e2) => {
const n2 = t33.pcb_trace_id;
return typeof n2 == "string" ? e2.get(n2) ?? AE(t33) : AE(t33);
};
var XE = (t33, e2, n2, o2, i2) => {
const r2 = n2.pcb_port_id;
if (!r2)
return false;
const s2 = (i2 ?? e2.viaDiameter) / 2;
return t33.obstacles.some((i3) => {
const a2 = IR(i3, t33.layerCount);
return !(a2.length !== 1 || a2[0] !== n2.z || !i3.connectedTo.includes(r2) || n2.x - s2 < i3.center.x - i3.width / 2 - pC || n2.x + s2 > i3.center.x + i3.width / 2 + pC || n2.y - s2 < i3.center.y - i3.height / 2 - pC || n2.y + s2 > i3.center.y + i3.height / 2 + pC) && (LT(OT(e2), i3, o2) || LT(e2.connectionName, i3, o2));
});
};
var WE = [0, 1, -1, 2, -2, 3, -3, 4];
var VE = WE.flatMap((t33) => WE.map((e2) => [t33, e2])).sort(([t33, e2], [n2, o2]) => Math.abs(t33) + Math.abs(e2) - Math.abs(n2) - Math.abs(o2));
var HE = VE.length;
var GE = (t33, e2, n2) => t33.x - e2 >= n2.minX - pC && t33.x + e2 <= n2.maxX + pC && t33.y - e2 >= n2.minY - pC && t33.y + e2 <= n2.maxY + pC;
var UE = (t33, e2) => {
const n2 = t33.at(-1);
n2 && rR(n2, e2) && n2.z === e2.z && n2.pcb_port_id === e2.pcb_port_id || t33.push(e2);
};
var ZE = (t33, e2, n2, o2, i2, r2, s2, a2 = 0, c2 = false) => {
const l2 = aR(n2);
if (l2 !== "pcb_pad_trace_clearance_error" && l2 !== "pcb_trace_error")
return false;
if (i2 < 0 || i2 >= t33.layerCount)
return false;
const h2 = e2[o2];
if (!h2 || h2.route.length < 2)
return false;
const d2 = h2.route.map((t34) => ({ ...t34 })), u2 = d2[0], p2 = d2.at(-1);
if (!u2 || !p2)
return false;
const m2 = OE(n2);
if (!m2)
return false;
const g2 = cR(n2), f2 = g2 ? CE(t33, e2, o2, m2, s2) : undefined, y2 = g2 ? f2?.segment : pE(yR(h2, o2), m2);
if (!y2 || y2.z === i2)
return false;
let { startIndex: _2, endIndex: b2 } = y2;
const x2 = r2 === "full" ? d2.length : r2;
for (let t34 = 0;t34 < x2; t34 += 1) {
let t35 = false;
const e3 = d2[_2 - 1];
e3?.z === y2.z && (_2 -= 1, t35 = true);
const n3 = d2[b2 + 1];
if (n3?.z === y2.z && (b2 += 1, t35 = true), !t35)
break;
}
const v2 = _2 === 0 && u2.pcb_port_id, I2 = b2 === d2.length - 1 && p2.pcb_port_id, S2 = h2.viaDiameter / 2, C2 = VE[a2 % HE];
let P2 = false;
const M2 = (e3) => {
const n3 = e3 === "start" ? u2 : p2, o3 = ((t34, e4, n4, o4) => {
const i3 = n4.pcb_port_id;
if (i3)
return t34.obstacles.find((r4) => {
const s3 = IR(r4, t34.layerCount);
return !(s3.length !== 1 || s3[0] !== n4.z || !r4.connectedTo.includes(i3) || !NR(n4, r4)) && (LT(OT(e4), r4, o4) || LT(e4.connectionName, r4, o4));
});
})(t33, h2, n3, s2), r3 = ((t34, e4) => {
const n4 = e4 === "start" ? t34[0] : t34.at(-1);
if (!n4)
return;
const o4 = e4 === "start" ? Array.from({ length: t34.length - 1 }, (t35, e5) => e5 + 1) : Array.from({ length: t34.length - 1 }, (e5, n5) => t34.length - n5 - 2);
for (const e5 of o4) {
const o5 = t34[e5];
if (!o5)
continue;
const i3 = o5.x - n4.x, r4 = o5.y - n4.y, s3 = Math.hypot(i3, r4);
if (!(s3 <= pC))
return { x: i3 / s3, y: r4 / s3 };
}
})(d2, e3);
if (!o3 || !r3)
return;
const a3 = ((t34, e4, n4, o4) => {
let i3 = 0, r4 = Math.hypot(e4.width, e4.height) + 2 * o4;
const s3 = o4 + pC, a4 = (e5) => ({ x: t34.x + n4.x * e5, y: t34.y + n4.y * e5 });
if (!(MR(a4(r4), e4) < s3)) {
for (;r4 - i3 > pC; ) {
const t35 = (i3 + r4) / 2;
MR(a4(t35), e4) >= s3 ? r4 = t35 : i3 = t35;
}
return a4(r4);
}
})(n3, o3, ((t34, e4) => {
const n4 = e4 * Math.PI / 4, o4 = Math.cos(n4), i3 = Math.sin(n4);
return { x: t34.x * o4 - t34.y * i3, y: t34.x * i3 + t34.y * o4 };
})(r3, e3 === "start" ? C2[0] : C2[1]), S2);
if (!a3 || !GE(a3, S2, t33.bounds) || MR(a3, o3) + pC < S2)
return;
if (!c2)
return a3;
const l3 = ((t34, e4, n4, o4, i3, r4) => {
const s3 = o4 + (t34.minBoardEdgeClearance ?? 0), a4 = { minX: t34.bounds.minX + s3, maxX: t34.bounds.maxX - s3, minY: t34.bounds.minY + s3, maxY: t34.bounds.maxY - s3 };
if (a4.minX > a4.maxX || a4.minY > a4.maxY)
return;
const c3 = tR(t34, e4, o4, i3, r4), l4 = (t35) => Me(t35, a4) && c3.every((e5) => GT(t35, e5) >= e5.clearance), h3 = HT(n4, a4);
if (l4(h3))
return Me(n4, a4) ? n4 : h3;
const d3 = c3.filter((t35) => GT(h3, t35) < t35.clearance), u3 = new Set(d3);
for (let t35 = 0;t35 < d3.length; t35 += 1)
for (const e5 of c3)
!u3.has(e5) && Xe(d3[t35].bounds, e5.bounds) && (u3.add(e5), d3.push(e5));
const p3 = d3.flatMap(qT), m3 = { x: a4.minX, y: a4.minY }, g3 = { x: a4.maxX, y: a4.minY }, f3 = { x: a4.maxX, y: a4.maxY }, y3 = { x: a4.minX, y: a4.maxY };
let _3;
p3.push(UT(m3, g3), UT(g3, f3), UT(f3, y3), UT(y3, m3));
let b3 = Number.POSITIVE_INFINITY;
const x3 = (t35) => {
const e5 = Ye(t35, n4);
e5 < b3 && l4(t35) && (_3 = t35, b3 = e5);
};
for (const t35 of p3)
for (const e5 of JT(n4, t35))
x3(e5);
for (let t35 = 0;t35 < p3.length; t35 += 1) {
const e5 = p3[t35];
if (!(Ye(n4, HT(n4, e5.bounds)) > b3))
for (let o5 = t35 + 1;o5 < p3.length; o5 += 1) {
const t36 = p3[o5];
if (Xe(e5.bounds, t36.bounds) && !(Ye(n4, HT(n4, t36.bounds)) > b3))
for (const n5 of KT(e5, t36))
x3(n5);
}
}
return _3;
})(t33, h2, a3, S2, [y2.z, i2], s2);
return P2 ||= l3 !== undefined && l3 !== a3, l3;
}, N2 = v2 ? M2("start") : undefined, w2 = I2 ? M2("end") : undefined;
if (v2 && !N2 || I2 && !w2 || c2 && !P2)
return false;
const T2 = [];
for (let t34 = 0;t34 < _2; t34 += 1)
UE(T2, d2[t34]);
const R2 = d2[_2], E2 = _2 > 0 && rR(d2[_2 - 1], R2), A2 = d2[b2], O2 = b2 < d2.length - 1 && rR(d2[b2 + 1], A2);
v2 ? (UE(T2, u2), UE(T2, { ...u2, ...N2, pcb_port_id: undefined }), UE(T2, { ...u2, ...N2, z: i2, pcb_port_id: undefined })) : (E2 || UE(T2, { ...R2, pcb_port_id: undefined }), UE(T2, { ...R2, z: i2, pcb_port_id: undefined }));
const k2 = I2 ? b2 - 1 : b2;
for (let t34 = _2 + 1;t34 <= k2; t34 += 1)
UE(T2, { ...d2[t34], z: i2, pcb_port_id: undefined });
I2 ? (UE(T2, { ...p2, ...w2, z: i2, pcb_port_id: undefined }), UE(T2, { ...p2, ...w2, pcb_port_id: undefined }), UE(T2, p2)) : O2 || UE(T2, { ...A2, pcb_port_id: undefined });
for (let t34 = b2 + 1;t34 < d2.length; t34 += 1)
UE(T2, d2[t34]);
for (let t34 = 1;t34 < T2.length - 1; t34 += 1)
T2[t34].pcb_port_id = undefined;
const D2 = t33.minBoardEdgeClearance ?? 0.2, L2 = yR(h2, o2), z2 = fR([h2]);
for (let e3 = 1;e3 < T2.length; e3 += 1) {
const n3 = T2[e3 - 1], o3 = T2[e3];
if (n3.z === o3.z && !L2.some((t34) => LR(n3, t34.start, t34.end) && LR(o3, t34.start, t34.end)) && YR(t33, n3, o3) < h2.traceThickness / 2 + D2)
return false;
if (n3.z !== o3.z && n3.toNextSegmentType !== "through_obstacle" && !z2.some((t34) => rR(t34, o3) && t34.radius >= S2) && $R(t33, o3) < S2 + D2)
return false;
}
return h2.route = T2, true;
};
var qE = (t33, e2, n2, o2, i2, r2, s2) => {
const a2 = aR(n2);
if (a2 !== "pcb_pad_trace_clearance_error" && a2 !== "pcb_trace_error")
return false;
if (i2 < 0 || i2 >= t33.layerCount)
return false;
const c2 = YE(n2, o2);
if (c2 === undefined)
return false;
const l2 = e2[c2];
if (!l2 || l2.route.length < 2)
return false;
const h2 = l2.route[0], d2 = l2.route.at(-1);
if (!h2 || !d2 || h2.z !== d2.z || i2 === h2.z)
return false;
if (l2.route.some((t34) => t34.z !== h2.z))
return false;
if (!h2.pcb_port_id || !d2.pcb_port_id)
return false;
if (!XE(t33, l2, h2, r2, s2) || !XE(t33, l2, d2, r2, s2))
return false;
const u2 = l2.route.map((t34) => ({ ...t34 }));
return l2.route = [u2[0], { ...u2[0], z: i2, pcb_port_id: undefined }, ...u2.slice(1, -1).map((t34) => ({ ...t34, z: i2 })), { ...u2.at(-1), z: i2, pcb_port_id: undefined }, u2.at(-1)], true;
};
var JE = (t33, e2, n2, o2, i2, r2, s2) => {
if (aR(n2) !== "pcb_pad_trace_clearance_error")
return false;
const a2 = YE(n2, o2);
if (a2 === undefined)
return false;
const c2 = e2[a2];
if (!c2 || c2.route.length < 4)
return false;
const l2 = c2.route.map((t34) => ({ ...t34 }));
if (i2 === "start") {
const e3 = l2[0];
if (!XE(t33, c2, e3, r2, s2))
return false;
let n3 = -1;
for (let t34 = 1;t34 < l2.length; t34 += 1)
if (l2[t34].z !== e3.z) {
n3 = t34;
break;
}
if (n3 <= 0)
return false;
const o3 = n3 - 1;
if (!rR(l2[o3], l2[n3]))
return false;
let i3 = n3;
for (;i3 + 1 < l2.length && rR(l2[n3], l2[i3 + 1]); )
i3 += 1;
const a3 = l2[i3].z, h3 = l2.slice(o3, i3 + 1).map((t34) => t34.z);
return c2.route = [e3, ...h3.slice(1).map((t34) => ({ ...e3, z: t34, pcb_port_id: undefined })), ...l2.slice(1, o3 + 1).map((t34) => ({ ...t34, z: a3 })), ...l2.slice(i3 + 1)], true;
}
const h2 = l2.at(-1);
if (!XE(t33, c2, h2, r2, s2))
return false;
let d2 = -1;
for (let t34 = l2.length - 2;t34 >= 0; t34 -= 1)
if (l2[t34].z !== h2.z) {
d2 = t34;
break;
}
if (d2 < 0 || d2 >= l2.length - 1)
return false;
const u2 = d2 + 1;
if (!rR(l2[d2], l2[u2]))
return false;
let p2 = d2;
for (;p2 - 1 >= 0 && rR(l2[d2], l2[p2 - 1]); )
p2 -= 1;
const m2 = l2[p2].z, g2 = l2.slice(p2, u2 + 1).map((t34) => t34.z);
return c2.route = [...l2.slice(0, p2 + 1), ...l2.slice(u2 + 1, -1).map((t34) => ({ ...t34, z: m2 })), { ...h2, z: m2, pcb_port_id: undefined }, ...g2.slice(1, -1).map((t34) => ({ ...h2, z: t34, pcb_port_id: undefined })), h2], true;
};
var QE = (t33, e2) => {
const n2 = t33.pcb_trace_id;
if (typeof n2 != "string")
return;
if (Array.isArray(t33.pcb_via_ids) && t33.pcb_via_ids.length > 0)
return;
const o2 = Array.isArray(t33.pcb_trace_ids) ? t33.pcb_trace_ids.filter((t34) => typeof t34 == "string") : [], i2 = t33.pcb_trace_error_id, r2 = `overlap_${n2}_`, s2 = typeof i2 == "string" && i2.startsWith(r2) ? i2.slice(r2.length) : undefined, a2 = [n2, ...o2, ...s2 ? [s2] : []], c2 = [...new Set(a2.map((t34) => e2.get(t34)).filter((t34) => t34 !== undefined))];
return c2.length >= 2 ? [c2[0], c2[1]] : undefined;
};
var KE = (t33, e2, n2, o2, i2) => {
if (aR(n2) !== "pcb_trace_error")
return;
const r2 = QE(n2, o2);
if (!r2)
return;
const s2 = n2.worst_contact_center ?? n2.center;
if (!s2 || typeof s2 != "object")
return;
const a2 = s2;
if (typeof a2.x != "number" || typeof a2.y != "number")
return;
const c2 = { x: a2.x, y: a2.y }, l2 = _R(e2), h2 = pE(l2, c2, r2[0]), d2 = pE(l2, c2, r2[1]);
if (!h2 || !d2 || h2.z !== d2.z)
return;
const [u2] = yE(h2, d2);
if (!u2)
return;
const p2 = u2.leftPoint.x - u2.rightPoint.x, m2 = u2.leftPoint.y - u2.rightPoint.y, g2 = Math.hypot(p2, m2), f2 = Number(n2.minimum_clearance), y2 = Number.isFinite(f2) ? f2 : wT.traceClearance, _2 = h2.radius + d2.radius + y2 - g2;
if (_2 <= pC)
return;
const b2 = i2 === 0 ? h2 : d2, x2 = i2 === 0 ? u2.leftT : u2.rightT, v2 = (1 - x2) ** 2 + x2 ** 2;
if (v2 <= pC)
return;
const I2 = _2 / v2, S2 = i2 === 0 ? u2.leftPoint : u2.rightPoint, C2 = i2 === 0 ? u2.rightPoint : u2.leftPoint, P2 = i2 === 0 ? 1 : -1, M2 = b2.end.x - b2.start.x, N2 = b2.end.y - b2.start.y, w2 = Math.hypot(M2, N2), T2 = (b2.routeIndex + (i2 === 0 ? d2.routeIndex : h2.routeIndex)) % 2 == 0 ? 1 : -1, R2 = g2 > pC ? (S2.x - C2.x) / g2 : w2 > pC ? -N2 / w2 * T2 * P2 : P2, E2 = g2 > pC ? (S2.y - C2.y) / g2 : w2 > pC ? M2 / w2 * T2 * P2 : 0;
return _E(e2, b2, R2 * I2, E2 * I2, t33, x2) ? { movedRouteIndex: b2.routeIndex } : undefined;
};
var tA = (t33) => {
const { srj: e2, via: n2, segment: o2, segments: i2, initialTarget: r2, requiredTraceDistance: s2, requiredObstacleDistance: a2, connMap: c2 } = t33, l2 = Math.min(...n2.zLayers), h2 = Math.max(...n2.zLayers), d2 = e2.obstacles.filter((t34) => !t34.isCopperPour && !LT(n2.rootConnectionName, t34, c2) && IR(t34, e2.layerCount).some((t35) => t35 >= l2 && t35 <= h2)), u2 = d2.filter((t34) => Boolean(RR(r2, t34, a2))), p2 = [r2, ...eR(n2, i2, s2 - n2.radius - o2.radius, c2), ...u2.flatMap((t34) => ((t35) => {
const { point: e3, obstacle: n3, requiredDistance: o3 } = t35, i3 = n3.center.x - n3.width / 2, r3 = n3.center.x + n3.width / 2, s3 = n3.center.y - n3.height / 2, a3 = n3.center.y + n3.height / 2, c3 = Math.max(i3 - e3.x, e3.x - r3, 0), l3 = Math.max(s3 - e3.y, e3.y - a3, 0), h3 = [];
if (c3 < o3) {
const t36 = Math.sqrt(o3 * o3 - c3 * c3);
h3.push({ x: e3.x, y: s3 - t36 - pC }, { x: e3.x, y: a3 + t36 + pC });
}
if (l3 < o3) {
const t36 = Math.sqrt(o3 * o3 - l3 * l3);
h3.push({ x: i3 - t36 - pC, y: e3.y }, { x: r3 + t36 + pC, y: e3.y });
}
return h3;
})({ point: r2, obstacle: t34, requiredDistance: a2 }))];
return p2.filter((t34) => {
if (!GE(t34, n2.radius, e2.bounds))
return false;
const r3 = PR(t34, o2);
return !(Math.hypot(t34.x - r3.x, t34.y - r3.y) < s2 - pC) && (!i2.some((e3) => e3.z >= l2 && e3.z <= h2 && !DT(n2.rootConnectionName, e3.rootConnectionName, c2) && be(t34, e3.start, e3.end) < s2 + e3.radius - o2.radius - pC) && d2.every((e3) => MR(t34, e3) >= a2 - pC));
}).sort((t34, e3) => Math.hypot(t34.x - n2.x, t34.y - n2.y) - Math.hypot(e3.x - n2.x, e3.y - n2.y))[0];
};
var eA = (t33, e2, n2, o2, i2, r2) => {
if (aR(n2) !== "pcb_trace_error")
return false;
const s2 = typeof n2.pcb_trace_error_id == "string" ? n2.pcb_trace_error_id.toLowerCase() : "", a2 = typeof n2.message == "string" ? n2.message.toLowerCase() : "";
if (!(typeof n2.pcb_via_id == "string" || Array.isArray(n2.pcb_via_ids) || s2.includes("_via_") || a2.includes("via")))
return false;
if (YE(n2, o2) !== i2)
return false;
if (QE(n2, o2))
return false;
const c2 = n2.worst_contact_center ?? n2.center;
if (!c2 || typeof c2 != "object")
return false;
const l2 = c2;
if (typeof l2.x != "number" || typeof l2.y != "number")
return false;
const h2 = { x: l2.x, y: l2.y }, d2 = _R(e2), u2 = pE(d2, h2, i2), p2 = Array.isArray(n2.pcb_trace_ids) ? n2.pcb_trace_ids.filter((t34) => typeof t34 == "string" && t34 !== n2.pcb_trace_id) : [], m2 = p2.map((t34) => o2.get(t34)).filter((t34) => t34 !== undefined), g2 = fR(e2), f2 = mE(p2.length > 0 ? g2.filter((t34) => m2.includes(t34.routeIndex)) : g2, h2);
if (!u2 || !f2 || !f2.movable || DT(f2.rootConnectionName, u2.rootConnectionName, r2))
return false;
const y2 = PR(f2, u2), _2 = f2.x - y2.x, b2 = f2.y - y2.y, x2 = Math.hypot(_2, b2), v2 = Number(n2.minimum_clearance), I2 = Number.isFinite(v2) ? v2 : wT.traceClearance, S2 = f2.radius + u2.radius + I2 - x2;
if (S2 <= pC)
return false;
const C2 = u2.end.x - u2.start.x, P2 = u2.end.y - u2.start.y, M2 = Math.hypot(C2, P2), N2 = f2.routeIndex % 2 == 0 ? 1 : -1, w2 = x2 > pC ? _2 / x2 : M2 > pC ? -P2 / M2 * N2 : 1, T2 = x2 > pC ? b2 / x2 : M2 > pC ? C2 / M2 * N2 : 0, R2 = f2.radius + u2.radius + I2, E2 = f2.radius + bC(t33) + yC, A2 = { x: f2.x + w2 * (S2 + yC), y: f2.y + T2 * (S2 + yC) }, O2 = tA({ srj: t33, via: f2, segment: u2, segments: d2, initialTarget: A2, requiredTraceDistance: R2, requiredObstacleDistance: E2, connMap: r2 });
return !!O2 && hE(e2, f2, O2.x - f2.x, O2.y - f2.y, t33);
};
var nA = (t33, e2, n2) => {
if (aR(e2) !== "pcb_trace_error")
return;
const o2 = OE(e2), i2 = t33[n2];
if (!o2 || !i2)
return;
const r2 = pE(yR(i2, n2), o2);
return r2 ? { center: o2, route: i2, segment: r2 } : undefined;
};
var oA = (t33, e2, n2, o2) => {
const i2 = nA(t33, e2, n2);
if (!i2)
return;
const { route: r2, segment: s2 } = i2, a2 = Math.max(0, s2.startIndex - o2), c2 = Math.min(r2.route.length - 1, s2.endIndex + o2), l2 = r2.route.slice(a2, c2 + 1), h2 = l2[0], d2 = l2.at(-1);
return h2 && d2 && !l2.some((t34) => t34.z !== h2.z) && h2.z === d2.z ? { route: r2, spanStartIndex: a2, spanEndIndex: c2, start: h2, end: d2 } : undefined;
};
var iA = (t33, e2, n2, o2, i2, r2, s2 = 0, a2, c2) => {
if (r2 < 0 || r2 >= t33.layerCount)
return false;
const l2 = QE(n2, o2);
if (!l2)
return false;
const h2 = l2[i2], d2 = nA(e2, n2, h2);
if (!d2 || d2.segment.z === r2)
return false;
const { route: u2, segment: p2 } = d2;
let { startIndex: m2, endIndex: g2 } = p2;
for (let t34 = 0;t34 < s2; t34 += 1) {
const t35 = u2.route[m2 - 1];
t35?.z === p2.z && (m2 -= 1);
const e3 = u2.route[g2 + 1];
e3?.z === p2.z && (g2 += 1);
}
if (m2 === 0 && u2.route[0]?.pcb_port_id && !XE(t33, u2, u2.route[0], a2, c2) || g2 === u2.route.length - 1 && u2.route.at(-1)?.pcb_port_id && !XE(t33, u2, u2.route.at(-1), a2, c2))
return false;
const f2 = u2.route[m2], y2 = u2.route[g2];
if (!f2 || !y2 || f2.z !== y2.z)
return false;
const _2 = u2.route.slice(m2, g2 + 1).map((t34) => ({ ...t34, z: r2, pcb_port_id: undefined }));
return u2.route.splice(m2, g2 - m2 + 1, { ...f2 }, ..._2, { ...y2 }), true;
};
var rA = (t33, e2, n2, o2, i2, r2) => {
if (o2 <= 0 || i2 <= 0)
return false;
const s2 = nA(t33, e2, n2);
if (!s2)
return false;
const { center: a2, route: c2, segment: l2 } = s2, h2 = l2.end.x - l2.start.x, d2 = l2.end.y - l2.start.y, u2 = Math.hypot(h2, d2);
if (u2 <= pC)
return false;
const p2 = PR(a2, l2), m2 = zT(p2.t - o2 / u2, 0.02, 0.98), g2 = zT(p2.t + o2 / u2, 0.02, 0.98);
if (m2 >= g2)
return false;
const f2 = (t34) => ({ x: l2.start.x + h2 * t34, y: l2.start.y + d2 * t34, z: l2.z }), y2 = f2(m2), _2 = f2(g2), b2 = -d2 / u2 * r2, x2 = h2 / u2 * r2, v2 = c2.route[l2.startIndex], I2 = c2.route[l2.endIndex];
return c2.route.splice(l2.startIndex, 2, { ...v2 }, y2, { ...y2, x: y2.x + b2 * i2, y: y2.y + x2 * i2 }, { ..._2, x: _2.x + b2 * i2, y: _2.y + x2 * i2 }, _2, { ...I2 }), true;
};
var sA = (t33, e2, n2, o2, i2, r2, s2, a2 = false) => {
if (!Number.isInteger(i2) || i2 < 0 || i2 >= t33.layerCount)
return false;
const c2 = OE(n2), l2 = e2[o2], h2 = l2?.route[0], d2 = l2?.route.at(-1);
if (!l2 || !c2 || !h2 || !d2 || h2.z !== d2.z || h2.z === i2 || l2.jumpers?.length || l2.route.some((t34) => t34.z !== h2.z || t34.toNextSegmentType === "through_obstacle"))
return false;
const u2 = d2.x - h2.x, p2 = d2.y - h2.y, m2 = Math.hypot(u2, p2);
if (m2 <= pC || m2 > 8)
return false;
const g2 = u2 / m2, f2 = p2 / m2, y2 = f2 * r2, _2 = -g2 * r2, b2 = (t34) => (t34.x - c2.x) * g2 + (t34.y - c2.y) * f2, x2 = (t34, e3, n3) => ({ x: c2.x + g2 * t34 + y2 * e3, y: c2.y + f2 * t34 + _2 * e3, z: n3 }), v2 = (l2.viaDiameter ?? t33.minViaDiameter ?? 0.3) + (t33.minTraceToPadEdgeClearance ?? wT.traceClearance ?? 0.1), I2 = (a2 ? 1.25 : -0.75) * v2, S2 = (a2 ? -0.75 : 1.25) * v2, C2 = b2(h2) + 0.5 * v2 * s2, P2 = b2(d2) + v2 * s2, M2 = x2(C2, I2, h2.z), N2 = x2(P2, S2, h2.z), w2 = x2(C2, 2 * v2, i2), T2 = x2(P2, 2 * v2, i2), R2 = [{ ...h2 }, M2, { ...M2, z: i2 }, w2, T2, { ...N2, z: i2 }, N2, { ...d2 }], E2 = t33.minBoardEdgeClearance ?? 0, A2 = (l2.viaDiameter ?? t33.minViaDiameter ?? 0.3) / 2, O2 = l2.traceThickness / 2;
if ([M2, N2].some((e3) => $R(t33, e3) + mC < A2 + E2))
return false;
for (let e3 = 0;e3 < R2.length - 1; e3 += 1) {
const n3 = R2[e3], o3 = R2[e3 + 1];
if (n3.z === o3.z && YR(t33, n3, o3) + mC < O2 + E2)
return false;
}
return l2.route.splice(0, l2.route.length, ...R2), true;
};
var aA = (t33, e2, n2, o2, i2, r2, s2) => {
if (!Number.isInteger(i2) || i2 < 1 || r2 <= 0)
return false;
const a2 = oA(e2, n2, o2, i2);
if (!a2)
return false;
const { route: c2, spanStartIndex: l2, spanEndIndex: h2, start: d2, end: u2 } = a2, p2 = u2.x - d2.x, m2 = u2.y - d2.y, g2 = Math.hypot(p2, m2);
if (g2 <= pC)
return false;
const f2 = -m2 / g2 * s2 * r2, y2 = p2 / g2 * s2 * r2, _2 = { ...d2, x: d2.x + f2, y: d2.y + y2, pcb_port_id: undefined }, b2 = { ...u2, x: u2.x + f2, y: u2.y + y2, pcb_port_id: undefined };
return !(!kR(_2, t33.bounds) || !kR(b2, t33.bounds)) && (c2.route.splice(l2, h2 - l2 + 1, { ...d2 }, _2, b2, { ...u2 }), true);
};
var cA = (t33, e2, n2, o2, i2, r2) => {
if (!Number.isInteger(i2) || i2 < 0)
return false;
const s2 = oA(e2, n2, o2, i2);
if (!s2)
return false;
const { route: a2, spanStartIndex: c2, spanEndIndex: l2, start: h2, end: d2 } = s2;
return !(Math.hypot(r2.x - h2.x, r2.y - h2.y) <= pC || Math.hypot(r2.x - d2.x, r2.y - d2.y) <= pC || !kR(r2, t33.bounds)) && (a2.route.splice(c2, l2 - c2 + 1, { ...h2 }, { x: r2.x, y: r2.y, z: h2.z }, { ...d2 }), true);
};
var lA = (t33, e2, n2, o2, i2, r2) => {
if (r2) {
const e3 = zE(t33), n3 = zE(r2);
if (e3 !== n3)
return e3 < n3;
}
const s2 = BE(t33), a2 = FE(t33);
return s2 < n2 || s2 === n2 && a2 < o2 || s2 === n2 && e2 < i2;
};
var hA = (t33, e2, n2, o2, i2, r2, s2 = true, a2 = false, c2 = true, l2 = false) => {
let h2 = false;
const d2 = fR(e2), u2 = _R(e2);
for (const p2 of n2) {
const n3 = OE(p2);
if (!n3)
continue;
let m2 = n3;
const g2 = p2.pcb_via_ids, f2 = aR(p2) === "pcb_via_clearance_error", y2 = DE(p2), _2 = Array.isArray(g2) && g2.length > 0, b2 = !f2 && !y2 && _2 && (typeof p2.pcb_trace_id == "string" || Array.isArray(p2.pcb_trace_ids)), x2 = l2 && b2;
if (_2 && !b2) {
m2 = ER(t33, p2, n3);
const c3 = YE(p2, o2), l3 = g2.length > 1 ? gE(d2, n3) : undefined;
if (l3) {
const n4 = a2 && aR(p2) === "pcb_via_clearance_error" && p2.pcb_via_pair_net_relation === "same_net", o3 = s2 && aR(p2) === "pcb_via_clearance_error";
h2 = (n4 ? xE(e2, l3[0], l3[1], t33, r2) : bE(e2, l3[0], l3[1], t33, r2, 0.16 * Math.abs(i2), o3)) || h2;
} else {
const o3 = mE(d2, n3, c3);
o3 && (h2 = fE(e2, o3, m2, t33) || h2);
}
continue;
}
const v2 = p2.pcb_trace_id, I2 = YE(p2, o2);
if (x2 && I2 === undefined)
continue;
const S2 = Array.isArray(p2.pcb_trace_ids) ? p2.pcb_trace_ids.filter((t34) => typeof t34 == "string") : [];
if (x2 && typeof v2 == "string" && I2 !== undefined && S2.includes(v2) && S2.some((t34) => t34 !== v2 && !o2.has(t34))) {
const o3 = mE(d2, n3, I2);
if (o3) {
h2 = fE(e2, o3, n3, t33) || h2;
continue;
}
}
const C2 = s2 && !b2 ? QE(p2, o2) : undefined;
if (C2) {
const o3 = pE(u2, n3, C2[0]), i3 = pE(u2, n3, C2[1]);
if (o3 && i3 && IE(e2, o3, i3, t33, r2)) {
h2 = true;
continue;
}
}
const P2 = cR(p2), M2 = P2 && I2 !== undefined ? CE(t33, e2, I2, n3, r2) : undefined, N2 = P2 ? M2?.segment : pE(u2, n3, I2);
if (N2) {
const o3 = P2 ? M2?.obstacle : TR(t33, n3);
if (P2 && !o3)
continue;
m2 = P2 ? o3?.center ?? n3 : ER(t33, p2, n3);
const s3 = x2 ? undefined : mE(d2, n3), a3 = aR(p2) === "pcb_via_trace_clearance_error", l3 = typeof p2.pcb_trace_error_id == "string" ? p2.pcb_trace_error_id.toLowerCase() : "", u3 = typeof p2.message == "string" ? p2.message.toLowerCase() : "", g3 = a3 || typeof p2.pcb_via_id == "string" || Array.isArray(p2.pcb_via_ids) || l3.includes("_via_") || u3.includes("via"), f3 = Array.isArray(p2.pcb_port_ids) && p2.pcb_port_ids.length > 0;
if (s3 && !DT(s3.rootConnectionName, N2.rootConnectionName, r2) && (a3 || Math.hypot(s3.x - n3.x, s3.y - n3.y) < 0.45)) {
if (vE(e2, s3, N2, t33, r2, 0.3 * Math.abs(i2), 1, c2) && (h2 = true, g3 && !f3))
continue;
}
h2 = (o3 !== undefined && (P2 || !LT(N2.rootConnectionName, o3, r2) && SE(o3, N2, t33.layerCount)) ? uE(e2, N2, o3, t33, r2, i2) : dE(e2, N2, m2, t33, i2)) || h2;
}
const w2 = x2 ? undefined : mE(d2, n3);
w2 && Math.hypot(w2.x - n3.x, w2.y - n3.y) < 0.35 && (h2 = fE(e2, w2, m2, t33) || h2);
}
return h2;
};
var dA = 0.000001;
var uA = 0.006;
var pA = [1, 0.5, 0.25, 0.1, 0.05, 0.025];
var mA = (t33, e2) => (e2.traceThickness ?? t33.minTraceWidth) / 2;
var gA = (t33) => t33.minTraceToPadEdgeClearance ?? 0.1;
var fA = (t33, e2) => e2.viaDiameter ?? t33.minViaDiameter ?? 0.3;
var yA = (t33, e2) => xe(t33, e2) < dA;
var _A = (t33) => {
const e2 = [], n2 = (t34) => {
e2.some((e3) => yA(e3, t34)) || e2.push({ x: t34.x, y: t34.y });
};
for (const e3 of t33.vias)
n2(e3);
for (let e3 = 0;e3 < t33.route.length - 1; e3 += 1) {
const o2 = t33.route[e3], i2 = t33.route[e3 + 1];
o2 && i2 && o2.z !== i2.z && (yA(o2, i2) && n2(o2));
}
return e2;
};
var bA = (t33) => xe({ x: 0, y: 0 }, t33) < dA ? { x: 0, y: 0 } : Be({ x: 0, y: 0 }, t33);
var xA = (t33, e2) => {
if (t33.zLayers && t33.zLayers.length > 0)
return t33.zLayers;
const n2 = Array.from({ length: e2 }, (t34, e3) => e3).filter((n3) => t33.layers.includes(HS(n3, e2)));
return n2.length > 0 ? n2 : Array.from({ length: e2 }, (t34, e3) => e3);
};
var vA = (t33, e2, n2) => DT(OT(t33), OT(e2), n2) || DT(OT(t33), e2.connectionName, n2) || DT(t33.connectionName, OT(e2), n2) || DT(t33.connectionName, e2.connectionName, n2);
var IA = (t33, e2, n2) => LT(OT(t33), e2, n2) || LT(t33.connectionName, e2, n2);
var SA = (t33, e2, n2, o2) => !n2.pcb_port_id && t33.obstacles.some((i2) => IA(e2, i2, o2) && xA(i2, t33.layerCount).includes(n2.z) && ((t34, e3) => t34.x >= e3.center.x - e3.width / 2 - dA && t34.x <= e3.center.x + e3.width / 2 + dA && t34.y >= e3.center.y - e3.height / 2 - dA && t34.y <= e3.center.y + e3.height / 2 + dA)(n2, i2));
var CA = (t33, e2, n2, o2, i2) => {
if (!((t34, e3) => t34.zLayers.includes(e3))(i2, n2.z))
return Number.POSITIVE_INFINITY;
const r2 = mA(t33, e2);
return i2.kind === "pad" ? De(n2, o2, i2.obstacle) - (gA(t33) + r2 + uA) : be(i2.center, n2, o2) - (gA(t33) + r2 + i2.diameter / 2 + uA);
};
var PA = (t33, e2, n2) => {
const o2 = n2.kind === "pad" ? n2.obstacle.center : n2.center, i2 = ze(o2, t33, e2);
let r2 = bA({ x: i2.x - o2.x, y: i2.y - o2.y });
if (Math.abs(r2.x) < dA && Math.abs(r2.y) < dA) {
const n3 = e2.x - t33.x, i3 = e2.y - t33.y, s2 = $e(t33, e2), a2 = bA({ x: -i3, y: n3 }), c2 = { x: -a2.x, y: -a2.y };
r2 = xe({ x: s2.x + a2.x, y: s2.y + a2.y }, o2) >= xe({ x: s2.x + c2.x, y: s2.y + c2.y }, o2) ? a2 : c2;
}
return r2;
};
var MA = (t33, e2, n2, o2) => {
if (n2 <= 0 || n2 >= e2.route.length - 1) {
const i3 = e2.route[n2];
return !i3 || !SA(t33, e2, i3, o2);
}
const i2 = e2.route[n2];
if (!i2 || i2.insideJumperPad)
return true;
const r2 = e2.route[n2 - 1], s2 = e2.route[n2 + 1];
return !(!r2 || r2.z === i2.z) || (!(!s2 || s2.z === i2.z) || e2.vias.some((t34) => yA(t34, i2)));
};
var NA = (t33, e2, n2) => {
let o2 = 0;
for (let i2 = 0;i2 < e2.route.length - 1; i2 += 1) {
const r2 = e2.route[i2], s2 = e2.route[i2 + 1];
if (r2 && s2 && r2.z === s2.z && !yA(r2, s2))
for (const i3 of n2) {
const n3 = CA(t33, e2, r2, s2, i3);
if (!(n3 >= 0) && (o2 += n3 * n3, i3.kind === "pad")) {
if (De(r2, s2, i3.obstacle) < dA) {
o2 += 0.01 / (be(i3.obstacle.center, r2, s2) + 0.01);
}
}
}
}
return o2;
};
var wA = (t33, e2, n2, o2) => {
let i2 = 0;
for (let r2 = 0;r2 < e2.route.length - 1; r2 += 1) {
const s2 = e2.route[r2], a2 = e2.route[r2 + 1];
if (s2 && a2 && s2.z === a2.z && !yA(s2, a2)) {
for (const r3 of n2)
if (!vA(e2, r3, o2)) {
for (let n3 = 0;n3 < r3.route.length - 1; n3 += 1) {
const o3 = r3.route[n3], c2 = r3.route[n3 + 1];
if (!o3 || !c2 || o3.z !== s2.z || c2.z !== s2.z || yA(o3, c2))
continue;
const l2 = Oe(s2, a2, o3, c2) - mA(t33, e2) - mA(t33, r3), h2 = gA(t33) + uA - l2;
h2 > 0 && (i2 += h2 * h2);
}
for (const n3 of _A(r3)) {
const o3 = be(n3, s2, a2) - mA(t33, e2) - fA(t33, r3) / 2, c2 = gA(t33) + uA - o3;
c2 > 0 && (i2 += c2 * c2);
}
}
}
}
return i2;
};
var TA = (t33, e2, n2, o2, i2) => {
const r2 = e2.route.map(() => ({ x: 0, y: 0 }));
for (let s2 = 0;s2 < e2.route.length - 1; s2 += 1) {
const a2 = e2.route[s2], c2 = e2.route[s2 + 1];
if (a2 && c2 && a2.z === c2.z && !yA(a2, c2)) {
for (const o3 of n2) {
const n3 = CA(t33, e2, a2, c2, o3);
if (n3 >= 0)
continue;
const l2 = PA(a2, c2, o3);
if (Math.abs(l2.x) < dA && Math.abs(l2.y) < dA)
continue;
const h2 = !MA(t33, e2, s2, i2), d2 = !MA(t33, e2, s2 + 1, i2);
if (!h2 && !d2)
continue;
const u2 = -n3, p2 = h2 && d2 ? 0.5 : h2 ? 1 : 0, m2 = h2 && d2 ? 0.5 : d2 ? 1 : 0;
r2[s2].x += l2.x * u2 * p2, r2[s2].y += l2.y * u2 * p2, r2[s2 + 1].x += l2.x * u2 * m2, r2[s2 + 1].y += l2.y * u2 * m2;
}
for (const n3 of o2)
if (!vA(e2, n3, i2))
for (let o3 = 0;o3 < n3.route.length - 1; o3 += 1) {
const l2 = n3.route[o3], h2 = n3.route[o3 + 1];
if (!l2 || !h2 || l2.z !== a2.z || h2.z !== a2.z || yA(l2, h2))
continue;
const d2 = Oe(a2, c2, l2, h2) - mA(t33, e2) - mA(t33, n3), u2 = t33.minTraceToPadEdgeClearance + uA - d2;
if (u2 <= 0)
continue;
const p2 = $e(a2, c2), m2 = ze(p2, l2, h2);
let g2 = bA({ x: p2.x - m2.x, y: p2.y - m2.y });
if (Math.abs(g2.x) < dA && Math.abs(g2.y) < dA) {
const t34 = c2.x - a2.x, e3 = c2.y - a2.y;
g2 = bA({ x: -e3, y: t34 });
}
const f2 = !MA(t33, e2, s2, i2), y2 = !MA(t33, e2, s2 + 1, i2);
if (!f2 && !y2)
continue;
const _2 = f2 && y2 ? 0.5 : f2 ? 1 : 0, b2 = f2 && y2 ? 0.5 : y2 ? 1 : 0;
r2[s2].x += g2.x * u2 * _2, r2[s2].y += g2.y * u2 * _2, r2[s2 + 1].x += g2.x * u2 * b2, r2[s2 + 1].y += g2.y * u2 * b2;
}
}
}
return r2;
};
var RA = (t33, e2, n2, o2, i2) => ({ ...e2, route: e2.route.map((r2, s2) => {
if (MA(t33, e2, s2, i2))
return { ...r2 };
const a2 = ((t34, e3) => {
const n3 = xe({ x: 0, y: 0 }, t34);
if (n3 <= e3 || n3 < dA)
return t34;
const o3 = e3 / n3;
return { x: t34.x * o3, y: t34.y * o3 };
})(n2[s2] ?? { x: 0, y: 0 }, 0.5);
return { ...r2, x: r2.x + a2.x * o2, y: r2.y + a2.y * o2 };
}), vias: e2.vias.map((t34) => ({ ...t34 })), jumpers: e2.jumpers ? [...e2.jumpers] : undefined });
var EA = (t33, e2) => e2.route.every((e3) => e3.x >= t33.bounds.minX - dA && e3.x <= t33.bounds.maxX + dA && e3.y >= t33.bounds.minY - dA && e3.y <= t33.bounds.maxY + dA);
var AA = (t33, e2, n2, o2, i2) => {
const r2 = ((t34, e3, n3, o3) => {
const i3 = [];
for (const e4 of t34.obstacles)
e4.isCopperPour || IA(n3, e4, o3) || i3.push({ kind: "pad", obstacle: e4, zLayers: xA(e4, t34.layerCount) });
const r3 = Array.from({ length: t34.layerCount }, (t35, e4) => e4);
for (const s3 of e3)
if (s3 !== n3 && !vA(n3, s3, o3))
for (const e4 of _A(s3))
i3.push({ kind: "via", center: { x: e4.x, y: e4.y }, diameter: fA(t34, s3), zLayers: r3, connectionName: s3.connectionName, rootConnectionName: s3.rootConnectionName });
return i3;
})(t33, e2, n2, i2), s2 = e2.filter((t34, e3) => e3 !== o2 && t34 !== n2);
let a2 = n2, c2 = NA(t33, a2, r2) + wA(t33, a2, s2, i2);
for (let e3 = 0;e3 < 160 && !(c2 <= dA); e3 += 1) {
const e4 = TA(t33, a2, r2, s2, i2);
if (e4.every((t34) => xe(t34, { x: 0, y: 0 }) < 0.000000001))
break;
let n3 = null, o3 = c2;
for (const l2 of pA) {
const h2 = RA(t33, a2, e4, l2, i2), d2 = NA(t33, h2, r2) + wA(t33, h2, s2, i2);
if (d2 < c2 - 0.000001 && EA(t33, h2)) {
n3 = h2, o3 = d2;
break;
}
}
if (!n3)
break;
a2 = n3, c2 = o3;
}
return a2;
};
var OA = 0.000001;
var kA = [1, 0.5, 0.25, 0.1, 0.05, 0.025];
var DA = (t33, e2) => t33.some((t34) => e2.includes(t34));
var LA = (t33, e2, n2, o2) => (LT(t33.rootConnectionName, n2, o2) || LT(e2.connectionName, n2, o2)) && MR(t33, n2) <= OA;
var zA = (t33, e2, n2, o2) => {
const i2 = [], r2 = e2[n2.routeIndex];
if (!r2)
return i2;
for (const e3 of t33.obstacles) {
if (e3.isCopperPour || LA(n2, r2, e3, o2))
continue;
const s2 = IR(e3, t33.layerCount);
DA(n2.zLayers, s2) && i2.push({ obstacle: e3 });
}
return i2;
};
var BA = (t33, e2, n2) => MR(e2, n2.obstacle) - (e2.radius + t33.minViaEdgeToPadEdgeClearance + 0.006);
var FA = (t33, e2, n2, o2) => fR(e2, t33.minViaDiameter).filter((t34) => t34.routeIndex === n2).reduce((n3, i2) => n3 + ((t34, e3, n4, o3) => {
let i3 = 0;
for (const r2 of zA(t34, e3, n4, o3)) {
const e4 = BA(t34, n4, r2);
!(e4 >= 0) && (i3 += e4 * e4, MR(n4, r2.obstacle) < OA) && (i3 += 0.01 / (xe(n4, r2.obstacle.center) + 0.01));
}
return i3;
})(t33, e2, i2, o2), 0);
var jA = (t33, e2, n2, o2) => {
const i2 = e2[n2];
if (!i2)
return [];
const r2 = i2.route.map(() => ({ x: 0, y: 0 })), s2 = fR(e2, t33.minViaDiameter).filter((t34) => t34.routeIndex === n2);
for (const n3 of s2)
if (n3.movable)
for (const i3 of zA(t33, e2, n3, o2)) {
const e3 = n3.radius + t33.minViaEdgeToPadEdgeClearance + 0.006, o3 = RR(n3, i3.obstacle, e3);
if (o3)
for (const t34 of n3.pointIndexes)
r2[t34].x += o3.direction.x * o3.penetration, r2[t34].y += o3.direction.y * o3.penetration;
}
return r2;
};
var $A = (t33, e2, n2, o2) => {
const i2 = new Set(fR([e2], t33.minViaDiameter).flatMap((t34) => t34.movable ? t34.pointIndexes : []));
return { ...e2, route: e2.route.map((t34, e3) => {
if (!i2.has(e3))
return { ...t34 };
const r2 = ((t35, e4) => {
const n3 = xe({ x: 0, y: 0 }, t35);
if (n3 <= e4 || n3 < OA)
return t35;
const o3 = e4 / n3;
return { x: t35.x * o3, y: t35.y * o3 };
})(n2[e3] ?? { x: 0, y: 0 }, 0.5);
return { ...t34, x: t34.x + r2.x * o2, y: t34.y + r2.y * o2 };
}), vias: e2.vias.map((t34) => ({ ...t34 })), jumpers: e2.jumpers ? [...e2.jumpers] : undefined };
};
var YA = (t33, e2) => e2.route.every((e3) => e3.x >= t33.bounds.minX - OA && e3.x <= t33.bounds.maxX + OA && e3.y >= t33.bounds.minY - OA && e3.y <= t33.bounds.maxY + OA);
var XA = (t33, e2, n2, o2, i2) => {
let r2 = n2, s2 = FA(t33, e2, o2, i2);
for (let n3 = 0;n3 < 160 && !(s2 <= OA); n3 += 1) {
const n4 = jA(t33, e2, o2, i2);
if (n4.every((t34) => xe(t34, { x: 0, y: 0 }) < 0.000000001))
break;
let a2 = null, c2 = s2;
for (const l2 of kA) {
const h2 = $A(t33, r2, n4, l2), d2 = [...e2];
d2[o2] = h2;
const u2 = FA(t33, d2, o2, i2);
if (u2 < s2 - 0.000001 && YA(t33, h2)) {
a2 = h2, c2 = u2;
break;
}
}
if (!a2)
break;
e2[o2] = a2, r2 = a2, s2 = c2;
}
return r2;
};
var WA = [0.2, 0.4, 0.8, 1.2].flatMap((t33) => [0.2, 0.3, 0.45, 0.6].flatMap((e2) => [-1, 1].map((n2) => ({ halfSpan: t33, offset: e2, directionSign: n2 })))).flatMap((t33) => [0, 1].map((e2) => ({ kind: "segment", routeSide: e2, ...t33 })));
var VA = [1, -1].flatMap((t33) => [1, -1].flatMap((e2) => [false, true].flatMap((n2) => [0, 1].map((o2) => ({ routeSide: o2, normalDirectionSign: t33, tangentDirectionSign: e2, reverseEndpointOffsets: n2 })))));
var HA = [0, 1].map((t33) => ({ kind: "displacementChain", routeSide: t33 }));
var GA = [...HA, ...[-1, 1].flatMap((t33) => [0, 1].map((e2) => ({ kind: "segment", routeSide: e2, halfSpan: 0.4, offset: 1.2, directionSign: t33 }))), ...[-1, 1].flatMap((t33) => [0, 1].map((e2) => ({ kind: "span", routeSide: e2, spanExpansion: 3, offset: 1.8, directionSign: t33 }))), ...[{ dx: -2.4, dy: -0.4 }, { dx: -2.4, dy: 0.4 }, { dx: 2.4, dy: -0.4 }, { dx: 2.4, dy: 0.4 }, { dx: -0.4, dy: -2.4 }, { dx: -0.4, dy: 2.4 }, { dx: 0.4, dy: -2.4 }, { dx: 0.4, dy: 2.4 }].flatMap((t33) => [0, 1].map((e2) => ({ kind: "waypoint", routeSide: e2, spanExpansion: 2, ...t33 }))), ...[{ dx: -0.17, dy: 0 }, { dx: 0.17, dy: 0 }, { dx: 0, dy: -0.17 }, { dx: 0, dy: 0.17 }].flatMap((t33) => [0, 1].map((e2) => ({ kind: "waypoint", routeSide: e2, spanExpansion: 0, ...t33 }))), ...WA];
var UA = [0, 1, 2];
var ZA = class extends kt {
srj;
inputHdRoutes;
guardedInputHdRoutes;
connMap;
effort;
drcEvaluator;
referenceDrcEvaluator;
autoroutingDrcEngine;
viaHoleDiameter;
configuredMaxIterations;
enableBroadFallback;
enableLargeBoardBroadFallback;
enableTargetedErrorSweep;
enablePostSolveClearanceRelaxation;
enableSafeTraceLayerMoves;
enableViaInPadLayerMoves;
enableTraceViaOwnerTargeting;
outputHdRoutes;
initialDrcIssueCount;
initialRepairDrcIssueCount;
initialLowCountErrorsHaveMovableTraces = false;
broadForceAccepted = false;
targetedForceAccepted = false;
candidateAttempts = 0;
viaInPadCandidateAttempts = 0;
viaInPadCandidatesAccepted = 0;
padTopologyErrorCursor = 0;
safeTraceLayerCursorByErrorId = new Map;
traceLayerCorridorCursorByErrorId = new Map;
tracePairDetourCursorByErrorId = new Map;
errorCursor = 0;
stalledIterations = 0;
bestDrcIssueCountSeen;
bestDrcIssueScoreSeen;
lastDrcCountImprovementCheckIteration = 0;
drcCountPlateauChecks = 0;
largeBoardBroadFallbackMisses = 0;
outputSnapshot;
legacyCleanCheckpoint;
viaPadRepairRolledBack = false;
referenceInputDrcIssueCount;
referenceCandidateDrcIssueCount;
referenceCandidateRolledBack = false;
referenceInputSnapshot;
inputSnapshot;
constructor(t33) {
if (super(), this.srj = t33.srj, this.inputHdRoutes = t33.hdRoutes, this.guardedInputHdRoutes = RE(oR(t33.hdRoutes)), this.connMap = t33.connMap, this.effort = t33.effort ?? 1, this.drcEvaluator = t33.drcEvaluator, this.referenceDrcEvaluator = t33.referenceDrcEvaluator, this.autoroutingDrcEngine = t33.autoroutingDrcEngine ?? (t33.drcEvaluator ? undefined : new cC(t33.srj, { connMap: t33.connMap, traceClearance: t33.srj.minTraceToPadEdgeClearance ?? wT.traceClearance, viaClearance: t33.srj.minTraceToPadEdgeClearance ?? wT.viaClearance, includeTraceViaOwnerMetadata: t33.enableTraceViaOwnerTargeting ?? false })), t33.viaHoleDiameter !== undefined && (!Number.isFinite(t33.viaHoleDiameter) || t33.viaHoleDiameter <= 0))
throw new Error("viaHoleDiameter must be a positive finite number");
this.viaHoleDiameter = t33.viaHoleDiameter, this.configuredMaxIterations = t33.maxIterations, this.enableBroadFallback = t33.enableBroadFallback ?? true, this.enableLargeBoardBroadFallback = t33.enableLargeBoardBroadFallback ?? true, this.enableTargetedErrorSweep = t33.enableTargetedErrorSweep ?? false, this.enablePostSolveClearanceRelaxation = t33.enablePostSolveClearanceRelaxation ?? true, this.enableSafeTraceLayerMoves = t33.enableSafeTraceLayerMoves ?? false, this.enableViaInPadLayerMoves = t33.enableViaInPadLayerMoves ?? false, this.enableTraceViaOwnerTargeting = t33.enableTraceViaOwnerTargeting ?? false, this.outputHdRoutes = t33.hdRoutes, this.referenceDrcEvaluator && (this.referenceInputSnapshot = this.getReferenceDrcSnapshot(this.inputHdRoutes)), this.MAX_ITERATIONS = this.configuredMaxIterations ?? xC(this.effort);
}
getConstructorParams() {
return [{ srj: this.srj, hdRoutes: this.inputHdRoutes, connMap: this.connMap, effort: this.effort, drcEvaluator: this.drcEvaluator, referenceDrcEvaluator: this.referenceDrcEvaluator, autoroutingDrcEngine: this.autoroutingDrcEngine, viaHoleDiameter: this.viaHoleDiameter, maxIterations: this.configuredMaxIterations, enableBroadFallback: this.enableBroadFallback, enableLargeBoardBroadFallback: this.enableLargeBoardBroadFallback, enableTargetedErrorSweep: this.enableTargetedErrorSweep, enablePostSolveClearanceRelaxation: this.enablePostSolveClearanceRelaxation, enableSafeTraceLayerMoves: this.enableSafeTraceLayerMoves, enableViaInPadLayerMoves: this.enableViaInPadLayerMoves, enableTraceViaOwnerTargeting: this.enableTraceViaOwnerTargeting }];
}
updateStats(t33) {
this.stats = { initialDrcIssueCount: this.initialDrcIssueCount ?? t33.count, finalDrcIssueCount: t33.count, globalDrcForceImproveMaxIterations: this.MAX_ITERATIONS, globalDrcForceImproveBroadForceAccepted: this.broadForceAccepted, globalDrcForceImproveTargetedForceAccepted: this.targetedForceAccepted, globalDrcForceImproveCandidateAttempts: this.candidateAttempts, globalDrcForceImproveViaInPadCandidateAttempts: this.viaInPadCandidateAttempts, globalDrcForceImproveViaInPadCandidatesAccepted: this.viaInPadCandidatesAccepted, globalDrcForceImproveStalledIterations: this.stalledIterations, globalDrcForceImproveBestDrcIssueCountSeen: this.bestDrcIssueCountSeen ?? t33.count, globalDrcForceImproveBestDrcIssueScoreSeen: this.bestDrcIssueScoreSeen ?? t33.issueScore, globalDrcForceImproveDrcCountPlateauChecks: this.drcCountPlateauChecks, globalDrcForceImproveLargeBoardBroadFallbackMisses: this.largeBoardBroadFallbackMisses, globalDrcForceImproveViaPadRepairRolledBack: this.viaPadRepairRolledBack, globalDrcForceImproveReferenceInputDrcIssueCount: this.referenceInputDrcIssueCount, globalDrcForceImproveReferenceCandidateDrcIssueCount: this.referenceCandidateDrcIssueCount, globalDrcForceImproveReferenceCandidateRolledBack: this.referenceCandidateRolledBack };
}
finishAtLegacyCleanCheckpoint() {
const t33 = this.legacyCleanCheckpoint;
return !!t33 && (this.outputHdRoutes = t33.routes, this.outputSnapshot = t33.snapshot, this.viaPadRepairRolledBack = true, this.updateStats(t33.snapshot), this.solved = true, true);
}
increaseMaxIterationsForDrcIssueCount(t33) {
this.configuredMaxIterations === undefined ? this.MAX_ITERATIONS = Math.max(this.MAX_ITERATIONS, ((t34, e2) => Math.max(xC(e2), Math.ceil(t34 * uC * Math.max(1, e2))))(t33, this.effort), ((t34, e2) => t34 > 120 && e2 > 0 ? 192 : 48)(this.inputHdRoutes.length, t33)) : this.MAX_ITERATIONS = this.configuredMaxIterations;
}
getSnapshot(t33) {
return (this.initialLowCountErrorsHaveMovableTraces ? gR : mR)(this.srj, t33, this.drcEvaluator, this.connMap, this.autoroutingDrcEngine);
}
getReferenceDrcSnapshot(t33) {
const e2 = { traces: [], srj: this.srj, routes: t33, hdRoutes: t33 }, n2 = this.referenceDrcEvaluator?.getCachedResult?.(e2);
if (n2) {
const t34 = Array.isArray(n2) ? n2 : n2.errors;
return { errors: t34, count: t34.length };
}
return mR(this.srj, t33, this.referenceDrcEvaluator, this.connMap, this.autoroutingDrcEngine);
}
getViaIssueCount(t33) {
return kE(t33);
}
getRepairIssueCount(t33) {
return BE(t33);
}
getRepairIssueScore(t33) {
return FE(t33);
}
acceptSolvedRoutes(t33, e2) {
const n2 = this.enablePostSolveClearanceRelaxation ? ((t34, e3, n3) => {
if (t34.minTraceToPadEdgeClearance === undefined || t34.minTraceToPadEdgeClearance <= 0)
return e3;
let o3 = false;
const i3 = oR(e3);
for (let e4 = 0;e4 < 4; e4 += 1)
for (let e5 = 0;e5 < i3.length; e5 += 1) {
const r3 = i3[e5];
if (!r3)
continue;
const s3 = AA(t34, i3, r3, e5, n3);
s3 !== r3 && (i3[e5] = s3, o3 = true);
}
return o3 ? i3 : e3;
})(this.srj, t33, this.connMap) : t33, o2 = this.enablePostSolveClearanceRelaxation ? ((t34, e3, n3) => {
if (t34.minViaEdgeToPadEdgeClearance === undefined || t34.minViaEdgeToPadEdgeClearance <= 0)
return e3;
let o3 = false;
const i3 = oR(e3);
for (let e4 = 0;e4 < 4; e4 += 1)
for (let e5 = 0;e5 < i3.length; e5 += 1) {
const r3 = i3[e5];
if (!r3)
continue;
const s3 = XA(t34, i3, r3, e5, n3);
s3 !== r3 && (i3[e5] = s3, o3 = true);
}
return o3 ? RE(i3) : e3;
})(this.srj, n2, this.connMap) : t33, i2 = o2 === t33 ? e2 : this.getSnapshot(o2), r2 = i2.count < e2.count || i2.count === e2.count && i2.issueScore <= e2.issueScore;
let s2 = r2 ? o2 : t33, a2 = r2 ? i2 : e2;
const c2 = this.inputSnapshot ?? this.getSnapshot(this.guardedInputHdRoutes);
if (this.referenceDrcEvaluator) {
const t34 = this.referenceInputSnapshot, e3 = this.getReferenceDrcSnapshot(s2);
this.referenceInputDrcIssueCount = t34.count, this.referenceCandidateDrcIssueCount = e3.count, e3.count > t34.count && (s2 = this.guardedInputHdRoutes, a2 = c2, this.referenceCandidateRolledBack = true);
}
this.outputHdRoutes = s2, this.outputSnapshot = a2, this.stalledIterations = 0, this.updateStats(a2), this.solved = true;
}
updateDrcCountPlateauState(t33) {
const e2 = this.getRepairIssueCount(t33), n2 = this.getRepairIssueScore(t33);
this.bestDrcIssueCountSeen ??= e2, this.bestDrcIssueScoreSeen ??= n2;
const o2 = this.initialRepairDrcIssueCount ?? e2, i2 = this.inputHdRoutes.length > 120 && o2 > 0;
if (this.enableBroadFallback && (!i2 || this.effort >= 2 || this.enableLargeBoardBroadFallback) && (o2 >= 20 || i2) && this.iterations < 192)
return (e2 < this.bestDrcIssueCountSeen || e2 === this.bestDrcIssueCountSeen && n2 < this.bestDrcIssueScoreSeen) && (this.bestDrcIssueCountSeen = e2, this.bestDrcIssueScoreSeen = n2), void (i2 && this.largeBoardBroadFallbackMisses >= 2 && (this.solved = true));
const r2 = ((t34) => t34 >= 20 ? 8 : t34 <= 2 ? 1 : 2)(o2);
if (!(this.iterations - this.lastDrcCountImprovementCheckIteration < r2)) {
if (this.lastDrcCountImprovementCheckIteration = this.iterations, e2 < this.bestDrcIssueCountSeen || e2 === this.bestDrcIssueCountSeen && n2 < this.bestDrcIssueScoreSeen)
return this.bestDrcIssueCountSeen = e2, this.bestDrcIssueScoreSeen = n2, void (this.drcCountPlateauChecks = 0);
this.drcCountPlateauChecks += 1, this.drcCountPlateauChecks >= 2 && (this.solved = true);
}
}
_step() {
let t33 = this.outputHdRoutes, e2 = this.outputSnapshot ?? this.getSnapshot(t33);
const n2 = zE(e2);
if (this.legacyCleanCheckpoint && n2 > 0)
return void this.finishAtLegacyCleanCheckpoint();
if (!this.legacyCleanCheckpoint && n2 === 0 && e2.errors.some(DE) && (this.legacyCleanCheckpoint = { routes: RE(oR(t33)), snapshot: e2 }), this.initialDrcIssueCount === undefined) {
this.inputSnapshot = e2, this.initialDrcIssueCount = e2.count, this.initialRepairDrcIssueCount = this.getRepairIssueCount(e2);
const n3 = $E(e2.errors);
this.initialLowCountErrorsHaveMovableTraces = this.initialRepairDrcIssueCount > 0 && this.initialRepairDrcIssueCount <= 3 && n3.every((t34) => YE(t34, e2.traceRouteIndexById) !== undefined), this.initialLowCountErrorsHaveMovableTraces && (e2 = this.getSnapshot(t33)), this.bestDrcIssueCountSeen = this.getRepairIssueCount(e2), this.bestDrcIssueScoreSeen = this.getRepairIssueScore(e2), this.increaseMaxIterationsForDrcIssueCount(this.getRepairIssueCount(e2));
}
if (e2.count === 0)
return void this.acceptSolvedRoutes(t33, e2);
let o2 = this.getRepairIssueCount(e2), i2 = this.getRepairIssueScore(e2), r2 = this.getViaIssueCount(e2);
const s2 = e2.errors.filter((t34) => Boolean(OE(t34)));
if (s2.length === 0)
return void this.acceptSolvedRoutes(t33, e2);
const a2 = (c2 = this.effort, Math.max(1, Math.round(3 * Math.max(1, c2))));
var c2;
let l2 = 0, h2 = 0, d2 = false, u2 = false, p2 = false;
const m2 = $E(s2), g2 = this.enableTargetedErrorSweep ? m2.find((t34) => t34.type === "pcb_via_clearance_error" && t34.pcb_via_pair_net_relation === "same_net") : undefined, f2 = this.enableTargetedErrorSweep && (this.iterations - 1) % 8 == 0, y2 = g2 ?? (f2 ? m2.find((t34) => t34.type === "pcb_via_clearance_error") : undefined), _2 = y2 ? [y2, ...m2.filter((t34) => t34 !== y2)] : m2, b2 = Math.min(_2.length, Math.max(1, Math.ceil(this.effort))), x2 = y2 ? 0 : this.errorCursor % _2.length, v2 = this.enableTargetedErrorSweep ? ((t34, e3) => {
const n3 = Math.max(2, Math.round(12 * Math.max(1, e3)));
return t34.filter((t35) => aR(t35) === "pcb_trace_error").slice(0, n3);
})(s2, this.effort) : [], I2 = o2 <= 1 || this.initialLowCountErrorsHaveMovableTraces, S2 = !this.initialLowCountErrorsHaveMovableTraces && o2 <= 8 && this.srj.layerCount > 1, C2 = y2 ? [] : s2.filter((t34) => t34.type === "pcb_pad_trace_clearance_error" || (this.enableSafeTraceLayerMoves || I2 || S2) && t34.type === "pcb_trace_error"), P2 = C2.map((t34, e3) => C2[(this.padTopologyErrorCursor + e3) % C2.length]);
for (const n3 of this.enableSafeTraceLayerMoves || this.enableViaInPadLayerMoves ? P2 : []) {
const s3 = !this.enableSafeTraceLayerMoves || h2 >= a2, c3 = !this.enableViaInPadLayerMoves || l2 >= a2;
if (u2 || s3 && c3)
break;
let p3;
this.padTopologyErrorCursor = (C2.indexOf(n3) + 1) % C2.length;
const m3 = typeof n3.pcb_trace_error_id == "string" ? n3.pcb_trace_error_id : typeof n3.pcb_trace_id == "string" ? n3.pcb_trace_id : undefined, g3 = YE(n3, e2.traceRouteIndexById), f3 = QE(n3, e2.traceRouteIndexById);
if (this.enableTraceViaOwnerTargeting && g3 !== undefined && Array.isArray(n3.pcb_via_ids) && n3.pcb_via_ids.length === 1 && l2 < a2) {
const o3 = oR(t33);
if (eA(this.srj, o3, n3, e2.traceRouteIndexById, g3, this.connMap)) {
const t34 = RE(o3), n4 = this.getSnapshot(t34), i3 = this.getViaIssueCount(n4);
l2 += 1, this.candidateAttempts += 1, i3 <= r2 && jE(n4, e2) && (p3 = { routes: t34, snapshot: n4, viaIssueCount: i3, usesViaInPad: false });
}
}
if (this.enableSafeTraceLayerMoves && g3 !== undefined) {
const o3 = f3 ?? [g3], i3 = o3.length * this.srj.layerCount * UA.length, s4 = o3.length * this.srj.layerCount * HE, c4 = i3 + s4, l3 = cR(n3), d3 = l3 ? 0 : i3, u3 = l3 ? s4 : 0;
let y4 = m3 ? this.safeTraceLayerCursorByErrorId.get(m3) ?? 0 : 0, _3 = 0;
for (;h2 < a2 && _3 < c4; ) {
const i4 = y4;
y4 = (y4 + 1) % c4, _3 += 1;
const a3 = i4 >= d3 && i4 < d3 + s4, l4 = i4 - (a3 ? d3 : u3), m4 = l4 % o3.length, g4 = Math.floor(l4 / o3.length), f4 = g4 % this.srj.layerCount, b3 = a3 ? "full" : UA[Math.floor(g4 / this.srj.layerCount) % UA.length], x3 = a3 ? Math.floor(g4 / this.srj.layerCount) : 0, v3 = o3[m4];
let I3 = false;
for (const o4 of [false, true]) {
const i5 = iR(t33, [v3]);
if (!ZE(this.srj, i5, n3, v3, f4, b3, this.connMap, x3, o4))
continue;
const s5 = EE(i5, [v3]);
I3 = true, this.candidateAttempts += 1;
const a4 = this.getSnapshot(s5), c5 = this.getViaIssueCount(a4), l5 = p3?.snapshot ?? e2;
c5 <= (p3?.viaIssueCount ?? r2) && (jE(a4, l5) || p3 !== undefined && BE(a4) === BE(l5) && a4.count < l5.count) && (p3 = { routes: s5, snapshot: a4, viaIssueCount: c5, usesViaInPad: false });
}
I3 && (h2 += 1);
}
m3 && this.safeTraceLayerCursorByErrorId.set(m3, y4);
}
if (this.enableSafeTraceLayerMoves && S2 && m3 && f3) {
let o3 = this.traceLayerCorridorCursorByErrorId.get(m3) ?? 0, i3 = 0;
for (;l2 < a2 && i3 < VA.length; ) {
const s4 = VA[o3 % VA.length];
o3 += 1, i3 += 1;
const a3 = f3[s4.routeSide], c4 = t33[a3]?.route[0]?.z;
if (c4 === undefined)
continue;
const h3 = (c4 + 1) % this.srj.layerCount, d3 = iR(t33, [a3]);
if (!sA(this.srj, d3, n3, a3, h3, s4.normalDirectionSign, s4.tangentDirectionSign, s4.reverseEndpointOffsets))
continue;
const u3 = EE(d3, [a3]);
l2 += 1, this.candidateAttempts += 1;
const m4 = this.getSnapshot(u3), g4 = this.getViaIssueCount(m4), y4 = p3?.snapshot ?? e2;
g4 <= (p3?.viaIssueCount ?? r2) && jE(m4, y4) && (p3 = { routes: u3, snapshot: m4, viaIssueCount: g4, usesViaInPad: false });
}
this.traceLayerCorridorCursorByErrorId.set(m3, o3);
}
if (this.enableSafeTraceLayerMoves && m3 && (this.initialLowCountErrorsHaveMovableTraces && (f3 || g3 !== undefined) || !this.initialLowCountErrorsHaveMovableTraces && f3)) {
const s4 = this.initialLowCountErrorsHaveMovableTraces ? GA : I2 ? [...HA, ...WA] : HA, c4 = f3 ?? [g3];
let h3 = this.tracePairDetourCursorByErrorId.get(m3) ?? 0, u3 = 0;
for (;l2 < a2 && u3 < s4.length; ) {
const m4 = s4[h3 % s4.length];
h3 += 1, u3 += 1;
const g4 = c4[m4.routeSide];
if (g4 === undefined)
continue;
const f4 = this.initialLowCountErrorsHaveMovableTraces && n3.worst_contact_center ? { ...n3, center: n3.worst_contact_center, message: n3.worst_contact_message ?? n3.message, actual_clearance: n3.worst_actual_clearance ?? n3.actual_clearance } : n3;
if (m4.kind === "displacementChain") {
const n4 = oR(t33), s5 = KE(this.srj, n4, f4, e2.traceRouteIndexById, m4.routeSide);
if (!s5)
continue;
d2 = true, l2 += 1, this.candidateAttempts += 1;
let c5 = RE(n4), h4 = this.getSnapshot(c5), u4 = this.getViaIssueCount(h4), g5 = this.getRepairIssueCount(h4);
if (g5 > 0 && l2 < a2) {
const t34 = oR(c5);
let e3 = false;
for (const n5 of h4.errors)
e3 = eA(this.srj, t34, n5, h4.traceRouteIndexById, s5.movedRouteIndex, this.connMap) || e3;
if (e3) {
l2 += 1, this.candidateAttempts += 1;
const e4 = RE(t34), n5 = this.getSnapshot(e4), o3 = this.getViaIssueCount(n5);
lA(n5, o3, g5, this.getRepairIssueScore(h4), u4, h4) && (c5 = e4, h4 = n5, u4 = o3, g5 = this.getRepairIssueCount(h4));
}
}
const y5 = p3 ? this.getRepairIssueCount(p3.snapshot) : o2, _4 = p3 ? this.getRepairIssueScore(p3.snapshot) : i2, b4 = p3?.viaIssueCount ?? r2;
if (u4 <= b4 && lA(h4, u4, y5, _4, b4, p3?.snapshot ?? e2) && (p3 = { routes: c5, snapshot: h4, viaIssueCount: u4, usesViaInPad: false }), g5 === 0)
break;
continue;
}
const y4 = iR(t33, [g4]);
if (!(m4.kind === "segment" ? rA(y4, f4, g4, m4.halfSpan, m4.offset, m4.directionSign) : m4.kind === "span" ? aA(this.srj, y4, f4, g4, m4.spanExpansion, m4.offset, m4.directionSign) : cA(this.srj, y4, f4, g4, m4.spanExpansion, { x: f4.center.x + m4.dx, y: f4.center.y + m4.dy })))
continue;
const _3 = EE(y4, [g4]);
d2 = true, l2 += 1, this.candidateAttempts += 1;
const b3 = this.getSnapshot(_3), x3 = this.getViaIssueCount(b3), v3 = p3 ? this.getRepairIssueCount(p3.snapshot) : o2, I3 = p3 ? this.getRepairIssueScore(p3.snapshot) : i2, S3 = p3?.viaIssueCount ?? r2;
(this.initialLowCountErrorsHaveMovableTraces ? lA(b3, x3, v3, I3, S3, p3?.snapshot ?? e2) : x3 <= S3 && jE(b3, p3?.snapshot ?? e2)) && (p3 = { routes: _3, snapshot: b3, viaIssueCount: x3, usesViaInPad: false });
}
this.tracePairDetourCursorByErrorId.set(m3, h3);
}
for (const s4 of this.enableViaInPadLayerMoves ? ["start", "end"] : []) {
if (l2 >= a2)
break;
if (g3 === undefined)
break;
const c4 = iR(t33, [g3]);
if (!JE(this.srj, c4, n3, e2.traceRouteIndexById, s4, this.connMap, this.viaHoleDiameter))
continue;
const h3 = EE(c4, [g3]);
this.viaInPadCandidateAttempts += 1, l2 += 1, this.candidateAttempts += 1;
const d3 = this.getSnapshot(h3), u3 = this.getViaIssueCount(d3), m4 = p3 ? this.getRepairIssueCount(p3.snapshot) : o2, f4 = p3 ? this.getRepairIssueScore(p3.snapshot) : i2;
lA(d3, u3, m4, f4, p3?.viaIssueCount ?? r2, p3?.snapshot ?? e2) && (p3 = { routes: h3, snapshot: d3, viaIssueCount: u3, usesViaInPad: true });
}
const y3 = this.enableViaInPadLayerMoves ? this.srj.layerCount : 0;
for (let s4 = 0;s4 < y3 && !(l2 >= a2) && g3 !== undefined; s4 += 1) {
const a3 = iR(t33, [g3]);
if (!qE(this.srj, a3, n3, e2.traceRouteIndexById, s4, this.connMap, this.viaHoleDiameter))
continue;
const c4 = EE(a3, [g3]);
this.viaInPadCandidateAttempts += 1, l2 += 1, this.candidateAttempts += 1;
const h3 = this.getSnapshot(c4), d3 = this.getViaIssueCount(h3), u3 = p3 ? this.getRepairIssueCount(p3.snapshot) : o2, m4 = p3 ? this.getRepairIssueScore(p3.snapshot) : i2;
lA(h3, d3, u3, m4, p3?.viaIssueCount ?? r2, p3?.snapshot ?? e2) && (p3 = { routes: c4, snapshot: h3, viaIssueCount: d3, usesViaInPad: true });
}
if (this.enableViaInPadLayerMoves && I2 && f3) {
const s4 = this.iterations % 2 == 0 ? [0, 1] : [1, 0], c4 = this.iterations % 3;
for (const h3 of s4)
for (let s5 = 0;s5 < this.srj.layerCount && !(l2 >= a2); s5 += 1) {
const a3 = f3[h3], d3 = iR(t33, [a3]);
if (!iA(this.srj, d3, n3, e2.traceRouteIndexById, h3, s5, c4, this.connMap, this.viaHoleDiameter))
continue;
const u3 = EE(d3, [a3]);
this.viaInPadCandidateAttempts += 1, l2 += 1, this.candidateAttempts += 1;
const m4 = this.getSnapshot(u3), g4 = this.getViaIssueCount(m4), y4 = p3 ? this.getRepairIssueCount(p3.snapshot) : o2, _3 = p3 ? this.getRepairIssueScore(p3.snapshot) : i2;
lA(m4, g4, y4, _3, p3?.viaIssueCount ?? r2, p3?.snapshot ?? e2) && (p3 = { routes: u3, snapshot: m4, viaIssueCount: g4, usesViaInPad: true });
}
}
p3 && (t33 = p3.routes, e2 = p3.snapshot, o2 = this.getRepairIssueCount(e2), i2 = this.getRepairIssueScore(e2), r2 = p3.viaIssueCount, this.targetedForceAccepted = true, p3.usesViaInPad && (this.viaInPadCandidatesAccepted += 1), u2 = true);
}
if (!u2 && v2.length >= 2) {
const n3 = oR(t33);
let s3 = false;
for (const t34 of v2)
s3 = hA(this.srj, n3, [t34], e2.traceRouteIndexById, 1, this.connMap, true, this.enableTargetedErrorSweep, false, this.enableTraceViaOwnerTargeting) || s3;
if (s3) {
const s4 = RE(n3);
l2 += 1, this.candidateAttempts += 1;
const a3 = this.getSnapshot(s4), c3 = this.getViaIssueCount(a3);
if (lA(a3, c3, o2, i2, r2, e2) && (t33 = s4, e2 = a3, o2 = this.getRepairIssueCount(a3), i2 = this.getRepairIssueScore(a3), r2 = c3, this.targetedForceAccepted = true, u2 = true, a3.count === 0))
return void this.acceptSolvedRoutes(t33, e2);
}
}
for (let n3 = 0;n3 < b2 && l2 < a2 && !u2; n3 += 1) {
const s3 = (x2 + n3) % _2.length, c3 = _2[s3];
if (!c3)
continue;
this.errorCursor = (s3 + 1) % _2.length;
const h3 = o2 === 1;
for (const n4 of vC(this.effort)) {
if (l2 >= a2)
break;
const s4 = oR(t33);
if (!hA(this.srj, s4, [c3], e2.traceRouteIndexById, n4, this.connMap, true, this.enableTargetedErrorSweep, h3, this.enableTraceViaOwnerTargeting))
continue;
const d3 = RE(s4);
l2 += 1, this.candidateAttempts += 1;
const p3 = this.getSnapshot(d3), m3 = this.getViaIssueCount(p3);
if (lA(p3, m3, o2, i2, r2, e2)) {
if (t33 = d3, e2 = p3, o2 = this.getRepairIssueCount(p3), i2 = this.getRepairIssueScore(p3), r2 = m3, this.targetedForceAccepted = true, u2 = true, p3.count === 0)
return void this.acceptSolvedRoutes(t33, e2);
break;
}
}
if (u2)
break;
}
const M2 = t33.length <= 120, N2 = (w2 = s2.length, Math.max(16, Math.min(64, 2 * w2)));
var w2;
const T2 = this.enableLargeBoardBroadFallback && this.MAX_ITERATIONS >= 192 && !M2 && this.stalledIterations > 0 && this.stalledIterations % N2 === 0;
if (this.enableBroadFallback && !u2 && (M2 || this.effort >= 2 && this.stalledIterations >= 2 || T2)) {
p2 = T2;
for (const n3 of [1, 2]) {
const s3 = NE(this.srj, t33, this.effort, n3, this.connMap, this.drcEvaluator === undefined, false);
if (s3 === t33)
continue;
const a3 = this.getSnapshot(s3), c3 = this.getViaIssueCount(a3);
if (lA(a3, c3, o2, i2, r2, e2) && (t33 = s3, e2 = a3, o2 = this.getRepairIssueCount(a3), i2 = this.getRepairIssueScore(a3), r2 = c3, this.broadForceAccepted = true, u2 = true, a3.count === 0))
return void this.acceptSolvedRoutes(t33, e2);
}
}
u2 ? this.largeBoardBroadFallbackMisses = 0 : p2 && (this.largeBoardBroadFallbackMisses += 1), this.outputHdRoutes = t33, this.outputSnapshot = e2, this.stalledIterations = u2 ? 0 : this.stalledIterations + 1, d2 || this.updateDrcCountPlateauState(e2), this.updateStats(e2), (this.solved || o2 === 0) && this.acceptSolvedRoutes(t33, e2);
}
tryFinalAcceptance() {
const t33 = this.outputSnapshot ?? this.getSnapshot(this.outputHdRoutes);
this.legacyCleanCheckpoint && zE(t33) > 0 && this.finishAtLegacyCleanCheckpoint() || this.acceptSolvedRoutes(this.outputHdRoutes, t33);
}
getOutput() {
return this.outputHdRoutes;
}
visualize() {
return super.visualize();
}
preview() {
return this.visualize();
}
};
var qA = class extends kt {
params;
inputHdRoutes;
guardedInputHdRoutes;
broadMaxIterations;
broadPassMultiplier;
autoroutingDrcEngine;
legacyDrcEvaluator;
outputHdRoutes;
phase = "start";
inputSnapshot;
baselineSolver;
baselineSnapshot;
broadInputSnapshot;
broadSnapshot;
broadSolver;
safeTraceLayerInputRoutes;
safeTraceLayerInputSnapshot;
safeTraceLayerSolver;
safeTraceLayerPhaseAccepted = false;
mixedSafeTraceLayerSolver;
mixedSafeTraceLayerPhaseAccepted = false;
legacySafeTraceLayerRoutes;
legacySafeTraceLayerSnapshot;
legacySafeTraceLayerSelectedSolver;
viaInPadSolver;
portfolioSelectedSolver;
selectedSolver;
referenceInputDrcIssueCount;
referenceCandidateDrcIssueCount;
referenceCandidateRolledBack = false;
mixedReferenceInputDrcIssueCount;
mixedReferenceCandidateDrcIssueCount;
referenceInputSnapshot;
constructor(t33) {
if (super(), !Number.isFinite(t33.broadPassMultiplier))
throw new Error("broadPassMultiplier must be a finite number");
if (t33.broadPassMultiplier <= 0)
throw new Error("broadPassMultiplier must be greater than zero");
if (!Number.isInteger(t33.broadMaxIterations))
throw new Error("broadMaxIterations must be an integer");
if (t33.broadMaxIterations <= 0)
throw new Error("broadMaxIterations must be greater than zero");
if (t33.viaInPadMaxIterations !== undefined && !Number.isInteger(t33.viaInPadMaxIterations))
throw new Error("viaInPadMaxIterations must be an integer");
if (t33.viaInPadMaxIterations !== undefined && t33.viaInPadMaxIterations <= 0)
throw new Error("viaInPadMaxIterations must be greater than zero");
this.autoroutingDrcEngine = t33.autoroutingDrcEngine ?? (t33.drcEvaluator ? undefined : new cC(t33.srj, { connMap: t33.connMap, traceClearance: t33.srj.minTraceToPadEdgeClearance ?? wT.traceClearance, viaClearance: t33.srj.minTraceToPadEdgeClearance ?? wT.viaClearance, includeTraceViaOwnerMetadata: t33.enableTraceViaOwnerTargeting ?? false })), this.legacyDrcEvaluator = (e2) => {
const n2 = t33.drcEvaluator?.evaluateLegacy ?? t33.drcEvaluator, o2 = n2 ? n2(e2) : this.autoroutingDrcEngine.evaluateLegacy(e2.traces), i2 = Array.isArray(o2) ? o2 : o2.errors, r2 = Array.isArray(o2) ? o2 : o2.errorsWithCenters ?? o2.errors;
return { errors: i2.filter((t34) => !DE(t34)), errorsWithCenters: r2.filter((t34) => !DE(t34)) };
}, this.params = { ...t33, autoroutingDrcEngine: this.autoroutingDrcEngine }, this.inputHdRoutes = t33.hdRoutes, this.guardedInputHdRoutes = RE(oR(t33.hdRoutes)), this.broadMaxIterations = t33.broadMaxIterations, this.broadPassMultiplier = t33.broadPassMultiplier, this.outputHdRoutes = t33.hdRoutes, this.params.referenceDrcEvaluator && (this.referenceInputSnapshot = this.getReferenceDrcSnapshot(this.inputHdRoutes));
}
getConstructorParams() {
return [{ ...this.params, hdRoutes: this.inputHdRoutes }];
}
stepBranch(t33, e2) {
if (this.activeSubSolver = t33, t33.step(), t33.failed)
throw new Error(`${e2} DRC repair branch failed: ${t33.error}`);
}
getReferenceDrcSnapshot(t33) {
const e2 = { traces: [], srj: this.params.srj, routes: t33, hdRoutes: t33 }, n2 = this.params.referenceDrcEvaluator?.getCachedResult?.(e2);
if (n2) {
const t34 = Array.isArray(n2) ? n2 : n2.errors;
return { errors: t34, count: t34.length };
}
return mR(this.params.srj, t33, this.params.referenceDrcEvaluator, this.params.connMap, this.autoroutingDrcEngine);
}
finishWithOutput(t33, e2, n2) {
let o2 = t33, i2 = e2;
if (this.params.referenceDrcEvaluator) {
const t34 = this.referenceInputSnapshot, e3 = this.getReferenceDrcSnapshot(o2);
this.referenceInputDrcIssueCount = t34.count, this.referenceCandidateDrcIssueCount = e3.count, (e3.count > t34.count || e3.count === t34.count && ((t35, e4) => {
const n3 = new Set(e4.map(LE));
return t35.some((t36) => !n3.has(LE(t36)));
})(e3.errors, t34.errors)) && (o2 = this.guardedInputHdRoutes, i2 = this.inputSnapshot, this.referenceCandidateRolledBack = true);
}
this.outputHdRoutes = o2, this.selectedSolver = n2, this.activeSubSolver = null, this.phase = "done", this.progress = 1, this.stats = { ...this.portfolioSelectedSolver?.stats ?? {}, ...n2?.stats ?? {}, finalDrcIssueCount: i2.count, drcBranchPortfolioInitialDrcIssueCount: this.inputSnapshot?.count ?? e2.count, drcBranchPortfolioBaselineDrcIssueCount: this.baselineSnapshot?.count ?? e2.count, drcBranchPortfolioBroadInitialDrcIssueCount: this.broadInputSnapshot?.count, drcBranchPortfolioBroadFinalDrcIssueCount: this.broadSnapshot?.count, drcBranchPortfolioBroadMaxIterations: this.broadMaxIterations, drcBranchPortfolioBroadBranchAttempted: Boolean(this.broadSolver), drcBranchPortfolioBroadBranchAccepted: this.portfolioSelectedSolver !== undefined && this.portfolioSelectedSolver === this.broadSolver, drcBranchPortfolioSafeTraceLayerPhaseAttempted: Boolean(this.safeTraceLayerSolver), drcBranchPortfolioSafeTraceLayerPhaseAccepted: this.safeTraceLayerPhaseAccepted, drcBranchPortfolioMixedSafeTraceLayerPhaseAttempted: Boolean(this.mixedSafeTraceLayerSolver), drcBranchPortfolioMixedSafeTraceLayerPhaseAccepted: this.mixedSafeTraceLayerPhaseAccepted, drcBranchPortfolioViaInPadPhaseAttempted: Boolean(this.viaInPadSolver), drcBranchPortfolioViaInPadMaxIterations: this.params.viaInPadMaxIterations, drcBranchPortfolioFinalNonViaPadDrcIssueCount: zE(i2), drcBranchPortfolioReferenceInputDrcIssueCount: this.referenceInputDrcIssueCount, drcBranchPortfolioReferenceCandidateDrcIssueCount: this.referenceCandidateDrcIssueCount, drcBranchPortfolioReferenceCandidateRolledBack: this.referenceCandidateRolledBack, drcBranchPortfolioMixedReferenceInputDrcIssueCount: this.mixedReferenceInputDrcIssueCount, drcBranchPortfolioMixedReferenceCandidateDrcIssueCount: this.mixedReferenceCandidateDrcIssueCount }, this.solved = true;
}
startBaselineBranch() {
this.baselineSolver = new ZA({ ...this.params, hdRoutes: this.inputHdRoutes, drcEvaluator: this.legacyDrcEvaluator, referenceDrcEvaluator: undefined, enableSafeTraceLayerMoves: false, enableViaInPadLayerMoves: false }), this.activeSubSolver = this.baselineSolver, this.phase = "baseline";
}
startSafeTraceLayerPhase(t33, e2, n2) {
this.portfolioSelectedSolver = n2, this.params.enableSafeTraceLayerMoves ? (this.safeTraceLayerInputRoutes = t33, this.safeTraceLayerInputSnapshot = e2, this.safeTraceLayerSolver = new ZA({ ...this.params, hdRoutes: t33, drcEvaluator: this.legacyDrcEvaluator, referenceDrcEvaluator: undefined, maxIterations: this.params.viaInPadMaxIterations ?? this.params.maxIterations, enableLargeBoardBroadFallback: false, enableTargetedErrorSweep: false, enablePostSolveClearanceRelaxation: false, enableSafeTraceLayerMoves: true, enableViaInPadLayerMoves: false }), this.activeSubSolver = this.safeTraceLayerSolver, this.phase = "safeTraceLayer") : this.startViaInPadPhase(t33, e2, n2);
}
startViaInPadPhase(t33, e2, n2) {
this.portfolioSelectedSolver = n2;
const o2 = this.params.enableViaInPadLayerMoves && this.params.viaInPadDrcEvaluator !== undefined;
e2.errors.some(DE) || o2 ? (this.viaInPadSolver = new ZA({ ...this.params, hdRoutes: t33, drcEvaluator: this.params.viaInPadDrcEvaluator ?? this.params.drcEvaluator, maxIterations: this.params.viaInPadMaxIterations ?? this.params.maxIterations, enableLargeBoardBroadFallback: false, enableTargetedErrorSweep: false, enablePostSolveClearanceRelaxation: false, enableSafeTraceLayerMoves: false, enableViaInPadLayerMoves: this.params.enableViaInPadLayerMoves }), this.activeSubSolver = this.viaInPadSolver, this.phase = "viaInPad") : this.finishWithOutput(t33, e2, n2);
}
startMixedSafeTraceLayerPhase(t33, e2, n2) {
this.legacySafeTraceLayerRoutes = t33, this.legacySafeTraceLayerSnapshot = e2, this.legacySafeTraceLayerSelectedSolver = n2, this.mixedSafeTraceLayerSolver = new ZA({ ...this.params, hdRoutes: this.safeTraceLayerInputRoutes, drcEvaluator: this.params.drcEvaluator, referenceDrcEvaluator: undefined, maxIterations: this.params.viaInPadMaxIterations ?? this.params.maxIterations, enableLargeBoardBroadFallback: false, enableTargetedErrorSweep: false, enablePostSolveClearanceRelaxation: false, enableSafeTraceLayerMoves: true, enableViaInPadLayerMoves: false }), this.activeSubSolver = this.mixedSafeTraceLayerSolver, this.phase = "mixedSafeTraceLayer";
}
startBroadBranch() {
const t33 = NE(this.params.srj, this.inputHdRoutes, this.params.effort ?? 1, this.broadPassMultiplier, this.params.connMap);
this.broadInputSnapshot = mR(this.params.srj, t33, this.params.drcEvaluator, this.params.connMap, this.autoroutingDrcEngine), jE(this.broadInputSnapshot, this.baselineSnapshot) ? (this.broadSolver = new ZA({ ...this.params, hdRoutes: t33, drcEvaluator: this.legacyDrcEvaluator, referenceDrcEvaluator: undefined, maxIterations: this.broadMaxIterations, enableSafeTraceLayerMoves: false, enableViaInPadLayerMoves: false }), this.activeSubSolver = this.broadSolver, this.phase = "broad") : this.startSafeTraceLayerPhase(this.baselineSolver.getOutput(), this.baselineSnapshot, this.baselineSolver);
}
_step() {
if (this.phase === "start")
return this.inputSnapshot = mR(this.params.srj, this.inputHdRoutes, this.params.drcEvaluator, this.params.connMap, this.autoroutingDrcEngine), zE(this.inputSnapshot) === 0 ? void this.startViaInPadPhase(this.inputHdRoutes, this.inputSnapshot) : void this.startBaselineBranch();
if (this.phase === "baseline") {
if (this.stepBranch(this.baselineSolver, "baseline"), !this.baselineSolver.solved)
return;
const t33 = this.baselineSolver.getOutput();
return this.baselineSnapshot = mR(this.params.srj, t33, this.params.drcEvaluator, this.params.connMap, this.autoroutingDrcEngine), zE(this.baselineSnapshot) === 0 ? void this.startViaInPadPhase(t33, this.baselineSnapshot, this.baselineSolver) : void (this.params.enableSafeTraceLayerMoves && this.baselineSnapshot.count <= 3 ? this.startSafeTraceLayerPhase(t33, this.baselineSnapshot, this.baselineSolver) : this.startBroadBranch());
}
if (this.phase === "broad") {
if (this.stepBranch(this.broadSolver, "broad"), !this.broadSolver.solved)
return;
const t33 = this.broadSolver.getOutput();
return this.broadSnapshot = mR(this.params.srj, t33, this.params.drcEvaluator, this.params.connMap, this.autoroutingDrcEngine), jE(this.broadSnapshot, this.baselineSnapshot) ? void this.startSafeTraceLayerPhase(t33, this.broadSnapshot, this.broadSolver) : void this.startSafeTraceLayerPhase(this.baselineSolver.getOutput(), this.baselineSnapshot, this.baselineSolver);
}
if (this.phase === "safeTraceLayer") {
if (this.stepBranch(this.safeTraceLayerSolver, "safe trace-layer"), !this.safeTraceLayerSolver.solved)
return;
const t33 = this.safeTraceLayerSolver.getOutput(), e2 = mR(this.params.srj, t33, this.params.drcEvaluator, this.params.connMap, this.autoroutingDrcEngine), n2 = kE(this.safeTraceLayerInputSnapshot, false), o2 = kE(e2, false);
this.safeTraceLayerPhaseAccepted = o2 <= n2 && lA(e2, o2, this.safeTraceLayerInputSnapshot.count, this.safeTraceLayerInputSnapshot.issueScore, n2, this.safeTraceLayerInputSnapshot);
const i2 = this.safeTraceLayerPhaseAccepted ? t33 : this.safeTraceLayerInputRoutes, r2 = this.safeTraceLayerPhaseAccepted ? e2 : this.safeTraceLayerInputSnapshot, s2 = this.safeTraceLayerPhaseAccepted ? this.safeTraceLayerSolver : this.portfolioSelectedSolver;
return r2.count > 0 && !this.broadInputSnapshot ? void this.startBroadBranch() : zE(r2) > 0 && this.safeTraceLayerInputSnapshot.errors.some(DE) ? void this.startMixedSafeTraceLayerPhase(i2, r2, s2) : void this.startViaInPadPhase(i2, r2, s2);
}
if (this.phase === "mixedSafeTraceLayer") {
if (this.stepBranch(this.mixedSafeTraceLayerSolver, "mixed safe trace-layer"), !this.mixedSafeTraceLayerSolver.solved)
return;
const t33 = this.mixedSafeTraceLayerSolver.getOutput(), e2 = mR(this.params.srj, t33, this.params.drcEvaluator, this.params.connMap, this.autoroutingDrcEngine), n2 = zE(e2) <= zE(this.legacySafeTraceLayerSnapshot);
let o2 = true;
if (this.params.referenceDrcEvaluator) {
const e3 = this.getReferenceDrcSnapshot(this.legacySafeTraceLayerRoutes), n3 = this.getReferenceDrcSnapshot(t33);
this.mixedReferenceInputDrcIssueCount = e3.count, this.mixedReferenceCandidateDrcIssueCount = n3.count, o2 = n3.count <= e3.count;
}
return this.mixedSafeTraceLayerPhaseAccepted = n2 && o2, void this.startViaInPadPhase(this.mixedSafeTraceLayerPhaseAccepted ? t33 : this.legacySafeTraceLayerRoutes, this.mixedSafeTraceLayerPhaseAccepted ? e2 : this.legacySafeTraceLayerSnapshot, this.mixedSafeTraceLayerPhaseAccepted ? this.mixedSafeTraceLayerSolver : this.legacySafeTraceLayerSelectedSolver);
}
if (this.phase === "viaInPad") {
if (this.stepBranch(this.viaInPadSolver, "via-in-pad"), !this.viaInPadSolver.solved)
return;
const t33 = this.viaInPadSolver.getOutput(), e2 = mR(this.params.srj, t33, this.params.viaInPadDrcEvaluator ?? this.params.drcEvaluator, this.params.connMap, this.autoroutingDrcEngine);
this.finishWithOutput(t33, e2, this.viaInPadSolver);
}
}
getOutput() {
return this.outputHdRoutes;
}
visualize() {
const t33 = this.activeSubSolver ?? this.selectedSolver;
return t33?.visualize() ?? super.visualize();
}
preview() {
const t33 = this.activeSubSolver ?? this.selectedSolver;
return t33?.preview() ?? this.visualize();
}
};
var JA = (t33) => t33.circuitJsonMetadata ?? {};
var QA = ({ connections: t33, obstacles: e2 }) => new Set([...t33.flatMap((t34) => t34.pointsToConnect.flatMap((t35) => t35.pcb_port_id ? [t35.pcb_port_id] : [])), ...e2.flatMap((t34) => {
const e3 = JA(t34).pcb_port_id;
return e3 ? [e3] : [];
})]);
var KA = (t33) => t33.__netConnectionName ?? t33.__rootConnectionNames?.[0] ?? t33.name;
var tO = (t33) => Array.from(new Set([t33.name, t33.__netConnectionName, ...t33.__rootConnectionNames ?? [], ...t33.pointsToConnect.flatMap((t34) => [t34.pointId, t34.pcb_port_id])])).filter((t34) => Boolean(t34));
var eO = (t33, e2) => {
const n2 = new Map, o2 = new Set, i2 = new Map;
for (const r2 of t33) {
const t34 = KA(r2);
for (const e3 of tO(r2)) {
const i3 = n2.get(e3);
i3 && i3 !== t34 ? (n2.delete(e3), o2.add(e3)) : o2.has(e3) || n2.set(e3, t34);
}
const s2 = e2.getNetConnectedToId(r2.name);
if (!s2)
continue;
const a2 = s2, c2 = i2.get(a2) ?? new Set;
c2.add(t34), i2.set(a2, c2);
}
return { connMap: e2, circuitJsonSourceTraceIdBySrjDeclaredConnectionReference: n2, circuitJsonSourceTraceIdsByConnectivityNetId: i2 };
};
var nO = (t33, e2) => {
const n2 = t33.circuitJsonSourceTraceIdBySrjDeclaredConnectionReference.get(e2);
if (n2)
return n2;
const o2 = t33.connMap.getNetConnectedToId(e2);
if (!o2)
return;
const i2 = t33.circuitJsonSourceTraceIdsByConnectivityNetId.get(o2);
return i2?.size === 1 ? i2.values().next().value : undefined;
};
function oO(t33, e2, n2 = t33, o2) {
const i2 = [], r2 = n2 === t33 ? t33.connections : [...t33.connections, ...n2.connections], s2 = n2 === t33 ? t33.obstacles : n2.obstacles, a2 = eO(r2, o2 ?? ii(n2 === t33 ? t33 : { ...n2, connections: r2 })), c2 = QA({ connections: r2, obstacles: s2 });
if (r2.forEach((t34) => {
const n3 = t34.pointsToConnect.map((t35) => t35.pcb_port_id).filter((t35) => Boolean(t35)), o3 = new Set(n3), r3 = (t35) => ((t36) => Array.from(new Set(t36.flatMap((t37) => t37.connectedTo))))(t35).filter((t36) => !o3.has(t36)), c3 = t34.pointsToConnect.map((t35) => t35.pointId).filter((t35) => Boolean(t35)), l2 = nO(a2, t34.name) ?? KA(t34), h2 = [], d2 = e2.find((e3) => (e3.connection_name ?? e3.connectionName) === t34.name);
if (d2) {
const t35 = (t36) => ("route_type" in t36) && t36.route_type === "jumper" ? t36.start : ("x" in t36) && ("y" in t36) ? { x: t36.x, y: t36.y } : { x: 0, y: 0 }, e3 = [t35(d2.route[0]), t35(d2.route[d2.route.length - 1])];
for (const t36 of e3)
for (const e4 of s2)
Fe(t36, e4) <= 0 && h2.push(e4);
}
const u2 = i2.find((t35) => t35.type === "source_trace" && t35.source_trace_id === l2);
if (u2) {
const t35 = u2;
t35.connected_source_port_ids = [...new Set([...t35.connected_source_port_ids, ...n3])], t35.connected_source_net_ids = [...new Set([...t35.connected_source_net_ids ?? [], ...c3, ...r3(h2)])];
} else
i2.push({ type: "source_trace", source_trace_id: l2, connected_source_port_ids: n3, connected_source_net_ids: r3(h2).concat(c3) });
}), e2[0] && "type" in e2[0]) {
const t34 = new Map(r2.map((t35) => [t35.name, t35]));
for (const n3 of e2) {
const e3 = [...new Set((n3.connectsTo ?? []).filter((t35) => c2.has(t35)))], o3 = new Set(e3), r3 = [...new Set((n3.connectsTo ?? []).filter((t35) => !o3.has(t35)))];
if (e3.length === 0 && r3.length === 0)
continue;
const s3 = t34.get(n3.connection_name), l2 = nO(a2, n3.connection_name) ?? n3.connectsTo?.map((t35) => nO(a2, t35)).find((t35) => t35 !== undefined) ?? (s3 ? KA(s3) : n3.connection_name), h2 = i2.find((t35) => t35.type === "source_trace" && t35.source_trace_id === l2);
h2?.type !== "source_trace" ? i2.push({ type: "source_trace", source_trace_id: l2, connected_source_port_ids: e3, connected_source_net_ids: r3 }) : (h2.connected_source_port_ids = [...new Set([...h2.connected_source_port_ids, ...e3])], h2.connected_source_net_ids = [...new Set([...h2.connected_source_net_ids ?? [], ...r3])]);
}
}
return i2;
}
function iO(t33, e2, n2) {
let o2, i2 = Number.POSITIVE_INFINITY;
for (const r2 of e2) {
const e3 = n2.get(r2);
if (!e3)
continue;
const s2 = Math.hypot(e3.x - t33.x, e3.y - t33.y);
s2 < i2 && (i2 = s2, o2 = r2);
}
return o2 ?? e2[0];
}
var rO = new Set(["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6", "inner7", "inner8"]);
var sO = (t33) => rO.has(t33);
function aO(t33) {
const e2 = [], n2 = new Set, o2 = new Set, i2 = function(t34) {
const e3 = new Map;
for (const n3 of t34.connections)
for (const t35 of n3.pointsToConnect)
t35.pcb_port_id && e3.set(t35.pcb_port_id, { x: t35.x, y: t35.y });
return e3;
}(t33), r2 = QA(t33);
for (const s2 of t33.obstacles) {
const t34 = s2.connectedTo, a2 = JA(s2);
if (a2.pcb_via_id)
continue;
const { pcb_smtpad_id: c2, pcb_plated_hole_id: l2 } = a2, h2 = [...new Set([...a2.pcb_port_id ? [a2.pcb_port_id] : [], ...t34.filter((t35) => r2.has(t35))])], d2 = iO(s2.center, h2, i2);
if (!c2 && !l2 && !d2)
continue;
const u2 = s2.layers.filter(sO);
if (u2.length === 0)
continue;
const { width: p2, height: m2 } = s2, g2 = s2.center.x, f2 = s2.center.y, y2 = s2.ccwRotationDegrees;
if (Boolean(l2) || u2.length > 1) {
const t35 = l2 ?? `pcb_plated_hole_${g2.toFixed(3)}_${f2.toFixed(3)}`;
if (o2.has(t35))
continue;
if (o2.add(t35), typeof y2 == "number" && Number.isFinite(y2)) {
const n3 = Math.max(0.5 * Math.min(p2, m2), 0.1);
e2.push({ type: "pcb_plated_hole", pcb_plated_hole_id: t35, shape: "rotated_pill_hole_with_rect_pad", hole_shape: "rotated_pill", pad_shape: "rect", hole_width: n3, hole_height: n3, hole_ccw_rotation: y2, rect_pad_width: p2, rect_pad_height: m2, rect_ccw_rotation: y2, hole_offset_x: 0, hole_offset_y: 0, x: g2, y: f2, layers: u2, ...d2 ? { pcb_port_id: d2 } : {} });
continue;
}
if (Math.abs(p2 - m2) < 0.001) {
e2.push({ type: "pcb_plated_hole", pcb_plated_hole_id: t35, shape: "circle", outer_diameter: Math.max(p2, m2), hole_diameter: Math.max(0.5 * Math.min(p2, m2), 0.1), x: g2, y: f2, layers: u2, ...d2 ? { pcb_port_id: d2 } : {} });
continue;
}
e2.push({ type: "pcb_plated_hole", pcb_plated_hole_id: t35, shape: "circular_hole_with_rect_pad", hole_shape: "circle", hole_diameter: Math.max(0.5 * Math.min(p2, m2), 0.1), rect_pad_width: p2, rect_pad_height: m2, hole_offset_x: 0, hole_offset_y: 0, x: g2, y: f2, layers: u2, ...d2 ? { pcb_port_id: d2 } : {} });
continue;
}
const _2 = c2 ?? `pcb_smtpad_${g2.toFixed(3)}_${f2.toFixed(3)}`;
n2.has(_2) || (n2.add(_2), typeof y2 == "number" && Number.isFinite(y2) ? e2.push({ type: "pcb_smtpad", pcb_smtpad_id: _2, layer: u2[0], shape: "rotated_rect", x: g2, y: f2, width: p2, height: m2, ccw_rotation: y2, ...d2 ? { pcb_port_id: d2 } : {} }) : e2.push({ type: "pcb_smtpad", pcb_smtpad_id: _2, layer: u2[0], shape: "rect", width: p2, height: m2, x: g2, y: f2, ...d2 ? { pcb_port_id: d2 } : {} }));
}
return e2;
}
function cO(t33, e2, n2) {
if (n2 && t33.layers !== undefined)
return t33.layers;
const o2 = n2 ? t33 : { from_layer: "top", to_layer: Co(e2 - 1, e2) };
return GS(o2, e2);
}
function lO(t33) {
const { minX: e2, maxX: n2, minY: o2, maxY: i2 } = t33.bounds;
return { type: "pcb_board", pcb_board_id: "__autorouting_board__", thickness: 1.6, num_layers: t33.layerCount, center: { x: (e2 + n2) / 2, y: (o2 + i2) / 2 }, width: n2 - e2, height: i2 - o2, ...t33.outline ? { outline: t33.outline, shape: "polygon" } : { shape: "rect" }, material: "fr4", ...t33.minBoardEdgeClearance !== undefined ? { min_board_edge_clearance: t33.minBoardEdgeClearance } : {} };
}
function hO(t33, e2, n2 = {}) {
const { minTraceWidth: o2 = 0.1, minViaDiameter: i2, minViaHoleDiameter: r2, originalSrj: s2, includeOriginalConnections: a2 = false } = n2, c2 = Yo(t33), l2 = i2 ?? c2.padDiameter, h2 = t33.min_via_hole_diameter ?? t33.minViaHoleDiameter, d2 = r2 ?? h2 ?? (i2 !== undefined ? 0.5 * l2 : c2.holeDiameter), u2 = [];
u2.push(...oO(t33, e2, a2 && s2 ? s2 : t33, n2.connectivityMaps?.source)), u2.push(...function(t34) {
const e3 = new Map;
return t34.connections.forEach((t35) => {
t35.pointsToConnect.forEach((t36) => {
t36.pcb_port_id && e3.set(t36.pcb_port_id, { type: "pcb_port", pcb_port_id: t36.pcb_port_id, source_port_id: t36.pcb_port_id, x: t36.x, y: t36.y, layers: So(t36) });
});
}), Array.from(e3.values());
}(a2 && s2 ? s2 : t33)), u2.push(...aO(s2 ?? t33)), u2.push(...function(t34, e3, n3 = 0.3, o3 = 0.5 * n3, i3 = false) {
const r3 = [], s3 = new Set;
return t34.length > 0 && ("type" in t34[0] && t34[0].type === "pcb_trace" ? t34.forEach((t35) => {
t35.route.forEach((a3) => {
if (a3.route_type === "via") {
if (!sO(a3.from_layer) || !sO(a3.to_layer))
return;
const c3 = a3.via_diameter ?? n3, l3 = a3.via_hole_diameter ?? o3, h3 = `${a3.x},${a3.y},${a3.from_layer},${a3.to_layer}`;
s3.has(h3) || (r3.push({ type: "pcb_via", pcb_via_id: `via_${r3.length}`, pcb_trace_id: t35.pcb_trace_id, x: a3.x, y: a3.y, outer_diameter: c3, hole_diameter: l3, layers: cO(a3, e3, i3) }), s3.add(h3));
}
});
}) : t34.forEach((t35, a3) => {
const c3 = `trace_${a3}`, l3 = t35.viaDiameter ?? n3, h3 = o3;
for (let n4 = 1;n4 < t35.route.length; n4++) {
const o4 = t35.route[n4 - 1], a4 = t35.route[n4];
if (o4.z !== a4.z && Math.abs(o4.x - a4.x) < 0.01 && Math.abs(o4.y - a4.y) < 0.01) {
const t36 = Co(o4.z, e3), n5 = Co(a4.z, e3), d3 = `${a4.x},${a4.y},${t36},${n5}`;
s3.has(d3) || (r3.push({ type: "pcb_via", pcb_via_id: `via_${r3.length}`, pcb_trace_id: c3, x: a4.x, y: a4.y, outer_diameter: l3, hole_diameter: h3, layers: cO({ from_layer: t36, to_layer: n5 }, e3, i3) }), s3.add(d3));
}
}
})), r3;
}(e2, t33.layerCount, l2, d2, (s2 ?? t33).allowBlindAndBuriedVias === true));
const p2 = eO(t33.connections, n2.connectivityMaps?.route ?? ii(t33));
return e2.length > 0 && ("type" in e2[0] && e2[0].type === "pcb_trace" ? e2.forEach((t34) => {
const e3 = nO(p2, t34.connection_name) ?? t34.connectsTo?.map((t35) => nO(p2, t35)).find((t35) => Boolean(t35)) ?? t34.connection_name;
u2.push(function(t35, e4) {
return { type: "pcb_trace", pcb_trace_id: t35.pcb_trace_id, source_trace_id: e4, route: t35.route.map((t36) => {
if (t36.route_type === "wire") {
if (!sO(t36.layer))
return null;
const e5 = "start_pcb_port_id" in t36 && typeof t36.start_pcb_port_id == "string" ? t36.start_pcb_port_id : undefined, n3 = "end_pcb_port_id" in t36 && typeof t36.end_pcb_port_id == "string" ? t36.end_pcb_port_id : undefined;
return { route_type: "wire", x: t36.x, y: t36.y, width: t36.width, layer: t36.layer, ...e5 ? { start_pcb_port_id: e5 } : {}, ...n3 ? { end_pcb_port_id: n3 } : {} };
}
return t36.route_type === "via" && sO(t36.from_layer) && sO(t36.to_layer) ? { route_type: "via", x: t36.x, y: t36.y, from_layer: t36.from_layer, to_layer: t36.to_layer } : null;
}).filter((t36) => t36 !== null) };
}(t34, e3));
}) : e2.forEach((e3, n3) => {
const i3 = function(t34, e4, n4, o3, i4 = 0.1) {
const r3 = [];
if (!t34.jumpers || t34.jumpers.length === 0)
return [{ type: "pcb_trace", pcb_trace_id: e4, source_trace_id: n4, route: t34.route.map((e5, n5) => {
const r4 = n5 === 0, s4 = n5 === t34.route.length - 1;
return { route_type: "wire", x: e5.x, y: e5.y, width: e5.traceThickness ?? i4, layer: Co(e5.z, o3), ...r4 && e5.pcb_port_id ? { start_pcb_port_id: e5.pcb_port_id } : {}, ...s4 && e5.pcb_port_id ? { end_pcb_port_id: e5.pcb_port_id } : {} };
}) }];
const s3 = [];
for (const e5 of t34.jumpers) {
let n5 = -1, o4 = -1;
for (let i5 = 0;i5 < t34.route.length; i5++) {
const r4 = t34.route[i5];
Math.abs(r4.x - e5.start.x) < 0.01 && Math.abs(r4.y - e5.start.y) < 0.01 && (n5 = i5), Math.abs(r4.x - e5.end.x) < 0.01 && Math.abs(r4.y - e5.end.y) < 0.01 && (o4 = i5);
}
n5 !== -1 && o4 !== -1 && (n5 > o4 && ([n5, o4] = [o4, n5]), s3.push({ startIdx: n5, endIdx: o4 }));
}
s3.sort((t35, e5) => t35.startIdx - e5.startIdx);
let a3 = 0, c3 = 0;
for (const { startIdx: l3, endIdx: h3 } of s3) {
if (l3 >= a3) {
const s4 = t34.route.slice(a3, l3 + 1);
s4.length > 0 && (r3.push({ type: "pcb_trace", pcb_trace_id: `${e4}_${c3}`, source_trace_id: n4, route: s4.map((t35, e5) => {
const n5 = e5 === 0 && a3 === 0;
return { route_type: "wire", x: t35.x, y: t35.y, width: t35.traceThickness ?? i4, layer: Co(t35.z, o3), ...n5 && t35.pcb_port_id ? { start_pcb_port_id: t35.pcb_port_id } : {} };
}) }), c3++);
}
a3 = h3;
}
if (a3 < t34.route.length) {
const s4 = t34.route.slice(a3);
if (s4.length > 0) {
r3.push({ type: "pcb_trace", pcb_trace_id: `${e4}_${c3}`, source_trace_id: n4, route: s4.map((e5, n5) => {
const r4 = n5 === s4.length - 1;
return { route_type: "wire", x: e5.x, y: e5.y, width: e5.traceThickness ?? i4, layer: Co(e5.z, o3), ...r4 && e5.pcb_port_id ? { end_pcb_port_id: e5.pcb_port_id } : {} };
}) });
}
}
return r3;
}(e3, `trace_${n3}`, nO(p2, e3.connectionName) ?? e3.connectionName, t33.layerCount, o2);
u2.push(...i3);
})), u2;
}
var dO = Symbol("originalPortPoint");
var uO = class extends ir {
constructor(t33) {
const e2 = t33.nodeWithPortPoints, n2 = (t33.traceThickness ?? 0.1) / 2 + (t33.traceMargin ?? 0.1), o2 = e2.width > 2 * n2 && e2.height > 2 * n2, i2 = e2.center.x - e2.width / 2 + n2, r2 = e2.center.x + e2.width / 2 - n2, s2 = e2.center.y - e2.height / 2 + n2, a2 = e2.center.y + e2.height / 2 - n2, c2 = e2.portPoints.map((t34) => ({ ...t34, x: Math.max(i2, Math.min(r2, t34.x)), y: Math.max(s2, Math.min(a2, t34.y)), [dO]: t34 })), l2 = new Map;
let h2 = false;
for (const t34 of c2) {
const e3 = `${t34.x},${t34.y},${t34.z}`, n3 = l2.get(e3), o3 = t34[dO];
!n3 || n3.x === o3.x && n3.y === o3.y || (h2 = true), l2.set(e3, o3);
}
super({ ...t33, nodeWithPortPoints: o2 ? { ...e2, width: e2.width - 2 * n2, height: e2.height - 2 * n2, portPoints: c2 } : e2 }), h2 && (this.failed = true, this.error = "Boundary clearance collapses distinct terminals"), o2 || (this.failed = true, this.error = "Node has no interior after copper boundary clearance");
}
getOutput() {
return super.getOutput().map((t33) => {
const e2 = t33.route[0], n2 = t33.route[t33.route.length - 1];
if (!e2[dO] || !n2[dO])
throw new Error("A13 route lost its original terminal metadata");
return { ...t33, route: [{ ...e2[dO] }, ...t33.route, { ...n2[dO] }] };
});
}
};
var pO = class extends uO {
constructor(t33) {
super(t33), this.validationParams = t33;
}
_step() {
if (super._step(), !this.solved)
return;
const t33 = this.getOutput(), { connMap: e2, layerCount: n2 } = this.validationParams, o2 = this.nodeWithPortPoints, i2 = t33.flatMap((t34) => t34.route), r2 = Math.max(this.traceThickness, this.viaDiameter) / 2 + Math.max(this.traceMargin, 0.1) + 0.000001, s2 = Math.min(...i2.map((t34) => t34.x)) - r2, a2 = Math.max(...i2.map((t34) => t34.x)) + r2, c2 = Math.min(...i2.map((t34) => t34.y)) - r2, l2 = Math.max(...i2.map((t34) => t34.y)) + r2, h2 = this.validationParams.obstacles.filter((t34) => {
const e3 = Math.hypot(t34.width, t34.height) / 2;
return t34.center.x + e3 >= s2 && t34.center.x - e3 <= a2 && t34.center.y + e3 >= c2 && t34.center.y - e3 <= l2;
});
this.stats.boardObstaclesChecked = h2.length;
const d2 = { layerCount: n2, minTraceWidth: this.traceThickness, minViaDiameter: this.viaDiameter, bounds: { minX: o2.center.x - o2.width / 2, maxX: o2.center.x + o2.width / 2, minY: o2.center.y - o2.height / 2, maxY: o2.center.y + o2.height / 2 }, ...this.validationParams.boardGeometry, obstacles: h2.map((n3) => ({ ...n3, connectedTo: [...n3.connectedTo, ...t33.filter((t34) => xo(n3, t34, e2)).map((t34) => t34.connectionName)] })), connections: t33.map((t34) => ({ name: t34.connectionName, rootConnectionName: t34.rootConnectionName, __netConnectionName: t34.rootConnectionName ?? t34.connectionName, pointsToConnect: [...[t34.route[0], t34.route.at(-1)].map((t35) => ({ x: t35.x, y: t35.y, layer: Co(t35.z, n2) })), ...h2.filter((n3) => xo(n3, t34, e2)).flatMap((t35) => {
const e3 = t35.circuitJsonMetadata?.pcb_port_id;
return e3 ? [{ ...t35.center, layer: Co(0, n2), pcb_port_id: e3 }] : [];
})] })) }, u2 = hO(d2, t33.map((t34, e3) => ({ type: "pcb_trace", pcb_trace_id: `${t34.connectionName}_${e3}`, connection_name: t34.connectionName, route: To(t34, n2) })));
this.validationParams.boardGeometry && u2.push(lO(d2));
const { errors: p2 } = VS(u2, { traceClearance: this.traceMargin, viaClearance: this.traceMargin, includeTraceContinuity: false }), m2 = SI({ srj: { ...d2, traces: undefined }, routes: t33 });
this.stats.boardDrcIssueCount = p2.length + m2.length, (p2.length > 0 || m2.length > 0) && (this.solved = false, this.failed = true, this.error = `A13 candidate fails board copper validation: ${p2[0]?.message ?? "fixed obstacle clearance violation"}`);
}
};
var mO = (t33) => `${t33.x.toFixed(6)},${t33.y.toFixed(6)},${t33.z}`;
var gO = (t33) => [t33.route[0], t33.route[t33.route.length - 1]];
var fO = (t33, e2, n2) => {
const o2 = new Map, i2 = (t34, e3) => {
o2.has(t34) || o2.set(t34, new Set), o2.has(e3) || o2.set(e3, new Set), o2.get(t34).add(e3), o2.get(e3).add(t34);
};
for (const n3 of t33)
if (n3.connectionName === e2 && n3.route.length !== 0) {
if (n3.route.length === 1) {
const t34 = mO(n3.route[0]);
o2.has(t34) || o2.set(t34, new Set);
continue;
}
for (let t34 = 0;t34 < n3.route.length - 1; t34++)
i2(mO(n3.route[t34]), mO(n3.route[t34 + 1]));
}
const r2 = new Set([n2]), s2 = [n2];
for (;s2.length > 0; ) {
const t34 = s2.pop();
for (const e3 of o2.get(t34) ?? [])
r2.has(e3) || (r2.add(e3), s2.push(e3));
}
return r2;
};
var yO = Array.from({ length: 6 }, (t33, e2) => e2);
var _O = class extends $s {
getSolverName() {
return "PortfolioSingleIntraNodeSolver";
}
constructorParams;
solvedRoutes = [];
nodeWithPortPoints;
connMap;
effort;
adaptiveSearchExpanded = false;
negotiatedSearchStarted = false;
enableNegotiatedSearch;
gridSearchSegmentWork;
gridSearchWorkScale;
rejectOverlappingTerminals;
getSolvedSegmentCount(t33) {
const e2 = t33.solvedConnectionsMap;
if (!(e2 instanceof Map))
return null;
let n2 = 0;
for (const t34 of e2.values())
Array.isArray(t34) && (n2 += t34.length);
return n2;
}
getNodeSegmentCount() {
return Math.max(1, this.nodeWithPortPoints.portPointsInPairs?.length ?? new Set(this.nodeWithPortPoints.portPoints.map((t33) => t33.connectionName)).size);
}
getCandidateProgress(t33) {
if (t33 instanceof ir) {
if (t33.solved)
return 1;
const e3 = t33.connections.length;
if (e3 === 0)
return 0;
const n2 = t33.routedCount / e3, o2 = Math.max(0, (t33.routedCount - t33.conflictCount) / e3);
return Math.min(0.99, (n2 + o2) / 2);
}
const e2 = this.getSolvedSegmentCount(t33);
return e2 !== null ? Math.min(1, e2 / this.getNodeSegmentCount()) : Math.max(0, Math.min(1, t33.progress || 0));
}
getTotalCandidateWork() {
return (this.supervisedSolvers ?? []).reduce((t33, { solver: e2 }) => t33 + (e2 instanceof ir ? 0 : e2.iterations), 0);
}
getDynamicExpansionWorkBudget() {
return Math.max(1, ...(this.supervisedSolvers ?? []).filter(({ solver: t33 }) => !(t33 instanceof ir)).map(({ solver: t33 }) => t33.MAX_ITERATIONS));
}
constructor(t33) {
if (super(), this.nodeWithPortPoints = t33.nodeWithPortPoints, this.connMap = t33.connMap, this.constructorParams = t33, this.effort = t33.effort ?? 1, this.gridSearchSegmentWork = t33.gridSearchSegmentWork ?? 1e4, this.gridSearchWorkScale = t33.gridSearchWorkScale ?? 1, this.rejectOverlappingTerminals = t33.rejectOverlappingTerminals ?? false, this.enableNegotiatedSearch = t33.enableNegotiatedSearch ?? false, this.MAX_ITERATIONS = 20000000 * this.effort, this.GREEDY_MULTIPLIER = 5, this.MIN_SUBSTEPS = 100, this.rejectOverlappingTerminals) {
const e2 = this.nodeWithPortPoints.portPoints, n2 = t33.traceWidth ?? 0.15;
for (let t34 = 0;t34 < e2.length; t34++)
for (let o2 = t34 + 1;o2 < e2.length; o2++) {
const i2 = e2[t34], r2 = e2[o2];
if (i2.z === r2.z && (i2.rootConnectionName ?? i2.connectionName) !== (r2.rootConnectionName ?? r2.connectionName) && !this.connMap?.areIdsConnected(i2.connectionName, r2.connectionName) && Math.hypot(i2.x - r2.x, i2.y - r2.y) < n2 - 0.000001)
return this.failed = true, void (this.error = "Unrelated route terminals overlap at the requested trace width");
}
}
}
getGridSearchIterationBudget() {
const t33 = this.nodeWithPortPoints, e2 = t33.availableZ?.length ?? new Set(t33.portPoints.map((t34) => t34.z)).size, n2 = Math.floor(t33.width / 0.1) * Math.floor(t33.height / 0.1) * e2, o2 = e2 > 2 ? this.gridSearchWorkScale : 1;
return Math.round(o2 * Math.max(150000, (e2 <= 2 ? 1e4 : this.gridSearchSegmentWork) * this.getNodeSegmentCount() ** 2, Math.round(n2 * (8 + 1.2 * Math.sqrt(this.getNodeSegmentCount())) * this.effort)));
}
getCombinationDefs() {
return [["throughObstacle"], ["singleLayerNoDifferentRootIntersections"], ["multiHeadPolyLine"], ["majorCombinations", "orderings6", "cellSizeFactor"], ["noVias"], ["orderings50"], ["flipTraceAlignmentDirection", "orderings6"], ["closedFormSingleTrace"], ["highDensityA01"], ["highDensityA03"], ...this.enableNegotiatedSearch ? [["highDensityA13"]] : []];
}
getHyperParameterDefs() {
return [{ name: "singleLayerNoDifferentRootIntersections", possibleValues: [{ SINGLE_LAYER_NO_DIFFERENT_ROOT_INTERSECTIONS: true }] }, { name: "majorCombinations", possibleValues: [{ FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: 2, FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: 1, FUTURE_CONNECTION_PROXIMITY_VD: 10, MISALIGNED_DIST_PENALTY_FACTOR: 5 }, { FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: 1, FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: 0.5, FUTURE_CONNECTION_PROXIMITY_VD: 5, MISALIGNED_DIST_PENALTY_FACTOR: 2 }, { FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: 10, FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: 1, FUTURE_CONNECTION_PROXIMITY_VD: 5, MISALIGNED_DIST_PENALTY_FACTOR: 10, VIA_PENALTY_FACTOR_2: 1 }] }, { name: "orderings6", possibleValues: yO.map((t33) => ({ SHUFFLE_SEED: t33 })) }, { name: "cellSizeFactor", possibleValues: [{ CELL_SIZE_FACTOR: 0.5 }, { CELL_SIZE_FACTOR: 1 }] }, { name: "flipTraceAlignmentDirection", possibleValues: [{ FLIP_TRACE_ALIGNMENT_DIRECTION: true }] }, { name: "noVias", possibleValues: [{ CELL_SIZE_FACTOR: 2, VIA_PENALTY_FACTOR_2: 10 }] }, { name: "orderings50", possibleValues: Array.from({ length: 20 }, (t33, e2) => ({ SHUFFLE_SEED: 100 + e2 })) }, { name: "throughObstacle", possibleValues: [{ THROUGH_OBSTACLE: true }] }, { name: "closedFormSingleTrace", possibleValues: [{ CLOSED_FORM_SINGLE_TRANSITION: true }] }, { name: "multiHeadPolyLine", possibleValues: [{ MULTI_HEAD_POLYLINE_SOLVER: true, SEGMENTS_PER_POLYLINE: 6, BOUNDARY_PADDING: 0.05 }, { MULTI_HEAD_POLYLINE_SOLVER: true, SEGMENTS_PER_POLYLINE: 6, BOUNDARY_PADDING: -0.05, ITERATION_PENALTY: 1e4, MINIMUM_FINAL_ACCEPTANCE_GAP: 0.001 }] }, { name: "highDensityA01", possibleValues: [{ HIGH_DENSITY_A01: true, SHUFFLE_SEED: yO[0] }] }, { name: "highDensityA03", possibleValues: [{ HIGH_DENSITY_A03: true }] }, { name: "highDensityA13", possibleValues: [{ HIGH_DENSITY_A13: true, SHUFFLE_SEED: 0 }] }];
}
initializeCandidateBudget(t33) {
if (t33 instanceof ir)
return;
const e2 = t33.setup;
typeof e2 == "function" && e2.call(t33), (t33 instanceof Pi || t33 instanceof Di) && (t33.MAX_ITERATIONS = Math.min(t33.MAX_ITERATIONS, this.getGridSearchIterationBudget()));
}
refreshDynamicIterationLimit() {
const t33 = (this.supervisedSolvers ?? []).reduce((t34, { solver: e2 }) => {
if (e2.solved || e2.failed)
return t34;
const n2 = Math.max(0, e2.MAX_ITERATIONS - e2.iterations + 1);
return t34 + Math.ceil(n2 / this.MIN_SUBSTEPS);
}, 0);
this.MAX_ITERATIONS = Math.max(this.iterations + 1, this.iterations + t33), this.stats.dynamicSupervisorIterationLimit = this.MAX_ITERATIONS;
}
initializeSolvers() {
super.initializeSolvers();
for (const { solver: t33 } of this.supervisedSolvers ?? [])
this.initializeCandidateBudget(t33);
this.stats.dynamicExpansionWorkBudget = this.getDynamicExpansionWorkBudget(), this.refreshDynamicIterationLimit();
}
addSupervisedCandidate(t33) {
const e2 = this.generateSolver(t33);
this.initializeCandidateBudget(e2);
const n2 = this.computeG(e2);
this.supervisedSolvers.push({ hyperParameters: t33, solver: e2, h: 0, g: n2, f: n2 });
}
expandAdaptiveSearch() {
if (!this.adaptiveSearchExpanded) {
this.adaptiveSearchExpanded = true;
for (const t33 of yO.slice(1))
this.addSupervisedCandidate({ HIGH_DENSITY_A01: true, SHUFFLE_SEED: t33 });
this.refreshDynamicIterationLimit(), this.stats.adaptiveSearchExpanded = true, this.stats.adaptiveSearchExpandedAtIteration = this.iterations, this.stats.candidateWorkAtExpansion = this.getTotalCandidateWork(), this.stats.bestProgressAtExpansion = Math.max(0, ...(this.supervisedSolvers ?? []).map(({ solver: t33 }) => this.getCandidateProgress(t33)));
}
}
shouldExpandPortfolio() {
if (this.adaptiveSearchExpanded)
return false;
const t33 = this.getDynamicExpansionWorkBudget();
return this.stats.dynamicExpansionWorkBudget = t33, this.getTotalCandidateWork() >= t33;
}
_step() {
this.supervisedSolvers || this.initializeSolvers(), this.adaptiveSearchExpanded || this.getSupervisedSolverWithBestFitness() || this.expandAdaptiveSearch(), super._step(), !this.negotiatedSearchStarted && this.activeSubSolver instanceof ir && (this.negotiatedSearchStarted = true, this.stats.negotiatedSearchStartedAtIteration = this.iterations), this.solved || this.failed || !this.shouldExpandPortfolio() || this.expandAdaptiveSearch();
}
computeG(t33) {
return t33 instanceof ir ? t33.routingIterations / 1e6 : t33 instanceof Pi || t33 instanceof Di || t33 instanceof ir ? t33.iterations / 1e6 : t33?.hyperParameters?.MULTI_HEAD_POLYLINE_SOLVER ? 1000 + ((t33.hyperParameters?.ITERATION_PENALTY ?? 0) + t33.iterations) / 1e4 + 1e4 * (t33.hyperParameters.SEGMENTS_PER_POLYLINE - 3) : t33.iterations / 1e4;
}
computeH(t33) {
return t33 instanceof ir || this.adaptiveSearchExpanded ? 1 - this.getCandidateProgress(t33) : 1 - (t33.progress || 0);
}
generateSolver(t33) {
if (t33.SINGLE_LAYER_NO_DIFFERENT_ROOT_INTERSECTIONS) {
if (!bs.isApplicable(this.nodeWithPortPoints)) {
const t34 = new Pr({ nodeWithPortPoints: this.nodeWithPortPoints, connMap: this.connMap, traceWidth: this.constructorParams.traceWidth, viaDiameter: this.constructorParams.viaDiameter, obstacleMargin: this.constructorParams.obstacleMargin });
return t34.failed = true, t34.error = "Single-layer no-different-root-intersection solver not applicable", t34;
}
return new bs({ nodeWithPortPoints: this.nodeWithPortPoints, traceWidth: this.constructorParams.traceWidth, viaDiameter: this.constructorParams.viaDiameter });
}
if (t33.HIGH_DENSITY_A13) {
const e2 = Math.max(1, Math.round(50000000 * this.effort)), n2 = new pO({ obstacles: this.constructorParams.obstacles ?? [], boardGeometry: this.constructorParams.boardGeometry, connMap: this.connMap, layerCount: this.constructorParams.layerCount ?? 2, nodeWithPortPoints: this.nodeWithPortPoints, cellSizeMm: 0.1, viaDiameter: this.constructorParams.viaDiameter ?? 0.3, viaMinDistFromBorder: (this.constructorParams.viaDiameter ?? 0.3) / 2, traceThickness: this.constructorParams.traceWidth ?? 0.15, traceMargin: 0.1, stepMultiplier: 1000, maxSearchIterations: e2, maxRounds: Math.max(1, Math.round(200 * this.effort)), hyperParameters: { shuffleSeed: t33.SHUFFLE_SEED ?? 0 } });
return n2.MAX_ITERATIONS = 2 * e2, n2;
}
if (t33.HIGH_DENSITY_A01) {
return new Pi({ nodeWithPortPoints: this.nodeWithPortPoints, cellSizeMm: 0.1, viaDiameter: this.constructorParams.viaDiameter ?? 0.3, viaMinDistFromBorder: (this.constructorParams.viaDiameter ?? 0.3) / 2, traceMargin: 0.1, traceThickness: this.constructorParams.traceWidth ?? 0.15, effort: this.effort, hyperParameters: { shuffleSeed: t33.SHUFFLE_SEED ?? 0 } });
}
if (t33.HIGH_DENSITY_A03) {
return new Di({ nodeWithPortPoints: this.nodeWithPortPoints, highResolutionCellSize: 0.1, highResolutionCellThickness: 8, lowResolutionCellSize: 0.4, viaDiameter: this.constructorParams.viaDiameter ?? 0.3, viaMinDistFromBorder: (this.constructorParams.viaDiameter ?? 0.3) / 2, traceMargin: 0.1, traceThickness: 0.1, effort: this.effort, hyperParameters: t33 });
}
return t33.CLOSED_FORM_TWO_TRACE_SAME_LAYER ? new js({ nodeWithPortPoints: this.nodeWithPortPoints, viaDiameter: this.constructorParams.viaDiameter }) : t33.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING ? new Bs({ nodeWithPortPoints: this.nodeWithPortPoints, viaDiameter: this.constructorParams.viaDiameter }) : t33.CLOSED_FORM_SINGLE_TRANSITION ? new vs({ nodeWithPortPoints: this.nodeWithPortPoints, viaDiameter: this.constructorParams.viaDiameter }) : t33.THROUGH_OBSTACLE ? new Ps({ nodeWithPortPoints: this.nodeWithPortPoints, obstacles: this.constructorParams.obstacles, connMap: this.connMap, layerCount: this.constructorParams.layerCount, viaDiameter: this.constructorParams.viaDiameter, traceThickness: this.constructorParams.traceWidth }) : t33.MULTI_HEAD_POLYLINE_SOLVER ? new ns({ nodeWithPortPoints: this.nodeWithPortPoints, connMap: this.connMap, hyperParameters: t33, viaDiameter: this.constructorParams.viaDiameter }) : new Tr({ ...this.constructorParams, hyperParameters: t33 });
}
onSolve(t33) {
let e2;
e2 = t33.solver instanceof Pi || t33.solver instanceof Di || t33.solver instanceof ir ? t33.solver.getOutput() : t33.solver.solvedRoutes;
const n2 = e2.map((t34) => {
const e3 = this.nodeWithPortPoints.portPoints.find((e4) => e4.connectionName === t34.connectionName);
return e3?.rootConnectionName ? { ...t34, rootConnectionName: e3.rootConnectionName } : t34;
});
this.solvedRoutes = ((t34, e3) => {
const n3 = [...t34], o2 = new Map;
for (const t35 of e3.portPoints) {
const e4 = o2.get(t35.connectionName) ?? [];
e4.push(t35), o2.set(t35.connectionName, e4);
}
for (const [t35, e4] of o2) {
if (e4.length <= 1)
continue;
const o3 = e4[0]?.rootConnectionName ?? t35, i2 = new Set(e4.map(mO));
let r2 = fO(n3, t35, mO(e4[0]));
for (const s2 of e4.slice(1)) {
const a2 = mO(s2);
if (r2.has(a2))
continue;
const c2 = n3.find((e5) => {
if ((e5.rootConnectionName ?? e5.connectionName) !== o3)
return false;
if (e5.connectionName === t35)
return false;
const [n4, s3] = gO(e5);
if (!n4 || !s3)
return false;
const c3 = mO(n4), l2 = mO(s3);
return r2.has(c3) && l2 === a2 || r2.has(l2) && c3 === a2 || i2.has(c3) && i2.has(l2) && (c3 === a2 || l2 === a2);
});
c2 && (n3.push({ ...c2, connectionName: t35, rootConnectionName: o3, route: c2.route.map((e5) => ({ ...e5, connectionName: t35, rootConnectionName: o3 })), vias: c2.vias.map((t36) => ({ ...t36 })), jumpers: c2.jumpers?.map((t36) => ({ ...t36, start: { ...t36.start }, end: { ...t36.end } })) }), r2 = fO(n3, t35, mO(e4[0])));
}
}
return n3;
})(n2, this.nodeWithPortPoints);
}
};
function bO(t33, e2, n2, o2, i2) {
const r2 = n2 - e2, s2 = i2 - o2, a2 = 0.000001;
if (Math.abs(t33.y - i2) < a2)
return t33.x - e2;
if (Math.abs(t33.x - n2) < a2)
return r2 + (i2 - t33.y);
if (Math.abs(t33.y - o2) < a2)
return r2 + s2 + (n2 - t33.x);
if (Math.abs(t33.x - e2) < a2)
return 2 * r2 + s2 + (t33.y - o2);
const c2 = Math.abs(t33.y - i2), l2 = Math.abs(t33.x - n2), h2 = Math.abs(t33.y - o2), d2 = Math.abs(t33.x - e2), u2 = Math.min(c2, l2, h2, d2);
return u2 === c2 ? Math.max(0, Math.min(r2, t33.x - e2)) : u2 === l2 ? r2 + Math.max(0, Math.min(s2, i2 - t33.y)) : u2 === h2 ? r2 + s2 + Math.max(0, Math.min(r2, n2 - t33.x)) : 2 * r2 + s2 + Math.max(0, Math.min(s2, t33.y - o2));
}
function xO(t33, e2, n2 = 0.000001) {
return Math.abs(t33 - e2) < n2;
}
function vO(t33) {
if (t33.length < 2)
return 0;
const e2 = t33.map(([t34, e3]) => t34 < e3 ? [t34, e3] : [e3, t34]);
let n2 = 0;
for (let t34 = 0;t34 < e2.length; t34++) {
const [o2, i2] = e2[t34];
for (let r2 = t34 + 1;r2 < e2.length; r2++) {
const [t35, s2] = e2[r2];
xO(o2, t35) || xO(o2, s2) || xO(i2, t35) || xO(i2, s2) || (o2 < t35 && t35 < i2 && i2 < s2 || t35 < o2 && o2 < s2 && s2 < i2) && n2++;
}
}
return n2;
}
var IO = (t33) => {
const e2 = t33.center.x - t33.width / 2, n2 = t33.center.x + t33.width / 2, o2 = t33.center.y - t33.height / 2, i2 = t33.center.y + t33.height / 2, r2 = new Map;
for (const e3 of t33.portPoints) {
const t34 = r2.get(e3.connectionName) ?? [];
t34.some((t35) => t35.x === e3.x && t35.y === e3.y && t35.z === e3.z) || t34.push({ x: e3.x, y: e3.y, z: e3.z }), r2.set(e3.connectionName, t34);
}
const s2 = new Map, a2 = [];
let c2 = 0;
for (const [t34, l3] of r2) {
if (l3.length < 2)
continue;
const t35 = l3[0], r3 = l3[1], h2 = bO(t35, e2, n2, o2, i2), d2 = bO(r3, e2, n2, o2, i2);
if (t35.z === r3.z) {
const e3 = t35.z, n3 = s2.get(e3) ?? [];
n3.push([h2, d2]), s2.set(e3, n3);
} else
c2++, a2.push([h2, d2]);
}
let l2 = 0;
for (const [t34, e3] of s2)
l2 += vO(e3);
return { numSameLayerCrossings: l2, numEntryExitLayerChanges: c2, numTransitionPairCrossings: vO(a2) };
};
var SO = (t33) => t33.availableZ?.length ? [...new Set(t33.availableZ)].sort((t34, e2) => t34 - e2) : [...new Set(t33.portPoints.map((t34) => t34.z ?? 0))].sort((t34, e2) => t34 - e2);
var CO = (t33) => SO(t33).length === 1 && IO(t33).numSameLayerCrossings > 0;
var PO = (t33, e2, n2) => {
const o2 = new Map, [i2] = SO(t33);
for (const e3 of t33.portPoints)
o2.set(e3.connectionName, [...o2.get(e3.connectionName) ?? [], e3]);
return Array.from(o2.entries()).flatMap(([o3, r2]) => {
if (r2.length < 2)
return [];
const s2 = r2[0], a2 = r2[r2.length - 1];
return [{ connectionName: o3, rootConnectionName: s2.rootConnectionName, regionId: t33.capacityMeshNodeId, traceThickness: e2, viaDiameter: n2, route: [{ x: s2.x, y: s2.y, z: i2 ?? s2.z ?? 0 }, { x: a2.x, y: a2.y, z: i2 ?? a2.z ?? 0 }], vias: [] }];
});
};
var MO = PO;
var NO = (t33, e2, n2) => ({ ...t33, x: e2.x + (t33.x - e2.x) * n2, y: e2.y + (t33.y - e2.y) * n2 });
var wO = (t33, e2, n2) => NO(t33, e2, n2);
var TO = ["#dc2626", "#2563eb", "#16a34a", "#ca8a04", "#9333ea", "#0891b2"];
var RO = (t33, e2, n2 = []) => [t33, e2 ? `rootConnectionName: ${e2}` : undefined, ...n2].filter(Boolean).join(`
`);
var EO = class extends si {
getSolverName() {
return "GrowShrinkHighDensityIntraNodeSolver";
}
constructorParams;
nodeWithPortPoints;
solvedRoutes = [];
failedSolvers = [];
activeSubSolver = null;
winningSolver;
scaleFactor = 1;
growthAttempts = 0;
maxGrowthAttempts;
minimumGrowthAttempts;
constructor(t33) {
super(), this.constructorParams = t33, this.nodeWithPortPoints = t33.nodeWithPortPoints;
const e2 = Math.min(this.nodeWithPortPoints.width, this.nodeWithPortPoints.height), n2 = e2 > 0 ? Math.max(0, Math.ceil(Math.log2((t33.viaDiameter ?? 0.3) / e2))) : 0;
this.maxGrowthAttempts = t33.maxGrowthAttempts ?? 3 + n2;
let o2 = Number.POSITIVE_INFINITY;
const i2 = this.nodeWithPortPoints.portPoints;
for (let t34 = 0;t34 < i2.length; t34++)
for (let e3 = t34 + 1;e3 < i2.length; e3++) {
const n3 = i2[t34], r2 = i2[e3];
if (n3.z !== r2.z || (n3.rootConnectionName ?? n3.connectionName) === (r2.rootConnectionName ?? r2.connectionName))
continue;
const s2 = Math.hypot(n3.x - r2.x, n3.y - r2.y);
s2 > 0.000000001 && (o2 = Math.min(o2, s2));
}
if (this.minimumGrowthAttempts = Math.min(this.maxGrowthAttempts, Math.max(n2, 0, Math.ceil(Math.log2((t33.traceWidth ?? 0.15) / 2 / o2)))), this.MAX_ITERATIONS = 20000000 * (t33.effort ?? 1) * (this.maxGrowthAttempts + 1), CO(this.nodeWithPortPoints)) {
if (!t33.fallbackToInvalidGeometryOnFailure)
return this.failed = true, this.progress = 1, void (this.error = "GrowShrinkHighDensityIntraNodeSolver cannot route an impossible single-layer crossing");
this.solvedRoutes = MO(this.nodeWithPortPoints, t33.traceWidth ?? 0.15, t33.viaDiameter ?? 0.3), this.solved = true, this.progress = 1, this.stats = { invalidGeometryFallback: true, reason: "single-layer node has same-layer crossings" };
}
}
getConstructorParams() {
return this.constructorParams;
}
createActiveSubSolver() {
const { growShrinkSolutionValidator: t33, ...e2 } = this.constructorParams;
var n2, o2;
this.activeSubSolver = new _O({ ...e2, enableNegotiatedSearch: this.scaleFactor === 1 && (e2.enableNegotiatedSearch ?? true), nodeWithPortPoints: (n2 = this.nodeWithPortPoints, o2 = this.scaleFactor, { ...n2, width: n2.width * o2, height: n2.height * o2, portPoints: n2.portPoints.map((t34) => wO(t34, n2.center, o2)), portPointsInPairs: n2.portPointsInPairs?.map(([t34, e3]) => [wO(t34, n2.center, o2), wO(e3, n2.center, o2)]) }) }), this.constructorParams.maxInnerIterationsPerGrowthAttempt && (this.activeSubSolver.MAX_ITERATIONS = this.constructorParams.maxInnerIterationsPerGrowthAttempt);
}
acceptSolution(t33) {
const e2 = this.scaleFactor === 1 ? t33.solvedRoutes : t33.solvedRoutes.map((t34) => ((t35, e3, n2) => ({ ...t35, route: t35.route.map((t36) => NO(t36, e3, n2)), vias: t35.vias.map((t36) => NO(t36, e3, n2)), jumpers: t35.jumpers?.map((t36) => ({ ...t36, start: NO(t36.start, e3, n2), end: NO(t36.end, e3, n2) })) }))(t34, this.nodeWithPortPoints.center, 1 / this.scaleFactor));
return this.constructorParams.growShrinkSolutionValidator && !this.constructorParams.growShrinkSolutionValidator(e2) ? (t33.solved = false, t33.failed = true, t33.error = "High-density scale solution rejected by validator", false) : (this.winningSolver = t33, this.solvedRoutes = e2, this.solved = true, this.failed = false, true);
}
computeProgress() {
return Math.min(0.99, (this.growthAttempts + (this.activeSubSolver?.progress ?? 0)) / (this.maxGrowthAttempts + 1));
}
_step() {
if (this.activeSubSolver || this.createActiveSubSolver(), this.activeSubSolver.step(), this.activeSubSolver.solved && this.acceptSolution(this.activeSubSolver))
this.activeSubSolver = null;
else if (this.activeSubSolver.failed) {
if (this.failedSolvers.push(this.activeSubSolver), this.error = this.activeSubSolver.error, this.activeSubSolver = null, this.growthAttempts >= this.maxGrowthAttempts)
return this.constructorParams.fallbackToInvalidGeometryOnFailure ? (this.solvedRoutes = PO(this.nodeWithPortPoints, this.constructorParams.traceWidth ?? 0.15, this.constructorParams.viaDiameter ?? 0.3), this.solved = true, this.failed = false, this.progress = 1, this.stats = { ...this.stats, invalidGeometryFallback: true, reason: "growth attempts exhausted", lastError: this.error }, void (this.error = null)) : (this.failed = true, void (this.error = `GrowShrinkHighDensityIntraNodeSolver failed after resizing to ${this.scaleFactor}x. Last error: ${this.error}`));
this.growthAttempts = Math.max(this.growthAttempts + 1, this.minimumGrowthAttempts), this.scaleFactor = 2 ** this.growthAttempts;
}
}
visualize() {
const t33 = this.activeSubSolver?.visualize() ?? this.winningSolver?.visualize();
return t33 || (this.solvedRoutes.length > 0 ? { title: this.stats.invalidGeometryFallback ? "Invalid same-layer crossing geometry" : "Grow/shrink high density routes", lines: this.solvedRoutes.flatMap((t34, e2) => t34.route.slice(0, -1).map((n2, o2) => ({ points: [n2, t34.route[o2 + 1]], strokeColor: TO[e2 % TO.length], strokeWidth: t34.traceThickness, layer: `z${n2.z}`, label: RO(t34.connectionName, t34.rootConnectionName, [`z${n2.z}`, this.stats.invalidGeometryFallback ? "invalid fallback route" : undefined].filter(Boolean)) }))), points: this.nodeWithPortPoints.portPoints.map((t34) => ({ x: t34.x, y: t34.y, color: TO[Math.max(0, this.solvedRoutes.findIndex((e2) => e2.connectionName === t34.connectionName)) % TO.length], label: RO(t34.connectionName, t34.rootConnectionName, [`z${t34.z}`]) })), rects: [{ center: this.nodeWithPortPoints.center, width: this.nodeWithPortPoints.width, height: this.nodeWithPortPoints.height, fill: this.stats.invalidGeometryFallback ? "rgba(245, 158, 11, 0.12)" : "rgba(14, 165, 233, 0.08)", stroke: this.stats.invalidGeometryFallback ? "rgba(217, 119, 6, 0.8)" : "rgba(14, 165, 233, 0.55)", label: [this.nodeWithPortPoints.capacityMeshNodeId, this.stats.reason].filter(Boolean).join(`
`) }], circles: [] } : t33 ?? { lines: [], points: [], rects: [], circles: [] });
}
};
var AO = (t33, e2, n2 = []) => [t33, e2 ? `rootConnectionName: ${e2}` : undefined, ...n2].filter(Boolean).join(`
`);
var OO = class extends si {
getSolverName() {
return "HighDensitySolver";
}
unsolvedNodePortPoints;
routes;
colorMap;
defaultViaDiameter = 0.3;
defaultTraceThickness = 0.15;
viaDiameter;
traceWidth;
obstacleMargin;
effort;
obstacles;
layerCount;
useGrowShrinkHighDensityIntraNodeSolver;
enableNegotiatedSearch;
gridSearchSegmentWork;
gridSearchWorkScale;
rejectOverlappingTerminals;
boardGeometry;
preserveTerminalPcbPortIds;
growShrinkMaxInnerIterationsPerGrowthAttempt;
growShrinkFallbackToInvalidGeometryOnFailure;
growShrinkSolutionValidator;
captureSearchDebug;
failedSolvers;
activeSubSolver = null;
connMap;
nodePfById;
nodeSolveMetadataById;
constructor({ nodePortPoints: t33, colorMap: e2, connMap: n2, viaDiameter: o2, traceWidth: i2, obstacleMargin: r2, effort: s2, nodePfById: a2, obstacles: c2, layerCount: l2, useGrowShrinkHighDensityIntraNodeSolver: h2, enableNegotiatedSearch: d2 = false, gridSearchSegmentWork: u2 = 1e4, gridSearchWorkScale: p2 = 1, rejectOverlappingTerminals: m2 = false, boardGeometry: g2, preserveTerminalPcbPortIds: f2, growShrinkMaxInnerIterationsPerGrowthAttempt: y2, growShrinkFallbackToInvalidGeometryOnFailure: _2, growShrinkSolutionValidator: b2, captureSearchDebug: x2 }) {
super(), this.unsolvedNodePortPoints = t33, this.colorMap = e2 ?? {}, this.connMap = n2, this.routes = [], this.failedSolvers = [], this.effort = s2 ?? 1, this.viaDiameter = o2 ?? this.defaultViaDiameter, this.traceWidth = i2 ?? this.defaultTraceThickness, this.obstacleMargin = r2 ?? 0.15, this.obstacles = c2 ?? [], this.layerCount = l2 ?? 2, this.enableNegotiatedSearch = d2, this.gridSearchSegmentWork = u2, this.gridSearchWorkScale = p2, this.rejectOverlappingTerminals = m2, this.boardGeometry = g2, this.useGrowShrinkHighDensityIntraNodeSolver = h2 ?? false, this.preserveTerminalPcbPortIds = f2 ?? false, this.growShrinkMaxInnerIterationsPerGrowthAttempt = y2, this.growShrinkFallbackToInvalidGeometryOnFailure = _2 ?? false, this.growShrinkSolutionValidator = b2, this.captureSearchDebug = x2 ?? true, this.MAX_ITERATIONS = 1e7 * this.effort * (this.useGrowShrinkHighDensityIntraNodeSolver ? 4 : 1), this.nodePfById = a2 instanceof Map ? new Map(a2) : new Map(Object.entries(a2 ?? {})), this.nodeSolveMetadataById = new Map, this.stats = { solverNodeCount: {}, difficultNodePfs: {}, highDensityResizeCount: 0 };
}
getSolvedNodeSolverType(t33) {
return t33 instanceof EO && t33.winningSolver ? this.getSolvedNodeSolverType(t33.winningSolver) : t33 instanceof _O && t33.winningSolver ? this.getConcreteSolverTypeName(t33.winningSolver) : this.getConcreteSolverTypeName(t33);
}
recordNodeSolveMetadata(t33, e2) {
const n2 = t33.nodeWithPortPoints, o2 = this.nodePfById.get(n2.capacityMeshNodeId) ?? null;
this.nodeSolveMetadataById.set(n2.capacityMeshNodeId, { node: n2, status: e2, solverType: this.getSolvedNodeSolverType(t33), iterations: t33.iterations, routeCount: t33.solvedRoutes.length, nodePf: o2, error: t33.error ?? undefined });
}
createNodeMarkerLabel(t33, e2) {
return ["hd_node_marker", `node: ${t33}`, `status: ${e2.status}`, `solver: ${e2.solverType}`, `iterations: ${e2.iterations}`, `routes: ${e2.routeCount}`, `nodePf: ${e2.nodePf ?? "n/a"}`, `portPoints: ${e2.node.portPoints.length}`, ...e2.error ? [`error: ${e2.error}`] : []].join(`
`);
}
getConcreteSolverTypeName(t33) {
if (t33 instanceof Tr) {
const e2 = this.getIntraNodeStrategyName(t33.hyperParameters);
return t33.cacheHit ? `${e2} [cached]` : e2;
}
return t33 instanceof Pr ? this.getIntraNodeStrategyName(t33.hyperParameters) : t33.getSolverName();
}
getIntraNodeStrategyName(t33) {
return t33?.MULTI_HEAD_POLYLINE_SOLVER ? "MultiHeadPolyLineIntraNodeSolver3" : t33?.SINGLE_LAYER_NO_DIFFERENT_ROOT_INTERSECTIONS ? "SingleLayerNoDifferentRootIntersectionsIntraNodeSolver" : t33?.CLOSED_FORM_SINGLE_TRANSITION ? "SingleTransitionIntraNodeSolver" : t33?.CLOSED_FORM_TWO_TRACE_SAME_LAYER ? "TwoCrossingRoutesHighDensitySolver" : t33?.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING ? "SingleTransitionCrossingRouteSolver" : t33?.HIGH_DENSITY_A01 ? "HighDensitySolverA01" : t33?.HIGH_DENSITY_A03 ? "HighDensitySolverA03" : "SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost";
}
recordSolvedNodeStats(t33, e2) {
const n2 = this.getSolvedNodeSolverType(t33), o2 = this.stats.solverNodeCount, i2 = this.stats.difficultNodePfs;
o2[n2] = (o2[n2] ?? 0) + 1;
const r2 = this.nodePfById.get(e2.capacityMeshNodeId) ?? null;
r2 !== null && r2 > 0.05 && (i2[n2] || (i2[n2] = []), i2[n2].push(r2));
}
recordResizeStats(t33) {
t33 instanceof EO && (this.stats.highDensityResizeCount = (this.stats.highDensityResizeCount ?? 0) + t33.growthAttempts);
}
getSolvedRoutesWithTerminalPcbPortIds(t33) {
const e2 = t33.nodeWithPortPoints.portPoints.filter((t34) => t34.pcb_port_id !== undefined);
if (e2.length === 0)
return t33.solvedRoutes;
const n2 = (t34, n3) => {
const o2 = e2.filter((e3) => e3.connectionName === t34.connectionName && e3.x === n3.x && e3.y === n3.y && e3.z === n3.z);
if (o2.length > 1)
throw new Error(`HighDensitySolver found multiple PCB terminals at an endpoint of "${t34.connectionName}"`);
const i2 = o2[0];
if (i2?.pcb_port_id)
return i2.pcb_port_id;
};
return t33.solvedRoutes.map((t34) => ({ ...t34, startPcbPortId: t34.route[0] ? n2(t34, t34.route[0]) : undefined, endPcbPortId: t34.route.length > 1 ? n2(t34, t34.route[t34.route.length - 1]) : undefined }));
}
_step() {
if (this.updateCacheStats(), this.activeSubSolver)
return this.activeSubSolver.step(), this.activeSubSolver.solved ? (this.routes.push(...this.preserveTerminalPcbPortIds ? this.getSolvedRoutesWithTerminalPcbPortIds(this.activeSubSolver) : this.activeSubSolver.solvedRoutes), this.recordNodeSolveMetadata(this.activeSubSolver, "solved"), this.recordSolvedNodeStats(this.activeSubSolver, this.activeSubSolver.nodeWithPortPoints), this.recordResizeStats(this.activeSubSolver), this.activeSubSolver = null) : this.activeSubSolver.failed && (this.recordNodeSolveMetadata(this.activeSubSolver, "failed"), this.recordResizeStats(this.activeSubSolver), this.failedSolvers.push(this.activeSubSolver), this.activeSubSolver = null), void this.updateCacheStats();
if (this.unsolvedNodePortPoints.length === 0)
return this.failedSolvers.length > 0 ? (this.solved = false, this.failed = true, this.error = `Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0, 5).map((t34) => t34.nodeWithPortPoints.capacityMeshNodeId)}. err0: ${this.failedSolvers[0].error}.`, void this.updateCacheStats()) : (this.solved = true, void this.updateCacheStats());
const t33 = { nodeWithPortPoints: this.unsolvedNodePortPoints.pop(), enableNegotiatedSearch: this.enableNegotiatedSearch, gridSearchSegmentWork: this.gridSearchSegmentWork, gridSearchWorkScale: this.gridSearchWorkScale, rejectOverlappingTerminals: this.rejectOverlappingTerminals, boardGeometry: this.boardGeometry, colorMap: this.colorMap, connMap: this.connMap, viaDiameter: this.viaDiameter, traceWidth: this.traceWidth, obstacleMargin: this.obstacleMargin, effort: this.effort, obstacles: this.obstacles, layerCount: this.layerCount, maxInnerIterationsPerGrowthAttempt: this.growShrinkMaxInnerIterationsPerGrowthAttempt, fallbackToInvalidGeometryOnFailure: this.growShrinkFallbackToInvalidGeometryOnFailure, growShrinkSolutionValidator: this.growShrinkSolutionValidator, captureSearchDebug: this.captureSearchDebug };
this.activeSubSolver = this.useGrowShrinkHighDensityIntraNodeSolver ? new EO(t33) : new _O(t33), this.updateCacheStats();
}
updateCacheStats() {
const t33 = oo();
this.stats.intraNodeCacheHits = t33.cacheHits, this.stats.intraNodeCacheMisses = t33.cacheMisses;
}
visualize() {
let t33 = { lines: [], points: [], rects: [], circles: [] };
for (const e2 of this.routes) {
const n2 = mi(e2.route, e2.connectionName, this.colorMap[e2.connectionName]);
for (const o2 of n2)
t33.lines.push({ points: o2.points, label: AO(e2.connectionName, e2.rootConnectionName), strokeColor: o2.z === 0 ? o2.color : Ao(o2.color, 0.5), layer: `z${o2.z}`, strokeWidth: e2.traceThickness, strokeDash: o2.z !== 0 ? [0.1, 0.3] : undefined });
for (const n3 of e2.vias)
t33.circles.push({ center: n3, layer: "z0,1", radius: e2.viaDiameter / 2, fill: this.colorMap[e2.connectionName], label: AO(e2.connectionName, e2.rootConnectionName, ["via"]) });
}
if (this.solved || this.failed)
for (const [e2, n2] of this.nodeSolveMetadataById) {
const o2 = n2.node.center.x - n2.node.width / 2, i2 = n2.node.center.x + n2.node.width / 2, r2 = n2.node.center.y - n2.node.height / 2, s2 = n2.node.center.y + n2.node.height / 2, a2 = this.createNodeMarkerLabel(e2, n2), c2 = n2.status === "solved" ? "blue" : "red";
if (t33.lines.push({ points: [{ x: o2, y: r2 }, { x: i2, y: r2 }], layer: "hd_node_boundaries", strokeColor: c2, strokeDash: "6, 4", strokeWidth: 0.03, label: a2 }, { points: [{ x: i2, y: r2 }, { x: i2, y: s2 }], layer: "hd_node_boundaries", strokeColor: c2, strokeDash: "6, 4", strokeWidth: 0.03, label: a2 }, { points: [{ x: i2, y: s2 }, { x: o2, y: s2 }], layer: "hd_node_boundaries", strokeColor: c2, strokeDash: "6, 4", strokeWidth: 0.03, label: a2 }, { points: [{ x: o2, y: s2 }, { x: o2, y: r2 }], layer: "hd_node_boundaries", strokeColor: c2, strokeDash: "6, 4", strokeWidth: 0.03, label: a2 }), n2.status === "solved")
t33.points.push({ x: n2.node.center.x, y: n2.node.center.y, color: c2, layer: "hd_node_markers", label: a2 });
else {
t33.lines.push({ points: [{ x: 0, y: 0 }, { x: n2.node.center.x, y: n2.node.center.y }], layer: "hd_failed_node_guides", strokeColor: "red", strokeDash: "8, 6", strokeWidth: 0.05, label: a2 });
const e3 = Math.max(0.1 * n2.node.width, 0.12), o3 = Math.max(0.1 * n2.node.height, 0.12);
t33.rects.push({ center: n2.node.center, layer: "hd_node_markers", width: e3, height: o3, fill: "red", label: a2 });
}
}
return this.activeSubSolver && (t33 = pi(t33, this.activeSubSolver.visualize())), t33;
}
};
var LO = (t33, e2 = 1, n2 = {}) => {
const o2 = n2.viaDiameter ?? 0.3, i2 = "width" in t33 ? t33.width : t33, r2 = n2.obstacleMargin ?? 0.2, s2 = "height" in t33 && typeof t33.height == "number" ? t33.height : i2;
if (!Number.isFinite(i2) || !Number.isFinite(s2))
return 0;
if (i2 <= 0 || s2 <= 0)
return 0;
const a2 = Math.min(i2, s2) / (o2 + r2), c2 = (Math.sqrt(i2 * s2) * Math.min(1.2, Math.max(0.85, a2 ** 0.05)) / (o2 / 2 + r2) / 2) ** 1.1 * e2;
return Number.isFinite(c2) ? t33.availableZ?.length === 1 && c2 > 1 ? 1 : c2 : 0;
};
var zO = (t33, e2 = 0.5, n2 = 16) => {
let o2 = 0, i2 = t33;
for (;o2 < n2; ) {
if (LO({ width: i2 }) <= e2)
break;
i2 /= 2, o2++;
}
return Math.max(1, o2);
};
var BO = (t33, e2, n2, o2) => {
if (t33?._containsTarget)
return 0;
if ((t33.availableZ?.length ?? 2) === 1 && (e2 > 0 || n2 > 0 || o2 > 0))
return 1;
const i2 = ((0.82 * e2 + 0.41 * n2 + 0.2 * o2) / 2) ** 1.1;
if (!Number.isFinite(i2))
return 1;
const r2 = LO(t33);
if (!Number.isFinite(r2) || r2 <= 0)
return i2 > 0 ? 1 : 0;
const s2 = i2 / r2;
if (Number.isNaN(s2))
throw new Error("calculateNodeProbabilityOfFailure returned NaN");
return Number.isFinite(s2) ? s2 : i2 > 0 ? 1 : 0;
};
var ek = class {
parent = {};
constructor(t33) {
for (const e2 of t33)
this.parent[e2] = e2;
}
find(t33) {
return this.parent[t33] === t33 ? t33 : this.parent[t33] = this.find(this.parent[t33]);
}
union(t33, e2) {
const n2 = this.find(t33), o2 = this.find(e2);
n2 !== o2 && (this.parent[o2] = n2);
}
getGroup(t33) {
const e2 = this.find(t33), n2 = [];
for (const t34 in this.parent)
this.find(t34) === e2 && n2.push(t34);
return n2;
}
};
var nk = class {
point;
left = null;
right = null;
constructor(t33) {
this.point = t33;
}
};
var ok = class {
root = null;
constructor(t33) {
t33.length > 0 && (this.root = this.buildTree(t33, 0));
}
buildTree(t33, e2) {
const n2 = e2 % 2 == 0 ? "x" : "y";
t33.sort((t34, e3) => t34[n2] - e3[n2]);
const o2 = Math.floor(t33.length / 2), i2 = new nk(t33[o2]);
return o2 > 0 && (i2.left = this.buildTree(t33.slice(0, o2), e2 + 1)), o2 < t33.length - 1 && (i2.right = this.buildTree(t33.slice(o2 + 1), e2 + 1)), i2;
}
findNearestNeighbor(t33) {
if (!this.root)
throw new Error("Tree is empty");
const e2 = this.root.point, n2 = this.distance(t33, e2);
return this.nearestNeighborSearch(this.root, t33, 0, e2, n2), e2;
}
nearestNeighborSearch(t33, e2, n2, o2, i2) {
if (!t33)
return o2;
const r2 = n2 % 2 ? "x" : "y", s2 = this.distance(e2, t33.point);
s2 < i2 && (o2 = t33.point, i2 = s2);
const a2 = e2[r2] - t33.point[r2], c2 = a2 <= 0 ? t33.left : t33.right, l2 = a2 <= 0 ? t33.right : t33.left;
return o2 = this.nearestNeighborSearch(c2, e2, n2 + 1, o2, i2), i2 = this.distance(e2, o2), Math.abs(a2) < i2 && (o2 = this.nearestNeighborSearch(l2, e2, n2 + 1, o2, i2)), o2;
}
findKNearestNeighbors(t33, e2) {
if (!this.root)
return [];
const n2 = [];
return this.kNearestNeighborSearch(this.root, t33, 0, n2, e2), n2.sort((t34, e3) => t34.distance - e3.distance).slice(0, e2).map((t34) => t34.point);
}
kNearestNeighborSearch(t33, e2, n2, o2, i2) {
if (!t33)
return;
const r2 = n2 % 2 ? "x" : "y", s2 = this.distance(e2, t33.point);
o2.push({ point: t33.point, distance: s2 });
const a2 = e2[r2] - t33.point[r2], c2 = a2 <= 0 ? t33.left : t33.right, l2 = a2 <= 0 ? t33.right : t33.left;
this.kNearestNeighborSearch(c2, e2, n2 + 1, o2, i2);
let h2 = 1 / 0;
o2.length >= i2 && (o2.sort((t34, e3) => t34.distance - e3.distance), h2 = o2[i2 - 1]?.distance || 1 / 0), (Math.abs(a2) < h2 || o2.length < i2) && this.kNearestNeighborSearch(l2, e2, n2 + 1, o2, i2);
}
distance(t33, e2) {
return Math.sqrt((t33.x - e2.x) ** 2 + (t33.y - e2.y) ** 2);
}
};
var ik = class {
parent = new Map;
rank = new Map;
constructor(t33) {
for (const e2 of t33) {
const t34 = this.pointToKey(e2);
this.parent.set(t34, t34), this.rank.set(t34, 0);
}
}
pointToKey(t33) {
return `${t33.x},${t33.y}`;
}
find(t33) {
const e2 = this.pointToKey(t33);
if (!this.parent.has(e2))
throw new Error(`Point ${e2} not found in DisjointSet`);
let n2 = e2;
for (;n2 !== this.parent.get(n2); )
n2 = this.parent.get(n2);
let o2 = e2;
for (;o2 !== n2; ) {
const t34 = this.parent.get(o2);
this.parent.set(o2, n2), o2 = t34;
}
return n2;
}
union(t33, e2) {
const n2 = this.find(t33), o2 = this.find(e2);
if (n2 === o2)
return false;
const i2 = this.rank.get(n2) || 0, r2 = this.rank.get(o2) || 0;
return i2 < r2 ? this.parent.set(n2, o2) : i2 > r2 ? this.parent.set(o2, n2) : (this.parent.set(o2, n2), this.rank.set(n2, i2 + 1)), true;
}
};
function rk(t33, e2 = {}) {
if (t33.length <= 1)
return [];
const n2 = [...t33], o2 = new ok(n2), i2 = [], r2 = Math.min(10, t33.length - 1);
for (const t34 of n2) {
const e3 = o2.findKNearestNeighbors(t34, r2 + 1);
for (const n3 of e3) {
if (t34.x === n3.x && t34.y === n3.y)
continue;
const e4 = Math.sqrt((t34.x - n3.x) ** 2 + (t34.y - n3.y) ** 2);
i2.push({ from: t34, to: n3, weight: e4 });
}
}
e2.extraEdges && i2.push(...e2.extraEdges), i2.sort((t34, e3) => t34.weight - e3.weight);
const s2 = new ik(n2), a2 = [];
for (const t34 of i2)
if (s2.union(t34.from, t34.to) && (a2.push(t34), a2.length === n2.length - 1))
break;
return a2;
}
var sk = (t33, e2) => {
const n2 = new Map;
for (const o3 of t33.pointsToConnect) {
if (!o3.pointId)
continue;
const t34 = e2.getNetConnectedToId(o3.pointId);
if (!t34)
continue;
const i2 = n2.get(t34) ?? [];
i2.push(o3), n2.set(t34, i2);
}
const o2 = [];
for (const t34 of n2.values()) {
const e3 = t34[0];
if (e3)
for (const n3 of t34.slice(1))
o2.push({ from: e3, to: n3, weight: 0 });
}
return o2;
};
var ak = (t33, e2) => ({ zeroWeightEdges: sk(t33, e2), arePointsConnected: (t34, n2) => Boolean(t34.pointId && n2.pointId && ((t35, e3, n3) => {
const o2 = t35.getNetConnectedToId(e3);
return !!o2 && o2 === t35.getNetConnectedToId(n3);
})(e2, t34.pointId, n2.pointId)) });
function ck(t33) {
if (t33.pointId)
return t33.pointId;
const e2 = [...So(t33)].sort().join("-");
return `${t33.x.toFixed(4)},${t33.y.toFixed(4)},${e2}`;
}
function lk(t33) {
if (t33.length === 0)
return [];
const e2 = t33.map((t34, e3) => `conn_${e3}`), n2 = new ek(e2), o2 = new Map;
t33.forEach((t34, e3) => {
const n3 = `conn_${e3}`;
t34.pointsToConnect.forEach((t35) => {
const e4 = ck(t35);
o2.has(e4) || o2.set(e4, []), o2.get(e4).push(n3);
});
});
for (const t34 of o2.values())
if (t34.length > 1) {
const e3 = t34[0];
for (let o3 = 1;o3 < t34.length; o3++)
n2.union(e3, t34[o3]);
}
const i2 = new Map;
t33.forEach((t34, e3) => {
const o3 = `conn_${e3}`, r3 = n2.find(o3);
i2.has(r3) || i2.set(r3, []), i2.get(r3).push(t34);
});
const r2 = [];
for (const t34 of i2.values()) {
if (t34.length === 1) {
r2.push(t34[0]);
continue;
}
const e3 = new Map, n3 = new Set;
let o3 = false;
const i3 = [], s2 = new Set;
let a2;
t34.forEach((t35) => {
t35.pointsToConnect.forEach((t36) => e3.set(ck(t36), t36));
const r3 = t35.__rootConnectionNames;
if (r3 && r3.length > 0)
for (const t36 of r3)
n3.add(t36);
else
n3.add(t35.name);
t35.isOffBoard && (o3 = true), t35.externallyConnectedPointIds && i3.push(...t35.externallyConnectedPointIds), t35.__netConnectionName && s2.add(t35.__netConnectionName), a2 === undefined && t35.nominalTraceWidth !== undefined && (a2 = t35.nominalTraceWidth);
});
const c2 = { name: t34.map((t35) => t35.name).join("__"), pointsToConnect: Array.from(e3.values()), isOffBoard: o3, externallyConnectedPointIds: i3.length > 0 ? i3 : undefined, __netConnectionName: s2.size > 0 ? Array.from(s2).join("__") : undefined, __rootConnectionNames: Array.from(n3), nominalTraceWidth: a2 };
r2.push(c2);
}
return r2;
}
var hk = class extends si {
constructor(t33, e2 = {}, n2) {
super(), this.ogSrj = t33, this.colorMap = e2;
const o2 = new Map;
for (const e3 of t33.buses ?? [])
if (e3.traceWidth !== undefined)
for (const t34 of e3.connectionNames)
o2.set(t34, Math.max(o2.get(t34) ?? 0, e3.traceWidth));
const i2 = t33.connections.map((t34) => {
const e3 = o2.get(t34.name);
return e3 === undefined ? t34 : { ...t34, nominalTraceWidth: Math.max(t34.nominalTraceWidth ?? 0, e3) };
});
this.unprocessedConnections = lk(i2), this.newConnections = [], this.initiallyConnectedMap = n2;
}
getSolverName() {
return "NetToPointPairsSolver";
}
unprocessedConnections;
newConnections;
initiallyConnectedMap;
_step() {
if (this.unprocessedConnections.length === 0)
return void (this.solved = true);
const t33 = this.unprocessedConnections.pop(), { zeroWeightEdges: e2, arePointsConnected: n2 } = ak(t33, this.initiallyConnectedMap);
if (t33.pointsToConnect.length === 2) {
const [e3, o3] = t33.pointsToConnect;
if (e3 && o3 && n2(e3, o3))
return;
return void this.newConnections.push({ ...t33, __rootConnectionNames: t33.__rootConnectionNames ?? [t33.name] });
}
const o2 = rk(t33.pointsToConnect, { extraEdges: e2 });
let i2 = 0;
for (const e3 of o2)
n2(e3.from, e3.to) || this.newConnections.push({ ...t33, pointsToConnect: [e3.from, e3.to], name: `${t33.name}_mst${i2++}`, __rootConnectionNames: t33.__rootConnectionNames ?? [t33.name], __netConnectionName: t33.__netConnectionName });
}
getNewSimpleRouteJson() {
return { ...structuredClone(this.ogSrj), connections: structuredClone(this.newConnections) };
}
visualize() {
const t33 = { lines: [], points: [], rects: [], circles: [], coordinateSystem: "cartesian", title: "Net To Point Pairs Visualization" };
return this.unprocessedConnections.forEach((e2) => {
e2.pointsToConnect.forEach((e3) => {
t33.points.push({ x: e3.x, y: e3.y, color: "red", label: e3.pcb_port_id ?? e3.pointId });
});
const n2 = e2.pointsToConnect.length ** 2, o2 = dr(0), i2 = new Set;
for (let r2 = 0;r2 < Math.max(n2, 2 * e2.pointsToConnect.length); r2++) {
const n3 = Math.floor(o2() * e2.pointsToConnect.length), r3 = Math.floor(o2() * e2.pointsToConnect.length);
i2.has(`${n3}-${r3}`) || (i2.add(`${n3}-${r3}`), t33.lines.push({ points: [e2.pointsToConnect[n3], e2.pointsToConnect[r3]], strokeColor: "rgba(255,0,0,0.25)", label: e2.name }));
}
}), this.newConnections.forEach((e2) => {
const n2 = this.colorMap?.[e2.name] || "blue";
e2.pointsToConnect.forEach((e3) => {
t33.points.push({ x: e3.x, y: e3.y, color: n2, label: e3.pcb_port_id ?? e3.pointId });
});
for (let o2 = 0;o2 < e2.pointsToConnect.length - 1; o2++)
for (let i2 = o2 + 1;i2 < e2.pointsToConnect.length; i2++)
t33.lines.push({ points: [e2.pointsToConnect[o2], e2.pointsToConnect[i2]], strokeColor: n2, label: e2.name });
}), t33;
}
};
var dk = class extends hk {
constructor(t33, e2 = {}, n2) {
const o2 = t33.connections.flatMap((t34) => t34.pointsToConnect), i2 = new Map;
for (const t34 of o2)
t34.pointId && i2.set(t34.pointId, t34);
const r2 = o2.map((t34) => t34.pointId).filter((t34) => !!t34), s2 = new ek(r2), a2 = [];
for (const e3 of t33.connections)
e3.isOffBoard ? e3.pointsToConnect.length >= 2 && e3.pointsToConnect[0].pointId && e3.pointsToConnect[1].pointId && s2.union(e3.pointsToConnect[0].pointId, e3.pointsToConnect[1].pointId) : a2.push(e3);
super({ ...t33, connections: a2 }, e2, n2), this.ogSrj = t33, this.colorMap = e2, this.connectionPointDsu = s2, this.connectionPointMap = i2, this.ogSrj = t33;
}
getSolverName() {
return "NetToPointPairsSolver2_OffBoardConnection";
}
connectionPointDsu;
connectionPointMap;
_findBestConnectionPointsFromDisjointSets(t33, e2) {
if (!t33.pointId || !e2.pointId)
return { pointsToConnect: [t33, e2] };
const n2 = this.connectionPointDsu.getGroup(t33.pointId).map((t34) => this.connectionPointMap.get(t34)), o2 = this.connectionPointDsu.getGroup(e2.pointId).map((t34) => this.connectionPointMap.get(t34));
let i2 = t33, r2 = e2, s2 = 1 / 0;
for (const t34 of n2)
for (const e3 of o2) {
const n3 = Math.sqrt(Math.pow(t34.x - e3.x, 2) + Math.pow(t34.y - e3.y, 2));
n3 < s2 && (s2 = n3, i2 = t34, r2 = e3);
}
return { pointsToConnect: [i2, r2] };
}
_step() {
if (this.unprocessedConnections.length === 0)
return void (this.solved = true);
const t33 = this.unprocessedConnections.pop(), { zeroWeightEdges: e2, arePointsConnected: n2 } = ak(t33, this.initiallyConnectedMap);
if (t33.pointsToConnect.length === 2) {
const [e3, o3] = t33.pointsToConnect;
if (e3 && o3 && n2(e3, o3))
return;
const i3 = this._findBestConnectionPointsFromDisjointSets(t33.pointsToConnect[0], t33.pointsToConnect[1]);
return void this.newConnections.push({ ...t33, pointsToConnect: i3.pointsToConnect, __rootConnectionNames: t33.__rootConnectionNames ?? [t33.name] });
}
const o2 = rk(t33.pointsToConnect, { extraEdges: e2 });
let i2 = 0;
for (const e3 of o2) {
if (n2(e3.from, e3.to))
continue;
const o3 = this._findBestConnectionPointsFromDisjointSets(e3.from, e3.to);
this.newConnections.push({ ...t33, pointsToConnect: o3.pointsToConnect, name: `${t33.name}_mst${i2++}`, __rootConnectionNames: t33.__rootConnectionNames ?? [t33.name], __netConnectionName: t33.__netConnectionName });
}
}
};
var uk = class {
netMap;
idToNetMap;
constructor(t33) {
this.netMap = t33, this.idToNetMap = {};
for (const [e2, n2] of Object.entries(t33))
for (const t34 of n2)
this.idToNetMap[t34] = e2;
}
addConnections(t33) {
for (const e2 of t33) {
const t34 = new Set;
for (const n3 of e2) {
const e3 = this.idToNetMap[n3];
e3 && t34.add(e3);
}
let n2;
if (t34.size === 0)
n2 = `connectivity_net${Object.keys(this.netMap).length}`, this.netMap[n2] = [];
else if (t34.size === 1)
n2 = t34.values().next().value ?? `connectivity_net${Object.keys(this.netMap).length}`;
else {
n2 = t34.values().next().value ?? `connectivity_net${Object.keys(this.netMap).length}`;
for (const e3 of t34)
if (e3 !== n2) {
const t35 = this.netMap[n2], o2 = this.netMap[e3];
if (t35 && o2) {
t35.push(...o2), this.netMap[e3] = t35;
for (const e4 of t35)
this.idToNetMap[e4] = n2;
}
}
}
for (const t35 of e2) {
const e3 = this.netMap[n2];
e3 && !e3.includes(t35) && e3.push(t35), this.idToNetMap[t35] = n2;
}
}
}
getIdsConnectedToNet(t33) {
return this.netMap[t33] || [];
}
getNetConnectedToId(t33) {
return this.idToNetMap[t33];
}
areIdsConnected(t33, e2) {
if (t33 === e2)
return true;
const n2 = this.getNetConnectedToId(t33);
if (!n2)
return false;
const o2 = this.getNetConnectedToId(e2);
return !!o2 && (n2 === o2 || o2 === t33 || o2 === t33);
}
areAllIdsConnected(t33) {
if (t33.length === 0)
return true;
const e2 = this.getNetConnectedToId(t33[0]);
if (!e2)
return false;
for (const n2 of t33) {
const t34 = this.getNetConnectedToId(n2);
if (t34 === undefined)
return false;
if (t34 !== e2)
return false;
}
return true;
}
};
function pk(t33, e2 = {}) {
const n2 = [], o2 = [], i2 = e2.color ?? "gray", r2 = e2.label, s2 = Xo[t33.footprint] ?? Xo["0603"], a2 = t33.end.x - t33.start.x, c2 = t33.end.y - t33.start.y, l2 = Math.abs(a2) > Math.abs(c2), h2 = l2 ? s2.padLength : s2.padWidth, d2 = l2 ? s2.padWidth : s2.padLength;
return n2.push({ center: t33.start, width: h2, height: d2, fill: Ao(i2, 0.5), stroke: "rgba(0, 0, 0, 0.5)", layer: "jumper", label: r2 ? `${r2} (start)` : undefined }), n2.push({ center: t33.end, width: h2, height: d2, fill: Ao(i2, 0.5), stroke: "rgba(0, 0, 0, 0.5)", layer: "jumper", label: r2 ? `${r2} (end)` : undefined }), o2.push({ points: [t33.start, t33.end], strokeColor: "rgba(100, 100, 100, 0.8)", strokeWidth: 0.3 * s2.padWidth, layer: "jumper-body" }), { rects: n2, lines: o2 };
}
function mk(t33, e2 = {}) {
const n2 = { rects: [], lines: [] };
for (const o2 of t33) {
const { rects: t34, lines: i2 } = pk(o2, e2);
n2.rects.push(...t34), n2.lines.push(...i2);
}
return n2;
}
var vk = class {
tree;
constructor(t33 = 9) {
this.tree = new te(t33);
}
insert(t33, e2, n2, o2, i2) {
this.tree.insert({ minX: e2, minY: n2, maxX: o2, maxY: i2, data: t33 });
}
bulkLoad(t33) {
const e2 = t33.map(({ item: t34, minX: e3, minY: n2, maxX: o2, maxY: i2 }) => ({ minX: e3, minY: n2, maxX: o2, maxY: i2, data: t34 }));
this.tree.load(e2);
}
search(t33, e2, n2, o2) {
return this.tree.search({ minX: t33, minY: e2, maxX: n2, maxY: o2 }).map((t34) => t34.data);
}
clear() {
this.tree.clear();
}
};
var Ik = class {
index;
items = [];
currentIndex = 0;
capacity;
constructor(t33) {
this.capacity = Math.max(1, t33), this.index = new Ft(this.capacity);
}
insert(t33, e2, n2, o2, i2) {
if (this.currentIndex >= this.index.numItems)
throw new Error("Exceeded initial capacity");
this.items[this.currentIndex] = t33, this.index.add(e2, n2, o2, i2), this.currentIndex++;
}
finish() {
this.index.finish();
}
search(t33, e2, n2, o2) {
return this.index.search(t33, e2, n2, o2).map((t34) => this.items[t34] || null).filter(Boolean);
}
clear() {
this.items = [], this.currentIndex = 0, this.index = new Ft(this.capacity);
}
};
var Sk = class {
idx;
storage = [];
constructor(t33 = "native", e2 = []) {
t33 === "flatbush" ? e2.length === 0 ? (this.idx = new vk, t33 = "rbush") : this.idx = new Ik(e2.length) : this.idx = t33 === "rbush" ? new vk : new class {
shi = new Ck(e2);
insert(t34) {}
search(t34, e3, n2, o2) {
const i2 = (t34 + n2) / 2, r2 = (e3 + o2) / 2, s2 = n2 - t34, a2 = o2 - e3;
return this.shi.getNodesInArea(i2, r2, s2, a2);
}
clear() {}
}, e2.forEach((t34) => this.insert(t34)), t33 === "flatbush" && e2.length > 0 && this.idx.finish?.();
}
insert(t33) {
this.storage.push(t33), this.idx.insert(t33, t33.center.x - t33.width / 2, t33.center.y - t33.height / 2, t33.center.x + t33.width / 2, t33.center.y + t33.height / 2);
}
search(t33) {
return this.idx.search(t33.minX, t33.minY, t33.maxX, t33.maxY);
}
searchArea(t33, e2, n2, o2) {
return this.search({ minX: t33 - n2 / 2, minY: e2 - o2 / 2, maxX: t33 + n2 / 2, maxY: e2 + o2 / 2 });
}
};
var Ck = class {
constructor(t33) {
this.obstacles = t33, this.buckets = new Map;
for (let e2 = 0;e2 < t33.length; e2++) {
const n2 = t33[e2], o2 = n2.center.x - n2.width / 2, i2 = n2.center.y - n2.height / 2, r2 = n2.center.x + n2.width / 2, s2 = n2.center.y + n2.height / 2;
for (let t34 = o2;t34 <= r2; t34 += this.CELL_SIZE)
for (let o3 = i2;o3 <= s2; o3 += this.CELL_SIZE) {
const i3 = this.getBucketKey(t34, o3), r3 = this.buckets.get(i3);
r3 ? r3.push([n2, e2]) : this.buckets.set(i3, [[n2, e2]]);
}
}
}
buckets;
CELL_SIZE = 0.4;
getBucketKey(t33, e2) {
return `${Math.floor(t33 / this.CELL_SIZE)}x${Math.floor(e2 / this.CELL_SIZE)}`;
}
getNodesInArea(t33, e2, n2, o2) {
const i2 = [], r2 = new Set, s2 = e2 - o2 / 2, a2 = t33 + n2 / 2, c2 = e2 + o2 / 2;
for (let e3 = t33 - n2 / 2;e3 <= a2; e3 += this.CELL_SIZE)
for (let t34 = s2;t34 <= c2; t34 += this.CELL_SIZE) {
const n3 = this.getBucketKey(e3, t34), o3 = this.buckets.get(n3) || [];
for (const t35 of o3)
r2.has(t35[1]) || (r2.add(t35[1]), i2.push(t35[0]));
}
return i2;
}
};
var Pk = (t33, e2) => {
const n2 = [], o2 = Math.abs(e2.x - t33.x), i2 = Math.abs(e2.y - t33.y), r2 = e2.x > t33.x ? 1 : -1, s2 = e2.y > t33.y ? 1 : -1, a2 = { x: e2.x - r2 * Math.abs(e2.y - t33.y), y: t33.y };
(a2.x - t33.x) * r2 >= 0 && (a2.x - e2.x) * r2 <= 0 && n2.push([t33, a2, e2]);
const c2 = { x: t33.x, y: e2.y - s2 * Math.abs(e2.x - t33.x) };
(c2.y - t33.y) * s2 >= 0 && (c2.y - e2.y) * s2 <= 0 && n2.push([t33, c2, e2]);
const l2 = Math.min(o2, i2), h2 = { x: t33.x + r2 * l2, y: t33.y + s2 * l2 };
return (h2.x - t33.x) * r2 >= 0 && (h2.x - e2.x) * r2 <= 0 && (h2.y - t33.y) * s2 >= 0 && (h2.y - e2.y) * s2 <= 0 && n2.push([t33, h2, e2]), n2;
};
function Mk(t33, e2, n2, o2) {
if (fe(t33, e2, n2, o2))
return 0;
const i2 = Nk(t33, n2, o2), r2 = Nk(e2, n2, o2), s2 = Nk(n2, t33, e2), a2 = Nk(o2, t33, e2);
return Math.min(i2, r2, s2, a2);
}
function Nk(t33, e2, n2) {
const o2 = { x: n2.x - e2.x, y: n2.y - e2.y }, i2 = wk({ x: t33.x - e2.x, y: t33.y - e2.y }, o2);
if (i2 <= 0)
return Tk(t33, e2);
const r2 = wk(o2, o2);
if (r2 <= i2)
return Tk(t33, n2);
const s2 = i2 / r2;
return Tk(t33, { x: e2.x + s2 * o2.x, y: e2.y + s2 * o2.y });
}
function wk(t33, e2) {
return t33.x * e2.x + t33.y * e2.y;
}
function Tk(t33, e2) {
const n2 = e2.x - t33.x, o2 = e2.y - t33.y;
return Math.sqrt(n2 * n2 + o2 * o2);
}
var Rk = 0.000001;
var Ek = (t33, e2, n2) => be(t33, e2, n2) <= Rk;
var Ak = (t33, e2) => Math.abs(t33.x - e2.x) <= Rk && Math.abs(t33.y - e2.y) <= Rk;
var Ok = (t33, e2) => {
if (!e2 || e2.length < 3)
return false;
for (let n3 = 0;n3 < e2.length; n3++) {
const o2 = e2[n3], i2 = e2[(n3 + 1) % e2.length];
if (Ek(t33, o2, i2))
return true;
}
let n2 = false;
for (let o2 = 0, i2 = e2.length - 1;o2 < e2.length; i2 = o2++) {
const r2 = e2[o2], s2 = e2[i2];
r2.y > t33.y != s2.y > t33.y && t33.x < (s2.x - r2.x) * (t33.y - r2.y) / (s2.y - r2.y) + r2.x && (n2 = !n2);
}
return n2;
};
var kk = ({ start: t33, end: e2, polygon: n2, margin: o2 = 0.2 }) => {
if (!n2 || n2.length < 3)
return false;
const i2 = Ok(t33, n2), r2 = Ok(e2, n2);
if (!i2 || !r2)
return true;
for (let i3 = 0;i3 < n2.length; i3++) {
const r3 = n2[i3], s2 = n2[(i3 + 1) % n2.length], a2 = Ek(t33, r3, s2), c2 = Ek(e2, r3, s2);
if (a2 && c2)
continue;
if (!fe(t33, e2, r3, s2)) {
if (!a2 && !c2) {
if (Mk(t33, e2, r3, s2) < o2 - Rk)
return true;
}
continue;
}
const l2 = ve(t33, e2, r3, s2);
if ((!l2 || !(a2 && Ak(l2, t33) || c2 && Ak(l2, e2))) && (!l2 || !Ak(l2, t33) && !Ak(l2, e2)))
return true;
}
return false;
};
var Dk = (t33) => {
const e2 = [], n2 = t33.route;
if (n2.length === 0)
return [];
let o2 = { startIndex: 0, endIndex: -1, z: n2[0].z, points: [n2[0]] };
for (let t34 = 1;t34 < n2.length; t34++)
n2[t34].z === o2.z ? o2.points.push(n2[t34]) : (o2.endIndex = t34 - 1, e2.push(o2), o2 = { startIndex: t34, endIndex: -1, z: n2[t34].z, points: [n2[t34]] });
return o2.endIndex = n2.length - 1, e2.push(o2), e2;
};
var Lk = ({ endpointX: t33, endpointY: e2, targetZ: n2, endpointPcbPortId: o2, terminalLayerIndicesByPcbPortId: i2, obstacleSHI: r2, route: s2, connMap: a2 }) => {
const c2 = o2 ? i2?.get(o2) : undefined;
if (c2 && !c2.has(n2))
return false;
const l2 = [s2.connectionName, s2.rootConnectionName].filter((t34) => t34 !== undefined), h2 = r2.searchArea(t33, e2, 2, 2).filter((n3) => {
if (!l2.some((t34) => n3.connectedTo.some((e3) => e3 === t34 || a2.areIdsConnected(t34, e3))))
return false;
const o3 = n3.width / 2 + 0.05, i3 = n3.height / 2 + 0.05, r3 = Math.abs(t33 - n3.center.x) <= o3, s3 = Math.abs(e2 - n3.center.y) <= i3;
return r3 && s3;
});
return h2.length > 0 && h2.some((t34) => t34.__zLayers?.includes(n2));
};
var zk = ({ currentSection: t33, targetZ: e2, route: n2, hdRouteSHI: o2, obstacleSHI: i2, connMap: r2, defaultTraceThickness: s2, obstacleMargin: a2, traceMargin: c2, shouldCheckStaticGeometryForSegment: l2 }) => {
const h2 = n2.traceThickness ?? s2, d2 = c2 ?? 0, u2 = [n2.connectionName, n2.rootConnectionName].filter((t34) => t34 !== undefined);
for (let n3 = 0;n3 < t33.points.length - 1; n3++) {
const c3 = { ...t33.points[n3], z: e2 }, p2 = { ...t33.points[n3 + 1], z: e2 }, m2 = o2.getConflictingRoutesForSegment(c3, p2, h2 / 2 + d2);
for (const { conflictingRoute: t34, distance: e3 } of m2) {
const n4 = [t34.connectionName, t34.rootConnectionName].filter((t35) => t35 !== undefined);
if (u2.some((t35) => n4.some((e4) => e4 === t35 || r2.areIdsConnected(e4, t35))))
continue;
const o3 = t34.traceThickness ?? s2;
if (e3 < h2 / 2 + (d2 > 0 ? Math.max(o3 / 2, t34.viaDiameter / 2) : o3 / 2) + d2)
return false;
}
if (l2?.(c3, p2) === false)
continue;
const g2 = { centerX: (c3.x + p2.x) / 2, centerY: (c3.y + p2.y) / 2, width: Math.abs(c3.x - p2.x), height: Math.abs(c3.y - p2.y) }, f2 = h2 / 2 + a2, y2 = i2.searchArea(g2.centerX, g2.centerY, g2.width + 2 * f2, g2.height + 2 * f2);
for (const t34 of y2) {
if (u2.some((e3) => t34.connectedTo.some((t35) => t35 === e3 || r2.areIdsConnected(t35, e3))))
continue;
if (t34.__zLayers?.includes(e2)) {
if (Math.abs(c3.x - t34.center.x) < 0.01 && Math.abs(c3.y - t34.center.y) < 0.01 || Math.abs(p2.x - t34.center.x) < 0.01 && Math.abs(p2.y - t34.center.y) < 0.01)
continue;
}
if (De(c3, p2, t34) < f2)
return false;
}
}
return true;
};
var Bk = class extends si {
getSolverName() {
return "SingleRouteUselessViaRemovalSolver";
}
obstacleSHI;
hdRouteSHI;
unsimplifiedRoute;
connMap;
outline;
terminalLayerIndicesByPcbPortId;
routeSections;
currentSectionIndex;
TRACE_THICKNESS = 0.15;
OBSTACLE_MARGIN = 0.1;
GEOMETRY_SHORTCUT_TRACE_MARGIN = 0.1;
GEOMETRY_SHORTCUT_OBSTACLE_MARGIN = 0.15;
MAX_GEOMETRY_SHORTCUT_ADDED_LENGTH = 4;
ENABLE_GEOMETRY_SHORTCUTS = true;
ENABLE_OBSTACLE_DETOUR_SHORTCUTS = false;
PRESERVE_ROUTE_ENDPOINTS = false;
geometryShortcutsApplied = 0;
multilayerSectionsCollapsed = 0;
obstacleDetourCandidatesValidated = 0;
constructor(t33) {
super(), this.currentSectionIndex = 0, this.obstacleSHI = t33.obstacleSHI, this.hdRouteSHI = t33.hdRouteSHI, this.unsimplifiedRoute = t33.unsimplifiedRoute, this.connMap = t33.connMap, this.outline = t33.outline, this.terminalLayerIndicesByPcbPortId = t33.terminalLayerIndicesByPcbPortId, this.GEOMETRY_SHORTCUT_TRACE_MARGIN = t33.geometryShortcutTraceMargin ?? this.GEOMETRY_SHORTCUT_TRACE_MARGIN, this.GEOMETRY_SHORTCUT_OBSTACLE_MARGIN = t33.geometryShortcutObstacleMargin ?? this.GEOMETRY_SHORTCUT_OBSTACLE_MARGIN, this.ENABLE_GEOMETRY_SHORTCUTS = t33.enableGeometryShortcuts ?? true, this.ENABLE_OBSTACLE_DETOUR_SHORTCUTS = t33.enableObstacleDetourShortcuts ?? false, this.PRESERVE_ROUTE_ENDPOINTS = t33.preserveRouteEndpoints ?? false, this.routeSections = Dk(this.unsimplifiedRoute);
}
getPathLength(t33) {
let e2 = 0;
for (let n2 = 1;n2 < t33.length; n2++)
e2 += Math.hypot(t33[n2].x - t33[n2 - 1].x, t33[n2].y - t33[n2 - 1].y);
return e2;
}
normalizeShortcutPath(t33, e2, n2) {
const o2 = t33.filter((e3, n3) => {
const o3 = t33[n3 - 1];
return !o3 || e3.x !== o3.x || e3.y !== o3.y;
});
return o2.map((t34, i2) => i2 === 0 ? { ...e2 } : i2 === o2.length - 1 ? { ...n2 } : { x: t34.x, y: t34.y, z: e2.z });
}
shortcutCrossesOutline(t33) {
if (!this.outline || this.outline.length < 3)
return false;
for (let e2 = 1;e2 < t33.length; e2++)
if (kk({ start: t33[e2 - 1], end: t33[e2], polygon: this.outline }))
return true;
return false;
}
getObstacleDetourPaths(t33, e2, n2, o2) {
const i2 = (this.unsimplifiedRoute.traceThickness ?? this.TRACE_THICKNESS) / 2 + this.GEOMETRY_SHORTCUT_OBSTACLE_MARGIN + 0.000001, r2 = this.MAX_GEOMETRY_SHORTCUT_ADDED_LENGTH / 2 + i2, s2 = Math.min(t33.x, e2.x) - r2, a2 = Math.max(t33.x, e2.x) + r2, c2 = Math.min(t33.y, e2.y) - r2, l2 = Math.max(t33.y, e2.y) + r2, h2 = this.obstacleSHI.search({ minX: s2, minY: c2, maxX: a2, maxY: l2 }).filter((t34) => t34.__zLayers?.includes(n2));
if (h2.length === 0)
return [];
const d2 = new Set, u2 = new Set;
for (const t34 of h2)
d2.add(t34.center.x - t34.width / 2 - i2), d2.add(t34.center.x + t34.width / 2 + i2), u2.add(t34.center.y - t34.height / 2 - i2), u2.add(t34.center.y + t34.height / 2 + i2);
const p2 = [], m2 = new Set, g2 = (n3) => {
let i3 = 0;
for (let t34 = 1;t34 < n3.length; t34++)
i3 += Math.hypot(n3[t34].x - n3[t34 - 1].x, n3[t34].y - n3[t34 - 1].y);
if (i3 > o2)
return;
const r3 = this.normalizeShortcutPath(n3, t33, e2);
let s3 = 0, a3 = -1;
for (let t34 = 0;t34 < r3.length - 1; t34++) {
const e3 = r3[t34 + 1].x - r3[t34].x, n4 = r3[t34 + 1].y - r3[t34].y, o3 = e3 * e3 + n4 * n4;
o3 > a3 && (s3 = t34, a3 = o3);
}
const c3 = r3.map((t34) => `${t34.x}:${t34.y}`).join("|");
m2.has(c3) || (m2.add(c3), p2.push({ path: r3, length: i3, longestSegmentIndex: s3 }));
};
for (const n3 of u2)
g2([t33, { x: t33.x, y: n3 }, { x: e2.x, y: n3 }, e2]);
for (const n3 of d2)
g2([t33, { x: n3, y: t33.y }, { x: n3, y: e2.y }, e2]);
return p2;
}
getDirectGeometryShortcut(t33, e2, n2) {
let o2 = null;
for (let i2 = 0;i2 < t33.points.length; i2++) {
const r2 = t33.points[i2];
for (let s2 = 0;s2 < n2.points.length; s2++) {
const a2 = n2.points[s2], c2 = [...t33.points.slice(i2), ...e2.points, ...n2.points.slice(0, s2 + 1)];
if (!c2.some((t34) => t34.insideJumperPad || t34.toNextSegmentType))
for (const e3 of Pk(r2, a2)) {
const l2 = this.normalizeShortcutPath(e3, r2, a2), h2 = this.getPathLength(c2) - this.getPathLength(l2);
if (h2 < -1e-6 || this.shortcutCrossesOutline(l2))
continue;
const d2 = { startIndex: t33.startIndex + i2, endIndex: n2.startIndex + s2, z: t33.z, points: l2 };
zk({ currentSection: d2, targetZ: t33.z, route: this.unsimplifiedRoute, hdRouteSHI: this.hdRouteSHI, obstacleSHI: this.obstacleSHI, connMap: this.connMap, defaultTraceThickness: this.TRACE_THICKNESS, obstacleMargin: this.GEOMETRY_SHORTCUT_OBSTACLE_MARGIN, traceMargin: this.GEOMETRY_SHORTCUT_TRACE_MARGIN }) && ((!o2 || h2 > o2.savedLength) && (o2 = { path: l2, previousPointIndex: i2, nextPointIndex: s2, savedLength: h2 }));
}
}
}
return o2;
}
getObstacleDetourShortcut(t33, e2, n2) {
const o2 = t33.points.length - 1, i2 = [];
for (let t34 = 0;t34 <= o2; t34++)
i2.push([t34, 0]);
for (let t34 = 1;t34 < n2.points.length; t34++)
i2.push([o2, t34]);
const r2 = [];
for (const [o3, s3] of i2) {
const i3 = t33.points[o3], a3 = n2.points[s3], c3 = [...t33.points.slice(o3), ...e2.points, ...n2.points.slice(0, s3 + 1)];
if (c3.some((t34) => t34.insideJumperPad || t34.toNextSegmentType))
continue;
const l2 = this.getPathLength(c3);
for (const { path: e3, length: n3, longestSegmentIndex: c4 } of this.getObstacleDetourPaths(i3, a3, t33.z, l2 + this.MAX_GEOMETRY_SHORTCUT_ADDED_LENGTH + 0.000001)) {
const t34 = l2 - n3;
t34 < -this.MAX_GEOMETRY_SHORTCUT_ADDED_LENGTH - 0.000001 || r2.push({ path: e3, previousPointIndex: o3, nextPointIndex: s3, savedLength: t34, validationFirstSegmentIndex: c4 });
}
}
r2.sort((t34, e3) => e3.savedLength - t34.savedLength);
let s2 = 0;
const a2 = r2.length >= 256, c2 = (({ targetZ: t34, route: e3, hdRouteSHI: n3, obstacleSHI: o3, connMap: i3, defaultTraceThickness: r3, obstacleMargin: s3, traceMargin: a3, useNumericSegmentKeys: c3 }) => {
const l2 = e3.traceThickness ?? r3, h2 = l2 / 2 + a3, d2 = l2 / 2 + s3, u2 = e3.connectionName, p2 = e3.rootConnectionName, m2 = new Map, g2 = new WeakMap, f2 = new WeakMap, y2 = c3 ? new Map : undefined;
let _2 = 0;
const b2 = (t35) => {
let e4 = y2.get(t35.x);
e4 || (e4 = new Map, y2.set(t35.x, e4));
let n4 = e4.get(t35.y);
return n4 === undefined && (n4 = _2++, e4.set(t35.y, n4)), n4;
}, x2 = (t35, e4) => {
if (c3) {
const n4 = b2(t35), o4 = b2(e4), i4 = Math.max(n4, o4);
return i4 * (i4 + 1) / 2 + Math.min(n4, o4);
}
return t35.x < e4.x || t35.x === e4.x && t35.y <= e4.y ? `${t35.x}:${t35.y}|${e4.x}:${e4.y}` : `${e4.x}:${e4.y}|${t35.x}:${t35.y}`;
}, v2 = (t35) => t35 === u2 || i3.areIdsConnected(t35, u2) || p2 !== undefined && (t35 === p2 || i3.areIdsConnected(t35, p2));
return (e4, i4) => {
const s4 = e4.length - 1;
for (let c4 = 0;c4 < s4; c4++) {
const s5 = c4 - 1, u3 = i4 === 0 ? c4 : c4 === 0 ? i4 : s5 >= i4 ? s5 + 1 : s5, p3 = e4[u3], y3 = e4[u3 + 1], _3 = x2(p3, y3), b3 = m2.get(_3);
if (b3 !== undefined) {
if (!b3)
return false;
continue;
}
const I2 = p3.z === t34 ? p3 : { ...p3, z: t34 }, S2 = y3.z === t34 ? y3 : { ...y3, z: t34 }, C2 = { centerX: (I2.x + S2.x) / 2, centerY: (I2.y + S2.y) / 2, width: Math.abs(I2.x - S2.x), height: Math.abs(I2.y - S2.y) }, P2 = o3.searchArea(C2.centerX, C2.centerY, C2.width + 2 * d2, C2.height + 2 * d2);
for (const e5 of P2) {
let n4 = g2.get(e5);
if ((n4 === undefined && (n4 = e5.connectedTo.some(v2), g2.set(e5, n4)), !n4) && ((!e5.__zLayers?.includes(t34) || !(Math.abs(I2.x - e5.center.x) < 0.01 && Math.abs(I2.y - e5.center.y) < 0.01 || Math.abs(S2.x - e5.center.x) < 0.01 && Math.abs(S2.y - e5.center.y) < 0.01)) && De(I2, S2, e5) < d2))
return m2.set(_3, false), false;
}
const M2 = n3.getConflictingRoutesForSegment(I2, S2, h2);
for (const { conflictingRoute: t35, distance: e5 } of M2) {
let n4 = f2.get(t35);
if (n4 === undefined && (n4 = v2(t35.connectionName) || t35.rootConnectionName !== undefined && v2(t35.rootConnectionName), f2.set(t35, n4)), n4)
continue;
const o4 = t35.traceThickness ?? r3, i5 = Math.max(o4 / 2, t35.viaDiameter / 2);
if (e5 < l2 / 2 + i5 + a3)
return m2.set(_3, false), false;
}
m2.set(_3, true);
}
return true;
};
})({ targetZ: t33.z, route: this.unsimplifiedRoute, hdRouteSHI: this.hdRouteSHI, obstacleSHI: this.obstacleSHI, connMap: this.connMap, defaultTraceThickness: this.TRACE_THICKNESS, obstacleMargin: this.GEOMETRY_SHORTCUT_OBSTACLE_MARGIN, traceMargin: this.GEOMETRY_SHORTCUT_TRACE_MARGIN, useNumericSegmentKeys: a2 });
for (const t34 of r2) {
s2++;
const { path: e3 } = t34;
if (c2(e3, t34.validationFirstSegmentIndex ?? 0) && !this.shortcutCrossesOutline(e3))
return this.obstacleDetourCandidatesValidated += s2, this.stats.obstacleDetourCandidatesValidated = this.obstacleDetourCandidatesValidated, t34;
}
return this.obstacleDetourCandidatesValidated += s2, this.stats.obstacleDetourCandidatesValidated = this.obstacleDetourCandidatesValidated, null;
}
findGeometryShortcut(t33, e2, n2) {
if (this.unsimplifiedRoute.jumpers?.length)
return null;
if (this.ENABLE_GEOMETRY_SHORTCUTS) {
const o2 = this.getDirectGeometryShortcut(t33, e2, n2);
if (o2)
return o2;
}
return this.ENABLE_OBSTACLE_DETOUR_SHORTCUTS ? this.getObstacleDetourShortcut(t33, e2, n2) : null;
}
applyGeometryShortcut(t33) {
const e2 = this.routeSections[this.currentSectionIndex - 1], n2 = this.routeSections[this.currentSectionIndex + 1], o2 = [...e2.points.slice(0, t33.previousPointIndex), ...t33.path, ...n2.points.slice(t33.nextPointIndex + 1)].filter((t34, e3, n3) => {
const o3 = n3[e3 - 1];
return !o3 || t34.x !== o3.x || t34.y !== o3.y || t34.z !== o3.z;
});
this.routeSections.splice(this.currentSectionIndex - 1, 3, { startIndex: e2.startIndex, endIndex: n2.endIndex, z: e2.z, points: o2 }), this.geometryShortcutsApplied++, this.stats.geometryShortcutsApplied = this.geometryShortcutsApplied, this.stats.viasRemovedByGeometryShortcuts = 2 * this.geometryShortcutsApplied, this.currentSectionIndex = Math.max(0, this.currentSectionIndex - 1);
}
findMultilayerSectionCollapse(t33, e2, n2) {
if (t33.z === n2.z || this.unsimplifiedRoute.jumpers?.length)
return null;
const o2 = t33.points[t33.points.length - 1];
if (o2?.insideJumperPad || o2?.toNextSegmentType || e2.points.some((t34) => t34.insideJumperPad || t34.toNextSegmentType))
return null;
const i2 = [{ targetZ: t33.z, mergeWith: "previous" }, { targetZ: n2.z, mergeWith: "next" }];
for (const t34 of i2)
if (t34.targetZ !== e2.z && zk({ currentSection: e2, targetZ: t34.targetZ, route: this.unsimplifiedRoute, hdRouteSHI: this.hdRouteSHI, obstacleSHI: this.obstacleSHI, connMap: this.connMap, defaultTraceThickness: this.TRACE_THICKNESS, obstacleMargin: this.GEOMETRY_SHORTCUT_OBSTACLE_MARGIN, traceMargin: this.GEOMETRY_SHORTCUT_TRACE_MARGIN }))
return t34;
return null;
}
applyMultilayerSectionCollapse(t33) {
const e2 = this.routeSections[this.currentSectionIndex - 1], n2 = this.routeSections[this.currentSectionIndex], o2 = this.routeSections[this.currentSectionIndex + 1], i2 = n2.points.map((e3) => ({ ...e3, z: t33.targetZ })), r2 = (t34) => t34.filter((e3, n3) => {
const o3 = t34[n3 - 1];
return !o3 || e3.x !== o3.x || e3.y !== o3.y || e3.z !== o3.z;
});
t33.mergeWith === "previous" ? this.routeSections.splice(this.currentSectionIndex - 1, 2, { startIndex: e2.startIndex, endIndex: n2.endIndex, z: t33.targetZ, points: r2([...e2.points, ...i2]) }) : this.routeSections.splice(this.currentSectionIndex, 2, { startIndex: n2.startIndex, endIndex: o2.endIndex, z: t33.targetZ, points: r2([...i2, ...o2.points]) }), this.multilayerSectionsCollapsed++, this.stats.multilayerSectionsCollapsed = this.multilayerSectionsCollapsed, this.stats.viasRemovedByMultilayerSectionCollapses = this.multilayerSectionsCollapsed, this.currentSectionIndex = Math.max(0, this.currentSectionIndex - 1);
}
_step() {
if (this.currentSectionIndex >= this.routeSections.length)
return void (this.solved = true);
if (this.currentSectionIndex === 0 && this.routeSections.length > 1) {
const t34 = this.routeSections[0], e3 = this.routeSections[1];
if (!this.PRESERVE_ROUTE_ENDPOINTS && t34.z !== e3.z) {
const n3 = e3.z, o3 = t34.points[0];
if (Lk({ endpointX: o3.x, endpointY: o3.y, targetZ: n3, endpointPcbPortId: this.unsimplifiedRoute.startPcbPortId, terminalLayerIndicesByPcbPortId: this.terminalLayerIndicesByPcbPortId, obstacleSHI: this.obstacleSHI, route: this.unsimplifiedRoute, connMap: this.connMap }) && zk({ currentSection: t34, targetZ: n3, route: this.unsimplifiedRoute, hdRouteSHI: this.hdRouteSHI, obstacleSHI: this.obstacleSHI, connMap: this.connMap, defaultTraceThickness: this.TRACE_THICKNESS, obstacleMargin: this.OBSTACLE_MARGIN }))
return t34.z = n3, t34.points = t34.points.map((t35) => ({ ...t35, z: n3 })), void (this.currentSectionIndex = 2);
}
return void this.currentSectionIndex++;
}
if (this.currentSectionIndex === this.routeSections.length - 1) {
if (!this.PRESERVE_ROUTE_ENDPOINTS && this.routeSections.length >= 2) {
const t34 = this.routeSections[this.routeSections.length - 1], e3 = this.routeSections[this.routeSections.length - 2];
if (t34.z !== e3.z) {
const n3 = e3.z, o3 = t34.points[t34.points.length - 1];
Lk({ endpointX: o3.x, endpointY: o3.y, targetZ: n3, endpointPcbPortId: this.unsimplifiedRoute.endPcbPortId, terminalLayerIndicesByPcbPortId: this.terminalLayerIndicesByPcbPortId, obstacleSHI: this.obstacleSHI, route: this.unsimplifiedRoute, connMap: this.connMap }) && zk({ currentSection: t34, targetZ: n3, route: this.unsimplifiedRoute, hdRouteSHI: this.hdRouteSHI, obstacleSHI: this.obstacleSHI, connMap: this.connMap, defaultTraceThickness: this.TRACE_THICKNESS, obstacleMargin: this.OBSTACLE_MARGIN }) && (t34.z = n3, t34.points = t34.points.map((t35) => ({ ...t35, z: n3 })));
}
}
return void (this.solved = true);
}
const t33 = this.routeSections[this.currentSectionIndex - 1], e2 = this.routeSections[this.currentSectionIndex], n2 = this.routeSections[this.currentSectionIndex + 1];
if (t33.z !== n2.z) {
const o3 = this.findMultilayerSectionCollapse(t33, e2, n2);
return o3 ? void this.applyMultilayerSectionCollapse(o3) : void this.currentSectionIndex++;
}
const o2 = t33.z;
if (zk({ currentSection: e2, targetZ: o2, route: this.unsimplifiedRoute, hdRouteSHI: this.hdRouteSHI, obstacleSHI: this.obstacleSHI, connMap: this.connMap, defaultTraceThickness: this.TRACE_THICKNESS, obstacleMargin: this.OBSTACLE_MARGIN }))
return e2.z = o2, e2.points = e2.points.map((t34) => ({ ...t34, z: o2 })), void (this.currentSectionIndex += 2);
const i2 = this.findGeometryShortcut(t33, e2, n2);
i2 ? this.applyGeometryShortcut(i2) : this.currentSectionIndex++;
}
getConstructorParams() {
return { obstacleSHI: this.obstacleSHI, hdRouteSHI: this.hdRouteSHI, unsimplifiedRoute: this.unsimplifiedRoute, connMap: this.connMap, outline: this.outline, geometryShortcutTraceMargin: this.GEOMETRY_SHORTCUT_TRACE_MARGIN, geometryShortcutObstacleMargin: this.GEOMETRY_SHORTCUT_OBSTACLE_MARGIN, enableGeometryShortcuts: this.ENABLE_GEOMETRY_SHORTCUTS, enableObstacleDetourShortcuts: this.ENABLE_OBSTACLE_DETOUR_SHORTCUTS, preserveRouteEndpoints: this.PRESERVE_ROUTE_ENDPOINTS, terminalLayerIndicesByPcbPortId: this.terminalLayerIndicesByPcbPortId };
}
getOptimizedHdRoute() {
const t33 = this.routeSections.flatMap((t34) => t34.points), e2 = [];
for (let n2 = 0;n2 < t33.length - 1; n2++)
t33[n2].z !== t33[n2 + 1].z && e2.push({ x: t33[n2].x, y: t33[n2].y });
return { connectionName: this.unsimplifiedRoute.connectionName, rootConnectionName: this.unsimplifiedRoute.rootConnectionName, startPcbPortId: this.unsimplifiedRoute.startPcbPortId, endPcbPortId: this.unsimplifiedRoute.endPcbPortId, route: t33, traceThickness: this.unsimplifiedRoute.traceThickness, vias: e2, viaDiameter: this.unsimplifiedRoute.viaDiameter, jumpers: this.unsimplifiedRoute.jumpers };
}
visualize() {
const t33 = { circles: [], lines: [], points: [], rects: [], coordinateSystem: "cartesian", title: "Single Route Useless Via Removal Solver" };
for (let e2 = 0;e2 < this.routeSections.length; e2++) {
const n2 = this.routeSections[e2];
t33.lines.push({ points: n2.points, strokeWidth: this.TRACE_THICKNESS, strokeColor: e2 === this.currentSectionIndex ? "orange" : n2.z === 0 ? "red" : "blue" });
}
return t33;
}
};
var Fk = class extends si {
constructor(t33) {
super(), this.input = t33, this.input = { ...t33, obstacles: Is(t33.obstacles, t33.layerCount) }, this.MAX_ITERATIONS = 1e6, this.unsimplifiedHdRoutes = t33.unsimplifiedHdRoutes, this.optimizedHdRoutes = [], this.unprocessedRoutes = [...t33.unsimplifiedHdRoutes], this.obstacleSHI = new Sk("flatbush", this.input.obstacles), this.hdRouteSHI = new hr([...this.unsimplifiedHdRoutes, ...t33.otherHdRoutes ?? []]);
}
getSolverName() {
return "UselessViaRemovalSolver";
}
unsimplifiedHdRoutes;
optimizedHdRoutes;
unprocessedRoutes;
activeSubSolver = null;
obstacleSHI = null;
hdRouteSHI = null;
_step() {
if (this.activeSubSolver) {
if (this.activeSubSolver.step(), this.activeSubSolver.solved) {
const t34 = this.activeSubSolver.getOptimizedHdRoute();
this.hdRouteSHI.removeRoute(t34.connectionName), this.hdRouteSHI.addRoute(t34), this.optimizedHdRoutes.push(t34), this.activeSubSolver = null;
} else
(this.activeSubSolver.failed || this.activeSubSolver.error) && (this.error = this.activeSubSolver.error, this.failed = true);
return;
}
const t33 = this.unprocessedRoutes.shift();
t33 ? this.activeSubSolver = new Bk({ hdRouteSHI: this.hdRouteSHI, obstacleSHI: this.obstacleSHI, unsimplifiedRoute: t33, connMap: this.input.connMap, outline: this.input.outline, geometryShortcutTraceMargin: this.input.geometryShortcutTraceMargin, geometryShortcutObstacleMargin: this.input.geometryShortcutObstacleMargin, enableGeometryShortcuts: this.input.enableGeometryShortcuts, enableObstacleDetourShortcuts: this.input.enableObstacleDetourShortcuts, preserveRouteEndpoints: this.input.preserveRouteEndpoints, terminalLayerIndicesByPcbPortId: this.input.terminalLayerIndicesByPcbPortId }) : this.solved = true;
}
getOptimizedHdRoutes() {
return this.optimizedHdRoutes;
}
visualize() {
const t33 = { lines: [], points: [], rects: [], circles: [], coordinateSystem: "cartesian", title: "Useless Via Removal Solver" };
for (const e2 of this.input.obstacles) {
let n2 = "rgba(128, 128, 128, 0.2)";
const o2 = e2.__zLayers?.includes(0), i2 = e2.__zLayers?.includes(1);
o2 && i2 ? n2 = "rgba(128, 0, 128, 0.2)" : o2 ? n2 = "rgba(255, 0, 0, 0.2)" : i2 && (n2 = "rgba(0, 0, 255, 0.2)"), t33.rects.push({ center: e2.center, width: e2.width, height: e2.height, fill: n2, label: `Obstacle (Z: ${e2.__zLayers?.join(", ")})` });
}
for (const e2 of this.optimizedHdRoutes) {
if (e2.route.length === 0)
continue;
const n2 = this.input.colorMap[e2.connectionName] || "#888888";
for (let n3 = 0;n3 < e2.route.length - 1; n3++) {
const o2 = e2.route[n3], i2 = e2.route[n3 + 1];
o2.z === i2.z && t33.lines.push({ points: [{ x: o2.x, y: o2.y }, { x: i2.x, y: i2.y }], strokeColor: o2.z === 0 ? "red" : "blue", strokeWidth: e2.traceThickness, label: `${e2.connectionName} (z=${o2.z})` });
}
for (const n3 of e2.vias)
t33.circles.push({ center: { x: n3.x, y: n3.y }, radius: e2.viaDiameter / 2, fill: "rgba(255, 0, 255, 0.5)", label: `${e2.connectionName} via` });
if (e2.jumpers && e2.jumpers.length > 0) {
const o2 = mk(e2.jumpers, { color: n2, label: e2.connectionName });
t33.rects.push(...o2.rects ?? []), t33.lines.push(...o2.lines ?? []);
}
}
return this.activeSubSolver && t33.lines.push(...this.activeSubSolver.visualize().lines ?? []), t33;
}
};
var jk = class extends si {
getSolverName() {
return "SingleSimplifiedPathSolver";
}
newRoute;
newVias;
headIndex = 0;
tailIndex = 0;
inputRoute;
otherHdRoutes;
obstacles;
connMap;
colorMap;
outline;
minBoardEdgeClearance;
constructor(t33) {
super(), this.inputRoute = t33.inputRoute, this.otherHdRoutes = t33.otherHdRoutes, this.obstacles = t33.obstacles, this.connMap = t33.connMap, this.colorMap = t33.colorMap, this.outline = t33.outline, this.minBoardEdgeClearance = t33.minBoardEdgeClearance ?? 0.2, this.newRoute = [this.inputRoute.route[0]], this.newVias = [];
}
getConstructorParams() {
return { inputRoute: this.inputRoute, otherHdRoutes: this.otherHdRoutes, obstacles: this.obstacles, connMap: this.connMap.netMap, colorMap: this.colorMap, outline: this.outline, minBoardEdgeClearance: this.minBoardEdgeClearance };
}
get simplifiedRoute() {
return { connectionName: this.inputRoute.connectionName, rootConnectionName: this.inputRoute.rootConnectionName, startPcbPortId: this.inputRoute.startPcbPortId, endPcbPortId: this.inputRoute.endPcbPortId, traceThickness: this.inputRoute.traceThickness, viaDiameter: this.inputRoute.viaDiameter, route: this.newRoute, vias: this.newVias, jumpers: this.inputRoute.jumpers };
}
isValidPath(t33) {
throw new Error("Not implemented");
}
_step() {
throw new Error("Not implemented");
}
getVisualsForNewRouteAndObstacles() {
const t33 = { lines: [], points: [], circles: [], rects: [], coordinateSystem: "cartesian", title: "Simplified Path Solver" };
for (let e2 = 0;e2 < this.inputRoute.route.length - 1; e2++)
t33.lines.push({ points: [{ x: this.inputRoute.route[e2].x, y: this.inputRoute.route[e2].y }, { x: this.inputRoute.route[e2 + 1].x, y: this.inputRoute.route[e2 + 1].y }], strokeColor: "rgba(255, 0, 0, 0.8)", strokeDash: this.inputRoute.route[e2].z === 1 ? "5, 5" : undefined, layer: `z${this.inputRoute.route[e2].z.toString()}` });
for (let e2 = 0;e2 < this.newRoute.length; e2++)
e2 < this.newRoute.length - 1 && t33.lines.push({ points: [{ x: this.newRoute[e2].x, y: this.newRoute[e2].y }, { x: this.newRoute[e2 + 1].x, y: this.newRoute[e2 + 1].y }], strokeWidth: 0.15, strokeColor: "rgba(0, 255, 0, 0.8)", strokeDash: this.newRoute[e2].z === 1 ? [0.4, 0.4] : undefined, layer: `z${this.newRoute[e2].z.toString()}` }), t33.points.push({ x: this.newRoute[e2].x, y: this.newRoute[e2].y, color: "rgba(0, 255, 0, 0.8)", label: `z: ${this.newRoute[e2].z}`, layer: `z${this.newRoute[e2].z.toString()}` });
for (const e2 of this.newVias)
t33.circles.push({ center: e2, radius: this.inputRoute.viaDiameter / 2, fill: "rgba(0, 0, 255, 0.5)" });
for (const e2 of this.obstacles)
t33.rects.push({ center: e2.center, width: e2.width, height: e2.height, fill: e2.layers?.includes("top") ? "rgba(255, 0, 0, 0.3)" : e2.layers?.includes("bottom") ? "rgba(0, 0, 255, 0.3)" : "rgba(128, 128, 128, 0.3)" });
for (const e2 of this.otherHdRoutes)
for (let n2 = 0;n2 < e2.route.length - 1; n2++)
t33.lines.push({ points: [{ x: e2.route[n2].x, y: e2.route[n2].y }, { x: e2.route[n2 + 1].x, y: e2.route[n2 + 1].y }], strokeWidth: 0.15, strokeColor: e2.route[n2].z === 0 ? "rgba(255, 0, 255, 0.5)" : e2.route[n2].z === 1 ? "rgba(128, 0, 128, 0.5)" : "rgba(0, 0, 255, 0.5)", layer: `z${e2.route[n2].z.toString()}` });
if ("filteredObstaclePathSegments" in this) {
const e2 = this.filteredObstaclePathSegments;
for (const [n2, o2] of e2)
t33.lines.push({ points: [n2, o2] });
}
return t33;
}
};
var $k = (t33) => ({ minX: Math.min(t33[0].x, t33[1].x), maxX: Math.max(t33[0].x, t33[1].x), minY: Math.min(t33[0].y, t33[1].y), maxY: Math.max(t33[0].y, t33[1].y) });
var Yk = class {
constructor(t33, e2 = 0.4) {
this.segments = t33, this.buckets = new Map, this.SEGMENT_MARGIN = e2;
const n2 = new Map;
for (const e3 of t33) {
const t34 = this.getSegmentKey(e3);
if (n2.has(t34))
continue;
n2.set(t34, e3);
const o2 = $k(e3), i2 = Math.floor(o2.minX / this.CELL_SIZE), r2 = Math.floor(o2.maxX / this.CELL_SIZE), s2 = Math.floor(o2.minY / this.CELL_SIZE), a2 = Math.floor(o2.maxY / this.CELL_SIZE);
for (let n3 = i2;n3 <= r2; n3++)
for (let o3 = s2;o3 <= a2; o3++) {
const i3 = `${n3}x${o3}`, r3 = this.buckets.get(i3), s3 = [e3[0], e3[1], t34];
r3 ? r3.push(s3) : this.buckets.set(i3, [s3]);
}
}
}
buckets;
CELL_SIZE = 0.4;
SEGMENT_MARGIN;
getBucketKey(t33, e2) {
return `${Math.floor(t33 / this.CELL_SIZE)}x${Math.floor(e2 / this.CELL_SIZE)}`;
}
getSegmentKey(t33) {
return `${t33[0].x}-${t33[0].y}-${t33[0].z}-${t33[1].x}-${t33[1].y}-${t33[1].z}`;
}
getSegmentsThatCouldIntersect(t33, e2) {
const n2 = [], o2 = new Set, i2 = Math.min(t33.x, e2.x) - this.SEGMENT_MARGIN, r2 = Math.min(t33.y, e2.y) - this.SEGMENT_MARGIN, s2 = Math.max(t33.x, e2.x) + this.SEGMENT_MARGIN, a2 = Math.max(t33.y, e2.y) + this.SEGMENT_MARGIN, c2 = Math.floor(i2 / this.CELL_SIZE), l2 = Math.floor(s2 / this.CELL_SIZE), h2 = Math.floor(r2 / this.CELL_SIZE), d2 = Math.floor(a2 / this.CELL_SIZE);
for (let t34 = c2;t34 <= l2; t34++)
for (let e3 = h2;e3 <= d2; e3++) {
const i3 = `${t34}x${e3}`, r3 = this.buckets.get(i3);
if (r3)
for (const t35 of r3) {
const e4 = t35[2];
o2.has(e4) || (o2.add(e4), n2.push(t35));
}
}
return n2;
}
};
var Xk = class extends jk {
pathSegments = [];
totalPathLength = 0;
headDistanceAlongPath = 0;
tailDistanceAlongPath = 0;
minStepSize = 0.25;
lastValidPath = null;
lastValidPathHeadDistance = 0;
STEP_SIZE_REDUCTION_FACTOR = 0.25;
maxStepSize = 4;
currentStepSize = this.maxStepSize;
lastHeadMoveDistance = 0;
cachedValidPathSegments;
filteredObstacles = [];
filteredObstaclePathSegments = [];
traceThicknessByObstacleSegmentId = new Map;
filteredVias = [];
filteredJumperPads = [];
jumperPadPointIndices = new Set;
segmentTree;
OBSTACLE_MARGIN = 0.1;
TRACE_THICKNESS = 0.15;
useTraceWidthAwareClearance = false;
clearanceTraceThickness = this.TRACE_THICKNESS;
TAIL_JUMP_RATIO = 0.8;
isSameNetRoute(t33) {
const e2 = [this.inputRoute.connectionName, this.inputRoute.rootConnectionName].filter((t34) => t34 !== undefined), n2 = [t33.connectionName, t33.rootConnectionName].filter((t34) => t34 !== undefined);
return e2.some((t34) => n2.some((e3) => t34 === e3 || this.connMap.areIdsConnected(t34, e3)));
}
constructor(t33) {
if (super(t33), this.cachedValidPathSegments = new Set, this.useTraceWidthAwareClearance = t33.useTraceWidthAwareClearance ?? false, this.clearanceTraceThickness = this.useTraceWidthAwareClearance ? this.inputRoute.traceThickness : this.TRACE_THICKNESS, this.inputRoute.route.length <= 1)
return this.newRoute = [...this.inputRoute.route], void (this.solved = true);
const e2 = this.inputRoute.route.reduce((t34, e3) => (t34.minX = Math.min(t34.minX, e3.x), t34.maxX = Math.max(t34.maxX, e3.x), t34.minY = Math.min(t34.minY, e3.y), t34.maxY = Math.max(t34.maxY, e3.y), t34), { minX: 1 / 0, maxX: -1 / 0, minY: 1 / 0, maxY: -1 / 0 }), n2 = this.useTraceWidthAwareClearance ? Math.max(0, ...this.otherHdRoutes.flatMap((t34) => [t34.traceThickness, ...t34.route.map((e3) => e3.traceThickness ?? t34.traceThickness)])) : this.TRACE_THICKNESS, o2 = this.useTraceWidthAwareClearance ? this.OBSTACLE_MARGIN + this.clearanceTraceThickness / 2 + n2 / 2 : this.OBSTACLE_MARGIN + this.TRACE_THICKNESS, i2 = { center: { x: (e2.minX + e2.maxX) / 2, y: (e2.minY + e2.maxY) / 2 }, width: e2.maxX - e2.minX, height: e2.maxY - e2.minY };
this.filteredObstacles = this.obstacles.filter((t34) => !t34.connectedTo.some((t35) => this.connMap.areIdsConnected(this.inputRoute.connectionName, t35))).filter((t34) => {
if (t34.connectedTo.some((t35) => this.connMap.areIdsConnected(this.inputRoute.connectionName, t35)))
return false;
return function(t35, e3) {
const n3 = Ee(t35), o3 = Ee(e3), i3 = Math.max(n3.minX - o3.maxX, o3.minX - n3.maxX, 0), r3 = Math.max(n3.minY - o3.maxY, o3.minY - n3.maxY, 0);
return Math.hypot(i3, r3);
}(i2, t34) < this.OBSTACLE_MARGIN + this.clearanceTraceThickness / 2;
}), this.filteredObstaclePathSegments = this.otherHdRoutes.flatMap((t34) => {
if (this.isSameNetRoute(t34))
return [];
const n3 = t34.route, i3 = [];
for (let r3 = 0;r3 < n3.length - 1; r3++) {
const s2 = n3[r3], a2 = n3[r3 + 1];
if (ke(s2, a2, e2) <= o2) {
i3.push([s2, a2]);
const e3 = `${s2.x}-${s2.y}-${s2.z}-${a2.x}-${a2.y}-${a2.z}`;
if (this.useTraceWidthAwareClearance) {
const n4 = Math.max(s2.traceThickness ?? t34.traceThickness, a2.traceThickness ?? t34.traceThickness);
this.traceThicknessByObstacleSegmentId.set(e3, Math.max(this.traceThicknessByObstacleSegmentId.get(e3) ?? 0, n4));
}
}
}
return i3;
}), this.segmentTree = this.useTraceWidthAwareClearance ? new Yk(this.filteredObstaclePathSegments, o2) : new Yk(this.filteredObstaclePathSegments), this.filteredVias = this.otherHdRoutes.flatMap((t34) => {
if (this.isSameNetRoute(t34))
return [];
const n3 = t34.vias, o3 = [];
for (const i3 of n3) {
const n4 = this.OBSTACLE_MARGIN + this.clearanceTraceThickness / 2 + t34.viaDiameter / 2, r3 = i3.x - n4, s2 = i3.x + n4, a2 = i3.y - n4, c2 = i3.y + n4;
r3 <= e2.maxX && s2 >= e2.minX && a2 <= e2.maxY && c2 >= e2.minY && o3.push({ ...i3, diameter: t34.viaDiameter });
}
return o3;
});
const r2 = (t34, n3) => {
const o3 = [];
for (const i3 of t34) {
const t35 = Xo[i3.footprint] ?? Xo["0603"], r3 = i3.end.x - i3.start.x, s2 = i3.end.y - i3.start.y, a2 = Math.abs(r3) > Math.abs(s2), c2 = a2 ? t35.padLength : t35.padWidth, l2 = a2 ? t35.padWidth : t35.padLength, h2 = this.OBSTACLE_MARGIN + this.clearanceTraceThickness / 2;
i3.start.x - c2 / 2 - h2 <= e2.maxX && i3.start.x + c2 / 2 + h2 >= e2.minX && i3.start.y - l2 / 2 - h2 <= e2.maxY && i3.start.y + l2 / 2 + h2 >= e2.minY && o3.push({ center: i3.start, width: c2, height: l2, connectionName: n3 }), i3.end.x - c2 / 2 - h2 <= e2.maxX && i3.end.x + c2 / 2 + h2 >= e2.minX && i3.end.y - l2 / 2 - h2 <= e2.maxY && i3.end.y + l2 / 2 + h2 >= e2.minY && o3.push({ center: i3.end, width: c2, height: l2, connectionName: n3 });
}
return o3;
};
if (this.filteredJumperPads = this.otherHdRoutes.flatMap((t34) => this.isSameNetRoute(t34) ? [] : r2(t34.jumpers ?? [], t34.connectionName)), this.inputRoute.jumpers && this.inputRoute.jumpers.length > 0) {
this.filteredJumperPads.push(...r2(this.inputRoute.jumpers, this.inputRoute.connectionName));
for (const t34 of this.inputRoute.jumpers)
for (let e3 = 0;e3 < this.inputRoute.route.length; e3++) {
const n3 = this.inputRoute.route[e3];
(Math.abs(n3.x - t34.start.x) < 0.01 && Math.abs(n3.y - t34.start.y) < 0.01 || Math.abs(n3.x - t34.end.x) < 0.01 && Math.abs(n3.y - t34.end.y) < 0.01) && this.jumperPadPointIndices.add(e3);
}
}
this.computePathSegments();
}
computePathSegments() {
let t33 = 0;
for (let e2 = 0;e2 < this.inputRoute.route.length - 1; e2++) {
const n2 = this.inputRoute.route[e2], o2 = this.inputRoute.route[e2 + 1], i2 = Math.sqrt((o2.x - n2.x) ** 2 + (o2.y - n2.y) ** 2) + e2 / 1e4;
this.pathSegments.push({ start: n2, end: o2, length: i2, startDistance: t33, endDistance: t33 + i2 }), t33 += i2;
}
this.totalPathLength = t33;
}
arePointsEqual(t33, e2) {
return t33.x === e2.x && t33.y === e2.y && t33.z === e2.z;
}
getPointAtDistance(t33) {
t33 = Math.max(0, Math.min(t33, this.totalPathLength));
const e2 = this.pathSegments.find((e3) => t33 >= e3.startDistance && t33 <= e3.endDistance);
if (!e2)
return this.inputRoute.route[this.inputRoute.route.length - 1];
const n2 = (t33 - e2.startDistance) / e2.length;
return { x: e2.start.x + n2 * (e2.end.x - e2.start.x), y: e2.start.y + n2 * (e2.end.y - e2.start.y), z: n2 < 0.5 ? e2.start.z : e2.end.z };
}
getNearestIndexForDistance(t33) {
if (t33 <= 0)
return 0;
if (t33 >= this.totalPathLength)
return this.inputRoute.route.length - 1;
const e2 = this.pathSegments.findIndex((e3) => t33 >= e3.startDistance && t33 <= e3.endDistance);
if (e2 === -1)
return 0;
const n2 = this.pathSegments[e2], o2 = (n2.startDistance + n2.endDistance) / 2;
return t33 > o2 ? e2 + 1 : e2;
}
isValidPathSegment(t33, e2) {
for (const n3 of this.filteredObstacles) {
if (!n3.__zLayers?.includes(t33.z))
continue;
if (De(t33, e2, n3) < this.OBSTACLE_MARGIN + this.clearanceTraceThickness / 2)
return false;
}
const n2 = this.segmentTree.getSegmentsThatCouldIntersect(t33, e2);
for (const [o2, i2, r2] of n2)
if (o2.z === t33.z && i2.z === t33.z) {
const n3 = Mk({ x: t33.x, y: t33.y }, { x: e2.x, y: e2.y }, { x: o2.x, y: o2.y }, { x: i2.x, y: i2.y });
if (!this.useTraceWidthAwareClearance) {
if (n3 < this.OBSTACLE_MARGIN + this.TRACE_THICKNESS)
return false;
continue;
}
const s2 = this.traceThicknessByObstacleSegmentId.get(r2);
if (s2 === undefined)
throw new Error(`Missing trace thickness for segment "${r2}"`);
if (n3 < this.OBSTACLE_MARGIN + this.clearanceTraceThickness / 2 + s2 / 2)
return false;
}
for (const n3 of this.filteredVias)
if (be(n3, t33, e2) < this.OBSTACLE_MARGIN + n3.diameter / 2 + this.clearanceTraceThickness / 2)
return false;
for (const n3 of this.filteredJumperPads) {
if (De(t33, e2, n3) < this.OBSTACLE_MARGIN + this.clearanceTraceThickness / 2)
return false;
}
if (this.outline && this.outline.length >= 3) {
if (kk({ start: { x: t33.x, y: t33.y }, end: { x: e2.x, y: e2.y }, polygon: this.outline, margin: this.minBoardEdgeClearance + this.inputRoute.traceThickness / 2 }))
return false;
}
return true;
}
isValidPath(t33) {
if (t33.length < 2)
return true;
for (let e2 = 0;e2 < t33.length - 1; e2++)
if (t33[e2].z !== t33[e2 + 1].z)
return false;
for (let e2 = 0;e2 < t33.length - 1; e2++)
if (!this.isValidPathSegment(t33[e2], t33[e2 + 1]))
return false;
return true;
}
find45DegreePath(t33, e2) {
if (this.arePointsEqual(t33, e2))
return [t33];
if (t33.z !== e2.z)
return null;
const n2 = Pk({ x: t33.x, y: t33.y }, { x: e2.x, y: e2.y });
for (const e3 of n2) {
const n3 = e3.map((e4) => ({ x: e4.x, y: e4.y, z: t33.z }));
if (this.isValidPath(n3))
return n3;
}
return null;
}
addPathToResult(t33) {
if (t33.length !== 0) {
for (let e2 = 0;e2 < t33.length; e2++)
e2 === 0 && this.newRoute.length > 0 && this.arePointsEqual(this.newRoute[this.newRoute.length - 1], t33[e2]) || this.newRoute.push(t33[e2]);
this.currentStepSize = this.maxStepSize;
}
}
appendOriginalRouteSlice(t33, e2) {
const n2 = this.pathSegments.findIndex((e3) => t33 >= e3.startDistance && t33 <= e3.endDistance);
if (n2 === -1)
throw new Error(`Could not find path segment containing distance ${t33}`);
for (let t34 = n2 + 1;t34 <= e2 && t34 < this.inputRoute.route.length; t34++) {
const e3 = this.inputRoute.route[t34], n3 = this.newRoute[this.newRoute.length - 1];
n3 && this.arePointsEqual(n3, e3) || this.newRoute.push({ ...e3 });
}
}
moveHead(t33) {
this.lastHeadMoveDistance = t33, this.headDistanceAlongPath = Math.min(this.headDistanceAlongPath + t33, this.totalPathLength);
}
stepBackAndReduceStepSize() {
this.headDistanceAlongPath = Math.max(this.tailDistanceAlongPath, this.headDistanceAlongPath - this.lastHeadMoveDistance), this.currentStepSize = Math.max(this.minStepSize, this.currentStepSize * this.STEP_SIZE_REDUCTION_FACTOR);
}
_step() {
const t33 = this.tailDistanceAlongPath >= this.totalPathLength, e2 = this.headDistanceAlongPath >= this.totalPathLength;
if (t33) {
const t34 = this.inputRoute.route[this.inputRoute.route.length - 1];
return this.newRoute.length !== 0 && this.arePointsEqual(this.newRoute[this.newRoute.length - 1], t34) || this.newRoute.push(t34), void (this.solved = true);
}
if (e2) {
const t34 = this.getPointAtDistance(this.tailDistanceAlongPath), e3 = this.inputRoute.route[this.inputRoute.route.length - 1], n3 = this.find45DegreePath(t34, e3);
if (n3)
return this.addPathToResult(n3), void (this.solved = true);
const o3 = this.lastValidPath ? this.lastValidPathHeadDistance : this.tailDistanceAlongPath;
this.lastValidPath && (this.addPathToResult(this.lastValidPath), this.lastValidPath = null);
this.getNearestIndexForDistance(o3);
return this.appendOriginalRouteSlice(o3, this.inputRoute.route.length - 1), this.tailDistanceAlongPath = this.totalPathLength, this.headDistanceAlongPath = this.totalPathLength, void (this.solved = true);
}
this.moveHead(this.currentStepSize);
const n2 = this.getPointAtDistance(this.tailDistanceAlongPath), o2 = this.getPointAtDistance(this.headDistanceAlongPath), i2 = this.getNearestIndexForDistance(this.tailDistanceAlongPath), r2 = this.getNearestIndexForDistance(this.headDistanceAlongPath);
let s2 = false, a2 = -1;
for (let t34 = i2;t34 < r2; t34++)
if (t34 + 1 < this.inputRoute.route.length && this.inputRoute.route[t34].z !== this.inputRoute.route[t34 + 1].z) {
s2 = true;
const e3 = t34;
a2 = this.pathSegments[e3].startDistance;
break;
}
if (s2 && this.lastHeadMoveDistance > this.minStepSize)
return void this.stepBackAndReduceStepSize();
let c2 = false, l2 = -1, h2 = -1;
for (let t34 = i2 + 1;t34 <= r2; t34++)
if (this.jumperPadPointIndices.has(t34)) {
c2 = true, l2 = t34, h2 = t34 > 0 && t34 - 1 < this.pathSegments.length ? this.pathSegments[t34 - 1].endDistance : this.pathSegments[0]?.startDistance ?? 0;
break;
}
if (c2 && this.lastHeadMoveDistance > this.minStepSize)
return void this.stepBackAndReduceStepSize();
if (c2 && l2 >= 0) {
const t34 = this.inputRoute.route[l2];
this.lastValidPath && (this.addPathToResult(this.lastValidPath), this.lastValidPath = null);
const e3 = this.newRoute[this.newRoute.length - 1];
return e3 && e3.x === t34.x && e3.y === t34.y || this.newRoute.push({ x: t34.x, y: t34.y, z: t34.z }), this.currentStepSize = this.maxStepSize, this.tailDistanceAlongPath = h2, this.headDistanceAlongPath = this.tailDistanceAlongPath, this.lastValidPath = null, void (this.lastValidPathHeadDistance = this.tailDistanceAlongPath);
}
if (s2 && a2 > 0) {
const t34 = this.lastValidPath ? this.lastValidPathHeadDistance : this.tailDistanceAlongPath, e3 = this.getNearestIndexForDistance(a2) + 1, n3 = this.inputRoute.route[e3], o3 = { x: n3.x, y: n3.y };
this.lastValidPath && (this.addPathToResult(this.lastValidPath), this.lastValidPath = null);
const i3 = this.newRoute[this.newRoute.length - 1], r3 = { x: o3.x, y: o3.y, z: i3.z };
if (!this.arePointsEqual(i3, r3)) {
const n4 = this.find45DegreePath(i3, r3);
n4 ? this.addPathToResult(n4) : this.appendOriginalRouteSlice(t34, e3 - 1);
}
this.newVias.push(o3), this.newRoute.push({ x: o3.x, y: o3.y, z: n3.z }), this.currentStepSize = this.maxStepSize;
const s3 = this.pathSegments.findIndex((t35) => t35.start === n3);
if (s3 !== -1)
this.tailDistanceAlongPath = this.pathSegments[s3].startDistance, this.headDistanceAlongPath = this.tailDistanceAlongPath, this.lastValidPath = null, this.lastValidPathHeadDistance = this.tailDistanceAlongPath;
else if (e3 < this.inputRoute.route.length) {
if (e3 === this.inputRoute.route.length - 1)
return void (this.solved = true);
console.warn("Fallback used for tailDistanceAlongPath after layer change");
const t35 = this.pathSegments.find((t36) => t36.start === this.inputRoute.route[e3]);
t35 ? (this.tailDistanceAlongPath = t35.startDistance, this.headDistanceAlongPath = this.tailDistanceAlongPath, this.lastValidPath = null, this.lastValidPathHeadDistance = this.tailDistanceAlongPath) : (console.error(`[${this.inputRoute.connectionName}] Could not find segment start after layer change. Path might be incomplete.
Index sought: ${e3}, Point: (${this.inputRoute.route[e3].x.toFixed(3)}, ${this.inputRoute.route[e3].y.toFixed(3)}, z=${this.inputRoute.route[e3].z})
Route Length: ${this.inputRoute.route.length}, Path Segments: ${this.pathSegments.length}`), this.solved = true);
} else
console.warn("Layer change occurred at the end of the path."), this.solved = true;
return;
}
const d2 = this.find45DegreePath(n2, o2);
if (!d2 && this.lastHeadMoveDistance > this.minStepSize)
this.stepBackAndReduceStepSize();
else {
if (!d2 && !this.lastValidPath) {
const t34 = this.getPointAtDistance(this.tailDistanceAlongPath);
this.tailDistanceAlongPath += this.minStepSize, this.moveHead(this.minStepSize);
const e3 = this.getNearestIndexForDistance(this.tailDistanceAlongPath), n3 = this.inputRoute.route[e3], o3 = this.inputRoute.route[this.inputRoute.route.length - 1];
return void (this.arePointsEqual(t34, n3) || this.arePointsEqual(n3, o3) || this.newRoute.push(n3));
}
if (d2)
return this.lastValidPath = d2, void (this.lastValidPathHeadDistance = this.headDistanceAlongPath);
this.lastValidPath && (this.addPathToResult(this.lastValidPath), this.lastValidPath = null, this.tailDistanceAlongPath = this.lastValidPathHeadDistance, this.moveHead(this.minStepSize));
}
}
visualize() {
const t33 = this.getVisualsForNewRouteAndObstacles(), e2 = this.getPointAtDistance(this.tailDistanceAlongPath), n2 = this.getPointAtDistance(this.headDistanceAlongPath);
t33.points.push({ x: e2.x, y: e2.y, color: "yellow", label: ["Tail", `z: ${e2.z}`].join(`
`) }), t33.points.push({ x: n2.x, y: n2.y, color: "orange", label: ["Head", `z: ${n2.z}`].join(`
`) });
const o2 = this.getPointAtDistance(this.headDistanceAlongPath + this.currentStepSize);
t33.points.push({ x: o2.x, y: o2.y, color: "red", label: ["Tentative Head", `z: ${o2.z}`].join(`
`) });
let i2 = 0;
for (;i2 < this.totalPathLength; ) {
const e3 = this.getPointAtDistance(i2);
t33.circles.push({ center: { x: e3.x, y: e3.y }, radius: 0.05, fill: "rgba(100, 100, 100, 0.5)" }), i2 += this.totalPathLength / 20;
}
if (this.lastValidPath && this.lastValidPath.length > 1)
for (let e3 = 0;e3 < this.lastValidPath.length - 1; e3++)
t33.lines.push({ points: [{ x: this.lastValidPath[e3].x, y: this.lastValidPath[e3].y }, { x: this.lastValidPath[e3 + 1].x, y: this.lastValidPath[e3 + 1].y }], strokeColor: "rgba(0, 255, 255, 0.9)", strokeDash: "3, 3" });
return t33;
}
};
var Wk = class extends Xk {
vertexIndex = 0;
constructor(t33) {
super(t33), this.newRoute = this.inputRoute.route.slice(0, 1).map((t34) => ({ ...t34 })), this.newVias = this.inputRoute.vias.map((t34) => ({ ...t34 }));
}
getSolverName() {
return "VertexShortcutPathSolver";
}
_step() {
const t33 = this.inputRoute.route, e2 = t33[this.vertexIndex];
if (this.vertexIndex >= t33.length - 1)
return void (this.solved = true);
let n2 = this.vertexIndex + 1;
const o2 = [0];
for (let e3 = this.vertexIndex;e3 < t33.length - 1; e3++) {
const i2 = t33[e3], r2 = t33[e3 + 1];
if (i2.z !== r2.z || i2.toNextSegmentType || i2.traceThickness !== r2.traceThickness || i2.traceThickness !== undefined && i2.traceThickness !== this.inputRoute.traceThickness || i2.insideJumperPad || r2.insideJumperPad)
break;
if (o2.push(o2.at(-1) + Math.hypot(r2.x - i2.x, r2.y - i2.y)), n2 = e3 + 1, r2.pcb_port_id || this.jumperPadPointIndices.has(n2))
break;
}
for (let i2 = n2;i2 > this.vertexIndex + 1; i2--) {
const n3 = t33[i2], r2 = o2[i2 - this.vertexIndex];
for (const t34 of Pk(e2, n3)) {
const o3 = t34.filter((e3, n4) => n4 === 0 || e3.x !== t34[n4 - 1].x || e3.y !== t34[n4 - 1].y).map((t35) => ({ ...t35, z: e2.z, traceThickness: e2.traceThickness })), s2 = o3.reduce((t35, e3, n4) => n4 === 0 ? t35 : t35 + Math.hypot(e3.x - o3[n4 - 1].x, e3.y - o3[n4 - 1].y), 0);
if (!(o3.length < 2 || s2 > r2 + 0.000000001 || s2 >= r2 - 0.000000001 && o3.length >= i2 - this.vertexIndex + 1) && this.isValidPath(o3))
return o3[o3.length - 1] = { ...n3 }, this.newRoute.push(...o3.slice(1)), void (this.vertexIndex = i2);
}
}
this.vertexIndex++, this.newRoute.push({ ...t33[this.vertexIndex] });
}
};
var Vk = class extends si {
getSolverName() {
return "MultiSimplifiedPathSolver";
}
simplifiedHdRoutes;
currentUnsimplifiedHdRouteIndex = 0;
activeSubSolver = null;
unsimplifiedHdRoutes;
otherHdRoutes;
obstacles;
connMap;
colorMap;
outline;
minBoardEdgeClearance;
defaultViaDiameter;
useTraceWidthAwareClearance;
enableVertexShortcuts;
constructor(t33) {
super(), this.MAX_ITERATIONS = 1e8, this.unsimplifiedHdRoutes = t33.unsimplifiedHdRoutes, this.otherHdRoutes = t33.otherHdRoutes ?? [];
const e2 = Math.max(2, ...[...t33.unsimplifiedHdRoutes, ...this.otherHdRoutes].flatMap((t34) => t34.route.map((t35) => t35.z + 1))) || 2;
this.obstacles = Is(t33.obstacles, e2), this.connMap = t33.connMap || new ti({}), this.colorMap = t33.colorMap || {}, this.outline = t33.outline, this.minBoardEdgeClearance = t33.minBoardEdgeClearance ?? 0.2, this.defaultViaDiameter = t33.defaultViaDiameter ?? 0.3, this.useTraceWidthAwareClearance = t33.useTraceWidthAwareClearance ?? false, this.enableVertexShortcuts = t33.enableVertexShortcuts ?? false, this.simplifiedHdRoutes = [];
}
_step() {
const t33 = this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];
if (!this.activeSubSolver)
return t33 ? (this.activeSubSolver = new Xk({ inputRoute: t33, otherHdRoutes: this.otherHdRoutes.concat(this.unsimplifiedHdRoutes.slice(this.currentUnsimplifiedHdRouteIndex + 1).concat(this.simplifiedHdRoutes)), obstacles: this.obstacles, connMap: this.connMap, colorMap: this.colorMap, outline: this.outline, minBoardEdgeClearance: this.minBoardEdgeClearance, useTraceWidthAwareClearance: this.useTraceWidthAwareClearance }), void this.currentUnsimplifiedHdRouteIndex++) : void (this.solved = true);
if (this.activeSubSolver.step(), this.activeSubSolver.solved) {
if (this.enableVertexShortcuts && !(this.activeSubSolver instanceof Wk))
return void (this.activeSubSolver = new Wk({ inputRoute: this.activeSubSolver.simplifiedRoute, otherHdRoutes: this.activeSubSolver.otherHdRoutes, obstacles: this.obstacles, connMap: this.connMap, colorMap: this.colorMap, outline: this.outline, minBoardEdgeClearance: this.minBoardEdgeClearance, useTraceWidthAwareClearance: this.useTraceWidthAwareClearance }));
this.simplifiedHdRoutes.push(this.activeSubSolver.simplifiedRoute), this.activeSubSolver = null;
}
}
visualize() {
if (this.activeSubSolver)
return this.activeSubSolver.visualize();
const t33 = { lines: [], points: [], circles: [], rects: [], coordinateSystem: "cartesian", title: "Multi Simplified Path Solver" };
for (const e2 of this.unsimplifiedHdRoutes)
if (!this.simplifiedHdRoutes.some((t34) => t34.connectionName === e2.connectionName)) {
for (let n2 = 0;n2 < e2.route.length - 1; n2++)
t33.lines.push({ points: [{ x: e2.route[n2].x, y: e2.route[n2].y }, { x: e2.route[n2 + 1].x, y: e2.route[n2 + 1].y }], strokeColor: e2.route[n2].z === 1 ? "rgba(0, 0, 255, 0.4)" : "rgba(255, 0, 0, 0.4)", strokeWidth: 0.15, strokeDash: e2.route[n2].z === 1 ? [0.5, 0.5] : undefined });
for (const n2 of e2.vias || [])
t33.circles.push({ center: n2, radius: (e2.viaDiameter ?? this.defaultViaDiameter) / 2, fill: "rgba(0, 0, 255, 0.4)" });
}
for (const e2 of this.simplifiedHdRoutes) {
const n2 = this.colorMap?.[e2.connectionName] || "rgba(128, 128, 128, 0.8)";
for (let o2 = 0;o2 < e2.route.length - 1; o2++)
t33.lines.push({ points: [{ x: e2.route[o2].x, y: e2.route[o2].y }, { x: e2.route[o2 + 1].x, y: e2.route[o2 + 1].y }], strokeWidth: 0.15, strokeColor: n2, strokeDash: e2.route[o2].z === 1 ? [0.5, 0.5] : undefined, step: 1 });
for (const n3 of e2.vias || [])
t33.circles.push({ center: n3, radius: e2.viaDiameter / 2, fill: "rgba(0, 0, 255, 0.5)", step: 1 });
}
for (const e2 of this.unsimplifiedHdRoutes) {
for (let n2 = 0;n2 < e2.route.length - 1; n2++)
t33.lines.push({ points: [{ x: e2.route[n2].x, y: e2.route[n2].y }, { x: e2.route[n2 + 1].x, y: e2.route[n2 + 1].y }], strokeWidth: 0.15, strokeColor: "rgba(255, 0, 0, 0.2)", strokeDash: [0.5, 0.5], step: 0, layer: `z${e2.route[n2].z.toString()}` });
for (const n2 of e2.vias)
t33.circles.push({ center: { x: n2.x, y: n2.y }, radius: e2.viaDiameter / 2, fill: "rgba(255, 0, 0, 0.2)", step: 0 });
}
for (const e2 of this.obstacles)
t33.rects.push({ center: e2.center, width: e2.width, height: e2.height, fill: e2.layers?.includes("top") ? "rgba(255, 0, 0, 0.3)" : e2.layers?.includes("bottom") ? "rgba(0, 0, 255, 0.3)" : "rgba(128, 128, 128, 0.3)" });
if (this.currentUnsimplifiedHdRouteIndex < this.unsimplifiedHdRoutes.length) {
const e2 = this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];
e2.route.length > 0 && t33.circles.push({ center: { x: e2.route[0].x, y: e2.route[0].y }, radius: 0.2, fill: "yellow", label: "Current" });
}
return t33;
}
};
var Hk = (t33, e2) => {
for (let n2 = 0;n2 < t33.route.length - 1; n2++) {
const o2 = t33.route[n2], i2 = t33.route[n2 + 1];
if (o2.z === i2.z || o2.x !== e2.x || o2.y !== e2.y || i2.x !== e2.x || i2.y !== e2.y)
continue;
let r2 = n2;
for (;r2 > 0 && t33.route[r2 - 1].x === e2.x && t33.route[r2 - 1].y === e2.y; )
r2--;
let s2 = n2 + 1;
for (;s2 < t33.route.length - 1 && t33.route[s2 + 1].x === e2.x && t33.route[s2 + 1].y === e2.y; )
s2++;
if (r2 === 0 || s2 === t33.route.length - 1)
return true;
}
return false;
};
var Gk = (t33, e2, n2) => n2?.get(e2.connectionName) ?? t33.idToNetMap[e2.connectionName] ?? (e2.rootConnectionName ? t33.idToNetMap[e2.rootConnectionName] : undefined);
var Uk = (t33, e2, n2) => {
for (const o2 of e2.connectedTo) {
if (o2 === n2.net)
return true;
if (t33.idToNetMap[o2] === n2.net)
return true;
if (t33.areIdsConnected(o2, n2.net))
return true;
}
return false;
};
var Zk = (t33, e2, n2) => {
const o2 = n2.mergedViaHdRoutes[t33.routeIndex];
if (!o2)
throw new Error(`SameNetViaMergerSolver could not find route for via at index ${t33.routeIndex}`);
const i2 = new Set;
for (let e3 = 1;e3 < o2.route.length; e3++) {
const n3 = o2.route[e3 - 1], r2 = o2.route[e3];
n3.z !== r2.z && (n3.x === t33.x && n3.y === t33.y && r2.x === t33.x && r2.y === t33.y && (i2.add(n3.z), i2.add(r2.z)));
}
if (i2.size === 0)
throw new Error(`SameNetViaMergerSolver could not find transition layers for via at (${t33.x}, ${t33.y})`);
for (const r2 of i2) {
const i3 = o2.traceThickness, s2 = { x: t33.x, y: t33.y, z: r2 }, a2 = { x: e2.x, y: e2.y, z: r2 };
if (s2.x === a2.x && s2.y === a2.y)
continue;
const c2 = n2.hdRouteSHI.getConflictingRoutesForSegment(s2, a2, i3 / 2);
for (const { conflictingRoute: e3, distance: r3 } of c2) {
if (e3.connectionName === o2.connectionName)
continue;
if (Gk(n2.connMap, e3, n2.netByConnectionName) === t33.net)
continue;
if (r3 < i3 / 2 + e3.traceThickness / 2)
return false;
}
const l2 = { centerX: (s2.x + a2.x) / 2, centerY: (s2.y + a2.y) / 2, width: Math.abs(s2.x - a2.x), height: Math.abs(s2.y - a2.y) }, h2 = i3 / 2 + 0.1, d2 = n2.obstacleSHI.searchArea(l2.centerX, l2.centerY, l2.width + 2 * h2, l2.height + 2 * h2);
for (const e3 of d2) {
if (!e3.__zLayers)
throw new Error(`SameNetViaMergerSolver found obstacle without zLayers near via at (${t33.x}, ${t33.y})`);
if (e3.__zLayers.includes(r2) && (!Uk(n2.connMap, e3, t33) && De(s2, a2, e3) < h2))
return false;
}
}
return true;
};
var qk = class extends si {
constructor(t33) {
if (super(), this.input = t33, !t33.connMap)
throw new Error("SameNetViaMergerSolver requires connMap");
this.input = { ...t33, obstacles: Is(t33.obstacles, t33.layerCount) }, this.MAX_ITERATIONS = 1e6, this.inputHdRoutes = this.input.inputHdRoutes, this.mergedViaHdRoutes = structuredClone(this.inputHdRoutes);
for (const t34 of this.mergedViaHdRoutes)
this.dedupeRouteVias(t34);
this.unprocessedRoutes = [...this.input.inputHdRoutes], this.colorMap = this.input.colorMap, this.outline = this.input.outline, this.obstacles = this.input.obstacles, this.obstacleSHI = new Sk("flatbush", this.input.obstacles), this.hdRouteSHI = this.createHdRouteSpatialIndex(), this.vias = [], this.offendingVias = [], this.connMap = t33.connMap, this.netByConnectionName = t33.netByConnectionName, this.viasByNet = new Map, this.rebuildVias();
}
getSolverName() {
return "SameNetViaMergerSolver";
}
inputHdRoutes;
mergedViaHdRoutes;
unprocessedRoutes;
vias;
offendingVias;
currentViaRoutes = [];
connMap;
colorMap;
outline;
obstacles;
viasByNet;
netByConnectionName;
obstacleSHI;
hdRouteSHI;
createHdRouteSpatialIndex() {
return new hr([...this.mergedViaHdRoutes, ...this.input.otherHdRoutes ?? []]);
}
rebuildVias() {
this.vias = [], this.viasByNet = new Map;
const t33 = (t34, e2, n2) => {
if (t34.vias.length === 0)
return;
const o2 = n2 ? ((t35, e3, n3) => {
const o3 = Gk(t35, e3, n3);
if (!o3)
throw new Error(`SameNetViaMergerSolver could not find net for route "${e3.connectionName}"`);
return o3;
})(this.connMap, t34, this.netByConnectionName) : Gk(this.connMap, t34, this.netByConnectionName);
if (o2)
for (let i2 = 0;i2 < t34.vias.length; i2++) {
const r2 = t34.vias[i2], s2 = [...new Set(t34.route.map((t35) => t35.z))];
if (s2.length === 0)
throw new Error(`SameNetViaMergerSolver found via on route "${t34.connectionName}" with no route points`);
const a2 = { x: r2.x, y: r2.y, diameter: t34.viaDiameter, net: o2, layers: s2, routeIndex: e2, mutable: n2 && !(this.input.preserveRouteEndpoints && Hk(t34, r2)) };
this.vias.push(a2);
const c2 = this.viasByNet.get(a2.net);
c2 ? c2.push(a2) : this.viasByNet.set(a2.net, [a2]);
}
};
for (let e2 = 0;e2 < this.mergedViaHdRoutes.length; e2++)
t33(this.mergedViaHdRoutes[e2], e2, true);
for (let e2 = 0;e2 < (this.input.otherHdRoutes?.length ?? 0); e2++)
t33(this.input.otherHdRoutes[e2], this.mergedViaHdRoutes.length + e2, false);
}
getViaKey(t33) {
return [t33.mutable ? "mutable" : "immutable", t33.routeIndex, t33.x, t33.y, t33.layers.join(","), t33.net].join(":");
}
dedupeRouteVias(t33) {
const e2 = new Set;
t33.vias = t33.vias.filter((t34) => {
const n2 = `${t34.x}:${t34.y}`;
return !e2.has(n2) && (e2.add(n2), true);
});
}
getOffendingViaGroupsBatch() {
const t33 = [], e2 = new Set, n2 = [];
for (const t34 of this.viasByNet.values()) {
if (t34.length < 2)
continue;
const e3 = Math.max(0.000001, ...t34.map((t35) => t35.diameter)), o2 = new Map;
for (let n3 = 0;n3 < t34.length; n3++) {
const i2 = t34[n3], r2 = `${Math.floor(i2.x / e3)}:${Math.floor(i2.y / e3)}`, s2 = o2.get(r2);
s2 ? s2.push(n3) : o2.set(r2, [n3]);
}
for (let i2 = 0;i2 < t34.length; i2++) {
const r2 = t34[i2], s2 = Math.floor(r2.x / e3), a2 = Math.floor(r2.y / e3), c2 = Math.ceil(2.5), l2 = [];
for (let e4 = -c2;e4 <= c2; e4++)
for (let n3 = -c2;n3 <= c2; n3++) {
const c3 = o2.get(`${s2 + e4}:${a2 + n3}`);
if (c3)
for (const e5 of c3) {
if (e5 === i2)
continue;
const n4 = t34[e5];
if (!n4.mutable)
continue;
const o3 = r2.x - n4.x, s3 = r2.y - n4.y, a3 = o3 * o3 + s3 * s3, c4 = r2.diameter / 2 + n4.diameter / 2, h2 = 2.5 * c4;
a3 !== 0 ? (a3 <= c4 * c4 || a3 <= h2 * h2 && Zk(n4, r2, { connMap: this.connMap, mergedViaHdRoutes: this.mergedViaHdRoutes, hdRouteSHI: this.hdRouteSHI, obstacleSHI: this.obstacleSHI, netByConnectionName: this.netByConnectionName })) && l2.push(n4) : r2.mutable || l2.push(n4);
}
}
l2.length > 0 && n2.push({ keep: r2, remove: l2 });
}
}
n2.sort((t34, e3) => e3.remove.length !== t34.remove.length ? e3.remove.length - t34.remove.length : t34.keep.mutable !== e3.keep.mutable ? t34.keep.mutable ? 1 : -1 : e3.keep.layers.length !== t34.keep.layers.length ? e3.keep.layers.length - t34.keep.layers.length : t34.keep.routeIndex - e3.keep.routeIndex);
for (const o2 of n2) {
const n3 = this.getViaKey(o2.keep);
if (e2.has(n3))
continue;
const i2 = o2.remove.filter((t34) => !e2.has(this.getViaKey(t34)));
if (i2.length !== 0) {
t33.push({ keep: o2.keep, remove: i2 }), e2.add(n3);
for (const t34 of i2)
e2.add(this.getViaKey(t34));
}
}
return t33;
}
moveViaTo(t33, e2, n2 = true) {
if (!t33.mutable)
throw new Error("SameNetViaMergerSolver cannot mutate an immutable via anchor");
const o2 = this.mergedViaHdRoutes[t33.routeIndex];
if (!o2)
throw new Error(`SameNetViaMergerSolver could not find route for via at index ${t33.routeIndex}`);
const i2 = o2.route, r2 = new Set;
let s2 = false;
for (let e3 = i2.length - 1;e3 >= 1; e3--) {
const n3 = i2[e3 - 1], o3 = i2[e3];
if (n3.z === o3.z)
continue;
if (n3.x !== t33.x || n3.y !== t33.y)
continue;
if (o3.x !== t33.x || o3.y !== t33.y)
continue;
let s3 = e3 - 1;
for (;s3 > 0 && i2[s3 - 1].x === t33.x && i2[s3 - 1].y === t33.y; )
s3--;
let a2 = e3;
for (;a2 < i2.length - 1 && i2[a2 + 1].x === t33.x && i2[a2 + 1].y === t33.y; )
a2++;
for (let t34 = s3;t34 <= a2; t34++)
r2.add(t34);
}
if (r2.size === 0)
throw new Error(`SameNetViaMergerSolver could not find route transition for via at (${t33.x}, ${t33.y}) on route "${o2.connectionName}"`);
for (const t34 of r2) {
const n3 = i2[t34];
i2[t34] = { ...n3, x: e2.x, y: e2.y };
}
if (o2.vias = o2.vias.flatMap((n3) => n3.x !== t33.x || n3.y !== t33.y ? n3 : (s2 = true, e2.mutable ? [{ x: e2.x, y: e2.y }] : [])), !s2)
throw new Error(`SameNetViaMergerSolver could not find via at (${t33.x}, ${t33.y}) on route "${o2.connectionName}"`);
this.dedupeRouteVias(o2), n2 && this.rebuildVias();
}
_step() {
const t33 = this.getOffendingViaGroupsBatch();
if (t33.length === 0)
return void (this.solved = true);
let e2 = 0;
for (const n2 of t33)
for (const t34 of n2.remove)
this.moveViaTo(t34, n2.keep, false), e2++;
this.rebuildVias(), this.hdRouteSHI = this.createHdRouteSpatialIndex(), this.stats.mergedViaGroups = t33.length, this.stats.mergedViaCount = e2;
}
getMergedViaHdRoutes() {
return this.mergedViaHdRoutes;
}
visualize() {
const t33 = { lines: [], points: [], rects: [], circles: [], coordinateSystem: "cartesian", title: "Same Net Via Merger Solver" };
for (const e2 of this.input.obstacles) {
if (!e2.__zLayers)
throw new Error("SameNetViaMergerSolver found obstacle without zLayers while visualizing");
let n2 = "rgba(128, 128, 128, 0.2)";
const o2 = e2.__zLayers.includes(0), i2 = e2.__zLayers.includes(1);
o2 && i2 ? n2 = "rgba(128, 0, 128, 0.2)" : o2 ? n2 = "rgba(255, 0, 0, 0.2)" : i2 && (n2 = "rgba(0, 0, 255, 0.2)"), t33.rects.push({ center: e2.center, width: e2.width, height: e2.height, fill: n2, label: `Obstacle (Z: ${e2.__zLayers?.join(", ")})` });
}
for (const e2 of this.mergedViaHdRoutes) {
if (e2.route.length === 0)
continue;
const n2 = this.input.colorMap[e2.connectionName];
if (!n2)
throw new Error(`SameNetViaMergerSolver could not find color for route "${e2.connectionName}"`);
for (let n3 = 0;n3 < e2.route.length - 1; n3++) {
const o2 = e2.route[n3], i2 = e2.route[n3 + 1];
o2.z === i2.z && t33.lines.push({ points: [{ x: o2.x, y: o2.y }, { x: i2.x, y: i2.y }], strokeColor: o2.z === 0 ? "rgba(255, 0, 0, 0.5)" : "rgba(0, 0, 255, 0.5)", strokeWidth: e2.traceThickness, label: `${e2.connectionName} (z=${o2.z})` });
}
for (const n3 of e2.vias)
t33.circles.push({ center: { x: n3.x, y: n3.y }, radius: e2.viaDiameter / 2, fill: "rgba(255, 0, 255, 0.5)", label: `${e2.connectionName} via` });
if (e2.jumpers && e2.jumpers.length > 0) {
const o2 = mk(e2.jumpers, { color: n2, label: e2.connectionName });
if (!o2.rects || !o2.lines)
throw new Error(`SameNetViaMergerSolver expected jumper graphics for route "${e2.connectionName}"`);
t33.rects.push(...o2.rects), t33.lines.push(...o2.lines);
}
}
return t33;
}
};
var Jk = { getConflictingRoutesForSegment: () => [], getConflictingRoutesNearPoint: () => [] };
var Qk = 0.000001;
var Kk = (t33, e2) => {
const n2 = `${t33.x}:${t33.y}:${t33.z}`, o2 = `${e2.x}:${e2.y}:${e2.z}`;
return n2 < o2 ? `${n2}|${o2}` : `${o2}|${n2}`;
};
var tD = (t33) => {
const e2 = new Set;
for (let n2 = 1;n2 < t33.route.length; n2++) {
const o2 = t33.route[n2 - 1], i2 = t33.route[n2];
o2.z === i2.z && e2.add(Kk(o2, i2));
}
return e2;
};
var eD = (t33) => t33.filter((e2, n2) => {
const o2 = t33[n2 - 1];
return !o2 || e2.x !== o2.x || e2.y !== o2.y || e2.z !== o2.z;
});
var nD = (t33) => {
const e2 = [], n2 = new Set;
for (let o2 = 1;o2 < t33.length; o2++) {
const i2 = t33[o2 - 1], r2 = t33[o2];
if (i2.z === r2.z)
continue;
if (i2.toNextSegmentType === "through_obstacle")
continue;
if (i2.x !== r2.x || i2.y !== r2.y)
throw new Error(`CrossingViaReductionSolver found a layer transition without a via at route point ${o2}`);
const s2 = `${r2.x}:${r2.y}`;
n2.has(s2) || (n2.add(s2), e2.push({ x: r2.x, y: r2.y }));
}
return e2;
};
var oD = (t33) => {
const e2 = [t33.connectionName];
return t33.rootConnectionName && e2.push(t33.rootConnectionName), e2;
};
var iD = (t33, e2, n2) => {
const o2 = oD(t33), i2 = oD(e2);
return o2.some((t34) => i2.some((e3) => t34 === e3 || n2.areIdsConnected(t34, e3)));
};
var rD = (t33, e2, n2) => {
const o2 = oD(e2);
return t33.connectedTo.some((t34) => o2.some((e3) => t34 === e3 || n2.areIdsConnected(t34, e3)));
};
var sD = (t33) => {
let e2 = 0;
for (let n2 = 1;n2 < t33.length; n2++)
e2 += Math.hypot(t33[n2].x - t33[n2 - 1].x, t33[n2].y - t33[n2 - 1].y);
return e2;
};
var aD = (t33, e2) => {
const n2 = sD(t33);
if (e2 <= Qk || e2 >= n2 - Qk)
return null;
let o2 = 0;
for (let n3 = 1;n3 < t33.length; n3++) {
const i2 = t33[n3 - 1], r2 = t33[n3], s2 = Math.hypot(r2.x - i2.x, r2.y - i2.y);
if (o2 + s2 < e2 - Qk) {
o2 += s2;
continue;
}
const a2 = e2 - o2;
if (a2 <= Qk)
return { prefix: t33.slice(0, n3).map((t34) => ({ ...t34 })), suffix: t33.slice(n3 - 1).map((t34) => ({ ...t34 })), point: { ...i2 } };
if (s2 - a2 <= Qk)
return { prefix: t33.slice(0, n3 + 1).map((t34) => ({ ...t34 })), suffix: t33.slice(n3).map((t34) => ({ ...t34 })), point: { ...r2 } };
const c2 = a2 / s2, l2 = { x: i2.x + (r2.x - i2.x) * c2, y: i2.y + (r2.y - i2.y) * c2, z: i2.z };
return { prefix: [...t33.slice(0, n3), l2].map((t34) => ({ ...t34 })), suffix: [l2, ...t33.slice(n3)].map((t34) => ({ ...t34 })), point: l2 };
}
return null;
};
var cD = (t33, e2, n2, o2) => {
const i2 = ve(t33, e2, n2, o2);
if (!i2)
return null;
const r2 = Math.hypot(i2.x - t33.x, i2.y - t33.y), s2 = Math.hypot(i2.x - e2.x, i2.y - e2.y), a2 = Math.hypot(i2.x - n2.x, i2.y - n2.y), c2 = Math.hypot(i2.x - o2.x, i2.y - o2.y);
return Math.min(r2, s2, a2, c2) <= Qk ? null : r2;
};
var lD = (t33) => t33.points.some((t34) => t34.insideJumperPad || t34.toNextSegmentType);
var hD = ({ sections: t33, sectionIndex: e2, side: n2 }) => {
const o2 = t33[e2], i2 = n2 === "start" ? t33[e2 - 1] : t33[e2 + 1];
if (!i2)
return null;
const r2 = n2 === "start" ? o2.points[0] : o2.points.at(-1), s2 = n2 === "start" ? i2.points.at(-1) : i2.points[0];
return r2.x !== s2.x || r2.y !== s2.y ? null : i2.z;
};
var dD = ({ sections: t33, sectionIndex: e2, targetZ: n2, side: o2 }) => hD({ sections: t33, sectionIndex: e2, side: o2 }) === n2;
var uD = ({ baseIndexes: t33, otherCandidateRoutes: e2, ignoredConnectionNames: n2, originalRouteSegmentKeys: o2 }) => {
const i2 = new hr([...e2]);
return { getConflictingRoutesForSegment: (e3, r2, s2) => {
const a2 = o2.has(Kk(e3, r2));
return [...a2 ? [] : t33.mutableRoutes.getConflictingRoutesForSegment(e3, r2, s2).filter(({ conflictingRoute: t34 }) => !n2.has(t34.connectionName)), ...a2 ? [] : t33.immutableRoutes?.getConflictingRoutesForSegment(e3, r2, s2) ?? [], ...i2.getConflictingRoutesForSegment(e3, r2, s2)];
}, getConflictingRoutesNearPoint: (e3, o3) => [...t33.mutableRoutes.getConflictingRoutesNearPoint(e3, o3).filter(({ conflictingRoute: t34 }) => !n2.has(t34.connectionName)), ...t33.immutableRoutes?.getConflictingRoutesNearPoint(e3, o3) ?? [], ...i2.getConflictingRoutesNearPoint(e3, o3)] };
};
var pD = class extends si {
input;
obstacleSHI;
traceMargin;
obstacleMargin;
reducedHdRoutes;
getSolverName() {
return "CrossingViaReductionSolver";
}
constructor(t33) {
super(), this.input = { ...t33, obstacles: Is(t33.obstacles, t33.layerCount) }, this.traceMargin = t33.traceMargin ?? 0.1, this.obstacleMargin = t33.obstacleMargin ?? 0.15, this.reducedHdRoutes = structuredClone([...t33.inputHdRoutes]), this.obstacleSHI = new Sk("flatbush", [...this.input.obstacles]), this.MAX_ITERATIONS = 1e6;
}
collapseDetourSection({ route: t33, section: e2, targetZ: n2 }) {
const o2 = e2.points.map((t34) => ({ ...t34, z: n2 })), i2 = eD([...t33.route.slice(0, e2.startIndex).map((t34) => ({ ...t34 })), ...o2, ...t33.route.slice(e2.endIndex + 1).map((t34) => ({ ...t34 }))]);
return { ...t33, route: i2, vias: nD(i2) };
}
relocateTransitionVia({ route: t33, section: e2, targetZ: n2, side: o2, newViaDistance: i2 }) {
const r2 = aD(e2.points, i2);
if (!r2)
return null;
const s2 = o2 === "start" ? n2 : e2.z, a2 = o2 === "start" ? e2.z : n2, c2 = [...r2.prefix.map((t34) => ({ ...t34, z: s2 })), ...r2.suffix.map((t34) => ({ ...t34, z: a2 }))], l2 = eD([...t33.route.slice(0, e2.startIndex).map((t34) => ({ ...t34 })), ...c2, ...t33.route.slice(e2.endIndex + 1).map((t34) => ({ ...t34 }))]);
return { route: { ...t33, route: l2, vias: nD(l2) }, relocatedVia: { x: r2.point.x, y: r2.point.y } };
}
relocateTransitionVias({ route: t33, sections: e2, crossingGroups: n2, detourZ: o2, detourTraceThickness: i2 }) {
const r2 = new Map;
for (const t34 of n2) {
const e3 = r2.get(t34.transitionSectionIndex) ?? [];
e3.push(t34), r2.set(t34.transitionSectionIndex, e3);
}
const s2 = [], a2 = [], c2 = t33.viaDiameter / 2 + i2 / 2 + this.traceMargin + Qk;
for (const [t34, n3] of r2) {
if (n3.length !== 1)
return null;
const i3 = e2[t34], r3 = n3[0];
if (!dD({ sections: e2, sectionIndex: t34, targetZ: o2, side: r3.side }))
return null;
const l3 = r3.side === "start" ? Math.max(...r3.crossingDistances) + c2 : Math.min(...r3.crossingDistances) - c2, h2 = aD(i3.points, l3);
if (!h2)
return null;
const d2 = r3.side === "start" ? o2 : i3.z, u2 = r3.side === "start" ? i3.z : o2;
s2.push({ section: i3, points: [...h2.prefix.map((t35) => ({ ...t35, z: d2 })), ...h2.suffix.map((t35) => ({ ...t35, z: u2 }))] }), a2.push({ x: h2.point.x, y: h2.point.y });
}
let l2 = t33.route.map((t34) => ({ ...t34 }));
for (const t34 of s2.sort((t35, e3) => e3.section.startIndex - t35.section.startIndex))
l2 = [...l2.slice(0, t34.section.startIndex), ...t34.points, ...l2.slice(t34.section.endIndex + 1)];
return l2 = eD(l2), { route: { ...t33, route: l2, vias: nD(l2) }, relocatedVias: a2 };
}
routeIsClear(t33, e2, n2) {
for (const o2 of Dk(t33)) {
for (let e3 = 1;e3 < o2.points.length; e3++) {
const i2 = o2.points[e3 - 1], r2 = o2.points[e3];
if (!n2.has(Kk(i2, r2)) && this.input.outline && kk({ start: i2, end: r2, polygon: [...this.input.outline], margin: t33.traceThickness / 2 }))
return false;
}
if (!zk({ currentSection: o2, targetZ: o2.z, route: t33, hdRouteSHI: e2, obstacleSHI: this.obstacleSHI, connMap: this.input.connMap, defaultTraceThickness: t33.traceThickness, obstacleMargin: this.obstacleMargin, traceMargin: this.traceMargin, shouldCheckStaticGeometryForSegment: (t34, e3) => !n2.has(Kk(t34, e3)) }))
return false;
}
return true;
}
relocatedViaIsClear(t33, e2, n2) {
const o2 = t33.viaDiameter / 2;
for (let i3 = 0;i3 < this.input.layerCount; i3++) {
if (n2.getConflictingRoutesNearPoint({ ...e2, z: i3 }, o2 + this.traceMargin).some(({ conflictingRoute: e3 }) => !iD(t33, e3, this.input.connMap)))
return false;
}
const i2 = o2 + this.obstacleMargin, r2 = this.obstacleSHI.searchArea(e2.x, e2.y, 2 * i2, 2 * i2);
for (const n3 of r2)
if (!rD(n3, t33, this.input.connMap) && De(e2, e2, n3) < i2)
return false;
if (this.input.outline)
for (let t34 = 0;t34 < this.input.outline.length; t34++) {
if (be(e2, this.input.outline[t34], this.input.outline[(t34 + 1) % this.input.outline.length]) < o2 + this.traceMargin)
return false;
}
return true;
}
changedSectionsAreStaticallyClear(t33, e2) {
for (const n2 of Dk(t33)) {
if (n2.points.some((t34, o2) => {
const i2 = n2.points[o2 - 1];
return i2 !== undefined && !e2.has(Kk(i2, t34));
})) {
if (this.input.outline) {
for (let e3 = 1;e3 < n2.points.length; e3++)
if (kk({ start: n2.points[e3 - 1], end: n2.points[e3], polygon: [...this.input.outline], margin: t33.traceThickness / 2 }))
return false;
}
if (!zk({ currentSection: n2, targetZ: n2.z, route: t33, hdRouteSHI: Jk, obstacleSHI: this.obstacleSHI, connMap: this.input.connMap, defaultTraceThickness: t33.traceThickness, obstacleMargin: Math.min(this.obstacleMargin, 0.1), traceMargin: this.traceMargin }))
return false;
}
}
return true;
}
candidateIsClear(t33, e2) {
const n2 = [{ routeIndex: t33.detourRouteIndex, route: t33.detourRoute }, ...t33.transitionUpdates], o2 = new Set(n2.map(({ routeIndex: t34 }) => this.reducedHdRoutes[t34].connectionName)), i2 = tD(this.reducedHdRoutes[t33.detourRouteIndex]), r2 = uD({ baseIndexes: e2, otherCandidateRoutes: t33.transitionUpdates.map(({ route: t34 }) => t34), ignoredConnectionNames: o2, originalRouteSegmentKeys: i2 });
if (this.stats.candidateClearanceChecks = (this.stats.candidateClearanceChecks ?? 0) + 1, !this.routeIsClear(t33.detourRoute, r2, i2))
return false;
for (const i3 of t33.transitionUpdates) {
const t34 = tD(this.reducedHdRoutes[i3.routeIndex]), r3 = uD({ baseIndexes: e2, otherCandidateRoutes: n2.filter(({ routeIndex: t35 }) => t35 !== i3.routeIndex).map(({ route: t35 }) => t35), ignoredConnectionNames: o2, originalRouteSegmentKeys: t34 });
if (!this.routeIsClear(i3.route, r3, t34) || i3.relocatedVias.some((t35) => !this.relocatedViaIsClear(i3.route, t35, r3)))
return false;
}
return this.changedSectionsAreStaticallyClear(t33.detourRoute, i2);
}
candidateRoutesHaveNoExternalCopperConflicts(t33, e2) {
const n2 = [t33.detourRoute, ...t33.transitionUpdates.map(({ route: t34 }) => t34)], o2 = new Set(n2.map(({ connectionName: t34 }) => t34)), i2 = [e2.mutableRoutes, ...e2.immutableRoutes ? [e2.immutableRoutes] : []];
for (const t34 of n2)
for (const e3 of Dk(t34))
for (let n3 = 1;n3 < e3.points.length; n3++) {
const r2 = e3.points[n3 - 1], s2 = e3.points[n3];
for (const e4 of i2) {
if (e4.getConflictingRoutesForSegment(r2, s2, t34.traceThickness / 2 + this.traceMargin).some(({ conflictingRoute: e5 }) => !o2.has(e5.connectionName) && !iD(t34, e5, this.input.connMap)))
return false;
}
}
return true;
}
buildTransitionSegmentIndex(t33, e2) {
const n2 = [];
for (let o3 = 0;o3 < this.reducedHdRoutes.length; o3++) {
if (this.reducedHdRoutes[o3].jumpers?.length)
continue;
const i2 = t33[o3];
for (let t34 = 0;t34 < i2.length; t34++) {
const r2 = i2[t34];
if (!lD(r2))
for (const s2 of ["start", "end"]) {
const a2 = hD({ sections: i2, sectionIndex: t34, side: s2 });
if (a2 === null || a2 === r2.z)
continue;
if (!e2.has(`${r2.z}:${a2}`))
continue;
let c2 = 0;
for (let e3 = 1;e3 < r2.points.length; e3++) {
const i3 = r2.points[e3 - 1], l2 = r2.points[e3], h2 = Math.hypot(l2.x - i3.x, l2.y - i3.y);
h2 > Qk && n2.push({ routeIndex: o3, sectionIndex: t34, side: s2, adjacentZ: a2, start: i3, end: l2, distanceFromSectionStart: c2 }), c2 += h2;
}
}
}
}
if (this.stats.transitionSegmentsIndexed = (this.stats.transitionSegmentsIndexed ?? 0) + n2.length, n2.length === 0)
return null;
const o2 = new Ik(n2.length);
for (const t34 of n2)
o2.insert(t34, Math.min(t34.start.x, t34.end.x), Math.min(t34.start.y, t34.end.y), Math.max(t34.start.x, t34.end.x), Math.max(t34.start.y, t34.end.y));
return o2.finish(), o2;
}
getIndexedCrossingGroups({ detourRouteIndex: t33, detourSection: e2, targetZ: n2, transitionSegmentIndex: o2 }) {
const i2 = new Map;
for (let r2 = 1;r2 < e2.points.length; r2++) {
const s2 = e2.points[r2 - 1], a2 = e2.points[r2];
if (Math.hypot(a2.x - s2.x, a2.y - s2.y) <= Qk)
continue;
this.stats.indexedDetourSegmentQueries = (this.stats.indexedDetourSegmentQueries ?? 0) + 1;
const c2 = o2.search(Math.min(s2.x, a2.x) - Qk, Math.min(s2.y, a2.y) - Qk, Math.max(s2.x, a2.x) + Qk, Math.max(s2.y, a2.y) + Qk);
for (const o3 of c2) {
if (o3.routeIndex === t33 || o3.start.z !== n2 || o3.adjacentZ !== e2.z)
continue;
this.stats.exactSegmentIntersectionChecks = (this.stats.exactSegmentIntersectionChecks ?? 0) + 1;
const r3 = cD(o3.start, o3.end, s2, a2);
if (r3 === null)
continue;
const c3 = `${o3.routeIndex}:${o3.sectionIndex}:${o3.side}`;
let l2 = i2.get(c3);
l2 || (l2 = { transitionRouteIndex: o3.routeIndex, transitionSectionIndex: o3.sectionIndex, side: o3.side, crossingDistances: [] }, i2.set(c3, l2)), l2.crossingDistances.push(o3.distanceFromSectionStart + r3);
}
}
return [...i2.values()].sort((t34, e3) => t34.transitionRouteIndex !== e3.transitionRouteIndex ? t34.transitionRouteIndex - e3.transitionRouteIndex : t34.transitionSectionIndex !== e3.transitionSectionIndex ? t34.transitionSectionIndex - e3.transitionSectionIndex : t34.side === e3.side ? 0 : t34.side === "start" ? -1 : 1);
}
tryCreateCandidate({ detourRouteIndex: t33, detourSection: e2, targetZ: n2, transitionRouteIndex: o2, transitionSection: i2, transitionSections: r2, transitionSectionIndex: s2, side: a2, crossingDistances: c2, baseClearanceIndexes: l2 }) {
if (!dD({ sections: r2, sectionIndex: s2, targetZ: e2.z, side: a2 }))
return null;
const h2 = this.reducedHdRoutes[t33], d2 = this.reducedHdRoutes[o2];
if (c2.length === 0)
return null;
const u2 = d2.viaDiameter / 2 + h2.traceThickness / 2 + this.traceMargin + Qk, p2 = a2 === "start" ? Math.max(...c2) + u2 : Math.min(...c2) - u2, m2 = this.relocateTransitionVia({ route: d2, section: i2, targetZ: e2.z, side: a2, newViaDistance: p2 });
if (!m2)
return null;
const g2 = this.collapseDetourSection({ route: h2, section: e2, targetZ: n2 });
if (h2.vias.length + d2.vias.length - g2.vias.length - m2.route.vias.length !== 2)
return null;
const f2 = { detourRouteIndex: t33, detourRoute: g2, transitionUpdates: [{ routeIndex: o2, route: m2.route, relocatedVias: [m2.relocatedVia] }] };
return this.candidateIsClear(f2, l2) ? f2 : null;
}
tryCreateMultiCrossingCandidate({ detourRouteIndex: t33, detourSection: e2, targetZ: n2, crossingGroups: o2, sectionsByRoute: i2, baseClearanceIndexes: r2 }) {
if (o2.length < 2)
return null;
const s2 = this.reducedHdRoutes[t33], a2 = [], c2 = new Map;
for (const t34 of o2) {
const e3 = c2.get(t34.transitionRouteIndex) ?? [];
e3.push(t34), c2.set(t34.transitionRouteIndex, e3);
}
for (const [t34, n3] of c2) {
const o3 = this.reducedHdRoutes[t34], r3 = this.relocateTransitionVias({ route: o3, sections: i2[t34], crossingGroups: n3, detourZ: e2.z, detourTraceThickness: s2.traceThickness });
if (!r3)
return null;
a2.push({ routeIndex: t34, route: r3.route, relocatedVias: r3.relocatedVias });
}
const l2 = this.collapseDetourSection({ route: s2, section: e2, targetZ: n2 });
if (s2.vias.length + [...c2.keys()].reduce((t34, e3) => t34 + this.reducedHdRoutes[e3].vias.length, 0) - (l2.vias.length + a2.reduce((t34, { route: e3 }) => t34 + e3.vias.length, 0)) !== 2)
return null;
this.stats.multiCrossingCandidates = (this.stats.multiCrossingCandidates ?? 0) + 1;
const h2 = { detourRouteIndex: t33, detourRoute: l2, transitionUpdates: a2 };
return this.candidateIsClear(h2, r2) ? this.candidateRoutesHaveNoExternalCopperConflicts(h2, r2) ? (this.stats.multiCrossingReductions = (this.stats.multiCrossingReductions ?? 0) + 1, this.stats.transitionRoutesMovedByMultiCrossingReductions = (this.stats.transitionRoutesMovedByMultiCrossingReductions ?? 0) + a2.length, h2) : (this.stats.multiCrossingPreexistingConflictRejections = (this.stats.multiCrossingPreexistingConflictRejections ?? 0) + 1, null) : null;
}
findCrossingReduction() {
const t33 = this.reducedHdRoutes.map((t34) => Dk(t34)), e2 = [], n2 = new Set;
for (let o3 = 0;o3 < this.reducedHdRoutes.length; o3++) {
if (this.reducedHdRoutes[o3].jumpers?.length)
continue;
const i3 = t33[o3];
for (let t34 = 1;t34 < i3.length - 1; t34++) {
const r2 = i3[t34 - 1], s2 = i3[t34], a2 = i3[t34 + 1];
r2.z !== a2.z || r2.z === s2.z || lD(s2) || (e2.push({ routeIndex: o3, section: s2, targetZ: r2.z }), n2.add(`${r2.z}:${s2.z}`));
}
}
if (e2.length === 0)
return null;
const o2 = this.buildTransitionSegmentIndex(t33, n2);
if (!o2)
return null;
let i2 = null;
for (const n3 of e2) {
const { routeIndex: e3, section: r2 } = n3, s2 = this.reducedHdRoutes[e3], a2 = this.getIndexedCrossingGroups({ detourRouteIndex: e3, detourSection: r2, targetZ: n3.targetZ, transitionSegmentIndex: o2 }).filter(({ transitionRouteIndex: t34 }) => {
const e4 = this.reducedHdRoutes[t34];
return !e4.jumpers?.length && !iD(s2, e4, this.input.connMap);
}), c2 = new Map;
for (const t34 of a2) {
const e4 = `${t34.transitionRouteIndex}:${t34.transitionSectionIndex}`, n4 = c2.get(e4) ?? [];
n4.push(t34), c2.set(e4, n4);
}
if (c2.size > 1) {
i2 ??= { mutableRoutes: new hr(this.reducedHdRoutes), immutableRoutes: this.input.otherHdRoutes?.length ? new hr([...this.input.otherHdRoutes]) : null };
let o3 = [{ groups: [], movement: 0 }];
const a3 = (e4) => {
const n4 = this.reducedHdRoutes[e4.transitionRouteIndex], o4 = t33[e4.transitionRouteIndex][e4.transitionSectionIndex], i3 = n4.viaDiameter / 2 + s2.traceThickness / 2 + this.traceMargin + Qk, r3 = e4.side === "start" ? Math.max(...e4.crossingDistances) + i3 : Math.min(...e4.crossingDistances) - i3;
return e4.side === "start" ? r3 : sD(o4.points) - r3;
};
for (const t34 of c2.values()) {
const e4 = t34.map((t35) => ({ group: t35, movement: a3(t35) })).sort((t35, e5) => t35.movement - e5.movement);
o3 = o3.flatMap((t35) => e4.map((e5) => ({ groups: [...t35.groups, e5.group], movement: t35.movement + e5.movement }))).sort((t35, e5) => t35.movement - e5.movement).slice(0, 4);
}
for (const s3 of o3) {
const o4 = this.tryCreateMultiCrossingCandidate({ detourRouteIndex: e3, detourSection: r2, targetZ: n3.targetZ, crossingGroups: s3.groups, sectionsByRoute: t33, baseClearanceIndexes: i2 });
if (o4)
return o4;
}
continue;
}
const l2 = c2.values().next().value ?? [];
for (const o3 of l2) {
const s3 = o3.transitionRouteIndex, a3 = t33[s3], c3 = a3[o3.transitionSectionIndex];
i2 ??= { mutableRoutes: new hr(this.reducedHdRoutes), immutableRoutes: this.input.otherHdRoutes?.length ? new hr([...this.input.otherHdRoutes]) : null };
const l3 = this.tryCreateCandidate({ detourRouteIndex: e3, detourSection: r2, targetZ: n3.targetZ, transitionRouteIndex: s3, transitionSection: c3, transitionSections: a3, transitionSectionIndex: o3.transitionSectionIndex, side: o3.side, crossingDistances: o3.crossingDistances, baseClearanceIndexes: i2 });
if (l3)
return l3;
}
}
return null;
}
_step() {
const t33 = this.findCrossingReduction();
if (t33) {
this.reducedHdRoutes[t33.detourRouteIndex] = t33.detourRoute;
for (const e2 of t33.transitionUpdates)
this.reducedHdRoutes[e2.routeIndex] = e2.route;
this.stats.crossingViaReductions = (this.stats.crossingViaReductions ?? 0) + 1, this.stats.viasRemovedByCrossingReductions = (this.stats.viasRemovedByCrossingReductions ?? 0) + 2;
} else
this.solved = true;
}
getReducedHdRoutes() {
return this.reducedHdRoutes;
}
visualize() {
const t33 = { lines: [], circles: [], rects: [], coordinateSystem: "cartesian", title: "Crossing Via Reduction Solver" };
for (const e2 of this.input.obstacles)
t33.rects.push({ center: e2.center, width: e2.width, height: e2.height, fill: "rgba(128, 128, 128, 0.2)" });
for (const e2 of this.reducedHdRoutes) {
for (let n2 = 1;n2 < e2.route.length; n2++) {
const o2 = e2.route[n2 - 1], i2 = e2.route[n2];
o2.z === i2.z && t33.lines.push({ points: [o2, i2], strokeColor: o2.z === 0 ? "#d32f2f" : "#3367a8", strokeWidth: e2.traceThickness, label: `${e2.connectionName} (z=${o2.z})` });
}
for (const n2 of e2.vias)
t33.circles.push({ center: n2, radius: e2.viaDiameter / 2, fill: "#ff20d6", label: `${e2.connectionName} via` });
}
return t33;
}
};
var mD = 0.000001;
var gD = (t33, e2) => Math.abs(t33.x - e2.center.x) <= e2.width / 2 + mD && Math.abs(t33.y - e2.center.y) <= e2.height / 2 + mD;
var fD = (t33) => (t33.__zLayers?.length ?? t33.layers?.length ?? 0) > 1;
var yD = class extends si {
constructor(t33) {
if (super(), this.simplificationConfig = t33, this.simplificationConfig = { ...t33, obstacles: Is(t33.obstacles, t33.layerCount) }, this.hdRoutes = this.markThroughObstacleSegments(t33.hdRoutes), t33.preserveRouteEndpoints) {
const e2 = new Map;
for (const n2 of t33.hdRoutes) {
const t34 = n2.route[0], o2 = n2.route.at(-1);
if (!t34 || !o2)
throw new Error(`TraceSimplificationSolver cannot preserve endpoints for empty route "${n2.connectionName}"`);
if (e2.has(n2.connectionName))
throw new Error(`TraceSimplificationSolver cannot preserve endpoints for duplicate route "${n2.connectionName}"`);
e2.set(n2.connectionName, { start: { ...t34 }, end: { ...o2 } });
}
this.preservedRouteEndpoints = e2;
}
this.MAX_ITERATIONS = 1e8;
}
getSolverName() {
return "TraceSimplificationSolver";
}
hdRoutes = [];
preservedRouteEndpoints;
simplificationPipelineLoops = 0;
MAX_SIMPLIFICATION_PIPELINE_LOOPS = 2;
PHASE_ORDER = ["via_removal", "crossing_via_reduction", "via_merging", "path_simplification"];
currentPhase = "via_removal";
extractResult = null;
get simplifiedHdRoutes() {
return this.hdRoutes;
}
validatePreservedRouteEndpoints(t33) {
if (!this.preservedRouteEndpoints)
return;
if (t33.length !== this.preservedRouteEndpoints.size)
throw new Error(`TraceSimplificationSolver changed the preserved route set (expected ${this.preservedRouteEndpoints.size}, got ${t33.length})`);
const e2 = new Set, n2 = (t34, e3) => Math.abs(t34.x - e3.x) <= mD && Math.abs(t34.y - e3.y) <= mD && t34.z === e3.z;
for (const o2 of t33) {
if (e2.has(o2.connectionName))
throw new Error(`TraceSimplificationSolver produced duplicate preserved route "${o2.connectionName}"`);
e2.add(o2.connectionName);
const t34 = this.preservedRouteEndpoints.get(o2.connectionName), i2 = o2.route[0], r2 = o2.route.at(-1);
if (!(t34 && i2 && r2 && n2(i2, t34.start) && n2(r2, t34.end)))
throw new Error(`TraceSimplificationSolver changed a preserved endpoint for route "${o2.connectionName}"`);
}
}
isSameNetObstacle(t33, e2) {
return e2.connectedTo.some((e3) => e3 === t33.connectionName || e3 === t33.rootConnectionName || this.simplificationConfig.connMap.areIdsConnected(t33.connectionName, e3) || t33.rootConnectionName !== undefined && this.simplificationConfig.connMap.areIdsConnected(t33.rootConnectionName, e3));
}
getSameNetObstacleForSegment(t33, e2, n2) {
return this.simplificationConfig.obstacles.find((o2) => fD(o2) && this.isSameNetObstacle(t33, o2) && gD(e2, o2) && gD(n2, o2));
}
isViaInsideSameNetObstacle(t33, e2) {
return this.simplificationConfig.obstacles.some((n2) => fD(n2) && this.isSameNetObstacle(t33, n2) && gD(e2, n2));
}
markThroughObstacleSegments(t33) {
return t33.map((t34) => ({ ...t34, route: t34.route.map((e2, n2, o2) => {
const i2 = o2[n2 + 1], r2 = i2 && e2.z !== i2.z && this.getSameNetObstacleForSegment(t34, e2, i2);
if (r2)
return { ...e2, toNextSegmentType: "through_obstacle", ...r2.circuitJsonMetadata ? { toNextSegmentCircuitJsonMetadata: r2.circuitJsonMetadata } : {} };
const s2 = { ...e2 };
return delete s2.toNextSegmentType, delete s2.toNextSegmentCircuitJsonMetadata, s2;
}), vias: t34.vias.filter((e2) => !this.isViaInsideSameNetObstacle(t34, e2)) }));
}
_step() {
if (this.simplificationPipelineLoops >= this.MAX_SIMPLIFICATION_PIPELINE_LOOPS)
this.solved = true;
else {
if (this.activeSubSolver) {
if (this.activeSubSolver.step(), !this.activeSubSolver.failed && !this.activeSubSolver.solved)
return;
if (this.activeSubSolver.solved) {
if (this.extractResult) {
const t33 = this.extractResult(this.activeSubSolver);
this.validatePreservedRouteEndpoints(t33), this.hdRoutes = this.markThroughObstacleSegments(t33);
}
if (this.activeSubSolver = null, this.extractResult = null, this.currentPhase === "via_removal" ? this.currentPhase = this.simplificationConfig.enableCrossingViaReduction ? "crossing_via_reduction" : "via_merging" : this.currentPhase === "crossing_via_reduction" ? this.currentPhase = "via_merging" : this.currentPhase === "via_merging" ? this.currentPhase = "path_simplification" : (this.currentPhase = "via_removal", this.simplificationPipelineLoops++), this.simplificationPipelineLoops >= this.MAX_SIMPLIFICATION_PIPELINE_LOOPS)
return void (this.solved = true);
} else if (this.activeSubSolver.failed)
return this.failed = true, void (this.error = this.activeSubSolver.error ?? "Sub-solver failed without error message");
}
if (!this.activeSubSolver && !this.solved)
switch (this.currentPhase) {
case "via_removal":
this.activeSubSolver = new Fk({ unsimplifiedHdRoutes: this.hdRoutes, otherHdRoutes: [...this.simplificationConfig.otherHdRoutes ?? []], obstacles: [...this.simplificationConfig.obstacles], colorMap: { ...this.simplificationConfig.colorMap }, layerCount: this.simplificationConfig.layerCount, connMap: this.simplificationConfig.connMap, outline: this.simplificationConfig.outline ? [...this.simplificationConfig.outline] : undefined, geometryShortcutTraceMargin: 0.1, geometryShortcutObstacleMargin: this.simplificationConfig.minTraceToPadEdgeClearance ?? 0.15, enableGeometryShortcuts: this.simplificationPipelineLoops > 0, enableObstacleDetourShortcuts: this.simplificationConfig.enableCrossingViaReduction === true && this.simplificationPipelineLoops > 0, preserveRouteEndpoints: this.simplificationConfig.preserveRouteEndpoints, terminalLayerIndicesByPcbPortId: this.simplificationConfig.terminalLayerIndicesByPcbPortId }), this.extractResult = (t33) => t33.getOptimizedHdRoutes() ?? [];
break;
case "crossing_via_reduction":
this.activeSubSolver = new pD({ inputHdRoutes: this.hdRoutes, otherHdRoutes: [...this.simplificationConfig.otherHdRoutes ?? []], obstacles: [...this.simplificationConfig.obstacles], connMap: this.simplificationConfig.connMap, layerCount: this.simplificationConfig.layerCount, outline: this.simplificationConfig.outline ? [...this.simplificationConfig.outline] : undefined, traceMargin: 0.1, obstacleMargin: this.simplificationConfig.minTraceToPadEdgeClearance ?? 0.15 }), this.extractResult = (t33) => t33.getReducedHdRoutes();
break;
case "via_merging":
this.activeSubSolver = new qk({ inputHdRoutes: this.hdRoutes, otherHdRoutes: [...this.simplificationConfig.otherHdRoutes ?? []], netByConnectionName: this.simplificationConfig.netByConnectionName, obstacles: [...this.simplificationConfig.obstacles], colorMap: { ...this.simplificationConfig.colorMap }, layerCount: this.simplificationConfig.layerCount, connMap: this.simplificationConfig.connMap, outline: this.simplificationConfig.outline ? [...this.simplificationConfig.outline] : undefined, preserveRouteEndpoints: this.simplificationConfig.preserveRouteEndpoints }), this.extractResult = (t33) => t33.getMergedViaHdRoutes() ?? [];
break;
case "path_simplification":
this.activeSubSolver = new Vk({ unsimplifiedHdRoutes: this.hdRoutes, otherHdRoutes: [...this.simplificationConfig.otherHdRoutes ?? []], obstacles: [...this.simplificationConfig.obstacles], connMap: this.simplificationConfig.connMap, colorMap: { ...this.simplificationConfig.colorMap }, outline: this.simplificationConfig.outline ? [...this.simplificationConfig.outline] : undefined, minBoardEdgeClearance: this.simplificationConfig.minBoardEdgeClearance, defaultViaDiameter: this.simplificationConfig.defaultViaDiameter, useTraceWidthAwareClearance: this.simplificationConfig.useTraceWidthAwareClearance, enableVertexShortcuts: this.simplificationConfig.enableVertexShortcuts }), this.extractResult = (t33) => t33.simplifiedHdRoutes;
break;
default:
this.failed = true, this.error = `Unknown phase: ${this.currentPhase}`;
}
}
}
visualize() {
if (this.activeSubSolver)
return this.activeSubSolver.visualize();
const t33 = { lines: [], points: [], rects: [], circles: [], coordinateSystem: "cartesian", title: "Trace Simplification Solver" };
for (const e2 of this.simplificationConfig.obstacles) {
let n2 = "rgba(128, 128, 128, 0.2)";
const o2 = e2.__zLayers?.includes(0), i2 = e2.__zLayers?.includes(1);
o2 && i2 ? n2 = "rgba(128, 0, 128, 0.2)" : o2 ? n2 = "rgba(255, 0, 0, 0.2)" : i2 && (n2 = "rgba(0, 0, 255, 0.2)"), t33.rects.push({ center: e2.center, width: e2.width, height: e2.height, fill: n2, label: `Obstacle (Z: ${e2.__zLayers?.join(", ")})` });
}
for (const e2 of this.simplificationConfig.otherHdRoutes ?? []) {
for (let n2 = 0;n2 < e2.route.length - 1; n2++) {
const o2 = e2.route[n2], i2 = e2.route[n2 + 1];
o2.z === i2.z && t33.lines.push({ points: [{ x: o2.x, y: o2.y }, { x: i2.x, y: i2.y }], strokeColor: o2.z === 0 ? "rgba(160, 32, 32, 0.55)" : "rgba(32, 32, 160, 0.55)", strokeWidth: e2.traceThickness, strokeDash: [0.08, 0.08], label: `${e2.connectionName} immutable (z=${o2.z})` });
}
for (const n2 of e2.vias)
t33.circles.push({ center: { x: n2.x, y: n2.y }, radius: e2.viaDiameter / 2, fill: "rgba(96, 96, 96, 0.45)", label: `${e2.connectionName} immutable via` });
}
for (const e2 of this.hdRoutes)
if (e2.route.length !== 0) {
for (let n2 = 0;n2 < e2.route.length - 1; n2++) {
const o2 = e2.route[n2], i2 = e2.route[n2 + 1];
o2.z === i2.z && t33.lines.push({ points: [{ x: o2.x, y: o2.y }, { x: i2.x, y: i2.y }], strokeColor: o2.z === 0 ? "red" : "blue", strokeWidth: e2.traceThickness, label: `${e2.connectionName} (z=${o2.z})` });
}
for (const n2 of e2.vias)
t33.circles.push({ center: { x: n2.x, y: n2.y }, radius: e2.viaDiameter / 2, fill: "rgba(255, 0, 255, 0.5)", label: `${e2.connectionName} via` });
if (e2.jumpers && e2.jumpers.length > 0) {
const n2 = mk(e2.jumpers, { color: "orange", label: e2.connectionName });
t33.rects.push(...n2.rects ?? []), t33.lines.push(...n2.lines ?? []);
}
}
return t33;
}
};
var _D = 0.000000001;
var bD = class extends si {
getSolverName() {
return "TraceWidthSolver";
}
hdRoutes;
hdRoutesWithWidths = [];
nominalTraceWidth;
minTraceWidth;
obstacleMargin;
TRACE_WIDTH_SCHEDULE;
connectionNominalTraceWidthMap;
unprocessedRoutes = [];
processedRoutes = [];
currentTrace = null;
cursorPosition = null;
currentTraceSegmentIndex = 0;
currentTraceSegmentT = 0;
currentScheduleIndex = 0;
currentTargetWidth = 0;
hasInsufficientClearance = false;
lastCollidingObstacles = [];
lastCollidingRoutes = [];
lastClearance = 1 / 0;
obstacles = [];
obstacleSHI;
hdRouteSHI;
connMap;
colorMap;
constructor(t33) {
super(), this.MAX_ITERATIONS = 1e6, this.hdRoutes = [...t33.hdRoutes], this.minTraceWidth = t33.minTraceWidth, this.obstacleMargin = t33.obstacleMargin ?? 0.15, this.nominalTraceWidth = 0, this.TRACE_WIDTH_SCHEDULE = [], this.unprocessedRoutes = [...this.hdRoutes], this.connMap = t33.connMap, this.colorMap = t33.colorMap;
const e2 = t33.layerCount;
this.obstacles = Is(t33.obstacles ?? [], e2), this.connectionNominalTraceWidthMap = new Map;
for (const e3 of t33.connection)
e3.nominalTraceWidth !== undefined && this.connectionNominalTraceWidthMap.set(e3.name, e3.nominalTraceWidth);
this.obstacles.length > 0 && (this.obstacleSHI = new Sk("flatbush", this.obstacles)), this.hdRouteSHI = new hr(this.hdRoutes);
}
getNominalTraceWidthForRoute(t33) {
const e2 = this.connectionNominalTraceWidthMap.get(t33.connectionName);
return e2 !== undefined ? e2 : t33.rootConnectionName ? this.connectionNominalTraceWidthMap.get(t33.rootConnectionName) : undefined;
}
_step() {
if (!this.currentTrace) {
const t34 = this.unprocessedRoutes.shift();
if (!t34)
return this.hdRoutesWithWidths = this.processedRoutes, void (this.solved = true);
const e2 = this.getNominalTraceWidthForRoute(t34);
if (e2 === undefined) {
const e3 = t34.traceThickness ?? this.minTraceWidth;
return this.processedRoutes.push(this.createRouteWithWidth(t34, e3)), void (this.currentTrace = null);
}
this.currentTrace = t34, this.nominalTraceWidth = e2;
const n2 = (this.nominalTraceWidth + this.minTraceWidth) / 2;
return this.TRACE_WIDTH_SCHEDULE = [this.nominalTraceWidth, n2], this.currentTrace.route.length < 2 ? (this.processedRoutes.push(this.createRouteWithWidth(this.currentTrace, this.minTraceWidth)), void (this.currentTrace = null)) : (this.currentScheduleIndex = 0, this.currentTargetWidth = this.TRACE_WIDTH_SCHEDULE[0], void this.initializeCursor());
}
const t33 = this.stepCursorForward();
(t33 ? this.getClearanceForSegment(this.cursorPosition, this.cursorPosition) : this.getMinimumRouteClearance()) < this.currentTargetWidth / 2 + this.obstacleMargin ? (this.hasInsufficientClearance = true, this.currentScheduleIndex++, this.currentScheduleIndex < this.TRACE_WIDTH_SCHEDULE.length ? (this.currentTargetWidth = this.TRACE_WIDTH_SCHEDULE[this.currentScheduleIndex], this.initializeCursor()) : this.finalizeCurrentTrace(this.minTraceWidth)) : t33 || this.finalizeCurrentTrace(this.currentTargetWidth);
}
initializeCursor() {
if (!this.currentTrace)
return;
const t33 = this.currentTrace.route[0];
this.cursorPosition = { ...t33 }, this.currentTraceSegmentIndex = 0, this.currentTraceSegmentT = 0, this.hasInsufficientClearance = false;
}
stepCursorForward() {
if (!this.currentTrace || !this.cursorPosition)
return false;
const t33 = this.currentTrace.route;
let e2 = 0.1;
for (;e2 > 0; ) {
if (this.currentTraceSegmentIndex >= t33.length - 1)
return false;
const n2 = t33[this.currentTraceSegmentIndex], o2 = t33[this.currentTraceSegmentIndex + 1];
if (n2.insideJumperPad && o2.insideJumperPad) {
this.currentTraceSegmentIndex++, this.currentTraceSegmentT = 0;
continue;
}
const i2 = o2.x - n2.x, r2 = o2.y - n2.y, s2 = Math.sqrt(i2 * i2 + r2 * r2);
if (s2 === 0) {
this.currentTraceSegmentIndex++, this.currentTraceSegmentT = 0;
continue;
}
const a2 = this.currentTraceSegmentT * s2, c2 = s2 - a2;
if (e2 <= c2) {
const t34 = a2 + e2;
return this.currentTraceSegmentT = t34 / s2, this.cursorPosition = { x: n2.x + i2 * this.currentTraceSegmentT, y: n2.y + r2 * this.currentTraceSegmentT, z: n2.z }, true;
}
if (e2 -= c2, this.currentTraceSegmentIndex++, this.currentTraceSegmentT = 0, this.currentTraceSegmentIndex >= t33.length - 1) {
const e3 = t33[t33.length - 1];
return this.cursorPosition = { ...e3 }, false;
}
}
return true;
}
isObstacleOwnJumperPad(t33) {
if (!this.currentTrace?.jumpers)
return false;
for (const e2 of this.currentTrace.jumpers) {
const n2 = Math.sqrt((t33.center.x - e2.start.x) ** 2 + (t33.center.y - e2.start.y) ** 2), o2 = Math.sqrt((t33.center.x - e2.end.x) ** 2 + (t33.center.y - e2.end.y) ** 2), i2 = Math.max(t33.width, t33.height) / 2 + 0.01;
if (n2 < i2 || o2 < i2)
return true;
}
return false;
}
getMinimumRouteClearance() {
if (!this.currentTrace)
return 1 / 0;
let t33 = 1 / 0;
const e2 = this.currentTrace.route;
for (let n2 = 0;n2 < e2.length - 1; n2++) {
const o2 = e2[n2], i2 = e2[n2 + 1];
o2.z === i2.z && (o2.insideJumperPad && i2.insideJumperPad || o2.toNextSegmentType !== "through_obstacle" && (t33 = Math.min(t33, this.getClearanceForSegment(o2, i2))));
}
return t33;
}
getClearanceForSegment(t33, e2) {
if (!this.currentTrace)
return 1 / 0;
const n2 = this.currentTrace.rootConnectionName ?? this.currentTrace.connectionName, o2 = this.currentTargetWidth / 2 + this.obstacleMargin;
let i2 = 1 / 0;
this.lastCollidingObstacles = [], this.lastCollidingRoutes = [];
const r2 = new Set(this.obstacleSHI?.search({ minX: Math.min(t33.x, e2.x) - o2, minY: Math.min(t33.y, e2.y) - o2, maxX: Math.max(t33.x, e2.x) + o2, maxY: Math.max(t33.y, e2.y) + o2 }));
for (const t34 of this.obstacles)
t34.ccwRotationDegrees && r2.add(t34);
for (const s3 of r2) {
if (!this.isObstacleOnPointLayer(s3, t33))
continue;
if (xo(s3, this.currentTrace, this.connMap))
continue;
if (s3.obstacleId && this.connMap?.areIdsConnected(n2, s3.obstacleId))
continue;
if (this.isObstacleOwnJumperPad(s3))
continue;
const r3 = -(s3.ccwRotationDegrees ?? 0) * Math.PI / 180, a2 = Math.cos(r3), c2 = Math.sin(r3), l2 = De({ x: (t33.x - s3.center.x) * a2 - (t33.y - s3.center.y) * c2, y: (t33.x - s3.center.x) * c2 + (t33.y - s3.center.y) * a2 }, { x: (e2.x - s3.center.x) * a2 - (e2.y - s3.center.y) * c2, y: (e2.x - s3.center.x) * c2 + (e2.y - s3.center.y) * a2 }, { center: { x: 0, y: 0 }, width: s3.width, height: s3.height });
i2 = Math.min(i2, l2), l2 < o2 && this.lastCollidingObstacles.push(s3);
}
const s2 = this.hdRouteSHI.getConflictingRoutesForSegment(t33, e2, o2);
for (const { conflictingRoute: r3 } of s2) {
const s3 = r3, a2 = s3.rootConnectionName ?? s3.connectionName;
if (a2 === n2)
continue;
if (this.connMap?.areIdsConnected(n2, a2))
continue;
let c2 = 1 / 0;
for (let n3 = 0;n3 < s3.route.length - 1; n3++) {
const o3 = s3.route[n3], i3 = s3.route[n3 + 1];
o3.z === i3.z && o3.z === t33.z && (o3.insideJumperPad && i3.insideJumperPad || o3.toNextSegmentType !== "through_obstacle" && (c2 = Math.min(c2, Oe(t33, e2, o3, i3) - (o3.traceThickness ?? s3.traceThickness) / 2)));
}
for (const n3 of s3.vias)
c2 = Math.min(c2, Le(t33, e2, { ...n3, radius: s3.viaDiameter / 2 }));
i2 = Math.min(i2, c2), c2 < o2 && this.lastCollidingRoutes.push(s3);
}
return this.lastClearance = i2, i2;
}
isObstacleOnPointLayer(t33, e2) {
return !t33.__zLayers || t33.__zLayers.includes(e2.z);
}
getAdjacentNonCoincidentRoutePoint(t33, e2) {
const n2 = t33.route[e2];
if (!n2)
return;
const o2 = e2 === 0 ? 1 : -1;
for (let i2 = e2 + o2;i2 >= 0 && i2 < t33.route.length; i2 += o2) {
const e3 = t33.route[i2];
if (xe(e3, n2) > _D)
return e3;
}
}
getObstacleWidthAlongVector(t33, e2) {
const n2 = (t33.ccwRotationDegrees ?? 0) * Math.PI / 180, o2 = Math.cos(n2), i2 = Math.sin(n2), r2 = o2, s2 = i2, a2 = -i2, c2 = o2;
return Math.abs(e2.x * r2 + e2.y * s2) * t33.width + Math.abs(e2.x * a2 + e2.y * c2) * t33.height;
}
getTerminalPadWidthLimit(t33, e2, n2) {
const o2 = t33.route[e2];
if (!o2)
return;
const i2 = this.getAdjacentNonCoincidentRoutePoint(t33, e2);
if (!i2)
return;
const r2 = e2 === 0 ? Be(o2, i2) : Be(i2, o2);
if (xe(r2, { x: 0, y: 0 }) <= _D)
return;
const s2 = { x: -r2.y, y: r2.x };
let a2;
for (const e3 of this.obstacles) {
if (!this.isObstacleOnPointLayer(e3, o2))
continue;
if (!xo(e3, t33, this.connMap))
continue;
if (Fe(o2, e3) > _D)
continue;
const n3 = this.getObstacleWidthAlongVector(e3, s2);
if (n3 <= _D)
continue;
const i3 = this.getObstacleWidthAlongVector(e3, r2) / 2;
(!a2 || n3 < a2.width || Math.abs(n3 - a2.width) <= _D && i3 > a2.neckDistance) && (a2 = { width: n3, neckDistance: i3 });
}
return !a2 || a2.width >= n2 - _D ? undefined : a2;
}
getRouteDistanceInfo(t33) {
const e2 = [0];
let n2 = 0;
for (let o2 = 1;o2 < t33.length; o2++) {
const i2 = t33[o2 - 1];
n2 += xe(t33[o2], i2), e2.push(n2);
}
return { distances: e2, totalDistance: n2 };
}
interpolateRoutePointAtDistance(t33, e2, n2) {
for (let o2 = 1;o2 < t33.length; o2++) {
const i2 = e2[o2 - 1], r2 = e2[o2], s2 = r2 - i2;
if (n2 > r2 + _D)
continue;
const a2 = t33[o2 - 1], c2 = t33[o2];
if (s2 <= _D)
return { ...c2 };
const l2 = Math.max(0, Math.min(1, (n2 - i2) / s2));
return { x: a2.x + (c2.x - a2.x) * l2, y: a2.y + (c2.y - a2.y) * l2, z: a2.z };
}
return { ...t33[t33.length - 1] };
}
getTaperWidthAtDistance({ distanceFromStart: t33, totalDistance: e2, startLimit: n2, endLimit: o2, taperDistance: i2, traceWidth: r2 }) {
let s2 = r2;
if (n2 !== undefined && t33 <= i2) {
const e3 = Math.min(n2.neckDistance, i2);
if (t33 <= e3)
s2 = Math.min(s2, n2.width);
else {
const o3 = (t33 - e3) / Math.max(i2 - e3, _D);
s2 = Math.min(s2, n2.width + (r2 - n2.width) * o3);
}
}
if (o2 !== undefined) {
const n3 = e2 - t33;
if (n3 <= i2) {
const t34 = Math.min(o2.neckDistance, i2);
if (n3 <= t34)
s2 = Math.min(s2, o2.width);
else {
const e3 = (n3 - t34) / Math.max(i2 - t34, _D);
s2 = Math.min(s2, o2.width + (r2 - o2.width) * e3);
}
}
}
return s2;
}
createTerminalTaperedRoute(t33, e2) {
if (t33.route.length < 2)
return t33.route.map((t34) => ({ ...t34, traceThickness: t34.traceThickness ?? e2 }));
const n2 = this.getTerminalPadWidthLimit(t33, 0, e2), o2 = this.getTerminalPadWidthLimit(t33, t33.route.length - 1, e2), { distances: i2, totalDistance: r2 } = this.getRouteDistanceInfo(t33.route);
if (r2 <= _D) {
const i3 = Math.min(n2?.width ?? e2, o2?.width ?? e2);
return t33.route.map((t34) => ({ ...t34, traceThickness: i3 }));
}
const s2 = Math.min(Math.max(2 * e2, 0.75), r2 / 2), a2 = i2.map((t34, e3) => ({ distanceFromStart: t34, originalPointIndex: e3 })), c2 = [];
if (n2 !== undefined) {
c2.push(n2.neckDistance);
for (let t34 = 0;t34 <= 8; t34++)
c2.push(s2 * t34 / 8);
}
if (o2 !== undefined) {
c2.push(r2 - o2.neckDistance);
for (let t34 = 0;t34 <= 8; t34++)
c2.push(r2 - s2 + s2 * t34 / 8);
}
for (const t34 of c2) {
const e3 = Math.max(0, Math.min(r2, t34));
a2.some((t35) => Math.abs(t35.distanceFromStart - e3) <= _D) || a2.push({ distanceFromStart: e3 });
}
return a2.sort((t34, e3) => {
const n3 = t34.distanceFromStart - e3.distanceFromStart;
return Math.abs(n3) > _D ? n3 : (t34.originalPointIndex ?? 1 / 0) - (e3.originalPointIndex ?? 1 / 0);
}), a2.map((a3) => {
const { distanceFromStart: c3 } = a3, l2 = a3.originalPointIndex !== undefined ? { ...t33.route[a3.originalPointIndex] } : this.interpolateRoutePointAtDistance(t33.route, i2, c3);
return l2.traceThickness = this.getTaperWidthAtDistance({ distanceFromStart: c3, totalDistance: r2, startLimit: n2, endLimit: o2, taperDistance: s2, traceWidth: e2 }), l2;
});
}
createRouteWithWidth(t33, e2) {
return { connectionName: t33.connectionName, rootConnectionName: t33.rootConnectionName, traceThickness: e2, viaDiameter: t33.viaDiameter, route: this.createTerminalTaperedRoute(t33, e2), vias: [...t33.vias], jumpers: t33.jumpers };
}
finalizeCurrentTrace(t33) {
if (!this.currentTrace)
return;
const e2 = this.createRouteWithWidth(this.currentTrace, t33);
this.processedRoutes.push(e2), this.hdRouteSHI.removeRoute(e2.connectionName), this.hdRouteSHI.addRoute(e2), this.currentTrace = null, this.cursorPosition = null, this.hasInsufficientClearance = false;
}
visualize() {
const t33 = { lines: [], points: [], circles: [], rects: [], coordinateSystem: "cartesian", title: `Trace Width Solver (schedule: [${this.TRACE_WIDTH_SCHEDULE.map((t34) => t34.toFixed(2)).join(", ")}]mm, fallback: ${this.minTraceWidth.toFixed(2)}mm, margin: ${this.obstacleMargin.toFixed(2)}mm)` }, e2 = new Set(this.lastCollidingObstacles.map((t34) => t34.obstacleId)), n2 = new Set(this.lastCollidingRoutes.map((t34) => t34.connectionName));
for (const n3 of this.obstacles) {
const o2 = e2.has(n3.obstacleId), i2 = n3.__zLayers?.includes(0), r2 = n3.__zLayers?.includes(1);
let s2;
s2 = o2 ? "rgba(255, 0, 0, 0.6)" : i2 && r2 ? "rgba(128, 0, 128, 0.15)" : i2 ? "rgba(255, 0, 0, 0.15)" : r2 ? "rgba(0, 0, 255, 0.15)" : "rgba(128, 128, 128, 0.15)", t33.rects.push({ center: n3.center, width: n3.width, height: n3.height, fill: s2, stroke: o2 ? "red" : undefined, label: o2 ? `COLLIDING: ${n3.obstacleId ?? "obstacle"}` : `${n3.obstacleId ?? "obstacle"} (Z: ${n3.__zLayers?.join(", ")})` });
}
for (const e3 of this.processedRoutes) {
if (e3.route.length === 0)
continue;
const n3 = e3.traceThickness === this.nominalTraceWidth, o2 = e3.traceThickness === this.TRACE_WIDTH_SCHEDULE[1], i2 = n3 ? "green" : o2 ? "yellow" : "orange";
for (let n4 = 0;n4 < e3.route.length - 1; n4++) {
const o3 = e3.route[n4], r2 = e3.route[n4 + 1];
o3.insideJumperPad && r2.insideJumperPad || o3.z === r2.z && t33.lines.push({ points: [{ x: o3.x, y: o3.y }, { x: r2.x, y: r2.y }], strokeColor: i2, strokeWidth: o3.traceThickness ?? e3.traceThickness, label: `${e3.connectionName} (w=${(o3.traceThickness ?? e3.traceThickness).toFixed(2)})` });
}
for (const n4 of e3.vias)
t33.circles.push({ center: { x: n4.x, y: n4.y }, radius: e3.viaDiameter / 2, fill: "rgba(255, 0, 255, 0.5)", label: `${e3.connectionName} via` });
if (e3.jumpers && e3.jumpers.length > 0) {
const n4 = mk(e3.jumpers, { color: i2, label: e3.connectionName });
t33.rects.push(...n4.rects ?? []), t33.lines.push(...n4.lines ?? []);
}
}
if (this.currentTrace) {
for (let e3 = 0;e3 < this.currentTrace.route.length - 1; e3++) {
const n3 = this.currentTrace.route[e3], o2 = this.currentTrace.route[e3 + 1];
n3.insideJumperPad && o2.insideJumperPad || n3.z === o2.z && t33.lines.push({ points: [{ x: n3.x, y: n3.y }, { x: o2.x, y: o2.y }], strokeColor: "cyan", strokeWidth: this.currentTrace.traceThickness ?? this.minTraceWidth, label: `Processing: ${this.currentTrace.connectionName}` });
}
this.cursorPosition && (t33.circles.push({ center: { x: this.cursorPosition.x, y: this.cursorPosition.y }, radius: this.currentTargetWidth / 2, stroke: this.hasInsufficientClearance ? "red" : "green", fill: "none", label: `Testing width: ${this.currentTargetWidth.toFixed(2)}mm (clearance: ${this.lastClearance.toFixed(2)}mm)` }), t33.points.push({ x: this.cursorPosition.x, y: this.cursorPosition.y, color: "orange", label: "Cursor" }));
}
for (const e3 of this.unprocessedRoutes) {
if (e3.route.length === 0)
continue;
const o2 = n2.has(e3.connectionName);
for (let n3 = 0;n3 < e3.route.length - 1; n3++) {
const i2 = e3.route[n3], r2 = e3.route[n3 + 1];
i2.z === r2.z && t33.lines.push({ points: [{ x: i2.x, y: i2.y }, { x: r2.x, y: r2.y }], strokeColor: o2 ? "rgba(255, 0, 0, 0.8)" : "rgba(128, 128, 128, 0.3)", strokeWidth: e3.traceThickness ?? this.minTraceWidth, label: o2 ? `COLLIDING: ${e3.connectionName}` : e3.connectionName });
}
}
return t33;
}
getHdRoutesWithWidths() {
return this.hdRoutesWithWidths;
}
};
var AD = (t33, e2 = {}) => {
const n2 = Math.min(...t33.availableZ);
return { center: !e2.rectMargin || e2.zOffset ? { x: t33.center.x + n2 * t33.width * (e2.zOffset ?? 0.05), y: t33.center.y - n2 * t33.width * (e2.zOffset ?? 0.05) } : t33.center, width: e2.rectMargin ? t33.width - 2 * e2.rectMargin : Math.max(t33.width - 0.5, 0.8 * t33.width), height: e2.rectMargin ? t33.height - 2 * e2.rectMargin : Math.max(t33.height - 0.5, 0.8 * t33.height), fill: t33._containsObstacle ? "rgba(255,0,0,0.1)" : { "0,1": "rgba(0,0,0,0.1)", 0: "rgba(0,200,200, 0.1)", 1: "rgba(0,0,200, 0.1)" }[t33.availableZ.join(",")] ?? "rgba(0,200,200,0.1)", layer: `z${t33.availableZ.join(",")}`, label: [t33.capacityMeshNodeId, `availableZ: ${t33.availableZ.join(",")}`, "" + (t33._containsTarget ? "containsTarget" : ""), "" + (t33._containsObstacle ? "containsObstacle" : "")].filter(Boolean).join(`
`) };
};
io();
function xL(t33) {
const e2 = t33.width / 2, n2 = t33.height / 2, o2 = t33.center.x, i2 = t33.center.y, r2 = { x: o2 - e2, y: i2 + n2 }, s2 = { x: o2 + e2, y: i2 + n2 }, a2 = { x: o2 - e2, y: i2 - n2 }, c2 = { x: o2 + e2, y: i2 - n2 };
return [{ start: r2, end: s2 }, { start: s2, end: c2 }, { start: c2, end: a2 }, { start: a2, end: r2 }];
}
var XL = Object.create;
var WL = Object.defineProperty;
var VL = Object.getOwnPropertyDescriptor;
var HL = Object.getOwnPropertyNames;
var GL = Object.getPrototypeOf;
var UL = Object.prototype.hasOwnProperty;
var ZL = (t33, e2) => function() {
return e2 || (0, t33[HL(t33)[0]])((e2 = { exports: {} }).exports, e2), e2.exports;
};
var qL = (t33, e2, n2) => (n2 = t33 != null ? XL(GL(t33)) : {}, ((t34, e3, n3, o2) => {
if (e3 && typeof e3 == "object" || typeof e3 == "function")
for (let i2 of HL(e3))
UL.call(t34, i2) || i2 === n3 || WL(t34, i2, { get: () => e3[i2], enumerable: !(o2 = VL(e3, i2)) || o2.enumerable });
return t34;
})(t33 && t33.__esModule ? n2 : WL(n2, "default", { value: t33, enumerable: true }), t33));
var JL = ZL({ "node_modules/is-buffer/index.js"(t33, e2) {
function n2(t34) {
return !!t34.constructor && typeof t34.constructor.isBuffer == "function" && t34.constructor.isBuffer(t34);
}
e2.exports = function(t34) {
return t34 != null && (n2(t34) || function(t35) {
return typeof t35.readFloatLE == "function" && typeof t35.slice == "function" && n2(t35.slice(0, 0));
}(t34) || !!t34._isBuffer);
};
} });
var QL = ZL({ "node_modules/kind-of/index.js"(t33, e2) {
var n2 = JL(), o2 = Object.prototype.toString;
e2.exports = function(t34) {
if (t34 === undefined)
return "undefined";
if (t34 === null)
return "null";
if (t34 === true || t34 === false || t34 instanceof Boolean)
return "boolean";
if (typeof t34 == "string" || t34 instanceof String)
return "string";
if (typeof t34 == "number" || t34 instanceof Number)
return "number";
if (typeof t34 == "function" || t34 instanceof Function)
return "function";
if (Array.isArray !== undefined && Array.isArray(t34))
return "array";
if (t34 instanceof RegExp)
return "regexp";
if (t34 instanceof Date)
return "date";
var e3 = o2.call(t34);
return e3 === "[object RegExp]" ? "regexp" : e3 === "[object Date]" ? "date" : e3 === "[object Arguments]" ? "arguments" : e3 === "[object Error]" ? "error" : n2(t34) ? "buffer" : e3 === "[object Set]" ? "set" : e3 === "[object WeakSet]" ? "weakset" : e3 === "[object Map]" ? "map" : e3 === "[object WeakMap]" ? "weakmap" : e3 === "[object Symbol]" ? "symbol" : e3 === "[object Int8Array]" ? "int8array" : e3 === "[object Uint8Array]" ? "uint8array" : e3 === "[object Uint8ClampedArray]" ? "uint8clampedarray" : e3 === "[object Int16Array]" ? "int16array" : e3 === "[object Uint16Array]" ? "uint16array" : e3 === "[object Int32Array]" ? "int32array" : e3 === "[object Uint32Array]" ? "uint32array" : e3 === "[object Float32Array]" ? "float32array" : e3 === "[object Float64Array]" ? "float64array" : "object";
};
} });
var KL = ZL({ "node_modules/rename-keys/index.js"(t33, e2) {
(function() {
function t34(t35, e3) {
if (typeof e3 != "function")
return t35;
var n2 = {};
for (var o2 in t35)
Object.prototype.hasOwnProperty.call(t35, o2) && (n2[e3(o2, t35[o2]) || o2] = t35[o2]);
return n2;
}
e2 !== undefined && e2.exports ? e2.exports = t34 : typeof define == "function" && define.amd ? define([], function() {
return t34;
}) : window.rename = t34;
})();
} });
var tz = ZL({ "node_modules/deep-rename-keys/index.js"(t33, e2) {
var n2 = QL(), o2 = KL();
e2.exports = function t34(e3, i2) {
var r2 = n2(e3);
if (r2 !== "object" && r2 !== "array")
throw new Error("expected an object");
var s2 = [];
for (var a2 in r2 === "object" && (e3 = o2(e3, i2), s2 = {}), e3)
if (e3.hasOwnProperty(a2)) {
var c2 = e3[a2];
n2(c2) === "object" || n2(c2) === "array" ? s2[a2] = t34(c2, i2) : s2[a2] = c2;
}
return s2;
};
} });
var ez = ZL({ "node_modules/eventemitter3/index.js"(t33, e2) {
var n2 = Object.prototype.hasOwnProperty, o2 = "~";
function i2() {}
function r2(t34, e3, n3) {
this.fn = t34, this.context = e3, this.once = n3 || false;
}
function s2() {
this._events = new i2, this._eventsCount = 0;
}
Object.create && (i2.prototype = Object.create(null), new i2().__proto__ || (o2 = false)), s2.prototype.eventNames = function() {
var t34, e3, i3 = [];
if (this._eventsCount === 0)
return i3;
for (e3 in t34 = this._events)
n2.call(t34, e3) && i3.push(o2 ? e3.slice(1) : e3);
return Object.getOwnPropertySymbols ? i3.concat(Object.getOwnPropertySymbols(t34)) : i3;
}, s2.prototype.listeners = function(t34, e3) {
var n3 = o2 ? o2 + t34 : t34, i3 = this._events[n3];
if (e3)
return !!i3;
if (!i3)
return [];
if (i3.fn)
return [i3.fn];
for (var r3 = 0, s3 = i3.length, a2 = new Array(s3);r3 < s3; r3++)
a2[r3] = i3[r3].fn;
return a2;
}, s2.prototype.emit = function(t34, e3, n3, i3, r3, s3) {
var a2 = o2 ? o2 + t34 : t34;
if (!this._events[a2])
return false;
var c2, l2, h2 = this._events[a2], d2 = arguments.length;
if (h2.fn) {
switch (h2.once && this.removeListener(t34, h2.fn, undefined, true), d2) {
case 1:
return h2.fn.call(h2.context), true;
case 2:
return h2.fn.call(h2.context, e3), true;
case 3:
return h2.fn.call(h2.context, e3, n3), true;
case 4:
return h2.fn.call(h2.context, e3, n3, i3), true;
case 5:
return h2.fn.call(h2.context, e3, n3, i3, r3), true;
case 6:
return h2.fn.call(h2.context, e3, n3, i3, r3, s3), true;
}
for (l2 = 1, c2 = new Array(d2 - 1);l2 < d2; l2++)
c2[l2 - 1] = arguments[l2];
h2.fn.apply(h2.context, c2);
} else {
var u2, p2 = h2.length;
for (l2 = 0;l2 < p2; l2++)
switch (h2[l2].once && this.removeListener(t34, h2[l2].fn, undefined, true), d2) {
case 1:
h2[l2].fn.call(h2[l2].context);
break;
case 2:
h2[l2].fn.call(h2[l2].context, e3);
break;
case 3:
h2[l2].fn.call(h2[l2].context, e3, n3);
break;
case 4:
h2[l2].fn.call(h2[l2].context, e3, n3, i3);
break;
default:
if (!c2)
for (u2 = 1, c2 = new Array(d2 - 1);u2 < d2; u2++)
c2[u2 - 1] = arguments[u2];
h2[l2].fn.apply(h2[l2].context, c2);
}
}
return true;
}, s2.prototype.on = function(t34, e3, n3) {
var i3 = new r2(e3, n3 || this), s3 = o2 ? o2 + t34 : t34;
return this._events[s3] ? this._events[s3].fn ? this._events[s3] = [this._events[s3], i3] : this._events[s3].push(i3) : (this._events[s3] = i3, this._eventsCount++), this;
}, s2.prototype.once = function(t34, e3, n3) {
var i3 = new r2(e3, n3 || this, true), s3 = o2 ? o2 + t34 : t34;
return this._events[s3] ? this._events[s3].fn ? this._events[s3] = [this._events[s3], i3] : this._events[s3].push(i3) : (this._events[s3] = i3, this._eventsCount++), this;
}, s2.prototype.removeListener = function(t34, e3, n3, r3) {
var s3 = o2 ? o2 + t34 : t34;
if (!this._events[s3])
return this;
if (!e3)
return --this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3], this;
var a2 = this._events[s3];
if (a2.fn)
a2.fn !== e3 || r3 && !a2.once || n3 && a2.context !== n3 || (--this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3]);
else {
for (var c2 = 0, l2 = [], h2 = a2.length;c2 < h2; c2++)
(a2[c2].fn !== e3 || r3 && !a2[c2].once || n3 && a2[c2].context !== n3) && l2.push(a2[c2]);
l2.length ? this._events[s3] = l2.length === 1 ? l2[0] : l2 : --this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3];
}
return this;
}, s2.prototype.removeAllListeners = function(t34) {
var e3;
return t34 ? (e3 = o2 ? o2 + t34 : t34, this._events[e3] && (--this._eventsCount === 0 ? this._events = new i2 : delete this._events[e3])) : (this._events = new i2, this._eventsCount = 0), this;
}, s2.prototype.off = s2.prototype.removeListener, s2.prototype.addListener = s2.prototype.on, s2.prototype.setMaxListeners = function() {
return this;
}, s2.prefixed = o2, s2.EventEmitter = s2, e2 !== undefined && (e2.exports = s2);
} });
var nz = ZL({ "node_modules/xml-lexer/dist/lexer.js"(t33, e2) {
function n2(t34, e3, n3) {
return e3 in t34 ? Object.defineProperty(t34, e3, { value: n3, enumerable: true, configurable: true, writable: true }) : t34[e3] = n3, t34;
}
var o2 = ez(), i2 = function() {}, r2 = { data: "state-data", cdata: "state-cdata", tagBegin: "state-tag-begin", tagName: "state-tag-name", tagEnd: "state-tag-end", attributeNameStart: "state-attribute-name-start", attributeName: "state-attribute-name", attributeNameEnd: "state-attribute-name-end", attributeValueBegin: "state-attribute-value-begin", attributeValue: "state-attribute-value" }, s2 = { lt: "action-lt", gt: "action-gt", space: "action-space", equal: "action-equal", quote: "action-quote", slash: "action-slash", char: "action-char", error: "action-error" }, a2 = { text: "text", openTag: "open-tag", closeTag: "close-tag", attributeName: "attribute-name", attributeValue: "attribute-value" }, c2 = { " ": s2.space, "\t": s2.space, "\n": s2.space, "\r": s2.space, "<": s2.lt, ">": s2.gt, '"': s2.quote, "'": s2.quote, "=": s2.equal, "/": s2.slash };
e2.exports = { State: r2, Action: s2, Type: a2, create: function(t34) {
var e3, l2, h2, d2, u2, p2, m2, g2, f2, y2;
t34 = Object.assign({ debug: false }, t34);
var _2 = new o2, b2 = r2.data, x2 = "", v2 = "", I2 = "", S2 = "", C2 = "", P2 = "", M2 = function(e4, n3) {
if (v2[0] !== "?" && v2[0] !== "!") {
var o3 = { type: e4, value: n3 };
t34.debug && console.log("emit:", o3), _2.emit("data", o3);
}
};
_2.stateMachine = (n2(y2 = {}, r2.data, (n2(e3 = {}, s2.lt, function() {
x2.trim() && M2(a2.text, x2), v2 = "", C2 = false, b2 = r2.tagBegin;
}), n2(e3, s2.char, function(t35) {
x2 += t35;
}), e3)), n2(y2, r2.cdata, n2({}, s2.char, function(t35) {
(x2 += t35).substr(-3) === "]]>" && (M2(a2.text, x2.slice(0, -3)), x2 = "", b2 = r2.data);
})), n2(y2, r2.tagBegin, (n2(l2 = {}, s2.space, i2), n2(l2, s2.char, function(t35) {
v2 = t35, b2 = r2.tagName;
}), n2(l2, s2.slash, function() {
v2 = "", C2 = true;
}), l2)), n2(y2, r2.tagName, (n2(h2 = {}, s2.space, function() {
C2 ? b2 = r2.tagEnd : (b2 = r2.attributeNameStart, M2(a2.openTag, v2));
}), n2(h2, s2.gt, function() {
M2(C2 ? a2.closeTag : a2.openTag, v2), x2 = "", b2 = r2.data;
}), n2(h2, s2.slash, function() {
b2 = r2.tagEnd, M2(a2.openTag, v2);
}), n2(h2, s2.char, function(t35) {
(v2 += t35) === "![CDATA[" && (b2 = r2.cdata, x2 = "", v2 = "");
}), h2)), n2(y2, r2.tagEnd, (n2(d2 = {}, s2.gt, function() {
M2(a2.closeTag, v2), x2 = "", b2 = r2.data;
}), n2(d2, s2.char, i2), d2)), n2(y2, r2.attributeNameStart, (n2(u2 = {}, s2.char, function(t35) {
I2 = t35, b2 = r2.attributeName;
}), n2(u2, s2.gt, function() {
x2 = "", b2 = r2.data;
}), n2(u2, s2.space, i2), n2(u2, s2.slash, function() {
C2 = true, b2 = r2.tagEnd;
}), u2)), n2(y2, r2.attributeName, (n2(p2 = {}, s2.space, function() {
b2 = r2.attributeNameEnd;
}), n2(p2, s2.equal, function() {
M2(a2.attributeName, I2), b2 = r2.attributeValueBegin;
}), n2(p2, s2.gt, function() {
S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), x2 = "", b2 = r2.data;
}), n2(p2, s2.slash, function() {
C2 = true, S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), b2 = r2.tagEnd;
}), n2(p2, s2.char, function(t35) {
I2 += t35;
}), p2)), n2(y2, r2.attributeNameEnd, (n2(m2 = {}, s2.space, i2), n2(m2, s2.equal, function() {
M2(a2.attributeName, I2), b2 = r2.attributeValueBegin;
}), n2(m2, s2.gt, function() {
S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), x2 = "", b2 = r2.data;
}), n2(m2, s2.char, function(t35) {
S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), I2 = t35, b2 = r2.attributeName;
}), m2)), n2(y2, r2.attributeValueBegin, (n2(g2 = {}, s2.space, i2), n2(g2, s2.quote, function(t35) {
P2 = t35, S2 = "", b2 = r2.attributeValue;
}), n2(g2, s2.gt, function() {
M2(a2.attributeValue, S2 = ""), x2 = "", b2 = r2.data;
}), n2(g2, s2.char, function(t35) {
P2 = "", S2 = t35, b2 = r2.attributeValue;
}), g2)), n2(y2, r2.attributeValue, (n2(f2 = {}, s2.space, function(t35) {
P2 ? S2 += t35 : (M2(a2.attributeValue, S2), b2 = r2.attributeNameStart);
}), n2(f2, s2.quote, function(t35) {
P2 === t35 ? (M2(a2.attributeValue, S2), b2 = r2.attributeNameStart) : S2 += t35;
}), n2(f2, s2.gt, function(t35) {
P2 ? S2 += t35 : (M2(a2.attributeValue, S2), x2 = "", b2 = r2.data);
}), n2(f2, s2.slash, function(t35) {
P2 ? S2 += t35 : (M2(a2.attributeValue, S2), C2 = true, b2 = r2.tagEnd);
}), n2(f2, s2.char, function(t35) {
S2 += t35;
}), f2)), y2);
var N2 = function(e4) {
t34.debug && console.log(b2, e4);
var n3 = _2.stateMachine[b2], o3 = n3[function(t35) {
return c2[t35] || s2.char;
}(e4)] || n3[s2.error] || n3[s2.char];
o3(e4);
};
return _2.write = function(t35) {
for (var e4 = t35.length, n3 = 0;n3 < e4; n3++)
N2(t35[n3]);
}, _2;
} };
} });
var oz = ZL({ "node_modules/xml-reader/dist/reader.js"(t33, e2) {
var n2 = ez(), o2 = nz(), i2 = o2.Type, r2 = { element: "element", text: "text" }, s2 = function(t34) {
return Object.assign({ name: "", type: r2.element, value: "", parent: null, attributes: {}, children: [] }, t34);
}, a2 = function(t34) {
t34 = Object.assign({ stream: false, parentNodes: true, doneEvent: "done", tagPrefix: "tag:", emitTopLevelOnly: false, debug: false }, t34);
var e3 = undefined, a3 = undefined, c2 = undefined, l2 = undefined, h2 = new n2, d2 = function(n3) {
switch (n3.type) {
case i2.openTag:
if (c2 === null)
(c2 = a3).name = n3.value;
else {
var o3 = s2({ name: n3.value, parent: c2 });
c2.children.push(o3), c2 = o3;
}
break;
case i2.closeTag:
var d3 = c2.parent;
if (t34.parentNodes || (c2.parent = null), c2.name !== n3.value)
break;
t34.stream && d3 === a3 && (a3.children = [], c2.parent = null), t34.emitTopLevelOnly && d3 !== a3 || (h2.emit(t34.tagPrefix + c2.name, c2), h2.emit("tag", c2.name, c2)), c2 === a3 && (e3.removeAllListeners("data"), h2.emit(t34.doneEvent, c2), a3 = null), c2 = d3;
break;
case i2.text:
c2 && c2.children.push(s2({ type: r2.text, value: n3.value, parent: t34.parentNodes ? c2 : null }));
break;
case i2.attributeName:
l2 = n3.value, c2.attributes[l2] = "";
break;
case i2.attributeValue:
c2.attributes[l2] = n3.value;
}
};
return h2.reset = function() {
(e3 = o2.create({ debug: t34.debug })).on("data", d2), a3 = s2(), c2 = null, l2 = "", h2.parse = e3.write;
}, h2.reset(), h2;
};
e2.exports = { parseSync: function(t34, e3) {
e3 = Object.assign({}, e3, { stream: false, tagPrefix: ":" });
var n3 = a2(e3), o3 = undefined;
return n3.on("done", function(t35) {
o3 = t35;
}), n3.parse(t34), o3;
}, create: a2, NodeType: r2 };
} });
(qL(tz()), qL(oz()), class {
MAX_ITERATIONS = 1e5;
solved = false;
failed = false;
iterations = 0;
progress = 0;
error = null;
activeSubSolver;
failedSubSolvers;
timeToSolve;
stats = {};
_setupDone = false;
setup() {
this._setupDone || (this._setup(), this._setupDone = true);
}
_setup() {}
step() {
if (this._setupDone || this.setup(), !this.solved && !this.failed) {
this.iterations++;
try {
this._step();
} catch (t33) {
throw this.error = `${this.constructor.name} error: ${t33}`, this.failed = true, t33;
}
!this.solved && this.iterations >= this.MAX_ITERATIONS && this.tryFinalAcceptance(), !this.solved && this.iterations >= this.MAX_ITERATIONS && (this.error = `${this.constructor.name} ran out of iterations`, this.failed = true), "computeProgress" in this && (this.progress = this.computeProgress());
}
}
_step() {}
getConstructorParams() {
throw new Error("getConstructorParams not implemented");
}
getOutput() {
return null;
}
solve() {
const t33 = Date.now();
for (;!this.solved && !this.failed; )
this.step();
const e2 = Date.now();
this.timeToSolve = e2 - t33;
}
visualize() {
return { lines: [], points: [], rects: [], circles: [] };
}
tryFinalAcceptance() {}
preview() {
return { lines: [], points: [], rects: [], circles: [] };
}
});
var Iz = Object.create;
var Sz = Object.defineProperty;
var Cz = Object.getOwnPropertyDescriptor;
var Pz = Object.getOwnPropertyNames;
var Mz = Object.getPrototypeOf;
var Nz = Object.prototype.hasOwnProperty;
var wz = (t33, e2) => function() {
return e2 || (0, t33[Pz(t33)[0]])((e2 = { exports: {} }).exports, e2), e2.exports;
};
var Tz = wz({ "node_modules/binary-search-bounds/search-bounds.js"(t33, e2) {
function n2(t34, e3, n3, o3, i3) {
for (var r3 = i3 + 1;o3 <= i3; ) {
var s3 = o3 + i3 >>> 1, a3 = t34[s3];
(n3 !== undefined ? n3(a3, e3) : a3 - e3) >= 0 ? (r3 = s3, i3 = s3 - 1) : o3 = s3 + 1;
}
return r3;
}
function o2(t34, e3, n3, o3, i3) {
for (var r3 = i3 + 1;o3 <= i3; ) {
var s3 = o3 + i3 >>> 1, a3 = t34[s3];
(n3 !== undefined ? n3(a3, e3) : a3 - e3) > 0 ? (r3 = s3, i3 = s3 - 1) : o3 = s3 + 1;
}
return r3;
}
function i2(t34, e3, n3, o3, i3) {
for (var r3 = o3 - 1;o3 <= i3; ) {
var s3 = o3 + i3 >>> 1, a3 = t34[s3];
(n3 !== undefined ? n3(a3, e3) : a3 - e3) < 0 ? (r3 = s3, o3 = s3 + 1) : i3 = s3 - 1;
}
return r3;
}
function r2(t34, e3, n3, o3, i3) {
for (var r3 = o3 - 1;o3 <= i3; ) {
var s3 = o3 + i3 >>> 1, a3 = t34[s3];
(n3 !== undefined ? n3(a3, e3) : a3 - e3) <= 0 ? (r3 = s3, o3 = s3 + 1) : i3 = s3 - 1;
}
return r3;
}
function s2(t34, e3, n3, o3, i3) {
for (;o3 <= i3; ) {
var r3 = o3 + i3 >>> 1, s3 = t34[r3], a3 = n3 !== undefined ? n3(s3, e3) : s3 - e3;
if (a3 === 0)
return r3;
a3 <= 0 ? o3 = r3 + 1 : i3 = r3 - 1;
}
return -1;
}
function a2(t34, e3, n3, o3, i3, r3) {
return typeof n3 == "function" ? r3(t34, e3, n3, o3 === undefined ? 0 : 0 | o3, i3 === undefined ? t34.length - 1 : 0 | i3) : r3(t34, e3, undefined, n3 === undefined ? 0 : 0 | n3, o3 === undefined ? t34.length - 1 : 0 | o3);
}
e2.exports = { ge: function(t34, e3, o3, i3, r3) {
return a2(t34, e3, o3, i3, r3, n2);
}, gt: function(t34, e3, n3, i3, r3) {
return a2(t34, e3, n3, i3, r3, o2);
}, lt: function(t34, e3, n3, o3, r3) {
return a2(t34, e3, n3, o3, r3, i2);
}, le: function(t34, e3, n3, o3, i3) {
return a2(t34, e3, n3, o3, i3, r2);
}, eq: function(t34, e3, n3, o3, i3) {
return a2(t34, e3, n3, o3, i3, s2);
} };
} });
var Rz = wz({ "node_modules/two-product/two-product.js"(t33, e2) {
e2.exports = function(t34, e3, o2) {
var i2 = t34 * e3, r2 = n2 * t34, s2 = r2 - (r2 - t34), a2 = t34 - s2, c2 = n2 * e3, l2 = c2 - (c2 - e3), h2 = e3 - l2, d2 = a2 * h2 - (i2 - s2 * l2 - a2 * l2 - s2 * h2);
if (o2)
return o2[0] = d2, o2[1] = i2, o2;
return [d2, i2];
};
var n2 = +(Math.pow(2, 27) + 1);
} });
var Ez = wz({ "node_modules/robust-sum/robust-sum.js"(t33, e2) {
e2.exports = function(t34, e3) {
var n2 = 0 | t34.length, o2 = 0 | e3.length;
if (n2 === 1 && o2 === 1)
return function(t35, e4) {
var n3 = t35 + e4, o3 = n3 - t35, i3 = n3 - o3, r3 = e4 - o3, s3 = t35 - i3, a3 = s3 + r3;
if (a3)
return [a3, n3];
return [n3];
}(t34[0], e3[0]);
var i2, r2, s2 = new Array(n2 + o2), a2 = 0, c2 = 0, l2 = 0, h2 = Math.abs, d2 = t34[c2], u2 = h2(d2), p2 = e3[l2], m2 = h2(p2);
u2 < m2 ? (r2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t34[c2]))) : (r2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = e3[l2])));
c2 < n2 && u2 < m2 || l2 >= o2 ? (i2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t34[c2]))) : (i2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = e3[l2])));
var g2, f2, y2 = i2 + r2, _2 = y2 - i2, b2 = r2 - _2, x2 = b2, v2 = y2;
for (;c2 < n2 && l2 < o2; )
u2 < m2 ? (i2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t34[c2]))) : (i2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = e3[l2]))), (b2 = (r2 = x2) - (_2 = (y2 = i2 + r2) - i2)) && (s2[a2++] = b2), x2 = v2 - ((g2 = v2 + y2) - (f2 = g2 - v2)) + (y2 - f2), v2 = g2;
for (;c2 < n2; )
(b2 = (r2 = x2) - (_2 = (y2 = (i2 = d2) + r2) - i2)) && (s2[a2++] = b2), x2 = v2 - ((g2 = v2 + y2) - (f2 = g2 - v2)) + (y2 - f2), v2 = g2, (c2 += 1) < n2 && (d2 = t34[c2]);
for (;l2 < o2; )
(b2 = (r2 = x2) - (_2 = (y2 = (i2 = p2) + r2) - i2)) && (s2[a2++] = b2), x2 = v2 - ((g2 = v2 + y2) - (f2 = g2 - v2)) + (y2 - f2), v2 = g2, (l2 += 1) < o2 && (p2 = e3[l2]);
x2 && (s2[a2++] = x2);
v2 && (s2[a2++] = v2);
a2 || (s2[a2++] = 0);
return s2.length = a2, s2;
};
} });
var Az = wz({ "node_modules/two-sum/two-sum.js"(t33, e2) {
e2.exports = function(t34, e3, n2) {
var o2 = t34 + e3, i2 = o2 - t34, r2 = e3 - i2, s2 = t34 - (o2 - i2);
if (n2)
return n2[0] = s2 + r2, n2[1] = o2, n2;
return [s2 + r2, o2];
};
} });
var Oz = wz({ "node_modules/robust-scale/robust-scale.js"(t33, e2) {
var n2 = Rz(), o2 = Az();
e2.exports = function(t34, e3) {
var i2 = t34.length;
if (i2 === 1) {
var r2 = n2(t34[0], e3);
return r2[0] ? r2 : [r2[1]];
}
var s2 = new Array(2 * i2), a2 = [0.1, 0.1], c2 = [0.1, 0.1], l2 = 0;
n2(t34[0], e3, a2), a2[0] && (s2[l2++] = a2[0]);
for (var h2 = 1;h2 < i2; ++h2) {
n2(t34[h2], e3, c2);
var d2 = a2[1];
o2(d2, c2[0], a2), a2[0] && (s2[l2++] = a2[0]);
var u2 = c2[1], p2 = a2[1], m2 = u2 + p2, g2 = p2 - (m2 - u2);
a2[1] = m2, g2 && (s2[l2++] = g2);
}
a2[1] && (s2[l2++] = a2[1]);
l2 === 0 && (s2[l2++] = 0);
return s2.length = l2, s2;
};
} });
var kz = wz({ "node_modules/robust-subtract/robust-diff.js"(t33, e2) {
e2.exports = function(t34, e3) {
var n2 = 0 | t34.length, o2 = 0 | e3.length;
if (n2 === 1 && o2 === 1)
return function(t35, e4) {
var n3 = t35 + e4, o3 = n3 - t35, i3 = n3 - o3, r3 = e4 - o3, s3 = t35 - i3, a3 = s3 + r3;
if (a3)
return [a3, n3];
return [n3];
}(t34[0], -e3[0]);
var i2, r2, s2 = new Array(n2 + o2), a2 = 0, c2 = 0, l2 = 0, h2 = Math.abs, d2 = t34[c2], u2 = h2(d2), p2 = -e3[l2], m2 = h2(p2);
u2 < m2 ? (r2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t34[c2]))) : (r2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = -e3[l2])));
c2 < n2 && u2 < m2 || l2 >= o2 ? (i2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t34[c2]))) : (i2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = -e3[l2])));
var g2, f2, y2 = i2 + r2, _2 = y2 - i2, b2 = r2 - _2, x2 = b2, v2 = y2;
for (;c2 < n2 && l2 < o2; )
u2 < m2 ? (i2 = d2, (c2 += 1) < n2 && (u2 = h2(d2 = t34[c2]))) : (i2 = p2, (l2 += 1) < o2 && (m2 = h2(p2 = -e3[l2]))), (b2 = (r2 = x2) - (_2 = (y2 = i2 + r2) - i2)) && (s2[a2++] = b2), x2 = v2 - ((g2 = v2 + y2) - (f2 = g2 - v2)) + (y2 - f2), v2 = g2;
for (;c2 < n2; )
(b2 = (r2 = x2) - (_2 = (y2 = (i2 = d2) + r2) - i2)) && (s2[a2++] = b2), x2 = v2 - ((g2 = v2 + y2) - (f2 = g2 - v2)) + (y2 - f2), v2 = g2, (c2 += 1) < n2 && (d2 = t34[c2]);
for (;l2 < o2; )
(b2 = (r2 = x2) - (_2 = (y2 = (i2 = p2) + r2) - i2)) && (s2[a2++] = b2), x2 = v2 - ((g2 = v2 + y2) - (f2 = g2 - v2)) + (y2 - f2), v2 = g2, (l2 += 1) < o2 && (p2 = -e3[l2]);
x2 && (s2[a2++] = x2);
v2 && (s2[a2++] = v2);
a2 || (s2[a2++] = 0);
return s2.length = a2, s2;
};
} });
var Dz = wz({ "node_modules/robust-orientation/orientation.js"(t33, e2) {
var n2 = Rz(), o2 = Ez(), i2 = Oz(), r2 = kz();
function s2(t34, e3, n3, o3) {
return function(n4, i3, r3) {
var s3 = t34(t34(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), t34(e3(n4[1], i3[0]), e3(-i3[1], n4[0]))), a3 = t34(e3(n4[1], r3[0]), e3(-r3[1], n4[0])), c3 = o3(s3, a3);
return c3[c3.length - 1];
};
}
function a2(t34, e3, n3, o3) {
return function(i3, r3, s3, a3) {
var c3 = t34(t34(n3(t34(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), r3[2]), t34(n3(t34(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), -s3[2]), n3(t34(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), a3[2]))), t34(n3(t34(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), i3[2]), t34(n3(t34(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -r3[2]), n3(t34(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), a3[2])))), l3 = t34(t34(n3(t34(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), i3[2]), t34(n3(t34(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -s3[2]), n3(t34(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), a3[2]))), t34(n3(t34(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), i3[2]), t34(n3(t34(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), -r3[2]), n3(t34(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), s3[2])))), h3 = o3(c3, l3);
return h3[h3.length - 1];
};
}
function c2(t34, e3, n3, o3) {
return function(i3, r3, s3, a3, c3) {
var l3 = t34(t34(t34(n3(t34(n3(t34(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), s3[2]), t34(n3(t34(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), -a3[2]), n3(t34(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), c3[2]))), r3[3]), t34(n3(t34(n3(t34(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), r3[2]), t34(n3(t34(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), -a3[2]), n3(t34(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), c3[2]))), -s3[3]), n3(t34(n3(t34(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), r3[2]), t34(n3(t34(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), -s3[2]), n3(t34(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), c3[2]))), a3[3]))), t34(n3(t34(n3(t34(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), r3[2]), t34(n3(t34(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), -s3[2]), n3(t34(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), a3[2]))), -c3[3]), t34(n3(t34(n3(t34(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), r3[2]), t34(n3(t34(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), -a3[2]), n3(t34(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), c3[2]))), i3[3]), n3(t34(n3(t34(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), i3[2]), t34(n3(t34(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -a3[2]), n3(t34(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), c3[2]))), -r3[3])))), t34(t34(n3(t34(n3(t34(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), i3[2]), t34(n3(t34(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -r3[2]), n3(t34(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), c3[2]))), a3[3]), t34(n3(t34(n3(t34(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), i3[2]), t34(n3(t34(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -r3[2]), n3(t34(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), a3[2]))), -c3[3]), n3(t34(n3(t34(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), r3[2]), t34(n3(t34(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), -s3[2]), n3(t34(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), a3[2]))), i3[3]))), t34(n3(t34(n3(t34(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), i3[2]), t34(n3(t34(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -s3[2]), n3(t34(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), a3[2]))), -r3[3]), t34(n3(t34(n3(t34(e3(r3[1], a3[0]), e3(-a3[1], r3[0])), i3[2]), t34(n3(t34(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -r3[2]), n3(t34(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), a3[2]))), s3[3]), n3(t34(n3(t34(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), i3[2]), t34(n3(t34(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), -r3[2]), n3(t34(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), s3[2]))), -a3[3]))))), h3 = t34(t34(t34(n3(t34(n3(t34(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), s3[2]), t34(n3(t34(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), -a3[2]), n3(t34(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), c3[2]))), i3[3]), n3(t34(n3(t34(e3(a3[1], c3[0]), e3(-c3[1], a3[0])), i3[2]), t34(n3(t34(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -a3[2]), n3(t34(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), c3[2]))), -s3[3])), t34(n3(t34(n3(t34(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), i3[2]), t34(n3(t34(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -s3[2]), n3(t34(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), c3[2]))), a3[3]), n3(t34(n3(t34(e3(s3[1], a3[0]), e3(-a3[1], s3[0])), i3[2]), t34(n3(t34(e3(i3[1], a3[0]), e3(-a3[1], i3[0])), -s3[2]), n3(t34(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), a3[2]))), -c3[3]))), t34(t34(n3(t34(n3(t34(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), r3[2]), t34(n3(t34(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), -s3[2]), n3(t34(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), c3[2]))), i3[3]), n3(t34(n3(t34(e3(s3[1], c3[0]), e3(-c3[1], s3[0])), i3[2]), t34(n3(t34(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -s3[2]), n3(t34(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), c3[2]))), -r3[3])), t34(n3(t34(n3(t34(e3(r3[1], c3[0]), e3(-c3[1], r3[0])), i3[2]), t34(n3(t34(e3(i3[1], c3[0]), e3(-c3[1], i3[0])), -r3[2]), n3(t34(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), c3[2]))), s3[3]), n3(t34(n3(t34(e3(r3[1], s3[0]), e3(-s3[1], r3[0])), i3[2]), t34(n3(t34(e3(i3[1], s3[0]), e3(-s3[1], i3[0])), -r3[2]), n3(t34(e3(i3[1], r3[0]), e3(-r3[1], i3[0])), s3[2]))), -c3[3])))), d3 = o3(l3, h3);
return d3[d3.length - 1];
};
}
function l2(t34) {
return (t34 === 3 ? s2 : t34 === 4 ? a2 : c2)(o2, n2, i2, r2);
}
var h2 = l2(3), d2 = l2(4), u2 = [function() {
return 0;
}, function() {
return 0;
}, function(t34, e3) {
return e3[0] - t34[0];
}, function(t34, e3, n3) {
var o3, i3 = (t34[1] - n3[1]) * (e3[0] - n3[0]), r3 = (t34[0] - n3[0]) * (e3[1] - n3[1]), s3 = i3 - r3;
if (i3 > 0) {
if (r3 <= 0)
return s3;
o3 = i3 + r3;
} else {
if (!(i3 < 0))
return s3;
if (r3 >= 0)
return s3;
o3 = -(i3 + r3);
}
var a3 = 0.00000000000000033306690738754716 * o3;
return s3 >= a3 || s3 <= -a3 ? s3 : h2(t34, e3, n3);
}, function(t34, e3, n3, o3) {
var i3 = t34[0] - o3[0], r3 = e3[0] - o3[0], s3 = n3[0] - o3[0], a3 = t34[1] - o3[1], c3 = e3[1] - o3[1], l3 = n3[1] - o3[1], h3 = t34[2] - o3[2], u3 = e3[2] - o3[2], p3 = n3[2] - o3[2], m3 = r3 * l3, g2 = s3 * c3, f2 = s3 * a3, y2 = i3 * l3, _2 = i3 * c3, b2 = r3 * a3, x2 = h3 * (m3 - g2) + u3 * (f2 - y2) + p3 * (_2 - b2), v2 = 0.0000000000000007771561172376103 * ((Math.abs(m3) + Math.abs(g2)) * Math.abs(h3) + (Math.abs(f2) + Math.abs(y2)) * Math.abs(u3) + (Math.abs(_2) + Math.abs(b2)) * Math.abs(p3));
return x2 > v2 || -x2 > v2 ? x2 : d2(t34, e3, n3, o3);
}];
function p2(t34) {
var e3 = u2[t34.length];
return e3 || (e3 = u2[t34.length] = l2(t34.length)), e3.apply(undefined, t34);
}
function m2(t34, e3, n3, o3, i3, r3, s3) {
return function(e4, n4, a3, c3, l3) {
switch (arguments.length) {
case 0:
case 1:
return 0;
case 2:
return o3(e4, n4);
case 3:
return i3(e4, n4, a3);
case 4:
return r3(e4, n4, a3, c3);
case 5:
return s3(e4, n4, a3, c3, l3);
}
for (var h3 = new Array(arguments.length), d3 = 0;d3 < arguments.length; ++d3)
h3[d3] = arguments[d3];
return t34(h3);
};
}
(function() {
for (;u2.length <= 5; )
u2.push(l2(u2.length));
e2.exports = m2.apply(undefined, [p2].concat(u2));
for (var t34 = 0;t34 <= 5; ++t34)
e2.exports[t34] = u2[t34];
})();
} });
var Lz = wz({ "node_modules/cdt2d/lib/monotone.js"(t33, e2) {
var n2 = Tz(), o2 = Dz()[3];
function i2(t34, e3, n3, o3, i3) {
this.a = t34, this.b = e3, this.idx = n3, this.lowerIds = o3, this.upperIds = i3;
}
function r2(t34, e3, n3, o3) {
this.a = t34, this.b = e3, this.type = n3, this.idx = o3;
}
function s2(t34, e3) {
var n3 = t34.a[0] - e3.a[0] || t34.a[1] - e3.a[1] || t34.type - e3.type;
return n3 || (t34.type !== 0 && (n3 = o2(t34.a, t34.b, e3.b)) ? n3 : t34.idx - e3.idx);
}
function a2(t34, e3) {
return o2(t34.a, t34.b, e3);
}
function c2(t34, e3, i3, r3, s3) {
for (var c3 = n2.lt(e3, r3, a2), l3 = n2.gt(e3, r3, a2), h3 = c3;h3 < l3; ++h3) {
for (var d3 = e3[h3], u2 = d3.lowerIds, p2 = u2.length;p2 > 1 && o2(i3[u2[p2 - 2]], i3[u2[p2 - 1]], r3) > 0; )
t34.push([u2[p2 - 1], u2[p2 - 2], s3]), p2 -= 1;
u2.length = p2, u2.push(s3);
var m2 = d3.upperIds;
for (p2 = m2.length;p2 > 1 && o2(i3[m2[p2 - 2]], i3[m2[p2 - 1]], r3) < 0; )
t34.push([m2[p2 - 2], m2[p2 - 1], s3]), p2 -= 1;
m2.length = p2, m2.push(s3);
}
}
function l2(t34, e3) {
var n3;
return (n3 = t34.a[0] < e3.a[0] ? o2(t34.a, t34.b, e3.a) : o2(e3.b, e3.a, t34.a)) ? n3 : (n3 = e3.b[0] < t34.b[0] ? o2(t34.a, t34.b, e3.b) : o2(e3.b, e3.a, t34.b)) || t34.idx - e3.idx;
}
function h2(t34, e3, o3) {
var r3 = n2.le(t34, o3, l2), s3 = t34[r3], a3 = s3.upperIds, c3 = a3[a3.length - 1];
s3.upperIds = [c3], t34.splice(r3 + 1, 0, new i2(o3.a, o3.b, o3.idx, [c3], a3));
}
function d2(t34, e3, o3) {
var i3 = o3.a;
o3.a = o3.b, o3.b = i3;
var r3 = n2.eq(t34, o3, l2), s3 = t34[r3];
t34[r3 - 1].upperIds = s3.upperIds, t34.splice(r3, 1);
}
e2.exports = function(t34, e3) {
for (var n3 = t34.length, o3 = e3.length, a3 = [], l3 = 0;l3 < n3; ++l3)
a3.push(new r2(t34[l3], null, 0, l3));
for (l3 = 0;l3 < o3; ++l3) {
var u2 = e3[l3], p2 = t34[u2[0]], m2 = t34[u2[1]];
p2[0] < m2[0] ? a3.push(new r2(p2, m2, 2, l3), new r2(m2, p2, 1, l3)) : p2[0] > m2[0] && a3.push(new r2(m2, p2, 2, l3), new r2(p2, m2, 1, l3));
}
a3.sort(s2);
for (var g2 = a3[0].a[0] - (1 + Math.abs(a3[0].a[0])) * Math.pow(2, -52), f2 = [new i2([g2, 1], [g2, 0], -1, [], [])], y2 = [], _2 = (l3 = 0, a3.length);l3 < _2; ++l3) {
var b2 = a3[l3], x2 = b2.type;
x2 === 0 ? c2(y2, f2, t34, b2.a, b2.idx) : x2 === 2 ? h2(f2, t34, b2) : d2(f2, t34, b2);
}
return y2;
};
} });
var zz = wz({ "node_modules/cdt2d/lib/triangulation.js"(t33, e2) {
var n2 = Tz();
function o2(t34, e3) {
this.stars = t34, this.edges = e3;
}
e2.exports = function(t34, e3) {
for (var n3 = new Array(t34), i3 = 0;i3 < t34; ++i3)
n3[i3] = [];
return new o2(n3, e3);
};
var i2 = o2.prototype;
function r2(t34, e3, n3) {
for (var o3 = 1, i3 = t34.length;o3 < i3; o3 += 2)
if (t34[o3 - 1] === e3 && t34[o3] === n3)
return t34[o3 - 1] = t34[i3 - 2], t34[o3] = t34[i3 - 1], void (t34.length = i3 - 2);
}
i2.isConstraint = function() {
var t34 = [0, 0];
function e3(t35, e4) {
return t35[0] - e4[0] || t35[1] - e4[1];
}
return function(o3, i3) {
return t34[0] = Math.min(o3, i3), t34[1] = Math.max(o3, i3), n2.eq(this.edges, t34, e3) >= 0;
};
}(), i2.removeTriangle = function(t34, e3, n3) {
var o3 = this.stars;
r2(o3[t34], e3, n3), r2(o3[e3], n3, t34), r2(o3[n3], t34, e3);
}, i2.addTriangle = function(t34, e3, n3) {
var o3 = this.stars;
o3[t34].push(e3, n3), o3[e3].push(n3, t34), o3[n3].push(t34, e3);
}, i2.opposite = function(t34, e3) {
for (var n3 = this.stars[e3], o3 = 1, i3 = n3.length;o3 < i3; o3 += 2)
if (n3[o3] === t34)
return n3[o3 - 1];
return -1;
}, i2.flip = function(t34, e3) {
var n3 = this.opposite(t34, e3), o3 = this.opposite(e3, t34);
this.removeTriangle(t34, e3, n3), this.removeTriangle(e3, t34, o3), this.addTriangle(t34, o3, n3), this.addTriangle(e3, n3, o3);
}, i2.edges = function() {
for (var t34 = this.stars, e3 = [], n3 = 0, o3 = t34.length;n3 < o3; ++n3)
for (var i3 = t34[n3], r3 = 0, s2 = i3.length;r3 < s2; r3 += 2)
e3.push([i3[r3], i3[r3 + 1]]);
return e3;
}, i2.cells = function() {
for (var t34 = this.stars, e3 = [], n3 = 0, o3 = t34.length;n3 < o3; ++n3)
for (var i3 = t34[n3], r3 = 0, s2 = i3.length;r3 < s2; r3 += 2) {
var a2 = i3[r3], c2 = i3[r3 + 1];
n3 < Math.min(a2, c2) && e3.push([n3, a2, c2]);
}
return e3;
};
} });
var Bz = wz({ "node_modules/robust-in-sphere/in-sphere.js"(t33, e2) {
var n2 = Rz(), o2 = Ez(), i2 = kz(), r2 = Oz();
function s2(t34) {
return (t34 === 3 ? a2 : t34 === 4 ? c2 : t34 === 5 ? l2 : h2)(o2, i2, n2, r2);
}
function a2(t34, e3, n3, o3) {
return function(i3, r3, s3) {
var a3 = n3(i3[0], i3[0]), c3 = o3(a3, r3[0]), l3 = o3(a3, s3[0]), h3 = n3(r3[0], r3[0]), d3 = o3(h3, i3[0]), u3 = o3(h3, s3[0]), p3 = n3(s3[0], s3[0]), m2 = o3(p3, i3[0]), g2 = o3(p3, r3[0]), f2 = t34(e3(g2, u3), e3(d3, c3)), y2 = e3(m2, l3), _2 = e3(f2, y2);
return _2[_2.length - 1];
};
}
function c2(t34, e3, n3, o3) {
return function(i3, r3, s3, a3) {
var c3 = t34(n3(i3[0], i3[0]), n3(i3[1], i3[1])), l3 = o3(c3, r3[0]), h3 = o3(c3, s3[0]), d3 = o3(c3, a3[0]), u3 = t34(n3(r3[0], r3[0]), n3(r3[1], r3[1])), p3 = o3(u3, i3[0]), m2 = o3(u3, s3[0]), g2 = o3(u3, a3[0]), f2 = t34(n3(s3[0], s3[0]), n3(s3[1], s3[1])), y2 = o3(f2, i3[0]), _2 = o3(f2, r3[0]), b2 = o3(f2, a3[0]), x2 = t34(n3(a3[0], a3[0]), n3(a3[1], a3[1])), v2 = o3(x2, i3[0]), I2 = o3(x2, r3[0]), S2 = o3(x2, s3[0]), C2 = t34(t34(o3(e3(S2, b2), r3[1]), t34(o3(e3(I2, g2), -s3[1]), o3(e3(_2, m2), a3[1]))), t34(o3(e3(I2, g2), i3[1]), t34(o3(e3(v2, d3), -r3[1]), o3(e3(p3, l3), a3[1])))), P2 = t34(t34(o3(e3(S2, b2), i3[1]), t34(o3(e3(v2, d3), -s3[1]), o3(e3(y2, h3), a3[1]))), t34(o3(e3(_2, m2), i3[1]), t34(o3(e3(y2, h3), -r3[1]), o3(e3(p3, l3), s3[1])))), M2 = e3(C2, P2);
return M2[M2.length - 1];
};
}
function l2(t34, e3, n3, o3) {
return function(i3, r3, s3, a3, c3) {
var l3 = t34(n3(i3[0], i3[0]), t34(n3(i3[1], i3[1]), n3(i3[2], i3[2]))), h3 = o3(l3, r3[0]), d3 = o3(l3, s3[0]), u3 = o3(l3, a3[0]), p3 = o3(l3, c3[0]), m2 = t34(n3(r3[0], r3[0]), t34(n3(r3[1], r3[1]), n3(r3[2], r3[2]))), g2 = o3(m2, i3[0]), f2 = o3(m2, s3[0]), y2 = o3(m2, a3[0]), _2 = o3(m2, c3[0]), b2 = t34(n3(s3[0], s3[0]), t34(n3(s3[1], s3[1]), n3(s3[2], s3[2]))), x2 = o3(b2, i3[0]), v2 = o3(b2, r3[0]), I2 = o3(b2, a3[0]), S2 = o3(b2, c3[0]), C2 = t34(n3(a3[0], a3[0]), t34(n3(a3[1], a3[1]), n3(a3[2], a3[2]))), P2 = o3(C2, i3[0]), M2 = o3(C2, r3[0]), N2 = o3(C2, s3[0]), w2 = o3(C2, c3[0]), T2 = t34(n3(c3[0], c3[0]), t34(n3(c3[1], c3[1]), n3(c3[2], c3[2]))), R2 = o3(T2, i3[0]), E2 = o3(T2, r3[0]), A2 = o3(T2, s3[0]), O2 = o3(T2, a3[0]), k2 = t34(t34(t34(o3(t34(o3(e3(O2, w2), s3[1]), t34(o3(e3(A2, S2), -a3[1]), o3(e3(N2, I2), c3[1]))), r3[2]), t34(o3(t34(o3(e3(O2, w2), r3[1]), t34(o3(e3(E2, _2), -a3[1]), o3(e3(M2, y2), c3[1]))), -s3[2]), o3(t34(o3(e3(A2, S2), r3[1]), t34(o3(e3(E2, _2), -s3[1]), o3(e3(v2, f2), c3[1]))), a3[2]))), t34(o3(t34(o3(e3(N2, I2), r3[1]), t34(o3(e3(M2, y2), -s3[1]), o3(e3(v2, f2), a3[1]))), -c3[2]), t34(o3(t34(o3(e3(O2, w2), r3[1]), t34(o3(e3(E2, _2), -a3[1]), o3(e3(M2, y2), c3[1]))), i3[2]), o3(t34(o3(e3(O2, w2), i3[1]), t34(o3(e3(R2, p3), -a3[1]), o3(e3(P2, u3), c3[1]))), -r3[2])))), t34(t34(o3(t34(o3(e3(E2, _2), i3[1]), t34(o3(e3(R2, p3), -r3[1]), o3(e3(g2, h3), c3[1]))), a3[2]), t34(o3(t34(o3(e3(M2, y2), i3[1]), t34(o3(e3(P2, u3), -r3[1]), o3(e3(g2, h3), a3[1]))), -c3[2]), o3(t34(o3(e3(N2, I2), r3[1]), t34(o3(e3(M2, y2), -s3[1]), o3(e3(v2, f2), a3[1]))), i3[2]))), t34(o3(t34(o3(e3(N2, I2), i3[1]), t34(o3(e3(P2, u3), -s3[1]), o3(e3(x2, d3), a3[1]))), -r3[2]), t34(o3(t34(o3(e3(M2, y2), i3[1]), t34(o3(e3(P2, u3), -r3[1]), o3(e3(g2, h3), a3[1]))), s3[2]), o3(t34(o3(e3(v2, f2), i3[1]), t34(o3(e3(x2, d3), -r3[1]), o3(e3(g2, h3), s3[1]))), -a3[2]))))), D2 = t34(t34(t34(o3(t34(o3(e3(O2, w2), s3[1]), t34(o3(e3(A2, S2), -a3[1]), o3(e3(N2, I2), c3[1]))), i3[2]), o3(t34(o3(e3(O2, w2), i3[1]), t34(o3(e3(R2, p3), -a3[1]), o3(e3(P2, u3), c3[1]))), -s3[2])), t34(o3(t34(o3(e3(A2, S2), i3[1]), t34(o3(e3(R2, p3), -s3[1]), o3(e3(x2, d3), c3[1]))), a3[2]), o3(t34(o3(e3(N2, I2), i3[1]), t34(o3(e3(P2, u3), -s3[1]), o3(e3(x2, d3), a3[1]))), -c3[2]))), t34(t34(o3(t34(o3(e3(A2, S2), r3[1]), t34(o3(e3(E2, _2), -s3[1]), o3(e3(v2, f2), c3[1]))), i3[2]), o3(t34(o3(e3(A2, S2), i3[1]), t34(o3(e3(R2, p3), -s3[1]), o3(e3(x2, d3), c3[1]))), -r3[2])), t34(o3(t34(o3(e3(E2, _2), i3[1]), t34(o3(e3(R2, p3), -r3[1]), o3(e3(g2, h3), c3[1]))), s3[2]), o3(t34(o3(e3(v2, f2), i3[1]), t34(o3(e3(x2, d3), -r3[1]), o3(e3(g2, h3), s3[1]))), -c3[2])))), L2 = e3(k2, D2);
return L2[L2.length - 1];
};
}
function h2(t34, e3, n3, o3) {
return function(i3, r3, s3, a3, c3, l3) {
var h3 = t34(t34(n3(i3[0], i3[0]), n3(i3[1], i3[1])), t34(n3(i3[2], i3[2]), n3(i3[3], i3[3]))), d3 = o3(h3, r3[0]), u3 = o3(h3, s3[0]), p3 = o3(h3, a3[0]), m2 = o3(h3, c3[0]), g2 = o3(h3, l3[0]), f2 = t34(t34(n3(r3[0], r3[0]), n3(r3[1], r3[1])), t34(n3(r3[2], r3[2]), n3(r3[3], r3[3]))), y2 = o3(f2, i3[0]), _2 = o3(f2, s3[0]), b2 = o3(f2, a3[0]), x2 = o3(f2, c3[0]), v2 = o3(f2, l3[0]), I2 = t34(t34(n3(s3[0], s3[0]), n3(s3[1], s3[1])), t34(n3(s3[2], s3[2]), n3(s3[3], s3[3]))), S2 = o3(I2, i3[0]), C2 = o3(I2, r3[0]), P2 = o3(I2, a3[0]), M2 = o3(I2, c3[0]), N2 = o3(I2, l3[0]), w2 = t34(t34(n3(a3[0], a3[0]), n3(a3[1], a3[1])), t34(n3(a3[2], a3[2]), n3(a3[3], a3[3]))), T2 = o3(w2, i3[0]), R2 = o3(w2, r3[0]), E2 = o3(w2, s3[0]), A2 = o3(w2, c3[0]), O2 = o3(w2, l3[0]), k2 = t34(t34(n3(c3[0], c3[0]), n3(c3[1], c3[1])), t34(n3(c3[2], c3[2]), n3(c3[3], c3[3]))), D2 = o3(k2, i3[0]), L2 = o3(k2, r3[0]), z2 = o3(k2, s3[0]), B2 = o3(k2, a3[0]), F2 = o3(k2, l3[0]), j2 = t34(t34(n3(l3[0], l3[0]), n3(l3[1], l3[1])), t34(n3(l3[2], l3[2]), n3(l3[3], l3[3]))), $ = o3(j2, i3[0]), Y2 = o3(j2, r3[0]), X2 = o3(j2, s3[0]), W2 = o3(j2, a3[0]), V2 = o3(j2, c3[0]), H2 = t34(t34(t34(o3(t34(t34(o3(t34(o3(e3(V2, F2), a3[1]), t34(o3(e3(W2, O2), -c3[1]), o3(e3(B2, A2), l3[1]))), s3[2]), o3(t34(o3(e3(V2, F2), s3[1]), t34(o3(e3(X2, N2), -c3[1]), o3(e3(z2, M2), l3[1]))), -a3[2])), t34(o3(t34(o3(e3(W2, O2), s3[1]), t34(o3(e3(X2, N2), -a3[1]), o3(e3(E2, P2), l3[1]))), c3[2]), o3(t34(o3(e3(B2, A2), s3[1]), t34(o3(e3(z2, M2), -a3[1]), o3(e3(E2, P2), c3[1]))), -l3[2]))), r3[3]), t34(o3(t34(t34(o3(t34(o3(e3(V2, F2), a3[1]), t34(o3(e3(W2, O2), -c3[1]), o3(e3(B2, A2), l3[1]))), r3[2]), o3(t34(o3(e3(V2, F2), r3[1]), t34(o3(e3(Y2, v2), -c3[1]), o3(e3(L2, x2), l3[1]))), -a3[2])), t34(o3(t34(o3(e3(W2, O2), r3[1]), t34(o3(e3(Y2, v2), -a3[1]), o3(e3(R2, b2), l3[1]))), c3[2]), o3(t34(o3(e3(B2, A2), r3[1]), t34(o3(e3(L2, x2), -a3[1]), o3(e3(R2, b2), c3[1]))), -l3[2]))), -s3[3]), o3(t34(t34(o3(t34(o3(e3(V2, F2), s3[1]), t34(o3(e3(X2, N2), -c3[1]), o3(e3(z2, M2), l3[1]))), r3[2]), o3(t34(o3(e3(V2, F2), r3[1]), t34(o3(e3(Y2, v2), -c3[1]), o3(e3(L2, x2), l3[1]))), -s3[2])), t34(o3(t34(o3(e3(X2, N2), r3[1]), t34(o3(e3(Y2, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), c3[2]), o3(t34(o3(e3(z2, M2), r3[1]), t34(o3(e3(L2, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), -l3[2]))), a3[3]))), t34(t34(o3(t34(t34(o3(t34(o3(e3(W2, O2), s3[1]), t34(o3(e3(X2, N2), -a3[1]), o3(e3(E2, P2), l3[1]))), r3[2]), o3(t34(o3(e3(W2, O2), r3[1]), t34(o3(e3(Y2, v2), -a3[1]), o3(e3(R2, b2), l3[1]))), -s3[2])), t34(o3(t34(o3(e3(X2, N2), r3[1]), t34(o3(e3(Y2, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), a3[2]), o3(t34(o3(e3(E2, P2), r3[1]), t34(o3(e3(R2, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), -l3[2]))), -c3[3]), o3(t34(t34(o3(t34(o3(e3(B2, A2), s3[1]), t34(o3(e3(z2, M2), -a3[1]), o3(e3(E2, P2), c3[1]))), r3[2]), o3(t34(o3(e3(B2, A2), r3[1]), t34(o3(e3(L2, x2), -a3[1]), o3(e3(R2, b2), c3[1]))), -s3[2])), t34(o3(t34(o3(e3(z2, M2), r3[1]), t34(o3(e3(L2, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), a3[2]), o3(t34(o3(e3(E2, P2), r3[1]), t34(o3(e3(R2, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), -c3[2]))), l3[3])), t34(o3(t34(t34(o3(t34(o3(e3(V2, F2), a3[1]), t34(o3(e3(W2, O2), -c3[1]), o3(e3(B2, A2), l3[1]))), r3[2]), o3(t34(o3(e3(V2, F2), r3[1]), t34(o3(e3(Y2, v2), -c3[1]), o3(e3(L2, x2), l3[1]))), -a3[2])), t34(o3(t34(o3(e3(W2, O2), r3[1]), t34(o3(e3(Y2, v2), -a3[1]), o3(e3(R2, b2), l3[1]))), c3[2]), o3(t34(o3(e3(B2, A2), r3[1]), t34(o3(e3(L2, x2), -a3[1]), o3(e3(R2, b2), c3[1]))), -l3[2]))), i3[3]), o3(t34(t34(o3(t34(o3(e3(V2, F2), a3[1]), t34(o3(e3(W2, O2), -c3[1]), o3(e3(B2, A2), l3[1]))), i3[2]), o3(t34(o3(e3(V2, F2), i3[1]), t34(o3(e3($, g2), -c3[1]), o3(e3(D2, m2), l3[1]))), -a3[2])), t34(o3(t34(o3(e3(W2, O2), i3[1]), t34(o3(e3($, g2), -a3[1]), o3(e3(T2, p3), l3[1]))), c3[2]), o3(t34(o3(e3(B2, A2), i3[1]), t34(o3(e3(D2, m2), -a3[1]), o3(e3(T2, p3), c3[1]))), -l3[2]))), -r3[3])))), t34(t34(t34(o3(t34(t34(o3(t34(o3(e3(V2, F2), r3[1]), t34(o3(e3(Y2, v2), -c3[1]), o3(e3(L2, x2), l3[1]))), i3[2]), o3(t34(o3(e3(V2, F2), i3[1]), t34(o3(e3($, g2), -c3[1]), o3(e3(D2, m2), l3[1]))), -r3[2])), t34(o3(t34(o3(e3(Y2, v2), i3[1]), t34(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), c3[2]), o3(t34(o3(e3(L2, x2), i3[1]), t34(o3(e3(D2, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), -l3[2]))), a3[3]), o3(t34(t34(o3(t34(o3(e3(W2, O2), r3[1]), t34(o3(e3(Y2, v2), -a3[1]), o3(e3(R2, b2), l3[1]))), i3[2]), o3(t34(o3(e3(W2, O2), i3[1]), t34(o3(e3($, g2), -a3[1]), o3(e3(T2, p3), l3[1]))), -r3[2])), t34(o3(t34(o3(e3(Y2, v2), i3[1]), t34(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), a3[2]), o3(t34(o3(e3(R2, b2), i3[1]), t34(o3(e3(T2, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), -l3[2]))), -c3[3])), t34(o3(t34(t34(o3(t34(o3(e3(B2, A2), r3[1]), t34(o3(e3(L2, x2), -a3[1]), o3(e3(R2, b2), c3[1]))), i3[2]), o3(t34(o3(e3(B2, A2), i3[1]), t34(o3(e3(D2, m2), -a3[1]), o3(e3(T2, p3), c3[1]))), -r3[2])), t34(o3(t34(o3(e3(L2, x2), i3[1]), t34(o3(e3(D2, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), a3[2]), o3(t34(o3(e3(R2, b2), i3[1]), t34(o3(e3(T2, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), -c3[2]))), l3[3]), o3(t34(t34(o3(t34(o3(e3(W2, O2), s3[1]), t34(o3(e3(X2, N2), -a3[1]), o3(e3(E2, P2), l3[1]))), r3[2]), o3(t34(o3(e3(W2, O2), r3[1]), t34(o3(e3(Y2, v2), -a3[1]), o3(e3(R2, b2), l3[1]))), -s3[2])), t34(o3(t34(o3(e3(X2, N2), r3[1]), t34(o3(e3(Y2, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), a3[2]), o3(t34(o3(e3(E2, P2), r3[1]), t34(o3(e3(R2, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), -l3[2]))), i3[3]))), t34(t34(o3(t34(t34(o3(t34(o3(e3(W2, O2), s3[1]), t34(o3(e3(X2, N2), -a3[1]), o3(e3(E2, P2), l3[1]))), i3[2]), o3(t34(o3(e3(W2, O2), i3[1]), t34(o3(e3($, g2), -a3[1]), o3(e3(T2, p3), l3[1]))), -s3[2])), t34(o3(t34(o3(e3(X2, N2), i3[1]), t34(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), a3[2]), o3(t34(o3(e3(E2, P2), i3[1]), t34(o3(e3(T2, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -l3[2]))), -r3[3]), o3(t34(t34(o3(t34(o3(e3(W2, O2), r3[1]), t34(o3(e3(Y2, v2), -a3[1]), o3(e3(R2, b2), l3[1]))), i3[2]), o3(t34(o3(e3(W2, O2), i3[1]), t34(o3(e3($, g2), -a3[1]), o3(e3(T2, p3), l3[1]))), -r3[2])), t34(o3(t34(o3(e3(Y2, v2), i3[1]), t34(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), a3[2]), o3(t34(o3(e3(R2, b2), i3[1]), t34(o3(e3(T2, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), -l3[2]))), s3[3])), t34(o3(t34(t34(o3(t34(o3(e3(X2, N2), r3[1]), t34(o3(e3(Y2, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), i3[2]), o3(t34(o3(e3(X2, N2), i3[1]), t34(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), -r3[2])), t34(o3(t34(o3(e3(Y2, v2), i3[1]), t34(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), s3[2]), o3(t34(o3(e3(C2, _2), i3[1]), t34(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -l3[2]))), -a3[3]), o3(t34(t34(o3(t34(o3(e3(E2, P2), r3[1]), t34(o3(e3(R2, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), i3[2]), o3(t34(o3(e3(E2, P2), i3[1]), t34(o3(e3(T2, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -r3[2])), t34(o3(t34(o3(e3(R2, b2), i3[1]), t34(o3(e3(T2, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), s3[2]), o3(t34(o3(e3(C2, _2), i3[1]), t34(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -a3[2]))), l3[3]))))), G2 = t34(t34(t34(o3(t34(t34(o3(t34(o3(e3(V2, F2), a3[1]), t34(o3(e3(W2, O2), -c3[1]), o3(e3(B2, A2), l3[1]))), s3[2]), o3(t34(o3(e3(V2, F2), s3[1]), t34(o3(e3(X2, N2), -c3[1]), o3(e3(z2, M2), l3[1]))), -a3[2])), t34(o3(t34(o3(e3(W2, O2), s3[1]), t34(o3(e3(X2, N2), -a3[1]), o3(e3(E2, P2), l3[1]))), c3[2]), o3(t34(o3(e3(B2, A2), s3[1]), t34(o3(e3(z2, M2), -a3[1]), o3(e3(E2, P2), c3[1]))), -l3[2]))), i3[3]), t34(o3(t34(t34(o3(t34(o3(e3(V2, F2), a3[1]), t34(o3(e3(W2, O2), -c3[1]), o3(e3(B2, A2), l3[1]))), i3[2]), o3(t34(o3(e3(V2, F2), i3[1]), t34(o3(e3($, g2), -c3[1]), o3(e3(D2, m2), l3[1]))), -a3[2])), t34(o3(t34(o3(e3(W2, O2), i3[1]), t34(o3(e3($, g2), -a3[1]), o3(e3(T2, p3), l3[1]))), c3[2]), o3(t34(o3(e3(B2, A2), i3[1]), t34(o3(e3(D2, m2), -a3[1]), o3(e3(T2, p3), c3[1]))), -l3[2]))), -s3[3]), o3(t34(t34(o3(t34(o3(e3(V2, F2), s3[1]), t34(o3(e3(X2, N2), -c3[1]), o3(e3(z2, M2), l3[1]))), i3[2]), o3(t34(o3(e3(V2, F2), i3[1]), t34(o3(e3($, g2), -c3[1]), o3(e3(D2, m2), l3[1]))), -s3[2])), t34(o3(t34(o3(e3(X2, N2), i3[1]), t34(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), c3[2]), o3(t34(o3(e3(z2, M2), i3[1]), t34(o3(e3(D2, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), -l3[2]))), a3[3]))), t34(t34(o3(t34(t34(o3(t34(o3(e3(W2, O2), s3[1]), t34(o3(e3(X2, N2), -a3[1]), o3(e3(E2, P2), l3[1]))), i3[2]), o3(t34(o3(e3(W2, O2), i3[1]), t34(o3(e3($, g2), -a3[1]), o3(e3(T2, p3), l3[1]))), -s3[2])), t34(o3(t34(o3(e3(X2, N2), i3[1]), t34(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), a3[2]), o3(t34(o3(e3(E2, P2), i3[1]), t34(o3(e3(T2, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -l3[2]))), -c3[3]), o3(t34(t34(o3(t34(o3(e3(B2, A2), s3[1]), t34(o3(e3(z2, M2), -a3[1]), o3(e3(E2, P2), c3[1]))), i3[2]), o3(t34(o3(e3(B2, A2), i3[1]), t34(o3(e3(D2, m2), -a3[1]), o3(e3(T2, p3), c3[1]))), -s3[2])), t34(o3(t34(o3(e3(z2, M2), i3[1]), t34(o3(e3(D2, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), a3[2]), o3(t34(o3(e3(E2, P2), i3[1]), t34(o3(e3(T2, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -c3[2]))), l3[3])), t34(o3(t34(t34(o3(t34(o3(e3(V2, F2), s3[1]), t34(o3(e3(X2, N2), -c3[1]), o3(e3(z2, M2), l3[1]))), r3[2]), o3(t34(o3(e3(V2, F2), r3[1]), t34(o3(e3(Y2, v2), -c3[1]), o3(e3(L2, x2), l3[1]))), -s3[2])), t34(o3(t34(o3(e3(X2, N2), r3[1]), t34(o3(e3(Y2, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), c3[2]), o3(t34(o3(e3(z2, M2), r3[1]), t34(o3(e3(L2, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), -l3[2]))), i3[3]), o3(t34(t34(o3(t34(o3(e3(V2, F2), s3[1]), t34(o3(e3(X2, N2), -c3[1]), o3(e3(z2, M2), l3[1]))), i3[2]), o3(t34(o3(e3(V2, F2), i3[1]), t34(o3(e3($, g2), -c3[1]), o3(e3(D2, m2), l3[1]))), -s3[2])), t34(o3(t34(o3(e3(X2, N2), i3[1]), t34(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), c3[2]), o3(t34(o3(e3(z2, M2), i3[1]), t34(o3(e3(D2, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), -l3[2]))), -r3[3])))), t34(t34(t34(o3(t34(t34(o3(t34(o3(e3(V2, F2), r3[1]), t34(o3(e3(Y2, v2), -c3[1]), o3(e3(L2, x2), l3[1]))), i3[2]), o3(t34(o3(e3(V2, F2), i3[1]), t34(o3(e3($, g2), -c3[1]), o3(e3(D2, m2), l3[1]))), -r3[2])), t34(o3(t34(o3(e3(Y2, v2), i3[1]), t34(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), c3[2]), o3(t34(o3(e3(L2, x2), i3[1]), t34(o3(e3(D2, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), -l3[2]))), s3[3]), o3(t34(t34(o3(t34(o3(e3(X2, N2), r3[1]), t34(o3(e3(Y2, v2), -s3[1]), o3(e3(C2, _2), l3[1]))), i3[2]), o3(t34(o3(e3(X2, N2), i3[1]), t34(o3(e3($, g2), -s3[1]), o3(e3(S2, u3), l3[1]))), -r3[2])), t34(o3(t34(o3(e3(Y2, v2), i3[1]), t34(o3(e3($, g2), -r3[1]), o3(e3(y2, d3), l3[1]))), s3[2]), o3(t34(o3(e3(C2, _2), i3[1]), t34(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -l3[2]))), -c3[3])), t34(o3(t34(t34(o3(t34(o3(e3(z2, M2), r3[1]), t34(o3(e3(L2, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), i3[2]), o3(t34(o3(e3(z2, M2), i3[1]), t34(o3(e3(D2, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), -r3[2])), t34(o3(t34(o3(e3(L2, x2), i3[1]), t34(o3(e3(D2, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), s3[2]), o3(t34(o3(e3(C2, _2), i3[1]), t34(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -c3[2]))), l3[3]), o3(t34(t34(o3(t34(o3(e3(B2, A2), s3[1]), t34(o3(e3(z2, M2), -a3[1]), o3(e3(E2, P2), c3[1]))), r3[2]), o3(t34(o3(e3(B2, A2), r3[1]), t34(o3(e3(L2, x2), -a3[1]), o3(e3(R2, b2), c3[1]))), -s3[2])), t34(o3(t34(o3(e3(z2, M2), r3[1]), t34(o3(e3(L2, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), a3[2]), o3(t34(o3(e3(E2, P2), r3[1]), t34(o3(e3(R2, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), -c3[2]))), i3[3]))), t34(t34(o3(t34(t34(o3(t34(o3(e3(B2, A2), s3[1]), t34(o3(e3(z2, M2), -a3[1]), o3(e3(E2, P2), c3[1]))), i3[2]), o3(t34(o3(e3(B2, A2), i3[1]), t34(o3(e3(D2, m2), -a3[1]), o3(e3(T2, p3), c3[1]))), -s3[2])), t34(o3(t34(o3(e3(z2, M2), i3[1]), t34(o3(e3(D2, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), a3[2]), o3(t34(o3(e3(E2, P2), i3[1]), t34(o3(e3(T2, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -c3[2]))), -r3[3]), o3(t34(t34(o3(t34(o3(e3(B2, A2), r3[1]), t34(o3(e3(L2, x2), -a3[1]), o3(e3(R2, b2), c3[1]))), i3[2]), o3(t34(o3(e3(B2, A2), i3[1]), t34(o3(e3(D2, m2), -a3[1]), o3(e3(T2, p3), c3[1]))), -r3[2])), t34(o3(t34(o3(e3(L2, x2), i3[1]), t34(o3(e3(D2, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), a3[2]), o3(t34(o3(e3(R2, b2), i3[1]), t34(o3(e3(T2, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), -c3[2]))), s3[3])), t34(o3(t34(t34(o3(t34(o3(e3(z2, M2), r3[1]), t34(o3(e3(L2, x2), -s3[1]), o3(e3(C2, _2), c3[1]))), i3[2]), o3(t34(o3(e3(z2, M2), i3[1]), t34(o3(e3(D2, m2), -s3[1]), o3(e3(S2, u3), c3[1]))), -r3[2])), t34(o3(t34(o3(e3(L2, x2), i3[1]), t34(o3(e3(D2, m2), -r3[1]), o3(e3(y2, d3), c3[1]))), s3[2]), o3(t34(o3(e3(C2, _2), i3[1]), t34(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -c3[2]))), -a3[3]), o3(t34(t34(o3(t34(o3(e3(E2, P2), r3[1]), t34(o3(e3(R2, b2), -s3[1]), o3(e3(C2, _2), a3[1]))), i3[2]), o3(t34(o3(e3(E2, P2), i3[1]), t34(o3(e3(T2, p3), -s3[1]), o3(e3(S2, u3), a3[1]))), -r3[2])), t34(o3(t34(o3(e3(R2, b2), i3[1]), t34(o3(e3(T2, p3), -r3[1]), o3(e3(y2, d3), a3[1]))), s3[2]), o3(t34(o3(e3(C2, _2), i3[1]), t34(o3(e3(S2, u3), -r3[1]), o3(e3(y2, d3), s3[1]))), -a3[2]))), c3[3]))))), U2 = e3(H2, G2);
return U2[U2.length - 1];
};
}
var d2 = [function() {
return 0;
}, function() {
return 0;
}, function() {
return 0;
}];
function u2(t34) {
var e3 = d2[t34.length];
return e3 || (e3 = d2[t34.length] = s2(t34.length)), e3.apply(undefined, t34);
}
function p2(t34, e3, n3, o3, i3, r3, s3, a3) {
return function(e4, n4, c3, l3, h3, d3) {
switch (arguments.length) {
case 0:
case 1:
return 0;
case 2:
return o3(e4, n4);
case 3:
return i3(e4, n4, c3);
case 4:
return r3(e4, n4, c3, l3);
case 5:
return s3(e4, n4, c3, l3, h3);
case 6:
return a3(e4, n4, c3, l3, h3, d3);
}
for (var u3 = new Array(arguments.length), p3 = 0;p3 < arguments.length; ++p3)
u3[p3] = arguments[p3];
return t34(u3);
};
}
(function() {
for (;d2.length <= 6; )
d2.push(s2(d2.length));
e2.exports = p2.apply(undefined, [u2].concat(d2));
for (var t34 = 0;t34 <= 6; ++t34)
e2.exports[t34] = d2[t34];
})();
} });
var Fz = wz({ "node_modules/cdt2d/lib/delaunay.js"(t33, e2) {
var n2 = Bz()[4];
Tz();
function o2(t34, e3, o3, i2, r2, s2) {
var a2 = e3.opposite(i2, r2);
if (!(a2 < 0)) {
if (r2 < i2) {
var c2 = i2;
i2 = r2, r2 = c2, c2 = s2, s2 = a2, a2 = c2;
}
e3.isConstraint(i2, r2) || n2(t34[i2], t34[r2], t34[s2], t34[a2]) < 0 && o3.push(i2, r2);
}
}
e2.exports = function(t34, e3) {
for (var i2 = [], r2 = t34.length, s2 = e3.stars, a2 = 0;a2 < r2; ++a2)
for (var c2 = s2[a2], l2 = 1;l2 < c2.length; l2 += 2) {
if (!((p2 = c2[l2]) < a2) && !e3.isConstraint(a2, p2)) {
for (var h2 = c2[l2 - 1], d2 = -1, u2 = 1;u2 < c2.length; u2 += 2)
if (c2[u2 - 1] === p2) {
d2 = c2[u2];
break;
}
d2 < 0 || n2(t34[a2], t34[p2], t34[h2], t34[d2]) < 0 && i2.push(a2, p2);
}
}
for (;i2.length > 0; ) {
for (var p2 = i2.pop(), m2 = (h2 = -1, d2 = -1, c2 = s2[a2 = i2.pop()], 1);m2 < c2.length; m2 += 2) {
var g2 = c2[m2 - 1], f2 = c2[m2];
g2 === p2 ? d2 = f2 : f2 === p2 && (h2 = g2);
}
h2 < 0 || d2 < 0 || (n2(t34[a2], t34[p2], t34[h2], t34[d2]) >= 0 || (e3.flip(a2, p2), o2(t34, e3, i2, h2, a2, d2), o2(t34, e3, i2, a2, d2, h2), o2(t34, e3, i2, d2, p2, h2), o2(t34, e3, i2, p2, h2, d2)));
}
};
} });
var jz = wz({ "node_modules/cdt2d/lib/filter.js"(t33, e2) {
var n2 = Tz();
function o2(t34, e3, n3, o3, i3, r2, s2) {
this.cells = t34, this.neighbor = e3, this.flags = o3, this.constraint = n3, this.active = i3, this.next = r2, this.boundary = s2;
}
function i2(t34, e3) {
return t34[0] - e3[0] || t34[1] - e3[1] || t34[2] - e3[2];
}
e2.exports = function(t34, e3, n3) {
var r2 = function(t35, e4) {
for (var n4 = t35.cells(), r3 = n4.length, s3 = 0;s3 < r3; ++s3) {
var a3 = (y3 = n4[s3])[0], c3 = y3[1], l3 = y3[2];
c3 < l3 ? c3 < a3 && (y3[0] = c3, y3[1] = l3, y3[2] = a3) : l3 < a3 && (y3[0] = l3, y3[1] = a3, y3[2] = c3);
}
n4.sort(i2);
var h3 = new Array(r3);
for (s3 = 0;s3 < h3.length; ++s3)
h3[s3] = 0;
var d3 = [], u3 = [], p3 = new Array(3 * r3), m3 = new Array(3 * r3), g3 = null;
e4 && (g3 = []);
var f3 = new o2(n4, p3, m3, h3, d3, u3, g3);
for (s3 = 0;s3 < r3; ++s3)
for (var y3 = n4[s3], _2 = 0;_2 < 3; ++_2) {
a3 = y3[_2], c3 = y3[(_2 + 1) % 3];
var b2 = p3[3 * s3 + _2] = f3.locate(c3, a3, t35.opposite(c3, a3)), x2 = m3[3 * s3 + _2] = t35.isConstraint(a3, c3);
b2 < 0 && (x2 ? u3.push(s3) : (d3.push(s3), h3[s3] = 1), e4 && g3.push([c3, a3, -1]));
}
return f3;
}(t34, n3);
if (e3 === 0)
return n3 ? r2.cells.concat(r2.boundary) : r2.cells;
var s2 = 1, a2 = r2.active, c2 = r2.next, l2 = r2.flags, h2 = r2.cells, d2 = r2.constraint, u2 = r2.neighbor;
for (;a2.length > 0 || c2.length > 0; ) {
for (;a2.length > 0; ) {
var p2 = a2.pop();
if (l2[p2] !== -s2) {
l2[p2] = s2;
h2[p2];
for (var m2 = 0;m2 < 3; ++m2) {
var g2 = u2[3 * p2 + m2];
g2 >= 0 && l2[g2] === 0 && (d2[3 * p2 + m2] ? c2.push(g2) : (a2.push(g2), l2[g2] = s2));
}
}
}
var f2 = c2;
c2 = a2, a2 = f2, c2.length = 0, s2 = -s2;
}
var y2 = function(t35, e4, n4) {
for (var o3 = 0, i3 = 0;i3 < t35.length; ++i3)
e4[i3] === n4 && (t35[o3++] = t35[i3]);
return t35.length = o3, t35;
}(h2, l2, e3);
if (n3)
return y2.concat(r2.boundary);
return y2;
}, o2.prototype.locate = function() {
var t34 = [0, 0, 0];
return function(e3, o3, r2) {
var s2 = e3, a2 = o3, c2 = r2;
return o3 < r2 ? o3 < e3 && (s2 = o3, a2 = r2, c2 = e3) : r2 < e3 && (s2 = r2, a2 = e3, c2 = o3), s2 < 0 ? -1 : (t34[0] = s2, t34[1] = a2, t34[2] = c2, n2.eq(this.cells, t34, i2));
};
}();
} });
var $z = wz({ "node_modules/cdt2d/cdt2d.js"(t33, e2) {
var n2 = Lz(), o2 = zz(), i2 = Fz(), r2 = jz();
function s2(t34) {
return [Math.min(t34[0], t34[1]), Math.max(t34[0], t34[1])];
}
function a2(t34, e3) {
return t34[0] - e3[0] || t34[1] - e3[1];
}
function c2(t34, e3, n3) {
return e3 in t34 ? t34[e3] : n3;
}
e2.exports = function(t34, e3, l2) {
Array.isArray(e3) ? (l2 = l2 || {}, e3 = e3 || []) : (l2 = e3 || {}, e3 = []);
var h2 = !!c2(l2, "delaunay", true), d2 = !!c2(l2, "interior", true), u2 = !!c2(l2, "exterior", true), p2 = !!c2(l2, "infinity", false);
if (!d2 && !u2 || t34.length === 0)
return [];
var m2 = n2(t34, e3);
if (h2 || d2 !== u2 || p2) {
for (var g2 = o2(t34.length, function(t35) {
return t35.map(s2).sort(a2);
}(e3)), f2 = 0;f2 < m2.length; ++f2) {
var y2 = m2[f2];
g2.addTriangle(y2[0], y2[1], y2[2]);
}
return h2 && i2(t34, g2), u2 ? d2 ? p2 ? r2(g2, 0, p2) : g2.cells() : r2(g2, 1, p2) : r2(g2, -1);
}
return m2;
};
} });
var $B = true;
var YB = { CCW: -1, CW: 1, NOT_ORIENTABLE: 0 };
var XB = 2 * Math.PI;
var WB = Object.freeze({ __proto__: null, BOUNDARY: 2, CCW: $B, CONTAINS: 3, CW: false, END_VERTEX: 2, INSIDE: 1, INTERLACE: 4, NOT_VERTEX: 0, ORIENTATION: YB, OUTSIDE: 0, OVERLAP_OPPOSITE: 2, OVERLAP_SAME: 1, PIx2: XB, START_VERTEX: 1 });
var VB = 0.000001;
function HB(t33) {
VB = t33;
}
function GB() {
return VB;
}
function UB(t33) {
return t33 < VB && t33 > -VB;
}
function ZB(t33, e2) {
return t33 - e2 < VB && t33 - e2 > -VB;
}
function qB(t33, e2) {
return t33 - e2 > VB;
}
function JB(t33, e2) {
return t33 - e2 < -VB;
}
var QB = { Utils: Object.freeze({ __proto__: null, DECIMALS: 3, EQ: ZB, EQ_0: UB, GE: function(t33, e2) {
return t33 - e2 > -VB;
}, GT: qB, LE: function(t33, e2) {
return t33 - e2 < VB;
}, LT: JB, getTolerance: GB, setTolerance: HB }), Errors: undefined, Matrix: undefined, Planar_set: undefined, Point: undefined, Vector: undefined, Line: undefined, Circle: undefined, Segment: undefined, Arc: undefined, Box: undefined, Edge: undefined, Face: undefined, Ray: undefined, Ray_shooting: undefined, Multiline: undefined, Polygon: undefined, Distance: undefined, Inversion: undefined };
for (let t33 in WB)
QB[t33] = WB[t33];
Object.defineProperty(QB, "DP_TOL", { get: function() {
return GB();
}, set: function(t33) {
HB(t33);
} });
var KB = class {
static get ILLEGAL_PARAMETERS() {
return new ReferenceError("Illegal Parameters");
}
static get ZERO_DIVISION() {
return new Error("Zero division");
}
static get UNRESOLVED_BOUNDARY_CONFLICT() {
return new Error("Unresolved boundary conflict in boolean operation");
}
static get INFINITE_LOOP() {
return new Error("Infinite loop");
}
static get CANNOT_COMPLETE_BOOLEAN_OPERATION() {
return new Error("Cannot complete boolean operation");
}
static get CANNOT_INVOKE_ABSTRACT_METHOD() {
return new Error("Abstract method cannot be invoked");
}
static get OPERATION_IS_NOT_SUPPORTED() {
return new Error("Operation is not supported");
}
static get UNSUPPORTED_SHAPE_TYPE() {
return new Error("Unsupported shape type");
}
};
QB.Errors = KB;
var tF = class {
constructor(t33, e2) {
this.first = t33, this.last = e2 || this.first;
}
[Symbol.iterator]() {
let t33;
return { next: () => (t33 = t33 ? t33.next : this.first, { value: t33, done: t33 === undefined }) };
}
get size() {
let t33 = 0;
for (let e2 of this)
t33++;
return t33;
}
toArray(t33 = undefined, e2 = undefined) {
let n2 = [], o2 = t33 || this.first, i2 = e2 || this.last, r2 = o2;
if (r2 === undefined)
return n2;
do {
n2.push(r2), r2 = r2.next;
} while (r2 !== i2.next);
return n2;
}
append(t33) {
return this.isEmpty() ? this.first = t33 : (t33.prev = this.last, this.last.next = t33), this.last = t33, this.last.next = undefined, this.first.prev = undefined, this;
}
insert(t33, e2) {
if (this.isEmpty())
this.first = t33, this.last = t33;
else if (e2 == null)
t33.next = this.first, this.first.prev = t33, this.first = t33;
else {
let n2 = e2.next;
e2.next = t33, n2 && (n2.prev = t33), t33.prev = e2, t33.next = n2, this.last === e2 && (this.last = t33);
}
return this.last.next = undefined, this.first.prev = undefined, this;
}
remove(t33) {
return t33 === this.first && t33 === this.last ? (this.first = undefined, this.last = undefined) : (t33.prev && (t33.prev.next = t33.next), t33.next && (t33.next.prev = t33.prev), t33 === this.first && (this.first = t33.next), t33 === this.last && (this.last = t33.prev)), this;
}
isEmpty() {
return this.first === undefined;
}
static testInfiniteLoop(t33) {
let e2 = t33, n2 = t33;
do {
if (e2 != t33 && e2 === n2)
throw KB.INFINITE_LOOP;
e2 = e2.next, n2 = n2.next.next;
} while (e2 != t33);
}
};
var eF = { stroke: "black" };
var nF = class {
constructor(t33 = eF) {
for (const e2 in t33)
this[e2] = t33[e2];
this.stroke = t33.stroke ?? eF.stroke;
}
toAttributesString() {
return Object.keys(this).reduce((t33, e2) => t33 + (this[e2] !== undefined ? this.toAttrString(e2, this[e2]) : ""), "");
}
toAttrString(t33, e2) {
const n2 = t33 === "className" ? "class" : this.convertCamelToKebabCase(t33);
return e2 === null ? `${n2} ` : `${n2}="${e2.toString()}" `;
}
convertCamelToKebabCase(t33) {
return t33.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g).join("-").toLowerCase();
}
};
function oF(t33) {
return new nF(t33).toAttributesString();
}
function iF(t33, e2) {
let n2 = [], [o2, i2, r2] = t33.standard, [s2, a2, c2] = e2.standard, l2 = o2 * a2 - i2 * s2, h2 = r2 * a2 - i2 * c2, d2 = o2 * c2 - r2 * s2;
if (!QB.Utils.EQ_0(l2)) {
let t34, e3;
i2 === 0 ? (t34 = r2 / o2, e3 = d2 / l2) : a2 === 0 ? (t34 = c2 / s2, e3 = d2 / l2) : o2 === 0 ? (t34 = h2 / l2, e3 = r2 / i2) : s2 === 0 ? (t34 = h2 / l2, e3 = c2 / a2) : (t34 = h2 / l2, e3 = d2 / l2), n2.push(new QB.Point(t34, e3));
}
return n2;
}
function rF(t33, e2) {
let n2 = [], o2 = e2.pc.projectionOn(t33), i2 = e2.pc.distanceTo(o2)[0];
if (QB.Utils.EQ(i2, e2.r))
n2.push(o2);
else if (QB.Utils.LT(i2, e2.r)) {
let r2, s2, a2 = Math.sqrt(e2.r * e2.r - i2 * i2);
r2 = t33.norm.rotate90CCW().multiply(a2), s2 = o2.translate(r2), n2.push(s2), r2 = t33.norm.rotate90CW().multiply(a2), s2 = o2.translate(r2), n2.push(s2);
}
return n2;
}
function sF(t33, e2) {
let n2 = [];
for (let o2 of e2.toSegments()) {
let e3 = cF(o2, t33);
for (let t34 of e3)
MF(t34, n2) || n2.push(t34);
}
return n2;
}
function aF(t33, e2) {
let n2 = [];
if (sF(t33, e2.box).length === 0)
return n2;
let o2 = rF(t33, new QB.Circle(e2.pc, e2.r));
for (let t34 of o2)
t34.on(e2) && n2.push(t34);
return n2;
}
function cF(t33, e2) {
let n2 = [];
return t33.ps.on(e2) && n2.push(t33.ps), t33.pe.on(e2) && !t33.isZeroLength() && n2.push(t33.pe), n2.length > 0 || t33.isZeroLength() || t33.ps.leftTo(e2) && t33.pe.leftTo(e2) || !t33.ps.leftTo(e2) && !t33.pe.leftTo(e2) ? n2 : iF(new QB.Line(t33.ps, t33.pe), e2);
}
function lF(t33, e2) {
let n2 = [];
if (t33.isZeroLength())
return t33.ps.on(e2) && n2.push(t33.ps), n2;
if (e2.isZeroLength())
return e2.ps.on(t33) && n2.push(e2.ps), n2;
let o2 = new QB.Line(t33.ps, t33.pe), i2 = new QB.Line(e2.ps, e2.pe);
if (o2.incidentTo(i2))
t33.ps.on(e2) && n2.push(t33.ps), t33.pe.on(e2) && n2.push(t33.pe), !e2.ps.on(t33) || e2.ps.equalTo(t33.ps) || e2.ps.equalTo(t33.pe) || n2.push(e2.ps), !e2.pe.on(t33) || e2.pe.equalTo(t33.ps) || e2.pe.equalTo(t33.pe) || n2.push(e2.pe);
else {
let r2 = iF(o2, i2);
r2.length > 0 && hF(r2[0], t33) && hF(r2[0], e2) && n2.push(r2[0]);
}
return n2;
}
function hF(t33, e2) {
const n2 = e2.box;
return QB.Utils.LE(t33.x, n2.xmax) && QB.Utils.GE(t33.x, n2.xmin) && QB.Utils.LE(t33.y, n2.ymax) && QB.Utils.GE(t33.y, n2.ymin);
}
function dF(t33, e2) {
let n2 = [];
if (t33.isZeroLength()) {
let [o3, i2] = t33.ps.distanceTo(e2.pc);
return QB.Utils.EQ(o3, e2.r) && n2.push(t33.ps), n2;
}
let o2 = rF(new QB.Line(t33.ps, t33.pe), e2);
for (let e3 of o2)
e3.on(t33) && n2.push(e3);
return n2;
}
function uF(t33, e2) {
let n2 = [];
if (t33.isZeroLength())
return t33.ps.on(e2) && n2.push(t33.ps), n2;
let o2 = rF(new QB.Line(t33.ps, t33.pe), new QB.Circle(e2.pc, e2.r));
for (let i2 of o2)
i2.on(t33) && i2.on(e2) && n2.push(i2);
return n2;
}
function pF(t33, e2) {
let n2 = [], o2 = new QB.Vector(t33.pc, e2.pc), i2 = t33.r, r2 = e2.r;
if (QB.Utils.EQ_0(i2) || QB.Utils.EQ_0(r2))
return n2;
if (QB.Utils.EQ_0(o2.x) && QB.Utils.EQ_0(o2.y) && QB.Utils.EQ(i2, r2))
return n2.push(t33.pc.translate(-i2, 0)), n2;
let s2, a2 = t33.pc.distanceTo(e2.pc)[0];
if (QB.Utils.GT(a2, i2 + r2))
return n2;
if (QB.Utils.LT(a2, Math.abs(i2 - r2)))
return n2;
if (o2.x /= a2, o2.y /= a2, QB.Utils.EQ(a2, i2 + r2) || QB.Utils.EQ(a2, Math.abs(i2 - r2)))
return s2 = t33.pc.translate(i2 * o2.x, i2 * o2.y), n2.push(s2), n2;
let c2 = i2 * i2 / (2 * a2) - r2 * r2 / (2 * a2) + a2 / 2, l2 = t33.pc.translate(c2 * o2.x, c2 * o2.y), h2 = Math.sqrt(i2 * i2 - c2 * c2);
return s2 = l2.translate(o2.rotate90CCW().multiply(h2)), n2.push(s2), s2 = l2.translate(o2.rotate90CW().multiply(h2)), n2.push(s2), n2;
}
function mF(t33, e2) {
let n2 = [];
if (t33.pc.equalTo(e2.pc) && QB.Utils.EQ(t33.r, e2.r)) {
let o3;
return o3 = t33.start, o3.on(e2) && n2.push(o3), o3 = t33.end, o3.on(e2) && n2.push(o3), o3 = e2.start, o3.on(t33) && n2.push(o3), o3 = e2.end, o3.on(t33) && n2.push(o3), n2;
}
let o2 = new QB.Circle(t33.pc, t33.r), i2 = new QB.Circle(e2.pc, e2.r), r2 = o2.intersect(i2);
for (let o3 of r2)
o3.on(t33) && o3.on(e2) && n2.push(o3);
return n2;
}
function gF(t33, e2) {
let n2 = [];
if (e2.pc.equalTo(t33.pc) && QB.Utils.EQ(e2.r, t33.r))
return n2.push(t33.start), n2.push(t33.end), n2;
let o2 = pF(e2, new QB.Circle(t33.pc, t33.r));
for (let e3 of o2)
e3.on(t33) && n2.push(e3);
return n2;
}
function fF(t33, e2) {
return t33.isSegment ? lF(t33.shape, e2) : uF(e2, t33.shape);
}
function yF(t33, e2) {
return t33.isSegment ? uF(t33.shape, e2) : mF(t33.shape, e2);
}
function _F(t33, e2) {
return t33.isSegment ? cF(t33.shape, e2) : aF(e2, t33.shape);
}
function bF(t33, e2) {
return t33.isSegment ? dF(t33.shape, e2) : gF(t33.shape, e2);
}
function xF(t33, e2) {
let n2 = [];
for (let o2 of e2.edges)
for (let e3 of fF(o2, t33))
n2.push(e3);
return n2;
}
function vF(t33, e2) {
let n2 = [];
for (let o2 of e2.edges)
for (let e3 of yF(o2, t33))
n2.push(e3);
return n2;
}
function IF(t33, e2) {
let n2 = [];
if (e2.isEmpty())
return n2;
for (let o2 of e2.edges)
for (let e3 of _F(o2, t33))
MF(e3, n2) || n2.push(e3);
return t33.sortPoints(n2);
}
function SF(t33, e2) {
let n2 = [];
if (e2.isEmpty())
return n2;
for (let o2 of e2.edges)
for (let e3 of bF(o2, t33))
n2.push(e3);
return n2;
}
function CF(t33, e2) {
return t33.isSegment ? fF(e2, t33.shape) : t33.isArc ? yF(e2, t33.shape) : t33.isLine ? _F(e2, t33.shape) : t33.isRay ? (n2 = e2, o2 = t33.shape, n2.isSegment ? wF(o2, n2.shape) : TF(o2, n2.shape)) : [];
var n2, o2;
}
function PF(t33, e2) {
let n2 = [];
if (e2.isEmpty() || t33.shape.box.not_intersect(e2.box))
return n2;
let o2 = e2.edges.search(t33.shape.box);
for (let e3 of o2)
n2 = [...n2, ...CF(t33, e3)];
return n2;
}
function MF(t33, e2) {
return e2.some((e3) => e3.equalTo(t33));
}
function NF(t33) {
return new QB.Line(t33.start, t33.norm);
}
function wF(t33, e2) {
return cF(e2, NF(t33)).filter((e3) => t33.contains(e3));
}
function TF(t33, e2) {
return aF(NF(t33), e2).filter((e3) => t33.contains(e3));
}
function RF(t33, e2) {
return rF(NF(t33), e2).filter((e3) => t33.contains(e3));
}
function EF(t33, e2) {
return iF(NF(t33), e2).filter((e3) => t33.contains(e3));
}
function AF(t33, e2) {
return IF(NF(t33), e2).filter((e3) => t33.contains(e3));
}
function OF(t33, e2) {
if (t33.intersect && t33.intersect instanceof Function)
return t33.intersect(e2);
throw KB.UNSUPPORTED_SHAPE_TYPE;
}
function kF(t33, e2) {
let n2 = [];
for (let o2 of e2)
n2 = [...n2, ...OF(t33, o2.shape)];
return n2;
}
var DF = class t33 extends tF {
constructor(...t34) {
if (super(), this.isInfinite = false, t34.length === 1 && t34[0] instanceof Array && t34[0].length > 0) {
const e2 = t34[0], n2 = e2.length, o2 = (t35) => t35 instanceof QB.Segment || t35 instanceof QB.Arc || t35 instanceof QB.Ray, i2 = (t35) => t35 instanceof QB.Segment || t35 instanceof QB.Arc;
if (!(n2 === 1 && ((t35) => t35 instanceof QB.Segment || t35 instanceof QB.Arc || t35 instanceof QB.Ray || t35 instanceof QB.Line)(e2[0]) || n2 > 1 && o2(e2[0]) && o2(e2[n2 - 1]) && e2.slice(1, n2 - 1).every(i2)))
throw QB.Errors.ILLEGAL_PARAMETERS;
this.isInfinite = e2.some((t35) => t35 instanceof QB.Ray || t35 instanceof QB.Line);
for (let t35 of e2) {
let e3 = new QB.Edge(t35);
this.append(e3);
}
this.setArcLength();
}
}
get edges() {
return [...this];
}
get box() {
return this.edges.reduce((t34, e2) => t34.merge(e2.box), new QB.Box);
}
get vertices() {
let t34 = this.edges.map((t35) => t35.start);
return t34.push(this.last.end), t34;
}
get length() {
if (this.isEmpty())
return 0;
if (this.isInfinite)
return Number.POSITIVE_INFINITY;
let t34 = 0;
for (let e2 of this)
t34 += e2.length;
return t34;
}
clone() {
return new t33(this.toShapes());
}
setArcLength() {
for (let t34 of this)
this.setOneEdgeArcLength(t34);
}
setOneEdgeArcLength(t34) {
t34 === this.first ? t34.arc_length = 0 : t34.arc_length = t34.prev.arc_length + t34.prev.length;
}
pointAtLength(t34) {
if (t34 > this.length || t34 < 0)
return null;
if (this.isInfinite)
return null;
let e2 = null;
for (let n2 of this)
if (t34 >= n2.arc_length && (n2 === this.last || t34 < n2.next.arc_length)) {
e2 = n2.pointAtLength(t34 - n2.arc_length);
break;
}
return e2;
}
addVertex(t34, e2) {
let n2 = e2.shape.split(t34);
if (n2[0] === null)
return e2.prev;
if (n2[1] === null)
return e2;
let o2 = new QB.Edge(n2[0]), i2 = e2.prev;
return this.insert(o2, i2), e2.shape = n2[1], o2;
}
getChain(t34, e2) {
let n2 = [];
for (let o2 = t34;o2 !== e2.next; o2 = o2.next)
n2.push(o2);
return n2;
}
split(t34) {
for (let e2 of t34) {
let t35 = this.findEdgeByPoint(e2);
this.addVertex(e2, t35);
}
return this;
}
findEdgeByPoint(t34) {
let e2;
for (let n2 of this)
if (n2.shape.contains(t34)) {
e2 = n2;
break;
}
return e2;
}
distanceTo(t34) {
if (t34 instanceof Point) {
const [e2, n2] = QB.Distance.shape2multiline(t34, this);
return [e2, n2.reverse()];
}
if (t34 instanceof QB.Line) {
const [e2, n2] = QB.Distance.shape2multiline(t34, this);
return [e2, n2.reverse()];
}
if (t34 instanceof QB.Circle) {
const [e2, n2] = QB.Distance.shape2multiline(t34, this);
return [e2, n2.reverse()];
}
if (t34 instanceof QB.Segment) {
const [e2, n2] = QB.Distance.shape2multiline(t34, this);
return [e2, n2.reverse()];
}
if (t34 instanceof QB.Arc) {
const [e2, n2] = QB.Distance.shape2multiline(t34, this);
return [e2, n2.reverse()];
}
if (t34 instanceof QB.Multiline)
return QB.Distance.multiline2multiline(this, t34);
throw QB.Errors.UNSUPPORTED_SHAPE_TYPE;
}
intersect(t34) {
return t34 instanceof QB.Multiline ? function(t35, e2) {
let n2 = [];
for (let o2 of t35)
for (let t36 of e2)
n2 = [...n2, ...OF(o2.shape, t36.shape)];
return n2;
}(this, t34) : kF(t34, this);
}
contains(t34) {
if (t34 instanceof QB.Point)
return this.edges.some((e2) => e2.shape.contains(t34));
throw QB.Errors.UNSUPPORTED_SHAPE_TYPE;
}
translate(e2) {
return new t33(this.edges.map((t34) => t34.shape.translate(e2)));
}
rotate(e2 = 0, n2 = new QB.Point) {
return new t33(this.edges.map((t34) => t34.shape.rotate(e2, n2)));
}
transform(e2 = new QB.Matrix) {
return new t33(this.edges.map((t34) => t34.shape.transform(e2)));
}
toShapes() {
return this.edges.map((t34) => t34.shape.clone());
}
toJSON() {
return this.edges.map((t34) => t34.toJSON());
}
svgPoints() {
return this.vertices.map((t34) => `${t34.x},${t34.y}`).join(" ");
}
dpath() {
let t34 = `M${this.first.start.x},${this.first.start.y}`;
for (let e2 of this)
t34 += e2.svg();
return t34;
}
svg(t34 = {}) {
let e2 = `
<path ${oF({ fill: "none", ...t34 })} d="`;
e2 += `
M${this.first.start.x},${this.first.start.y}`;
for (let t35 of this)
e2 += t35.svg();
return e2 += `" >
</path>`, e2;
}
};
QB.Multiline = DF;
function LF(t34, e2, n2) {
let o2 = n2.length, i2 = t34.shape.split(e2);
if (i2.length === 0)
return;
let r2 = 0;
r2 = i2[0] === null ? 0 : i2[1] === null ? t34.shape.length : i2[0].length;
let s2, a2 = 0;
ZB(r2, 0) && (a2 |= 1), ZB(r2, t34.shape.length) && (a2 |= 2), s2 = r2 === 1 / 0 ? i2[0].coord(e2) : 2 & a2 && t34.next && t34.next.arc_length === 0 ? 0 : t34.arc_length + r2, n2.push({ id: o2, pt: e2, arc_length: s2, edge_before: t34, edge_after: undefined, face: t34.face, is_vertex: a2 });
}
function zF(t34) {
t34.int_points1_sorted = BF(t34.int_points1), t34.int_points2_sorted = BF(t34.int_points2);
}
function BF(t34) {
let e2 = new Map, n2 = 0;
for (let o2 of t34)
e2.has(o2.face) || (e2.set(o2.face, n2), n2++);
for (let n3 of t34)
n3.faceId = e2.get(n3.face);
return t34.slice().sort(FF);
}
function FF(t34, e2) {
return t34.faceId < e2.faceId ? -1 : t34.faceId > e2.faceId ? 1 : t34.arc_length < e2.arc_length ? -1 : t34.arc_length > e2.arc_length ? 1 : 0;
}
function jF(t34) {
if (t34.int_points1.length < 2)
return;
let e2, n2, o2, i2, r2 = false;
for (let s2 = 0;s2 < t34.int_points1_sorted.length; s2++)
if (t34.int_points1_sorted[s2].id !== -1) {
e2 = t34.int_points1_sorted[s2], n2 = t34.int_points2[e2.id];
for (let a2 = s2 + 1;a2 < t34.int_points1_sorted.length && (o2 = t34.int_points1_sorted[a2], ZB(o2.arc_length, e2.arc_length)); a2++)
o2.id !== -1 && (i2 = t34.int_points2[o2.id], i2.id !== -1 && o2.edge_before === e2.edge_before && o2.edge_after === e2.edge_after && i2.edge_before === n2.edge_before && i2.edge_after === n2.edge_after && (o2.id = -1, i2.id = -1, r2 = true));
}
n2 = t34.int_points2_sorted[0], e2 = t34.int_points1[n2.id];
for (let o3 = 1;o3 < t34.int_points2_sorted.length; o3++) {
let i3 = t34.int_points2_sorted[o3];
if (i3.id === -1)
continue;
if (n2.id === -1 || !ZB(i3.arc_length, n2.arc_length)) {
n2 = i3, e2 = t34.int_points1[n2.id];
continue;
}
let s2 = t34.int_points1[i3.id];
s2.edge_before === e2.edge_before && s2.edge_after === e2.edge_after && i3.edge_before === n2.edge_before && i3.edge_after === n2.edge_after && (s2.id = -1, i3.id = -1, r2 = true);
}
r2 && (t34.int_points1 = t34.int_points1.filter((t35) => t35.id >= 0), t34.int_points2 = t34.int_points2.filter((t35) => t35.id >= 0), t34.int_points1.forEach((t35, e3) => t35.id = e3), t34.int_points2.forEach((t35, e3) => t35.id = e3));
}
function $F(t34) {
for (let e2 of t34)
e2.edge_before && (e2.edge_before.bvStart = undefined, e2.edge_before.bvEnd = undefined, e2.edge_before.bv = undefined, e2.edge_before.overlap = undefined), e2.edge_after && (e2.edge_after.bvStart = undefined, e2.edge_after.bvEnd = undefined, e2.edge_after.bv = undefined, e2.edge_after.overlap = undefined);
for (let e2 of t34)
e2.edge_before && (e2.edge_before.bvEnd = 2), e2.edge_after && (e2.edge_after.bvStart = 2);
}
function YF(t34, e2) {
for (let n2 of t34)
n2.edge_before && n2.edge_before.setInclusion(e2), n2.edge_after && n2.edge_after.setInclusion(e2);
}
function XF(t34, e2, n2) {
let o2, i2, r2 = 1;
if (t34.length === 1)
return 1;
o2 = t34[e2];
for (let s2 = e2 + 1;s2 < t34.length && o2.face === n2 && (i2 = t34[s2], i2.pt.equalTo(o2.pt) && i2.edge_before === o2.edge_before && i2.edge_after === o2.edge_after); s2++)
r2++;
return r2;
}
function WF(t34, e2) {
if (e2) {
for (let n2 of e2) {
let e3 = n2.edge_before;
if (n2.is_vertex = 0, e3.shape.start && e3.shape.start.equalTo(n2.pt) && (n2.is_vertex |= 1), e3.shape.end && e3.shape.end.equalTo(n2.pt) && (n2.is_vertex |= 2), 1 & n2.is_vertex) {
n2.edge_before = e3.prev, e3.prev && (n2.is_vertex = 2);
continue;
}
if (2 & n2.is_vertex)
continue;
let o2 = t34.addVertex(n2.pt, e3);
n2.edge_before = o2;
}
for (let n2 of e2)
n2.edge_before ? n2.edge_after = n2.edge_before.next : t34 instanceof DF && 1 & n2.is_vertex && (n2.edge_after = t34.first);
}
}
function VF(t34, e2, n2) {
const o2 = t34.edge_before, i2 = e2.edge_after, r2 = n2.length;
o2.next = n2[0], n2[0].prev = o2, n2[r2 - 1].next = i2, i2.prev = n2[r2 - 1];
}
QB.multiline = (...t34) => new QB.Multiline(...t34);
var { INSIDE: HF, OUTSIDE: GF, BOUNDARY: UF, OVERLAP_SAME: ZF, OVERLAP_OPPOSITE: qF } = WB;
var { NOT_VERTEX: JF, START_VERTEX: QF, END_VERTEX: KF } = WB;
function tj(t34, e2) {
let n2 = e2.clone().reverse(), [o2] = sj(t34, n2, 3, true);
return o2;
}
function ej(t34, e2) {
let [n2] = sj(t34, e2, 2, true);
return n2;
}
function nj(t34, e2) {
let [n2, o2] = sj(t34, e2, 2, false), i2 = [];
for (let t35 of n2.faces)
i2 = [...i2, ...[...t35.edges].map((t36) => t36.shape)];
let r2 = [];
for (let t35 of o2.faces)
r2 = [...r2, ...[...t35.edges].map((t36) => t36.shape)];
return [i2, r2];
}
function oj(t34, e2) {
let [n2] = sj(t34, e2, 3, false), i2 = [];
for (let t35 of n2.faces)
i2 = [...i2, ...[...t35.edges].map((t36) => t36.shape)];
return i2;
}
function ij(t34, e2) {
let n2 = t34.clone(), o2 = e2.clone(), i2 = aj(n2, o2);
return zF(i2), WF(n2, i2.int_points1_sorted), WF(o2, i2.int_points2_sorted), jF(i2), zF(i2), [i2.int_points1_sorted.map((t35) => t35.pt), i2.int_points2_sorted.map((t35) => t35.pt)];
}
function rj(t34, e2, n2, o2) {
let i2 = cj(t34, n2.int_points1), r2 = cj(e2, n2.int_points2);
for (lj(i2, e2), lj(r2, t34), $F(n2.int_points1), $F(n2.int_points2), YF(n2.int_points1, e2), YF(n2.int_points2, t34);hj(t34, e2, n2.int_points1, n2.int_points1_sorted, n2.int_points2, n2); )
;
((function(t35) {
let e3, n3, o3, i3 = t35.int_points1.length;
for (let r3 = 0;r3 < i3; r3++) {
let s2 = t35.int_points1_sorted[r3];
s2.face !== e3 && (n3 = r3, e3 = s2.face);
let a2, c2 = r3, l2 = XF(t35.int_points1_sorted, r3, e3);
a2 = c2 + l2 < i3 && t35.int_points1_sorted[c2 + l2].face === e3 ? c2 + l2 : n3;
let h2 = XF(t35.int_points1_sorted, a2, e3);
o3 = null;
for (let n4 = a2;n4 < a2 + h2; n4++) {
let i4 = t35.int_points1_sorted[n4];
if (i4.face === e3 && t35.int_points2[i4.id].face === t35.int_points2[s2.id].face) {
o3 = i4;
break;
}
}
if (o3 === null)
continue;
let d2 = s2.edge_after, u2 = o3.edge_before;
if (d2.bv !== 2 || u2.bv !== 2)
continue;
if (d2 !== u2)
continue;
let p2 = t35.int_points2[s2.id], m2 = t35.int_points2[o3.id], g2 = p2.edge_after, f2 = m2.edge_before;
g2.bv === 2 && f2.bv === 2 && g2 === f2 || (p2 = t35.int_points2[o3.id], m2 = t35.int_points2[s2.id], g2 = p2.edge_after, f2 = m2.edge_before), g2.bv === 2 && f2.bv === 2 && g2 === f2 && d2.setOverlap(g2);
}
}))(n2), dj(t34, o2, n2.int_points1_sorted, true), dj(e2, o2, n2.int_points2_sorted, false), mj(t34, i2, o2, true), mj(e2, r2, o2, false);
}
function sj(t34, e2, n2, o2) {
let i2 = t34.clone(), r2 = e2.clone(), s2 = aj(i2, r2);
return zF(s2), WF(i2, s2.int_points1_sorted), WF(r2, s2.int_points2_sorted), jF(s2), zF(s2), rj(i2, r2, s2, n2), o2 && function(t35, e3, n3) {
((function(t36, e4, n4, o3) {
for (let n5 of e4.faces) {
for (let e5 of n5)
t36.edges.add(e5);
o3.find((t37) => t37.face === n5) === undefined && t36.addFace(n5.first, n5.last);
}
}))(t35, e3, 0, n3.int_points2), function(t36, e4, n4) {
if (n4.int_points1.length !== 0)
for (let t37 = 0;t37 < n4.int_points1.length; t37++) {
let e5 = n4.int_points1[t37], o3 = n4.int_points2[t37];
if (e5.edge_before !== undefined && e5.edge_after === undefined && o3.edge_before === undefined && o3.edge_after !== undefined && (e5.edge_before.next = o3.edge_after, o3.edge_after.prev = e5.edge_before, e5.edge_after = o3.edge_after, o3.edge_before = e5.edge_before), o3.edge_before !== undefined && o3.edge_after === undefined && e5.edge_before === undefined && e5.edge_after !== undefined && (o3.edge_before.next = e5.edge_after, e5.edge_after.prev = o3.edge_before, o3.edge_after = e5.edge_after, e5.edge_before = o3.edge_before), e5.edge_before !== undefined && e5.edge_after === undefined)
for (let t38 of n4.int_points1_sorted)
t38 !== e5 && t38.edge_before === undefined && t38.edge_after !== undefined && t38.pt.equalTo(e5.pt) && (e5.edge_before.next = t38.edge_after, t38.edge_after.prev = e5.edge_before, e5.edge_after = t38.edge_after, t38.edge_before = e5.edge_before);
if (o3.edge_before !== undefined && o3.edge_after === undefined)
for (let t38 of n4.int_points2_sorted)
t38 !== o3 && t38.edge_before === undefined && t38.edge_after !== undefined && t38.pt.equalTo(o3.pt) && (o3.edge_before.next = t38.edge_after, t38.edge_after.prev = o3.edge_before, o3.edge_after = t38.edge_after, t38.edge_before = o3.edge_before);
}
}(0, 0, n3), uj(t35, n3.int_points1), uj(e3, n3.int_points2), pj(t35, n3.int_points1, n3.int_points2), pj(t35, n3.int_points2, n3.int_points1);
}(i2, r2, s2), [i2, r2];
}
function aj(t34, e2) {
let n2 = { int_points1: [], int_points2: [] };
for (let o2 of t34.edges) {
let t35 = e2.edges.search(o2.box);
for (let e3 of t35) {
let t36 = o2.shape.intersect(e3.shape);
for (let i2 of t36)
LF(o2, i2, n2.int_points1), LF(e3, i2, n2.int_points2);
}
}
return n2;
}
function cj(t34, e2) {
let n2 = [];
for (let o2 of t34.faces)
e2.find((t35) => t35.face === o2) || n2.push(o2);
return n2;
}
function lj(t34, e2) {
for (let n2 of t34)
n2.first.bv = n2.first.bvStart = n2.first.bvEnd = undefined, n2.first.setInclusion(e2);
}
function hj(t34, e2, n2, o2, i2, r2) {
let s2, a2, c2, l2 = o2.length, h2 = false;
for (let d2 = 0;d2 < l2; d2++) {
let u2 = o2[d2];
u2.face !== s2 && (a2 = d2, s2 = u2.face);
let p2, m2 = d2, g2 = XF(o2, d2, s2);
p2 = m2 + g2 < l2 && o2[m2 + g2].face === s2 ? m2 + g2 : a2;
let f2 = XF(o2, p2, s2);
c2 = null;
for (let t35 = p2;t35 < p2 + f2; t35++) {
let e3 = o2[t35];
if (e3.face === s2 && i2[e3.id].face === i2[u2.id].face) {
c2 = e3;
break;
}
}
if (c2 === null)
continue;
let y2 = u2.edge_after, _2 = c2.edge_before;
if (y2.bv !== UF || _2.bv == UF)
if (y2.bv == UF || _2.bv !== UF) {
if (y2.bv === UF && _2.bv === UF && y2 != _2 || y2.bv === HF && _2.bv === GF || y2.bv === GF && _2.bv === HF) {
let t35 = y2.next;
for (;t35 != _2; )
t35.bvStart = undefined, t35.bvEnd = undefined, t35.bv = undefined, t35.setInclusion(e2), t35 = t35.next;
}
if (y2.bv === UF && _2.bv === UF && y2 != _2) {
let t35, e3 = y2.next;
for (;e3 != _2; ) {
if (e3.bv != UF) {
if (t35 === undefined)
t35 = e3.bv;
else if (e3.bv != t35)
throw KB.UNRESOLVED_BOUNDARY_CONFLICT;
}
e3 = e3.next;
}
t35 != null && (y2.bv = t35, _2.bv = t35);
continue;
}
if (y2.bv === HF && _2.bv === GF || y2.bv === GF && _2.bv === HF) {
let o3 = y2;
for (;o3 != _2; ) {
if (o3.bvStart === y2.bv && o3.bvEnd === _2.bv) {
let [s3, a3] = o3.shape.distanceTo(e2);
if (s3 < 10 * QB.DP_TOL) {
LF(o3, a3.ps, n2);
let s4 = n2[n2.length - 1];
if (s4.is_vertex & QF)
s4.edge_after = o3, s4.edge_before = o3.prev, o3.bvStart = UF, o3.bv = undefined, o3.setInclusion(e2);
else if (s4.is_vertex & KF)
s4.edge_after = o3.next, o3.bvEnd = UF, o3.bv = undefined, o3.setInclusion(e2);
else {
let t35 = e2.addVertex(s4.pt, o3);
s4.edge_before = t35, s4.edge_after = t35.next, t35.setInclusion(e2), t35.next.bvStart = UF, t35.next.bvEnd = undefined, t35.next.bv = undefined, t35.next.setInclusion(e2);
}
let c3 = e2.findEdgeByPoint(a3.pe);
LF(c3, a3.pe, i2);
let l3 = i2[i2.length - 1];
if (l3.is_vertex & QF)
l3.edge_after = c3, l3.edge_before = c3.prev;
else if (l3.is_vertex & KF)
l3.edge_after = c3.next;
else {
let n3 = i2.find((t35) => t35.edge_after === c3), o4 = e2.addVertex(l3.pt, c3);
l3.edge_before = o4, l3.edge_after = o4.next, n3 && (n3.edge_after = o4), o4.bvStart = undefined, o4.bvEnd = UF, o4.bv = undefined, o4.setInclusion(t34), o4.next.bvStart = UF, o4.next.bvEnd = undefined, o4.next.bv = undefined, o4.next.setInclusion(t34);
}
zF(r2), h2 = true;
break;
}
}
o3 = o3.next;
}
if (h2)
break;
throw KB.UNRESOLVED_BOUNDARY_CONFLICT;
}
} else
_2.bv = y2.bv;
else
y2.bv = _2.bv;
}
return h2;
}
function dj(t34, e2, n2, o2) {
if (!n2)
return;
let i2, r2, s2, a2;
for (let c2 = 0;c2 < n2.length; c2++) {
if (s2 = n2[c2], s2.face !== i2 && (r2 = c2, i2 = s2.face), i2.isEmpty())
continue;
let l2, h2 = c2, d2 = XF(n2, c2, i2);
l2 = h2 + d2 < n2.length && n2[h2 + d2].face === s2.face ? h2 + d2 : r2, a2 = n2[l2];
let u2 = l2, p2 = XF(n2, u2, i2), m2 = s2.edge_after, g2 = a2.edge_before;
if (m2.bv === HF && g2.bv === HF && e2 === 1 || m2.bv === GF && g2.bv === GF && e2 === 2 || (m2.bv === GF || g2.bv === GF) && e2 === 3 && !o2 || (m2.bv === HF || g2.bv === HF) && e2 === 3 && o2 || m2.bv === UF && g2.bv === UF && m2.overlap & ZF && o2 || m2.bv === UF && g2.bv === UF && m2.overlap & qF) {
t34.removeChain(i2, m2, g2);
for (let t35 = h2;t35 < h2 + d2; t35++)
n2[t35].edge_after = undefined;
for (let t35 = u2;t35 < u2 + p2; t35++)
n2[t35].edge_before = undefined;
}
c2 += d2 - 1;
}
}
function uj(t34, e2) {
for (let n2 of e2)
t34.faces.delete(n2.face), n2.face = undefined, n2.edge_before && (n2.edge_before.face = undefined), n2.edge_after && (n2.edge_after.face = undefined);
}
function pj(t34, e2, n2) {
for (let o2 of e2) {
if (o2.edge_before === undefined || o2.edge_after === undefined)
continue;
if (o2.face)
continue;
if (o2.edge_after.face || o2.edge_before.face)
continue;
let { edge_after: i2, edge_before: r2 } = o2;
try {
tF.testInfiniteLoop(i2);
} catch (t35) {
throw KB.CANNOT_COMPLETE_BOOLEAN_OPERATION;
}
let s2 = t34.addFace(i2, r2);
for (let t35 of e2)
t35.edge_before && t35.edge_after && t35.edge_before.face === s2 && t35.edge_after.face === s2 && (t35.face = s2);
for (let t35 of n2)
t35.edge_before && t35.edge_after && t35.edge_before.face === s2 && t35.edge_after.face === s2 && (t35.face = s2);
}
}
function mj(t34, e2, n2, o2) {
for (let i2 of e2) {
let e3 = i2.first.bv;
(n2 === 1 && e3 === HF || n2 === 3 && e3 === HF && o2 || n2 === 3 && e3 === GF && !o2 || n2 === 2 && e3 === GF) && t34.deleteFace(i2);
}
}
var gj = Object.freeze({ __proto__: null, BOOLEAN_INTERSECT: 2, BOOLEAN_SUBTRACT: 3, BOOLEAN_UNION: 1, calculateIntersections: ij, innerClip: nj, intersect: ej, outerClip: oj, removeNotRelevantChains: dj, removeOldFaces: uj, restoreFaces: pj, subtract: tj, unify: function(t34, e2) {
let [n2] = sj(t34, e2, 1, true);
return n2;
} });
var fj = RegExp("T.F..FFF.|T.F...F..");
var yj = RegExp("T........|.T.......|...T.....|....T....");
var _j = RegExp("FT.......|F..T.....|F...T....");
var bj = RegExp("T.F..F...");
var xj = RegExp("T.F..F...|.TF..F...|..FT.F...|..F.TF...");
var vj = class {
constructor() {
this.m = new Array(9).fill(undefined);
}
get I2I() {
return this.m[0];
}
set I2I(t34) {
this.m[0] = t34;
}
get I2B() {
return this.m[1];
}
set I2B(t34) {
this.m[1] = t34;
}
get I2E() {
return this.m[2];
}
set I2E(t34) {
this.m[2] = t34;
}
get B2I() {
return this.m[3];
}
set B2I(t34) {
this.m[3] = t34;
}
get B2B() {
return this.m[4];
}
set B2B(t34) {
this.m[4] = t34;
}
get B2E() {
return this.m[5];
}
set B2E(t34) {
this.m[5] = t34;
}
get E2I() {
return this.m[6];
}
set E2I(t34) {
this.m[6] = t34;
}
get E2B() {
return this.m[7];
}
set E2B(t34) {
this.m[7] = t34;
}
get E2E() {
return this.m[8];
}
set E2E(t34) {
this.m[8] = t34;
}
toString() {
return this.m.map((t34) => t34 instanceof Array && t34.length > 0 ? "T" : t34 instanceof Array && t34.length === 0 ? "F" : "*").join("");
}
equal() {
return fj.test(this.toString());
}
intersect() {
return yj.test(this.toString());
}
touch() {
return _j.test(this.toString());
}
inside() {
return bj.test(this.toString());
}
covered() {
return xj.test(this.toString());
}
};
function Ij(t34, e2) {
let n2, o2 = new QB.Ray(e2), i2 = new QB.Line(o2.pt, o2.norm);
const r2 = new QB.Box(o2.box.xmin - QB.DP_TOL, o2.box.ymin - QB.DP_TOL, o2.box.xmax + QB.DP_TOL, o2.box.ymax + QB.DP_TOL);
if (t34.box.not_intersect(r2))
return QB.OUTSIDE;
let s2 = t34.edges.search(r2);
if (s2.length === 0)
return QB.OUTSIDE;
for (let t35 of s2)
if (t35.shape.contains(e2))
return QB.BOUNDARY;
let a2 = [...t34.faces], c2 = [];
for (let t35 of s2)
for (let n3 of o2.intersect(t35.shape)) {
if (n3.equalTo(e2))
return QB.BOUNDARY;
c2.push({ pt: n3, edge: t35, face_index: a2.indexOf(t35.face) });
}
c2.sort((t35, e3) => JB(t35.pt.x, e3.pt.x) ? -1 : qB(t35.pt.x, e3.pt.x) ? 1 : t35.face_index < e3.face_index ? -1 : t35.face_index > e3.face_index ? 1 : t35.edge.arc_length < e3.edge.arc_length ? -1 : t35.edge.arc_length > e3.edge.arc_length ? 1 : 0);
let l2 = 0;
for (let t35 = 0;t35 < c2.length; t35++) {
let e3 = c2[t35];
if (e3.pt.equalTo(e3.edge.shape.start)) {
if (t35 > 0 && e3.pt.equalTo(c2[t35 - 1].pt) && e3.face_index === c2[t35 - 1].face_index && e3.edge.prev === c2[t35 - 1].edge)
continue;
let n3 = e3.edge.prev;
for (;UB(n3.length); )
n3 = n3.prev;
let o3 = n3.shape.tangentInEnd(), r3 = e3.pt.translate(o3), s3 = e3.edge.shape.tangentInStart(), a3 = e3.pt.translate(s3), h2 = r3.leftTo(i2), d2 = a3.leftTo(i2);
(h2 && !d2 || !h2 && d2) && l2++;
} else if (e3.pt.equalTo(e3.edge.shape.end)) {
if (t35 > 0 && e3.pt.equalTo(c2[t35 - 1].pt) && e3.face_index === c2[t35 - 1].face_index && e3.edge.next === c2[t35 - 1].edge)
continue;
let n3 = e3.edge.next;
for (;UB(n3.length); )
n3 = n3.next;
let o3 = n3.shape.tangentInStart(), r3 = e3.pt.translate(o3), s3 = e3.edge.shape.tangentInEnd(), a3 = e3.pt.translate(s3), h2 = r3.leftTo(i2), d2 = a3.leftTo(i2);
(h2 && !d2 || !h2 && d2) && l2++;
} else if (e3.edge.shape instanceof QB.Segment)
l2++;
else {
let t36 = e3.edge.shape.box;
ZB(e3.pt.y, t36.ymin) || ZB(e3.pt.y, t36.ymax) || l2++;
}
}
return n2 = l2 % 2 == 1 ? 1 : 0, n2;
}
function Sj(t34, e2) {
return Nj(t34, e2).intersect();
}
function Cj(t34, e2) {
return Nj(t34, e2).inside();
}
function Pj(t34, e2) {
return Nj(t34, e2).covered();
}
function Mj(t34, e2) {
return Pj(e2, t34);
}
function Nj(t34, e2) {
return t34 instanceof QB.Line && e2 instanceof QB.Line ? function(t35, e3) {
let n2 = new vj, o2 = iF(t35, e3);
o2.length === 0 ? t35.contains(e3.pt) && e3.contains(t35.pt) ? (n2.I2I = [t35], n2.I2E = [], n2.E2I = []) : (n2.I2I = [], n2.I2E = [t35], n2.E2I = [e3]) : (n2.I2I = o2, n2.I2E = t35.split(o2), n2.E2I = e3.split(o2));
return n2;
}(t34, e2) : t34 instanceof QB.Line && e2 instanceof QB.Circle ? function(t35, e3) {
let n2 = new vj, o2 = rF(t35, e3);
if (o2.length === 0)
n2.I2I = [], n2.I2B = [], n2.I2E = [t35], n2.E2I = [e3];
else if (o2.length === 1)
n2.I2I = [], n2.I2B = o2, n2.I2E = t35.split(o2), n2.E2I = [e3];
else {
let i2 = new DF([t35]), r2 = t35.sortPoints(o2);
i2.split(r2);
let s2 = i2.toShapes();
n2.I2I = [s2[1]], n2.I2B = r2, n2.I2E = [s2[0], s2[2]], n2.E2I = new QB.Polygon([e3.toArc()]).cutWithLine(t35);
}
return n2;
}(t34, e2) : t34 instanceof QB.Line && e2 instanceof QB.Box ? function(t35, e3) {
let n2 = new vj, o2 = sF(t35, e3);
if (o2.length === 0)
n2.I2I = [], n2.I2B = [], n2.I2E = [t35], n2.E2I = [e3];
else if (o2.length === 1)
n2.I2I = [], n2.I2B = o2, n2.I2E = t35.split(o2), n2.E2I = [e3];
else {
let i2 = new DF([t35]), r2 = t35.sortPoints(o2);
i2.split(r2);
let s2 = i2.toShapes();
e3.toSegments().some((t36) => t36.contains(o2[0]) && t36.contains(o2[1])) ? (n2.I2I = [], n2.I2B = [s2[1]], n2.I2E = [s2[0], s2[2]], n2.E2I = [e3]) : (n2.I2I = [s2[1]], n2.I2B = r2, n2.I2E = [s2[0], s2[2]], n2.E2I = new QB.Polygon(e3.toSegments()).cutWithLine(t35));
}
return n2;
}(t34, e2) : t34 instanceof QB.Line && e2 instanceof QB.Polygon ? function(t35, e3) {
let n2 = new vj, o2 = IF(t35, e3), i2 = new DF([t35]), r2 = o2.length > 0 ? o2.slice() : t35.sortPoints(o2);
return i2.split(r2), [...i2].forEach((t36) => t36.setInclusion(e3)), n2.I2I = [...i2].filter((t36) => t36.bv === QB.INSIDE).map((t36) => t36.shape), n2.I2B = [...i2].slice(1).map((t36) => t36.bv === QB.BOUNDARY ? t36.shape : t36.shape.start), n2.I2E = [...i2].filter((t36) => t36.bv === QB.OUTSIDE).map((t36) => t36.shape), n2.E2I = e3.cutWithLine(t35), n2;
}(t34, e2) : (t34 instanceof QB.Segment || t34 instanceof QB.Arc) && e2 instanceof QB.Polygon ? wj(t34, e2) : (t34 instanceof QB.Segment || t34 instanceof QB.Arc) && (e2 instanceof QB.Circle || e2 instanceof QB.Box) ? wj(t34, new QB.Polygon(e2)) : t34 instanceof QB.Polygon && e2 instanceof QB.Polygon ? Tj(t34, e2) : (t34 instanceof QB.Circle || t34 instanceof QB.Box) && (e2 instanceof QB.Circle || e2 instanceof QB.Box) ? Tj(new QB.Polygon(t34), new QB.Polygon(e2)) : (t34 instanceof QB.Circle || t34 instanceof QB.Box) && e2 instanceof QB.Polygon ? Tj(new QB.Polygon(t34), e2) : t34 instanceof QB.Polygon && (e2 instanceof QB.Circle || e2 instanceof QB.Box) ? Tj(t34, new QB.Polygon(e2)) : undefined;
}
function wj(t34, e2) {
let n2 = new vj, o2 = function(t35, e3) {
return t35 instanceof QB.Line ? IF(t35, e3) : t35 instanceof QB.Segment ? xF(t35, e3) : t35 instanceof QB.Arc ? vF(t35, e3) : [];
}(t34, e2), i2 = o2.length > 0 ? o2.slice() : t34.sortPoints(o2), r2 = new DF([t34]);
r2.split(i2), [...r2].forEach((t35) => t35.setInclusion(e2)), n2.I2I = [...r2].filter((t35) => t35.bv === QB.INSIDE).map((t35) => t35.shape), n2.I2B = [...r2].slice(1).map((t35) => t35.bv === QB.BOUNDARY ? t35.shape : t35.shape.start), n2.I2E = [...r2].filter((t35) => t35.bv === QB.OUTSIDE).map((t35) => t35.shape), n2.B2I = [], n2.B2B = [], n2.B2E = [];
for (let o3 of [t34.start, t34.end])
switch (Ij(e2, o3)) {
case QB.INSIDE:
n2.B2I.push(o3);
break;
case QB.BOUNDARY:
n2.B2B.push(o3);
break;
case QB.OUTSIDE:
n2.B2E.push(o3);
}
return n2;
}
function Tj(t34, e2) {
let n2 = new vj, [o2, i2] = ij(t34, e2), r2 = ej(t34, e2), s2 = tj(t34, e2), a2 = tj(e2, t34), [c2, l2] = nj(t34, e2), h2 = oj(t34, e2), d2 = oj(e2, t34);
return n2.I2I = r2.isEmpty() ? [] : [r2], n2.I2B = l2, n2.I2E = s2.isEmpty() ? [] : [s2], n2.B2I = c2, n2.B2B = o2, n2.B2E = h2, n2.E2I = a2.isEmpty() ? [] : [a2], n2.E2B = d2, n2;
}
var Rj = Object.freeze({ __proto__: null, contain: function(t34, e2) {
return Cj(e2, t34);
}, cover: Mj, covered: Pj, disjoint: function(t34, e2) {
return !Sj(t34, e2);
}, equal: function(t34, e2) {
return Nj(t34, e2).equal();
}, inside: Cj, intersect: Sj, relate: Nj, touch: function(t34, e2) {
return Nj(t34, e2).touch();
} });
var Ej = class t34 {
constructor(t35 = 1, e2 = 0, n2 = 0, o2 = 1, i2 = 0, r2 = 0) {
this.a = t35, this.b = e2, this.c = n2, this.d = o2, this.tx = i2, this.ty = r2;
}
fromMatrix3x3(e2) {
const [n2, o2, i2] = e2[0], [r2, s2, a2] = e2[1];
return new t34(n2, r2, o2, s2, i2, a2);
}
toMatrix3x3() {
return [[this.a, this.c, this.tx], [this.b, this.d, this.ty], [0, 0, 1]];
}
clone() {
return new t34(this.a, this.b, this.c, this.d, this.tx, this.ty);
}
transform(t35) {
return [t35[0] * this.a + t35[1] * this.c + this.tx, t35[0] * this.b + t35[1] * this.d + this.ty];
}
multiply(e2) {
return new t34(this.a * e2.a + this.c * e2.b, this.b * e2.a + this.d * e2.b, this.a * e2.c + this.c * e2.d, this.b * e2.c + this.d * e2.d, this.a * e2.tx + this.c * e2.ty + this.tx, this.b * e2.tx + this.d * e2.ty + this.ty);
}
translate(...e2) {
let n2, o2;
if (e2.length != 1 || isNaN(e2[0].x) || isNaN(e2[0].y)) {
if (e2.length !== 2 || typeof e2[0] != "number" || typeof e2[1] != "number")
throw KB.ILLEGAL_PARAMETERS;
n2 = e2[0], o2 = e2[1];
} else
n2 = e2[0].x, o2 = e2[0].y;
return this.multiply(new t34(1, 0, 0, 1, n2, o2));
}
rotate(e2, n2 = 0, o2 = 0) {
let i2 = Math.cos(e2), r2 = Math.sin(e2);
return this.translate(n2, o2).multiply(new t34(i2, r2, -r2, i2, 0, 0)).translate(-n2, -o2);
}
scale(e2, n2) {
return this.multiply(new t34(e2, 0, 0, n2, 0, 0));
}
equalTo(t35) {
return !!QB.Utils.EQ(this.tx, t35.tx) && (!!QB.Utils.EQ(this.ty, t35.ty) && (!!QB.Utils.EQ(this.a, t35.a) && (!!QB.Utils.EQ(this.b, t35.b) && (!!QB.Utils.EQ(this.c, t35.c) && !!QB.Utils.EQ(this.d, t35.d)))));
}
};
QB.Matrix = Ej;
QB.matrix = (...t35) => new QB.Matrix(...t35);
var Aj = class {
constructor(t35, e2) {
this.low = t35, this.high = e2;
}
get max() {
return this.clone();
}
less_than(t35) {
return this.low < t35.low || this.low === t35.low && this.high < t35.high;
}
equal_to(t35) {
return this.low === t35.low && this.high === t35.high;
}
intersect(t35) {
return !this.not_intersect(t35);
}
not_intersect(t35) {
return this.high < t35.low || t35.high < this.low;
}
merge(t35) {
const e2 = this.low === undefined ? t35.low : this.low < t35.low ? this.low : t35.low, n2 = this.high === undefined ? t35.high : this.high > t35.high ? this.high : t35.high, o2 = this.clone();
return o2.low = e2, o2.high = n2, o2;
}
output() {
return [this.low, this.high];
}
comparable_less_than(t35, e2) {
return t35 < e2;
}
};
var Oj = class t35 extends Aj {
clone() {
return new t35(this.low, this.high);
}
};
var kj = class {
constructor(t36, e2, n2 = null, o2 = null, i2 = null, r2 = 0) {
if (this.left = n2, this.right = o2, this.parent = i2, this.color = r2, this.item = { key: undefined, values: [] }, e2 !== undefined && this.item.values.push(e2), t36 !== undefined)
if (Array.isArray(t36)) {
const [e3, n3] = t36;
if (!Number.isNaN(e3) && !Number.isNaN(n3)) {
let t37 = e3, o3 = n3;
t37 > o3 && ([t37, o3] = [o3, t37]), this.item.key = new Oj(t37, o3);
}
} else
this.item.key = t36;
this.max = this.item.key ? this.item.key.max : undefined;
}
isNil() {
return this.item.key === undefined && this.item.values.length === 0 && this.left === null && this.right === null && this.color === 0;
}
requireKey() {
if (!this.item.key)
throw new Error("Node key is undefined (nil/sentinel). Operation is not applicable.");
return this.item.key;
}
less_than(t36) {
const e2 = this.requireKey(), n2 = t36.requireKey();
return e2.less_than(n2);
}
_value_equal(t36) {
const e2 = this.item.values[0], n2 = t36.item.values[0];
return e2 && n2 && e2.equal_to ? e2.equal_to(n2) : e2 === n2;
}
equal_to(t36) {
const e2 = this.requireKey(), n2 = t36.requireKey();
return e2.equal_to(n2);
}
intersect(t36) {
const e2 = this.requireKey(), n2 = t36.requireKey();
return e2.intersect(n2);
}
copy_data(t36) {
this.item.key = t36.item.key, this.item.values = t36.item.values.slice();
}
update_max() {
this.max = this.item.key ? this.item.key.max : undefined, this.right && this.right.max && (this.max = this.max ? this.max.merge(this.right.max) : this.right.max), this.left && this.left.max && (this.max = this.max ? this.max.merge(this.left.max) : this.left.max);
}
not_intersect_left_subtree(t36) {
if (!this.left)
return true;
const e2 = this.left.max ? this.left.max.high : this.left.item.key.high, n2 = this.requireKey(), o2 = t36.requireKey();
return n2.comparable_less_than(e2, o2.low);
}
not_intersect_right_subtree(t36) {
if (!this.right)
return true;
const e2 = this.right.max ? this.right.max.low : this.right.item.key.low, n2 = this.requireKey(), o2 = t36.requireKey();
return n2.comparable_less_than(o2.high, e2);
}
};
var Dj = class t36 {
constructor() {
this.root = null, this.nil_node = new kj;
}
get size() {
let t37 = 0;
return this.tree_walk(this.root, (e2) => t37 += e2.item.values.length), t37;
}
get keys() {
const t37 = [];
return this.tree_walk(this.root, (e2) => t37.push(e2.item.key.output())), t37;
}
get values() {
const t37 = [];
return this.tree_walk(this.root, (e2) => {
for (const n2 of e2.item.values)
t37.push(n2);
}), t37;
}
get items() {
const t37 = [];
return this.tree_walk(this.root, (e2) => {
const n2 = e2.item.key.output();
for (const o2 of e2.item.values)
t37.push({ key: n2, value: o2 });
}), t37;
}
isEmpty() {
return this.root == null || this.root === this.nil_node;
}
clear() {
this.root = null;
}
insert(t37, e2 = t37) {
if (t37 === undefined)
return;
const n2 = this.tree_search(this.root, new kj(t37));
if (n2)
return n2.item.values.push(e2), n2;
const o2 = new kj(t37, e2, this.nil_node, this.nil_node, null, 1);
return this.tree_insert(o2), this.recalc_max(o2), o2;
}
exist(t37, e2 = t37) {
const n2 = this.tree_search(this.root, new kj(t37));
return !!n2 && (arguments.length < 2 || e2 === t37 || n2.item.values.some((t38) => t38 && t38.equal_to ? t38.equal_to(e2) : t38 === e2));
}
remove(t37, e2 = t37) {
const n2 = this.tree_search(this.root, new kj(t37));
if (!n2)
return;
if (arguments.length < 2)
return this.tree_delete(n2), n2;
const o2 = n2.item.values.findIndex((t38) => t38 && t38.equal_to ? t38.equal_to(e2) : t38 === e2);
return o2 >= 0 ? (n2.item.values.splice(o2, 1), n2.item.values.length === 0 && this.tree_delete(n2), n2) : undefined;
}
search(t37, e2 = (t38, e3) => t38 === e3 ? e3.output() : t38) {
const n2 = new kj(t37), o2 = [];
this.tree_search_interval(this.root, n2, o2);
const i2 = [];
for (const t38 of o2)
for (const n3 of t38.item.values)
i2.push(e2(n3, t38.item.key));
return i2;
}
intersect_any(t37) {
const e2 = new kj(t37);
return this.tree_find_any_interval(this.root, e2);
}
forEach(t37) {
this.tree_walk(this.root, (e2) => {
for (const n2 of e2.item.values)
t37(e2.item.key, n2);
});
}
map(e2) {
const n2 = new t36;
return this.tree_walk(this.root, (t37) => {
for (const o2 of t37.item.values)
n2.insert(t37.item.key, e2(o2, t37.item.key));
}), n2;
}
*iterate(t37, e2 = (t38, e3) => t38 === e3 ? e3.output() : t38) {
let n2 = null;
for (t37 ? n2 = this.tree_search_nearest_forward(this.root, new kj(t37)) : this.root && (n2 = this.local_minimum(this.root));n2; ) {
for (const t38 of n2.item.values)
yield e2(t38, n2.item.key);
n2 = this.tree_successor(n2);
}
}
recalc_max(t37) {
let e2 = t37;
for (;e2.parent != null; )
e2.parent.update_max(), e2 = e2.parent;
}
tree_insert(t37) {
let e2 = this.root, n2 = null;
if (this.root == null || this.root === this.nil_node)
this.root = t37;
else {
for (;e2 !== this.nil_node; )
n2 = e2, e2 = t37.less_than(e2) ? e2.left : e2.right;
t37.parent = n2, t37.less_than(n2) ? n2.left = t37 : n2.right = t37;
}
this.insert_fixup(t37);
}
insert_fixup(t37) {
let e2, n2;
for (e2 = t37;e2 !== this.root && e2.parent.color === 1; )
e2.parent === e2.parent.parent.left ? (n2 = e2.parent.parent.right, n2.color === 1 ? (e2.parent.color = 0, n2.color = 0, e2.parent.parent.color = 1, e2 = e2.parent.parent) : (e2 === e2.parent.right && (e2 = e2.parent, this.rotate_left(e2)), e2.parent.color = 0, e2.parent.parent.color = 1, this.rotate_right(e2.parent.parent))) : (n2 = e2.parent.parent.left, n2.color === 1 ? (e2.parent.color = 0, n2.color = 0, e2.parent.parent.color = 1, e2 = e2.parent.parent) : (e2 === e2.parent.left && (e2 = e2.parent, this.rotate_right(e2)), e2.parent.color = 0, e2.parent.parent.color = 1, this.rotate_left(e2.parent.parent)));
this.root.color = 0;
}
tree_delete(t37) {
let e2, n2;
e2 = t37.left === this.nil_node || t37.right === this.nil_node ? t37 : this.tree_successor(t37), n2 = e2.left !== this.nil_node ? e2.left : e2.right, n2.parent = e2.parent, e2 === this.root ? this.root = n2 : (e2 === e2.parent.left ? e2.parent.left = n2 : e2.parent.right = n2, e2.parent.update_max()), this.recalc_max(n2), e2 !== t37 && (t37.copy_data(e2), t37.update_max(), this.recalc_max(t37)), e2.color === 0 && this.delete_fixup(n2);
}
delete_fixup(t37) {
let e2, n2 = t37;
for (;n2 !== this.root && n2.parent != null && n2.color === 0; )
n2 === n2.parent.left ? (e2 = n2.parent.right, e2.color === 1 && (e2.color = 0, n2.parent.color = 1, this.rotate_left(n2.parent), e2 = n2.parent.right), e2.left.color === 0 && e2.right.color === 0 ? (e2.color = 1, n2 = n2.parent) : (e2.right.color === 0 && (e2.color = 1, e2.left.color = 0, this.rotate_right(e2), e2 = n2.parent.right), e2.color = n2.parent.color, n2.parent.color = 0, e2.right.color = 0, this.rotate_left(n2.parent), n2 = this.root)) : (e2 = n2.parent.left, e2.color === 1 && (e2.color = 0, n2.parent.color = 1, this.rotate_right(n2.parent), e2 = n2.parent.left), e2.left.color === 0 && e2.right.color === 0 ? (e2.color = 1, n2 = n2.parent) : (e2.left.color === 0 && (e2.color = 1, e2.right.color = 0, this.rotate_left(e2), e2 = n2.parent.left), e2.color = n2.parent.color, n2.parent.color = 0, e2.left.color = 0, this.rotate_right(n2.parent), n2 = this.root));
n2.color = 0;
}
tree_search(t37, e2) {
if (t37 != null && t37 !== this.nil_node)
return e2.equal_to(t37) ? t37 : e2.less_than(t37) ? this.tree_search(t37.left, e2) : this.tree_search(t37.right, e2);
}
tree_search_nearest_forward(t37, e2) {
let n2 = null, o2 = t37;
for (;o2 && o2 !== this.nil_node; )
o2.less_than(e2) ? o2.intersect(e2) ? (n2 = o2, o2 = o2.left) : o2 = o2.right : (n2 && !o2.less_than(n2) || (n2 = o2), o2 = o2.left);
return n2 || null;
}
tree_search_interval(t37, e2, n2) {
t37 != null && t37 !== this.nil_node && (t37.left === this.nil_node || t37.not_intersect_left_subtree(e2) || this.tree_search_interval(t37.left, e2, n2), t37.intersect(e2) && n2.push(t37), t37.right === this.nil_node || t37.not_intersect_right_subtree(e2) || this.tree_search_interval(t37.right, e2, n2));
}
tree_find_any_interval(t37, e2) {
let n2 = false;
return t37 != null && t37 !== this.nil_node && (t37.left === this.nil_node || t37.not_intersect_left_subtree(e2) || (n2 = this.tree_find_any_interval(t37.left, e2)), n2 || (n2 = t37.intersect(e2)), n2 || t37.right === this.nil_node || t37.not_intersect_right_subtree(e2) || (n2 = this.tree_find_any_interval(t37.right, e2))), n2;
}
local_minimum(t37) {
let e2 = t37;
for (;e2.left != null && e2.left !== this.nil_node; )
e2 = e2.left;
return e2;
}
local_maximum(t37) {
let e2 = t37;
for (;e2.right != null && e2.right !== this.nil_node; )
e2 = e2.right;
return e2;
}
tree_successor(t37) {
let e2, n2, o2;
if (t37.right !== this.nil_node)
e2 = this.local_minimum(t37.right);
else {
for (n2 = t37, o2 = t37.parent;o2 != null && o2.right === n2; )
n2 = o2, o2 = o2.parent;
e2 = o2;
}
return e2;
}
rotate_left(t37) {
const e2 = t37.right;
t37.right = e2.left, e2.left !== this.nil_node && (e2.left.parent = t37), e2.parent = t37.parent, t37 === this.root ? this.root = e2 : t37 === t37.parent.left ? t37.parent.left = e2 : t37.parent.right = e2, e2.left = t37, t37.parent = e2, t37 !== null && t37 !== this.nil_node && t37.update_max(), e2 != null && e2 !== this.nil_node && e2.update_max();
}
rotate_right(t37) {
const e2 = t37.left;
t37.left = e2.right, e2.right !== this.nil_node && (e2.right.parent = t37), e2.parent = t37.parent, t37 === this.root ? this.root = e2 : t37 === t37.parent.left ? t37.parent.left = e2 : t37.parent.right = e2, e2.right = t37, t37.parent = e2, t37 !== null && t37 !== this.nil_node && t37.update_max(), e2 != null && e2 !== this.nil_node && e2.update_max();
}
tree_walk(t37, e2) {
t37 != null && t37 !== this.nil_node && (this.tree_walk(t37.left, e2), e2(t37), this.tree_walk(t37.right, e2));
}
testRedBlackProperty() {
let t37 = true;
return this.tree_walk(this.root, function(e2) {
e2.color === 1 && (e2.left.color === 0 && e2.right.color === 0 || (t37 = false));
}), t37;
}
testBlackHeightProperty(t37) {
let e2 = 0, n2 = 0, o2 = 0;
if (t37.color === 0 && e2++, n2 = t37.left !== this.nil_node ? this.testBlackHeightProperty(t37.left) : 1, o2 = t37.right !== this.nil_node ? this.testBlackHeightProperty(t37.right) : 1, n2 !== o2)
throw new Error("Red-black height property violated");
return e2 += n2, e2;
}
};
var Lj = class extends Set {
constructor(t37) {
super(t37), this.index = new Dj, this.forEach((t38) => this.index.insert(t38));
}
add(t37) {
let e2 = this.size;
const { key: n2, value: o2 } = t37, i2 = n2 || t37.box, r2 = o2 || t37;
return super.add(r2), this.size > e2 && this.index.insert(i2, r2), this;
}
delete(t37) {
const { key: e2, value: n2 } = t37, o2 = e2 || t37.box, i2 = n2 || t37;
let r2 = super.delete(i2);
return r2 && this.index.remove(o2, i2), r2;
}
clear() {
super.clear(), this.index = new Dj;
}
search(t37) {
return this.index.search(t37);
}
hit(t37) {
let e2 = new QB.Box(t37.x - 1, t37.y - 1, t37.x + 1, t37.y + 1);
return this.index.search(e2).filter((e3) => t37.on(e3));
}
svg() {
return [...this].reduce((t37, e2) => t37 + e2.svg(), "");
}
};
QB.PlanarSet = Lj;
var zj = class {
get name() {
throw KB.CANNOT_INVOKE_ABSTRACT_METHOD;
}
get box() {
throw KB.CANNOT_INVOKE_ABSTRACT_METHOD;
}
clone() {
throw KB.CANNOT_INVOKE_ABSTRACT_METHOD;
}
translate(...t37) {
return this.transform(new Ej().translate(...t37));
}
rotate(t37, e2 = new QB.Point) {
return this.transform(new Ej().rotate(t37, e2.x, e2.y));
}
scale(t37, e2) {
return this.transform(new Ej().scale(t37, e2));
}
transform(...t37) {
throw KB.CANNOT_INVOKE_ABSTRACT_METHOD;
}
toJSON() {
return Object.assign({}, this, { name: this.name });
}
svg(t37 = {}) {
throw KB.CANNOT_INVOKE_ABSTRACT_METHOD;
}
};
QB.Point = class t37 extends zj {
constructor(...t38) {
if (super(), this.x = 0, this.y = 0, t38.length !== 0) {
if (t38.length === 1 && t38[0] instanceof Array && t38[0].length === 2) {
let e2 = t38[0];
if (typeof e2[0] == "number" && typeof e2[1] == "number")
return this.x = e2[0], void (this.y = e2[1]);
}
if (t38.length === 1 && t38[0] instanceof Object && t38[0].name === "point") {
let { x: e2, y: n2 } = t38[0];
return this.x = e2, void (this.y = n2);
}
if (t38.length === 2 && typeof t38[0] == "number" && typeof t38[1] == "number")
return this.x = t38[0], void (this.y = t38[1]);
throw KB.ILLEGAL_PARAMETERS;
}
}
get box() {
return new QB.Box(this.x, this.y, this.x, this.y);
}
clone() {
return new QB.Point(this.x, this.y);
}
get vertices() {
return [this.clone()];
}
equalTo(t38) {
return QB.Utils.EQ(this.x, t38.x) && QB.Utils.EQ(this.y, t38.y);
}
lessThan(t38) {
return !!QB.Utils.LT(this.y, t38.y) || !(!QB.Utils.EQ(this.y, t38.y) || !QB.Utils.LT(this.x, t38.x));
}
transform(t38) {
return new QB.Point(t38.transform([this.x, this.y]));
}
projectionOn(t38) {
if (this.equalTo(t38.pt))
return this.clone();
let e2 = new QB.Vector(this, t38.pt);
if (QB.Utils.EQ_0(e2.cross(t38.norm)))
return t38.pt.clone();
let n2 = e2.dot(t38.norm), o2 = t38.norm.multiply(n2);
return this.translate(o2);
}
leftTo(t38) {
let e2 = new QB.Vector(t38.pt, this);
return QB.Utils.GT(e2.dot(t38.norm), 0);
}
distanceTo(e2) {
if (e2 instanceof t37) {
let t38 = e2.x - this.x, n2 = e2.y - this.y;
return [Math.sqrt(t38 * t38 + n2 * n2), new QB.Segment(this, e2)];
}
return e2 instanceof QB.Line ? QB.Distance.point2line(this, e2) : e2 instanceof QB.Circle ? QB.Distance.point2circle(this, e2) : e2 instanceof QB.Segment ? QB.Distance.point2segment(this, e2) : e2 instanceof QB.Arc ? QB.Distance.point2arc(this, e2) : e2 instanceof QB.Polygon ? QB.Distance.point2polygon(this, e2) : e2 instanceof QB.PlanarSet ? QB.Distance.shape2planarSet(this, e2) : e2 instanceof QB.Multiline ? QB.Distance.shape2multiline(this, e2) : undefined;
}
on(t38) {
if (t38 instanceof QB.Point)
return this.equalTo(t38);
if (t38.contains && t38.contains instanceof Function)
return t38.contains(this);
throw QB.Errors.UNSUPPORTED_SHAPE_TYPE;
}
get name() {
return "point";
}
svg(t38 = {}) {
const e2 = t38.r ?? 3;
return `
<circle cx="${this.x}" cy="${this.y}" r="${e2}"
${oF({ fill: "red", ...t38 })} />`;
}
};
QB.point = (...t38) => new QB.Point(...t38);
QB.Vector = class extends zj {
constructor(...t38) {
if (super(), this.x = 0, this.y = 0, t38.length !== 0) {
if (t38.length === 1 && t38[0] instanceof Array && t38[0].length === 2) {
let e2 = t38[0];
if (typeof e2[0] == "number" && typeof e2[1] == "number")
return this.x = e2[0], void (this.y = e2[1]);
}
if (t38.length === 1 && t38[0] instanceof Object && t38[0].name === "vector") {
let { x: e2, y: n2 } = t38[0];
return this.x = e2, void (this.y = n2);
}
if (t38.length === 1 && t38[0] instanceof Object && t38[0].name === "segment") {
let { start: e2, end: n2 } = t38[0];
return this.x = n2.x - e2.x, void (this.y = n2.y - e2.y);
}
if (t38.length === 2) {
let e2 = t38[0], n2 = t38[1];
if (typeof e2 == "number" && typeof n2 == "number")
return this.x = e2, void (this.y = n2);
if (e2 instanceof QB.Point && n2 instanceof QB.Point)
return this.x = n2.x - e2.x, void (this.y = n2.y - e2.y);
}
throw KB.ILLEGAL_PARAMETERS;
}
}
clone() {
return new QB.Vector(this.x, this.y);
}
get slope() {
let t38 = Math.atan2(this.y, this.x);
return t38 < 0 && (t38 = 2 * Math.PI + t38), t38;
}
get length() {
return Math.sqrt(this.dot(this));
}
isZeroLength() {
return QB.Utils.EQ_0(this.length);
}
equalTo(t38) {
return QB.Utils.EQ(this.x, t38.x) && QB.Utils.EQ(this.y, t38.y);
}
multiply(t38) {
return new QB.Vector(t38 * this.x, t38 * this.y);
}
dot(t38) {
return this.x * t38.x + this.y * t38.y;
}
cross(t38) {
return this.x * t38.y - this.y * t38.x;
}
normalize() {
if (this.isZeroLength())
throw KB.ZERO_DIVISION;
return new QB.Vector(this.x / this.length, this.y / this.length);
}
rotate(t38, e2 = new QB.Point) {
if (e2.x === 0 && e2.y === 0)
return this.transform(new Ej().rotate(t38));
throw KB.OPERATION_IS_NOT_SUPPORTED;
}
transform(t38) {
return new QB.Vector(t38.transform([this.x, this.y]));
}
rotate90CCW() {
return new QB.Vector(-this.y, this.x);
}
rotate90CW() {
return new QB.Vector(this.y, -this.x);
}
invert() {
return new QB.Vector(-this.x, -this.y);
}
add(t38) {
return new QB.Vector(this.x + t38.x, this.y + t38.y);
}
subtract(t38) {
return new QB.Vector(this.x - t38.x, this.y - t38.y);
}
angleTo(t38) {
let e2 = this.normalize(), n2 = t38.normalize(), o2 = Math.atan2(e2.cross(n2), e2.dot(n2));
return o2 < 0 && (o2 += 2 * Math.PI), o2;
}
projectionOn(t38) {
let e2 = t38.normalize(), n2 = this.dot(e2);
return e2.multiply(n2);
}
get name() {
return "vector";
}
};
var Bj = (...t38) => new QB.Vector(...t38);
QB.vector = Bj;
QB.Segment = class t38 extends zj {
constructor(...t39) {
if (super(), this.ps = new QB.Point, this.pe = new QB.Point, t39.length !== 0) {
if (t39.length === 1 && t39[0] instanceof Array && t39[0].length === 4) {
let e2 = t39[0];
return this.ps = new QB.Point(e2[0], e2[1]), void (this.pe = new QB.Point(e2[2], e2[3]));
}
if (t39.length === 1 && t39[0] instanceof Object && t39[0].name === "segment") {
let { ps: e2, pe: n2 } = t39[0];
return this.ps = new QB.Point(e2.x, e2.y), void (this.pe = new QB.Point(n2.x, n2.y));
}
if (!(t39.length === 1 && t39[0] instanceof QB.Point)) {
if (t39.length === 2 && t39[0] instanceof QB.Point && t39[1] instanceof QB.Point)
return this.ps = t39[0].clone(), void (this.pe = t39[1].clone());
if (t39.length === 4)
return this.ps = new QB.Point(t39[0], t39[1]), void (this.pe = new QB.Point(t39[2], t39[3]));
throw KB.ILLEGAL_PARAMETERS;
}
this.ps = t39[0].clone();
}
}
clone() {
return new QB.Segment(this.start, this.end);
}
get start() {
return this.ps;
}
get end() {
return this.pe;
}
get vertices() {
return [this.ps.clone(), this.pe.clone()];
}
get length() {
return this.start.distanceTo(this.end)[0];
}
get slope() {
return new QB.Vector(this.start, this.end).slope;
}
get box() {
return new QB.Box(Math.min(this.start.x, this.end.x), Math.min(this.start.y, this.end.y), Math.max(this.start.x, this.end.x), Math.max(this.start.y, this.end.y));
}
equalTo(t39) {
return this.ps.equalTo(t39.ps) && this.pe.equalTo(t39.pe);
}
contains(t39) {
return QB.Utils.EQ_0(this.distanceToPoint(t39));
}
intersect(t39) {
return t39 instanceof QB.Point ? this.contains(t39) ? [t39] : [] : t39 instanceof QB.Line ? cF(this, t39) : t39 instanceof QB.Ray ? wF(t39, this) : t39 instanceof QB.Segment ? lF(this, t39) : t39 instanceof QB.Circle ? dF(this, t39) : t39 instanceof QB.Box ? function(t40, e2) {
let n2 = [];
for (let o2 of e2.toSegments()) {
let e3 = lF(o2, t40);
for (let t41 of e3)
n2.push(t41);
}
return n2;
}(this, t39) : t39 instanceof QB.Arc ? uF(this, t39) : t39 instanceof QB.Polygon ? xF(this, t39) : t39 instanceof QB.Multiline ? kF(this, t39) : undefined;
}
distanceTo(t39) {
if (t39 instanceof QB.Point) {
let [e2, n2] = QB.Distance.point2segment(t39, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t39 instanceof QB.Circle) {
let [e2, n2] = QB.Distance.segment2circle(this, t39);
return [e2, n2];
}
if (t39 instanceof QB.Line) {
let [e2, n2] = QB.Distance.segment2line(this, t39);
return [e2, n2];
}
if (t39 instanceof QB.Segment) {
let [e2, n2] = QB.Distance.segment2segment(this, t39);
return [e2, n2];
}
if (t39 instanceof QB.Arc) {
let [e2, n2] = QB.Distance.segment2arc(this, t39);
return [e2, n2];
}
if (t39 instanceof QB.Polygon) {
let [e2, n2] = QB.Distance.shape2polygon(this, t39);
return [e2, n2];
}
if (t39 instanceof QB.PlanarSet) {
let [e2, n2] = QB.Distance.shape2planarSet(this, t39);
return [e2, n2];
}
if (t39 instanceof QB.Multiline)
return QB.Distance.shape2multiline(this, t39);
}
tangentInStart() {
return new QB.Vector(this.start, this.end).normalize();
}
tangentInEnd() {
return new QB.Vector(this.end, this.start).normalize();
}
reverse() {
return new t38(this.end, this.start);
}
split(t39) {
return this.start.equalTo(t39) ? [null, this.clone()] : this.end.equalTo(t39) ? [this.clone(), null] : [new QB.Segment(this.start, t39), new QB.Segment(t39, this.end)];
}
middle() {
return new QB.Point((this.start.x + this.end.x) / 2, (this.start.y + this.end.y) / 2);
}
pointAtLength(t39) {
if (t39 > this.length || t39 < 0)
return null;
if (t39 == 0)
return this.start;
if (t39 == this.length)
return this.end;
let e2 = t39 / this.length;
return new QB.Point((this.end.x - this.start.x) * e2 + this.start.x, (this.end.y - this.start.y) * e2 + this.start.y);
}
distanceToPoint(t39) {
let [e2, ...n2] = QB.Distance.point2segment(t39, this);
return e2;
}
definiteIntegral(t39 = 0) {
return (this.end.x - this.start.x) * (this.start.y - t39 + (this.end.y - t39)) / 2;
}
transform(e2 = new QB.Matrix) {
return new t38(this.ps.transform(e2), this.pe.transform(e2));
}
isZeroLength() {
return this.ps.equalTo(this.pe);
}
sortPoints(t39) {
return new QB.Line(this.start, this.end).sortPoints(t39);
}
get name() {
return "segment";
}
svg(t39 = {}) {
return `
<line x1="${this.start.x}" y1="${this.start.y}" x2="${this.end.x}" y2="${this.end.y}" ${oF(t39)} />`;
}
};
QB.segment = (...t39) => new QB.Segment(...t39);
var { vector: Fj } = QB;
QB.Line = class t39 extends zj {
constructor(...e2) {
if (super(), this.pt = new QB.Point, this.norm = new QB.Vector(0, 1), e2.length !== 0) {
if (e2.length === 1 && e2[0] instanceof Object && e2[0].name === "line") {
let { pt: t40, norm: n2 } = e2[0];
return this.pt = new QB.Point(t40), void (this.norm = new QB.Vector(n2));
}
if (e2.length === 2) {
let n2 = e2[0], o2 = e2[1];
if (n2 instanceof QB.Point && o2 instanceof QB.Point)
return this.pt = n2, this.norm = t39.points2norm(n2, o2), void (this.norm.dot(Fj(this.pt.x, this.pt.y)) >= 0 && this.norm.invert());
if (n2 instanceof QB.Point && o2 instanceof QB.Vector) {
if (QB.Utils.EQ_0(o2.x) && QB.Utils.EQ_0(o2.y))
throw KB.ILLEGAL_PARAMETERS;
return this.pt = n2.clone(), this.norm = o2.clone(), this.norm = this.norm.normalize(), void (this.norm.dot(Fj(this.pt.x, this.pt.y)) >= 0 && this.norm.invert());
}
if (n2 instanceof QB.Vector && o2 instanceof QB.Point) {
if (QB.Utils.EQ_0(n2.x) && QB.Utils.EQ_0(n2.y))
throw KB.ILLEGAL_PARAMETERS;
return this.pt = o2.clone(), this.norm = n2.clone(), this.norm = this.norm.normalize(), void (this.norm.dot(Fj(this.pt.x, this.pt.y)) >= 0 && this.norm.invert());
}
}
throw KB.ILLEGAL_PARAMETERS;
}
}
clone() {
return new QB.Line(this.pt, this.norm);
}
get start() {}
get end() {}
get length() {
return Number.POSITIVE_INFINITY;
}
get box() {
return new QB.Box(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
}
get middle() {}
get slope() {
return new QB.Vector(this.norm.y, -this.norm.x).slope;
}
get standard() {
return [this.norm.x, this.norm.y, this.norm.dot(Fj(this.pt.x, this.pt.y))];
}
parallelTo(t40) {
return QB.Utils.EQ_0(this.norm.cross(t40.norm));
}
incidentTo(t40) {
return this.parallelTo(t40) && this.pt.on(t40);
}
contains(t40) {
if (this.pt.equalTo(t40))
return true;
let e2 = new QB.Vector(this.pt, t40);
return QB.Utils.EQ_0(this.norm.dot(e2));
}
coord(t40) {
return Fj(t40.x, t40.y).cross(this.norm);
}
intersect(t40) {
return t40 instanceof QB.Point ? this.contains(t40) ? [t40] : [] : t40 instanceof QB.Line ? iF(this, t40) : t40 instanceof QB.Ray ? EF(t40, this) : t40 instanceof QB.Circle ? rF(this, t40) : t40 instanceof QB.Box ? sF(this, t40) : t40 instanceof QB.Segment ? cF(t40, this) : t40 instanceof QB.Arc ? aF(this, t40) : t40 instanceof QB.Polygon ? IF(this, t40) : t40 instanceof QB.Multiline ? kF(this, t40) : undefined;
}
distanceTo(t40) {
if (t40 instanceof QB.Point) {
let [e2, n2] = QB.Distance.point2line(t40, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t40 instanceof QB.Circle) {
let [e2, n2] = QB.Distance.circle2line(t40, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t40 instanceof QB.Segment) {
let [e2, n2] = QB.Distance.segment2line(t40, this);
return [e2, n2.reverse()];
}
if (t40 instanceof QB.Arc) {
let [e2, n2] = QB.Distance.arc2line(t40, this);
return [e2, n2.reverse()];
}
if (t40 instanceof QB.Polygon) {
let [e2, n2] = QB.Distance.shape2polygon(this, t40);
return [e2, n2];
}
}
split(t40) {
if (t40 instanceof QB.Point)
return [new QB.Ray(t40, this.norm), new QB.Ray(t40, this.norm)];
{
let e2 = new QB.Multiline([this]), n2 = this.sortPoints(t40);
return e2.split(n2), e2.toShapes();
}
}
rotate(t40, e2 = new QB.Point) {
return new QB.Line(this.pt.rotate(t40, e2), this.norm.rotate(t40));
}
transform(t40) {
return new QB.Line(this.pt.transform(t40), this.norm.clone());
}
sortPoints(t40) {
return t40.slice().sort((t41, e2) => this.coord(t41) < this.coord(e2) ? -1 : this.coord(t41) > this.coord(e2) ? 1 : 0);
}
get name() {
return "line";
}
svg(t40, e2 = {}) {
let n2 = sF(this, t40);
if (n2.length === 0)
return "";
let o2 = n2[0], i2 = n2.length === 2 ? n2[1] : n2.find((t41) => !t41.equalTo(o2));
return i2 === undefined && (i2 = o2), new QB.Segment(o2, i2).svg(e2);
}
static points2norm(t40, e2) {
if (t40.equalTo(e2))
throw KB.ILLEGAL_PARAMETERS;
return new QB.Vector(t40, e2).normalize().rotate90CCW();
}
};
QB.line = (...t40) => new QB.Line(...t40);
QB.Circle = class extends zj {
constructor(...t40) {
if (super(), this.pc = new QB.Point, this.r = 1, t40.length === 1 && t40[0] instanceof Object && t40[0].name === "circle") {
let { pc: e2, r: n2 } = t40[0];
this.pc = new QB.Point(e2), this.r = n2;
} else {
let [e2, n2] = [...t40];
e2 && e2 instanceof QB.Point && (this.pc = e2.clone()), n2 !== undefined && (this.r = n2);
}
}
clone() {
return new QB.Circle(this.pc.clone(), this.r);
}
get center() {
return this.pc;
}
get box() {
return new QB.Box(this.pc.x - this.r, this.pc.y - this.r, this.pc.x + this.r, this.pc.y + this.r);
}
contains(t40) {
return t40 instanceof QB.Point ? QB.Utils.LE(t40.distanceTo(this.center)[0], this.r) : t40 instanceof QB.Segment ? QB.Utils.LE(t40.start.distanceTo(this.center)[0], this.r) && QB.Utils.LE(t40.end.distanceTo(this.center)[0], this.r) : t40 instanceof QB.Arc ? this.intersect(t40).length === 0 && QB.Utils.LE(t40.start.distanceTo(this.center)[0], this.r) && QB.Utils.LE(t40.end.distanceTo(this.center)[0], this.r) : t40 instanceof QB.Circle ? this.intersect(t40).length === 0 && QB.Utils.LE(t40.r, this.r) && QB.Utils.LE(t40.center.distanceTo(this.center)[0], this.r) : undefined;
}
toArc(t40 = true) {
return new QB.Arc(this.center, this.r, Math.PI, -Math.PI, t40);
}
scale(t40, e2) {
if (t40 !== e2)
throw KB.OPERATION_IS_NOT_SUPPORTED;
if (this.pc.x !== 0 || this.pc.y !== 0)
throw KB.OPERATION_IS_NOT_SUPPORTED;
return new QB.Circle(this.pc, this.r * t40);
}
transform(t40 = new QB.Matrix) {
return new QB.Circle(this.pc.transform(t40), this.r);
}
intersect(t40) {
return t40 instanceof QB.Point ? this.contains(t40) ? [t40] : [] : t40 instanceof QB.Line ? rF(t40, this) : t40 instanceof QB.Ray ? RF(t40, this) : t40 instanceof QB.Segment ? dF(t40, this) : t40 instanceof QB.Circle ? pF(t40, this) : t40 instanceof QB.Box ? function(t41, e2) {
let n2 = [];
for (let o2 of e2.toSegments()) {
let e3 = dF(o2, t41);
for (let t42 of e3)
n2.push(t42);
}
return n2;
}(this, t40) : t40 instanceof QB.Arc ? gF(t40, this) : t40 instanceof QB.Polygon ? SF(this, t40) : t40 instanceof QB.Multiline ? kF(this, t40) : undefined;
}
distanceTo(t40) {
if (t40 instanceof QB.Point) {
let [e2, n2] = QB.Distance.point2circle(t40, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t40 instanceof QB.Circle) {
let [e2, n2] = QB.Distance.circle2circle(this, t40);
return [e2, n2];
}
if (t40 instanceof QB.Line) {
let [e2, n2] = QB.Distance.circle2line(this, t40);
return [e2, n2];
}
if (t40 instanceof QB.Segment) {
let [e2, n2] = QB.Distance.segment2circle(t40, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t40 instanceof QB.Arc) {
let [e2, n2] = QB.Distance.arc2circle(t40, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t40 instanceof QB.Polygon) {
let [e2, n2] = QB.Distance.shape2polygon(this, t40);
return [e2, n2];
}
if (t40 instanceof QB.PlanarSet) {
let [e2, n2] = QB.Distance.shape2planarSet(this, t40);
return [e2, n2];
}
if (t40 instanceof QB.Multiline) {
let [e2, n2] = QB.Distance.shape2multiline(this, t40);
return [e2, n2];
}
}
get name() {
return "circle";
}
svg(t40 = {}) {
return `
<circle cx="${this.pc.x}" cy="${this.pc.y}" r="${this.r}"
${oF({ fill: "none", ...t40 })} />`;
}
};
QB.circle = (...t40) => new QB.Circle(...t40);
QB.Arc = class extends zj {
constructor(...t40) {
if (super(), this.pc = new QB.Point, this.r = 1, this.startAngle = 0, this.endAngle = 2 * Math.PI, this.counterClockwise = true, t40.length !== 0)
if (t40.length === 1 && t40[0] instanceof Object && t40[0].name === "arc") {
let { pc: e2, r: n2, startAngle: o2, endAngle: i2, counterClockwise: r2 } = t40[0];
this.pc = new QB.Point(e2.x, e2.y), this.r = n2, this.startAngle = o2, this.endAngle = i2, this.counterClockwise = r2;
} else {
let [e2, n2, o2, i2, r2] = [...t40];
e2 && e2 instanceof QB.Point && (this.pc = e2.clone()), n2 !== undefined && (this.r = n2), o2 !== undefined && (this.startAngle = o2), i2 !== undefined && (this.endAngle = i2), r2 !== undefined && (this.counterClockwise = r2);
}
}
clone() {
return new QB.Arc(this.pc.clone(), this.r, this.startAngle, this.endAngle, this.counterClockwise);
}
get sweep() {
let t40 = this.startAngle, e2 = this.endAngle;
if (QB.Utils.EQ(Math.abs(t40 - e2), QB.PIx2))
return QB.PIx2;
Math.abs(t40) > QB.PIx2 && (t40 -= Math.trunc(t40 / QB.PIx2) * QB.PIx2), t40 < 0 && (t40 += QB.PIx2), Math.abs(e2) > QB.PIx2 && (e2 -= Math.trunc(e2 / QB.PIx2) * QB.PIx2), e2 < 0 && (e2 += QB.PIx2);
let n2 = this.counterClockwise ? e2 - t40 : t40 - e2;
return n2 < 0 && (n2 += QB.PIx2), n2;
}
get start() {
return new QB.Point(this.pc.x + this.r, this.pc.y).rotate(this.startAngle, this.pc);
}
get end() {
return new QB.Point(this.pc.x + this.r, this.pc.y).rotate(this.endAngle, this.pc);
}
get center() {
return this.pc.clone();
}
get vertices() {
return [this.start.clone(), this.end.clone()];
}
get length() {
return Math.abs(this.sweep * this.r);
}
get box() {
let t40 = this.breakToFunctional().reduce((t41, e2) => t41.merge(e2.start.box), new QB.Box);
return t40 = t40.merge(this.end.box), t40;
}
contains(t40) {
if (!QB.Utils.EQ(this.pc.distanceTo(t40)[0], this.r))
return false;
if (t40.equalTo(this.start))
return true;
let e2 = new QB.Vector(this.pc, t40).slope, n2 = new QB.Arc(this.pc, this.r, this.startAngle, e2, this.counterClockwise);
return QB.Utils.LE(n2.length, this.length);
}
split(t40) {
if (this.start.equalTo(t40))
return [null, this.clone()];
if (this.end.equalTo(t40))
return [this.clone(), null];
let e2 = new QB.Vector(this.pc, t40).slope;
return [new QB.Arc(this.pc, this.r, this.startAngle, e2, this.counterClockwise), new QB.Arc(this.pc, this.r, e2, this.endAngle, this.counterClockwise)];
}
middle() {
let t40 = this.counterClockwise ? this.startAngle + this.sweep / 2 : this.startAngle - this.sweep / 2;
return new QB.Arc(this.pc, this.r, this.startAngle, t40, this.counterClockwise).end;
}
pointAtLength(t40) {
if (t40 > this.length || t40 < 0)
return null;
if (t40 === 0)
return this.start;
if (t40 === this.length)
return this.end;
let e2 = t40 / this.length, n2 = this.counterClockwise ? this.startAngle + this.sweep * e2 : this.startAngle - this.sweep * e2;
return new QB.Arc(this.pc, this.r, this.startAngle, n2, this.counterClockwise).end;
}
chordHeight() {
return (1 - Math.cos(Math.abs(this.sweep / 2))) * this.r;
}
intersect(t40) {
return t40 instanceof QB.Point ? this.contains(t40) ? [t40] : [] : t40 instanceof QB.Line ? aF(t40, this) : t40 instanceof QB.Ray ? TF(t40, this) : t40 instanceof QB.Circle ? gF(this, t40) : t40 instanceof QB.Segment ? uF(t40, this) : t40 instanceof QB.Box ? function(t41, e2) {
let n2 = [];
for (let o2 of e2.toSegments()) {
let e3 = uF(o2, t41);
for (let t42 of e3)
n2.push(t42);
}
return n2;
}(this, t40) : t40 instanceof QB.Arc ? mF(this, t40) : t40 instanceof QB.Polygon ? vF(this, t40) : t40 instanceof QB.Multiline ? kF(this, t40) : undefined;
}
distanceTo(t40) {
if (t40 instanceof QB.Point) {
let [e2, n2] = QB.Distance.point2arc(t40, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t40 instanceof QB.Circle) {
let [e2, n2] = QB.Distance.arc2circle(this, t40);
return [e2, n2];
}
if (t40 instanceof QB.Line) {
let [e2, n2] = QB.Distance.arc2line(this, t40);
return [e2, n2];
}
if (t40 instanceof QB.Segment) {
let [e2, n2] = QB.Distance.segment2arc(t40, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t40 instanceof QB.Arc) {
let [e2, n2] = QB.Distance.arc2arc(this, t40);
return [e2, n2];
}
if (t40 instanceof QB.Polygon) {
let [e2, n2] = QB.Distance.shape2polygon(this, t40);
return [e2, n2];
}
if (t40 instanceof QB.PlanarSet) {
let [e2, n2] = QB.Distance.shape2planarSet(this, t40);
return [e2, n2];
}
if (t40 instanceof QB.Multiline)
return QB.Distance.shape2multiline(this, t40);
}
breakToFunctional() {
let t40 = [], e2 = [0, Math.PI / 2, Math.PI, 3 * Math.PI / 2], n2 = this.startAngle, o2 = this.endAngle;
QB.Utils.EQ(Math.abs(n2 - o2), QB.PIx2) && (o2 = n2), Math.abs(n2) > QB.PIx2 && (n2 -= Math.trunc(n2 / QB.PIx2) * QB.PIx2), n2 < 0 && (n2 += QB.PIx2), Math.abs(o2) > QB.PIx2 && (o2 -= Math.trunc(o2 / QB.PIx2) * QB.PIx2), o2 < 0 && (o2 += QB.PIx2);
let i2, r2, s2, a2 = n2;
this.counterClockwise ? (r2 = Math.ceil(n2 / (Math.PI / 2)) % 4, s2 = 1) : (r2 = Math.floor(n2 / (Math.PI / 2)) % 4, s2 = -1);
for (let o3 = 0, c2 = r2;o3 < 4; o3++, c2 = (c2 + s2 + 4) % 4) {
if (i2 = e2[c2], i2 === a2)
continue;
let o4 = this.counterClockwise ? i2 - n2 : n2 - i2;
if (o4 < 0 && (o4 += QB.PIx2), o4 > this.sweep)
break;
t40.push(new QB.Arc(this.pc, this.r, a2, i2, this.counterClockwise)), a2 = i2;
}
return t40.length === 0 ? (t40.push(this), t40) : (i2 = o2, a2 !== i2 && t40.push(new QB.Arc(this.pc, this.r, a2, i2, this.counterClockwise)), t40);
}
tangentInStart() {
let t40 = new QB.Vector(this.pc, this.start), e2 = this.counterClockwise ? Math.PI / 2 : -Math.PI / 2;
return t40.rotate(e2).normalize();
}
tangentInEnd() {
let t40 = new QB.Vector(this.pc, this.end), e2 = this.counterClockwise ? -Math.PI / 2 : Math.PI / 2;
return t40.rotate(e2).normalize();
}
reverse() {
return new QB.Arc(this.pc, this.r, this.endAngle, this.startAngle, !this.counterClockwise);
}
transform(t40 = new QB.Matrix) {
let e2 = this.start.transform(t40), n2 = this.end.transform(t40), o2 = this.pc.transform(t40), i2 = this.counterClockwise;
return t40.a * t40.d < 0 && (i2 = !i2), QB.Arc.arcSE(o2, e2, n2, i2);
}
static arcSE(t40, e2, n2, o2) {
let { vector: i2 } = QB, r2 = i2(t40, e2).slope, s2 = i2(t40, n2).slope;
QB.Utils.EQ(r2, s2) && (s2 += 2 * Math.PI, o2 = true);
let a2 = i2(t40, e2).length;
return new QB.Arc(t40, a2, r2, s2, o2);
}
definiteIntegral(t40 = 0) {
return this.breakToFunctional().reduce((e2, n2) => e2 + n2.circularSegmentDefiniteIntegral(t40), 0);
}
circularSegmentDefiniteIntegral(t40) {
let e2 = new QB.Segment(this.start, this.end).definiteIntegral(t40), n2 = QB.Utils.EQ(this.sweep, QB.PIx2) ? 0 : this.circularSegmentArea();
return this.counterClockwise ? e2 - n2 : e2 + n2;
}
circularSegmentArea() {
return 0.5 * this.r * this.r * (this.sweep - Math.sin(this.sweep));
}
sortPoints(t40) {
let { vector: e2 } = QB;
return t40.slice().sort((t41, n2) => {
let o2 = e2(this.pc, t41).slope, i2 = e2(this.pc, n2).slope;
return o2 < i2 ? -1 : o2 > i2 ? 1 : 0;
});
}
get name() {
return "arc";
}
svg(t40 = {}) {
let e2 = this.sweep <= Math.PI ? "0" : "1", n2 = this.counterClockwise ? "1" : "0";
if (QB.Utils.EQ(this.sweep, 2 * Math.PI)) {
return new QB.Circle(this.pc, this.r).svg(t40);
}
return `
<path d="M${this.start.x},${this.start.y}
A${this.r},${this.r} 0 ${e2},${n2} ${this.end.x},${this.end.y}"
${oF({ fill: "none", ...t40 })} />`;
}
};
QB.arc = (...t40) => new QB.Arc(...t40);
QB.Box = class t40 extends zj {
constructor(t41 = undefined, e2 = undefined, n2 = undefined, o2 = undefined) {
super(), this.xmin = t41, this.ymin = e2, this.xmax = n2, this.ymax = o2;
}
clone() {
return new t40(this.xmin, this.ymin, this.xmax, this.ymax);
}
get low() {
return new QB.Point(this.xmin, this.ymin);
}
get high() {
return new QB.Point(this.xmax, this.ymax);
}
get max() {
return this.clone();
}
get center() {
return new QB.Point((this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2);
}
get width() {
return Math.abs(this.xmax - this.xmin);
}
get height() {
return Math.abs(this.ymax - this.ymin);
}
get box() {
return this.clone();
}
not_intersect(t41) {
return this.xmax < t41.xmin || this.xmin > t41.xmax || this.ymax < t41.ymin || this.ymin > t41.ymax;
}
intersect(t41) {
return !this.not_intersect(t41);
}
merge(e2) {
return new t40(this.xmin === undefined ? e2.xmin : Math.min(this.xmin, e2.xmin), this.ymin === undefined ? e2.ymin : Math.min(this.ymin, e2.ymin), this.xmax === undefined ? e2.xmax : Math.max(this.xmax, e2.xmax), this.ymax === undefined ? e2.ymax : Math.max(this.ymax, e2.ymax));
}
less_than(t41) {
return !!this.low.lessThan(t41.low) || !(!this.low.equalTo(t41.low) || !this.high.lessThan(t41.high));
}
equal_to(t41) {
return this.low.equalTo(t41.low) && this.high.equalTo(t41.high);
}
output() {
return this.clone();
}
comparable_less_than(t41, e2) {
return t41.lessThan(e2);
}
set(t41, e2, n2, o2) {
this.xmin = t41, this.ymin = e2, this.xmax = n2, this.ymax = o2;
}
extend(e2) {
return e2 <= 0 ? this.clone() : new t40(this.xmin - e2, this.ymin - e2, this.xmax + e2, this.ymax + e2);
}
toPoints() {
return [new QB.Point(this.xmin, this.ymin), new QB.Point(this.xmax, this.ymin), new QB.Point(this.xmax, this.ymax), new QB.Point(this.xmin, this.ymax)];
}
toSegments() {
let t41 = this.toPoints();
return [new QB.Segment(t41[0], t41[1]), new QB.Segment(t41[1], t41[2]), new QB.Segment(t41[2], t41[3]), new QB.Segment(t41[3], t41[0])];
}
rotate(t41, e2 = new QB.Point) {
throw KB.OPERATION_IS_NOT_SUPPORTED;
}
transform(e2 = new QB.Matrix) {
return this.toPoints().map((t41) => t41.transform(e2)).reduce((t41, e3) => t41.merge(e3.box), new t40);
}
contains(t41) {
return t41 instanceof QB.Point ? t41.x >= this.xmin && t41.x <= this.xmax && t41.y >= this.ymin && t41.y <= this.ymax : t41 instanceof QB.Segment ? t41.vertices.every((t42) => this.contains(t42)) : t41 instanceof QB.Box ? t41.toSegments().every((t42) => this.contains(t42)) : t41 instanceof QB.Circle ? this.contains(t41.box) : t41 instanceof QB.Arc ? t41.vertices.every((t42) => this.contains(t42)) && this.toSegments().every((e2) => uF(e2, t41).length === 0) : !(t41 instanceof QB.Line || t41 instanceof QB.Ray) && (t41 instanceof QB.Multiline ? t41.toShapes().every((t42) => this.contains(t42)) : t41 instanceof QB.Polygon ? this.contains(t41.box) : undefined);
}
distanceTo(t41) {
const e2 = this.toSegments().map((e3) => e3.distanceTo(t41));
let n2 = [Number.MAX_SAFE_INTEGER, null];
return e2.forEach((t42) => {
t42[0] < n2[0] && (n2 = t42);
}), n2;
}
get name() {
return "box";
}
svg(t41 = {}) {
const e2 = this.xmax - this.xmin, n2 = this.ymax - this.ymin;
return `
<rect x="${this.xmin}" y="${this.ymin}" width="${e2}" height="${n2}"
${oF({ fill: "none", ...t41 })} />`;
}
};
QB.box = (...t41) => new QB.Box(...t41);
QB.Edge = class {
constructor(t41) {
this.shape = t41, this.next = undefined, this.prev = undefined, this.face = undefined, this.arc_length = 0, this.bvStart = undefined, this.bvEnd = undefined, this.bv = undefined, this.overlap = undefined;
}
get start() {
return this.shape.start;
}
get end() {
return this.shape.end;
}
get length() {
return this.shape.length;
}
get box() {
return this.shape.box;
}
get isSegment() {
return this.shape instanceof QB.Segment;
}
get isArc() {
return this.shape instanceof QB.Arc;
}
get isLine() {
return this.shape instanceof QB.Line;
}
get isRay() {
return this.shape instanceof QB.Ray;
}
middle() {
return this.shape.middle();
}
pointAtLength(t41) {
return this.shape.pointAtLength(t41);
}
contains(t41) {
return this.shape.contains(t41);
}
setInclusion(t41) {
if (this.bv !== undefined)
return this.bv;
if (this.shape instanceof QB.Line || this.shape instanceof QB.Ray)
return this.bv = QB.OUTSIDE, this.bv;
if (this.bvStart === undefined && (this.bvStart = Ij(t41, this.start)), this.bvEnd === undefined && (this.bvEnd = Ij(t41, this.end)), this.bvStart === QB.OUTSIDE || this.bvEnd == QB.OUTSIDE)
this.bv = QB.OUTSIDE;
else if (this.bvStart === QB.INSIDE || this.bvEnd == QB.INSIDE)
this.bv = QB.INSIDE;
else {
let e2 = Ij(t41, this.middle());
this.bv = e2;
}
return this.bv;
}
setOverlap(t41) {
let e2, n2 = this.shape, o2 = t41.shape;
n2 instanceof QB.Segment && o2 instanceof QB.Segment ? n2.start.equalTo(o2.start) && n2.end.equalTo(o2.end) ? e2 = QB.OVERLAP_SAME : n2.start.equalTo(o2.end) && n2.end.equalTo(o2.start) && (e2 = QB.OVERLAP_OPPOSITE) : (n2 instanceof QB.Arc && o2 instanceof QB.Arc || n2 instanceof QB.Segment && o2 instanceof QB.Arc || n2 instanceof QB.Arc && o2 instanceof QB.Segment) && (n2.start.equalTo(o2.start) && n2.end.equalTo(o2.end) && n2.middle().equalTo(o2.middle()) ? e2 = QB.OVERLAP_SAME : n2.start.equalTo(o2.end) && n2.end.equalTo(o2.start) && n2.middle().equalTo(o2.middle()) && (e2 = QB.OVERLAP_OPPOSITE)), this.overlap === undefined && (this.overlap = e2), t41.overlap === undefined && (t41.overlap = e2);
}
svg() {
if (this.shape instanceof QB.Segment)
return ` L${this.shape.end.x},${this.shape.end.y}`;
if (this.shape instanceof QB.Arc) {
let t41, e2 = this.shape, n2 = e2.counterClockwise ? "1" : "0";
if (QB.Utils.EQ(e2.sweep, 2 * Math.PI)) {
let o2 = e2.counterClockwise ? 1 : -1, i2 = new QB.Arc(e2.pc, e2.r, e2.startAngle, e2.startAngle + o2 * Math.PI, e2.counterClockwise), r2 = new QB.Arc(e2.pc, e2.r, e2.startAngle + o2 * Math.PI, e2.endAngle, e2.counterClockwise);
return t41 = "0", ` A${i2.r},${i2.r} 0 ${t41},${n2} ${i2.end.x},${i2.end.y}
A${r2.r},${r2.r} 0 ${t41},${n2} ${r2.end.x},${r2.end.y}`;
}
return t41 = e2.sweep <= Math.PI ? "0" : "1", ` A${e2.r},${e2.r} 0 ${t41},${n2} ${e2.end.x},${e2.end.y}`;
}
}
toJSON() {
return this.shape.toJSON();
}
};
var jj = class extends tF {
constructor(t41, e2) {
super(t41, e2), this.setCircularLinks();
}
setCircularLinks() {
this.isEmpty() || (this.last.next = this.first, this.first.prev = this.last);
}
[Symbol.iterator]() {
let t41;
return { next: () => {
let e2 = t41 || this.first, n2 = !this.first || !!t41 && t41 === this.first;
return t41 = e2 ? e2.next : undefined, { value: e2, done: n2 };
} };
}
append(t41) {
return super.append(t41), this.setCircularLinks(), this;
}
insert(t41, e2) {
return super.insert(t41, e2), this.setCircularLinks(), this;
}
remove(t41) {
return super.remove(t41), this;
}
};
QB.Face = class t41 extends jj {
constructor(e2, ...n2) {
if (super(), this._box = undefined, this._orientation = undefined, n2.length !== 0) {
if (n2.length === 1) {
if (n2[0] instanceof Array) {
let o2 = n2[0];
if (o2.length === 0)
return;
if (o2.every((t42) => t42 instanceof QB.Point)) {
let n3 = t41.points2segments(o2);
this.shapes2face(e2.edges, n3);
} else if (o2.every((t42) => t42 instanceof Array && t42.length === 2)) {
let n3 = o2.map((t42) => new QB.Point(t42[0], t42[1])), i2 = t41.points2segments(n3);
this.shapes2face(e2.edges, i2);
} else if (o2.every((t42) => t42 instanceof QB.Segment || t42 instanceof QB.Arc))
this.shapes2face(e2.edges, o2);
else if (o2.every((t42) => t42.name === "segment" || t42.name === "arc")) {
let t42 = [];
for (let e3 of o2) {
let n3;
n3 = e3.name === "segment" ? new QB.Segment(e3) : new QB.Arc(e3), t42.push(n3);
}
this.shapes2face(e2.edges, t42);
}
} else if (n2[0] instanceof t41) {
let t42 = n2[0];
this.first = t42.first, this.last = t42.last;
for (let n3 of t42)
e2.edges.add(n3);
} else if (n2[0] instanceof QB.Circle)
this.shapes2face(e2.edges, [n2[0].toArc($B)]);
else if (n2[0] instanceof QB.Box) {
let t42 = n2[0];
this.shapes2face(e2.edges, [new QB.Segment(new QB.Point(t42.xmin, t42.ymin), new QB.Point(t42.xmax, t42.ymin)), new QB.Segment(new QB.Point(t42.xmax, t42.ymin), new QB.Point(t42.xmax, t42.ymax)), new QB.Segment(new QB.Point(t42.xmax, t42.ymax), new QB.Point(t42.xmin, t42.ymax)), new QB.Segment(new QB.Point(t42.xmin, t42.ymax), new QB.Point(t42.xmin, t42.ymin))]);
}
}
n2.length === 2 && n2[0] instanceof QB.Edge && n2[1] instanceof QB.Edge && (this.first = n2[0], this.last = n2[1], this.last.next = this.first, this.first.prev = this.last, this.setArcLength());
}
}
get edges() {
return this.toArray();
}
get vertices() {
return this.edges.map((t42) => t42.shape.start.clone());
}
get shapes() {
return this.edges.map((t42) => t42.shape.clone());
}
get box() {
if (this._box === undefined) {
let t42 = new QB.Box;
for (let e2 of this)
t42 = t42.merge(e2.box);
this._box = t42;
}
return this._box;
}
get perimeter() {
return this.last.arc_length + this.last.length;
}
pointAtLength(t42) {
if (t42 > this.perimeter || t42 < 0)
return null;
let e2 = null;
for (let n2 of this)
if (t42 >= n2.arc_length && (n2 === this.last || t42 < n2.next.arc_length)) {
e2 = n2.pointAtLength(t42 - n2.arc_length);
break;
}
return e2;
}
static points2segments(t42) {
let e2 = [];
for (let n2 = 0;n2 < t42.length; n2++)
t42[n2].equalTo(t42[(n2 + 1) % t42.length]) || e2.push(new QB.Segment(t42[n2], t42[(n2 + 1) % t42.length]));
return e2;
}
shapes2face(t42, e2) {
for (let n2 of e2) {
let e3 = new QB.Edge(n2);
this.append(e3), t42.add(e3);
}
}
append(t42) {
return super.append(t42), this.setOneEdgeArcLength(t42), t42.face = this, this;
}
insert(t42, e2) {
return super.insert(t42, e2), this.setOneEdgeArcLength(t42), t42.face = this, this;
}
remove(t42) {
return super.remove(t42), this.setArcLength(), this;
}
merge_with_next_edge(t42) {
return t42.shape.end.x = t42.next.shape.end.x, t42.shape.end.y = t42.next.shape.end.y, this.remove(t42.next), this;
}
reverse() {
let t42 = [], e2 = this.last;
do {
e2.shape = e2.shape.reverse(), t42.push(e2), e2 = e2.prev;
} while (e2 !== this.last);
this.first = undefined, this.last = undefined;
for (let e3 of t42)
this.first === undefined ? (e3.prev = e3, e3.next = e3, this.first = e3, this.last = e3) : (e3.prev = this.last, this.last.next = e3, this.last = e3, this.last.next = this.first, this.first.prev = this.last), this.setOneEdgeArcLength(e3);
this._orientation !== undefined && (this._orientation = undefined, this._orientation = this.orientation());
}
setArcLength() {
for (let t42 of this)
this.setOneEdgeArcLength(t42), t42.face = this;
}
setOneEdgeArcLength(t42) {
t42 === this.first ? t42.arc_length = 0 : t42.arc_length = t42.prev.arc_length + t42.prev.length;
}
area() {
return Math.abs(this.signedArea());
}
signedArea() {
let t42 = 0, e2 = this.box.ymin;
for (let n2 of this)
t42 += n2.shape.definiteIntegral(e2);
return t42;
}
orientation() {
if (this._orientation === undefined) {
let t42 = this.signedArea();
QB.Utils.EQ_0(t42) ? this._orientation = YB.NOT_ORIENTABLE : QB.Utils.LT(t42, 0) ? this._orientation = YB.CCW : this._orientation = YB.CW;
}
return this._orientation;
}
isSimple(e2) {
return t41.getSelfIntersections(this, e2, true).length === 0;
}
static getSelfIntersections(t42, e2, n2 = false) {
let o2 = [];
for (let i2 of t42) {
let r2 = e2.search(i2.box);
for (let e3 of r2) {
if (i2 === e3)
continue;
if (e3.face !== t42)
continue;
if (i2.shape instanceof QB.Segment && e3.shape instanceof QB.Segment && (i2.next === e3 || i2.prev === e3))
continue;
let r3 = i2.shape.intersect(e3.shape);
for (let t43 of r3)
if ((!t43.equalTo(i2.start) || !t43.equalTo(e3.end) || e3 !== i2.prev) && (!t43.equalTo(i2.end) || !t43.equalTo(e3.start) || e3 !== i2.next) && (o2.push(t43), n2))
break;
if (o2.length > 0 && n2)
break;
}
if (o2.length > 0 && n2)
break;
}
return o2;
}
findEdgeByPoint(t42) {
let e2;
for (let n2 of this)
if (!t42.equalTo(n2.shape.start) && (t42.equalTo(n2.shape.end) || n2.shape.contains(t42))) {
e2 = n2;
break;
}
return e2;
}
toPolygon() {
return new QB.Polygon(this.shapes);
}
toJSON() {
return this.edges.map((t42) => t42.toJSON());
}
svg() {
let t42 = `M${this.first.start.x},${this.first.start.y}`;
for (let e2 of this)
t42 += e2.svg();
return t42 += " z", t42;
}
};
QB.Ray = class t42 extends zj {
constructor(...t43) {
if (super(), this.pt = new QB.Point, this.norm = new QB.Vector(0, 1), t43.length !== 0 && (t43.length >= 1 && t43[0] instanceof QB.Point && (this.pt = t43[0].clone()), t43.length !== 1)) {
if (!(t43.length === 2 && t43[1] instanceof QB.Vector))
throw KB.ILLEGAL_PARAMETERS;
this.norm = t43[1].clone();
}
}
clone() {
return new t42(this.pt, this.norm);
}
get slope() {
return new QB.Vector(this.norm.y, -this.norm.x).slope;
}
get box() {
let t43 = this.slope;
return new QB.Box(t43 > Math.PI / 2 && t43 < 3 * Math.PI / 2 ? Number.NEGATIVE_INFINITY : this.pt.x, t43 >= 0 && t43 <= Math.PI ? this.pt.y : Number.NEGATIVE_INFINITY, t43 >= Math.PI / 2 && t43 <= 3 * Math.PI / 2 ? this.pt.x : Number.POSITIVE_INFINITY, t43 >= Math.PI && t43 <= 2 * Math.PI || t43 === 0 ? this.pt.y : Number.POSITIVE_INFINITY);
}
get start() {
return this.pt;
}
get end() {}
get length() {
return Number.POSITIVE_INFINITY;
}
contains(t43) {
if (this.pt.equalTo(t43))
return true;
let e2 = new QB.Vector(this.pt, t43);
return QB.Utils.EQ_0(this.norm.dot(e2)) && QB.Utils.GE(e2.cross(this.norm), 0);
}
coord(t43) {
return Bj(t43.x, t43.y).cross(this.norm);
}
split(t43) {
return this.contains(t43) ? this.pt.equalTo(t43) ? [this] : [new QB.Segment(this.pt, t43), new QB.Ray(t43, this.norm)] : [];
}
intersect(t43) {
return t43 instanceof QB.Point ? this.contains(t43) ? [t43] : [] : t43 instanceof QB.Segment ? wF(this, t43) : t43 instanceof QB.Arc ? TF(this, t43) : t43 instanceof QB.Line ? EF(this, t43) : t43 instanceof QB.Ray ? (n2 = t43, iF(NF(e2 = this), NF(n2)).filter((t44) => e2.contains(t44)).filter((t44) => n2.contains(t44))) : t43 instanceof QB.Circle ? RF(this, t43) : t43 instanceof QB.Box ? function(t44, e3) {
return sF(NF(t44), e3).filter((e4) => t44.contains(e4));
}(this, t43) : t43 instanceof QB.Polygon ? AF(this, t43) : t43 instanceof QB.Multiline ? kF(this, t43) : undefined;
var e2, n2;
}
rotate(t43, e2 = new QB.Point) {
return new QB.Ray(this.pt.rotate(t43, e2), this.norm.rotate(t43));
}
transform(t43) {
return new QB.Ray(this.pt.transform(t43), this.norm.clone());
}
get name() {
return "ray";
}
svg(t43, e2 = {}) {
let n2 = sF(new QB.Line(this.pt, this.norm), t43);
return n2 = n2.filter((t44) => this.contains(t44)), n2.length === 0 || n2.length === 2 ? "" : new QB.Segment(this.pt, n2[0]).svg(e2);
}
};
QB.ray = (...t43) => new QB.Ray(...t43);
QB.Polygon = class t43 {
constructor() {
this.faces = new QB.PlanarSet, this.edges = new QB.PlanarSet;
let t44 = [...arguments];
if (t44.length === 1 && (t44[0] instanceof Array && t44[0].length > 0 || t44[0] instanceof QB.Circle || t44[0] instanceof QB.Box)) {
let e2 = t44[0];
if (t44[0] instanceof Array && t44[0].every((t45) => t45 instanceof Array))
if (e2.every((t45) => t45 instanceof Array && t45.length === 2 && typeof t45[0] == "number" && typeof t45[1] == "number"))
this.faces.add(new QB.Face(this, e2));
else
for (let t45 of e2)
if (t45 instanceof Array && t45[0] instanceof Array && t45[0].every((t46) => t46 instanceof Array && t46.length === 2 && typeof t46[0] == "number" && typeof t46[1] == "number"))
for (let e3 of t45)
this.faces.add(new QB.Face(this, e3));
else
this.faces.add(new QB.Face(this, t45));
else
this.faces.add(new QB.Face(this, e2));
}
}
get box() {
return [...this.faces].reduce((t44, e2) => t44.merge(e2.box), new QB.Box);
}
get vertices() {
return [...this.faces].flatMap((t44) => t44.vertices);
}
clone() {
let e2 = new t43;
for (let t44 of this.faces)
e2.addFace(t44.shapes);
return e2;
}
createFromArray(e2) {
const n2 = new t43;
return e2.forEach((t44) => [...t44.faces].forEach((t45) => n2.addFace(t45.shapes))), n2;
}
isEmpty() {
return this.edges.size === 0 || this.faces.size === 0;
}
isValid() {
let t44 = true;
for (let e2 of this.faces)
if (!e2.isSimple(this.edges)) {
t44 = false;
break;
}
return t44;
}
area() {
let t44 = [...this.faces].reduce((t45, e2) => t45 + e2.signedArea(), 0);
return Math.abs(t44);
}
addFace(...t44) {
let e2 = new QB.Face(this, ...t44);
return this.faces.add(e2), e2;
}
deleteFace(t44) {
for (let e2 of t44)
this.edges.delete(e2);
return this.faces.delete(t44);
}
recreateFaces() {
this.faces.clear();
for (let t45 of this.edges)
t45.face = null;
let t44, e2 = true;
for (;e2; ) {
e2 = false;
for (let n2 of this.edges)
if (n2.face === null) {
t44 = n2, e2 = true;
break;
}
if (e2) {
let e3 = t44;
do {
e3 = e3.next;
} while (e3.next !== t44);
this.addFace(t44, e3);
}
}
}
removeChain(t44, e2, n2) {
if (n2.next !== e2) {
for (let o2 = e2;o2 !== n2.next; o2 = o2.next)
if (t44.remove(o2), this.edges.delete(o2), t44.isEmpty()) {
this.deleteFace(t44);
break;
}
} else
this.deleteFace(t44);
}
addVertex(t44, e2) {
let n2 = e2.shape.split(t44);
if (n2[0] === null)
return e2.prev;
if (n2[1] === null)
return e2;
let o2 = new QB.Edge(n2[0]), i2 = e2.prev;
return e2.face.insert(o2, i2), this.edges.delete(e2), this.edges.add(o2), e2.shape = n2[1], this.edges.add(e2), o2;
}
removeEndVertex(t44) {
const e2 = t44.next;
e2 !== t44 && (t44.face.merge_with_next_edge(t44), this.edges.delete(e2));
}
cut(t44) {
const e2 = this.splitToIslands().flatMap((e3) => e3._cutSingleIsland(t44)).filter((t45) => t45.isValid() && t45.isEmpty() === false);
return this.createFromArray(e2);
}
_cutSingleIsland(t44) {
let e2 = this.clone();
const n2 = t44.clone();
let o2, i2, r2 = { int_points1: [], int_points2: [], int_points1_sorted: [], int_points2_sorted: [] };
for (let t45 of n2.edges)
for (let n3 of e2.edges) {
let e3 = CF(t45, n3);
for (let o3 of e3)
LF(t45, o3, r2.int_points1), LF(n3, o3, r2.int_points2);
}
if (r2.int_points1.length === 0)
return e2;
r2.int_points1_sorted = BF(r2.int_points1), r2.int_points2_sorted = BF(r2.int_points2), WF(n2, r2.int_points1_sorted), WF(e2, r2.int_points2_sorted), jF(r2), r2.int_points1_sorted = BF(r2.int_points1), r2.int_points2_sorted = BF(r2.int_points2), $F(r2.int_points1), YF(r2.int_points1, e2);
for (let t45 of r2.int_points1_sorted)
t45.edge_before && t45.edge_after && t45.edge_before.bv === t45.edge_after.bv && (r2.int_points2[t45.id] = -1, t45.id = -1);
if (r2.int_points1 = r2.int_points1.filter((t45) => t45.id >= 0), r2.int_points2 = r2.int_points2.filter((t45) => t45.id >= 0), r2.int_points1.forEach((t45, e3) => {
t45.id = e3;
}), r2.int_points2.forEach((t45, e3) => {
t45.id = e3;
}), r2.int_points1.length === 0)
return e2;
r2.int_points1_sorted = BF(r2.int_points1), r2.int_points2_sorted = BF(r2.int_points2);
for (let t45 = 1;t45 < r2.int_points1_sorted.length; t45++)
if (i2 = r2.int_points1_sorted[t45], o2 = r2.int_points1_sorted[t45 - 1], i2.edge_before && i2.edge_before.bv === 1) {
let t46 = o2.edge_after, s2 = i2.edge_before, a2 = n2.getChain(t46, s2);
VF(r2.int_points2[o2.id], r2.int_points2[i2.id], a2), a2.forEach((t47) => e2.edges.add(t47)), a2 = a2.reverse().map((t47) => new QB.Edge(t47.shape.reverse()));
for (let t47 = 0;t47 < a2.length - 1; t47++)
a2[t47].next = a2[t47 + 1], a2[t47 + 1].prev = a2[t47];
VF(r2.int_points2[i2.id], r2.int_points2[o2.id], a2), a2.forEach((t47) => e2.edges.add(t47));
}
return e2.recreateFaces(), e2;
}
cutWithLine(t44) {
let e2 = new DF([t44]);
return this.cut(e2);
}
findEdgeByPoint(t44) {
let e2;
for (let n2 of this.faces)
if (e2 = n2.findEdgeByPoint(t44), e2 !== undefined)
break;
return e2;
}
splitToIslands() {
if (this.isEmpty())
return [];
let t44 = this.toArray();
t44.sort((t45, e3) => e3.area() - t45.area());
let e2 = [...t44[0].faces][0].orientation(), n2 = t44.filter((t45) => [...t45.faces][0].orientation() === e2);
for (let o2 of t44) {
let t45 = [...o2.faces][0];
if (t45.orientation() !== e2) {
for (let e3 of n2)
if (t45.shapes.every((t46) => e3.contains(t46))) {
e3.addFace(t45.shapes);
break;
}
}
}
return n2;
}
rearrange() {
if (this.faces.size <= 1)
return this.clone();
const e2 = this.splitToIslands(), n2 = new t43;
return e2.forEach((t44) => {
t44.faces.forEach((t45) => n2.addFace(t45.shapes));
}), n2;
}
orientation() {
return this.isEmpty() ? YB.NOT_ORIENTABLE : [...this.faces][0].orientation();
}
isOuter(t44) {
return t44.orientation() === this.orientation();
}
isMultiPolygon() {
let t44 = 0;
return this.faces.forEach((e2) => {
this.isOuter(e2) && t44++;
}), t44 > 1;
}
reverse() {
for (let t44 of this.faces)
t44.reverse();
return this;
}
contains(t44) {
if (t44 instanceof QB.Point) {
let e2 = Ij(this, t44);
return e2 === 1 || e2 === 2;
}
return Mj(this, t44);
}
distanceTo(t44) {
if (t44 instanceof QB.Point) {
let [e2, n2] = QB.Distance.point2polygon(t44, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t44 instanceof QB.Circle || t44 instanceof QB.Line || t44 instanceof QB.Segment || t44 instanceof QB.Arc) {
let [e2, n2] = QB.Distance.shape2polygon(t44, this);
return n2 = n2.reverse(), [e2, n2];
}
if (t44 instanceof QB.Polygon) {
let e2, n2, o2 = [Number.POSITIVE_INFINITY, new QB.Segment];
for (let i2 of this.edges) {
let r2 = o2[0];
[e2, n2] = QB.Distance.shape2planarSet(i2.shape, t44.edges, r2), QB.Utils.LT(e2, r2) && (o2 = [e2, n2]);
}
return o2;
}
}
intersect(t44) {
return t44 instanceof QB.Point ? this.contains(t44) ? [t44] : [] : t44 instanceof QB.Line ? IF(t44, this) : t44 instanceof QB.Ray ? AF(t44, this) : t44 instanceof QB.Circle ? SF(t44, this) : t44 instanceof QB.Segment ? xF(t44, this) : t44 instanceof QB.Arc ? vF(t44, this) : t44 instanceof QB.Polygon ? function(t45, e2) {
let n2 = [];
if (t45.isEmpty() || e2.isEmpty())
return n2;
if (t45.box.not_intersect(e2.box))
return n2;
for (let o2 of t45.edges)
n2 = [...n2, ...PF(o2, e2)];
return n2;
}(t44, this) : t44 instanceof QB.Multiline ? function(t45, e2) {
let n2 = [];
if (e2.isEmpty() || t45.size === 0)
return n2;
for (let o2 of t45)
n2 = [...n2, ...PF(o2, e2)];
return n2;
}(t44, this) : undefined;
}
translate(e2) {
let n2 = new t43;
for (let t44 of this.faces)
n2.addFace(t44.shapes.map((t45) => t45.translate(e2)));
return n2;
}
rotate(e2 = 0, n2 = new QB.Point) {
let o2 = new t43;
for (let t44 of this.faces)
o2.addFace(t44.shapes.map((t45) => t45.rotate(e2, n2)));
return o2;
}
scale(e2, n2) {
let o2 = new t43;
for (let t44 of this.faces)
o2.addFace(t44.shapes.map((t45) => t45.scale(e2, n2)));
return o2;
}
transform(e2 = new QB.Matrix) {
let n2 = new t43;
for (let t44 of this.faces)
n2.addFace(t44.shapes.map((t45) => t45.transform(e2)));
return n2;
}
toJSON() {
return [...this.faces].map((t44) => t44.toJSON());
}
toArray() {
return [...this.faces].map((t44) => t44.toPolygon());
}
dpath() {
return [...this.faces].reduce((t44, e2) => t44 + e2.svg(), "");
}
svg(t44 = {}) {
let e2 = `
<path ${oF({ fillRule: "evenodd", fill: "lightcyan", ...t44 })} d="`;
for (let t45 of this.faces)
e2 += `
${t45.svg()}`;
return e2 += `" >
</path>`, e2;
}
};
QB.polygon = (...t44) => new QB.Polygon(...t44);
var { Circle: $j, Line: Yj, Point: Xj, Vector: Wj, Utils: Vj } = QB;
QB.Inversion = class t44 {
constructor(t45) {
this.circle = t45;
}
get inversion_circle() {
return this.circle;
}
static inversePoint(t45, e2) {
const n2 = new Wj(t45.pc, e2), o2 = t45.r * t45.r, i2 = n2.dot(n2);
return Vj.EQ_0(i2) ? new Xj(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY) : t45.pc.translate(n2.multiply(o2 / i2));
}
static inverseCircle(t45, e2) {
const n2 = t45.pc.distanceTo(e2.pc)[0];
if (Vj.EQ(n2, e2.r)) {
let n3 = t45.r * t45.r / (2 * e2.r), o2 = new Wj(t45.pc, e2.pc);
o2 = o2.normalize();
let i2 = t45.pc.translate(o2.multiply(n3));
return new Yj(i2, o2);
}
{
let n3 = new Wj(t45.pc, e2.pc), o2 = t45.r * t45.r / (n3.dot(n3) - e2.r * e2.r), i2 = t45.pc.translate(n3.multiply(o2)), r2 = Math.abs(o2) * e2.r;
return new $j(i2, r2);
}
}
static inverseLine(t45, e2) {
const [n2, o2] = t45.pc.distanceTo(e2);
if (Vj.EQ_0(n2))
return e2.clone();
{
let e3 = t45.r * t45.r / (2 * n2), i2 = new Wj(t45.pc, o2.end);
return i2 = i2.multiply(e3 / n2), new $j(t45.pc.translate(i2), e3);
}
}
inverse(e2) {
return e2 instanceof Xj ? t44.inversePoint(this.circle, e2) : e2 instanceof $j ? t44.inverseCircle(this.circle, e2) : e2 instanceof Yj ? t44.inverseLine(this.circle, e2) : undefined;
}
};
QB.inversion = (t45) => new QB.Inversion(t45);
QB.Distance = class t45 {
static point2point(t46, e2) {
return t46.distanceTo(e2);
}
static point2line(t46, e2) {
let n2 = t46.projectionOn(e2);
return [new QB.Vector(t46, n2).length, new QB.Segment(t46, n2)];
}
static point2circle(t46, e2) {
let [n2, o2] = t46.distanceTo(e2.center);
if (QB.Utils.EQ_0(n2))
return [e2.r, new QB.Segment(t46, e2.toArc().start)];
{
let o3 = Math.abs(n2 - e2.r), i2 = new QB.Vector(e2.pc, t46).normalize().multiply(e2.r), r2 = e2.pc.translate(i2);
return [o3, new QB.Segment(t46, r2)];
}
}
static point2segment(e2, n2) {
if (n2.start.equalTo(n2.end))
return t45.point2point(e2, n2.start);
let o2, i2, r2 = new QB.Vector(n2.start, n2.end), s2 = new QB.Vector(n2.start, e2), a2 = new QB.Vector(n2.end, e2), c2 = r2.dot(s2), l2 = -r2.dot(a2);
if (QB.Utils.GE(c2, 0) && QB.Utils.GE(l2, 0)) {
let t46 = n2.tangentInStart();
return o2 = Math.abs(t46.cross(s2)), i2 = n2.start.translate(t46.multiply(t46.dot(s2))), [o2, new QB.Segment(e2, i2)];
}
return c2 < 0 ? e2.distanceTo(n2.start) : e2.distanceTo(n2.end);
}
static point2arc(e2, n2) {
let o2, i2, r2 = new QB.Circle(n2.pc, n2.r), s2 = [];
return [o2, i2] = t45.point2circle(e2, r2), i2.end.on(n2) && s2.push(t45.point2circle(e2, r2)), s2.push(t45.point2point(e2, n2.start)), s2.push(t45.point2point(e2, n2.end)), t45.sort(s2), s2[0];
}
static point2edge(e2, n2) {
return n2.shape instanceof QB.Segment ? t45.point2segment(e2, n2.shape) : t45.point2arc(e2, n2.shape);
}
static segment2line(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new QB.Segment(o2[0], o2[0])];
let i2 = [];
return i2.push(t45.point2line(e2.start, n2)), i2.push(t45.point2line(e2.end, n2)), t45.sort(i2), i2[0];
}
static segment2segment(e2, n2) {
let o2 = lF(e2, n2);
if (o2.length > 0)
return [0, new QB.Segment(o2[0], o2[0])];
let i2, r2, s2 = [];
return [i2, r2] = t45.point2segment(n2.start, e2), s2.push([i2, r2.reverse()]), [i2, r2] = t45.point2segment(n2.end, e2), s2.push([i2, r2.reverse()]), s2.push(t45.point2segment(e2.start, n2)), s2.push(t45.point2segment(e2.end, n2)), t45.sort(s2), s2[0];
}
static segment2circle(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new QB.Segment(o2[0], o2[0])];
let i2 = new QB.Line(e2.ps, e2.pe), [r2, s2] = t45.point2line(n2.center, i2);
if (QB.Utils.GE(r2, n2.r) && s2.end.on(e2))
return t45.point2circle(s2.end, n2);
{
let [o3, i3] = t45.point2circle(e2.start, n2), [r3, s3] = t45.point2circle(e2.end, n2);
return QB.Utils.LT(o3, r3) ? [o3, i3] : [r3, s3];
}
}
static segment2arc(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new QB.Segment(o2[0], o2[0])];
let i2 = new QB.Line(e2.ps, e2.pe), r2 = new QB.Circle(n2.pc, n2.r), [s2, a2] = t45.point2line(r2.center, i2);
if (QB.Utils.GE(s2, r2.r) && a2.end.on(e2)) {
let [e3, o3] = t45.point2circle(a2.end, r2);
if (o3.end.on(n2))
return [e3, o3];
}
let c2, l2, h2 = [];
return h2.push(t45.point2arc(e2.start, n2)), h2.push(t45.point2arc(e2.end, n2)), [c2, l2] = t45.point2segment(n2.start, e2), h2.push([c2, l2.reverse()]), [c2, l2] = t45.point2segment(n2.end, e2), h2.push([c2, l2.reverse()]), t45.sort(h2), h2[0];
}
static circle2circle(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new QB.Segment(o2[0], o2[0])];
if (e2.center.equalTo(n2.center)) {
let o3 = e2.toArc(), i2 = n2.toArc();
return t45.point2point(o3.start, i2.start);
}
{
let o3 = new QB.Line(e2.center, n2.center), i2 = o3.intersect(e2), r2 = o3.intersect(n2), s2 = [];
return s2.push(t45.point2point(i2[0], r2[0])), s2.push(t45.point2point(i2[0], r2[1])), s2.push(t45.point2point(i2[1], r2[0])), s2.push(t45.point2point(i2[1], r2[1])), t45.sort(s2), s2[0];
}
}
static circle2line(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new QB.Segment(o2[0], o2[0])];
let [i2, r2] = t45.point2line(e2.center, n2), [s2, a2] = t45.point2circle(r2.end, e2);
return a2 = a2.reverse(), [s2, a2];
}
static arc2line(e2, n2) {
let o2 = n2.intersect(e2);
if (o2.length > 0)
return [0, new QB.Segment(o2[0], o2[0])];
let i2 = new QB.Circle(e2.center, e2.r), [r2, s2] = t45.point2line(i2.center, n2);
if (!QB.Utils.GE(r2, i2.r)) {
let o3 = [];
return o3.push(t45.point2line(e2.start, n2)), o3.push(t45.point2line(e2.end, n2)), t45.sort(o3), o3[0];
}
{
let [n3, o3] = t45.point2circle(s2.end, i2);
if (o3.end.on(e2))
return [n3, o3];
}
}
static arc2circle(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new QB.Segment(o2[0], o2[0])];
let i2 = new QB.Circle(e2.center, e2.r), [r2, s2] = t45.circle2circle(i2, n2);
if (s2.start.on(e2))
return [r2, s2];
{
let o3 = [];
return o3.push(t45.point2circle(e2.start, n2)), o3.push(t45.point2circle(e2.end, n2)), t45.sort(o3), o3[0];
}
}
static arc2arc(e2, n2) {
let o2 = e2.intersect(n2);
if (o2.length > 0)
return [0, new QB.Segment(o2[0], o2[0])];
let i2 = new QB.Circle(e2.center, e2.r), r2 = new QB.Circle(n2.center, n2.r), [s2, a2] = t45.circle2circle(i2, r2);
if (a2.start.on(e2) && a2.end.on(n2))
return [s2, a2];
{
let o3, i3, r3 = [];
return [o3, i3] = t45.point2arc(e2.start, n2), i3.end.on(n2) && r3.push([o3, i3]), [o3, i3] = t45.point2arc(e2.end, n2), i3.end.on(n2) && r3.push([o3, i3]), [o3, i3] = t45.point2arc(n2.start, e2), i3.end.on(e2) && r3.push([o3, i3.reverse()]), [o3, i3] = t45.point2arc(n2.end, e2), i3.end.on(e2) && r3.push([o3, i3.reverse()]), [o3, i3] = t45.point2point(e2.start, n2.start), r3.push([o3, i3]), [o3, i3] = t45.point2point(e2.start, n2.end), r3.push([o3, i3]), [o3, i3] = t45.point2point(e2.end, n2.start), r3.push([o3, i3]), [o3, i3] = t45.point2point(e2.end, n2.end), r3.push([o3, i3]), t45.sort(r3), r3[0];
}
}
static point2polygon(e2, n2) {
let o2 = [Number.POSITIVE_INFINITY, new QB.Segment];
for (let i2 of n2.edges) {
let [n3, r2] = t45.point2edge(e2, i2);
QB.Utils.LT(n3, o2[0]) && (o2 = [n3, r2]);
}
return o2;
}
static shape2polygon(t46, e2) {
let n2 = [Number.POSITIVE_INFINITY, new QB.Segment];
for (let o2 of e2.edges) {
let [e3, i2] = t46.distanceTo(o2.shape);
QB.Utils.LT(e3, n2[0]) && (n2 = [e3, i2]);
}
return n2;
}
static polygon2polygon(t46, e2) {
let n2 = [Number.POSITIVE_INFINITY, new QB.Segment];
for (let o2 of t46.edges)
for (let t47 of e2.edges) {
let [e3, i2] = o2.shape.distanceTo(t47.shape);
QB.Utils.LT(e3, n2[0]) && (n2 = [e3, i2]);
}
return n2;
}
static box2box_minmax(t46, e2) {
let n2 = Math.max(Math.max(t46.xmin - e2.xmax, 0), Math.max(e2.xmin - t46.xmax, 0)), o2 = Math.max(Math.max(t46.ymin - e2.ymax, 0), Math.max(e2.ymin - t46.ymax, 0)), i2 = n2 * n2 + o2 * o2, r2 = t46.merge(e2), s2 = r2.xmax - r2.xmin, a2 = r2.ymax - r2.ymin;
return [i2, s2 * s2 + a2 * a2];
}
static minmax_tree_process_level(e2, n2, o2, i2) {
let r2, s2;
for (let a3 of n2) {
[r2, s2] = t45.box2box_minmax(e2.box, a3.item.key);
for (let t46 of a3.item.values)
t46 instanceof QB.Edge ? i2.insert([r2, s2], t46.shape) : i2.insert([r2, s2], t46);
QB.Utils.LT(s2, o2) && (o2 = s2);
}
if (n2.length === 0)
return o2;
let a2 = [...n2.map((t46) => t46.left.isNil() ? undefined : t46.left).filter((t46) => t46 !== undefined), ...n2.map((t46) => t46.right.isNil() ? undefined : t46.right).filter((t46) => t46 !== undefined)].filter((n3) => {
let [i3, r3] = t45.box2box_minmax(e2.box, n3.max);
return QB.Utils.LE(i3, o2);
});
return o2 = t45.minmax_tree_process_level(e2, a2, o2, i2);
}
static minmax_tree(e2, n2, o2) {
let i2 = new Dj, r2 = [n2.index.root], s2 = o2 < Number.POSITIVE_INFINITY ? o2 * o2 : Number.POSITIVE_INFINITY;
return s2 = t45.minmax_tree_process_level(e2, r2, s2, i2), i2;
}
static minmax_tree_calc_distance(e2, n2, o2) {
let i2, r2;
if (n2 != null && !n2.isNil()) {
if ([i2, r2] = t45.minmax_tree_calc_distance(e2, n2.left, o2), r2)
return [i2, r2];
if (QB.Utils.LT(i2[0], Math.sqrt(n2.item.key.low)))
return [i2, true];
let [s2, a2] = t45.distanceToArray(e2, n2.item.values);
return QB.Utils.LT(s2, i2[0]) && (i2 = [s2, a2]), [i2, r2] = t45.minmax_tree_calc_distance(e2, n2.right, i2), [i2, r2];
}
return [o2, false];
}
static shape2planarSet(e2, n2, o2 = Number.POSITIVE_INFINITY) {
let i2 = [o2, new QB.Segment], r2 = false;
if (n2 instanceof QB.PlanarSet) {
let s2 = t45.minmax_tree(e2, n2, o2);
[i2, r2] = t45.minmax_tree_calc_distance(e2, s2.root, i2);
}
return i2;
}
static sort(t46) {
t46.sort((t47, e2) => QB.Utils.LT(t47[0], e2[0]) ? -1 : QB.Utils.GT(t47[0], e2[0]) ? 1 : 0);
}
static distance(t46, e2) {
return t46.distanceTo(e2);
}
static distanceToArray(t46, e2) {
let n2 = [Number.POSITIVE_INFINITY, new QB.Segment];
for (let o2 of e2) {
let [e3, i2] = t46.distanceTo(o2);
QB.Utils.LT(e3, n2[0]) && (n2 = [e3, i2]);
}
return n2;
}
static shape2multiline(e2, n2) {
let o2 = [Number.POSITIVE_INFINITY, new QB.Segment];
for (let i2 of n2) {
let [n3, r2] = t45.distance(e2, i2.shape);
QB.Utils.LT(n3, o2[0]) && (o2 = [n3, r2]);
}
return o2;
}
static multiline2multiline(e2, n2) {
let o2 = [Number.POSITIVE_INFINITY, new QB.Segment];
for (let i2 of e2)
for (let e3 of n2) {
let [n3, r2] = t45.distance(i2.shape, e3.shape);
QB.Utils.LT(n3, o2[0]) && (o2 = [n3, r2]);
}
return o2;
}
};
var { Multiline: Hj, Point: Gj, Segment: Uj, Polygon: Zj } = QB;
function qj(t46) {
return new Gj(t46.split(" ").map(Number));
}
function Jj(t46) {
return t46.split(", ").map(qj);
}
function Qj(t46) {
const e2 = Jj(t46);
let n2 = [];
for (let t47 = 0;t47 < e2.length - 1; t47++)
n2.push(new Uj(e2[t47], e2[t47 + 1]));
return new Hj(n2);
}
function Kj(t46) {
const e2 = t46.replace(/\(\(/, "").replace(/\)\)$/, "").split("), ("), n2 = new Zj;
let o2;
return e2.forEach((t47, e3) => {
let i2 = t47.split(", ").map((t48) => new Gj(t48.split(" ").map(Number)));
const r2 = n2.addFace(i2);
e3 === 0 ? o2 = r2.orientation() : r2.orientation() === o2 && r2.reverse();
}), n2;
}
function t$(t46) {
if (t46.startsWith("POLYGON")) {
return Kj(t46.replace(/^POLYGON /, ""));
}
return function(t47) {
const e2 = t47.split(/\)\), \(\(/).map((t48) => "((" + t48 + "))").map(Kj), n2 = new Zj;
return e2.reduce((t48, e3) => [...t48, ...e3?.faces], []).forEach((t48) => n2.addFace([...t48?.shapes])), n2;
}(t46.replace(/^MULTIPOLYGON \(\(\((.*)\)\)\)$/, "$1"));
}
function e$(t46) {
return t46.split(`
`)?.every((t47) => t47.includes("POINT"));
}
function n$(t46) {
return t46.split(`
`)?.every((t47) => t47.includes("LINESTRING"));
}
QB.isWktString = function(t47) {
return t47.startsWith("POINT") || e$(t47) || t47.startsWith("LINESTRING") || n$(t47) || t47.startsWith("MULTILINESTRING") || t47.startsWith("POLYGON") || t47.startsWith("MULTIPOINT") || t47.startsWith("MULTIPOLYGON") || t47.startsWith("GEOMETRYCOLLECTION");
}, QB.parseWKT = function t46(e2) {
if (e2.startsWith("POINT")) {
return qj(e2.replace(/^POINT \(/, "").replace(/\)$/, ""));
}
if (e2.startsWith("MULTIPOINT")) {
return Jj(e2.replace(/^MULTIPOINT \(/, "").replace(/\)$/, ""));
}
if (e2.startsWith("LINESTRING")) {
return Qj(e2.replace(/^LINESTRING \(/, "").replace(/\)$/, ""));
}
if (e2.startsWith("MULTILINESTRING")) {
return function(t47) {
return t47.replace(/\(\(/, "").replace(/\)\)$/, "").split("), (").map(Qj);
}(e2.replace(/^MULTILINESTRING /, ""));
}
if (e2.startsWith("POLYGON") || e2.startsWith("MULTIPOLYGON"))
return t$(e2);
if (e2.startsWith("GEOMETRYCOLLECTION")) {
const n2 = /(?<type>POINT|LINESTRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON) \((?:[^\(\)]|\([^\)]*\))*\)/g, o2 = e2.match(n2);
o2[0].startsWith("GEOMETRYCOLLECTION") && (o2[0] = o2[0].replace("GEOMETRYCOLLECTION (", ""));
return o2.map(t46).map((t47) => t47 instanceof Array ? t47 : [t47]).reduce((t47, e3) => [...t47, ...e3], []);
}
return e$(e2) ? function(t47) {
return t47.split(`
`).map((t48) => t48.match(/\(([^)]+)\)/)[1]).map(qj);
}(e2) : n$(e2) ? function(t47) {
return t47.split(`
`).map((t48) => t48.match(/\(([^)]+)\)/)[1]).map(Qj).reduce((t48, e3) => [...t48, ...e3], []);
}(e2) : [];
}, QB.BooleanOperations = gj, QB.Relations = Rj;
o$ = $z(), i$ = 1, r$ = o$ != null ? Iz(Mz(o$)) : {}, ((t47, e2, n2, o2) => {
if (e2 && typeof e2 == "object" || typeof e2 == "function")
for (let i2 of Pz(e2))
Nz.call(t47, i2) || i2 === n2 || Sz(t47, i2, { get: () => e2[i2], enumerable: !(o2 = Cz(e2, i2)) || o2.enumerable });
})(!i$ && o$ && o$.__esModule ? r$ : Sz(r$, "default", { value: o$, enumerable: true }), o$);
var o$;
var i$;
var r$;
var s$ = Object.create;
var a$ = Object.defineProperty;
var c$ = Object.getOwnPropertyDescriptor;
var l$ = Object.getOwnPropertyNames;
var h$ = Object.getPrototypeOf;
var d$ = Object.prototype.hasOwnProperty;
var u$ = (t47, e2) => function() {
return e2 || (0, t47[l$(t47)[0]])((e2 = { exports: {} }).exports, e2), e2.exports;
};
var p$ = (t47, e2, n2) => (n2 = t47 != null ? s$(h$(t47)) : {}, ((t48, e3, n3, o2) => {
if (e3 && typeof e3 == "object" || typeof e3 == "function")
for (let i2 of l$(e3))
d$.call(t48, i2) || i2 === n3 || a$(t48, i2, { get: () => e3[i2], enumerable: !(o2 = c$(e3, i2)) || o2.enumerable });
return t48;
})(t47 && t47.__esModule ? n2 : a$(n2, "default", { value: t47, enumerable: true }), t47));
var m$ = u$({ "node_modules/is-buffer/index.js"(t47, e2) {
function n2(t48) {
return !!t48.constructor && typeof t48.constructor.isBuffer == "function" && t48.constructor.isBuffer(t48);
}
e2.exports = function(t48) {
return t48 != null && (n2(t48) || function(t49) {
return typeof t49.readFloatLE == "function" && typeof t49.slice == "function" && n2(t49.slice(0, 0));
}(t48) || !!t48._isBuffer);
};
} });
var g$ = u$({ "node_modules/kind-of/index.js"(t47, e2) {
var n2 = m$(), o2 = Object.prototype.toString;
e2.exports = function(t48) {
if (t48 === undefined)
return "undefined";
if (t48 === null)
return "null";
if (t48 === true || t48 === false || t48 instanceof Boolean)
return "boolean";
if (typeof t48 == "string" || t48 instanceof String)
return "string";
if (typeof t48 == "number" || t48 instanceof Number)
return "number";
if (typeof t48 == "function" || t48 instanceof Function)
return "function";
if (Array.isArray !== undefined && Array.isArray(t48))
return "array";
if (t48 instanceof RegExp)
return "regexp";
if (t48 instanceof Date)
return "date";
var e3 = o2.call(t48);
return e3 === "[object RegExp]" ? "regexp" : e3 === "[object Date]" ? "date" : e3 === "[object Arguments]" ? "arguments" : e3 === "[object Error]" ? "error" : n2(t48) ? "buffer" : e3 === "[object Set]" ? "set" : e3 === "[object WeakSet]" ? "weakset" : e3 === "[object Map]" ? "map" : e3 === "[object WeakMap]" ? "weakmap" : e3 === "[object Symbol]" ? "symbol" : e3 === "[object Int8Array]" ? "int8array" : e3 === "[object Uint8Array]" ? "uint8array" : e3 === "[object Uint8ClampedArray]" ? "uint8clampedarray" : e3 === "[object Int16Array]" ? "int16array" : e3 === "[object Uint16Array]" ? "uint16array" : e3 === "[object Int32Array]" ? "int32array" : e3 === "[object Uint32Array]" ? "uint32array" : e3 === "[object Float32Array]" ? "float32array" : e3 === "[object Float64Array]" ? "float64array" : "object";
};
} });
var f$ = u$({ "node_modules/rename-keys/index.js"(t47, e2) {
(function() {
function t48(t49, e3) {
if (typeof e3 != "function")
return t49;
var n2 = {};
for (var o2 in t49)
Object.prototype.hasOwnProperty.call(t49, o2) && (n2[e3(o2, t49[o2]) || o2] = t49[o2]);
return n2;
}
e2 !== undefined && e2.exports ? e2.exports = t48 : typeof define == "function" && define.amd ? define([], function() {
return t48;
}) : window.rename = t48;
})();
} });
var y$ = u$({ "node_modules/deep-rename-keys/index.js"(t47, e2) {
var n2 = g$(), o2 = f$();
e2.exports = function t48(e3, i2) {
var r2 = n2(e3);
if (r2 !== "object" && r2 !== "array")
throw new Error("expected an object");
var s2 = [];
for (var a2 in r2 === "object" && (e3 = o2(e3, i2), s2 = {}), e3)
if (e3.hasOwnProperty(a2)) {
var c2 = e3[a2];
n2(c2) === "object" || n2(c2) === "array" ? s2[a2] = t48(c2, i2) : s2[a2] = c2;
}
return s2;
};
} });
var _$ = u$({ "node_modules/eventemitter3/index.js"(t47, e2) {
var n2 = Object.prototype.hasOwnProperty, o2 = "~";
function i2() {}
function r2(t48, e3, n3) {
this.fn = t48, this.context = e3, this.once = n3 || false;
}
function s2() {
this._events = new i2, this._eventsCount = 0;
}
Object.create && (i2.prototype = Object.create(null), new i2().__proto__ || (o2 = false)), s2.prototype.eventNames = function() {
var t48, e3, i3 = [];
if (this._eventsCount === 0)
return i3;
for (e3 in t48 = this._events)
n2.call(t48, e3) && i3.push(o2 ? e3.slice(1) : e3);
return Object.getOwnPropertySymbols ? i3.concat(Object.getOwnPropertySymbols(t48)) : i3;
}, s2.prototype.listeners = function(t48, e3) {
var n3 = o2 ? o2 + t48 : t48, i3 = this._events[n3];
if (e3)
return !!i3;
if (!i3)
return [];
if (i3.fn)
return [i3.fn];
for (var r3 = 0, s3 = i3.length, a2 = new Array(s3);r3 < s3; r3++)
a2[r3] = i3[r3].fn;
return a2;
}, s2.prototype.emit = function(t48, e3, n3, i3, r3, s3) {
var a2 = o2 ? o2 + t48 : t48;
if (!this._events[a2])
return false;
var c2, l2, h2 = this._events[a2], d2 = arguments.length;
if (h2.fn) {
switch (h2.once && this.removeListener(t48, h2.fn, undefined, true), d2) {
case 1:
return h2.fn.call(h2.context), true;
case 2:
return h2.fn.call(h2.context, e3), true;
case 3:
return h2.fn.call(h2.context, e3, n3), true;
case 4:
return h2.fn.call(h2.context, e3, n3, i3), true;
case 5:
return h2.fn.call(h2.context, e3, n3, i3, r3), true;
case 6:
return h2.fn.call(h2.context, e3, n3, i3, r3, s3), true;
}
for (l2 = 1, c2 = new Array(d2 - 1);l2 < d2; l2++)
c2[l2 - 1] = arguments[l2];
h2.fn.apply(h2.context, c2);
} else {
var u2, p2 = h2.length;
for (l2 = 0;l2 < p2; l2++)
switch (h2[l2].once && this.removeListener(t48, h2[l2].fn, undefined, true), d2) {
case 1:
h2[l2].fn.call(h2[l2].context);
break;
case 2:
h2[l2].fn.call(h2[l2].context, e3);
break;
case 3:
h2[l2].fn.call(h2[l2].context, e3, n3);
break;
case 4:
h2[l2].fn.call(h2[l2].context, e3, n3, i3);
break;
default:
if (!c2)
for (u2 = 1, c2 = new Array(d2 - 1);u2 < d2; u2++)
c2[u2 - 1] = arguments[u2];
h2[l2].fn.apply(h2[l2].context, c2);
}
}
return true;
}, s2.prototype.on = function(t48, e3, n3) {
var i3 = new r2(e3, n3 || this), s3 = o2 ? o2 + t48 : t48;
return this._events[s3] ? this._events[s3].fn ? this._events[s3] = [this._events[s3], i3] : this._events[s3].push(i3) : (this._events[s3] = i3, this._eventsCount++), this;
}, s2.prototype.once = function(t48, e3, n3) {
var i3 = new r2(e3, n3 || this, true), s3 = o2 ? o2 + t48 : t48;
return this._events[s3] ? this._events[s3].fn ? this._events[s3] = [this._events[s3], i3] : this._events[s3].push(i3) : (this._events[s3] = i3, this._eventsCount++), this;
}, s2.prototype.removeListener = function(t48, e3, n3, r3) {
var s3 = o2 ? o2 + t48 : t48;
if (!this._events[s3])
return this;
if (!e3)
return --this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3], this;
var a2 = this._events[s3];
if (a2.fn)
a2.fn !== e3 || r3 && !a2.once || n3 && a2.context !== n3 || (--this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3]);
else {
for (var c2 = 0, l2 = [], h2 = a2.length;c2 < h2; c2++)
(a2[c2].fn !== e3 || r3 && !a2[c2].once || n3 && a2[c2].context !== n3) && l2.push(a2[c2]);
l2.length ? this._events[s3] = l2.length === 1 ? l2[0] : l2 : --this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3];
}
return this;
}, s2.prototype.removeAllListeners = function(t48) {
var e3;
return t48 ? (e3 = o2 ? o2 + t48 : t48, this._events[e3] && (--this._eventsCount === 0 ? this._events = new i2 : delete this._events[e3])) : (this._events = new i2, this._eventsCount = 0), this;
}, s2.prototype.off = s2.prototype.removeListener, s2.prototype.addListener = s2.prototype.on, s2.prototype.setMaxListeners = function() {
return this;
}, s2.prefixed = o2, s2.EventEmitter = s2, e2 !== undefined && (e2.exports = s2);
} });
var b$ = u$({ "node_modules/xml-lexer/dist/lexer.js"(t47, e2) {
function n2(t48, e3, n3) {
return e3 in t48 ? Object.defineProperty(t48, e3, { value: n3, enumerable: true, configurable: true, writable: true }) : t48[e3] = n3, t48;
}
var o2 = _$(), i2 = function() {}, r2 = { data: "state-data", cdata: "state-cdata", tagBegin: "state-tag-begin", tagName: "state-tag-name", tagEnd: "state-tag-end", attributeNameStart: "state-attribute-name-start", attributeName: "state-attribute-name", attributeNameEnd: "state-attribute-name-end", attributeValueBegin: "state-attribute-value-begin", attributeValue: "state-attribute-value" }, s2 = { lt: "action-lt", gt: "action-gt", space: "action-space", equal: "action-equal", quote: "action-quote", slash: "action-slash", char: "action-char", error: "action-error" }, a2 = { text: "text", openTag: "open-tag", closeTag: "close-tag", attributeName: "attribute-name", attributeValue: "attribute-value" }, c2 = { " ": s2.space, "\t": s2.space, "\n": s2.space, "\r": s2.space, "<": s2.lt, ">": s2.gt, '"': s2.quote, "'": s2.quote, "=": s2.equal, "/": s2.slash };
e2.exports = { State: r2, Action: s2, Type: a2, create: function(t48) {
var e3, l2, h2, d2, u2, p2, m2, g2, f2, y2;
t48 = Object.assign({ debug: false }, t48);
var _2 = new o2, b2 = r2.data, x2 = "", v2 = "", I2 = "", S2 = "", C2 = "", P2 = "", M2 = function(e4, n3) {
if (v2[0] !== "?" && v2[0] !== "!") {
var o3 = { type: e4, value: n3 };
t48.debug && console.log("emit:", o3), _2.emit("data", o3);
}
};
_2.stateMachine = (n2(y2 = {}, r2.data, (n2(e3 = {}, s2.lt, function() {
x2.trim() && M2(a2.text, x2), v2 = "", C2 = false, b2 = r2.tagBegin;
}), n2(e3, s2.char, function(t49) {
x2 += t49;
}), e3)), n2(y2, r2.cdata, n2({}, s2.char, function(t49) {
(x2 += t49).substr(-3) === "]]>" && (M2(a2.text, x2.slice(0, -3)), x2 = "", b2 = r2.data);
})), n2(y2, r2.tagBegin, (n2(l2 = {}, s2.space, i2), n2(l2, s2.char, function(t49) {
v2 = t49, b2 = r2.tagName;
}), n2(l2, s2.slash, function() {
v2 = "", C2 = true;
}), l2)), n2(y2, r2.tagName, (n2(h2 = {}, s2.space, function() {
C2 ? b2 = r2.tagEnd : (b2 = r2.attributeNameStart, M2(a2.openTag, v2));
}), n2(h2, s2.gt, function() {
M2(C2 ? a2.closeTag : a2.openTag, v2), x2 = "", b2 = r2.data;
}), n2(h2, s2.slash, function() {
b2 = r2.tagEnd, M2(a2.openTag, v2);
}), n2(h2, s2.char, function(t49) {
(v2 += t49) === "![CDATA[" && (b2 = r2.cdata, x2 = "", v2 = "");
}), h2)), n2(y2, r2.tagEnd, (n2(d2 = {}, s2.gt, function() {
M2(a2.closeTag, v2), x2 = "", b2 = r2.data;
}), n2(d2, s2.char, i2), d2)), n2(y2, r2.attributeNameStart, (n2(u2 = {}, s2.char, function(t49) {
I2 = t49, b2 = r2.attributeName;
}), n2(u2, s2.gt, function() {
x2 = "", b2 = r2.data;
}), n2(u2, s2.space, i2), n2(u2, s2.slash, function() {
C2 = true, b2 = r2.tagEnd;
}), u2)), n2(y2, r2.attributeName, (n2(p2 = {}, s2.space, function() {
b2 = r2.attributeNameEnd;
}), n2(p2, s2.equal, function() {
M2(a2.attributeName, I2), b2 = r2.attributeValueBegin;
}), n2(p2, s2.gt, function() {
S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), x2 = "", b2 = r2.data;
}), n2(p2, s2.slash, function() {
C2 = true, S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), b2 = r2.tagEnd;
}), n2(p2, s2.char, function(t49) {
I2 += t49;
}), p2)), n2(y2, r2.attributeNameEnd, (n2(m2 = {}, s2.space, i2), n2(m2, s2.equal, function() {
M2(a2.attributeName, I2), b2 = r2.attributeValueBegin;
}), n2(m2, s2.gt, function() {
S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), x2 = "", b2 = r2.data;
}), n2(m2, s2.char, function(t49) {
S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), I2 = t49, b2 = r2.attributeName;
}), m2)), n2(y2, r2.attributeValueBegin, (n2(g2 = {}, s2.space, i2), n2(g2, s2.quote, function(t49) {
P2 = t49, S2 = "", b2 = r2.attributeValue;
}), n2(g2, s2.gt, function() {
M2(a2.attributeValue, S2 = ""), x2 = "", b2 = r2.data;
}), n2(g2, s2.char, function(t49) {
P2 = "", S2 = t49, b2 = r2.attributeValue;
}), g2)), n2(y2, r2.attributeValue, (n2(f2 = {}, s2.space, function(t49) {
P2 ? S2 += t49 : (M2(a2.attributeValue, S2), b2 = r2.attributeNameStart);
}), n2(f2, s2.quote, function(t49) {
P2 === t49 ? (M2(a2.attributeValue, S2), b2 = r2.attributeNameStart) : S2 += t49;
}), n2(f2, s2.gt, function(t49) {
P2 ? S2 += t49 : (M2(a2.attributeValue, S2), x2 = "", b2 = r2.data);
}), n2(f2, s2.slash, function(t49) {
P2 ? S2 += t49 : (M2(a2.attributeValue, S2), C2 = true, b2 = r2.tagEnd);
}), n2(f2, s2.char, function(t49) {
S2 += t49;
}), f2)), y2);
var N2 = function(e4) {
t48.debug && console.log(b2, e4);
var n3 = _2.stateMachine[b2], o3 = n3[function(t49) {
return c2[t49] || s2.char;
}(e4)] || n3[s2.error] || n3[s2.char];
o3(e4);
};
return _2.write = function(t49) {
for (var e4 = t49.length, n3 = 0;n3 < e4; n3++)
N2(t49[n3]);
}, _2;
} };
} });
var x$ = u$({ "node_modules/xml-reader/dist/reader.js"(t47, e2) {
var n2 = _$(), o2 = b$(), i2 = o2.Type, r2 = { element: "element", text: "text" }, s2 = function(t48) {
return Object.assign({ name: "", type: r2.element, value: "", parent: null, attributes: {}, children: [] }, t48);
}, a2 = function(t48) {
t48 = Object.assign({ stream: false, parentNodes: true, doneEvent: "done", tagPrefix: "tag:", emitTopLevelOnly: false, debug: false }, t48);
var e3 = undefined, a3 = undefined, c2 = undefined, l2 = undefined, h2 = new n2, d2 = function(n3) {
switch (n3.type) {
case i2.openTag:
if (c2 === null)
(c2 = a3).name = n3.value;
else {
var o3 = s2({ name: n3.value, parent: c2 });
c2.children.push(o3), c2 = o3;
}
break;
case i2.closeTag:
var d3 = c2.parent;
if (t48.parentNodes || (c2.parent = null), c2.name !== n3.value)
break;
t48.stream && d3 === a3 && (a3.children = [], c2.parent = null), t48.emitTopLevelOnly && d3 !== a3 || (h2.emit(t48.tagPrefix + c2.name, c2), h2.emit("tag", c2.name, c2)), c2 === a3 && (e3.removeAllListeners("data"), h2.emit(t48.doneEvent, c2), a3 = null), c2 = d3;
break;
case i2.text:
c2 && c2.children.push(s2({ type: r2.text, value: n3.value, parent: t48.parentNodes ? c2 : null }));
break;
case i2.attributeName:
l2 = n3.value, c2.attributes[l2] = "";
break;
case i2.attributeValue:
c2.attributes[l2] = n3.value;
}
};
return h2.reset = function() {
(e3 = o2.create({ debug: t48.debug })).on("data", d2), a3 = s2(), c2 = null, l2 = "", h2.parse = e3.write;
}, h2.reset(), h2;
};
e2.exports = { parseSync: function(t48, e3) {
e3 = Object.assign({}, e3, { stream: false, tagPrefix: ":" });
var n3 = a2(e3), o3 = undefined;
return n3.on("done", function(t49) {
o3 = t49;
}), n3.parse(t48), o3;
}, create: a2, NodeType: r2 };
} });
var P$ = (p$(y$()), p$(x$()), Object.create);
var M$ = Object.defineProperty;
var N$ = Object.getOwnPropertyDescriptor;
var w$ = Object.getOwnPropertyNames;
var T$ = Object.getPrototypeOf;
var R$ = Object.prototype.hasOwnProperty;
var E$ = (t47, e2) => function() {
return e2 || (0, t47[w$(t47)[0]])((e2 = { exports: {} }).exports, e2), e2.exports;
};
var A$ = (t47, e2, n2) => (n2 = t47 != null ? P$(T$(t47)) : {}, ((t48, e3, n3, o2) => {
if (e3 && typeof e3 == "object" || typeof e3 == "function")
for (let i2 of w$(e3))
R$.call(t48, i2) || i2 === n3 || M$(t48, i2, { get: () => e3[i2], enumerable: !(o2 = N$(e3, i2)) || o2.enumerable });
return t48;
})(t47 && t47.__esModule ? n2 : M$(n2, "default", { value: t47, enumerable: true }), t47));
var O$ = E$({ "node_modules/is-buffer/index.js"(t47, e2) {
function n2(t48) {
return !!t48.constructor && typeof t48.constructor.isBuffer == "function" && t48.constructor.isBuffer(t48);
}
e2.exports = function(t48) {
return t48 != null && (n2(t48) || function(t49) {
return typeof t49.readFloatLE == "function" && typeof t49.slice == "function" && n2(t49.slice(0, 0));
}(t48) || !!t48._isBuffer);
};
} });
var k$ = E$({ "node_modules/kind-of/index.js"(t47, e2) {
var n2 = O$(), o2 = Object.prototype.toString;
e2.exports = function(t48) {
if (t48 === undefined)
return "undefined";
if (t48 === null)
return "null";
if (t48 === true || t48 === false || t48 instanceof Boolean)
return "boolean";
if (typeof t48 == "string" || t48 instanceof String)
return "string";
if (typeof t48 == "number" || t48 instanceof Number)
return "number";
if (typeof t48 == "function" || t48 instanceof Function)
return "function";
if (Array.isArray !== undefined && Array.isArray(t48))
return "array";
if (t48 instanceof RegExp)
return "regexp";
if (t48 instanceof Date)
return "date";
var e3 = o2.call(t48);
return e3 === "[object RegExp]" ? "regexp" : e3 === "[object Date]" ? "date" : e3 === "[object Arguments]" ? "arguments" : e3 === "[object Error]" ? "error" : n2(t48) ? "buffer" : e3 === "[object Set]" ? "set" : e3 === "[object WeakSet]" ? "weakset" : e3 === "[object Map]" ? "map" : e3 === "[object WeakMap]" ? "weakmap" : e3 === "[object Symbol]" ? "symbol" : e3 === "[object Int8Array]" ? "int8array" : e3 === "[object Uint8Array]" ? "uint8array" : e3 === "[object Uint8ClampedArray]" ? "uint8clampedarray" : e3 === "[object Int16Array]" ? "int16array" : e3 === "[object Uint16Array]" ? "uint16array" : e3 === "[object Int32Array]" ? "int32array" : e3 === "[object Uint32Array]" ? "uint32array" : e3 === "[object Float32Array]" ? "float32array" : e3 === "[object Float64Array]" ? "float64array" : "object";
};
} });
var D$ = E$({ "node_modules/rename-keys/index.js"(t47, e2) {
(function() {
function t48(t49, e3) {
if (typeof e3 != "function")
return t49;
var n2 = {};
for (var o2 in t49)
Object.prototype.hasOwnProperty.call(t49, o2) && (n2[e3(o2, t49[o2]) || o2] = t49[o2]);
return n2;
}
e2 !== undefined && e2.exports ? e2.exports = t48 : typeof define == "function" && define.amd ? define([], function() {
return t48;
}) : window.rename = t48;
})();
} });
var L$ = E$({ "node_modules/deep-rename-keys/index.js"(t47, e2) {
var n2 = k$(), o2 = D$();
e2.exports = function t48(e3, i2) {
var r2 = n2(e3);
if (r2 !== "object" && r2 !== "array")
throw new Error("expected an object");
var s2 = [];
for (var a2 in r2 === "object" && (e3 = o2(e3, i2), s2 = {}), e3)
if (e3.hasOwnProperty(a2)) {
var c2 = e3[a2];
n2(c2) === "object" || n2(c2) === "array" ? s2[a2] = t48(c2, i2) : s2[a2] = c2;
}
return s2;
};
} });
var z$ = E$({ "node_modules/eventemitter3/index.js"(t47, e2) {
var n2 = Object.prototype.hasOwnProperty, o2 = "~";
function i2() {}
function r2(t48, e3, n3) {
this.fn = t48, this.context = e3, this.once = n3 || false;
}
function s2() {
this._events = new i2, this._eventsCount = 0;
}
Object.create && (i2.prototype = Object.create(null), new i2().__proto__ || (o2 = false)), s2.prototype.eventNames = function() {
var t48, e3, i3 = [];
if (this._eventsCount === 0)
return i3;
for (e3 in t48 = this._events)
n2.call(t48, e3) && i3.push(o2 ? e3.slice(1) : e3);
return Object.getOwnPropertySymbols ? i3.concat(Object.getOwnPropertySymbols(t48)) : i3;
}, s2.prototype.listeners = function(t48, e3) {
var n3 = o2 ? o2 + t48 : t48, i3 = this._events[n3];
if (e3)
return !!i3;
if (!i3)
return [];
if (i3.fn)
return [i3.fn];
for (var r3 = 0, s3 = i3.length, a2 = new Array(s3);r3 < s3; r3++)
a2[r3] = i3[r3].fn;
return a2;
}, s2.prototype.emit = function(t48, e3, n3, i3, r3, s3) {
var a2 = o2 ? o2 + t48 : t48;
if (!this._events[a2])
return false;
var c2, l2, h2 = this._events[a2], d2 = arguments.length;
if (h2.fn) {
switch (h2.once && this.removeListener(t48, h2.fn, undefined, true), d2) {
case 1:
return h2.fn.call(h2.context), true;
case 2:
return h2.fn.call(h2.context, e3), true;
case 3:
return h2.fn.call(h2.context, e3, n3), true;
case 4:
return h2.fn.call(h2.context, e3, n3, i3), true;
case 5:
return h2.fn.call(h2.context, e3, n3, i3, r3), true;
case 6:
return h2.fn.call(h2.context, e3, n3, i3, r3, s3), true;
}
for (l2 = 1, c2 = new Array(d2 - 1);l2 < d2; l2++)
c2[l2 - 1] = arguments[l2];
h2.fn.apply(h2.context, c2);
} else {
var u2, p2 = h2.length;
for (l2 = 0;l2 < p2; l2++)
switch (h2[l2].once && this.removeListener(t48, h2[l2].fn, undefined, true), d2) {
case 1:
h2[l2].fn.call(h2[l2].context);
break;
case 2:
h2[l2].fn.call(h2[l2].context, e3);
break;
case 3:
h2[l2].fn.call(h2[l2].context, e3, n3);
break;
case 4:
h2[l2].fn.call(h2[l2].context, e3, n3, i3);
break;
default:
if (!c2)
for (u2 = 1, c2 = new Array(d2 - 1);u2 < d2; u2++)
c2[u2 - 1] = arguments[u2];
h2[l2].fn.apply(h2[l2].context, c2);
}
}
return true;
}, s2.prototype.on = function(t48, e3, n3) {
var i3 = new r2(e3, n3 || this), s3 = o2 ? o2 + t48 : t48;
return this._events[s3] ? this._events[s3].fn ? this._events[s3] = [this._events[s3], i3] : this._events[s3].push(i3) : (this._events[s3] = i3, this._eventsCount++), this;
}, s2.prototype.once = function(t48, e3, n3) {
var i3 = new r2(e3, n3 || this, true), s3 = o2 ? o2 + t48 : t48;
return this._events[s3] ? this._events[s3].fn ? this._events[s3] = [this._events[s3], i3] : this._events[s3].push(i3) : (this._events[s3] = i3, this._eventsCount++), this;
}, s2.prototype.removeListener = function(t48, e3, n3, r3) {
var s3 = o2 ? o2 + t48 : t48;
if (!this._events[s3])
return this;
if (!e3)
return --this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3], this;
var a2 = this._events[s3];
if (a2.fn)
a2.fn !== e3 || r3 && !a2.once || n3 && a2.context !== n3 || (--this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3]);
else {
for (var c2 = 0, l2 = [], h2 = a2.length;c2 < h2; c2++)
(a2[c2].fn !== e3 || r3 && !a2[c2].once || n3 && a2[c2].context !== n3) && l2.push(a2[c2]);
l2.length ? this._events[s3] = l2.length === 1 ? l2[0] : l2 : --this._eventsCount === 0 ? this._events = new i2 : delete this._events[s3];
}
return this;
}, s2.prototype.removeAllListeners = function(t48) {
var e3;
return t48 ? (e3 = o2 ? o2 + t48 : t48, this._events[e3] && (--this._eventsCount === 0 ? this._events = new i2 : delete this._events[e3])) : (this._events = new i2, this._eventsCount = 0), this;
}, s2.prototype.off = s2.prototype.removeListener, s2.prototype.addListener = s2.prototype.on, s2.prototype.setMaxListeners = function() {
return this;
}, s2.prefixed = o2, s2.EventEmitter = s2, e2 !== undefined && (e2.exports = s2);
} });
var B$ = E$({ "node_modules/xml-lexer/dist/lexer.js"(t47, e2) {
function n2(t48, e3, n3) {
return e3 in t48 ? Object.defineProperty(t48, e3, { value: n3, enumerable: true, configurable: true, writable: true }) : t48[e3] = n3, t48;
}
var o2 = z$(), i2 = function() {}, r2 = { data: "state-data", cdata: "state-cdata", tagBegin: "state-tag-begin", tagName: "state-tag-name", tagEnd: "state-tag-end", attributeNameStart: "state-attribute-name-start", attributeName: "state-attribute-name", attributeNameEnd: "state-attribute-name-end", attributeValueBegin: "state-attribute-value-begin", attributeValue: "state-attribute-value" }, s2 = { lt: "action-lt", gt: "action-gt", space: "action-space", equal: "action-equal", quote: "action-quote", slash: "action-slash", char: "action-char", error: "action-error" }, a2 = { text: "text", openTag: "open-tag", closeTag: "close-tag", attributeName: "attribute-name", attributeValue: "attribute-value" }, c2 = { " ": s2.space, "\t": s2.space, "\n": s2.space, "\r": s2.space, "<": s2.lt, ">": s2.gt, '"': s2.quote, "'": s2.quote, "=": s2.equal, "/": s2.slash };
e2.exports = { State: r2, Action: s2, Type: a2, create: function(t48) {
var e3, l2, h2, d2, u2, p2, m2, g2, f2, y2;
t48 = Object.assign({ debug: false }, t48);
var _2 = new o2, b2 = r2.data, x2 = "", v2 = "", I2 = "", S2 = "", C2 = "", P2 = "", M2 = function(e4, n3) {
if (v2[0] !== "?" && v2[0] !== "!") {
var o3 = { type: e4, value: n3 };
t48.debug && console.log("emit:", o3), _2.emit("data", o3);
}
};
_2.stateMachine = (n2(y2 = {}, r2.data, (n2(e3 = {}, s2.lt, function() {
x2.trim() && M2(a2.text, x2), v2 = "", C2 = false, b2 = r2.tagBegin;
}), n2(e3, s2.char, function(t49) {
x2 += t49;
}), e3)), n2(y2, r2.cdata, n2({}, s2.char, function(t49) {
(x2 += t49).substr(-3) === "]]>" && (M2(a2.text, x2.slice(0, -3)), x2 = "", b2 = r2.data);
})), n2(y2, r2.tagBegin, (n2(l2 = {}, s2.space, i2), n2(l2, s2.char, function(t49) {
v2 = t49, b2 = r2.tagName;
}), n2(l2, s2.slash, function() {
v2 = "", C2 = true;
}), l2)), n2(y2, r2.tagName, (n2(h2 = {}, s2.space, function() {
C2 ? b2 = r2.tagEnd : (b2 = r2.attributeNameStart, M2(a2.openTag, v2));
}), n2(h2, s2.gt, function() {
M2(C2 ? a2.closeTag : a2.openTag, v2), x2 = "", b2 = r2.data;
}), n2(h2, s2.slash, function() {
b2 = r2.tagEnd, M2(a2.openTag, v2);
}), n2(h2, s2.char, function(t49) {
(v2 += t49) === "![CDATA[" && (b2 = r2.cdata, x2 = "", v2 = "");
}), h2)), n2(y2, r2.tagEnd, (n2(d2 = {}, s2.gt, function() {
M2(a2.closeTag, v2), x2 = "", b2 = r2.data;
}), n2(d2, s2.char, i2), d2)), n2(y2, r2.attributeNameStart, (n2(u2 = {}, s2.char, function(t49) {
I2 = t49, b2 = r2.attributeName;
}), n2(u2, s2.gt, function() {
x2 = "", b2 = r2.data;
}), n2(u2, s2.space, i2), n2(u2, s2.slash, function() {
C2 = true, b2 = r2.tagEnd;
}), u2)), n2(y2, r2.attributeName, (n2(p2 = {}, s2.space, function() {
b2 = r2.attributeNameEnd;
}), n2(p2, s2.equal, function() {
M2(a2.attributeName, I2), b2 = r2.attributeValueBegin;
}), n2(p2, s2.gt, function() {
S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), x2 = "", b2 = r2.data;
}), n2(p2, s2.slash, function() {
C2 = true, S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), b2 = r2.tagEnd;
}), n2(p2, s2.char, function(t49) {
I2 += t49;
}), p2)), n2(y2, r2.attributeNameEnd, (n2(m2 = {}, s2.space, i2), n2(m2, s2.equal, function() {
M2(a2.attributeName, I2), b2 = r2.attributeValueBegin;
}), n2(m2, s2.gt, function() {
S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), x2 = "", b2 = r2.data;
}), n2(m2, s2.char, function(t49) {
S2 = "", M2(a2.attributeName, I2), M2(a2.attributeValue, S2), I2 = t49, b2 = r2.attributeName;
}), m2)), n2(y2, r2.attributeValueBegin, (n2(g2 = {}, s2.space, i2), n2(g2, s2.quote, function(t49) {
P2 = t49, S2 = "", b2 = r2.attributeValue;
}), n2(g2, s2.gt, function() {
M2(a2.attributeValue, S2 = ""), x2 = "", b2 = r2.data;
}), n2(g2, s2.char, function(t49) {
P2 = "", S2 = t49, b2 = r2.attributeValue;
}), g2)), n2(y2, r2.attributeValue, (n2(f2 = {}, s2.space, function(t49) {
P2 ? S2 += t49 : (M2(a2.attributeValue, S2), b2 = r2.attributeNameStart);
}), n2(f2, s2.quote, function(t49) {
P2 === t49 ? (M2(a2.attributeValue, S2), b2 = r2.attributeNameStart) : S2 += t49;
}), n2(f2, s2.gt, function(t49) {
P2 ? S2 += t49 : (M2(a2.attributeValue, S2), x2 = "", b2 = r2.data);
}), n2(f2, s2.slash, function(t49) {
P2 ? S2 += t49 : (M2(a2.attributeValue, S2), C2 = true, b2 = r2.tagEnd);
}), n2(f2, s2.char, function(t49) {
S2 += t49;
}), f2)), y2);
var N2 = function(e4) {
t48.debug && console.log(b2, e4);
var n3 = _2.stateMachine[b2], o3 = n3[function(t49) {
return c2[t49] || s2.char;
}(e4)] || n3[s2.error] || n3[s2.char];
o3(e4);
};
return _2.write = function(t49) {
for (var e4 = t49.length, n3 = 0;n3 < e4; n3++)
N2(t49[n3]);
}, _2;
} };
} });
var F$ = E$({ "node_modules/xml-reader/dist/reader.js"(t47, e2) {
var n2 = z$(), o2 = B$(), i2 = o2.Type, r2 = { element: "element", text: "text" }, s2 = function(t48) {
return Object.assign({ name: "", type: r2.element, value: "", parent: null, attributes: {}, children: [] }, t48);
}, a2 = function(t48) {
t48 = Object.assign({ stream: false, parentNodes: true, doneEvent: "done", tagPrefix: "tag:", emitTopLevelOnly: false, debug: false }, t48);
var e3 = undefined, a3 = undefined, c2 = undefined, l2 = undefined, h2 = new n2, d2 = function(n3) {
switch (n3.type) {
case i2.openTag:
if (c2 === null)
(c2 = a3).name = n3.value;
else {
var o3 = s2({ name: n3.value, parent: c2 });
c2.children.push(o3), c2 = o3;
}
break;
case i2.closeTag:
var d3 = c2.parent;
if (t48.parentNodes || (c2.parent = null), c2.name !== n3.value)
break;
t48.stream && d3 === a3 && (a3.children = [], c2.parent = null), t48.emitTopLevelOnly && d3 !== a3 || (h2.emit(t48.tagPrefix + c2.name, c2), h2.emit("tag", c2.name, c2)), c2 === a3 && (e3.removeAllListeners("data"), h2.emit(t48.doneEvent, c2), a3 = null), c2 = d3;
break;
case i2.text:
c2 && c2.children.push(s2({ type: r2.text, value: n3.value, parent: t48.parentNodes ? c2 : null }));
break;
case i2.attributeName:
l2 = n3.value, c2.attributes[l2] = "";
break;
case i2.attributeValue:
c2.attributes[l2] = n3.value;
}
};
return h2.reset = function() {
(e3 = o2.create({ debug: t48.debug })).on("data", d2), a3 = s2(), c2 = null, l2 = "", h2.parse = e3.write;
}, h2.reset(), h2;
};
e2.exports = { parseSync: function(t48, e3) {
e3 = Object.assign({}, e3, { stream: false, tagPrefix: ":" });
var n3 = a2(e3), o3 = undefined;
return n3.on("done", function(t49) {
o3 = t49;
}), n3.parse(t48), o3;
}, create: a2, NodeType: r2 };
} });
A$(L$()), A$(F$());
var QY = (t47) => {
const { candidates: e2, mapOfCapacityMeshNodeIdToRef: n2 } = t47;
let o2 = true;
for (const t48 of e2) {
let e3 = false;
t48.port.nodeIds.forEach((t49) => {
const o3 = n2.get(t49);
if (!o3)
throw new Error(`Could not find capacity mesh node for id ${t49}`);
o3._containsObstacle && (e3 = true);
}), e3 || (o2 = false);
}
return o2;
};
var KY = (t47) => t47.depth + 1000 * t47.countOfCrampedPortPointsInPath;
var tX = class extends kt {
constructor(t47) {
if (super(), this.input = t47, this.input.depthLimit < 1)
throw new Error("Depth limit must be at least 1");
this._setup();
}
queue = [];
resultExploredPortPoints = [];
currentExploredPortPoints = null;
visitedExploredPortPoints = new Map;
getSolverName() {
return "singleTargetNecessaryCrampedPortPointSolver";
}
_setup() {
const t47 = this.input.mapOfCapacityMeshNodeIdToSegmentPortPoints.get(this.input.target.capacityMeshNodeId) ?? [];
for (const e2 of t47) {
if (this.input.shouldIgnoreCrampedPortPoints && e2.cramped)
continue;
const t48 = { port: e2, depth: 1, parent: null, countOfCrampedPortPointsInPath: e2.cramped ? 1 : 0 }, n2 = this.visitedExploredPortPoints.get(e2);
(!n2 || this.getCandidateCost(t48) < this.getCandidateCost(n2)) && (this.visitedExploredPortPoints.set(e2, t48), this.queue.push(t48));
}
}
_step() {
if (this.queue.length === 0)
return this.currentExploredPortPoints = null, void (this.solved = true);
for (;this.queue.length > 0; ) {
this.currentExploredPortPoints = this.queue.shift();
if (this.visitedExploredPortPoints.get(this.currentExploredPortPoints.port) !== this.currentExploredPortPoints)
continue;
if (this.currentExploredPortPoints.depth === this.input.depthLimit) {
this.resultExploredPortPoints.push(this.currentExploredPortPoints);
continue;
}
const t47 = this.currentExploredPortPoints.port.nodeIds.map((t48) => {
const e2 = this.input.mapOfCapacityMeshNodeIdToRef.get(t48);
if (!e2)
throw new Error(`Could not find capacity mesh node for id ${t48}`);
return e2;
}).flatMap((t48) => this.input.mapOfCapacityMeshNodeIdToSegmentPortPoints.get(t48.capacityMeshNodeId) ?? []);
for (const e2 of t47) {
if (this.input.shouldIgnoreCrampedPortPoints && e2.cramped)
continue;
const t48 = { port: e2, depth: this.currentExploredPortPoints.depth + 1, parent: this.currentExploredPortPoints, countOfCrampedPortPointsInPath: this.currentExploredPortPoints.countOfCrampedPortPointsInPath + (e2.cramped ? 1 : 0) }, n2 = this.visitedExploredPortPoints.get(e2);
n2 && this.getCandidateCost(n2) <= this.getCandidateCost(t48) || (this.visitedExploredPortPoints.set(e2, t48), this.queue.push(t48));
}
}
this.solved = true;
}
getCandidateCost(t47) {
return t47.depth + 1000 * t47.countOfCrampedPortPointsInPath;
}
getOutput() {
return this.resultExploredPortPoints;
}
visualize() {
const t47 = { points: [], rects: [] };
for (const e2 of this.visitedExploredPortPoints.keys())
t47.points.push({ ...e2, color: e2.cramped ? "blue" : "green" });
return t47;
}
};
var eX = class extends kt {
constructor(t47) {
super(), this.input = t47, this._setup();
}
unprocessedTargets = [];
targetNode = [];
currentTarget;
crampedPortPointsToKeep = new Set;
candidatesAtDepth = [];
isRunningCrampedPass = false;
filteredOutput;
activeSubSolver = null;
nodeMap = new Map;
mapOfCapacityMeshNodeIdToSegmentPortPoints = new Map;
getSolverName() {
return "multiTargetNecessaryCrampedPortPointSolver";
}
_setup() {
this.targetNode = this.input.capacityMeshNodes.filter((t47) => t47._containsObstacle), this.targetNode = this.targetNode.filter((t47) => {
for (const e2 of this.input.simpleRouteJson.connections)
for (const n2 of e2.pointsToConnect)
if (Fe(n2, t47) <= 0)
return true;
return false;
}), this.unprocessedTargets = [...this.targetNode], this.unprocessedTargets.sort((t47, e2) => t47.center.x - e2.center.x);
for (const t47 of this.input.capacityMeshNodes)
this.nodeMap.set(t47.capacityMeshNodeId, t47);
for (const t47 of this.input.sharedEdgeSegments)
for (const e2 of t47.portPoints) {
const t48 = e2.nodeIds;
for (const n2 of t48) {
if (!this.nodeMap.get(n2))
throw new Error(`Could not find capacity mesh node for id ${n2}`);
const t49 = this.mapOfCapacityMeshNodeIdToSegmentPortPoints.get(n2) || [];
this.mapOfCapacityMeshNodeIdToSegmentPortPoints.set(n2, [...t49, e2]);
}
}
}
_step() {
if (this.activeSubSolver) {
if (this.activeSubSolver._step(), !this.activeSubSolver.solved)
return;
if (this.activeSubSolver.failed)
return this.failed = true, void (this.error = this.activeSubSolver.error);
if (this.candidatesAtDepth = this.activeSubSolver.getOutput(), this.activeSubSolver = null, !this.currentTarget)
return this.failed = true, void (this.error = "Missing current capacity mesh node while finishing BFS");
if (!this.isRunningCrampedPass) {
return QY({ candidates: this.candidatesAtDepth, mapOfCapacityMeshNodeIdToRef: this.nodeMap }) || this.candidatesAtDepth.length === 0 ? (this.isRunningCrampedPass = true, void (this.activeSubSolver = new tX({ target: this.currentTarget, depthLimit: 3, shouldIgnoreCrampedPortPoints: false, mapOfCapacityMeshNodeIdToSegmentPortPoints: this.mapOfCapacityMeshNodeIdToSegmentPortPoints, mapOfCapacityMeshNodeIdToRef: this.nodeMap }))) : void (this.currentTarget = undefined);
}
let t47 = this.candidatesAtDepth.filter((t48) => {
const e2 = t48.port;
return e2.nodeIds.map((t49) => {
const e3 = this.nodeMap.get(t49);
if (!e3)
throw this.failed = true, this.error = `Could not find capacity mesh node for id ${t49}`, new Error(`Could not find capacity mesh node for id ${t49}`);
return e3;
}).every((t49) => !t49._containsObstacle) && e2.cramped;
});
if (QY({ candidates: t47, mapOfCapacityMeshNodeIdToRef: this.nodeMap }) && (this.error = `All candidates are blocked by obstacles even after including cramped port points for capacity mesh node ${this.currentTarget.capacityMeshNodeId}`), this.candidatesAtDepth = [...t47].sort((t48, e2) => {
const n2 = KY(t48) - KY(e2);
return n2 !== 0 ? n2 : this.getCandidateExitCapacity(e2) - this.getCandidateExitCapacity(t48);
}), this.candidatesAtDepth.length === 0)
this.error = `No candidates found for capacity mesh node ${this.currentTarget.capacityMeshNodeId} even after including cramped port points`;
else {
const t48 = new Map;
for (const e3 of this.candidatesAtDepth) {
if (!e3.parent)
throw new Error(`Missing parent for cramped escape candidate ${e3.port.segmentPortPointId}`);
const n2 = `${e3.parent.port.segmentPortPointId}->${e3.port.segmentPortPointId}`;
if (!t48.has(n2) && (t48.set(n2, e3), t48.size === 5))
break;
}
const e2 = [...t48.values()];
for (const t49 of e2)
this.keepCandidatePath(t49);
}
return this.isRunningCrampedPass = false, void (this.currentTarget = undefined);
}
if (!this.currentTarget)
return this.currentTarget = this.unprocessedTargets.shift(), this.currentTarget ? (this.isRunningCrampedPass = false, this.candidatesAtDepth = [], void (this.activeSubSolver = new tX({ target: this.currentTarget, depthLimit: 2, shouldIgnoreCrampedPortPoints: true, mapOfCapacityMeshNodeIdToSegmentPortPoints: this.mapOfCapacityMeshNodeIdToSegmentPortPoints, mapOfCapacityMeshNodeIdToRef: this.nodeMap }))) : void (this.solved = true);
}
getOutput() {
return this.filteredOutput || (this.filteredOutput = this.input.sharedEdgeSegments.map((t47) => ({ ...t47, portPoints: t47.portPoints.flatMap((t48) => !t48.cramped || this.crampedPortPointsToKeep.has(t48) ? [t48] : this.isMultilayerEscapePort(t48) ? [{ ...t48, tinyHypergraphPortPenalty: 1000 }] : []) }))), this.filteredOutput;
}
getCandidateExitCapacity(t47) {
if (!t47.parent)
throw new Error(`Missing parent for cramped escape candidate ${t47.port.segmentPortPointId}`);
const e2 = new Set(t47.parent.port.nodeIds), n2 = t47.port.nodeIds.filter((t48) => !e2.has(t48)).map((t48) => {
const e3 = this.nodeMap.get(t48);
if (!e3)
throw new Error(`Could not find capacity mesh node for id ${t48}`);
return e3;
});
if (n2.length === 0)
throw new Error(`Could not find exit node for cramped escape candidate ${t47.port.segmentPortPointId}`);
return Math.max(0, ...n2.map((t48) => t48.width * t48.height * t48.availableZ.length));
}
keepCandidatePath(t47) {
this.crampedPortPointsToKeep.add(t47.port);
let e2 = t47.parent;
for (;e2; )
this.crampedPortPointsToKeep.add(e2.port), e2 = e2.parent;
}
isMultilayerEscapePort(t47) {
return t47.nodeIds.some((t48) => (this.nodeMap.get(t48)?.availableZ.length ?? 0) > 1);
}
visualize() {
const t47 = { rects: [], points: [] };
for (const e2 of this.targetNode)
t47.rects.push({ ...e2, fill: this.currentTarget?.capacityMeshNodeId === e2.capacityMeshNodeId ? "rgba(255, 0, 0, 0.5)" : "rgba(255, 0, 0, 0.2)" });
for (const e2 of this.candidatesAtDepth)
t47.points.push({ ...e2.port, color: e2.port.cramped ? "blue" : "green" });
for (const e2 of this.crampedPortPointsToKeep)
t47.points.push({ ...e2, color: "blue" });
return this.activeSubSolver ? At(t47, this.activeSubSolver.visualize()) : t47;
}
};
var nX = (t47) => `${t47.x.toFixed(4)},${t47.y.toFixed(4)}`;
var oX = (t47) => t47.netIsAssignable === true && (t47.layers?.length ?? 0) > 1;
var iX = (t47, e2) => t47.connectedTo?.find((t48) => t48.startsWith("pcb_via")) ?? t47.obstacleId ?? `assignable_via_${e2}`;
var rX = (t47) => [...new Set(t47.obstacle.layers.map((e2) => mo(e2, t47.layerCount)))].sort((t48, e2) => t48 - e2);
function cX(t47, e2) {
if (t47 == null)
throw new Error(e2);
}
function lX(t47, e2) {
const n2 = [];
for (const o2 of t47)
e2.includes(o2) && n2.push(o2);
return n2;
}
function hX(t47) {
if (Fe(t47.point, t47.region.d) <= 0.001) {
if (lX(So(t47.point).map((e2) => mo(e2, t47.layerCount)), t47.region.d.availableZ).length > 0)
return true;
}
return false;
}
function dX({ graph: t47, point: e2, layerCount: n2 }) {
const o2 = t47.regions.filter((t48) => hX({ point: e2, region: t48, layerCount: n2 })), i2 = function({ point: t48, layerCount: e3 }) {
const n3 = So(t48).map((t49) => mo(t49, e3));
return [...new Set(n3)];
}({ point: e2, layerCount: n2 });
return o2.find((t48) => function({ region: t49, pointZLayers: e3 }) {
return t49.ports.some((t50) => e3.includes(t50.d.z) && lX(e3, t50.region1.d.availableZ).length > 0 && lX(e3, t50.region2.d.availableZ).length > 0);
}({ region: t48, pointZLayers: i2 })) ?? o2[0];
}
var uX = (t47, e2) => {
const n2 = t47.getNetConnectedToId(e2);
if (!n2)
throw new Error(`Could not resolve net ID for connection "${e2}"`);
return n2;
};
var pX = (t47) => {
const e2 = t47.graph.regions.filter((e3) => e3.d.availableZ.includes(t47.z) && !e3.d._assignableVia).map((e3) => ({ region: e3, distance: Fe(t47.point, e3.d) })).sort((t48, e3) => t48.distance - e3.distance || t48.region.d.width * t48.region.d.height - e3.region.d.width * e3.region.d.height), n2 = e2[0]?.distance;
if (n2 === undefined)
return [];
const o2 = Math.max(n2 + 0.000001, t47.viaRadius + 0.15);
return e2.filter((t48) => t48.distance <= o2).slice(0, 4).map((t48) => t48.region);
};
function mX(t47) {
const e2 = { ports: [], regions: [] }, n2 = [];
for (const n3 of t47.capacityMeshNodes) {
const o2 = n3._connectedTo?.map((e3) => uX(t47.connectivityMap, e3));
e2.regions.push({ regionId: n3.capacityMeshNodeId, d: o2 ? { ...n3, _connectedTo: [...new Set(o2)] } : n3, ports: [] });
}
for (const n3 of t47.segmentPortPoints) {
const [t48, o2] = n3.nodeIds, i2 = e2.regions.find((e3) => e3.regionId === t48), r2 = e2.regions.find((t49) => t49.regionId === o2);
cX(i2, `Could not find region with id ${t48} for segment port point ${n3.segmentPortPointId}`), cX(r2, `Could not find region with id ${o2} for segment port point ${n3.segmentPortPointId}`);
for (const t49 of n3.availableZ) {
const o3 = n3._preloadedTracePortAssignments?.filter((e3) => e3.z === t49), s2 = { portId: `${n3.segmentPortPointId}::${t49}`, x: n3.x, y: n3.y, z: t49, distToCentermostPortOnZ: n3.distToCentermostPortOnZ, cramped: n3.cramped, regions: [i2, r2], tinyHypergraphPortPenalty: n3.tinyHypergraphPortPenalty, _preloadedFixedNetIds: o3 && o3.length > 0 ? [...new Set(o3.map((t50) => t50.fixedNetId))].sort() : undefined, _preloadedTracePortAssignments: o3 }, a2 = { portId: n3.segmentPortPointId, d: s2, region1: i2, region2: r2 };
e2.ports.push(a2), i2.ports.push(a2), r2.ports.push(a2);
}
}
((t48) => {
for (const [e3, n3] of t48.assignableViaObstacles.entries()) {
if (!oX(n3))
continue;
const o2 = rX({ obstacle: n3, layerCount: t48.layerCount });
if (o2.length < 2)
continue;
const i2 = `assignable-via:${iX(n3, e3)}`, r2 = Math.min(n3.width, n3.height) / 2, s2 = { regionId: i2, d: { capacityMeshNodeId: i2, center: { ...n3.center }, width: n3.width, height: n3.height, layer: `z${o2.join(",")}`, availableZ: o2, _containsObstacle: false, _completelyInsideObstacle: false, _containsTarget: false, _assignableVia: true, _assignedViaObstacle: n3 }, ports: [] }, a2 = [];
for (const e4 of o2)
for (const o3 of pX({ graph: t48.graph, point: n3.center, z: e4, viaRadius: r2 })) {
const t49 = { portId: `${i2}:port:${o3.regionId}:z${e4}`, x: n3.center.x, y: n3.center.y, z: e4, distToCentermostPortOnZ: 0, cramped: false, regions: [o3, s2] }, r3 = { portId: t49.portId, d: t49, region1: o3, region2: s2 };
a2.push(r3), o3.ports.push(r3);
}
if (new Set(a2.map((t49) => t49.d.z)).size < 2)
for (const t49 of a2)
t49.region1.ports = t49.region1.ports.filter((e4) => e4 !== t49);
else
s2.ports.push(...a2), t48.graph.regions.push(s2), t48.graph.ports.push(...a2);
}
})({ graph: e2, assignableViaObstacles: t47.assignableViaObstacles ?? [], layerCount: t47.layerCount });
for (const o2 of t47.simpleRouteJsonConnections) {
const [i2, r2] = o2.pointsToConnect, s2 = dX({ graph: e2, point: i2, layerCount: t47.layerCount }), a2 = dX({ graph: e2, point: r2, layerCount: t47.layerCount });
cX(s2, `Could not find start region for connection "${o2.name}"`), cX(a2, `Could not find end region for connection "${o2.name}"`), n2.push({ connectionId: o2.name, mutuallyConnectedNetworkId: uX(t47.connectivityMap, o2.name), startRegion: s2, endRegion: a2, simpleRouteConnection: o2 });
}
return { graph: e2, connections: n2 };
}
var SX = class {
MAX_ITERATIONS = 1000;
solved = false;
failed = false;
iterations = 0;
progress = 0;
error = null;
activeSubSolver;
failedSubSolvers;
timeToSolve;
stats = {};
pendingEffects;
cacheHit;
cacheKey;
cacheToSolveSpaceTransform;
getSolverName() {
return this.constructor.name;
}
step() {
if (!this.solved && !this.failed) {
this.iterations++;
try {
this._step();
} catch (t47) {
throw this.error = `${this.getSolverName()} error: ${t47}`, console.error(this.error), this.failed = true, t47;
}
!this.solved && this.iterations > this.MAX_ITERATIONS && this.tryFinalAcceptance(), !this.solved && this.iterations > this.MAX_ITERATIONS && (this.error = `${this.getSolverName()} ran out of iterations (MAX_ITERATIONS=${this.MAX_ITERATIONS})`, this.failed = true), "computeProgress" in this && (this.progress = this.computeProgress());
}
}
_step() {}
getConstructorParams() {
throw new Error("getConstructorParams not implemented");
}
solve() {
const t47 = Date.now();
for (;!this.solved && !this.failed; )
this.step();
const e2 = Date.now();
this.timeToSolve = e2 - t47;
}
visualize() {
return { lines: [], points: [], rects: [], circles: [] };
}
tryFinalAcceptance() {}
preview() {
return { lines: [], points: [], rects: [], circles: [] };
}
};
var CX = (t47, e2) => {
const n2 = (t48) => t48 === " " || t48 === `
` || t48 === "\r" || t48 === "\t", o2 = (t48) => {
let e3 = 0, o3 = t48.length;
for (;e3 < o3 && n2(t48[e3]); )
e3 += 1;
for (;o3 > e3 && n2(t48[o3 - 1]); )
o3 -= 1;
return t48.slice(e3, o3);
}, i2 = (t48) => {
const e3 = [];
let n3 = 0, i3 = 0;
for (let r3 = 0;r3 < t48.length; r3 += 1) {
const s3 = t48[r3];
s3 !== "(" ? s3 !== ")" ? s3 === "," && i3 === 0 && (e3.push(o2(t48.slice(n3, r3))), n3 = r3 + 1) : i3 > 0 && (i3 -= 1) : i3 += 1;
}
return e3.push(o2(t48.slice(n3))), e3;
}, r2 = (t48) => {
return `${e3 = t48, Math.min(1, Math.max(0, e3))}`;
var e3;
}, s2 = ((t48) => {
const e3 = o2(t48);
if (!e3.startsWith("#"))
return null;
const n3 = e3.slice(1);
if (n3.length !== 3 && n3.length !== 6)
return null;
for (const t49 of n3) {
const e4 = t49.toLowerCase();
if (!(e4 >= "0" && e4 <= "9") && !(e4 >= "a" && e4 <= "f"))
return null;
}
if (n3.length === 3) {
const [t49, e4, o3] = n3;
return { r: Number.parseInt(t49 + t49, 16), g: Number.parseInt(e4 + e4, 16), b: Number.parseInt(o3 + o3, 16) };
}
return { r: Number.parseInt(n3.slice(0, 2), 16), g: Number.parseInt(n3.slice(2, 4), 16), b: Number.parseInt(n3.slice(4, 6), 16) };
})(e2);
if (s2)
return `rgba(${s2.r}, ${s2.g}, ${s2.b}, ${r2(1 - t47)})`;
const a2 = ((t48) => {
const e3 = o2(t48), n3 = e3.indexOf("(");
return n3 <= 0 || e3[e3.length - 1] !== ")" ? null : { name: o2(e3.slice(0, n3)).toLowerCase(), args: i2(e3.slice(n3 + 1, -1)) };
})(e2);
if (!a2)
return e2;
const { name: c2, args: l2 } = a2;
if (c2 === "hsl" || c2 === "rgb")
return l2.length !== 3 ? e2 : `${c2}a(${l2[0]}, ${l2[1]}, ${l2[2]}, ${r2(1 - t47)})`;
if (c2 === "hsla" || c2 === "rgba") {
if (l2.length !== 4)
return e2;
const n3 = ((t48) => {
const e3 = o2(t48);
if (!e3)
return null;
const n4 = Number.parseFloat(e3);
return Number.isFinite(n4) ? n4 : null;
})(l2[3]);
return n3 === null ? e2 : `${c2}(${l2[0]}, ${l2[1]}, ${l2[2]}, ${r2(n3 - t47)})`;
}
return e2;
};
var PX = (t47, e2) => {
try {
return CX(e2, t47);
} catch (e3) {
return console.error(e3), t47;
}
};
var MX = (t47) => t47.rootConnectionName ?? t47.connectionName;
var NX = (t47) => {
const e2 = [];
for (let n2 = 0;n2 < t47.route.length - 1; n2 += 1) {
const o2 = t47.route[n2], i2 = t47.route[n2 + 1];
if (!o2 || !i2 || o2.z === i2.z)
continue;
if (Math.abs(o2.x - i2.x) > 0.000001 || Math.abs(o2.y - i2.y) > 0.000001)
continue;
const r2 = { x: Math.round(1000 * o2.x) / 1000, y: Math.round(1000 * o2.y) / 1000 }, s2 = e2.at(-1);
s2 && s2.x === r2.x && s2.y === r2.y || e2.push(r2);
}
return e2;
};
var wX = (t47, e2, n2 = 0.001) => Math.abs(t47.x - e2.x) <= n2 && Math.abs(t47.y - e2.y) <= n2;
var TX = (t47, e2) => ({ minX: t47.center.x - t47.width / 2 + e2, maxX: t47.center.x + t47.width / 2 - e2, minY: t47.center.y - t47.height / 2 + e2, maxY: t47.center.y + t47.height / 2 - e2 });
var RX = (t47, e2) => ({ x: t47.x - e2.x, y: t47.y - e2.y });
var EX = (t47, e2) => t47.x * e2.x + t47.y * e2.y;
var AX = (t47, e2, n2) => ({ x: t47.x + (e2.x - t47.x) * n2, y: t47.y + (e2.y - t47.y) * n2 });
var OX = (t47) => {
const e2 = [];
for (let n2 = 0;n2 < t47.length; n2 += 1) {
const o2 = t47[n2];
if (o2)
for (let t48 = 0;t48 < o2.route.length - 1; t48 += 1) {
const i2 = o2.route[t48], r2 = o2.route[t48 + 1];
i2 && r2 && (i2.z !== r2.z || wX(i2, r2) || e2.push({ routeIndex: n2, rootConnectionName: MX(o2), startIndex: t48, endIndex: t48 + 1, start: i2, end: r2, z: i2.z, traceRadius: (o2.traceThickness ?? 0.1) / 2 }));
}
}
return e2;
};
var kX = (t47, e2, n2 = 0.000001) => {
const o2 = e2.end.x - e2.start.x, i2 = e2.end.y - e2.start.y, r2 = o2 * o2 + i2 * i2;
if (r2 <= n2)
return { x: e2.start.x, y: e2.start.y, t: 0 };
const s2 = ((t47.x - e2.start.x) * o2 + (t47.y - e2.start.y) * i2) / r2, a2 = (c2 = s2, Math.max(0, Math.min(c2, 1)));
var c2;
return { x: e2.start.x + o2 * a2, y: e2.start.y + i2 * a2, t: a2 };
};
var DX = (t47, e2, n2 = 0.000001) => {
const o2 = RX(t47.end, t47.start), i2 = RX(e2.end, e2.start), r2 = RX(t47.start, e2.start), s2 = EX(o2, o2), a2 = EX(o2, i2), c2 = EX(i2, i2), l2 = EX(o2, r2), h2 = EX(i2, r2), d2 = s2 * c2 - a2 * a2, u2 = n2;
let p2, m2, g2 = d2, f2 = d2;
d2 <= u2 ? (p2 = 0, g2 = 1, m2 = h2, f2 = c2) : (p2 = a2 * h2 - c2 * l2, m2 = s2 * h2 - a2 * l2, p2 < 0 ? (p2 = 0, m2 = h2, f2 = c2) : p2 > g2 && (p2 = g2, m2 = h2 + a2, f2 = c2)), m2 < 0 ? (m2 = 0, -l2 < 0 ? p2 = 0 : -l2 > s2 ? p2 = g2 : (p2 = -l2, g2 = s2)) : m2 > f2 && (m2 = f2, -l2 + a2 < 0 ? p2 = 0 : -l2 + a2 > s2 ? p2 = g2 : (p2 = -l2 + a2, g2 = s2));
const y2 = Math.abs(p2) <= u2 ? 0 : p2 / g2, _2 = Math.abs(m2) <= u2 ? 0 : m2 / f2, b2 = AX(t47.start, t47.end, y2), x2 = AX(e2.start, e2.end, _2), v2 = kX(t47.start, e2, n2), I2 = kX(t47.end, e2, n2), S2 = kX(e2.start, t47, n2), C2 = kX(e2.end, t47, n2);
return [{ leftT: y2, rightT: _2, leftPoint: b2, rightPoint: x2 }, { leftT: 0, rightT: v2.t, leftPoint: t47.start, rightPoint: v2 }, { leftT: 1, rightT: I2.t, leftPoint: t47.end, rightPoint: I2 }, { leftT: S2.t, rightT: 0, leftPoint: S2, rightPoint: e2.start }, { leftT: C2.t, rightT: 1, leftPoint: C2, rightPoint: e2.end }].sort((t48, e3) => Math.hypot(t48.leftPoint.x - t48.rightPoint.x, t48.leftPoint.y - t48.rightPoint.y) - Math.hypot(e3.leftPoint.x - e3.rightPoint.x, e3.leftPoint.y - e3.rightPoint.y));
};
var LX = 0.000001;
var zX = (t47) => {
const e2 = [];
for (const n2 of t47) {
const t48 = e2[n2.routeIndex] ?? [];
t48[n2.startIndex] = n2, e2[n2.routeIndex] = t48;
}
return e2;
};
var BX = (t47, e2) => t47 < e2 ? [t47, e2] : [e2, t47];
var FX = (t47, e2) => t47.some(([t48, n2]) => t48 === e2[0] && n2 === e2[1]);
var jX = (t47, e2, n2) => {
let o2, i2 = Number.POSITIVE_INFINITY;
for (const r2 of t47) {
if (r2.routeIndex !== e2.routeIndex || r2.z !== e2.z || r2.endIndex !== e2.startIndex && r2.startIndex !== e2.endIndex)
continue;
const [t48] = DX(r2, n2);
if (!t48)
continue;
const s2 = Math.hypot(t48.leftPoint.x - t48.rightPoint.x, t48.leftPoint.y - t48.rightPoint.y);
s2 >= i2 || (i2 = s2, o2 = r2);
}
return o2;
};
var $X = (t47, e2) => {
const n2 = OX(e2), o2 = OX(t47), i2 = zX(o2), r2 = [];
for (let t48 = 0;t48 < n2.length; t48 += 1) {
const e3 = n2[t48];
if (e3)
for (let s2 = t48 + 1;s2 < n2.length; s2 += 1) {
const t49 = n2[s2];
if (!t49 || e3.z !== t49.z || e3.rootConnectionName === t49.rootConnectionName || Math.max(e3.start.x, e3.end.x) < Math.min(t49.start.x, t49.end.x) || Math.max(t49.start.x, t49.end.x) < Math.min(e3.start.x, e3.end.x) || Math.max(e3.start.y, e3.end.y) < Math.min(t49.start.y, t49.end.y) || Math.max(t49.start.y, t49.end.y) < Math.min(e3.start.y, e3.end.y))
continue;
const [a2] = DX(e3, t49);
if (!a2 || Math.hypot(a2.leftPoint.x - a2.rightPoint.x, a2.leftPoint.y - a2.rightPoint.y) > LX || a2.leftT <= LX || a2.leftT >= 0.999999 || a2.rightT <= LX || a2.rightT >= 0.999999)
continue;
const c2 = i2[e3.routeIndex]?.[e3.startIndex], l2 = i2[t49.routeIndex]?.[t49.startIndex];
if (!c2 || !l2)
continue;
const [h2] = DX(c2, l2);
if (!h2 || Math.hypot(h2.leftPoint.x - h2.rightPoint.x, h2.leftPoint.y - h2.rightPoint.y) <= LX)
continue;
const d2 = jX(o2, c2, l2), u2 = jX(o2, l2, c2), p2 = d2 ? [c2, d2] : [c2], m2 = u2 ? [l2, u2] : [l2];
for (const n3 of p2)
for (const o3 of m2) {
const i3 = { leftRouteIndex: e3.routeIndex, leftStartPointIndex: n3.startIndex, rightRouteIndex: t49.routeIndex, rightStartPointIndex: o3.startIndex };
r2.some((t50) => t50.leftRouteIndex === i3.leftRouteIndex && t50.leftStartPointIndex === i3.leftStartPointIndex && t50.rightRouteIndex === i3.rightRouteIndex && t50.rightStartPointIndex === i3.rightStartPointIndex) || r2.push(i3);
}
}
}
return r2;
};
var YX = (t47) => {
const e2 = OX(t47), n2 = [];
for (let t48 = 0;t48 < e2.length; t48 += 1) {
const o2 = e2[t48];
if (o2)
for (let i2 = t48 + 1;i2 < e2.length; i2 += 1) {
const t49 = e2[i2];
if (!t49 || o2.z !== t49.z || o2.rootConnectionName === t49.rootConnectionName)
continue;
const [r2] = DX(o2, t49);
if (!r2)
continue;
if (Math.hypot(r2.leftPoint.x - r2.rightPoint.x, r2.leftPoint.y - r2.rightPoint.y) + LX < o2.traceRadius + t49.traceRadius) {
const e3 = BX(o2.routeIndex, t49.routeIndex);
FX(n2, e3) || n2.push(e3);
}
}
}
return n2;
};
var XX = (t47, e2) => e2 <= 1 || e2 >= t47 - 2;
var WX = (t47, e2) => e2.some((e3) => XX(t47, e3));
var VX = 0.2;
var HX = 0.4;
var GX = 0.65 + 0.05;
var UX = 0.03;
var ZX = 1000;
var qX = 0.000001;
var JX = 0.015;
var QX = (t47) => Math.round(t47 * ZX) / ZX;
var KX = (t47, e2) => ({ x: t47.x - e2.x, y: t47.y - e2.y });
var tW = (t47, e2) => ({ x: t47.x * e2, y: t47.y * e2 });
var eW = (t47, e2) => t47.x * e2.x + t47.y * e2.y;
var nW = (t47, e2, n2) => ({ x: t47.x + (e2.x - t47.x) * n2, y: t47.y + (e2.y - t47.y) * n2 });
var oW = (t47) => Math.max(0, Math.min(t47, 1));
var iW = (t47, e2, n2) => Math.max(e2, Math.min(t47, n2));
var rW = (t47, e2) => {
const n2 = ((t48) => Math.hypot(t48.x, t48.y))(t47);
return n2 <= e2 || n2 <= qX ? t47 : tW(t47, e2 / n2);
};
var sW = (t47, e2 = 0) => ({ minX: t47.center.x - t47.width / 2 - e2, maxX: t47.center.x + t47.width / 2 + e2, minY: t47.center.y - t47.height / 2 - e2, maxY: t47.center.y + t47.height / 2 + e2 });
var aW = (t47, e2, n2 = 0) => {
const o2 = sW(e2, n2);
return t47.x >= o2.minX && t47.x <= o2.maxX && t47.y >= o2.minY && t47.y <= o2.maxY;
};
var cW = (t47, e2, n2) => {
if (t47.regionId) {
const n3 = e2.findIndex((e3) => e3.capacityMeshNodeId === t47.regionId);
if (n3 !== -1)
return n3;
}
const o2 = [...t47.route.map(({ x: t48, y: e3 }) => ({ x: t48, y: e3 })), ...t47.vias.map(({ x: t48, y: e3 }) => ({ x: t48, y: e3 }))];
let i2 = -1, r2 = Number.POSITIVE_INFINITY;
for (let t48 = 0;t48 < e2.length; t48++) {
const s2 = e2[t48];
if (!s2 || !o2.every((t49) => aW(t49, s2, n2)))
continue;
const a2 = s2.width * s2.height;
a2 < r2 && (r2 = a2, i2 = t48);
}
return i2;
};
var lW = (t47, e2, n2, o2) => {
const i2 = ((t48, e3, n3) => {
const o3 = Math.min(Math.abs(t48.originalX - n3.minX), Math.abs(n3.maxX - t48.originalX)), i3 = Math.min(Math.abs(t48.originalY - n3.minY), Math.abs(n3.maxY - t48.originalY));
if (Math.abs(o3 - i3) <= qX)
return Math.abs(e3.x - t48.x) >= Math.abs(e3.y - t48.y) ? "y" : "x";
return o3 < i3 ? "y" : "x";
})(t47, e2, n2);
return rW(i2 === "x" ? { x: 1.1 * (t47.x - e2.x) * o2, y: 0 } : { x: 0, y: 1.1 * (t47.y - e2.y) * o2 }, 0.06 * o2);
};
var hW = (t47, e2, n2, o2, i2 = 3.5, r2 = 0.2, s2 = 0.4) => {
const a2 = Math.max(t47, 0);
if (a2 >= s2)
return 0;
const c2 = a2 / r2;
if (c2 < 1) {
const t48 = 1 - c2;
return e2 * t48 ** 3 * (1 + t48 * i2);
}
const l2 = (a2 - r2) / Math.max(s2 - r2, qX), h2 = e2 * n2 * Math.exp(-l2 * o2);
return h2 < 0.00001 ? 0 : h2;
};
var dW = (t47, e2) => {
const n2 = t47.boundaryPadding > 0 ? 0.001 : 0, o2 = e2.minX + t47.boundaryPadding + n2, i2 = e2.maxX - t47.boundaryPadding - n2, r2 = e2.minY + t47.boundaryPadding + n2, s2 = e2.maxY - t47.boundaryPadding - n2;
t47.x = iW(t47.x, o2, i2), t47.y = iW(t47.y, r2, s2);
};
var uW = (t47, e2) => {
for (const n2 of t47)
for (const t48 of n2.nodes)
dW(t48, e2);
};
var pW = (t47) => t47.kind === "via" ? 0.4 : 0.25;
var mW = (t47) => (t47.kind, 0.5);
var gW = (t47) => t47.kind === "via" ? 12 : 3.5;
var fW = (t47) => t47.kind === "via" ? 0.18 : 0.06;
var yW = (t47) => t47.kind === "via" ? 1.35 : 1.05;
var _W = (t47, e2) => t47.kind === "via" ? 3 * e2 : e2;
var bW = (t47, e2, n2, o2) => {
const i2 = 2 * e2;
t47[i2] = (t47[i2] ?? 0) + n2, t47[i2 + 1] = (t47[i2 + 1] ?? 0) + o2;
};
var xW = (t47, e2, n2, o2, i2, r2) => {
if (t47.fixed || bW(o2, t47.node.forceIndex, e2, n2), !t47.fixed && i2 && r2 !== undefined) {
const t48 = 2 * r2;
i2[t48] = (i2[t48] ?? 0) + e2, i2[t48 + 1] = (i2[t48 + 1] ?? 0) + n2;
}
};
var vW = (t47, e2, n2, o2, i2 = 0.5) => {
const { startNode: r2, endNode: s2 } = t47, a2 = 1 - oW(i2), c2 = oW(i2), l2 = r2.fixed ? 0 : a2, h2 = s2.fixed ? 0 : c2, d2 = l2 + h2;
if (!(d2 <= qX)) {
if (!r2.fixed && l2 > 0) {
const t48 = l2 / d2;
bW(o2, r2.forceIndex, e2 * t48, n2 * t48);
}
if (!s2.fixed && h2 > 0) {
const t48 = h2 / d2;
bW(o2, s2.forceIndex, e2 * t48, n2 * t48);
}
}
};
var IW = (t47, e2, n2, o2, i2) => {
if (e2.fixed)
return { x: 0, y: 0 };
const { minX: r2, maxX: s2, minY: a2, maxY: c2 } = t47, l2 = ((t48) => t48.kind === "via" ? 0.65 : VX)(e2), h2 = ((t48) => t48.kind === "via" ? GX : HX)(e2), d2 = ((t48) => t48.kind === "via" ? 0.015 : 0.08)(e2), u2 = ((t48) => t48.kind === "via" ? 80 : 20)(e2), p2 = gW(e2);
return { x: hW(n2 - r2, UX, d2, u2, p2, l2, h2) * i2 - hW(s2 - n2, UX, d2, u2, p2, l2, h2) * i2, y: hW(o2 - a2, UX, d2, u2, p2, l2, h2) * i2 - hW(c2 - o2, UX, d2, u2, p2, l2, h2) * i2 };
};
var SW = (t47) => {
if (t47.length === 0)
return null;
const e2 = new Ft(t47.length);
for (const n2 of t47) {
const { startNode: t48, endNode: o2 } = n2;
e2.add(Math.min(t48.x, o2.x), Math.min(t48.y, o2.y), Math.max(t48.x, o2.x), Math.max(t48.y, o2.y));
}
return e2.finish(), { index: e2, segments: t47 };
};
var CW = (t47) => {
const e2 = new Map, n2 = new Map;
for (const e3 of t47) {
const t48 = n2.get(e3.z) ?? [];
t48.push(e3), n2.set(e3.z, t48);
}
for (const [t48, o2] of n2) {
const n3 = SW(o2);
n3 && e2.set(t48, n3);
}
return { byLayer: e2 };
};
var PW = (t47, e2, n2, o2, i2) => {
const r2 = (t48) => ({ candidateIndexes: t48.index.search(n2 - i2, o2 - i2, n2 + i2, o2 + i2), segments: t48.segments });
if (e2.kind === "point") {
const n3 = t47.byLayer.get(e2.z);
return n3 ? [r2(n3)] : [];
}
const s2 = [];
for (const e3 of t47.byLayer.values())
s2.push(r2(e3));
return s2;
};
var MW = (t47) => {
const e2 = [];
for (let n2 = 0;n2 < t47.length; n2 += 1) {
const o2 = t47[n2];
if (!o2)
continue;
const i2 = new Set;
for (let t48 = 0;t48 < o2.route.length - 1; t48 += 1) {
const r2 = o2.route[t48], s2 = o2.route[t48 + 1];
if (!r2 || !s2)
continue;
if (r2.z === s2.z || !wX(r2, s2))
continue;
const a2 = [t48, t48 + 1];
for (let e3 = t48 - 1;e3 >= 0; e3 -= 1) {
const t49 = o2.route[e3];
if (!t49 || !wX(t49, r2))
break;
a2.push(e3);
}
for (let e3 = t48 + 2;e3 < o2.route.length; e3 += 1) {
const t49 = o2.route[e3];
if (!t49 || !wX(t49, r2))
break;
a2.push(e3);
}
const c2 = [...new Set(a2)].sort((t49, e3) => t49 - e3);
let l2 = false;
for (const t49 of c2)
if (i2.has(t49)) {
l2 = true;
break;
}
if (!l2) {
for (const t49 of c2)
i2.add(t49);
e2.push({ routeIndex: n2, rootConnectionName: MX(o2), pointIndexes: c2, x: r2.x, y: r2.y, radius: (o2.viaDiameter ?? 0.3) / 2, movable: !WX(o2.route.length, c2) });
}
}
}
return e2;
};
var NW = (t47) => {
const { routes: e2, via: n2, dx: o2, dy: i2, node: r2 } = t47;
if (!n2.movable)
return false;
n2.x += o2, n2.y += i2, ((t48, e3) => {
const n3 = TX(e3, t48.radius + qX);
t48.x = iW(t48.x, n3.minX, n3.maxX), t48.y = iW(t48.y, n3.minY, n3.maxY);
})(n2, r2);
const s2 = e2[n2.routeIndex];
if (!s2)
return false;
for (const t48 of n2.pointIndexes) {
const e3 = s2.route[t48];
e3 && (e3.x = n2.x, e3.y = n2.y);
}
return true;
};
var wW = (t47) => {
const { routes: e2, node: n2, vias: o2 } = t47;
let i2 = false;
for (let t48 = 0;t48 < o2.length; t48 += 1) {
const r2 = o2[t48];
if (r2)
for (let s2 = t48 + 1;s2 < o2.length; s2 += 1) {
const a2 = o2[s2];
if (!a2)
continue;
const c2 = r2.radius + a2.radius + 0.1 + JX, l2 = r2.x - a2.x, h2 = r2.y - a2.y, d2 = Math.hypot(l2, h2), u2 = c2 - d2;
if (u2 <= 0)
continue;
const p2 = 1.61803398875 * (97 * t48 + 13 * s2), m2 = d2 > qX ? l2 / d2 : Math.cos(p2), g2 = d2 > qX ? h2 / d2 : Math.sin(p2), f2 = Number(r2.movable) + Number(a2.movable);
if (f2 === 0)
continue;
const y2 = Math.min(0.04, u2 / f2);
i2 = NW({ routes: e2, via: r2, dx: m2 * y2, dy: g2 * y2, node: n2 }) || i2, i2 = NW({ routes: e2, via: a2, dx: -m2 * y2, dy: -g2 * y2, node: n2 }) || i2;
}
}
return i2;
};
var TW = (t47) => {
const { routes: e2, node: n2, vias: o2, segments: i2 } = t47;
let r2 = false;
for (let t48 = 0;t48 < o2.length; t48 += 1) {
const s2 = o2[t48];
if (s2?.movable)
for (const o3 of i2) {
if (s2.rootConnectionName === o3.rootConnectionName)
continue;
const i3 = kX(s2, o3), a2 = s2.x - i3.x, c2 = s2.y - i3.y, l2 = Math.hypot(a2, c2), h2 = s2.radius + o3.traceRadius + 0.1 + JX - l2;
if (h2 <= 0)
continue;
const d2 = o3.end.x - o3.start.x, u2 = o3.end.y - o3.start.y, p2 = Math.hypot(d2, u2), m2 = t48 % 2 == 0 ? 1 : -1, g2 = l2 > qX ? a2 / l2 : p2 > qX ? -u2 / p2 * m2 : 1, f2 = l2 > qX ? c2 / l2 : p2 > qX ? d2 / p2 * m2 : 0, y2 = Math.min(0.04, h2);
r2 = NW({ routes: e2, via: s2, dx: g2 * y2, dy: f2 * y2, node: n2 }) || r2;
}
}
return r2;
};
var RW = (t47) => {
const { routes: e2, routeIndex: n2, pointIndex: o2, dx: i2, dy: r2, node: s2 } = t47, a2 = e2[n2];
if (!a2 || o2 <= 0 || o2 >= a2.route.length - 1)
return false;
const c2 = ((t48, e3, n3 = 0.001) => {
const o3 = t48[e3];
if (!o3)
return [];
const i3 = [e3];
for (let r3 = e3 - 1;r3 >= 0; r3 -= 1) {
const e4 = t48[r3];
if (!e4 || !wX(e4, o3, n3))
break;
i3.push(r3);
}
for (let r3 = e3 + 1;r3 < t48.length; r3 += 1) {
const e4 = t48[r3];
if (!e4 || !wX(e4, o3, n3))
break;
i3.push(r3);
}
return [...new Set(i3)];
})(a2.route, o2);
if (WX(a2.route.length, c2))
return false;
const l2 = TX(s2, qX);
let h2 = false;
for (const t48 of c2) {
const e3 = a2.route[t48];
e3 && (e3.x = iW(e3.x + i2, l2.minX, l2.maxX), e3.y = iW(e3.y + r2, l2.minY, l2.maxY), h2 = true);
}
return h2;
};
var EW = (t47) => {
const { routes: e2, segment: n2, dx: o2, dy: i2, node: r2, t: s2 } = t47, a2 = 1 - oW(s2), c2 = oW(s2), l2 = RW({ routes: e2, routeIndex: n2.routeIndex, pointIndex: n2.startIndex, dx: o2 * a2, dy: i2 * a2, node: r2 }), h2 = RW({ routes: e2, routeIndex: n2.routeIndex, pointIndex: n2.endIndex, dx: o2 * c2, dy: i2 * c2, node: r2 });
return l2 || h2;
};
var AW = (t47) => {
const { routes: e2, node: n2, segments: o2, movableRouteIndexes: i2 } = t47;
let r2 = false;
for (let t48 = 0;t48 < o2.length; t48 += 1) {
const s2 = o2[t48];
if (s2)
for (let a2 = t48 + 1;a2 < o2.length; a2 += 1) {
const c2 = o2[a2];
if (!c2 || s2.z !== c2.z || s2.rootConnectionName === c2.rootConnectionName)
continue;
const l2 = s2.traceRadius + c2.traceRadius + 0.1 + JX;
if (Math.max(s2.start.x, s2.end.x) + l2 <= Math.min(c2.start.x, c2.end.x) || Math.max(c2.start.x, c2.end.x) + l2 <= Math.min(s2.start.x, s2.end.x) || Math.max(s2.start.y, s2.end.y) + l2 <= Math.min(c2.start.y, c2.end.y) || Math.max(c2.start.y, c2.end.y) + l2 <= Math.min(s2.start.y, s2.end.y))
continue;
const [h2] = DX(s2, c2);
if (!h2)
continue;
const d2 = h2.leftPoint.x - h2.rightPoint.x, u2 = h2.leftPoint.y - h2.rightPoint.y, p2 = Math.hypot(d2, u2), m2 = l2 - p2;
if (m2 <= 0)
continue;
const g2 = !i2 || i2.has(s2.routeIndex), f2 = !i2 || i2.has(c2.routeIndex), y2 = Number(g2) + Number(f2);
if (y2 === 0)
continue;
const _2 = s2.end.x - s2.start.x, b2 = s2.end.y - s2.start.y, x2 = Math.hypot(_2, b2), v2 = (t48 + a2) % 2 == 0 ? 1 : -1, I2 = p2 > qX ? d2 / p2 : x2 > qX ? -b2 / x2 * v2 : 1, S2 = p2 > qX ? u2 / p2 : x2 > qX ? _2 / x2 * v2 : 0, C2 = Math.min(0.025, m2 / y2);
g2 && (r2 = EW({ routes: e2, segment: s2, dx: I2 * C2, dy: S2 * C2, node: n2, t: h2.leftT }) || r2), f2 && (r2 = EW({ routes: e2, segment: c2, dx: -I2 * C2, dy: -S2 * C2, node: n2, t: h2.rightT }) || r2);
}
}
return r2;
};
var OW = (t47, e2) => {
for (let n2 = 0;n2 < 10; n2 += 1) {
const n3 = MW(e2), o2 = OX(e2), i2 = wW({ routes: e2, node: t47, vias: n3 }), r2 = TW({ routes: e2, node: t47, vias: n3, segments: o2 }), s2 = AW({ routes: e2, node: t47, segments: o2 });
if (!i2 && !r2 && !s2)
break;
}
for (const t48 of e2)
t48.vias = NX(t48);
return e2;
};
var kW = (t47, e2, n2) => {
for (let o2 = 0;o2 < 10; o2 += 1) {
if (!AW({ routes: e2, node: t47, segments: OX(e2), movableRouteIndexes: n2 }))
break;
}
for (const t48 of n2) {
const n3 = e2[t48];
n3 && (n3.vias = NX(n3));
}
return e2;
};
var DW = (t47, e2, n2, o2, i2, r2 = 3, s2 = 0.02) => {
for (let a2 = 0;a2 < r2; a2 += 1) {
i2.fill(0);
const r3 = CW(o2);
for (let t48 = 0;t48 < n2.length; t48 += 1) {
const e3 = n2[t48];
if (!e3 || e3.kind !== "via")
continue;
const o3 = e3.node;
for (let r4 = t48 + 1;r4 < n2.length; r4 += 1) {
const c2 = n2[r4];
if (!c2 || c2.kind !== "via")
continue;
if (e3.rootConnectionName === c2.rootConnectionName)
continue;
const l2 = c2.node, h2 = o3.x - l2.x, d2 = o3.y - l2.y;
if (Math.abs(h2) >= VX || Math.abs(d2) >= VX)
continue;
const u2 = Math.hypot(h2, d2), p2 = VX - u2;
if (p2 <= 0)
continue;
let m2 = 0, g2 = 0;
if (u2 > qX) {
const t49 = 1 / u2;
m2 = h2 * t49, g2 = d2 * t49;
} else {
const e4 = 1.61803398875 * (1009 * a2 + 97 * t48 + 13 * r4);
m2 = Math.cos(e4), g2 = Math.sin(e4);
}
const f2 = Math.min(s2, 0.9 * p2), y2 = m2 * f2, _2 = g2 * f2;
xW(e3, y2, _2, i2), xW(c2, -y2, -_2, i2);
}
}
for (let t48 = 0;t48 < n2.length; t48 += 1) {
const e3 = n2[t48];
if (!e3)
continue;
const o3 = e3.node, c2 = pW(e3), l2 = PW(r3, e3, o3.x, o3.y, c2);
for (const n3 of l2)
for (const r4 of n3.candidateIndexes) {
const l3 = n3.segments[r4];
if (!l3)
continue;
if (e3.rootConnectionName === l3.rootConnectionName)
continue;
const { startNode: h2, endNode: d2 } = l3, u2 = d2.x - h2.x, p2 = d2.y - h2.y, m2 = u2 * u2 + p2 * p2;
if (m2 <= qX)
continue;
const g2 = o3.x - h2.x, f2 = o3.y - h2.y, y2 = oW((g2 * u2 + f2 * p2) / m2), _2 = h2.x + u2 * y2, b2 = h2.y + p2 * y2, x2 = o3.x - _2, v2 = o3.y - b2, I2 = Math.hypot(x2, v2), S2 = c2 - I2;
if (S2 <= 0)
continue;
const C2 = 1009 * a2 + 97 * t48 + 13 * l3.obstacleIndex;
let P2 = 0, M2 = 0;
if (I2 > qX) {
const t49 = 1 / I2;
P2 = x2 * t49, M2 = v2 * t49;
} else {
const t49 = -p2, e4 = u2, n4 = Math.hypot(t49, e4);
if (n4 > qX) {
const o4 = (C2 % 2 == 0 ? 1 : -1) / n4;
P2 = t49 * o4, M2 = e4 * o4;
} else {
const t50 = 1.61803398875 * C2;
P2 = Math.cos(t50), M2 = Math.sin(t50);
}
}
const N2 = Math.min(_W(e3, s2), S2 * yW(e3)), w2 = P2 * N2, T2 = M2 * N2;
xW(e3, w2, T2, i2), vW(l3, -w2, -T2, i2, y2);
}
}
for (let t48 = 0;t48 < e2.length; t48 += 1) {
const n3 = e2[t48];
if (n3)
for (let t49 = 0;t49 < n3.nodes.length; t49 += 1) {
const e3 = n3.nodes[t49];
if (!e3 || e3.fixed)
continue;
const o3 = 2 * e3.forceIndex;
let r4 = i2[o3] ?? 0, a3 = i2[o3 + 1] ?? 0;
const c2 = Math.hypot(r4, a3);
if (c2 > s2 && c2 > qX) {
const t50 = s2 / c2;
r4 *= t50, a3 *= t50;
}
e3.x += r4, e3.y += a3;
}
}
uW(e2, t47);
}
};
var LW = (t47, e2, n2, o2) => {
const { mutableRoutes: i2, totalNodeCount: r2 } = ((t48) => {
let e3 = 0;
return { mutableRoutes: t48.map((t49) => {
const n3 = [], o3 = new Int32Array(t49.route.length);
o3.fill(-1);
for (let i3 = 0;i3 < t49.route.length; i3 += 1) {
const r3 = t49.route[i3];
if (!r3)
continue;
const s3 = t49.route[i3 - 1], a3 = n3.at(-1), c3 = n3.length - 1;
a3 && s3 && s3.x === r3.x && s3.y === r3.y ? (s3.z !== r3.z && (a3.boundaryPadding = Math.max(a3.boundaryPadding, t49.viaDiameter / 2)), a3.pointIndexes.push(i3), a3.fixed ||= XX(t49.route.length, i3), o3[i3] = c3) : (n3.push({ x: r3.x, y: r3.y, originalX: r3.x, originalY: r3.y, boundaryPadding: 0, pointIndexes: [i3], fixed: XX(t49.route.length, i3), forceIndex: e3 }), o3[i3] = n3.length - 1, e3 += 1);
}
return { route: t49, rootConnectionName: t49.rootConnectionName ?? t49.connectionName, nodes: n3, pointNodeIndexes: o3 };
}), totalNodeCount: e3 };
})(e2), s2 = ((t48) => {
const e3 = [];
for (let n3 = 0;n3 < t48.length; n3 += 1) {
const o3 = t48[n3];
if (o3)
for (let t49 = 0;t49 < o3.nodes.length; t49 += 1) {
const i3 = o3.nodes[t49], r3 = i3?.pointIndexes[0], s3 = r3 === undefined ? undefined : o3.route.route[r3];
i3 && s3 && (i3.pointIndexes.length > 1 ? e3.push({ kind: "via", routeIndex: n3, rootConnectionName: o3.rootConnectionName, node: i3, fixed: i3.fixed }) : e3.push({ kind: "point", routeIndex: n3, rootConnectionName: o3.rootConnectionName, node: i3, z: s3.z, fixed: i3.fixed }));
}
}
return e3;
})(i2), a2 = ((t48) => {
const e3 = [];
for (let n3 = 0;n3 < t48.length; n3 += 1) {
const o3 = t48[n3];
if (o3)
for (let t49 = 0;t49 < o3.nodes.length - 1; t49 += 1) {
const n4 = o3.nodes[t49], i3 = o3.nodes[t49 + 1], r3 = n4?.pointIndexes[0], s3 = r3 === undefined ? undefined : o3.route.route[r3];
n4 && i3 && s3 && e3.push({ obstacleIndex: e3.length, rootConnectionName: o3.rootConnectionName, z: s3.z, startNode: n4, endNode: i3 });
}
}
return e3;
})(i2), c2 = new Float64Array(2 * r2), l2 = new Float64Array(2 * r2), h2 = o2?.includeForceVectors ?? true;
uW(i2, t47);
let d2 = [];
for (let e3 = 0;e3 < n2; e3 += 1) {
const o3 = n2 <= 1 ? 0 : e3 / Math.max(n2 - 1, 1), r3 = 0.25 + 0.75 * (1 - o3), u3 = 1 - o3, p2 = h2 && e3 === n2 - 1, m2 = p2 ? new Float64Array(2 * s2.length) : undefined;
c2.fill(0);
for (let t48 = 0;t48 < s2.length; t48 += 1) {
const e4 = s2[t48];
if (!e4 || e4.kind !== "via")
continue;
const n3 = e4.node;
for (let o4 = t48 + 1;o4 < s2.length; o4 += 1) {
const i3 = s2[o4];
if (!i3 || i3.kind !== "via")
continue;
if (e4.rootConnectionName === i3.rootConnectionName)
continue;
const a3 = i3.node, l3 = n3.x - a3.x, h3 = n3.y - a3.y;
if (Math.abs(l3) >= HX || Math.abs(h3) >= HX)
continue;
const d3 = Math.hypot(l3, h3);
let u4 = 0, p3 = 0;
if (d3 > qX) {
const t49 = 1 / d3;
u4 = l3 * t49, p3 = h3 * t49;
} else {
const e5 = 1.61803398875 * (97 * t48 + 13 * o4);
u4 = Math.cos(e5), p3 = Math.sin(e5);
}
const g3 = hW(d3, 0.034, 0.08, 18) * r3;
if (g3 <= 0)
continue;
const f2 = u4 * g3, y2 = p3 * g3;
xW(e4, f2, y2, c2, m2, t48), xW(i3, -f2, -y2, c2, m2, o4);
}
}
const g2 = CW(a2);
for (let t48 = 0;t48 < s2.length; t48 += 1) {
const e4 = s2[t48];
if (!e4)
continue;
const n3 = e4.node, o4 = mW(e4), i3 = PW(g2, e4, n3.x, n3.y, o4);
for (const s3 of i3)
for (const i4 of s3.candidateIndexes) {
const a3 = s3.segments[i4];
if (!a3)
continue;
if (e4.rootConnectionName === a3.rootConnectionName)
continue;
const { startNode: l3, endNode: h3 } = a3, d3 = h3.x - l3.x, u4 = h3.y - l3.y, p3 = d3 * d3 + u4 * u4;
if (p3 <= qX)
continue;
const g3 = n3.x - l3.x, f2 = n3.y - l3.y, y2 = oW((g3 * d3 + f2 * u4) / p3), _2 = l3.x + d3 * y2, b2 = l3.y + u4 * y2, x2 = n3.x - _2, v2 = n3.y - b2, I2 = Math.hypot(x2, v2), S2 = 97 * t48 + 13 * a3.obstacleIndex;
let C2 = 0, P2 = 0;
if (I2 > qX) {
const t49 = 1 / I2;
C2 = x2 * t49, P2 = v2 * t49;
} else {
const t49 = -u4, e5 = d3, n4 = Math.hypot(t49, e5);
if (n4 > qX) {
const o5 = (S2 % 2 == 0 ? 1 : -1) / n4;
C2 = t49 * o5, P2 = e5 * o5;
} else {
const t50 = 1.61803398875 * S2;
C2 = Math.cos(t50), P2 = Math.sin(t50);
}
}
const M2 = hW(I2, fW(e4), 0.08, 18, gW(e4), pW(e4), o4) * r3;
if (M2 <= 0)
continue;
const N2 = C2 * M2, w2 = P2 * M2;
xW(e4, N2, w2, c2, m2, t48), vW(a3, -N2, -w2, c2, y2);
}
}
p2 && (d2 = new Array(s2.length));
for (let e4 = 0;e4 < s2.length; e4 += 1) {
const n3 = s2[e4];
if (!n3)
continue;
const o4 = n3.node, i3 = IW(t47, n3, o4.x, o4.y, r3);
if (xW(n3, i3.x, i3.y, c2, m2, e4), p2 && m2) {
const t48 = 2 * e4;
d2[e4] = { kind: n3.kind, routeIndex: n3.routeIndex, rootConnectionName: n3.rootConnectionName, x: o4.x, y: o4.y, dx: m2[t48] ?? 0, dy: m2[t48 + 1] ?? 0 };
}
}
for (let e4 = 0;e4 < i2.length; e4 += 1) {
const n3 = i2[e4];
if (!n3)
continue;
const o4 = n3.nodes.length - 2;
for (let e5 = 0;e5 < n3.nodes.length; e5 += 1) {
const i3 = n3.nodes[e5];
if (!i3 || i3.fixed)
continue;
const s3 = 2 * i3.forceIndex;
let a3 = (c2[s3] ?? 0) + 0.14 * (i3.originalX - i3.x), l3 = (c2[s3 + 1] ?? 0) + 0.14 * (i3.originalY - i3.y), h3 = 0, d3 = 0, p3 = 0, m3 = 0;
const g3 = n3.nodes[e5 - 1], f2 = n3.nodes[e5 + 1];
if (g3 || f2) {
let t48 = 0, e6 = 0, n4 = 0;
if (g3 && (t48 += g3.x, e6 += g3.y, n4 += 1), f2 && (t48 += f2.x, e6 += f2.y, n4 += 1), n4 > 0) {
const o5 = 1 / n4;
a3 += 0.22 * (t48 * o5 - i3.x), l3 += 0.22 * (e6 * o5 - i3.y);
}
}
if (g3 && f2 && u3 > 0) {
const t48 = KX(f2, g3), e6 = eW(t48, t48);
if (e6 > qX) {
const n4 = oW(eW(KX(i3, g3), t48) / e6), o5 = nW(g3, f2, n4), r4 = rW(tW(KX(o5, i3), 0.55 * u3), 0.02 * u3);
h3 = r4.x, d3 = r4.y;
}
}
if (u3 > 0) {
if (e5 === 1 && g3?.fixed) {
const e6 = lW(g3, i3, t47, u3);
p3 += e6.x, m3 += e6.y;
}
if (e5 === o4 && f2?.fixed) {
const e6 = lW(f2, i3, t47, u3);
p3 += e6.x, m3 += e6.y;
}
}
let y2 = 0.85 * a3 * r3, _2 = 0.85 * l3 * r3;
const b2 = Math.hypot(y2, _2), x2 = 0.012 * r3;
if (b2 > x2 && b2 > qX) {
const t48 = x2 / b2;
y2 *= t48, _2 *= t48;
}
i3.x += y2 + h3 + p3, i3.y += _2 + d3 + m3;
}
}
uW(i2, t47), DW(t47, i2, s2, a2, l2, 3, 0.02);
}
DW(t47, i2, s2, a2, l2, 8, 0.03);
const u2 = ((t48) => t48.map(({ route: t49, nodes: e3, pointNodeIndexes: n3 }) => {
const o3 = t49.route.map((t50, o4) => {
const i4 = n3[o4] ?? -1, r3 = i4 >= 0 ? e3[i4] : undefined;
return r3 ? { ...t50, x: QX(r3.x), y: QX(r3.y) } : t50;
}), i3 = { ...t49, route: o3, vias: [] };
return i3.vias = NX(i3), i3;
}))(i2);
return { routes: u2, forceVectors: d2, stepsCompleted: n2 };
};
var zW = class extends SX {
sampleEntries;
originalHdRoutes;
originalNodeWithPortPoints;
colorMap;
totalStepsPerNode;
nodeAssignmentMargin;
improvedRoutesByIndex = new Map;
activeSampleIndex = 0;
latestVisualization = {};
constructor(t47) {
super(), this.originalHdRoutes = t47.hdRoutes, this.originalNodeWithPortPoints = t47.nodeWithPortPoints, this.colorMap = t47.colorMap ?? {}, this.totalStepsPerNode = t47.totalStepsPerNode ?? 60, this.nodeAssignmentMargin = t47.nodeAssignmentMargin ?? 0.2;
const e2 = new Map;
for (let n2 = 0;n2 < t47.hdRoutes.length; n2++) {
const o2 = cW(t47.hdRoutes[n2], t47.nodeWithPortPoints, this.nodeAssignmentMargin);
if (o2 === -1)
continue;
const i2 = e2.get(o2) ?? [];
i2.push(n2), e2.set(o2, i2);
}
this.sampleEntries = Array.from(e2.entries()).map(([e3, n2]) => ({ node: t47.nodeWithPortPoints[e3], routeIndexes: n2 })), this.MAX_ITERATIONS = Math.max(10 * this.sampleEntries.length, 1000), this.stats = { nodeAssignmentMargin: this.nodeAssignmentMargin, sampleCount: this.sampleEntries.length, improvedNodeCount: 0, improvedRouteCount: 0, totalStepsPerNode: this.totalStepsPerNode };
}
getSolverName() {
return "HighDensityForceImproveSolver";
}
getConstructorParams() {
return [{ nodeWithPortPoints: this.originalNodeWithPortPoints, hdRoutes: this.originalHdRoutes, totalStepsPerNode: this.totalStepsPerNode, nodeAssignmentMargin: this.nodeAssignmentMargin, colorMap: this.colorMap }];
}
_step() {
const t47 = this.sampleEntries[this.activeSampleIndex];
if (!t47)
return void (this.solved = true);
const e2 = sW(t47.node), n2 = t47.routeIndexes.map((t48) => this.originalHdRoutes[t48]), o2 = LW(e2, n2, this.totalStepsPerNode, { includeForceVectors: true });
OW(t47.node, o2.routes);
const i2 = $X(n2, o2.routes);
let r2 = i2.length === 0 ? o2 : LW(e2, ((t48, e3) => {
const { routes: n3, node: o3, selectors: i3 } = t48, r3 = structuredClone(n3), s2 = OX(n3), a2 = zX(s2), c2 = i3.flatMap((t49) => {
const e4 = a2[t49.leftRouteIndex]?.[t49.leftStartPointIndex], n4 = a2[t49.rightRouteIndex]?.[t49.rightStartPointIndex];
if (!e4 || !n4)
return [];
const [o4] = DX(e4, n4);
if (!o4)
return [];
const i4 = o4.leftPoint.x - o4.rightPoint.x, r4 = o4.leftPoint.y - o4.rightPoint.y, s3 = Math.hypot(i4, r4);
return s3 <= LX ? [] : [{ selector: t49, directionX: i4 / s3, directionY: r4 / s3, requiredDistance: e4.traceRadius + n4.traceRadius + 0.015 }];
});
for (let t49 = 0;t49 < 3; t49 += 1) {
const t50 = OX(r3), n4 = zX(t50);
for (const t51 of c2) {
const i4 = n4[t51.selector.leftRouteIndex]?.[t51.selector.leftStartPointIndex], s3 = n4[t51.selector.rightRouteIndex]?.[t51.selector.rightStartPointIndex];
if (!i4 || !s3)
continue;
const [a3] = DX(i4, s3);
if (!a3)
continue;
const c3 = (a3.leftPoint.x - a3.rightPoint.x) * t51.directionX + (a3.leftPoint.y - a3.rightPoint.y) * t51.directionY, l2 = t51.requiredDistance - c3;
if (l2 <= 0)
continue;
const h2 = Math.min(0.025, l2 / 2);
e3({ routes: r3, segment: i4, dx: t51.directionX * h2, dy: t51.directionY * h2, node: o3, t: a3.leftT }), e3({ routes: r3, segment: s3, dx: -t51.directionX * h2, dy: -t51.directionY * h2, node: o3, t: a3.rightT });
}
}
for (const t49 of r3)
t49.vias = NX(t49);
return r3;
})({ routes: n2, node: t47.node, selectors: i2 }, EW), this.totalStepsPerNode, { includeForceVectors: true });
if (r2 !== o2) {
OW(t47.node, r2.routes);
const e3 = $X(n2, r2.routes);
if (e3.length > 0) {
const o3 = ((t48, e4) => {
const { originalRoutes: n3, guardedRoutes: o4, node: i3, crossingSelectors: r3, protectedSelectors: s2 } = t48, a2 = zX(OX(n3)), c2 = zX(OX(o4)), l2 = YX(o4), h2 = s2.map(({ leftRouteIndex: t49, rightRouteIndex: e5 }) => BX(t49, e5)), d2 = TX(i3, LX);
for (const t49 of r3) {
const r4 = c2[t49.leftRouteIndex]?.[t49.leftStartPointIndex], s3 = c2[t49.rightRouteIndex]?.[t49.rightStartPointIndex];
if (!r4 || !s3)
continue;
const [u2] = DX(r4, s3);
if (!(!u2 || Math.hypot(u2.leftPoint.x - u2.rightPoint.x, u2.leftPoint.y - u2.rightPoint.y) > LX || u2.leftT <= LX || u2.leftT >= 0.999999 || u2.rightT <= LX || u2.rightT >= 0.999999))
for (const r5 of ["right", "left"]) {
const s4 = r5 === "left" ? t49.leftRouteIndex : t49.rightRouteIndex, u3 = r5 === "left" ? t49.leftStartPointIndex : t49.rightStartPointIndex, p2 = r5 === "left" ? t49.rightRouteIndex : t49.leftRouteIndex, m2 = r5 === "left" ? t49.rightStartPointIndex : t49.leftStartPointIndex, g2 = n3[s4], f2 = o4[s4], y2 = a2[p2]?.[m2], _2 = c2[p2]?.[m2];
if (!(g2 && f2 && y2 && _2))
continue;
const b2 = g2.route[u3]?.z, x2 = [];
for (let t50 = u3 - 2;t50 <= u3 + 3; t50 += 1) {
const e5 = g2.route[t50];
!e5 || t50 <= 0 || t50 >= g2.route.length - 1 || e5.z !== b2 || [g2.route[t50 - 1], g2.route[t50 + 1]].some((t51) => t51 && t51.z !== e5.z) || x2.push(t50);
}
if (x2.length !== 0)
for (const [t50, n4] of [[y2.start, _2.start], [y2.end, _2.end]])
for (const r6 of [1.51, 1.25, 1.75, 2]) {
const a3 = [...o4], c3 = structuredClone(f2);
a3[s4] = c3;
let u4 = true;
for (const e5 of x2) {
const o5 = g2.route[e5], i4 = c3.route[e5];
if (!o5 || !i4)
continue;
const s5 = n4.x + (o5.x - t50.x) * r6, a4 = n4.y + (o5.y - t50.y) * r6;
if (s5 <= d2.minX || s5 >= d2.maxX || a4 <= d2.minY || a4 >= d2.maxY) {
u4 = false;
break;
}
i4.x = s5, i4.y = a4;
}
if (!u4)
continue;
c3.vias = NX(c3);
let p3 = a3, m3 = YX(p3);
const y3 = new Set;
for (const [t51, e5] of m3)
FX(l2, [t51, e5]) || (t51 === s4 && e5 !== s4 ? y3.add(e5) : e5 === s4 && t51 !== s4 && y3.add(t51));
if (y3.size > 0) {
const t51 = e4(i3, structuredClone(a3), y3), n5 = YX(t51);
h2.every((t52) => !FX(n5, t52)) && n5.length < m3.length && (p3 = t51, m3 = n5);
}
if (h2.every((t51) => !FX(m3, t51)) && m3.length < l2.length)
return p3;
}
}
}
})({ originalRoutes: n2, guardedRoutes: r2.routes, node: t47.node, crossingSelectors: e3, protectedSelectors: [...i2, ...e3] }, kW);
o3 && (r2 = { ...r2, routes: o3 });
}
}
for (let e3 = 0;e3 < t47.routeIndexes.length; e3++)
this.improvedRoutesByIndex.set(t47.routeIndexes[e3], r2.routes[e3]);
this.latestVisualization = BW({ node: t47.node, routes: r2.routes, forceVectors: r2.forceVectors, colorMap: this.colorMap }), this.activeSampleIndex += 1, this.stats = { nodeAssignmentMargin: this.nodeAssignmentMargin, sampleCount: this.sampleEntries.length, improvedNodeCount: this.activeSampleIndex, improvedRouteCount: this.improvedRoutesByIndex.size, totalStepsPerNode: this.totalStepsPerNode }, this.activeSampleIndex >= this.sampleEntries.length && (this.solved = true);
}
getOutput() {
return this.originalHdRoutes.map((t47, e2) => this.improvedRoutesByIndex.get(e2) ?? t47);
}
visualize() {
return this.solved ? BW({ routes: this.getOutput(), colorMap: this.colorMap }) : this.latestVisualization;
}
};
var BW = (t47) => {
const e2 = [], n2 = [], o2 = [];
t47.node && o2.push({ center: t47.node.center, width: t47.node.width, height: t47.node.height, stroke: "rgba(14,165,233,0.7)", fill: "rgba(14,165,233,0.04)", label: t47.node.capacityMeshNodeId });
for (const o3 of t47.routes) {
const i2 = t47.colorMap?.[o3.connectionName] ?? "#0ea5e9";
for (let t48 = 0;t48 < o3.route.length - 1; t48++) {
const n3 = o3.route[t48], r2 = o3.route[t48 + 1];
n3.z === r2.z && e2.push({ points: [{ x: n3.x, y: n3.y }, { x: r2.x, y: r2.y }], strokeColor: n3.z === 0 ? i2 : PX(i2, 0.5), strokeWidth: o3.traceThickness, layer: `z${n3.z}`, strokeDash: n3.z !== 0 ? [0.1, 0.3] : undefined });
}
for (const t48 of o3.vias)
n2.push({ center: { x: t48.x, y: t48.y }, radius: o3.viaDiameter / 2, stroke: i2, fill: "rgba(14,165,233,0.12)" });
}
for (const n3 of t47.forceVectors ?? [])
e2.push({ points: [{ x: n3.x, y: n3.y }, { x: n3.x + 5 * n3.dx, y: n3.y + 5 * n3.dy }], strokeColor: "rgba(244,63,94,0.85)", strokeWidth: 0.06, strokeDash: [0.08, 0.08] });
return { lines: e2, circles: n2, rects: o2 };
};
var FW = class extends si {
constructor(t47, e2, n2 = Number.POSITIVE_INFINITY, o2 = 0.010000000000000002) {
super(), this.nodes = t47, this.maxNodeDimension = e2, this.maxNodeRatio = n2, this.minNodeArea = o2, this.outputNodes = [];
}
outputNodes;
getSolverName() {
return "NodeDimensionSubdivisionSolver";
}
getSubdivisionGrid(t47) {
const e2 = Number.isFinite(this.maxNodeDimension) && this.maxNodeDimension > 0, n2 = Number.isFinite(this.maxNodeRatio) && this.maxNodeRatio > 0;
let o2 = e2 ? Math.max(1, Math.ceil(t47.width / this.maxNodeDimension)) : 1, i2 = e2 ? Math.max(1, Math.ceil(t47.height / this.maxNodeDimension)) : 1;
if (n2 && t47.width > 0 && t47.height > 0)
for (;; ) {
const e3 = t47.width / o2, n3 = t47.height / i2;
if ((e3 >= n3 ? e3 / n3 : n3 / e3) <= this.maxNodeRatio)
break;
e3 >= n3 ? o2++ : i2++;
}
return { cols: o2, rows: i2 };
}
shouldRemoveNode(t47) {
const e2 = Number.isFinite(this.minNodeArea) && this.minNodeArea > 0;
if (!Number.isFinite(t47.width) || !Number.isFinite(t47.height))
return true;
if (!e2 || t47.width * t47.height >= this.minNodeArea)
return false;
if (Math.min(t47.width, t47.height) < 0.002)
return true;
if (t47._containsTarget)
return false;
let n2 = 0;
for (const e3 of this.nodes)
if (e3.capacityMeshNodeId !== t47.capacityMeshNodeId && t47.availableZ.some((t48) => e3.availableZ.includes(t48)) && li(t47, e3)) {
if (e3._containsTarget)
return false;
if (n2++, n2 >= 2)
return false;
}
return true;
}
subdivideNode(t47) {
if (this.shouldRemoveNode(t47))
return [];
const { cols: e2, rows: n2 } = this.getSubdivisionGrid(t47);
if (e2 === 1 && n2 === 1)
return [t47];
const o2 = t47.width / e2, i2 = t47.height / n2, r2 = t47.center.x - t47.width / 2, s2 = t47.center.y - t47.height / 2, a2 = [];
for (let c2 = 0;c2 < n2; c2++)
for (let n3 = 0;n3 < e2; n3++)
a2.push({ ...t47, capacityMeshNodeId: `${t47.capacityMeshNodeId}__sub_${c2}_${n3}`, center: { x: r2 + o2 * (n3 + 0.5), y: s2 + i2 * (c2 + 0.5) }, width: o2, height: i2, availableZ: [...t47.availableZ] });
return a2;
}
_step() {
const t47 = this.nodes.length;
let e2 = 0, n2 = 0, o2 = 0;
for (const t48 of this.nodes) {
const i2 = !Number.isFinite(t48.width) || !Number.isFinite(t48.height), r2 = this.subdivideNode(t48);
r2.length !== 0 ? (r2.length > 1 && e2++, this.outputNodes.push(...r2)) : i2 ? o2++ : n2++;
}
this.stats = { inputNodeCount: t47, outputNodeCount: this.outputNodes.length, subdividedNodeCount: e2, removedSmallNodeCount: n2, removedInvalidNodeCount: o2, maxNodeDimension: this.maxNodeDimension, maxNodeRatio: this.maxNodeRatio, minNodeArea: this.minNodeArea }, this.solved = true;
}
visualize() {
return { rects: this.outputNodes.map((t47) => ({ center: t47.center, width: t47.width, height: t47.height, label: `${t47.capacityMeshNodeId}
${t47.width.toFixed(2)}x${t47.height.toFixed(2)}`, layer: `z${t47.availableZ.join(",")}`, fill: "rgba(0, 200, 255, 0.08)", stroke: "rgba(0, 120, 180, 0.5)" })) };
}
};
var jW = (t47) => {
const e2 = [...new Set(t47.filter((t48) => typeof t48 == "number" && Number.isInteger(t48) && t48 >= 0))].sort((t48, e3) => t48 - e3);
if (e2.length !== 0)
return `z${e2.join(",")}`;
};
var $W = (t47) => {
const e2 = [];
for (let n2 = 0;n2 < 31; n2++)
t47 & 1 << n2 && e2.push(n2);
return e2;
};
var YW = (t47) => typeof t47 == "object" && t47 !== null;
var XW = (t47) => YW(t47) ? { ...t47 } : t47 === undefined ? {} : { value: t47 };
var WW = (t47, e2) => {
const n2 = t47.topology.regionMetadata?.[e2];
if (YW(n2)) {
if (typeof n2.serializedRegionId == "string")
return n2.serializedRegionId;
if (typeof n2.regionId == "string")
return n2.regionId;
if (typeof n2.capacityMeshNodeId == "string")
return n2.capacityMeshNodeId;
}
return `region-${e2}`;
};
var VW = (t47, e2) => {
const n2 = t47.topology.portMetadata?.[e2];
if (YW(n2)) {
if (typeof n2.serializedPortId == "string")
return n2.serializedPortId;
if (typeof n2.portId == "string")
return (o2 = n2.portId).includes("::") ? o2.slice(0, o2.indexOf("::")) : o2;
}
var o2;
return `port-${e2}`;
};
var HW = (t47, e2) => {
const n2 = t47.problem.routeMetadata?.[e2];
return YW(n2) && typeof n2.connectionId == "string" ? n2.connectionId : `route-${e2}`;
};
var GW = (t47, e2) => {
const n2 = XW(t47.topology.regionMetadata?.[e2]);
if (YW(n2.center) || (n2.center = { x: t47.topology.regionCenterX[e2], y: t47.topology.regionCenterY[e2] }), typeof n2.width != "number" && (n2.width = t47.topology.regionWidth[e2]), typeof n2.height != "number" && (n2.height = t47.topology.regionHeight[e2]), !Array.isArray(n2.availableZ)) {
const o2 = t47.topology.regionAvailableZMask?.[e2] ?? 0;
o2 !== 0 && (n2.availableZ = $W(o2));
}
return n2.layer = jW(Array.isArray(n2.availableZ) ? n2.availableZ : []) ?? jW((t47.topology.regionIncidentPorts[e2] ?? []).map((e3) => t47.topology.portZ[e3])) ?? "z0", n2;
};
var UW = (t47, e2) => {
const n2 = XW(t47.topology.portMetadata?.[e2]);
return typeof n2.x != "number" && (n2.x = t47.topology.portX[e2]), typeof n2.y != "number" && (n2.y = t47.topology.portY[e2]), typeof n2.z != "number" && (n2.z = t47.topology.portZ[e2]), n2.layer = jW([t47.topology.portZ[e2]]) ?? "z0", n2;
};
var ZW = (t47, e2, n2) => {
const o2 = (t47.topology.incidentPortRegion[e2] ?? []).find((t48) => t48 !== n2);
if (o2 === undefined)
throw new Error(`Port ${e2} is not incident to a region outside route region ${n2}`);
return o2;
};
var qW = (t47, e2, n2) => {
const { orderedPortIds: o2, orderedRegionIds: i2 } = ((t48, e3, n3) => {
if (n3.length === 0)
throw new Error(`Route ${e3} has no solved segments`);
const o3 = t48.problem.routeStartPort[e3], i3 = t48.problem.routeEndPort[e3], r3 = o3 === i3, s3 = new Map;
n3.forEach((t49, e4) => {
const n4 = { ...t49, segmentIndex: e4 }, o4 = s3.get(t49.fromPortId) ?? [];
o4.push(n4), s3.set(t49.fromPortId, o4);
const i4 = s3.get(t49.toPortId) ?? [];
i4.push(n4), s3.set(t49.toPortId, i4);
});
const a3 = [o3], c3 = [], l3 = (t49, e4, o4) => {
if (t49 === i3 && (!r3 || e4.size === n3.length))
return true;
for (const h3 of s3.get(t49) ?? []) {
if (e4.has(h3.segmentIndex))
continue;
const s4 = h3.fromPortId === t49 ? h3.toPortId : h3.fromPortId, d2 = r3 && s4 === i3 && e4.size + 1 === n3.length;
if (o4.has(s4) && !d2)
continue;
e4.add(h3.segmentIndex);
const u2 = !o4.has(s4);
if (u2 && o4.add(s4), c3.push(h3.regionId), a3.push(s4), l3(s4, e4, o4))
return true;
a3.pop(), c3.pop(), u2 && o4.delete(s4), e4.delete(h3.segmentIndex);
}
return false;
};
if (!l3(o3, new Set, new Set([o3])))
throw new Error(`Route ${e3} is not a single ordered path from ${o3} to ${i3}`);
return { orderedPortIds: a3, orderedRegionIds: c3 };
})(t47, e2, n2), r2 = i2[0], s2 = i2[i2.length - 1];
if (r2 === undefined || s2 === undefined)
throw new Error(`Route ${e2} could not determine endpoint regions`);
const a2 = WW(t47, ZW(t47, o2[0], r2)), c2 = WW(t47, ZW(t47, o2[o2.length - 1], s2)), l2 = ((t48, e3, n3, o3) => {
const i3 = t48.problem.routeMetadata?.[e3];
return { connectionId: HW(t48, e3), startRegionId: (YW(i3) && typeof i3.startRegionId == "string" ? i3.startRegionId : undefined) ?? n3, endRegionId: (YW(i3) && typeof i3.endRegionId == "string" ? i3.endRegionId : undefined) ?? o3, mutuallyConnectedNetworkId: (YW(i3) && typeof i3.mutuallyConnectedNetworkId == "string" ? i3.mutuallyConnectedNetworkId : undefined) ?? `net-${t48.problem.routeNet[e3]}` };
})(t47, e2, a2, c2), h2 = o2.map((e3, n3) => {
const r3 = { portId: VW(t47, e3), g: n3, h: 0, f: n3, hops: n3, ripRequired: false, nextRegionId: n3 < i2.length ? WW(t47, i2[n3]) : l2.endRegionId };
return n3 > 0 && (r3.lastPortId = VW(t47, o2[n3 - 1]), r3.lastRegionId = WW(t47, i2[n3 - 1])), r3;
});
return { connection: l2, solvedRoute: { connection: l2, path: h2, requiredRip: false } };
};
var JW = (t47) => {
if (!t47.solved || t47.failed)
throw new Error("convertToSerializedHyperGraph requires a solved, non-failed solver");
const { topology: e2 } = t47, n2 = ((t48) => {
const e3 = Array.from({ length: t48.problem.routeCount }, () => []);
return t48.state.regionSegments.forEach((t49, n3) => {
for (const [o3, i3, r3] of t49)
e3[o3].push({ regionId: n3, fromPortId: i3, toPortId: r3 });
}), e3;
})(t47), o2 = Array.from({ length: e2.regionCount }, (n3, o3) => {
const i3 = t47.state.regionSegments[o3].map(([e3, n4, o4]) => ({ regionPort1Id: VW(t47, n4), regionPort2Id: VW(t47, o4), connectionId: HW(t47, e3) }));
return { regionId: WW(t47, o3), pointIds: e2.regionIncidentPorts[o3].map((e3) => VW(t47, e3)), d: GW(t47, o3), ...i3.length > 0 && { assignments: i3 } };
}), i2 = Array.from({ length: e2.portCount }, (n3, o3) => {
const [i3, r3] = e2.incidentPortRegion[o3] ?? [];
if (i3 === undefined || r3 === undefined)
throw new Error(`Port ${o3} is missing incident regions`);
return { portId: VW(t47, o3), region1Id: WW(t47, i3), region2Id: WW(t47, r3), d: UW(t47, o3) };
}), r2 = n2.map((e3, n3) => qW(t47, n3, e3));
return { regions: o2, ports: i2, connections: r2.map(({ connection: t48 }) => t48), solvedRoutes: r2.map(({ solvedRoute: t48 }) => t48) };
};
var QW = 0.3;
var KW = (t47) => t47 > 0 && !(t47 & t47 - 1);
var tV = (t47, e2, n2, o2, i2, r2 = 0, s2 = 0.3, a2 = 0) => (2 * e2 + 1 * n2 + 1 * o2) * (s2 + 0.15) ** 2 * (1 + i2 / 5) / t47 + (KW(r2) ? 10 * e2 : 0) + a2 * (i2 / eV(r2)) ** 2 * 0.1 ** 2 / t47;
var eV = (t47) => {
if (t47 === 0)
return 2;
let e2 = t47 >>> 0, n2 = 0;
for (;e2 !== 0; )
n2 += 1 & e2, e2 >>>= 1;
return n2;
};
var nV = (t47, e2, n2, o2, i2, r2) => {
const { netIds: s2, lesserAngles: a2, greaterAngles: c2, layerMasks: l2 } = t47;
let h2 = 0, d2 = 0;
for (let t48 = 0;t48 < s2.length; t48++) {
if (e2 === s2[t48])
continue;
(n2 < a2[t48] && a2[t48] < o2) !== (n2 < c2[t48] && c2[t48] < o2) && ((i2 & l2[t48]) !== 0 ? h2++ : d2++);
}
return [h2, d2, r2];
};
var oV = (t47, e2, n2) => {
const o2 = t47.routeStartPort[e2], i2 = t47.routeEndPort[e2], r2 = new Map;
for (const { fromPortId: t48, toPortId: e3 } of n2) {
const n3 = r2.get(t48) ?? new Set;
n3.add(e3), r2.set(t48, n3);
const o3 = r2.get(e3) ?? new Set;
o3.add(t48), r2.set(e3, o3);
}
const s2 = new Set, a2 = [o2];
for (;a2.length > 0; ) {
const t48 = a2.pop();
if (!s2.has(t48)) {
s2.add(t48);
for (const e3 of r2.get(t48) ?? [])
a2.push(e3);
}
}
if (!s2.has(i2))
throw new Error(`Initial assignments for route ${e2} do not connect ${o2} to ${i2}`);
if (n2.some(({ fromPortId: t48, toPortId: e3 }) => !s2.has(t48) || !s2.has(e3)))
throw new Error(`Initial assignments for route ${e2} contain disconnected segments`);
};
var iV = ({ topology: t47, problem: e2, state: n2, routeSuccessCountByRouteId: o2, appendSegmentToRegionCache: i2 }) => {
const r2 = e2.initialAssignments ?? [];
if (r2.length === 0)
return;
const s2 = new Map;
for (const n3 of r2) {
const { routeId: o3, regionId: i3, fromPortId: r3, toPortId: a3 } = n3;
if (!Number.isInteger(o3) || o3 < 0 || o3 >= e2.routeCount)
throw new Error(`Initial assignment references invalid route ${o3}`);
if (!Number.isInteger(i3) || i3 < 0 || i3 >= t47.regionCount)
throw new Error(`Initial assignment references invalid region ${i3}`);
for (const e3 of [r3, a3]) {
if (!Number.isInteger(e3) || e3 < 0 || e3 >= t47.portCount)
throw new Error(`Initial assignment references invalid port ${e3}`);
if (!t47.incidentPortRegion[e3]?.includes(i3))
throw new Error(`Initial assignment port ${e3} is not incident to region ${i3}`);
}
const c2 = s2.get(o3) ?? [];
c2.push(n3), s2.set(o3, c2);
}
for (const [t48, n3] of s2)
oV(e2, t48, n3);
const a2 = new Set(s2.keys());
for (const { routeId: t48, regionId: o3, fromPortId: s3, toPortId: a3 } of r2) {
const r3 = e2.routeNet[t48];
for (const t49 of [s3, a3]) {
const e3 = n2.portAssignment[t49];
if (e3 !== -1 && e3 !== r3)
throw new Error(`Initial assignment port ${t49} is assigned to multiple nets`);
n2.portAssignment[t49] = r3;
}
n2.currentRouteNetId = r3, n2.regionSegments[o3].push([t48, s3, a3]), i2(o3, s3, a3);
}
n2.currentRouteNetId = undefined, n2.unroutedRoutes = n2.unroutedRoutes.filter((t48) => !a2.has(t48));
for (const t48 of a2)
o2[t48] = 1;
return { initialAssignmentCount: r2.length, initiallyRoutedRouteCount: a2.size };
};
var rV = class {
constructor(t47, e2) {
this.items = t47, this.compare = e2;
}
get length() {
return this.items.length;
}
toArray() {
return [...this.items];
}
clear() {
this.items.length = 0;
}
queue(t47) {
this.items.push(t47), this.siftUp(this.items.length - 1);
}
dequeue() {
const t47 = this.items[0];
if (t47 === undefined)
return;
const e2 = this.items.pop();
return this.items.length > 0 && (this.items[0] = e2, this.siftDown(0)), t47;
}
siftUp(t47) {
let e2 = t47;
for (;e2 > 0; ) {
const t48 = e2 - 1 >> 1, n2 = this.items[t48], o2 = this.items[e2];
if (this.compare(n2, o2) <= 0)
return;
this.items[t48] = o2, this.items[e2] = n2, e2 = t48;
}
}
siftDown(t47) {
let e2 = t47;
const n2 = this.items.length;
for (;; ) {
const t48 = 2 * e2 + 1;
if (t48 >= n2)
return;
const o2 = t48 + 1;
let i2 = t48;
o2 < n2 && this.compare(this.items[o2], this.items[t48]) < 0 && (i2 = o2);
const r2 = this.items[e2], s2 = this.items[i2];
if (this.compare(r2, s2) <= 0)
return;
this.items[e2] = s2, this.items[i2] = r2, e2 = i2;
}
}
};
var sV = (t47, e2) => {
const n2 = [...t47], o2 = ((t48) => {
let e3 = t48 >>> 0;
return () => {
e3 += 1831565813;
let t49 = e3;
return t49 = Math.imul(t49 ^ t49 >>> 15, 1 | t49), t49 ^= t49 + Math.imul(t49 ^ t49 >>> 7, 61 | t49), ((t49 ^ t49 >>> 14) >>> 0) / 4294967296;
};
})(e2);
for (let t48 = n2.length - 1;t48 > 0; t48--) {
const e3 = Math.floor(o2() * (t48 + 1));
[n2[t48], n2[e3]] = [n2[e3], n2[t48]];
}
return n2;
};
var aV = (t47, e2) => t47.routeMetadata?.[e2];
var cV = (t47) => t47?.simpleRouteConnection?.pointsToConnect?.map(({ pointId: t48 }) => typeof t48 == "string" ? t48 : null).filter((t48) => t48 !== null) ?? [];
var lV = (t47, e2) => {
const n2 = aV(t47, e2)?.connectionId;
return typeof n2 == "string" ? n2 : `route-${e2}`;
};
var hV = (t47, e2, n2) => {
const o2 = t47.portEndpointNetIds[n2];
if (!o2)
return false;
for (const t48 of o2)
if (t48 !== e2)
return true;
return false;
};
var dV = (t47, e2, n2) => {
const o2 = t47.regionNetId[n2];
return o2 !== -1 && o2 !== e2;
};
var uV = (t47) => [...new Set(t47.routeIds)].filter((e2) => !((t48, e3) => {
const { topology: n2, problem: o2, problemSetup: i2, portAssignment: r2, maxPrecheckHops: s2 } = t48, a2 = o2.routeNet[e3], c2 = o2.routeStartPort[e3], l2 = o2.routeEndPort[e3];
if (c2 === l2)
return true;
const h2 = t48.getStartingNextRegionId(e3, c2);
if (h2 === undefined)
return false;
const d2 = [{ portId: c2, nextRegionId: h2 }], u2 = new Set([c2 * n2.regionCount + h2]);
for (let t49 = 0;t49 < d2.length; t49++) {
const e4 = d2[t49];
if (!dV(o2, a2, e4.nextRegionId))
for (const t50 of n2.regionIncidentPorts[e4.nextRegionId] ?? []) {
const c3 = r2[t50];
if (hV(i2, a2, t50))
continue;
if (t50 === l2) {
if (c3 !== -1 && c3 !== a2)
continue;
return true;
}
if (t50 === e4.portId)
continue;
if (c3 !== -1 && c3 !== a2)
continue;
if (o2.portSectionMask[t50] === 0)
continue;
const h3 = n2.incidentPortRegion[t50] ?? [], p2 = h3[0] === e4.nextRegionId ? h3[1] : h3[0];
if (p2 === undefined || dV(o2, a2, p2))
continue;
const m2 = t50 * n2.regionCount + p2;
if (!u2.has(m2)) {
if (u2.size >= s2)
return true;
u2.add(m2), d2.push({ portId: t50, nextRegionId: p2 });
}
}
}
return false;
})(t47, e2)).map((e2) => t47.getRouteSummary(e2));
var pV = (t47) => {
const e2 = new Array(t47);
for (let n2 = 0;n2 < t47; n2++)
e2[n2] = n2;
return e2;
};
var mV = "rgba(220, 38, 38, 0.98)";
var gV = "rgba(220, 38, 38, 0.18)";
var fV = (...t47) => t47.filter((t48) => Boolean(t48)).join(`
`);
var yV = (t47, e2) => {
const n2 = 0.005 * t47.topology.portZ[e2];
return { x: t47.topology.portX[e2] + n2, y: t47.topology.portY[e2] + n2 };
};
var _V = (t47, e2) => jW([t47.topology.portZ[e2]]) ?? "z0";
var bV = (t47, e2) => {
const n2 = t47.topology.portMetadata?.[e2];
return `port: ${n2?.serializedPortId ?? n2?.portId ?? `port-${e2}`}`;
};
var xV = (t47, e2) => `z: ${t47.topology.portZ[e2]}`;
var vV = (t47, e2) => ((t48, e3, n2) => {
const o2 = t48.topology.portZ[e3], i2 = t48.topology.portZ[n2];
return o2 === i2 ? `z: ${o2}` : `z: ${o2} -> ${i2}`;
})(t47, t47.problem.routeStartPort[e2], t47.problem.routeEndPort[e2]);
var IV = (t47, e2) => `net: ${t47.problem.routeNet[e2]}`;
var SV = 0.05;
var CV = { r: 255, g: 64, b: 64, a: 0.72 };
var PV = "rgba(220, 38, 38, 0.98)";
var MV = "rgba(220, 38, 38, 0.12)";
var NV = "10 6";
var wV = (...t47) => t47.filter((t48) => Boolean(t48)).join(`
`);
var TV = (t47) => Math.min(1, Math.max(0, t47));
var RV = (t47, e2, n2) => Math.round(t47 + (e2 - t47) * n2);
var EV = ({ r: t47, g: e2, b: n2, a: o2 }) => `rgba(${t47}, ${e2}, ${n2}, ${o2})`;
var AV = (t47, e2) => {
const n2 = t47.problem.routeMetadata?.[e2];
return n2?.connectionId ?? n2?.mutuallyConnectedNetworkId ?? `route-${e2}`;
};
var OV = (t47) => typeof t47.centerRouteId == "number";
var kV = (t47, e2) => OV(t47) ? e2 === t47.centerRouteId ? 1 : 0.5 : 1;
var DV = (t47, e2) => {
const n2 = t47.match(/^(rgba|hsla)\((.*),\s*([0-9]*\.?[0-9]+)\)$/);
if (!n2)
return t47;
const [, o2, i2, r2] = n2, s2 = TV(Number(r2) * e2);
return `${o2}(${i2}, ${Number(s2.toFixed(3))})`;
};
var LV = (t47, e2, n2 = 0.8) => ((t48, e3, n3 = 0.8) => {
const o2 = `${t48.problem.routeNet[e3]}:${AV(t48, e3)}`;
let i2 = 0;
for (let t49 = 0;t49 < o2.length; t49++)
i2 = 17777 * o2.charCodeAt(t49) + ((i2 << 5) - i2);
return `hsla(${Math.abs(i2) % 360}, 70%, 50%, ${n3})`;
})(t47, e2, n2 * kV(t47, e2));
var zV = (t47, e2) => `net: ${t47.problem.routeNet[e2]}`;
var BV = (t47, e2) => {
const n2 = t47.topology.regionMetadata?.[e2], o2 = n2?.polygon;
if (Array.isArray(o2) && o2.length >= 3) {
const t48 = o2.map((t49) => t49.x), e3 = o2.map((t49) => t49.y);
return { minX: Math.min(...t48), maxX: Math.max(...t48), minY: Math.min(...e3), maxY: Math.max(...e3) };
}
const i2 = n2?.bounds;
if (i2 && typeof i2.minX == "number" && typeof i2.maxX == "number" && typeof i2.minY == "number" && typeof i2.maxY == "number")
return i2;
const r2 = t47.topology.regionWidth[e2], s2 = t47.topology.regionHeight[e2], a2 = t47.topology.regionCenterX[e2], c2 = t47.topology.regionCenterY[e2];
return { minX: a2 - r2 / 2, maxX: a2 + r2 / 2, minY: c2 - s2 / 2, maxY: c2 + s2 / 2 };
};
var FV = (t47, e2) => ({ x: t47.topology.regionCenterX[e2], y: t47.topology.regionCenterY[e2] });
var jV = (t47, e2) => {
const n2 = t47.topology.regionMetadata?.[e2], o2 = Array.isArray(n2?.availableZ) ? n2.availableZ.filter((t48) => typeof t48 == "number" && Number.isInteger(t48) && t48 >= 0) : [];
if (o2.length > 0)
return jW(o2) ?? "z0";
const i2 = $W(t47.topology.regionAvailableZMask?.[e2] ?? 0);
if (i2.length > 0)
return jW(i2) ?? "z0";
const r2 = [...new Set((t47.topology.regionIncidentPorts[e2] ?? []).map((e3) => t47.topology.portZ[e3]))].sort((t48, e3) => t48 - e3);
return jW(r2) ?? "z0";
};
var $V = (t47, e2) => {
const n2 = t47.state.regionIntersectionCaches[e2], o2 = n2?.existingRegionCost ?? 0, i2 = t47.state.regionCongestionCost[e2] ?? 0, r2 = t47.problem.regionNetId[e2];
return wV(`region: region-${e2}`, `net: ${r2 === -1 ? "free" : `${r2}`}`, t47.getAdditionalRegionLabel(e2), `cost: ${o2.toFixed(3)}`, `congestion: ${i2.toFixed(3)}`, `same layer X: ${n2?.existingSameLayerIntersections ?? 0}`, `trans X: ${n2?.existingCrossingLayerIntersections ?? 0}`, `entry exit X: ${n2?.existingEntryExitLayerChanges ?? 0}`);
};
var YV = (t47, e2) => {
const n2 = t47.topology.regionMetadata?.[e2];
return n2?.isConnectionRegion ? { r: 255, g: 100, b: 255, a: 0.6 } : n2?.isThroughJumper ? { r: 100, g: 200, b: 100, a: 0.5 } : n2?.isPad ? { r: 255, g: 200, b: 100, a: 0.5 } : n2?.layer === "bottom" ? { r: 52, g: 152, b: 219, a: 0.08 } : { r: 200, g: 200, b: 255, a: 0.1 };
};
var XV = (t47, e2) => {
const n2 = YV(t47, e2), o2 = TV(t47.state.regionIntersectionCaches[e2]?.existingRegionCost ?? 0);
return EV((r2 = CV, s2 = o2 ** 0.8, { r: RV((i2 = n2).r, r2.r, s2), g: RV(i2.g, r2.g, s2), b: RV(i2.b, r2.b, s2), a: Number((i2.a + (r2.a - i2.a) * s2).toFixed(3)) }));
var i2, r2, s2;
};
var WV = (t47, e2) => {
const n2 = ((t48, e3) => ({ x: t48.topology.portX[e3], y: t48.topology.portY[e3] }))(t47, e2), o2 = 0.005 * t47.topology.portZ[e2];
return { x: n2.x + o2, y: n2.y + o2 };
};
var VV = WV;
var HV = (t47, e2) => jW([t47.topology.portZ[e2]]) ?? "z0";
var GV = (t47, e2) => {
const n2 = t47.topology.portMetadata?.[e2];
return `port: ${n2?.serializedPortId ?? n2?.portId ?? `port-${e2}`}`;
};
var UV = (t47, e2, n2) => {
if (n2 !== undefined)
return `net: ${t47.problem.routeNet[n2]}`;
const o2 = t47.state.portAssignment[e2];
if (o2 >= 0)
return `net: ${o2}`;
const i2 = new Set;
for (let n3 = 0;n3 < t47.problem.routeCount; n3++)
t47.problem.routeStartPort[n3] !== e2 && t47.problem.routeEndPort[n3] !== e2 || i2.add(t47.problem.routeNet[n3]);
return i2.size !== 0 ? `net: ${Array.from(i2).sort((t48, e3) => t48 - e3).join(", ")}` : undefined;
};
var ZV = (t47, e2) => `z: ${t47.topology.portZ[e2]}`;
var qV = (t47, e2, n2) => {
const o2 = t47.topology.portZ[e2], i2 = t47.topology.portZ[n2];
return o2 === i2 ? `z: ${o2}` : `z: ${o2} -> ${i2}`;
};
var JV = (t47, e2) => qV(t47, t47.problem.routeStartPort[e2], t47.problem.routeEndPort[e2]);
var QV = (t47, e2, n2) => wV(GV(t47, e2), ((t48, e3) => {
const n3 = t48.topology.incidentPortRegion[e3]?.[0], o2 = t48.topology.incidentPortRegion[e3]?.[1];
return `connects: region-${n3 ?? "?"} <-> region-${o2 ?? "?"}`;
})(t47, e2), UV(t47, e2, n2));
var KV = (t47, e2, n2, o2) => {
const i2 = t47.topology.portZ[n2];
return i2 !== t47.topology.portZ[o2] ? { strokeColor: DV("rgba(22, 160, 133, 0.95)", kV(t47, e2)), strokeDash: "2 4 2" } : i2 > 0 ? { strokeColor: DV("rgba(52, 152, 219, 0.95)", kV(t47, e2)), strokeDash: "3 2" } : { strokeColor: LV(t47, e2) };
};
var tH = (t47, e2) => {
for (let n2 = 0;n2 < t47.state.regionSegments.length; n2++) {
const o2 = t47.state.regionSegments[n2] ?? [];
for (const [i2, r2, s2] of o2)
e2.lines.push({ points: [WV(t47, r2), WV(t47, s2)], label: wV(`route: ${AV(t47, i2)}`, `region: region-${n2}`, qV(t47, r2, s2)), layer: HV(t47, r2), ...KV(t47, i2, r2, s2) });
}
};
var eH = (t47, e2) => {
const n2 = new Set;
for (let o2 = 0;o2 < t47.state.regionSegments.length; o2++) {
const i2 = t47.state.regionSegments[o2] ?? [];
for (const [o3, r2, s2] of i2)
for (const i3 of [r2, s2]) {
const r3 = `${o3}:${i3}`;
if (n2.has(r3))
continue;
n2.add(r3);
const s3 = WV(t47, i3);
e2.points.push({ x: s3.x, y: s3.y, color: LV(t47, o3, 1), layer: HV(t47, i3), label: wV(`route: ${AV(t47, o3)}`, GV(t47, i3), UV(t47, i3, o3), ZV(t47, i3)) });
}
}
};
var nH = (t47, e2) => {
for (let n2 = 0;n2 < t47.problem.routeCount; n2++)
if (t47.problem.routeStartPort[n2] === e2 || t47.problem.routeEndPort[n2] === e2)
return true;
return false;
};
var oH = (t47, e2, n2) => {
const o2 = ((t48, e3) => {
const n3 = new Set;
for (let o3 = 0;o3 < e3.length; o3++)
if (e3[o3] === 1)
for (const e4 of t48.topology.incidentPortRegion[o3] ?? [])
n3.add(e4);
return n3;
})(t47, n2), i2 = "rgba(245, 158, 11, 0.95)", r2 = "rgba(245, 158, 11, 0.08)";
for (const n3 of o2) {
const o3 = t47.topology.regionMetadata?.[n3], s2 = o3?.polygon, a2 = BV(t47, n3), c2 = FV(t47, n3), l2 = a2.maxX - a2.minX, h2 = a2.maxY - a2.minY, d2 = jV(t47, n3), u2 = wV("section region", $V(t47, n3));
Array.isArray(s2) && s2.length >= 3 ? e2.polygons.push({ points: s2, fill: r2, stroke: i2, strokeWidth: 2, layer: d2, label: u2 }) : e2.rects.push({ center: c2, width: Math.max(l2 - SV, 0.05), height: Math.max(h2 - SV, 0.05), fill: r2, stroke: i2, layer: d2, label: u2 });
}
for (let o3 = 0;o3 < n2.length; o3++)
n2[o3] === 1 && e2.circles.push({ center: VV(t47, o3), radius: 0.07, fill: "rgba(251, 191, 36, 0.18)", stroke: i2, layer: HV(t47, o3), label: wV(QV(t47, o3), ZV(t47, o3), "section port") });
};
var iH = (t47, e2 = {}) => {
const n2 = { arrows: [], circles: [], infiniteLines: [], lines: [], points: [], polygons: [], rects: [], texts: [], title: "Tiny HyperGraph", coordinateSystem: "cartesian" }, o2 = ((t48, e3) => {
if (!e3?.highlightSectionMask)
return;
const n3 = e3.sectionPortMask ?? t48.problem.portSectionMask;
if (n3.length !== t48.topology.portCount)
return;
let o3 = 0, i3 = 0;
for (let t49 = 0;t49 < n3.length; t49++)
n3[t49] === 1 ? o3 += 1 : i3 += 1;
return o3 !== 0 && i3 !== 0 ? n3 : undefined;
})(t47, e2), i2 = ((t48) => {
const e3 = t48.getStaticallyUnroutableRoutes();
if (e3.length !== 0)
return new Set(e3.map((t49) => t49.routeId));
})(t47);
for (let e3 = 0;e3 < t47.topology.regionCount; e3++) {
const o3 = t47.topology.regionMetadata?.[e3], i3 = o3?.polygon, r3 = BV(t47, e3), s3 = FV(t47, e3), a2 = r3.maxX - r3.minX, c2 = r3.maxY - r3.minY, l2 = jV(t47, e3), h2 = EV(YV(t47, e3));
Array.isArray(i3) && i3.length >= 3 ? n2.polygons.push({ points: i3, fill: h2, layer: l2 }) : n2.rects.push({ center: s3, width: Math.max(a2 - SV, 0.05), height: Math.max(c2 - SV, 0.05), fill: XV(t47, e3), layer: l2, label: $V(t47, e3) });
}
if (((t48, e3, n3) => {
for (let o3 = 0;o3 < t48.problem.routeCount; o3++) {
if (n3 && !n3.has(o3))
continue;
const i3 = t48.problem.routeStartPort[o3], r3 = t48.problem.routeEndPort[o3], s3 = WV(t48, i3), a2 = WV(t48, r3), c2 = LV(t48, o3), l2 = AV(t48, o3), h2 = zV(t48, o3);
e3.points.push({ x: s3.x, y: s3.y, color: c2, layer: HV(t48, i3), label: wV(`route: ${l2}`, h2, "endpoint: start", GV(t48, i3), ZV(t48, i3)) }), e3.points.push({ x: a2.x, y: a2.y, color: c2, layer: HV(t48, r3), label: wV(`route: ${l2}`, h2, "endpoint: end", GV(t48, r3), ZV(t48, r3)) });
}
})(t47, n2, i2), t47.iterations === 0) {
for (const t48 of n2.polygons)
t48.stroke = "rgba(128, 128, 128, 0.5)";
for (const t48 of n2.rects)
t48.stroke = "rgba(128, 128, 128, 0.5)";
}
if (t47.iterations === 0) {
for (let i3 = 0;i3 < t47.topology.portCount; i3++) {
const r3 = o2?.[i3] === 1;
e2.showOnlySectionPortsOnIdle && !r3 || n2.circles.push({ center: VV(t47, i3), radius: 0.05, fill: t47.topology.portZ[i3] > 0 ? "rgba(52, 152, 219, 0.55)" : "rgba(128, 128, 128, 0.5)", layer: HV(t47, i3), label: wV(QV(t47, i3), ZV(t47, i3)) });
}
if (i2)
((t48, e3) => {
for (const n3 of t48.getStaticallyUnroutableRoutes()) {
const { routeId: o3, connectionId: i3, startPortId: r3, endPortId: s3 } = n3, a2 = yV(t48, r3), c2 = yV(t48, s3), l2 = fV(`static reachability failed: ${i3}`, IV(t48, o3), n3.startRegionId ? `startRegionId: ${n3.startRegionId}` : undefined, n3.endRegionId ? `endRegionId: ${n3.endRegionId}` : undefined, n3.pointIds.length >= 2 ? `points: ${n3.pointIds.join(" -> ")}` : undefined, vV(t48, o3));
e3.lines.push({ points: [a2, c2], strokeColor: mV, strokeDash: "8 4", label: l2 }), e3.circles.push({ center: a2, radius: 0.12, fill: gV, stroke: mV, layer: _V(t48, r3), label: fV(l2, "endpoint: start", bV(t48, r3), xV(t48, r3)) }), e3.circles.push({ center: c2, radius: 0.12, fill: gV, stroke: mV, layer: _V(t48, s3), label: fV(l2, "endpoint: end", bV(t48, s3), xV(t48, s3)) });
}
})(t47, n2);
else {
const o3 = new Set;
for (const e3 of t47.state.regionSegments)
for (const [t48] of e3)
o3.add(t48);
if (o3.size > 0 && (tH(t47, n2), eH(t47, n2)), e2.showInitialRouteHints !== false) {
const e3 = new Set(t47.state.unroutedRoutes);
t47.state.currentRouteId !== undefined && e3.add(t47.state.currentRouteId), ((t48, e4, n3) => {
for (let o4 = 0;o4 < t48.problem.routeCount; o4++) {
if (n3 && !n3.has(o4))
continue;
const i3 = t48.problem.routeStartPort[o4], r3 = t48.problem.routeEndPort[o4], s3 = WV(t48, i3), a2 = WV(t48, r3), c2 = { x: (s3.x + a2.x) / 2, y: (s3.y + a2.y) / 2 };
e4.lines.push({ points: [s3, a2], strokeColor: LV(t48, o4), strokeDash: "3 3", layer: HV(t48, i3), label: wV(AV(t48, o4), JV(t48, o4)) }), e4.points.push({ x: c2.x, y: c2.y, color: LV(t48, o4, 1), layer: HV(t48, i3), label: wV(AV(t48, o4), JV(t48, o4)) });
}
})(t47, n2, e3);
}
}
} else
tH(t47, n2), eH(t47, n2), ((t48) => OV(t48) && t48.showUnassignedPortsInVisualization === true)(t47) && ((t48, e3) => {
for (let n3 = 0;n3 < t48.topology.portCount; n3++)
t48.state.portAssignment[n3] >= 0 || nH(t48, n3) || e3.circles.push({ center: VV(t48, n3), radius: 0.04, fill: t48.topology.portZ[n3] > 0 ? "rgba(52, 152, 219, 0.2)" : "rgba(128, 128, 128, 0.2)", stroke: t48.topology.portZ[n3] > 0 ? "rgba(52, 152, 219, 0.6)" : "rgba(128, 128, 128, 0.6)", layer: HV(t48, n3), label: wV(QV(t48, n3), ZV(t48, n3), "state: unassigned") });
})(t47, n2), OV(t47) || (((t48, e3) => {
const n3 = t48.state.currentRouteId;
if (n3 === undefined || t48.solved)
return;
const o3 = t48.problem.routeStartPort[n3], i3 = t48.problem.routeEndPort[n3], r3 = WV(t48, o3), s3 = WV(t48, i3), a2 = LV(t48, n3), c2 = AV(t48, n3);
e3.lines.push({ points: [r3, s3], strokeColor: a2, strokeDash: "10 5", label: wV(c2, JV(t48, n3)) });
})(t47, n2), ((t48, e3) => {
if (t48.solved)
return;
const n3 = t48.state.currentRouteId, o3 = t48.state.candidateQueue.toArray().sort((t49, e4) => t49.f - e4.f).slice(0, 10);
for (let i4 = 0;i4 < o3.length; i4++) {
const r4 = o3[i4], s4 = WV(t48, r4.portId), a2 = i4 === 0;
e3.points.push({ x: s4.x, y: s4.y, color: a2 ? "green" : "rgba(128, 128, 128, 0.25)", layer: HV(t48, r4.portId), label: wV(QV(t48, r4.portId, n3), ZV(t48, r4.portId), `g: ${r4.g.toFixed(2)}`, `h: ${r4.h.toFixed(2)}`, `f: ${r4.f.toFixed(2)}`) });
}
const i3 = o3[0];
if (!i3)
return;
const r3 = [];
let s3 = i3;
for (;s3; )
r3.unshift(WV(t48, s3.portId)), s3 = s3.prevCandidate;
r3.length > 1 && e3.lines.push({ points: r3, strokeColor: n3 !== undefined ? LV(t48, n3) : "rgba(0, 160, 120, 0.9)" });
})(t47, n2));
o2 && oH(t47, n2, o2), ((t48, e3) => {
if (t48.failed)
for (const n3 of t48.getNeverSuccessfullyRoutedRoutes()) {
const { routeId: o3, connectionId: i3, attempts: r3, startPortId: s3, endPortId: a2 } = n3, c2 = zV(t48, o3), l2 = VV(t48, s3), h2 = VV(t48, a2), d2 = wV(`never routed: ${i3}`, `attempts: ${r3}`, c2, n3.startRegionId ? `startRegionId: ${n3.startRegionId}` : undefined, n3.endRegionId ? `endRegionId: ${n3.endRegionId}` : undefined);
e3.lines.push({ points: [{ x: 0, y: 0 }, { x: l2.x, y: l2.y }], strokeColor: PV, strokeDash: NV, layer: HV(t48, s3), label: wV(d2, "origin guide", "endpoint: start") }), e3.circles.push({ center: l2, radius: 1, fill: MV, stroke: PV, layer: HV(t48, s3), label: wV(d2, "endpoint: start", GV(t48, s3), ZV(t48, s3)) }), e3.lines.push({ points: [{ x: 0, y: 0 }, { x: h2.x, y: h2.y }], strokeColor: PV, strokeDash: NV, layer: HV(t48, a2), label: wV(d2, "origin guide", "endpoint: end") }), e3.circles.push({ center: h2, radius: 1, fill: MV, stroke: PV, layer: HV(t48, a2), label: wV(d2, "endpoint: end", GV(t48, a2), ZV(t48, a2)) });
}
})(t47, n2);
const r2 = t47.state.unroutedRoutes.length + (t47.state.currentRouteId === undefined ? 0 : 1), s2 = o2 ? o2.reduce((t48, e3) => t48 + Number(e3 === 1), 0) : 0;
return n2.title = ["Tiny HyperGraph", `iter=${t47.iterations}`, `pending=${r2}`, o2 ? `sectionPorts=${s2}` : undefined, i2 ? `staticReachabilityFailed=${i2.size}` : undefined, t47.failed ? "failed" : t47.solved ? "solved" : "running"].filter(Boolean).join(" | "), n2;
};
var rH = 50000;
var sH = () => ({ netIds: new Int32Array(0), lesserAngles: new Int32Array(0), greaterAngles: new Int32Array(0), layerMasks: new Int32Array(0), existingCrossingLayerIntersections: 0, existingSameLayerIntersections: 0, existingEntryExitLayerChanges: 0, existingRegionCost: 0, existingSegmentCount: 0 });
var aH = (t47) => ({ netIds: new Int32Array(t47.netIds), lesserAngles: new Int32Array(t47.lesserAngles), greaterAngles: new Int32Array(t47.greaterAngles), layerMasks: new Int32Array(t47.layerMasks), existingCrossingLayerIntersections: t47.existingCrossingLayerIntersections, existingSameLayerIntersections: t47.existingSameLayerIntersections, existingEntryExitLayerChanges: t47.existingEntryExitLayerChanges, existingRegionCost: t47.existingRegionCost, existingSegmentCount: t47.existingSegmentCount });
var cH = (t47) => {
return { portAssignment: new Int32Array(t47.portAssignment), regionSegments: (e2 = t47.regionSegments, e2.map((t48) => t48.map(([t49, e3, n2]) => [t49, e3, n2]))), regionIntersectionCaches: t47.regionIntersectionCaches.map(aH), regionCongestionCost: new Float64Array(t47.regionCongestionCost), ripCount: t47.ripCount };
var e2;
};
var lH = (t47, e2) => {
e2 && (e2.minViaPadDiameter !== undefined && (t47.minViaPadDiameter = e2.minViaPadDiameter), e2.DISTANCE_TO_COST !== undefined && (t47.DISTANCE_TO_COST = e2.DISTANCE_TO_COST), e2.RIP_THRESHOLD_START !== undefined && (t47.RIP_THRESHOLD_START = e2.RIP_THRESHOLD_START), e2.RIP_THRESHOLD_END !== undefined && (t47.RIP_THRESHOLD_END = e2.RIP_THRESHOLD_END), e2.RIP_THRESHOLD_RAMP_ATTEMPTS !== undefined && (t47.RIP_THRESHOLD_RAMP_ATTEMPTS = e2.RIP_THRESHOLD_RAMP_ATTEMPTS), e2.RIP_CONGESTION_REGION_COST_FACTOR !== undefined && (t47.RIP_CONGESTION_REGION_COST_FACTOR = e2.RIP_CONGESTION_REGION_COST_FACTOR), e2.TRACE_DENSITY_COST_FACTOR !== undefined && (t47.TRACE_DENSITY_COST_FACTOR = Math.max(0, e2.TRACE_DENSITY_COST_FACTOR)), e2.USE_LAZY_ROUTE_HEURISTIC !== undefined && (t47.USE_LAZY_ROUTE_HEURISTIC = e2.USE_LAZY_ROUTE_HEURISTIC), e2.USE_SPARSE_CANDIDATE_STORAGE !== undefined && (t47.USE_SPARSE_CANDIDATE_STORAGE = e2.USE_SPARSE_CANDIDATE_STORAGE), e2.MAX_ITERATIONS !== undefined && (t47.MAX_ITERATIONS = e2.MAX_ITERATIONS), e2.VERBOSE !== undefined && (t47.VERBOSE = e2.VERBOSE), e2.STATIC_REACHABILITY_PRECHECK !== undefined && (t47.STATIC_REACHABILITY_PRECHECK = e2.STATIC_REACHABILITY_PRECHECK), e2.STATIC_REACHABILITY_PRECHECK_MAX_HOPS !== undefined && (t47.STATIC_REACHABILITY_PRECHECK_MAX_HOPS = e2.STATIC_REACHABILITY_PRECHECK_MAX_HOPS), e2.ACCEPT_BEST_SOLUTION_ON_TIMEOUT !== undefined && (t47.ACCEPT_BEST_SOLUTION_ON_TIMEOUT = e2.ACCEPT_BEST_SOLUTION_ON_TIMEOUT), e2.GREEDY_FINAL_ROUTE_ITERS !== undefined && (t47.GREEDY_FINAL_ROUTE_ITERS = e2.GREEDY_FINAL_ROUTE_ITERS), e2.PARTIAL_RIP_ENABLED !== undefined && (t47.PARTIAL_RIP_ENABLED = e2.PARTIAL_RIP_ENABLED), e2.PARTIAL_RIP_MIN_ROUTE_COUNT !== undefined && (t47.PARTIAL_RIP_MIN_ROUTE_COUNT = e2.PARTIAL_RIP_MIN_ROUTE_COUNT), e2.PARTIAL_RIP_MAX_ROUTE_COUNT !== undefined && (t47.PARTIAL_RIP_MAX_ROUTE_COUNT = e2.PARTIAL_RIP_MAX_ROUTE_COUNT), e2.PARTIAL_RIP_MAX_DISTANCE !== undefined && (t47.PARTIAL_RIP_MAX_DISTANCE = e2.PARTIAL_RIP_MAX_DISTANCE), e2.PARTIAL_RIP_QUALITY_MAX_DISTANCE !== undefined && (t47.PARTIAL_RIP_QUALITY_MAX_DISTANCE = e2.PARTIAL_RIP_QUALITY_MAX_DISTANCE), e2.PARTIAL_RIP_MAX_ATTEMPTS !== undefined && (t47.PARTIAL_RIP_MAX_ATTEMPTS = e2.PARTIAL_RIP_MAX_ATTEMPTS), e2.PARTIAL_RIP_WARMUP_FULL_RIP_ATTEMPTS !== undefined && (t47.PARTIAL_RIP_WARMUP_FULL_RIP_ATTEMPTS = e2.PARTIAL_RIP_WARMUP_FULL_RIP_ATTEMPTS), e2.PARTIAL_RIP_COMPLEXITY_SELECTION_MIN_ROUTE_COUNT !== undefined && (t47.PARTIAL_RIP_COMPLEXITY_SELECTION_MIN_ROUTE_COUNT = e2.PARTIAL_RIP_COMPLEXITY_SELECTION_MIN_ROUTE_COUNT), e2.PARTIAL_RIP_TARGET_MAX_COST_IMPROVEMENT_RATIO !== undefined && (t47.PARTIAL_RIP_TARGET_MAX_COST_IMPROVEMENT_RATIO = e2.PARTIAL_RIP_TARGET_MAX_COST_IMPROVEMENT_RATIO), e2.PARTIAL_RIP_MAX_REGION_COST_GROWTH_RATIO !== undefined && (t47.PARTIAL_RIP_MAX_REGION_COST_GROWTH_RATIO = e2.PARTIAL_RIP_MAX_REGION_COST_GROWTH_RATIO), e2.PARTIAL_RIP_MAX_TOTAL_COST_GROWTH_RATIO !== undefined && (t47.PARTIAL_RIP_MAX_TOTAL_COST_GROWTH_RATIO = e2.PARTIAL_RIP_MAX_TOTAL_COST_GROWTH_RATIO), e2.OUTSIDE_IN_ROUTING !== undefined && (t47.OUTSIDE_IN_ROUTING = e2.OUTSIDE_IN_ROUTING), e2.OUTSIDE_IN_MAX_DISTANCE !== undefined && (t47.OUTSIDE_IN_MAX_DISTANCE = e2.OUTSIDE_IN_MAX_DISTANCE));
};
var hH = (t47) => ({ minViaPadDiameter: t47.minViaPadDiameter, DISTANCE_TO_COST: t47.DISTANCE_TO_COST, RIP_THRESHOLD_START: t47.RIP_THRESHOLD_START, RIP_THRESHOLD_END: t47.RIP_THRESHOLD_END, RIP_THRESHOLD_RAMP_ATTEMPTS: t47.RIP_THRESHOLD_RAMP_ATTEMPTS, RIP_CONGESTION_REGION_COST_FACTOR: t47.RIP_CONGESTION_REGION_COST_FACTOR, TRACE_DENSITY_COST_FACTOR: t47.TRACE_DENSITY_COST_FACTOR, USE_LAZY_ROUTE_HEURISTIC: t47.USE_LAZY_ROUTE_HEURISTIC, USE_SPARSE_CANDIDATE_STORAGE: t47.USE_SPARSE_CANDIDATE_STORAGE, MAX_ITERATIONS: t47.MAX_ITERATIONS, VERBOSE: t47.VERBOSE, STATIC_REACHABILITY_PRECHECK: t47.STATIC_REACHABILITY_PRECHECK, STATIC_REACHABILITY_PRECHECK_MAX_HOPS: t47.STATIC_REACHABILITY_PRECHECK_MAX_HOPS, ACCEPT_BEST_SOLUTION_ON_TIMEOUT: t47.ACCEPT_BEST_SOLUTION_ON_TIMEOUT, GREEDY_FINAL_ROUTE_ITERS: t47.GREEDY_FINAL_ROUTE_ITERS, PARTIAL_RIP_ENABLED: t47.PARTIAL_RIP_ENABLED, PARTIAL_RIP_MIN_ROUTE_COUNT: t47.PARTIAL_RIP_MIN_ROUTE_COUNT, PARTIAL_RIP_MAX_ROUTE_COUNT: t47.PARTIAL_RIP_MAX_ROUTE_COUNT, PARTIAL_RIP_MAX_DISTANCE: t47.PARTIAL_RIP_MAX_DISTANCE, PARTIAL_RIP_QUALITY_MAX_DISTANCE: t47.PARTIAL_RIP_QUALITY_MAX_DISTANCE, PARTIAL_RIP_MAX_ATTEMPTS: t47.PARTIAL_RIP_MAX_ATTEMPTS, PARTIAL_RIP_WARMUP_FULL_RIP_ATTEMPTS: t47.PARTIAL_RIP_WARMUP_FULL_RIP_ATTEMPTS, PARTIAL_RIP_COMPLEXITY_SELECTION_MIN_ROUTE_COUNT: t47.PARTIAL_RIP_COMPLEXITY_SELECTION_MIN_ROUTE_COUNT, PARTIAL_RIP_TARGET_MAX_COST_IMPROVEMENT_RATIO: t47.PARTIAL_RIP_TARGET_MAX_COST_IMPROVEMENT_RATIO, PARTIAL_RIP_MAX_REGION_COST_GROWTH_RATIO: t47.PARTIAL_RIP_MAX_REGION_COST_GROWTH_RATIO, PARTIAL_RIP_MAX_TOTAL_COST_GROWTH_RATIO: t47.PARTIAL_RIP_MAX_TOTAL_COST_GROWTH_RATIO, OUTSIDE_IN_ROUTING: t47.OUTSIDE_IN_ROUTING, OUTSIDE_IN_MAX_DISTANCE: t47.OUTSIDE_IN_MAX_DISTANCE });
var dH = (t47, e2) => t47.f - e2.f;
var uH = class extends kt {
constructor(t47, e2, n2) {
super(), this.topology = t47, this.problem = e2, lH(this, n2);
let o2 = 1;
const i2 = new Int32Array(t47.portCount).fill(-1), r2 = new Int32Array(t47.portCount).fill(-1);
for (let e3 = 0;e3 < t47.portCount; e3++) {
const n3 = t47.incidentPortRegion[e3] ?? [];
n3.length > o2 && (o2 = n3.length), i2[e3] = n3[0] ?? -1, r2[e3] = n3[1] ?? -1;
}
this.candidateHopSlotStride = o2, this.candidateFirstRegionByPortId = i2, this.candidateSecondRegionByPortId = r2;
const s2 = t47.portCount * o2;
this.candidateHopCapacity = s2, this.state = { portAssignment: new Int32Array(t47.portCount).fill(-1), regionSegments: Array.from({ length: t47.regionCount }, () => []), regionIntersectionCaches: Array.from({ length: t47.regionCount }, () => sH()), currentRouteId: undefined, currentRouteNetId: undefined, unroutedRoutes: pV(e2.routeCount), candidateQueue: new rV([], dH), candidateBestCostByHopId: this.USE_SPARSE_CANDIDATE_STORAGE ? new Map : new Float64Array(s2), candidateBestCostGenerationByHopId: this.USE_SPARSE_CANDIDATE_STORAGE ? new Map : new Uint32Array(s2), candidateBestCostGeneration: 1, goalPortId: -1, ripCount: 0, regionCongestionCost: new Float64Array(t47.regionCount).fill(0) }, this.routeAttemptCountByRouteId = new Uint32Array(e2.routeCount), this.routeSuccessCountByRouteId = new Uint32Array(e2.routeCount);
const a2 = iV({ topology: t47, problem: e2, state: this.state, routeSuccessCountByRouteId: this.routeSuccessCountByRouteId, appendSegmentToRegionCache: (t48, e3, n3) => this.appendSegmentToRegionCache(t48, e3, n3) });
a2 && (this.stats = { ...this.stats, ...a2 });
}
state;
candidateHopSlotStride;
candidateHopCapacity;
candidateFirstRegionByPortId;
candidateSecondRegionByPortId;
candidateOverflowBestCost;
_problemSetup;
routeAttemptCountByRouteId;
routeSuccessCountByRouteId;
bestSolvedStateSnapshot;
bestSolvedStateSummary;
hasLoggedNeverSuccessfullyRoutedRoutes = false;
staticallyUnroutableRoutes = [];
segmentGeometryScratch = { lesserAngle: 0, greaterAngle: 0, layerMask: 0, entryExitLayerChanges: 0 };
ADD_SEGMENT_DISTANCE_TO_G = false;
DISTANCE_TO_COST = 0.05;
minViaPadDiameter = QW;
RIP_THRESHOLD_START = 0.05;
RIP_THRESHOLD_END = 0.8;
RIP_THRESHOLD_RAMP_ATTEMPTS = 50;
RIP_CONGESTION_REGION_COST_FACTOR = 0.1;
TRACE_DENSITY_COST_FACTOR = 0;
USE_LAZY_ROUTE_HEURISTIC = false;
USE_SPARSE_CANDIDATE_STORAGE = false;
MAX_ITERATIONS = 1e6;
VERBOSE = false;
STATIC_REACHABILITY_PRECHECK = true;
STATIC_REACHABILITY_PRECHECK_MAX_HOPS = 16;
ACCEPT_BEST_SOLUTION_ON_TIMEOUT = true;
GREEDY_FINAL_ROUTE_ITERS = 4;
PARTIAL_RIP_ENABLED = false;
PARTIAL_RIP_MIN_ROUTE_COUNT = 0;
PARTIAL_RIP_MAX_ROUTE_COUNT = Number.POSITIVE_INFINITY;
PARTIAL_RIP_MAX_DISTANCE = 12;
PARTIAL_RIP_QUALITY_MAX_DISTANCE;
PARTIAL_RIP_MAX_ATTEMPTS = Number.POSITIVE_INFINITY;
PARTIAL_RIP_WARMUP_FULL_RIP_ATTEMPTS = 0;
PARTIAL_RIP_COMPLEXITY_SELECTION_MIN_ROUTE_COUNT = Number.POSITIVE_INFINITY;
PARTIAL_RIP_TARGET_MAX_COST_IMPROVEMENT_RATIO = 0;
PARTIAL_RIP_MAX_REGION_COST_GROWTH_RATIO = 0.2;
PARTIAL_RIP_MAX_TOTAL_COST_GROWTH_RATIO = 0.1;
OUTSIDE_IN_ROUTING = false;
OUTSIDE_IN_MAX_DISTANCE = 24;
get problemSetup() {
return this._problemSetup || (this._problemSetup = this.computeProblemSetup()), this._problemSetup;
}
computeProblemSetup() {
const { topology: t47, problem: e2 } = this, n2 = this.USE_LAZY_ROUTE_HEURISTIC ? undefined : new Float64Array(t47.portCount * e2.routeCount), o2 = t47.portX, i2 = t47.portY, r2 = Array.from({ length: t47.portCount }, () => new Set), s2 = new Int32Array(t47.portCount).fill(-1), a2 = (t48, e3) => {
r2[t48].add(e3);
const n3 = s2[t48];
n3 === -1 ? s2[t48] = e3 : n3 !== e3 && (s2[t48] = -2);
};
for (let r3 = 0;r3 < e2.routeCount; r3++) {
const s3 = e2.routeNet[r3];
if (a2(e2.routeStartPort[r3], s3), a2(e2.routeEndPort[r3], s3), n2) {
const s4 = e2.routeEndPort[r3], a3 = o2[s4], c2 = i2[s4];
for (let s5 = 0;s5 < t47.portCount; s5++) {
const t48 = o2[s5] - a3, l2 = i2[s5] - c2;
n2[s5 * e2.routeCount + r3] = Math.sqrt(t48 * t48 + l2 * l2) * this.DISTANCE_TO_COST;
}
}
}
return { portHCostToEndOfRoute: n2, portEndpointNetIds: r2, portEndpointReservationNetId: s2 };
}
_setup() {
if (this.problemSetup, this.STATIC_REACHABILITY_PRECHECK) {
const t47 = uV({ topology: this.topology, problem: this.problem, problemSetup: this.problemSetup, portAssignment: this.state.portAssignment, routeIds: this.state.unroutedRoutes, maxPrecheckHops: Math.max(0, this.STATIC_REACHABILITY_PRECHECK_MAX_HOPS), getStartingNextRegionId: (t48, e2) => this.getStartingNextRegionId(t48, e2), getRouteSummary: (t48) => this.getRouteSummary(t48) });
this.staticallyUnroutableRoutes = t47, t47.length > 0 && (this.failed = true, this.error = ((t48) => {
const e2 = t48.slice(0, 5).map((t49) => {
const e3 = t49.pointIds.length >= 2 ? `${t49.pointIds[0]}->${t49.pointIds[1]}` : `${t49.startPortId}->${t49.endPortId}`;
return `${t49.connectionId} (${e3})`;
}).join(", "), n2 = t48.length - 5;
return ["Static reachability precheck failed:", `${t48.length} route(s) have no legal path under the current reservation and start-region rules`, n2 > 0 ? `${e2}, +${n2} more` : e2].join(" ");
})(t47), this.stats = { ...this.stats, staticallyUnroutableRouteCount: t47.length });
}
}
_step() {
const { problem: t47, topology: e2, state: n2 } = this;
if (n2.currentRouteId === undefined) {
if (n2.unroutedRoutes.length === 0)
return void this.onAllRoutesRouted();
n2.currentRouteId = n2.unroutedRoutes.shift(), n2.currentRouteNetId = t47.routeNet[n2.currentRouteId], this.routeAttemptCountByRouteId[n2.currentRouteId] += 1, this.resetCandidateBestCosts();
const e3 = this.getRouteStartPortId(n2.currentRouteId);
n2.candidateQueue.clear();
const o3 = this.getStartingNextRegionId(n2.currentRouteId, e3);
if (o3 === undefined)
return this.failed = true, void (this.error = `Start port ${e3} has no incident regions`);
this.setCandidateBestCost(this.getHopId(e3, o3), 0), n2.candidateQueue.queue({ nextRegionId: o3, portId: e3, f: 0, g: 0, h: 0 }), n2.goalPortId = this.getRouteEndPortId(n2.currentRouteId);
}
const o2 = n2.candidateQueue.dequeue();
if (!o2)
return void this.onOutOfCandidates();
const i2 = this.getHopId(o2.portId, o2.nextRegionId);
if (o2.g > this.getCandidateBestCost(i2))
return;
if (this.isRegionReservedForDifferentNet(o2.nextRegionId))
return;
const r2 = e2.regionIncidentPorts[o2.nextRegionId];
for (const i3 of r2) {
const r3 = n2.portAssignment[i3];
if (this.isPortReservedForDifferentNet(i3))
continue;
if (i3 === n2.goalPortId) {
if (r3 !== -1 && r3 !== n2.currentRouteNetId)
continue;
return void this.onPathFound(o2);
}
if (r3 !== -1 && r3 !== n2.currentRouteNetId)
continue;
if (i3 === o2.portId)
continue;
if (t47.portSectionMask[i3] === 0)
continue;
const s2 = e2.incidentPortRegion[i3][0] === o2.nextRegionId ? e2.incidentPortRegion[i3][1] : e2.incidentPortRegion[i3][0];
if (s2 === undefined || this.isRegionReservedForDifferentNet(s2))
continue;
const a2 = this.getHopId(i3, s2);
if (n2.candidateQueue.isClosedHop?.(i3, s2) === true)
continue;
const c2 = this.getCandidateBestCost(a2);
if (o2.g >= c2)
continue;
const l2 = this.computeG(o2, i3, c2);
if (!Number.isFinite(l2) || l2 >= c2)
continue;
const h2 = this.computeH(i3), d2 = { prevRegionId: o2.nextRegionId, nextRegionId: s2, portId: i3, g: l2, h: h2, f: l2 + h2, prevCandidate: o2 };
if (i3 === n2.goalPortId)
return void this.onPathFound(d2);
this.setCandidateBestCost(a2, l2), n2.candidateQueue.queue(d2);
}
}
resetCandidateBestCosts() {
const { state: t47 } = this;
if (this.candidateOverflowBestCost?.clear(), t47.candidateBestCostGeneration === 4294967295)
return t47.candidateBestCostByHopId instanceof Map && t47.candidateBestCostByHopId.clear(), t47.candidateBestCostGenerationByHopId instanceof Map ? t47.candidateBestCostGenerationByHopId.clear() : t47.candidateBestCostGenerationByHopId.fill(0), void (t47.candidateBestCostGeneration = 1);
t47.candidateBestCostGeneration += 1;
}
getCandidateBestCost(t47) {
if (t47 < 0)
return this.candidateOverflowBestCost?.get(t47) ?? Number.POSITIVE_INFINITY;
const { state: e2 } = this, n2 = e2.candidateBestCostGenerationByHopId;
return (n2 instanceof Map ? n2.get(t47) : n2[t47]) === e2.candidateBestCostGeneration ? e2.candidateBestCostByHopId instanceof Map ? e2.candidateBestCostByHopId.get(t47) : e2.candidateBestCostByHopId[t47] : Number.POSITIVE_INFINITY;
}
setCandidateBestCost(t47, e2) {
if (t47 < 0)
return this.candidateOverflowBestCost || (this.candidateOverflowBestCost = new Map), void this.candidateOverflowBestCost.set(t47, e2);
const { state: n2 } = this;
n2.candidateBestCostGenerationByHopId instanceof Map ? n2.candidateBestCostGenerationByHopId.set(t47, n2.candidateBestCostGeneration) : n2.candidateBestCostGenerationByHopId[t47] = n2.candidateBestCostGeneration, n2.candidateBestCostByHopId instanceof Map ? n2.candidateBestCostByHopId.set(t47, e2) : n2.candidateBestCostByHopId[t47] = e2;
}
getHopId(t47, e2) {
const n2 = t47 * this.candidateHopSlotStride;
if (this.candidateFirstRegionByPortId[t47] === e2)
return n2;
if (this.candidateSecondRegionByPortId[t47] === e2)
return n2 + 1;
const o2 = this.topology.incidentPortRegion[t47];
for (let t48 = 2;t48 < (o2?.length ?? 0); t48++)
if (o2[t48] === e2)
return n2 + t48;
return -(t47 * this.topology.regionCount + e2) - 1;
}
getStartingNextRegionId(t47, e2) {
const n2 = this.topology.incidentPortRegion[e2] ?? [], o2 = this.problem.routeNet[t47];
return n2.find((t48) => this.problem.regionNetId[t48] === -1) ?? n2.find((t48) => this.problem.regionNetId[t48] === o2) ?? n2[0];
}
getRouteStartPortId(t47) {
return this.problem.routeStartPort[t47];
}
getRouteEndPortId(t47) {
return this.problem.routeEndPort[t47];
}
isPortReservedForDifferentNet(t47) {
const e2 = this.problemSetup.portEndpointReservationNetId[t47] ?? -1;
return e2 === -2 || e2 !== -1 && e2 !== this.state.currentRouteNetId;
}
isRegionReservedForDifferentNet(t47) {
const e2 = this.problem.regionNetId[t47];
return e2 !== -1 && e2 !== this.state.currentRouteNetId;
}
isKnownSingleLayerRegion(t47) {
const e2 = this.topology.regionAvailableZMask?.[t47] ?? 0;
return KW(e2);
}
computeRegionCostForRegion(t47, e2, n2, o2, i2) {
return ((t48, e3, n3, o3, i3, r2, s2 = 0, a2 = 0.3, c2 = 0) => tV(t48 * e3, n3, o3, i3, r2, s2, a2, c2))(this.topology.regionWidth[t47], this.topology.regionHeight[t47], e2, n2, o2, i2, this.topology.regionAvailableZMask?.[t47] ?? 0, this.minViaPadDiameter, this.TRACE_DENSITY_COST_FACTOR);
}
populateSegmentGeometryScratch(t47, e2, n2) {
const { topology: o2 } = this, i2 = this.segmentGeometryScratch, r2 = this.candidateFirstRegionByPortId[e2] === t47 || this.candidateSecondRegionByPortId[e2] !== t47 ? o2.portAngleForRegion1[e2] : o2.portAngleForRegion2?.[e2] ?? o2.portAngleForRegion1[e2], s2 = this.candidateFirstRegionByPortId[n2] === t47 || this.candidateSecondRegionByPortId[n2] !== t47 ? o2.portAngleForRegion1[n2] : o2.portAngleForRegion2?.[n2] ?? o2.portAngleForRegion1[n2], a2 = o2.portZ[e2], c2 = o2.portZ[n2];
return i2.lesserAngle = r2 < s2 ? r2 : s2, i2.greaterAngle = r2 < s2 ? s2 : r2, i2.layerMask = 1 << a2 | 1 << c2, i2.entryExitLayerChanges = a2 !== c2 ? 1 : 0, i2;
}
appendSegmentToRegionCache(t47, e2, n2) {
const { state: o2 } = this, i2 = o2.regionIntersectionCaches[t47], r2 = this.populateSegmentGeometryScratch(t47, e2, n2), [s2, a2, c2] = nV(i2, o2.currentRouteNetId, r2.lesserAngle, r2.greaterAngle, r2.layerMask, r2.entryExitLayerChanges), l2 = i2.netIds.length + 1, h2 = new Int32Array(l2);
h2.set(i2.netIds), h2[l2 - 1] = o2.currentRouteNetId;
const d2 = new Int32Array(l2);
d2.set(i2.lesserAngles), d2[l2 - 1] = r2.lesserAngle;
const u2 = new Int32Array(l2);
u2.set(i2.greaterAngles), u2[l2 - 1] = r2.greaterAngle;
const p2 = new Int32Array(l2);
p2.set(i2.layerMasks), p2[l2 - 1] = r2.layerMask;
const m2 = i2.existingSameLayerIntersections + s2, g2 = i2.existingCrossingLayerIntersections + a2, f2 = i2.existingEntryExitLayerChanges + c2, y2 = d2.length;
o2.regionIntersectionCaches[t47] = { netIds: h2, lesserAngles: d2, greaterAngles: u2, layerMasks: p2, existingSameLayerIntersections: m2, existingCrossingLayerIntersections: g2, existingEntryExitLayerChanges: f2, existingSegmentCount: y2, existingRegionCost: this.computeRegionCostForRegion(t47, m2, g2, f2, y2) };
}
getSolvedPathSegments(t47) {
const { state: e2 } = this, n2 = [];
let o2 = t47;
for (;o2; )
n2.unshift(o2), o2 = o2.prevCandidate;
const i2 = [];
for (let t48 = 1;t48 < n2.length; t48++)
i2.push({ regionId: n2[t48 - 1].nextRegionId, fromPortId: n2[t48 - 1].portId, toPortId: n2[t48].portId });
const r2 = n2[n2.length - 1];
return r2 && r2.portId !== e2.goalPortId && i2.push({ regionId: r2.nextRegionId, fromPortId: r2.portId, toPortId: e2.goalPortId }), i2;
}
resetRoutingStateForRerip() {
const { topology: t47, problem: e2, state: n2 } = this;
n2.portAssignment.fill(-1), n2.regionSegments = Array.from({ length: t47.regionCount }, () => []), n2.regionIntersectionCaches = Array.from({ length: t47.regionCount }, () => sH()), n2.currentRouteNetId = undefined, n2.currentRouteId = undefined, n2.unroutedRoutes = sV(pV(e2.routeCount), n2.ripCount), n2.candidateQueue.clear(), this.resetCandidateBestCosts(), n2.goalPortId = -1;
}
getMaxRegionCost() {
const { topology: t47, state: e2 } = this;
let n2 = 0;
for (let o2 = 0;o2 < t47.regionCount; o2++) {
const t48 = e2.regionIntersectionCaches[o2]?.existingRegionCost ?? 0;
n2 = Math.max(n2, t48);
}
return n2;
}
getRouteMetadata(t47) {
return this.problem.routeMetadata?.[t47];
}
getRouteConnectionId(t47) {
const e2 = this.getRouteMetadata(t47)?.connectionId;
return typeof e2 == "string" ? e2 : `route-${t47}`;
}
getRouteSummary(t47) {
return (({ problem: t48, routeId: e2, getRouteMetadata: n2, getRouteConnectionId: o2 }) => {
const i2 = n2?.(e2) ?? aV(t48, e2);
return { routeId: e2, connectionId: o2?.(e2) ?? lV(t48, e2), startPortId: t48.routeStartPort[e2], endPortId: t48.routeEndPort[e2], startRegionId: typeof i2?.startRegionId == "string" ? i2.startRegionId : undefined, endRegionId: typeof i2?.endRegionId == "string" ? i2.endRegionId : undefined, pointIds: cV(i2) };
})({ problem: this.problem, routeId: t47, getRouteMetadata: (t48) => this.getRouteMetadata(t48), getRouteConnectionId: (t48) => this.getRouteConnectionId(t48) });
}
getAdditionalRegionLabel(t47) {}
getNeverSuccessfullyRoutedRoutes() {
const t47 = [];
for (let e2 = 0;e2 < this.problem.routeCount; e2++) {
const n2 = this.routeAttemptCountByRouteId[e2];
n2 === 0 || this.routeSuccessCountByRouteId[e2] > 0 || t47.push({ ...this.getRouteSummary(e2), attempts: n2 });
}
return t47;
}
getStaticallyUnroutableRoutes() {
return this.staticallyUnroutableRoutes;
}
logNeverSuccessfullyRoutedRoutes() {
if (!this.VERBOSE || this.hasLoggedNeverSuccessfullyRoutedRoutes)
return;
const t47 = this.getNeverSuccessfullyRoutedRoutes();
if (this.hasLoggedNeverSuccessfullyRoutedRoutes = true, t47.length !== 0) {
console.log(["[TinyHyperGraphSolver:never-routed-summary]", `count=${t47.length}`].join(" "));
for (const e2 of t47) {
const t48 = e2.pointIds.length >= 2 ? `${e2.pointIds[0]}->${e2.pointIds[1]}` : "unknown";
console.log(["[TinyHyperGraphSolver:never-routed]", `routeId=${e2.routeId}`, `connectionId=${e2.connectionId}`, `attempts=${e2.attempts}`, `pointPath=${t48}`, `startRegionId=${e2.startRegionId ?? "unknown"}`, `endRegionId=${e2.endRegionId ?? "unknown"}`].join(" "));
}
}
}
logRipEvent(t47, e2, n2 = {}) {
this.VERBOSE && console.log(["[TinyHyperGraphSolver:rip]", `ripCount=${this.state.ripCount}`, `maxRegionCostBeforeRip=${e2.toFixed(3)}`, `reason=${t47}`, ...Object.entries(n2).map(([t48, e3]) => `${t48}=${typeof e3 == "number" ? Number.isInteger(e3) ? String(e3) : e3.toFixed(3) : e3}`)].join(" "));
}
compareRegionCostSummaries(t47, e2) {
return t47.maxRegionCost !== e2.maxRegionCost ? t47.maxRegionCost - e2.maxRegionCost : t47.totalRegionCost - e2.totalRegionCost;
}
captureBestSolvedState(t47) {
this.bestSolvedStateSummary && this.compareRegionCostSummaries(t47, this.bestSolvedStateSummary) >= 0 || this.replaceBestSolvedState(t47);
}
replaceBestSolvedState(t47) {
this.bestSolvedStateSummary = t47, this.bestSolvedStateSnapshot = cH({ portAssignment: this.state.portAssignment, regionSegments: this.state.regionSegments, regionIntersectionCaches: this.state.regionIntersectionCaches, regionCongestionCost: this.state.regionCongestionCost, ripCount: this.state.ripCount });
}
restoreBestSolvedState() {
if (!this.bestSolvedStateSnapshot)
return;
const t47 = cH(this.bestSolvedStateSnapshot);
this.state.portAssignment = t47.portAssignment, this.state.regionSegments = t47.regionSegments, this.state.regionIntersectionCaches = t47.regionIntersectionCaches, this.state.regionCongestionCost = t47.regionCongestionCost, this.state.ripCount = t47.ripCount, this.state.currentRouteId = undefined, this.state.currentRouteNetId = undefined, this.state.unroutedRoutes = [], this.state.candidateQueue.clear(), this.resetCandidateBestCosts(), this.state.goalPortId = -1;
}
getRemainingRouteIdsForGreedyFinalRoute() {
const t47 = new Set(this.state.unroutedRoutes);
return this.state.currentRouteId !== undefined && t47.add(this.state.currentRouteId), [...t47];
}
applySnapshotToGreedyFinalRouteSolver(t47, e2, n2) {
const o2 = cH(e2);
t47.state.portAssignment = o2.portAssignment, t47.state.regionSegments = o2.regionSegments, t47.state.regionIntersectionCaches = o2.regionIntersectionCaches, t47.state.regionCongestionCost = o2.regionCongestionCost, t47.state.ripCount = 0, t47.state.currentRouteId = undefined, t47.state.currentRouteNetId = undefined, t47.state.unroutedRoutes = [...n2], t47.state.candidateQueue.clear(), t47.resetCandidateBestCosts(), t47.state.goalPortId = -1;
}
summarizeSolvedState(t47) {
let e2 = 0, n2 = 0;
for (const o2 of t47.state.regionIntersectionCaches) {
const t48 = o2.existingRegionCost;
e2 = Math.max(e2, t48), n2 += t48;
}
return { maxRegionCost: e2, totalRegionCost: n2 };
}
tryGreedyFinalRouteAcceptance() {
const t47 = Math.max(0, Math.floor(this.GREEDY_FINAL_ROUTE_ITERS));
if (t47 === 0)
return false;
const e2 = this.getRemainingRouteIdsForGreedyFinalRoute();
if (e2.length === 0)
return false;
const n2 = cH({ portAssignment: this.state.portAssignment, regionSegments: this.state.regionSegments, regionIntersectionCaches: this.state.regionIntersectionCaches, regionCongestionCost: this.state.regionCongestionCost, ripCount: this.state.ripCount });
for (let o2 = 0;o2 < t47; o2++) {
const t48 = o2 === 0 ? e2 : sV(e2, this.state.ripCount + o2), i2 = new pH(this.topology, this.problem, { ...hH(this), ACCEPT_BEST_SOLUTION_ON_TIMEOUT: false, GREEDY_FINAL_ROUTE_ITERS: 0, MAX_ITERATIONS: rH, RIP_THRESHOLD_RAMP_ATTEMPTS: 0, STATIC_REACHABILITY_PRECHECK: false });
if (this.applySnapshotToGreedyFinalRouteSolver(i2, n2, t48), i2.solve(), i2.solved && !i2.failed)
return this.bestSolvedStateSnapshot = cH({ portAssignment: i2.state.portAssignment, regionSegments: i2.state.regionSegments, regionIntersectionCaches: i2.state.regionIntersectionCaches, regionCongestionCost: i2.state.regionCongestionCost, ripCount: i2.state.ripCount }), this.bestSolvedStateSummary = this.summarizeSolvedState(i2), this.restoreBestSolvedState(), this.stats = { ...this.stats, acceptedGreedyFinalRouteOnTimeout: true, greedyFinalRouteIter: o2, greedyFinalRouteRemainingRouteCount: e2.length, greedyFinalRouteMaxIterations: rH, neverSuccessfullyRoutedRouteCount: 0, maxRegionCost: this.bestSolvedStateSummary.maxRegionCost, totalRegionCost: this.bestSolvedStateSummary.totalRegionCost, bestMaxRegionCost: this.bestSolvedStateSummary.maxRegionCost, bestTotalRegionCost: this.bestSolvedStateSummary.totalRegionCost }, this.solved = true, this.failed = false, this.error = null, true;
}
return this.stats = { ...this.stats, greedyFinalRouteAttemptCount: t47, greedyFinalRouteRemainingRouteCount: e2.length, greedyFinalRouteMaxIterations: rH }, false;
}
onAllRoutesRouted() {
const { topology: t47, state: e2 } = this, n2 = this.RIP_THRESHOLD_RAMP_ATTEMPTS <= 0 ? 1 : Math.min(1, e2.ripCount / this.RIP_THRESHOLD_RAMP_ATTEMPTS), o2 = this.RIP_THRESHOLD_START + (this.RIP_THRESHOLD_END - this.RIP_THRESHOLD_START) * n2, i2 = [], r2 = new Float64Array(t47.regionCount);
let s2 = 0, a2 = 0;
for (let n3 = 0;n3 < t47.regionCount; n3++) {
const t48 = e2.regionIntersectionCaches[n3]?.existingRegionCost ?? 0;
r2[n3] = t48, s2 = Math.max(s2, t48), a2 += t48, t48 > o2 && i2.push(n3);
}
if (this.captureBestSolvedState({ maxRegionCost: s2, totalRegionCost: a2 }), this.stats = { ...this.stats, currentRipThreshold: o2, hotRegionCount: i2.length, maxRegionCost: s2, totalRegionCost: a2, bestMaxRegionCost: this.bestSolvedStateSummary?.maxRegionCost, bestTotalRegionCost: this.bestSolvedStateSummary?.totalRegionCost, ripCount: e2.ripCount }, i2.length === 0 || e2.ripCount >= this.RIP_THRESHOLD_RAMP_ATTEMPTS)
this.solved = true;
else {
for (let n3 = 0;n3 < t47.regionCount; n3++)
e2.regionCongestionCost[n3] += r2[n3] * this.RIP_CONGESTION_REGION_COST_FACTOR;
e2.ripCount += 1, this.resetRoutingStateForRerip(), this.stats = { ...this.stats, ripCount: e2.ripCount, maxRegionCostBeforeRip: s2, reripRegionCount: i2.length }, this.logRipEvent("hot_regions", s2, { hotRegionCount: i2.length, currentRipThreshold: o2 });
}
}
onOutOfCandidates() {
const { topology: t47, state: e2 } = this, n2 = e2.currentRouteId, o2 = this.getMaxRegionCost();
for (let n3 = 0;n3 < t47.regionCount; n3++) {
const t48 = e2.regionIntersectionCaches[n3]?.existingRegionCost ?? 0;
e2.regionCongestionCost[n3] += t48 * this.RIP_CONGESTION_REGION_COST_FACTOR;
}
e2.ripCount += 1, this.resetRoutingStateForRerip(), this.stats = { ...this.stats, ripCount: e2.ripCount, maxRegionCost: o2, maxRegionCostBeforeRip: o2, reripReason: "out_of_candidates" }, this.logRipEvent("out_of_candidates", o2, { ...n2 === undefined ? {} : { routeId: n2, connectionId: this.getRouteConnectionId(n2) } });
}
onPathFound(t47) {
const { state: e2 } = this, n2 = e2.currentRouteId;
if (n2 === undefined)
return;
this.routeSuccessCountByRouteId[n2] += 1;
const o2 = this.getSolvedPathSegments(t47);
for (const { regionId: t48, fromPortId: i2, toPortId: r2 } of o2)
e2.regionSegments[t48].push([n2, i2, r2]), e2.portAssignment[i2] = e2.currentRouteNetId, e2.portAssignment[r2] = e2.currentRouteNetId, this.appendSegmentToRegionCache(t48, i2, r2);
e2.candidateQueue.clear(), e2.currentRouteNetId = undefined, e2.currentRouteId = undefined;
}
computeG(t47, e2, n2 = Number.POSITIVE_INFINITY, o2) {
const { state: i2, topology: r2 } = this, s2 = t47.nextRegionId, a2 = i2.regionIntersectionCaches[s2];
let c2 = 0;
if (this.ADD_SEGMENT_DISTANCE_TO_G) {
let n3 = o2;
if (n3 === undefined) {
const o3 = r2.portX[t47.portId] - r2.portX[e2], i3 = r2.portY[t47.portId] - r2.portY[e2];
n3 = Math.sqrt(o3 * o3 + i3 * i3);
}
c2 = n3 * this.DISTANCE_TO_COST;
}
if (t47.g + i2.regionCongestionCost[s2] + (this.problem.portPenalty?.[e2] ?? 0) + c2 > n2 + 0.000000001)
return Number.POSITIVE_INFINITY;
const l2 = t47.portId, h2 = this.candidateFirstRegionByPortId[l2] === s2 || this.candidateSecondRegionByPortId[l2] !== s2 ? r2.portAngleForRegion1[l2] : r2.portAngleForRegion2?.[l2] ?? r2.portAngleForRegion1[l2], d2 = this.candidateFirstRegionByPortId[e2] === s2 || this.candidateSecondRegionByPortId[e2] !== s2 ? r2.portAngleForRegion1[e2] : r2.portAngleForRegion2?.[e2] ?? r2.portAngleForRegion1[e2], u2 = h2 < d2 ? h2 : d2, p2 = h2 < d2 ? d2 : h2, m2 = r2.portZ[l2], g2 = r2.portZ[e2], f2 = 1 << m2 | 1 << g2, y2 = m2 !== g2 ? 1 : 0, [_2, b2, x2] = nV(a2, i2.currentRouteNetId, u2, p2, f2, y2);
if (_2 > 0 && this.isKnownSingleLayerRegion(s2))
return Number.POSITIVE_INFINITY;
const v2 = this.computeRegionCostForRegion(s2, a2.existingSameLayerIntersections + _2, a2.existingCrossingLayerIntersections + b2, a2.existingEntryExitLayerChanges + x2, a2.existingSegmentCount + 1) - a2.existingRegionCost;
return t47.g + v2 + i2.regionCongestionCost[s2] + (this.problem.portPenalty?.[e2] ?? 0) + c2;
}
tryFinalAcceptance() {
const t47 = this.getNeverSuccessfullyRoutedRoutes();
if (this.stats = { ...this.stats, neverSuccessfullyRoutedRouteCount: t47.length }, this.ACCEPT_BEST_SOLUTION_ON_TIMEOUT && this.bestSolvedStateSnapshot && this.bestSolvedStateSummary)
return this.restoreBestSolvedState(), this.stats = { ...this.stats, acceptedBestSolutionOnTimeout: true, maxRegionCost: this.bestSolvedStateSummary.maxRegionCost, totalRegionCost: this.bestSolvedStateSummary.totalRegionCost, bestMaxRegionCost: this.bestSolvedStateSummary.maxRegionCost, bestTotalRegionCost: this.bestSolvedStateSummary.totalRegionCost }, this.solved = true, this.failed = false, void (this.error = null);
this.ACCEPT_BEST_SOLUTION_ON_TIMEOUT && this.tryGreedyFinalRouteAcceptance() || this.logNeverSuccessfullyRoutedRoutes();
}
computeH(t47) {
const e2 = this.problemSetup.portHCostToEndOfRoute;
if (e2)
return e2[t47 * this.problem.routeCount + this.state.currentRouteId];
const n2 = this.getRouteEndPortId(this.state.currentRouteId), o2 = this.topology.portX[t47] - this.topology.portX[n2], i2 = this.topology.portY[t47] - this.topology.portY[n2];
return Math.sqrt(o2 * o2 + i2 * i2) * this.DISTANCE_TO_COST;
}
visualize() {
return iH(this);
}
getOutput() {
return JW(this);
}
};
var pH = class extends uH {
computeG(t47, e2) {
return t47.g;
}
};
var mH = class {
constructor(t47, e2) {
this.regionCount = t47, this.compactHopIndex = e2, e2 && (this.hopStateGeneration = new Uint32Array(e2.hopCapacity), this.hopIndexOrClosed = new Int32Array(e2.hopCapacity));
}
items = [];
indexByHopId = new Map;
closedHopIds = new Set;
hopStateGeneration;
hopIndexOrClosed;
currentHopStateGeneration = 1;
get length() {
return this.items.length;
}
toArray() {
return [...this.items];
}
clear() {
this.items.length = 0, this.indexByHopId.clear(), this.closedHopIds.clear(), this.hopStateGeneration && (this.currentHopStateGeneration === 4294967295 ? (this.hopStateGeneration.fill(0), this.currentHopStateGeneration = 1) : this.currentHopStateGeneration += 1);
}
isClosedHop(t47, e2) {
return this.isHopClosed(this.getHopIdFromValues(t47, e2));
}
queue(t47) {
const e2 = this.getHopId(t47);
if (this.isHopClosed(e2))
return;
const n2 = this.getQueuedHopIndex(e2);
if (n2 !== undefined) {
const e3 = this.items[n2];
if (t47.g >= e3.g)
return;
return this.items[n2] = t47, void (t47.f <= e3.f ? this.siftUp(n2) : this.siftDown(n2));
}
const o2 = this.items.length;
this.items.push(t47), this.siftUp(o2);
}
dequeue() {
const t47 = this.items[0];
if (!t47)
return;
const e2 = this.getHopId(t47);
this.closeHop(e2);
const n2 = this.items.pop();
return this.items.length > 0 && (this.items[0] = n2, this.siftDown(0)), t47;
}
getHopId(t47) {
return this.getHopIdFromValues(t47.portId, t47.nextRegionId);
}
getHopIdFromValues(t47, e2) {
const n2 = this.compactHopIndex;
if (!n2)
return t47 * this.regionCount + e2;
const o2 = t47 * n2.hopSlotStride;
if (n2.firstRegionByPortId[t47] === e2)
return o2;
if (n2.secondRegionByPortId[t47] === e2)
return o2 + 1;
const i2 = n2.incidentPortRegion[t47];
for (let t48 = 2;t48 < (i2?.length ?? 0); t48++)
if (i2[t48] === e2)
return o2 + t48;
return -(t47 * this.regionCount + e2) - 1;
}
getQueuedHopIndex(t47) {
if (t47 >= 0 && this.hopStateGeneration?.[t47] === this.currentHopStateGeneration) {
const e2 = this.hopIndexOrClosed[t47];
return e2 >= 0 ? e2 : undefined;
}
return this.indexByHopId.get(t47);
}
isHopClosed(t47) {
return t47 >= 0 && this.hopStateGeneration?.[t47] === this.currentHopStateGeneration ? this.hopIndexOrClosed[t47] === -1 : this.closedHopIds.has(t47);
}
setQueuedHopIndex(t47, e2) {
if (t47 >= 0 && this.hopStateGeneration)
return this.hopStateGeneration[t47] = this.currentHopStateGeneration, void (this.hopIndexOrClosed[t47] = e2);
this.indexByHopId.set(t47, e2);
}
closeHop(t47) {
if (t47 >= 0 && this.hopStateGeneration)
return this.hopStateGeneration[t47] = this.currentHopStateGeneration, void (this.hopIndexOrClosed[t47] = -1);
this.indexByHopId.delete(t47), this.closedHopIds.add(t47);
}
siftUp(t47) {
const e2 = this.items[t47];
let n2 = t47;
for (;n2 > 0; ) {
const t48 = n2 - 1 >> 1, o2 = this.items[t48];
if (o2.f <= e2.f)
break;
this.items[n2] = o2, this.setQueuedHopIndex(this.getHopId(o2), n2), n2 = t48;
}
this.items[n2] = e2, this.setQueuedHopIndex(this.getHopId(e2), n2);
}
siftDown(t47) {
const e2 = this.items[t47];
let n2 = t47;
for (;; ) {
const t48 = 2 * n2 + 1;
if (t48 >= this.items.length)
break;
const o2 = t48 + 1, i2 = o2 < this.items.length && this.items[o2].f < this.items[t48].f ? o2 : t48, r2 = this.items[i2];
if (e2.f <= r2.f)
break;
this.items[n2] = r2, this.setQueuedHopIndex(this.getHopId(r2), n2), n2 = i2;
}
this.items[n2] = e2, this.setQueuedHopIndex(this.getHopId(e2), n2);
}
};
var gH = class extends uH {
constructor(t47, e2, n2) {
super(t47, e2, n2), this.ADD_SEGMENT_DISTANCE_TO_G = true;
}
_setup() {
super._setup(), this.state.candidateQueue = new mH(this.topology.regionCount, { hopCapacity: this.candidateHopCapacity, hopSlotStride: this.candidateHopSlotStride, firstRegionByPortId: this.candidateFirstRegionByPortId, secondRegionByPortId: this.candidateSecondRegionByPortId, incidentPortRegion: this.topology.incidentPortRegion });
}
onPathFound(t47) {
const e2 = this.state.goalPortId;
if (t47.portId === e2)
return void super.onPathFound(t47);
const n2 = this.computeG(t47, e2);
if (!Number.isFinite(n2))
return;
const o2 = this.getHopId(e2, t47.nextRegionId);
n2 >= this.getCandidateBestCost(o2) || (this.setCandidateBestCost(o2, n2), this.state.candidateQueue.queue({ prevRegionId: t47.nextRegionId, nextRegionId: t47.nextRegionId, portId: e2, g: n2, h: 0, f: n2, prevCandidate: t47 }));
}
};
var fH = new Set;
var yH = class extends gH {
partialRipRoutePlans = new Map;
outsideInRouteSearch;
oneSidedFallbackRouteId;
partialRipWindowDistance;
partialRipCount = 0;
partiallyRippedRouteCount = 0;
partiallyRippedSegmentCount = 0;
retainedPartialRipSegmentCount = 0;
outsideInRouteCount = 0;
outsideInCompletedRouteCount = 0;
outsideInFallbackRouteCount = 0;
outsideInForwardExpansionCount = 0;
outsideInReverseExpansionCount = 0;
outsideInDistancePruneCount = 0;
completedRoundSummaries = [];
firstCompletedRoundSummary;
partialRipQualityBaselineSummary;
bestSolvedRoundSummary;
partialRipTargetReached = false;
useComplexityAwareSelection = false;
constructor(t47, e2, n2) {
super(t47, e2, n2), n2?.PARTIAL_RIP_ENABLED === undefined && (this.PARTIAL_RIP_ENABLED = true), n2?.OUTSIDE_IN_ROUTING === undefined && (this.OUTSIDE_IN_ROUTING = true), this.PARTIAL_RIP_ENABLED && n2?.PARTIAL_RIP_MAX_ATTEMPTS === undefined && (this.PARTIAL_RIP_MAX_ATTEMPTS = 10), (e2.routeCount < Math.max(0, this.PARTIAL_RIP_MIN_ROUTE_COUNT) || e2.routeCount > Math.max(0, this.PARTIAL_RIP_MAX_ROUTE_COUNT)) && (this.PARTIAL_RIP_ENABLED = false, this.OUTSIDE_IN_ROUTING = false), this.useComplexityAwareSelection = e2.routeCount >= Math.max(0, this.PARTIAL_RIP_COMPLEXITY_SELECTION_MIN_ROUTE_COUNT);
}
getRouteStartPortId(t47) {
return this.PARTIAL_RIP_ENABLED ? this.partialRipRoutePlans.get(t47)?.activeStartPortId ?? super.getRouteStartPortId(t47) : super.getRouteStartPortId(t47);
}
getRouteEndPortId(t47) {
return this.PARTIAL_RIP_ENABLED ? this.partialRipRoutePlans.get(t47)?.activeEndPortId ?? super.getRouteEndPortId(t47) : super.getRouteEndPortId(t47);
}
getStartingNextRegionId(t47, e2) {
if (!this.PARTIAL_RIP_ENABLED)
return super.getStartingNextRegionId(t47, e2);
const n2 = this.partialRipRoutePlans.get(t47);
return n2 && n2.activeStartPortId === e2 ? n2.forcedStartRegionId : super.getStartingNextRegionId(t47, e2);
}
getEndingNextRegionId(t47, e2) {
const n2 = this.partialRipRoutePlans.get(t47);
return n2 && n2.activeEndPortId === e2 ? n2.forcedEndRegionId : super.getStartingNextRegionId(t47, e2);
}
computeH(t47) {
if (!this.PARTIAL_RIP_ENABLED)
return super.computeH(t47);
const e2 = this.state.currentRouteId;
if (e2 === undefined || !this.partialRipRoutePlans.has(e2))
return super.computeH(t47);
const n2 = this.getRouteEndPortId(e2), o2 = this.topology.portX[t47] - this.topology.portX[n2], i2 = this.topology.portY[t47] - this.topology.portY[n2];
return Math.sqrt(o2 * o2 + i2 * i2) * this.DISTANCE_TO_COST;
}
onPathFound(t47) {
if (!this.PARTIAL_RIP_ENABLED && !this.OUTSIDE_IN_ROUTING)
return void super.onPathFound(t47);
const e2 = this.state.currentRouteId, n2 = e2 !== undefined && this.outsideInRouteSearch?.routeId === e2;
super.onPathFound(t47), e2 !== undefined && this.state.currentRouteId === undefined && (this.partialRipRoutePlans.delete(e2), n2 && (this.outsideInCompletedRouteCount += 1), this.oneSidedFallbackRouteId === e2 && (this.oneSidedFallbackRouteId = undefined)), this.outsideInRouteSearch = undefined, this.publishOutsideInStats();
}
resetRoutingStateForRerip() {
this.PARTIAL_RIP_ENABLED || this.OUTSIDE_IN_ROUTING ? (this.partialRipRoutePlans.clear(), this.outsideInRouteSearch = undefined, this.oneSidedFallbackRouteId = undefined, super.resetRoutingStateForRerip()) : super.resetRoutingStateForRerip();
}
clearPartialRipPlans(t47) {
for (const e2 of t47)
this.partialRipRoutePlans.delete(e2);
}
getRouteIdsPreferredForPreservation() {
return fH;
}
getCommittedRouteSegments(t47) {
const e2 = [];
for (let n3 = 0;n3 < this.state.regionSegments.length; n3++)
for (const [o3, i3, r3] of this.state.regionSegments[n3] ?? [])
o3 === t47 && e2.push({ segmentIndex: e2.length, regionId: n3, fromPortId: i3, toPortId: r3 });
if (e2.length === 0)
return;
const n2 = new Map;
for (const t48 of e2)
for (const e3 of [t48.fromPortId, t48.toPortId]) {
const o3 = n2.get(e3) ?? [];
o3.push(t48.segmentIndex), n2.set(e3, o3);
}
const o2 = this.problem.routeEndPort[t47], i2 = [], r2 = new Set, s2 = new Set([this.problem.routeStartPort[t47]]), a2 = (t48) => {
if (t48 === o2)
return true;
for (const o3 of n2.get(t48) ?? []) {
if (r2.has(o3))
continue;
const n3 = e2[o3], c2 = n3.fromPortId === t48 ? n3.toPortId : n3.fromPortId;
if (!s2.has(c2)) {
if (r2.add(o3), s2.add(c2), i2.push({ regionId: n3.regionId, fromPortId: t48, toPortId: c2 }), a2(c2))
return true;
i2.pop(), s2.delete(c2), r2.delete(o3);
}
}
return false;
};
return a2(this.problem.routeStartPort[t47]) && r2.size === e2.length ? i2 : undefined;
}
getSegmentDistance(t47) {
const e2 = this.topology.portX[t47.fromPortId] - this.topology.portX[t47.toPortId], n2 = this.topology.portY[t47.fromPortId] - this.topology.portY[t47.toPortId];
return Math.sqrt(e2 * e2 + n2 * n2);
}
getPartialRipWindow(t47, e2, n2) {
let o2, i2 = Number.NEGATIVE_INFINITY;
for (let r3 = 0;r3 < t47.length; r3++) {
const s3 = t47[r3];
if (!e2.has(s3.regionId))
continue;
const a3 = n2[s3.regionId] ?? 0;
a3 > i2 && (i2 = a3, o2 = r3);
}
if (o2 === undefined)
return;
const r2 = Math.max(0, this.partialRipWindowDistance ?? this.PARTIAL_RIP_MAX_DISTANCE);
let s2 = o2, a2 = o2, c2 = this.getSegmentDistance(t47[o2]) / 2, l2 = c2;
for (;s2 > 0; ) {
const e3 = this.getSegmentDistance(t47[s2 - 1]);
if (c2 + e3 > r2)
break;
s2 -= 1, c2 += e3;
}
for (;a2 + 1 < t47.length; ) {
const e3 = this.getSegmentDistance(t47[a2 + 1]);
if (l2 + e3 > r2)
break;
a2 += 1, l2 += e3;
}
return { startIndex: s2, endIndex: a2 };
}
appendRetainedSegment(t47, e2, n2) {
t47[n2.regionId].push([e2, n2.fromPortId, n2.toPortId]);
}
preparePartialRip(t47, e2) {
if (!this.PARTIAL_RIP_ENABLED || t47.length === 0)
return false;
const n2 = new Set(t47);
if (this.partialRipWindowDistance === undefined) {
let n3 = 0;
for (const o4 of t47)
n3 = Math.max(n3, e2[o4] ?? 0);
const o3 = Math.max(0, this.PARTIAL_RIP_MAX_DISTANCE), i3 = Math.max(o3, this.PARTIAL_RIP_QUALITY_MAX_DISTANCE ?? 2 * o3);
this.partialRipWindowDistance = n3 <= 1.5 * this.RIP_THRESHOLD_END ? i3 : o3;
}
const o2 = new Set;
for (const e3 of t47)
for (const [t48] of this.state.regionSegments[e3] ?? [])
o2.add(t48);
if (o2.size === 0)
return false;
const i2 = this.getRouteIdsPreferredForPreservation(), r2 = [...o2].some((t48) => !i2.has(t48)), s2 = Array.from({ length: this.topology.regionCount }, () => []), a2 = new Map;
let c2 = 0, l2 = 0;
for (let t48 = 0;t48 < this.problem.routeCount; t48++) {
const h2 = this.getCommittedRouteSegments(t48);
if (!h2)
return false;
if (!o2.has(t48) || r2 && i2.has(t48)) {
for (const e3 of h2)
this.appendRetainedSegment(s2, t48, e3), l2 += 1;
continue;
}
const d2 = this.getPartialRipWindow(h2, n2, e2);
if (!d2)
return false;
for (let e3 = 0;e3 < h2.length; e3++) {
const n3 = h2[e3];
e3 >= d2.startIndex && e3 <= d2.endIndex ? c2 += 1 : (this.appendRetainedSegment(s2, t48, n3), l2 += 1);
}
const u2 = h2[d2.startIndex], p2 = h2[d2.endIndex];
a2.set(t48, { routeId: t48, activeStartPortId: u2.fromPortId, activeEndPortId: p2.toPortId, forcedStartRegionId: u2.regionId, forcedEndRegionId: p2.regionId, rippedSegmentCount: d2.endIndex - d2.startIndex + 1, retainedSegmentCount: h2.length - (d2.endIndex - d2.startIndex + 1) });
}
return a2.size !== 0 && c2 !== 0 && (this.partialRipRoutePlans = a2, this.rebuildRetainedRoutingState(s2, [...a2.keys()]), this.partialRipCount += 1, this.partiallyRippedRouteCount += a2.size, this.partiallyRippedSegmentCount += c2, this.retainedPartialRipSegmentCount += l2, this.publishPartialRipStats(), true);
}
rebuildRetainedRoutingState(t47, e2) {
this.state.portAssignment.fill(-1), this.state.regionSegments = Array.from({ length: this.topology.regionCount }, () => []), this.state.regionIntersectionCaches = Array.from({ length: this.topology.regionCount }, () => sH()), this.state.currentRouteId = undefined, this.state.currentRouteNetId = undefined, this.state.unroutedRoutes = e2, this.state.candidateQueue.clear(), this.resetCandidateBestCosts(), this.state.goalPortId = -1, this.outsideInRouteSearch = undefined, this.oneSidedFallbackRouteId = undefined;
for (let e3 = 0;e3 < t47.length; e3++)
for (const [n2, o2, i2] of t47[e3] ?? []) {
const t48 = this.problem.routeNet[n2];
this.state.currentRouteNetId = t48;
for (const e4 of [o2, i2]) {
const n3 = this.state.portAssignment[e4];
if (n3 !== -1 && n3 !== t48)
throw new Error(`OutsideInPartialRipTinyHyperGraphSolver: retained port ${e4} belongs to multiple nets`);
this.state.portAssignment[e4] = t48;
}
this.state.regionSegments[e3].push([n2, o2, i2]), this.appendSegmentToRegionCache(e3, o2, i2);
}
this.state.currentRouteNetId = undefined;
}
publishPartialRipStats() {
this.stats = { ...this.stats, partialRipCount: this.partialRipCount, partiallyRippedRouteCount: this.partiallyRippedRouteCount, partiallyRippedSegmentCount: this.partiallyRippedSegmentCount, retainedPartialRipSegmentCount: this.retainedPartialRipSegmentCount, partialRipMaxDistance: this.partialRipWindowDistance ?? this.PARTIAL_RIP_MAX_DISTANCE, partialRipBaseMaxDistance: this.PARTIAL_RIP_MAX_DISTANCE, partialRipQualityMaxDistance: this.PARTIAL_RIP_QUALITY_MAX_DISTANCE ?? 2 * this.PARTIAL_RIP_MAX_DISTANCE, partialRipMaxAttempts: this.PARTIAL_RIP_MAX_ATTEMPTS };
}
publishOutsideInStats() {
this.stats = { ...this.stats, outsideInRouteCount: this.outsideInRouteCount, outsideInCompletedRouteCount: this.outsideInCompletedRouteCount, outsideInFallbackRouteCount: this.outsideInFallbackRouteCount, outsideInForwardExpansionCount: this.outsideInForwardExpansionCount, outsideInReverseExpansionCount: this.outsideInReverseExpansionCount, outsideInDistancePruneCount: this.outsideInDistancePruneCount, outsideInMaxDistance: this.OUTSIDE_IN_MAX_DISTANCE };
}
createOutsideInFrontier(t47, e2, n2) {
const o2 = new rV([], (t48, e3) => t48.f === e3.f ? t48.g - e3.g : t48.f - e3.f), i2 = this.topology.portX[t47] - this.topology.portX[n2], r2 = this.topology.portY[t47] - this.topology.portY[n2], s2 = Math.sqrt(i2 * i2 + r2 * r2) * this.DISTANCE_TO_COST, a2 = { portId: t47, nextRegionId: e2, f: s2, g: 0, h: s2, travelDistance: 0 };
return o2.queue(a2), { queue: o2, bestCostByHopId: new Map([[this.getHopId(t47, e2), 0]]), settledByPortId: new Map, settledByRegionId: new Map, targetPortId: n2 };
}
startOutsideInRouteSearch(t47) {
const e2 = this.getRouteStartPortId(t47), n2 = this.getRouteEndPortId(t47), o2 = this.getStartingNextRegionId(t47, e2), i2 = this.getEndingNextRegionId(t47, n2);
return o2 !== undefined && i2 !== undefined && (this.state.goalPortId = n2, this.state.candidateQueue.clear(), this.resetCandidateBestCosts(), this.outsideInRouteSearch = { routeId: t47, forward: this.createOutsideInFrontier(e2, o2, n2), reverse: this.createOutsideInFrontier(n2, i2, e2), expandForwardNext: true, distanceLimitHit: false, bestJoinedCost: Number.POSITIVE_INFINITY }, this.outsideInRouteCount += 1, this.publishOutsideInStats(), true);
}
dequeueFreshCandidate(t47) {
for (;t47.queue.length > 0; ) {
const e2 = t47.queue.dequeue(), n2 = this.getHopId(e2.portId, e2.nextRegionId);
if (e2.g <= (t47.bestCostByHopId.get(n2) ?? 1 / 0))
return e2;
}
}
recordSettledCandidate(t47, e2) {
const n2 = t47.settledByPortId.get(e2.portId);
(!n2 || e2.g < n2.g) && t47.settledByPortId.set(e2.portId, e2);
const o2 = t47.settledByRegionId.get(e2.nextRegionId) ?? [];
o2.push(e2), o2.sort((t48, e3) => t48.g - e3.g), o2.length > 16 && (o2.length = 16), t47.settledByRegionId.set(e2.nextRegionId, o2);
}
getCandidatePath(t47) {
const e2 = [];
let n2 = t47;
for (;n2; )
e2.push(n2), n2 = n2.prevCandidate;
return e2.reverse(), e2;
}
buildJoinedCandidate(t47, e2) {
const n2 = this.getCandidatePath(t47), o2 = this.getCandidatePath(e2), i2 = n2.map(({ portId: t48 }) => t48), r2 = n2.slice(0, -1).map(({ nextRegionId: t48 }) => t48);
if (t47.portId !== e2.portId) {
if (t47.nextRegionId !== e2.nextRegionId)
return;
const n3 = this.topology.portX[t47.portId] - this.topology.portX[e2.portId], o3 = this.topology.portY[t47.portId] - this.topology.portY[e2.portId], s3 = Math.sqrt(n3 * n3 + o3 * o3);
if (t47.travelDistance + e2.travelDistance + s3 > 2 * this.OUTSIDE_IN_MAX_DISTANCE)
return;
const a3 = this.computeG(t47, e2.portId);
if (!Number.isFinite(a3))
return;
r2.push(t47.nextRegionId), i2.push(e2.portId);
}
for (let t48 = o2.length - 2;t48 >= 0; t48--) {
const e3 = o2[t48];
r2.push(e3.nextRegionId), i2.push(e3.portId);
}
if (new Set(i2).size !== i2.length || r2.length + 1 !== i2.length)
return;
let s2 = { portId: i2[0], nextRegionId: r2[0], f: 0, g: 0, h: 0 };
for (let t48 = 1;t48 < i2.length; t48++)
s2 = { portId: i2[t48], prevRegionId: r2[t48 - 1], nextRegionId: r2[t48] ?? r2[t48 - 1], prevCandidate: s2, f: 0, g: 0, h: 0 };
const a2 = t47.portId === e2.portId ? 0 : this.computeG(t47, e2.portId) - t47.g;
return { candidate: s2, cost: t47.g + e2.g + a2 };
}
considerOutsideInJoins(t47, e2) {
const n2 = this.outsideInRouteSearch, o2 = e2 ? n2.reverse : n2.forward, i2 = (t48) => {
!t48 || t48.cost >= n2.bestJoinedCost || (n2.bestJoinedCandidate = t48.candidate, n2.bestJoinedCost = t48.cost, n2.remainingPostMeetingExpansions = 24);
}, r2 = o2.settledByPortId.get(t47.portId);
r2 && i2(e2 ? this.buildJoinedCandidate(t47, r2) : this.buildJoinedCandidate(r2, t47));
for (const n3 of o2.settledByRegionId.get(t47.nextRegionId) ?? [])
i2(e2 ? this.buildJoinedCandidate(t47, n3) : this.buildJoinedCandidate(n3, t47));
}
commitBestOutsideInJoin() {
const t47 = this.outsideInRouteSearch?.bestJoinedCandidate;
return !!t47 && (this.onPathFound(t47), true);
}
expandOutsideInFrontier(t47) {
const e2 = this.outsideInRouteSearch, n2 = t47 ? e2.forward : e2.reverse, o2 = this.dequeueFreshCandidate(n2);
if (!o2)
return false;
if (t47 ? this.outsideInForwardExpansionCount += 1 : this.outsideInReverseExpansionCount += 1, this.isRegionReservedForDifferentNet(o2.nextRegionId))
return true;
this.recordSettledCandidate(n2, o2), this.considerOutsideInJoins(o2, t47);
for (const t48 of this.topology.regionIncidentPorts[o2.nextRegionId] ?? []) {
if (t48 === o2.portId)
continue;
if (this.isPortReservedForDifferentNet(t48))
continue;
const i2 = this.state.portAssignment[t48];
if (i2 !== -1 && i2 !== this.state.currentRouteNetId)
continue;
if (t48 !== n2.targetPortId && this.problem.portSectionMask[t48] === 0)
continue;
const r2 = this.topology.portX[o2.portId] - this.topology.portX[t48], s2 = this.topology.portY[o2.portId] - this.topology.portY[t48], a2 = Math.sqrt(r2 * r2 + s2 * s2), c2 = o2.travelDistance + a2;
if (c2 > this.OUTSIDE_IN_MAX_DISTANCE) {
e2.distanceLimitHit = true, this.outsideInDistancePruneCount += 1;
continue;
}
const l2 = this.topology.incidentPortRegion[t48]?.[0] === o2.nextRegionId ? this.topology.incidentPortRegion[t48]?.[1] : this.topology.incidentPortRegion[t48]?.[0];
if (l2 === undefined || this.isRegionReservedForDifferentNet(l2))
continue;
const h2 = this.getHopId(t48, l2), d2 = n2.bestCostByHopId.get(h2) ?? 1 / 0;
if (o2.g >= d2)
continue;
const u2 = this.computeG(o2, t48, d2, a2);
if (!Number.isFinite(u2) || u2 >= d2)
continue;
n2.bestCostByHopId.set(h2, u2);
const p2 = this.topology.portX[t48] - this.topology.portX[n2.targetPortId], m2 = this.topology.portY[t48] - this.topology.portY[n2.targetPortId], g2 = Math.sqrt(p2 * p2 + m2 * m2) * this.DISTANCE_TO_COST;
n2.queue.queue({ portId: t48, prevRegionId: o2.nextRegionId, nextRegionId: l2, prevCandidate: o2, f: u2 + g2, g: u2, h: g2, travelDistance: c2 });
}
return true;
}
fallBackToOneSidedRouteSearch() {
const t47 = this.state.currentRouteId;
t47 !== undefined && (this.outsideInRouteSearch = undefined, this.outsideInFallbackRouteCount += 1, this.oneSidedFallbackRouteId = t47, this.state.currentRouteId = undefined, this.state.currentRouteNetId = undefined, this.state.goalPortId = -1, this.state.candidateQueue.clear(), this.resetCandidateBestCosts(), this.state.unroutedRoutes.unshift(t47), this.publishOutsideInStats());
}
_step() {
if (!this.OUTSIDE_IN_ROUTING)
return void super._step();
const t47 = this.state.currentRouteId ?? this.state.unroutedRoutes[0];
if (t47 !== undefined && !this.partialRipRoutePlans.has(t47))
return void super._step();
if (this.oneSidedFallbackRouteId !== undefined)
return void super._step();
if (this.state.currentRouteId === undefined) {
if (this.state.unroutedRoutes.length === 0)
return void this.onAllRoutesRouted();
const t48 = this.state.unroutedRoutes.shift();
if (this.state.currentRouteId = t48, this.state.currentRouteNetId = this.problem.routeNet[t48], this.routeAttemptCountByRouteId[t48] += 1, !this.startOutsideInRouteSearch(t48))
return this.failed = true, void (this.error = `Route ${t48} has an endpoint without an incident region`);
}
const e2 = this.outsideInRouteSearch;
if (!e2)
return;
let n2 = this.expandOutsideInFrontier(e2.expandForwardNext);
if (this.state.currentRouteId !== undefined && (n2 || (n2 = this.expandOutsideInFrontier(!e2.expandForwardNext), this.state.currentRouteId !== undefined)))
if (e2.expandForwardNext = !e2.expandForwardNext, e2.bestJoinedCandidate && (e2.remainingPostMeetingExpansions = (e2.remainingPostMeetingExpansions ?? 1) - 1, (e2.remainingPostMeetingExpansions ?? 0) <= 0))
this.commitBestOutsideInJoin();
else {
if (!n2 && e2.forward.queue.length === 0 && e2.reverse.queue.length === 0) {
if (this.commitBestOutsideInJoin())
return;
this.outsideInRouteSearch = undefined, e2.distanceLimitHit ? this.fallBackToOneSidedRouteSearch() : this.onOutOfCandidates();
}
this.publishOutsideInStats();
}
}
shouldReplaceBestSolvedState(t47) {
const e2 = this.bestSolvedRoundSummary;
if (!e2)
return true;
if (!this.useComplexityAwareSelection)
return this.compareRegionCostSummaries(t47, e2) < 0;
const n2 = this.partialRipQualityBaselineSummary;
if (!n2)
return this.compareRegionCostSummaries(t47, e2) < 0;
const o2 = this.firstCompletedRoundSummary ?? n2, i2 = o2.maxRegionCost * (1 + Math.max(0, this.PARTIAL_RIP_MAX_REGION_COST_GROWTH_RATIO)), r2 = o2.totalRegionCost * (1 + Math.max(0, this.PARTIAL_RIP_MAX_TOTAL_COST_GROWTH_RATIO)), s2 = t47.maxRegionCost <= i2 && t47.totalRegionCost <= r2;
return s2 !== (e2.maxRegionCost <= i2 && e2.totalRegionCost <= r2) ? s2 : s2 && t47.segmentCount !== e2.segmentCount ? t47.segmentCount < e2.segmentCount : this.compareRegionCostSummaries(t47, e2) < 0;
}
onAllRoutesRouted() {
if (!this.PARTIAL_RIP_ENABLED)
return void super.onAllRoutesRouted();
const { state: t47, topology: e2 } = this, n2 = Math.min(this.RIP_THRESHOLD_RAMP_ATTEMPTS, this.PARTIAL_RIP_MAX_ATTEMPTS), o2 = Math.max(0, this.RIP_THRESHOLD_RAMP_ATTEMPTS), i2 = o2 <= 0 ? 1 : Math.min(1, t47.ripCount / o2), r2 = this.RIP_THRESHOLD_START + (this.RIP_THRESHOLD_END - this.RIP_THRESHOLD_START) * i2, s2 = new Float64Array(e2.regionCount), a2 = [];
let c2 = 0, l2 = 0, h2 = 0, d2 = 0, u2 = 0;
for (let n3 = 0;n3 < e2.regionCount; n3++) {
const e3 = t47.regionIntersectionCaches[n3]?.existingRegionCost ?? 0;
s2[n3] = e3, c2 = Math.max(c2, e3), l2 += e3;
const o3 = t47.regionSegments[n3]?.length ?? 0;
h2 += o3, d2 = Math.max(d2, o3), u2 += o3 * o3, e3 > r2 && a2.push(n3);
}
const p2 = { maxRegionCost: c2, totalRegionCost: l2 }, m2 = { ...p2, ripCount: t47.ripCount, segmentCount: h2, maxRegionSegmentCount: d2, squaredRegionSegmentCount: u2 };
this.completedRoundSummaries.push(m2), this.firstCompletedRoundSummary ??= m2, this.partialRipQualityBaselineSummary === undefined && t47.ripCount >= Math.max(0, this.PARTIAL_RIP_WARMUP_FULL_RIP_ATTEMPTS) && (this.partialRipQualityBaselineSummary = m2);
this.shouldReplaceBestSolvedState(m2) && (this.replaceBestSolvedState(p2), this.bestSolvedRoundSummary = m2);
const g2 = this.firstCompletedRoundSummary, f2 = this.partialRipQualityBaselineSummary ?? g2, y2 = Math.max(0, this.PARTIAL_RIP_TARGET_MAX_COST_IMPROVEMENT_RATIO), _2 = Math.max(0, this.PARTIAL_RIP_MAX_TOTAL_COST_GROWTH_RATIO), b2 = f2.maxRegionCost * (1 - y2), x2 = f2.totalRegionCost * (1 + _2), v2 = this.useComplexityAwareSelection && t47.ripCount > f2.ripCount && y2 > 0 && c2 <= b2 && l2 <= x2 && h2 <= f2.segmentCount;
if (v2 && (this.partialRipTargetReached = true), this.stats = { ...this.stats, currentRipThreshold: r2, hotRegionCount: a2.length, maxRegionCost: c2, totalRegionCost: l2, bestMaxRegionCost: this.bestSolvedStateSummary?.maxRegionCost, bestTotalRegionCost: this.bestSolvedStateSummary?.totalRegionCost, ripCount: t47.ripCount, completedRoundSummaries: this.completedRoundSummaries.map((t48) => ({ ...t48 })), firstMaxRegionCost: g2.maxRegionCost, firstTotalRegionCost: g2.totalRegionCost, firstSegmentCount: g2.segmentCount, firstMaxRegionSegmentCount: g2.maxRegionSegmentCount, firstSquaredRegionSegmentCount: g2.squaredRegionSegmentCount, partialRipQualityBaselineRipCount: f2.ripCount, partialRipQualityBaselineMaxRegionCost: f2.maxRegionCost, partialRipQualityBaselineTotalRegionCost: f2.totalRegionCost, partialRipQualityBaselineSegmentCount: f2.segmentCount, partialRipQualityBaselineMaxRegionSegmentCount: f2.maxRegionSegmentCount, partialRipQualityBaselineSquaredRegionSegmentCount: f2.squaredRegionSegmentCount, bestSolvedSegmentCount: this.bestSolvedRoundSummary?.segmentCount, bestSolvedMaxRegionSegmentCount: this.bestSolvedRoundSummary?.maxRegionSegmentCount, bestSolvedSquaredRegionSegmentCount: this.bestSolvedRoundSummary?.squaredRegionSegmentCount, partialRipTargetMaxRegionCost: b2, partialRipMaxTargetTotalRegionCost: x2, partialRipComplexityAwareSelection: this.useComplexityAwareSelection, partialRipComplexitySelectionMinRouteCount: this.PARTIAL_RIP_COMPLEXITY_SELECTION_MIN_ROUTE_COUNT, partialRipMaxRegionCostGrowthRatio: this.PARTIAL_RIP_MAX_REGION_COST_GROWTH_RATIO, partialRipTargetReached: this.partialRipTargetReached }, this.publishPartialRipStats(), a2.length === 0 || v2 || t47.ripCount >= n2)
return this.restoreBestSolvedState(), void (this.solved = true);
for (let n3 = 0;n3 < e2.regionCount; n3++)
t47.regionCongestionCost[n3] += s2[n3] * this.RIP_CONGESTION_REGION_COST_FACTOR;
const I2 = t47.ripCount < Math.max(0, this.PARTIAL_RIP_WARMUP_FULL_RIP_ATTEMPTS);
t47.ripCount += 1;
const S2 = !I2 && this.preparePartialRip(a2, s2);
S2 || this.resetRoutingStateForRerip();
const C2 = I2 ? "warmup_full" : S2 ? "partial" : "full_fallback";
this.stats = { ...this.stats, ripCount: t47.ripCount, maxRegionCostBeforeRip: c2, reripRegionCount: a2.length, reripMode: C2, partialRipWarmupFullRipAttempts: this.PARTIAL_RIP_WARMUP_FULL_RIP_ATTEMPTS }, this.logRipEvent("hot_regions", c2, { hotRegionCount: a2.length, currentRipThreshold: r2, reripMode: C2, partialRouteCount: S2 ? this.partialRipRoutePlans.size : 0 });
}
};
var _H = (t47) => {
const e2 = typeof t47.d?.netId == "number" ? t47.d.netId : typeof t47.d?.NetId == "number" ? t47.d.NetId : undefined;
return Number.isFinite(e2) ? e2 : undefined;
};
var bH = (t47) => {
const e2 = new Set;
for (const n3 of t47.connections ?? [])
e2.add(n3.startRegionId), e2.add(n3.endRegionId);
const n2 = new Set(t47.regions.filter((t48) => ((t49) => {
if (t49.d?._containsObstacle !== true)
return false;
const e3 = _H(t49);
return e3 === undefined || e3 === -1;
})(t48) && !e2.has(t48.regionId)).map((t48) => t48.regionId));
if (n2.size === 0)
return t47;
const o2 = t47.ports.filter((t48) => !n2.has(t48.region1Id) && !n2.has(t48.region2Id)), i2 = (t47.connections ?? []).find((t48) => n2.has(t48.startRegionId) || n2.has(t48.endRegionId));
if (i2)
throw new Error(`Connection "${i2.connectionId}" references full-obstacle region`);
return { ...t47, regions: t47.regions.filter((t48) => !n2.has(t48.regionId)), ports: o2 };
};
var xH = (t47) => {
const e2 = t47.d?.bounds;
if (e2)
return e2;
const n2 = t47.d?.center, o2 = t47.d?.width, i2 = t47.d?.height;
return n2 && typeof n2.x == "number" && typeof n2.y == "number" && typeof o2 == "number" && typeof i2 == "number" ? { minX: n2.x - o2 / 2, maxX: n2.x + o2 / 2, minY: n2.y - i2 / 2, maxY: n2.y + i2 / 2 } : { minX: 0, maxX: 0, minY: 0, maxY: 0 };
};
var vH = (t47) => Number(t47.d?.x ?? 0);
var IH = (t47) => Number(t47.d?.y ?? 0);
var SH = (t47, e2) => {
if (!e2)
return 0;
const n2 = xH(e2), o2 = vH(t47), i2 = IH(t47), r2 = n2.minX <= o2 && o2 <= n2.maxX, s2 = n2.minY <= i2 && i2 <= n2.maxY;
if (s2 && o2 >= n2.maxX) {
const t48 = Math.max(n2.maxY - n2.minY, 0.000000001), e3 = (i2 - n2.minY) / t48;
return Math.round(9000 * e3);
}
if (r2 && i2 >= n2.maxY) {
const t48 = Math.max(n2.maxX - n2.minX, 0.000000001), e3 = (n2.maxX - o2) / t48;
return 9000 + Math.round(9000 * e3);
}
if (s2 && o2 <= n2.minX) {
const t48 = Math.max(n2.maxY - n2.minY, 0.000000001), e3 = (n2.maxY - i2) / t48;
return 18000 + Math.round(9000 * e3);
}
if (r2 && i2 <= n2.minY) {
const t48 = Math.max(n2.maxX - n2.minX, 0.000000001), e3 = (o2 - n2.minX) / t48;
return 27000 + Math.round(9000 * e3);
}
const a2 = Math.abs(o2 - n2.minX), c2 = Math.abs(o2 - n2.maxX), l2 = Math.abs(i2 - n2.minY), h2 = Math.abs(i2 - n2.maxY), d2 = Math.min(a2, c2, l2, h2), u2 = Math.max(n2.maxX - n2.minX, 0.000000001), p2 = Math.max(n2.maxY - n2.minY, 0.000000001);
if (d2 === c2) {
const t48 = (i2 - n2.minY) / p2;
return Math.round(9000 * t48);
}
if (d2 === h2) {
const t48 = (n2.maxX - o2) / u2;
return 9000 + Math.round(9000 * t48);
}
if (d2 === a2) {
const t48 = (n2.maxY - i2) / p2;
return 18000 + Math.round(9000 * t48);
}
const m2 = (o2 - n2.minX) / u2;
return 27000 + Math.round(9000 * m2);
};
var CH = (t47, e2) => {
if (!t47)
return;
return [...t47.pointIds].sort((t48, n2) => {
const o2 = e2.get(t48), i2 = e2.get(n2), r2 = Number(o2?.d?.distToCentermostPortOnZ ?? Number.POSITIVE_INFINITY), s2 = Number(i2?.d?.distToCentermostPortOnZ ?? Number.POSITIVE_INFINITY);
if (r2 !== s2)
return r2 - s2;
const a2 = Number(o2?.d?.z ?? 0), c2 = Number(i2?.d?.z ?? 0);
return a2 !== c2 ? a2 - c2 : t48.localeCompare(n2);
})[0];
};
var PH = (t47) => {
const e2 = bH(t47), n2 = new Map, o2 = new Map, i2 = new Map, r2 = new Map((e2.solvedRoutes ?? []).map((t48) => [t48.connection.connectionId, t48]));
e2.regions.forEach((t48, e3) => {
n2.set(t48.regionId, e3);
}), e2.ports.forEach((t48, e3) => {
o2.set(t48.portId, e3), i2.set(t48.portId, t48);
});
const s2 = e2.regions.length, a2 = e2.ports.length, c2 = e2.regions.map((t48) => t48.pointIds.map((t49) => o2.get(t49)).filter((t49) => t49 !== undefined)), l2 = Array.from({ length: a2 }, () => []), h2 = new Float64Array(s2), d2 = new Float64Array(s2), u2 = new Float64Array(s2), p2 = new Float64Array(s2), m2 = new Int32Array(s2), g2 = new Int32Array(s2).fill(-1), f2 = new Int8Array(s2);
e2.regions.forEach((t48, e3) => {
const n3 = ((t49) => {
const e4 = xH(t49), n4 = typeof t49.d?.width == "number" ? t49.d.width : e4.maxX - e4.minX, o4 = typeof t49.d?.height == "number" ? t49.d.height : e4.maxY - e4.minY;
return { centerX: typeof t49.d?.center?.x == "number" ? t49.d.center.x : (e4.minX + e4.maxX) / 2, centerY: typeof t49.d?.center?.y == "number" ? t49.d.center.y : (e4.minY + e4.maxY) / 2, width: n4, height: o4 };
})(t48);
h2[e3] = n3.width, d2[e3] = n3.height, u2[e3] = n3.centerX, p2[e3] = n3.centerY, m2[e3] = ((t49) => {
const e4 = t49.d?.availableZ;
if (!Array.isArray(e4))
return 0;
let n4 = 0;
for (const t50 of e4)
!Number.isInteger(t50) || t50 < 0 || t50 >= 31 || (n4 |= 1 << t50);
return n4;
})(t48);
const o3 = _H(t48);
o3 !== undefined && (g2[e3] = o3, f2[e3] = 1);
});
const y2 = new Int32Array(a2), _2 = new Int32Array(a2), b2 = new Float64Array(a2), x2 = new Float64Array(a2), v2 = new Int32Array(a2);
e2.ports.forEach((t48, o3) => {
const i3 = n2.get(t48.region1Id), r3 = n2.get(t48.region2Id);
if (i3 === undefined || r3 === undefined)
throw new Error(`Port "${t48.portId}" references missing regions "${t48.region1Id}" or "${t48.region2Id}"`);
l2[o3] = [i3, r3], b2[o3] = vH(t48), x2[o3] = IH(t48), v2[o3] = ((t49) => {
const e3 = Number(t49.d?.z ?? 0);
return Number.isFinite(e3) ? e3 : 0;
})(t48), y2[o3] = SH(t48, e2.regions[i3]), _2[o3] = SH(t48, e2.regions[r3]);
});
const I2 = e2.regions.map((t48, e3) => ((t49, e4) => {
const n3 = t49.d && typeof t49.d == "object" && !Array.isArray(t49.d) ? { ...t49.d } : { value: t49.d };
return n3.layer = e4, Object.defineProperty(n3, "serializedRegionId", { value: t49.regionId, enumerable: false, configurable: true, writable: true }), n3;
})(t48, ((t49) => jW($W(m2[t49])) ?? jW((c2[t49] ?? []).map((t50) => v2[t50])) ?? "z0")(e3))), S2 = e2.ports.map((t48, e3) => ((t49, e4) => {
const n3 = t49.d && typeof t49.d == "object" && !Array.isArray(t49.d) ? { ...t49.d } : { value: t49.d };
return n3.layer = e4, Object.defineProperty(n3, "serializedPortId", { value: t49.portId, enumerable: false, configurable: true, writable: true }), n3;
})(t48, jW([v2[e3]]) ?? "z0")), C2 = e2.connections ?? [], P2 = new Map;
let M2 = 0;
const N2 = (t48) => {
const e3 = t48.mutuallyConnectedNetworkId ?? t48.connectionId;
let n3 = P2.get(e3);
return n3 === undefined && (n3 = M2++, P2.set(e3, n3)), n3;
}, w2 = Array.from({ length: s2 }, () => new Set), T2 = (t48, e3) => {
const o3 = n2.get(t48);
if (o3 === undefined)
throw new Error(`Connection references missing region "${t48}"`);
w2[o3].add(e3);
};
C2.forEach((t48) => {
const e3 = N2(t48);
T2(t48.startRegionId, e3), T2(t48.endRegionId, e3);
}), w2.forEach((t48, e3) => {
f2[e3] !== 1 && t48.size === 1 && (g2[e3] = [...t48][0]);
});
const R2 = C2.map((t48) => {
const n3 = r2.get(t48.connectionId), o3 = ((t49, e3) => t49.ports.filter((t50) => t50.region1Id === e3.startRegionId && t50.region2Id === e3.endRegionId || t50.region2Id === e3.startRegionId && t50.region1Id === e3.endRegionId).map((t50) => t50.portId))(e2, t48);
return { connection: t48, solvedRoute: n3, sharedPortIds: o3 };
}).filter(({ solvedRoute: t48, sharedPortIds: e3 }) => e3.length === 0 || (t48?.path.length ?? 0) > 1), E2 = R2.length, A2 = new Map(R2.map(({ connection: t48 }, e3) => [t48.connectionId, e3])), O2 = new Int8Array(a2).fill(1), k2 = new Int32Array(E2), D2 = new Int32Array(E2), L2 = new Int32Array(E2);
R2.forEach(({ connection: t48, solvedRoute: n3 }, r3) => {
const s3 = CH(e2.regions.find((e3) => e3.regionId === t48.startRegionId), i2), a3 = CH(e2.regions.find((e3) => e3.regionId === t48.endRegionId), i2), c3 = n3?.path[0]?.portId ?? s3, l3 = n3?.path[n3.path.length - 1]?.portId ?? a3, h3 = c3 !== undefined ? o2.get(c3) : undefined, d3 = l3 !== undefined ? o2.get(l3) : undefined;
if (h3 === undefined || d3 === undefined)
throw new Error(`Connection "${t48.connectionId}" could not be mapped to route endpoints`);
k2[r3] = h3, D2[r3] = d3, L2[r3] = N2(t48);
});
const z2 = { portCount: a2, regionCount: s2, regionIncidentPorts: c2, incidentPortRegion: l2, regionWidth: h2, regionHeight: d2, regionCenterX: u2, regionCenterY: p2, regionAvailableZMask: m2, regionMetadata: I2, portAngleForRegion1: y2, portAngleForRegion2: _2, portX: b2, portY: x2, portZ: v2, portMetadata: S2 }, B2 = e2.regions.flatMap((t48, e3) => (t48.assignments ?? []).map((n3) => {
const i3 = A2.get(n3.connectionId);
if (i3 === undefined)
throw new Error(`Region "${t48.regionId}" assignment references unknown routable connection "${n3.connectionId}"`);
const r3 = o2.get(n3.regionPort1Id), s3 = o2.get(n3.regionPort2Id);
if (r3 === undefined || s3 === undefined)
throw new Error(`Region "${t48.regionId}" assignment references missing port "${r3 === undefined ? n3.regionPort1Id : n3.regionPort2Id}"`);
if (!c2[e3]?.includes(r3) || !c2[e3]?.includes(s3))
throw new Error(`Region "${t48.regionId}" assignment ports must both belong to the region`);
return { routeId: i3, regionId: e3, fromPortId: r3, toPortId: s3 };
})), F2 = Float64Array.from(e2.ports, (t48) => {
const e3 = Number(t48.d?.tinyHypergraphPortPenalty ?? 0);
return Number.isFinite(e3) && e3 > 0 ? e3 : 0;
}), j2 = F2.some((t48) => t48 > 0), $ = { routeCount: E2, portSectionMask: O2, routeMetadata: R2.map(({ connection: t48 }) => t48), routeStartPort: k2, routeEndPort: D2, routeNet: L2, regionNetId: g2, ...B2.length > 0 && { initialAssignments: B2 }, ...j2 && { portPenalty: F2 } }, Y2 = [], X2 = [];
for (const { solvedRoute: t48 } of R2) {
if (!t48) {
Y2.push([]), X2.push([]);
continue;
}
const e3 = [], i3 = [];
for (let r3 = 1;r3 < t48.path.length; r3++) {
const s3 = t48.path[r3 - 1], a3 = t48.path[r3], c3 = s3?.portId, l3 = a3?.portId, h3 = c3 !== undefined ? o2.get(c3) : undefined, d3 = l3 !== undefined ? o2.get(l3) : undefined;
if (h3 === undefined || d3 === undefined)
continue;
const u3 = typeof s3?.nextRegionId == "string" ? s3.nextRegionId : typeof a3?.lastRegionId == "string" ? a3.lastRegionId : undefined;
e3.push([h3, d3]), i3.push(u3 !== undefined ? n2.get(u3) : undefined);
}
Y2.push(e3), X2.push(i3);
}
return { topology: z2, problem: $, solution: { solvedRoutePathSegments: Y2, solvedRoutePathRegionIds: X2 } };
};
var MH = (t47) => typeof t47 == "object" && t47 !== null;
var NH = (t47) => Array.isArray(t47) ? t47.map((t48) => NH(t48)) : MH(t47) ? Object.fromEntries(Object.entries(t47).map(([t48, e2]) => [t48, NH(e2)])) : t47;
var wH = (t47) => MH(t47) ? { ...t47 } : t47 === undefined ? {} : { value: t47 };
var TH = (t47, e2 = 0) => typeof t47 == "number" && Number.isFinite(t47) ? t47 : e2;
var RH = (t47) => ({ x: TH(t47.d?.x), y: TH(t47.d?.y) });
var EH = (t47) => [t47.region1Id, t47.region2Id].sort().join("\x00");
var AH = (t47, e2) => Math.hypot(t47.x - e2.x, t47.y - e2.y);
var OH = (t47) => {
const e2 = Math.hypot(t47.x, t47.y);
if (!(e2 <= 0.000000001))
return { x: t47.x / e2, y: t47.y / e2 };
};
var kH = (t47) => {
const e2 = t47?.d?.center;
if (MH(e2))
return { x: TH(e2.x), y: TH(e2.y) };
const n2 = ((t48) => {
const e3 = t48?.d?.bounds;
if (MH(e3) && typeof e3.minX == "number" && typeof e3.maxX == "number" && typeof e3.minY == "number" && typeof e3.maxY == "number")
return { minX: e3.minX, maxX: e3.maxX, minY: e3.minY, maxY: e3.maxY };
const n3 = t48?.d?.center, o2 = TH(t48?.d?.width), i2 = TH(t48?.d?.height);
if (MH(n3)) {
const t49 = TH(n3.x), e4 = TH(n3.y);
return { minX: t49 - o2 / 2, maxX: t49 + o2 / 2, minY: e4 - i2 / 2, maxY: e4 + i2 / 2 };
}
return { minX: 0, maxX: 0, minY: 0, maxY: 0 };
})(t47);
return { x: (n2.minX + n2.maxX) / 2, y: (n2.minY + n2.maxY) / 2 };
};
var DH = (t47, e2) => {
const n2 = EH(t47), o2 = RH(t47);
let i2, r2 = Number.POSITIVE_INFINITY;
for (const s2 of e2) {
if (s2.portId === t47.portId)
continue;
if (EH(s2) !== n2)
continue;
const e3 = AH(o2, RH(s2));
e3 <= 0.000000001 || e3 >= r2 || (i2 = s2, r2 = e3);
}
return i2;
};
var LH = (t47, e2, n2) => {
const o2 = RH(t47);
if (e2) {
const t48 = RH(e2), n3 = OH({ x: o2.x - t48.x, y: o2.y - t48.y });
if (n3)
return n3;
}
return ((t48, e3) => {
const n3 = kH(e3.get(t48.region1Id)), o3 = kH(e3.get(t48.region2Id));
return OH({ x: -(o3.y - n3.y), y: o3.x - n3.x }) ?? { x: 1, y: 0 };
})(t47, n2);
};
var zH = (t47, e2, n2) => {
const o2 = `${t47}::dup${e2}`;
if (!n2.has(o2))
return n2.add(o2), o2;
for (let t48 = 2;; t48++) {
const e3 = `${o2}-${t48}`;
if (!n2.has(e3))
return n2.add(e3), e3;
}
};
var BH = (t47, e2, n2) => {
const o2 = t47.indexOf(e2);
o2 !== -1 ? t47.splice(o2 + 1, 0, ...n2) : t47.push(...n2);
};
var FH = (t47, e2) => {
const n2 = t47.portMetadata?.[e2];
if (MH(n2)) {
if (typeof n2.serializedPortId == "string")
return n2.serializedPortId;
if (typeof n2.portId == "string")
return n2.portId;
}
return `port-${e2}`;
};
var jH = (t47, e2) => ({ routeCount: 1, portSectionMask: new Int8Array(t47.portSectionMask), routeMetadata: t47.routeMetadata === undefined ? undefined : [t47.routeMetadata[e2]], routeStartPort: Int32Array.from([t47.routeStartPort[e2]]), routeEndPort: Int32Array.from([t47.routeEndPort[e2]]), routeNet: Int32Array.from([t47.routeNet[e2]]), regionNetId: new Int32Array(t47.regionNetId), portPenalty: t47.portPenalty === undefined ? undefined : new Float64Array(t47.portPenalty) });
var $H = (t47) => {
const e2 = new Set;
for (const n2 of t47.state.regionSegments)
for (const [, t48, o2] of n2)
e2.add(t48), e2.add(o2);
return e2.size === 0 && t47.problem.routeCount === 1 && (e2.add(t47.problem.routeStartPort[0]), e2.add(t47.problem.routeEndPort[0])), e2;
};
var YH = class extends kt {
constructor(t47, e2 = {}) {
super(), this.serializedHyperGraph = t47, this.options = e2;
}
revisedSerializedHyperGraph;
report = { portUseCounts: {}, duplicatedPorts: [] };
getDuplicatePortProximity() {
return this.options.duplicatePortProximity ?? 0.05;
}
getIndividualRouteSolveOptions() {
return { RIP_THRESHOLD_RAMP_ATTEMPTS: 0, STATIC_REACHABILITY_PRECHECK: false, ...this.options.routeSolveOptions };
}
getPortUseCounts() {
const { topology: t47, problem: e2 } = PH(this.serializedHyperGraph);
this.options.useSerializedPortPenalties === false && (e2.portPenalty = undefined);
const n2 = new Map;
for (let o2 = 0;o2 < e2.routeCount; o2++) {
const i2 = jH(e2, o2), r2 = new uH(t47, i2, this.getIndividualRouteSolveOptions());
if (r2.solve(), !r2.solved || r2.failed)
throw new Error(`Route ${o2} could not be solved independently: ${r2.error ?? "unknown error"}`);
for (const e3 of $H(r2)) {
const o3 = FH(t47, e3);
n2.set(o3, (n2.get(o3) ?? 0) + 1);
}
}
return n2;
}
duplicateCongestedPorts(t47) {
const e2 = this.getDuplicatePortProximity();
if (!(e2 > 0))
throw new Error("duplicatePortProximity must be greater than zero");
const { solvedRoutes: n2, ...o2 } = this.serializedHyperGraph, i2 = this.serializedHyperGraph.regions.map((t48) => ({ ...t48, pointIds: [...t48.pointIds], d: NH(t48.d) })), r2 = this.serializedHyperGraph.ports.map((t48) => ({ ...t48, d: NH(t48.d) })), s2 = new Map(i2.map((t48) => [t48.regionId, t48])), a2 = new Map(r2.map((t48) => [t48.portId, t48])), c2 = new Set(r2.map((t48) => t48.portId)), l2 = [];
for (const [n3, o3] of [...t47.entries()].sort(([t48], [e3]) => t48.localeCompare(e3))) {
if (o3 <= 1)
continue;
const t48 = a2.get(n3);
if (!t48)
continue;
const i3 = o3 - 1, h2 = DH(t48, this.serializedHyperGraph.ports), d2 = LH(t48, h2, s2), u2 = RH(t48), p2 = [];
for (let s3 = 1;s3 <= i3; s3++) {
const a3 = zH(n3, s3, c2), l3 = e2 * s3 / (i3 + 1), h3 = wH(NH(t48.d));
h3.x = u2.x + d2.x * l3, h3.y = u2.y + d2.y * l3, h3.duplicatedFromPortId = n3, h3.duplicateIndex = s3, h3.duplicatePortUseCount = o3, h3.duplicatePortProximity = e2, h3.repairReason = "congested-port", r2.push({ ...t48, portId: a3, d: h3 }), p2.push(a3);
}
for (const e3 of [t48.region1Id, t48.region2Id]) {
const t49 = s2.get(e3);
t49 && BH(t49.pointIds, n3, p2);
}
l2.push({ sourcePortId: n3, duplicatePortIds: p2, useCount: o3 });
}
return this.report = { portUseCounts: Object.fromEntries([...t47.entries()].sort()), duplicatedPorts: l2 }, { ...o2, regions: i2, ports: r2, connections: this.serializedHyperGraph.connections === undefined ? undefined : NH(this.serializedHyperGraph.connections) };
}
_setup() {
try {
const t47 = this.getPortUseCounts();
this.revisedSerializedHyperGraph = this.duplicateCongestedPorts(t47), this.stats = { ...this.stats, duplicateSourcePortCount: this.report.duplicatedPorts.length, duplicatedPortCount: this.report.duplicatedPorts.reduce((t48, e2) => t48 + e2.duplicatePortIds.length, 0) }, this.solved = true;
} catch (t47) {
this.failed = true, this.error = t47 instanceof Error ? t47.message : String(t47);
}
}
_step() {
this.failed || (this.solved = true);
}
getOutput() {
if (!this.revisedSerializedHyperGraph || this.failed)
throw new Error("DuplicateCongestedPortSolver does not have a repaired topology output");
return this.revisedSerializedHyperGraph;
}
};
var XH = (t47, e2) => {
const n2 = t47.owners.size - e2.owners.size;
if (n2 !== 0)
return n2;
const o2 = t47.distance - e2.distance;
return o2 !== 0 ? o2 : t47.queueOrder - e2.queueOrder;
};
var WH = class {
heap = [];
push(t47) {
this.heap.push(t47);
let e2 = this.heap.length - 1;
for (;e2 > 0; ) {
const t48 = Math.floor((e2 - 1) / 2);
if (XH(this.heap[t48], this.heap[e2]) <= 0)
break;
[this.heap[t48], this.heap[e2]] = [this.heap[e2], this.heap[t48]], e2 = t48;
}
}
pop() {
const t47 = this.heap[0], e2 = this.heap.pop();
if (!t47 || !e2)
return null;
if (this.heap.length === 0)
return t47;
this.heap[0] = e2;
let n2 = 0;
for (;; ) {
const t48 = 2 * n2 + 1, e3 = t48 + 1;
let o2 = n2;
if (t48 < this.heap.length && XH(this.heap[t48], this.heap[o2]) < 0 && (o2 = t48), e3 < this.heap.length && XH(this.heap[e3], this.heap[o2]) < 0 && (o2 = e3), o2 === n2)
break;
[this.heap[n2], this.heap[o2]] = [this.heap[o2], this.heap[n2]], n2 = o2;
}
return t47;
}
};
var VH = (t47, e2, n2) => {
if (t47 === e2)
return true;
if (t47.size > e2.size + n2.length)
return false;
for (const o2 of t47)
if (!e2.has(o2) && !n2.includes(o2))
return false;
return true;
};
var HH = (t47, e2) => !(t47.distance > e2.distance) && ((t48, e3) => {
if (t48.size > e3.size)
return false;
for (const n2 of t48)
if (!e3.has(n2))
return false;
return true;
})(t47.owners, e2.owners);
var GH = (t47, e2) => {
const n2 = [], o2 = [];
let i2 = t47;
for (;i2 !== null; )
n2.push(i2.state), i2.incomingHop !== null && o2.push(i2.incomingHop), i2 = i2.parent;
return n2.reverse(), o2.reverse(), { found: true, states: n2, hops: o2, owners: new Set(t47.owners), distance: t47.distance, expandedLabelCount: e2 };
};
var UH = (t47) => {
for (;; ) {
const e2 = t47.pop();
if (e2 === null)
return null;
if (e2.active)
return e2;
}
};
var ZH = (t47, e2) => {
lH(t47, e2), e2 && (e2.MAX_RIPS !== undefined && (t47.MAX_RIPS = e2.MAX_RIPS), e2.MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT !== undefined && (t47.MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT = e2.MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT), e2.EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST !== undefined && (t47.EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST = e2.EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST));
};
var qH = (t47) => t47.map((t48) => t48.map(([t49, e2, n2]) => [t49, e2, n2]));
var JH = (t47) => ({ netIds: new Int32Array(t47.netIds), lesserAngles: new Int32Array(t47.lesserAngles), greaterAngles: new Int32Array(t47.greaterAngles), layerMasks: new Int32Array(t47.layerMasks), existingCrossingLayerIntersections: t47.existingCrossingLayerIntersections, existingSameLayerIntersections: t47.existingSameLayerIntersections, existingEntryExitLayerChanges: t47.existingEntryExitLayerChanges, existingRegionCost: t47.existingRegionCost, existingSegmentCount: t47.existingSegmentCount });
var QH = (t47) => ({ portAssignment: new Int32Array(t47.portAssignment), regionSegments: qH(t47.regionSegments), regionIntersectionCaches: t47.regionIntersectionCaches.map(JH) });
var KH = (t47, e2) => {
const n2 = QH(e2);
t47.state.portAssignment = n2.portAssignment, t47.state.regionSegments = n2.regionSegments, t47.state.regionIntersectionCaches = n2.regionIntersectionCaches;
};
var tG = (t47) => {
let e2 = 0, n2 = 0;
for (let o2 = 0;o2 < t47.length; o2++) {
const i2 = t47[o2]?.existingRegionCost ?? 0;
e2 = Math.max(e2, i2), n2 += i2;
}
return { maxRegionCost: e2, totalRegionCost: n2 };
};
var eG = (t47, e2) => t47.maxRegionCost !== e2.maxRegionCost ? t47.maxRegionCost - e2.maxRegionCost : t47.totalRegionCost - e2.totalRegionCost;
var nG = (t47, e2, n2) => {
const o2 = t47.incidentPortRegion[e2] ?? [], i2 = t47.incidentPortRegion[n2] ?? [], r2 = o2.find((t48) => i2.includes(t48));
if (r2 === undefined)
throw new Error(`Ports ${e2} and ${n2} do not share a region`);
return r2;
};
var oG = (t47, e2, n2, o2) => {
const i2 = n2.solvedRoutePathSegments[o2] ?? [], r2 = n2.solvedRoutePathRegionIds?.[o2] ?? [], s2 = e2.routeStartPort[o2], a2 = e2.routeEndPort[o2];
if (i2.length === 0) {
if (s2 === a2)
return { orderedPortIds: [s2], orderedRegionIds: [] };
throw new Error(`Route ${o2} does not have an existing solved path`);
}
const c2 = new Map;
i2.forEach(([t48, e3], n3) => {
const o3 = { segmentIndex: n3, fromPortId: t48, toPortId: e3, regionId: r2[n3] }, i3 = c2.get(t48) ?? [];
i3.push(o3), c2.set(t48, i3);
const s3 = c2.get(e3) ?? [];
s3.push(o3), c2.set(e3, s3);
});
const l2 = [s2], h2 = [], d2 = new Set;
let u2, p2 = s2;
for (;p2 !== a2 || d2.size < i2.length; ) {
const e3 = (c2.get(p2) ?? []).filter(({ segmentIndex: t48, fromPortId: e4, toPortId: n4 }) => {
if (d2.has(t48))
return false;
const o3 = e4 === p2 ? n4 : e4, r4 = o3 === a2 && d2.size + 1 === i2.length;
return o3 !== u2 || r4;
}), n3 = p2 === a2 && d2.size === 0 && e3.length === 2 || e3.length === 1 ? e3[0] : undefined;
if (!n3)
throw new Error(`Route ${o2} is not a single ordered path from ${s2} to ${a2}`);
const r3 = n3.fromPortId === p2 ? n3.toPortId : n3.fromPortId;
d2.add(n3.segmentIndex), h2.push(n3.regionId ?? nG(t47, n3.fromPortId, n3.toPortId)), l2.push(r3), u2 = p2, p2 = r3;
}
if (d2.size !== i2.length)
throw new Error(`Route ${o2} contains disconnected solved segments`);
return { orderedPortIds: l2, orderedRegionIds: h2 };
};
var iG = (t47, e2, n2, o2) => {
const i2 = new uH(t47, e2, o2);
return ((t48, e3) => {
t48.state.portAssignment.fill(-1), t48.state.regionSegments = Array.from({ length: t48.topology.regionCount }, () => []), t48.state.regionIntersectionCaches = Array.from({ length: t48.topology.regionCount }, () => sH()), t48.state.currentRouteId = undefined, t48.state.currentRouteNetId = undefined, t48.state.unroutedRoutes = [], t48.state.candidateQueue.clear(), t48.resetCandidateBestCosts(), t48.state.goalPortId = -1, t48.state.ripCount = 0, t48.state.regionCongestionCost.fill(0);
for (let n3 = 0;n3 < e3.length; n3++)
for (const [o3, i3, r2] of e3[n3] ?? [])
t48.state.currentRouteNetId = t48.problem.routeNet[o3], t48.state.regionSegments[n3].push([o3, i3, r2]), t48.state.portAssignment[i3] = t48.state.currentRouteNetId, t48.state.portAssignment[r2] = t48.state.currentRouteNetId, t48.appendSegmentToRegionCache(n3, i3, r2);
t48.state.currentRouteId = undefined, t48.state.currentRouteNetId = undefined, t48.solved = true, t48.failed = false, t48.error = null;
})(i2, n2), i2;
};
var rG = (t47, e2, n2) => {
const o2 = new Int32Array(e2.routeStartPort), i2 = new Int32Array(e2.routeEndPort), r2 = Array.from({ length: e2.routeCount }, (t48, e3) => ({ routeId: e3, fixedSegments: [] })), s2 = [];
for (let a2 = 0;a2 < e2.routeCount; a2++) {
const c2 = r2[a2], { orderedPortIds: l2, orderedRegionIds: h2 } = oG(t47, e2, n2, a2), d2 = [];
let u2;
for (let t48 = 0;t48 < l2.length; t48++) {
const n3 = l2[t48], o3 = e2.portSectionMask[n3] === 1;
o3 && u2 === undefined ? u2 = t48 : o3 || u2 === undefined || (d2.push({ startIndex: u2, endIndex: t48 - 1 }), u2 = undefined);
}
if (u2 !== undefined && d2.push({ startIndex: u2, endIndex: l2.length - 1 }), d2.length === 0) {
for (let t48 = 1;t48 < l2.length; t48++)
c2.fixedSegments.push({ regionId: h2[t48 - 1], fromPortId: l2[t48 - 1], toPortId: l2[t48] });
continue;
}
if (d2.length > 1)
throw new Error(`Route ${a2} enters the section multiple times; only one contiguous section span is currently supported`);
const p2 = d2[0], m2 = Math.max(0, p2.startIndex - 1), g2 = Math.min(l2.length - 1, p2.endIndex + 1);
if (g2 <= m2)
throw new Error(`Route ${a2} does not have a valid section span`);
for (let t48 = 1;t48 <= m2; t48++)
c2.fixedSegments.push({ regionId: h2[t48 - 1], fromPortId: l2[t48 - 1], toPortId: l2[t48] });
for (let t48 = g2 + 1;t48 < l2.length; t48++)
c2.fixedSegments.push({ regionId: h2[t48 - 1], fromPortId: l2[t48 - 1], toPortId: l2[t48] });
c2.activeStartPortId = l2[m2], c2.activeEndPortId = l2[g2], c2.forcedStartRegionId = h2[m2], o2[a2] = c2.activeStartPortId, i2[a2] = c2.activeEndPortId, s2.push(a2);
}
return { sectionProblem: { routeCount: e2.routeCount, portSectionMask: new Int8Array(e2.portSectionMask), routeMetadata: e2.routeMetadata, routeStartPort: o2, routeEndPort: i2, routeNet: new Int32Array(e2.routeNet), regionNetId: new Int32Array(e2.regionNetId), portPenalty: e2.portPenalty === undefined ? undefined : new Float64Array(e2.portPenalty) }, routePlans: r2, activeRouteIds: s2 };
};
var sG = (t47, e2, n2) => rG(t47, e2, n2).activeRouteIds;
var aG = class extends uH {
constructor(t47, e2, n2, o2, i2, r2, s2, a2) {
super(t47, e2, a2), this.routePlans = n2, this.activeRouteIds = o2, this.mutableRegionIds = i2, this.immutableRegionSummary = r2, this.baselineSummary = s2, ZH(this, a2), this.state.unroutedRoutes = [...o2], this.applyFixedSegments(), this.fixedSnapshot = QH({ portAssignment: this.state.portAssignment, regionSegments: this.state.regionSegments, regionIntersectionCaches: this.state.regionIntersectionCaches });
}
bestSnapshot;
fixedSnapshot;
bestSummary;
baselineBeatRipCount;
previousBestMaxRegionCost = Number.POSITIVE_INFINITY;
ripsSinceBestMaxRegionCostImprovement = 0;
MAX_RIPS = Number.POSITIVE_INFINITY;
MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT = Number.POSITIVE_INFINITY;
EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST = Number.POSITIVE_INFINITY;
applyFixedSegments() {
for (const t47 of this.routePlans)
for (const { regionId: e2, fromPortId: n2, toPortId: o2 } of t47.fixedSegments)
this.state.currentRouteNetId = this.problem.routeNet[t47.routeId], this.state.regionSegments[e2].push([t47.routeId, n2, o2]), this.state.portAssignment[n2] = this.state.currentRouteNetId, this.state.portAssignment[o2] = this.state.currentRouteNetId, this.appendSegmentToRegionCache(e2, n2, o2);
this.state.currentRouteId = undefined, this.state.currentRouteNetId = undefined;
}
captureBestState(t47) {
this.bestSummary && eG(t47, this.bestSummary) >= 0 || (this.bestSummary = t47, this.bestSnapshot = QH({ portAssignment: this.state.portAssignment, regionSegments: this.state.regionSegments, regionIntersectionCaches: this.state.regionIntersectionCaches }));
}
restoreBestState() {
this.bestSnapshot && (KH(this, this.bestSnapshot), this.state.currentRouteId = undefined, this.state.currentRouteNetId = undefined, this.state.unroutedRoutes = [], this.state.candidateQueue.clear(), this.resetCandidateBestCosts(), this.state.goalPortId = -1);
}
getStartingNextRegionId(t47, e2) {
const n2 = this.routePlans[t47]?.forcedStartRegionId;
return n2 !== undefined ? n2 : super.getStartingNextRegionId(t47, e2);
}
resetRoutingStateForRerip() {
if (!this.fixedSnapshot)
return super.resetRoutingStateForRerip(), this.state.unroutedRoutes = sV([...this.activeRouteIds], this.state.ripCount), void this.applyFixedSegments();
KH(this, this.fixedSnapshot), this.state.currentRouteId = undefined, this.state.currentRouteNetId = undefined, this.state.unroutedRoutes = sV([...this.activeRouteIds], this.state.ripCount), this.state.candidateQueue.clear(), this.resetCandidateBestCosts(), this.state.goalPortId = -1;
}
onAllRoutesRouted() {
const { state: t47 } = this, e2 = Math.min(this.MAX_RIPS, this.RIP_THRESHOLD_RAMP_ATTEMPTS), n2 = e2 <= 0 ? 1 : Math.min(1, t47.ripCount / e2), o2 = this.RIP_THRESHOLD_START + (this.RIP_THRESHOLD_END - this.RIP_THRESHOLD_START) * n2, i2 = [], r2 = new Float64Array(this.mutableRegionIds.length);
let s2 = 0, a2 = 0;
for (let e3 = 0;e3 < this.mutableRegionIds.length; e3++) {
const n3 = this.mutableRegionIds[e3], c3 = t47.regionIntersectionCaches[n3]?.existingRegionCost ?? 0;
r2[e3] = c3, s2 = Math.max(s2, c3), a2 += c3, c3 > o2 && i2.push(n3);
}
const c2 = Math.max(this.immutableRegionSummary.maxRegionCost, s2), l2 = this.immutableRegionSummary.totalRegionCost + a2;
this.captureBestState({ maxRegionCost: c2, totalRegionCost: l2 });
const h2 = this.bestSummary ?? { maxRegionCost: c2, totalRegionCost: l2 };
if (h2.maxRegionCost < this.previousBestMaxRegionCost - Number.EPSILON ? (this.previousBestMaxRegionCost = h2.maxRegionCost, this.ripsSinceBestMaxRegionCostImprovement = 0) : this.ripsSinceBestMaxRegionCostImprovement += 1, this.baselineBeatRipCount === undefined && h2.maxRegionCost < this.baselineSummary.maxRegionCost - Number.EPSILON && (this.baselineBeatRipCount = t47.ripCount), this.stats = { ...this.stats, activeRouteCount: this.activeRouteIds.length, currentRipThreshold: o2, hotRegionCount: i2.length, maxRegionCost: c2, totalRegionCost: l2, bestMaxRegionCost: h2.maxRegionCost, bestTotalRegionCost: h2.totalRegionCost, ripCount: t47.ripCount }, i2.length === 0 || t47.ripCount >= e2 || this.ripsSinceBestMaxRegionCostImprovement >= this.MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT || this.baselineBeatRipCount !== undefined && t47.ripCount - this.baselineBeatRipCount >= this.EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST)
return this.restoreBestState(), void (this.solved = true);
for (let e3 = 0;e3 < this.mutableRegionIds.length; e3++) {
const n3 = this.mutableRegionIds[e3];
t47.regionCongestionCost[n3] += r2[e3] * this.RIP_CONGESTION_REGION_COST_FACTOR;
}
t47.ripCount += 1, this.resetRoutingStateForRerip(), this.stats = { ...this.stats, ripCount: t47.ripCount, reripRegionCount: i2.length };
}
onOutOfCandidates() {
const { state: t47 } = this;
for (const e2 of this.mutableRegionIds) {
const n2 = t47.regionIntersectionCaches[e2]?.existingRegionCost ?? 0;
t47.regionCongestionCost[e2] += n2 * this.RIP_CONGESTION_REGION_COST_FACTOR;
}
t47.ripCount += 1, this.resetRoutingStateForRerip(), this.stats = { ...this.stats, ripCount: t47.ripCount, reripReason: "out_of_candidates" };
}
tryFinalAcceptance() {
if (this.bestSnapshot)
return this.restoreBestState(), void (this.solved = true);
this.fixedSnapshot && KH(this, this.fixedSnapshot), this.state.currentRouteId = undefined, this.state.currentRouteNetId = undefined, this.state.unroutedRoutes = [...this.activeRouteIds], this.state.candidateQueue.clear(), this.resetCandidateBestCosts(), this.state.goalPortId = -1, this.stats = { ...this.stats, acceptedFixedSectionStateOnTimeout: true }, this.solved = true;
}
visualize() {
return iH(this, { highlightSectionMask: true, showInitialRouteHints: false, showOnlySectionPortsOnIdle: true });
}
};
var cG = class extends kt {
constructor(t47, e2, n2, o2) {
super(), this.topology = t47, this.problem = e2, this.initialSolution = n2, ZH(this, o2), this.baselineSolver = ((t48, e3, n3, o3) => {
const i2 = Array.from({ length: t48.regionCount }, () => []);
for (let o4 = 0;o4 < e3.routeCount; o4++) {
const { orderedPortIds: r2, orderedRegionIds: s2 } = oG(t48, e3, n3, o4);
for (let t49 = 1;t49 < r2.length; t49++) {
const e4 = r2[t49 - 1], n4 = r2[t49];
i2[s2[t49 - 1]].push([o4, e4, n4]);
}
}
return iG(t48, e3, i2, o3);
})(t47, e2, n2, hH(this)), this.baselineSummary = tG(this.baselineSolver.state.regionIntersectionCaches), this.sectionRegionIds = ((t48, e3) => {
const n3 = new Set;
for (let o3 = 0;o3 < e3.portSectionMask.length; o3++)
if (e3.portSectionMask[o3] === 1)
for (const e4 of t48.incidentPortRegion[o3] ?? [])
n3.add(e4);
return [...n3];
})(t47, e2), this.sectionBaselineSummary = ((t48, e3) => {
let n3 = 0, o3 = 0;
for (const i2 of e3) {
const e4 = t48[i2]?.existingRegionCost ?? 0;
n3 = Math.max(n3, e4), o3 += e4;
}
return { maxRegionCost: n3, totalRegionCost: o3 };
})(this.baselineSolver.state.regionIntersectionCaches, this.sectionRegionIds), this.outsideSectionBaselineSummary = ((t48, e3) => {
const n3 = new Set(e3);
let o3 = 0, i2 = 0;
for (let e4 = 0;e4 < t48.length; e4++) {
if (n3.has(e4))
continue;
const r2 = t48[e4]?.existingRegionCost ?? 0;
o3 = Math.max(o3, r2), i2 += r2;
}
return { maxRegionCost: o3, totalRegionCost: i2 };
})(this.baselineSolver.state.regionIntersectionCaches, this.sectionRegionIds), this.applySectionRipPolicy();
}
baselineSolver;
baselineSummary;
sectionBaselineSummary;
outsideSectionBaselineSummary;
sectionRegionIds;
optimizedSolver;
sectionSolver;
activeRouteIds = [];
DISTANCE_TO_COST = 0.05;
minViaPadDiameter = QW;
VERBOSE = false;
RIP_THRESHOLD_START = 0.05;
RIP_THRESHOLD_END = 0.8;
RIP_THRESHOLD_RAMP_ATTEMPTS = 50;
MAX_RIPS = Number.POSITIVE_INFINITY;
MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT = 10;
EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST = 10;
RIP_CONGESTION_REGION_COST_FACTOR = 0.1;
MAX_ITERATIONS = 1e6;
STATIC_REACHABILITY_PRECHECK = false;
STATIC_REACHABILITY_PRECHECK_MAX_HOPS = 16;
ACCEPT_BEST_SOLUTION_ON_TIMEOUT = true;
GREEDY_FINAL_ROUTE_ITERS = 4;
applySectionRipPolicy() {
this.RIP_THRESHOLD_START = 0.05, this.RIP_THRESHOLD_END = Math.max(this.RIP_THRESHOLD_START, this.sectionBaselineSummary.maxRegionCost), this.MAX_RIPS = Math.min(this.MAX_RIPS, 20);
}
_setup() {
this.applySectionRipPolicy();
const { sectionProblem: t47, routePlans: e2, activeRouteIds: n2 } = rG(this.topology, this.problem, this.initialSolution);
if (this.activeRouteIds = n2, n2.length === 0)
return this.optimizedSolver = this.baselineSolver, this.stats = { ...this.stats, activeRouteCount: 0, initialMaxRegionCost: this.baselineSummary.maxRegionCost, finalMaxRegionCost: this.baselineSummary.maxRegionCost, optimized: false }, void (this.solved = true);
var o2;
this.sectionSolver = new aG(this.topology, t47, e2, n2, this.sectionRegionIds, this.outsideSectionBaselineSummary, this.baselineSummary, { ...hH(o2 = this), MAX_RIPS: o2.MAX_RIPS, MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT: o2.MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT, EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST: o2.EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST }), this.activeSubSolver = this.sectionSolver, this.stats = { ...this.stats, sectionBaselineMaxRegionCost: this.sectionBaselineSummary.maxRegionCost, sectionBaselineTotalRegionCost: this.sectionBaselineSummary.totalRegionCost, effectiveRipThresholdStart: this.RIP_THRESHOLD_START, effectiveRipThresholdEnd: this.RIP_THRESHOLD_END, effectiveMaxRips: this.MAX_RIPS };
}
_step() {
if (!this.sectionSolver)
return void (this.solved = true);
if (this.sectionSolver.step(), this.stats = { ...this.stats, ...this.sectionSolver.stats, activeRouteCount: this.activeRouteIds.length }, this.sectionSolver.failed)
return this.optimizedSolver = this.baselineSolver, this.stats = { ...this.stats, initialMaxRegionCost: this.baselineSummary.maxRegionCost, initialTotalRegionCost: this.baselineSummary.totalRegionCost, finalMaxRegionCost: this.baselineSummary.maxRegionCost, finalTotalRegionCost: this.baselineSummary.totalRegionCost, optimized: false, sectionSearchFailedFallbackToBaseline: true, sectionSearchError: this.sectionSolver.error }, void (this.solved = true);
if (!this.sectionSolver.solved)
return;
const t47 = iG(this.topology, this.problem, qH(this.sectionSolver.state.regionSegments), hH(this)), e2 = tG(t47.state.regionIntersectionCaches), n2 = eG(e2, this.baselineSummary) < 0;
this.optimizedSolver = n2 ? t47 : this.baselineSolver;
const o2 = n2 ? e2 : this.baselineSummary;
this.stats = { ...this.stats, initialMaxRegionCost: this.baselineSummary.maxRegionCost, initialTotalRegionCost: this.baselineSummary.totalRegionCost, candidateMaxRegionCost: e2.maxRegionCost, candidateTotalRegionCost: e2.totalRegionCost, finalMaxRegionCost: o2.maxRegionCost, finalTotalRegionCost: o2.totalRegionCost, optimized: n2 }, this.solved = true;
}
tryFinalAcceptance() {
this.optimizedSolver = this.baselineSolver, this.stats = { ...this.stats, initialMaxRegionCost: this.baselineSummary.maxRegionCost, initialTotalRegionCost: this.baselineSummary.totalRegionCost, finalMaxRegionCost: this.baselineSummary.maxRegionCost, finalTotalRegionCost: this.baselineSummary.totalRegionCost, optimized: false, sectionSolverTimeoutFallbackToBaseline: true }, this.solved = true, this.failed = false, this.error = null;
}
getSolvedSolver() {
if (!this.solved || this.failed || !this.optimizedSolver)
throw new Error("TinyHyperGraphSectionSolver does not have a solved output yet");
return this.optimizedSolver;
}
visualize() {
return this.optimizedSolver ? iH(this.optimizedSolver, { highlightSectionMask: true }) : this.sectionSolver ? this.sectionSolver.visualize() : iH(this.baselineSolver, { highlightSectionMask: true, showInitialRouteHints: false, showOnlySectionPortsOnIdle: true });
}
getOutput() {
return this.getSolvedSolver().getOutput();
}
};
var lG = ["self-touch", "onehop-all", "onehop-touch", "twohop-all", "twohop-touch"];
var hG = { "self-all": 0, "self-touch": 0, "onehop-all": 1, "onehop-touch": 1, "twohop-all": 2, "twohop-touch": 2, "threehop-all": 3, "threehop-touch": 3, "fourhop-all": 4, "fourhop-touch": 4 };
var dG = (t47, e2) => {
const n2 = new Set(e2);
for (const o2 of e2)
for (const e3 of t47.regionIncidentPorts[o2] ?? [])
for (const o3 of t47.incidentPortRegion[e3] ?? [])
n2.add(o3);
return [...n2];
};
var uG = (t47, e2, n2) => {
let o2 = [...new Set(e2)];
for (let e3 = 0;e3 < n2; e3 += 1)
o2 = dG(t47, o2);
return o2;
};
var pG = (t47, e2, n2) => e2.flatMap((e3) => n2.map((n3) => ((t48, e4, n4) => ({ label: `hot-${e4}-${n4}`, family: n4, regionIds: uG(t48, [e4], hG[n4]), portSelectionRule: n4.endsWith("-all") ? "all-incident-regions-selected" : "touches-selected-region" }))(t47, e3, n3)));
var mG = { RIP_THRESHOLD_RAMP_ATTEMPTS: 5 };
var gG = { DISTANCE_TO_COST: 0.05, RIP_THRESHOLD_RAMP_ATTEMPTS: 16, RIP_CONGESTION_REGION_COST_FACTOR: 0.1, MAX_ITERATIONS: 50000, MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT: 6, EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST: Number.POSITIVE_INFINITY };
var fG = (t47) => t47.state.regionIntersectionCaches.reduce((t48, e2) => Math.max(t48, e2.existingRegionCost), 0);
var yG = (t47, e2) => {
const n2 = PH(t47), o2 = new cG(n2.topology, n2.problem, n2.solution, e2);
return fG(o2.baselineSolver);
};
var _G = (t47, e2, n2) => {
const o2 = new Set(e2);
return Int8Array.from({ length: t47.portCount }, (e3, i2) => {
const r2 = t47.incidentPortRegion[i2] ?? [];
return n2 === "touches-selected-region" ? r2.some((t48) => o2.has(t48)) ? 1 : 0 : r2.length > 0 && r2.every((t48) => o2.has(t48)) ? 1 : 0;
});
};
var bG = (t47, e2) => ({ routeCount: t47.routeCount, portSectionMask: e2, routeMetadata: t47.routeMetadata, routeStartPort: new Int32Array(t47.routeStartPort), routeEndPort: new Int32Array(t47.routeEndPort), routeNet: new Int32Array(t47.routeNet), regionNetId: new Int32Array(t47.regionNetId), portPenalty: t47.portPenalty === undefined ? undefined : new Float64Array(t47.portPenalty) });
var xG = (t47, e2, n2, o2, i2, r2) => {
const s2 = performance.now(), a2 = performance.now(), c2 = new cG(e2, n2, o2, r2), l2 = fG(c2.baselineSolver), h2 = performance.now() - a2;
let d2, u2, p2 = l2, m2 = new Int8Array(e2.portCount), g2 = 0, f2 = 0, y2 = 0, _2 = 0, b2 = 0, x2 = 0, v2 = 0;
const I2 = new Set, S2 = i2?.maxHotRegions ?? r2.MAX_HOT_REGIONS ?? 2;
for (const s3 of ((t48, e3, n3, o3) => {
const i3 = t48.state.regionIntersectionCaches.map((t49, e4) => ({ regionId: e4, regionCost: t49.existingRegionCost })).filter(({ regionCost: t49 }) => t49 > 0).sort((t49, e4) => e4.regionCost - t49.regionCost).slice(0, n3).map(({ regionId: t49 }) => t49);
return pG(e3, i3, o3);
})(t47, e2, S2, i2?.candidateFamilies ?? [...lG])) {
const t48 = bG(n2, _G(e2, s3.regionIds, s3.portSelectionRule));
g2 += 1;
const i3 = t48.portSectionMask.join(",");
if (I2.has(i3))
y2 += 1;
else {
I2.add(i3);
try {
const n3 = performance.now(), i4 = sG(e2, t48, o2);
if (_2 += performance.now() - n3, i4.length === 0)
continue;
f2 += 1;
const a3 = performance.now(), c3 = new cG(e2, t48, o2, r2);
b2 += performance.now() - a3;
const l3 = performance.now();
if (c3.solve(), x2 += performance.now() - l3, c3.failed || !c3.solved)
continue;
if (Number(c3.stats.finalMaxRegionCost ?? fG(c3.getSolvedSolver())) < p2 - 0.000000001) {
const e3 = performance.now(), n4 = yG(c3.getOutput(), r2);
v2 += performance.now() - e3, n4 < p2 - 0.000000001 && (p2 = n4, m2 = new Int8Array(t48.portSectionMask), d2 = s3.label, u2 = s3.family);
}
} catch {}
}
}
return { portSectionMask: m2, baselineMaxRegionCost: l2, finalMaxRegionCost: p2, generatedCandidateCount: g2, candidateCount: f2, duplicateCandidateCount: y2, totalMs: performance.now() - s2, baselineEvaluationMs: h2, candidateEligibilityMs: _2, candidateInitMs: b2, candidateSolveMs: x2, candidateReplayScoreMs: v2, winningCandidateLabel: d2, winningCandidateFamily: u2 };
};
var vG = class extends Lt {
initialVisualizationSolver;
selectedSectionMask;
selectedSectionCandidateLabel;
selectedSectionCandidateFamily;
constructor(t47) {
super(t47), this.MAX_ITERATIONS = 200000;
}
loadHyperGraph(t47) {
return PH(t47);
}
getSolveGraphOptions() {
return { ...mG, ...this.inputProblem.minViaPadDiameter === undefined ? {} : { minViaPadDiameter: this.inputProblem.minViaPadDiameter }, ...this.inputProblem.solveGraphOptions };
}
getSectionSolverOptions() {
return { ...gG, ...this.inputProblem.minViaPadDiameter === undefined ? {} : { minViaPadDiameter: this.inputProblem.minViaPadDiameter }, ...this.inputProblem.sectionSolverOptions };
}
pipelineDef = [{ solverName: "solveGraph", solverClass: uH, getConstructorParams: (t47) => {
const { topology: e2, problem: n2 } = t47.loadHyperGraph(t47.inputProblem.serializedHyperGraph);
return [e2, n2, t47.getSolveGraphOptions()];
} }, { solverName: "optimizeSection", solverClass: cG, getConstructorParams: (t47) => t47.getSectionStageParams() }];
getSectionStageParams() {
const t47 = this.getStageOutput("solveGraph");
if (!t47)
throw new Error("solveGraph did not produce a solved serialized hypergraph");
const e2 = this.getSolver("solveGraph");
if (!e2)
throw new Error("solveGraph solver is unavailable");
const n2 = this.getSectionSolverOptions(), { topology: o2, problem: i2, solution: r2 } = this.loadHyperGraph(t47), s2 = this.inputProblem.createSectionMask ? this.inputProblem.createSectionMask({ serializedHyperGraph: this.inputProblem.serializedHyperGraph, solvedSerializedHyperGraph: t47, solvedSolver: e2, topology: o2, problem: i2, solution: r2 }) : (() => {
const t48 = xG(e2, o2, i2, r2, this.inputProblem.sectionSearchConfig, n2);
return this.selectedSectionCandidateLabel = t48.winningCandidateLabel, this.selectedSectionCandidateFamily = t48.winningCandidateFamily, this.stats = { ...this.stats, sectionSearchGeneratedCandidateCount: t48.generatedCandidateCount, sectionSearchCandidateCount: t48.candidateCount, sectionSearchDuplicateCandidateCount: t48.duplicateCandidateCount, sectionSearchBaselineMaxRegionCost: t48.baselineMaxRegionCost, sectionSearchFinalMaxRegionCost: t48.finalMaxRegionCost, sectionSearchDelta: t48.baselineMaxRegionCost - t48.finalMaxRegionCost, selectedSectionCandidateLabel: t48.winningCandidateLabel ?? null, selectedSectionCandidateFamily: t48.winningCandidateFamily ?? null, sectionSearchMs: t48.totalMs, sectionSearchBaselineEvaluationMs: t48.baselineEvaluationMs, sectionSearchCandidateEligibilityMs: t48.candidateEligibilityMs, sectionSearchCandidateInitMs: t48.candidateInitMs, sectionSearchCandidateSolveMs: t48.candidateSolveMs, sectionSearchCandidateReplayScoreMs: t48.candidateReplayScoreMs }, t48.portSectionMask;
})();
return this.selectedSectionMask = new Int8Array(s2), i2.portSectionMask = new Int8Array(s2), this.stats = { ...this.stats, sectionMaskPortCount: [...s2].filter((t48) => t48 === 1).length }, [o2, i2, r2, n2];
}
getInitialVisualizationSolver() {
if (!this.initialVisualizationSolver) {
const { topology: t47, problem: e2 } = this.loadHyperGraph(this.inputProblem.serializedHyperGraph);
this.initialVisualizationSolver = new uH(t47, e2, this.getSolveGraphOptions());
}
return this.initialVisualizationSolver;
}
initialVisualize() {
return this.getInitialVisualizationSolver().visualize();
}
visualize() {
return this.iterations === 0 ? this.initialVisualize() ?? super.visualize() : super.visualize();
}
getOutput() {
return this.getStageOutput("optimizeSection") ?? this.getStageOutput("solveGraph") ?? null;
}
tryFinalAcceptance() {
this.getStageOutput("solveGraph") && (this.stats = { ...this.stats, acceptedSolveGraphOutputOnSectionPipelineTimeout: true }, this.activeSubSolver = undefined, this.solved = true, this.failed = false, this.error = null);
}
};
var IG = class extends yH {
failedOwnerPairCounts = new Map;
selectiveReripStats = { selectiveRipCount: 0, selectivelyRippedRouteCount: 0, globalReripCount: 0, alternateBlockerSearchCount: 0, alternateOwnerCount: 0, failedOwnerPairCount: 0, maxFailedOwnerPairCount: 0, failedOwnerPairs: [], lastDirectOwnerRouteIds: [], lastRepeatedOwnerRouteIds: [], lastAlternateOwnerRouteIds: [], lastRippedRouteIds: [], lastRelaxedSearchExpandedLabelCount: 0, lastAlternateSearchExpandedLabelCount: 0 };
selectiveReripCongestionUpdateCount = 0;
constructor(t47, e2, n2) {
super(t47, e2, n2);
}
getSelectiveReripStats() {
return { ...this.selectiveReripStats, failedOwnerPairs: this.selectiveReripStats.failedOwnerPairs.map((t47) => ({ ...t47 })), lastDirectOwnerRouteIds: [...this.selectiveReripStats.lastDirectOwnerRouteIds], lastRepeatedOwnerRouteIds: [...this.selectiveReripStats.lastRepeatedOwnerRouteIds], lastAlternateOwnerRouteIds: [...this.selectiveReripStats.lastAlternateOwnerRouteIds], lastRippedRouteIds: [...this.selectiveReripStats.lastRippedRouteIds] };
}
onOutOfCandidates() {
const t47 = this.state.currentRouteId;
if (t47 === undefined)
throw new Error("SelectiveReripTinyHyperGraphSolver: candidate search exhausted without a current route");
const e2 = this.findRelaxedBlockerPathPreferringPreservedRoutes();
if (!e2.found || e2.owners.size === 0)
return this.selectiveReripStats.globalReripCount += 1, this.selectiveReripStats.globalReripReason = e2.found ? "no_blocker_path" : e2.reason, this.selectiveReripStats.lastFailedRouteId = t47, this.selectiveReripStats.lastDirectOwnerRouteIds = [], this.selectiveReripStats.lastRepeatedOwnerRouteIds = [], this.selectiveReripStats.lastAlternateOwnerRouteIds = [], this.selectiveReripStats.lastRippedRouteIds = [], this.selectiveReripStats.lastRelaxedSearchExpandedLabelCount = e2.expandedLabelCount, this.selectiveReripStats.lastAlternateSearchExpandedLabelCount = 0, super.onOutOfCandidates(), void this.publishSelectiveReripStats();
const n2 = [...e2.owners], o2 = [];
for (const e3 of n2) {
this.incrementFailedOwnerPair(t47, e3) >= 2 && o2.push(e3);
}
if (n2.some((e3) => this.hasFailedOwnerPath(e3, t47)))
return this.selectiveReripStats.globalReripCount += 1, this.selectiveReripStats.globalReripReason = "failed_owner_cycle", this.selectiveReripStats.lastFailedRouteId = t47, this.selectiveReripStats.lastDirectOwnerRouteIds = n2, this.selectiveReripStats.lastRepeatedOwnerRouteIds = o2, this.selectiveReripStats.lastAlternateOwnerRouteIds = [], this.selectiveReripStats.lastRippedRouteIds = [], this.selectiveReripStats.lastRelaxedSearchExpandedLabelCount = e2.expandedLabelCount, this.selectiveReripStats.lastAlternateSearchExpandedLabelCount = 0, this.failedOwnerPairCounts.clear(), super.onOutOfCandidates(), void this.publishSelectiveReripStats();
let i2;
if (o2.length > 0 && (this.selectiveReripStats.alternateBlockerSearchCount += 1, i2 = this.findRelaxedBlockerPathPreferringPreservedRoutes(new Set(o2)), !i2.found))
return this.selectiveReripStats.globalReripCount += 1, this.selectiveReripStats.globalReripReason = i2.reason, this.selectiveReripStats.lastFailedRouteId = t47, this.selectiveReripStats.lastDirectOwnerRouteIds = n2, this.selectiveReripStats.lastRepeatedOwnerRouteIds = o2, this.selectiveReripStats.lastAlternateOwnerRouteIds = [], this.selectiveReripStats.lastRippedRouteIds = [], this.selectiveReripStats.lastRelaxedSearchExpandedLabelCount = e2.expandedLabelCount, this.selectiveReripStats.lastAlternateSearchExpandedLabelCount = i2.expandedLabelCount, super.onOutOfCandidates(), void this.publishSelectiveReripStats();
const r2 = i2?.found ? [...i2.owners] : undefined, s2 = function(t48) {
const e3 = new Set(t48.alternateOwnerRouteIds ?? t48.directOwnerRouteIds);
if (e3.delete(t48.failedRouteId), e3.size === 0)
throw new Error(`SelectiveReripTinyHyperGraphSolver: route ${t48.failedRouteId} has blocker resources but no distinct committed owner can be reripped`);
return e3;
}({ failedRouteId: t47, directOwnerRouteIds: n2, alternateOwnerRouteIds: r2 });
this.clearPartialRipPlans(s2);
const a2 = (r2 ?? []).filter((t48) => !e2.owners.has(t48));
this.selectiveReripCongestionUpdateCount < 1 && (this.addCongestionCostForSelectiveRerip(), this.selectiveReripCongestionUpdateCount += 1), this.rebuildCommittedState(s2), this.state.ripCount += 1, this.state.currentRouteId = undefined, this.state.currentRouteNetId = undefined, this.state.unroutedRoutes = function(t48) {
const e3 = t48.pendingRouteIds.filter((e4) => e4 !== t48.failedRouteId && !t48.rippedRouteIds.has(e4)), n3 = [...t48.rippedRouteIds].filter((e4) => e4 !== t48.failedRouteId);
return [t48.failedRouteId, ...e3, ...n3];
}({ failedRouteId: t47, pendingRouteIds: this.state.unroutedRoutes, rippedRouteIds: s2 }), this.state.candidateQueue.clear(), this.resetCandidateBestCosts(), this.state.goalPortId = -1, this.selectiveReripStats.selectiveRipCount += 1, this.selectiveReripStats.selectivelyRippedRouteCount += s2.size, this.selectiveReripStats.alternateOwnerCount += a2.length, this.selectiveReripStats.lastFailedRouteId = t47, this.selectiveReripStats.lastDirectOwnerRouteIds = n2, this.selectiveReripStats.lastRepeatedOwnerRouteIds = o2, this.selectiveReripStats.lastAlternateOwnerRouteIds = a2, this.selectiveReripStats.lastRippedRouteIds = [...s2], this.selectiveReripStats.lastRelaxedSearchExpandedLabelCount = e2.expandedLabelCount, this.selectiveReripStats.lastAlternateSearchExpandedLabelCount = i2?.expandedLabelCount ?? 0, this.publishSelectiveReripStats();
}
addCongestionCostForSelectiveRerip() {
for (let t47 = 0;t47 < this.topology.regionCount; t47++) {
const e2 = this.state.regionIntersectionCaches[t47]?.existingRegionCost ?? 0;
this.state.regionCongestionCost[t47] += e2 * this.RIP_CONGESTION_REGION_COST_FACTOR;
}
}
findRelaxedBlockerPath(t47 = new Set) {
const e2 = this.state.currentRouteId, n2 = this.state.currentRouteNetId;
if (e2 === undefined || n2 === undefined)
throw new Error("SelectiveReripTinyHyperGraphSolver: blocker search requires a current route and net");
const o2 = this.getRouteStartPortId(e2), i2 = this.getRouteEndPortId(e2), r2 = this.getStartingNextRegionId(e2, o2);
if (r2 === undefined)
throw new Error(`SelectiveReripTinyHyperGraphSolver: route ${this.describeRoute(e2)} has no starting region for blocker search`);
const s2 = this.getPortOwners(), a2 = new Map, c2 = new Map, l2 = new Map;
return ((t48) => {
const e3 = t48.maxExpandedLabels ?? Number.POSITIVE_INFINITY;
if (e3 !== Number.POSITIVE_INFINITY && (!Number.isInteger(e3) || e3 < 0))
throw new Error("maxExpandedLabels must be a non-negative integer");
const n3 = new Map, o3 = new WH;
let i3 = 0, r3 = 0;
const s3 = { state: t48.start, stateKey: t48.getStateKey(t48.start), owners: new Set, distance: 0, parent: null, incomingHop: null, queueOrder: i3++, active: true };
for (n3.set(s3.stateKey, [s3]), o3.push(s3);; ) {
const s4 = UH(o3);
if (s4 === null)
return { found: false, reason: "no_path", expandedLabelCount: r3 };
if (t48.isGoal(s4.state))
return GH(s4, r3);
if (r3 >= e3)
return { found: false, reason: "expansion_limit", expandedLabelCount: r3 };
r3++;
for (const e4 of t48.getHops(s4.state)) {
if (!Number.isFinite(e4.distance) || e4.distance < 0)
throw new Error("Distinct-owner blocker hops require finite distances >= 0");
const r4 = s4.distance + e4.distance;
if (!Number.isFinite(r4))
throw new Error("Distinct-owner blocker path distance overflowed");
const a3 = t48.getStateKey(e4.state), c3 = i3++, l3 = n3.get(a3) ?? [], h2 = e4.owners ?? [];
let d2 = false;
for (const t49 of l3)
if (t49.distance <= r4 && VH(t49.owners, s4.owners, h2)) {
d2 = true;
break;
}
if (d2)
continue;
let u2 = s4.owners;
for (const t49 of h2)
u2.has(t49) || (u2 === s4.owners && (u2 = new Set(s4.owners)), u2.add(t49));
const p2 = { state: e4.state, stateKey: a3, owners: u2, distance: r4, parent: s4, incomingHop: e4, queueOrder: c3, active: true }, m2 = [];
for (const t49 of l3)
HH(p2, t49) ? t49.active = false : m2.push(t49);
m2.push(p2), n3.set(p2.stateKey, m2), o3.push(p2);
}
}
})({ start: { portId: o2, nextRegionId: r2 }, getStateKey: ({ portId: t48, nextRegionId: e3 }) => this.getHopId(t48, e3), isGoal: ({ portId: t48 }) => t48 === i2, getHops: (e3) => {
const o3 = this.getHopId(e3.portId, e3.nextRegionId), r3 = l2.get(o3);
if (r3)
return r3;
const h2 = this.getRelaxedSearchHops({ state: e3, goalPortId: i2, routeNetId: n2, portOwners: s2, portResources: a2, hopTemplatesByRegion: c2, forbiddenOwnerRouteIds: t47 });
return l2.set(o3, h2), h2;
}, maxExpandedLabels: this.getRelaxedSearchExpansionLimit() });
}
findRelaxedBlockerPathPreferringPreservedRoutes(t47 = new Set) {
const e2 = this.getRouteIdsPreferredForPreservation();
if (e2.size === 0)
return this.findRelaxedBlockerPath(t47);
const n2 = new Set(t47);
for (const t48 of e2)
n2.add(t48);
const o2 = this.findRelaxedBlockerPath(n2);
return o2.found && o2.owners.size > 0 ? o2 : this.findRelaxedBlockerPath(t47);
}
getRelaxedSearchExpansionLimit() {
let t47 = 0;
for (const e3 of this.topology.incidentPortRegion)
t47 += e3.length;
const e2 = Math.max(4, Math.ceil(Math.log2(this.problem.routeCount + 1)));
return Math.max(4096, t47 * e2 * 4);
}
getRelaxedSearchHops(t47) {
const { state: e2, goalPortId: n2, routeNetId: o2 } = t47;
if (this.isRegionReservedForDifferentNet(e2.nextRegionId))
return [];
if (!t47.buildRegionTemplates && !this.isKnownSingleLayerRegion(e2.nextRegionId)) {
let n3 = t47.hopTemplatesByRegion.get(e2.nextRegionId);
n3 || (n3 = this.getRelaxedSearchHops({ ...t47, buildRegionTemplates: true }), t47.hopTemplatesByRegion.set(e2.nextRegionId, n3));
const o3 = [];
for (const t48 of n3)
t48.state.portId !== e2.portId && o3.push({ state: t48.state, owners: t48.owners, data: t48.data, distance: Math.hypot(this.topology.portX[e2.portId] - this.topology.portX[t48.state.portId], this.topology.portY[e2.portId] - this.topology.portY[t48.state.portId]) });
return o3;
}
const i2 = [];
for (const r2 of this.topology.regionIncidentPorts[e2.nextRegionId] ?? []) {
if (r2 === e2.portId && !t47.buildRegionTemplates)
continue;
if (this.isPortReservedForDifferentNet(r2))
continue;
if (r2 !== n2 && this.problem.portSectionMask[r2] === 0)
continue;
const s2 = this.getHopBlockerResources({ regionId: e2.nextRegionId, fromPortId: e2.portId, toPortId: r2, routeNetId: o2, portOwners: t47.portOwners, portResources: t47.portResources }), a2 = [];
for (const t48 of s2)
for (const e3 of t48.owners)
a2.includes(e3) || a2.push(e3);
if (a2.some((e3) => t47.forbiddenOwnerRouteIds.has(e3)))
continue;
let c2 = e2.nextRegionId;
if (r2 !== n2) {
const [t48, n3] = this.topology.incidentPortRegion[r2] ?? [];
if (c2 = t48 === e2.nextRegionId ? n3 : t48, c2 === undefined || this.isRegionReservedForDifferentNet(c2))
continue;
}
i2.push({ state: { portId: r2, nextRegionId: c2 }, distance: Math.hypot(this.topology.portX[e2.portId] - this.topology.portX[r2], this.topology.portY[e2.portId] - this.topology.portY[r2]), owners: a2, data: { resources: s2 } });
}
return i2;
}
getHopBlockerResources(t47) {
const e2 = [], n2 = this.state.portAssignment[t47.toPortId];
if (n2 !== -1 && n2 !== t47.routeNetId) {
let o3 = t47.portResources.get(t47.toPortId);
if (!o3) {
const e3 = [...t47.portOwners.get(t47.toPortId) ?? new Set].filter((e4) => this.problem.routeNet[e4] !== t47.routeNetId);
if (e3.length === 0)
throw new Error(`SelectiveReripTinyHyperGraphSolver: port ${t47.toPortId} is assigned to foreign net ${n2} without a committed route owner`);
o3 = { kind: "port", portId: t47.toPortId, owners: e3 }, t47.portResources.set(t47.toPortId, o3);
}
e2.push(o3);
}
const o2 = this.getHardBlockedCrossingOwners(t47.regionId, t47.fromPortId, t47.toPortId);
return o2.length > 0 && e2.push({ kind: "same_layer_intersection", regionId: t47.regionId, fromPortId: t47.fromPortId, toPortId: t47.toPortId, owners: o2 }), e2;
}
getPortOwners() {
const t47 = new Map;
for (const e2 of this.state.regionSegments)
for (const [n2, o2, i2] of e2)
for (const e3 of [o2, i2]) {
const o3 = t47.get(e3) ?? new Set;
o3.add(n2), t47.set(e3, o3);
}
return t47;
}
getHardBlockedCrossingOwners(t47, e2, n2) {
if (!this.isKnownSingleLayerRegion(t47))
return [];
const o2 = this.state.currentRouteNetId;
if (o2 === undefined)
throw new Error("SelectiveReripTinyHyperGraphSolver: crossing ownership requires a current route net");
const i2 = new Set;
for (const [r2, s2, a2] of this.state.regionSegments[t47] ?? [])
this.problem.routeNet[r2] !== o2 && this.segmentsCrossOnSameLayer(t47, e2, n2, s2, a2) && i2.add(r2);
return [...i2];
}
segmentsCrossOnSameLayer(t47, e2, n2, o2, i2) {
const r2 = { ...this.populateSegmentGeometryScratch(t47, e2, n2) }, s2 = { ...this.populateSegmentGeometryScratch(t47, o2, i2) };
if ((r2.layerMask & s2.layerMask) === 0)
return false;
if (r2.lesserAngle === s2.lesserAngle || r2.lesserAngle === s2.greaterAngle || r2.greaterAngle === s2.lesserAngle || r2.greaterAngle === s2.greaterAngle)
return false;
return (r2.lesserAngle < s2.lesserAngle && s2.lesserAngle < r2.greaterAngle) !== (r2.lesserAngle < s2.greaterAngle && s2.greaterAngle < r2.greaterAngle);
}
rebuildCommittedState(t47) {
this.state.regionSegments = this.state.regionSegments.map((e2) => e2.filter(([e3]) => !t47.has(e3))), this.state.portAssignment.fill(-1), this.state.regionIntersectionCaches = Array.from({ length: this.topology.regionCount }, () => sH());
for (let t48 = 0;t48 < this.state.regionSegments.length; t48++)
for (const [e2, n2, o2] of this.state.regionSegments[t48]) {
const i2 = this.problem.routeNet[e2];
this.state.currentRouteNetId = i2;
for (const t49 of [n2, o2]) {
const e3 = this.state.portAssignment[t49];
if (e3 !== -1 && e3 !== i2)
throw new Error(`SelectiveReripTinyHyperGraphSolver: rebuilding committed routes found cross-net ownership at port ${t49} between net ${e3} and net ${i2}`);
this.state.portAssignment[t49] = i2;
}
this.appendSegmentToRegionCache(t48, n2, o2);
}
this.state.currentRouteNetId = undefined;
}
incrementFailedOwnerPair(t47, e2) {
const n2 = this.failedOwnerPairCounts.get(t47) ?? new Map, o2 = (n2.get(e2) ?? 0) + 1;
return n2.set(e2, o2), this.failedOwnerPairCounts.set(t47, n2), o2;
}
hasFailedOwnerPath(t47, e2) {
const n2 = [t47], o2 = new Set;
for (;n2.length > 0; ) {
const t48 = n2.pop();
if (t48 === e2)
return true;
o2.has(t48) || (o2.add(t48), n2.push(...this.failedOwnerPairCounts.get(t48)?.keys() ?? []));
}
return false;
}
publishSelectiveReripStats() {
const t47 = [];
for (const [e2, n2] of this.failedOwnerPairCounts)
for (const [o2, i2] of n2)
t47.push({ failedRouteId: e2, ownerRouteId: o2, count: i2 });
t47.sort((t48, e2) => t48.failedRouteId - e2.failedRouteId || t48.ownerRouteId - e2.ownerRouteId), this.selectiveReripStats.failedOwnerPairs = t47, this.selectiveReripStats.failedOwnerPairCount = t47.length, this.selectiveReripStats.maxFailedOwnerPairCount = Math.max(0, ...t47.map(({ count: t48 }) => t48)), this.stats = { ...this.stats, ...this.getSelectiveReripStats() };
}
describeRoute(t47) {
const e2 = this.problem.routeMetadata?.[t47]?.connectionId;
return e2 === undefined ? String(t47) : `${t47} (${String(e2)})`;
}
};
var SG = class extends IG {
initialAssignmentRouteIds;
getRouteIdsPreferredForPreservation() {
return this.initialAssignmentRouteIds || (this.initialAssignmentRouteIds = new Set((this.problem.initialAssignments ?? []).map((t47) => t47.routeId))), this.initialAssignmentRouteIds;
}
resetRoutingStateForRerip() {
super.resetRoutingStateForRerip(), this.problem.initialAssignments?.length && iV({ topology: this.topology, problem: this.problem, state: this.state, routeSuccessCountByRouteId: this.routeSuccessCountByRouteId, appendSegmentToRegionCache: (t47, e2, n2) => this.appendSegmentToRegionCache(t47, e2, n2) });
}
};
var CG = (t47) => {
if (typeof t47 != "object" || t47 === null)
return false;
const e2 = t47, n2 = e2.preloadedTraceSection;
return typeof e2.connectionId == "string" && typeof n2?.traceId == "string" && typeof n2.startRoutePosition == "number" && typeof n2.endRoutePosition == "number" && typeof n2.startPoint?.x == "number" && typeof n2.startPoint.y == "number" && typeof n2.startPoint.z == "number" && typeof n2.endPoint?.x == "number" && typeof n2.endPoint.y == "number" && typeof n2.endPoint.z == "number";
};
var PG = (t47, e2) => `__tscircuit_preloaded_trace__:${JSON.stringify([t47, e2])}`;
var MG = (t47) => [t47.region1Id, t47.region2Id];
var NG = (t47, e2) => {
const n2 = new Set(MG(e2));
return MG(t47).filter((t48) => n2.has(t48));
};
var wG = (t47, e2, n2) => {
const o2 = t47[e2], i2 = t47[e2 + 1], r2 = NG(o2.port, i2.port);
if (r2.length === 0)
return;
if (r2.length === 1)
return r2[0];
const s2 = t47[e2 + 2];
if (s2) {
const t48 = new Set(NG(i2.port, s2.port)), e3 = r2.find((e4) => t48.has(e4));
if (e3)
return e3;
}
return n2 && r2.includes(n2) ? n2 : [...r2].sort()[0];
};
var TG = (t47, e2) => MG(t47).find((t48) => t48 !== e2) ?? e2;
var RG = (t47) => {
const e2 = new Set((t47.connections ?? []).filter(CG).map((t48) => t48.connectionId)), n2 = t47.ports.filter((t48) => (t48.d?._preloadedTracePortAssignments?.length ?? 0) > 0).length, o2 = t47.regions.reduce((t48, n3) => t48 + (n3.assignments ?? []).filter((t49) => e2.has(t49.connectionId)).length, 0);
return { preloadedTraceCount: e2.size, preloadedPortCount: n2, preloadedAssignmentCount: o2 };
};
var EG = (t47) => typeof t47 == "object" && t47 !== null ? t47 : {};
var AG = (t47) => typeof t47 == "object" && t47 !== null ? t47 : {};
var OG = 0.000001;
var kG = { DISTANCE_TO_COST: 0.05, RIP_THRESHOLD_START: 0.05, RIP_THRESHOLD_END: 0.8, RIP_CONGESTION_REGION_COST_FACTOR: 0.1, ACCEPT_BEST_SOLUTION_ON_TIMEOUT: true, GREEDY_FINAL_ROUTE_ITERS: 4, PARTIAL_RIP_MIN_ROUTE_COUNT: 100, PARTIAL_RIP_MAX_ROUTE_COUNT: 350, PARTIAL_RIP_MAX_ATTEMPTS: 7, PARTIAL_RIP_WARMUP_FULL_RIP_ATTEMPTS: 1, PARTIAL_RIP_COMPLEXITY_SELECTION_MIN_ROUTE_COUNT: 100, PARTIAL_RIP_TARGET_MAX_COST_IMPROVEMENT_RATIO: 0.02, PARTIAL_RIP_MAX_REGION_COST_GROWTH_RATIO: 0.05, PARTIAL_RIP_MAX_TOTAL_COST_GROWTH_RATIO: 0.1 };
var DG = { DISTANCE_TO_COST: 0.05, RIP_THRESHOLD_START: 0.05, RIP_THRESHOLD_END: 0.8, RIP_CONGESTION_REGION_COST_FACTOR: 0.1, ACCEPT_BEST_SOLUTION_ON_TIMEOUT: true, GREEDY_FINAL_ROUTE_ITERS: 4, MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT: 6, EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST: Number.POSITIVE_INFINITY };
var LG = (t47) => Math.max(t47, 0.01);
var zG = (t47) => Number.isFinite(t47) ? { minViaPadDiameter: t47 } : {};
var BG = (t47, e2) => {
const n2 = LG(t47);
return { ...kG, ...zG(e2), USE_SPARSE_CANDIDATE_STORAGE: false, RIP_THRESHOLD_RAMP_ATTEMPTS: Math.ceil(10 * n2), MAX_ITERATIONS: Math.ceil(2000000 * n2) };
};
var FG = (t47, e2) => {
const n2 = LG(t47);
return { ...DG, ...zG(e2), USE_SPARSE_CANDIDATE_STORAGE: false, RIP_THRESHOLD_RAMP_ATTEMPTS: Math.ceil(16 * n2), MAX_ITERATIONS: Math.ceil(1e6 * n2) };
};
var jG = (t47) => (t47.solveGraphOptions?.MAX_ITERATIONS ?? 1e6) + (t47.sectionSolverOptions?.MAX_ITERATIONS ?? 1e6) + 1e6;
var $G = (t47) => t47.mutuallyConnectedNetworkId;
var YG = (t47, e2) => t47.simpleRouteConnection?.pointsToConnect[e2];
var XG = (t47) => {
const e2 = YG(t47.routeMetadata, t47.endpointIndex);
if (!e2)
return t47.fallbackZ;
const n2 = So(e2).map((e3) => mo(e3, t47.layerCount));
return t47.regionAvailableZ.find((t48) => n2.includes(t48)) ?? t47.fallbackZ;
};
var WG = (t47, e2) => {
const n2 = t47.d, o2 = n2.bounds;
return { capacityMeshNodeId: t47.d.capacityMeshNodeId, center: { x: t47.d.center.x, y: t47.d.center.y }, width: t47.d.width, height: t47.d.height, availableZ: [...t47.d.availableZ], ...o2 ? { bounds: { minX: o2.minX, maxX: o2.maxX, minY: o2.minY, maxY: o2.maxY } } : {}, _containsObstacle: t47.d._containsObstacle, _containsTarget: t47.d._containsTarget, _offBoardConnectionId: t47.d._offBoardConnectionId, _offBoardConnectedCapacityMeshNodeIds: t47.d._offBoardConnectedCapacityMeshNodeIds === undefined ? undefined : [...t47.d._offBoardConnectedCapacityMeshNodeIds], _qfpRegionType: n2._qfpRegionType, _isNarrowQfpPadGap: n2._isNarrowQfpPadGap, ...e2 !== undefined ? { netId: e2 } : {} };
};
var VG = (t47) => {
const e2 = t47.d;
return { portId: t47.d.portId, x: t47.d.x, y: t47.d.y, z: t47.d.z, prevPortPointId: e2.prevPortPointId, nextPortPointId: e2.nextPortPointId, distToCentermostPortOnZ: t47.d.distToCentermostPortOnZ, tinyHypergraphPortPenalty: t47.d.tinyHypergraphPortPenalty, cramped: t47.d.cramped, _preloadedFixedNetIds: t47.d._preloadedFixedNetIds, _preloadedTracePortAssignments: t47.d._preloadedTracePortAssignments };
};
var HG = (t47) => {
const e2 = function() {
const t48 = new Map;
return (e3) => {
const n3 = e3.mutuallyConnectedNetworkId;
let o3 = t48.get(n3);
return o3 === undefined && (o3 = t48.size, t48.set(n3, o3)), o3;
};
}(), n2 = function(t48) {
const e3 = new Map, n3 = new Set, o3 = new Map;
for (const i4 of t48.params.connections) {
const r3 = i4.mutuallyConnectedNetworkId, s3 = t48.getNetIndex({ connectionId: i4.connectionId, mutuallyConnectedNetworkId: r3 });
for (const t49 of [i4.connectionId, r3])
o3.set(t49, s3);
for (const o4 of i4.simpleRouteConnection.pointsToConnect)
for (const i5 of t48.params.graph.regions) {
if (!hX({ point: o4, region: i5, layerCount: t48.params.layerCount }))
continue;
if (o4.pcb_port_id === undefined && i5.d._containsTarget !== true) {
n3.add(i5.regionId);
continue;
}
let r4 = e3.get(i5.regionId);
r4 || (r4 = new Set, e3.set(i5.regionId, r4)), r4.add(s3);
}
}
for (const n4 of t48.params.graph.regions)
for (const t49 of n4.d._connectedTo ?? []) {
const i4 = o3.get(t49);
if (i4 === undefined)
continue;
let r3 = e3.get(n4.regionId);
r3 || (r3 = new Set, e3.set(n4.regionId, r3)), r3.add(i4);
}
const i3 = new Map;
for (const t49 of n3)
i3.set(t49, -1);
for (const [t49, n4] of e3)
n4.size === 1 && i3.set(t49, [...n4][0]);
return i3;
}({ params: t47, getNetIndex: e2 }), o2 = t47.graph.regions.map((t48) => ({ regionId: t48.regionId, pointIds: t48.ports.map((t49) => t49.d.portId), d: WG(t48, n2.get(t48.regionId)) })), i2 = t47.graph.ports.map((t48) => ({ portId: t48.d.portId, region1Id: t48.region1.regionId, region2Id: t48.region2.regionId, d: VG(t48) })), r2 = t47.connections.map((t48) => ({ connectionId: t48.connectionId, mutuallyConnectedNetworkId: t48.mutuallyConnectedNetworkId, startRegionId: t48.startRegion.regionId, endRegionId: t48.endRegion.regionId, simpleRouteConnection: t48.simpleRouteConnection })), s2 = [];
for (const n3 of t47.connections) {
const r3 = { connectionId: n3.connectionId, mutuallyConnectedNetworkId: n3.mutuallyConnectedNetworkId, simpleRouteConnection: n3.simpleRouteConnection }, a3 = e2(r3), c2 = YG(r3, 0), l2 = YG(r3, 1), h2 = n3.startRegion.d.availableZ[0] ?? 0, d2 = n3.endRegion.d.availableZ[0] ?? 0, u2 = XG({ routeMetadata: r3, endpointIndex: 0, fallbackZ: h2, regionAvailableZ: n3.startRegion.d.availableZ, layerCount: t47.layerCount }), p2 = XG({ routeMetadata: r3, endpointIndex: 1, fallbackZ: d2, regionAvailableZ: n3.endRegion.d.availableZ, layerCount: t47.layerCount }), m2 = `tiny-terminal:start-region:${n3.connectionId}`, g2 = `tiny-terminal:end-region:${n3.connectionId}`, f2 = `tiny-terminal:start-port:${n3.connectionId}`, y2 = `tiny-terminal:end-port:${n3.connectionId}`;
o2.push({ regionId: m2, pointIds: [f2], d: { capacityMeshNodeId: m2, center: { x: c2?.x ?? n3.startRegion.d.center.x, y: c2?.y ?? n3.startRegion.d.center.y }, width: OG, height: OG, availableZ: [u2], _containsTarget: true, _tinyTerminal: true, _tinyTerminalNetId: n3.mutuallyConnectedNetworkId, netId: a3 } }), o2.push({ regionId: g2, pointIds: [y2], d: { capacityMeshNodeId: g2, center: { x: l2?.x ?? n3.endRegion.d.center.x, y: l2?.y ?? n3.endRegion.d.center.y }, width: OG, height: OG, availableZ: [p2], _containsTarget: true, _tinyTerminal: true, _tinyTerminalNetId: n3.mutuallyConnectedNetworkId, netId: a3 } }), i2.push({ portId: f2, region1Id: n3.startRegion.regionId, region2Id: m2, d: { portId: f2, x: c2?.x ?? n3.startRegion.d.center.x, y: c2?.y ?? n3.startRegion.d.center.y, z: u2, distToCentermostPortOnZ: 0, _tinyTerminal: true, ...t47.preserveTerminalPcbPortIds && c2?.pcb_port_id ? { pcb_port_id: c2.pcb_port_id } : {} } }), i2.push({ portId: y2, region1Id: n3.endRegion.regionId, region2Id: g2, d: { portId: y2, x: l2?.x ?? n3.endRegion.d.center.x, y: l2?.y ?? n3.endRegion.d.center.y, z: p2, distToCentermostPortOnZ: 0, _tinyTerminal: true, ...t47.preserveTerminalPcbPortIds && l2?.pcb_port_id ? { pcb_port_id: l2.pcb_port_id } : {} } });
const _2 = o2.find((t48) => t48.regionId === n3.startRegion.regionId), b2 = o2.find((t48) => t48.regionId === n3.endRegion.regionId);
_2?.pointIds.push(f2), b2?.pointIds.push(y2), s2.push({ connection: { connectionId: n3.connectionId }, path: [{ portId: f2 }, { portId: y2 }] });
}
const a2 = { regions: o2, ports: i2, connections: r2, solvedRoutes: s2 };
return ((t48) => {
const e3 = new Map, n3 = new Map, o3 = new Set((t48.connections ?? []).flatMap((t49) => [t49.startRegionId, t49.endRegionId])), i3 = new Set(t48.regions.filter((t49) => {
const e4 = typeof t49.d?.netId == "number" ? t49.d.netId : typeof t49.d?.NetId == "number" ? t49.d.NetId : undefined;
return t49.d?._containsObstacle === true && (e4 === undefined || e4 === -1) && !o3.has(t49.regionId);
}).map((t49) => t49.regionId));
let r3 = 0;
for (const o4 of t48.ports) {
const t49 = o4.d, s4 = t49?._preloadedTracePortAssignments ?? [];
if (s4.length > 0 && r3++, !i3.has(o4.region1Id) && !i3.has(o4.region2Id))
for (const t50 of s4) {
const i4 = n3.get(t50.traceId);
if (i4 !== undefined && i4 !== t50.fixedNetId)
throw new Error(`Preloaded trace "${t50.traceId}" maps to multiple canonical nets`);
n3.set(t50.traceId, t50.fixedNetId);
const r4 = e3.get(t50.traceId) ?? [];
r4.push({ port: o4, assignment: t50 }), e3.set(t50.traceId, r4);
}
}
const s3 = new Map(t48.regions.map((t49) => [t49.regionId, t49])), a3 = t48.connections ??= [], c2 = t48.solvedRoutes ??= [];
for (const [t49, o4] of e3) {
o4.sort((t50, e5) => t50.assignment.routePosition - e5.assignment.routePosition || t50.assignment.z - e5.assignment.z || t50.port.portId.localeCompare(e5.port.portId));
const e4 = o4.filter(({ port: t50 }, e5) => e5 === 0 || t50.portId !== o4[e5 - 1].port.portId);
if (e4.length < 2)
continue;
const i4 = [];
let r4;
for (let t50 = 0;t50 < e4.length - 1; t50++) {
const n4 = e4[t50], o5 = e4[t50 + 1];
if (n4.assignment.z === o5.assignment.z && Math.abs(n4.assignment.routePosition - o5.assignment.routePosition) <= 0.000001) {
r4 = undefined;
continue;
}
const s4 = wG(e4, t50, r4);
s4 ? (i4.push({ regionId: s4, from: n4, to: o5 }), r4 = s4) : r4 = undefined;
}
const d2 = [];
for (const t50 of i4) {
const e5 = d2.at(-1);
e5 && e5.at(-1).to.port.portId === t50.from.port.portId ? e5.push(t50) : d2.push([t50]);
}
for (const [e5, o5] of d2.entries()) {
const i5 = PG(t49, e5);
for (const e6 of o5) {
const n4 = s3.get(e6.regionId);
if (!n4)
throw new Error(`Preloaded trace "${t49}" references missing region "${e6.regionId}"`);
n4.assignments = [...n4.assignments ?? [], { regionPort1Id: e6.from.port.portId, regionPort2Id: e6.to.port.portId, connectionId: i5 }];
}
const r5 = o5[0], l3 = o5.at(-1), d3 = r5.from.port, u2 = l3.to.port, p2 = { connectionId: i5, mutuallyConnectedNetworkId: n3.get(t49) ?? t49, startRegionId: TG(d3, r5.regionId), endRegionId: TG(u2, l3.regionId), preloadedTraceSection: { traceId: t49, startRoutePosition: r5.from.assignment.routePosition, endRoutePosition: l3.to.assignment.routePosition, startPoint: { x: r5.from.assignment.tracePoint.x, y: r5.from.assignment.tracePoint.y, z: r5.from.assignment.z }, endPoint: { x: l3.to.assignment.tracePoint.x, y: l3.to.assignment.tracePoint.y, z: l3.to.assignment.z } } };
a3.push(p2), c2.push({ requiredRip: false, connection: p2, path: [d3, u2].map((t50) => ({ portId: t50.portId, g: 0, h: 0, f: 0, hops: 0, ripRequired: false })) });
}
}
})(a2), a2;
};
var GG = (t47) => {
const e2 = new Map;
for (let n2 = 0;n2 < t47.problem.routeNet.length; n2++) {
const o2 = t47.problem.routeMetadata?.[n2], i2 = o2?.mutuallyConnectedNetworkId;
if (typeof i2 != "string" || i2.length === 0)
throw new Error(`Tiny hypergraph route ${n2} is missing a net ID`);
e2.set(i2, t47.problem.routeNet[n2]);
}
for (let n2 = 0;n2 < t47.problem.regionNetId.length; n2++) {
const o2 = t47.topology.regionMetadata?.[n2]?._tinyTerminalNetId;
if (typeof o2 != "string")
continue;
const i2 = e2.get(o2);
i2 !== undefined && (t47.problem.regionNetId[n2] = i2);
}
};
var UG = (t47) => {
const e2 = new Map;
t47.topology.regionMetadata?.forEach((t48, n3) => {
typeof t48.serializedRegionId == "string" && e2.set(t48.serializedRegionId, n3);
});
const n2 = new Set;
for (const e3 of t47.problem.routeMetadata ?? [])
CG(e3) || (typeof e3.startRegionId == "string" && n2.add(e3.startRegionId), typeof e3.endRegionId == "string" && n2.add(e3.endRegionId));
for (const o2 of t47.problem.routeMetadata ?? [])
if (CG(o2))
for (const i2 of [o2.startRegionId, o2.endRegionId]) {
if (typeof i2 != "string" || n2.has(i2))
continue;
const o3 = e2.get(i2);
if (o3 === undefined)
continue;
const r2 = t47.topology.regionMetadata?.[o3];
typeof r2?.netId == "number" || typeof r2?.NetId == "number" || (t47.problem.regionNetId[o3] = -1);
}
};
var ZG = (t47) => {
if (t47.problem.metadataPortPenaltiesApplied)
return 0;
let e2 = 0, n2 = t47.problem.portPenalty !== undefined;
for (let o3 = 0;o3 < t47.topology.portCount; o3++) {
const i2 = Number(t47.topology.portMetadata?.[o3]?.tinyHypergraphPortPenalty), r2 = Number.isFinite(i2) && i2 > 0 ? i2 : 0;
r2 > 0 && e2++, t47.problem.portPenalty?.[o3] !== r2 && (n2 = false);
}
if (n2)
return t47.problem.metadataPortPenaltiesApplied = true, e2;
e2 = 0;
const o2 = t47.problem.portPenalty ? new Float64Array(t47.problem.portPenalty) : new Float64Array(t47.topology.portCount);
for (let n3 = 0;n3 < t47.topology.portCount; n3++) {
const i2 = Number(t47.topology.portMetadata?.[n3]?.tinyHypergraphPortPenalty);
!Number.isFinite(i2) || i2 <= 0 || (o2[n3] += i2, e2++);
}
return e2 > 0 && (t47.problem.portPenalty = o2), t47.problem.metadataPortPenaltiesApplied = true, e2;
};
var qG = class extends vG {
configuredSolvers = new WeakSet;
duplicatePortPenaltyCount = 0;
metadataPortPenaltyCount = 0;
crampedPortPenaltyCount = 0;
preloadedPortCount = 0;
preloadedFixedSegmentCount = 0;
crampedPortTraversalPenalty;
useSelectiveReripRouting;
constructor(t47, e2) {
super(t47), this.useSelectiveReripRouting = e2, this.crampedPortTraversalPenalty = 150;
const n2 = RG(t47.serializedHyperGraph);
if (this.preloadedPortCount = n2.preloadedPortCount, this.preloadedFixedSegmentCount = n2.preloadedAssignmentCount, e2) {
const t48 = this.pipelineDef.find((t49) => t49.solverName === "solveGraph");
if (!t48)
throw new Error("Tiny hypergraph pipeline is missing the solveGraph stage");
t48.solverClass = SG;
}
this.MAX_ITERATIONS = jG(t47);
}
loadHyperGraph(t47) {
const e2 = super.loadHyperGraph(t47);
((t48, e3) => {
const n3 = new Map;
for (const t49 of e3.connections ?? [])
CG(t49) && n3.set(t49.connectionId, t49.preloadedTraceSection);
for (const e4 of t48.problem.routeMetadata ?? []) {
const t49 = n3.get(e4.connectionId);
t49 && (e4.preloadedTraceSection = t49);
}
})(e2, this.inputProblem.serializedHyperGraph);
const n2 = ZG(e2), { duplicatePortPenaltyCount: o2, crampedPortPenaltyCount: i2 } = ((t48, e3) => {
let n3 = 0, o3 = 0;
const i3 = t48.problem.portPenalty ? new Float64Array(t48.problem.portPenalty) : new Float64Array(t48.topology.portCount);
for (let r2 = 0;r2 < t48.topology.portCount; r2++) {
const s2 = t48.topology.portMetadata?.[r2];
typeof s2?.duplicatedFromPortId == "string" && (i3[r2] += 150, n3++), s2?.cramped && e3 > 0 && (i3[r2] += e3, o3++);
}
return (n3 > 0 || o3 > 0) && (t48.problem.portPenalty = i3), { duplicatePortPenaltyCount: n3, crampedPortPenaltyCount: o3 };
})(e2, this.crampedPortTraversalPenalty);
return GG(e2), UG(e2), this.metadataPortPenaltyCount = Math.max(this.metadataPortPenaltyCount, n2), this.duplicatePortPenaltyCount = Math.max(this.duplicatePortPenaltyCount, o2), this.crampedPortPenaltyCount = Math.max(this.crampedPortPenaltyCount, i2), e2;
}
_step() {
super._step(), this.configureSolver(this.activeSubSolver);
}
getInitialVisualizationSolver() {
if (this.useSelectiveReripRouting && !this.initialVisualizationSolver) {
const { topology: t48, problem: e2 } = this.loadHyperGraph(this.inputProblem.serializedHyperGraph);
this.initialVisualizationSolver = new SG(t48, e2, this.getSolveGraphOptions());
}
const t47 = super.getInitialVisualizationSolver();
return this.configureSolver(t47), t47;
}
getSolvedTinySolver() {
const t47 = this.getSolver("optimizeSection");
if (t47?.solved && !t47.failed)
return t47.getSolvedSolver();
const e2 = this.getSolver("solveGraph");
if (e2?.solved && !e2.failed)
return e2;
throw new Error("TinyHyperGraph section pipeline does not have a solved graph");
}
configureSolver(t47) {
if (t47 && !this.configuredSolvers.has(t47)) {
if (t47 instanceof cG || t47 instanceof uH) {
const e2 = t47;
ZG(e2), GG(e2), UG(e2);
}
this.configuredSolvers.add(t47);
}
}
};
var JG = class extends si {
constructor(t47) {
super(), this.params = t47;
const e2 = ((t48) => t48.map((t49) => {
const e3 = t49.simpleRouteConnection;
if (!e3)
throw new Error(`TinyHypergraphPortPointPathingSolver requires a SimpleRouteConnection for "${t49.connectionId}"`);
const n3 = t49.mutuallyConnectedNetworkId;
if (!n3)
throw new Error(`TinyHypergraphPortPointPathingSolver requires a net ID for "${t49.connectionId}"`);
return { ...t49, mutuallyConnectedNetworkId: n3, simpleRouteConnection: e3 };
}))(t47.connections), n2 = t47.flags.USE_SELECTIVE_RERIP_ROUTING ? function(t48, e3) {
const n3 = new Map;
for (const o3 of t48) {
const t49 = e3(o3);
n3.set(t49, (n3.get(t49) ?? 0) + 1);
}
return t48.map((t49, e4) => ({ connection: t49, index: e4 })).sort((t49, o3) => (n3.get(e3(o3.connection)) ?? 0) - (n3.get(e3(t49.connection)) ?? 0) || t49.index - o3.index).map(({ connection: t49 }) => t49);
}(e2, $G) : e2;
this.rootConnectionNameByConnectionId = new Map(n2.map((t48) => [t48.connectionId, t48.simpleRouteConnection.__rootConnectionNames?.[0]]));
const o2 = HG({ ...t47, connections: n2 });
this.originalPreloadedSegmentKeysByConnectionId = ((t48) => {
const e3 = new Map;
for (const n3 of t48.connections ?? [])
CG(n3) && e3.set(n3.connectionId, new Set);
for (const n3 of t48.regions)
for (const t49 of n3.assignments ?? []) {
const o3 = e3.get(t49.connectionId);
if (!o3)
continue;
const [i3, r3] = [t49.regionPort1Id, t49.regionPort2Id].sort();
o3.add(JSON.stringify([n3.regionId, i3, r3]));
}
return e3;
})(o2);
const i2 = RG(o2), r2 = i2.preloadedPortCount > 0, s2 = r2 && t47.flags.USE_PARTIAL_RIP_ROUTING_WITH_PRELOADED_TRACES === true, a2 = s2 ? Math.max(o2.connections?.length ?? 0, i2.preloadedAssignmentCount) : undefined;
let c2 = o2;
const l2 = new YH(o2, { duplicatePortProximity: 0.05, useSerializedPortPenalties: false, routeSolveOptions: { ...zG(t47.minViaPadDiameter), USE_SPARSE_CANDIDATE_STORAGE: false, ACCEPT_BEST_SOLUTION_ON_TIMEOUT: true, GREEDY_FINAL_ROUTE_ITERS: 4, MAX_ITERATIONS: Math.ceil(2000000 * LG(t47.effort)), RIP_THRESHOLD_RAMP_ATTEMPTS: 0, STATIC_REACHABILITY_PRECHECK: true } });
if (l2.solve(), l2.failed)
this.duplicateCongestedPortError = l2.error ?? "unknown error";
else {
this.duplicateCongestedPortReport = l2.report, c2 = l2.getOutput();
for (const t48 of c2.ports) {
const e3 = AG(t48.d);
typeof e3.duplicatedFromPortId == "string" && (delete e3._preloadedFixedNetIds, delete e3._preloadedTracePortAssignments);
}
}
this.duplicatedPortCount = this.duplicateCongestedPortReport?.duplicatedPorts.reduce((t48, e3) => t48 + e3.duplicatePortIds.length, 0) ?? 0;
const h2 = ((t48, e3, n3, o3 = true, i3) => {
const r3 = t48.connections?.length ?? 0, s3 = i3 ?? r3, a3 = kG.PARTIAL_RIP_MIN_ROUTE_COUNT, c3 = kG.PARTIAL_RIP_MAX_ROUTE_COUNT, l3 = o3 && s3 >= a3 && s3 <= c3;
return { serializedHyperGraph: t48, createSectionMask: ({ topology: t49 }) => new Int8Array(t49.portCount), solveGraphOptions: { ...BG(e3, n3), ...l3 ? { PARTIAL_RIP_MIN_ROUTE_COUNT: 0, PARTIAL_RIP_MAX_ROUTE_COUNT: Number.POSITIVE_INFINITY, PARTIAL_RIP_COMPLEXITY_SELECTION_MIN_ROUTE_COUNT: 0 } : { PARTIAL_RIP_ENABLED: false, OUTSIDE_IN_ROUTING: false } }, sectionSolverOptions: FG(e3, n3) };
})({ ...c2, solvedRoutes: o2.solvedRoutes }, t47.effort, t47.minViaPadDiameter, !r2 || s2, a2);
this.tinyPipelineSolver = new qG(h2, t47.flags.USE_SELECTIVE_RERIP_ROUTING === true), this.primaryTinyPipelineSolver = this.tinyPipelineSolver, n2.length >= 30 && n2.length <= 99 && (this.alternativeTinyPipelineInput = { ...h2, solveGraphOptions: { ...h2.solveGraphOptions, TRACE_DENSITY_COST_FACTOR: 1 } }), this.MAX_ITERATIONS = jG(h2) * (this.alternativeTinyPipelineInput ? 2 : 1), this.originalRegionById = new Map(t47.graph.regions.map((t48) => [t48.regionId, t48])), this.originalRegionIds = new Set(this.originalRegionById.keys()), this.inputNodeWithPortPoints = ((t48, e3) => {
const n3 = new Map(e3.regions.map((t49) => [t49.regionId, t49])), o3 = new Map(e3.ports.map((t49) => [t49.portId, t49]));
return t48.graph.regions.map((t49) => {
const e4 = n3.get(t49.regionId), i3 = (e4?.pointIds ?? t49.ports.map((t50) => t50.d.portId)).map((t50) => o3.get(t50)).filter((t50) => t50 && !AG(t50.d)._tinyTerminal).map((t50) => {
const e5 = t50, o4 = AG(e5.d), i4 = n3.get(e5.region1Id), r3 = n3.get(e5.region2Id), s3 = Boolean(EG(i4?.d)._offBoardConnectionId ?? EG(r3?.d)._offBoardConnectionId);
return { portPointId: e5.portId, x: Number(o4.x ?? 0), y: Number(o4.y ?? 0), z: Number(o4.z ?? 0), prevPortPointId: typeof o4.prevPortPointId == "string" ? o4.prevPortPointId : undefined, nextPortPointId: typeof o4.nextPortPointId == "string" ? o4.nextPortPointId : undefined, connectionNodeIds: [e5.region1Id, e5.region2Id], distToCentermostPortOnZ: Number(o4.distToCentermostPortOnZ ?? 0), cramped: Boolean(o4.cramped), connectsToOffBoardNode: s3 };
});
return { capacityMeshNodeId: t49.d.capacityMeshNodeId, center: t49.d.center, width: t49.d.width, height: t49.d.height, portPoints: i3, availableZ: t49.d.availableZ, _containsObstacle: t49.d._containsObstacle, _containsTarget: t49.d._containsTarget, _offBoardConnectionId: t49.d._offBoardConnectionId, _offBoardConnectedCapacityMeshNodeIds: t49.d._offBoardConnectedCapacityMeshNodeIds, _qfpRegionType: t49.d._qfpRegionType, _isNarrowQfpPadGap: t49.d._isNarrowQfpPadGap };
});
})(t47, c2);
}
tinyPipelineSolver;
primaryTinyPipelineSolver;
alternativeTinyPipelineSolver;
alternativeTinyPipelineInput;
candidatePortfolioPhase = "primary";
primaryCandidateSummary;
alternativeCandidateSummary;
alternativeCandidateEvaluated = false;
selectedCandidate = "primary";
duplicateCongestedPortReport;
duplicateCongestedPortError;
duplicatedPortCount = 0;
inputNodeWithPortPoints;
originalRegionById;
originalRegionIds;
rootConnectionNameByConnectionId;
originalPreloadedSegmentKeysByConnectionId;
getSolverName() {
return "TinyHypergraphPortPointPathingSolver";
}
getChangedPreloadedRouteIds(t47) {
const e2 = new Map, n2 = new Map;
for (let o3 = 0;o3 < t47.problem.routeCount; o3++) {
const i2 = this.getRouteMetadata(t47, o3);
CG(i2) && (e2.set(i2.connectionId, o3), n2.set(o3, new Set));
}
for (let e3 = 0;e3 < t47.state.regionSegments.length; e3++) {
const o3 = t47.topology.regionMetadata?.[e3]?.serializedRegionId;
for (const [i2, r2, s2] of t47.state.regionSegments[e3] ?? []) {
const e4 = n2.get(i2);
if (!e4)
continue;
const a2 = t47.topology.portMetadata?.[r2]?.serializedPortId, c2 = t47.topology.portMetadata?.[s2]?.serializedPortId;
if (typeof o3 != "string" || typeof a2 != "string" || typeof c2 != "string")
throw new Error(`Tiny hypergraph preloaded route ${i2} has a segment without serialized topology IDs`);
const [l2, h2] = [a2, c2].sort();
e4.add(JSON.stringify([o3, l2, h2]));
}
}
const o2 = new Set;
for (const [t48, i2] of this.originalPreloadedSegmentKeysByConnectionId) {
const r2 = e2.get(t48);
if (r2 === undefined)
throw new Error(`Tiny hypergraph lost preloaded trace section "${t48}"`);
const s2 = n2.get(r2);
if (i2.size > 0 && s2.size === 0)
throw new Error(`Tiny hypergraph lost preloaded trace section "${t48}"`);
(i2.size !== s2.size || [...i2].some((t49) => !s2.has(t49))) && o2.add(r2);
}
return o2;
}
summarizePipelineCandidate(t47) {
const e2 = t47.getSolvedTinySolver();
let n2 = 0, o2 = 0, i2 = 0, r2 = 0, s2 = 0, a2 = 0;
const c2 = e2.topology.regionMetadata ?? [];
for (let t48 = 0;t48 < e2.state.regionSegments.length; t48++) {
const l2 = e2.state.regionSegments[t48];
s2 += l2.length;
for (const [, t49, n3] of l2)
e2.topology.portZ[t49] !== e2.topology.portZ[n3] && (a2 += 1);
const h2 = c2[t48]?.capacityMeshNodeId;
if (!h2 || !this.originalRegionIds.has(h2))
continue;
const d2 = this.originalRegionById.get(h2);
if (!d2 || l2.length === 0)
continue;
const u2 = l2.map(([t49, n3, o3]) => [this.createAssignedPortPoint(e2, t49, n3), this.createAssignedPortPoint(e2, t49, o3)]), p2 = { capacityMeshNodeId: d2.d.capacityMeshNodeId, center: d2.d.center, width: d2.d.width, height: d2.d.height, portPoints: u2.flat(), availableZ: d2.d.availableZ }, m2 = IO(p2), g2 = BO(d2.d, m2.numSameLayerCrossings, m2.numEntryExitLayerChanges, m2.numTransitionPairCrossings);
n2 += g2, o2 += g2 * g2, i2 = Math.max(i2, g2), r2 += p2.portPoints.length ** 2;
}
return { nodePfSum: n2, nodePfSquaredSum: o2, nodePfMax: i2, squaredNodePortPointCount: r2, segmentCount: s2, layerChangeCount: a2, changedPreloadedTraceSectionCount: this.getChangedPreloadedRouteIds(e2).size };
}
shouldEvaluateAlternative(t47) {
const e2 = this.primaryTinyPipelineSolver.getSolvedTinySolver().problem.routeCount;
return this.alternativeTinyPipelineInput !== undefined && ((t48, e3) => t48.nodePfSum > 4 && t48.nodePfMax > 1 && t48.squaredNodePortPointCount / Math.max(1, e3) >= 125)(t47, e2);
}
shouldSelectAlternative(t47, e2) {
return ((t48, e3, n2) => {
if (e3.changedPreloadedTraceSectionCount > t48.changedPreloadedTraceSectionCount)
return false;
const o2 = n2 > 40 ? 0.92 : 0.95, i2 = e3.nodePfSum <= 0.9 * t48.nodePfSum && e3.nodePfSquaredSum <= 0.85 * t48.nodePfSquaredSum && e3.nodePfMax <= 0.85 * t48.nodePfMax && e3.squaredNodePortPointCount < 0.98 * t48.squaredNodePortPointCount && e3.segmentCount <= 0.97 * t48.segmentCount;
return e3.nodePfSum <= 1.03 * t48.nodePfSum && e3.nodePfSquaredSum <= 1.06 * t48.nodePfSquaredSum && (e3.squaredNodePortPointCount < t48.squaredNodePortPointCount * o2 || i2);
})(t47, e2, this.primaryTinyPipelineSolver.getSolvedTinySolver().problem.routeCount);
}
finishCandidatePortfolio() {
this.candidatePortfolioPhase = "complete", this.solved = this.tinyPipelineSolver.solved, this.failed = this.tinyPipelineSolver.failed, this.error = this.tinyPipelineSolver.error ?? null;
}
getSolveGraphBenchmarkMetrics() {
const t47 = this.tinyPipelineSolver.getSolver("solveGraph");
if (!t47)
return;
const e2 = t47.state.regionSegments.map((t48) => t48.length), n2 = this.selectedCandidate === "alternative" ? this.alternativeCandidateSummary : this.primaryCandidateSummary, o2 = t47.stats, i2 = this.tinyPipelineSolver.getStageStats().solveGraph;
return { routeCount: t47.problem.routeCount, traceDensityCandidateEvaluated: this.alternativeCandidateEvaluated, traceDensityCandidateSelected: this.selectedCandidate === "alternative", downstreamNodePfSum: n2?.nodePfSum, downstreamNodePfSquaredSum: n2?.nodePfSquaredSum, downstreamNodePfMax: n2?.nodePfMax, downstreamSquaredNodePortPointCount: n2?.squaredNodePortPointCount, changedPreloadedTraceSectionCount: n2?.changedPreloadedTraceSectionCount, iterations: t47.iterations, timeMs: i2?.timeSpent, ripCount: o2.ripCount, partialRipCount: o2.partialRipCount, partiallyRippedRouteCount: o2.partiallyRippedRouteCount, partiallyRippedSegmentCount: o2.partiallyRippedSegmentCount, retainedPartialRipSegmentCount: o2.retainedPartialRipSegmentCount, firstMaxRegionCost: o2.firstMaxRegionCost, bestMaxRegionCost: o2.bestMaxRegionCost, firstTotalRegionCost: o2.firstTotalRegionCost, bestTotalRegionCost: o2.bestTotalRegionCost, firstSegmentCount: o2.firstSegmentCount, bestSolvedSegmentCount: o2.bestSolvedSegmentCount, bestSolvedMaxRegionSegmentCount: o2.bestSolvedMaxRegionSegmentCount, bestSolvedSquaredRegionSegmentCount: o2.bestSolvedSquaredRegionSegmentCount, finalMaxRegionSegmentCount: Math.max(0, ...e2), finalSquaredRegionSegmentCount: e2.reduce((t48, e3) => t48 + e3 * e3, 0), finalSegmentCount: n2?.segmentCount, finalLayerChangeCount: n2?.layerChangeCount, warmupFullRipAttempts: o2.partialRipWarmupFullRipAttempts, complexityAwareSelection: o2.partialRipComplexityAwareSelection, targetReached: o2.partialRipTargetReached, outsideInCompletedRouteCount: o2.outsideInCompletedRouteCount, outsideInFallbackRouteCount: o2.outsideInFallbackRouteCount, outsideInForwardExpansionCount: o2.outsideInForwardExpansionCount, outsideInReverseExpansionCount: o2.outsideInReverseExpansionCount };
}
_step() {
this.tinyPipelineSolver.step(), this.candidatePortfolioPhase === "primary" && this.primaryTinyPipelineSolver.failed ? (this.alternativeTinyPipelineInput = undefined, this.finishCandidatePortfolio()) : this.candidatePortfolioPhase === "primary" && this.primaryTinyPipelineSolver.solved ? (this.primaryCandidateSummary = this.summarizePipelineCandidate(this.primaryTinyPipelineSolver), this.shouldEvaluateAlternative(this.primaryCandidateSummary) ? (this.alternativeCandidateEvaluated = true, this.alternativeTinyPipelineSolver = new qG(this.alternativeTinyPipelineInput, this.params.flags.USE_SELECTIVE_RERIP_ROUTING === true), this.tinyPipelineSolver = this.alternativeTinyPipelineSolver, this.candidatePortfolioPhase = "alternative") : (this.alternativeTinyPipelineInput = undefined, this.finishCandidatePortfolio())) : this.candidatePortfolioPhase === "alternative" && (this.tinyPipelineSolver.solved || this.tinyPipelineSolver.failed) && (this.tinyPipelineSolver.solved && !this.tinyPipelineSolver.failed && (this.alternativeCandidateSummary = this.summarizePipelineCandidate(this.tinyPipelineSolver)), this.alternativeCandidateSummary && this.primaryCandidateSummary && this.shouldSelectAlternative(this.primaryCandidateSummary, this.alternativeCandidateSummary) ? (this.selectedCandidate = "alternative", this.primaryTinyPipelineSolver = undefined, this.alternativeTinyPipelineSolver = undefined) : (this.tinyPipelineSolver = this.primaryTinyPipelineSolver, this.alternativeTinyPipelineSolver = undefined), this.alternativeTinyPipelineInput = undefined, this.finishCandidatePortfolio());
const t47 = this.tinyPipelineSolver.getSolver("optimizeSection"), e2 = this.getCurrentTinySolver();
this.solved = this.candidatePortfolioPhase === "complete" && this.tinyPipelineSolver.solved, this.failed = this.candidatePortfolioPhase === "complete" && this.tinyPipelineSolver.failed, this.error = this.failed ? this.tinyPipelineSolver.error ?? null : null, this.progress = this.candidatePortfolioPhase === "complete" ? 1 : this.candidatePortfolioPhase === "alternative" ? 0.5 + 0.5 * this.tinyPipelineSolver.progress : this.alternativeTinyPipelineInput ? 0.5 * this.tinyPipelineSolver.progress : this.tinyPipelineSolver.progress, this.stats = { duplicateCongestedPortSourceCount: this.duplicateCongestedPortReport?.duplicatedPorts.length ?? 0, duplicateCongestedPortCount: this.duplicatedPortCount, duplicateCongestedPortFallbackToOriginal: Boolean(this.duplicateCongestedPortError), duplicateCongestedPortPenalty: this.duplicatedPortCount > 0 ? 150 : 0, duplicateCongestedPortPenaltyCount: this.tinyPipelineSolver.duplicatePortPenaltyCount, metadataPortPenaltyCount: this.tinyPipelineSolver.metadataPortPenaltyCount, crampedPortPenalty: this.tinyPipelineSolver.crampedPortTraversalPenalty, crampedPortPenaltyCount: this.tinyPipelineSolver.crampedPortPenaltyCount, preloadedPortCount: this.tinyPipelineSolver.preloadedPortCount, preloadedFixedSegmentCount: this.tinyPipelineSolver.preloadedFixedSegmentCount, duplicateCongestedPortError: this.duplicateCongestedPortError, candidatePortfolioPhase: this.candidatePortfolioPhase, candidatePortfolioSelectedCandidate: this.selectedCandidate, candidatePortfolioPrimarySummary: this.primaryCandidateSummary, candidatePortfolioAlternativeSummary: this.alternativeCandidateSummary, ...this.tinyPipelineSolver.stats ?? {}, ...e2?.stats ?? {}, ...t47?.stats ?? {}, currentStage: this.tinyPipelineSolver.getCurrentStageName(), stageStats: this.tinyPipelineSolver.getStageStats() }, this.activeSubSolver = this.tinyPipelineSolver.activeSubSolver ?? null;
}
preview() {
return this.visualize();
}
getCurrentTinySolver() {
const t47 = this.tinyPipelineSolver.getSolver("optimizeSection");
if (t47?.solved && !t47.failed)
return t47.getSolvedSolver();
const e2 = this.tinyPipelineSolver.getSolver("solveGraph");
return e2 || undefined;
}
getSolvedTinySolver() {
return this.tinyPipelineSolver.getSolvedTinySolver();
}
getRouteMetadata(t47, e2) {
return t47.problem.routeMetadata?.[e2];
}
createAssignedPortPoint(t47, e2, n2) {
const o2 = this.getRouteMetadata(t47, e2), i2 = o2 ? ((t48) => t48.simpleRouteConnection?.name ?? t48.connectionId)(o2) : `route-${e2}`, r2 = o2 ? this.rootConnectionNameByConnectionId.get(o2.connectionId) ?? o2.mutuallyConnectedNetworkId : undefined, s2 = t47.topology.portMetadata?.[n2];
return { portPointId: String(s2?.serializedPortId ?? s2?.portId ?? `tiny-port-${n2}`), x: t47.topology.portX[n2], y: t47.topology.portY[n2], z: t47.topology.portZ[n2], connectionName: i2, rootConnectionName: r2, ...this.params.preserveTerminalPcbPortIds && typeof s2?.pcb_port_id == "string" ? { pcb_port_id: s2.pcb_port_id } : {}, prevPortPointId: typeof s2?.prevPortPointId == "string" ? s2.prevPortPointId : undefined, nextPortPointId: typeof s2?.nextPortPointId == "string" ? s2.nextPortPointId : undefined };
}
getOutput() {
const t47 = this.getSolvedTinySolver(), e2 = [], n2 = t47.state.regionSegments, o2 = t47.topology.regionMetadata ?? [], i2 = this.getChangedPreloadedRouteIds(t47);
for (let r3 = 0;r3 < n2.length; r3++) {
const s2 = o2[r3]?.capacityMeshNodeId;
if (!s2 || !this.originalRegionIds.has(s2))
continue;
const a2 = this.originalRegionById.get(s2);
if (!a2)
continue;
const c2 = n2[r3].filter(([e3]) => {
const n3 = this.getRouteMetadata(t47, e3);
return !CG(n3) || i2.has(e3);
}).map(([e3, n3, o3]) => {
const i3 = this.createAssignedPortPoint(t47, e3, n3), r4 = this.createAssignedPortPoint(t47, e3, o3);
return i3.portPointId && r4.portPointId && (i3.nextPortPointId = r4.portPointId, r4.prevPortPointId = i3.portPointId), [i3, r4];
}), l2 = c2.flat();
l2.length !== 0 && e2.push({ capacityMeshNodeId: a2.d.capacityMeshNodeId, center: a2.d.center, width: a2.d.width, height: a2.d.height, portPoints: l2, portPointsInPairs: c2, availableZ: a2.d.availableZ });
}
const r2 = [...i2].map((e3) => {
const n3 = this.getRouteMetadata(t47, e3);
if (!CG(n3))
throw new Error(`Changed preloaded hypergraph route ${e3} is missing section metadata`);
const o3 = n3.preloadedTraceSection;
return { connectionName: n3.connectionId, traceId: o3.traceId, startRoutePosition: o3.startRoutePosition, endRoutePosition: o3.endRoutePosition, connection: { name: n3.connectionId, __rootConnectionNames: [n3.mutuallyConnectedNetworkId], pointsToConnect: [{ x: o3.startPoint.x, y: o3.startPoint.y, layer: Co(o3.startPoint.z, this.params.layerCount) }, { x: o3.endPoint.x, y: o3.endPoint.y, layer: Co(o3.endPoint.z, this.params.layerCount) }] } };
});
return this.stats.changedPreloadedTraceSectionCount = r2.length, { nodesWithPortPoints: e2, inputNodeWithPortPoints: this.inputNodeWithPortPoints, changedPreloadedTraceSections: r2 };
}
computeNodePf(t47) {
const e2 = this.getOutput().nodesWithPortPoints.find((e3) => e3.capacityMeshNodeId === t47.capacityMeshNodeId);
return this.computeSolvedNodePf(t47.capacityMeshNodeId, e2);
}
computeNodePfMap() {
const t47 = new Map(this.getOutput().nodesWithPortPoints.map((t48) => [t48.capacityMeshNodeId, t48]));
return new Map(this.inputNodeWithPortPoints.map((e2) => [e2.capacityMeshNodeId, this.computeSolvedNodePf(e2.capacityMeshNodeId, t47.get(e2.capacityMeshNodeId))]));
}
computeSolvedNodePf(t47, e2) {
const n2 = this.originalRegionById.get(t47);
if (!e2 || !n2)
return null;
const o2 = IO(e2);
return BO(n2.d, o2.numSameLayerCrossings, o2.numEntryExitLayerChanges, o2.numTransitionPairCrossings);
}
tryFinalAcceptance() {}
getConstructorParams() {
return [this.params];
}
visualize() {
return this.tinyPipelineSolver.visualize();
}
};
var QG = (t47, e2) => {
if (!t47 || t47 === "none")
return t47;
try {
const n2 = gt(t47);
return `rgba(${n2.red},${n2.green},${n2.blue},${e2})`;
} catch {
return Ao(t47, 1 - e2);
}
};
var KG = ({ srj: t47, opacity: e2 = 0.25, visualizationOptions: n2 = {} }) => {
const o2 = Ho({ ...t47, obstacles: [] }, n2);
return { ...o2, points: [], lines: o2.lines?.map((t48) => ({ ...t48, strokeColor: QG(t48.strokeColor, e2) })), rects: o2.rects?.map((t48) => ({ ...t48, fill: QG(t48.fill, e2), stroke: QG(t48.stroke, e2) })), circles: o2.circles?.map((t48) => ({ ...t48, fill: QG(t48.fill, e2), stroke: QG(t48.stroke, e2) })) };
};
function tU(t47, e2) {
return t47.x >= e2.center.x - e2.width / 2 && t47.x <= e2.center.x + e2.width / 2 && t47.y >= e2.center.y - e2.height / 2 && t47.y <= e2.center.y + e2.height / 2;
}
var eU = "escape-via:";
var nU = 0.0001;
var oU = (t47) => t47.obstacleId ?? [t47.layers.join("."), t47.center.x.toFixed(4), t47.center.y.toFixed(4), t47.width.toFixed(4), t47.height.toFixed(4)].join(":");
var iU = (t47, e2, n2 = 0.0001) => xe(t47, e2) <= n2;
var rU = class extends si {
constructor(t47, e2 = {}) {
super(), this.ogSrj = t47, this.viaDiameter = e2.viaDiameter ?? Yo(t47).padDiameter, this.viaRadius = this.viaDiameter / 2, this.minTraceWidth = e2.minTraceWidth ?? t47.minTraceWidth, this.obstacleMargin = e2.obstacleMargin ?? t47.defaultObstacleMargin ?? 0.15, this.requiredViaToPadClearance = Math.max(this.obstacleMargin, t47.minViaEdgeToPadEdgeClearance ?? 0), this.escapeOffset = this.viaRadius + Math.max(this.minTraceWidth / 2, this.requiredViaToPadClearance), this.requiredTraceClearance = this.minTraceWidth / 2 + this.obstacleMargin / 2, this.requiredViaToViaClearance = this.viaDiameter + this.obstacleMargin, this.outputSrj = t47, this.escapeViaMetadataByPointId = new Map, this.createdEscapeVias = [];
}
getSolverName() {
return "EscapeViaLocationSolver";
}
viaDiameter;
viaRadius;
minTraceWidth;
obstacleMargin;
escapeOffset;
requiredTraceClearance;
requiredViaToPadClearance;
requiredViaToViaClearance;
outputSrj;
escapeViaMetadataByPointId;
createdEscapeVias;
nextEscapeViaIndex = 0;
getConnectionNetIds(t47) {
return new Set([t47.name, ...t47.__rootConnectionNames ?? [], t47.__netConnectionName].filter((t48) => Boolean(t48)));
}
obstacleMatchesConnectionNet(t47, e2) {
return t47.connectedTo.some((t48) => e2.has(t48));
}
getObstacleZs(t47) {
return t47.__zLayers && t47.__zLayers.length > 0 ? t47.__zLayers : t47.layers.map((t48) => mo(t48, this.ogSrj.layerCount));
}
getViaSpanLayers(t47, e2) {
const n2 = mo(t47, this.ogSrj.layerCount), o2 = mo(e2, this.ogSrj.layerCount), i2 = Math.min(n2, o2), r2 = Math.max(n2, o2), s2 = Array.from({ length: r2 - i2 + 1 }, (t48, e3) => i2 + e3);
return { __zLayers: s2, layers: s2.map((t48) => Co(t48, this.ogSrj.layerCount)) };
}
createEscapeViaObstacle(t47) {
const { escapeVia: e2, connectionNetIds: n2 } = t47, { layers: o2, __zLayers: i2 } = this.getViaSpanLayers(e2.sourceLayer, e2.targetLayer);
return { obstacleId: `escape-via-obstacle:${e2.pointId}`, type: "rect", layers: o2, __zLayers: i2, center: { x: e2.x, y: e2.y }, width: this.viaDiameter, height: this.viaDiameter, connectedTo: Array.from(n2) };
}
selectSourceObstacle(t47) {
const { point: e2, sourceLayer: n2, connectionNetIds: o2 } = t47;
return this.ogSrj.obstacles.filter((t48) => !t48.isCopperPour && t48.layers.includes(n2) && tU(e2, t48)).sort((t48, n3) => {
const i2 = t48.connectedTo.includes(e2.pointId ?? "") || t48.connectedTo.includes(e2.pcb_port_id ?? "") || this.obstacleMatchesConnectionNet(t48, o2);
return i2 !== (n3.connectedTo.includes(e2.pointId ?? "") || n3.connectedTo.includes(e2.pcb_port_id ?? "") || this.obstacleMatchesConnectionNet(n3, o2)) ? i2 ? -1 : 1 : t48.width * t48.height - n3.width * n3.height;
})[0];
}
getCandidatePositions(t47, e2) {
if (!e2)
return this.dedupeCandidatePositions([{ x: t47.x + this.escapeOffset, y: t47.y }, { x: t47.x - this.escapeOffset, y: t47.y }, { x: t47.x, y: t47.y + this.escapeOffset }, { x: t47.x, y: t47.y - this.escapeOffset }, { x: t47.x + this.escapeOffset, y: t47.y + this.escapeOffset }, { x: t47.x + this.escapeOffset, y: t47.y - this.escapeOffset }, { x: t47.x - this.escapeOffset, y: t47.y + this.escapeOffset }, { x: t47.x - this.escapeOffset, y: t47.y - this.escapeOffset }]);
const n2 = e2.center.x - e2.width / 2, o2 = e2.center.x + e2.width / 2, i2 = e2.center.y - e2.height / 2, r2 = e2.center.y + e2.height / 2, s2 = n2 - this.escapeOffset, a2 = o2 + this.escapeOffset, c2 = i2 - this.escapeOffset, l2 = r2 + this.escapeOffset, h2 = this.getEdgeSamples(i2, r2, t47.y), d2 = this.getEdgeSamples(n2, o2, t47.x), u2 = [];
for (const t48 of h2)
u2.push({ x: s2, y: t48 }, { x: a2, y: t48 });
for (const t48 of d2)
u2.push({ x: t48, y: c2 }, { x: t48, y: l2 });
return this.dedupeCandidatePositions(u2);
}
dedupeCandidatePositions(t47) {
const e2 = [];
for (const n2 of t47)
e2.some((t48) => iU(t48, n2)) || e2.push(n2);
return e2;
}
pushEdgeSample(t47, e2, n2, o2) {
const i2 = Math.max(n2, Math.min(o2, e2));
t47.some((t48) => Math.abs(t48 - i2) <= nU) || t47.push(i2);
}
getEdgeSamples(t47, e2, n2) {
const o2 = [], i2 = e2 - t47;
if (this.pushEdgeSample(o2, n2, t47, e2), i2 <= nU)
return o2;
this.pushEdgeSample(o2, t47, t47, e2), this.pushEdgeSample(o2, e2, t47, e2), this.pushEdgeSample(o2, (t47 + e2) / 2, t47, e2);
const r2 = Math.max(t47, Math.min(e2, n2)), s2 = Math.max(this.requiredViaToViaClearance, nU), a2 = Math.ceil(i2 / s2);
for (let n3 = 1;n3 <= a2; n3++) {
const i3 = n3 * s2;
this.pushEdgeSample(o2, r2 + i3, t47, e2), this.pushEdgeSample(o2, r2 - i3, t47, e2);
}
return o2;
}
isInsideBoard(t47) {
return !!(t47.x >= this.ogSrj.bounds.minX + this.viaRadius && t47.x <= this.ogSrj.bounds.maxX - this.viaRadius && t47.y >= this.ogSrj.bounds.minY + this.viaRadius && t47.y <= this.ogSrj.bounds.maxY - this.viaRadius) && (!(this.ogSrj.outline && this.ogSrj.outline.length >= 3) || Ok(t47, this.ogSrj.outline));
}
hasClearEscapePath(t47) {
const { sourcePoint: e2, candidate: n2, sourceLayer: o2, sourceObstacle: i2 } = t47;
if (this.ogSrj.outline && this.ogSrj.outline.length >= 3) {
if (kk({ start: e2, end: n2, polygon: this.ogSrj.outline, margin: this.requiredTraceClearance }))
return false;
}
for (const t48 of this.ogSrj.obstacles) {
if (t48 === i2)
continue;
if (!t48.layers.includes(o2))
continue;
if (tU(n2, t48))
return false;
const r2 = xL(t48);
if (Math.min(...r2.map((t49) => Mk(e2, n2, t49.start, t49.end))) + nU < this.requiredTraceClearance)
return false;
}
return true;
}
getBoardBoundarySegments() {
if (this.ogSrj.outline && this.ogSrj.outline.length >= 3)
return this.ogSrj.outline.map((t48, e3) => ({ start: t48, end: this.ogSrj.outline[(e3 + 1) % this.ogSrj.outline.length] }));
const { minX: t47, maxX: e2, minY: n2, maxY: o2 } = this.ogSrj.bounds;
return [{ start: { x: t47, y: n2 }, end: { x: e2, y: n2 } }, { start: { x: e2, y: n2 }, end: { x: e2, y: o2 } }, { start: { x: e2, y: o2 }, end: { x: t47, y: o2 } }, { start: { x: t47, y: o2 }, end: { x: t47, y: n2 } }];
}
getRayProbeDistance() {
const { minX: t47, maxX: e2, minY: n2, maxY: o2 } = this.ogSrj.bounds;
return 2 * Math.hypot(e2 - t47, o2 - n2) + this.viaDiameter;
}
getRayIntersectionDistance(t47) {
const { rayStart: e2, rayEnd: n2, segmentStart: o2, segmentEnd: i2 } = t47;
if (!fe(e2, n2, o2, i2))
return null;
const r2 = ve(e2, n2, o2, i2);
if (!r2)
return null;
const s2 = xe(e2, r2);
return s2 <= nU ? null : s2;
}
getProjectedFreeSpace(t47) {
const { sourcePoint: e2, candidate: n2 } = t47, o2 = n2.x - e2.x, i2 = n2.y - e2.y;
return Math.abs(o2) <= nU || Math.abs(i2) <= nU ? this.getProjectedFreeSpaceAlongDirection({ ...t47, direction: { x: o2, y: i2 }, travelDistance: xe(e2, n2) }) : Math.min(this.getProjectedFreeSpaceAlongDirection({ ...t47, direction: { x: 0, y: Math.sign(i2) }, travelDistance: Math.abs(i2) }), this.getProjectedFreeSpaceAlongDirection({ ...t47, direction: { x: Math.sign(o2), y: Math.sign(i2) }, travelDistance: xe(e2, n2) }), this.getProjectedFreeSpaceAlongDirection({ ...t47, direction: { x: Math.sign(o2), y: 0 }, travelDistance: Math.abs(o2) }));
}
getProjectedFreeSpaceAlongDirection(t47) {
const { sourcePoint: e2, sourceLayer: n2, sourceObstacle: o2, direction: i2, travelDistance: r2 } = t47, s2 = Math.hypot(i2.x, i2.y);
if (s2 <= nU || r2 <= nU)
return 0;
const a2 = this.getRayProbeDistance(), c2 = i2.x / s2, l2 = i2.y / s2, h2 = { x: e2.x + c2 * a2, y: e2.y + l2 * a2 };
let d2 = Number.POSITIVE_INFINITY;
for (const t48 of this.ogSrj.obstacles)
if (t48 !== o2 && t48.layers.includes(n2))
for (const n3 of xL(t48)) {
const t49 = this.getRayIntersectionDistance({ rayStart: e2, rayEnd: h2, segmentStart: n3.start, segmentEnd: n3.end });
t49 !== null && (d2 = Math.min(d2, t49));
}
for (const t48 of this.getBoardBoundarySegments()) {
const n3 = this.getRayIntersectionDistance({ rayStart: e2, rayEnd: h2, segmentStart: t48.start, segmentEnd: t48.end });
n3 !== null && (d2 = Math.min(d2, n3));
}
return Number.isFinite(d2) ? Math.max(0, d2 - r2) : 0;
}
getMinBlockingClearance(t47) {
const { candidate: e2, connectionNetIds: n2, sourceZ: o2, targetZ: i2 } = t47, r2 = Math.min(o2, i2), s2 = Math.max(o2, i2);
let a2 = Number.POSITIVE_INFINITY;
for (const t48 of this.ogSrj.obstacles) {
const n3 = this.getObstacleZs(t48);
if (!n3.some((t49) => t49 >= r2 && t49 <= s2))
continue;
if (t48.isCopperPour && !n3.includes(o2))
continue;
const i3 = Fe(e2, t48) - this.viaRadius;
if (a2 = Math.min(a2, i3), a2 + nU < this.requiredViaToPadClearance)
return a2;
}
return a2;
}
getMinPlacedEscapeViaClearance(t47) {
let e2 = Number.POSITIVE_INFINITY;
for (const n2 of this.createdEscapeVias) {
const o2 = xe(t47, n2) - this.viaDiameter;
if (e2 = Math.min(e2, o2), e2 + nU < this.obstacleMargin)
return e2;
}
return e2;
}
selectPointOwner(t47) {
const { point: e2, groupConnections: n2, matchingCopperPours: o2 } = t47, i2 = ck(e2), r2 = n2.map((t48) => ({ connection: t48, pointIndex: t48.pointsToConnect.findIndex((t49) => ck(t49) === i2) })).filter((t48) => t48.pointIndex !== -1);
return r2.length === 0 ? null : (r2.sort((t48, e3) => {
const n3 = o2.some((e4) => this.obstacleMatchesConnectionNet(e4, this.getConnectionNetIds(t48.connection)));
return n3 !== o2.some((t49) => this.obstacleMatchesConnectionNet(t49, this.getConnectionNetIds(e3.connection))) ? n3 ? -1 : 1 : t48.pointIndex - e3.pointIndex;
}), r2[0]);
}
findBestEscapeViaCandidate(t47) {
const { connection: e2, point: n2, pointIndex: o2, matchingCopperPours: i2, connectionNetIds: r2, sourceObstacle: s2 } = t47;
if (!vo(n2))
return null;
const a2 = n2.layer, c2 = mo(a2, this.ogSrj.layerCount), l2 = s2 ?? this.selectSourceObstacle({ point: n2, sourceLayer: a2, connectionNetIds: r2 }), h2 = this.getCandidatePositions(n2, l2);
let d2 = null;
for (const t48 of i2) {
const i3 = t48.layers[0];
if (!i3 || i3 === a2)
continue;
const s3 = mo(i3, this.ogSrj.layerCount), u2 = oU(t48);
for (const p2 of h2) {
if (!this.isInsideBoard(p2))
continue;
if (!tU(p2, t48))
continue;
if (!this.hasClearEscapePath({ sourcePoint: n2, candidate: p2, sourceLayer: a2, sourceObstacle: l2 }))
continue;
const h3 = this.getMinBlockingClearance({ candidate: p2, connectionNetIds: r2, sourceZ: c2, targetZ: s3 });
if (h3 + nU < this.requiredViaToPadClearance)
continue;
const m2 = this.getMinPlacedEscapeViaClearance(p2);
if (m2 + nU < this.obstacleMargin)
continue;
const g2 = this.getProjectedFreeSpace({ sourcePoint: n2, candidate: p2, sourceLayer: a2, sourceObstacle: l2 }), f2 = Math.min(g2, 3), y2 = 100 * h3 - xe(n2, p2) - 0.5 * Math.abs(s3 - c2) + 2 * f2 + (Number.isFinite(m2) ? 10 * Math.min(m2, this.requiredViaToViaClearance) : 0);
(!d2 || y2 > d2.score) && (d2 = { pointId: `${eU}${e2.name}:${n2.pointId ?? `p${o2}`}:${i3}:${this.nextEscapeViaIndex++}`, x: p2.x, y: p2.y, connectionName: e2.name, rootConnectionName: e2.__rootConnectionNames?.[0] ?? e2.name, sourcePointIndex: o2, sourcePointId: n2.pointId, sourceLayer: a2, targetLayer: i3, targetPourKey: u2, score: y2 });
}
}
return d2;
}
buildPointPlacementPlans(t47) {
const { mergedConnection: e2, groupConnections: n2, matchingCopperPours: o2, connectionNetIds: i2 } = t47, r2 = [];
for (const t48 of e2.pointsToConnect) {
const e3 = this.selectPointOwner({ point: t48, groupConnections: n2, matchingCopperPours: o2 });
if (!e3)
continue;
const s2 = vo(t48) ? this.selectSourceObstacle({ point: t48, sourceLayer: t48.layer, connectionNetIds: i2 }) : undefined, a2 = vo(t48) ? this.getCandidatePositions(t48, s2).length : 0;
r2.push({ point: t48, pointOwner: e3, sourceObstacle: s2, candidateCount: a2 });
}
return r2.sort((t48, e3) => {
if (t48.candidateCount !== e3.candidateCount)
return t48.candidateCount - e3.candidateCount;
const n3 = (t48.sourceObstacle?.width ?? 0) * (t48.sourceObstacle?.height ?? 0), o3 = (e3.sourceObstacle?.width ?? 0) * (e3.sourceObstacle?.height ?? 0);
return n3 !== o3 ? n3 - o3 : t48.pointOwner.pointIndex - e3.pointOwner.pointIndex;
});
}
_step() {
const t47 = this.ogSrj.obstacles.filter((t48) => t48.isCopperPour), e2 = this.ogSrj.connections, n2 = e2.map((t48) => structuredClone(t48)), o2 = new Map(n2.map((t48) => [t48.name, t48])), i2 = structuredClone(this.ogSrj.obstacles), r2 = lk([...e2]);
for (const n3 of r2) {
const r3 = new Set(n3.__rootConnectionNames ?? [n3.name]), s2 = e2.filter((t48) => (t48.__rootConnectionNames ?? [t48.name]).some((t49) => r3.has(t49)));
if (s2.length === 0)
continue;
const a2 = new Set;
for (const t48 of s2)
for (const e3 of this.getConnectionNetIds(t48))
a2.add(e3);
const c2 = t47.filter((t48) => this.obstacleMatchesConnectionNet(t48, a2));
if (c2.length === 0)
continue;
const l2 = new Map, h2 = new Map, d2 = this.buildPointPlacementPlans({ mergedConnection: n3, groupConnections: s2, matchingCopperPours: c2, connectionNetIds: a2 });
for (const { point: t48, pointOwner: e3, sourceObstacle: n4 } of d2) {
const r4 = this.findBestEscapeViaCandidate({ connection: e3.connection, point: t48, pointIndex: e3.pointIndex, matchingCopperPours: c2, connectionNetIds: a2, sourceObstacle: n4 });
if (!r4)
continue;
const s3 = o2.get(e3.connection.name);
if (!s3)
continue;
if (s3.pointsToConnect.some((t49) => vo(t49) && t49.layer === r4.sourceLayer && iU(t49, r4)))
continue;
s3.pointsToConnect.push({ x: r4.x, y: r4.y, layer: r4.sourceLayer, pointId: r4.pointId, terminalVia: { toLayer: r4.targetLayer, viaDiameter: this.viaDiameter } }), this.escapeViaMetadataByPointId.set(r4.pointId, r4), this.createdEscapeVias.push(r4), i2.push(this.createEscapeViaObstacle({ escapeVia: r4, connectionNetIds: this.getConnectionNetIds(e3.connection) }));
const d3 = l2.get(r4.targetPourKey);
d3 ? d3.push(r4.pointId) : l2.set(r4.targetPourKey, [r4.pointId]), h2.has(r4.targetPourKey) || h2.set(r4.targetPourKey, e3.connection.name);
}
for (const [t48, e3] of l2.entries()) {
if (e3.length <= 1)
continue;
const n4 = h2.get(t48);
if (!n4)
continue;
const i3 = o2.get(n4);
i3 && (i3.externallyConnectedPointIds = [...i3.externallyConnectedPointIds ?? [], e3]);
}
}
this.outputSrj = { ...structuredClone(this.ogSrj), connections: n2, obstacles: i2 }, this.solved = true;
}
getOutputSimpleRouteJson() {
return structuredClone(this.outputSrj);
}
getEscapeViaMetadataByPointId() {
return new Map(this.escapeViaMetadataByPointId);
}
visualize() {
return { title: "Escape Via Location Solver", points: this.outputSrj.connections.flatMap((t47) => t47.pointsToConnect.map((e2) => ({ x: e2.x, y: e2.y, color: e2.pointId?.startsWith(eU) === true ? "#0f766e" : "#dc2626", label: e2.pointId?.startsWith(eU) === true ? `${t47.name}
escape via` : t47.name }))), lines: this.createdEscapeVias.map((t47) => {
const e2 = this.outputSrj.connections.find((e3) => e3.name === t47.connectionName)?.pointsToConnect[t47.sourcePointIndex] ?? null;
return { points: e2 ? [{ x: e2.x, y: e2.y }, { x: t47.x, y: t47.y }] : [{ x: t47.x, y: t47.y }], strokeColor: "#0f766e" };
}), circles: this.createdEscapeVias.map((t47) => ({ center: { x: t47.x, y: t47.y }, radius: this.viaRadius, strokeColor: "#0f766e", label: `${t47.connectionName}
${t47.targetLayer}` })), rects: this.outputSrj.obstacles.filter((t47) => !t47.isCopperPour).map((t47) => ({ ...t47, fill: "rgba(220,38,38,0.12)" })) };
}
};
var sU = (t47) => ({ ...t47 });
var aU = (t47) => ({ ...t47, route: t47.route?.map(sU), vias: t47.vias?.map((t48) => ({ ...t48 })) });
var cU = (t47) => t47.map(aU);
var lU = "#0000FF";
var hU = 0.15;
var dU = 0.000001;
var uU = 0.1;
var pU = ["top", "bottom", "left", "right"];
var mU = (t47) => t47.x * t47.x + t47.y * t47.y;
var gU = (t47, e2) => ({ x: t47.x - e2.x, y: t47.y - e2.y });
var fU = (t47, e2, n2) => {
const o2 = gU(n2, e2), i2 = mU(o2);
if (i2 <= dU)
return Math.sqrt(mU(gU(t47, e2)));
const r2 = (a2 = gU(t47, e2), c2 = o2, s2 = (a2.x * c2.x + a2.y * c2.y) / i2, Math.max(0, Math.min(1, s2)));
var s2, a2, c2;
const l2 = { x: e2.x + o2.x * r2, y: e2.y + o2.y * r2 };
return Math.sqrt(mU(gU(t47, l2)));
};
var yU = (t47) => t47?.z === 1 ? "bottom" : "top";
var _U = (t47, e2, n2) => (t47.z ?? 0) === (e2.z ?? 0) && ((e2.z ?? 0) === (n2.z ?? 0) && (t47.x === e2.x && e2.x === n2.x || t47.y === e2.y && e2.y === n2.y));
var bU = (t47, e2, n2) => {
const o2 = n2?.get(t47);
if (o2)
return o2;
const i2 = t47.route ?? [], r2 = t47.traceThickness ?? hU;
let { POSITIVE_INFINITY: s2, POSITIVE_INFINITY: a2, NEGATIVE_INFINITY: c2, NEGATIVE_INFINITY: l2 } = Number, h2 = false;
const d2 = (t48, e3, n3) => {
s2 = Math.min(s2, t48 - n3), a2 = Math.min(a2, e3 - n3), c2 = Math.max(c2, t48 + n3), l2 = Math.max(l2, e3 + n3), h2 = true;
}, u2 = { segments: [], segmentsByLayer: { top: [], bottom: [] }, vias: (t47.vias ?? []).map((n3) => {
const o3 = (n3.diameter ?? t47.viaDiameter ?? 0.3) / 2;
return d2(n3.x, n3.y, o3), { center: { x: n3.x, y: n3.y }, radius: o3, routeIndex: e2 };
}), bounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 } };
for (let t48 = 0;t48 < i2.length - 1; ) {
const n3 = i2[t48];
let o3 = t48 + 1, s3 = i2[o3];
const a3 = r2 / 2;
for (n3 && d2(n3.x, n3.y, a3), s3 && d2(s3.x, s3.y, a3);o3 < i2.length - 1; ) {
const t49 = i2[o3], e3 = i2[o3 + 1];
if (!n3 || !t49 || !e3)
break;
if (yU(n3) !== yU(t49))
break;
if (yU(t49) !== yU(e3))
break;
if (!_U(n3, t49, e3))
break;
o3 += 1, s3 = e3, d2(e3.x, e3.y, a3);
}
if (!n3 || !s3) {
t48 += 1;
continue;
}
const c3 = yU(n3), l3 = { start: n3, end: s3, routeIndex: e2, pointIndex: t48, endPointIndex: o3, thickness: r2, halfThickness: a3, layer: c3, minX: Math.min(n3.x, s3.x) - a3, maxX: Math.max(n3.x, s3.x) + a3, minY: Math.min(n3.y, s3.y) - a3, maxY: Math.max(n3.y, s3.y) + a3 };
u2.segments.push(l3), u2.segmentsByLayer[c3].push(l3), t48 = o3;
}
if (!h2)
for (const t48 of i2)
d2(t48.x, t48.y, r2 / 2);
return u2.bounds = h2 ? { minX: s2, minY: a2, maxX: c2, maxY: l2 } : { minX: 0, minY: 0, maxX: 0, maxY: 0 }, n2?.set(t47, u2), u2;
};
var xU = (t47, e2, n2) => e2.x <= Math.max(t47.x, n2.x) + dU && e2.x >= Math.min(t47.x, n2.x) - dU && e2.y <= Math.max(t47.y, n2.y) + dU && e2.y >= Math.min(t47.y, n2.y) - dU;
var vU = (t47, e2, n2) => (e2.y - t47.y) * (n2.x - e2.x) - (e2.x - t47.x) * (n2.y - e2.y);
var IU = (t47, e2, n2, o2) => ((t48, e3, n3, o3) => {
const i2 = vU(t48, e3, n3), r2 = vU(t48, e3, o3), s2 = vU(n3, o3, t48), a2 = vU(n3, o3, e3);
return !!(Math.abs(i2) <= dU && xU(t48, n3, e3)) || !!(Math.abs(r2) <= dU && xU(t48, o3, e3)) || !!(Math.abs(s2) <= dU && xU(n3, t48, o3)) || !!(Math.abs(a2) <= dU && xU(n3, e3, o3)) || i2 > 0 != r2 > 0 && s2 > 0 != a2 > 0;
})(t47, e2, n2, o2) ? 0 : Math.min(fU(t47, n2, o2), fU(e2, n2, o2), fU(n2, t47, e2), fU(o2, t47, e2));
var SU = (t47, e2) => Math.abs(t47.x - e2.x) <= dU && Math.abs(t47.y - e2.y) <= dU;
var CU = (t47, e2) => SU(t47.start, e2.start) || SU(t47.start, e2.end) || SU(t47.end, e2.start) || SU(t47.end, e2.end);
var PU = (t47) => {
if (!t47)
return [];
const e2 = [t47.connectionName, t47.rootConnectionName].filter((t48) => Boolean(t48));
return Array.from(new Set(e2));
};
var MU = (t47, e2) => {
const n2 = PU(t47), o2 = PU(e2);
return n2.length !== 0 && o2.length !== 0 && n2.some((t48) => o2.includes(t48));
};
var NU = (t47, e2, n2) => t47.minX - n2 <= e2.maxX && t47.maxX + n2 >= e2.minX && t47.minY - n2 <= e2.maxY && t47.maxY + n2 >= e2.minY;
var wU = (t47, e2, n2) => {
const o2 = n2 + t47.halfThickness + e2.halfThickness - dU;
return t47.minX - n2 <= e2.maxX && t47.maxX + n2 >= e2.minX && t47.minY - n2 <= e2.maxY && t47.maxY + n2 >= e2.minY && o2 > 0;
};
var TU = (t47, e2, n2, o2) => {
const i2 = o2 + n2.halfThickness + e2 - dU, r2 = t47.x - i2, s2 = t47.x + i2, a2 = t47.y - i2, c2 = t47.y + i2;
return r2 <= n2.maxX && s2 >= n2.minX && a2 <= n2.maxY && c2 >= n2.minY;
};
var RU = (t47, e2) => {
const n2 = new WeakMap, o2 = t47.map((t48, e3) => bU(t48, e3, n2)), i2 = [], r2 = new Set, s2 = (t48) => {
r2.has(t48.label) || (r2.add(t48.label), i2.push(t48));
};
for (let n3 = 0;n3 < o2.length; n3 += 1) {
const i3 = o2[n3];
if (i3)
for (let r3 = n3 + 1;r3 < o2.length; r3 += 1) {
const a2 = o2[r3];
if (a2 && (!MU(t47[n3], t47[r3]) && NU(i3.bounds, a2.bounds, e2))) {
for (const t48 of ["top", "bottom"]) {
const o3 = i3.segmentsByLayer[t48], c2 = a2.segmentsByLayer[t48];
for (const i4 of o3)
for (const o4 of c2) {
if (CU(i4, o4))
continue;
if (!wU(i4, o4, e2))
continue;
const a3 = e2 + (i4.thickness + o4.thickness) / 2 - dU;
if (IU(i4.start, i4.end, o4.start, o4.end) >= a3)
continue;
s2({ center: { x: (Math.max(i4.minX - e2, o4.minX - e2) + Math.min(i4.maxX + e2, o4.maxX + e2)) / 2, y: (Math.max(i4.minY - e2, o4.minY - e2) + Math.min(i4.maxY + e2, o4.maxY + e2)) / 2 }, label: `trace-violation:${n3}:s${i4.pointIndex}:${r3}:s${o4.pointIndex}:${t48}` });
}
}
for (const t48 of i3.segments)
for (const [o3, i4] of a2.vias.entries()) {
if (!TU(i4.center, i4.radius, t48, e2))
continue;
const a3 = e2 + t48.halfThickness + i4.radius - dU;
fU(i4.center, t48.start, t48.end) >= a3 || s2({ center: i4.center, label: `trace-violation:${n3}:s${t48.pointIndex}:${r3}:v${o3}` });
}
for (const t48 of a2.segments)
for (const [o3, a3] of i3.vias.entries()) {
if (!TU(a3.center, a3.radius, t48, e2))
continue;
const i4 = e2 + t48.halfThickness + a3.radius - dU;
fU(a3.center, t48.start, t48.end) >= i4 || s2({ center: a3.center, label: `trace-violation:${n3}:v${o3}:${r3}:s${t48.pointIndex}` });
}
}
}
}
return ((t48) => {
const e3 = [];
for (const n3 of t48) {
const t49 = e3.find((t50) => {
return e4 = t50.center, o3 = n3.center, Math.hypot(e4.x - o3.x, e4.y - o3.y) <= 0.28;
var e4, o3;
});
t49 ? (t49.center = { x: (t49.center.x * t49.count + n3.center.x) / (t49.count + 1), y: (t49.center.y * t49.count + n3.center.y) / (t49.count + 1) }, t49.labels.push(n3.label), t49.count += 1) : e3.push({ center: n3.center, labels: [n3.label], count: 1 });
}
return e3.map((t49, e4) => ({ center: t49.center, radius: Math.min(0.3, 0.2 + 0.035 * Math.sqrt(t49.count - 1)), stroke: "#f59e0b", fill: "rgba(245, 158, 11, 0.46)", label: t49.count === 1 ? t49.labels[0] : `trace-violations:${e4}:count-${t49.count}` }));
})(i2);
};
var EU = new WeakMap;
var AU = new WeakMap;
var OU = new WeakMap;
var kU = (t47) => {
let e2 = EU.get(t47);
return e2 === undefined && (e2 = t47.length > 2 && t47[t47.length - 1] - t47[0] === t47.length - 1 ? `${t47[0]}..${t47[t47.length - 1]}` : t47.join(","), EU.set(t47, e2)), e2;
};
var DU = ({ routeIndexes: t47, layers: e2, routePointIndexes: n2 }) => `${t47[0]}:${e2[0]}:${kU(n2[0])}:${t47[1]}:${e2[1]}:${kU(n2[1])}`;
var LU = (t47, e2, n2, o2, i2, r2, s2) => {
const a2 = ((t48, e3, n3, o3, i3, r3) => t48 < n3 ? `${t48}:${e3}:${kU(i3)}:${n3}:${o3}:${kU(r3)}` : `${n3}:${o3}:${kU(r3)}:${t48}:${e3}:${kU(i3)}`)(e2, n2, o2, i2, r2, s2);
t47.has(a2) || (e2 < o2 ? t47.set(a2, { routeIndexes: [e2, o2], layers: [n2, i2], routePointIndexes: [r2, s2] }) : t47.set(a2, { routeIndexes: [o2, e2], layers: [i2, n2], routePointIndexes: [s2, r2] }));
};
var zU = (t47) => {
const e2 = AU.get(t47);
if (e2)
return e2;
const n2 = [];
for (let e3 = t47.pointIndex;e3 <= t47.endPointIndex; e3 += 1)
n2.push(e3);
return AU.set(t47, n2), n2;
};
var BU = (t47, e2) => !e2 || t47.some((t48) => e2.has(t48));
var FU = (t47, e2) => {
const n2 = OU.get(e2);
if (n2)
return n2;
const o2 = t47.route ?? [], i2 = [];
for (let t48 = 0;t48 < o2.length; t48 += 1) {
const n3 = o2[t48];
n3 && (Math.abs(n3.x - e2.center.x) <= dU && Math.abs(n3.y - e2.center.y) <= dU && i2.push(t48));
}
return OU.set(e2, i2), i2;
};
var jU = (t47, e2, n2) => t47.minX - n2 <= e2.maxX && t47.maxX + n2 >= e2.minX && t47.minY - n2 <= e2.maxY && t47.maxY + n2 >= e2.minY;
var $U = (t47, e2, n2) => {
const o2 = n2 + t47.halfThickness + e2.halfThickness - dU;
return t47.minX - n2 <= e2.maxX && t47.maxX + n2 >= e2.minX && t47.minY - n2 <= e2.maxY && t47.maxY + n2 >= e2.minY && o2 > 0;
};
var YU = (t47, e2, n2, o2) => {
const i2 = o2 + n2.halfThickness + e2 - dU, r2 = t47.x - i2, s2 = t47.x + i2, a2 = t47.y - i2, c2 = t47.y + i2;
return r2 <= n2.maxX && s2 >= n2.minX && a2 <= n2.maxY && c2 >= n2.minY;
};
var XU = (t47, e2, n2) => {
const o2 = n2 + t47.radius + e2.radius - dU;
return Math.abs(t47.center.x - e2.center.x) <= o2 && Math.abs(t47.center.y - e2.center.y) <= o2;
};
var WU = (t47, e2, n2, o2, i2) => {
const r2 = t47.map((t48, e3) => bU(t48, e3, o2)), s2 = new Map;
if (e2.size === 0)
return [];
const a2 = Array.from(e2), c2 = new Map, l2 = (t48) => {
const e3 = c2.get(t48);
if (e3)
return e3;
const o3 = r2[t48];
if (!o3)
return [];
const i3 = [];
for (let e4 = 0;e4 < r2.length; e4 += 1) {
if (e4 === t48)
continue;
const s3 = r2[e4];
s3 && (jU(o3.bounds, s3.bounds, n2) && i3.push(e4));
}
return c2.set(t48, i3), i3;
};
for (const t48 of a2) {
const o3 = r2[t48];
if (!o3)
continue;
const a3 = l2(t48), c3 = i2?.get(t48);
for (const l3 of o3.segments) {
const o4 = zU(l3);
if (BU(o4, c3))
for (const c4 of a3) {
if (t48 > c4 && e2.has(c4))
continue;
const a4 = r2[c4];
if (!a4)
continue;
const h2 = i2?.get(c4), d2 = a4.segmentsByLayer[l3.layer];
for (const t49 of d2) {
const e3 = zU(t49);
if (!BU(e3, h2))
continue;
if (CU(l3, t49))
continue;
if (!$U(l3, t49, n2))
continue;
const i3 = n2 + (l3.thickness + t49.thickness) / 2 - dU;
IU(l3.start, l3.end, t49.start, t49.end) < i3 && LU(s2, l3.routeIndex, l3.layer, t49.routeIndex, t49.layer, o4, e3);
}
}
}
}
for (const o3 of a2) {
const a3 = r2[o3];
if (!a3)
continue;
const c3 = l2(o3), h2 = i2?.get(o3);
for (const l3 of a3.vias) {
const a4 = FU(t47[l3.routeIndex], l3);
if (BU(a4, h2))
for (const t48 of c3) {
if (o3 > t48 && e2.has(t48))
continue;
const c4 = r2[t48];
if (!c4)
continue;
const h3 = i2?.get(t48);
for (const t49 of c4.segments) {
const e3 = zU(t49);
if (!BU(e3, h3))
continue;
if (!YU(l3.center, l3.radius, t49, n2))
continue;
const o4 = n2 + t49.thickness / 2 + l3.radius - dU;
fU(l3.center, t49.start, t49.end) < o4 && LU(s2, t49.routeIndex, t49.layer, l3.routeIndex, "via", e3, a4);
}
}
}
}
for (const e3 of a2) {
const o3 = r2[e3];
if (!o3)
continue;
const a3 = l2(e3), c3 = i2?.get(e3);
for (const e4 of o3.segments) {
const o4 = zU(e4);
if (BU(o4, c3))
for (const c4 of a3) {
const a4 = r2[c4];
if (!a4)
continue;
const l3 = i2?.get(c4);
for (const i3 of a4.vias) {
const r3 = FU(t47[i3.routeIndex], i3);
if (!BU(r3, l3))
continue;
if (!YU(i3.center, i3.radius, e4, n2))
continue;
const a5 = n2 + e4.thickness / 2 + i3.radius - dU;
fU(i3.center, e4.start, e4.end) < a5 && LU(s2, e4.routeIndex, e4.layer, i3.routeIndex, "via", o4, r3);
}
}
}
}
for (const o3 of a2) {
const a3 = r2[o3];
if (!a3)
continue;
const c3 = l2(o3), h2 = i2?.get(o3);
for (const l3 of a3.vias) {
const a4 = FU(t47[l3.routeIndex], l3);
if (BU(a4, h2))
for (const h3 of c3) {
if (o3 > h3 && e2.has(h3))
continue;
const c4 = r2[h3];
if (!c4)
continue;
const d2 = i2?.get(h3);
for (const e3 of c4.vias) {
const o4 = FU(t47[e3.routeIndex], e3);
if (!BU(o4, d2))
continue;
if (!XU(l3, e3, n2))
continue;
const i3 = n2 + l3.radius + e3.radius - dU;
Math.hypot(l3.center.x - e3.center.x, l3.center.y - e3.center.y) < i3 && LU(s2, l3.routeIndex, "via", e3.routeIndex, "via", a4, o4);
}
}
}
}
return Array.from(s2.values());
};
var VU = (t47, e2) => t47.x >= e2.minX - dU && t47.x <= e2.maxX + dU && t47.y >= e2.minY - dU && t47.y <= e2.maxY + dU;
var HU = (t47, e2, n2) => {
switch (e2) {
case "left":
return { minX: t47.minX, maxX: t47.minX + n2, minY: t47.minY, maxY: t47.maxY };
case "right":
return { minX: t47.maxX - n2, maxX: t47.maxX, minY: t47.minY, maxY: t47.maxY };
case "top":
return { minX: t47.minX, maxX: t47.maxX, minY: t47.maxY - n2, maxY: t47.maxY };
case "bottom":
return { minX: t47.minX, maxX: t47.maxX, minY: t47.minY, maxY: t47.minY + n2 };
}
};
var GU = (t47, e2, n2) => {
const o2 = e2.x - t47.x, i2 = e2.y - t47.y;
let r2 = 0, s2 = 1;
const a2 = (t48, e3) => {
if (Math.abs(t48) <= dU)
return e3 >= -1e-6;
const n3 = e3 / t48;
return t48 < 0 ? !(n3 > s2) && (n3 > r2 && (r2 = n3), true) : !(n3 < r2) && (n3 < s2 && (s2 = n3), true);
};
if (!(a2(-o2, t47.x - n2.minX) && a2(o2, n2.maxX - t47.x) && a2(-i2, t47.y - n2.minY) && a2(i2, n2.maxY - t47.y)))
return 0;
const c2 = Math.hypot(o2, i2);
return Math.max(0, s2 - r2) * c2;
};
var UU = (t47, e2) => pU.filter((n2) => {
switch (n2) {
case "left":
return Math.abs(t47.x - e2.minX) <= dU;
case "right":
return Math.abs(t47.x - e2.maxX) <= dU;
case "top":
return Math.abs(t47.y - e2.maxY) <= dU;
case "bottom":
return Math.abs(t47.y - e2.minY) <= dU;
}
return false;
});
var ZU = (t47, e2) => {
const n2 = [];
return t47.x < e2.minX - dU && n2.push("left"), t47.x > e2.maxX + dU && n2.push("right"), t47.y > e2.maxY + dU && n2.push("top"), t47.y < e2.minY - dU && n2.push("bottom"), n2;
};
var qU = (t47, e2, n2) => {
const o2 = e2.x - t47.x, i2 = e2.y - t47.y;
switch (n2) {
case "left":
case "right":
return Math.abs(o2) <= dU && Math.abs(i2) > dU;
case "top":
case "bottom":
return Math.abs(i2) <= dU && Math.abs(o2) > dU;
}
};
var JU = (t47, e2, n2) => {
const o2 = [], i2 = Math.max(n2, dU), r2 = Math.min(0.1, i2 / 4);
for (let n3 = 0;n3 < t47.length; n3 += 1) {
const s2 = t47[n3], a2 = s2?.route ?? [];
for (let t48 = 0;t48 < a2.length - 1; t48 += 1) {
const c2 = a2[t48], l2 = a2[t48 + 1];
if (!c2 || !l2)
continue;
const h2 = ZU(c2, e2), d2 = ZU(l2, e2), u2 = UU(c2, e2), p2 = UU(l2, e2), m2 = pU.filter((t49) => {
if (s2.connectedPadSides?.includes(t49))
return false;
return !(GU(c2, l2, HU(e2, t49, i2)) <= r2) && !!qU(c2, l2, t49);
}), g2 = !VU(c2, e2) || !VU(l2, e2), f2 = Array.from(new Set([...m2, ...h2, ...d2]));
(g2 || f2.length !== 0) && o2.push({ routeIndex: n3, connectionName: s2.connectionName ?? s2.rootConnectionName ?? `route-${n3}`, segmentIndex: t48, touchedSides: f2, startSides: u2, endSides: p2, start: c2, end: l2 });
}
}
return o2;
};
var QU = (t47) => t47?.center && t47.width && t47.height ? { minX: t47.center.x - t47.width / 2, maxX: t47.center.x + t47.width / 2, minY: t47.center.y - t47.height / 2, maxY: t47.center.y + t47.height / 2, width: t47.width, height: t47.height, center: t47.center } : null;
var KU = (t47) => t47 === "bottom" ? lU : "#FF0000";
var tZ = (t47) => {
const e2 = t47.route ?? [], n2 = [];
if (e2.length < 2)
return n2;
let o2 = yU(e2[0]), i2 = [e2[0]];
for (let r2 = 1;r2 < e2.length; r2 += 1) {
const s2 = e2[r2], a2 = yU(s2);
a2 === o2 ? i2.push(s2) : (i2.length >= 2 && n2.push({ points: i2, strokeColor: KU(o2), strokeWidth: t47.traceThickness ?? hU, label: t47.connectionName ?? "route" }), o2 = a2, i2 = [e2[r2 - 1], s2]);
}
return i2.length >= 2 && n2.push({ points: i2, strokeColor: KU(o2), strokeWidth: t47.traceThickness ?? hU, label: t47.connectionName ?? "route" }), n2;
};
var eZ = (t47) => {
const e2 = aU(t47), n2 = e2.route ?? [], o2 = e2.vias ?? [];
for (let t48 = 1;t48 < n2.length; t48++) {
const i2 = n2[t48 - 1], r2 = n2[t48];
if ((i2.z ?? 0) === (r2.z ?? 0))
continue;
if (i2.x !== r2.x || i2.y !== r2.y)
throw new Error("Node repair requires coincident via transition endpoints");
let s2 = -1, a2 = 0.001;
for (let t49 = 0;t49 < o2.length; t49++) {
const e3 = o2[t49], n3 = Math.hypot(e3.x - i2.x, e3.y - i2.y);
n3 <= a2 && (s2 = t49, a2 = n3);
}
s2 === -1 ? o2.push({ x: i2.x, y: i2.y, diameter: e2.viaDiameter }) : o2[s2] = { ...o2[s2], x: i2.x, y: i2.y };
}
return (o2.length || e2.vias) && (e2.vias = o2), e2;
};
var nZ = (t47) => {
const e2 = t47.route ?? [], n2 = [];
for (let o2 = 1;o2 < e2.length; o2++) {
const i2 = e2[o2 - 1], r2 = e2[o2];
(i2.z ?? 0) === (r2.z ?? 0) && n2.push({ start: i2, end: r2, radius: (t47.traceThickness ?? hU) / 2, minZ: i2.z ?? 0, maxZ: i2.z ?? 0, indexes: [o2 - 1, o2], via: false });
}
for (const [o2, i2] of (t47.vias ?? []).entries()) {
const r2 = e2.flatMap((t48, e3) => t48.x === i2.x && t48.y === i2.y ? [e3] : []), s2 = r2.map((t48) => e2[t48].z ?? 0);
n2.push({ start: i2, end: i2, radius: (i2.diameter ?? t47.viaDiameter ?? 0.3) / 2, minZ: s2.length ? Math.min(...s2) : 0, maxZ: s2.length ? Math.max(...s2) : 1, indexes: r2, via: true, viaIndex: o2 });
}
return n2;
};
var oZ = (t47, e2, n2, o2 = [], i2, r2 = new WeakMap) => {
const s2 = [...t47, ...o2], a2 = s2.map((t48) => {
let e3 = r2.get(t48);
return e3 || (e3 = nZ(t48), r2.set(t48, e3)), e3;
}), c2 = i2 ? i2.evaluation.conflicts.filter((t48) => t48.firstRoute !== i2.changedRoute && t48.secondRoute !== i2.changedRoute) : [];
let l2 = c2.reduce((t48, e3) => t48 + e3.penetration ** 2, 0);
for (let o3 = 0;o3 < t47.length; o3++) {
const r3 = t47[o3], h2 = new Set([r3.connectionName, r3.rootConnectionName].filter(Boolean));
if (!i2 || o3 === i2.changedRoute) {
const t48 = a2[o3].filter((t49) => t49.via);
for (let n3 = 0;n3 < t48.length; n3++) {
const i3 = t48[n3];
for (let r4 = n3 + 1;r4 < t48.length; r4++) {
const s3 = t48[r4];
if (i3.maxZ < s3.minZ || s3.maxZ < i3.minZ)
continue;
const a3 = Math.hypot(i3.start.x - s3.start.x, i3.start.y - s3.start.y);
if (a3 === 0)
continue;
const h3 = e2 + i3.radius + s3.radius - a3;
h3 <= dU || (c2.push({ key: `${o3}:vias:${n3}:${r4}`, firstRoute: o3, secondRoute: o3, first: i3, second: s3, penetration: h3 }), l2 += h3 ** 2);
}
}
for (const [t49, i3] of n2.entries()) {
if (i3.connectedTo?.some((t50) => h2.has(t50)))
continue;
let n3;
for (const r4 of a2[o3]) {
if (i3.zLayers && !i3.zLayers.some((t50) => t50 >= r4.minZ && t50 <= r4.maxZ))
continue;
const s3 = e2 - iZ(r4, i3);
s3 <= dU || s3 <= (n3?.penetration ?? 0) || (n3 = { key: `${o3}:pad:${t49}`, firstRoute: o3, secondRoute: -1, first: r4, second: r4, penetration: s3 });
}
n3 && (c2.push(n3), l2 += n3.penetration ** 2);
}
}
for (let t48 = o3 + 1;t48 < s2.length; t48++) {
if (i2 && o3 !== i2.changedRoute && t48 !== i2.changedRoute)
continue;
const n3 = s2[t48], r4 = h2.has(n3.connectionName) || h2.has(n3.rootConnectionName), d2 = new Map;
for (const n4 of a2[o3])
for (const i3 of a2[t48]) {
if (r4 && (!n4.via || !i3.via))
continue;
if (n4.maxZ < i3.minZ || i3.maxZ < n4.minZ)
continue;
if (r4 && n4.start.x === i3.start.x && n4.start.y === i3.start.y)
continue;
const s3 = e2 + n4.radius + i3.radius;
if (Math.min(n4.start.x, n4.end.x) > Math.max(i3.start.x, i3.end.x) + s3 || Math.min(i3.start.x, i3.end.x) > Math.max(n4.start.x, n4.end.x) + s3 || Math.min(n4.start.y, n4.end.y) > Math.max(i3.start.y, i3.end.y) + s3 || Math.min(i3.start.y, i3.end.y) > Math.max(n4.start.y, n4.end.y) + s3)
continue;
const a3 = s3 - IU(n4.start, n4.end, i3.start, i3.end);
if (a3 <= dU)
continue;
const c3 = `${n4.via ? `via:${n4.viaIndex}` : `trace:${n4.minZ}`}:${i3.via ? `via:${i3.viaIndex}` : `trace:${i3.minZ}`}`;
a3 <= (d2.get(c3)?.penetration ?? 0) || d2.set(c3, { key: `${o3}:${t48}:${c3}`, firstRoute: o3, secondRoute: t48, first: n4, second: i3, penetration: a3 });
}
for (const t49 of d2.values())
c2.push(t49), l2 += t49.penetration ** 2;
}
}
return c2.sort((t48, e3) => e3.penetration - t48.penetration), { conflicts: c2, score: l2 };
};
var iZ = (t47, e2) => {
if (!e2.center || e2.width === undefined || e2.height === undefined)
return 1 / 0;
const n2 = e2.center.x - e2.width / 2, o2 = e2.center.x + e2.width / 2, i2 = e2.center.y - e2.height / 2, r2 = e2.center.y + e2.height / 2;
let s2 = 0;
for (const e3 of [t47.start, t47.end])
e3.x >= n2 && e3.x <= o2 && e3.y >= i2 && e3.y <= r2 && (s2 = Math.max(s2, t47.radius + Math.min(e3.x - n2, o2 - e3.x, e3.y - i2, r2 - e3.y)));
if (s2 > 0)
return -s2;
const a2 = [{ x: n2, y: i2 }, { x: o2, y: i2 }, { x: o2, y: r2 }, { x: n2, y: r2 }];
return Math.min(...a2.map((e3, n3) => IU(t47.start, t47.end, e3, a2[(n3 + 1) % 4]))) - t47.radius;
};
var rZ = (t47, e2) => {
const n2 = nZ(t47).filter((t48) => !e2.zLayers || e2.zLayers.some((e3) => e3 >= t48.minZ && e3 <= t48.maxZ));
return Math.min(...n2.map((t48) => iZ(t48, e2)));
};
var sZ = (t47, e2, n2, o2, i2) => {
const r2 = aU(t47), s2 = r2.route ?? [], a2 = t47.route ?? [], c2 = (t48) => t48 === 0 || t48 === s2.length - 1, l2 = new Set;
for (const t48 of e2.indexes) {
if (c2(t48))
continue;
const e3 = a2[t48];
a2.forEach((t49, n3) => {
t49.x === e3.x && t49.y === e3.y && l2.add(n3);
});
}
if (!([...l2].some(c2) || e2.via && e2.indexes.some(c2))) {
if (l2.size === 0) {
if (e2.via || e2.indexes.length !== 2)
return;
const [t48, i3] = e2.indexes, r3 = s2[t48], a3 = s2[i3], c3 = [0.25, 0.75].map((t49) => ({ ...r3, x: r3.x + (a3.x - r3.x) * t49 + n2, y: r3.y + (a3.y - r3.y) * t49 + o2 }));
s2.splice(i3, 0, ...c3);
} else {
for (const t48 of l2)
s2[t48].x += n2, s2[t48].y += o2;
for (const t48 of r2.vias ?? [])
[...l2].some((e3) => a2[e3].x === t48.x && a2[e3].y === t48.y) && (t48.x += n2, t48.y += o2);
}
if (!s2.some((t48, e3) => e3 > 0 && e3 < s2.length - 1 && (t48.x < i2.minX || t48.x > i2.maxX || t48.y < i2.minY || t48.y > i2.maxY)))
return r2;
}
};
var aZ = (t47) => {
const e2 = [], n2 = t47.route ?? [];
for (let o2 = 1;o2 < n2.length; o2++) {
const i2 = n2[o2 - 1], r2 = n2[o2];
(i2.z ?? 0) === (r2.z ?? 0) && e2.push({ start: i2, end: r2, radius: (t47.traceThickness ?? hU) / 2, minZ: i2.z ?? 0, maxZ: i2.z ?? 0 });
}
for (const o2 of t47.vias ?? []) {
let i2 = 1 / 0, r2 = -1 / 0;
for (let t48 = 1;t48 < n2.length; t48++) {
const e3 = n2[t48 - 1], s2 = n2[t48];
Math.hypot(e3.x - o2.x, e3.y - o2.y) > 0.001 || Math.hypot(s2.x - o2.x, s2.y - o2.y) > 0.001 || e3.z === s2.z || (i2 = Math.min(i2, e3.z ?? 0, s2.z ?? 0), r2 = Math.max(r2, e3.z ?? 0, s2.z ?? 0));
}
e2.push({ start: o2, end: o2, radius: (o2.diameter ?? t47.viaDiameter ?? 0.3) / 2, minZ: i2 === 1 / 0 ? 0 : i2, maxZ: r2 === -1 / 0 ? 1 : r2 });
}
return e2;
};
var cZ = (t47, e2) => {
let n2 = 1 / 0;
for (const o2 of t47)
o2.maxZ < e2.minZ || e2.maxZ < o2.minZ || (n2 = Math.min(n2, IU(o2.start, o2.end, e2.start, e2.end) - o2.radius - e2.radius));
return n2;
};
var lZ = class {
constructor(t47, e2, n2 = []) {
this.minimumClearance = e2, this.obstacles = n2, this.fixedCopper = t47.map((t48) => ({ route: t48, copper: aZ(t48) }));
}
fixedCopper;
cache = new WeakMap;
allows(t47, e2, n2, o2 = true) {
if (o2 && ((t48, e3, n3) => {
const o3 = new Map(oZ(t48, n3, []).conflicts.map((t49) => [t49.key, t49.penetration]));
return oZ(e3, n3, []).conflicts.some((t49) => t49.penetration > (o3.get(t49.key) ?? 0) + dU);
})(t47, e2, this.minimumClearance))
return false;
if (this.fixedCopper.length === 0 && this.obstacles.length === 0)
return true;
for (const o3 of n2) {
const n3 = t47[o3], i2 = e2[o3];
if (n3 === i2)
continue;
const r2 = this.cache.get(n3) ?? aZ(n3), s2 = this.cache.get(i2) ?? aZ(i2);
this.cache.set(n3, r2), this.cache.set(i2, s2);
const a2 = new Set([n3.connectionName, n3.rootConnectionName].filter(Boolean));
for (const t48 of this.obstacles) {
if (t48.connectedTo?.some((t49) => a2.has(t49)))
continue;
const e3 = rZ(i2, t48);
if (e3 >= this.minimumClearance - dU)
continue;
const o4 = rZ(n3, t48);
if (e3 < Math.min(o4, this.minimumClearance) - dU)
return false;
}
for (const t48 of this.fixedCopper)
if (!a2.has(t48.route.connectionName) && !a2.has(t48.route.rootConnectionName))
for (const e3 of t48.copper) {
const t49 = cZ(s2, e3);
if (t49 >= this.minimumClearance - dU)
continue;
const n4 = cZ(r2, e3);
if (t49 < Math.min(n4, this.minimumClearance) - dU)
return false;
}
}
return true;
}
};
var hZ = (t47, e2) => ({ title: `HighDensityRepair02 Initial State (margin=${e2})`, routes: t47 });
var dZ = (t47) => {
const e2 = [];
for (const n2 of t47) {
const t48 = e2[e2.length - 1];
t48 && t48.z === n2.z && SU(t48, n2) || e2.push(n2);
}
return e2;
};
var uZ = (t47, e2, n2) => {
const o2 = Math.max(0, t47.minX - e2.maxX, e2.minX - t47.maxX), i2 = Math.max(0, t47.minY - e2.maxY, e2.minY - t47.maxY);
return Math.hypot(o2, i2) <= n2 + dU;
};
var pZ = (t47, e2) => {
let n2 = Number.POSITIVE_INFINITY;
for (const o2 of t47.segments)
for (const t48 of e2.segments) {
if (o2.layer !== t48.layer)
continue;
const e3 = IU(o2.start, o2.end, t48.start, t48.end) - (o2.thickness + t48.thickness) / 2;
n2 = Math.min(n2, e3);
}
return n2;
};
var mZ = ({ currentRoutes: t47, candidateRoutes: e2, candidateRouteIndexes: n2, maximumAllowedClearance: o2 }) => {
const i2 = new WeakMap, r2 = new WeakMap, s2 = [], a2 = Array.from(n2).sort((t48, e3) => t48 - e3), c2 = t47.map((t48, e3) => bU(t48, e3, i2)), l2 = e2.map((t48, e3) => bU(t48, e3, r2)), h2 = new Set;
for (const t48 of a2)
for (let n3 = 0;n3 < e2.length; n3 += 1) {
if (n3 === t48)
continue;
const e3 = Math.min(t48, n3), i3 = Math.max(t48, n3), r3 = `${e3}:${i3}`;
if (h2.has(r3))
continue;
h2.add(r3);
const a3 = l2[e3], d2 = l2[i3];
if (!a3 || !d2 || !uZ(a3.bounds, d2.bounds, o2))
continue;
const u2 = pZ(a3, d2);
if (!Number.isFinite(u2) || u2 > o2 + dU || !c2[e3] || !c2[i3])
continue;
const p2 = pZ(c2[e3], c2[i3]);
!Number.isFinite(p2) || u2 >= p2 - dU || s2.push({ routeIndexes: [e3, i3], previousClearance: p2, nextClearance: u2 });
}
return s2;
};
var gZ = 0.001;
var fZ = (t47, e2) => t47.map((t48) => {
const n2 = t48.route ?? [];
return n2.length === 0 ? t48 : { ...t48, route: n2.map((t49, o2) => o2 === 0 || o2 === n2.length - 1 ? ((t50, e3) => {
const n3 = { ...t50 };
return Math.abs(n3.x - e3.minX) <= gZ ? n3.x = e3.minX : Math.abs(n3.x - e3.maxX) <= gZ && (n3.x = e3.maxX), Math.abs(n3.y - e3.minY) <= gZ ? n3.y = e3.minY : Math.abs(n3.y - e3.maxY) <= gZ && (n3.y = e3.maxY), n3;
})(t49, e2) : t49) };
});
var yZ = (t47, e2) => Array.from(e2).flatMap((e3) => tZ(t47[e3]).map((t48) => ({ ...t48, strokeColor: "#000000", strokeWidth: t48.strokeWidth, label: `candidate:${t48.label}` })));
var _Z = (t47, e2, n2, o2, i2) => {
const r2 = "rgba(0, 0, 0, 0)";
switch (e2) {
case "left":
return { center: { x: t47.minX + n2 / 2, y: t47.center.y }, width: n2, height: t47.height, stroke: r2, fill: o2, label: i2 };
case "right":
return { center: { x: t47.maxX - n2 / 2, y: t47.center.y }, width: n2, height: t47.height, stroke: r2, fill: o2, label: i2 };
case "top":
return { center: { x: t47.center.x, y: t47.maxY - n2 / 2 }, width: t47.width, height: n2, stroke: r2, fill: o2, label: i2 };
case "bottom":
return { center: { x: t47.center.x, y: t47.minY + n2 / 2 }, width: t47.width, height: n2, stroke: r2, fill: o2, label: i2 };
}
};
var bZ = ({ routes: t47, candidateRoutes: e2, candidateRouteIndexes: n2, originalRoutes: o2, boundary: i2, side: r2, margin: s2, rejected: a2, rejectionReason: c2 }) => {
const l2 = Array.from(n2).map((t48) => e2[t48].connectionName ?? `route-${t48}`);
return { title: a2 ? `${r2} move rejected (${c2})` : `${r2} move accepted`, routes: a2 ? t47 : e2, originalRoutes: o2, activeSide: r2, candidateRouteNames: l2, overlayLines: a2 ? yZ(e2, n2) : [], overlayRects: [_Z(i2, r2, s2, a2 ? "rgba(220, 38, 38, 0.14)" : "rgba(16, 185, 129, 0.14)", a2 ? `rejected:${r2}` : `accepted:${r2}`)] };
};
var xZ = (t47, e2, n2, o2) => {
const i2 = (t47?.adjacentObstacles ?? []).some((t48) => ((t49, e3, n3, o3) => {
const i3 = ((t50) => t50.center && t50.width && t50.height ? { minX: t50.center.x - t50.width / 2, maxX: t50.center.x + t50.width / 2, minY: t50.center.y - t50.height / 2, maxY: t50.center.y + t50.height / 2 } : null)(t49);
if (!i3)
return false;
switch (n3) {
case "left":
return i3.maxX >= e3.minX - dU && i3.minX <= e3.minX + o3 + dU;
case "right":
return i3.minX <= e3.maxX + dU && i3.maxX >= e3.maxX - o3 - dU;
case "top":
return i3.minY <= e3.maxY + dU && i3.maxY >= e3.maxY - o3 - dU;
case "bottom":
return i3.maxY >= e3.minY - dU && i3.minY <= e3.minY + o3 + dU;
}
})(t48, e2, n2, o2));
return { hasObstacle: i2, moveAmount: i2 ? o2 : o2 / 2 };
};
var vZ = ({ start: t47, end: e2, side: n2, boundary: o2, amount: i2, targetAxisValue: r2 }) => {
const s2 = (({ side: t48, boundary: e3, amount: n3, targetAxisValue: o3 }) => {
const i3 = o3 ?? (() => {
switch (t48) {
case "left":
return e3.minX + n3;
case "right":
return e3.maxX - n3;
case "top":
return e3.maxY - n3;
case "bottom":
return e3.minY + n3;
}
})();
switch (t48) {
case "left":
case "right":
return Math.min(Math.max(i3, e3.minX), e3.maxX);
case "top":
case "bottom":
return Math.min(Math.max(i3, e3.minY), e3.maxY);
}
})({ side: n2, boundary: o2, amount: i2, targetAxisValue: r2 });
switch (n2) {
case "left":
case "right":
return dZ([t47, { x: s2, y: t47.y, z: t47.z }, { x: s2, y: e2.y, z: e2.z }, e2]);
case "top":
case "bottom":
return dZ([t47, { x: t47.x, y: s2, z: t47.z }, { x: e2.x, y: s2, z: e2.z }, e2]);
}
};
var IZ = (t47, e2, n2, o2, i2, r2, s2, a2 = false) => {
const c2 = t47.route ?? [];
if (c2.length < 2 || e2.length === 0)
return aU(t47);
const l2 = a2 ? i2 : Math.max(i2, r2), h2 = ((t48, e3) => {
switch (t48) {
case "left":
return { x: e3, y: 0 };
case "right":
return { x: -e3, y: 0 };
case "top":
return { x: 0, y: -e3 };
case "bottom":
return { x: 0, y: e3 };
}
})(o2, l2);
if (a2 || (t47.vias?.length ?? 0) > 0 || c2.length > 2) {
const n3 = aU(t47), o3 = n3.route ?? [];
for (const t48 of e2) {
const e3 = o3[t48];
e3 && (o3[t48] = { ...e3, x: e3.x + h2.x, y: e3.y + h2.y });
}
for (const o4 of n3.vias ?? []) {
e2.some((e3) => {
const n4 = t47.route?.[e3];
return !!n4 && SU(n4, o4);
}) && (o4.x += h2.x, o4.y += h2.y);
}
return n3;
}
const d2 = aU(t47);
if (c2.length === 2 && e2.length === 2 && e2[0] === 0 && e2[1] === 1) {
const e3 = c2[0], i3 = c2[1];
return aU({ ...t47, route: vZ({ start: e3, end: i3, side: o2, boundary: n2, amount: l2, targetAxisValue: s2 }) });
}
return d2;
};
var SZ = (t47, e2, n2) => {
switch (n2) {
case "left":
return t47.x - e2.minX;
case "right":
return e2.maxX - t47.x;
case "top":
return e2.maxY - t47.y;
case "bottom":
return t47.y - e2.minY;
}
};
var CZ = (t47, e2, n2) => {
const o2 = ((t48) => {
const e3 = t48.route ?? [];
if (e3.length === 0)
return [];
const n3 = [];
for (let t49 = 0;t49 < e3.length; t49 += 1) {
const o3 = e3[t49];
if (!o3)
continue;
t49 === 0 || t49 === e3.length - 1 || n3.push(o3);
const i2 = e3[t49 + 1];
i2 && n3.push({ x: (o3.x + i2.x) / 2, y: (o3.y + i2.y) / 2 });
}
return n3;
})(t47);
return o2.length === 0 ? Number.POSITIVE_INFINITY : o2.reduce((t48, o3) => Math.min(t48, SZ(o3, e2, n2)), Number.POSITIVE_INFINITY);
};
var PZ = (t47, e2, n2 = []) => {
const o2 = t47.route ?? [], i2 = [], r2 = new Set, s2 = e2.length === 0 || e2.includes("via");
if (o2.length === 2)
return [0, 1];
const a2 = (t48) => {
if (t48 <= 0 || t48 >= o2.length - 1)
return;
if (r2.has(t48))
return;
const n3 = o2[t48];
n3 && (s2 || e2.includes(yU(n3))) && (r2.add(t48), i2.push(t48));
};
if (n2.length > 0)
for (const t48 of n2)
a2(t48);
else
for (let t48 = 1;t48 < o2.length - 1; t48 += 1)
a2(t48);
for (let t48 = 0;t48 < i2.length; t48 += 1) {
const e3 = i2[t48], n3 = o2[e3];
if (n3)
for (let t49 = 1;t49 < o2.length - 1; t49 += 1) {
if (r2.has(t49))
continue;
const e4 = o2[t49];
e4 && (e4.z !== n3.z && SU(e4, n3) && (r2.add(t49), i2.push(t49)));
}
}
return i2.sort((t48, e3) => t48 - e3), i2;
};
var MZ = (t47, e2) => Math.max(0, ...(t47.route ?? []).map((t48) => Math.max(e2.minX - t48.x, t48.x - e2.maxX, e2.minY - t48.y, t48.y - e2.maxY, 0)));
var NZ = (t47, e2, n2, o2) => SZ(t47, e2, n2) <= o2 + dU;
var wZ = (t47, e2, n2, o2) => {
const i2 = t47.route ?? [], r2 = [], s2 = new Set;
let a2 = 1, c2 = i2.length - 2;
for (;a2 < i2.length - 1 && SU(i2[a2], i2[0]); )
a2 += 1;
for (;c2 > 0 && SU(i2[c2], i2[i2.length - 1]); )
c2 -= 1;
for (let t48 = a2;t48 <= c2; t48 += 1)
NZ(i2[t48], e2, n2, o2) && (s2.add(t48), r2.push(t48));
for (let t48 = 0;t48 < r2.length; t48 += 1) {
const e3 = i2[r2[t48]];
if (e3)
for (let t49 = a2;t49 <= c2; t49 += 1) {
if (s2.has(t49))
continue;
const n3 = i2[t49];
n3 && (n3.z !== e3.z && SU(n3, e3) && (s2.add(t49), r2.push(t49)));
}
}
return r2.length === 0 && i2.length === 2 && i2.some((t48) => NZ(t48, e2, n2, o2)) ? [0, 1] : (r2.sort((t48, e3) => t48 - e3), r2);
};
var TZ = (t47, e2, n2) => {
const o2 = t47.route ?? [], i2 = n2 === 0 ? o2[0] : o2[o2.length - 1];
return i2 ? pU.filter((t48) => SZ(i2, e2, t48) <= dU) : [];
};
var RZ = (t47, e2, n2) => {
const o2 = t47.route ?? [], i2 = e2.route ?? [];
if (o2.length === 0 || i2.length === 0)
return true;
for (const e3 of [0, -1]) {
const o3 = TZ(t47, n2, e3);
if (o3.length === 0)
continue;
const r2 = e3 === 0 ? i2[0] : i2[i2.length - 1];
if (!r2)
return false;
for (const t48 of o3)
if (SZ(r2, n2, t48) > dU)
return false;
}
return true;
};
var EZ = (t47, e2) => Math.hypot(e2.x - t47.x, e2.y - t47.y);
var AZ = (t47, e2, n2, o2) => {
const i2 = t47.route ?? [];
if (i2.length === 0)
return "none";
let r2 = false;
for (let t48 = 0;t48 < i2.length; t48 += 1) {
const s2 = i2[t48];
if (s2 && NZ(s2, e2, n2, o2)) {
if (t48 !== 0 && t48 !== i2.length - 1)
return "interior";
r2 = true;
}
}
for (let t48 = 0;t48 < i2.length - 1; t48 += 1) {
const r3 = i2[t48], s2 = i2[t48 + 1];
if (r3 && s2 && (NZ(r3, e2, n2, o2) && NZ(s2, e2, n2, o2) && !(EZ(r3, s2) <= dU)))
return "interior";
}
return r2 ? "endpoint" : "none";
};
var OZ = ({ currentRoutes: t47, routeIndex: e2, side: n2, moveSide: o2 = n2, boundary: i2, margin: r2, moveAmount: s2, geometryCache: a2, fixedCopperGuard: c2 }) => {
const l2 = t47[e2], h2 = (l2.route?.length ?? 0) === 2, d2 = wZ(l2, i2, n2, r2);
if (d2.length === 0)
return null;
const u2 = new Set, p2 = new Map, m2 = new Set, g2 = t47.slice();
let f2 = false, y2 = "overlap";
const _2 = new Set([e2]), b2 = new Map([[e2, new Set]]), x2 = new Map([[e2, new Set]]), v2 = [e2];
let I2 = 0, S2 = null, C2 = null, P2 = null, M2 = null;
const N2 = (t48) => new Set(t48.map((t49) => DU(t49))), w2 = () => S2 || (S2 = WU(t47, u2, r2, a2, p2), S2), T2 = () => P2 || (P2 = WU(t47, u2, 0, a2, p2), P2), R2 = () => M2 || (M2 = WU(g2, u2, 0, a2, p2), M2);
for (;I2 < v2.length && !f2; ) {
const c3 = v2[I2];
if (I2 += 1, _2.delete(c3), u2.has(c3))
continue;
const l3 = g2[c3], h3 = Array.from(b2.get(c3) ?? []), d3 = Array.from(x2.get(c3) ?? []);
b2.delete(c3), x2.delete(c3);
const T3 = c3 === e2 ? wZ(l3, i2, n2, r2) : PZ(l3, h3, d3);
if (T3.length === 0) {
if (c3 === e2)
return null;
f2 = true, y2 = "eventual-overlap";
break;
}
const R3 = l3.route ?? [], E2 = c3 === e2 ? undefined : o2 === "left" || o2 === "right" ? (R3[T3[0]]?.x ?? 0) + (o2 === "left" ? s2 : -s2) : (R3[T3[0]]?.y ?? 0) + (o2 === "top" ? -s2 : s2);
g2[c3] = IZ(l3, T3, i2, o2, s2, r2, E2, c3 !== e2), u2.add(c3), p2.set(c3, new Set(T3)), S2 = null, C2 = null, P2 = null, M2 = null, (l3.route?.length ?? 0) === 2 && m2.add(c3);
const A2 = MZ(t47[c3], i2);
if (MZ(g2[c3], i2) > A2 + 0.000001) {
f2 = true, y2 = "boundary";
break;
}
if (!RZ(t47[c3], g2[c3], i2)) {
f2 = true, y2 = "endpoint-boundary";
break;
}
const O2 = WU(g2, new Set([c3]), r2, a2, new Map([[c3, new Set(T3)]]));
for (const t48 of O2) {
if (N2(w2()).has(DU(t48)))
continue;
const [e3, n3] = t48.routeIndexes, o3 = u2.has(e3), i3 = u2.has(n3);
if (o3 && i3)
continue;
const r3 = o3 ? n3 : e3, s3 = o3 ? t48.layers[1] : t48.layers[0], a3 = o3 ? t48.routePointIndexes[1] : t48.routePointIndexes[0];
if (u2.has(r3) || _2.has(r3)) {
if (_2.has(r3)) {
const t49 = b2.get(r3) ?? new Set;
t49.add(s3), b2.set(r3, t49);
const e4 = x2.get(r3) ?? new Set;
for (const t50 of a3)
e4.add(t50);
x2.set(r3, e4);
}
} else
_2.add(r3), v2.push(r3), b2.set(r3, new Set([s3])), x2.set(r3, new Set(a3));
}
}
if (!f2 && u2.size > 1) {
const t48 = N2(w2()), e3 = N2(C2 || (C2 = WU(g2, u2, r2, a2, p2), C2));
for (const n3 of e3)
if (!t48.has(n3)) {
f2 = true, y2 = "eventual-overlap";
break;
}
}
if (!f2 && u2.size > 1) {
const t48 = N2(T2()), e3 = N2(R2());
for (const n3 of e3)
if (!t48.has(n3)) {
f2 = true, y2 = "eventual-overlap";
break;
}
}
if (!f2) {
const e3 = new Set(WU(t47, u2, 0, a2).map((t48) => DU(t48))), n3 = WU(g2, u2, 0, a2);
for (const t48 of n3) {
const n4 = DU(t48);
if (!e3.has(n4)) {
f2 = true, y2 = "eventual-overlap";
break;
}
}
}
if (!f2) {
const e3 = (({ currentRoutes: t48, candidateRoutes: e4, candidateRouteIndexes: n3, boundary: o3, activeSide: i3 }) => {
const r3 = pU.filter((t49) => t49 !== i3), s3 = [];
for (const i4 of n3) {
const n4 = t48[i4], a3 = e4[i4];
if (n4 && a3)
for (const t49 of r3) {
const e5 = CZ(n4, o3, t49), r4 = CZ(a3, o3, t49);
e5 > dU && r4 <= dU && s3.push({ routeIndex: i4, side: t49, previousClearance: e5, nextClearance: r4 });
}
}
return s3;
})({ currentRoutes: t47, candidateRoutes: g2, candidateRouteIndexes: u2, boundary: i2, activeSide: n2 });
e3.length > 0 && (f2 = true, y2 = "boundary-touch");
}
if (!f2) {
const e3 = (({ currentRoutes: t48, candidateRoutes: e4, candidateRouteIndexes: n3, geometryCache: o3, currentConflicts: i3, candidateConflicts: r3 }) => {
const s3 = i3 ?? WU(t48, n3, 0, o3), a3 = r3 ?? WU(e4, n3, 0, o3), c3 = new Set(s3.map((t49) => DU(t49)));
return a3.filter((t49) => {
const o4 = DU(t49);
if (c3.has(o4))
return false;
const [i4, r4] = t49.routeIndexes, [s4, a4] = t49.layers, l3 = n3.has(i4), h3 = n3.has(r4);
if (l3 && h3)
return false;
const d3 = l3 ? a4 : s4, u3 = e4[l3 ? r4 : i4];
return !!u3 && PZ(u3, [d3]).length === 0;
});
})({ currentRoutes: t47, candidateRoutes: g2, candidateRouteIndexes: u2, geometryCache: a2, currentConflicts: T2(), candidateConflicts: R2() });
e3.length > 0 && (f2 = true, y2 = "fixed-trace-touch");
}
if (!f2) {
mZ({ currentRoutes: t47, candidateRoutes: g2, candidateRouteIndexes: u2, maximumAllowedClearance: Math.min(r2 / 2, uU) }).length > 0 && (f2 = true, y2 = "trace-clearance");
}
return !f2 && ((t48, e3, n3, o3, i3, r3) => Array.from(n3).some((n4) => {
const s3 = t48[n4], a3 = e3[n4];
return pU.filter((t49) => t49 !== i3).some((t49) => {
const e4 = AZ(s3, o3, t49, r3), n5 = AZ(a3, o3, t49, r3);
return e4 === "none" && n5 !== "none";
});
}))(t47, g2, u2, i2, n2, r2) && (f2 = true, y2 = "side-regression"), f2 || !c2 || c2.allows(t47, g2, u2) || (f2 = true, y2 = "fixed-copper-clearance"), { isTwoPointRoute: h2, movableIndexes: d2, candidateRouteIndexes: u2, movedTwoPointRouteIndexes: m2, candidateRoutes: g2, rejected: f2, rejectionReason: y2 };
};
var kZ = (t47, e2, n2, o2, i2) => {
const r2 = t47.route ?? [];
if (e2.length === 0)
return null;
if (o2 === "top" || o2 === "bottom") {
const t48 = e2.reduce((t49, e3) => t49 + (r2[e3]?.x ?? n2.center.x), 0) / e2.length;
return t48 < n2.center.x - i2 / 2 ? "right" : t48 > n2.center.x + i2 / 2 ? "left" : null;
}
const s2 = e2.reduce((t48, e3) => t48 + (r2[e3]?.y ?? n2.center.y), 0) / e2.length;
return s2 > n2.center.y + i2 / 2 ? "bottom" : s2 < n2.center.y - i2 / 2 ? "top" : null;
};
var DZ = ({ side: t47, sample: e2, boundary: n2, margin: o2, repairedRoutes: i2, frames: r2, captureProgressFrames: s2, lockedTwoPointRoutes: a2, geometryCache: c2, fixedCopperGuard: l2, allowTwoPointWithoutObstacle: h2 = false }) => {
const { hasObstacle: d2, moveAmount: u2 } = xZ(e2, n2, t47, o2);
s2 && r2.push(((t48, e3, n3, o3, i3, r3) => ({ title: `${n3} boundary analysis: move=${i3.toFixed(3)} (${r3 ? "obstacle-side" : "clear-side"})`, routes: t48, activeSide: n3, overlayRects: [_Z(e3, n3, o3, "rgba(245, 158, 11, 0.16)", `strip:${n3}`)] }))(cU(i2), n2, t47, o2, u2, d2));
const p2 = new Set;
let m2 = 0;
for (let e3 = 0;e3 < i2.length; e3 += 1) {
if (p2.has(e3))
continue;
if (a2.has(e3))
continue;
const g2 = i2[e3];
if (g2.connectedPadSides?.includes(t47))
continue;
if ((g2.route?.length ?? 0) === 2 && !d2 && !h2)
continue;
let f2 = OZ({ currentRoutes: i2, routeIndex: e3, side: t47, boundary: n2, margin: o2, moveAmount: u2, geometryCache: c2, fixedCopperGuard: l2 });
if (f2) {
if (f2.rejected) {
const r3 = kZ(g2, f2.movableIndexes, n2, t47, o2);
if (r3) {
const s3 = OZ({ currentRoutes: i2, routeIndex: e3, side: t47, moveSide: r3, boundary: n2, margin: o2, moveAmount: u2, geometryCache: c2, fixedCopperGuard: l2 });
s3 && !s3.rejected && (f2 = s3);
}
}
if (s2 && r2.push(bZ({ routes: cU(i2), candidateRoutes: f2.candidateRoutes, candidateRouteIndexes: f2.candidateRouteIndexes, originalRoutes: f2.rejected ? undefined : Array.from(f2.candidateRouteIndexes).map((t48) => aU(i2[t48])), boundary: n2, side: t47, margin: o2, rejected: f2.rejected, rejectionReason: f2.rejectionReason })), !f2.rejected) {
i2.splice(0, i2.length, ...f2.candidateRoutes);
for (const t48 of f2.movedTwoPointRouteIndexes)
a2.add(t48);
m2 += 1;
}
p2.add(e3);
}
}
return { movesAccepted: m2 };
};
var LZ = (t47, e2, n2, o2) => NZ(t47, e2, n2, o2);
var zZ = (t47, e2, n2, o2) => {
switch (n2) {
case "left":
return { ...t47, x: Math.min(e2.minX + o2, e2.maxX) };
case "right":
return { ...t47, x: Math.max(e2.maxX - o2, e2.minX) };
case "top":
return { ...t47, y: Math.max(e2.maxY - o2, e2.minY) };
case "bottom":
return { ...t47, y: Math.min(e2.minY + o2, e2.maxY) };
}
};
var BZ = (t47) => `${t47.routeIndexes[0]}:${t47.layers[0]}:${t47.routeIndexes[1]}:${t47.layers[1]}`;
var FZ = (t47) => {
if (!t47)
return [];
const e2 = [t47.connectionName, t47.rootConnectionName].filter((t48) => Boolean(t48));
return Array.from(new Set(e2));
};
var jZ = (t47, e2) => {
const n2 = FZ(t47), o2 = FZ(e2);
return n2.length !== 0 && o2.length !== 0 && n2.some((t48) => o2.includes(t48));
};
var $Z = (t47, e2, n2) => t47 ? JU([t47], e2, n2).length : 0;
var YZ = (t47, e2, n2, o2) => {
const i2 = new Set(WU(t47, new Set([n2]), o2).map(DU));
return WU(e2, new Set([n2]), o2).some((t48) => !i2.has(DU(t48)));
};
var XZ = (t47, e2, n2) => JU(t47, e2, n2).length;
var WZ = (t47) => {
if (!t47)
return [];
const e2 = [t47.connectionName, t47.rootConnectionName].filter((t48) => Boolean(t48));
return Array.from(new Set(e2));
};
var VZ = (t47, e2) => WU(t47, new Set(t47.map((t48, e3) => e3)), uU, e2).filter((e3) => !(e3.layers[0] === "via" && e3.layers[1] === "via" || ((t48, e4) => {
const n2 = WZ(t48), o2 = WZ(e4);
return n2.length !== 0 && o2.length !== 0 && n2.some((t49) => o2.includes(t49));
})(t47[e3.routeIndexes[0]], t47[e3.routeIndexes[1]]))).length;
var HZ = (t47) => {
const e2 = pU;
return [...e2.slice(t47 % e2.length), ...e2.slice(0, t47 % e2.length)];
};
var GZ = (t47, e2, n2 = false, o2 = true) => {
const i2 = QU(t47?.nodeWithPortPoints), r2 = (t47?.nodeHdRoutes ?? []).map(eZ), s2 = Math.max(e2 ?? 0.4, 0.05), a2 = new lZ(t47?.fixedHdRoutes ?? [], Math.min(s2 / 2, uU), t47?.clearanceObstacles ?? t47?.adjacentObstacles), c2 = i2 && o2 ? ((t48, e3) => t48.map((t49) => {
const n3 = t49.route ?? [];
let o3 = false;
const i3 = n3.map((t50) => {
let { x: n4, y: i4 } = t50;
return n4 < e3.minX ? n4 = e3.minX : n4 > e3.maxX && (n4 = e3.maxX), i4 < e3.minY ? i4 = e3.minY : i4 > e3.maxY && (i4 = e3.maxY), n4 === t50.x && i4 === t50.y ? t50 : (o3 = true, { ...t50, x: n4, y: i4 });
});
return o3 ? { ...t49, route: i3 } : t49;
}))(fZ(cU(r2), i2), i2) : cU(r2), l2 = o2 && a2.allows(r2, c2, r2.keys()) ? c2 : r2, h2 = cU(l2);
if (!i2)
return { boundary: null, baseRoutes: l2, repairedRoutes: h2, margin: s2, frames: [{ title: "HighDensityRepair02 Missing Boundary", routes: h2 }] };
const d2 = n2 ? [hZ(cU(h2), s2)] : [];
if (o2) {
const e3 = new WeakMap;
let o3 = XZ(h2, i2, s2);
for (let r4 = 0;r4 < 1; r4 += 1) {
const c4 = new Set;
let l3 = 0;
for (const o4 of HZ(r4)) {
const { movesAccepted: u4 } = DZ({ side: o4, sample: t47, boundary: i2, frames: d2, margin: s2, repairedRoutes: h2, captureProgressFrames: n2, lockedTwoPointRoutes: c4, geometryCache: e3, fixedCopperGuard: a2, allowTwoPointWithoutObstacle: r4 >= 1 });
l3 += u4;
}
const u3 = XZ(h2, i2, s2);
if (l3 === 0)
break;
if (u3 === 0)
break;
if (u3 >= o3)
break;
o3 = u3;
}
const r3 = cU(h2), c3 = VZ(h2, e3);
(({ routes: t48, boundary: e4, margin: n3, geometryCache: o4, fixedCopperGuard: i3 }) => {
const r4 = JU(t48, e4, n3);
if (r4.length === 0)
return { movesAccepted: 0 };
const s3 = new Map;
for (const t49 of r4) {
const e5 = s3.get(t49.routeIndex) ?? new Set;
for (const n4 of t49.touchedSides)
e5.add(n4);
s3.set(t49.routeIndex, e5);
}
const a3 = [0.000008, 0.01, n3 / 4, n3 / 2, n3 + 0.000008];
let c4 = 0;
const l3 = (r5, s4, a4) => {
const c5 = s4.route ?? [];
if (c5.length < 2)
return false;
const l4 = { ...s4, route: dZ(c5) };
if ((l4.route?.length ?? 0) < 2)
return false;
const h4 = t48.slice();
if (h4[r5] = l4, i3 && !i3.allows(t48, h4, [r5]))
return false;
if ($Z(h4[r5], e4, n3) >= a4)
return false;
const d4 = (e5) => jZ(t48[e5.routeIndexes[0]], t48[e5.routeIndexes[1]]), u4 = new Set(WU(t48, new Set([r5]), 0, o4).filter((t49) => !d4(t49)).map(BZ));
return !WU(h4, new Set([r5]), 0, o4).filter((t49) => !d4(t49)).some((t49) => !u4.has(BZ(t49))) && !(mZ({ currentRoutes: t48, candidateRoutes: h4, candidateRouteIndexes: new Set([r5]), maximumAllowedClearance: Math.min(n3 / 2, uU) }).filter((e5) => !jZ(t48[e5.routeIndexes[0]], t48[e5.routeIndexes[1]])).length > 0 || (t48[r5] = l4, 0));
}, h3 = (n4, o5, i4, r5) => {
if (o5.length === 0)
return false;
for (const s4 of a3) {
const a4 = t48[n4], c5 = aU(a4), h4 = c5.route ?? [];
let d4 = false;
for (const t49 of PZ(a4, [], o5)) {
const n5 = h4[t49];
n5 && (h4[t49] = zZ(n5, e4, i4, s4), d4 = true);
}
if (!d4)
return false;
if (l3(n4, c5, r5))
return true;
}
return false;
}, d3 = (t49, n4) => {
const o5 = [];
return n4 === "top" || n4 === "bottom" ? (Math.abs(t49.x - e4.minX) <= dU && o5.push("left"), Math.abs(t49.x - e4.maxX) <= dU && o5.push("right")) : (Math.abs(t49.y - e4.minY) <= dU && o5.push("bottom"), Math.abs(t49.y - e4.maxY) <= dU && o5.push("top")), o5;
}, u3 = (o5, i4, r5) => {
const s4 = t48[o5], c5 = s4.route ?? [];
if (c5.length !== 2)
return false;
const [h4, u4] = c5;
if (!LZ(h4, e4, i4, n3))
return false;
if (!LZ(u4, e4, i4, n3))
return false;
const p2 = d3(h4, i4), m2 = d3(u4, i4);
for (const t49 of a3) {
let n4 = zZ(h4, e4, i4, t49), a4 = zZ(u4, e4, i4, t49);
for (const o6 of p2)
n4 = zZ(n4, e4, o6, t49);
for (const n5 of m2)
a4 = zZ(a4, e4, n5, t49);
const c6 = { ...s4, route: [h4, n4, a4, u4] };
if (l3(o5, c6, r5))
return true;
}
return false;
};
for (const [o5, i4] of s3)
if (t48[o5])
for (const r5 of i4) {
let i5 = true;
for (;i5; ) {
i5 = false;
const s4 = t48[o5].route ?? [];
if (s4.length === 2) {
const i6 = $Z(t48[o5], e4, n3);
i6 > 0 && u3(o5, r5, i6) && (c4 += 1);
break;
}
if (s4.length < 3)
break;
const a4 = $Z(t48[o5], e4, n3);
if (a4 === 0)
break;
const l4 = [];
for (let t49 = 1;t49 < s4.length - 1; t49 += 1) {
const o6 = s4[t49];
o6 && LZ(o6, e4, r5, n3) && l4.push(t49);
}
if (l4.length === 0)
break;
if (h3(o5, l4, r5, a4)) {
c4 += 1, i5 = true;
continue;
}
let d4 = false, p2 = a4, m2 = 0;
for (;m2 < l4.length; ) {
let i6 = m2;
for (;i6 + 1 < l4.length && l4[i6 + 1] === l4[i6] + 1; )
i6 += 1;
h3(o5, l4.slice(m2, i6 + 1), r5, p2) && (c4 += 1, d4 = true, p2 = $Z(t48[o5], e4, n3)), m2 = i6 + 1;
}
if (!d4) {
const i6 = t48[o5].route ?? [];
let s5 = a4;
for (let a5 = 1;a5 < i6.length - 1; a5 += 1) {
const l5 = i6[a5];
l5 && LZ(l5, e4, r5, n3) && h3(o5, [a5], r5, s5) && (c4 += 1, d4 = true, s5 = $Z(t48[o5], e4, n3));
}
}
d4 && (i5 = true);
}
}
for (const [o5, i4] of s3) {
const r5 = t48[o5];
if (!r5)
continue;
const s4 = r5.route ?? [];
if (s4.length <= 2)
continue;
const a4 = $Z(t48[o5], e4, n3);
if (a4 !== 0)
for (const l4 of i4) {
if (!s4.every((t49) => LZ(t49, e4, l4, n3)))
continue;
const i5 = s4[0]?.z;
if (!s4.every((t49) => t49.z === i5))
continue;
const h4 = { ...r5, route: [s4[0], s4[s4.length - 1]] }, d4 = t48[o5];
t48[o5] = h4, u3(o5, l4, a4) ? c4 += 1 : t48[o5] = d4;
break;
}
}
})({ routes: r3, boundary: i2, margin: s2, geometryCache: e3, fixedCopperGuard: a2 });
VZ(r3, e3) <= c3 && h2.splice(0, h2.length, ...r3), (({ routes: t48, boundary: e4, clearanceMargin: n3, fixedCopperGuard: o4 }) => {
for (let i3 = 0;i3 < t48.length; i3 += 1) {
const r4 = t48[i3];
if ((r4.route ?? []).length <= 2)
continue;
const s3 = n3, a3 = Math.max(e4.width / 2 - dU, 0), c4 = Math.max(e4.height / 2 - dU, 0), l3 = Math.min(s3, a3), h3 = Math.min(s3, c4), d3 = r4.connectedPadSides ?? [], u3 = e4.minX + (d3.includes("left") ? 0 : l3), p2 = e4.maxX - (d3.includes("right") ? 0 : l3), m2 = e4.minY + (d3.includes("bottom") ? 0 : h3), g2 = e4.maxY - (d3.includes("top") ? 0 : h3), f2 = aU(r4), y2 = f2.route ?? [];
let _2 = false;
for (let t49 = 1;t49 < y2.length - 1; t49 += 1) {
const e5 = y2[t49];
if (!e5)
continue;
const n4 = Math.min(Math.max(e5.x, u3), p2), o5 = Math.min(Math.max(e5.y, m2), g2);
(Math.abs(n4 - e5.x) > dU || Math.abs(o5 - e5.y) > dU) && (e5.x = n4, e5.y = o5, _2 = true);
}
if (!_2)
continue;
if (f2.route = dZ(y2), (f2.route?.length ?? 0) < 2)
continue;
const b2 = cU(t48);
b2[i3] = f2;
const x2 = YZ(t48, b2, i3, 0), v2 = YZ(t48, b2, i3, n3), I2 = mZ({ currentRoutes: t48, candidateRoutes: b2, candidateRouteIndexes: new Set([i3]), maximumAllowedClearance: n3 }).length > 0;
x2 || v2 || I2 || !o4.allows(t48, b2, [i3]) || (t48[i3] = f2);
}
})({ routes: h2, boundary: i2, clearanceMargin: s2, fixedCopperGuard: a2 });
}
const u2 = (({ routes: t48, fixedRoutes: e3 = [], boundary: n3, fixedCopperGuard: o3, adjacentObstacles: i3 = [], clearanceObstacles: r3 = i3, clearance: s3 = 0.1, boundaryMargin: a3 = 0.2, maxCandidates: c3 }) => {
let l3 = t48;
const h3 = new WeakMap;
let d3 = oZ(l3, s3, r3, e3, undefined, h3);
const u3 = c3 ?? Math.max(256, 96 * d3.conflicts.length), p2 = { routes: t48, initialConflictCount: d3.conflicts.length, finalConflictCount: d3.conflicts.length, candidateCount: 0 };
for (;d3.conflicts.length && p2.candidateCount < u3; ) {
let t49 = false;
const i4 = new Map(d3.conflicts.map((t50) => [t50.key, t50.penetration]));
for (const c4 of d3.conflicts) {
for (const [m2, g2] of [[c4.firstRoute, c4.first], [c4.secondRoute, c4.second]]) {
if (m2 < 0 || m2 >= l3.length)
continue;
const f2 = l3[m2], y2 = new Set([f2.connectionName, f2.rootConnectionName].filter(Boolean)), _2 = r3.filter((t50) => !t50.connectedTo?.some((t51) => y2.has(t51))), b2 = nZ(f2), x2 = JU([f2], n3, a3).length, v2 = _2.map((t50) => Math.min(...b2.filter((e4) => !t50.zLayers || t50.zLayers.some((t51) => t51 >= e4.minZ && t51 <= e4.maxZ)).map((e4) => iZ(e4, t50))));
for (const y3 of [1.01, 2, 4]) {
const b3 = Math.max(0.01, c4.penetration * y3);
for (const [c5, y4] of [[1, 0], [-1, 0], [0, 1], [0, -1], [Math.SQRT1_2, Math.SQRT1_2], [-Math.SQRT1_2, Math.SQRT1_2], [Math.SQRT1_2, -Math.SQRT1_2], [-Math.SQRT1_2, -Math.SQRT1_2]]) {
if (p2.candidateCount >= u3)
break;
p2.candidateCount++;
const I2 = sZ(f2, g2, c5 * b3, y4 * b3, n3);
if (!I2)
continue;
if (JU([I2], n3, a3).length > x2)
continue;
const S2 = [...l3];
S2[m2] = I2;
const C2 = oZ(S2, s3, r3, e3, { evaluation: d3, changedRoute: m2 }, h3);
if (C2.conflicts.length > d3.conflicts.length || C2.score >= d3.score - 0.000000000001)
continue;
if (C2.conflicts.some((t50) => t50.penetration > (i4.get(t50.key) ?? 0) + dU))
continue;
if (!o3.allows(l3, S2, [m2], false))
continue;
const P2 = nZ(I2);
if (!_2.some((t50, e4) => Math.min(...P2.filter((e5) => !t50.zLayers || t50.zLayers.some((t51) => t51 >= e5.minZ && t51 <= e5.maxZ)).map((e5) => iZ(e5, t50))) < Math.min(s3, v2[e4]) - dU)) {
l3 = S2, d3 = C2, t49 = true;
break;
}
}
if (t49 || p2.candidateCount >= u3)
break;
}
if (t49 || p2.candidateCount >= u3)
break;
}
if (t49 || p2.candidateCount >= u3)
break;
}
if (!t49)
break;
}
return { ...p2, routes: l3, finalConflictCount: d3.conflicts.length };
})({ fixedRoutes: t47?.fixedHdRoutes, routes: h2, boundary: i2, fixedCopperGuard: a2, adjacentObstacles: t47?.adjacentObstacles, clearanceObstacles: t47?.clearanceObstacles, boundaryMargin: s2 });
return h2.splice(0, h2.length, ...u2.routes), d2.push(((t48, e3, n3) => ({ title: `HighDensityRepair02 Final State (margin=${n3})`, routes: t48, originalRoutes: e3 }))(cU(h2), cU(l2), s2)), { boundary: i2, baseRoutes: l2, repairedRoutes: h2, frames: d2, margin: s2, clearanceRepairStats: { nodeClearanceInitialConflictCount: u2.initialConflictCount, nodeClearanceFinalConflictCount: u2.finalConflictCount, nodeClearanceCandidateCount: u2.candidateCount } };
};
var UZ = class extends kt {
constructor(t47 = {}) {
super(), this.params = t47, this.showBoundryViolationMarkers = t47.showBoundryViolationMarkers ?? false;
}
frames = [];
traceViolationCounts = new WeakMap;
clearanceRepairStats = {};
currentFrameIndex = 0;
showBoundryViolationMarkers;
repairedRoutes = [];
_setup() {
this.buildFrames();
const t47 = this.getCurrentBoundryViolationCount(), e2 = this.getCurrentTraceViolationCount();
this.stats = { ...this.clearanceRepairStats, boundryViolationCount: t47, traceViolationCount: e2, margin: this.params.margin ?? 0.4, frames: this.frames.length, currentFrame: this.currentFrameIndex };
}
_step() {
if (this.frames.length <= 1) {
const t48 = this.getCurrentBoundryViolationCount(), e3 = this.getCurrentTraceViolationCount();
return this.showBoundryViolationMarkers = true, this.stats = { ...this.stats, boundryViolationCount: t48, traceViolationCount: e3 }, void (this.solved = true);
}
this.currentFrameIndex < this.frames.length - 1 && (this.currentFrameIndex += 1);
const t47 = this.getCurrentBoundryViolationCount(), e2 = this.getCurrentTraceViolationCount();
this.stats = { ...this.clearanceRepairStats, boundryViolationCount: t47, traceViolationCount: e2, margin: this.params.margin ?? 0.4, frames: this.frames.length, currentFrame: this.currentFrameIndex, title: this.frames[this.currentFrameIndex]?.title }, this.currentFrameIndex >= this.frames.length - 1 && (this.showBoundryViolationMarkers = true, this.solved = true);
}
getConstructorParams() {
return [this.params];
}
getOutput() {
const t47 = this.getCurrentTraceViolationCount();
return { ...this.clearanceRepairStats, margin: this.params.margin ?? 0.4, repairedRoutes: this.repairedRoutes, frameCount: this.frames.length, traceViolationCount: t47 };
}
setShowBoundryViolationMarkers(t47) {
this.showBoundryViolationMarkers = t47;
}
buildFrames() {
const t47 = GZ(this.params.sample, this.params.margin, this.params.captureProgressFrames ?? false, this.params.repairBoundaryDiagonals ?? true);
this.clearanceRepairStats = t47.clearanceRepairStats ?? {}, this.frames = t47.frames, this.repairedRoutes = t47.repairedRoutes;
}
getCurrentFrame() {
const t47 = this.params.sample;
return this.frames[this.currentFrameIndex] ?? { title: "HighDensityRepair02", routes: cU(t47?.nodeHdRoutes ?? []) };
}
getBoundryViolationsForFrame(t47) {
const e2 = QU(this.params.sample?.nodeWithPortPoints);
return e2 ? JU(t47.routes, e2, this.params.margin ?? 0.4) : [];
}
getCurrentBoundryViolationCount() {
return this.getBoundryViolationsForFrame(this.getCurrentFrame()).length;
}
getRouteNetNames(t47) {
if (!t47)
return [];
const e2 = [t47.connectionName, t47.rootConnectionName].filter((t48) => Boolean(t48));
return Array.from(new Set(e2));
}
areRoutesSameNet(t47, e2) {
const n2 = this.getRouteNetNames(t47), o2 = this.getRouteNetNames(e2);
return n2.length !== 0 && o2.length !== 0 && n2.some((t48) => o2.includes(t48));
}
getCurrentTraceViolationCount() {
const t47 = this.getCurrentFrame(), e2 = this.traceViolationCounts.get(t47);
if (e2 !== undefined)
return e2;
const n2 = t47.routes, o2 = new Set(n2.map((t48, e3) => e3)), i2 = WU(n2, o2, uU).filter((t48) => !(t48.layers[0] === "via" && t48.layers[1] === "via" || this.areRoutesSameNet(n2[t48.routeIndexes[0]], n2[t48.routeIndexes[1]]))).length;
return this.traceViolationCounts.set(t47, i2), i2;
}
visualize() {
const t47 = this.params.sample, e2 = t47?.nodeWithPortPoints, n2 = t47?.adjacentObstacles ?? [], o2 = this.getCurrentFrame(), i2 = QU(e2), r2 = i2 && e2?.capacityMeshNodeId ? [{ center: i2.center, width: i2.width, height: i2.height, stroke: "#1d4ed8", fill: "rgba(29, 78, 216, 0.08)", label: e2.capacityMeshNodeId }] : i2 ? [{ center: i2.center, width: i2.width, height: i2.height, stroke: "#1d4ed8", fill: "rgba(29, 78, 216, 0.08)", label: "capacity-node" }] : [], s2 = n2.filter((t48) => t48.center && t48.width && t48.height).map((t48, e3) => ({ center: t48.center, width: t48.width, height: t48.height, stroke: t48.type === "oval" ? "#a855f7" : "#dc2626", fill: t48.type === "oval" ? "rgba(168, 85, 247, 0.12)" : "rgba(220, 38, 38, 0.08)", label: t48.type ? `obstacle:${t48.type}:${e3}` : `obstacle:${e3}` })), a2 = this.showBoundryViolationMarkers && i2 ? this.getBoundryViolationsForFrame(o2).map((t48) => {
const e3 = t48.end.x - t48.start.x, n3 = t48.end.y - t48.start.y, o3 = Math.max(Math.hypot(e3, n3), 0.2), i3 = Math.abs(e3) >= Math.abs(n3);
return { center: { x: (t48.start.x + t48.end.x) / 2, y: (t48.start.y + t48.end.y) / 2 }, width: i3 ? o3 : 0.18, height: i3 ? 0.18 : o3, stroke: "#b45309", fill: "rgba(250, 204, 21, 0.45)", label: `boundry-violation:${t48.routeIndex}:${t48.segmentIndex}` };
}) : [];
const c2 = this.showBoundryViolationMarkers ? RU(o2.routes, uU) : [], l2 = [...(e2?.portPoints ?? []).map((t48) => ({ x: t48.x, y: t48.y, color: "#0f766e", label: t48.connectionName ?? t48.portPointId ?? "port-point" })), ...o2.routes.flatMap((t48) => t48.route ?? []).map((t48) => ({ x: t48.x, y: t48.y, color: yU(t48) === "bottom" ? lU : "#0ea5e9", label: "" })), ...o2.overlayPoints ?? []], h2 = [...(o2.originalRoutes ?? []).flatMap((t48) => tZ(t48).map((t49) => ({ ...t49, strokeColor: "#111111", strokeWidth: Math.max(0.6 * t49.strokeWidth, 0.05), label: `original:${t49.label}` }))), ...o2.routes.filter((t48) => (t48.route?.length ?? 0) >= 2).flatMap((t48) => tZ(t48)), ...o2.overlayLines ?? []], d2 = o2.routes.flatMap((t48) => (t48.vias ?? []).map((e3) => ({ center: { x: e3.x, y: e3.y }, radius: (e3.diameter ?? t48.viaDiameter ?? 0.3) / 2, stroke: "#7c3aed", fill: "rgba(124, 58, 237, 0.2)", label: t48.connectionName ? `via:${t48.connectionName}` : "via" })));
return d2.push(...c2), { coordinateSystem: "cartesian", title: o2.title, rects: [...r2, ...s2, ...o2.overlayRects ?? [], ...a2], points: l2, lines: h2, circles: d2, arrows: o2.overlayArrows };
}
};
var ZZ = (t47, e2, n2, o2) => {
const i2 = 0.001, r2 = new Set;
for (const s2 of [e2.route[0], e2.route.at(-1)]) {
if (!s2)
continue;
n2.some((t48) => t48.__zLayers.includes(s2.z) && xo(t48, e2, o2) && Math.abs(s2.x - t48.center.x) <= t48.width / 2 + i2 && Math.abs(s2.y - t48.center.y) <= t48.height / 2 + i2) && (Math.abs(s2.x - (t47.center.x - t47.width / 2)) <= i2 && r2.add("left"), Math.abs(s2.x - (t47.center.x + t47.width / 2)) <= i2 && r2.add("right"), Math.abs(s2.y - (t47.center.y - t47.height / 2)) <= i2 && r2.add("bottom"), Math.abs(s2.y - (t47.center.y + t47.height / 2)) <= i2 && r2.add("top"));
}
return [...r2];
};
var qZ = (t47, e2) => t47.minX <= e2.maxX && t47.maxX >= e2.minX && t47.minY <= e2.maxY && t47.maxY >= e2.minY;
var JZ = (t47, e2 = 0) => ({ minX: t47.center.x - t47.width / 2 - e2, maxX: t47.center.x + t47.width / 2 + e2, minY: t47.center.y - t47.height / 2 - e2, maxY: t47.center.y + t47.height / 2 + e2 });
var QZ = (t47) => ({ minX: t47.center.x - t47.width / 2, maxX: t47.center.x + t47.width / 2, minY: t47.center.y - t47.height / 2, maxY: t47.center.y + t47.height / 2 });
var KZ = (t47, e2, n2 = 0) => {
const o2 = JZ(e2, n2);
return t47.x >= o2.minX && t47.x <= o2.maxX && t47.y >= o2.minY && t47.y <= o2.maxY;
};
var tq = (t47, e2, n2) => t47.route.length > 0 && e2.some((e3) => ((t48) => (t48.__zLayers?.length ?? t48.layers?.length ?? 0) > 1)(e3) && xo(e3, t47, n2) && t47.route.every((t48) => ((t49, e4) => {
const n3 = e4.width / 2, o2 = e4.height / 2;
return Math.abs(t49.x - e4.center.x) <= n3 + 0.001 && Math.abs(t49.y - e4.center.y) <= o2 + 0.001;
})(t48, e3)));
var eq = (t47, e2, n2) => {
if (t47.regionId) {
const n3 = e2.findIndex((e3) => e3.capacityMeshNodeId === t47.regionId);
if (n3 !== -1)
return n3;
}
const o2 = [...t47.route.map(({ x: t48, y: e3 }) => ({ x: t48, y: e3 })), ...t47.vias.map(({ x: t48, y: e3 }) => ({ x: t48, y: e3 }))];
for (let t48 = 0;t48 < e2.length; t48++) {
const i2 = e2[t48];
if (o2.every((t49) => KZ(t49, i2, n2)))
return t48;
}
return -1;
};
var nq = (t47, e2) => ({ connectionName: t47.connectionName ?? e2.connectionName, rootConnectionName: e2.rootConnectionName, ...e2.startPcbPortId ? { startPcbPortId: e2.startPcbPortId } : {}, ...e2.endPcbPortId ? { endPcbPortId: e2.endPcbPortId } : {}, regionId: t47.capacityMeshNodeId ?? e2.regionId, traceThickness: e2.traceThickness, viaDiameter: t47.viaDiameter ?? e2.viaDiameter, route: t47.route?.map((t48) => ({ x: t48.x, y: t48.y, z: t48.z ?? 0 })) ?? e2.route, vias: t47.vias?.map((t48) => ({ x: t48.x, y: t48.y })) ?? e2.vias, jumpers: e2.jumpers });
var oq = (t47, e2, n2, o2, i2) => {
const r2 = JZ(t47, n2);
return e2.search(r2).filter((t48) => qZ(r2, QZ(t48))).filter((t48) => !i2 || !o2.some((e3) => xo(t48, e3, i2))).map((t48) => ({ type: t48.type, center: t48.center, width: t48.width, height: t48.height }));
};
var iq = class extends si {
repairMargin;
minimumTraceWidth;
sampleEntries;
originalHdRoutes;
originalNodeWithPortPoints;
originalObstacles;
obstacleSHI;
colorMap;
connMap;
repairedRoutesByIndex = new Map;
activeSampleIndex = 0;
activeSubSolver = null;
latestVisualization = {};
constructor(t47) {
super(), this.repairMargin = t47.repairMargin ?? 0.2, this.minimumTraceWidth = t47.minimumTraceWidth, this.originalHdRoutes = t47.hdRoutes, this.originalNodeWithPortPoints = t47.nodeWithPortPoints, this.originalObstacles = t47.obstacles, this.obstacleSHI = new Sk("flatbush", this.originalObstacles), this.colorMap = t47.colorMap ?? {}, this.connMap = t47.connMap;
const e2 = new Map;
for (let n3 = 0;n3 < t47.hdRoutes.length; n3++) {
if (tq(t47.hdRoutes[n3], t47.obstacles, t47.connMap))
continue;
const o3 = eq(t47.hdRoutes[n3], t47.nodeWithPortPoints, this.repairMargin);
if (o3 === -1)
continue;
const i3 = e2.get(o3) ?? [];
i3.push(n3), e2.set(o3, i3);
}
const n2 = Is(t47.obstacles, Math.max(2, ...t47.nodeWithPortPoints.flatMap((t48) => t48.availableZ?.map((t49) => t49 + 1) ?? []))), o2 = t47.hdRoutes.map((e3) => ((t48, e4, n3) => ({ capacityMeshNodeId: t48.regionId, connectionName: t48.connectionName, rootConnectionName: e4?.getNetConnectedToId(t48.connectionName) ?? t48.rootConnectionName, route: t48.route.map((t49) => ({ x: t49.x, y: t49.y, z: t49.z })), traceThickness: Math.max(t48.traceThickness, n3 ?? t48.traceThickness), vias: t48.vias.map((e5) => ({ x: e5.x, y: e5.y, diameter: t48.viaDiameter })), viaDiameter: t48.viaDiameter }))(e3, t47.connMap, t47.minimumTraceWidth)), i2 = new Ik(t47.hdRoutes.length);
for (const [e3, n3] of t47.hdRoutes.entries()) {
const t48 = [...n3.route, ...n3.vias];
if (t48.length === 0)
throw new Error(`High density repair route "${n3.connectionName}" has no points`);
const r3 = Math.max(o2[e3].traceThickness, n3.viaDiameter) / 2;
i2.insert({ routeIndex: e3 }, Math.min(...t48.map((t49) => t49.x)) - r3, Math.min(...t48.map((t49) => t49.y)) - r3, Math.max(...t48.map((t49) => t49.x)) + r3, Math.max(...t48.map((t49) => t49.y)) + r3);
}
t47.hdRoutes.length > 0 && i2.finish();
const r2 = Array.from(e2.entries()).map(([e3, r3]) => {
const s2 = t47.nodeWithPortPoints[e3], a2 = Math.max(...r3.map((e4) => Math.max(o2[e4].traceThickness, t47.hdRoutes[e4].viaDiameter) / 2)), c2 = JZ(s2, Math.max(this.repairMargin, a2 + 0.1)), l2 = new Set(r3);
return { node: s2, routeIndexes: r3, sample: { nodeWithPortPoints: { capacityMeshNodeId: s2.capacityMeshNodeId, center: s2.center, width: s2.width, height: s2.height, portPoints: s2.portPoints.map((t48) => ({ x: t48.x, y: t48.y, z: t48.z, connectionName: t48.connectionName, portPointId: t48.portPointId, prevPortPointId: t48.prevPortPointId, nextPortPointId: t48.nextPortPointId })) }, nodeHdRoutes: r3.map((e4) => ({ ...o2[e4], ...t47.connMap ? { connectedPadSides: ZZ(s2, t47.hdRoutes[e4], n2, t47.connMap) } : {} })), fixedHdRoutes: i2.search(c2.minX, c2.minY, c2.maxX, c2.maxY).filter(({ routeIndex: t48 }) => !l2.has(t48)).map(({ routeIndex: t48 }) => o2[t48]), clearanceObstacles: n2.filter((t48) => qZ(c2, QZ(t48))).map((e4) => ({ type: e4.type, center: e4.center, width: e4.width, height: e4.height, zLayers: e4.__zLayers, connectedTo: [...new Set(e4.connectedTo.flatMap((e5) => {
const n3 = t47.connMap?.getNetConnectedToId(e5);
return n3 ? [e5, n3] : [e5];
}))] })), adjacentObstacles: oq(s2, this.obstacleSHI, this.repairMargin, r3.map((e4) => t47.hdRoutes[e4]), t47.connMap) } };
});
this.sampleEntries = r2, this.MAX_ITERATIONS = Math.max(1000 * this.sampleEntries.length, 1e5), this.stats = { sampleCount: this.sampleEntries.length, repairedNodeCount: 0, repairedRouteCount: 0 };
}
getSolverName() {
return "Pipeline4HighDensityRepairSolver";
}
getConstructorParams() {
return [{ nodeWithPortPoints: this.sampleEntries.map((t47) => t47.node), hdRoutes: this.originalHdRoutes, obstacles: this.originalObstacles, repairMargin: this.repairMargin, minimumTraceWidth: this.minimumTraceWidth, colorMap: this.colorMap, connMap: this.connMap }];
}
_step() {
const t47 = this.sampleEntries[this.activeSampleIndex];
if (t47) {
if (this.activeSubSolver) {
if (this.activeSubSolver.step(), this.latestVisualization = this.activeSubSolver.visualize(), this.activeSubSolver.failed)
return this.failed = true, this.error = this.activeSubSolver.error ?? `High density repair failed for node ${t47.node.capacityMeshNodeId}`, void (this.activeSubSolver = null);
if (!this.activeSubSolver.solved)
return;
const e2 = this.activeSubSolver.getOutput().repairedRoutes, n2 = { nodeClearanceInitialConflictCount: Number(this.stats.nodeClearanceInitialConflictCount ?? 0) + Number(this.activeSubSolver.stats.nodeClearanceInitialConflictCount ?? 0), nodeClearanceFinalConflictCount: Number(this.stats.nodeClearanceFinalConflictCount ?? 0) + Number(this.activeSubSolver.stats.nodeClearanceFinalConflictCount ?? 0), nodeClearanceCandidateCount: Number(this.stats.nodeClearanceCandidateCount ?? 0) + Number(this.activeSubSolver.stats.nodeClearanceCandidateCount ?? 0) };
for (let n3 = 0;n3 < t47.routeIndexes.length; n3++) {
const o2 = t47.routeIndexes[n3], i2 = this.originalHdRoutes[o2], r2 = e2[n3];
this.repairedRoutesByIndex.set(o2, r2 ? nq(r2, i2) : i2);
}
return this.activeSubSolver = null, this.activeSampleIndex += 1, this.stats = { ...n2, sampleCount: this.sampleEntries.length, repairedNodeCount: this.activeSampleIndex, repairedRouteCount: this.repairedRoutesByIndex.size }, void (this.activeSampleIndex >= this.sampleEntries.length && (this.solved = true));
}
this.activeSubSolver = new UZ({ repairBoundaryDiagonals: false, sample: t47.sample, margin: this.repairMargin }), this.latestVisualization = this.activeSubSolver.visualize();
} else
this.solved = true;
}
getOutput() {
return this.originalHdRoutes.map((t47, e2) => this.repairedRoutesByIndex.get(e2) ?? t47);
}
visualize() {
if (this.activeSubSolver)
return this.activeSubSolver.visualize();
if (!this.solved)
return this.latestVisualization;
const t47 = [], e2 = [];
for (const n2 of this.getOutput()) {
const o2 = this.colorMap[n2.connectionName] ?? "#0ea5e9";
for (let e3 = 0;e3 < n2.route.length - 1; e3++) {
const i2 = n2.route[e3], r2 = n2.route[e3 + 1];
i2.z === r2.z && t47.push({ points: [{ x: i2.x, y: i2.y }, { x: r2.x, y: r2.y }], strokeColor: i2.z === 0 ? o2 : Ao(o2, 0.5), strokeWidth: n2.traceThickness, layer: `z${i2.z}`, strokeDash: i2.z !== 0 ? [0.1, 0.3] : undefined });
}
for (const t48 of n2.vias)
e2.push({ center: { x: t48.x, y: t48.y }, radius: n2.viaDiameter / 2, stroke: o2, fill: "rgba(14,165,233,0.12)" });
}
return { title: "Pipeline4 High Density Repair", lines: t47, circles: e2 };
}
};
var rq = 0.000001;
var sq = ({ startGap: t47, endGap: e2, segmentGap: n2, requiredGap: o2 }) => {
const i2 = t47 < o2 && e2 >= o2 - rq && n2 >= t47 - rq, r2 = e2 < o2 && t47 >= o2 - rq && n2 >= e2 - rq, s2 = t47 < o2 && e2 < o2 && n2 >= Math.min(t47, e2) - rq;
return i2 || r2 || s2;
};
var aq = class {
minClearance;
rootsByConnection = new Map;
sameNetCache = new Map;
segments = [];
vias = [];
segmentIndexesByLayer;
viaIndex;
constructor({ hdRoutes: t47, minClearance: e2 = 0.1 }) {
this.minClearance = e2;
for (const e3 of t47)
this.addRoute(e3);
this.buildSpatialIndexes();
}
addRoute(t47) {
const e2 = this.rootsByConnection.get(t47.connectionName) ?? new Set;
e2.add(t47.rootConnectionName ?? t47.connectionName), this.rootsByConnection.set(t47.connectionName, e2), this.sameNetCache.clear();
for (let e3 = 0;e3 < t47.route.length - 1; e3 += 1) {
const n2 = t47.route[e3], o2 = t47.route[e3 + 1];
if (n2.z !== o2.z)
continue;
if (n2.insideJumperPad && o2.insideJumperPad)
continue;
const i2 = { connectionName: t47.connectionName, start: n2, end: o2, traceThickness: t47.traceThickness };
this.segments.push(i2), this.insertSegmentIntoSpatialIndex(i2);
}
for (const e3 of t47.vias) {
const n2 = { connectionName: t47.connectionName, x: e3.x, y: e3.y, diameter: t47.viaDiameter };
this.vias.push(n2), this.insertViaIntoSpatialIndex(n2);
}
}
insertSegmentIntoSpatialIndex(t47) {
if (!this.segmentIndexesByLayer)
return;
let e2 = this.segmentIndexesByLayer.get(t47.start.z);
e2 || (e2 = new vk, this.segmentIndexesByLayer.set(t47.start.z, e2));
const n2 = t47.traceThickness / 2;
e2.insert(t47, Math.min(t47.start.x, t47.end.x) - n2, Math.min(t47.start.y, t47.end.y) - n2, Math.max(t47.start.x, t47.end.x) + n2, Math.max(t47.start.y, t47.end.y) + n2);
}
insertViaIntoSpatialIndex(t47) {
if (!this.viaIndex)
return;
const e2 = t47.diameter / 2;
this.viaIndex.insert(t47, t47.x - e2, t47.y - e2, t47.x + e2, t47.y + e2);
}
buildSpatialIndexes() {
this.segmentIndexesByLayer = new Map;
const t47 = new Map;
for (const e2 of this.segments) {
const n2 = t47.get(e2.start.z);
n2 ? n2.push(e2) : t47.set(e2.start.z, [e2]);
}
for (const [e2, n2] of t47) {
const t48 = new vk;
t48.bulkLoad(n2.map((t49) => {
const e3 = t49.traceThickness / 2;
return { item: t49, minX: Math.min(t49.start.x, t49.end.x) - e3, minY: Math.min(t49.start.y, t49.end.y) - e3, maxX: Math.max(t49.start.x, t49.end.x) + e3, maxY: Math.max(t49.start.y, t49.end.y) + e3 };
})), this.segmentIndexesByLayer.set(e2, t48);
}
this.viaIndex = new vk, this.viaIndex.bulkLoad(this.vias.map((t48) => {
const e2 = t48.diameter / 2;
return { item: t48, minX: t48.x - e2, minY: t48.y - e2, maxX: t48.x + e2, maxY: t48.y + e2 };
}));
}
areSameNet(t47, e2) {
if (t47 === e2)
return true;
const n2 = this.sameNetCache.get(t47)?.get(e2);
if (n2 !== undefined)
return n2;
const o2 = this.rootsByConnection.get(t47), i2 = this.rootsByConnection.get(e2);
let r2 = false;
if (o2 && i2) {
for (const t48 of o2)
if (i2.has(t48)) {
r2 = true;
break;
}
}
let s2 = this.sameNetCache.get(t47);
return s2 || (s2 = new Map, this.sameNetCache.set(t47, s2)), s2.set(e2, r2), r2;
}
isSegmentClear({ connectionName: t47, start: e2, end: n2, traceThickness: o2 }) {
const i2 = o2 / 2, r2 = this.minClearance + i2, s2 = Math.min(e2.x, n2.x) - r2, a2 = Math.min(e2.y, n2.y) - r2, c2 = Math.max(e2.x, n2.x) + r2, l2 = Math.max(e2.y, n2.y) + r2, h2 = this.segmentIndexesByLayer?.get(e2.z)?.search(s2, a2, c2, l2) ?? [];
for (const o3 of h2) {
if (this.areSameNet(t47, o3.connectionName))
continue;
const r3 = this.minClearance + i2 + o3.traceThickness / 2, s3 = Mk(e2, n2, o3.start, o3.end);
if (s3 < r3 && !sq({ startGap: be(e2, o3.start, o3.end), endGap: be(n2, o3.start, o3.end), segmentGap: s3, requiredGap: r3 }))
return false;
}
const d2 = this.viaIndex?.search(s2, a2, c2, l2) ?? [];
for (const o3 of d2) {
if (this.areSameNet(t47, o3.connectionName))
continue;
const r3 = this.minClearance + i2 + o3.diameter / 2, s3 = be(o3, e2, n2);
if (s3 < r3 && !sq({ startGap: Math.hypot(e2.x - o3.x, e2.y - o3.y), endGap: Math.hypot(n2.x - o3.x, n2.y - o3.y), segmentGap: s3, requiredGap: r3 }))
return false;
}
return true;
}
};
var cq = 0.000000001;
var lq = 1.25;
var hq = (t47, e2) => t47 < e2 ? -1 : t47 > e2 ? 1 : 0;
var dq = (t47, e2) => hq(t47.z, e2.z) || hq(t47.x, e2.x) || hq(t47.y, e2.y);
var uq = (t47) => `${t47.z.toFixed(6)}:${t47.x.toFixed(6)}:${t47.y.toFixed(6)}`;
var pq = (t47) => {
const e2 = t47.route.map(uq).join("|"), n2 = [...t47.route].reverse().map(uq).join("|");
return e2 <= n2 ? e2 : n2;
};
var mq = (t47, e2) => {
const n2 = t47.connectionName.localeCompare(e2.connectionName);
if (n2 !== 0)
return n2;
const o2 = (t47.rootConnectionName ?? "").localeCompare(e2.rootConnectionName ?? "");
if (o2 !== 0)
return o2;
const i2 = pq(t47).localeCompare(pq(e2));
return i2 !== 0 ? i2 : hq(t47.traceThickness, e2.traceThickness) || hq(t47.viaDiameter, e2.viaDiameter) || hq(t47.route.length, e2.route.length) || hq(t47.vias.length, e2.vias.length) || hq(t47.jumpers?.length ?? 0, e2.jumpers?.length ?? 0);
};
var gq = 1e5;
var fq = 0.001;
var yq = 1.000000001;
var _q = class extends si {
getSolverName() {
return "SingleHighDensityRouteStitchSolver3";
}
mergedHdRoute;
remainingHdRoutes;
start;
end;
colorMap;
allowedLayerTransitionPointKeys;
isStitchSegmentClear;
stitchClearanceMode;
isPlanarStitchClear(t47, e2) {
return this.isStitchSegmentClear({ connectionName: this.mergedHdRoute.connectionName, start: t47, end: e2, traceThickness: this.mergedHdRoute.traceThickness });
}
constructor(t47) {
super();
const e2 = [...t47.hdRoutes].sort(mq);
if (this.remainingHdRoutes = e2, this.colorMap = t47.colorMap ?? {}, this.allowedLayerTransitionPointKeys = t47.allowedLayerTransitionPointKeys, this.isStitchSegmentClear = t47.isStitchSegmentClear, this.stitchClearanceMode = t47.stitchClearanceMode, e2.length === 0) {
this.start = t47.start, this.end = t47.end;
const n3 = t47.defaultTraceThickness ?? 0.15, o3 = [{ x: t47.start.x, y: t47.start.y, z: t47.start.z }], i3 = [];
if (t47.start.z !== t47.end.z) {
if (t47.allowedLayerTransitionPointKeys && !t47.allowedLayerTransitionPointKeys.has(nX(t47.start)))
return this.failed = true, void (this.error = `Layer transition at ${nX(t47.start)} is not allowed`);
o3.push({ x: t47.start.x, y: t47.start.y, z: t47.end.z }), i3.push({ x: t47.start.x, y: t47.start.y });
}
const r3 = o3[o3.length - 1], s3 = { x: t47.end.x, y: t47.end.y, z: t47.end.z }, a3 = { connectionName: t47.connectionName, start: r3, end: s3, traceThickness: n3 };
return xe(r3, s3) > fq && !this.isStitchSegmentClear(a3) && this.stitchClearanceMode === "require_clear" ? (this.failed = true, void (this.error = `Terminal stitch for "${t47.connectionName}" violates copper clearance`)) : (o3.push(s3), this.mergedHdRoute = { connectionName: t47.connectionName, ...t47.preserveTerminalPcbPortIds && t47.start.pcb_port_id ? { startPcbPortId: t47.start.pcb_port_id } : {}, ...t47.preserveTerminalPcbPortIds && t47.end.pcb_port_id ? { endPcbPortId: t47.end.pcb_port_id } : {}, rootConnectionName: e2[0]?.rootConnectionName, route: o3, vias: i3, jumpers: [], viaDiameter: t47.defaultViaDiameter ?? 0.3, traceThickness: n3 }, void (this.solved = true));
}
const n2 = new Set((t47.preserveTerminalPcbPortIds ? [t47.start.pcb_port_id, t47.end.pcb_port_id] : []).filter((t48) => t48 !== undefined));
if (t47.preserveTerminalPcbPortIds && t47.start.pcb_port_id && t47.start.pcb_port_id === t47.end.pcb_port_id)
throw new Error(`SingleHighDensityRouteStitchSolver3 received duplicate PCB terminal "${t47.start.pcb_port_id}" for "${t47.connectionName}"`);
const o2 = e2.flatMap((t48) => [t48.startPcbPortId, t48.endPcbPortId]).filter((t48) => t48 !== undefined);
if (n2.size > 0) {
for (const e3 of o2)
if (!n2.has(e3))
throw new Error(`SingleHighDensityRouteStitchSolver3 found unknown PCB terminal "${e3}" on "${t47.connectionName}"`);
}
let i2 = 1 / 0, r2 = e2[0], s2 = "start-to-end";
for (const n3 of e2) {
const e3 = n3.route[0], o3 = n3.route[n3.route.length - 1], a3 = xe(t47.start, e3), c3 = xe(t47.start, o3), l3 = xe(t47.end, e3), h3 = xe(t47.end, o3), d3 = Math.min(a3, c3, l3, h3);
(d3 < i2 - cq || Math.abs(d3 - i2) <= cq && mq(n3, r2) < 0) && (i2 = d3, r2 = n3, s2 = Math.min(l3, h3) < Math.min(a3, c3) - cq || Math.abs(Math.min(l3, h3) - Math.min(a3, c3)) <= cq && dq(t47.end, t47.start) < 0 ? "end-to-start" : "start-to-end");
}
s2 === "start-to-end" ? (this.start = t47.start, this.end = t47.end) : (this.start = t47.end, this.end = t47.start);
const a2 = r2.route[0], c2 = r2.route[r2.route.length - 1], l2 = xe(this.start, a2), h2 = xe(this.start, c2), d2 = l2 < h2 - cq || Math.abs(l2 - h2) <= cq && dq(a2, c2) <= 0 ? a2 : c2, u2 = d2 === a2 ? r2.startPcbPortId : r2.endPcbPortId;
if (u2 && this.start.pcb_port_id && u2 !== this.start.pcb_port_id)
throw new Error(`SingleHighDensityRouteStitchSolver3 terminal identity disagrees with route orientation for "${t47.connectionName}"`);
this.mergedHdRoute = { connectionName: t47.connectionName, ...t47.preserveTerminalPcbPortIds && this.start.pcb_port_id ? { startPcbPortId: this.start.pcb_port_id } : {}, ...t47.preserveTerminalPcbPortIds && this.end.pcb_port_id ? { endPcbPortId: this.end.pcb_port_id } : {}, rootConnectionName: r2.rootConnectionName, route: [{ x: this.start.x, y: this.start.y, z: d2.z }], vias: [], jumpers: [], viaDiameter: r2.viaDiameter, traceThickness: r2.traceThickness };
}
getDisjointedRoute() {
for (const t47 of this.remainingHdRoutes) {
if ([t47.route[0], t47.route[t47.route.length - 1]].some((e2) => !this.remainingHdRoutes.some((n2) => {
if (n2 === t47)
return false;
return [n2.route[0], n2.route[n2.route.length - 1]].some((t48) => t48.z === e2.z && xe(e2, t48) < 0.001);
})))
return { firstRoute: t47 };
}
return { firstRoute: this.remainingHdRoutes[0] };
}
_step() {
if (this.remainingHdRoutes.length === 0) {
const t48 = this.mergedHdRoute.route[this.mergedHdRoute.route.length - 1], e3 = { ...this.end, z: t48.z }, n3 = xe(t48, e3);
if (n3 > fq && n3 <= lq) {
if (!this.isPlanarStitchClear(t48, e3) && this.stitchClearanceMode === "require_clear")
return this.failed = true, void (this.error = `Terminal stitch for "${this.mergedHdRoute.connectionName}" violates copper clearance`);
this.mergedHdRoute.route.push({ x: this.end.x, y: this.end.y, z: t48.z });
}
return void (this.solved = true);
}
const t47 = this.mergedHdRoute.route[this.mergedHdRoute.route.length - 1];
let e2 = -1, n2 = "first", o2 = 1 / 0, i2 = false;
for (let r3 = 0;r3 < this.remainingHdRoutes.length; r3++) {
const s3 = this.remainingHdRoutes[r3], a2 = s3.route[0], c2 = s3.route[s3.route.length - 1], l2 = xe(t47, a2), h2 = xe(t47, c2);
let d2 = 1 / 0;
if (t47.z === a2.z) {
if (l2 < fq)
d2 = l2;
else if (l2 <= 1) {
const e3 = this.isPlanarStitchClear(t47, a2);
if (e3 || this.stitchClearanceMode === "prefer_clear") {
d2 = gq + (e3 ? 0 : yq) + l2;
} else
i2 = true;
}
} else
l2 < fq && (!this.allowedLayerTransitionPointKeys || this.allowedLayerTransitionPointKeys.has(nX(a2))) && (d2 = 1000 + l2);
d2 < o2 && (o2 = d2, e2 = r3, n2 = "first");
let u2 = 1 / 0;
if (t47.z === c2.z) {
if (h2 < fq)
u2 = h2;
else if (h2 <= 1) {
const e3 = this.isPlanarStitchClear(t47, c2);
if (e3 || this.stitchClearanceMode === "prefer_clear") {
u2 = gq + (e3 ? 0 : yq) + h2;
} else
i2 = true;
}
} else
h2 < fq && (!this.allowedLayerTransitionPointKeys || this.allowedLayerTransitionPointKeys.has(nX(c2))) && (u2 = 1000 + h2);
u2 < o2 && (o2 = u2, e2 = r3, n2 = "last");
}
if (e2 === -1)
return i2 ? (this.failed = true, void (this.error = `Route stitch for "${this.mergedHdRoute.connectionName}" violates copper clearance`)) : void (this.remainingHdRoutes = []);
const r2 = this.remainingHdRoutes[e2];
let s2;
this.remainingHdRoutes.splice(e2, 1), s2 = n2 === "first" ? r2.route : ((t48) => {
const e3 = [...t48].reverse().map((t49) => {
const { toNextSegmentType: e4, ...n3 } = t49;
return n3;
});
for (let n3 = 0;n3 < t48.length - 1; n3++) {
const o3 = t48[n3]?.toNextSegmentType;
if (!o3)
continue;
const i3 = t48.length - n3 - 2;
e3[i3] = { ...e3[i3], toNextSegmentType: o3 };
}
return e3;
})(r2.route), s2.length > 0 && xe(t47, s2[0]) < fq && t47.z === s2[0].z ? (s2[0].toNextSegmentType && (t47.toNextSegmentType = s2[0].toNextSegmentType), this.mergedHdRoute.route.push(...s2.slice(1))) : this.mergedHdRoute.route.push(...s2), this.mergedHdRoute.vias.push(...r2.vias), r2.jumpers && this.mergedHdRoute.jumpers.push(...r2.jumpers);
}
visualize() {
const t47 = { points: [], lines: [], circles: [], rects: [], title: "Single High Density Route Stitch Solver 3" };
if (t47.points?.push({ x: this.start.x, y: this.start.y, color: "green", label: "Start" }, { x: this.end.x, y: this.end.y, color: "red", label: "End" }), this.mergedHdRoute && this.mergedHdRoute.route.length > 1) {
t47.lines?.push({ points: this.mergedHdRoute.route.map((t48) => ({ x: t48.x, y: t48.y })), strokeColor: "green" });
for (const e2 of this.mergedHdRoute.route)
t47.points?.push({ x: e2.x, y: e2.y, color: "green" });
for (const e2 of this.mergedHdRoute.vias)
t47.circles?.push({ center: { x: e2.x, y: e2.y }, radius: this.mergedHdRoute.viaDiameter / 2, fill: "green" });
if (this.mergedHdRoute.jumpers && this.mergedHdRoute.jumpers.length > 0) {
const e2 = mk(this.mergedHdRoute.jumpers, { color: "green", label: this.mergedHdRoute.connectionName });
t47.rects.push(...e2.rects ?? []), t47.lines.push(...e2.lines ?? []);
}
}
for (const e2 of this.remainingHdRoutes) {
t47.lines?.push({ points: e2.route.map((t48) => ({ x: t48.x, y: t48.y })), strokeColor: "orange" });
for (const n2 of e2.route)
t47.points?.push({ x: n2.x, y: n2.y, color: "orange" });
for (const n2 of e2.vias)
t47.circles?.push({ center: { x: n2.x, y: n2.y }, radius: e2.viaDiameter / 2, fill: "orange" });
if (e2.jumpers && e2.jumpers.length > 0) {
const n2 = mk(e2.jumpers, { color: "orange", label: e2.connectionName });
t47.rects.push(...n2.rects ?? []), t47.lines.push(...n2.lines ?? []);
}
}
return t47;
}
};
var bq = class {
constructor(t47 = false) {
this.preferSameLayerTerminalEndpoints = t47;
}
endpointClusters = new Map;
getEndpointKey(t47, e2) {
const n2 = this.endpointClusters.get(t47) ?? [];
let o2, i2 = 1 / 0;
for (const t48 of n2) {
if (t48.point.z !== e2.z)
continue;
const n3 = xe(t48.point, e2);
n3 <= 0.1 && (n3 < i2 - cq || Math.abs(n3 - i2) <= cq && (!o2 || dq(t48.point, o2.point) < 0)) && (o2 = t48, i2 = n3);
}
if (o2)
return o2.key;
const r2 = `${t47}:endpoint_${n2.length}`;
return n2.push({ key: r2, point: { x: e2.x, y: e2.y, z: e2.z } }), this.endpointClusters.set(t47, n2), r2;
}
getClusters(t47) {
return this.endpointClusters.get(t47) ?? [];
}
getClosestEndpointKey(t47, e2, n2) {
const o2 = e2.flatMap((t48) => [t48.route[0], t48.route[t48.route.length - 1]]), i2 = o2.filter((t48) => t48.z === n2.z), r2 = this.preferSameLayerTerminalEndpoints && i2.length > 0 ? i2 : o2;
let s2 = null, a2 = null, c2 = 1 / 0;
for (const e3 of r2) {
const o3 = xe(n2, e3), i3 = this.getEndpointKey(t47, e3);
(o3 < c2 - cq || Math.abs(o3 - c2) <= cq && (s2 === null || i3.localeCompare(s2) < 0 || i3 === s2 && a2 !== null && dq(e3, a2) < 0)) && (c2 = o3, s2 = i3, a2 = e3);
}
return s2;
}
};
var xq = (t47, e2, n2) => {
const o2 = t47.get(e2) ?? [];
o2.some((t48) => t48.nextHash === n2.nextHash && t48.routeIndex === n2.routeIndex) || (o2.push(n2), t47.set(e2, o2));
};
var vq = (t47) => {
const e2 = [...t47.possibleEndpoints].sort(dq), n2 = e2.reduce((e3, n3) => {
const o3 = xe(n3, t47.globalStart), i3 = xe(e3, t47.globalStart);
return o3 < i3 - cq || Math.abs(o3 - i3) <= cq && dq(n3, e3) < 0 ? n3 : e3;
}), o2 = e2.filter((t48) => t48 !== n2), i2 = (o2.length > 0 ? o2 : t47.possibleEndpoints).reduce((e3, n3) => {
const o3 = xe(n3, t47.globalEnd), i3 = xe(e3, t47.globalEnd);
return o3 < i3 - cq || Math.abs(o3 - i3) <= cq && dq(n3, e3) < 0 ? n3 : e3;
});
return { start: n2, end: i2 };
};
var Iq = (t47) => {
const e2 = [...t47.terminals].sort(dq);
let n2 = e2[0], o2 = xe(t47.islandEndpoint, n2);
for (const i2 of e2.slice(1)) {
const e3 = xe(t47.islandEndpoint, i2);
(e3 < o2 - cq || Math.abs(e3 - o2) <= cq && dq(i2, n2) < 0) && (n2 = i2, o2 = e3);
}
return o2 <= lq ? n2 : t47.islandEndpoint;
};
var Sq = (t47) => {
if (t47.hdRoutes.length <= 2)
return t47.hdRoutes;
const e2 = [...t47.hdRoutes].sort(mq), n2 = t47.endpointIndex.getClosestEndpointKey(t47.connectionName, e2, t47.start), o2 = t47.endpointIndex.getClosestEndpointKey(t47.connectionName, e2, t47.end);
if (!n2 || !o2 || n2 === o2)
return e2;
const i2 = new Map;
for (let n3 = 0;n3 < e2.length; n3++) {
const o3 = e2[n3], r3 = t47.endpointIndex.getEndpointKey(t47.connectionName, o3.route[0]), s3 = t47.endpointIndex.getEndpointKey(t47.connectionName, o3.route[o3.route.length - 1]);
xq(i2, r3, { nextHash: s3, routeIndex: n3 }), xq(i2, s3, { nextHash: r3, routeIndex: n3 });
}
const r2 = [...t47.endpointIndex.getClusters(t47.connectionName)].sort((t48, e3) => dq(t48.point, e3.point));
for (let t48 = 0;t48 < r2.length; t48++) {
const e3 = r2[t48];
for (let n3 = t48 + 1;n3 < r2.length; n3++) {
const t49 = r2[n3];
e3.point.z === t49.point.z && (xe(e3.point, t49.point) > 1 || (xq(i2, e3.key, { nextHash: t49.key, routeIndex: null }), xq(i2, t49.key, { nextHash: e3.key, routeIndex: null })));
}
}
for (const [t48, n3] of i2.entries())
i2.set(t48, [...n3].sort((t49, n4) => {
if (t49.routeIndex === null && n4.routeIndex !== null)
return 1;
if (t49.routeIndex !== null && n4.routeIndex === null)
return -1;
if (t49.routeIndex !== null && n4.routeIndex !== null) {
const o3 = mq(e2[t49.routeIndex], e2[n4.routeIndex]);
if (o3 !== 0)
return o3;
}
return t49.nextHash.localeCompare(n4.nextHash);
}));
const s2 = [n2], a2 = new Set([n2]), c2 = new Map;
for (;s2.length > 0; ) {
const t48 = s2.shift();
if (t48 === o2)
break;
for (const e3 of i2.get(t48) ?? [])
a2.has(e3.nextHash) || (a2.add(e3.nextHash), c2.set(e3.nextHash, { prevHash: t48, routeIndex: e3.routeIndex }), s2.push(e3.nextHash));
}
if (!a2.has(o2))
return e2;
const l2 = [];
let h2 = o2;
for (;h2 !== n2; ) {
const t48 = c2.get(h2);
if (!t48)
return e2;
t48.routeIndex !== null && l2.push(t48.routeIndex), h2 = t48.prevHash;
}
if (l2.length === 0)
return t47.hdRoutes;
const d2 = l2.reverse().map((t48) => e2[t48]);
return d2.length > 0 && !t47.canStitchBetweenTerminals({ connectionName: t47.connectionName, hdRoutes: d2, start: t47.start, end: t47.end }) ? e2 : d2;
};
var Cq = class extends si {
getSolverName() {
return "MultipleHighDensityRouteStitchSolver3";
}
unsolvedRoutes;
activeSolver = null;
mergedHdRoutes = [];
colorMap = {};
defaultTraceThickness;
defaultViaDiameter;
allowedLayerTransitionPointKeys;
preserveTerminalPcbPortIds;
endpointIndex;
clearanceValidator;
canStitchBetweenTerminals(t47) {
const e2 = new _q({ connectionName: t47.connectionName, hdRoutes: t47.hdRoutes, start: t47.start, end: t47.end, colorMap: this.colorMap, defaultTraceThickness: this.defaultTraceThickness, defaultViaDiameter: this.defaultViaDiameter, allowedLayerTransitionPointKeys: this.allowedLayerTransitionPointKeys, preserveTerminalPcbPortIds: this.preserveTerminalPcbPortIds, isStitchSegmentClear: (t48) => this.clearanceValidator.isSegmentClear(t48), stitchClearanceMode: "require_clear" });
for (;!e2.solved && !e2.failed && e2.iterations < e2.MAX_ITERATIONS; )
e2.step();
if (e2.failed)
return false;
const n2 = e2.mergedHdRoute.route[0], o2 = e2.mergedHdRoute.route[e2.mergedHdRoute.route.length - 1];
return n2.z === e2.start.z && o2.z === e2.end.z && xe(n2, e2.start) + xe(o2, e2.end) <= lq;
}
getSharedRootPathRoutes(t47) {
const e2 = t47.rootConnectionName;
if (!e2)
return null;
const n2 = new Set(t47.hdRoutes), o2 = t47.allHdRoutes.filter((t48) => (t48.rootConnectionName ?? t48.connectionName) === e2);
if (o2.every((t48) => n2.has(t48)))
return null;
const i2 = Sq({ connectionName: t47.connectionName, hdRoutes: o2, start: t47.start, end: t47.end, endpointIndex: this.endpointIndex, canStitchBetweenTerminals: (t48) => this.canStitchBetweenTerminals(t48) });
return !i2.some((t48) => !n2.has(t48)) || i2.length >= o2.length ? null : i2;
}
constructor(t47) {
super(), this.endpointIndex = new bq(t47.preferSameLayerTerminalEndpoints), this.colorMap = t47.colorMap ?? {}, this.allowedLayerTransitionPointKeys = t47.allowedLayerTransitionPointKeys, this.preserveTerminalPcbPortIds = t47.preserveTerminalPcbPortIds ?? false;
const e2 = [...t47.hdRoutes].sort(mq);
this.clearanceValidator = new aq({ hdRoutes: e2 });
const n2 = e2[0];
this.defaultTraceThickness = n2?.traceThickness ?? 0.15, this.defaultViaDiameter = n2?.viaDiameter ?? t47.defaultViaDiameter ?? 0.3;
const o2 = new uk({}), i2 = [], r2 = new Map;
for (let t48 = 0;t48 < e2.length; t48++) {
const n3 = e2[t48], o3 = n3.route[0], r3 = n3.route[n3.route.length - 1];
i2.push([`route_island_${t48}`, this.endpointIndex.getEndpointKey(n3.connectionName, o3), this.endpointIndex.getEndpointKey(n3.connectionName, r3)]);
}
o2.addConnections(i2);
for (const t48 of i2)
for (const e3 of t48.slice(1))
r2.set(e3, (r2.get(e3) ?? 0) + 1);
this.unsolvedRoutes = [];
const s2 = Array.from(new Set(Object.values(o2.idToNetMap)));
for (const n3 of s2) {
const i3 = o2.getIdsConnectedToNet(n3), s3 = e2.filter((t48, e3) => i3.includes(`route_island_${e3}`));
if (s3.length === 0)
continue;
const a3 = t47.connections.find((t48) => t48.name === s3[0].connectionName), c2 = s3.flatMap((t48) => [t48.route[0], t48.route[t48.route.length - 1]]), l2 = new Map, h2 = [];
for (const t48 of c2) {
const e3 = this.endpointIndex.getEndpointKey(s3[0].connectionName, t48);
l2.has(e3) || l2.set(e3, t48), r2.get(e3) === 1 && h2.push(t48);
}
const d2 = h2.length > 0 ? h2 : [...l2.values()];
if (d2.length === 0)
continue;
let u2, p2;
if (d2.length >= 2) {
const e3 = { ...a3.pointsToConnect[0], z: mo(Io(a3.pointsToConnect[0]), t47.layerCount) }, n4 = { ...a3.pointsToConnect[1], z: mo(Io(a3.pointsToConnect[1]), t47.layerCount) };
(({ start: u2, end: p2 } = vq({ possibleEndpoints: d2, globalStart: e3, globalEnd: n4 }))), xe(u2, a3.pointsToConnect[1]) < xe(p2, a3.pointsToConnect[0]) && ([u2, p2] = [p2, u2]), u2 = Iq({ islandEndpoint: u2, terminals: [e3, n4] }), p2 = Iq({ islandEndpoint: p2, terminals: [e3, n4] });
} else
u2 = { ...a3.pointsToConnect[0], z: mo(Io(a3.pointsToConnect[0]), t47.layerCount) }, p2 = { ...a3.pointsToConnect[1], z: mo(Io(a3.pointsToConnect[1]), t47.layerCount) };
const m2 = Sq({ connectionName: s3[0].connectionName, hdRoutes: s3, start: u2, end: p2, endpointIndex: this.endpointIndex, canStitchBetweenTerminals: (t48) => this.canStitchBetweenTerminals(t48) });
this.unsolvedRoutes.push({ connectionName: s3[0].connectionName, hdRoutes: m2, start: u2, end: p2 });
}
const a2 = new Map;
for (const t48 of this.unsolvedRoutes) {
const e3 = a2.get(t48.connectionName);
e3 ? e3.push(t48) : a2.set(t48.connectionName, [t48]);
}
this.unsolvedRoutes = Array.from(a2.entries()).flatMap(([n3, o3]) => {
const i3 = t47.connections.find((t48) => t48.name === n3), r3 = o3.some((t48) => t48.hdRoutes.some((t49) => t49.route.length < 2)), s3 = o3.length > 1 && ((t48) => {
for (let e3 = 0;e3 < t48.length; e3++)
for (let n4 = e3 + 1;n4 < t48.length; n4++) {
const o4 = [t48[e3].start, t48[e3].end], i4 = [t48[n4].start, t48[n4].end];
for (const t49 of o4)
for (const e4 of i4)
if (t49.z === e4.z && xe(t49, e4) <= 1)
return true;
}
return false;
})(o3);
if (!i3)
return o3;
const a3 = { ...i3.pointsToConnect[0], z: mo(Io(i3.pointsToConnect[0]), t47.layerCount) }, c2 = { ...i3.pointsToConnect[1], z: mo(Io(i3.pointsToConnect[1]), t47.layerCount) }, l2 = o3.flatMap((t48) => t48.hdRoutes), h2 = o3.length > 1 ? this.getSharedRootPathRoutes({ connectionName: n3, rootConnectionName: i3.__rootConnectionNames?.[0] ?? l2[0]?.rootConnectionName, hdRoutes: l2, allHdRoutes: e2, start: a3, end: c2 }) : null;
return r3 || s3 || h2 ? [{ connectionName: n3, hdRoutes: h2 ?? Sq({ connectionName: n3, hdRoutes: l2, start: a3, end: c2, endpointIndex: this.endpointIndex, canStitchBetweenTerminals: (t48) => this.canStitchBetweenTerminals(t48) }), start: a3, end: c2 }] : o3;
}), this.MAX_ITERATIONS = 1e5;
}
_step() {
if (this.activeSolver)
return this.activeSolver.step(), void (this.activeSolver.solved ? (this.activeSolver instanceof _q && (this.clearanceValidator.addRoute(this.activeSolver.mergedHdRoute), this.mergedHdRoutes.push(this.activeSolver.mergedHdRoute)), this.activeSolver = null) : this.activeSolver.failed && (this.failed = true, this.error = this.activeSolver.error));
const t47 = this.unsolvedRoutes.pop();
t47 ? this.activeSolver = new _q({ connectionName: t47.connectionName, hdRoutes: t47.hdRoutes, start: t47.start, end: t47.end, colorMap: this.colorMap, defaultTraceThickness: this.defaultTraceThickness, defaultViaDiameter: this.defaultViaDiameter, allowedLayerTransitionPointKeys: this.allowedLayerTransitionPointKeys, preserveTerminalPcbPortIds: this.preserveTerminalPcbPortIds, isStitchSegmentClear: (t48) => this.clearanceValidator.isSegmentClear(t48), stitchClearanceMode: "prefer_clear" }) : this.solved = true;
}
visualize() {
const t47 = { points: [], lines: [], circles: [], rects: [], title: "Multiple High Density Route Stitch Solver 3" };
if (this.activeSolver) {
const e2 = this.activeSolver.visualize();
e2.points?.length && t47.points?.push(...e2.points), e2.lines?.length && t47.lines?.push(...e2.lines), e2.circles?.length && t47.circles?.push(...e2.circles), e2.rects?.length && (t47.rects || (t47.rects = []), t47.rects.push(...e2.rects));
}
for (const [e2, n2] of this.mergedHdRoutes.entries()) {
const o2 = this.colorMap[n2.connectionName] ?? `hsl(120, 100%, ${40 + 10 * e2 % 40}%)`;
for (let e3 = 0;e3 < n2.route.length - 1; e3++) {
const i2 = n2.route[e3], r2 = n2.route[e3 + 1], s2 = i2.z !== 0 ? Ao(o2, 0.5) : o2;
t47.lines?.push({ points: [{ x: i2.x, y: i2.y }, { x: r2.x, y: r2.y }], strokeColor: s2, strokeWidth: n2.traceThickness });
}
for (const e3 of n2.route) {
const n3 = e3.z !== 0 ? Ao(o2, 0.5) : o2;
t47.points?.push({ x: e3.x, y: e3.y, color: n3 });
}
for (const e3 of n2.vias)
t47.circles?.push({ center: { x: e3.x, y: e3.y }, radius: n2.viaDiameter / 2, fill: o2 });
if (n2.jumpers && n2.jumpers.length > 0) {
const e3 = mk(n2.jumpers, { color: o2, label: n2.connectionName });
t47.rects.push(...e3.rects ?? []), t47.lines.push(...e3.lines ?? []);
}
}
return t47;
}
};
var Pq = (t47) => (t47 % 360 + 360) % 360;
var Mq = (t47, e2) => {
const { ccwRotationDegrees: n2, ...o2 } = t47, i2 = ((t48) => {
const e3 = Pq(t48), n3 = [0, 90, 180, 270];
for (const t49 of n3)
if (Math.min(Math.abs(e3 - t49), 360 - Math.abs(e3 - t49)) <= 0.01)
return t49;
return null;
})(e2);
return i2 === 90 || i2 === 270 ? { ...o2, width: t47.height, height: t47.width } : o2;
};
var Nq = (t47, e2) => !(So(t47).length > 0 && !So(t47).some((t48) => e2.layers.includes(t48))) && Me(t47, We(e2));
var wq = (t47, e2) => {
const { minX: n2, maxX: o2, minY: i2, maxY: r2 } = We(e2);
return { x: Math.max(n2, Math.min(o2, t47.x)), y: Math.max(i2, Math.min(r2, t47.y)) };
};
var Tq = (t47, e2) => t47.obstacleId ?? `${t47.componentId ?? "obstacle"}_${e2}`;
function Rq(t47, e2 = 2) {
const { center: n2, width: o2, height: i2, rotation: r2 } = t47, s2 = [], a2 = Math.max(1, Math.ceil(e2)), c2 = r2 * Math.PI / 180, l2 = Math.cos(c2), h2 = Math.sin(c2);
if (o2 >= i2) {
const t48 = o2 / a2;
for (let e3 = 0;e3 < a2; e3++) {
const o3 = (e3 - a2 / 2 + 0.5) * t48, r3 = o3 * l2, c3 = o3 * h2, d2 = Math.abs(t48 * l2) + Math.abs(i2 * h2), u2 = Math.abs(t48 * h2) + Math.abs(i2 * l2);
s2.push({ center: { x: n2.x + r3, y: n2.y + c3 }, width: d2, height: u2 });
}
} else {
const t48 = i2 / a2;
for (let e3 = 0;e3 < a2; e3++) {
const i3 = (e3 - a2 / 2 + 0.5) * t48, r3 = -i3 * h2, c3 = i3 * l2, d2 = Math.abs(o2 * l2) + Math.abs(t48 * h2), u2 = Math.abs(o2 * h2) + Math.abs(t48 * l2);
s2.push({ center: { x: n2.x + r3, y: n2.y + c3 }, width: d2, height: u2 });
}
}
return s2;
}
var Eq = (t47) => {
if (t47.type === "oval")
return Eq({ ...t47, type: "rect" });
const e2 = t47.ccwRotationDegrees;
if (typeof e2 != "number" || !Number.isFinite(e2))
return [t47];
if (((t48) => {
const e3 = Pq(t48);
return [0, 90, 180, 270].some((t49) => Math.min(Math.abs(e3 - t49), 360 - Math.abs(e3 - t49)) <= 0.01);
})(e2))
return [Mq(t47, e2)];
const { ccwRotationDegrees: n2, ...o2 } = t47, i2 = { center: t47.center, width: t47.width, height: t47.height, rotation: e2 }, r2 = ((t48) => {
const e3 = Math.max(t48.width, t48.height), n3 = Math.min(t48.width, t48.height);
return t48.obstacleId?.startsWith("trace_obstacle_") ? Math.max(2, Math.ceil(e3 / 0.75)) : n3 <= 0 ? 2 : e3 / n3 < 2 || n3 >= 0.9 ? null : Math.max(2, Math.ceil(e3 / 0.75));
})(t47), s2 = t47.connectedTo.length > 0 && !t47.obstacleId?.startsWith("trace_obstacle_") ? ((t48) => {
const e3 = t48.rotation * Math.PI / 180, n3 = Math.cos(e3), o3 = Math.sin(e3), i3 = [-1, 1].flatMap((e4) => [-1, 1].map((i4) => {
const r4 = e4 * (t48.width / 2), s4 = i4 * (t48.height / 2);
return { x: t48.center.x + r4 * n3 - s4 * o3, y: t48.center.y + r4 * o3 + s4 * n3 };
})), r3 = [i3[0], i3[2], i3[3], i3[1]], s3 = Math.min(...r3.map((t49) => t49.x)), a3 = Math.max(...r3.map((t49) => t49.x)), c2 = Math.min(...r3.map((t49) => t49.y)), l2 = Math.max(...r3.map((t49) => t49.y)), h2 = a3 - s3 <= l2 - c2 ? "x" : "y", d2 = h2 === "x" ? s3 : c2, u2 = h2 === "x" ? a3 : l2, p2 = Math.max(1, Math.ceil((u2 - d2) / 0.4)), m2 = (u2 - d2) / p2, g2 = (t49, e4, n4) => {
const o4 = [], i4 = (t50) => t50[h2];
for (let r4 = 0;r4 < t49.length; r4++) {
const s4 = t49[r4], a4 = t49[(r4 + 1) % t49.length], c3 = i4(s4), l3 = i4(a4), h3 = n4 ? c3 >= e4 : c3 <= e4, d3 = n4 ? l3 >= e4 : l3 <= e4;
if (h3 && o4.push(s4), h3 === d3)
continue;
const u3 = (e4 - c3) / (l3 - c3);
o4.push({ x: s4.x + (a4.x - s4.x) * u3, y: s4.y + (a4.y - s4.y) * u3 });
}
return o4;
}, f2 = [];
for (let t49 = 0;t49 < p2; t49++) {
const e4 = d2 + t49 * m2, n4 = t49 === p2 - 1 ? u2 : e4 + m2, o4 = g2(g2(r3, e4, true), n4, false);
if (o4.length === 0)
continue;
const i4 = Math.min(...o4.map((t50) => t50.x)), s4 = Math.max(...o4.map((t50) => t50.x)), a4 = Math.min(...o4.map((t50) => t50.y)), c3 = Math.max(...o4.map((t50) => t50.y));
f2.push({ center: { x: (i4 + s4) / 2, y: (a4 + c3) / 2 }, width: s4 - i4, height: c3 - a4 });
}
return f2;
})(i2) : r2 === null ? ((t48, e3) => {
const { center: n3, width: o3, height: i3, rotation: r3 } = t48, s3 = Math.max(1, Math.ceil(o3 / e3)), a3 = Math.max(1, Math.ceil(i3 / e3)), c2 = o3 / s3, l2 = i3 / a3, h2 = r3 * Math.PI / 180, d2 = Math.cos(h2), u2 = Math.sin(h2), p2 = [];
for (let t49 = 0;t49 < s3; t49++) {
const e4 = (t49 - s3 / 2 + 0.5) * c2;
for (let t50 = 0;t50 < a3; t50++) {
const o4 = (t50 - a3 / 2 + 0.5) * l2;
p2.push({ center: { x: n3.x + e4 * d2 - o4 * u2, y: n3.y + e4 * u2 + o4 * d2 }, width: Math.abs(c2 * d2) + Math.abs(l2 * u2), height: Math.abs(c2 * u2) + Math.abs(l2 * d2) });
}
}
return p2;
})(i2, ((t48) => t48.obstacleId?.startsWith("trace_obstacle_") ? 0.75 : 0.4)(t47)) : t47.obstacleId?.startsWith("trace_obstacle_") ? Rq(i2, r2) : ((t48, e3) => {
const { center: n3, width: o3, height: i3, rotation: r3 } = t48, s3 = Math.max(o3, i3), a3 = Math.min(o3, i3), c2 = Math.max(1, Math.ceil(e3)), l2 = s3 / c2, h2 = r3 * Math.PI / 180, d2 = Math.cos(h2), u2 = Math.sin(h2), p2 = Math.max(l2, 0.75 * a3), m2 = [];
for (let t49 = 0;t49 < c2; t49++) {
const e4 = (t49 - c2 / 2 + 0.5) * l2, r4 = o3 >= i3 ? e4 * d2 : -e4 * u2, s4 = o3 >= i3 ? e4 * u2 : e4 * d2;
m2.push({ center: { x: n3.x + r4, y: n3.y + s4 }, width: p2, height: p2 });
}
return m2;
})(i2, r2), a2 = t47.connectedTo.length > 0 ? s2.reduce((e3, n3, o3) => {
const i3 = s2[e3], r3 = (i3.center.x - t47.center.x) ** 2 + (i3.center.y - t47.center.y) ** 2;
return (n3.center.x - t47.center.x) ** 2 + (n3.center.y - t47.center.y) ** 2 < r3 ? o3 : e3;
}, 0) : -1;
return s2.map((t48, e3) => ({ ...o2, obstacleId: e3 === a2 ? o2.obstacleId : o2.obstacleId ? `${o2.obstacleId}_approx_${e3}` : undefined, connectedTo: o2.connectedTo, center: t48.center, width: t48.width, height: t48.height }));
};
var Aq = (t47) => {
const e2 = new Map, n2 = new Map, o2 = new Map;
for (const [i3, r2] of t47.obstacles.entries()) {
const t48 = Eq(r2), s2 = Tq(r2, i3);
n2.set(s2, t48), o2.set(s2, r2);
for (const n3 of t48) {
const t49 = [n3.center.x.toFixed(6), n3.center.y.toFixed(6), n3.width.toFixed(6), n3.height.toFixed(6), n3.layers.join(",")].join(":"), o3 = e2.get(t49);
o3 ? o3.connectedTo = [...new Set([...o3.connectedTo, ...n3.connectedTo])] : e2.set(t49, n3);
}
}
const i2 = t47.connections.map((t48) => ({ ...t48, pointsToConnect: t48.pointsToConnect.map((t49) => {
const e3 = ((t50) => [t50.pointId, t50.pcb_port_id].filter((t51) => Boolean(t51)))(t49);
if (e3.length === 0)
return t49;
for (const [i3, r2] of o2) {
if (!e3.some((t50) => r2.connectedTo.includes(t50)))
continue;
if (!Nq(t49, r2))
continue;
const o3 = n2.get(i3) ?? [];
if (o3.length === 0)
continue;
if (o3.some((e4) => Nq(t49, e4)))
return t49;
let s2 = o3[0], a2 = Number.POSITIVE_INFINITY;
for (const e4 of o3) {
const n3 = xe(wq(t49, e4), t49);
n3 < a2 && (a2 = n3, s2 = e4);
}
return { ...t49, ...wq(t49, s2) };
}
return t49;
}) }));
return { ...t47, connections: i2, obstacles: [...e2.values()] };
};
var Oq = 0.001;
var kq = (t47) => t47.route_type === "wire";
var Dq = (t47) => t47.route_type === "via";
var Lq = (t47) => t47.route_type === "through_obstacle";
var zq = (t47, e2, n2) => {
const o2 = mo(t47, n2), i2 = mo(e2, n2), r2 = Math.min(o2, i2), s2 = Math.max(o2, i2);
return Array.from({ length: s2 - r2 + 1 }, (t48, e3) => Co(r2 + e3, n2));
};
var Bq = ({ obstacleId: t47, start: e2, end: n2, width: o2, layer: i2, connectedTo: r2 }) => {
const s2 = n2.x - e2.x, a2 = n2.y - e2.y, c2 = Math.hypot(s2, a2);
return c2 <= Oq ? null : { obstacleId: t47, type: "rect", layers: [i2], center: { x: (e2.x + n2.x) / 2, y: (e2.y + n2.y) / 2 }, width: c2, height: Math.max(o2, Oq), ccwRotationDegrees: 180 * Math.atan2(a2, s2) / Math.PI, connectedTo: r2 };
};
function Fq(t47) {
if (!t47)
return t47;
const e2 = ((t48) => {
if (!t48)
return [];
const e3 = [], n2 = Yo(t48);
for (const [o2, i2] of (t48.traces ?? []).entries()) {
const r2 = i2.connectsTo ?? [];
for (let s2 = 0;s2 < i2.route.length; s2++) {
const a2 = i2.route[s2];
if (Dq(a2)) {
const c2 = a2.via_diameter ?? n2.padDiameter;
e3.push({ obstacleId: `trace_obstacle_${i2.pcb_trace_id}_${o2}_${s2}_via`, type: "rect", layers: zq(a2.from_layer, a2.to_layer, t48.layerCount), center: { x: a2.x, y: a2.y }, width: Math.max(c2, Oq), height: Math.max(c2, Oq), connectedTo: r2 });
continue;
}
if (Lq(a2)) {
const n3 = Bq({ obstacleId: `trace_obstacle_${i2.pcb_trace_id}_${o2}_${s2}_through`, start: a2.start, end: a2.end, width: a2.width, layer: a2.from_layer, connectedTo: r2 });
n3 && (n3.layers = zq(a2.from_layer, a2.to_layer, t48.layerCount), e3.push(n3));
}
}
for (let t49 = 0;t49 < i2.route.length - 1; t49++) {
const n3 = i2.route[t49], s2 = i2.route[t49 + 1];
if (!kq(n3) || !kq(s2) || n3.layer !== s2.layer)
continue;
const a2 = Bq({ obstacleId: `trace_obstacle_${i2.pcb_trace_id}_${o2}_${t49}_wire`, start: n3, end: s2, width: n3.width, layer: n3.layer, connectedTo: r2 });
a2 && e3.push(a2);
}
}
return e3;
})(t47);
return e2.length === 0 ? t47 : { ...t47, obstacles: [...t47.obstacles ?? [], ...e2] };
}
function jq(t47, e2) {
const n2 = function(t48, e3) {
const n3 = go(t48.__zLayers ?? t48.zLayers ?? [], e3);
if (n3.length > 0)
return n3;
const o2 = fo(t48.layers, e3);
if (o2.length > 0)
return o2;
throw new Error(`Obstacle "${t48.obstacleId ?? "unknown"}" has no layers on this ${e3}-layer board`);
}(t47, e2);
return { ...t47, layers: n2.map((t48) => Co(t48, e2)), zLayers: n2, __zLayers: n2 };
}
function $q(t47) {
return { ...t47, obstacles: t47.obstacles.map((e2) => jq(e2, t47.layerCount)), jumpers: t47.jumpers?.map((e2) => ({ ...e2, pads: e2.pads.map((e3) => jq(e3, t47.layerCount)) })) };
}
var Yq = (t47) => {
const e2 = t47.obstacles.filter((e3) => !((t48, e4) => !((t49) => (t49.connectedTo?.length ?? 0) > 0 || (t49.offBoardConnectsTo?.length ?? 0) > 0 || t49.netIsAssignable === true)(t48) && (e4.outline && e4.outline.length >= 3 ? !Te(t48, e4.outline) : !Xe({ minX: t48.center.x - t48.width / 2, maxX: t48.center.x + t48.width / 2, minY: t48.center.y - t48.height / 2, maxY: t48.center.y + t48.height / 2 }, e4.bounds)))(e3, t47)), n2 = e2.length !== t47.obstacles.length, o2 = n2 && t47.outline && t47.outline.length >= 3 ? ((t48) => {
if (t48.width && t48.height && t48.center) {
const e4 = t48.width / 2, n4 = t48.height / 2;
return { minX: t48.center.x - e4, minY: t48.center.y - n4, maxX: t48.center.x + e4, maxY: t48.center.y + n4, width: t48.width, height: t48.height, center: { x: t48.center.x, y: t48.center.y } };
}
if (!t48.outline || t48.outline.length === 0)
throw new Error("Unable to compute board bounds. pcb_board must include width/height/center or a non-empty outline.");
let { POSITIVE_INFINITY: e3, POSITIVE_INFINITY: n3, NEGATIVE_INFINITY: o3, NEGATIVE_INFINITY: i2 } = Number;
for (const r3 of t48.outline)
e3 = Math.min(e3, r3.x), n3 = Math.min(n3, r3.y), o3 = Math.max(o3, r3.x), i2 = Math.max(i2, r3.y);
const r2 = o3 - e3, s2 = i2 - n3;
return { minX: e3, minY: n3, maxX: o3, maxY: i2, width: r2, height: s2, center: { x: e3 + r2 / 2, y: n3 + s2 / 2 } };
})({ center: { x: 0, y: 0 }, num_layers: t47.layerCount, outline: t47.outline }) : t47.bounds;
return n2 ? { ...t47, obstacles: e2, bounds: o2 } : t47;
};
function Xq(t47) {
const { minX: e2, maxX: n2, minY: o2, maxY: i2 } = t47.bounds;
for (const r2 of t47.connections)
if (!r2.isOffBoard) {
for (const [t48, s2] of r2.pointsToConnect.entries())
if (!(s2.x >= e2 && s2.x <= n2 && s2.y >= o2 && s2.y <= i2))
return `Connection "${r2.name}" point "${s2.pointId ?? t48}" at (${s2.x}, ${s2.y}) is outside routing bounds: x [${e2}, ${n2}], y [${o2}, ${i2}]`;
}
return null;
}
var Wq = class extends si {
constructor(t47, e2 = {}) {
super(), this.inputSrj = t47, this.visualizationOptions = e2, this.MAX_ITERATIONS = 1;
}
outputSrj;
_step() {
if (this.error = Xq(this.inputSrj), this.error)
return void (this.failed = true);
const t47 = $q(this.inputSrj), e2 = Fq(t47) ?? t47, n2 = Aq(Yq(e2));
this.outputSrj = $q(n2), this.solved = true;
}
getOutputSimpleRouteJson() {
if (!this.outputSrj)
throw new Error("PreprocessSimpleRouteJsonSolver has not solved yet");
return this.outputSrj;
}
getConstructorParams() {
return [this.inputSrj, this.visualizationOptions];
}
visualize() {
return this.outputSrj ? pi(Ho({ ...this.outputSrj, traces: [] }, this.visualizationOptions), KG({ srj: this.outputSrj, visualizationOptions: this.visualizationOptions })) : { lines: [], points: [], rects: [], circles: [] };
}
};
c(T(), 1);
var A0 = (t47) => t47.rootConnectionName ?? t47.connectionName;
var O0 = (t47, e2) => t47.flatMap((t48, n2) => A0(t48) === e2 ? [n2] : []);
var k0 = (t47, e2, n2, o2) => {
const i2 = (t48, e3, n3) => {
const o3 = n3.x - e3.x, i3 = n3.y - e3.y, r3 = t48.x - e3.x, s3 = t48.y - e3.y, a3 = o3 ** 2 + i3 ** 2, c3 = a3 === 0 ? 0 : Math.max(0, Math.min(1, (r3 * o3 + s3 * i3) / a3));
return Math.hypot(t48.x - (e3.x + c3 * o3), t48.y - (e3.y + c3 * i3));
}, r2 = { x: e2.x - t47.x, y: e2.y - t47.y }, s2 = { x: o2.x - n2.x, y: o2.y - n2.y }, a2 = { x: n2.x - t47.x, y: n2.y - t47.y }, c2 = (t48, e3) => t48.x * e3.y - t48.y * e3.x, l2 = c2(r2, s2), h2 = Math.hypot(r2.x, r2.y), d2 = 0.000000000001 * (h2 * Math.hypot(s2.x, s2.y) + 1);
if (Math.abs(l2) > d2) {
const t48 = c2(a2, s2) / l2, e3 = c2(a2, r2) / l2;
if (t48 >= -1e-12 && t48 <= 1 + 0.000000000001 && e3 >= -1e-12 && e3 <= 1 + 0.000000000001)
return 0;
} else if (h2 > 0.000000000001 && Math.abs(c2(a2, r2)) <= d2) {
const i3 = Math.abs(r2.x) >= Math.abs(r2.y), s3 = Math.min(i3 ? t47.x : t47.y, i3 ? e2.x : e2.y), a3 = Math.max(i3 ? t47.x : t47.y, i3 ? e2.x : e2.y), c3 = Math.min(i3 ? n2.x : n2.y, i3 ? o2.x : o2.y), l3 = Math.max(i3 ? n2.x : n2.y, i3 ? o2.x : o2.y);
if (Math.max(s3, c3) <= Math.min(a3, l3) + 0.000000000001)
return 0;
}
return Math.min(i2(t47, n2, o2), i2(e2, n2, o2), i2(n2, t47, e2), i2(o2, t47, e2));
};
var D0 = (t47, e2) => Math.hypot(e2.x - t47.x, e2.y - t47.y);
var L0 = (t47) => {
let e2 = 0;
for (let n2 = 0;n2 < t47.route.length - 1; n2++)
e2 += D0(t47.route[n2], t47.route[n2 + 1]);
return e2;
};
var z0 = (t47, e2) => e2.reduce((e3, n2) => e3 + L0(t47[n2]), 0);
var B0 = (t47, e2) => {
const { __zLayers: n2, zLayers: o2 } = t47, i2 = n2 !== undefined ? n2 : o2;
if (i2 !== undefined) {
if (!Array.isArray(i2) || i2.length === 0 || i2.some((t48) => !Number.isInteger(t48) || t48 < 0 || t48 >= e2))
throw new Error("Obstacle has invalid z-layer indexes");
return i2;
}
if (t47.layers.length === 0)
throw new Error("Obstacle has no declared layers");
return t47.layers.map((t48) => {
if (t48 === "top")
return 0;
if (t48 === "bottom")
return e2 - 1;
const n3 = /^inner(\d+)$/.exec(t48), o3 = n3 ? Number(n3[1]) : -1;
if (o3 <= 0 || o3 >= e2 - 1)
throw new Error(`Obstacle has invalid layer name "${t48}"`);
return o3;
});
};
var F0 = (t47) => {
const e2 = (t48, e3, n3, o3) => {
const i3 = n3.center.x - n3.width / 2 - o3, r3 = n3.center.x + n3.width / 2 + o3, s2 = n3.center.y - n3.height / 2 - o3, a2 = n3.center.y + n3.height / 2 + o3;
if (t48.x >= i3 && t48.x <= r3 && t48.y >= s2 && t48.y <= a2 || e3.x >= i3 && e3.x <= r3 && e3.y >= s2 && e3.y <= a2)
return true;
const c2 = [{ x: i3, y: s2 }, { x: r3, y: s2 }, { x: r3, y: a2 }, { x: i3, y: a2 }];
return c2.some((n4, o4) => k0(t48, e3, n4, c2[(o4 + 1) % c2.length]) === 0);
};
if (t47.bounds && t47.meanderPoints.some((e3) => e3.x < t47.bounds.minX || e3.x > t47.bounds.maxX || e3.y < t47.bounds.minY || e3.y > t47.bounds.maxY))
return false;
const n2 = (t48, e3, n3) => {
const o3 = n3.x - e3.x, i3 = n3.y - e3.y, r3 = o3 * o3 + i3 * i3, s2 = r3 === 0 ? 0 : Math.max(0, Math.min(1, ((t48.x - e3.x) * o3 + (t48.y - e3.y) * i3) / r3));
return Math.hypot(t48.x - (e3.x + s2 * o3), t48.y - (e3.y + s2 * i3));
}, o2 = t47.meanderPoints.some((e3) => !t47.route.route.slice(1).some((o3, i3) => {
const r3 = t47.route.route[i3];
return r3.z === e3.z && o3.z === e3.z && n2(e3, r3, o3) <= 0.000000001;
})), i2 = A0(t47.route), r2 = t47.route.traceThickness / 2 + t47.obstacleMargin;
for (let s2 = 0;s2 < t47.meanderPoints.length - 1; s2++) {
const a2 = t47.meanderPoints[s2], c2 = t47.meanderPoints[s2 + 1], l2 = t47.route.route.slice(1).some((e3, o3) => {
const i3 = t47.route.route[o3];
return a2.z === c2.z && i3.z === a2.z && e3.z === c2.z && n2(a2, i3, e3) <= 0.000000001 && n2(c2, i3, e3) <= 0.000000001;
});
if (!o2 || !l2) {
for (const n3 of t47.obstacles) {
if (!B0(n3, t47.layerCount).includes(a2.z))
continue;
const o3 = s2 === 0 || s2 === t47.meanderPoints.length - 2;
if ((!n3.connectedTo.includes(i2) || !o3) && e2(a2, c2, n3, r2))
return false;
}
for (const e3 of t47.routedRoutes) {
const o3 = A0(e3) === i2;
for (const i3 of e3.vias) {
if (i3.zLayers && !i3.zLayers.includes(a2.z))
continue;
const r3 = Math.hypot(i3.x - a2.x, i3.y - a2.y) <= 0.00000001 || Math.hypot(i3.x - c2.x, i3.y - c2.y) <= 0.00000001, s3 = t47.route.traceThickness / 2 + e3.viaDiameter / 2 + t47.obstacleMargin;
if ((!o3 || !r3) && n2(i3, a2, c2) < s3)
return false;
}
if (!o3)
for (let n3 = 0;n3 < e3.route.length - 1; n3++) {
const o4 = e3.route[n3], i3 = e3.route[n3 + 1];
if (a2.z !== o4.z || a2.z !== i3.z)
continue;
const r3 = t47.route.traceThickness / 2 + e3.traceThickness / 2 + t47.obstacleMargin;
if (k0(a2, c2, o4, i3) < r3)
return false;
}
}
}
}
return true;
};
var j0 = (t47) => {
const e2 = [];
for (const n3 of t47.routeIndexes) {
const o2 = t47.routes[n3], i2 = t47.minMeanderGap ?? Math.max(0.3, 2 * o2.traceThickness), r2 = o2.traceThickness + i2, s2 = Math.max(t47.minimumToothPitch ?? 0, 2 * r2), a2 = t47.minMeanderHeight ?? r2;
for (let i3 = 0;i3 < o2.route.length - 1; i3++) {
const r3 = o2.route[i3], c2 = o2.route[i3 + 1], l2 = D0(r3, c2);
if (l2 <= 0 || r3.z !== c2.z)
continue;
const h2 = Math.min(Math.max(0, Math.floor(l2 / s2) - 1), t47.maxToothCount);
for (let o3 = 1;o3 <= h2; o3++) {
const r4 = l2 / (o3 + 1), c3 = [r4, Math.sqrt(s2 * r4), s2].filter((t48, e3, n4) => n4.findIndex((e4) => Math.abs(e4 - t48) < 0.000000001) === e3), h3 = o3 % 2 == 0 ? ["balanced", "negative", "positive"] : ["negative", "positive"];
for (const r5 of c3)
for (const s3 of h3)
e2.push({ routeIndex: n3, segmentIndex: i3, segmentLength: l2, toothCount: o3, maximumDepth: t47.maximumDepth, minimumHeight: a2, toothPitch: r5, placement: s3, heightProfile: o3 > 1 ? "tapered" : "uniform" });
}
}
}
const n2 = { balanced: 0, negative: 1, positive: 2 };
return e2.sort((t48, e3) => t48.toothCount - e3.toothCount || n2[t48.placement] - n2[e3.placement] || e3.toothPitch - t48.toothPitch || e3.segmentLength - t48.segmentLength);
};
var $0 = (t47) => {
if (t47.centerlineDistanceCost === null)
return 0;
const e2 = t47.predictedToothDepths.flatMap((t48, e3) => t48 > 0 ? [e3] : []);
if (e2.length === 0)
return 0;
const n2 = e2.map((e3) => t47.predictedToothDepths[e3]), o2 = Math.max(...n2), i2 = n2.reduce((t48, e3) => t48 + e3, 0) / n2.length, r2 = Math.sqrt(n2.reduce((t48, e3) => t48 + (e3 - i2) ** 2, 0) / n2.length), s2 = e2[0], a2 = (e2.at(-1) - s2 + 1) * t47.toothPitch, c2 = o2 / (t47.toothPitch / 2), l2 = t47.addedLength / a2, h2 = c2 / (1 + c2) * 40, d2 = l2 / (1 + l2) * 30, u2 = t47.predictedToothDepths.map((e3, n3) => Math.sin(Math.PI * (n3 + 1) / (t47.predictedToothDepths.length + 1))), p2 = Math.max(...u2), m2 = Math.sqrt(t47.predictedToothDepths.reduce((t48, e3, n3) => t48 + (e3 - o2 * u2[n3] / p2) ** 2, 0) / t47.predictedToothDepths.length), g2 = 100 - h2 - d2 - Math.min(10, (t47.heightProfile === "tapered" ? m2 : r2) / i2 * 10) - 2 * (n2.length - 1) - 7 * Math.min(1, t47.addedLength / t47.segmentLength) - 100 * t47.centerlineDistanceCost, f2 = t47.centerlineDistanceCost > 0 ? g2 : Math.max(0, g2);
return Math.round(1e6 * f2) / 1e6;
};
var Y0 = (t47) => {
if (t47.toothDepths.length !== t47.toothCount)
throw new Error(`LengthMatchingSolver: expected ${t47.toothCount} tooth depths, received ${t47.toothDepths.length}`);
if (t47.toothDepths.some((t48) => !Number.isFinite(t48) || t48 < 0))
throw new Error("LengthMatchingSolver: every meander tooth depth must be a non-negative finite number");
const e2 = t47.route.route[t47.segmentIndex], n2 = t47.route.route[t47.segmentIndex + 1], o2 = D0(e2, n2), i2 = (n2.x - e2.x) / o2, r2 = (n2.y - e2.y) / o2, s2 = (o2 - (t47.toothCount - 0.5) * t47.toothPitch) / 2, a2 = [{ ...e2 }];
for (let n3 = 0;n3 < t47.toothCount; n3++) {
const o3 = t47.toothDepths[n3];
if (o3 === 0)
continue;
const c2 = t47.placement === "balanced" ? n3 % 2 == 0 ? -1 : 1 : t47.placement === "negative" ? -1 : 1, l2 = { x: -r2 * c2, y: i2 * c2 }, h2 = s2 + n3 * t47.toothPitch, d2 = h2 + t47.toothPitch / 2, u2 = { ...e2, x: e2.x + i2 * h2, y: e2.y + r2 * h2 };
a2.push(u2, { ...u2, x: u2.x + l2.x * o3, y: u2.y + l2.y * o3 }, { ...e2, x: e2.x + i2 * d2 + l2.x * o3, y: e2.y + r2 * d2 + l2.y * o3 }, { ...e2, x: e2.x + i2 * d2, y: e2.y + r2 * d2 });
}
return a2.push({ ...n2 }), ((t48) => {
if (t48.length < 3)
return t48;
const e3 = [{ ...t48[0] }];
for (let n3 = 1;n3 < t48.length - 1; n3++) {
const o3 = t48[n3 - 1], i3 = t48[n3], r3 = t48[n3 + 1], s3 = Math.hypot(i3.x - o3.x, i3.y - o3.y), a3 = Math.hypot(r3.x - i3.x, r3.y - i3.y);
if (s3 === 0 || a3 === 0)
throw new Error("LengthMatchingSolver: meander contains a zero-length segment");
const c2 = { x: (i3.x - o3.x) / s3, y: (i3.y - o3.y) / s3 }, l2 = { x: (r3.x - i3.x) / a3, y: (r3.y - i3.y) / a3 };
if (Math.abs(c2.x * l2.y - c2.y * l2.x) < 0.000000001) {
e3.push({ ...i3 });
continue;
}
const h2 = Math.min(s3, a3) / 2, d2 = { ...i3, x: i3.x - c2.x * h2, y: i3.y - c2.y * h2 }, u2 = { ...i3, x: i3.x + l2.x * h2, y: i3.y + l2.y * h2 }, p2 = e3.at(-1);
d2.x === p2.x && d2.y === p2.y || e3.push(d2);
for (let t49 = 1;t49 < 6; t49++) {
const n4 = t49 / 6, o4 = 1 - n4;
e3.push({ ...i3, x: o4 ** 2 * d2.x + 2 * o4 * n4 * i3.x + n4 ** 2 * u2.x, y: o4 ** 2 * d2.y + 2 * o4 * n4 * i3.y + n4 ** 2 * u2.y });
}
e3.push(u2);
}
return e3.push({ ...t48[t48.length - 1] }), e3;
})(a2);
};
var X0 = (t47) => [...t47.route.route.slice(0, t47.segmentIndex), ...Y0(t47), ...t47.route.route.slice(t47.segmentIndex + 2)];
var W0 = (t47) => {
const e2 = L0(t47.route), n2 = (() => {
const e3 = [];
for (let n3 = 0;n3 < t47.candidate.toothCount; n3++) {
const o3 = Array(t47.candidate.toothCount).fill(0);
o3[n3] = t47.candidate.maximumDepth;
const i3 = Y0({ ...t47.candidate, route: t47.route, toothDepths: o3 });
if (t47.isGeometryValid(i3)) {
e3.push(t47.candidate.maximumDepth);
continue;
}
let r3 = 0, s3 = t47.candidate.maximumDepth;
for (let e4 = 0;e4 < 32; e4++) {
const e5 = (r3 + s3) / 2, o4 = Array(t47.candidate.toothCount).fill(0);
o4[n3] = e5;
const i4 = Y0({ ...t47.candidate, route: t47.route, toothDepths: o4 });
t47.isGeometryValid(i4) ? r3 = e5 : s3 = e5;
}
e3.push(r3);
}
return e3;
})(), o2 = ((t48) => {
if (t48.heightProfile !== "tapered")
return Array(t48.toothCount).fill(1);
const e3 = Array.from({ length: t48.toothCount }, (e4, n4) => Math.sin(Math.PI * (n4 + 1) / (t48.toothCount + 1))), n3 = Math.max(...e3);
return e3.map((t49) => t49 / n3);
})(t47.candidate), i2 = t47.candidate.maximumDepth, r2 = n2.map((t48, e3) => Math.min(t48, i2 * o2[e3])), s2 = [0.25, 0.75], a2 = r2.map((t48) => t48 * s2[0]), c2 = r2.map((t48) => t48 * s2[1]), l2 = X0({ ...t47.candidate, route: t47.route, toothDepths: a2 }), h2 = X0({ ...t47.candidate, route: t47.route, toothDepths: c2 }), d2 = [L0({ ...t47.route, route: l2 }) - e2, L0({ ...t47.route, route: h2 }) - e2], u2 = X0({ ...t47.candidate, route: t47.route, toothDepths: r2 }), p2 = L0({ ...t47.route, route: u2 }) - e2, m2 = (d2[1] - d2[0]) / (s2[1] - s2[0]), g2 = d2[0] - m2 * s2[0], f2 = m2 > 0 && Number.isFinite(m2) ? (t47.targetAddedLength - g2) / m2 : 0, y2 = Math.min(t47.targetAddedLength, p2), _2 = t47.targetAddedLength > 0 && y2 > 0 ? ((e3) => {
let n3 = 0, o3 = t47.candidate.maximumDepth;
for (let i4 = 0;i4 < 32; i4++) {
const i5 = (n3 + o3) / 2, r3 = e3.maximumToothDepths.map((t48, n4) => Math.min(t48, i5 * e3.toothHeightWeights[n4])), s3 = X0({ ...t47.candidate, route: t47.route, toothDepths: r3 }), a3 = L0({ ...t47.route, route: s3 }) - e3.originalLength, c3 = Y0({ ...t47.candidate, route: t47.route, toothDepths: r3 });
t47.isGeometryValid(c3) ? a3 < e3.targetAddedLength ? n3 = i5 : o3 = i5 : o3 = i5;
}
const i3 = (n3 + o3) / 2;
return { depthLevel: i3, toothDepths: e3.maximumToothDepths.map((t48, n4) => Math.min(t48, i3 * e3.toothHeightWeights[n4])) };
})({ maximumToothDepths: n2, toothHeightWeights: o2, originalLength: e2, targetAddedLength: y2 }) : { depthLevel: f2 * i2, toothDepths: r2.map((t48) => Math.max(0, t48 * f2)) }, b2 = _2.depthLevel / i2, x2 = _2.toothDepths, v2 = X0({ ...t47.candidate, route: t47.route, toothDepths: x2 }), I2 = L0({ ...t47.route, route: v2 }) - e2, S2 = Math.abs(y2 - I2), C2 = Y0({ ...t47.candidate, route: t47.route, toothDepths: x2 });
let P2 = 0;
if (t47.getCenterlineDistanceCost && (P2 = t47.getCenterlineDistanceCost(C2)), P2 !== null && (!Number.isFinite(P2) || P2 < 0))
throw new Error("LengthMatchingSolver: meander centerline distance cost must be a non-negative finite number");
const M2 = Number.isFinite(b2) && b2 > 0 && b2 <= 1, N2 = x2.every((e3) => e3 === 0 || e3 >= t47.candidate.minimumHeight), w2 = t47.isGeometryValid(C2);
let T2, R2 = null;
P2 === null ? R2 = "no-paired-same-layer-geometry" : M2 ? S2 > t47.lengthTolerance ? R2 = "target-error" : w2 ? N2 || (R2 = "below-minimum-height") : R2 = "invalid-geometry" : R2 = "invalid-scale", T2 = R2 ? { valid: false, invalidReason: R2 } : { valid: true, invalidReason: null };
const E2 = { ...t47.candidate, connectionName: t47.connectionName, maximumToothDepths: n2, sampleScaleFactors: s2, sampleAddedLengths: d2, slope: m2, intercept: g2, predictedScaleFactor: b2, predictedToothDepths: x2, predictedRoute: v2, addedLength: I2, maximumAddedLength: p2, resultingError: S2, testedSegment: [{ ...t47.route.route[t47.candidate.segmentIndex] }, { ...t47.route.route[t47.candidate.segmentIndex + 1] }], meanderPoints: C2, centerlineDistanceCost: P2, qualityScore: 0, ...T2 };
return { ...E2, qualityScore: $0(E2) };
};
var V0 = (t47) => {
const e2 = ((t48) => {
if (t48.heightProfile !== "tapered")
return Array(t48.toothCount).fill(1);
const e3 = Array.from({ length: t48.toothCount }, (e4, n4) => Math.sin(Math.PI * (n4 + 1) / (t48.toothCount + 1))), n3 = Math.max(...e3);
return e3.map((t49) => t49 / n3);
})(t47.candidate), n2 = Math.max(...e2.map((e3) => t47.candidate.minimumHeight / e3)), o2 = t47.candidate.maximumDepth / 2 ** 30, i2 = e2.map((t48) => t48 * (n2 + o2));
if (i2.some((e3) => e3 > t47.candidate.maximumDepth))
return null;
const r2 = Y0({ ...t47.candidate, route: t47.route, toothDepths: i2 });
if (!t47.isGeometryValid(r2))
return null;
const s2 = X0({ ...t47.candidate, route: t47.route, toothDepths: i2 }), a2 = L0({ ...t47.route, route: s2 }) - L0(t47.route), c2 = W0({ ...t47, targetAddedLength: a2 });
return c2.valid ? c2 : null;
};
var H0 = (t47) => {
const e2 = (t48, e3) => {
const n3 = t48[e3.routeIndex];
if (!n3)
throw new Error(`LengthMatchingSolver: dual meander references missing route ${e3.routeIndex}`);
const o3 = [...t48];
return o3[e3.routeIndex] = { ...n3, route: e3.predictedRoute }, o3;
}, n2 = (() => {
if (t47.targetAddedLength + t47.config.lengthTolerance < t47.plan.minimumAddedLength || t47.targetAddedLength - t47.config.lengthTolerance > t47.plan.maximumAddedLength)
return null;
const e3 = t47.plan.attemptOptions.map((t48) => Math.min(...t48.map((t49) => t49.attempt.addedLength)));
let n3 = Math.max(0, t47.targetAddedLength - t47.plan.minimumAddedLength), o3 = e3.map((t48, e4) => e4);
for (;n3 > 0.000000001 && o3.length > 0; ) {
const i3 = n3 / o3.length;
let r3 = 0;
const s3 = [];
for (const n4 of o3) {
const o4 = Math.max(...t47.plan.attemptOptions[n4].map((t48) => t48.attempt.maximumAddedLength)) - e3[n4], a3 = Math.min(o4, i3);
e3[n4] += a3, r3 += a3, o4 - a3 > 0.000000001 && s3.push(n4);
}
if (r3 <= 0.000000001)
break;
n3 -= r3, o3 = s3;
}
return n3 <= t47.config.lengthTolerance ? e3 : null;
})();
if (!n2)
return null;
const o2 = t47.plan.attemptOptions.map((t48, e3) => ({ attemptOptions: t48, targetAddedLength: n2[e3] })).sort((t48, e3) => e3.attemptOptions[0].candidate.routeIndex - t48.attemptOptions[0].candidate.routeIndex || e3.attemptOptions[0].candidate.segmentIndex - t48.attemptOptions[0].candidate.segmentIndex);
let i2 = [...t47.routes];
const r2 = [];
for (const n3 of o2) {
const o3 = n3.attemptOptions[0]?.candidate;
if (!o3)
throw new Error("LengthMatchingSolver: empty dual-meander segment options");
const s3 = i2[o3.routeIndex];
if (!s3)
throw new Error(`LengthMatchingSolver: missing planned dual-meander route ${o3.routeIndex}`);
let a3 = null;
for (const e3 of n3.attemptOptions) {
if (e3.attempt.addedLength - t47.config.lengthTolerance > n3.targetAddedLength || e3.attempt.maximumAddedLength + t47.config.lengthTolerance < n3.targetAddedLength)
continue;
const o4 = W0({ candidate: e3.candidate, route: s3, connectionName: t47.connectionName, targetAddedLength: n3.targetAddedLength, lengthTolerance: t47.config.lengthTolerance, isGeometryValid: (e4) => F0({ route: s3, meanderPoints: e4, routedRoutes: t47.excludedConnectionName ? i2.filter((e5) => A0(e5) !== t47.excludedConnectionName) : i2, ...t47.config }) });
o4.valid && (!a3 || o4.qualityScore > a3.qualityScore) && (a3 = o4);
}
if (!a3)
return null;
i2 = e2(i2, a3), r2.push(a3);
}
const s2 = r2.reduce((t48, e3) => t48 + e3.addedLength, 0);
if (Math.abs(s2 - t47.targetAddedLength) > t47.config.lengthTolerance)
return null;
const a2 = r2[0];
if (!a2)
throw new Error("LengthMatchingSolver: fitted an empty dual-meander plan");
return { attempts: [a2, ...r2.slice(1)], routes: i2, addedLength: s2 };
};
var G0 = (t47) => {
if (t47.length === 0)
throw new Error("LengthMatchingSolver: cannot score an empty meander plan");
return t47.reduce((t48, e2) => t48 + e2.qualityScore, 0) / t47.length - 3 * (t47.length - 1);
};
var U0 = (t47) => {
const e2 = (t48) => [t48.candidate.toothCount, t48.candidate.placement, t48.candidate.heightProfile].join(":"), n2 = new Map;
for (const o3 of t47) {
const t48 = e2(o3), i2 = `${o3.candidate.routeIndex}:${o3.candidate.segmentIndex}`, r2 = n2.get(t48);
if (!r2) {
n2.set(t48, new Map([[i2, [o3]]]));
continue;
}
const s2 = r2.get(i2);
s2 ? s2.push(o3) : r2.set(i2, [o3]);
}
const o2 = [];
for (const t48 of n2.values()) {
const e3 = [...t48.values()].map((t49) => ({ attempts: t49, maximumAddedLength: Math.max(...t49.map((t50) => t50.attempt.maximumAddedLength)), minimumAddedLength: Math.min(...t49.map((t50) => t50.attempt.addedLength)), rankingAttempt: t49.reduce((t50, e4) => e4.attempt.qualityScore > t50.attempt.qualityScore ? e4 : t50) })).sort((t49, e4) => e4.maximumAddedLength - t49.maximumAddedLength);
for (const t49 of e3)
o2.push({ attempts: [t49.rankingAttempt], attemptOptions: [t49.attempts], minimumAddedLength: t49.minimumAddedLength, maximumAddedLength: t49.maximumAddedLength, rankingQualityScore: t49.rankingAttempt.attempt.qualityScore });
for (let t49 = 2;t49 <= e3.length; t49++) {
const n3 = e3.slice(0, t49), i2 = n3.map((t50) => t50.rankingAttempt);
o2.push({ attempts: i2, attemptOptions: n3.map((t50) => t50.attempts), minimumAddedLength: n3.reduce((t50, e4) => t50 + e4.minimumAddedLength, 0), maximumAddedLength: n3.reduce((t50, e4) => t50 + e4.maximumAddedLength, 0), rankingQualityScore: G0(i2.map((t50) => t50.attempt)) });
}
}
return o2;
};
var Z0 = class extends Error {
connectionName;
reason;
constructor(t47) {
super(t47.message), this.name = "LengthMatchingNoSolutionError", this.connectionName = t47.connectionName, this.reason = t47.reason;
}
};
var q0 = (t47) => [t47.routeIndex, t47.segmentIndex, t47.toothCount, t47.placement, t47.toothPitch, t47.heightProfile, t47.maximumDepth, t47.minimumHeight].join(":");
var J0 = (t47) => {
const e2 = new Map, n2 = [...t47.attempts].sort((t48, e3) => t48.addedLength - e3.addedLength);
let o2 = t47.targetAddedLength;
for (let t48 = 0;t48 < n2.length; t48++) {
const i2 = n2[t48], r2 = Math.min(i2.addedLength, o2 / (n2.length - t48));
e2.set(q0(i2), { routeIndex: i2.routeIndex, segmentIndex: i2.segmentIndex, targetAddedLength: r2 }), o2 -= r2;
}
return e2;
};
var Q0 = (t47, e2) => `z${B0(t47, e2).join(",")}`;
var K0 = (t47) => `z${t47}`;
var t1 = (t47) => {
if (!t47.showAttempt)
return;
if (!t47.attempt)
return void ((t48) => {
const e3 = t48.activePair?.candidates[t48.activePair.candidateIndex];
if (!e3)
return;
const n3 = t48.routes[e3.routeIndex];
if (!n3)
return;
const o3 = n3.route[e3.segmentIndex], i3 = n3.route[e3.segmentIndex + 1];
o3 && i3 && t48.graphics.lines.push({ points: [o3, i3], strokeColor: "rgba(234, 179, 8, 0.6)", strokeWidth: 2 * n3.traceThickness, strokeDash: [0.1, 0.1], layer: K0(o3.z) });
})(t47);
const e2 = t47.routes[t47.attempt.routeIndex], [n2, o2] = t47.attempt.testedSegment, i2 = t47.theme.getConnectionColor(t47.attempt.connectionName);
t47.graphics.lines.push({ points: [n2, o2], strokeColor: t47.theme.getTestedSegmentColor(i2), strokeWidth: e2.traceThickness, strokeDash: [0.15, 0.15], layer: K0(n2.z) }), t47.attempt.valid ? t47.graphics.lines.push({ points: t47.attempt.meanderPoints.map(({ x: t48, y: e3 }) => ({ x: t48, y: e3 })), strokeColor: "rgba(234, 179, 8, 0.6)", strokeWidth: 2 * e2.traceThickness, strokeDash: [0.1, 0.1], layer: K0(n2.z) }) : t47.graphics.lines.push({ points: t47.attempt.meanderPoints.map(({ x: t48, y: e3 }) => ({ x: t48, y: e3 })), strokeColor: t47.theme.getRejectedCandidateColor(i2), strokeWidth: e2.traceThickness, strokeDash: [0.1, 0.1], layer: K0(n2.z) }), t47.graphics.points.push({ x: n2.x, y: n2.y, color: i2, layer: K0(n2.z) }, { x: o2.x, y: o2.y, color: i2, layer: K0(o2.z) });
};
var e1 = (t47) => {
const e2 = { lines: [], points: [], rects: [], circles: [] }, n2 = ((t48) => {
for (const e3 of Object.values(t48))
Tt(0, e3);
return { getConnectionColor: (e3, n3) => t48[e3] ?? (n3 ? t48[n3] : undefined) ?? ((t49) => t49 ? `hsl(${300 * t49.split("").reduce((t50, e4) => t50 + e4.charCodeAt(0), 0) / t49.length % 360}, 100%, 50%)` : "rgba(0, 0, 0, 0.5)")(e3), getInnerLayerConnectionColor: (t49) => Tt(0.5, t49), getTestedSegmentColor: (t49) => Tt(0.55, t49), getRejectedCandidateColor: (t49) => Tt(0.45, t49), boardBounds: { fill: "rgba(30,41,59,0.03)", stroke: "rgba(30,41,59,0.55)" }, obstacle: { fill: "rgba(255,0,0,0.25)", stroke: "rgba(255,0,0,0.5)" }, via: { fill: "blue", stroke: "none" } };
})(t47.colorMap);
return ((t48) => {
for (const e3 of t48.routes) {
const n3 = A0(e3), o2 = t48.theme.getConnectionColor(n3, e3.connectionName);
for (let n4 = 0;n4 < e3.route.length - 1; n4++) {
const i3 = e3.route[n4], r2 = e3.route[n4 + 1];
i3.z === r2.z && t48.graphics.lines.push({ points: [i3, r2], strokeColor: i3.z === 0 ? o2 : t48.theme.getInnerLayerConnectionColor(o2), strokeWidth: e3.traceThickness, ...i3.z === 0 ? {} : { strokeDash: [0.2, 0.2] }, layer: K0(i3.z) });
}
const i2 = [...new Set(e3.route.map((t49) => t49.z))];
for (const n4 of e3.vias)
t48.graphics.circles.push({ center: n4, radius: e3.viaDiameter / 2, fill: t48.theme.via.fill, stroke: t48.theme.via.stroke, layer: `z${(n4.zLayers ?? i2).join(",")}` });
}
})({ routes: t47.routes, theme: n2, graphics: e2 }), ((t48) => {
if (t48.bounds) {
const { minX: e3, maxX: n3, minY: o2, maxY: i2 } = t48.bounds;
t48.graphics.rects.push({ center: { x: (e3 + n3) / 2, y: (o2 + i2) / 2 }, width: n3 - e3, height: i2 - o2, fill: t48.theme.boardBounds.fill, stroke: t48.theme.boardBounds.stroke, layer: `z${Array.from({ length: t48.layerCount }, (t49, e4) => e4).join(",")}` });
}
for (const e3 of t48.obstacles)
t48.graphics.rects.push({ center: e3.center, width: e3.width, height: e3.height, ccwRotationDegrees: e3.ccwRotationDegrees, fill: t48.theme.obstacle.fill, stroke: t48.theme.obstacle.stroke, layer: Q0(e3, t48.layerCount) });
})({ obstacles: t47.obstacles, bounds: t47.bounds, layerCount: t47.layerCount, theme: n2, graphics: e2 }), t1({ routes: t47.routes, attempt: t47.currentAttempt, activePair: t47.activePair, showAttempt: !t47.solved, theme: n2, graphics: e2 }), { ...e2 };
};
var n1 = class extends kt {
constructor(t47) {
super(), this.params = t47, this.MAX_ITERATIONS = 1e5, this.matchedHdRoutes = t47.hdRoutes.map((t48) => ({ ...t48, route: t48.route.map((t49) => ({ ...t49 })) })), this.pairs = t47.differentialPairs ?? [];
}
matchedHdRoutes;
pairs;
nextPairIndex = 0;
activePair = null;
currentAttempt = null;
config = null;
candidatesTried = 0;
getSolverName() {
return "LengthMatchingSolver";
}
startNextPair() {
const t47 = this.pairs[this.nextPairIndex++];
if (!t47)
return void (this.solved = true);
((t48, e3) => {
if (t48.connectionNames[0] === t48.connectionNames[1])
throw new Error("LengthMatchingSolver: a differential pair must reference two distinct connections");
if (!Number.isFinite(t48.lengthTolerance) || t48.lengthTolerance < 0)
throw new Error("LengthMatchingSolver: differential pair lengthTolerance must be a non-negative finite number");
for (const e4 of [t48.minimumCenterlineDistance, t48.maximumCenterlineDistance])
if (e4 !== undefined && (!Number.isFinite(e4) || e4 <= 0))
throw new Error("LengthMatchingSolver: differential pair centerline distances must be positive finite numbers");
if (t48.minimumCenterlineDistance !== undefined && t48.maximumCenterlineDistance !== undefined && t48.minimumCenterlineDistance > t48.maximumCenterlineDistance)
throw new Error("LengthMatchingSolver: differential pair minimumCenterlineDistance cannot exceed maximumCenterlineDistance");
const n3 = new Map(e3.map((t49) => [t49.name, t49]));
for (const e4 of t48.connectionNames) {
const t49 = n3.get(e4);
if (!t49)
throw new Error(`LengthMatchingSolver: differential pair references unknown connection "${e4}"`);
if (t49.pointsToConnect.length !== 2)
throw new Error(`LengthMatchingSolver: differential pair connection "${e4}" must have exactly two points before MST splitting`);
}
})(t47, this.params.originalConnections);
const e2 = O0(this.matchedHdRoutes, t47.connectionNames[0]), n2 = O0(this.matchedHdRoutes, t47.connectionNames[1]);
if (e2.length === 0 && n2.length === 0)
return;
if (e2.length === 0 || n2.length === 0)
throw new Error(`LengthMatchingSolver: differential pair ${t47.connectionNames.join("/")} has routed geometry for only one connection`);
const o2 = z0(this.matchedHdRoutes, e2), i2 = z0(this.matchedHdRoutes, n2), r2 = Math.abs(o2 - i2);
if (r2 <= t47.lengthTolerance)
return;
const s2 = o2 < i2, a2 = t47.connectionNames[s2 ? 0 : 1], c2 = t47.connectionNames[s2 ? 1 : 0], l2 = j0({ routes: this.matchedHdRoutes, routeIndexes: s2 ? e2 : n2, maximumDepth: this.getConfig().maximumMeanderDepth, minimumToothPitch: this.getConfig().minimumToothPitch, minMeanderGap: this.getConfig().minMeanderGap, minMeanderHeight: this.getConfig().minMeanderHeight, maxToothCount: this.getConfig().maxToothCount });
if (l2.length === 0)
throw new Z0({ message: `LengthMatchingSolver: no same-layer straight segment can tune connection "${a2}"`, connectionName: a2, reason: "no-meander-candidate" });
this.activePair = { pair: t47, longerConnectionName: c2, longerRouteIndexes: s2 ? n2 : e2, shorterConnectionName: a2, targetAddedLength: r2, remainingAddedLength: r2, candidates: l2, candidateIndex: 0, lastMatchedSegmentIndexByRoute: new Map, partialAttempts: [], fullAttempts: [], plannedAttemptTargets: null, hasMinimumHeightBlockedAttempt: false };
}
acceptAttempt(t47, e2) {
const n2 = this.matchedHdRoutes[e2.routeIndex];
this.matchedHdRoutes[e2.routeIndex] = { ...n2, route: e2.predictedRoute }, t47.remainingAddedLength -= e2.addedLength, t47.lastMatchedSegmentIndexByRoute.set(e2.routeIndex, e2.segmentIndex), t47.candidateIndex = 0, t47.partialAttempts = [], t47.fullAttempts = [], t47.plannedAttemptTargets?.delete(q0(e2)), t47.plannedAttemptTargets?.size === 0 && (t47.plannedAttemptTargets = null), t47.remainingAddedLength <= t47.pair.lengthTolerance && (this.activePair = null);
}
tryCandidate(t47) {
let e2;
for (;!e2; ) {
const n3 = t47.candidates[t47.candidateIndex++];
if (!n3)
break;
const o3 = t47.lastMatchedSegmentIndexByRoute.get(n3.routeIndex);
(o3 === undefined || n3.segmentIndex < o3) && (!t47.plannedAttemptTargets || t47.plannedAttemptTargets.has(q0(n3)) && ![...t47.plannedAttemptTargets.values()].some((t48) => t48.routeIndex === n3.routeIndex && t48.segmentIndex > n3.segmentIndex)) && (e2 = n3);
}
if (!e2) {
const e3 = t47.fullAttempts.reduce((t48, e4) => !t48 || e4.qualityScore > t48.qualityScore ? e4 : t48, null), n3 = ((t48) => {
const e4 = (t49) => [t49.toothCount, t49.placement, t49.heightProfile].join(":"), n4 = new Map;
for (const o4 of t48.attempts) {
const t49 = `${o4.routeIndex}:${o4.segmentIndex}`, i3 = e4(o4), r2 = n4.get(i3);
if (!r2) {
n4.set(i3, new Map([[t49, [o4]]]));
continue;
}
const s2 = r2.get(t49);
s2 ? s2.push(o4) : r2.set(t49, [o4]);
}
let o3 = null;
for (const e5 of n4.values()) {
const n5 = [...e5.values()].map((t49) => ({ attempts: t49, maximumCapacityAttempt: t49.reduce((t50, e6) => e6.addedLength > t50.addedLength ? e6 : t50) })).sort((t49, e6) => e6.maximumCapacityAttempt.addedLength - t49.maximumCapacityAttempt.addedLength);
let i3 = 0;
for (let e6 = 0;e6 < n5.length; e6++) {
if (i3 += n5[e6].maximumCapacityAttempt.addedLength, i3 + t48.lengthTolerance < t48.targetAddedLength)
continue;
const r2 = n5.slice(0, e6 + 1), s2 = r2.map((t49) => t49.maximumCapacityAttempt), a2 = J0({ attempts: s2, targetAddedLength: t48.targetAddedLength }), c2 = r2.map((e7) => {
const n6 = a2.get(q0(e7.maximumCapacityAttempt));
if (!n6)
throw new Error(`LengthMatchingSolver: missing capacity target for ${q0(e7.maximumCapacityAttempt)}`);
const o4 = e7.attempts.filter((e8) => e8.addedLength + t48.lengthTolerance >= n6.targetAddedLength);
if (o4.length === 0)
throw new Error(`LengthMatchingSolver: no pitch can supply planned target for route ${e7.maximumCapacityAttempt.routeIndex} segment ${e7.maximumCapacityAttempt.segmentIndex}`);
return o4.reduce((t49, e8) => e8.qualityScore > t49.qualityScore || e8.qualityScore === t49.qualityScore && e8.toothPitch > t49.toothPitch ? e8 : t49);
}), l2 = G0(c2);
if (!o3) {
o3 = { attempts: c2 };
break;
}
const h2 = G0(o3.attempts);
(c2.length < o3.attempts.length || c2.length === o3.attempts.length && l2 > h2) && (o3 = { attempts: c2 });
break;
}
}
return o3;
})({ attempts: t47.partialAttempts, targetAddedLength: t47.remainingAddedLength, lengthTolerance: t47.pair.lengthTolerance });
if (e3 && (!n3 || e3.qualityScore >= G0(n3.attempts)))
return void this.acceptAttempt(t47, e3);
if (!n3) {
if (!(t47.hasMinimumHeightBlockedAttempt && t47.plannedAttemptTargets === null && t47.lastMatchedSegmentIndexByRoute.size === 0))
throw new Z0({ message: `LengthMatchingSolver: linear regression exhausted all segment/tooth combinations for "${t47.shorterConnectionName}"; required ${t47.targetAddedLength.toFixed(4)}mm`, connectionName: t47.shorterConnectionName, reason: "meander-search-exhausted" });
return this.tryDualMeanderPlan(t47);
}
return t47.plannedAttemptTargets = J0({ attempts: n3.attempts, targetAddedLength: t47.remainingAddedLength }), t47.candidateIndex = 0, t47.partialAttempts = [], void (t47.fullAttempts = []);
}
const n2 = this.matchedHdRoutes[e2.routeIndex], o2 = this.getConfig(), i2 = t47.plannedAttemptTargets?.get(q0(e2));
if (t47.plannedAttemptTargets !== null && i2 === undefined)
throw new Error(`LengthMatchingSolver: missing planned target for ${q0(e2)}`);
this.currentAttempt = W0({ candidate: e2, route: n2, connectionName: t47.shorterConnectionName, targetAddedLength: i2 === undefined ? t47.remainingAddedLength : i2.targetAddedLength, lengthTolerance: t47.pair.lengthTolerance, isGeometryValid: (t48) => F0({ route: n2, meanderPoints: t48, routedRoutes: this.matchedHdRoutes, obstacles: o2.obstacles, bounds: o2.bounds, layerCount: o2.layerCount, obstacleMargin: o2.obstacleMargin }), getCenterlineDistanceCost: t47.pair.minimumCenterlineDistance === undefined && t47.pair.maximumCenterlineDistance === undefined ? undefined : (e3) => ((t48) => {
let e4 = 0, n3 = 0;
for (let o3 = 0;o3 < t48.meanderPoints.length - 1; o3++) {
const i3 = t48.meanderPoints[o3], r2 = t48.meanderPoints[o3 + 1], s2 = Math.hypot(r2.x - i3.x, r2.y - i3.y);
if (s2 !== 0) {
for (let e5 = 0;e5 < 4; e5++) {
const o4 = (e5 + 0.5) / 4, a2 = { x: i3.x + (r2.x - i3.x) * o4, y: i3.y + (r2.y - i3.y) * o4 }, c2 = [];
for (const e6 of t48.pairedRoutes)
for (let t49 = 0;t49 < e6.route.length - 1; t49++) {
const n4 = e6.route[t49], o5 = e6.route[t49 + 1];
i3.z === n4.z && i3.z === o5.z && c2.push(k0(a2, a2, n4, o5));
}
if (c2.length === 0)
return null;
const l2 = Math.min(...c2);
n3 += s2 * Math.max(0, (t48.minimumCenterlineDistance ?? Number.NEGATIVE_INFINITY) - l2, l2 - (t48.maximumCenterlineDistance ?? Number.POSITIVE_INFINITY)) / 4;
}
e4 += s2;
}
}
if (e4 === 0)
throw new Error("LengthMatchingSolver: cannot measure a zero-length meander centerline");
return n3 / e4;
})({ meanderPoints: e3, pairedRoutes: t47.longerRouteIndexes.map((t48) => this.matchedHdRoutes[t48]), minimumCenterlineDistance: t47.pair.minimumCenterlineDistance, maximumCenterlineDistance: t47.pair.maximumCenterlineDistance }) }), this.candidatesTried++, this.currentAttempt.invalidReason === "below-minimum-height" && (t47.hasMinimumHeightBlockedAttempt = true), this.stats = { pair: `${t47.pair.connectionNames[0]}/${t47.pair.connectionNames[1]}`, candidatesTried: this.candidatesTried, segmentIndex: e2.segmentIndex, toothCount: e2.toothCount, toothPitch: e2.toothPitch, placement: e2.placement, predictedScaleFactor: this.currentAttempt.predictedScaleFactor, predictedToothDepths: this.currentAttempt.predictedToothDepths, resultingError: this.currentAttempt.resultingError, qualityScore: this.currentAttempt.qualityScore, accepted: this.currentAttempt.valid }, this.currentAttempt.valid && (t47.plannedAttemptTargets === null ? t47.remainingAddedLength - this.currentAttempt.addedLength <= t47.pair.lengthTolerance ? t47.fullAttempts.push(this.currentAttempt) : t47.partialAttempts.push(this.currentAttempt) : this.acceptAttempt(t47, this.currentAttempt));
}
tryDualMeanderPlan(t47) {
if (t47.remainingAddedLength !== t47.targetAddedLength)
throw new Error(`LengthMatchingSolver: cannot start a dual-meander plan after partially tuning "${t47.shorterConnectionName}"`);
const e2 = this.getConfig(), n2 = j0({ routes: this.matchedHdRoutes, routeIndexes: t47.longerRouteIndexes, maximumDepth: e2.maximumMeanderDepth, minimumToothPitch: e2.minimumToothPitch, minMeanderGap: e2.minMeanderGap, minMeanderHeight: e2.minMeanderHeight, maxToothCount: e2.maxToothCount }), o2 = ((t48) => {
const e3 = (t49, e4) => t49.rankingQualityScore !== e4.rankingQualityScore ? t49.rankingQualityScore > e4.rankingQualityScore : t49.leftIndex !== e4.leftIndex ? t49.leftIndex < e4.leftIndex : t49.rightIndex < e4.rightIndex, n3 = (t49, n4) => {
t49.push(n4);
let o4 = t49.length - 1;
for (;o4 > 0; ) {
const i4 = Math.floor((o4 - 1) / 2), r4 = t49[i4];
if (e3(r4, n4))
break;
t49[o4] = r4, o4 = i4;
}
t49[o4] = n4;
}, o3 = (t49) => {
const n4 = t49[0], o4 = t49.pop();
if (!n4 || !o4 || t49.length === 0)
return n4;
let i4 = 0;
for (;; ) {
const n5 = 2 * i4 + 1, r4 = n5 + 1;
if (n5 >= t49.length)
break;
const s4 = r4 < t49.length && e3(t49[r4], t49[n5]) ? r4 : n5, a3 = t49[s4];
if (e3(o4, a3))
break;
t49[i4] = a3, i4 = s4;
}
return t49[i4] = o4, n4;
}, i3 = function* (t49) {
const e4 = [...t49.leftOptions].sort((e5, n4) => t49.getLeftQualityScore(n4) - t49.getLeftQualityScore(e5)), i4 = [...t49.rightOptions].sort((e5, n4) => t49.getRightQualityScore(n4) - t49.getRightQualityScore(e5)), r4 = [];
for (let o4 = 0;o4 < e4.length; o4++) {
const s4 = i4[0];
if (!s4)
break;
n3(r4, { leftIndex: o4, rightIndex: 0, rankingQualityScore: (t49.getLeftQualityScore(e4[o4]) + t49.getRightQualityScore(s4)) / 2 });
}
for (;r4.length > 0; ) {
const s4 = o3(r4);
yield [e4[s4.leftIndex], i4[s4.rightIndex]];
const a3 = s4.rightIndex + 1, c3 = i4[a3];
c3 && n3(r4, { leftIndex: s4.leftIndex, rightIndex: a3, rankingQualityScore: (t49.getLeftQualityScore(e4[s4.leftIndex]) + t49.getRightQualityScore(c3)) / 2 });
}
}, r3 = (t49, e4) => {
const n4 = t49[e4.routeIndex];
if (!n4)
throw new Error(`LengthMatchingSolver: dual meander references missing route ${e4.routeIndex}`);
const o4 = [...t49];
return o4[e4.routeIndex] = { ...n4, route: e4.predictedRoute }, o4;
}, s3 = (t49) => {
const e4 = t49.routes[t49.attempt.routeIndex];
if (!e4)
throw new Error(`LengthMatchingSolver: cannot validate missing dual-meander route ${t49.attempt.routeIndex}`);
return F0({ route: e4, meanderPoints: t49.attempt.meanderPoints, routedRoutes: t49.routes, ...t49.config });
}, a2 = (t49) => {
const e4 = t49.routes.filter((e5) => A0(e5) !== t49.counterpartConnectionName), n4 = [];
for (const o4 of t49.candidates) {
const i4 = t49.routes[o4.routeIndex];
if (!i4)
throw new Error(`LengthMatchingSolver: dual-meander candidate references missing route ${o4.routeIndex}`);
const r4 = V0({ candidate: o4, route: i4, connectionName: t49.connectionName, lengthTolerance: t49.config.lengthTolerance, isGeometryValid: (n5) => F0({ route: i4, meanderPoints: n5, routedRoutes: e4, ...t49.config }) });
r4 && n4.push({ candidate: o4, attempt: r4 });
}
return n4;
}, c2 = { obstacles: t48.obstacles, bounds: t48.bounds, layerCount: t48.layerCount, obstacleMargin: t48.obstacleMargin }, l2 = a2({ candidates: t48.shorterCandidates, routes: t48.routes, connectionName: t48.shorterConnectionName, counterpartConnectionName: t48.longerConnectionName, config: { ...c2, lengthTolerance: t48.lengthTolerance } });
if (l2.length === 0)
return null;
const h2 = a2({ candidates: t48.longerCandidates, routes: t48.routes, connectionName: t48.longerConnectionName, counterpartConnectionName: t48.shorterConnectionName, config: { ...c2, lengthTolerance: t48.lengthTolerance } }), d2 = i3({ leftOptions: h2, rightOptions: l2, getLeftQualityScore: (t49) => t49.attempt.qualityScore, getRightQualityScore: (t49) => t49.attempt.qualityScore });
for (const [e4, n4] of d2) {
const o4 = Math.max(e4.attempt.addedLength, n4.attempt.addedLength - t48.originalLengthDifference), i4 = o4 + t48.originalLengthDifference;
if (o4 - t48.lengthTolerance > e4.attempt.maximumAddedLength || i4 - t48.lengthTolerance > n4.attempt.maximumAddedLength)
continue;
const a3 = t48.routes[e4.candidate.routeIndex];
if (!a3)
throw new Error(`LengthMatchingSolver: missing longer route ${e4.candidate.routeIndex}`);
const l3 = t48.routes[n4.candidate.routeIndex];
if (!l3)
throw new Error(`LengthMatchingSolver: missing shorter route ${n4.candidate.routeIndex}`);
const h3 = t48.routes.filter((e5) => A0(e5) !== t48.shorterConnectionName), d3 = W0({ candidate: e4.candidate, route: a3, connectionName: t48.longerConnectionName, targetAddedLength: o4, lengthTolerance: t48.lengthTolerance, isGeometryValid: (t49) => F0({ route: a3, meanderPoints: t49, routedRoutes: h3, ...c2 }) });
if (!d3.valid || Math.abs(d3.addedLength - o4) > t48.lengthTolerance)
continue;
const u3 = r3(t48.routes, d3), p2 = d3.addedLength + t48.originalLengthDifference, m2 = W0({ candidate: n4.candidate, route: l3, connectionName: t48.shorterConnectionName, targetAddedLength: p2, lengthTolerance: t48.lengthTolerance, isGeometryValid: (t49) => F0({ route: l3, meanderPoints: t49, routedRoutes: u3, ...c2 }) });
if (!m2.valid)
continue;
const g2 = r3(u3, m2), f2 = O0(g2, t48.longerConnectionName), y2 = O0(g2, t48.shorterConnectionName);
if (!(Math.abs(z0(g2, y2) - z0(g2, f2)) > t48.lengthTolerance) && s3({ attempt: d3, routes: g2, config: c2 }) && s3({ attempt: m2, routes: g2, config: c2 }))
return { longerAttempts: [d3], shorterAttempts: [m2] };
}
const u2 = i3({ leftOptions: U0(h2), rightOptions: U0(l2), getLeftQualityScore: (t49) => t49.rankingQualityScore, getRightQualityScore: (t49) => t49.rankingQualityScore });
for (const [e4, n4] of u2) {
if (e4.attempts.length === 1 && n4.attempts.length === 1)
continue;
const o4 = Math.max(e4.minimumAddedLength, n4.minimumAddedLength - t48.originalLengthDifference), i4 = o4 + t48.originalLengthDifference;
if (o4 - t48.lengthTolerance > e4.maximumAddedLength || i4 - t48.lengthTolerance > n4.maximumAddedLength)
continue;
const r4 = H0({ plan: e4, targetAddedLength: o4, routes: t48.routes, connectionName: t48.longerConnectionName, excludedConnectionName: t48.shorterConnectionName, config: { ...c2, lengthTolerance: t48.lengthTolerance } });
if (!r4)
continue;
const a3 = H0({ plan: n4, targetAddedLength: r4.addedLength + t48.originalLengthDifference, routes: r4.routes, connectionName: t48.shorterConnectionName, config: { ...c2, lengthTolerance: t48.lengthTolerance } });
if (!a3)
continue;
const l3 = O0(a3.routes, t48.longerConnectionName), h3 = O0(a3.routes, t48.shorterConnectionName), d3 = Math.abs(z0(a3.routes, h3) - z0(a3.routes, l3)), u3 = [...r4.attempts, ...a3.attempts];
if (!(d3 > t48.lengthTolerance || u3.some((t49) => !s3({ attempt: t49, routes: a3.routes, config: c2 }))))
return { longerAttempts: r4.attempts, shorterAttempts: a3.attempts };
}
return null;
})({ routes: this.matchedHdRoutes, longerConnectionName: t47.longerConnectionName, shorterConnectionName: t47.shorterConnectionName, originalLengthDifference: t47.targetAddedLength, lengthTolerance: t47.pair.lengthTolerance, longerCandidates: n2, shorterCandidates: t47.candidates, obstacles: e2.obstacles, bounds: e2.bounds, layerCount: e2.layerCount, obstacleMargin: e2.obstacleMargin });
if (!o2)
throw new Z0({ message: `LengthMatchingSolver: linear regression exhausted all segment/tooth combinations for "${t47.shorterConnectionName}"; required ${t47.targetAddedLength.toFixed(4)}mm`, connectionName: t47.shorterConnectionName, reason: "meander-search-exhausted" });
const i2 = [...this.matchedHdRoutes];
for (const t48 of [...o2.longerAttempts, ...o2.shorterAttempts]) {
const e3 = this.matchedHdRoutes[t48.routeIndex];
if (!e3)
throw new Error(`LengthMatchingSolver: cannot commit dual meander to missing route ${t48.routeIndex}`);
i2[t48.routeIndex] = { ...e3, route: t48.predictedRoute };
}
this.matchedHdRoutes = i2, this.currentAttempt = o2.shorterAttempts[0];
const r2 = o2.longerAttempts.reduce((t48, e3) => t48 + e3.addedLength, 0), s2 = o2.shorterAttempts.reduce((t48, e3) => t48 + e3.addedLength, 0);
this.stats = { pair: `${t47.pair.connectionNames[0]}/${t47.pair.connectionNames[1]}`, mode: "dual-meander", longerAddedLength: r2, shorterAddedLength: s2, resultingError: Math.abs(s2 - r2 - t47.targetAddedLength) }, this.activePair = null;
}
getConfig() {
return this.config || (this.config = ((t47) => {
const e2 = t47.maximumMeanderDepth ?? 5, n2 = t47.maxToothCount ?? 12;
if (!Number.isFinite(e2) || e2 <= 0)
throw new Error("LengthMatchingSolver: maximumMeanderDepth must be a positive finite number");
if (t47.minimumToothPitch !== undefined && (!Number.isFinite(t47.minimumToothPitch) || t47.minimumToothPitch <= 0))
throw new Error("LengthMatchingSolver: minimumToothPitch must be a positive finite number");
if (t47.minMeanderGap !== undefined && (!Number.isFinite(t47.minMeanderGap) || t47.minMeanderGap <= 0))
throw new Error("LengthMatchingSolver: minMeanderGap must be a positive finite number");
if (t47.minMeanderHeight !== undefined && (!Number.isFinite(t47.minMeanderHeight) || t47.minMeanderHeight <= 0))
throw new Error("LengthMatchingSolver: minMeanderHeight must be a positive finite number");
if (t47.minMeanderHeight !== undefined && t47.minMeanderHeight > e2)
throw new Error("LengthMatchingSolver: minMeanderHeight cannot exceed maximumMeanderDepth");
if (!Number.isFinite(n2) || !Number.isInteger(n2) || n2 <= 0)
throw new Error("LengthMatchingSolver: maxToothCount must be a positive finite integer");
return { maximumMeanderDepth: e2, minimumToothPitch: t47.minimumToothPitch, minMeanderGap: t47.minMeanderGap, minMeanderHeight: t47.minMeanderHeight, maxToothCount: n2, obstacles: t47.obstacles ?? [], bounds: t47.bounds, obstacleMargin: t47.obstacleMargin ?? 0.15, layerCount: t47.layerCount ?? 2, colorMap: t47.colorMap ?? {} };
})(this.params)), this.config;
}
_step() {
this.getConfig(), this.activePair ? this.tryCandidate(this.activePair) : this.startNextPair();
}
getConstructorParams() {
return [this.params];
}
getOutput() {
if (!this.solved)
throw new Error("LengthMatchingSolver: getOutput() called before the solver completed");
return { matchedHdRoutes: this.matchedHdRoutes };
}
getBestEffortOutput() {
const t47 = structuredClone(this.matchedHdRoutes), e2 = this.activePair?.fullAttempts ?? [];
let n2 = null;
for (const t48 of e2)
(!n2 || t48.qualityScore > n2.qualityScore) && (n2 = t48);
if (!n2)
for (const t48 of this.activePair?.partialAttempts ?? [])
(!n2 || t48.addedLength > n2.addedLength || t48.addedLength === n2.addedLength && t48.qualityScore > n2.qualityScore) && (n2 = t48);
if (n2) {
const e3 = t47[n2.routeIndex];
e3 && (t47[n2.routeIndex] = { ...e3, route: structuredClone(n2.predictedRoute) });
}
return { matchedHdRoutes: t47 };
}
computeProgress() {
if (this.solved)
return 1;
if (this.pairs.length === 0)
return this.config ? 1 : 0;
const t47 = Math.max(0, this.nextPairIndex - 1), e2 = this.activePair ? this.activePair.candidateIndex / this.activePair.candidates.length : 0;
return Math.min(0.99, (t47 + e2) / this.pairs.length);
}
visualize() {
const t47 = this.getConfig();
return e1({ routes: this.matchedHdRoutes, obstacles: t47.obstacles, bounds: t47.bounds, layerCount: t47.layerCount, colorMap: t47.colorMap, activePair: this.activePair, currentAttempt: this.currentAttempt, solved: this.solved });
}
};
var o1 = (t47, e2) => {
if (t47 === "top")
return 0;
if (t47 === "bottom")
return e2 - 1;
const n2 = /^inner(\d+)$/.exec(t47);
if (!n2)
return -1;
const o2 = Number(n2[1]);
return o2 > 0 && o2 < e2 - 1 ? o2 : -1;
};
var i1 = (t47, e2) => t47 === 0 ? "top" : t47 === e2 - 1 ? "bottom" : `inner${t47}`;
var r1 = (t47, e2, n2) => {
const o2 = o1(t47, n2), i2 = o1(e2, n2);
if (o2 < 0 || i2 < 0)
return [];
const r2 = Math.min(o2, i2), s2 = Math.max(o2, i2);
return Array.from({ length: s2 - r2 + 1 }, (t48, e3) => i1(r2 + e3, n2));
};
var s1 = 0.00000001;
var a1 = (t47, e2) => {
if (t47.route.length === 0)
throw new Error(`trace "${t47.connection_name}" has an empty route`);
if (t47.route.some((t48) => t48.route_type !== "wire" && t48.route_type !== "via"))
throw new Error(`trace "${t47.connection_name}" contains unsupported jumper or through-obstacle geometry`);
const n2 = t47.route.findIndex((t48) => t48.route_type === "wire"), o2 = t47.route[n2], i2 = t47.route.findLast((t48) => t48.route_type === "wire");
if (o2?.route_type !== "wire" || !i2)
throw new Error(`trace "${t47.connection_name}" must contain a wire point`);
const r2 = [], s2 = [], a2 = [], c2 = [];
let l2 = null, h2 = o2.width;
if (n2 > 0) {
let e3 = o2.layer;
for (let o3 = n2 - 1;o3 >= 0; o3--) {
const n3 = t47.route[o3];
if (n3?.route_type !== "via")
throw new Error(`trace "${t47.connection_name}" has unsupported geometry before its first wire`);
if (e3 === n3.to_layer)
e3 = n3.from_layer;
else {
if (e3 !== n3.from_layer)
throw new Error(`trace "${t47.connection_name}" has discontinuous leading vias`);
e3 = n3.to_layer;
}
}
const i3 = t47.route[0];
if (i3.route_type !== "via")
throw new Error(`trace "${t47.connection_name}" has an invalid leading entry`);
l2 = { x: i3.x, y: i3.y, layer: e3, width: o2.width }, r2.push(l2);
}
for (const n3 of t47.route) {
if (n3.route_type === "wire") {
if (!Number.isFinite(n3.x) || !Number.isFinite(n3.y) || !Number.isFinite(n3.width) || n3.width <= 0 || o1(n3.layer, e2) < 0)
throw new Error(`trace "${t47.connection_name}" has an invalid wire point`);
h2 = Math.max(h2, n3.width);
const o4 = { x: n3.x, y: n3.y, layer: n3.layer, width: n3.width };
if (l2) {
if (l2.layer !== o4.layer)
throw new Error(`trace "${t47.connection_name}" changes layers without a via`);
Math.hypot(l2.x - o4.x, l2.y - o4.y) > s1 && s2.push({ start: l2, end: o4, layer: o4.layer, width: Math.max(l2.width, o4.width), connectionName: t47.connection_name, terminal: null });
}
r2.push(o4), l2 = o4;
continue;
}
if (n3.route_type !== "via")
throw new Error(`trace "${t47.connection_name}" contains unsupported route geometry`);
if (!l2)
throw new Error(`trace "${t47.connection_name}" has a leading via`);
const o3 = o1(n3.from_layer, e2), i3 = o1(n3.to_layer, e2), d3 = n3.via_diameter ?? l2.width;
if (!Number.isFinite(n3.x) || !Number.isFinite(n3.y) || o3 < 0 || i3 < 0 || o3 === i3 || n3.via_diameter !== undefined && (!Number.isFinite(n3.via_diameter) || n3.via_diameter <= 0) || n3.via_hole_diameter !== undefined && (!Number.isFinite(n3.via_hole_diameter) || n3.via_hole_diameter <= 0 || n3.via_hole_diameter >= d3))
throw new Error(`trace "${t47.connection_name}" has an invalid via`);
const u2 = l2.layer === n3.from_layer ? n3.from_layer : l2.layer === n3.to_layer ? n3.to_layer : null;
if (!u2)
throw new Error(`trace "${t47.connection_name}" has a discontinuous via transition`);
Math.hypot(l2.x - n3.x, l2.y - n3.y) > s1 && s2.push({ start: l2, end: n3, layer: l2.layer, width: l2.width, connectionName: t47.connection_name, terminal: null });
const p2 = u2 === n3.from_layer ? n3.to_layer : n3.from_layer;
c2.push({ ...n3, from_layer: u2, to_layer: p2 }), a2.push({ x: n3.x, y: n3.y, layers: r1(u2, p2, e2), diameter: d3, connectionName: t47.connection_name, terminal: r2.length === 1 ? "start" : null }), l2 = { x: n3.x, y: n3.y, layer: p2, width: l2.width }, r2.push(l2);
}
if (r2.length < 2 || s2.length === 0)
throw new Error(`trace "${t47.connection_name}" does not contain a routable path`);
s2[0].terminal = s2.length === 1 ? "both" : "start", s2[s2.length - 1].terminal = s2.length === 1 ? "both" : "end";
const d2 = a2.at(-1);
return d2 && Math.hypot(d2.x - i2.x, d2.y - i2.y) <= s1 && (d2.terminal = "end"), { source: t47, points: r2, segments: s2, vias: a2, transitions: c2, width: h2, viaDiameter: t47.__postProcessingViaDiameter ?? h2, ...o2.start_pcb_port_id ? { startPortId: o2.start_pcb_port_id } : {}, ...i2.end_pcb_port_id ? { endPortId: i2.end_pcb_port_id } : {} };
};
var c1 = (t47, e2) => {
const n2 = [], o2 = [], i2 = t47.route.find((t48) => t48.route_type === "wire"), r2 = i2?.route_type === "wire" ? i2.width : null, s2 = { "0603": 0.95, 1206: 1.8, "1206x4_pair": 1.8 };
let a2 = null;
for (let i3 = 0;i3 < t47.route.length; i3++) {
const c2 = t47.route[i3];
if (c2.route_type === "wire") {
if (!Number.isFinite(c2.x) || !Number.isFinite(c2.y) || !Number.isFinite(c2.width) || c2.width <= 0 || o1(c2.layer, e2) < 0)
throw new Error(`PostProcessingSolver: immutable trace "${t47.connection_name}" has an invalid wire`);
if (a2 && a2.layer !== c2.layer)
throw new Error(`PostProcessingSolver: immutable trace "${t47.connection_name}" changes layer without a transition`);
a2 && n2.push({ start: a2, end: c2, layer: c2.layer, width: Math.max(a2.width, c2.width), connectionName: t47.connection_name, terminal: null }), a2 = c2;
continue;
}
if (c2.route_type === "via") {
const s3 = r1(c2.from_layer, c2.to_layer, e2), l3 = a2, h3 = c2.via_diameter ?? l3?.width ?? r2;
if (!Number.isFinite(c2.x) || !Number.isFinite(c2.y) || s3.length < 2 || h3 === null || !Number.isFinite(h3) || h3 <= 0 || c2.via_hole_diameter !== undefined && (!Number.isFinite(c2.via_hole_diameter) || c2.via_hole_diameter <= 0 || h3 !== null && c2.via_hole_diameter >= h3))
throw new Error(`PostProcessingSolver: immutable trace "${t47.connection_name}" has an invalid via`);
l3 && Math.hypot(l3.x - c2.x, l3.y - c2.y) > 0.00000001 && n2.push({ start: l3, end: c2, layer: l3.layer, width: l3.width, connectionName: t47.connection_name, terminal: null }), o2.push({ x: c2.x, y: c2.y, layers: s3, diameter: h3, connectionName: t47.connection_name, terminal: i3 === 0 ? "start" : i3 === t47.route.length - 1 ? "end" : null });
const d3 = t47.route.slice(i3 + 1).find((t48) => t48.route_type === "wire"), u2 = l3?.layer === c2.from_layer ? c2.to_layer : l3?.layer === c2.to_layer ? c2.from_layer : d3?.route_type !== "wire" || d3.layer !== c2.from_layer && d3.layer !== c2.to_layer ? null : d3.layer;
if (!u2)
throw new Error(`PostProcessingSolver: immutable trace "${t47.connection_name}" has a discontinuous via`);
a2 = { x: c2.x, y: c2.y, layer: u2, width: l3?.width ?? r2 ?? h3 };
continue;
}
if (c2.route_type === "jumper") {
const o3 = s2[c2.footprint];
if (!Number.isFinite(c2.start.x) || !Number.isFinite(c2.start.y) || !Number.isFinite(c2.end.x) || !Number.isFinite(c2.end.y) || o1(c2.layer, e2) < 0)
throw new Error(`PostProcessingSolver: immutable trace "${t47.connection_name}" has an invalid jumper`);
if (a2 && (a2.layer !== c2.layer || Math.hypot(a2.x - c2.start.x, a2.y - c2.start.y) > 0.00000001))
throw new Error(`PostProcessingSolver: immutable trace "${t47.connection_name}" has a discontinuous jumper`);
n2.push({ start: c2.start, end: c2.end, layer: c2.layer, width: o3, connectionName: t47.connection_name, terminal: null }), a2 = { ...c2.end, layer: c2.layer, width: o3 };
continue;
}
const l2 = r1(c2.from_layer, c2.to_layer, e2);
if (!Number.isFinite(c2.start.x) || !Number.isFinite(c2.start.y) || !Number.isFinite(c2.end.x) || !Number.isFinite(c2.end.y) || !Number.isFinite(c2.width) || c2.width <= 0 || l2.length < 2)
throw new Error(`PostProcessingSolver: immutable trace "${t47.connection_name}" has invalid through-obstacle copper`);
if (a2 && (a2.layer !== c2.from_layer && a2.layer !== c2.to_layer || Math.hypot(a2.x - c2.start.x, a2.y - c2.start.y) > 0.00000001))
throw new Error(`PostProcessingSolver: immutable trace "${t47.connection_name}" has discontinuous through-obstacle copper`);
for (const e3 of l2)
n2.push({ start: c2.start, end: c2.end, layer: e3, width: c2.width, connectionName: t47.connection_name, terminal: null });
const h2 = a2, d2 = h2?.layer === c2.to_layer ? c2.from_layer : c2.to_layer;
a2 = { ...c2.end, layer: d2, width: c2.width };
}
return { segments: n2, vias: o2 };
};
var l1 = (t47, e2) => {
const n2 = c1(t47, e2);
return [...n2.segments.map((n3, o2) => ({ connectionName: `${t47.connection_name}#immutable-segment-${o2}`, rootConnectionName: t47.connection_name, traceThickness: n3.width, viaDiameter: n3.width, route: [{ x: n3.start.x, y: n3.start.y, z: o1(n3.layer, e2), traceThickness: n3.width }, { x: n3.end.x, y: n3.end.y, z: o1(n3.layer, e2), traceThickness: n3.width }], vias: [] })), ...n2.vias.map((n3, o2) => ({ connectionName: `${t47.connection_name}#immutable-via-${o2}`, rootConnectionName: t47.connection_name, traceThickness: n3.diameter, viaDiameter: n3.diameter, route: [], vias: [{ x: n3.x, y: n3.y, zLayers: n3.layers.map((t48) => o1(t48, e2)) }] }))];
};
var h1 = (t47) => t47.segments.reduce((t48, e2) => t48 + Math.hypot(e2.end.x - e2.start.x, e2.end.y - e2.start.y), 0);
var d1 = (t47) => {
const { simpleRouteJson: e2 } = t47.params, n2 = ((t48) => {
const e3 = new Set(t48.reroutedPairs.map((t49) => t49.connectionNames.join("\x00")));
return t48.declaredPairs.filter((n3) => {
const o3 = n3.connectionNames.map((e4) => t48.traces.filter((t49) => t49.connection_name === e4));
if (o3.some((t49) => t49.length !== 1))
return false;
if (e3.has(n3.connectionNames.join("\x00")))
return true;
const i3 = o3.map((t49) => t49[0]);
if (i3.some((t49) => t49.route.length < 2 || t49.route[0]?.route_type !== "wire" || !t49.route.every((t50) => t50.route_type === "wire" || t50.route_type === "via")))
return false;
const r3 = i3.map((e4) => h1(a1(e4, t48.layerCount)));
return Math.abs(r3[0] - r3[1]) > n3.lengthTolerance + 0.0000001;
}).map((t49) => structuredClone(t49));
})({ traces: t47.result.traces, declaredPairs: e2.differentialPairs, reroutedPairs: t47.result.reroutedPairs, layerCount: e2.layerCount }), o2 = new Set(n2.flatMap((t48) => t48.connectionNames)), i2 = [], r2 = [], s2 = [], a2 = new Set;
for (let n3 = 0;n3 < t47.result.traces.length; n3++) {
const c3 = t47.result.traces[n3];
if (!o2.has(c3.connection_name))
continue;
const l2 = c3.route.every((t48) => t48.route_type === "wire" || t48.route_type === "via"), h2 = c3.route[0]?.route_type === "wire";
if (!l2 || !h2)
throw new Error(`PostProcessingSolver: rerouted connection "${c3.connection_name}" cannot be bound to LengthMatchingSolver`);
const d2 = a1(c3, e2.layerCount), u2 = c3.route[0];
if (u2.route_type !== "wire")
throw new Error(`PostProcessingSolver: trace "${c3.connection_name}" lost its first wire during binding`);
const p2 = [{ x: u2.x, y: u2.y, z: o1(u2.layer, e2.layerCount), traceThickness: u2.width }], m2 = [], g2 = [];
let { layer: f2, width: y2 } = u2;
for (const t48 of c3.route.slice(1)) {
if (t48.route_type === "wire") {
if (t48.layer !== f2)
throw new Error(`PostProcessingSolver: trace "${c3.connection_name}" changes layers without a via while binding`);
p2.push({ x: t48.x, y: t48.y, z: o1(t48.layer, e2.layerCount), traceThickness: t48.width }), y2 = t48.width;
continue;
}
if (t48.route_type !== "via")
throw new Error(`PostProcessingSolver: trace "${c3.connection_name}" contains unsupported bound geometry`);
const n4 = f2 === t48.from_layer ? t48.to_layer : f2 === t48.to_layer ? t48.from_layer : null;
if (!n4)
throw new Error(`PostProcessingSolver: trace "${c3.connection_name}" has a discontinuous bound via`);
const o3 = p2.at(-1);
Math.hypot(o3.x - t48.x, o3.y - t48.y) > 0.00000001 && p2.push({ x: t48.x, y: t48.y, z: o1(f2, e2.layerCount), traceThickness: y2 }), p2.push({ x: t48.x, y: t48.y, z: o1(n4, e2.layerCount), traceThickness: y2 }), m2.push({ x: t48.x, y: t48.y, zLayers: r1(t48.from_layer, t48.to_layer, e2.layerCount).map((t49) => o1(t49, e2.layerCount)) }), g2.push({ ...t48 }), f2 = n4;
}
if (p2.length < 2)
throw new Error(`PostProcessingSolver: trace "${c3.connection_name}" has no bound copper segments`);
const _2 = Math.max(...p2.map((t48) => t48.traceThickness ?? d2.width)), b2 = d2.viaDiameter, x2 = i2.length;
i2.push({ connectionName: c3.connection_name, traceThickness: _2, viaDiameter: b2, route: p2, vias: m2 });
const v2 = p2[0], I2 = p2.at(-1);
r2.push({ name: c3.connection_name, pointsToConnect: [{ x: v2.x, y: v2.y, layer: u2.layer, ...d2.startPortId ? { pcb_port_id: d2.startPortId } : {} }, { x: I2.x, y: I2.y, layer: d2.points.at(-1).layer, ...d2.endPortId ? { pcb_port_id: d2.endPortId } : {} }] }), s2.push({ traceIndex: n3, matchedRouteIndex: x2, viaTemplates: g2, startEndpoint: { ...v2 }, endEndpoint: { ...I2 }, ...d2.startPortId ? { startPortId: d2.startPortId } : {}, ...d2.endPortId ? { endPortId: d2.endPortId } : {} }), a2.add(c3.connection_name);
}
for (const t48 of o2)
if (!a2.has(t48))
throw new Error(`PostProcessingSolver: missing LengthMatchingSolver binding for rerouted connection "${t48}"`);
for (const n3 of t47.result.traces)
o2.has(n3.connection_name) || i2.push(...l1(n3, e2.layerCount));
const c2 = e2.minTraceToPadEdgeClearance ?? Math.max(0, ...i2.filter((t48) => t48.route.length >= 2).map((t48) => t48.traceThickness));
return { solverParams: { hdRoutes: i2, originalConnections: r2, differentialPairs: n2, obstacles: e2.obstacles, bounds: e2.bounds, layerCount: e2.layerCount, obstacleMargin: c2 }, traceBindings: s2, baseTraces: structuredClone(t47.result.traces) };
};
var u1 = (t47) => {
const e2 = new Map;
for (const n3 of t47.differentialPairs)
for (const o3 of n3.connectionNames) {
const n4 = t47.hdRoutes.map((t48, e3) => ({ route: t48, hdRouteIndex: e3 })).filter(({ route: t48 }) => t48.connectionName === o3);
n4.length === 1 && e2.set(n4[0].hdRouteIndex, o3);
}
const n2 = t47.hdRoutes.map((e3, n3) => {
const o3 = [], i2 = new Map;
for (let t48 = 0;t48 < (e3.jumpers?.length ?? 0); t48++) {
const n4 = e3.jumpers[t48], o4 = e3.route.map((t49, e4) => ({ point: t49, index: e4 })).filter(({ point: t49 }) => Math.hypot(t49.x - n4.start.x, t49.y - n4.start.y) <= 0.00000001).map(({ index: t49 }) => t49), r2 = e3.route.map((t49, e4) => ({ point: t49, index: e4 })).filter(({ point: t49 }) => Math.hypot(t49.x - n4.end.x, t49.y - n4.end.y) <= 0.00000001).map(({ index: t49 }) => t49), s2 = [...o4.flatMap((t49) => r2.filter((e4) => e4 > t49).map((e4) => ({ startIndex: t49, endIndex: e4 }))), ...r2.flatMap((t49) => o4.filter((e4) => e4 > t49).map((e4) => ({ startIndex: t49, endIndex: e4 })))];
if (s2.length !== 1)
throw new Error(`PostProcessingSolver: immutable HD route "${e3.connectionName}" has an ambiguous jumper traversal`);
const a2 = s2[0];
if (i2.has(a2.startIndex) || [...i2.values()].some(({ endIndex: t49 }) => a2.startIndex < t49 || a2.endIndex <= t49))
throw new Error(`PostProcessingSolver: immutable HD route "${e3.connectionName}" has overlapping or unordered jumpers`);
i2.set(a2.startIndex, { endIndex: a2.endIndex, jumperIndex: t48 });
}
if (e3.route.length > 0) {
const n4 = e3.route[0];
o3.push({ route_type: "wire", x: n4.x, y: n4.y, width: n4.traceThickness ?? e3.traceThickness, layer: i1(n4.z, t47.layerCount) });
for (let n5 = 0;n5 < e3.route.length - 1; n5++) {
const r3 = e3.route[n5], s3 = i2.get(n5);
if (s3) {
const i3 = e3.route[s3.endIndex], a4 = e3.jumpers[s3.jumperIndex];
if (r3.z !== i3.z)
throw new Error(`PostProcessingSolver: immutable HD route "${e3.connectionName}" changes layers through a jumper`);
o3.push({ route_type: "jumper", start: { x: r3.x, y: r3.y }, end: { x: i3.x, y: i3.y }, footprint: a4.footprint, layer: i1(r3.z, t47.layerCount) }), o3.push({ route_type: "wire", x: i3.x, y: i3.y, width: i3.traceThickness ?? e3.traceThickness, layer: i1(i3.z, t47.layerCount) }), n5 = s3.endIndex - 1;
continue;
}
const a3 = e3.route[n5 + 1], c2 = i1(r3.z, t47.layerCount), l2 = i1(a3.z, t47.layerCount);
r3.z !== a3.z && (r3.toNextSegmentType === "through_obstacle" ? o3.push({ route_type: "through_obstacle", start: { x: r3.x, y: r3.y }, end: { x: a3.x, y: a3.y }, from_layer: c2, to_layer: l2, width: r3.traceThickness ?? e3.traceThickness }) : o3.push({ route_type: "via", x: a3.x, y: a3.y, from_layer: c2, to_layer: l2, via_diameter: e3.viaDiameter })), o3.push({ route_type: "wire", x: a3.x, y: a3.y, width: a3.traceThickness ?? e3.traceThickness, layer: l2 });
}
const r2 = o3.filter((t48) => t48.route_type === "wire"), s2 = e3.startPcbPortId ?? e3.route[0]?.pcb_port_id, a2 = e3.endPcbPortId ?? e3.route.at(-1)?.pcb_port_id;
s2 && r2[0] && (r2[0].start_pcb_port_id = s2), a2 && r2.at(-1) && (r2.at(-1).end_pcb_port_id = a2);
}
return { type: "pcb_trace", pcb_trace_id: `post_processing_hd_route_${n3}`, connection_name: e3.connectionName, __postProcessingViaDiameter: e3.viaDiameter, route: o3 };
}), o2 = structuredClone(t47.obstacles);
for (let n3 = 0;n3 < t47.hdRoutes.length; n3++) {
const i2 = t47.hdRoutes[n3], r2 = new Set([i2.connectionName, i2.rootConnectionName, i2.startPcbPortId, i2.endPcbPortId, i2.route[0]?.pcb_port_id, i2.route.at(-1)?.pcb_port_id, e2.get(n3)].filter((t48) => t48 !== undefined));
for (const t48 of o2)
t48.connectedTo.some((t49) => r2.has(t49)) && (t48.connectedTo = [...new Set([...t48.connectedTo, ...r2])]);
}
return { params: { simpleRouteJson: { traces: n2, differentialPairs: structuredClone(t47.differentialPairs), obstacles: o2, bounds: structuredClone(t47.bounds), layerCount: t47.layerCount, minTraceToPadEdgeClearance: t47.minTraceToPadEdgeClearance }, ...t47.routingGrid ? { routingGrid: structuredClone(t47.routingGrid) } : {} }, routeBindings: [...e2.entries()].map(([t48, e3]) => ({ hdRouteIndex: t48, traceIndex: t48, internalConnectionName: e3 })), sourceHdRoutes: structuredClone(t47.hdRoutes) };
};
function p1(t47) {
const e2 = structuredClone(t47.model.sourceHdRoutes);
for (const n2 of t47.model.routeBindings) {
const o2 = t47.binding.traceBindings.find((t48) => t48.traceIndex === n2.traceIndex);
if (!o2)
continue;
const i2 = t47.result.matchedHdRoutes[o2.matchedRouteIndex], r2 = e2[n2.hdRouteIndex];
if (!i2 || !r2)
throw new Error(`PostProcessingSolver: missing matched or source HD route for "${n2.internalConnectionName}"`);
if (i2.connectionName !== n2.internalConnectionName)
throw new Error(`PostProcessingSolver: matched HD binding changed "${n2.internalConnectionName}" to "${i2.connectionName}"`);
const s2 = i2.route.map((t48) => ({ ...t48 })), a2 = (e3, o3) => {
if (e3 && o3 && (o3.pcb_port_id && (e3.pcb_port_id = o3.pcb_port_id), o3.insideJumperPad && t47.rejectInsideJumperPad))
throw new Error(`PostProcessingSolver: cannot restore jumper-pad metadata on rerouted connection "${n2.internalConnectionName}"`);
};
a2(s2[0], r2.route[0]), a2(s2.at(-1), r2.route.at(-1)), e2[n2.hdRouteIndex] = { ...r2, route: s2, vias: structuredClone(i2.vias) };
}
return { hdRoutes: e2, postProcessingErrors: [] };
}
var m1 = class extends Error {
connectionNames;
reason;
constructor(t47) {
super(`PostProcessingSolver: differential pair ${t47.connectionNames.join("/")} ${t47.message}`), this.name = "DifferentialPairRoutingError", this.connectionNames = [t47.connectionNames[0], t47.connectionNames[1]], this.reason = t47.reason;
}
};
var g1 = class extends Error {
connectionNames;
reason;
constructor(t47) {
super(t47.message), this.name = "PostProcessingConstraintError", this.connectionNames = [...t47.connectionNames], this.reason = t47.reason;
}
};
var f1 = class extends Error {
reason = "grid-capacity-exhausted";
constructor(t47) {
super(t47), this.name = "PostProcessingGridCapacityError";
}
};
var y1 = (t47) => {
const e2 = 75000 * t47.simpleRouteJson.differentialPairs.length;
if (!Number.isSafeInteger(e2))
throw new Error("PostProcessingSolver: derived rerouting iteration bound exceeds the safe integer range");
const n2 = Math.min(e2, 80000);
return Math.max(1, n2);
};
var _1 = (t47) => structuredClone(t47);
var b1 = (t47, e2, n2) => {
const o2 = (t48) => {
const n3 = -(e2.ccwRotationDegrees ?? 0) * Math.PI / 180, o3 = t48.x - e2.center.x, i3 = t48.y - e2.center.y;
return { x: o3 * Math.cos(n3) - i3 * Math.sin(n3), y: o3 * Math.sin(n3) + i3 * Math.cos(n3) };
}, i2 = o2(t47.start), r2 = o2(t47.end), s2 = e2.width / 2 + n2, a2 = e2.height / 2 + n2;
if (Math.abs(i2.x) <= s2 && Math.abs(i2.y) <= a2 || Math.abs(r2.x) <= s2 && Math.abs(r2.y) <= a2)
return true;
const c2 = [{ x: -s2, y: -a2 }, { x: s2, y: -a2 }, { x: s2, y: a2 }, { x: -s2, y: a2 }];
return c2.some((t48, e3) => k0(i2, r2, t48, c2[(e3 + 1) % c2.length]) <= 0.0000001);
};
var x1 = (t47) => {
const e2 = [], n2 = [];
for (const o3 of t47.immutableTraces) {
const i3 = c1(o3, t47.layerCount);
e2.push(...i3.segments), n2.push(...i3.vias);
}
const o2 = Array.from({ length: t47.layerCount }, () => []);
for (const n3 of e2) {
const e3 = o1(n3.layer, t47.layerCount);
o2[e3].push(n3);
}
const i2 = (t48, e3) => Math.hypot(t48.x - e3.x, t48.y - e3.y) <= 0.00000001, r2 = (t48, e3, n3) => {
const o3 = n3.x - e3.x, i3 = n3.y - e3.y, r3 = o3 * o3 + i3 * i3, s3 = r3 === 0 ? 0 : Math.max(0, Math.min(1, ((t48.x - e3.x) * o3 + (t48.y - e3.y) * i3) / r3));
return Math.hypot(t48.x - e3.x - o3 * s3, t48.y - e3.y - i3 * s3);
}, s2 = (t48, e3, n3) => {
const o3 = -(e3.ccwRotationDegrees ?? 0) * Math.PI / 180, i3 = t48.x - e3.center.x, r3 = t48.y - e3.center.y, s3 = i3 * Math.cos(o3) - r3 * Math.sin(o3), a3 = i3 * Math.sin(o3) + r3 * Math.cos(o3);
return Math.abs(s3) <= e3.width / 2 + n3 && Math.abs(a3) <= e3.height / 2 + n3;
}, a2 = (e3, n3) => {
const o3 = o1(n3, t47.layerCount);
return B0(e3, t47.layerCount).includes(o3);
}, c2 = (e3, n3, o3) => {
const i3 = ((e4, n4, o4) => {
const i4 = Math.hypot(n4.x, n4.y);
if (i4 <= 0.0000000001)
throw new Error("PostProcessingSolver: cannot orient terminal fanout on a zero-length spine");
const r4 = -n4.y / i4 * t47.side * t47.centerlineSpacing / 2, s3 = n4.x / i4 * t47.side * t47.centerlineSpacing / 2, a3 = o4 === "start" ? [t47.firstStartTerminal, t47.secondStartTerminal] : [t47.firstEndTerminal, t47.secondEndTerminal], c3 = [t47.firstWidth, t47.secondWidth], l3 = [t47.firstConnectionName, t47.secondConnectionName];
return a3.map((t48, n5) => {
const i5 = n5 === 0 ? 1 : -1, a4 = { x: e4.x + r4 * i5, y: e4.y + s3 * i5 };
return { start: o4 === "start" ? t48 : a4, end: o4 === "start" ? a4 : t48, layer: e4.layer, width: c3[n5], connectionName: l3[n5], terminal: o4 };
});
})(e3, n3, o3), r3 = i3.map((t48) => o3 === "start" ? t48.end : t48.start);
return i3.every(l2) && r3.every((n4, o4) => t47.obstacles.every((r4) => !a2(r4, e3.layer) || !s2(n4, r4, 1.5 * i3[o4].width + (t47.terminalMiterMargin ?? 0)))) && k0(i3[0].start, i3[0].end, i3[1].start, i3[1].end) >= i3[0].width / 2 + i3[1].width / 2 - 0.0000001;
}, l2 = (e3) => {
const i3 = e3.width / 2, c3 = i3 + (t47.minTraceToPadEdgeClearance ?? e3.width), l3 = o1(e3.layer, t47.layerCount), h3 = Math.min(e3.start.x, e3.end.x), d2 = Math.max(e3.start.x, e3.end.x), u2 = Math.min(e3.start.y, e3.end.y), p2 = Math.max(e3.start.y, e3.end.y);
for (const n3 of [e3.start, e3.end])
if (n3.x - i3 < t47.bounds.minX || n3.x + i3 > t47.bounds.maxX || n3.y - i3 < t47.bounds.minY || n3.y + i3 > t47.bounds.maxY)
return false;
for (const n3 of t47.obstacles) {
if (!a2(n3, e3.layer))
continue;
const o3 = Math.hypot(n3.width / 2 + c3, n3.height / 2 + c3);
if (d2 < n3.center.x - o3 || h3 > n3.center.x + o3 || p2 < n3.center.y - o3 || u2 > n3.center.y + o3)
continue;
const [i4, r3] = e3.connectionName === t47.firstConnectionName ? [t47.firstStartTerminal, t47.firstEndTerminal] : [t47.secondStartTerminal, t47.secondEndTerminal], l4 = s2(i4, n3, 0) && (s2(e3.start, n3, c3) || s2(e3.end, n3, c3)) && Math.hypot(e3.end.x - i4.x, e3.end.y - i4.y) >= Math.hypot(e3.start.x - i4.x, e3.start.y - i4.y), m2 = s2(r3, n3, 0) && (s2(e3.start, n3, c3) || s2(e3.end, n3, c3)) && Math.hypot(e3.end.x - r3.x, e3.end.y - r3.y) <= Math.hypot(e3.start.x - r3.x, e3.start.y - r3.y);
if (!(n3.connectedTo.includes(e3.connectionName) && (l4 || m2)) && b1(e3, n3, c3))
return false;
}
for (const t48 of o2[l3]) {
const n3 = e3.width / 2 + t48.width / 2 + Math.max(e3.width, t48.width);
if (!(d2 + n3 < Math.min(t48.start.x, t48.end.x) || h3 - n3 > Math.max(t48.start.x, t48.end.x) || p2 + n3 < Math.min(t48.start.y, t48.end.y) || u2 - n3 > Math.max(t48.start.y, t48.end.y)) && k0(e3.start, e3.end, t48.start, t48.end) < n3)
return false;
}
for (const t48 of n2)
if (t48.layers.includes(e3.layer) && r2(t48, e3.start, e3.end) < e3.width / 2 + t48.diameter / 2 + e3.width)
return false;
return true;
}, h2 = (o3) => {
const i3 = o3.diameter / 2;
if (o3.x - i3 < t47.bounds.minX || o3.x + i3 > t47.bounds.maxX || o3.y - i3 < t47.bounds.minY || o3.y + i3 > t47.bounds.maxY)
return false;
for (const e3 of t47.obstacles) {
if (!o3.layers.some((t48) => a2(e3, t48)))
continue;
if (!(o3.terminal !== null && e3.connectedTo.includes(o3.connectionName) && s2(o3, e3, 0)) && s2(o3, e3, i3 + o3.diameter))
return false;
}
for (const t48 of e2) {
if (!o3.layers.includes(t48.layer))
continue;
const e3 = i3 + t48.width / 2 + Math.max(o3.diameter, t48.width);
if (r2(o3, t48.start, t48.end) < e3)
return false;
}
for (const t48 of n2) {
if (!t48.layers.some((t49) => o3.layers.includes(t49)))
continue;
const e3 = i3 + t48.diameter / 2 + Math.max(o3.diameter, t48.diameter);
if (Math.hypot(o3.x - t48.x, o3.y - t48.y) < e3)
return false;
}
return true;
};
return { isEdgeValid: (e3, n3) => {
if (e3.layer !== n3.layer || !((e4, n4) => {
const o4 = Math.hypot(n4.x - e4.x, n4.y - e4.y);
if (o4 === 0)
return [];
const r3 = -(n4.y - e4.y) / o4 * t47.side * t47.centerlineSpacing / 2, s3 = (n4.x - e4.x) / o4 * t47.side * t47.centerlineSpacing / 2, a3 = i2(e4, t47.start), c3 = i2(n4, t47.end), l3 = t47.terminalFanout ? a3 && c3 ? "both" : a3 ? "start" : c3 ? "end" : null : null, h3 = a3 && t47.terminalFanout ? t47.firstStartTerminal : { x: e4.x + r3, y: e4.y + s3 }, d2 = c3 && t47.terminalFanout ? t47.firstEndTerminal : { x: n4.x + r3, y: n4.y + s3 }, u2 = a3 && t47.terminalFanout ? t47.secondStartTerminal : { x: e4.x - r3, y: e4.y - s3 }, p2 = c3 && t47.terminalFanout ? t47.secondEndTerminal : { x: n4.x - r3, y: n4.y - s3 };
return [{ start: h3, end: d2, layer: e4.layer, width: t47.firstWidth, connectionName: t47.firstConnectionName, terminal: l3 }, { start: u2, end: p2, layer: e4.layer, width: t47.secondWidth, connectionName: t47.secondConnectionName, terminal: l3 }];
})(e3, n3).every(l2))
return false;
if (t47.terminalFanout || t47.terminalMiterMargin === undefined)
return true;
const o3 = { x: n3.x - e3.x, y: n3.y - e3.y };
return !(i2(e3, t47.start) && !c2(e3, o3, "start")) && !(i2(n3, t47.end) && !c2(n3, o3, "end"));
}, isTerminalFanoutValid: c2, isViaValid: (e3, n3, o3) => {
const r3 = Math.hypot(o3.x, o3.y);
if (r3 <= 0.0000000001)
throw new Error("PostProcessingSolver: cannot orient a coupled via on a zero-length spine");
const s3 = r1(e3.layer, n3, t47.layerCount), a3 = -o3.y / r3 * t47.side * t47.centerlineSpacing / 2, c3 = o3.x / r3 * t47.side * t47.centerlineSpacing / 2, l3 = i2(e3, t47.start) ? "start" : i2(e3, t47.end) ? "end" : null;
return [{ x: e3.x + a3, y: e3.y + c3, layers: s3, diameter: t47.firstViaDiameter, connectionName: t47.firstConnectionName, terminal: l3 }, { x: e3.x - a3, y: e3.y - c3, layers: s3, diameter: t47.secondViaDiameter, connectionName: t47.secondConnectionName, terminal: l3 }].every(h2);
} };
};
var v1 = (t47, e2, n2) => {
const o2 = 0.0000001, i2 = (t48, e3) => {
const n3 = -(e3.ccwRotationDegrees ?? 0) * Math.PI / 180, o3 = t48.x - e3.center.x, i3 = t48.y - e3.center.y;
return { x: o3 * Math.cos(n3) - i3 * Math.sin(n3), y: o3 * Math.sin(n3) + i3 * Math.cos(n3) };
}, r2 = (t48, e3, n3) => {
const o3 = n3.x - e3.x, i3 = n3.y - e3.y, r3 = o3 * o3 + i3 * i3, s3 = r3 === 0 ? 0 : Math.max(0, Math.min(1, ((t48.x - e3.x) * o3 + (t48.y - e3.y) * i3) / r3));
return Math.hypot(t48.x - (e3.x + s3 * o3), t48.y - (e3.y + s3 * i3));
}, s2 = (t48, e3, n3) => {
const o3 = o1(e3, n3);
return B0(t48, n3).includes(o3);
}, a2 = (t48, e3, n3) => {
const a3 = t48.width / 2;
if (t48.start.x - a3 < e3.bounds.minX - o2 || t48.start.x + a3 > e3.bounds.maxX + o2 || t48.start.y - a3 < e3.bounds.minY - o2 || t48.start.y + a3 > e3.bounds.maxY + o2 || t48.end.x - a3 < e3.bounds.minX - o2 || t48.end.x + a3 > e3.bounds.maxX + o2 || t48.end.y - a3 < e3.bounds.minY - o2 || t48.end.y + a3 > e3.bounds.maxY + o2)
return false;
for (const n4 of e3.obstacles) {
if (!s2(n4, t48.layer, e3.layerCount))
continue;
const r3 = t48.terminal === "both" ? [t48.start, t48.end] : t48.terminal === "start" ? [t48.start] : t48.terminal === "end" ? [t48.end] : [];
if (!(n4.connectedTo.includes(t48.connectionName) && r3.some((t49) => {
const e4 = i2(t49, n4);
return Math.abs(e4.x) <= n4.width / 2 + o2 && Math.abs(e4.y) <= n4.height / 2 + o2;
})) && b1(t48, n4, a3 + (e3.minTraceToPadEdgeClearance ?? t48.width)))
return false;
}
for (const e4 of n3.segments) {
if (e4.layer !== t48.layer)
continue;
const n4 = t48.width / 2 + e4.width / 2 + Math.max(t48.width, e4.width);
if (k0(t48.start, t48.end, e4.start, e4.end) < n4 - o2)
return false;
}
for (const e4 of n3.vias) {
if (!e4.layers.includes(t48.layer))
continue;
const n4 = t48.width / 2 + e4.diameter / 2 + t48.width;
if (r2(e4, t48.start, t48.end) < n4 - o2)
return false;
}
return true;
}, c2 = (t48, e3, n3) => {
const a3 = t48.diameter / 2;
if (t48.x - a3 < e3.bounds.minX - o2 || t48.x + a3 > e3.bounds.maxX + o2 || t48.y - a3 < e3.bounds.minY - o2 || t48.y + a3 > e3.bounds.maxY + o2)
return false;
for (const n4 of e3.obstacles) {
if (!t48.layers.some((t49) => s2(n4, t49, e3.layerCount)))
continue;
const r3 = i2(t48, n4);
if (!(t48.terminal !== null && n4.connectedTo.includes(t48.connectionName) && Math.abs(r3.x) <= n4.width / 2 + o2 && Math.abs(r3.y) <= n4.height / 2 + o2) && Math.abs(r3.x) <= n4.width / 2 + a3 + t48.diameter && Math.abs(r3.y) <= n4.height / 2 + a3 + t48.diameter)
return false;
}
for (const e4 of n3.segments) {
if (!t48.layers.includes(e4.layer))
continue;
const n4 = a3 + e4.width / 2 + Math.max(t48.diameter, e4.width);
if (r2(t48, e4.start, e4.end) < n4 - o2)
return false;
}
for (const e4 of n3.vias) {
if (!e4.layers.some((e5) => t48.layers.includes(e5)))
continue;
const n4 = a3 + e4.diameter / 2 + Math.max(t48.diameter, e4.diameter);
if (Math.hypot(t48.x - e4.x, t48.y - e4.y) < n4 - o2)
return false;
}
return true;
}, l2 = (t48) => {
for (let e3 = 0;e3 < t48.segments.length; e3++) {
const n3 = t48.segments[e3];
for (let i3 = e3 + 2;i3 < t48.segments.length; i3++) {
const r3 = t48.segments[i3];
if (n3.layer !== r3.layer)
continue;
if (!(t48.segments.slice(e3 + 1, i3).reduce((t49, e4) => t49 + Math.hypot(e4.end.x - e4.start.x, e4.end.y - e4.start.y), 0) <= n3.width + r3.width + o2) && k0(n3.start, n3.end, r3.start, r3.end) < n3.width / 2 + r3.width / 2 - o2)
return true;
}
}
for (const e3 of t48.vias)
for (const n3 of t48.segments) {
if (!e3.layers.includes(n3.layer))
continue;
if (!(Math.hypot(e3.x - n3.start.x, e3.y - n3.start.y) <= o2 || Math.hypot(e3.x - n3.end.x, e3.y - n3.end.y) <= o2) && r2(e3, n3.start, n3.end) < e3.diameter / 2 + n3.width / 2 - o2)
return true;
}
return false;
}, h2 = ((t48, e3) => {
const n3 = [], o3 = [];
for (const i3 of t48) {
const t49 = c1(i3, e3);
n3.push(...t49.segments), o3.push(...t49.vias);
}
return { segments: n3, vias: o3 };
})(n2.immutableTraces, n2.layerCount);
if (!((t48, e3) => {
for (const n3 of t48.segments)
for (const t49 of e3.segments) {
if (n3.layer !== t49.layer)
continue;
const e4 = n3.width / 2 + t49.width / 2;
if (k0(n3.start, n3.end, t49.start, t49.end) < e4 - o2)
return false;
}
for (const [n3, i3] of [[t48.vias, e3.segments], [e3.vias, t48.segments]])
for (const t49 of n3)
for (const e4 of i3)
if (t49.layers.includes(e4.layer) && r2(t49, e4.start, e4.end) < t49.diameter / 2 + e4.width / 2 - o2)
return false;
for (const n3 of t48.vias)
for (const t49 of e3.vias)
if (n3.layers.some((e4) => t49.layers.includes(e4)) && Math.hypot(n3.x - t49.x, n3.y - t49.y) < n3.diameter / 2 + t49.diameter / 2 - o2)
return false;
return true;
})(t47, e2) || l2(t47) || l2(e2))
return false;
for (const o3 of [t47, e2])
if (o3.segments.some((t48) => !a2(t48, n2, h2)) || o3.vias.some((t48) => !c2(t48, n2, h2)))
return false;
return true;
};
var I1 = [{ x: 1, y: 0 }, { x: 1, y: 1 }, { x: 0, y: 1 }, { x: -1, y: 1 }, { x: -1, y: 0 }, { x: -1, y: -1 }, { x: 0, y: -1 }, { x: 1, y: -1 }];
var S1 = class {
constructor(t47) {
this.input = t47;
const { bounds: e2, grid: n2 } = t47, o2 = { minX: e2.minX + n2.outerPerimeterWidth, maxX: e2.maxX - n2.outerPerimeterWidth, minY: e2.minY + n2.outerPerimeterWidth, maxY: e2.maxY - n2.outerPerimeterWidth }, i2 = this.createAxis(e2.minX, e2.maxX, n2.outerGridStep, [o2.minX, o2.maxX]), r2 = this.createAxis(e2.minY, e2.maxY, n2.outerGridStep, [o2.minY, o2.maxY]), s2 = this.createAxis(o2.minX, o2.maxX, n2.innerGridStep, [], t47.start.x), a2 = this.createAxis(o2.minY, o2.maxY, n2.innerGridStep, [], t47.start.y), c2 = this.createGrid(i2, r2, (t48) => t48.x <= o2.minX || t48.x >= o2.maxX || t48.y <= o2.minY || t48.y >= o2.maxY), l2 = this.createGrid(s2, a2, () => true);
this.connectLocalNeighbors(c2), this.connectLocalNeighbors(l2);
for (const t48 of ["left", "right", "bottom", "top"])
this.connectBoundaries(t48, c2, l2, o2);
const h2 = this.nodes.map((t48, e3) => e3);
this.connectEndpoint(t47.start, h2), this.connectEndpoint(t47.end, h2);
}
nodes = [];
nodeIdByPoint = new Map;
endpointNodeIdByPoint = new Map;
getPlanarNeighbors(t47) {
const e2 = this.endpointNodeIdByPoint.get(this.exactKeyFor(t47)) ?? this.nodeIdByPoint.get(this.keyFor(t47));
if (e2 === undefined)
throw new Error(`PostProcessingSolver: coupled path point (${t47.x}, ${t47.y}) is not on the composite grid`);
return [...this.nodes[e2].neighborIds].map((e3) => ({ ...this.nodes[e3].point, layer: t47.layer }));
}
getNodeCount() {
return this.nodes.length;
}
getSearchStateCountUpperBound(t47) {
const e2 = this.nodes.reduce((t48, e3) => t48 + e3.neighborIds.size, 0) * t47 + 1;
if (!Number.isSafeInteger(e2))
throw new Error("PostProcessingSolver: composite-grid search-state bound exceeds the safe integer range");
return e2;
}
createAxis(t47, e2, n2, o2, i2 = t47) {
const r2 = [t47, e2, ...o2].map((t48) => ({ value: t48, fixed: true }));
for (let o3 = Math.ceil((t47 - i2) / n2);i2 + o3 * n2 < e2 - 0.00000001; o3++)
r2.push({ value: i2 + o3 * n2, fixed: false });
r2.sort((t48, e3) => t48.value - e3.value || Number(e3.fixed) - Number(t48.fixed));
const s2 = [];
for (const t48 of r2) {
const e3 = s2.at(-1);
!e3 || Math.abs(t48.value - e3.value) > 0.00000001 ? s2.push(t48) : t48.fixed && !e3.fixed && (s2[s2.length - 1] = t48);
}
return s2.map((t48) => t48.value);
}
createGrid(t47, e2, n2) {
return e2.map((e3) => t47.map((t48) => {
const o2 = { x: t48, y: e3 };
return n2(o2) ? this.addNode(o2) : null;
}));
}
connectLocalNeighbors(t47) {
for (let e2 = 0;e2 < t47.length; e2++)
for (let n2 = 0;n2 < (t47[e2]?.length ?? 0); n2++) {
const o2 = t47[e2][n2];
if (o2 !== null)
for (const i2 of I1) {
const r2 = t47[e2 + i2.y]?.[n2 + i2.x];
r2 != null && this.connect(o2, r2);
}
}
}
connectBoundaries(t47, e2, n2, o2) {
const i2 = t47 === "left" ? o2.minX : t47 === "right" ? o2.maxX : t47 === "bottom" ? o2.minY : o2.maxY, r2 = t47 === "left" || t47 === "right", s2 = (t48) => Math.abs((r2 ? t48.x : t48.y) - i2) <= 0.00000001, a2 = (t48) => {
const e3 = new Set;
for (const n3 of t48)
for (const t49 of n3)
t49 !== null && s2(this.nodes[t49].point) && e3.add(t49);
return [...e3].sort((t49, e4) => {
const n3 = this.nodes[t49].point, o3 = this.nodes[e4].point;
return (r2 ? n3.y - o3.y : n3.x - o3.x) || t49 - e4;
});
}, c2 = a2(e2), l2 = a2(n2);
if (c2.length === 0 || l2.length === 0)
throw new Error(`PostProcessingSolver: composite grid has no ${t47} boundary bridge candidates`);
for (const t48 of c2)
this.connect(t48, this.findNearestAlongBoundary(t48, l2, r2));
for (const t48 of l2)
this.connect(t48, this.findNearestAlongBoundary(t48, c2, r2));
}
findNearestAlongBoundary(t47, e2, n2) {
const o2 = this.nodes[t47].point;
let i2 = e2[0], r2 = Number.POSITIVE_INFINITY;
for (const t48 of e2) {
const e3 = this.nodes[t48].point, s2 = Math.abs(n2 ? o2.y - e3.y : o2.x - e3.x);
(s2 < r2 - 0.00000001 || Math.abs(s2 - r2) <= 0.00000001 && t48 < i2) && (r2 = s2, i2 = t48);
}
return i2;
}
connectEndpoint(t47, e2) {
const n2 = this.nodeIdByPoint.get(this.keyFor(t47)), o2 = n2 === undefined ? null : this.nodes[n2].point, i2 = o2?.x === t47.x && o2.y === t47.y ? n2 : this.nodes.push({ point: { x: t47.x, y: t47.y }, neighborIds: new Set }) - 1;
this.endpointNodeIdByPoint.set(this.exactKeyFor(t47), i2);
const r2 = (t48, n3) => {
const o3 = this.nodes[t48].point, i3 = e2.filter((e3) => e3 !== t48).map((t49) => ({ nodeId: t49, distance: Math.hypot(this.nodes[t49].point.x - o3.x, this.nodes[t49].point.y - o3.y) })).filter(({ distance: t49 }) => t49 > 0.0000000001).sort((t49, e3) => t49.distance - e3.distance || t49.nodeId - e3.nodeId).slice(0, n3);
if (i3.length === 0)
throw new Error("PostProcessingSolver: composite grid has no endpoint connection candidates");
for (const { nodeId: e3 } of i3)
this.connect(t48, e3);
};
r2(i2, 8);
for (const e3 of I1) {
const n3 = { x: t47.x + e3.x * this.input.grid.innerGridStep, y: t47.y + e3.y * this.input.grid.innerGridStep };
if (n3.x < this.input.bounds.minX || n3.x > this.input.bounds.maxX || n3.y < this.input.bounds.minY || n3.y > this.input.bounds.maxY)
continue;
const o3 = this.addNode(n3);
this.connect(i2, o3), r2(o3, 4);
}
}
addNode(t47) {
const e2 = this.keyFor(t47), n2 = this.nodeIdByPoint.get(e2);
if (n2 !== undefined)
return n2;
const o2 = this.nodes.length;
return this.nodes.push({ point: { x: t47.x, y: t47.y }, neighborIds: new Set }), this.nodeIdByPoint.set(e2, o2), o2;
}
connect(t47, e2) {
if (t47 === e2)
return;
const n2 = this.nodes[t47], o2 = this.nodes[e2];
n2.neighborIds.add(e2), o2.neighborIds.add(t47);
}
keyFor(t47) {
const e2 = Object.is(t47.x, -0) ? 0 : t47.x, n2 = Object.is(t47.y, -0) ? 0 : t47.y;
return `${e2.toFixed(12)}:${n2.toFixed(12)}`;
}
exactKeyFor(t47) {
return `${Object.is(t47.x, -0) ? 0 : t47.x}:${Object.is(t47.y, -0) ? 0 : t47.y}`;
}
};
var C1 = class {
constructor(t47) {
if (this.input = t47, this.startLayer = o1(t47.start.layer, t47.layerCount), this.endLayer = o1(t47.end.layer, t47.layerCount), this.grid = new S1(t47), this.maxSearchStates = this.grid.getSearchStateCountUpperBound(t47.layerCount), this.exploredStateLimit = Math.min(this.maxSearchStates, 20000), this.startLayer < 0 || this.endLayer < 0)
return this.queue = [], void (this.status = "exhausted");
const e2 = { point: t47.start, direction: null, cost: 0, estimate: this.estimate(t47.start), parent: null, sequence: 0 };
this.queue = [e2], this.bestCosts.set(this.keyFor(t47.start, null), 0);
}
queue;
bestCosts = new Map;
startLayer;
endLayer;
grid;
maxSearchStates;
exploredStateLimit;
current = null;
result = null;
status = "searching";
explored = 0;
nextSequence = 1;
isComplete() {
return this.status !== "searching";
}
getPath() {
return this.result;
}
getPreviewPath() {
return this.current ? this.createPath(this.current) : [this.input.start];
}
getExploredCount() {
return this.explored;
}
getProgress() {
return this.status !== "searching" ? 1 : Math.min(0.99, this.explored / this.exploredStateLimit);
}
getGridNodeCount() {
return this.grid.getNodeCount();
}
step() {
if (this.status !== "searching")
return;
const t47 = this.popQueue();
if (!t47)
return void (this.status = "exhausted");
const e2 = this.bestCosts.get(this.keyFor(t47.point, t47.direction));
if (e2 === undefined)
throw new Error("PostProcessingSolver: coupled path queue contains an untracked state");
if (t47.cost > e2 + 0.0000000001)
this.queue.length === 0 && (this.status = "exhausted");
else {
if (this.current = t47, this.explored++, this.explored > this.maxSearchStates)
throw new Error(`PostProcessingSolver: coupled path search exceeded its ${this.maxSearchStates}-state graph invariant limit`);
if (this.isEnd(t47.point)) {
const e3 = this.createPath(t47);
return e3[e3.length - 1] = this.input.end, this.result = this.simplifyPath(e3), void (this.status = "found");
}
this.explored >= this.exploredStateLimit ? this.status = "exhausted" : (this.enqueuePlanarNeighbors(t47), this.enqueueViaNeighbors(t47), this.queue.length === 0 && (this.status = "exhausted"));
}
}
isEnd(t47) {
return t47.layer === this.input.end.layer && t47.x === this.input.end.x && t47.y === this.input.end.y;
}
estimate(t47) {
return Math.hypot(t47.x - this.input.end.x, t47.y - this.input.end.y) + 3 * Math.abs(o1(t47.layer, this.input.layerCount) - this.endLayer);
}
keyFor(t47, e2) {
return `${Object.is(t47.x, -0) ? 0 : t47.x}:${Object.is(t47.y, -0) ? 0 : t47.y}:${t47.layer}:${e2?.key ?? "start"}`;
}
createDirection(t47, e2) {
const n2 = e2.x - t47.x, o2 = e2.y - t47.y, i2 = Math.hypot(n2, o2);
if (i2 <= 0.0000000001)
throw new Error("PostProcessingSolver: composite grid produced a zero-length planar edge");
const r2 = n2 / i2, s2 = o2 / i2;
return { x: r2, y: s2, key: `${r2.toFixed(6)}:${s2.toFixed(6)}` };
}
createPath(t47) {
const e2 = [];
let n2 = t47;
for (;n2; )
e2.push(n2.point), n2 = n2.parent;
return e2.reverse();
}
simplifyPath(t47) {
return t47.filter((e2, n2) => {
if (n2 === 0 || n2 === t47.length - 1)
return true;
const o2 = t47[n2 - 1], i2 = t47[n2 + 1], r2 = { x: e2.x - o2.x, y: e2.y - o2.y }, s2 = { x: i2.x - e2.x, y: i2.y - e2.y }, a2 = r2.x * s2.y - r2.y * s2.x, c2 = Math.hypot(r2.x, r2.y) * Math.hypot(s2.x, s2.y);
return Math.abs(a2) > 0.0000000001 * c2 || e2.layer !== o2.layer || e2.layer !== i2.layer;
});
}
hasHigherQueuePriority(t47, e2) {
return t47.estimate !== e2.estimate ? t47.estimate < e2.estimate : t47.cost !== e2.cost ? t47.cost < e2.cost : t47.point.x !== e2.point.x ? t47.point.x < e2.point.x : t47.point.y !== e2.point.y ? t47.point.y < e2.point.y : t47.point.layer !== e2.point.layer ? t47.point.layer < e2.point.layer : t47.sequence < e2.sequence;
}
pushQueue(t47) {
this.queue.push(t47);
let e2 = this.queue.length - 1;
for (;e2 > 0; ) {
const n2 = Math.floor((e2 - 1) / 2), o2 = this.queue[n2];
if (!this.hasHigherQueuePriority(t47, o2))
break;
this.queue[e2] = o2, e2 = n2;
}
this.queue[e2] = t47;
}
popQueue() {
const t47 = this.queue[0], e2 = this.queue.pop();
if (!t47 || !e2 || this.queue.length === 0)
return t47;
let n2 = 0;
for (;; ) {
const t48 = 2 * n2 + 1;
if (t48 >= this.queue.length)
break;
const o2 = t48 + 1;
let i2 = t48;
o2 < this.queue.length && this.hasHigherQueuePriority(this.queue[o2], this.queue[t48]) && (i2 = o2);
const r2 = this.queue[i2];
if (!this.hasHigherQueuePriority(r2, e2))
break;
this.queue[n2] = r2, n2 = i2;
}
return this.queue[n2] = e2, t47;
}
enqueuePlanarNeighbors(t47) {
for (const e2 of this.grid.getPlanarNeighbors(t47.point)) {
if (!this.input.isEdgeValid(t47.point, e2))
continue;
const n2 = this.createDirection(t47.point, e2), o2 = t47.direction === null || t47.direction.key === n2.key ? 0 : 0.18, i2 = t47.cost + Math.hypot(e2.x - t47.point.x, e2.y - t47.point.y) + o2, r2 = this.keyFor(e2, n2);
(this.bestCosts.get(r2) ?? Number.POSITIVE_INFINITY) <= i2 || (this.bestCosts.set(r2, i2), this.pushQueue({ point: e2, direction: n2, cost: i2, estimate: i2 + this.estimate(e2), parent: t47, sequence: this.nextSequence++ }));
}
}
enqueueViaNeighbors(t47) {
if (!t47.direction)
return;
const e2 = o1(t47.point.layer, this.input.layerCount);
for (const n2 of [e2 - 1, e2 + 1]) {
if (n2 < 0 || n2 >= this.input.layerCount)
continue;
const e3 = i1(n2, this.input.layerCount);
if (!this.input.isViaValid(t47.point, e3, t47.direction))
continue;
const o2 = { ...t47.point, layer: e3 }, i2 = t47.cost + 4, r2 = this.keyFor(o2, t47.direction);
(this.bestCosts.get(r2) ?? Number.POSITIVE_INFINITY) <= i2 || (this.bestCosts.set(r2, i2), this.pushQueue({ point: o2, direction: t47.direction, cost: i2, estimate: i2 + this.estimate(o2), parent: t47, sequence: this.nextSequence++ }));
}
}
};
var P1 = (t47) => {
const e2 = Math.min(t47.bounds.maxX - t47.bounds.minX, t47.bounds.maxY - t47.bounds.minY), n2 = t47.config?.innerGridStep ?? t47.defaultInnerGridStep, o2 = t47.config?.outerGridStep ?? 4 * n2, i2 = t47.config?.outerPerimeterWidth ?? Math.min(o2, e2 / 4);
if (!Number.isFinite(n2) || n2 < 0.0001)
throw new Error("PostProcessingSolver: routingGrid.innerGridStep must be finite and at least 0.0001");
if (!Number.isFinite(o2) || o2 <= n2)
throw new Error("PostProcessingSolver: routingGrid.outerGridStep must be finite and greater than innerGridStep");
if (!Number.isFinite(i2) || i2 <= 0 || 2 * i2 >= e2)
throw new Error("PostProcessingSolver: routingGrid.outerPerimeterWidth must be finite, positive, and less than half the smaller board extent");
const r2 = t47.bounds.maxX - t47.bounds.minX, s2 = t47.bounds.maxY - t47.bounds.minY;
if ((Math.ceil(r2 / o2) + 4) * (Math.ceil(s2 / o2) + 4) + (Math.ceil((r2 - 2 * i2) / n2) + 2) * (Math.ceil((s2 - 2 * i2) / n2) + 2) + 18 > 250000)
throw new f1("PostProcessingSolver: valid input exceeds the 250000-node optimization grid capacity");
return { innerGridStep: n2, outerGridStep: o2, outerPerimeterWidth: i2 };
};
var M1 = (t47) => {
const e2 = -t47.pathDirection.y, n2 = t47.pathDirection.x, o2 = Math.tan(t47.maximumTurnDegrees * Math.PI / 180), i2 = Math.max(0, ...t47.lanes.map(({ point: i3, polarity: r3 }) => {
const s3 = i3.x - t47.anchor.x, a3 = i3.y - t47.anchor.y, c2 = s3 * t47.escapeDirection.x + a3 * t47.escapeDirection.y, l2 = s3 * e2 + a3 * n2, h2 = r3 * t47.side * t47.centerlineSpacing / 2;
return c2 + Math.abs(l2 - h2) / o2;
})), r2 = t47.maxUncoupledLength ?? i2;
if (i2 > r2 + 0.00000001)
return null;
const s2 = Math.max(0.05, Math.min(0.25, t47.searchStep / 2)), a2 = Math.max(1, Math.ceil((r2 - i2) / s2) + 1);
for (let o3 = 0;o3 < a2; o3++) {
const a3 = Math.min(r2, i2 + o3 * s2), c2 = { x: t47.anchor.x + t47.escapeDirection.x * a3, y: t47.anchor.y + t47.escapeDirection.y * a3, layer: t47.anchor.layer };
if (t47.lanes.every(({ point: o4, polarity: i3 }) => {
const r3 = i3 * t47.side * t47.centerlineSpacing / 2, s3 = c2.x + e2 * r3, a4 = c2.y + n2 * r3;
return t47.maxUncoupledLength === undefined || Math.hypot(s3 - o4.x, a4 - o4.y) <= t47.maxUncoupledLength + 0.00000001;
}) && t47.isValid(c2))
return c2;
}
return null;
};
var N1 = [0.75, 0.5, 1, 0.25, 1.25];
var w1 = 100;
var T1 = class {
constructor(t47) {
this.input = t47, this.pairName = t47.pair.connectionNames.join("/"), this.prepared = this.prepare();
}
pairName;
prepared;
candidates = [];
result = null;
search = null;
nextAttempt = 0;
exploredNodeCount = 0;
isComplete() {
return this.result !== null;
}
getResult() {
if (!this.result)
throw new Error(`PostProcessingSolver: differential pair ${this.pairName} is not complete`);
return this.result;
}
getPreviewPath() {
return this.search?.getPreviewPath() ?? null;
}
getProgress() {
if (this.result)
return 1;
const t47 = this.prepared.attempts.length, e2 = this.search?.getProgress() ?? 0;
return Math.min(0.99, (this.nextAttempt + e2) / t47);
}
getStats() {
return { phase: this.search ? "searching" : "candidate-selection", pair: this.pairName, attemptIndex: this.nextAttempt, attemptCount: this.prepared.attempts.length, exploredNodeCount: this.exploredNodeCount + (this.search?.getExploredCount() ?? 0), gridNodeCount: this.search?.getGridNodeCount() ?? 0, acceptedCandidateCount: this.candidates.length };
}
step() {
if (this.result)
return;
const t47 = this.prepared;
if (!this.search) {
const e3 = t47.attempts[this.nextAttempt];
return e3 ? void (this.search = new C1(e3.input)) : void this.complete();
}
if (this.search.step(), !this.search.isComplete())
return;
const e2 = this.search.getPath();
this.exploredNodeCount += this.search.getExploredCount();
const n2 = t47.attempts[this.nextAttempt];
if (!n2)
throw new Error(`PostProcessingSolver: differential pair ${this.pairName} lost its active attempt`);
if (this.search = null, this.nextAttempt++, !e2)
return;
const o2 = ((t48) => {
const e3 = (t49, e4) => Math.hypot(t49.x - e4.x, t49.y - e4.y) <= 0.00000001;
if (t48.path.length < 2)
throw new Error("PostProcessingSolver: coupled path has fewer than two stations");
const n3 = (n4, o4) => {
for (let i3 = n4 + o4;i3 >= 0 && i3 < t48.path.length; i3 += o4) {
const o5 = t48.path[i3];
if (!e3(o5, t48.path[n4]))
return o5;
}
return null;
}, o3 = (e4) => {
const o4 = t48.path[e4], i3 = n3(e4, -1), r3 = n3(e4, 1), s3 = (t49, e5) => {
const n4 = e5.x - t49.x, o5 = e5.y - t49.y, i4 = Math.hypot(n4, o5);
if (i4 <= 0.0000000001)
throw new Error("PostProcessingSolver: cannot offset a zero-length spine");
return { x: -o5 / i4, y: n4 / i4 };
}, a3 = t48.side * t48.centerlineSpacing / 2;
if (!i3 || !r3) {
const t49 = s3(i3 ?? o4, r3 ?? o4);
return { x: t49.x * a3, y: t49.y * a3 };
}
if (t48.terminalFanout && e4 === 1)
return s3(i3, o4);
if (t48.terminalFanout && e4 === t48.path.length - 2)
return s3(o4, r3);
if (t48.terminalFanout && t48.path[e4 + 1]?.layer !== o4.layer)
return s3(i3, o4);
const c3 = s3(i3, o4), l3 = s3(o4, r3), h3 = { x: c3.x + l3.x, y: c3.y + l3.y }, d3 = Math.hypot(h3.x, h3.y);
if (d3 <= 0.0000000001)
return null;
const u3 = h3.x / d3, p3 = h3.y / d3, m3 = a3 / (u3 * c3.x + p3 * c3.y);
return { x: u3 * m3, y: p3 * m3 };
}, i2 = t48.first.points[0], r2 = t48.first.points.at(-1), s2 = t48.reverseSecond ? t48.second.points.at(-1) : t48.second.points[0], a2 = t48.reverseSecond ? t48.second.points[0] : t48.second.points.at(-1), c2 = [[{ route_type: "wire", x: i2.x, y: i2.y, width: i2.width, layer: i2.layer }], [{ route_type: "wire", x: s2.x, y: s2.y, width: s2.width, layer: s2.layer }]], l2 = [t48.first.transitions[0], t48.second.transitions[0]];
let h2 = 0;
const d2 = t48.terminalFanout ? 1 : 0, u2 = t48.path.length - 2, p2 = t48.path[u2], m2 = t48.path[u2 - 1], g2 = t48.terminalFanout && p2?.layer === r2.layer && m2?.layer === p2.layer, f2 = t48.terminalFanout ? g2 ? u2 - 1 : t48.path.length - 1 : t48.path.length;
for (let n4 = d2;n4 < f2; n4++) {
const i3 = t48.path[n4], r3 = o3(n4);
if (!r3)
return null;
for (const o4 of [0, 1]) {
const s3 = o4 === 0 ? 1 : -1, a3 = { x: i3.x + r3.x * s3, y: i3.y + r3.y * s3 }, h3 = c2[o4], d3 = t48.path[n4 - 1];
if (d3 && d3.layer !== i3.layer) {
if (!e3(d3, i3))
throw new Error("PostProcessingSolver: a coupled layer transition moved in the plane");
const n5 = [...h3].reverse().find((t49) => t49.route_type === "wire");
if (!n5)
throw new Error("PostProcessingSolver: generated via has no preceding wire");
const r4 = l2[o4];
h3.push({ route_type: "via", x: n5.x, y: n5.y, from_layer: d3.layer, to_layer: i3.layer, via_diameter: r4?.via_diameter ?? (o4 === 0 ? t48.first.viaDiameter : t48.second.viaDiameter), ...r4?.via_hole_diameter !== undefined ? { via_hole_diameter: r4.via_hole_diameter } : {} }), h3.push({ route_type: "wire", x: n5.x, y: n5.y, width: o4 === 0 ? t48.first.width : t48.second.width, layer: i3.layer });
} else {
const n5 = h3.at(-1);
n5?.route_type === "wire" && e3(n5, a3) && n5.layer === i3.layer || h3.push({ route_type: "wire", ...a3, width: o4 === 0 ? t48.first.width : t48.second.width, layer: i3.layer });
}
}
t48.path[n4 - 1]?.layer !== i3.layer && n4 > 0 && h2++;
}
const y2 = (e4, n4) => {
const o4 = e4.at(-1);
if (!o4 || o4.route_type !== "wire")
throw new Error("PostProcessingSolver: terminal fanout has no preceding wire");
const i3 = e4.at(-2);
let r3 = false;
if (i3?.route_type === "wire" && i3.layer === o4.layer && o4.layer === n4.layer) {
const t49 = { x: o4.x - i3.x, y: o4.y - i3.y }, e5 = { x: n4.x - o4.x, y: n4.y - o4.y }, s3 = Math.hypot(t49.x, t49.y), a3 = Math.hypot(e5.x, e5.y);
if (s3 > 0.00000001 && a3 > 0.00000001 && Math.abs(t49.x * e5.x + t49.y * e5.y) <= 0.00000001) {
const e6 = { x: o4.x - t49.x / s3 * a3, y: o4.y - t49.y / s3 * a3 };
(e6.x - i3.x) * (t49.x / s3) + (e6.y - i3.y) * (t49.y / s3) > 0.00000001 && (o4.x = e6.x, o4.y = e6.y, r3 = true);
}
}
t48.terminalFanout && !r3 && o4.x !== n4.x && o4.y !== n4.y && e4.push({ route_type: "wire", x: n4.x, y: o4.y, width: n4.width, layer: n4.layer }), e4.push({ route_type: "wire", x: n4.x, y: n4.y, width: n4.width, layer: n4.layer });
};
y2(c2[0], r2), y2(c2[1], a2), t48.reverseSecond && (c2[1] = c2[1].reverse().map((t49) => t49.route_type === "via" ? { ...t49, from_layer: t49.to_layer, to_layer: t49.from_layer } : t49));
const _2 = (t49, e4) => {
const n4 = t49.filter((t50) => t50.route_type === "wire");
for (const t50 of n4)
delete t50.start_pcb_port_id, delete t50.end_pcb_port_id;
e4.startPortId && (n4[0].start_pcb_port_id = e4.startPortId), e4.endPortId && (n4.at(-1).end_pcb_port_id = e4.endPortId);
};
_2(c2[0], t48.first), _2(c2[1], t48.second);
const b2 = { ...t48.first.source, route: c2[0] }, x2 = { ...t48.second.source, route: c2[1] };
return { first: b2, second: x2, firstParsed: a1(b2, t48.layerCount), secondParsed: a1(x2, t48.layerCount), edgeGap: t48.edgeGap, centerlineDistance: t48.centerlineSpacing, bendCount: Math.max(0, t48.path.length - h2 - 2), viaPairCount: h2 };
})({ first: t47.first, second: t47.second, reverseSecond: t47.reverseSecond, path: e2, centerlineSpacing: n2.edgeGap + t47.first.width / 2 + t47.second.width / 2, edgeGap: n2.edgeGap, side: n2.side, layerCount: this.input.layerCount, terminalFanout: t47.terminalFanout });
o2 && v1(o2.firstParsed, o2.secondParsed, t47.context) && this.candidates.push(o2);
}
prepare() {
const t47 = this.input.traces.map((t48, e3) => ({ trace: t48, index: e3 })).filter(({ trace: t48 }) => t48.connection_name === this.input.pair.connectionNames[0]), e2 = this.input.traces.map((t48, e3) => ({ trace: t48, index: e3 })).filter(({ trace: t48 }) => t48.connection_name === this.input.pair.connectionNames[1]);
if (t47.length !== 1 || e2.length !== 1)
throw new m1({ connectionNames: this.input.pair.connectionNames, reason: "trace-resolution-failure", message: "must resolve each connection_name to exactly one non-branching trace" });
if (t47[0].index === e2[0].index)
throw new m1({ connectionNames: this.input.pair.connectionNames, reason: "trace-resolution-failure", message: "resolved both members to one trace" });
let n2, o2;
try {
n2 = a1(t47[0].trace, this.input.layerCount), o2 = a1(e2[0].trace, this.input.layerCount);
} catch (t48) {
throw new m1({ connectionNames: this.input.pair.connectionNames, reason: "invalid-routed-geometry", message: `has unsupported or invalid routed geometry: ${t48 instanceof Error ? t48.message : String(t48)}` });
}
const i2 = n2.points[0], r2 = n2.points.at(-1), s2 = Math.hypot(i2.x - o2.points[0].x, i2.y - o2.points[0].y) + Math.hypot(r2.x - o2.points.at(-1).x, r2.y - o2.points.at(-1).y), a2 = Math.hypot(i2.x - o2.points.at(-1).x, i2.y - o2.points.at(-1).y) + Math.hypot(r2.x - o2.points[0].x, r2.y - o2.points[0].y) + 0.00000001 < s2, c2 = a2 ? o2.points.at(-1) : o2.points[0], l2 = a2 ? o2.points[0] : o2.points.at(-1);
if (i2.layer !== c2.layer || r2.layer !== l2.layer)
throw new m1({ connectionNames: this.input.pair.connectionNames, reason: "terminal-layer-mismatch", message: "does not have common paired layers at both terminal stations" });
const h2 = { x: (i2.x + c2.x) / 2, y: (i2.y + c2.y) / 2, layer: i2.layer }, d2 = { x: (r2.x + l2.x) / 2, y: (r2.y + l2.y) / 2, layer: r2.layer }, u2 = Math.hypot(d2.x - h2.x, d2.y - h2.y);
if (u2 < 0.000001)
throw new m1({ connectionNames: this.input.pair.connectionNames, reason: "coincident-terminal-midpoints", message: "has coincident terminal-pair midpoints" });
const p2 = { x: -(d2.y - h2.y) / u2, y: (d2.x - h2.x) / u2 }, m2 = i2.x - c2.x, g2 = i2.y - c2.y, f2 = m2 * p2.x + g2 * p2.y >= 0 ? 1 : -1, y2 = (t48, e3) => {
const n3 = t48.x - e3.x, o3 = t48.y - e3.y, i3 = Math.hypot(n3, o3);
return i3 > 0.00000001 && Math.abs(n3 * p2.x + o3 * p2.y) / i3 < 0.5;
}, _2 = y2(i2, c2) && y2(r2, l2), b2 = { x: p2.y, y: -p2.x }, x2 = [i2, c2].some((t48) => (t48.x - h2.x) * b2.x + (t48.y - h2.y) * b2.y > 0.00000001), v2 = { immutableTraces: this.input.traces.filter((n3, o3) => o3 !== t47[0].index && o3 !== e2[0].index), obstacles: this.input.obstacles, bounds: this.input.bounds, layerCount: this.input.layerCount, minTraceToPadEdgeClearance: this.input.minTraceToPadEdgeClearance }, I2 = ((t48) => {
const { minimumCenterlineDistance: e3, maximumCenterlineDistance: n3 } = t48;
if (e3 === undefined && n3 === undefined)
return t48.legacyCenterlineDistances;
const o3 = [...e3 !== undefined && n3 !== undefined ? [(e3 + n3) / 2, e3, n3, e3 - 0.25, n3 + 0.25] : e3 !== undefined ? [e3, e3 + 0.25, e3 + 0.5, e3 - 0.25, e3 + 1] : [n3, n3 - 0.25, n3 - 0.5, n3 + 0.25, n3 - 1], ...t48.legacyCenterlineDistances];
return o3.filter((e4, n4) => e4 > t48.minimumPhysicalDistance && o3.findIndex((t49) => Math.abs(t49 - e4) < 0.00000001) === n4);
})({ minimumCenterlineDistance: this.input.pair.minimumCenterlineDistance, maximumCenterlineDistance: this.input.pair.maximumCenterlineDistance, minimumPhysicalDistance: n2.width / 2 + o2.width / 2, legacyCenterlineDistances: N1.map((t48) => t48 + n2.width / 2 + o2.width / 2) }).flatMap((t48) => {
const e3 = t48 - n2.width / 2 - o2.width / 2;
return [f2, f2 === 1 ? -1 : 1].flatMap((s3) => {
const a3 = P1({ config: this.input.routingGrid, bounds: this.input.bounds, defaultInnerGridStep: Math.max(0.25, Math.min(0.5, t48 / 2)) }), u3 = (e4, a4) => x1({ ...v2, start: e4, end: a4, firstConnectionName: n2.source.connection_name, secondConnectionName: o2.source.connection_name, firstStartTerminal: i2, firstEndTerminal: r2, secondStartTerminal: c2, secondEndTerminal: l2, firstWidth: n2.width, secondWidth: o2.width, firstViaDiameter: n2.transitions[0]?.via_diameter ?? n2.viaDiameter, secondViaDiameter: o2.transitions[0]?.via_diameter ?? o2.viaDiameter, centerlineSpacing: t48, side: s3, terminalFanout: _2, terminalMiterMargin: this.input.pair.maxUncoupledLength === undefined ? undefined : t48 / 2 });
let m3 = this.input.pair.maxUncoupledLength === undefined ? ((t49, e4) => {
if (!x2 || _2)
return h2;
const n3 = [{ terminal: i2, offset: e4 * t49 / 2 }, { terminal: c2, offset: -e4 * t49 / 2 }], o3 = Math.tan(55 * Math.PI / 180), r3 = Math.max(...n3.map(({ terminal: t50, offset: e5 }) => {
const n4 = (t50.x - h2.x) * b2.x + (t50.y - h2.y) * b2.y, i3 = (t50.x - h2.x) * p2.x + (t50.y - h2.y) * p2.y;
return n4 + Math.abs(i3 - e5) / o3;
}));
return { x: h2.x + b2.x * r3, y: h2.y + b2.y * r3, layer: h2.layer };
})(t48, s3) : h2, g3 = d2;
if (!_2 && this.input.pair.maxUncoupledLength !== undefined) {
const e4 = u3(h2, d2), n3 = M1({ anchor: h2, escapeDirection: b2, pathDirection: b2, centerlineSpacing: t48, side: s3, lanes: [{ point: i2, polarity: 1 }, { point: c2, polarity: -1 }], maxUncoupledLength: this.input.pair.maxUncoupledLength, maximumTurnDegrees: 55, searchStep: a3.innerGridStep, isValid: (t49) => e4.isTerminalFanoutValid(t49, b2, "start") }), o3 = M1({ anchor: d2, escapeDirection: { x: -b2.x, y: -b2.y }, pathDirection: b2, centerlineSpacing: t48, side: s3, lanes: [{ point: r2, polarity: 1 }, { point: l2, polarity: -1 }], maxUncoupledLength: this.input.pair.maxUncoupledLength, maximumTurnDegrees: 45, searchStep: a3.innerGridStep, isValid: (t49) => e4.isTerminalFanoutValid(t49, b2, "end") });
if (!n3 || !o3)
return [];
m3 = n3, g3 = o3;
if ((g3.x - m3.x) * b2.x + (g3.y - m3.y) * b2.y <= a3.innerGridStep)
return [];
}
const f3 = u3(m3, g3);
return [{ edgeGap: e3, side: s3, input: { start: m3, end: g3, bounds: this.input.bounds, layerCount: this.input.layerCount, grid: a3, ...f3 } }];
});
});
return { first: n2, second: o2, reverseSecond: a2, terminalFanout: _2, context: v2, attempts: I2 };
}
complete() {
if (this.candidates.length === 0)
throw new m1({ connectionNames: this.input.pair.connectionNames, reason: "no-valid-candidate", message: "could not be improved without violating bounds, copper clearance, or coupled-via constraints" });
this.candidates.sort((t47, e2) => this.score(t47) - this.score(e2) || t47.edgeGap - e2.edgeGap), this.result = { status: "accepted", candidate: this.candidates[0] };
}
score(t47) {
return (this.input.pair.minimumCenterlineDistance !== undefined || this.input.pair.maximumCenterlineDistance !== undefined ? Math.max(0, (this.input.pair.minimumCenterlineDistance ?? Number.NEGATIVE_INFINITY) - t47.centerlineDistance) * w1 + Math.max(0, t47.centerlineDistance - (this.input.pair.maximumCenterlineDistance ?? Number.POSITIVE_INFINITY)) * w1 : t47.edgeGap < 0.5 ? (0.5 - t47.edgeGap) * w1 : t47.edgeGap > 1 ? (t47.edgeGap - 1) * w1 : 0) + h1(t47.firstParsed) + h1(t47.secondParsed) + 0.15 * t47.bendCount + 8 * t47.viaPairCount;
}
};
var R1 = (t47) => {
const e2 = { lines: [], points: [], rects: [], circles: [] };
e2.rects.push({ center: { x: (t47.bounds.minX + t47.bounds.maxX) / 2, y: (t47.bounds.minY + t47.bounds.maxY) / 2 }, width: t47.bounds.maxX - t47.bounds.minX, height: t47.bounds.maxY - t47.bounds.minY, fill: "rgba(30, 70, 120, 0.04)", stroke: "rgba(30, 70, 120, 0.55)", layer: `z${Array.from({ length: t47.layerCount }, (t48, e3) => e3).join(",")}` });
for (const n2 of t47.obstacles) {
const o2 = B0(n2, t47.layerCount);
e2.rects.push({ center: n2.center, width: n2.width, height: n2.height, ccwRotationDegrees: n2.ccwRotationDegrees, fill: "rgba(220, 60, 60, 0.16)", stroke: "rgba(190, 40, 40, 0.75)", layer: `z${o2.join(",")}` });
}
for (let n2 = 0;n2 < (t47.previewPath?.length ?? 0) - 1; n2++) {
const o2 = t47.previewPath[n2], i2 = t47.previewPath[n2 + 1];
if (o2.layer !== i2.layer)
continue;
const r2 = o1(o2.layer, t47.layerCount);
e2.lines.push({ points: [o2, i2], strokeColor: "#16a34a", strokeWidth: 0.08, strokeDash: [0.18, 0.12], layer: `z${r2}` });
}
for (const n2 of t47.traces) {
if (t47.activeConnectionNames?.includes(n2.connection_name))
continue;
const o2 = "#2563eb";
let i2 = null;
for (const r2 of n2.route)
if (r2.route_type === "wire") {
if (i2 && i2.layer === r2.layer) {
const n3 = o1(r2.layer, t47.layerCount);
e2.lines.push({ points: [i2, r2], strokeColor: o2, strokeWidth: Math.max(i2.width, r2.width), ...n3 === 0 ? {} : { strokeDash: [0.2, 0.16] }, layer: `z${n3}` });
}
i2 = r2;
} else if (r2.route_type === "via") {
const n3 = r1(r2.from_layer, r2.to_layer, t47.layerCount).map((e3) => o1(e3, t47.layerCount));
if (e2.circles.push({ center: r2, radius: (r2.via_diameter ?? i2?.width ?? 0.2) / 2, fill: "rgba(37, 99, 235, 0.45)", stroke: o2, layer: `z${n3.join(",")}` }), i2) {
const t48 = i2.width;
i2 = { x: r2.x, y: r2.y, layer: r2.to_layer, width: t48 };
}
}
}
return e2;
};
var E1 = class extends kt {
constructor(t47) {
super(), this.params = t47, this.outputTraces = _1(t47.simpleRouteJson.traces), this.MAX_ITERATIONS = y1(t47);
}
outputTraces;
reroutedPairs = [];
failures = [];
nextPairIndex = 0;
activeConnectionNames = null;
activeSession = null;
getSolverName() {
return "DifferentialPairReroutingSolver";
}
_step() {
const t47 = this.params.simpleRouteJson.differentialPairs[this.nextPairIndex];
if (!t47)
return void this.finish();
this.activeConnectionNames = t47.connectionNames;
try {
if (!this.activeSession)
return this.activeSession = new T1({ pair: t47, traces: this.outputTraces, obstacles: this.params.simpleRouteJson.obstacles, bounds: this.params.simpleRouteJson.bounds, layerCount: this.params.simpleRouteJson.layerCount, minTraceToPadEdgeClearance: this.params.simpleRouteJson.minTraceToPadEdgeClearance, routingGrid: this.params.routingGrid }), void (this.stats = this.activeSession.getStats());
this.activeSession.step();
} catch (e3) {
if (!(e3 instanceof m1))
throw e3;
return void this.skipFailedPair(t47, e3);
}
if (this.stats = this.activeSession.getStats(), !this.activeSession.isComplete())
return;
const e2 = this.activeSession.getResult();
this.activeSession = null;
for (const t48 of [e2.candidate.first, e2.candidate.second]) {
const e3 = this.outputTraces.findIndex((e4) => e4.connection_name === t48.connection_name);
if (e3 < 0)
throw new Error(`DifferentialPairReroutingSolver: accepted replacement for unknown connection "${t48.connection_name}"`);
this.outputTraces[e3] = t48;
}
this.reroutedPairs.push(t47), this.nextPairIndex++, this.nextPairIndex !== this.params.simpleRouteJson.differentialPairs.length ? this.stats = { phase: "accepted", pair: t47.connectionNames.join("/"), pairIndex: this.nextPairIndex - 1, pairCount: this.params.simpleRouteJson.differentialPairs.length } : this.finish();
}
finish() {
this.activeConnectionNames = null, this.solved = true, this.stats = { phase: "complete", acceptedPairCount: this.reroutedPairs.length, skippedPairCount: this.failures.length };
}
skipFailedPair(t47, e2) {
this.failures.push({ connectionNames: [...t47.connectionNames], reason: e2.reason, message: e2.message }), this.activeSession = null, this.nextPairIndex++, this.nextPairIndex !== this.params.simpleRouteJson.differentialPairs.length ? this.stats = { phase: "skipped", pair: t47.connectionNames.join("/"), pairIndex: this.nextPairIndex - 1, pairCount: this.params.simpleRouteJson.differentialPairs.length, skippedPairCount: this.failures.length } : this.finish();
}
getConstructorParams() {
return [this.params];
}
getOutput() {
if (!this.solved)
throw new Error("DifferentialPairReroutingSolver: getOutput() called before completion");
return this.getBestEffortOutput();
}
getBestEffortOutput() {
return { traces: _1(this.outputTraces), reroutedPairs: this.reroutedPairs.map((t47) => ({ ...t47, connectionNames: [...t47.connectionNames] })), failures: this.failures.map((t47) => ({ ...t47, connectionNames: [...t47.connectionNames] })) };
}
computeProgress() {
return this.solved ? 1 : this.params.simpleRouteJson.differentialPairs.length === 0 ? 0 : (this.nextPairIndex + (this.activeSession?.getProgress() ?? 0)) / this.params.simpleRouteJson.differentialPairs.length;
}
visualize() {
return R1({ traces: this.outputTraces, obstacles: this.params.simpleRouteJson.obstacles, bounds: this.params.simpleRouteJson.bounds, layerCount: this.params.simpleRouteJson.layerCount, activeConnectionNames: this.activeConnectionNames, previewPath: this.activeSession?.getPreviewPath() ?? null });
}
};
var A1 = 0.00000001;
var O1 = class extends kt {
constructor(t47) {
super(), this.input = t47, this.traces = _1(t47.traces), this.MAX_ITERATIONS = Math.max(1, t47.reroutedPairs.length + 1);
}
traces;
nextPairIndex = 0;
getSolverName() {
return "FortyFiveDegreeSimplificationSolver";
}
_step() {
const t47 = this.input.reroutedPairs[this.nextPairIndex];
if (!t47)
return this.solved = true, void (this.stats = { phase: "complete", simplifiedPairCount: this.nextPairIndex });
this.traces = ((t48) => {
const e2 = t48.pair.connectionNames.join("/"), n2 = t48.pair.connectionNames.map((e3) => t48.traces.map((t49, e4) => ({ trace: t49, index: e4 })).filter(({ trace: t49 }) => t49.connection_name === e3));
if (n2[0].length !== 1 || n2[1].length !== 1)
throw new Error(`FortyFiveDegreeSimplificationSolver: pair ${e2} must resolve to exactly two traces`);
const o2 = n2[0][0].index, i2 = n2[1][0].index;
if (o2 === i2)
throw new Error(`FortyFiveDegreeSimplificationSolver: pair ${e2} resolved both members to one trace`);
const r2 = structuredClone(t48.traces), s2 = { immutableTraces: r2.filter((t49, e3) => e3 !== o2 && e3 !== i2), obstacles: t48.obstacles, bounds: t48.bounds, layerCount: t48.layerCount, minTraceToPadEdgeClearance: t48.minTraceToPadEdgeClearance }, a2 = (n3) => {
const r3 = a1(n3[o2], t48.layerCount), s3 = a1(n3[i2], t48.layerCount);
let a3 = 0;
for (const [t49, n4] of [[r3.segments, s3.segments], [s3.segments, r3.segments]])
for (const o3 of t49) {
if (o3.terminal !== null)
continue;
const t50 = n4.filter((t51) => t51.layer === o3.layer);
if (t50.length === 0)
throw new Error(`FortyFiveDegreeSimplificationSolver: pair ${e2} lost common-layer interior copper`);
a3 = Math.max(a3, Math.min(...t50.map((t51) => k0(o3.start, o3.end, t51.start, t51.end))));
}
return a3;
}, c2 = (e3) => {
const n3 = a1(e3[o2], t48.layerCount), r3 = a1(e3[i2], t48.layerCount);
let s3 = Number.POSITIVE_INFINITY;
for (const [t49, e4] of [[n3.segments, r3.segments], [r3.segments, n3.segments]])
for (const n4 of t49)
if (n4.terminal === null)
for (const t50 of e4)
t50.layer === n4.layer && (s3 = Math.min(s3, k0(n4.start, n4.end, t50.start, t50.end) - n4.width / 2 - t50.width / 2));
return Number.isFinite(s3) ? s3 : null;
}, l2 = (e3) => {
const n3 = a1(e3[o2], t48.layerCount), r3 = a1(e3[i2], t48.layerCount);
return v1(n3, r3, s2);
};
if (!l2(r2))
throw new Error(`FortyFiveDegreeSimplificationSolver: rerouted pair ${e2} has invalid complete copper before simplification`);
if (t48.pair.maxUncoupledLength !== undefined && t48.pair.minimumCenterlineDistance !== undefined && t48.pair.maximumCenterlineDistance !== undefined && Math.abs(t48.pair.minimumCenterlineDistance - t48.pair.maximumCenterlineDistance) <= A1)
return r2;
const h2 = a1(r2[o2], t48.layerCount), d2 = a1(r2[i2], t48.layerCount), u2 = Math.abs(h1(h2) - h1(d2)), p2 = c2(r2), m2 = t48.pair.maximumCenterlineDistance ?? 1 + h2.width / 2 + d2.width / 2, g2 = Math.min(a2(r2), m2), f2 = (t49) => {
if (!l2(t49))
return false;
if (a2(t49) > g2 + A1)
return false;
const e3 = c2(t49);
return p2 === null || e3 === null || e3 >= p2 - A1;
}, y2 = (t49, e3) => {
const n3 = Math.abs(e3.x - t49.x), o3 = Math.abs(e3.y - t49.y), i3 = e3.x >= t49.x ? 1 : -1, r3 = e3.y >= t49.y ? 1 : -1, s3 = [], a3 = { x: e3.x - i3 * o3, y: t49.y };
(a3.x - t49.x) * i3 >= -1e-8 && (a3.x - e3.x) * i3 <= A1 && s3.push([t49, a3, e3]);
const c3 = { x: t49.x, y: e3.y - r3 * n3 };
(c3.y - t49.y) * r3 >= -1e-8 && (c3.y - e3.y) * r3 <= A1 && s3.push([t49, c3, e3]);
const l3 = { x: t49.x + i3 * Math.min(n3, o3), y: t49.y + r3 * Math.min(n3, o3) };
return s3.push([t49, l3, e3]), s3.map((t50, e4) => {
const n4 = t50.filter((e5, n5) => n5 === 0 || Math.hypot(e5.x - t50[n5 - 1].x, e5.y - t50[n5 - 1].y) > A1), o4 = n4.slice(0, -1).map((t51, e5) => {
const o5 = n4[e5 + 1], i4 = Math.abs(o5.x - t51.x), r4 = Math.abs(o5.y - t51.y);
return { length: Math.hypot(i4, r4), straight: i4 <= A1 || r4 <= A1 ? Math.hypot(i4, r4) : 0 };
});
return { points: n4, usableStraightLength: Math.max(0, ...o4.map((t51) => t51.straight)), bendCount: Math.max(0, n4.length - 2), priority: e4 };
}).filter((t50, e4, n4) => n4.findIndex((e5) => JSON.stringify(e5.points) === JSON.stringify(t50.points)) === e4).sort((t50, e4) => e4.usableStraightLength - t50.usableStraightLength || t50.bendCount - e4.bendCount || t50.priority - e4.priority);
}, _2 = (t49) => {
const e3 = [];
for (let n3 = 0;n3 < t49.route.length - 1; n3++) {
const o3 = t49.route[n3];
if (o3?.route_type === "wire")
for (let i3 = t49.route.length - 1;i3 >= n3 + 1; i3--) {
if (n3 === 0 || i3 === t49.route.length - 1)
continue;
const r3 = t49.route[i3];
r3?.route_type === "wire" && r3.layer === o3.layer && (t49.route.slice(n3 + 1, i3).some((t50) => t50.route_type !== "wire" || t50.layer !== o3.layer) || e3.push({ startIndex: n3, endIndex: i3, skippedPointCount: i3 - n3 - 1 }));
}
}
return e3.sort((t50, e4) => e4.skippedPointCount - t50.skippedPointCount || t50.startIndex - e4.startIndex || e4.endIndex - t50.endIndex);
}, b2 = (t49, e3, n3) => {
const o3 = t49.route[e3.startIndex], i3 = t49.route[e3.endIndex], r3 = Math.max(o3.width, i3.width), s3 = n3.points.slice(1, -1).map((t50) => ({ route_type: "wire", ...t50, width: r3, layer: o3.layer }));
return { ...t49, route: [...t49.route.slice(0, e3.startIndex + 1), ...s3, ...t49.route.slice(e3.endIndex)] };
};
for (const t49 of [o2, i2]) {
let e3 = true;
for (;e3; ) {
e3 = false;
const n3 = r2[t49];
for (const s3 of _2(n3)) {
const a3 = n3.route[s3.startIndex], c3 = n3.route[s3.endIndex], l3 = n3.route.slice(s3.startIndex, s3.endIndex + 1), h3 = l3.slice(0, -1).every((t50, e4) => {
const n4 = l3[e4 + 1], o3 = Math.abs(n4.x - t50.x), i3 = Math.abs(n4.y - t50.y);
return o3 <= A1 || i3 <= A1 || Math.abs(o3 - i3) <= A1;
});
for (const d3 of y2(a3, c3)) {
if (d3.points.length >= l3.length && h3)
continue;
const a4 = b2(n3, s3, d3), c4 = [...r2];
if (c4[t49] = a4, JSON.stringify(a4.route) === JSON.stringify(n3.route))
continue;
if (f2(c4)) {
r2[t49] = a4, e3 = true;
break;
}
const u3 = t49 === o2 ? i2 : o2, p3 = r2[u3], m3 = _2(p3).find((t50) => t50.startIndex === s3.startIndex && t50.endIndex === s3.endIndex);
if (!m3)
continue;
const g3 = p3.route[m3.startIndex], x3 = p3.route[m3.endIndex];
for (const n4 of y2(g3, x3)) {
const o3 = b2(p3, m3, n4), i3 = [...c4];
if (i3[u3] = o3, f2(i3)) {
r2[t49] = a4, r2[u3] = o3, e3 = true;
break;
}
}
if (e3)
break;
}
if (e3)
break;
}
}
}
if (!f2(r2))
throw new Error(`FortyFiveDegreeSimplificationSolver: pair ${e2} produced invalid complete copper`);
const x2 = a1(r2[o2], t48.layerCount), v2 = a1(r2[i2], t48.layerCount), I2 = Math.abs(h1(x2) - h1(v2));
return Math.abs(I2 - u2) > t48.pair.lengthTolerance + A1 ? structuredClone(t48.traces) : r2;
})({ traces: this.traces, pair: t47, obstacles: this.input.obstacles, bounds: this.input.bounds, layerCount: this.input.layerCount, minTraceToPadEdgeClearance: this.input.minTraceToPadEdgeClearance }), this.nextPairIndex++, this.stats = { phase: "simplifying", pair: t47.connectionNames.join("/"), pairIndex: this.nextPairIndex - 1, pairCount: this.input.reroutedPairs.length };
}
getConstructorParams() {
return [this.input];
}
getOutput() {
if (!this.solved)
throw new Error("FortyFiveDegreeSimplificationSolver: getOutput() called before completion");
return this.getBestEffortOutput();
}
getBestEffortOutput() {
return { traces: _1(this.traces), reroutedPairs: this.input.reroutedPairs.map((t47) => ({ ...t47, connectionNames: [...t47.connectionNames] })) };
}
computeProgress() {
return this.solved ? 1 : this.input.reroutedPairs.length === 0 ? 0 : this.nextPairIndex / this.input.reroutedPairs.length;
}
visualize() {
return R1({ traces: this.traces, obstacles: this.input.obstacles, bounds: this.input.bounds, layerCount: this.input.layerCount, activeConnectionNames: this.input.reroutedPairs[this.nextPairIndex]?.connectionNames ?? null, previewPath: null });
}
};
var k1 = (t47, e2) => Math.abs(t47 - e2) <= 0.0000001;
var D1 = (t47, e2) => k1(t47.x, e2.x) && k1(t47.y, e2.y);
var L1 = (t47) => {
const e2 = t47.candidatePair.map((e3, n2) => {
const o2 = t47.originalPair[n2];
return { ...e3, segments: e3.segments.filter((t48) => !o2.segments.some((e4) => {
return o3 = t48, (n3 = e4).layer === o3.layer && !!k1(n3.width, o3.width) && !!D1(n3.start, o3.start) && !!D1(n3.end, o3.end);
var n3, o3;
})), vias: e3.vias.filter((t48) => !o2.vias.some((e4) => {
return !!D1(n3 = e4, o3 = t48) && !!k1(n3.diameter, o3.diameter) && n3.layers.length === o3.layers.length && !!n3.layers.every((t49) => o3.layers.includes(t49));
var n3, o3;
})) };
});
return [e2[0], e2[1]];
};
var z1 = class extends kt {
constructor(t47) {
super(), this.input = t47;
}
output = null;
visualizationTraces = null;
getSolverName() {
return "HdRouteReconstructionSolver";
}
_step() {
this.visualizationTraces = ((t47) => {
const { simpleRouteJson: e2 } = t47.params;
if (t47.result.matchedHdRoutes.length !== t47.binding.solverParams.hdRoutes.length)
throw new Error("PostProcessingSolver: LengthMatchingSolver changed the search route count");
const n2 = structuredClone(t47.binding.baseTraces);
for (const o2 of t47.binding.traceBindings) {
const i2 = t47.result.matchedHdRoutes[o2.matchedRouteIndex];
if (!i2)
throw new Error(`PostProcessingSolver: missing matched route at index ${o2.matchedRouteIndex}`);
const r2 = n2[o2.traceIndex];
if (!r2)
throw new Error(`PostProcessingSolver: missing simplified trace binding at index ${o2.traceIndex}`);
if (r2.connection_name !== i2.connectionName)
throw new Error(`PostProcessingSolver: route binding changed connection "${r2.connection_name}" to "${i2.connectionName}"`);
if (i2.route.length < 2)
throw new Error(`PostProcessingSolver: matched connection "${i2.connectionName}" has incomplete geometry`);
const s2 = i2.route[0], a2 = i2.route.at(-1);
if (Math.hypot(s2.x - o2.startEndpoint.x, s2.y - o2.startEndpoint.y) > 0.00000001 || s2.z !== o2.startEndpoint.z || Math.hypot(a2.x - o2.endEndpoint.x, a2.y - o2.endEndpoint.y) > 0.00000001 || a2.z !== o2.endEndpoint.z)
throw new Error(`PostProcessingSolver: matched connection "${i2.connectionName}" moved a preserved endpoint`);
const c2 = [];
let l2 = 0;
const h2 = (t48) => ({ route_type: "wire", x: t48.x, y: t48.y, width: t48.traceThickness ?? i2.traceThickness, layer: i1(t48.z, e2.layerCount) });
c2.push(h2(i2.route[0]));
for (let t48 = 1;t48 < i2.route.length; t48++) {
const n3 = i2.route[t48 - 1], r3 = i2.route[t48];
if (n3.z === r3.z) {
c2.push(h2(r3));
continue;
}
if (Math.hypot(n3.x - r3.x, n3.y - r3.y) > 0.00000001)
throw new Error(`PostProcessingSolver: matched connection "${i2.connectionName}" moves while changing layers`);
const s3 = o2.viaTemplates[l2++];
if (!s3)
throw new Error(`PostProcessingSolver: matched connection "${i2.connectionName}" added an unbound via`);
if (Math.hypot(s3.x - r3.x, s3.y - r3.y) > 0.00000001)
throw new Error(`PostProcessingSolver: matched connection "${i2.connectionName}" moved a preserved via`);
const a3 = i1(n3.z, e2.layerCount), d3 = i1(r3.z, e2.layerCount), u2 = new Set([s3.from_layer, s3.to_layer]);
if (!u2.has(a3) || !u2.has(d3))
throw new Error(`PostProcessingSolver: matched connection "${i2.connectionName}" changed a preserved via span`);
c2.push({ ...s3 }), c2.push(h2(r3));
}
if (l2 !== o2.viaTemplates.length)
throw new Error(`PostProcessingSolver: matched connection "${i2.connectionName}" removed a preserved via`);
const d2 = c2.filter((t48) => t48.route_type === "wire");
for (const t48 of d2)
delete t48.start_pcb_port_id, delete t48.end_pcb_port_id;
o2.startPortId && (d2[0].start_pcb_port_id = o2.startPortId), o2.endPortId && (d2.at(-1).end_pcb_port_id = o2.endPortId), n2[o2.traceIndex] = { ...r2, route: c2 };
}
for (const o2 of t47.binding.solverParams.differentialPairs) {
const i2 = o2.connectionNames.join("/"), r2 = o2.connectionNames.map((t48) => n2.map((t49, e3) => ({ trace: t49, index: e3 })).filter(({ trace: e3 }) => e3.connection_name === t48));
if (r2[0].length !== 1 || r2[1].length !== 1)
throw new Error(`PostProcessingSolver: reconstructed pair ${i2} does not resolve to complete copper`);
const s2 = r2[0][0], a2 = r2[1][0], c2 = o2.connectionNames.map((e3) => {
const n3 = t47.binding.baseTraces.filter((t48) => t48.connection_name === e3);
if (n3.length !== 1)
throw new Error(`PostProcessingSolver: original pair ${i2} does not resolve to complete copper`);
return n3[0];
}), l2 = a1(s2.trace, e2.layerCount), h2 = a1(a2.trace, e2.layerCount), d2 = a1(c2[0], e2.layerCount), u2 = a1(c2[1], e2.layerCount), p2 = Math.abs(h1(l2) - h1(h2));
if (p2 > o2.lengthTolerance + 0.0000001)
throw new g1({ message: `PostProcessingSolver: reconstructed pair ${i2} exceeds length tolerance ${o2.lengthTolerance} with error ${p2}`, connectionNames: [...o2.connectionNames], reason: "length-tolerance-unsatisfied" });
const m2 = { immutableTraces: n2.filter((t48, e3) => e3 !== s2.index && e3 !== a2.index), obstacles: e2.obstacles, bounds: e2.bounds, layerCount: e2.layerCount, minTraceToPadEdgeClearance: e2.minTraceToPadEdgeClearance }, g2 = v1(l2, h2, { ...m2, obstacles: [] }), f2 = L1({ candidatePair: [l2, h2], originalPair: [d2, u2] }), y2 = v1(f2[0], f2[1], { ...m2, immutableTraces: [] });
if (!g2 || !y2)
throw new g1({ message: `PostProcessingSolver: length matching produced invalid complete copper for pair ${i2}`, connectionNames: [...o2.connectionNames], reason: "invalid-final-copper" });
}
return n2;
})(this.input), this.output = p1({ ...this.input, rejectInsideJumperPad: true }), this.stats = { phase: "complete", routeCount: this.output.hdRoutes.length }, this.solved = true;
}
getConstructorParams() {
return [this.input];
}
getOutput() {
if (!this.output || !this.solved)
throw new Error("HdRouteReconstructionSolver: getOutput() called before completion");
return structuredClone(this.output);
}
visualize() {
const t47 = this.visualizationTraces ?? this.input.simplified.traces, { obstacles: e2, bounds: n2, layerCount: o2 } = this.input.params.simpleRouteJson;
return R1({ traces: t47, obstacles: e2, bounds: n2, layerCount: o2, activeConnectionNames: null, previewPath: null });
}
};
var B1 = class extends Lt {
differentialPairReroutingSolver;
fortyFiveDegreeSimplificationSolver;
lengthMatchingSolver;
hdRouteReconstructionSolver;
lengthMatchingBinding = null;
model;
fallbackOutput = null;
postProcessingErrors = [];
pipelineDef = [Dt("differentialPairReroutingSolver", E1, (t47) => [t47.model.params]), Dt("fortyFiveDegreeSimplificationSolver", O1, (t47) => {
const e2 = t47.getStageOutput("differentialPairReroutingSolver");
if (!e2)
throw new Error("PostProcessingSolver: rerouting stage completed without output");
const { obstacles: n2, bounds: o2, layerCount: i2, minTraceToPadEdgeClearance: r2 } = t47.model.params.simpleRouteJson;
return [{ ...e2, obstacles: n2, bounds: o2, layerCount: i2, minTraceToPadEdgeClearance: r2 }];
}), Dt("lengthMatchingSolver", n1, (t47) => {
const e2 = t47.getStageOutput("fortyFiveDegreeSimplificationSolver");
if (!e2)
throw new Error("PostProcessingSolver: 45-degree simplification stage completed without output");
return t47.lengthMatchingBinding = d1({ result: e2, params: t47.model.params }), [t47.lengthMatchingBinding.solverParams];
}), Dt("hdRouteReconstructionSolver", z1, (t47) => {
const e2 = t47.getStageOutput("fortyFiveDegreeSimplificationSolver"), n2 = t47.getStageOutput("lengthMatchingSolver");
if (!e2 || !n2 || !t47.lengthMatchingBinding)
throw new Error("PostProcessingSolver: reconstruction stage is missing a required binding or output");
return [{ binding: t47.lengthMatchingBinding, result: n2, simplified: e2, params: t47.model.params, model: t47.model }];
}, { onSolved: (t47) => {
const e2 = t47.getStageOutput("differentialPairReroutingSolver");
if (!e2)
throw new Error("PostProcessingSolver: cannot summarize missing rerouting output");
t47.stats = { phase: "complete", acceptedPairCount: e2.reroutedPairs.length }, e2.failures.length > 0 && (t47.stats.skippedPairCount = e2.failures.length, t47.stats.postProcessingErrorCount = e2.failures.length);
} })];
constructor(t47) {
super(structuredClone(t47));
let e2 = null;
try {
(function(t48) {
if (!t48 || typeof t48 != "object")
throw new Error("PostProcessingSolver: params must be an object");
if (!Array.isArray(t48.hdRoutes))
throw new Error("PostProcessingSolver: hdRoutes must be an array");
if (!Array.isArray(t48.differentialPairs))
throw new Error("PostProcessingSolver: differentialPairs must be an array");
if (!Array.isArray(t48.obstacles))
throw new Error("PostProcessingSolver: obstacles must be an array");
if (t48.minTraceToPadEdgeClearance !== undefined && (!Number.isFinite(t48.minTraceToPadEdgeClearance) || t48.minTraceToPadEdgeClearance < 0))
throw new Error("PostProcessingSolver: minTraceToPadEdgeClearance must be finite and nonnegative");
if (!Number.isInteger(t48.layerCount) || t48.layerCount < 1)
throw new Error("PostProcessingSolver: layerCount must be a positive integer");
for (const e4 of t48.obstacles) {
if (!e4 || typeof e4 != "object" || e4.type !== "rect" || !e4.center || !Number.isFinite(e4.center.x) || !Number.isFinite(e4.center.y) || !Number.isFinite(e4.width) || e4.width <= 0 || !Number.isFinite(e4.height) || e4.height <= 0 || !Array.isArray(e4.layers) || e4.layers.some((t49) => typeof t49 != "string") || !Array.isArray(e4.connectedTo) || e4.connectedTo.some((t49) => typeof t49 != "string" || t49.length === 0) || e4.ccwRotationDegrees !== undefined && !Number.isFinite(e4.ccwRotationDegrees))
throw new Error("PostProcessingSolver: obstacle declaration is invalid");
B0(e4, t48.layerCount);
}
const { minX: e3, maxX: n3, minY: o2, maxY: i2 } = t48.bounds ?? {};
if (![e3, n3, o2, i2].every(Number.isFinite) || e3 >= n3 || o2 >= i2)
throw new Error("PostProcessingSolver: bounds must have finite positive extents");
const r2 = new Set(t48.differentialPairs.flatMap((t49) => t49.connectionNames));
for (const e4 of t48.hdRoutes) {
if (!e4 || typeof e4 != "object" || typeof e4.connectionName != "string" || e4.connectionName.length === 0 || e4.rootConnectionName !== undefined && (typeof e4.rootConnectionName != "string" || e4.rootConnectionName.length === 0) || !Number.isFinite(e4.traceThickness) || e4.traceThickness <= 0 || !Number.isFinite(e4.viaDiameter) || e4.viaDiameter < 0 || e4.viaDiameter === 0 && r2.has(e4.connectionName) || !Array.isArray(e4.route) || !Array.isArray(e4.vias) || e4.jumpers !== undefined && !Array.isArray(e4.jumpers))
throw new Error("PostProcessingSolver: HD route declaration is invalid");
if (e4.startPcbPortId !== undefined && (typeof e4.startPcbPortId != "string" || e4.startPcbPortId.length === 0) || e4.endPcbPortId !== undefined && (typeof e4.endPcbPortId != "string" || e4.endPcbPortId.length === 0))
throw new Error(`PostProcessingSolver: HD route "${e4.connectionName}" has invalid terminal metadata`);
for (const n4 of e4.route)
if (!n4 || typeof n4 != "object" || !Number.isFinite(n4.x) || !Number.isFinite(n4.y) || !Number.isInteger(n4.z) || n4.z < 0 || n4.z >= t48.layerCount || n4.traceThickness !== undefined && (!Number.isFinite(n4.traceThickness) || n4.traceThickness <= 0))
throw new Error(`PostProcessingSolver: HD route "${e4.connectionName}" has an invalid route point`);
for (const n4 of e4.vias)
if (!n4 || typeof n4 != "object" || !Number.isFinite(n4.x) || !Number.isFinite(n4.y) || n4.zLayers !== undefined && (!Array.isArray(n4.zLayers) || n4.zLayers.some((e5) => !Number.isInteger(e5) || e5 < 0 || e5 >= t48.layerCount)))
throw new Error(`PostProcessingSolver: HD route "${e4.connectionName}" has an invalid via`);
if (e4.vias.length > 0 && e4.viaDiameter <= 0)
throw new Error(`PostProcessingSolver: HD route "${e4.connectionName}" has a non-positive via diameter`);
for (const t49 of e4.jumpers ?? [])
if (!(t49 && typeof t49 == "object" && t49.route_type === "jumper" && Number.isFinite(t49.start?.x) && Number.isFinite(t49.start?.y) && Number.isFinite(t49.end?.x) && Number.isFinite(t49.end?.y) && ["0603", "1206", "1206x4_pair"].includes(t49.footprint)))
throw new Error(`PostProcessingSolver: HD route "${e4.connectionName}" has an invalid jumper`);
}
const s2 = new Set;
for (const e4 of t48.differentialPairs) {
if (!e4 || typeof e4 != "object" || !Array.isArray(e4.connectionNames) || e4.connectionNames.length !== 2 || e4.connectionNames[0] === e4.connectionNames[1] || !e4.connectionNames.every((t49) => typeof t49 == "string" && t49.length > 0) || !Number.isFinite(e4.lengthTolerance) || e4.lengthTolerance < 0)
throw new Error("PostProcessingSolver: differential pair declaration is invalid");
for (const t49 of [e4.minimumCenterlineDistance, e4.maximumCenterlineDistance])
if (t49 !== undefined && (!Number.isFinite(t49) || t49 <= 0))
throw new Error("PostProcessingSolver: differential pair centerline distances must be positive finite numbers");
if (e4.maxUncoupledLength !== undefined && (!Number.isFinite(e4.maxUncoupledLength) || e4.maxUncoupledLength < 0))
throw new Error("PostProcessingSolver: differential pair maxUncoupledLength must be a non-negative finite number");
if (e4.minimumCenterlineDistance !== undefined && e4.maximumCenterlineDistance !== undefined && e4.minimumCenterlineDistance > e4.maximumCenterlineDistance)
throw new Error("PostProcessingSolver: differential pair minimumCenterlineDistance cannot exceed maximumCenterlineDistance");
for (const t49 of e4.connectionNames) {
if (s2.has(t49))
throw new Error(`PostProcessingSolver: connection "${t49}" belongs to multiple differential pairs`);
s2.add(t49);
}
}
for (const e4 of [0.25, 0.5])
P1({ config: t48.routingGrid, bounds: t48.bounds, defaultInnerGridStep: e4 });
})(t47);
} catch (t48) {
if (!(t48 instanceof f1))
throw t48;
e2 = t48;
}
if (this.model = u1(t47), e2)
return void this.finishWithBestEffortOutput({ stage: "differentialPairReroutingSolver", message: e2.message, reason: e2.reason });
const n2 = y1(this.model.params) + Math.max(1, t47.differentialPairs.length + 1) + 1e5 + 10;
if (!Number.isSafeInteger(n2))
throw new Error("PostProcessingSolver: derived pipeline iteration bound exceeds the safe integer range");
this.MAX_ITERATIONS = n2;
}
getSolverName() {
return "PostProcessingSolver";
}
getConstructorParams() {
return [structuredClone(this.inputProblem)];
}
_step() {
const t47 = this.getCurrentStageName();
try {
super._step();
} catch (e3) {
const n2 = this.classifyOptimizationFailure(e3, t47);
if (!n2)
throw e3;
return void this.finishWithBestEffortOutput(n2);
}
if (!this.failed)
return;
const e2 = this.classifyIterationFailure(this.error, t47);
if (!e2)
throw new Error(this.error ?? "PostProcessingSolver failed without an error message");
this.finishWithBestEffortOutput(e2);
}
tryFinalAcceptance() {
const t47 = this.getCurrentStageName();
t47 !== "differentialPairReroutingSolver" && t47 !== "lengthMatchingSolver" || this.finishWithBestEffortOutput({ stage: t47, message: "PostProcessingSolver reached its iteration limit", reason: "iteration-limit-exhausted" });
}
classifyOptimizationFailure(t47, e2) {
return e2 === "lengthMatchingSolver" && t47 instanceof Z0 ? { stage: e2, message: t47.message, connectionName: t47.connectionName, reason: t47.reason } : e2 === "hdRouteReconstructionSolver" && t47 instanceof g1 || e2 === "differentialPairReroutingSolver" && t47 instanceof m1 && t47.reason === "no-valid-candidate" ? { stage: e2, message: t47.message, connectionNames: [...t47.connectionNames], reason: t47.reason } : null;
}
classifyIterationFailure(t47, e2) {
return e2 !== "differentialPairReroutingSolver" && e2 !== "lengthMatchingSolver" ? null : t47 && t47.endsWith("ran out of iterations") ? { stage: e2, message: t47, reason: "iteration-limit-exhausted" } : null;
}
createBestEffortOutput(t47) {
let e2 = this.lengthMatchingBinding;
if (!e2) {
const t48 = this.getStageOutput("fortyFiveDegreeSimplificationSolver") ?? this.fortyFiveDegreeSimplificationSolver?.getBestEffortOutput(), n3 = this.getStageOutput("differentialPairReroutingSolver") ?? this.differentialPairReroutingSolver?.getBestEffortOutput(), o2 = t48 ?? n3;
o2 && (e2 = d1({ result: o2, params: this.model.params }));
}
if (!e2)
return { output: { hdRoutes: structuredClone(this.inputProblem.hdRoutes), postProcessingErrors: [] }, source: "input-hd-routes" };
let n2 = this.getStageOutput("lengthMatchingSolver");
return n2 || (n2 = this.lengthMatchingSolver?.getBestEffortOutput()), n2 && t47.reason !== "invalid-final-copper" || (n2 = { matchedHdRoutes: e2.solverParams.hdRoutes }), { output: p1({ binding: e2, result: n2, model: this.model }), source: "best-effort-hd-routes" };
}
finishWithBestEffortOutput(t47) {
const e2 = this.createBestEffortOutput(t47), n2 = { type: "post_processing_error", ...t47, returnedRouteSource: e2.source };
this.postProcessingErrors.push(n2), this.fallbackOutput = e2.output, this.activeSubSolver = null, this.error = null, this.failed = false, this.solved = true, this.progress = 1, this.stats = { phase: "complete", postProcessingErrorCount: this.postProcessingErrors.length };
}
getOutput() {
if (!this.solved)
throw new Error("PostProcessingSolver: getOutput() called before the solver completed");
const t47 = this.fallbackOutput ?? this.getStageOutput("hdRouteReconstructionSolver");
if (!t47)
throw new Error("PostProcessingSolver: completed pipeline is missing reconstruction output");
const e2 = this.getStageOutput("differentialPairReroutingSolver") ?? this.differentialPairReroutingSolver?.getBestEffortOutput(), n2 = e2?.failures ?? [];
let o2 = "input-hd-routes";
(e2?.reroutedPairs.length ?? 0) > 0 && (o2 = "best-effort-hd-routes");
const i2 = [...n2.map((t48) => ({ type: "post_processing_error", stage: "differentialPairReroutingSolver", message: t48.message, connectionNames: [...t48.connectionNames], reason: t48.reason, returnedRouteSource: o2 })), ...this.postProcessingErrors], r2 = structuredClone(t47);
return r2.postProcessingErrors = structuredClone(i2), r2;
}
initialVisualize() {
if (this.fallbackOutput)
return { lines: this.fallbackOutput.hdRoutes.map((t48) => ({ points: t48.route.map(({ x: t49, y: e3 }) => ({ x: t49, y: e3 })), strokeWidth: t48.traceThickness })) };
const { traces: t47, obstacles: e2, bounds: n2, layerCount: o2 } = this.model.params.simpleRouteJson;
return R1({ traces: structuredClone(t47), obstacles: e2, bounds: n2, layerCount: o2, activeConnectionNames: null, previewPath: null });
}
finalVisualize() {
if (this.fallbackOutput)
return this.initialVisualize();
const t47 = u1({ ...this.inputProblem, hdRoutes: this.getOutput().hdRoutes }), { traces: e2, obstacles: n2, bounds: o2, layerCount: i2 } = t47.params.simpleRouteJson;
return R1({ traces: e2, obstacles: n2, bounds: o2, layerCount: i2, activeConnectionNames: null, previewPath: null });
}
};
var F1 = class t47 {
static generators = new Map;
static register(e2) {
t47.generators.set(e2.componentKind, e2);
}
static create(e2) {
const n2 = e2.detectedComponent.componentKind, o2 = t47.generators.get(n2);
if (!o2)
throw new Error(`No topology generator registered for component kind "${n2}"`);
return new o2(e2);
}
};
var j1 = (t48) => [t48.obstacle.obstacleId ?? t48.obstacle.componentId ?? "obstacle", t48.start.x.toFixed(4), t48.start.y.toFixed(4), t48.end.x.toFixed(4), t48.end.y.toFixed(4), t48.expansionDirection.x, t48.expansionDirection.y].join(":");
var $1 = (t48) => {
let e2 = 0;
for (const n2 of t48)
e2 = 31 * e2 + n2.charCodeAt(0) >>> 0;
return e2;
};
var Y1 = (t48, e2) => `hsla(${$1(j1(t48)) % 360},72%,36%,${e2})`;
var X1 = (t48) => {
const e2 = t48.expansionDirection;
return e2.x < 0 ? "left" : e2.x > 0 ? "right" : e2.y < 0 ? "bottom" : "top";
};
var W1 = (t48) => ({ x: (t48.start.x + t48.end.x) / 2, y: (t48.start.y + t48.end.y) / 2 });
var V1 = (t48) => {
const e2 = /^bga-gapfill-(\d+)-/.exec(t48.capacityMeshNodeId);
return e2 ? Number.parseInt(e2[1], 10) : null;
};
var H1 = (t48, e2) => {
const n2 = W1(t48), o2 = W1(e2), i2 = n2.y - o2.y;
if (Math.abs(i2) > 0.000001)
return i2;
const r2 = n2.x - o2.x;
return Math.abs(r2) > 0.000001 ? r2 : j1(t48).localeCompare(j1(e2));
};
var G1 = (t48) => {
const e2 = [...t48].sort(H1), n2 = [];
let o2 = e2.shift();
for (;o2 && (n2.push(o2), e2.length !== 0); ) {
const t49 = W1(o2);
let n3 = 0, i2 = Number.POSITIVE_INFINITY;
for (let o3 = 0;o3 < e2.length; o3++) {
const r2 = e2[o3], s2 = W1(r2), a2 = (s2.x - t49.x) ** 2 + (s2.y - t49.y) ** 2;
a2 < i2 - 0.000000001 ? (i2 = a2, n3 = o3) : Math.abs(a2 - i2) <= 0.000000001 && H1(r2, e2[n3]) < 0 && (n3 = o3);
}
o2 = e2.splice(n3, 1)[0];
}
return n2;
};
var U1 = (t48, e2) => {
const n2 = j1(t48), o2 = e2.findIndex((t49) => j1(t49) === n2);
return o2 >= 0 ? `E${o2 + 1}` : `E${$1(n2).toString(36).slice(0, 4)}`;
};
var Z1 = (t48) => t48.flatMap((t49) => {
const e2 = We(t49);
return [{ obstacle: t49, start: { x: e2.minX, y: e2.minY }, end: { x: e2.minX, y: e2.maxY }, expansionDirection: { x: -1, y: 0 } }, { obstacle: t49, start: { x: e2.maxX, y: e2.minY }, end: { x: e2.maxX, y: e2.maxY }, expansionDirection: { x: 1, y: 0 } }, { obstacle: t49, start: { x: e2.minX, y: e2.minY }, end: { x: e2.maxX, y: e2.minY }, expansionDirection: { x: 0, y: -1 } }, { obstacle: t49, start: { x: e2.minX, y: e2.maxY }, end: { x: e2.maxX, y: e2.maxY }, expansionDirection: { x: 0, y: 1 } }];
});
var q1 = 0.001;
var J1 = 0.001;
var Q1 = class extends kt {
constructor(t48) {
super(), this.inputProblem = t48;
}
meshIndex;
allEdges = [];
queueEdges = [];
disconnectedEdges = [];
currentEdge = null;
lastSearchBounds = null;
lastCandidateMeshNodes = [];
lastMatchedMeshNode = null;
_setup() {
const t48 = Math.max(this.inputProblem.meshNodes.length, 1);
this.meshIndex = new Ft(t48);
for (const t49 of this.inputProblem.meshNodes) {
const e3 = We(t49);
this.meshIndex.add(e3.minX, e3.minY, e3.maxX, e3.maxY);
}
this.meshIndex.finish();
const e2 = Z1(this.inputProblem.unmarkedComponentObstacles);
this.queueEdges = e2, this.allEdges = G1(e2), this.currentEdge = null, this.lastSearchBounds = null, this.lastCandidateMeshNodes = [], this.lastMatchedMeshNode = null;
}
_step() {
const t48 = this.queueEdges.shift();
if (!t48)
return this.currentEdge = null, this.lastSearchBounds = null, this.lastCandidateMeshNodes = [], this.lastMatchedMeshNode = null, void (this.solved = true);
this.currentEdge = t48, this.lastMatchedMeshNode = null;
const e2 = Math.abs(t48.start.x - t48.end.x) <= q1, n2 = e2 ? { minX: t48.start.x - J1, maxX: t48.start.x + J1, minY: Math.min(t48.start.y, t48.end.y), maxY: Math.max(t48.start.y, t48.end.y) } : { minX: Math.min(t48.start.x, t48.end.x), maxX: Math.max(t48.start.x, t48.end.x), minY: t48.start.y - J1, maxY: t48.start.y + J1 };
this.lastSearchBounds = n2;
const o2 = this.meshIndex.search(n2.minX, n2.minY, n2.maxX, n2.maxY);
this.lastCandidateMeshNodes = o2.map((t49) => this.inputProblem.meshNodes[t49]);
let i2 = false;
for (const n3 of o2) {
const o3 = this.inputProblem.meshNodes[n3], r2 = We(o3);
if (e2) {
if (!(Math.min(r2.maxY, Math.max(t48.start.y, t48.end.y)) - Math.max(r2.minY, Math.min(t48.start.y, t48.end.y)) > q1))
continue;
if (t48.expansionDirection.x === -1 && Math.abs(r2.maxX - t48.start.x) <= q1) {
i2 = true, this.lastMatchedMeshNode = o3;
break;
}
if (t48.expansionDirection.x === 1 && Math.abs(r2.minX - t48.start.x) <= q1) {
i2 = true, this.lastMatchedMeshNode = o3;
break;
}
continue;
}
if (Math.min(r2.maxX, Math.max(t48.start.x, t48.end.x)) - Math.max(r2.minX, Math.min(t48.start.x, t48.end.x)) > q1) {
if (t48.expansionDirection.y === -1 && Math.abs(r2.maxY - t48.start.y) <= q1) {
i2 = true, this.lastMatchedMeshNode = o3;
break;
}
if (t48.expansionDirection.y === 1 && Math.abs(r2.minY - t48.start.y) <= q1) {
i2 = true, this.lastMatchedMeshNode = o3;
break;
}
}
}
i2 || this.disconnectedEdges.push(t48);
}
getOutput() {
return this.disconnectedEdges;
}
visualize() {
const t48 = this.disconnectedEdges, e2 = this.allEdges.length > 0 ? this.allEdges : [...t48, ...this.currentEdge ? [this.currentEdge] : []], n2 = this.currentEdge ? Y1(this.currentEdge, 0.88) : "rgba(40,40,40,0.4)", o2 = this.inputProblem.meshNodes.map((t49) => ({ ...AD(t49, { rectMargin: 0.01 }), fill: t49._containsObstacle ? "rgba(120,120,120,0.18)" : "rgba(120,120,120,0.08)", stroke: t49._containsObstacle ? "rgba(120,120,120,0.42)" : "rgba(120,120,120,0.24)" })), i2 = this.lastSearchBounds && this.currentEdge ? [{ center: (r2 = this.lastSearchBounds, { x: (r2.minX + r2.maxX) / 2, y: (r2.minY + r2.maxY) / 2 }), width: this.lastSearchBounds.maxX - this.lastSearchBounds.minX, height: this.lastSearchBounds.maxY - this.lastSearchBounds.minY, fill: Y1(this.currentEdge, 0.1), stroke: Y1(this.currentEdge, 0.36), label: [U1(this.currentEdge, e2), "search band"].join(" ") }] : [];
var r2;
const s2 = this.lastCandidateMeshNodes.map((t49) => ({ ...AD(t49, { rectMargin: 0.018 }), fill: t49 === this.lastMatchedMeshNode ? "rgba(0,180,90,0.24)" : this.currentEdge ? Y1(this.currentEdge, 0.16) : "rgba(80,120,160,0.16)", stroke: t49 === this.lastMatchedMeshNode ? "rgba(0,150,80,0.88)" : n2, label: [t49 === this.lastMatchedMeshNode ? "matched" : "candidate", t49.capacityMeshNodeId, `z:${t49.availableZ.join(",")}`].join(`
`) })), a2 = this.inputProblem.unmarkedComponentObstacles.map((t49) => ({ center: t49.center, width: t49.width, height: t49.height, fill: "rgba(160,160,160,0.10)", stroke: "rgba(160,160,160,0.40)", label: t49.obstacleId ?? t49.componentId ?? "obstacle" })), c2 = t48.map((t49) => ({ points: [t49.start, t49.end], strokeColor: Y1(t49, 0.14), strokeWidth: 0.01, strokeDash: "5 4", label: [U1(t49, e2), X1(t49), "disconnected"].join(" ") })), l2 = [], h2 = [];
if (this.currentEdge) {
const t49 = W1(this.currentEdge);
l2.push({ points: [this.currentEdge.start, this.currentEdge.end], strokeColor: Y1(this.currentEdge, 1), strokeWidth: 0.06, label: [U1(this.currentEdge, e2), X1(this.currentEdge), "checking"].join(" ") }, { points: [t49, { x: t49.x + 0.16 * this.currentEdge.expansionDirection.x, y: t49.y + 0.16 * this.currentEdge.expansionDirection.y }], strokeColor: Y1(this.currentEdge, 0.82), strokeWidth: 0.02, strokeDash: "3 3" }), h2.push({ ...t49, color: Y1(this.currentEdge, 1), label: U1(this.currentEdge, e2) });
}
return { rects: [...o2, ...i2, ...s2, ...a2], lines: [...c2, ...l2], points: h2 };
}
};
var K1 = 0.001;
var t210 = 0.001;
var e2 = 0.000001;
var n2 = class extends kt {
constructor(t48) {
super(), this.inputProblem = t48;
}
meshIndex;
meshBounds;
expandedNodes = [];
_setup() {
const t48 = Math.max(this.inputProblem.meshNodes.length, 1);
this.meshIndex = new Ft(t48);
let { POSITIVE_INFINITY: e3, NEGATIVE_INFINITY: n3, POSITIVE_INFINITY: o2, NEGATIVE_INFINITY: i2 } = Number;
for (const t49 of this.inputProblem.meshNodes) {
const r2 = We(t49);
this.meshIndex.add(r2.minX, r2.minY, r2.maxX, r2.maxY), e3 = Math.min(e3, r2.minX), n3 = Math.max(n3, r2.maxX), o2 = Math.min(o2, r2.minY), i2 = Math.max(i2, r2.maxY);
}
this.meshIndex.finish(), this.meshBounds = this.inputProblem.meshNodes.length ? { minX: e3, maxX: n3, minY: o2, maxY: i2 } : { minX: 0, maxX: 0, minY: 0, maxY: 0 };
}
getObstacleAvailableZ(t48) {
return t48.__zLayers ?? t48.layers.map((t49) => mo(t49, this.inputProblem.layerCount));
}
getSharedOverlapArea(t48, e3) {
if (!t48.availableZ.some((t49) => e3.availableZ.includes(t49)))
return 0;
const n3 = We(t48), o2 = We(e3), i2 = Math.min(n3.maxX, o2.maxX) - Math.max(n3.minX, o2.minX), r2 = Math.min(n3.maxY, o2.maxY) - Math.max(n3.minY, o2.minY);
return i2 <= e2 || r2 <= e2 ? 0 : i2 * r2;
}
getNodeObstacleOverlapArea(t48, e3) {
const n3 = this.getObstacleAvailableZ(e3);
if (!t48.availableZ.some((t49) => n3.includes(t49)))
return 0;
const o2 = We(t48), i2 = We(e3), r2 = Math.min(o2.maxX, i2.maxX) - Math.max(o2.minX, i2.minX), s2 = Math.min(o2.maxY, i2.maxY) - Math.max(o2.minY, i2.minY);
return r2 <= e2 || s2 <= e2 ? 0 : r2 * s2;
}
getClosestMeshNode(t48, e3) {
const n3 = Math.abs(t48.start.x - t48.end.x) <= K1, o2 = this.getObstacleAvailableZ(t48.obstacle), i2 = n3 ? t48.expansionDirection.x < 0 ? { minX: this.meshBounds.minX, maxX: t48.start.x, minY: Math.min(t48.start.y, t48.end.y) - t210, maxY: Math.max(t48.start.y, t48.end.y) + t210 } : { minX: t48.start.x, maxX: this.meshBounds.maxX, minY: Math.min(t48.start.y, t48.end.y) - t210, maxY: Math.max(t48.start.y, t48.end.y) + t210 } : t48.expansionDirection.y < 0 ? { minX: Math.min(t48.start.x, t48.end.x) - t210, maxX: Math.max(t48.start.x, t48.end.x) + t210, minY: this.meshBounds.minY, maxY: t48.start.y } : { minX: Math.min(t48.start.x, t48.end.x) - t210, maxX: Math.max(t48.start.x, t48.end.x) + t210, minY: t48.start.y, maxY: this.meshBounds.maxY }, r2 = this.meshIndex.search(i2.minX, i2.minY, i2.maxX, i2.maxY);
let s2 = null, a2 = Number.POSITIVE_INFINITY;
const c2 = [...r2.map((t49) => this.inputProblem.meshNodes[t49]), ...e3];
for (const e4 of c2) {
if (e4._containsObstacle)
continue;
if (!e4.availableZ.some((t49) => o2.includes(t49)))
continue;
const i3 = We(e4);
if ((n3 ? Math.min(Math.max(t48.start.y, t48.end.y), i3.maxY) - Math.max(Math.min(t48.start.y, t48.end.y), i3.minY) : Math.min(Math.max(t48.start.x, t48.end.x), i3.maxX) - Math.max(Math.min(t48.start.x, t48.end.x), i3.minX)) <= K1)
continue;
const r3 = n3 ? t48.expansionDirection.x < 0 ? t48.start.x - i3.maxX : i3.minX - t48.start.x : t48.expansionDirection.y < 0 ? t48.start.y - i3.maxY : i3.minY - t48.start.y;
r3 < K1 || (r3 >= a2 || (a2 = r3, s2 = e4));
}
return s2;
}
createExpandedNode(t48, e3, n3) {
const o2 = We(e3), i2 = this.getObstacleAvailableZ(t48.obstacle);
if (Math.abs(t48.start.x - t48.end.x) <= K1) {
const r3 = Math.max(Math.min(t48.start.y, t48.end.y), o2.minY), s3 = Math.min(Math.max(t48.start.y, t48.end.y), o2.maxY), a3 = t48.expansionDirection.x < 0 ? o2.maxX : t48.start.x, c3 = t48.expansionDirection.x < 0 ? t48.start.x : o2.minX;
return c3 - a3 <= K1 || s3 - r3 <= K1 ? null : { capacityMeshNodeId: `bga-gapfill-${n3}-${t48.obstacle.obstacleId ?? "no-obstacle"}-${e3.capacityMeshNodeId}`, center: { x: (a3 + c3) / 2, y: (r3 + s3) / 2 }, width: c3 - a3, height: s3 - r3, layer: `z${i2.join(",")}`, availableZ: i2 };
}
const r2 = Math.max(Math.min(t48.start.x, t48.end.x), o2.minX), s2 = Math.min(Math.max(t48.start.x, t48.end.x), o2.maxX), a2 = t48.expansionDirection.y < 0 ? o2.maxY : t48.start.y, c2 = t48.expansionDirection.y < 0 ? t48.start.y : o2.minY;
return s2 - r2 <= K1 || c2 - a2 <= K1 ? null : { capacityMeshNodeId: `bga-gapfill-${n3}-${t48.obstacle.obstacleId ?? "no-obstacle"}-${e3.capacityMeshNodeId}`, center: { x: (r2 + s2) / 2, y: (a2 + c2) / 2 }, width: s2 - r2, height: c2 - a2, layer: `z${i2.join(",")}`, availableZ: i2 };
}
overlapsExistingGeometry(t48, e3) {
for (const e4 of this.inputProblem.meshNodes)
if (this.getSharedOverlapArea(t48, e4) > 0)
return true;
for (const n3 of e3)
if (this.getSharedOverlapArea(t48, n3) > 0)
return true;
for (const e4 of this.inputProblem.edgesWithObstacle)
if (this.getNodeObstacleOverlapArea(t48, e4.obstacle) > 0)
return true;
return false;
}
_step() {
const t48 = [];
for (const [e3, n3] of this.inputProblem.edgesWithObstacle.entries()) {
const o2 = this.getClosestMeshNode(n3, t48);
if (!o2)
continue;
const i2 = this.createExpandedNode(n3, o2, e3);
i2 && (this.overlapsExistingGeometry(i2, t48) || t48.push(i2));
}
this.expandedNodes = t48, this.solved = true;
}
getOutput() {
return this.expandedNodes;
}
visualize() {
const t48 = this.inputProblem.edgesWithObstacle, e3 = G1(t48);
return { rects: [...this.inputProblem.meshNodes.map((t49) => ({ ...AD(t49, { rectMargin: 0.01 }), fill: t49._containsObstacle ? "rgba(255,0,0,0.16)" : "rgba(0,120,255,0.08)", stroke: t49._containsObstacle ? "rgba(255,0,0,0.35)" : "rgba(0,120,255,0.28)" })), ...this.expandedNodes.map((n3) => {
const o2 = V1(n3), i2 = o2 === null ? null : t48[o2] ?? null;
return { ...AD(n3, { rectMargin: 0.012, zOffset: 0.01 }), fill: i2 ? Y1(i2, 0.24) : "rgba(0,160,100,0.24)", stroke: i2 ? Y1(i2, 0.72) : "rgba(0,160,100,0.68)", label: [i2 ? U1(i2, e3) : "E?", "expanded", n3.capacityMeshNodeId, `z:${n3.availableZ.join(",")}`].join(`
`) };
})], lines: [...this.inputProblem.edgesWithObstacle.map((t49) => ({ points: [t49.start, t49.end], strokeColor: Y1(t49, 0.9), strokeWidth: 0.034, label: [U1(t49, e3), X1(t49)].join(" ") })), ...this.inputProblem.edgesWithObstacle.map((t49) => {
const e4 = W1(t49);
return { points: [e4, { x: e4.x + 0.16 * t49.expansionDirection.x, y: e4.y + 0.16 * t49.expansionDirection.y }], strokeColor: Y1(t49, 0.7), strokeWidth: 0.016, strokeDash: "3 3" };
})], points: this.inputProblem.edgesWithObstacle.map((t49) => ({ ...W1(t49), color: Y1(t49, 0.95), label: U1(t49, e3) })) };
}
};
var o2 = 0.001;
var i2 = class extends Lt {
constructor(t48) {
super(t48), this.inputProblem = t48;
}
detectEdgesNotConnectedToMesh;
expandUnconnectedEdgesToMesh;
pipelineDef = [Dt("detectEdgesNotConnectedToMesh", Q1, (t48) => [t48.inputProblem]), Dt("expandUnconnectedEdgesToMesh", n2, (t48) => [{ meshNodes: t48.inputProblem.meshNodes, edgesWithObstacle: t48.detectEdgesNotConnectedToMesh.getOutput(), layerCount: t48.inputProblem.layerCount }])];
getOutput() {
return [...this.inputProblem.meshNodes, ...this.expandUnconnectedEdgesToMesh.getOutput()];
}
getExpandedNodes() {
return this.expandUnconnectedEdgesToMesh.getOutput();
}
getObstacleLayer(t48) {
return `z${(t48.obstacle.__zLayers ?? t48.obstacle.layers.map((t49) => mo(t49, this.inputProblem.layerCount))).join(",")}`;
}
getObstacleRects() {
return this.inputProblem.unmarkedComponentObstacles.map((t48) => {
const e3 = t48.__zLayers ?? t48.layers.map((t49) => mo(t49, this.inputProblem.layerCount));
return { center: t48.center, width: t48.width, height: t48.height, fill: "rgba(150,150,150,0.08)", stroke: "rgba(90,90,90,0.42)", label: t48.obstacleId ?? t48.componentId ?? "bga obstacle", layer: `z${e3.join(",")}` };
});
}
getBaseMeshRects() {
return this.inputProblem.meshNodes.map((t48) => ({ ...AD(t48, { rectMargin: 0.025, zOffset: 0.01 }), fill: t48._containsObstacle ? "rgba(210,60,60,0.14)" : "rgba(80,120,160,0.08)", stroke: t48._containsObstacle ? "rgba(190,40,40,0.42)" : "rgba(80,120,160,0.28)", label: `mesh ${t48.capacityMeshNodeId}
z:${t48.availableZ.join(",")}` }));
}
initialVisualize() {
const t48 = Z1(this.inputProblem.unmarkedComponentObstacles), e3 = G1(t48), n3 = [...t48.map((t49) => ({ points: [t49.start, t49.end], strokeColor: Y1(t49, 0.72), strokeWidth: 0.018, strokeDash: "0.05 0.035", layer: this.getObstacleLayer(t49), label: [U1(t49, e3), X1(t49)].join(" ") })), ...t48.map((t49) => {
const e4 = W1(t49);
return { points: [e4, { x: e4.x + 0.18 * t49.expansionDirection.x, y: e4.y + 0.18 * t49.expansionDirection.y }], strokeColor: Y1(t49, 0.64), strokeWidth: 0.012, strokeDash: "0.035 0.025", layer: this.getObstacleLayer(t49) };
})];
return { title: "BGA GapFill: candidate obstacle edges", rects: [...this.getBaseMeshRects(), ...this.getObstacleRects()], lines: n3 };
}
finalVisualize() {
const t48 = this.getStageOutput("detectEdgesNotConnectedToMesh") ?? [], e3 = this.getStageOutput("expandUnconnectedEdgesToMesh") ?? [], n3 = G1(Z1(this.inputProblem.unmarkedComponentObstacles)), o3 = new Map;
for (const t49 of e3) {
const e4 = V1(t49);
e4 !== null && o3.set(e4, t49);
}
const i3 = e3.map((e4) => {
const o4 = V1(e4), i4 = o4 === null ? null : t48[o4] ?? null, r3 = i4 ? (({ expandedNode: t49, edge: e5, meshNodes: n4 }) => {
const o5 = We(t49), i5 = Math.abs(e5.start.x - e5.end.x) <= o2;
return n4.filter((n5) => {
if (n5._containsObstacle)
return false;
if (!t49.availableZ.some((t50) => n5.availableZ.includes(t50)))
return false;
const r4 = We(n5);
return i5 ? !(Math.min(o5.maxY, r4.maxY) - Math.max(o5.minY, r4.minY) <= o2) && (e5.expansionDirection.x < 0 ? Math.abs(r4.maxX - o5.minX) <= o2 : Math.abs(r4.minX - o5.maxX) <= o2) : !(Math.min(o5.maxX, r4.maxX) - Math.max(o5.minX, r4.minX) <= o2) && (e5.expansionDirection.y < 0 ? Math.abs(r4.maxY - o5.minY) <= o2 : Math.abs(r4.minY - o5.maxY) <= o2);
}).map((t50) => t50.capacityMeshNodeId);
})({ expandedNode: e4, edge: i4, meshNodes: this.inputProblem.meshNodes }) : [], s3 = i4 ? U1(i4, n3) : "E?", a3 = i4 === null ? "rgba(0,160,100,0.72)" : Y1(i4, 0.72);
return { ...AD(e4, { rectMargin: 0.012, zOffset: 0.01 }), fill: i4 === null ? "rgba(0,160,100,0.24)" : Y1(i4, 0.16), stroke: a3, label: [`${s3} gap fill`, r3.length > 0 ? `to ${r3.join(",")}` : "target mesh not adjacent", `z:${e4.availableZ.join(",")}`].join(`
`) };
}), r2 = t48.map((t49, e4) => {
const i4 = o3.get(e4);
return { points: [t49.start, t49.end], strokeColor: i4 ? Y1(t49, 0.68) : "rgba(80,80,80,0.14)", strokeWidth: i4 ? 0.026 : 0.008, ...i4 ? {} : { strokeDash: "5 4" }, layer: this.getObstacleLayer(t49), label: [[U1(t49, n3), X1(t49)].join(" "), i4 ? "filled" : "no fill created"].join(`
`) };
}), s2 = t48.flatMap((t49, e4) => {
const n4 = W1(t49), i4 = o3.get(e4);
return i4 ? [{ points: [n4, i4.center], strokeColor: Y1(t49, 0.42), strokeWidth: 0.012, strokeDash: "0.035 0.025", layer: this.getObstacleLayer(t49) }] : [];
}), a2 = t48.flatMap((t49, e4) => o3.has(e4) ? [{ ...W1(t49), color: Y1(t49, 0.82), label: U1(t49, n3), layer: this.getObstacleLayer(t49) }] : []);
return { title: "BGA GapFill: disconnected edges and created mesh", rects: [...this.getBaseMeshRects(), ...this.getObstacleRects(), ...i3], lines: [...r2, ...s2], points: a2 };
}
};
function r2(t48, e3) {
const n3 = [];
for (let o3 = 0;o3 < t48.length; o3++) {
const i3 = t48[o3];
n3.push(i3);
const r3 = t48[o3 + 1];
if (r3 === undefined)
continue;
const s2 = Math.round((r3 - i3) / e3);
if (!(s2 <= 1))
for (let t49 = 1;t49 < s2; t49++) {
const e4 = t49 / s2;
n3.push(Number((i3 + (r3 - i3) * e4).toFixed(6)));
}
}
return n3;
}
var s2 = 0.001;
function a2(t48) {
const e3 = [];
for (let n4 = 1;n4 < t48.length; n4++) {
const o4 = t48[n4] - t48[n4 - 1];
o4 > s2 && e3.push(o4);
}
if (e3.length === 0)
return null;
const n3 = Math.min(...e3), o3 = e3.filter((t49) => t49 <= 1.5 * n3).sort((t49, e4) => t49 - e4), i3 = Math.floor(o3.length / 2);
return o3.length % 2 == 0 ? (o3[i3 - 1] + o3[i3]) / 2 : o3[i3];
}
function c2(t48) {
return [...new Set(t48)].sort((t49, e3) => t49 - e3);
}
function l2(t48) {
return Number(t48.toFixed(6));
}
var h2 = class t48 {
static fromObstacles(e3) {
if (e3.length === 0)
return null;
const n3 = c2(e3.map((t49) => t49.center.x)), o3 = c2(e3.map((t49) => t49.center.y)), i3 = a2(n3), r3 = a2(o3);
return i3 === null || r3 === null ? null : new t48({ obstacles: e3, xCoordinates: r2(n3, i3), yCoordinates: r2(o3, r3), pitchX: i3, pitchY: r3 });
}
xCoordinates;
yCoordinates;
pitchX;
pitchY;
originX;
originY;
rowCount;
colCount;
padWidth;
padHeight;
slots = new Map;
constructor(t49) {
this.xCoordinates = t49.xCoordinates, this.yCoordinates = t49.yCoordinates, this.pitchX = t49.pitchX, this.pitchY = t49.pitchY, this.originX = this.xCoordinates[0], this.originY = this.yCoordinates[0], this.colCount = this.xCoordinates.length, this.rowCount = this.yCoordinates.length, this.padWidth = t49.obstacles[0].width, this.padHeight = t49.obstacles[0].height;
for (const e3 of t49.obstacles) {
const t50 = this.getSlotForObstacle(e3);
t50 && this.slots.set(this.getSlotKey(t50.row, t50.col), { ...t50, obstacle: e3 });
}
}
getSlotKey(t49, e3) {
return `${t49}:${e3}`;
}
getAxisIndex(t49, e3) {
let n3 = -1, o3 = Number.POSITIVE_INFINITY;
for (let i3 = 0;i3 < t49.length; i3++) {
const r3 = Math.abs(t49[i3] - e3);
r3 < o3 && (o3 = r3, n3 = i3);
}
return o3 <= s2 ? n3 : null;
}
getAxisCoordinate(t49, e3) {
return t49[e3];
}
hasPadAt(t49, e3) {
return this.slots.has(this.getSlotKey(t49, e3));
}
getSlotForObstacle(t49) {
const e3 = this.getAxisIndex(this.yCoordinates, t49.center.y), n3 = this.getAxisIndex(this.xCoordinates, t49.center.x);
return e3 === null || n3 === null || e3 < 0 || e3 >= this.rowCount || n3 < 0 || n3 >= this.colCount ? null : { row: e3, col: n3 };
}
getSlotCenter(t49, e3) {
return { x: this.getAxisCoordinate(this.xCoordinates, e3), y: this.getAxisCoordinate(this.yCoordinates, t49) };
}
getHorizontalGap(t49, e3) {
const n3 = this.getSlotCenter(t49, e3), o3 = this.getSlotCenter(t49, e3 + 1), i3 = Math.abs(o3.x - n3.x);
return { orientation: "horizontal", row: t49, col: e3, center: { x: l2((n3.x + o3.x) / 2), y: n3.y }, width: i3 - this.padWidth, height: this.padHeight, isBetweenTwoPads: this.hasPadAt(t49, e3) && this.hasPadAt(t49, e3 + 1) };
}
getVerticalGap(t49, e3) {
const n3 = this.getSlotCenter(t49, e3), o3 = this.getSlotCenter(t49 + 1, e3), i3 = Math.abs(o3.y - n3.y);
return { orientation: "vertical", row: t49, col: e3, center: { x: n3.x, y: l2((n3.y + o3.y) / 2) }, width: this.padWidth, height: i3 - this.padHeight, isBetweenTwoPads: this.hasPadAt(t49, e3) && this.hasPadAt(t49 + 1, e3) };
}
getDiagonalGap(t49, e3) {
const n3 = this.getSlotCenter(t49, e3), o3 = this.getSlotCenter(t49 + 1, e3 + 1), i3 = Math.abs(o3.x - n3.x), r3 = Math.abs(o3.y - n3.y);
return { orientation: "diagonal", row: t49, col: e3, center: { x: l2((n3.x + o3.x) / 2), y: l2((n3.y + o3.y) / 2) }, width: i3 - this.padWidth, height: r3 - this.padHeight, isBetweenTwoPads: this.hasPadAt(t49, e3) && this.hasPadAt(t49 + 1, e3 + 1) };
}
getDiagonalGaps() {
const t49 = [];
for (let e3 = 0;e3 < this.rowCount - 1; e3++)
for (let n3 = 0;n3 < this.colCount - 1; n3++)
t49.push(this.getDiagonalGap(e3, n3));
return t49.filter((t50) => t50.width > s2 && t50.height > s2);
}
getAxisGaps() {
const t49 = [];
for (let e3 = 0;e3 < this.rowCount; e3++)
for (let n3 = 0;n3 < this.colCount - 1; n3++)
t49.push(this.getHorizontalGap(e3, n3));
for (let e3 = 0;e3 < this.rowCount - 1; e3++)
for (let n3 = 0;n3 < this.colCount; n3++)
t49.push(this.getVerticalGap(e3, n3));
return t49.filter((t50) => t50.width > s2 && t50.height > s2);
}
getMissingSlots() {
const t49 = [];
for (let e3 = 0;e3 < this.rowCount; e3++)
for (let n3 = 0;n3 < this.colCount; n3++)
this.hasPadAt(e3, n3) || t49.push({ row: e3, col: n3, center: this.getSlotCenter(e3, n3), width: this.padWidth, height: this.padHeight });
return t49;
}
};
function d2(t49) {
if ([t49.point.pointId, t49.point.pcb_port_id].filter((t50) => typeof t50 == "string").some((e4) => t49.obstacle.connectedTo.includes(e4)))
return true;
if (t49.obstacle.connectedTo.length === 0)
return false;
if (Fe(t49.point, t49.obstacle) > 0.001)
return false;
const e3 = So(t49.point).map((e4) => mo(e4, t49.layerCount)), n3 = t49.obstacle.layers.map((e4) => mo(e4, t49.layerCount));
return e3.some((t50) => n3.includes(t50));
}
function u2(t49) {
return t49.obstacleId ?? [t49.componentId ?? "no-component", t49.center.x, t49.center.y, t49.width, t49.height, t49.layers.join(",")].join(":");
}
function p2({ componentId: t49, orientationKey: e3, row: n3, col: o3, center: i3, width: r3, height: s3 }) {
return ["cmn", e3, t49, n3, o3, i3.x, i3.y, r3, s3].join("_");
}
function m2(t49) {
const { componentId: e3, bgaGap: n3, freeLayers: o3, multiLayerThreshold: i3 } = t49, r3 = n3.width > i3 && n3.height > i3;
let s3 = "d";
n3.orientation === "horizontal" && (s3 = "h"), n3.orientation === "vertical" && (s3 = "v");
const a3 = p2({ componentId: e3, orientationKey: s3, row: n3.row, col: n3.col, center: n3.center, width: n3.width, height: n3.height });
return n3.orientation === "diagonal" && r3 || !n3.isBetweenTwoPads && r3 ? [{ center: n3.center, width: n3.width, height: n3.height, availableZ: [...o3], capacityMeshNodeId: `${a3}_all`, layer: "" }] : o3.map((t50) => ({ center: n3.center, width: n3.width, height: n3.height, availableZ: [t50], capacityMeshNodeId: `${a3}_${t50}`, layer: "" }));
}
function g2(t49) {
const { componentId: e3, obstacle: n3, freeLayers: o3, layerCount: i3 } = t49, r3 = n3.layers.map((t50) => mo(t50, i3)), s3 = o3.filter((t50) => !r3.includes(t50)), a3 = u2(n3);
return s3.map((t50) => ({ capacityMeshNodeId: `free-${e3}-${a3}-${t50}`, center: n3.center, width: n3.width, height: n3.height, layer: `z${t50}`, availableZ: [t50] }));
}
function f2(t49, e3, n3) {
const o3 = e3.layers.map((t50) => mo(t50, n3.layerCount)), i3 = u2(e3), r3 = function(t50) {
for (const e4 of t50.srj.connections)
for (const n4 of e4.pointsToConnect)
if (d2({ point: n4, obstacle: t50.obstacle, layerCount: t50.srj.layerCount }))
return e4.__rootConnectionNames?.[0] ?? e4.name;
}({ obstacle: e3, srj: n3 });
return { capacityMeshNodeId: `obstacle-${t49}-${i3}-${o3.join(",")}-${e3.center.x}-${e3.center.y}`, _containsObstacle: true, ...r3 ? { _containsTarget: true, _targetConnectionName: r3 } : {}, center: e3.center, width: e3.width, height: e3.height, layer: `z${o3.join(",")}`, availableZ: o3 };
}
var y2 = class extends kt {
constructor(t49) {
super(), this.inputProblem = t49;
}
componentObstacles = [];
meshNodes = [];
getConstructorParams() {
return [this.inputProblem];
}
_step() {
const { srj: t49, componentBounds: e3, componentId: n3, markedComponentObstacles: o3, unmarkedComponentObstacles: i3 } = this.inputProblem, r3 = t49.obstacles.filter((t50) => t50.isCopperPour === true).filter((t50) => Xe(We(t50), e3)).flatMap((e4) => e4.layers.map((e5) => mo(e5, t49.layerCount))), s3 = Array.from({ length: t49.layerCount }, (t50, e4) => e4).filter((t50) => !r3.includes(t50));
if (this.componentObstacles = o3, o3.length === 0 || s3.length === 0)
return void (this.solved = true);
const a3 = h2.fromObstacles(o3);
if (!a3)
return void (this.solved = true);
const c3 = a3.getAxisGaps(), l3 = a3.getDiagonalGaps(), h3 = a3.getMissingSlots(), d3 = 1.2 * (this.inputProblem.viaDiameter ?? Yo(t49).padDiameter);
this.meshNodes = [...c3.flatMap((t50) => m2({ componentId: n3, bgaGap: t50, freeLayers: s3, multiLayerThreshold: d3 })), ...l3.flatMap((t50) => m2({ componentId: n3, bgaGap: t50, freeLayers: s3, multiLayerThreshold: d3 })), ...h3.flatMap((t50) => function(t51) {
const { componentId: e4, missingBgaSlot: n4, freeLayers: o4, multiLayerThreshold: i4 } = t51, r4 = p2({ componentId: e4, orientationKey: "missing", row: n4.row, col: n4.col, center: n4.center, width: n4.width, height: n4.height });
return n4.width > i4 && n4.height > i4 ? [{ center: n4.center, width: n4.width, height: n4.height, availableZ: [...o4], capacityMeshNodeId: `${r4}_all`, layer: "" }] : o4.map((t52) => ({ center: n4.center, width: n4.width, height: n4.height, availableZ: [t52], capacityMeshNodeId: `${r4}_${t52}`, layer: "" }));
}({ componentId: n3, missingBgaSlot: t50, freeLayers: s3, multiLayerThreshold: d3 })), ...o3.flatMap((e4) => [...g2({ componentId: n3, obstacle: e4, freeLayers: s3, layerCount: t49.layerCount }), f2(n3, e4, t49)]), ...i3.flatMap((e4) => [f2(n3, e4, t49)])], this.meshNodes = function(t50) {
const e4 = new Map;
return t50.map((t51) => {
const n4 = e4.get(t51.capacityMeshNodeId) ?? 0;
return e4.set(t51.capacityMeshNodeId, n4 + 1), n4 === 0 ? t51 : { ...t51, capacityMeshNodeId: `${t51.capacityMeshNodeId}__dup${n4}` };
});
}(this.meshNodes), this.solved = true;
}
getOutput() {
return this.meshNodes;
}
visualize() {
return { rects: [{ center: { x: (this.inputProblem.componentBounds.minX + this.inputProblem.componentBounds.maxX) / 2, y: (this.inputProblem.componentBounds.minY + this.inputProblem.componentBounds.maxY) / 2 }, width: this.inputProblem.componentBounds.maxX - this.inputProblem.componentBounds.minX, height: this.inputProblem.componentBounds.maxY - this.inputProblem.componentBounds.minY, fill: "rgba(0,0,0,0)", stroke: "rgba(30,30,30,0.65)", label: `component ${this.inputProblem.componentId}` }, ...this.inputProblem.markedComponentObstacles.map((t49) => ({ center: t49.center, width: t49.width, height: t49.height, fill: "rgba(255,0,0,0.18)", stroke: "rgba(255,0,0,0.52)", label: `pad ${t49.obstacleId ?? "obstacle"}` })), ...this.inputProblem.unmarkedComponentObstacles.map((t49) => ({ center: t49.center, width: t49.width, height: t49.height, fill: "rgba(255,140,0,0.14)", stroke: "rgba(255,140,0,0.42)", label: `foreign ${t49.obstacleId ?? "obstacle"}` })), ...this.meshNodes.map((t49) => ({ ...AD(t49, { rectMargin: 0.01 }), fill: t49._containsObstacle ? "rgba(255,0,0,0.14)" : t49.capacityMeshNodeId.includes("missing") ? "rgba(0,200,120,0.18)" : "rgba(0,120,255,0.12)", stroke: t49._containsObstacle ? "rgba(255,0,0,0.36)" : t49.capacityMeshNodeId.includes("missing") ? "rgba(0,200,120,0.52)" : "rgba(0,120,255,0.38)" }))] };
}
};
function _2(t49) {
return t49.capacityMeshNodeId.startsWith("bga-gapfill-");
}
function b2(t49) {
return JSON.stringify({ availableZ: [...t49.availableZ].sort((t50, e3) => t50 - e3), _containsTarget: t49._containsTarget ?? false, _targetConnectionName: t49._targetConnectionName ?? null, _depth: t49._depth ?? null, _strawNode: t49._strawNode ?? false, _strawParentCapacityMeshNodeId: t49._strawParentCapacityMeshNodeId ?? null, _qfpRegionType: t49._qfpRegionType ?? null, _isNarrowQfpPadGap: t49._isNarrowQfpPadGap ?? false, _soicRegionType: t49._soicRegionType ?? null, _offBoardConnectionId: t49._offBoardConnectionId ?? null, _offboardNetName: t49._offboardNetName ?? null, _isVirtualOffboard: t49._isVirtualOffboard ?? false, _containsObstacle: t49._containsObstacle ?? false });
}
function x2(t49, e3) {
const n3 = We(t49);
for (const o3 of e3) {
if (!t49.availableZ.some((t50) => o3.availableZ.includes(t50)))
continue;
const e4 = We(o3);
if (Xe(n3, e4))
return true;
}
return false;
}
function v2(t49) {
const e3 = t49[0];
if (!e3)
throw new Error("createMergedNode requires at least one source node");
let { POSITIVE_INFINITY: n3, NEGATIVE_INFINITY: o3, POSITIVE_INFINITY: i3, NEGATIVE_INFINITY: r3 } = Number;
for (const e4 of t49) {
const t50 = We(e4);
n3 = Math.min(n3, t50.minX), o3 = Math.max(o3, t50.maxX), i3 = Math.min(i3, t50.minY), r3 = Math.max(r3, t50.maxY);
}
return { ...e3, capacityMeshNodeId: `merge:${t49.map((t50) => t50.capacityMeshNodeId).join(":")}`, center: { x: (n3 + o3) / 2, y: (i3 + r3) / 2 }, width: o3 - n3, height: r3 - i3 };
}
function I2(t49, e3, n3) {
return { center: t49.center, width: t49.width, height: t49.height, fill: e3, stroke: e3, label: n3 };
}
var S2 = class extends kt {
constructor(t49) {
super(), this.inputProblem = t49;
}
obstacleNodes = [];
passthroughNodes = [];
mergedNodes = [];
pendingGroups = [];
totalGroupCount = 0;
processedGroupCount = 0;
debugFilteredNodes = [];
debugMergeEvents = [];
currentGroupKey = null;
currentRootNodeId = null;
lastMergedNodeId = null;
_setup() {
this.obstacleNodes = this.inputProblem.meshNodes.filter((t50) => t50._containsObstacle === true), this.passthroughNodes = [], this.mergedNodes = [], this.pendingGroups = [], this.totalGroupCount = 0, this.processedGroupCount = 0, this.debugFilteredNodes = [], this.debugMergeEvents = [], this.currentGroupKey = null, this.currentRootNodeId = null, this.lastMergedNodeId = null;
const t49 = new Map;
for (const e3 of this.inputProblem.meshNodes) {
if (e3._containsObstacle === true) {
this.passthroughNodes.push(e3), this.debugFilteredNodes.push({ type: "preserved-obstacle", node: e3, reason: "contains-obstacle" });
continue;
}
if (_2(e3)) {
this.passthroughNodes.push(e3);
continue;
}
if (e3.availableZ.length !== this.inputProblem.layerCount) {
this.passthroughNodes.push(e3);
continue;
}
let n3 = false;
for (let t50 = 0;t50 < this.inputProblem.layerCount; t50 += 1)
if (!e3.availableZ.includes(t50)) {
n3 = true;
break;
}
if (n3) {
this.passthroughNodes.push(e3);
continue;
}
if (x2(e3, this.obstacleNodes)) {
this.passthroughNodes.push(e3), this.debugFilteredNodes.push({ type: "preserved-overlap", node: e3, reason: "overlaps-obstacle" });
continue;
}
const o3 = b2(e3), i3 = t49.get(o3);
i3 ? i3.push(e3) : t49.set(o3, [e3]);
}
for (const [e3, n3] of t49.entries())
n3.length <= 1 ? this.passthroughNodes.push(...n3) : this.pendingGroups.push({ groupKey: e3, nodes: n3 });
this.pendingGroups.sort((t50, e3) => e3.nodes.length - t50.nodes.length), this.totalGroupCount = this.pendingGroups.length, this.updateStats("setup");
}
_step() {
const t49 = this.pendingGroups.shift();
if (!t49)
return this.currentGroupKey = null, this.currentRootNodeId = null, this.solved = true, void this.updateStats("done");
const e3 = t49.nodes[0];
this.currentGroupKey = t49.groupKey, this.currentRootNodeId = e3 ? e3.capacityMeshNodeId : null;
const n3 = function(t50) {
if (!t50.nodes[0])
return { outputNodes: [], mergeEvents: [] };
let { POSITIVE_INFINITY: e4, POSITIVE_INFINITY: n4, POSITIVE_INFINITY: o4, POSITIVE_INFINITY: i3 } = Number;
for (const r4 of t50.nodes) {
e4 = Math.min(e4, r4.width), n4 = Math.min(n4, r4.height);
const t51 = We(r4);
o4 = Math.min(o4, t51.minX), i3 = Math.min(i3, t51.minY);
}
const r3 = new Map, s3 = [];
for (const a4 of t50.nodes) {
const t51 = We(a4), c4 = Math.round((t51.minX - o4) / e4), l4 = Math.round((t51.minY - i3) / n4), h3 = Math.max(1, Math.round(a4.width / e4)), d3 = Math.max(1, Math.round(a4.height / n4));
for (let t52 = 0;t52 < d3; t52 += 1)
for (let e5 = 0;e5 < h3; e5 += 1)
r3.set(`${c4 + e5},${l4 + t52}`, a4);
s3.push({ col: c4, row: l4 });
}
s3.sort((t51, e5) => t51.row - e5.row || t51.col - e5.col);
const a3 = new Set, c3 = [], l3 = [];
for (const o5 of s3) {
const i4 = `${o5.col},${o5.row}`;
if (a3.has(i4))
continue;
let s4 = 0;
for (;; ) {
const t51 = `${o5.col + s4},${o5.row}`;
if (!r3.has(t51))
break;
if (a3.has(t51))
break;
s4 += 1;
}
let h3 = s4, d3 = 1, u3 = 1, p3 = 1;
for (let t51 = 1;; t51 += 1) {
const i5 = o5.row + t51 - 1;
let s5 = 0;
for (;s5 < h3; ) {
const t52 = `${o5.col + s5},${i5}`;
if (!r3.has(t52))
break;
if (a3.has(t52))
break;
s5 += 1;
}
if (s5 === 0)
break;
h3 = Math.min(h3, s5);
for (let o6 = h3;o6 >= 1; o6 -= 1) {
const i6 = o6 * e4, r4 = t51 * n4, s6 = Math.min(i6, r4);
if ((s6 <= 0.000001 ? Number.POSITIVE_INFINITY : Math.max(i6, r4) / s6) > 4)
continue;
const a4 = o6 * t51;
a4 > p3 && (p3 = a4, d3 = o6, u3 = t51);
break;
}
}
const m3 = new Map;
for (let t51 = 0;t51 < u3; t51 += 1)
for (let e5 = 0;e5 < d3; e5 += 1) {
const n5 = `${o5.col + e5},${o5.row + t51}`, i5 = r3.get(n5);
i5 && (a3.add(n5), m3.set(i5.capacityMeshNodeId, i5));
}
const g3 = [...m3.values()];
if (g3.length <= 1) {
const t51 = g3[0];
t51 && c3.push(t51);
continue;
}
const f3 = v2(g3);
c3.push(f3), l3.push({ type: "merge", groupKey: t50.groupKey, sourceNodes: g3, mergedNode: f3 });
}
return { outputNodes: c3, mergeEvents: l3 };
}(t49);
this.mergedNodes.push(...n3.outputNodes), this.processedGroupCount += 1, this.debugMergeEvents.push(...n3.mergeEvents);
const o3 = n3.mergeEvents[n3.mergeEvents.length - 1];
o3 && (this.lastMergedNodeId = o3.mergedNode.capacityMeshNodeId), this.updateStats(n3.mergeEvents.length > 0 ? "merged-group" : "passthrough-group");
}
computeProgress() {
return this.totalGroupCount === 0 ? 1 : this.processedGroupCount / this.totalGroupCount;
}
updateStats(t49) {
const e3 = new Set(this.debugMergeEvents.map((t50) => t50.groupKey)), n3 = { lastAction: t49, totalGroupCount: this.totalGroupCount, processedGroupCount: this.processedGroupCount, pendingGroupCount: this.pendingGroups.length, mergedNodeCount: this.mergedNodes.length, passthroughNodeCount: this.passthroughNodes.length, gapFillNodeCount: this.passthroughNodes.filter(_2).length, preservedObstacleNodeCount: this.debugFilteredNodes.filter((t50) => t50.type === "preserved-obstacle").length, preservedOverlapNodeCount: this.debugFilteredNodes.filter((t50) => t50.type === "preserved-overlap").length, mergeCount: this.debugMergeEvents.length, mergedGroupCount: e3.size, currentGroupKey: this.currentGroupKey, currentRootNodeId: this.currentRootNodeId, lastMergedNodeId: this.lastMergedNodeId };
this.stats = n3;
}
getConstructorParams() {
return [this.inputProblem];
}
getOutput() {
return [...this.mergedNodes, ...this.passthroughNodes];
}
visualize() {
const t49 = this.getOutput(), e3 = this.currentRootNodeId ? t49.find((t50) => t50.capacityMeshNodeId === this.currentRootNodeId) ?? null : null, n3 = this.lastMergedNodeId ? t49.find((t50) => t50.capacityMeshNodeId === this.lastMergedNodeId) ?? null : null;
return { rects: [...this.debugFilteredNodes.map((t50) => I2(t50.node, t50.type === "preserved-obstacle" ? "rgba(255,64,64,0.35)" : "rgba(255,160,64,0.35)", t50.reason)), ...this.passthroughNodes.map((t50) => I2(t50, t50._containsObstacle ? "rgba(255,0,0,0.35)" : _2(t50) ? "rgba(0,120,255,0.18)" : "rgba(160,160,160,0.12)")), ...this.mergedNodes.map((t50) => I2(t50, "rgba(120,120,120,0.14)")), ...e3 ? [I2(e3, "rgba(255,215,0,0.35)", "active-group")] : [], ...n3 ? [I2(n3, "rgba(0,200,120,0.28)", "merged")] : []] };
}
};
var C2 = class extends kt {
constructor(t49) {
super(), this.inputProblem = t49;
}
obstacleQueue = [];
obstacleQueueIndex = 0;
meshNodes = [];
_setup() {
this.obstacleQueue = this.inputProblem.obstacles, this.obstacleQueueIndex = 0, this.meshNodes = [...this.inputProblem.meshNodes];
}
_step() {
if (this.obstacleQueueIndex >= this.obstacleQueue.length)
return void (this.solved = true);
const t49 = this.obstacleQueue[this.obstacleQueueIndex], e3 = t49.layers.map((t50) => mo(t50, this.inputProblem.layerCount)), n3 = [];
for (const o3 of this.meshNodes) {
if (o3._containsObstacle) {
n3.push(o3);
continue;
}
if (!e3.some((t50) => o3.availableZ.includes(t50))) {
n3.push(o3);
continue;
}
if (!Xe(We(o3), We(t49))) {
n3.push(o3);
continue;
}
if (o3.availableZ.length === 1)
continue;
const i3 = o3.availableZ.filter((t50) => !e3.includes(t50));
for (const t50 of i3) {
const e4 = { ...o3, capacityMeshNodeId: `${o3.capacityMeshNodeId}:z${t50}`, availableZ: [t50], layer: `z${t50}` };
n3.push(e4);
}
}
this.meshNodes = n3, this.obstacleQueueIndex += 1, this.stats = { obstaclesProcessed: this.obstacleQueueIndex, obstacleCount: this.obstacleQueue.length, meshNodeCount: this.meshNodes.length };
}
computeProgress() {
return this.obstacleQueue.length === 0 ? 1 : this.obstacleQueueIndex / this.obstacleQueue.length;
}
getConstructorParams() {
return [this.inputProblem];
}
getOutput() {
return this.meshNodes;
}
visualize() {
const t49 = this.obstacleQueueIndex < this.obstacleQueue.length ? this.obstacleQueue[this.obstacleQueueIndex] ?? null : null, e3 = this.obstacleQueue.slice(0, this.obstacleQueueIndex), n3 = t49 ? this.obstacleQueue.slice(this.obstacleQueueIndex + 1) : [];
return { rects: [...e3.map((t50) => ({ center: t50.center, width: t50.width, height: t50.height, fill: "rgba(160,160,160,0.10)", stroke: "rgba(160,160,160,0.35)", label: `processed ${t50.obstacleId ?? "obstacle"}` })), ...t49 ? [{ center: t49.center, width: t49.width, height: t49.height, fill: "rgba(255,140,0,0.22)", stroke: "rgba(255,140,0,0.75)", label: `active ${t49.obstacleId ?? "obstacle"}` }] : [], ...n3.map((t50) => ({ center: t50.center, width: t50.width, height: t50.height, fill: "rgba(255,0,0,0.05)", stroke: "rgba(255,0,0,0.22)", label: `pending ${t50.obstacleId ?? "obstacle"}` })), ...this.meshNodes.map((t50) => ({ ...AD(t50, { rectMargin: 0.01 }), fill: t50._containsObstacle ? "rgba(255,0,0,0.18)" : "rgba(0,120,255,0.12)", stroke: t50._containsObstacle ? "rgba(255,0,0,0.45)" : "rgba(0,120,255,0.45)" }))] };
}
};
F1.register(class extends Lt {
constructor(t49) {
super(t49), this.inputProblem = t49;
}
static componentKind = "bga";
initialTopologySolver;
removeMeshNodeOverlappingWithUnmarkedObstacle;
gapfillDueToNodeRemoval;
mergeMeshNodes;
markedComponentObstacles = [];
unmarkedComponentObstacles = [];
pipelineDef = [Dt("initialTopologySolver", y2, (t49) => [{ srj: t49.inputProblem.inputSrj, componentBounds: t49.inputProblem.detectedComponent.bounds, componentId: t49.inputProblem.detectedComponent.componentId, markedComponentObstacles: t49.markedComponentObstacles, unmarkedComponentObstacles: t49.unmarkedComponentObstacles, viaDiameter: t49.inputProblem.viaDiameter }]), Dt("removeMeshNodeOverlappingWithUnmarkedObstacle", C2, (t49) => [{ meshNodes: t49.initialTopologySolver.getOutput(), obstacles: t49.unmarkedComponentObstacles, layerCount: t49.inputProblem.inputSrj.layerCount }]), Dt("gapfillDueToNodeRemoval", i2, (t49) => [{ meshNodes: t49.removeMeshNodeOverlappingWithUnmarkedObstacle.getOutput(), unmarkedComponentObstacles: t49.unmarkedComponentObstacles, layerCount: t49.inputProblem.inputSrj.layerCount }]), Dt("mergeMeshNodes", S2, (t49) => [{ meshNodes: t49.gapfillDueToNodeRemoval.getOutput(), layerCount: t49.inputProblem.inputSrj.layerCount }])];
_setup() {
const t49 = this.inputProblem.detectedComponent.bounds, e3 = this.inputProblem.detectedComponent.componentId, n3 = [], o3 = [];
for (const i3 of this.inputProblem.inputSrj.obstacles) {
const r3 = We(i3);
Xe(t49, r3) && (i3.componentId !== e3 ? o3.push(i3) : n3.push(i3));
}
this.markedComponentObstacles = n3, this.unmarkedComponentObstacles = o3;
}
getConstructorParams() {
return [this.inputProblem];
}
getOutput() {
return { routingRegions: this.mergeMeshNodes?.getOutput() ?? this.gapfillDueToNodeRemoval?.getOutput() ?? this.removeMeshNodeOverlappingWithUnmarkedObstacle?.getOutput() ?? [] };
}
initialVisualize() {
return { rects: [{ center: { x: (this.inputProblem.detectedComponent.bounds.minX + this.inputProblem.detectedComponent.bounds.maxX) / 2, y: (this.inputProblem.detectedComponent.bounds.minY + this.inputProblem.detectedComponent.bounds.maxY) / 2 }, width: this.inputProblem.detectedComponent.bounds.maxX - this.inputProblem.detectedComponent.bounds.minX, height: this.inputProblem.detectedComponent.bounds.maxY - this.inputProblem.detectedComponent.bounds.minY, fill: "rgba(0,0,0,0)", stroke: "rgba(30,30,30,0.65)", label: `bga ${this.inputProblem.detectedComponent.componentId}` }, ...this.markedComponentObstacles.map((t49) => ({ center: t49.center, width: t49.width, height: t49.height, fill: "rgba(255,0,0,0.18)", stroke: "rgba(255,0,0,0.52)", label: `pad ${t49.obstacleId ?? "obstacle"}` })), ...this.unmarkedComponentObstacles.map((t49) => ({ center: t49.center, width: t49.width, height: t49.height, fill: "rgba(255,140,0,0.14)", stroke: "rgba(255,140,0,0.42)", label: `foreign ${t49.obstacleId ?? "obstacle"}` }))] };
}
finalVisualize() {
return { rects: this.getOutput().routingRegions.map((t49) => ({ ...AD(t49, { rectMargin: 0.01 }), fill: t49._containsObstacle ? "rgba(255,0,0,0.16)" : "rgba(0,120,255,0.12)", stroke: t49._containsObstacle ? "rgba(255,0,0,0.36)" : "rgba(0,120,255,0.42)" })) };
}
});
var P2 = 0.000001;
function M2(t49, e3) {
return t49.__zLayers && t49.__zLayers.length > 0 ? go(t49.__zLayers, e3) : fo(t49.layers, e3);
}
function N2(t49) {
const e3 = [...t49].sort((t50, e4) => t50 - e4), n3 = [];
for (let t50 = 1;t50 < e3.length; t50++) {
const o4 = e3[t50] - e3[t50 - 1];
o4 > P2 && n3.push(o4);
}
const o3 = n3.length > 0 ? Math.max(P2, Math.min(...n3) / 4) : 0.001, i3 = [];
for (const t50 of e3) {
const e4 = i3[i3.length - 1];
(e4 === undefined || Math.abs(t50 - e4) > o3) && i3.push(t50);
}
return i3;
}
function w2(t49) {
return Array.from({ length: Math.max(0, t49) }, (t50, e3) => e3);
}
var T2 = 0.000001;
function R2(t49) {
return t49.maxX - t49.minX > T2 && t49.maxY - t49.minY > T2;
}
function E2(t49) {
return function(t50) {
const e3 = Math.min(t50.width, t50.height), n3 = Math.max(t50.width, t50.height);
return e3 <= 0 ? 0 : n3 / e3;
}(t49) >= 1.5;
}
function A2(t49, e3) {
const n3 = [{ side: "top", distance: Math.abs(t49.center.y - e3.minY) }, { side: "right", distance: Math.abs(e3.maxX - t49.center.x) }, { side: "bottom", distance: Math.abs(e3.maxY - t49.center.y) }, { side: "left", distance: Math.abs(t49.center.x - e3.minX) }];
return n3.sort((t50, e4) => t50.distance - e4.distance), n3[0].side;
}
function O2(t49, e3) {
return t49.map((t50, n3) => ({ key: `pad:${t50.obstacleId ?? n3}`, bounds: Ee(t50), regionType: "pad", obstacleZ: M2(t50, e3) }));
}
function k2(t49, e3) {
return t49.map((t50, n3) => ({ key: `thermal-pad:${t50.obstacleId ?? n3}`, bounds: Ee(t50), regionType: "pad", obstacleZ: M2(t50, e3) }));
}
function D2(t49, e3) {
return !!R2(t49) && Math.min(t49.maxX - t49.minX, t49.maxY - t49.minY) <= e3;
}
function L2({ side: t49, sideObstacles: e3, bounds: n3, innerBounds: o3, narrowThreshold: i3 }) {
const r3 = [];
for (let s3 = 0;s3 < e3.length - 1; s3++) {
const a3 = Ee(e3[s3]), c3 = Ee(e3[s3 + 1]);
let l3;
l3 = t49 === "top" ? { minX: a3.maxX, maxX: c3.minX, minY: n3.minY, maxY: o3.minY } : t49 === "right" ? { minX: o3.maxX, maxX: n3.maxX, minY: a3.maxY, maxY: c3.minY } : t49 === "bottom" ? { minX: a3.maxX, maxX: c3.minX, minY: o3.maxY, maxY: n3.maxY } : { minX: n3.minX, maxX: o3.minX, minY: a3.maxY, maxY: c3.minY }, r3.push({ key: `${t49}-gap-${s3}`, bounds: l3, regionType: "pad-gap", isNarrowPadGap: D2(l3, i3) });
}
return r3;
}
function z2({ side: t49, sideObstacles: e3, thermalPadBounds: n3, narrowThreshold: o3 }) {
const i3 = [];
for (let r3 = 0;r3 < e3.length; r3++) {
const s3 = Ee(e3[r3]), a3 = e3[r3 - 1] ? Ee(e3[r3 - 1]) : null, c3 = e3[r3 + 1] ? Ee(e3[r3 + 1]) : null;
let l3;
l3 = t49 === "top" ? { minX: a3 ? (a3.maxX + s3.minX) / 2 : s3.minX, maxX: c3 ? (s3.maxX + c3.minX) / 2 : s3.maxX, minY: s3.maxY, maxY: n3.minY } : t49 === "right" ? { minX: n3.maxX, maxX: s3.minX, minY: a3 ? (a3.maxY + s3.minY) / 2 : s3.minY, maxY: c3 ? (s3.maxY + c3.minY) / 2 : s3.maxY } : t49 === "bottom" ? { minX: a3 ? (a3.maxX + s3.minX) / 2 : s3.minX, maxX: c3 ? (s3.maxX + c3.minX) / 2 : s3.maxX, minY: n3.maxY, maxY: s3.minY } : { minX: s3.maxX, maxX: n3.minX, minY: a3 ? (a3.maxY + s3.minY) / 2 : s3.minY, maxY: c3 ? (s3.maxY + c3.minY) / 2 : s3.maxY }, i3.push({ key: `inner-${t49}-pad-${r3}`, bounds: l3, regionType: "pad-gap", isNarrowPadGap: D2(l3, o3) });
}
return i3;
}
function B2({ bounds: t49, innerBounds: e3, sideGroups: n3 }) {
const o3 = n3.top[0] ? Ee(n3.top[0]) : null, i3 = n3.top.at(-1) ? Ee(n3.top.at(-1)) : null, r3 = n3.right[0] ? Ee(n3.right[0]) : null, s3 = n3.right.at(-1) ? Ee(n3.right.at(-1)) : null, a3 = n3.bottom[0] ? Ee(n3.bottom[0]) : null, c3 = n3.bottom.at(-1) ? Ee(n3.bottom.at(-1)) : null, l3 = n3.left[0] ? Ee(n3.left[0]) : null, h3 = n3.left.at(-1) ? Ee(n3.left.at(-1)) : null;
return [{ key: "corner-nw-outer", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: t49.minY, maxY: e3.minY } }, { key: "corner-nw-top", regionType: "corner", bounds: { minX: e3.minX, maxX: o3?.minX ?? e3.minX, minY: t49.minY, maxY: e3.minY } }, { key: "corner-nw-left", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: e3.minY, maxY: l3?.minY ?? e3.minY } }, { key: "corner-ne-outer", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: t49.minY, maxY: e3.minY } }, { key: "corner-ne-top", regionType: "corner", bounds: { minX: i3?.maxX ?? e3.maxX, maxX: e3.maxX, minY: t49.minY, maxY: e3.minY } }, { key: "corner-ne-right", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: e3.minY, maxY: r3?.minY ?? e3.minY } }, { key: "corner-se-outer", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: e3.maxY, maxY: t49.maxY } }, { key: "corner-se-right", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: s3?.maxY ?? e3.maxY, maxY: e3.maxY } }, { key: "corner-se-bottom", regionType: "corner", bounds: { minX: c3?.maxX ?? e3.maxX, maxX: e3.maxX, minY: e3.maxY, maxY: t49.maxY } }, { key: "corner-sw-outer", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: e3.maxY, maxY: t49.maxY } }, { key: "corner-sw-bottom", regionType: "corner", bounds: { minX: e3.minX, maxX: a3?.minX ?? e3.minX, minY: e3.maxY, maxY: t49.maxY } }, { key: "corner-sw-left", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: h3?.maxY ?? e3.maxY, maxY: e3.maxY } }];
}
function F2({ innerBounds: t49, thermalPadBounds: e3, sideGroups: n3 }) {
const o3 = n3.top[0] ? Ee(n3.top[0]) : null, i3 = n3.top.at(-1) ? Ee(n3.top.at(-1)) : null, r3 = n3.right[0] ? Ee(n3.right[0]) : null, s3 = n3.right.at(-1) ? Ee(n3.right.at(-1)) : null, a3 = n3.bottom[0] ? Ee(n3.bottom[0]) : null, c3 = n3.bottom.at(-1) ? Ee(n3.bottom.at(-1)) : null, l3 = n3.left[0] ? Ee(n3.left[0]) : null, h3 = n3.left.at(-1) ? Ee(n3.left.at(-1)) : null;
return [{ key: "inner-corner-nw-core", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: t49.minY, maxY: e3.minY } }, { key: "inner-corner-nw-top", regionType: "corner", bounds: { minX: e3.minX, maxX: o3?.minX ?? e3.minX, minY: t49.minY, maxY: e3.minY } }, { key: "inner-corner-nw-left", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: e3.minY, maxY: l3?.minY ?? e3.minY } }, { key: "inner-corner-ne-core", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: t49.minY, maxY: e3.minY } }, { key: "inner-corner-ne-top", regionType: "corner", bounds: { minX: i3?.maxX ?? e3.maxX, maxX: e3.maxX, minY: t49.minY, maxY: e3.minY } }, { key: "inner-corner-ne-right", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: e3.minY, maxY: r3?.minY ?? e3.minY } }, { key: "inner-corner-se-core", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: e3.maxY, maxY: t49.maxY } }, { key: "inner-corner-se-right", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: s3?.maxY ?? e3.maxY, maxY: e3.maxY } }, { key: "inner-corner-se-bottom", regionType: "corner", bounds: { minX: c3?.maxX ?? e3.maxX, maxX: e3.maxX, minY: e3.maxY, maxY: t49.maxY } }, { key: "inner-corner-sw-core", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: e3.maxY, maxY: t49.maxY } }, { key: "inner-corner-sw-bottom", regionType: "corner", bounds: { minX: e3.minX, maxX: a3?.minX ?? e3.minX, minY: e3.maxY, maxY: t49.maxY } }, { key: "inner-corner-sw-left", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: h3?.maxY ?? e3.maxY, maxY: e3.maxY } }];
}
F1.register(class extends kt {
constructor(t49) {
super(), this.inputProblem = t49;
}
static componentKind = "qfp_thermalpad";
output = null;
getConstructorParams() {
return [this.inputProblem];
}
_step() {
if (this.output)
return void (this.solved = true);
const { layerCount: t49, obstacles: e3 } = this.inputProblem.inputSrj, { bounds: n3, componentId: o3 } = this.inputProblem.detectedComponent, i3 = w2(t49), r3 = e3.filter((t50) => t50.componentId === o3), s3 = r3.length > 0 ? r3 : e3, { padRingObstacles: a3, thermalPadObstacles: c3 } = function(t50) {
return { padRingObstacles: t50.filter(E2), thermalPadObstacles: t50.filter((t51) => !E2(t51)) };
}(s3), l3 = function(t50, e4) {
const n4 = { top: [], right: [], bottom: [], left: [] };
for (const o4 of t50)
n4[A2(o4, e4)].push(o4);
return n4.top.sort((t51, e5) => t51.center.x - e5.center.x), n4.bottom.sort((t51, e5) => t51.center.x - e5.center.x), n4.left.sort((t51, e5) => t51.center.y - e5.center.y), n4.right.sort((t51, e5) => t51.center.y - e5.center.y), n4;
}(a3, n3), h3 = function({ bounds: t50, sideGroups: e4 }) {
return { minX: e4.left.length > 0 ? Math.max(...e4.left.map((t51) => Ee(t51).maxX)) : t50.minX, maxX: e4.right.length > 0 ? Math.min(...e4.right.map((t51) => Ee(t51).minX)) : t50.maxX, minY: e4.top.length > 0 ? Math.max(...e4.top.map((t51) => Ee(t51).maxY)) : t50.minY, maxY: e4.bottom.length > 0 ? Math.min(...e4.bottom.map((t51) => Ee(t51).minY)) : t50.maxY };
}({ bounds: n3, sideGroups: l3 }), d3 = function(t50) {
return t50.length === 0 ? null : t50.reduce((t51, e4) => {
const n4 = Ee(e4);
return { minX: Math.min(t51.minX, n4.minX), maxX: Math.max(t51.maxX, n4.maxX), minY: Math.min(t51.minY, n4.minY), maxY: Math.max(t51.maxY, n4.maxY) };
}, Ee(t50[0]));
}(c3);
if (!d3)
return this.failed = true, void (this.error = "QfpThermalPadTopologyGeneratorSolver requires a thermal pad");
const u3 = o3, p3 = this.inputProblem.viaDiameter ?? Yo(this.inputProblem.inputSrj).padDiameter, m3 = this.inputProblem.obstacleMargin ?? this.inputProblem.inputSrj.defaultObstacleMargin ?? 0.15, g3 = p3 + 2 * m3, f3 = this.inputProblem.inputSrj.minTraceWidth + 2 * m3, y3 = [...O2(a3, t49), ...k2(c3, t49), ...L2({ side: "top", sideObstacles: l3.top, bounds: n3, innerBounds: h3, narrowThreshold: f3 }), ...L2({ side: "right", sideObstacles: l3.right, bounds: n3, innerBounds: h3, narrowThreshold: f3 }), ...L2({ side: "bottom", sideObstacles: l3.bottom, bounds: n3, innerBounds: h3, narrowThreshold: f3 }), ...L2({ side: "left", sideObstacles: l3.left, bounds: n3, innerBounds: h3, narrowThreshold: f3 }), ...z2({ side: "top", sideObstacles: l3.top, thermalPadBounds: d3, narrowThreshold: f3 }), ...z2({ side: "right", sideObstacles: l3.right, thermalPadBounds: d3, narrowThreshold: f3 }), ...z2({ side: "bottom", sideObstacles: l3.bottom, thermalPadBounds: d3, narrowThreshold: f3 }), ...z2({ side: "left", sideObstacles: l3.left, thermalPadBounds: d3, narrowThreshold: f3 }), ...F2({ innerBounds: h3, thermalPadBounds: d3, sideGroups: l3 }), ...B2({ bounds: n3, innerBounds: h3, sideGroups: l3 })].flatMap((t50) => function({ nodeId: t51, bounds: e4, availableZ: n4, multiLayerThreshold: o4, regionType: i4, isNarrowPadGap: r4 = false, obstacleZ: s4 = [] }) {
if (!R2(e4))
return [];
const a4 = function(t52) {
return { center: { x: (t52.minX + t52.maxX) / 2, y: (t52.minY + t52.maxY) / 2 }, width: t52.maxX - t52.minX, height: t52.maxY - t52.minY };
}(e4), c4 = Math.min(a4.width, a4.height) > o4, l4 = c4 ? [{ availableZ: n4.filter((t52) => !s4.includes(t52)), containsObstacle: false }, { availableZ: n4.filter((t52) => s4.includes(t52)), containsObstacle: true }].filter((t52) => t52.availableZ.length > 0) : n4.map((t52) => ({ availableZ: [t52], containsObstacle: s4.includes(t52) }));
return l4.map((e5) => ({ capacityMeshNodeId: l4.length === 1 ? t51 : c4 ? `${t51}:${e5.containsObstacle ? "obstacle" : "free"}` : `${t51}:z${e5.availableZ[0]}`, center: a4.center, width: a4.width, height: a4.height, layer: `z${e5.availableZ.join(",")}`, availableZ: e5.availableZ, _qfpRegionType: i4, _isNarrowQfpPadGap: r4, _containsObstacle: e5.containsObstacle }));
}({ nodeId: `qfp_thermalpad:${u3}:${t50.key}`, bounds: t50.bounds, availableZ: i3, multiLayerThreshold: g3, regionType: t50.regionType, isNarrowPadGap: t50.isNarrowPadGap, obstacleZ: t50.obstacleZ }));
this.output = { routingRegions: y3 }, this.stats = { componentId: o3, layerCount: t49, viaDiameter: p3, obstacleMargin: m3, multiLayerThreshold: g3, narrowPadGapThreshold: f3, thermalPadCount: c3.length, perimeterPadCount: a3.length, innerCornerRectCount: y3.filter((t50) => t50.capacityMeshNodeId.includes(":inner-corner-")).length, narrowPadGapNodeCount: y3.filter((t50) => t50._isNarrowQfpPadGap).length, topPadCount: l3.top.length, rightPadCount: l3.right.length, bottomPadCount: l3.bottom.length, leftPadCount: l3.left.length, multiLayerNodeCount: y3.filter((t50) => t50.availableZ.length > 1).length, totalMeshNodeCount: y3.length }, this.solved = true;
}
getOutput() {
if (!this.output)
throw new Error("QfpThermalPadTopologyGeneratorSolver has not solved yet");
return this.output;
}
});
var j2 = 0.000001;
function $2(t49) {
return t49.maxX - t49.minX > j2 && t49.maxY - t49.minY > j2;
}
function Y2(t49, e3) {
const n3 = [{ side: "top", distance: Math.abs(t49.center.y - e3.minY) }, { side: "right", distance: Math.abs(e3.maxX - t49.center.x) }, { side: "bottom", distance: Math.abs(e3.maxY - t49.center.y) }, { side: "left", distance: Math.abs(t49.center.x - e3.minX) }];
return n3.sort((t50, e4) => t50.distance - e4.distance), n3[0].side;
}
function X2(t49, e3) {
return t49.map((t50, n3) => ({ key: `pad:${t50.obstacleId ?? n3}`, bounds: Ee(t50), regionType: "pad", obstacleZ: M2(t50, e3), connectedTo: [...t50.connectedTo] }));
}
function W2(t49, e3) {
return !!$2(t49) && Math.min(t49.maxX - t49.minX, t49.maxY - t49.minY) <= e3;
}
function V2({ side: t49, sideObstacles: e3, bounds: n3, centralBounds: o3, narrowThreshold: i3 }) {
const r3 = [];
for (let s3 = 0;s3 < e3.length - 1; s3++) {
const a3 = Ee(e3[s3]), c3 = Ee(e3[s3 + 1]);
let l3;
l3 = t49 === "top" ? { minX: a3.maxX, maxX: c3.minX, minY: n3.minY, maxY: o3.minY } : t49 === "right" ? { minX: o3.maxX, maxX: n3.maxX, minY: a3.maxY, maxY: c3.minY } : t49 === "bottom" ? { minX: a3.maxX, maxX: c3.minX, minY: o3.maxY, maxY: n3.maxY } : { minX: n3.minX, maxX: o3.minX, minY: a3.maxY, maxY: c3.minY }, r3.push({ key: `${t49}-gap-${s3}`, bounds: l3, regionType: "pad-gap", isNarrowPadGap: W2(l3, i3) });
}
return r3;
}
function H2({ bounds: t49, centralBounds: e3, sideGroups: n3 }) {
const o3 = n3.top[0] ? Ee(n3.top[0]) : null, i3 = n3.top.at(-1) ? Ee(n3.top.at(-1)) : null, r3 = n3.right[0] ? Ee(n3.right[0]) : null, s3 = n3.right.at(-1) ? Ee(n3.right.at(-1)) : null, a3 = n3.bottom[0] ? Ee(n3.bottom[0]) : null, c3 = n3.bottom.at(-1) ? Ee(n3.bottom.at(-1)) : null, l3 = n3.left[0] ? Ee(n3.left[0]) : null, h3 = n3.left.at(-1) ? Ee(n3.left.at(-1)) : null;
return [{ key: "corner-nw-outer", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: t49.minY, maxY: e3.minY } }, { key: "corner-nw-top", regionType: "corner", bounds: { minX: e3.minX, maxX: o3?.minX ?? e3.minX, minY: t49.minY, maxY: e3.minY } }, { key: "corner-nw-left", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: e3.minY, maxY: l3?.minY ?? e3.minY } }, { key: "corner-ne-outer", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: t49.minY, maxY: e3.minY } }, { key: "corner-ne-top", regionType: "corner", bounds: { minX: i3?.maxX ?? e3.maxX, maxX: e3.maxX, minY: t49.minY, maxY: e3.minY } }, { key: "corner-ne-right", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: e3.minY, maxY: r3?.minY ?? e3.minY } }, { key: "corner-se-outer", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: e3.maxY, maxY: t49.maxY } }, { key: "corner-se-right", regionType: "corner", bounds: { minX: e3.maxX, maxX: t49.maxX, minY: s3?.maxY ?? e3.maxY, maxY: e3.maxY } }, { key: "corner-se-bottom", regionType: "corner", bounds: { minX: c3?.maxX ?? e3.maxX, maxX: e3.maxX, minY: e3.maxY, maxY: t49.maxY } }, { key: "corner-sw-outer", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: e3.maxY, maxY: t49.maxY } }, { key: "corner-sw-bottom", regionType: "corner", bounds: { minX: e3.minX, maxX: a3?.minX ?? e3.minX, minY: e3.maxY, maxY: t49.maxY } }, { key: "corner-sw-left", regionType: "corner", bounds: { minX: t49.minX, maxX: e3.minX, minY: h3?.maxY ?? e3.maxY, maxY: e3.maxY } }];
}
F1.register(class extends kt {
constructor(t49) {
super(), this.inputProblem = t49;
}
static componentKind = "qfp";
output = null;
getConstructorParams() {
return [this.inputProblem];
}
_step() {
if (this.output)
return void (this.solved = true);
const { layerCount: t49, obstacles: e3 } = this.inputProblem.inputSrj, { bounds: n3, componentId: o3 } = this.inputProblem.detectedComponent, i3 = w2(t49), r3 = e3.filter((t50) => t50.componentId === o3), s3 = r3.length > 0 ? r3 : e3, a3 = function(t50, e4) {
const n4 = { top: [], right: [], bottom: [], left: [] };
for (const o4 of t50)
n4[Y2(o4, e4)].push(o4);
return n4.top.sort((t51, e5) => t51.center.x - e5.center.x), n4.bottom.sort((t51, e5) => t51.center.x - e5.center.x), n4.left.sort((t51, e5) => t51.center.y - e5.center.y), n4.right.sort((t51, e5) => t51.center.y - e5.center.y), n4;
}(s3, n3), c3 = function({ bounds: t50, sideGroups: e4 }) {
return { minX: e4.left.length > 0 ? Math.max(...e4.left.map((t51) => Ee(t51).maxX)) : t50.minX, maxX: e4.right.length > 0 ? Math.min(...e4.right.map((t51) => Ee(t51).minX)) : t50.maxX, minY: e4.top.length > 0 ? Math.max(...e4.top.map((t51) => Ee(t51).maxY)) : t50.minY, maxY: e4.bottom.length > 0 ? Math.min(...e4.bottom.map((t51) => Ee(t51).minY)) : t50.maxY };
}({ bounds: n3, sideGroups: a3 }), l3 = o3, h3 = this.inputProblem.viaDiameter ?? Yo(this.inputProblem.inputSrj).padDiameter, d3 = this.inputProblem.obstacleMargin ?? this.inputProblem.inputSrj.defaultObstacleMargin ?? 0.15, u3 = h3 + 2 * d3, p3 = this.inputProblem.inputSrj.minTraceWidth + 2 * d3, m3 = [{ key: "center", bounds: c3, regionType: "center" }, ...X2(s3, t49), ...V2({ side: "top", sideObstacles: a3.top, bounds: n3, centralBounds: c3, narrowThreshold: p3 }), ...V2({ side: "right", sideObstacles: a3.right, bounds: n3, centralBounds: c3, narrowThreshold: p3 }), ...V2({ side: "bottom", sideObstacles: a3.bottom, bounds: n3, centralBounds: c3, narrowThreshold: p3 }), ...V2({ side: "left", sideObstacles: a3.left, bounds: n3, centralBounds: c3, narrowThreshold: p3 }), ...H2({ bounds: n3, centralBounds: c3, sideGroups: a3 })].flatMap((t50) => function({ nodeId: t51, bounds: e4, availableZ: n4, multiLayerThreshold: o4, regionType: i4, isNarrowPadGap: r4 = false, obstacleZ: s4 = [], connectedTo: a4 }) {
if (!$2(e4))
return [];
const c4 = function(t52) {
return { center: { x: (t52.minX + t52.maxX) / 2, y: (t52.minY + t52.maxY) / 2 }, width: t52.maxX - t52.minX, height: t52.maxY - t52.minY };
}(e4), l4 = Math.min(c4.width, c4.height) > o4, h4 = l4 ? [{ availableZ: n4.filter((t52) => !s4.includes(t52)), containsObstacle: false }, { availableZ: n4.filter((t52) => s4.includes(t52)), containsObstacle: true }].filter((t52) => t52.availableZ.length > 0) : n4.map((t52) => ({ availableZ: [t52], containsObstacle: s4.includes(t52) }));
return h4.map((e5) => ({ capacityMeshNodeId: h4.length === 1 ? t51 : l4 ? `${t51}:${e5.containsObstacle ? "obstacle" : "free"}` : `${t51}:z${e5.availableZ[0]}`, center: c4.center, width: c4.width, height: c4.height, layer: `z${e5.availableZ.join(",")}`, availableZ: e5.availableZ, _qfpRegionType: i4, _isNarrowQfpPadGap: r4, _containsObstacle: e5.containsObstacle, _connectedTo: e5.containsObstacle ? a4 : undefined }));
}({ nodeId: `qfp:${l3}:${t50.key}`, bounds: t50.bounds, availableZ: i3, multiLayerThreshold: u3, regionType: t50.regionType, isNarrowPadGap: t50.isNarrowPadGap, obstacleZ: t50.obstacleZ, connectedTo: t50.connectedTo }));
this.output = { routingRegions: m3 }, this.stats = { componentId: o3, layerCount: t49, viaDiameter: h3, obstacleMargin: d3, multiLayerThreshold: u3, narrowPadGapThreshold: p3, narrowPadGapNodeCount: m3.filter((t50) => t50._isNarrowQfpPadGap).length, topPadCount: a3.top.length, rightPadCount: a3.right.length, bottomPadCount: a3.bottom.length, leftPadCount: a3.left.length, multiLayerNodeCount: m3.filter((t50) => t50.availableZ.length > 1).length, totalMeshNodeCount: m3.length }, this.solved = true;
}
getOutput() {
if (!this.output)
throw new Error("QfpTopologyGeneratorSolver has not solved yet");
return this.output;
}
});
var G2 = 0.000001;
function U2({ nodeId: t49, bounds: e3, availableZ: n3, multiLayerThreshold: o3, regionType: i3, obstacleZ: r3 = [], connectedTo: s3 }) {
if (!function(t50) {
return t50.maxX - t50.minX > G2 && t50.maxY - t50.minY > G2;
}(e3))
return [];
const a3 = function(t50) {
return { center: { x: (t50.minX + t50.maxX) / 2, y: (t50.minY + t50.maxY) / 2 }, width: t50.maxX - t50.minX, height: t50.maxY - t50.minY };
}(e3), c3 = Math.min(a3.width, a3.height) > o3, l3 = c3 ? [{ availableZ: n3.filter((t50) => !r3.includes(t50)), containsObstacle: false }, { availableZ: n3.filter((t50) => r3.includes(t50)), containsObstacle: true }].filter((t50) => t50.availableZ.length > 0) : n3.map((t50) => ({ availableZ: [t50], containsObstacle: r3.includes(t50) }));
return l3.map((e4) => ({ capacityMeshNodeId: l3.length === 1 ? t49 : c3 ? `${t49}:${e4.containsObstacle ? "obstacle" : "free"}` : `${t49}:z${e4.availableZ[0]}`, center: a3.center, width: a3.width, height: a3.height, layer: `z${e4.availableZ.join(",")}`, availableZ: e4.availableZ, _soicRegionType: i3, _containsObstacle: e4.containsObstacle, _connectedTo: e4.containsObstacle ? s3 : undefined }));
}
function Z2(t49, e3) {
let n3 = 0, o3 = Number.POSITIVE_INFINITY;
for (let i3 = 0;i3 < e3.length; i3++) {
const r3 = Math.abs(t49 - e3[i3]);
r3 < o3 && (n3 = i3, o3 = r3);
}
return n3;
}
function q2(t49, e3) {
return t49.map((t50, n3) => ({ key: `pad:${t50.obstacleId ?? n3}`, bounds: Ee(t50), regionType: "pad", obstacleZ: M2(t50, e3), connectedTo: [...t50.connectedTo] }));
}
function J2(t49, e3) {
if (t49.componentId !== e3.componentId)
return false;
const { bounds: n3 } = e3;
return t49.center.x >= n3.minX && t49.center.x <= n3.maxX && t49.center.y >= n3.minY && t49.center.y <= n3.maxY;
}
function Q2({ detectedComponent: t49, inputSrj: e3 }) {
const n3 = e3.obstacles.filter((e4) => J2(e4, t49)), o3 = Array.from({ length: e3.layerCount }, (t50, e4) => e4), i3 = o3.map((t50) => Co(t50, e3.layerCount)), r3 = Array.from(new Set(n3.flatMap((t50) => t50.connectedTo))), { bounds: s3 } = t49;
return { obstacleId: `${t49.componentId}_component_bounds`, componentId: t49.componentId, type: "rect", layers: i3, __zLayers: o3, center: { x: (s3.minX + s3.maxX) / 2, y: (s3.minY + s3.maxY) / 2 }, width: s3.maxX - s3.minX, height: s3.maxY - s3.minY, connectedTo: r3 };
}
function K2(t49) {
if (t49.length === 0)
return { minX: 0, maxX: 0, minY: 0, maxY: 0 };
let { POSITIVE_INFINITY: e3, NEGATIVE_INFINITY: n3, POSITIVE_INFINITY: o3, NEGATIVE_INFINITY: i3 } = Number;
for (const r3 of t49) {
const t50 = Ee(r3);
e3 = Math.min(e3, t50.minX), n3 = Math.max(n3, t50.maxX), o3 = Math.min(o3, t50.minY), i3 = Math.max(i3, t50.maxY);
}
return { minX: e3, maxX: n3, minY: o3, maxY: i3 };
}
function t52(t49) {
const e3 = t49.componentDetectionOutput ?? [], n3 = function({ detectedComponents: t50, inputSrj: e4 }) {
return t50.map((t51) => {
const n4 = e4.obstacles.filter((e5) => J2(e5, t51));
return { componentId: t51.componentId, componentKind: t51.componentKind, memberObstacleIds: n4.map((e5, n5) => e5.obstacleId ?? `${t51.componentId}:member:${n5}`), memberObstacles: n4, replacementObstacle: Q2({ detectedComponent: t51, inputSrj: e4 }) };
});
}({ detectedComponents: e3, inputSrj: t49.inputSrj }), o3 = t49.globalNoConnectionSrj ?? (e3.length > 0 ? function({ detectedComponents: t50, inputSrj: e4 }) {
return { ...structuredClone(e4), obstacles: [...e4.obstacles.filter((e5) => !t50.some((t51) => J2(e5, t51))), ...t50.map((t51) => Q2({ detectedComponent: t51, inputSrj: e4 }))] };
}({ detectedComponents: e3, inputSrj: t49.inputSrj }) : t49.inputSrj) ?? t49.brokenSrj?.componentsAsObstaclesSrj, i3 = t49.components ?? n3 ?? t49.brokenSrj?.components ?? [];
if (!o3)
throw new Error("MultiGraphTopologyPlannerSolver requires globalNoConnectionSrj or detected components");
return { globalNoConnectionSrj: o3, components: i3 };
}
function e5({ rects: t49, components: e3 }) {
return t49 && e3.length !== 0 ? t49.filter((t50) => !function(t51) {
return typeof t51.label == "string" && t51.label.startsWith("node ");
}(t50) || !e3.some((e4) => function({ rect: t51, obstacle: e6 }) {
if (!t51.center || t51.width === undefined || t51.height === undefined)
return false;
const n3 = 0.000000001, o3 = We({ center: t51.center, width: t51.width, height: t51.height }), i3 = We({ center: e6.center, width: e6.width, height: e6.height });
return n5({ bounds: o3, outerBounds: i3, epsilon: n3 });
}({ rect: t50, obstacle: e4.replacementObstacle }))) : t49;
}
function n5({ bounds: t49, outerBounds: e3, epsilon: n3 }) {
return t49.minX >= e3.minX - n3 && t49.maxX <= e3.maxX + n3 && t49.minY >= e3.minY - n3 && t49.maxY <= e3.maxY + n3;
}
F1.register(class extends kt {
constructor(t49) {
super(), this.inputProblem = t49;
}
static componentKind = "soic";
output = null;
getConstructorParams() {
return [this.inputProblem];
}
_step() {
if (this.output)
return void (this.solved = true);
const { layerCount: t49, obstacles: e3 } = this.inputProblem.inputSrj, { bounds: n3, componentId: o3 } = this.inputProblem.detectedComponent, i3 = w2(t49), r3 = e3.filter((t50) => t50.componentId === o3), s3 = r3.length > 0 ? r3 : e3, a3 = function(t50) {
const e4 = N2(t50.map((t51) => t51.center.y)).length;
return N2(t50.map((t51) => t51.center.x)).length === 2 && e4 !== 2 ? "vertical-columns" : "horizontal-rows";
}(s3), c3 = function({ obstacles: t50, orientation: e4 }) {
const n4 = { left: [], right: [], top: [], bottom: [] };
if (e4 === "vertical-columns") {
const e6 = N2(t50.map((t51) => t51.center.x));
for (const o5 of t50)
n4[Z2(o5.center.x, e6) === 0 ? "left" : "right"].push(o5);
return n4.left.sort((t51, e7) => t51.center.y - e7.center.y), n4.right.sort((t51, e7) => t51.center.y - e7.center.y), n4;
}
const o4 = N2(t50.map((t51) => t51.center.y));
for (const e6 of t50)
n4[Z2(e6.center.y, o4) === 0 ? "top" : "bottom"].push(e6);
return n4.top.sort((t51, e6) => t51.center.x - e6.center.x), n4.bottom.sort((t51, e6) => t51.center.x - e6.center.x), n4;
}({ obstacles: s3, orientation: a3 }), l3 = function({ bounds: t50, orientation: e4, sideGroups: n4 }) {
return e4 === "vertical-columns" ? { minX: Math.max(...n4.left.map((t51) => Ee(t51).maxX)), maxX: Math.min(...n4.right.map((t51) => Ee(t51).minX)), minY: t50.minY, maxY: t50.maxY } : { minX: t50.minX, maxX: t50.maxX, minY: Math.max(...n4.top.map((t51) => Ee(t51).maxY)), maxY: Math.min(...n4.bottom.map((t51) => Ee(t51).minY)) };
}({ bounds: n3, orientation: a3, sideGroups: c3 }), h3 = o3, d3 = this.inputProblem.viaDiameter ?? Yo(this.inputProblem.inputSrj).padDiameter, u3 = this.inputProblem.obstacleMargin ?? this.inputProblem.inputSrj.defaultObstacleMargin ?? 0.15, p3 = 2 * (d3 + u3), m3 = a3 === "vertical-columns" ? ["left", "right"] : ["top", "bottom"], g3 = [{ key: "center", bounds: l3, regionType: "center" }, ...q2(s3, t49), ...m3.flatMap((t50) => function({ side: t51, sideObstacles: e4, bounds: n4, centralBounds: o4 }) {
const i4 = [];
for (let r4 = 0;r4 < e4.length - 1; r4++) {
const s4 = Ee(e4[r4]), a4 = Ee(e4[r4 + 1]);
let c4;
c4 = t51 === "left" ? { minX: n4.minX, maxX: o4.minX, minY: s4.maxY, maxY: a4.minY } : t51 === "right" ? { minX: o4.maxX, maxX: n4.maxX, minY: s4.maxY, maxY: a4.minY } : t51 === "top" ? { minX: s4.maxX, maxX: a4.minX, minY: n4.minY, maxY: o4.minY } : { minX: s4.maxX, maxX: a4.minX, minY: o4.maxY, maxY: n4.maxY }, i4.push({ key: `${t51}-gap-${r4}`, bounds: c4, regionType: "pad-gap" });
}
return i4;
}({ side: t50, sideObstacles: c3[t50], bounds: n3, centralBounds: l3 }))], f3 = g3.flatMap((t50) => U2({ nodeId: `soic:${h3}:${t50.key}`, bounds: t50.bounds, availableZ: i3, multiLayerThreshold: p3, regionType: t50.regionType, obstacleZ: t50.obstacleZ, connectedTo: t50.connectedTo }));
this.output = { routingRegions: f3 }, this.stats = { componentId: o3, layerCount: t49, orientation: a3, viaDiameter: d3, obstacleMargin: u3, multiLayerThreshold: p3, firstSidePadCount: c3[m3[0]].length, secondSidePadCount: c3[m3[1]].length, multiLayerNodeCount: f3.filter((t50) => t50.availableZ.length > 1).length, totalMeshNodeCount: f3.length }, this.solved = true;
}
getOutput() {
if (!this.output)
throw new Error("SoicTopologyGeneratorSolver has not solved yet");
return this.output;
}
});
var o5 = class extends kt {
constructor(t49) {
super(), this.inputProblem = t49;
}
activeSubSolver = null;
currentIndex = 0;
componentMeshNodes = [];
getConstructorParams() {
return [this.inputProblem];
}
_step() {
if (this.activeSubSolver) {
if (this.activeSubSolver.step(), this.activeSubSolver.failed)
return this.error = this.activeSubSolver.error, this.failed = true, void (this.activeSubSolver = null);
if (!this.activeSubSolver.solved)
return;
return this.componentMeshNodes.push(this.activeSubSolver.getOutput().routingRegions), this.currentIndex += 1, void (this.activeSubSolver = null);
}
if (this.currentIndex >= this.inputProblem.componentSrjs.length)
return void (this.solved = true);
const t49 = this.inputProblem.componentKinds[this.currentIndex], e3 = this.inputProblem.componentSrjs[this.currentIndex], n3 = { inputSrj: e3, detectedComponent: { componentId: this.inputProblem.componentIds[this.currentIndex], componentKind: t49, bounds: { __type: "rect", ...e3.bounds } }, viaDiameter: this.inputProblem.viaDiameter, obstacleMargin: this.inputProblem.obstacleMargin };
this.activeSubSolver = F1.create(n3);
}
getOutput() {
return { componentMeshNodes: this.componentMeshNodes };
}
visualize() {
if (this.activeSubSolver)
return this.activeSubSolver.visualize();
const t49 = this.inputProblem.componentSrjs[this.currentIndex] ?? null, e3 = this.componentMeshNodes.flatMap((t50) => t50);
return { rects: [...t49 ? [{ center: { x: (t49.bounds.minX + t49.bounds.maxX) / 2, y: (t49.bounds.minY + t49.bounds.maxY) / 2 }, width: t49.bounds.maxX - t49.bounds.minX, height: t49.bounds.maxY - t49.bounds.minY, fill: "rgba(0,0,0,0)", stroke: "rgba(255,140,0,0.72)", label: `active component ${this.inputProblem.componentIds[this.currentIndex] ?? this.currentIndex}` }, ...t49.obstacles.map((t50) => ({ center: t50.center, width: t50.width, height: t50.height, fill: "rgba(255,140,0,0.10)", stroke: "rgba(255,140,0,0.30)", label: t50.obstacleId ?? t50.componentId ?? "obstacle" }))] : [], ...e3.map((t50) => ({ ...AD(t50, { rectMargin: 0.01 }), fill: t50._containsObstacle ? "rgba(255,0,0,0.14)" : "rgba(0,120,255,0.12)", stroke: t50._containsObstacle ? "rgba(255,0,0,0.34)" : "rgba(0,120,255,0.38)" }))] };
}
};
var i5 = 0.001;
function r5(t49) {
const e3 = [...t49].sort((t50, e4) => t50 - e4), n3 = [];
for (const t50 of e3) {
const e4 = n3[n3.length - 1];
(e4 === undefined || Math.abs(t50 - e4) > i5) && n3.push(t50);
}
return n3;
}
function s5(t49) {
const e3 = Math.min(...t49), n3 = Math.max(...t49);
return !(e3 <= 0) && n3 / e3 <= 1.01;
}
function a5(t49) {
if (!function(t50) {
return s5(t50.map((t51) => t51.width)) && s5(t50.map((t51) => t51.height));
}(t49))
return false;
if (!function(t50) {
return t50.every((t51) => {
const e4 = Math.min(t51.width, t51.height), n4 = Math.max(t51.width, t51.height);
return !(e4 <= 0) && n4 / e4 <= 1.5;
});
}(t49))
return false;
const e3 = r5(t49.map((t50) => t50.center.y)), n3 = r5(t49.map((t50) => t50.center.x)), o3 = e3.length, i3 = n3.length;
if (o3 < 3 || i3 < 3)
return false;
const r3 = o3 * i3;
return !((r3 > 0 ? t49.length / r3 : 0) < 0.5) && !!function(t50, e4, n4) {
if (e4.length < 3)
return false;
if (n4.length < 3)
return false;
const o4 = new Set(e4.slice(1, -1)), i4 = new Set(n4.slice(1, -1));
let r4 = 0;
for (const e6 of t50)
o4.has(e6.center.y) && i4.has(e6.center.x) && (r4 += 1);
return r4 >= 1;
}(t49, e3, n3);
}
function c5(t49) {
return [Math.round(t49.width / i5), Math.round(t49.height / i5), t49.layers.join(",")].join(":");
}
function l5(t49) {
if (t49.length < 3)
return false;
const e3 = [...t49].sort((t50, e4) => t50 - e4), n3 = e3[1] - e3[0];
return !(n3 <= i5) && e3.every((t50, o3) => o3 === 0 || Math.abs(t50 - e3[o3 - 1] - n3) <= i5);
}
function h5(t49) {
const e3 = function(t50) {
const e4 = new Map;
for (const n4 of t50) {
const t51 = Math.round(n4.center.y / i5), o3 = Math.round(n4.center.x / i5), i3 = e4.get(t51) ?? { y: n4.center.y, obstaclesByX: new Map };
i3.obstaclesByX.set(o3, n4), e4.set(t51, i3);
}
return [...e4.values()];
}(t49);
let n3 = [];
for (const t50 of e3) {
const o3 = [...t50.obstaclesByX.keys()];
if (!l5([...t50.obstaclesByX.values()].map((t51) => t51.center.x)))
continue;
const i3 = e3.filter((t51) => o3.every((e4) => t51.obstaclesByX.has(e4)));
if (!l5(i3.map((t51) => t51.y)))
continue;
const r3 = i3.flatMap((t51) => o3.map((e4) => t51.obstaclesByX.get(e4)));
r3.length > n3.length && (n3 = r3);
}
return n3;
}
function d5(t49) {
if (a5(t49))
return t49;
const e3 = Map.groupBy(t49, c5);
let n3 = [];
for (const t50 of e3.values()) {
const e4 = h5(t50);
e4.length > n3.length && (n3 = e4);
}
return n3.length > 0 ? n3 : null;
}
function u5(t49) {
const e3 = Math.min(t49.width, t49.height), n3 = Math.max(t49.width, t49.height);
return e3 > 0 && n3 / e3 >= 1.5;
}
function p5({ perimeterPadObstacles: t49, thermalPadObstacles: e3 }) {
if (e3.length === 0)
return true;
if (e3.length > 4)
return false;
const n3 = K2(t49), o3 = n3.maxX - n3.minX, i3 = n3.maxY - n3.minY, r3 = n3.minX + 0.2 * o3, s3 = n3.maxX - 0.2 * o3, a3 = n3.minY + 0.2 * i3, c3 = n3.maxY - 0.2 * i3, l3 = Math.min(...t49.map((t50) => Math.min(t50.width, t50.height)));
return e3.every((t50) => {
const e4 = Math.min(t50.width, t50.height);
return t50.center.x >= r3 && t50.center.x <= s3 && t50.center.y >= a3 && t50.center.y <= c3 && e4 > l3;
});
}
function m5(t49) {
if (t49.length < 12)
return false;
if (t49.length > 32)
return false;
const { counts: e3, maxNearestSideRatio: n3 } = function(t50) {
const e4 = K2(t50), n4 = e4.maxX - e4.minX, o3 = e4.maxY - e4.minY, i3 = { top: 0, right: 0, bottom: 0, left: 0 };
if (n4 <= 0 || o3 <= 0)
return { counts: i3, maxNearestSideRatio: 1 };
let r3 = 0;
for (const s3 of t50) {
const t51 = s3.width > s3.height, a3 = [{ side: "top", distance: Math.abs(s3.center.y - e4.minY), axisSpan: o3, orientationMatches: !t51 }, { side: "right", distance: Math.abs(e4.maxX - s3.center.x), axisSpan: n4, orientationMatches: t51 }, { side: "bottom", distance: Math.abs(e4.maxY - s3.center.y), axisSpan: o3, orientationMatches: !t51 }, { side: "left", distance: Math.abs(s3.center.x - e4.minX), axisSpan: n4, orientationMatches: t51 }].filter((t53) => t53.orientationMatches).sort((t53, e6) => t53.distance - e6.distance)[0];
i3[a3.side] += 1, r3 = Math.max(r3, a3.distance / a3.axisSpan);
}
return { counts: i3, maxNearestSideRatio: r3 };
}(t49);
return e3.top >= 3 && e3.right >= 3 && e3.bottom >= 3 && e3.left >= 3 && n3 <= 0.25;
}
function g5(t49) {
const e3 = function(t50) {
return t50.filter(u5);
}(t49);
return { perimeterPadObstacles: e3, thermalPadObstacles: t49.filter((t50) => !u5(t50)) };
}
function f5(t49) {
const e3 = Math.min(...t49), n3 = Math.max(...t49);
return !(e3 <= 0) && n3 / e3 <= 1.01;
}
function y5(t49, e3) {
let n3 = 0, o3 = Number.POSITIVE_INFINITY;
for (let i3 = 0;i3 < e3.length; i3++) {
const r3 = Math.abs(t49 - e3[i3]);
r3 < o3 && (n3 = i3, o3 = r3);
}
return n3;
}
function _5({ memberObstacles: t49, inputSrj: e3 }) {
if (!function(t50) {
return f5(t50.map((t51) => t51.width)) && f5(t50.map((t51) => t51.height));
}(t49))
return false;
const n3 = r5(t49.map((t50) => t50.center.y)), o3 = r5(t49.map((t50) => t50.center.x));
if (!(n3.length === 2 && o3.length >= 4 || o3.length === 2 && n3.length >= 4))
return false;
const i3 = function({ memberObstacles: t50, rowAxisValues: e4, columnAxisValues: n4 }) {
if (e4.length === 2 && n4.length >= 4) {
const n6 = [[], []];
for (const o4 of t50)
n6[y5(o4.center.y, e4)].push(o4);
return Math.min(...n6[1].map((t51) => t51.center.y - t51.height / 2)) - Math.max(...n6[0].map((t51) => t51.center.y + t51.height / 2));
}
if (n4.length === 2 && e4.length >= 4) {
const e6 = [[], []];
for (const o4 of t50)
e6[y5(o4.center.x, n4)].push(o4);
return Math.min(...e6[1].map((t51) => t51.center.x - t51.width / 2)) - Math.max(...e6[0].map((t51) => t51.center.x + t51.width / 2));
}
return null;
}({ memberObstacles: t49, rowAxisValues: n3, columnAxisValues: o3 });
if (i3 === null)
return false;
return i3 > 2 * (Yo(e3).padDiameter + (e3.defaultObstacleMargin ?? 0.15));
}
var b5 = [class t49 {
constructor(t54) {
this.params = t54;
}
static componentKind = "qfp_thermalpad";
componentKind = t49.componentKind;
static isMatch({ memberObstacles: t54 }) {
return function(t55) {
const { perimeterPadObstacles: e3, thermalPadObstacles: n3 } = g5(t55);
return n3.length !== 0 && !!m5(e3) && p5({ perimeterPadObstacles: e3, thermalPadObstacles: n3 });
}(t54);
}
}, class t50 {
constructor(t54) {
this.params = t54;
}
static componentKind = "qfp";
componentKind = t50.componentKind;
static isMatch({ memberObstacles: t54 }) {
return function(t55) {
const { perimeterPadObstacles: e3, thermalPadObstacles: n3 } = g5(t55);
return !(n3.length > 0) && !!p5({ perimeterPadObstacles: e3, thermalPadObstacles: n3 }) && m5(e3);
}(t54);
}
}, class t51 {
constructor(t54) {
this.params = t54;
}
static componentKind = "soic";
componentKind = t51.componentKind;
static isMatch(t54) {
return _5(t54);
}
}, class t53 {
constructor(t54) {
this.params = t54;
}
static componentKind = "bga";
componentKind = t53.componentKind;
static isMatch({ memberObstacles: t54 }) {
return function(t55) {
return d5(t55) !== null;
}(t54);
}
}];
function x5(t54) {
return function(t55) {
for (const e3 of b5)
if (e3.isMatch(t55))
return new e3(t55);
return null;
}(t54)?.componentKind ?? null;
}
var v5 = class extends kt {
inputSrj;
initialized = false;
groupedComponentObstacles = {};
groupedComponentKinds = {};
unprocessedComponentIds = [];
detectedComponents = [];
currentComponentId = null;
currentMemberObstacles = [];
output = null;
constructor({ inputSrj: t54 }) {
super(), this.inputSrj = t54;
}
getConstructorParams() {
return [{ inputSrj: this.inputSrj }];
}
_step() {
this.initialized ? this.output ? this.solved = true : this.currentComponentId !== null || this.unprocessedComponentIds.length > 0 ? this.processNextComponent() : (this.finalizeOutput(), this.solved = true) : this.initializeDetectionState();
}
getOutput() {
if (!this.output)
throw new Error("ComponentDetectionSolver has not solved yet");
return this.output;
}
visualize() {
const t54 = [];
t54.push(...this.inputSrj.obstacles.filter((t55) => !t55.componentId).map((t55) => ({ center: t55.center, width: t55.width, height: t55.height, fill: "rgba(120, 120, 120, 0.10)", stroke: "rgba(120, 120, 120, 0.40)", label: t55.obstacleId, layer: t55.layers.join(","), step: 0 })));
const e3 = new Set(this.detectedComponents.map((t55) => t55.componentId));
for (const n3 of this.inputSrj.obstacles) {
if (!n3.componentId)
continue;
if (e3.has(n3.componentId))
continue;
const o3 = n3.componentId === this.currentComponentId, i3 = Oo(n3.componentId), r3 = this.groupedComponentKinds[n3.componentId];
t54.push({ center: n3.center, width: n3.width, height: n3.height, fill: Ao(i3, o3 ? 0.55 : 0.82), stroke: Ao(i3, o3 ? 0.1 : 0.45), label: r3 ? `${n3.componentId} ${r3.toUpperCase()}` : n3.componentId, layer: n3.layers.join(","), step: o3 ? 1 : 0 });
}
for (const e4 of this.detectedComponents) {
const n3 = Oo(e4.componentId);
t54.push({ center: { x: (e4.bounds.minX + e4.bounds.maxX) / 2, y: (e4.bounds.minY + e4.bounds.maxY) / 2 }, width: e4.bounds.maxX - e4.bounds.minX, height: e4.bounds.maxY - e4.bounds.minY, fill: Ao(n3, 0.88), stroke: Ao(n3, 0.1), label: `${e4.componentId} ${e4.componentKind.toUpperCase()} region`, step: 2 });
}
return { title: this.getVisualizationTitle(), rects: t54, lines: [], points: [], circles: [] };
}
preview() {
return this.visualize();
}
initializeDetectionState() {
this.initialized = true, this.groupedComponentKinds = {}, this.groupedComponentObstacles = this.groupObstaclesByComponentId({ obstacles: this.inputSrj.obstacles }), this.unprocessedComponentIds = Object.keys(this.groupedComponentObstacles).sort(), this.detectedComponents = [], this.currentComponentId = null, this.currentMemberObstacles = [], this.output = null;
}
processNextComponent() {
if (!this.currentComponentId) {
const t54 = this.unprocessedComponentIds.shift();
return t54 ? (this.currentComponentId = t54, void (this.currentMemberObstacles = this.groupedComponentObstacles[t54] ?? [])) : (this.currentComponentId = null, void (this.currentMemberObstacles = []));
}
if (this.currentMemberObstacles.length === 0)
return this.currentComponentId = null, void (this.currentMemberObstacles = []);
this.detectedComponents.push(this.createDetectedComponent({ componentId: this.currentComponentId, componentKind: this.groupedComponentKinds[this.currentComponentId], memberObstacles: this.currentMemberObstacles })), this.currentComponentId = null, this.currentMemberObstacles = [];
}
finalizeOutput() {
this.output = this.detectedComponents.map((t54) => ({ ...t54, bounds: { ...t54.bounds } })), this.stats = { initialized: this.initialized, totalComponentCount: Object.keys(this.groupedComponentObstacles).length, detectedComponentCount: this.detectedComponents.length, detectedBgaComponentCount: this.detectedComponents.filter((t54) => t54.componentKind === "bga").length, detectedQfpComponentCount: this.detectedComponents.filter((t54) => t54.componentKind === "qfp").length, detectedQfpComponentIds: this.detectedComponents.filter((t54) => t54.componentKind === "qfp").map((t54) => t54.componentId), detectedQfpThermalPadComponentCount: this.detectedComponents.filter((t54) => t54.componentKind === "qfp_thermalpad").length, detectedQfpThermalPadComponentIds: this.detectedComponents.filter((t54) => t54.componentKind === "qfp_thermalpad").map((t54) => t54.componentId), detectedSoicComponentCount: this.detectedComponents.filter((t54) => t54.componentKind === "soic").length, detectedSoicComponentIds: this.detectedComponents.filter((t54) => t54.componentKind === "soic").map((t54) => t54.componentId), remainingComponentCount: this.unprocessedComponentIds.length, hasActiveComponent: this.currentComponentId !== null };
}
groupObstaclesByComponentId({ obstacles: t54 }) {
const e3 = {}, n3 = {};
for (const n4 of t54)
n4.componentId && (e3[n4.componentId] ??= [], e3[n4.componentId].push(n4));
const o3 = Object.entries(e3).flatMap(([t55, e4]) => {
const o4 = this.inputSrj.bounds;
if (e4.some((t56) => !n5({ bounds: Ee(t56), outerBounds: o4, epsilon: 0 })))
return [];
const i3 = x5({ memberObstacles: e4, inputSrj: this.inputSrj });
if (!i3)
return [];
n3[t55] = i3;
return [[t55, i3 === "bga" ? d5(e4) : e4]];
});
return this.groupedComponentKinds = n3, Object.fromEntries(o3);
}
createDetectedComponent({ componentId: t54, componentKind: e3, memberObstacles: n3 }) {
return { componentId: t54, componentKind: e3, bounds: { __type: "rect", ...K2(n3) } };
}
getVisualizationTitle() {
const t54 = Object.keys(this.groupedComponentObstacles).length || new Set(this.inputSrj.obstacles.map((t55) => t55.componentId).filter((t55) => Boolean(t55))).size, e3 = this.detectedComponents.length;
return this.initialized ? this.output || this.solved ? `Component Detection: done ${e3}/${t54}` : this.currentComponentId !== null || this.unprocessedComponentIds.length > 0 ? `Component Detection: ${e3}/${t54} processed` : `Component Detection: finalizing ${e3}/${t54}` : "Component Detection: setup";
}
};
var I5 = (t54) => t54.componentId && t54.obstacleId ? `${t54.componentId}
${t54.obstacleId}` : t54.componentId ?? t54.obstacleId ?? "obstacle";
var S5 = class extends Lt {
rectBoundsComponentDetection;
pipelineDef = [Dt("rectBoundsComponentDetection", v5, (t54) => [{ inputSrj: t54.inputProblem.inputSrj }])];
getConstructorParams() {
return [this.inputProblem];
}
getOutput() {
const t54 = this.getStageOutput("rectBoundsComponentDetection");
if (!t54)
throw new Error("ComponentDetectionSolver has not solved yet");
return t54;
}
initialVisualize() {
const { bounds: t54 } = this.inputProblem.inputSrj;
return { title: "Component Detection: board and grouped component pads", rects: [{ center: { x: (t54.minX + t54.maxX) / 2, y: (t54.minY + t54.maxY) / 2 }, width: t54.maxX - t54.minX, height: t54.maxY - t54.minY, fill: "rgba(0, 0, 0, 0)", stroke: "rgba(40, 40, 40, 0.7)", label: "Board bounds", step: 0 }, ...this.inputProblem.inputSrj.obstacles.map((t55) => {
const e3 = t55.componentId ? Oo(t55.componentId) : null;
return { center: t55.center, width: t55.width, height: t55.height, fill: e3 ? Ao(e3, 0.72) : "rgba(120, 120, 120, 0.10)", stroke: e3 ? Ao(e3, 0.28) : "rgba(120, 120, 120, 0.40)", label: I5(t55), layer: t55.layers.join(","), step: t55.componentId ? 1 : 0 };
})], lines: [], points: [], circles: [] };
}
};
var C5 = 0.000000001;
function P5(t54) {
return We({ center: t54.center, width: t54.width, height: t54.height });
}
function M5(t54, e3) {
const n3 = { minX: Math.max(t54.minX, e3.minX), maxX: Math.min(t54.maxX, e3.maxX), minY: Math.max(t54.minY, e3.minY), maxY: Math.min(t54.maxY, e3.maxY) };
return N5(n3) ? n3 : null;
}
function N5(t54) {
const e3 = t54.maxX - t54.minX, n3 = t54.maxY - t54.minY, o3 = Number.isFinite(e3) && e3 > C5, i3 = Number.isFinite(n3) && n3 > C5;
return o3 && i3;
}
function w5(t54) {
(function(t55) {
if (!Number.isInteger(t55.layerCount))
throw new Error("TopologyMergingSolver: layerCount must be an integer");
if (t55.layerCount <= 0)
throw new Error("TopologyMergingSolver: layerCount must be positive");
if (t55.nodeGroups.length === 0)
throw new Error("TopologyMergingSolver: at least one node group is required");
const e4 = new Set;
let n4 = 0;
for (const o3 of t55.nodeGroups) {
if (e4.has(o3.groupId))
throw new Error(`TopologyMergingSolver: duplicate topology group id "${o3.groupId}"`);
if (e4.add(o3.groupId), n4 += o3.nodes.length, o3.nodes.length === 0)
throw new Error(`TopologyMergingSolver: topology group "${o3.groupId}" is empty`);
const i3 = new Set;
for (const e6 of o3.nodes) {
if (i3.has(e6.capacityMeshNodeId))
throw new Error(`TopologyMergingSolver: duplicate node id "${e6.capacityMeshNodeId}" in group "${o3.groupId}"`);
i3.add(e6.capacityMeshNodeId), T5({ node: e6, groupId: o3.groupId, layerCount: t55.layerCount });
}
}
if (n4 === 0)
throw new Error("TopologyMergingSolver: topology node groups are empty");
})(t54);
const e3 = [], n3 = new Map;
for (let o3 = 0;o3 < t54.nodeGroups.length; o3++) {
const i3 = t54.nodeGroups[o3];
for (const t55 of i3.nodes) {
const r3 = { sourceKey: `${i3.groupId}:${t55.capacityMeshNodeId}`, groupIndex: o3, node: t55, bounds: P5(t55) };
e3.push(r3), n3.set(r3.sourceKey, r3);
}
}
return { preparedNodes: e3, preparedNodeBySourceKey: n3 };
}
function T5({ node: t54, groupId: e3, layerCount: n3 }) {
if (!N5(P5(t54)))
throw new Error(`TopologyMergingSolver: node "${t54.capacityMeshNodeId}" in group "${e3}" has invalid bounds`);
if (t54.availableZ.length === 0)
throw new Error(`TopologyMergingSolver: node "${t54.capacityMeshNodeId}" in group "${e3}" has no available layers`);
const o3 = [...new Set(t54.availableZ)].sort((t55, e4) => t55 - e4), i3 = o3.some((t55) => !Number.isInteger(t55) || t55 < 0 || t55 >= n3), r3 = o3.length === t54.availableZ.length && o3.every((e4, n4) => e4 === t54.availableZ[n4]);
if (i3 || !r3)
throw new Error(`TopologyMergingSolver: node "${t54.capacityMeshNodeId}" in group "${e3}" has invalid or unsorted availableZ`);
}
var R5 = 0.00001;
var E5 = 0.00004;
function A5({ regions: t54, preparedNodeBySourceKey: e3, nodeGroups: n3, provenance: o3, preserveSourceIds: i3 = true }) {
i3 && (o3.groupIndexesByNodeId.clear(), o3.sourceKeysByNodeId.clear());
const r3 = [...t54].sort((t55, e4) => t55.bounds.minX - e4.bounds.minX || t55.bounds.minY - e4.bounds.minY || t55.bounds.maxX - e4.bounds.maxX || t55.bounds.maxY - e4.bounds.maxY || t55.availableZ[0] - e4.availableZ[0]), s3 = new Set;
return r3.map((t55, r4) => {
const a3 = t55.sourceKeys.map((t56) => {
const n4 = e3.get(t56);
if (!n4)
throw new Error(`TopologyMergingSolver: missing source node for "${t56}"`);
return n4;
}), c3 = a3.map(({ node: t56 }) => t56), l3 = function({ sourceNodes: t56, isComponentTopologyNode: e4 }) {
if (t56.length === 1)
return { _isComponentTopologyNode: !!e4 || t56[0]._isComponentTopologyNode };
const n4 = t56.map((t57) => t57.capacityMeshNodeId), o4 = O5(t56.map((t57) => t57._targetConnectionName), "target connection", n4), i4 = O5(t56.map((t57) => t57._offBoardConnectionId), "off-board connection", n4), r6 = O5(t56.map((t57) => t57._offboardNetName), "off-board net", n4), s4 = Array.from(new Set(t56.flatMap((t57) => t57._offBoardConnectedCapacityMeshNodeIds ?? []))), a4 = Array.from(new Set(t56.flatMap((t57) => t57._connectedTo ?? [])));
return { _containsObstacle: t56.some((t57) => t57._containsObstacle) || undefined, _completelyInsideObstacle: t56.some((t57) => t57._completelyInsideObstacle) || undefined, _containsTarget: t56.some((t57) => t57._containsTarget) || undefined, _targetConnectionName: o4, _isVirtualOffboard: t56.some((t57) => t57._isVirtualOffboard) || undefined, _offboardNetName: r6, _offBoardConnectionId: i4, _offBoardConnectedCapacityMeshNodeIds: s4.length > 0 ? s4 : undefined, _qfpRegionType: k5(t56.map((t57) => t57._qfpRegionType)), _isNarrowQfpPadGap: t56.some((t57) => t57._isNarrowQfpPadGap) || undefined, _soicRegionType: k5(t56.map((t57) => t57._soicRegionType)), _isComponentTopologyNode: e4 || undefined, _connectedTo: a4.length > 0 ? a4 : undefined };
}({ sourceNodes: c3, isComponentTopologyNode: a3.some(({ groupIndex: t56 }) => n3[t56].isComponent) }), h3 = i3 && a3.length === 1 ? a3[0].node : null, d3 = Boolean(h3 && function({ region: t56, sourceNode: e4, usedNodeIds: n4 }) {
const o4 = P5(e4), i4 = Math.abs(t56.bounds.minX - o4.minX) <= R5 && Math.abs(t56.bounds.maxX - o4.maxX) <= R5 && Math.abs(t56.bounds.minY - o4.minY) <= R5 && Math.abs(t56.bounds.maxY - o4.maxY) <= R5, r6 = t56.availableZ.length === e4.availableZ.length && t56.availableZ.every((t57, n6) => t57 === e4.availableZ[n6]);
return i4 && r6 && !n4.has(e4.capacityMeshNodeId);
}({ region: t55, sourceNode: h3, usedNodeIds: s3 }));
let u3 = d3 ? h3.capacityMeshNodeId : `topology_merge_${r4}`;
for (;s3.has(u3); )
u3 = `${u3}_next`;
return s3.add(u3), i3 && (o3.groupIndexesByNodeId.set(u3, [...new Set(a3.map(({ groupIndex: t56 }) => t56))]), o3.sourceKeysByNodeId.set(u3, [...t55.sourceKeys])), { ...h3 ?? c3[0], ...l3, capacityMeshNodeId: u3, center: { x: (t55.bounds.minX + t55.bounds.maxX) / 2, y: (t55.bounds.minY + t55.bounds.maxY) / 2 }, width: t55.bounds.maxX - t55.bounds.minX, height: t55.bounds.maxY - t55.bounds.minY, layer: `z${t55.availableZ.join(",")}`, availableZ: [...t55.availableZ], _adjacentNodeIds: undefined, _parent: undefined, _strawNode: undefined, _strawParentCapacityMeshNodeId: undefined };
});
}
function O5(t54, e3, n3) {
const o3 = Array.from(new Set(t54.filter((t55) => t55 !== undefined)));
if (o3.length > 1)
throw new Error(`TopologyMergingSolver: conflicting ${e3} values for overlapping source nodes ${n3.join(", ")}`);
return o3[0];
}
function k5(t54) {
const e3 = Array.from(new Set(t54.filter((t55) => t55 !== undefined)));
return e3.length === 1 ? e3[0] : undefined;
}
function D5({ node: t54, sourceKey: e3, preparedNodeBySourceKey: n3 }) {
const o3 = n3.get(e3);
if (!o3)
throw new Error(`TopologyMergingSolver: missing source node for output "${t54.capacityMeshNodeId}"`);
const i3 = P5(t54), r3 = i3.minX >= o3.bounds.minX - E5 && i3.maxX <= o3.bounds.maxX + E5 && i3.minY >= o3.bounds.minY - E5 && i3.maxY <= o3.bounds.maxY + E5, s3 = t54.availableZ.every((t55) => o3.node.availableZ.includes(t55));
if (!r3 || !s3)
throw new Error(`TopologyMergingSolver: output node "${t54.capacityMeshNodeId}" escapes its source geometry or layers`);
}
function L5({ groupIndexesA: t54, groupIndexesB: e3, sourceKeysA: n3, sourceKeysB: o3, sharedLayers: i3, preparedNodeBySourceKey: r3 }) {
if (t54.length !== 1 || e3.length !== 1 || t54[0] !== e3[0] || n3.length !== 1 || o3.length !== 1 || n3[0] === o3[0])
return false;
const s3 = r3.get(n3[0]), a3 = r3.get(o3[0]);
if (!s3 || !a3 || i3.length === 0)
return false;
return i3.some((t55) => s3.node.availableZ.includes(t55) && a3.node.availableZ.includes(t55)) && M5(s3.bounds, a3.bounds) !== null;
}
function z5(t54) {
const e3 = [...t54].sort((t55, e4) => t55 - e4), n3 = [];
for (const t55 of e3) {
const e4 = n3[n3.length - 1];
(e4 === undefined || Math.abs(t55 - e4) > R5) && n3.push(t55);
}
return n3;
}
function B5(t54, e3) {
return e3.x >= t54.minX - R5 && e3.x <= t54.maxX + R5 && e3.y >= t54.minY - R5 && e3.y <= t54.maxY + R5;
}
function F5({ coveringNodes: t54, nodeGroups: e3, layerCount: n3 }) {
const o3 = new Map;
for (let i3 = 0;i3 < n3; i3++) {
const n4 = t54.filter(({ node: t55 }) => t55.availableZ.includes(i3)).sort((t55, e4) => t55.sourceKey.localeCompare(e4.sourceKey));
if (n4.length === 0)
continue;
const r3 = new Set(n4.map(({ groupIndex: t55 }) => t55)), s3 = n4.filter(({ node: t55 }) => t55._containsObstacle && t55._containsTarget), a3 = s3.filter(({ groupIndex: t55 }) => !e3[t55].isComponent), c3 = new Set(s3.map(({ groupIndex: t55 }) => t55)), l3 = s3.length > 0 ? a3.length > 0 || c3.size === 1 ? "target-passthrough" : "target-merged" : r3.size === 1 ? "passthrough" : "merged", h3 = W5({ topologyMode: l3, nodesOnLayer: n4, targetObstacleNodes: s3, globalTargetObstacleNodes: a3 });
for (const t55 of h3) {
const e4 = JSON.stringify({ mode: l3, sourceKeys: t55 }), n6 = o3.get(e4);
n6 ? n6.availableZ.push(i3) : o3.set(e4, { availableZ: [i3], sourceKeys: t55, topologyMode: l3, topologySignature: e4 });
}
}
return [...o3.values()];
}
function j5(t54) {
return JSON.stringify({ availableZ: t54.availableZ, topologySignature: t54.topologySignature });
}
function $5(t54) {
return JSON.stringify({ mergeKey: j5(t54), minY: t54.bounds.minY.toPrecision(15), maxY: t54.bounds.maxY.toPrecision(15) });
}
function Y5(t54) {
return JSON.stringify({ mergeKey: j5(t54), minX: t54.bounds.minX.toPrecision(15), maxX: t54.bounds.maxX.toPrecision(15) });
}
function X5(t54, e3) {
const n3 = new Map;
for (const o3 of t54) {
const t55 = e3 === "horizontal" ? $5(o3) : Y5(o3), i3 = n3.get(t55) ?? [];
i3.push(o3), n3.set(t55, i3);
}
return [...n3.values()].flatMap((t55) => function(t56, e4) {
const n4 = [...t56].sort((t57, n6) => e4 === "horizontal" ? t57.bounds.minX - n6.bounds.minX : t57.bounds.minY - n6.bounds.minY), o3 = [];
for (const t57 of n4) {
const n6 = o3[o3.length - 1], i3 = n6 !== undefined && (e4 === "horizontal" ? Math.abs(n6.bounds.maxX - t57.bounds.minX) <= R5 : Math.abs(n6.bounds.maxY - t57.bounds.minY) <= R5);
n6 && i3 ? e4 === "horizontal" ? n6.bounds.maxX = t57.bounds.maxX : n6.bounds.maxY = t57.bounds.maxY : o3.push({ ...t57, bounds: { ...t57.bounds }, availableZ: [...t57.availableZ], sourceKeys: [...t57.sourceKeys] });
}
return o3;
}(t55, e3));
}
function W5({ topologyMode: t54, nodesOnLayer: e3, targetObstacleNodes: n3, globalTargetObstacleNodes: o3 }) {
if (t54 === "target-passthrough") {
return (o3.length > 0 ? o3 : n3).map(({ sourceKey: t55 }) => [t55]);
}
return t54 === "target-merged" ? [n3.map(({ sourceKey: t55 }) => t55).sort()] : t54 === "passthrough" ? e3.map(({ sourceKey: t55 }) => [t55]) : [e3.map(({ sourceKey: t55 }) => t55).sort()];
}
var V5 = class extends kt {
constructor(t54) {
super(), this.inputProblem = t54, this.MAX_ITERATIONS = 1e5;
const { preparedNodes: e3, preparedNodeBySourceKey: n3 } = w5(t54);
this.preparedNodes = e3, this.preparedNodeBySourceKey = n3, this.xCoordinates = z5(this.preparedNodes.flatMap(({ bounds: t55 }) => [t55.minX, t55.maxX])), this.stats = { inputNodeCount: this.preparedNodes.length, xSlabCount: Math.max(0, this.xCoordinates.length - 1), processedXSlabCount: 0, atomicRegionCount: 0, outputNodeCount: 0 };
}
preparedNodes;
preparedNodeBySourceKey;
outputProvenance = { groupIndexesByNodeId: new Map, sourceKeysByNodeId: new Map };
xCoordinates;
atomicRegions = [];
outputNodes = [];
currentXIndex = 0;
getConstructorParams() {
return [this.inputProblem];
}
_step() {
if (this.inputProblem.nodeGroups.length === 1)
return void this.completePassthroughTopology();
if (this.currentXIndex < this.xCoordinates.length - 1)
return this.processCurrentXSlab(), this.currentXIndex += 1, this.stats.processedXSlabCount = this.currentXIndex, void (this.stats.atomicRegionCount = this.atomicRegions.length);
const t54 = function(t55) {
let e3 = t55;
for (;; ) {
const t56 = X5(e3, "horizontal"), n3 = X5(t56, "vertical");
if (n3.length === e3.length)
return n3;
e3 = n3;
}
}(function({ regions: t55, preparedNodeBySourceKey: e3 }) {
const n3 = new Map;
for (const e4 of t55)
for (const t56 of e4.sourceKeys) {
const o4 = n3.get(t56) ?? new Set;
o4.add(e4.topologyMode), n3.set(t56, o4);
}
const o3 = new Set([...n3.entries()].filter(([, t56]) => t56.size === 1 && t56.has("target-passthrough")).map(([t56]) => t56));
return o3.size === 0 ? t55 : [...t55.filter((t56) => t56.topologyMode !== "target-passthrough" || !o3.has(t56.sourceKeys[0])), ...[...o3].map((t56) => {
const n4 = e3.get(t56);
if (!n4)
throw new Error(`TopologyMergingSolver: missing authoritative target source "${t56}"`);
return { bounds: { ...n4.bounds }, availableZ: [...n4.node.availableZ], sourceKeys: [t56], topologyMode: "target-passthrough", topologySignature: JSON.stringify({ mode: "target-passthrough", sourceKeys: [t56] }) };
})];
}({ regions: this.atomicRegions, preparedNodeBySourceKey: this.preparedNodeBySourceKey }));
this.outputNodes = A5({ regions: t54, preparedNodeBySourceKey: this.preparedNodeBySourceKey, nodeGroups: this.inputProblem.nodeGroups, provenance: this.outputProvenance }), function({ nodes: t55, preparedNodeBySourceKey: e3, provenance: n3 }) {
const o3 = new Set;
for (const i3 of t55) {
if (o3.has(i3.capacityMeshNodeId))
throw new Error(`TopologyMergingSolver: duplicate output node id "${i3.capacityMeshNodeId}"`);
if (o3.add(i3.capacityMeshNodeId), !N5(P5(i3)))
throw new Error(`TopologyMergingSolver: output node "${i3.capacityMeshNodeId}" has invalid bounds`);
if (i3.availableZ.length === 0)
throw new Error(`TopologyMergingSolver: output node "${i3.capacityMeshNodeId}" has no available layers`);
const t56 = n3.sourceKeysByNodeId.get(i3.capacityMeshNodeId);
if (!t56)
throw new Error(`TopologyMergingSolver: missing output provenance for node "${i3.capacityMeshNodeId}"`);
t56.length === 1 && D5({ node: i3, sourceKey: t56[0], preparedNodeBySourceKey: e3 });
}
for (let o4 = 0;o4 < t55.length; o4++) {
const i3 = t55[o4];
for (let r3 = o4 + 1;r3 < t55.length; r3++) {
const o6 = t55[r3], s3 = i3.availableZ.filter((t56) => o6.availableZ.includes(t56));
if (s3.length === 0)
continue;
const a3 = M5(P5(i3), P5(o6));
if (!a3)
continue;
const c3 = a3.maxX - a3.minX, l3 = a3.maxY - a3.minY;
if (c3 <= E5 || l3 <= E5)
continue;
const h3 = n3.groupIndexesByNodeId.get(i3.capacityMeshNodeId), d3 = n3.groupIndexesByNodeId.get(o6.capacityMeshNodeId);
if (!h3 || !d3)
throw new Error(`TopologyMergingSolver: missing output provenance for overlapping nodes "${i3.capacityMeshNodeId}" and "${o6.capacityMeshNodeId}"`);
const u3 = n3.sourceKeysByNodeId.get(i3.capacityMeshNodeId), p3 = n3.sourceKeysByNodeId.get(o6.capacityMeshNodeId);
if (!u3 || !p3)
throw new Error(`TopologyMergingSolver: missing source provenance for overlapping nodes "${i3.capacityMeshNodeId}" and "${o6.capacityMeshNodeId}"`);
if (!L5({ groupIndexesA: h3, groupIndexesB: d3, sourceKeysA: u3, sourceKeysB: p3, sharedLayers: s3, preparedNodeBySourceKey: e3 }))
throw new Error(`TopologyMergingSolver: output nodes "${i3.capacityMeshNodeId}" and "${o6.capacityMeshNodeId}" have an unresolved inter-group overlap on a shared layer`);
}
}
}({ nodes: this.outputNodes, preparedNodeBySourceKey: this.preparedNodeBySourceKey, provenance: this.outputProvenance }), this.stats.outputNodeCount = this.outputNodes.length, this.stats.compactedRegionCount = t54.length, this.solved = true;
}
getOutput() {
if (!this.solved)
throw new Error("TopologyMergingSolver: getOutput() called before the solver completed");
return this.outputNodes;
}
computeProgress() {
const t54 = Math.max(1, this.xCoordinates.length - 1);
return this.solved ? 1 : Math.min(0.99, this.currentXIndex / t54);
}
visualize() {
const t54 = this.solved ? this.outputNodes : A5({ regions: this.atomicRegions, preparedNodeBySourceKey: this.preparedNodeBySourceKey, nodeGroups: this.inputProblem.nodeGroups, provenance: this.outputProvenance, preserveSourceIds: false });
return { title: `Topology Merging: ${t54.length} refined regions`, coordinateSystem: "cartesian", rects: t54.map((t55) => ({ ...AD(t55, { rectMargin: 0.01, zOffset: 0.02 }), label: `${t55.capacityMeshNodeId}
availableZ: ${t55.availableZ.join(",")}
component: ${t55._isComponentTopologyNode ? "yes" : "no"}` })), lines: [], points: [], circles: [], texts: [] };
}
completePassthroughTopology() {
const t54 = this.inputProblem.nodeGroups[0];
this.outputNodes = t54.nodes;
for (const e3 of this.outputNodes)
this.outputProvenance.groupIndexesByNodeId.set(e3.capacityMeshNodeId, [0]), this.outputProvenance.sourceKeysByNodeId.set(e3.capacityMeshNodeId, [`${t54.groupId}:${e3.capacityMeshNodeId}`]);
this.stats.processedXSlabCount = this.stats.xSlabCount, this.stats.atomicRegionCount = 0, this.stats.compactedRegionCount = 0, this.stats.outputNodeCount = this.outputNodes.length, this.stats.passthroughNodeCount = this.outputNodes.length, this.solved = true;
}
processCurrentXSlab() {
const t54 = this.xCoordinates[this.currentXIndex], e3 = this.xCoordinates[this.currentXIndex + 1];
if (e3 - t54 <= R5)
return;
const n3 = (t54 + e3) / 2, o3 = this.preparedNodes.filter(({ bounds: t55 }) => n3 >= t55.minX - R5 && n3 <= t55.maxX + R5), i3 = z5(o3.flatMap(({ bounds: t55 }) => [t55.minY, t55.maxY]));
for (let r3 = 0;r3 < i3.length - 1; r3++) {
const s3 = i3[r3], a3 = i3[r3 + 1];
if (a3 - s3 <= R5)
continue;
const c3 = { x: n3, y: (s3 + a3) / 2 }, l3 = o3.filter(({ bounds: t55 }) => B5(t55, c3));
if (l3.length === 0)
continue;
const h3 = F5({ coveringNodes: l3, nodeGroups: this.inputProblem.nodeGroups, layerCount: this.inputProblem.layerCount });
for (const n4 of h3)
this.atomicRegions.push({ bounds: { minX: t54, maxX: e3, minY: s3, maxY: a3 }, availableZ: n4.availableZ, sourceKeys: n4.sourceKeys, topologyMode: n4.topologyMode, topologySignature: n4.topologySignature });
}
}
};
function H5({ meshNodes: t54, components: e3 }) {
return e3.length === 0 ? t54 : t54.map((t55) => {
const n3 = e3.some((e4) => function({ node: t56, component: e6 }) {
const { replacementObstacle: n4 } = e6, o3 = Math.abs(t56.center.x - n4.center.x) <= C5 && Math.abs(t56.center.y - n4.center.y) <= C5 && Math.abs(t56.width - n4.width) <= C5 && Math.abs(t56.height - n4.height) <= C5;
if (e6.componentKind !== "qfp" && e6.componentKind !== "qfp_thermalpad" && e6.componentKind !== "soic")
return o3;
const i3 = n4.center.x - n4.width / 2, r3 = n4.center.x + n4.width / 2, s3 = n4.center.y - n4.height / 2, a3 = n4.center.y + n4.height / 2, c3 = t56.center.x >= i3 - C5 && t56.center.x <= r3 + C5 && t56.center.y >= s3 - C5 && t56.center.y <= a3 + C5, l3 = t56.width * t56.height, h3 = n4.width * n4.height, d3 = c3 && l3 >= 0.2 * h3;
return o3 || d3;
}({ node: t55, component: e4 }));
return n3 ? { ...t55, _containsObstacle: undefined, _completelyInsideObstacle: undefined, _containsTarget: undefined, _targetConnectionName: undefined, _connectedTo: undefined } : t55;
});
}
var G5 = class extends Lt {
globalTopologySolver;
componentTopologyBatchSolver;
normalizedInput;
pipelineDef = [Dt("globalTopologySolver", Qn, (t54) => [t54.getGlobalTopologySolverInput()]), Dt("componentTopologyBatchSolver", o5, (t54) => [{ componentSrjs: t54.getComponentNoConnectionSrjs(), componentIds: t54.normalizedInput.components.map((t55) => t55.componentId), componentKinds: t54.normalizedInput.components.map((t55) => t55.componentKind), viaDiameter: t54.inputProblem.viaDiameter, obstacleMargin: t54.inputProblem.obstacleMargin }])];
constructor(t54) {
super(t54), this.normalizedInput = t52(t54);
}
getConstructorParams() {
return [this.inputProblem];
}
getOutput() {
const t54 = H5({ meshNodes: this.getStageOutput("globalTopologySolver")?.meshNodes ?? [], components: this.normalizedInput.components }), e3 = this.getStageOutput("componentTopologyBatchSolver")?.componentMeshNodes ?? [], n3 = this.getComponentNoConnectionSrjs();
return { globalNoConnectionSrj: this.normalizedInput.globalNoConnectionSrj, componentNoConnectionSrjs: n3, globalMeshNodes: t54, componentMeshNodes: e3 };
}
finalVisualize() {
const t54 = this.getOutput();
return { title: "Topology Planning: generated topology groups", rects: [...t54.componentNoConnectionSrjs.flatMap((t55, e3) => {
const n3 = this.normalizedInput.components[e3] ?? null;
return t55.obstacles.map((t56) => ({ center: t56.center, width: t56.width, height: t56.height, fill: "rgba(120, 120, 120, 0.06)", stroke: "rgba(120, 120, 120, 0.35)", label: t56.obstacleId ?? n3?.componentId ?? "component-pad", layer: t56.layers.join(",") }));
}), ...[...t54.globalMeshNodes, ...t54.componentMeshNodes.flat()].map((t55) => {
const e3 = this.normalizedInput.components.find((e4) => t55.capacityMeshNodeId.includes(e4.componentId));
return { ...AD(t55, { rectMargin: 0.01 }), fill: t55._containsObstacle ? Ao("red", 0.82) : "rgba(0, 120, 255, 0.12)", stroke: t55._containsObstacle ? Ao("red", 0.3) : "rgba(0, 120, 255, 0.55)", label: e3 ? `${e3.componentKind.toUpperCase()} ${t55.capacityMeshNodeId}` : t55.capacityMeshNodeId };
})], lines: [], points: [], circles: [], texts: [] };
}
visualize() {
return this.filterGlobalRectDiffNodesFromVisualization({ visualization: super.visualize() });
}
preview() {
return this.filterGlobalRectDiffNodesFromVisualization({ visualization: super.preview() });
}
getComponentNoConnectionSrjs() {
return this.normalizedInput.components.map((t54) => function({ inputSrj: t55, component: e3 }) {
const n3 = K2(e3.memberObstacles), o3 = Math.max(t55.minViaPadDiameter ?? t55.min_via_pad_diameter ?? t55.minViaDiameter ?? 0.3, t55.defaultObstacleMargin ?? 0.15, 2 * t55.minTraceWidth), i3 = new Set(e3.memberObstacles.flatMap((t56) => t56.connectedTo)), r3 = t55.connections.flatMap((t56) => t56.pointsToConnect.filter((t57) => {
const e4 = [t57.pointId, t57.pcb_port_id].filter((t58) => typeof t58 == "string").some((t58) => i3.has(t58)), r4 = t57.x >= n3.minX - o3 && t57.x <= n3.maxX + o3 && t57.y >= n3.minY - o3 && t57.y <= n3.maxY + o3;
return e4 && r4;
})).reduce((t56, e4) => ({ minX: Math.min(t56.minX, e4.x), maxX: Math.max(t56.maxX, e4.x), minY: Math.min(t56.minY, e4.y), maxY: Math.max(t56.maxY, e4.y) }), n3), s3 = t55.obstacles.filter((t56) => Xe(Ee(t56), r3)).map((t56) => ({ ...t56 }));
return { ...structuredClone(t55), bounds: r3, obstacles: s3 };
}({ inputSrj: this.inputProblem.inputSrj, component: t54 }));
}
getGlobalTopologySolverInput() {
return { simpleRouteJson: this.normalizedInput.globalNoConnectionSrj, maxGapFillPasses: 4 };
}
filterGlobalRectDiffNodesFromVisualization({ visualization: t54 }) {
return { ...t54, rects: e5({ rects: t54.rects, components: this.normalizedInput.components }) };
}
};
var U5 = (t54, e3) => {
if (t54)
return Object.entries(e3).sort(([t55], [e4]) => e4.length - t55.length).find(([e4]) => t54.includes(e4))?.[1];
};
var Z5 = (t54, e3) => ({ ...t54, points: t54.points?.map((t55) => ({ ...t55, color: U5(t55.label, e3) ?? t55.color })), lines: t54.lines?.map((t55) => ({ ...t55, strokeColor: U5(t55.label, e3) ?? t55.strokeColor })), circles: t54.circles?.map((t55) => {
const n3 = U5(t55.label, e3);
return n3 ? { ...t55, fill: n3, stroke: n3 } : t55;
}) });
var q5 = class extends si {
constructor(t54) {
super(), this.topologyPlanningSolver = t54, this.solved = t54.solved, this.failed = t54.failed, this.error = t54.error, this.stats = t54.stats;
}
getOutput() {
return this.topologyPlanningSolver.getOutput().componentMeshNodes.flat();
}
visualize() {
return this.topologyPlanningSolver.finalVisualize() ?? this.topologyPlanningSolver.visualize();
}
preview() {
return this.visualize();
}
};
var J5 = class {
MAX_ITERATIONS = 1e5;
solved = false;
failed = false;
iterations = 0;
progress = 0;
error = null;
activeSubSolver;
failedSubSolvers;
timeToSolve;
stats = {};
_setupDone = false;
getSolverName() {
return this.constructor.name;
}
setup() {
this._setupDone || (this._setup(), this._setupDone = true);
}
_setup() {}
step() {
if (this._setupDone || this.setup(), !this.solved && !this.failed) {
this.iterations++;
try {
this._step();
} catch (t54) {
throw this.error = `${this.getSolverName()} error: ${t54}`, this.failed = true, t54;
}
!this.solved && this.iterations >= this.MAX_ITERATIONS && this.tryFinalAcceptance(), !this.solved && this.iterations >= this.MAX_ITERATIONS && (this.error = `${this.getSolverName()} ran out of iterations`, this.failed = true), "computeProgress" in this && (this.progress = this.computeProgress());
}
}
_step() {}
getConstructorParams() {
throw new Error("getConstructorParams not implemented");
}
getOutput() {
return null;
}
solve() {
const t54 = Date.now();
for (;!this.solved && !this.failed; )
this.step();
const e3 = Date.now();
this.timeToSolve = e3 - t54;
}
visualize() {
return { lines: [], points: [], rects: [], circles: [] };
}
tryFinalAcceptance() {}
preview() {
return { lines: [], points: [], rects: [], circles: [] };
}
};
var Q5 = (t54) => t54.filter((t55) => Boolean(t55));
var K5 = (t54, e3, n3) => {
const o3 = `${Math.round(100 * t54.x)},${Math.round(100 * t54.y)}`, i3 = e3.map((t55) => ((t56, e4) => t56 === "top" ? 0 : t56 === "bottom" ? e4 - 1 : Number.parseInt(t56.slice(5), 10))(t55, n3)).sort().join("-");
return `${o3}:${i3}`;
};
var t310 = class {
parent = new Map;
constructor(t54, e3 = t54.traces ?? [], n3 = {}) {
for (const e4 of t54.connections)
this.unionAll(Q5([e4.name, e4.source_trace_id, e4.rootConnectionName, e4.netConnectionName, ...e4.mergedConnectionNames ?? [], ...e4.pointsToConnect.flatMap((e6) => [e6.pointId, e6.pcb_port_id, ...n3.includePhysicalPositionAliases ? [K5(e6, e6.layers ?? [e6.layer], t54.layerCount)] : []])]));
for (const n4 of [...e3, ...t54.fixedTraces ?? []])
this.unionAll(Q5([n4.pcb_trace_id, n4.connection_name, n4.source_trace_id, n4.rootConnectionName, ...n4.mergedConnectionNames ?? [], ...n4.connectsTo ?? []]));
for (const e4 of t54.obstacles)
this.unionAll(n3.includePhysicalPositionAliases ? Q5([e4.obstacleId, ...e4.connectedTo, ...e4.offBoardConnectsTo ?? [], K5(e4.center, e4.layers, t54.layerCount)]) : e4.connectedTo);
}
canonicalize(t54) {
return [...new Set(t54.map((t55) => this.find(t55)))];
}
unionAll(t54) {
const e3 = t54[0];
if (e3) {
this.add(e3);
for (let n3 = 1;n3 < t54.length; n3++)
this.union(e3, t54[n3]);
}
}
add(t54) {
this.parent.has(t54) || this.parent.set(t54, t54);
}
find(t54) {
this.add(t54);
const e3 = this.parent.get(t54);
if (e3 === t54)
return t54;
const n3 = this.find(e3);
return this.parent.set(t54, n3), n3;
}
union(t54, e3) {
const n3 = this.find(t54), o3 = this.find(e3);
n3 !== o3 && this.parent.set(o3, n3);
}
};
var e3 = 0.000001;
var n3 = (t54, e4) => Math.hypot(e4.x - t54.x, e4.y - t54.y);
var o3 = (t54, e4, n4) => {
const o4 = n4.x - e4.x, i3 = n4.y - e4.y, r3 = o4 * o4 + i3 * i3;
if (r3 <= 0.000000000001)
return n3(t54, e4);
const s3 = r3(((t54.x - e4.x) * o4 + (t54.y - e4.y) * i3) / r3, 0, 1);
return Math.hypot(t54.x - (e4.x + o4 * s3), t54.y - (e4.y + i3 * s3));
};
var i3 = (t54, e4, n4 = 0.000001) => Math.abs(t54.x - e4.x) <= n4 && Math.abs(t54.y - e4.y) <= n4;
var r3 = (t54, e4, n4) => Math.max(e4, Math.min(n4, t54));
var s3 = (t54, e4, n4) => (e4.x - t54.x) * (n4.y - t54.y) - (e4.y - t54.y) * (n4.x - t54.x);
var a3 = (t54, e4, n4) => Math.abs(s3(e4, n4, t54)) <= 0.000000001 && t54.x >= Math.min(e4.x, n4.x) - 0.000000001 && t54.x <= Math.max(e4.x, n4.x) + 0.000000001 && t54.y >= Math.min(e4.y, n4.y) - 0.000000001 && t54.y <= Math.max(e4.y, n4.y) + 0.000000001;
var c3 = (t54, e4, n4, o4) => ((t55, e6, n6, o6) => {
const i4 = s3(t55, e6, n6), r4 = s3(t55, e6, o6), s4 = s3(n6, o6, t55), a4 = s3(n6, o6, e6);
return i4 * r4 < 0 && s4 * a4 < 0 || Math.abs(i4) <= 0.000000001 && a3(n6, t55, e6) || Math.abs(r4) <= 0.000000001 && a3(o6, t55, e6) || Math.abs(s4) <= 0.000000001 && a3(t55, n6, o6) || Math.abs(a4) <= 0.000000001 && a3(e6, n6, o6);
})(t54, e4, n4, o4) ? 0 : Math.min(o3(t54, n4, o4), o3(e4, n4, o4), o3(n4, t54, e4), o3(o4, t54, e4));
var l3 = (t54, e4) => {
let n4 = false;
for (let o4 = 0, i4 = e4.length - 1;o4 < e4.length; i4 = o4++) {
const r4 = e4[o4], s4 = e4[i4];
if (a3(t54, s4, r4))
return true;
r4.y > t54.y != s4.y > t54.y && t54.x < (s4.x - r4.x) * (t54.y - r4.y) / (s4.y - r4.y) + r4.x && (n4 = !n4);
}
return n4;
};
var h3 = (t54, e4, n4) => {
if (l3(t54, n4) || l3(e4, n4))
return 0;
let o4 = Number.POSITIVE_INFINITY;
for (let i4 = 0;i4 < n4.length; i4++) {
const r4 = n4[i4], s4 = n4[(i4 + 1) % n4.length];
o4 = Math.min(o4, c3(t54, e4, r4, s4));
}
return o4;
};
function d3(t54, e4, n4) {
let o4 = 0, i4 = 1;
const r4 = e4.x - t54.x, s4 = e4.y - t54.y, a4 = [[-r4, t54.x - n4.minX], [r4, n4.maxX - t54.x], [-s4, t54.y - n4.minY], [s4, n4.maxY - t54.y]];
for (const [t55, e6] of a4) {
if (Math.abs(t55) < 0.000000000001) {
if (e6 < 0)
return false;
continue;
}
const n6 = e6 / t55;
if (t55 < 0 ? o4 = Math.max(o4, n6) : i4 = Math.min(i4, n6), o4 > i4)
return false;
}
return true;
}
function u3({ start: t54, end: e4, width: n4, base: o4 }) {
const i4 = n3(t54, e4), r4 = ((t55) => r3(1.25 * t55, 0.25, 0.75))(n4), s4 = Math.max(1, Math.ceil(i4 / r4)), a4 = n4 / 2, c4 = [];
for (let i6 = 0;i6 < s4; i6++) {
const r6 = i6 / s4, l4 = (i6 + 1) / s4, h4 = t54.x + (e4.x - t54.x) * r6, d4 = t54.y + (e4.y - t54.y) * r6, u4 = t54.x + (e4.x - t54.x) * l4, p3 = t54.y + (e4.y - t54.y) * l4;
c4.push({ ...o4, minX: Math.min(h4, u4) - a4, minY: Math.min(d4, p3) - a4, maxX: Math.max(h4, u4) + a4, maxY: Math.max(d4, p3) + a4, exactShape: { type: "segment", start: { x: h4, y: d4 }, end: { x: u4, y: p3 }, width: n4 } });
}
return c4;
}
var p3 = (t54, e4, n4) => {
const o4 = Math.cos(n4), i4 = Math.sin(n4), r4 = t54.x - e4.x, s4 = t54.y - e4.y;
return { x: e4.x + r4 * o4 - s4 * i4, y: e4.y + r4 * i4 + s4 * o4 };
};
var m3 = class {
nodeIndices = [];
priorities = [];
get size() {
return this.nodeIndices.length;
}
push(t54, e4) {
let n4 = this.nodeIndices.length;
for (this.nodeIndices.push(t54), this.priorities.push(e4);n4 > 0; ) {
const t55 = n4 - 1 >> 1;
if (this.priorities[t55] <= e4)
break;
this.swap(n4, t55), n4 = t55;
}
}
pop() {
const t54 = this.nodeIndices[0], e4 = this.nodeIndices.pop(), n4 = this.priorities.pop();
if (this.nodeIndices.length === 0)
return t54;
this.nodeIndices[0] = e4, this.priorities[0] = n4;
let o4 = 0;
for (;; ) {
const t55 = 2 * o4 + 1, e6 = t55 + 1;
if (t55 >= this.nodeIndices.length)
break;
let n6 = t55;
if (e6 < this.nodeIndices.length && this.priorities[e6] < this.priorities[t55] && (n6 = e6), this.priorities[o4] <= this.priorities[n6])
break;
this.swap(o4, n6), o4 = n6;
}
return t54;
}
swap(t54, e4) {
[this.nodeIndices[t54], this.nodeIndices[e4]] = [this.nodeIndices[e4], this.nodeIndices[t54]], [this.priorities[t54], this.priorities[e4]] = [this.priorities[e4], this.priorities[t54]];
}
};
var g3 = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]];
var f3 = ["#d53535", "#3478c8", "#8e44ad", "#15956f"];
var y3 = class extends J5 {
problem;
searchBounds;
rows;
columns;
origin;
nodes = [];
open = new m3;
bestCost = new Map;
closed = new Set;
baseStateCount;
stateSpaceUpperBound;
endLayerIndices;
targetCell;
segmentWidthCache = new Map;
closedStateCount = 0;
output = null;
constructor(t54) {
super(), this.problem = t54;
const e4 = Math.max(t54.traceWidth, t54.viaDiameter) / 2 + t54.obstacleIndex.clearance, n4 = r3(Math.min(t54.start.x, t54.end.x) - t54.searchPadding, t54.bounds.minX + e4, t54.bounds.maxX - e4), o4 = r3(Math.max(t54.start.x, t54.end.x) + t54.searchPadding, t54.bounds.minX + e4, t54.bounds.maxX - e4), i4 = r3(Math.min(t54.start.y, t54.end.y) - t54.searchPadding, t54.bounds.minY + e4, t54.bounds.maxY - e4), r4 = r3(Math.max(t54.start.y, t54.end.y) + t54.searchPadding, t54.bounds.minY + e4, t54.bounds.maxY - e4), s4 = Math.floor((n4 - t54.gridOffset.x) / t54.gridSize) * t54.gridSize + t54.gridOffset.x, a4 = Math.floor((i4 - t54.gridOffset.y) / t54.gridSize) * t54.gridSize + t54.gridOffset.y;
this.origin = { x: s4, y: a4 }, this.columns = Math.max(2, Math.floor((o4 - s4) / t54.gridSize) + 1), this.rows = Math.max(2, Math.floor((r4 - a4) / t54.gridSize) + 1), this.searchBounds = { minX: s4, minY: a4, maxX: s4 + (this.columns - 1) * t54.gridSize, maxY: a4 + (this.rows - 1) * t54.gridSize };
const c4 = this.rows * this.columns * t54.layers.length * (t54.maxViaCount + 1);
this.baseStateCount = c4, this.stateSpaceUpperBound = c4 * (this.rows * this.columns + 1), this.targetCell = this.pointToCell(t54.end), this.endLayerIndices = new Set(t54.endLayers.map((e6) => t54.layers.indexOf(e6)).filter((t55) => t55 >= 0));
const l4 = this.pointToCell(t54.start);
for (const e6 of t54.startLayers) {
const n6 = t54.layers.indexOf(e6);
if (n6 < 0 || this.endpointCollides(t54.start, n6))
continue;
const o6 = { ...l4, ...t54.start, layerIndex: n6, viaCount: 0, viaPoints: [], g: 0, f: this.heuristic(t54.start), parentIndex: -1 }, i6 = this.nodes.length;
this.nodes.push(o6), this.open.push(i6, o6.f), this.bestCost.set(this.toStateIndex(o6), 0);
}
this.open.size !== 0 && this.endLayerIndices.size !== 0 || (this.failed = true, this.error = "No collision-free multilayer route endpoint"), this.MAX_ITERATIONS = Math.min(15000, Math.max(2000, 2 * c4)), this.stats = this.createStats();
}
getSolverName() {
return `LayerAwareGridRouteSolver(${this.problem.gridSize.toFixed(3)}mm)`;
}
_step() {
if (this.open.size === 0)
return this.failed = true, void (this.error = "No collision-free multilayer grid route found");
const t54 = this.open.pop(), e4 = this.nodes[t54], n4 = this.toStateIndex(e4);
if (!this.closed.has(n4)) {
if (this.closed.add(n4), this.closedStateCount++, e4.row === this.targetCell.row && e4.column === this.targetCell.column && this.endLayerIndices.has(e4.layerIndex) && e4.viaCount >= this.problem.minViaCount && !this.segmentCollides(e4, this.problem.end))
return this.output = this.reconstructRoute(t54), this.solved = true, void (this.stats = this.createStats());
this.expandPlanarMoves(t54, e4), this.expandViaMoves(t54, e4), this.stats = this.createStats();
}
}
expandPlanarMoves(t54, e4) {
for (const [n4, o4] of g3) {
const i4 = e4.row + n4, r4 = e4.column + o4;
if (i4 < 0 || i4 >= this.rows || r4 < 0 || r4 >= this.columns)
continue;
const s4 = this.cellToPoint(i4, r4), a4 = this.getSafeSegmentWidth(e4, s4);
if (a4 <= 0)
continue;
const c4 = this.problem.gridSize * (n4 !== 0 && o4 !== 0 ? Math.SQRT2 : 1) * Math.max(1, (this.problem.traceWidth / a4) ** this.problem.neckPenaltyExponent);
this.enqueueNode({ row: i4, column: r4, ...s4, layerIndex: e4.layerIndex, viaCount: e4.viaCount, viaPoints: e4.viaPoints, g: e4.g + c4, parentIndex: t54 });
}
}
expandViaMoves(t54, e4) {
if (e4.viaCount >= this.problem.maxViaCount)
return;
const n4 = 0.5 * this.problem.gridSize;
if (n3(e4, this.problem.start) < n4 - 0.000000001 || n3(e4, this.problem.end) < n4 - 0.000000001)
return;
const o4 = e4.parentIndex >= 0 ? this.nodes[e4.parentIndex] : undefined;
if (!o4 || o4.layerIndex === e4.layerIndex || !i3(o4, e4))
for (let n6 = 0;n6 < this.problem.layers.length; n6++)
n6 !== e4.layerIndex && (this.problem.obstacleIndex.collidesVia({ point: e4, layers: this.problem.layers, padDiameter: this.problem.viaDiameter, holeDiameter: this.problem.viaHoleDiameter, connectionNames: this.problem.connectionNames, ignoreTraceIndex: this.problem.ignoreTraceIndex, ignoreTraceIndices: this.problem.softTraceIndices, ignoreRouteRange: this.problem.ignoreRouteRange, obstacleClearance: this.problem.obstacleClearance, blockSameNetObstacles: true, sameNetObstacleClearance: 0, otherNewViaPoints: e4.viaPoints, fixedVias: this.problem.fixedVias }) || this.enqueueNode({ row: e4.row, column: e4.column, x: e4.x, y: e4.y, layerIndex: n6, viaCount: e4.viaCount + 1, viaPoints: [...e4.viaPoints, { x: e4.x, y: e4.y }], g: e4.g + this.problem.viaCost, parentIndex: t54 }));
}
enqueueNode(t54) {
const e4 = this.toStateIndex(t54);
if (this.closed.has(e4) || t54.g >= (this.bestCost.get(e4) ?? Number.POSITIVE_INFINITY))
return;
this.bestCost.set(e4, t54.g);
const n4 = t54.g + this.heuristic(t54), o4 = this.nodes.length;
this.nodes.push({ ...t54, f: n4 }), this.open.push(o4, n4);
}
endpointCollides(t54, e4) {
return this.getSafeSegmentWidth({ ...t54, layerIndex: e4, viaCount: 0 }, t54) <= 0;
}
segmentCollides(t54, e4) {
return this.getSafeSegmentWidth(t54, e4) <= 0;
}
getSafeSegmentWidth(t54, e4) {
const n4 = this.problem.layers[t54.layerIndex], o4 = this.problem.startLayers.length === 1 && t54.viaCount === 0 && n4 === this.problem.originalStartLayer && n3(this.problem.start, t54) <= this.problem.maxStartNeckLength + 0.000000001 && n3(this.problem.start, e4) <= this.problem.maxStartNeckLength + 0.000000001, i4 = this.problem.endLayers.length === 1 && n4 === this.problem.originalEndLayer && n3(this.problem.end, t54) <= this.problem.maxEndNeckLength + 0.000000001 && n3(this.problem.end, e4) <= this.problem.maxEndNeckLength + 0.000000001, r4 = Math.max(o4 ? this.problem.startNeckWidth : 0, i4 ? this.problem.endNeckWidth : 0), s4 = [t54.x, t54.y, e4.x, e4.y, t54.layerIndex, t54.viaCount, r4].join(":"), a4 = this.segmentWidthCache.get(s4);
if (a4 !== undefined)
return a4;
const c4 = (o6) => !this.problem.obstacleIndex.collides({ start: t54, end: e4, layer: n4, width: o6, connectionNames: this.problem.connectionNames, ignoreTraceIndex: this.problem.ignoreTraceIndex, ignoreTraceIndices: this.problem.softTraceIndices, ignoreRouteRange: this.problem.ignoreRouteRange, obstacleClearance: this.problem.obstacleClearance });
let l4 = 0;
if (o4 || i4) {
const t55 = 0.025;
let e6 = Math.ceil((r4 - 0.000000001) / t55), n6 = Math.floor((this.problem.traceWidth + 0.000000001) / t55);
for (;e6 <= n6; ) {
const o6 = Math.floor((e6 + n6) / 2), i6 = Number((o6 * t55).toFixed(6));
c4(i6) ? (l4 = i6, e6 = o6 + 1) : n6 = o6 - 1;
}
l4 < r4 - 0.000000001 && c4(r4) && (l4 = r4);
} else
l4 = c4(this.problem.traceWidth) ? this.problem.traceWidth : 0;
return this.segmentWidthCache.set(s4, l4), l4;
}
reconstructRoute(t54) {
const e4 = [];
let n4 = t54;
for (;n4 >= 0; ) {
const t55 = this.nodes[n4];
e4.push(t55), n4 = t55.parentIndex;
}
e4.reverse();
const o4 = e4[e4.length - 1];
i3(o4, this.problem.end) || e4.push({ ...o4, ...this.problem.end, row: this.targetCell.row, column: this.targetCell.column, parentIndex: -1 });
const i4 = [];
let r4 = [e4[0]];
for (let t55 = 1;t55 < e4.length; t55++) {
const n6 = e4[t55 - 1], o6 = e4[t55];
o6.layerIndex !== n6.layerIndex ? (i4.push(r4), r4 = [o6]) : r4.push(o6);
}
i4.push(r4);
const s4 = [];
for (let t55 = 0;t55 < i4.length; t55++) {
const e6 = this.simplifySection(i4[t55]), n6 = e6.slice(0, -1).map((t56, n7) => this.getSafeSegmentWidth(t56, e6[n7 + 1])), o6 = e6.map((t56, o7) => ({ route_type: "wire", x: t56.x, y: t56.y, layer: this.problem.layers[t56.layerIndex], width: n6.length === 0 ? Math.min(this.problem.startNeckWidth, this.problem.endNeckWidth) : o7 === 0 ? n6[0] : o7 === e6.length - 1 ? n6[n6.length - 1] : Math.min(n6[o7 - 1], n6[o7]) }));
s4.push(...o6);
const r6 = i4[t55 + 1];
if (r6) {
const t56 = this.problem.layers[e6.at(-1).layerIndex], n7 = this.problem.layers[r6[0].layerIndex], o7 = e6.at(-1);
s4.push({ route_type: "via", x: o7.x, y: o7.y, from_layer: t56, to_layer: n7, via_diameter: this.problem.viaDiameter, via_hole_diameter: this.problem.viaHoleDiameter });
}
}
return { route: s4, traceWidth: this.problem.traceWidth, startNeckWidth: this.problem.startNeckWidth, endNeckWidth: this.problem.endNeckWidth, gridSize: this.problem.gridSize, gridOffset: this.problem.gridOffset, viaCount: i4.length - 1 };
}
simplifySection(t54) {
return t54.length <= 2 ? t54 : this.problem.neckPenaltyExponent > 1 ? this.simplifyStrictSection(t54) : this.simplifyWidthPreservingSection(t54);
}
simplifyStrictSection(t54) {
const e4 = t54.slice(0, -1).map((e6, n6) => this.getSafeSegmentWidth(e6, t54[n6 + 1])), n4 = [0];
for (let o6 = 0;o6 < e4.length; o6++)
n4.push(n4[o6] + this.getWidthPenalizedCost(t54[o6], t54[o6 + 1], e4[o6]));
const o4 = [t54[0]];
let i4 = 0;
for (;i4 < t54.length - 1; ) {
let r4 = t54.length - 1;
for (;r4 > i4 + 1 && !this.shortcutPreservesRouteQuality(t54, e4, n4, i4, r4); )
r4--;
o4.push(t54[r4]), i4 = r4;
}
return this.removeRedundantCollinearPoints(o4);
}
shortcutPreservesRouteQuality(t54, e4, n4, o4, i4) {
const r4 = this.getSafeSegmentWidth(t54[o4], t54[i4]);
if (r4 <= 0)
return false;
let s4 = Number.POSITIVE_INFINITY;
for (let t55 = o4;t55 < i4; t55++)
s4 = Math.min(s4, e4[t55]);
const a4 = n4[i4] - n4[o4];
return r4 >= s4 - 0.000000001 && this.getWidthPenalizedCost(t54[o4], t54[i4], r4) <= a4 + 0.000000001;
}
getWidthPenalizedCost(t54, e4, n4) {
return n3(t54, e4) * Math.max(1, (this.problem.traceWidth / n4) ** this.problem.neckPenaltyExponent);
}
simplifyWidthPreservingSection(t54) {
const e4 = t54.slice(0, -1).map((e6, n6) => this.getSafeSegmentWidth(e6, t54[n6 + 1])), n4 = [0];
for (let o6 = 0;o6 < e4.length; o6++)
n4.push(n4[o6] + n3(t54[o6], t54[o6 + 1]) * Math.max(1, (this.problem.traceWidth / e4[o6]) ** this.problem.neckPenaltyExponent));
const o4 = new Float64Array(t54.length).fill(Number.POSITIVE_INFINITY), i4 = new Float64Array(t54.length).fill(Number.POSITIVE_INFINITY), r4 = new Int32Array(t54.length).fill(-1);
o4[0] = 0, i4[0] = 0;
for (let s6 = 1;s6 < t54.length; s6++) {
let a6 = Number.POSITIVE_INFINITY;
for (let c4 = s6 - 1;c4 >= 0; c4--) {
if (a6 = Math.min(a6, e4[c4]), !Number.isFinite(o4[c4]))
continue;
const l4 = this.getSafeSegmentWidth(t54[c4], t54[s6]);
if (l4 < a6 - 0.000000001)
continue;
const h4 = n3(t54[c4], t54[s6]);
if (h4 * Math.max(1, (this.problem.traceWidth / l4) ** this.problem.neckPenaltyExponent) > n4[s6] - n4[c4] + 0.000000001)
continue;
const d4 = o4[c4] + h4 * Math.max(0, this.problem.traceWidth - l4), u4 = i4[c4] + h4;
(d4 < o4[s6] - 0.000000001 || Math.abs(d4 - o4[s6]) <= 0.000000001 && u4 < i4[s6] - 0.000000001) && (o4[s6] = d4, i4[s6] = u4, r4[s6] = c4);
}
}
const s4 = [];
let a4 = t54.length - 1;
for (;a4 >= 0 && (s4.push(t54[a4]), a4 !== 0); )
if (a4 = r4[a4], a4 < 0)
return t54;
return s4.reverse(), this.removeRedundantCollinearPoints(s4);
}
removeRedundantCollinearPoints(t54) {
return t54.filter((t55, e4, n4) => {
if (e4 === 0 || e4 === n4.length - 1)
return true;
const o4 = n4[e4 - 1], i4 = n4[e4 + 1], r4 = (t55.x - o4.x) * (i4.y - t55.y) - (t55.y - o4.y) * (i4.x - t55.x), s4 = Math.abs(this.getSafeSegmentWidth(o4, t55) - this.getSafeSegmentWidth(t55, i4)) < 0.000000001;
return Math.abs(r4) > 0.00000001 || !s4;
});
}
pointToCell(t54) {
return { column: r3(Math.round((t54.x - this.origin.x) / this.problem.gridSize), 0, this.columns - 1), row: r3(Math.round((t54.y - this.origin.y) / this.problem.gridSize), 0, this.rows - 1) };
}
cellToPoint(t54, e4) {
return { x: this.origin.x + e4 * this.problem.gridSize, y: this.origin.y + t54 * this.problem.gridSize };
}
toStateIndex(t54) {
const e4 = ((t54.viaCount * this.problem.layers.length + t54.layerIndex) * this.rows + t54.row) * this.columns + t54.column;
if (t54.viaCount !== 1 || t54.viaPoints.length === 0 || n3(t54, t54.viaPoints[0]) >= this.problem.viaHoleDiameter + this.problem.obstacleIndex.minViaHoleEdgeToViaHoleEdgeClearance - 0.000000001)
return e4;
const n4 = this.pointToCell(t54.viaPoints[0]);
return e4 + (1 + n4.row * this.columns + n4.column) * this.baseStateCount;
}
heuristic(t54) {
return n3(t54, this.problem.end);
}
createStats() {
return { phase: "layer-aware-grid-search", gridSize: this.problem.gridSize, traceWidth: this.problem.traceWidth, startNeckWidth: this.problem.startNeckWidth, endNeckWidth: this.problem.endNeckWidth, maxViaCount: this.problem.maxViaCount, minViaCount: this.problem.minViaCount, openStates: this.open.size, closedStates: this.closedStateCount, trackedStates: this.bestCost.size, stateSpaceUpperBound: this.stateSpaceUpperBound };
}
computeProgress() {
return Math.min(0.99, this.iterations / this.MAX_ITERATIONS);
}
getOutput() {
return this.output;
}
getConstructorParams() {
const { obstacleIndex: t54, ...e4 } = this.problem;
return [e4];
}
visualize() {
const t54 = this.nodes.filter((t55) => this.closed.has(this.toStateIndex(t55))).slice(-2e3).map((t55) => ({ x: t55.x, y: t55.y, color: `${f3[t55.layerIndex % f3.length]}55` })), e4 = [], n4 = [], o4 = this.output?.route ?? [];
for (let t55 = 0;t55 < o4.length - 1; t55++) {
const i4 = o4[t55], r4 = o4[t55 + 1];
if (i4?.route_type === "wire" && r4?.route_type === "wire" && i4.layer === r4.layer) {
const t56 = this.problem.layers.indexOf(i4.layer);
e4.push({ points: [i4, r4], strokeColor: f3[t56 % f3.length] ?? "#333", strokeWidth: i4.width });
}
i4?.route_type === "via" && n4.push({ center: i4, radius: (i4.via_diameter ?? this.problem.viaDiameter) / 2, fill: "#d4a017" });
}
return { coordinateSystem: "cartesian", title: this.getSolverName(), rects: [{ center: { x: (this.searchBounds.minX + this.searchBounds.maxX) / 2, y: (this.searchBounds.minY + this.searchBounds.maxY) / 2 }, width: this.searchBounds.maxX - this.searchBounds.minX, height: this.searchBounds.maxY - this.searchBounds.minY, stroke: "#777" }], points: [...t54, { ...this.problem.start, color: "green", label: "reroute start" }, { ...this.problem.end, color: "purple", label: "reroute target" }], lines: e4, circles: n4, texts: [] };
}
};
var _3 = [{ direction: 1, strength: 0.7 }, { direction: -1, strength: 0.7 }, { direction: 1, strength: 1 }, { direction: -1, strength: 1 }];
var b3 = (t54, e4, n4) => {
const o4 = n4.x - e4.x, i4 = n4.y - e4.y, r4 = o4 * o4 + i4 * i4;
if (r4 <= 0.000000000001)
return { ...e4 };
const s4 = r3(((t54.x - e4.x) * o4 + (t54.y - e4.y) * i4) / r4, 0, 1);
return { x: e4.x + o4 * s4, y: e4.y + i4 * s4 };
};
var x3 = class extends J5 {
problem;
phase = "prepare-candidate";
variantCursor = 0;
relaxationIteration = 0;
candidatePoints = [];
sampledPoints;
output = null;
constructor(t54) {
super(), this.problem = t54, this.sampledPoints = this.sampleRoute(), this.MAX_ITERATIONS = 100, this.stats = this.createStats();
}
getSolverName() {
return "ElasticTracePushSolver";
}
_step() {
switch (this.phase) {
case "prepare-candidate":
if (this.variantCursor >= _3.length)
return this.failed = true, void (this.error = "No collision-free elastic displacement found");
this.candidatePoints = this.sampledPoints.map((t54) => ({ ...t54 })), this.relaxationIteration = 0, this.phase = "relax-candidate";
break;
case "relax-candidate":
this.relaxCandidate(), this.relaxationIteration++, this.relaxationIteration >= 10 && (this.phase = "validate-candidate");
break;
case "validate-candidate": {
const t54 = this.simplifyCandidate(this.candidatePoints);
this.pathCollides(t54) ? (this.variantCursor++, this.phase = "prepare-candidate") : (this.output = { points: t54, traceWidth: this.problem.traceWidth }, this.phase = "complete");
break;
}
case "complete":
this.solved = true;
}
this.stats = this.createStats();
}
sampleRoute() {
const t54 = [], e4 = r3(2 * this.problem.traceWidth, 0.2, 0.45), n4 = this.problem.trace.route;
for (let o4 = this.problem.range.startIndex;o4 < this.problem.range.endIndex; o4++) {
const i4 = n4[o4], r4 = n4[o4 + 1];
if (i4?.route_type !== "wire" || r4?.route_type !== "wire" || i4.layer !== r4.layer)
continue;
t54.length === 0 && t54.push({ x: i4.x, y: i4.y });
const s4 = n3(i4, r4), a4 = Math.max(1, Math.ceil(s4 / e4));
for (let e6 = 1;e6 <= a4; e6++) {
const n6 = e6 / a4;
t54.push({ x: i4.x + (r4.x - i4.x) * n6, y: i4.y + (r4.y - i4.y) * n6 });
}
}
return t54;
}
relaxCandidate() {
const t54 = _3[this.variantCursor], e4 = this.candidatePoints.map((t55) => ({ ...t55 })), n4 = new Uint8Array(this.candidatePoints.length);
for (let o4 = 1;o4 < this.candidatePoints.length - 1; o4++) {
const i4 = this.candidatePoints[o4], r4 = this.findNearestCorridorSegment(i4);
if (!r4)
continue;
const s4 = n3(r4.segment.start, r4.segment.end);
if (s4 <= 0.000000001)
continue;
const a4 = r4.segment.width / 2 + this.problem.traceWidth / 2 + this.problem.obstacleIndex.clearance + 0.025;
if (r4.distance > a4 + 0.35)
continue;
const c4 = { x: (r4.segment.start.y - r4.segment.end.y) / s4 * t54.direction, y: (r4.segment.end.x - r4.segment.start.x) / s4 * t54.direction }, l4 = a4 - ((i4.x - r4.closest.x) * c4.x + (i4.y - r4.closest.y) * c4.y);
if (l4 <= 0)
continue;
const h4 = Math.min(0.35, l4 * t54.strength);
e4[o4] = { x: i4.x + c4.x * h4, y: i4.y + c4.y * h4 }, n4[o4] = 1;
}
for (let t55 = 1;t55 < e4.length - 1; t55++) {
if (!n4[t55])
continue;
const o4 = e4[t55 - 1], i4 = e4[t55], r4 = e4[t55 + 1];
e4[t55] = { x: 0.85 * i4.x + (o4.x + r4.x) / 2 * 0.15, y: 0.85 * i4.y + (o4.y + r4.y) / 2 * 0.15 };
}
this.candidatePoints = e4;
}
findNearestCorridorSegment(t54) {
let e4;
for (const n4 of this.problem.corridor) {
if (n4.layer !== this.problem.layer)
continue;
const o4 = b3(t54, n4.start, n4.end), i4 = n3(t54, o4);
(!e4 || i4 < e4.distance) && (e4 = { segment: n4, closest: o4, distance: i4 });
}
return e4;
}
simplifyCandidate(t54) {
if (t54.length <= 2)
return t54;
const e4 = [t54[0]];
let n4 = 0;
for (;n4 < t54.length - 1; ) {
let o4 = t54.length - 1;
for (;o4 > n4 + 1 && this.segmentCollides(t54[n4], t54[o4]); )
o4--;
e4.push(t54[o4]), n4 = o4;
}
return e4.filter((t55, e6, n6) => e6 === 0 || !i3(t55, n6[e6 - 1]));
}
pathCollides(t54) {
if (t54.length < 2)
return true;
for (let e4 = 0;e4 < t54.length - 1; e4++)
if (this.segmentCollides(t54[e4], t54[e4 + 1]))
return true;
return false;
}
segmentCollides(t54, e4) {
return this.problem.obstacleIndex.collides({ start: t54, end: e4, layer: this.problem.layer, width: this.problem.traceWidth, connectionNames: this.problem.connectionNames, ignoreTraceIndex: -1 });
}
createStats() {
const t54 = _3[this.variantCursor];
return { phase: this.phase, direction: t54?.direction, strength: t54?.strength, variantCursor: this.variantCursor, relaxationIteration: this.relaxationIteration, sampledPointCount: this.sampledPoints.length };
}
computeProgress() {
return Math.min(0.99, (this.variantCursor + this.relaxationIteration / 12) / _3.length);
}
getOutput() {
return this.output;
}
getConstructorParams() {
return [this.problem];
}
visualize() {
return { coordinateSystem: "cartesian", title: `Elastic trace push: ${this.phase}`, lines: [...this.problem.corridor.map((t54) => ({ points: [t54.start, t54.end], strokeColor: "rgba(255, 128, 0, 0.6)", strokeWidth: t54.width })), ...this.candidatePoints.length > 1 ? [{ points: this.candidatePoints, strokeColor: "#1769d2", strokeWidth: this.problem.traceWidth }] : []], points: [], rects: [], circles: [], texts: [] };
}
};
var v3 = (t54, e4) => {
const n4 = Math.abs(e4.x - t54.x), o4 = Math.abs(e4.y - t54.y);
return n4 <= e3 || o4 <= e3 || Math.abs(n4 - o4) <= e3;
};
var I3 = (t54) => {
let e4 = 0;
for (let n4 = 0;n4 < t54.length - 1; n4++)
v3(t54[n4], t54[n4 + 1]) || e4++;
return e4;
};
var S3 = (t54) => {
let e4 = 0;
for (let n4 = 0;n4 < t54.length - 1; n4++)
e4 += n3(t54[n4], t54[n4 + 1]);
return e4;
};
var C3 = (t54) => t54.filter((e4, n4) => n4 === 0 || !i3(e4, t54[n4 - 1]));
var P3 = (t54, e4) => {
const n4 = e4.x - t54.x, o4 = e4.y - t54.y, i4 = Math.abs(n4), r4 = Math.abs(o4), s4 = Math.sign(n4), a4 = Math.sign(o4), c4 = [];
v3(t54, e4) && c4.push([t54, e4]), c4.push([t54, { x: e4.x, y: t54.y }, e4], [t54, { x: t54.x, y: e4.y }, e4]), i4 >= r4 ? c4.push([t54, { x: e4.x - s4 * r4, y: t54.y }, e4], [t54, { x: t54.x + s4 * r4, y: e4.y }, e4]) : c4.push([t54, { x: t54.x, y: e4.y - a4 * i4 }, e4], [t54, { x: e4.x, y: t54.y + a4 * i4 }, e4]);
const l4 = new Map;
for (const t55 of c4) {
const e6 = C3(t55);
if (e6.length < 2 || e6.some((t56, n7) => n7 < e6.length - 1 && !v3(t56, e6[n7 + 1])))
continue;
const n6 = e6.map((t56) => `${t56.x.toFixed(6)},${t56.y.toFixed(6)}`).join(";");
l4.set(n6, e6);
}
return [...l4.values()].sort((t55, e6) => S3(t55) - S3(e6) || t55.length - e6.length);
};
var M3 = class {
nodeIndices = [];
priorities = [];
get size() {
return this.nodeIndices.length;
}
push(t54, e4) {
let n4 = this.nodeIndices.length;
for (this.nodeIndices.push(t54), this.priorities.push(e4);n4 > 0; ) {
const t55 = n4 - 1 >> 1;
if (this.priorities[t55] <= e4)
break;
this.swap(n4, t55), n4 = t55;
}
}
pop() {
const t54 = this.nodeIndices[0], e4 = this.nodeIndices.pop(), n4 = this.priorities.pop();
if (this.nodeIndices.length === 0)
return t54;
this.nodeIndices[0] = e4, this.priorities[0] = n4;
let o4 = 0;
for (;; ) {
const t55 = 2 * o4 + 1, e6 = t55 + 1;
if (t55 >= this.nodeIndices.length)
break;
let n6 = t55;
if (e6 < this.nodeIndices.length && this.priorities[e6] < this.priorities[t55] && (n6 = e6), this.priorities[o4] <= this.priorities[n6])
break;
this.swap(o4, n6), o4 = n6;
}
return t54;
}
swap(t54, e4) {
[this.nodeIndices[t54], this.nodeIndices[e4]] = [this.nodeIndices[e4], this.nodeIndices[t54]], [this.priorities[t54], this.priorities[e4]] = [this.priorities[e4], this.priorities[t54]];
}
};
var N3 = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]];
var w3 = class extends J5 {
problem;
searchBounds;
rows;
columns;
origin;
nodes = [];
open = new M3;
bestCost;
closed;
closedCellCount = 0;
targetCell;
output = null;
constructor(t54) {
super(), this.problem = t54;
const e4 = t54.traceWidth / 2 + t54.obstacleIndex.clearance, n4 = r3(Math.min(t54.start.x, t54.end.x) - t54.searchPadding, t54.bounds.minX + e4, t54.bounds.maxX - e4), o4 = r3(Math.max(t54.start.x, t54.end.x) + t54.searchPadding, t54.bounds.minX + e4, t54.bounds.maxX - e4), i4 = r3(Math.min(t54.start.y, t54.end.y) - t54.searchPadding, t54.bounds.minY + e4, t54.bounds.maxY - e4), r4 = r3(Math.max(t54.start.y, t54.end.y) + t54.searchPadding, t54.bounds.minY + e4, t54.bounds.maxY - e4), s4 = Math.floor((n4 - t54.gridOffset.x) / t54.gridSize) * t54.gridSize + t54.gridOffset.x, a4 = Math.floor((i4 - t54.gridOffset.y) / t54.gridSize) * t54.gridSize + t54.gridOffset.y;
if (this.origin = { x: s4, y: a4 }, this.columns = Math.max(2, Math.floor((o4 - s4) / t54.gridSize) + 1), this.rows = Math.max(2, Math.floor((r4 - a4) / t54.gridSize) + 1), this.searchBounds = { minX: s4, minY: a4, maxX: s4 + (this.columns - 1) * t54.gridSize, maxY: a4 + (this.rows - 1) * t54.gridSize }, this.bestCost = new Float64Array(this.rows * this.columns).fill(Number.POSITIVE_INFINITY), this.closed = new Uint8Array(this.rows * this.columns), this.endpointCollides(t54.start) || this.endpointCollides(t54.end))
return this.failed = true, this.error = "Grid-route endpoint violates obstacle clearance", this.targetCell = { row: 0, column: 0 }, this.MAX_ITERATIONS = 1, void (this.stats = this.createStats());
const c4 = this.pointToCell(t54.start);
this.targetCell = this.pointToCell(t54.end);
const l4 = { ...c4, x: t54.start.x, y: t54.start.y, g: 0, f: this.heuristic(t54.start), parentIndex: -1 };
this.nodes.push(l4), this.open.push(0, l4.f), this.bestCost[this.toFlatIndex(c4.row, c4.column)] = 0, this.MAX_ITERATIONS = Math.min(5000, Math.max(1000, this.rows * this.columns * 2)), this.stats = this.createStats();
}
endpointCollides(t54) {
return this.problem.obstacleIndex.collides({ start: t54, end: t54, layer: this.problem.layer, width: this.problem.traceWidth, connectionNames: this.problem.connectionNames, ignoreTraceIndex: this.problem.ignoreTraceIndex, ignoreRouteRange: this.problem.ignoreRouteRange, obstacleClearance: this.problem.obstacleClearance });
}
getSolverName() {
return `ObstacleAwareGridRouteSolver(${this.problem.gridSize.toFixed(3)}mm)`;
}
_step() {
if (this.open.size === 0)
return this.failed = true, void (this.error = "No collision-free grid route found");
const t54 = this.open.pop(), e4 = this.nodes[t54], n4 = this.toFlatIndex(e4.row, e4.column);
if (!this.closed[n4]) {
if (this.closed[n4] = 1, this.closedCellCount++, e4.row === this.targetCell.row && e4.column === this.targetCell.column && this.getAllowedConnector(e4, this.problem.end) !== null)
return this.output = { points: this.reconstructPath(t54), traceWidth: this.problem.traceWidth, gridSize: this.problem.gridSize, gridOffset: this.problem.gridOffset }, this.solved = true, void (this.stats = this.createStats());
for (const [n6, o4] of N3) {
const i4 = e4.row + n6, r4 = e4.column + o4;
if (i4 < 0 || i4 >= this.rows || r4 < 0 || r4 >= this.columns)
continue;
const s4 = this.toFlatIndex(i4, r4);
if (this.closed[s4])
continue;
const a4 = this.cellToPoint(i4, r4), c4 = this.getAllowedConnector(e4, a4);
if (c4 === null)
continue;
const l4 = e4.parentIndex === -1 && this.problem.requireOctilinear ? S3(c4) : this.problem.gridSize * (n6 !== 0 && o4 !== 0 ? Math.SQRT2 : 1), h4 = e4.g + l4;
if (h4 >= this.bestCost[s4])
continue;
this.bestCost[s4] = h4;
const d4 = h4 + this.heuristic(a4), u4 = this.nodes.length;
this.nodes.push({ row: i4, column: r4, ...a4, g: h4, f: d4, parentIndex: t54 }), this.open.push(u4, d4);
}
this.stats = this.createStats();
}
}
segmentCollides(t54, e4) {
return this.problem.obstacleIndex.collides({ start: t54, end: e4, layer: this.problem.layer, width: this.problem.traceWidth, connectionNames: this.problem.connectionNames, ignoreTraceIndex: this.problem.ignoreTraceIndex, ignoreRouteRange: this.problem.ignoreRouteRange, obstacleClearance: this.problem.obstacleClearance });
}
getAllowedConnector(t54, e4) {
return this.problem.requireOctilinear && (("parentIndex" in t54) && t54.parentIndex === -1 || i3(e4, this.problem.end)) ? P3(t54, e4).find((t55) => t55.slice(0, -1).every((e6, n4) => !this.segmentCollides(e6, t55[n4 + 1]))) ?? null : this.segmentCollides(t54, e4) ? null : [t54, e4];
}
pointToCell(t54) {
return { column: r3(Math.round((t54.x - this.origin.x) / this.problem.gridSize), 0, this.columns - 1), row: r3(Math.round((t54.y - this.origin.y) / this.problem.gridSize), 0, this.rows - 1) };
}
cellToPoint(t54, e4) {
return { x: this.origin.x + e4 * this.problem.gridSize, y: this.origin.y + t54 * this.problem.gridSize };
}
toFlatIndex(t54, e4) {
return t54 * this.columns + e4;
}
heuristic(t54) {
return Math.hypot(this.problem.end.x - t54.x, this.problem.end.y - t54.y);
}
reconstructPath(t54) {
const e4 = [];
let n4 = t54;
for (;n4 >= 0; ) {
const t55 = this.nodes[n4];
e4.push({ x: t55.x, y: t55.y }), n4 = t55.parentIndex;
}
if (e4.reverse(), i3(e4[0], this.problem.start) || e4.unshift({ ...this.problem.start }), i3(e4[e4.length - 1], this.problem.end) || e4.push({ ...this.problem.end }), this.problem.requireOctilinear) {
const t55 = [e4[0]];
for (let n6 = 0;n6 < e4.length - 1; n6++) {
const o6 = e4[n6], i6 = e4[n6 + 1], r4 = n6 === 0 || n6 === e4.length - 2 ? this.getAllowedConnector(n6 === 0 ? { ...o6, parentIndex: -1 } : o6, i6) : [o6, i6];
if (!r4)
return e4;
t55.push(...r4.slice(1));
}
return t55.filter((t56, e6, n6) => {
if (e6 === 0 || e6 === n6.length - 1)
return true;
const o6 = n6[e6 - 1], i6 = n6[e6 + 1], r4 = (t56.x - o6.x) * (i6.y - t56.y) - (t56.y - o6.y) * (i6.x - t56.x);
return Math.abs(r4) > 0.00000001 || !v3(o6, i6);
});
}
const o4 = [e4[0]];
let i4 = 0;
for (;i4 < e4.length - 1; ) {
let t55 = e4.length - 1;
for (;t55 > i4 + 1 && this.segmentCollides(e4[i4], e4[t55]); )
t55--;
o4.push(e4[t55]), i4 = t55;
}
return o4.filter((t55, e6, n6) => {
if (e6 === 0 || e6 === n6.length - 1)
return true;
const o6 = n6[e6 - 1], i6 = n6[e6 + 1], r4 = (t55.x - o6.x) * (i6.y - t55.y) - (t55.y - o6.y) * (i6.x - t55.x);
return Math.abs(r4) > 0.00000001;
});
}
createStats() {
return { phase: "obstacle-aware-grid-search", gridSize: this.problem.gridSize, traceWidth: this.problem.traceWidth, gridOffset: this.problem.gridOffset, openCells: this.open.size, closedCells: this.closedCellCount, gridCells: this.rows * this.columns };
}
computeProgress() {
return Math.min(0.99, this.iterations / this.MAX_ITERATIONS);
}
getOutput() {
return this.output;
}
getConstructorParams() {
const { obstacleIndex: t54, ...e4 } = this.problem;
return [e4];
}
visualize() {
const t54 = this.nodes.filter((t55) => this.closed[this.toFlatIndex(t55.row, t55.column)]).slice(-2e3).map((t55) => ({ x: t55.x, y: t55.y, color: "rgba(0,90,255,0.22)" })), e4 = this.output?.points ?? [];
return { coordinateSystem: "cartesian", title: this.getSolverName(), rects: [{ center: { x: (this.searchBounds.minX + this.searchBounds.maxX) / 2, y: (this.searchBounds.minY + this.searchBounds.maxY) / 2 }, width: this.searchBounds.maxX - this.searchBounds.minX, height: this.searchBounds.maxY - this.searchBounds.minY, stroke: "#777" }], points: [...t54, { ...this.problem.start, color: "green", label: "reroute start" }, { ...this.problem.end, color: "purple", label: "reroute target" }], lines: e4.length > 1 ? [{ points: e4, strokeColor: "#00a050", strokeWidth: this.problem.traceWidth }] : [], circles: [], texts: [] };
}
};
var T3 = class {
items;
clearance;
boardEdgeClearance;
boardLayers;
minViaHoleEdgeToViaHoleEdgeClearance;
defaultViaHoleDiameter;
bounds;
maxIndexedViaHoleDiameter;
index;
connectionNameSets;
copperObjectIds;
connectionNameResolver;
connectedPads;
dynamicTraceIndex;
constructor(t54, e4, n4, o4 = [], i4 = new t310(t54, e4)) {
var r4;
this.bounds = t54.bounds, this.boardLayers = (r4 = t54.layerCount, ["top", ...Array.from({ length: Math.max(0, r4 - 2) }, (t55, e6) => `inner${e6 + 1}`), ...r4 > 1 ? ["bottom"] : []]), this.dynamicTraceIndex = n4, this.clearance = Math.max(t54.defaultObstacleMargin ?? 0, t54.minTraceToPadEdgeClearance ?? 0, 0.1), this.boardEdgeClearance = t54.minBoardEdgeClearance ?? this.clearance, this.minViaHoleEdgeToViaHoleEdgeClearance = Math.max(t54.minViaHoleEdgeToViaHoleEdgeClearance ?? 0, 0.1), this.defaultViaHoleDiameter = t54.min_via_hole_diameter ?? t54.minViaHoleDiameter ?? 0.3, this.items = [...t54.obstacles.flatMap((t55, e6) => function(t56, e7 = 0.6) {
const n6 = (t56.ccwRotationDegrees ?? 0) * Math.PI / 180, o6 = Math.max(1, Math.ceil(t56.width / e7)), i6 = Math.max(1, Math.ceil(t56.height / e7)), r6 = t56.width / o6, s6 = t56.height / i6, a4 = [];
for (let e8 = 0;e8 < i6; e8++)
for (let i7 = 0;i7 < o6; i7++) {
const o7 = { x: t56.center.x - t56.width / 2 + (i7 + 0.5) * r6, y: t56.center.y - t56.height / 2 + (e8 + 0.5) * s6 }, c4 = r6 / 2, l4 = s6 / 2, h4 = [{ x: o7.x - c4, y: o7.y - l4 }, { x: o7.x + c4, y: o7.y - l4 }, { x: o7.x + c4, y: o7.y + l4 }, { x: o7.x - c4, y: o7.y + l4 }].map((e9) => p3(e9, t56.center, n6));
a4.push({ minX: Math.min(...h4.map((t57) => t57.x)), minY: Math.min(...h4.map((t57) => t57.y)), maxX: Math.max(...h4.map((t57) => t57.x)), maxY: Math.max(...h4.map((t57) => t57.y)), layers: t56.layers, kind: "obstacle", obstacleKind: t56.connectedTo[0]?.startsWith("pcb_via_") ? "via" : t56.connectedTo[0]?.startsWith("pcb_smtpad_") || t56.connectedTo[0]?.startsWith("pcb_plated_hole_") ? "pad" : "other", connectionNames: t56.connectedTo, exactShape: { type: "polygon", points: h4 } });
}
return a4;
}(t55).map((t56) => ({ ...t56, copperObjectId: `obstacle:${e6}` }))), ...this.createTraceItems(t54.fixedTraces ?? [], true), ...this.createTraceItems(e4), ...o4], this.maxIndexedViaHoleDiameter = this.items.reduce((t55, e6) => e6.kind === "via" ? Math.max(t55, e6.viaHoleDiameter ?? this.defaultViaHoleDiameter) : t55, this.defaultViaHoleDiameter), this.connectionNameResolver = i4;
const s4 = new Map;
this.connectionNameSets = this.items.map((t55) => {
let e6 = s4.get(t55.connectionNames);
return e6 || (e6 = new Set(i4.canonicalize(t55.connectionNames)), s4.set(t55.connectionNames, e6)), e6;
}), this.copperObjectIds = this.items.map((t55, e6) => t55.copperObjectId ?? `indexed-item:${e6}`), this.connectedPads = t54.obstacles.flatMap((t55) => t55.connectedTo.some((t56) => t56.startsWith("pcb_smtpad_") || t56.startsWith("pcb_plated_hole_")) ? [{ obstacle: t55, canonicalConnectionNames: new Set(i4.canonicalize(t55.connectedTo)) }] : []), this.index = this.items.length > 0 ? new Ft(this.items.length) : null;
for (const t55 of this.items)
this.index.add(t55.minX, t55.minY, t55.maxX, t55.maxY);
this.index?.finish();
}
createTraceItems(t54, e4 = false) {
const n4 = [];
for (let o4 = 0;o4 < t54.length; o4++) {
const i4 = t54[o4], r4 = e4 ? undefined : o4, s4 = `${e4 ? "fixed-trace" : "trace"}:${o4}`, a4 = !e4 && o4 === this.dynamicTraceIndex, c4 = [i4.connection_name, i4.source_trace_id, i4.rootConnectionName, ...i4.mergedConnectionNames ?? [], ...i4.connectsTo ?? []].filter((t55) => Boolean(t55));
for (let t55 = 0;t55 < i4.route.length; t55++) {
const e6 = i4.route[t55];
if (e6.route_type === "via") {
const o7 = e6.via_diameter ?? 0.6;
n4.push({ minX: e6.x - o7 / 2, minY: e6.y - o7 / 2, maxX: e6.x + o7 / 2, maxY: e6.y + o7 / 2, layers: this.boardLayers, kind: "via", connectionNames: c4, copperObjectId: s4, traceIndex: r4, routeStartIndex: t55, routeEndIndex: t55, viaHoleDiameter: e6.via_hole_diameter ?? this.defaultViaHoleDiameter, exactShape: { type: "circle", center: { x: e6.x, y: e6.y }, radius: o7 / 2 } });
continue;
}
if (a4)
continue;
const o6 = i4.route[t55 + 1];
e6.route_type === "wire" && o6?.route_type === "wire" && e6.layer === o6.layer && n4.push(...u3({ start: e6, end: o6, width: e6.width, base: { layers: [e6.layer], kind: "trace", connectionNames: c4, copperObjectId: s4, traceIndex: r4, routeStartIndex: t55, routeEndIndex: t55 + 1 } }));
}
}
return n4;
}
collides(t54) {
if (this.isOutsideBounds(t54))
return true;
const { radius: e4, candidates: n4, canonicalConnectionNames: o4 } = this.getCollisionCandidates(t54);
for (const i4 of n4)
if (this.itemCollides(i4, t54, e4, o4))
return true;
return false;
}
findCollisions(t54) {
const { radius: e4, candidates: n4, canonicalConnectionNames: o4 } = this.getCollisionCandidates(t54), i4 = [];
for (const r4 of n4)
this.itemCollides(r4, t54, e4, o4) && i4.push(this.items[r4]);
return i4;
}
getSameNetCopperContactIds(t54) {
const e4 = t54.width / 2, n4 = this.index?.search(Math.min(t54.start.x, t54.end.x) - e4, Math.min(t54.start.y, t54.end.y) - e4, Math.max(t54.start.x, t54.end.x) + e4, Math.max(t54.start.y, t54.end.y) + e4) ?? [], o4 = new Set(this.connectionNameResolver.canonicalize(t54.connectionNames)), i4 = new Set;
for (const r4 of n4) {
const n6 = this.items[r4];
n6.layers.includes(t54.layer) && (n6.traceIndex === t54.ignoreTraceIndex || t54.ignoreTraceIndices?.includes(n6.traceIndex ?? -1) || [...this.connectionNameSets[r4]].some((t55) => o4.has(t55)) && this.itemCopperTouches(n6, t54, e4) && i4.add(this.copperObjectIds[r4]));
}
return i4;
}
getConnectedPadWidthLimit(t54) {
if (Math.hypot(t54.end.x - t54.start.x, t54.end.y - t54.start.y) <= 0.00001)
return null;
const e4 = this.getConnectedPadWidthLimitAtPoint(t54, t54.start), n4 = this.getConnectedPadWidthLimitAtPoint(t54, t54.end);
return e4 === null ? n4 : n4 === null ? e4 : Math.min(e4, n4);
}
getConnectedPadWidthLimitAtPoint(t54, e4) {
const n4 = this.getConnectedPadsAtPoint(t54, e4);
return n4.length === 0 ? null : Math.max(...n4.map(({ obstacle: e6 }) => this.getPadWidthNormalToQuery(e6, t54)));
}
getConnectedPadEndpointWidthLimitAtPoint(t54, e4) {
const n4 = this.getConnectedPadsAtPoint(t54, e4);
return n4.length === 0 ? null : Math.max(...n4.map(({ obstacle: t55 }) => {
const n6 = this.getObstacleLocalPoint(e4, t55);
return Math.max(0, 2 * Math.min(t55.width / 2 - Math.abs(n6.x), t55.height / 2 - Math.abs(n6.y)));
}));
}
getConnectedPadBoundaryPoint(t54, e4) {
const n4 = e4 === "start" ? t54.start : t54.end, o4 = e4 === "start" ? t54.end : t54.start, i4 = this.getConnectedPadsAtPoint(t54, n4).sort((e6, n6) => this.getPadWidthNormalToQuery(n6.obstacle, t54) - this.getPadWidthNormalToQuery(e6.obstacle, t54))[0];
return !i4 || this.pointIsInsideObstacle(o4, i4.obstacle) ? null : this.getObstacleBoundaryPoint(n4, o4, i4.obstacle);
}
getConnectedPadsAtPoint(t54, e4) {
const n4 = new Set(this.connectionNameResolver.canonicalize(t54.connectionNames));
return this.connectedPads.filter(({ obstacle: o4, canonicalConnectionNames: i4 }) => o4.layers.includes(t54.layer) && [...i4].some((t55) => n4.has(t55)) && this.pointIsInsideObstacle(e4, o4));
}
pointIsInsideObstacle(t54, e4) {
const { x: n4, y: o4 } = this.getObstacleLocalPoint(t54, e4);
return Math.abs(n4) <= e4.width / 2 + 0.000000001 && Math.abs(o4) <= e4.height / 2 + 0.000000001;
}
getObstacleLocalPoint(t54, e4) {
const n4 = -(e4.ccwRotationDegrees ?? 0) * Math.PI / 180, o4 = Math.cos(n4), i4 = Math.sin(n4), r4 = t54.x - e4.center.x, s4 = t54.y - e4.center.y;
return { x: r4 * o4 - s4 * i4, y: r4 * i4 + s4 * o4 };
}
getPadWidthNormalToQuery(t54, e4) {
const n4 = e4.end.x - e4.start.x, o4 = e4.end.y - e4.start.y, i4 = Math.hypot(n4, o4);
if (i4 <= 0.000000001)
return Math.min(t54.width, t54.height);
const r4 = -o4 / i4, s4 = n4 / i4, a4 = -(t54.ccwRotationDegrees ?? 0) * Math.PI / 180, c4 = Math.cos(a4), l4 = Math.sin(a4), h4 = r4 * c4 - s4 * l4, d4 = r4 * l4 + s4 * c4;
return Math.abs(h4) * t54.width + Math.abs(d4) * t54.height;
}
getObstacleBoundaryPoint(t54, e4, n4) {
const o4 = -(n4.ccwRotationDegrees ?? 0) * Math.PI / 180, i4 = Math.cos(o4), r4 = Math.sin(o4), s4 = (t55) => {
const e6 = t55.x - n4.center.x, o6 = t55.y - n4.center.y;
return { x: e6 * i4 - o6 * r4, y: e6 * r4 + o6 * i4 };
}, a4 = s4(t54), c4 = s4(e4), l4 = { x: c4.x - a4.x, y: c4.y - a4.y }, h4 = [];
if (Math.abs(l4.x) > 0.000000000001) {
const t55 = l4.x > 0 ? n4.width / 2 : -n4.width / 2;
h4.push((t55 - a4.x) / l4.x);
}
if (Math.abs(l4.y) > 0.000000000001) {
const t55 = l4.y > 0 ? n4.height / 2 : -n4.height / 2;
h4.push((t55 - a4.y) / l4.y);
}
const d4 = Math.min(...h4.filter((t55) => t55 >= 0 && t55 <= 1));
return Number.isFinite(d4) ? { x: t54.x + (e4.x - t54.x) * d4, y: t54.y + (e4.y - t54.y) * d4 } : null;
}
getConnectedLayersAtPoint(t54, e4) {
const n4 = new Set(this.connectionNameResolver.canonicalize(e4)), o4 = new Set, i4 = this.index?.search(t54.x, t54.y, t54.x, t54.y) ?? [];
for (const e6 of i4) {
const i6 = this.items[e6];
if (i6.kind !== "obstacle")
continue;
if (![...this.connectionNameSets[e6]].some((t55) => n4.has(t55)))
continue;
if (i6.exactShape?.type === "polygon" ? h3(t54, t54, i6.exactShape.points) <= 0.000000001 : i6.exactShape?.type === "circle" ? Math.hypot(i6.exactShape.center.x - t54.x, i6.exactShape.center.y - t54.y) <= i6.exactShape.radius + 0.000000001 : t54.x >= i6.minX - 0.000000001 && t54.x <= i6.maxX + 0.000000001 && t54.y >= i6.minY - 0.000000001 && t54.y <= i6.maxY + 0.000000001)
for (const t55 of i6.layers)
o4.add(t55);
}
return [...o4];
}
collidesVia(t54) {
return this.getViaViolationSignatures(t54).size > 0;
}
getViaViolationSignatures(t54) {
const e4 = new Set;
for (const n6 of t54.layers) {
const o6 = { start: t54.point, end: t54.point, layer: n6, width: t54.padDiameter, connectionNames: t54.connectionNames, ignoreTraceIndex: t54.ignoreTraceIndex, ignoreTraceIndices: t54.ignoreTraceIndices, ignoreRouteRange: t54.ignoreRouteRange, obstacleClearance: t54.obstacleClearance, blockSameNetObstacles: t54.blockSameNetObstacles, sameNetObstacleClearance: t54.sameNetObstacleClearance };
this.isOutsideBounds(o6) && e4.add(`board-edge:${n6}`);
const { radius: i6, candidates: r6, canonicalConnectionNames: s6 } = this.getCollisionCandidates(o6);
for (const t55 of r6)
this.itemCollides(t55, o6, i6, s6) && e4.add(`copper:${n6}:${this.getViolationObjectId(t55)}`);
}
const n4 = t54.holeDiameter + this.minViaHoleEdgeToViaHoleEdgeClearance;
for (const o6 of t54.otherNewViaPoints ?? [])
Math.hypot(o6.x - t54.point.x, o6.y - t54.point.y) < n4 - 0.000000001 && e4.add(`new-via-drill:${o6.x},${o6.y}:${t54.holeDiameter}`);
const o4 = t54.fixedVias ?? [];
for (let n6 = 0;n6 < o4.length; n6++) {
const i6 = o4[n6], r6 = t54.holeDiameter / 2 + i6.holeDiameter / 2 + this.minViaHoleEdgeToViaHoleEdgeClearance;
Math.hypot(i6.point.x - t54.point.x, i6.point.y - t54.point.y) < r6 - 0.000000001 && e4.add(`fixed-via-drill:${n6}:${i6.point.x},${i6.point.y}:${i6.holeDiameter}`);
}
const i4 = t54.holeDiameter / 2 + this.maxIndexedViaHoleDiameter / 2 + this.minViaHoleEdgeToViaHoleEdgeClearance, r4 = this.index?.search(t54.point.x - i4, t54.point.y - i4, t54.point.x + i4, t54.point.y + i4) ?? [], s4 = new Set;
for (const n6 of r4) {
const o6 = this.items[n6];
if (o6.kind !== "via" || o6.exactShape?.type !== "circle")
continue;
if (o6.traceIndex === t54.ignoreTraceIndex && t54.ignoreRouteRange && (o6.routeEndIndex ?? -1) >= t54.ignoreRouteRange.start && (o6.routeStartIndex ?? Number.POSITIVE_INFINITY) <= t54.ignoreRouteRange.end)
continue;
if (t54.ignoreTraceIndices?.includes(o6.traceIndex ?? -1))
continue;
const i6 = `${this.copperObjectIds[n6] ?? "unknown"}:${o6.routeStartIndex ?? -1}`;
if (s4.has(i6))
continue;
s4.add(i6);
const r6 = o6.viaHoleDiameter ?? this.defaultViaHoleDiameter, a4 = t54.holeDiameter / 2 + r6 / 2 + this.minViaHoleEdgeToViaHoleEdgeClearance;
Math.hypot(o6.exactShape.center.x - t54.point.x, o6.exactShape.center.y - t54.point.y) < a4 - 0.000000001 && e4.add(`indexed-via-drill:${this.getViolationObjectId(n6)}`);
}
return e4;
}
getViolationObjectId(t54) {
const e4 = this.items[t54], n4 = this.copperObjectIds[t54], o4 = `${e4.routeStartIndex ?? ""}-${e4.routeEndIndex ?? ""}`;
if (e4.kind === "obstacle")
return n4;
if (e4.exactShape?.type === "segment") {
const { start: t55, end: i4, width: r4 } = e4.exactShape;
return `${n4}:${e4.kind}:${o4}:${t55.x},${t55.y}:${i4.x},${i4.y}:${r4}`;
}
if (e4.exactShape?.type === "circle") {
const { center: t55, radius: i4 } = e4.exactShape;
return `${n4}:${e4.kind}:${o4}:${t55.x},${t55.y}:${i4}`;
}
return e4.exactShape?.type === "polygon" ? `${n4}:${e4.kind}:${o4}:${e4.exactShape.points.map((t55) => `${t55.x},${t55.y}`).join(";")}` : `${n4}:${e4.kind}:${o4}:${e4.minX},${e4.minY},${e4.maxX},${e4.maxY}`;
}
getCollisionCandidates(t54) {
const e4 = Math.max(this.clearance, t54.obstacleClearance ?? this.clearance, t54.sameNetObstacleClearance ?? 0), n4 = t54.width / 2 + e4, o4 = { minX: Math.min(t54.start.x, t54.end.x) - n4, minY: Math.min(t54.start.y, t54.end.y) - n4, maxX: Math.max(t54.start.x, t54.end.x) + n4, maxY: Math.max(t54.start.y, t54.end.y) + n4 };
return { radius: n4, candidates: this.index?.search(o4.minX, o4.minY, o4.maxX, o4.maxY) ?? [], canonicalConnectionNames: this.connectionNameResolver.canonicalize(t54.connectionNames) };
}
itemCollides(t54, e4, n4, o4) {
const i4 = this.items[t54];
if (!i4.layers.includes(e4.layer))
return false;
const r4 = this.connectionNameSets[t54], s4 = o4.some((t55) => r4.has(t55));
if (s4 && (!e4.blockSameNetObstacles || i4.kind !== "obstacle" || i4.obstacleKind === "via"))
return false;
if (i4.kind === "trace" && e4.ignoreTraceIndices?.includes(i4.traceIndex ?? -1))
return false;
if (i4.kind === "trace" && i4.traceIndex === e4.ignoreTraceIndex && e4.ignoreRouteRange && (i4.routeEndIndex ?? -1) >= e4.ignoreRouteRange.start && (i4.routeStartIndex ?? Number.POSITIVE_INFINITY) <= e4.ignoreRouteRange.end)
return false;
const a4 = i4.kind === "obstacle" && i4.obstacleKind === "pad" ? s4 && e4.blockSameNetObstacles ? e4.sameNetObstacleClearance ?? e4.obstacleClearance ?? this.clearance : e4.obstacleClearance ?? this.clearance : this.clearance, c4 = e4.width / 2 + a4;
return i4.exactShape?.type === "segment" ? c3(e4.start, e4.end, i4.exactShape.start, i4.exactShape.end) <= c4 + i4.exactShape.width / 2 + 0.000000001 : i4.exactShape?.type === "polygon" ? h3(e4.start, e4.end, i4.exactShape.points) <= c4 + 0.000000001 : i4.exactShape?.type === "circle" ? o3(i4.exactShape.center, e4.start, e4.end) <= c4 + i4.exactShape.radius + 0.000000001 : d3(e4.start, e4.end, { minX: i4.minX - c4, minY: i4.minY - c4, maxX: i4.maxX + c4, maxY: i4.maxY + c4 });
}
itemCopperTouches(t54, e4, n4) {
return t54.exactShape?.type === "segment" ? c3(e4.start, e4.end, t54.exactShape.start, t54.exactShape.end) <= n4 + t54.exactShape.width / 2 + 0.000000001 : t54.exactShape?.type === "polygon" ? h3(e4.start, e4.end, t54.exactShape.points) <= n4 + 0.000000001 : t54.exactShape?.type === "circle" ? o3(t54.exactShape.center, e4.start, e4.end) <= n4 + t54.exactShape.radius + 0.000000001 : d3(e4.start, e4.end, { minX: t54.minX - n4, minY: t54.minY - n4, maxX: t54.maxX + n4, maxY: t54.maxY + n4 });
}
isOutsideBounds(t54) {
const e4 = t54.width / 2 + this.boardEdgeClearance;
return Math.min(t54.start.x, t54.end.x) - e4 < this.bounds.minX || Math.max(t54.start.x, t54.end.x) + e4 > this.bounds.maxX || Math.min(t54.start.y, t54.end.y) - e4 < this.bounds.minY || Math.max(t54.start.y, t54.end.y) + e4 > this.bounds.maxY;
}
};
var R3 = [{ x: 0, y: 0 }, { x: 0.5, y: 0 }, { x: 0, y: 0.5 }, { x: 0.5, y: 0.5 }];
var E3 = (t54) => t54?.route_type === "wire";
var A3 = class extends J5 {
inputProblem;
traces;
corridor;
phase = "scan-corridor";
corridorCursor = 0;
blockerCursor = 0;
offsetCursor = 0;
resolutionCursor = 0;
attemptedGridCount = 0;
blockerIndex;
connectionNameResolver;
connectionByTraceId = new Map;
mutableTraceIndices;
blockersByTrace = new Map;
blockers = [];
currentBlocker = null;
currentRange = null;
currentTraceWidth = 0;
gridResolutions = [];
currentObstacleIndex = null;
output = null;
constructor(t54, e4 = new t310(t54.simpleRouteJson, t54.traces)) {
super(), this.inputProblem = structuredClone(t54), this.traces = structuredClone(t54.traces), this.corridor = structuredClone(t54.corridor), this.mutableTraceIndices = t54.mutableTraceIndices ? new Set(t54.mutableTraceIndices) : null, this.connectionNameResolver = e4, this.blockerIndex = new T3(this.inputProblem.simpleRouteJson, this.traces, t54.powerTraceIndex, [], this.connectionNameResolver), this.activeSubSolver = null, this.MAX_ITERATIONS = 25000, this.stats = this.createStats();
}
getSolverName() {
return "LocalTraceInflationSolver";
}
_step() {
if (this.activeSubSolver)
return this.stepActiveSubSolver(), void (this.stats = this.createStats());
switch (this.phase) {
case "scan-corridor":
this.scanNextCorridorSegment();
break;
case "select-blocker":
this.selectNextBlocker();
break;
case "try-elastic-push":
break;
case "try-grid-candidate":
this.startNextGridCandidate();
break;
case "complete":
this.output ? this.solved = true : (this.failed = true, this.error = "No locally reroutable trace blocks the power corridor");
}
this.stats = this.createStats();
}
scanNextCorridorSegment() {
const t54 = this.corridor[this.corridorCursor];
if (!t54)
return this.blockers = [...this.blockersByTrace.values()].sort((t55, e6) => t55.traceIndex - e6.traceIndex), void (this.phase = "select-blocker");
const e4 = this.traces[this.inputProblem.powerTraceIndex], n4 = this.blockerIndex.findCollisions({ start: t54.start, end: t54.end, layer: t54.layer, width: t54.width, connectionNames: e4 ? this.getTraceConnectionNames(e4) : [] });
for (const t55 of n4)
this.recordBlockingTrace(t55);
this.corridorCursor++;
}
recordBlockingTrace(t54) {
if (t54.kind !== "trace" || t54.traceIndex === undefined || t54.routeStartIndex === undefined || t54.routeEndIndex === undefined || t54.traceIndex === this.inputProblem.powerTraceIndex || this.mutableTraceIndices !== null && !this.mutableTraceIndices.has(t54.traceIndex))
return;
const e4 = this.traces[t54.traceIndex];
if (!e4)
return;
const n4 = this.findConnectionForTrace(e4);
if ((n4 ? this.resolveNominalTraceWidth(n4) : this.getTraceNominalWidth(e4)) >= (this.inputProblem.pushOnlyNominalWidthsBelow ?? this.inputProblem.nominalPowerWidth) - e3)
return;
const o4 = this.blockersByTrace.get(t54.traceIndex);
if (o4)
return o4.firstRouteIndex = Math.min(o4.firstRouteIndex, t54.routeStartIndex), void (o4.lastRouteIndex = Math.max(o4.lastRouteIndex, t54.routeEndIndex));
this.blockersByTrace.set(t54.traceIndex, { traceIndex: t54.traceIndex, firstRouteIndex: t54.routeStartIndex, lastRouteIndex: t54.routeEndIndex });
}
selectNextBlocker() {
if (this.currentBlocker = this.blockers[this.blockerCursor] ?? null, !this.currentBlocker)
return void (this.phase = "complete");
const t54 = this.findStableAnchorRange(this.currentBlocker);
if (!t54)
return void this.blockerCursor++;
const e4 = this.traces[this.currentBlocker.traceIndex];
this.currentRange = t54, this.currentTraceWidth = this.getRangeWidth(e4, t54), this.gridResolutions = this.getGridResolutions(this.currentTraceWidth), this.resolutionCursor = 0, this.offsetCursor = 0, this.currentObstacleIndex = new T3(this.inputProblem.simpleRouteJson, this.traces, this.currentBlocker.traceIndex, this.createInflatedCorridorItems(), this.connectionNameResolver), this.activeSubSolver = new x3({ trace: e4, range: t54, layer: e4.route[t54.startIndex].layer, traceWidth: this.currentTraceWidth, corridor: this.corridor, obstacleIndex: this.currentObstacleIndex, connectionNames: this.getTraceConnectionNames(e4) }), this.phase = "try-elastic-push";
}
findStableAnchorRange(t54) {
const e4 = this.traces[t54.traceIndex];
if (!e4)
return null;
let { firstRouteIndex: n4, lastRouteIndex: o4 } = t54;
for (;n4 > 0; ) {
const t55 = e4.route[n4];
if (E3(t55) && this.pointClearsCorridor(t55))
break;
n4--;
}
for (;o4 < e4.route.length - 1; ) {
const t55 = e4.route[o4];
if (E3(t55) && this.pointClearsCorridor(t55))
break;
o4++;
}
const i4 = e4.route[n4], r4 = e4.route[o4];
if (!E3(i4) || !E3(r4) || i4.layer !== r4.layer || !this.pointClearsCorridor(i4) || !this.pointClearsCorridor(r4) || n4 >= o4)
return null;
const s4 = { startIndex: n4, endIndex: o4 }, a4 = this.getRangeLength(e4, s4);
return !Number.isFinite(a4) || a4 > (this.inputProblem.maxRerouteLength ?? 10) + e3 ? null : s4;
}
pointClearsCorridor(t54) {
return this.corridor.every((e4) => {
if (e4.layer !== t54.layer)
return true;
const n4 = e4.width / 2 + t54.width / 2 + this.blockerIndex.clearance;
return o3(t54, e4.start, e4.end) >= n4 - e3;
});
}
startNextGridCandidate() {
if (!this.currentBlocker || !this.currentRange)
return void (this.phase = "select-blocker");
if (this.resolutionCursor >= this.gridResolutions.length)
return this.blockerCursor++, void (this.phase = "select-blocker");
if (this.offsetCursor >= R3.length)
return this.resolutionCursor++, void (this.offsetCursor = 0);
const t54 = this.traces[this.currentBlocker.traceIndex], e4 = t54.route[this.currentRange.startIndex], n4 = t54.route[this.currentRange.endIndex];
if (!E3(e4) || !E3(n4))
return this.blockerCursor++, void (this.phase = "select-blocker");
const o4 = this.gridResolutions[this.resolutionCursor], i4 = R3[this.offsetCursor], r4 = this.currentObstacleIndex;
if (!r4)
return this.blockerCursor++, void (this.phase = "select-blocker");
this.attemptedGridCount++, this.activeSubSolver = new w3({ start: e4, end: n4, layer: e4.layer, traceWidth: this.currentTraceWidth, gridSize: o4, gridOffset: { x: i4.x * o4, y: i4.y * o4 }, connectionNames: this.getTraceConnectionNames(t54), obstacleIndex: r4, ignoreTraceIndex: this.currentBlocker.traceIndex, ignoreRouteRange: { start: this.currentRange.startIndex, end: this.currentRange.endIndex }, bounds: this.inputProblem.simpleRouteJson.bounds, searchPadding: r3(2.5 * this.inputProblem.nominalPowerWidth, 1.5, 4) });
}
stepActiveSubSolver() {
const t54 = this.activeSubSolver;
if (t54.step(), t54.solved || t54.failed) {
if (t54.solved) {
const e4 = t54.getOutput();
if (e4)
return this.applyRoute(e4, t54 instanceof x3 ? "elastic" : "grid"), this.activeSubSolver = null, void (this.phase = "complete");
}
this.failedSubSolvers ??= [], this.failedSubSolvers.push(t54), this.activeSubSolver = null, t54 instanceof x3 ? this.phase = "try-grid-candidate" : this.offsetCursor++;
}
}
applyRoute(t54, e4) {
const n4 = this.currentBlocker, o4 = this.currentRange, i4 = this.traces[n4.traceIndex], r4 = i4.route[o4.startIndex], s4 = i4.route[o4.endIndex], a4 = t54.points.map((t55) => ({ route_type: "wire", x: t55.x, y: t55.y, width: this.currentTraceWidth, layer: r4.layer }));
a4[0].width = Math.max(a4[0].width, r4.width), a4[a4.length - 1].width = Math.max(a4[a4.length - 1].width, s4.width), i4.route.splice(o4.startIndex, o4.endIndex - o4.startIndex + 1, ...a4), this.output = { traces: this.traces, pushedTraceIndex: n4.traceIndex, replacedRange: o4, strategy: e4 };
}
createInflatedCorridorItems() {
return this.corridor.flatMap((t54) => u3({ start: t54.start, end: t54.end, width: t54.width, base: { layers: [t54.layer], kind: "obstacle", connectionNames: [] } }));
}
getGridResolutions(t54) {
return [r3(1.5 * t54, 0.1, 0.3), r3(0.75 * t54, 0.08, 0.18)].filter((t55, e4, n4) => n4.findIndex((e6) => Math.abs(e6 - t55) < e3) === e4);
}
getRangeWidth(t54, e4) {
let n4 = this.inputProblem.simpleRouteJson.minTraceWidth;
for (let o4 = e4.startIndex;o4 <= e4.endIndex; o4++) {
const e6 = t54.route[o4];
E3(e6) && (n4 = Math.max(n4, e6.width));
}
return n4;
}
getRangeLength(t54, e4) {
let n4 = 0;
for (let o4 = e4.startIndex;o4 < e4.endIndex; o4++) {
const e6 = t54.route[o4], i4 = t54.route[o4 + 1];
if (!E3(e6) || !E3(i4) || e6.layer !== i4.layer)
return Number.POSITIVE_INFINITY;
n4 += n3(e6, i4);
}
return n4;
}
resolveNominalTraceWidth(t54) {
return Math.max(t54.nominalTraceWidth ?? t54.width ?? this.inputProblem.simpleRouteJson.nominalTraceWidth ?? this.inputProblem.simpleRouteJson.minTraceWidth, this.inputProblem.simpleRouteJson.minTraceWidth);
}
getTraceNominalWidth(t54) {
return t54.route.reduce((t55, e4) => e4.route_type === "wire" ? Math.max(t55, e4.width) : t55, this.inputProblem.simpleRouteJson.minTraceWidth);
}
findConnectionForTrace(t54) {
const e4 = this.connectionByTraceId.get(t54.pcb_trace_id);
if (e4 !== undefined)
return e4 ?? undefined;
const n4 = this.getTraceConnectionNames(t54), o4 = this.inputProblem.simpleRouteJson.connections.find((t55) => [t55.name, t55.source_trace_id, t55.rootConnectionName, t55.netConnectionName, ...t55.mergedConnectionNames ?? []].filter((t56) => Boolean(t56)).some((t56) => n4.includes(t56))) ?? null;
return this.connectionByTraceId.set(t54.pcb_trace_id, o4), o4 ?? undefined;
}
getTraceConnectionNames(t54) {
return [t54.connection_name, t54.source_trace_id, t54.rootConnectionName, ...t54.mergedConnectionNames ?? []].filter((t55) => Boolean(t55));
}
createStats() {
return { phase: this.phase, corridorSegment: this.corridorCursor, corridorSegmentCount: this.corridor.length, blockingTraceCount: this.blockersByTrace.size, blockerCursor: this.blockerCursor, pushedTraceIndex: this.currentBlocker?.traceIndex, anchorRange: this.currentRange, traceWidth: this.currentTraceWidth, gridSize: this.gridResolutions[this.resolutionCursor], gridOffsetVariant: this.offsetCursor, attemptedGridCount: this.attemptedGridCount };
}
computeProgress() {
return this.phase === "scan-corridor" ? this.corridor.length === 0 ? 0.25 : this.corridorCursor / this.corridor.length * 0.25 : this.blockers.length === 0 ? 0.5 : Math.min(0.99, 0.25 + this.blockerCursor / this.blockers.length);
}
getOutput() {
return this.output;
}
getConstructorParams() {
return [this.inputProblem];
}
visualize() {
const t54 = [];
for (let e4 = 0;e4 < this.traces.length; e4++) {
const n4 = this.traces[e4];
for (let o4 = 0;o4 < n4.route.length - 1; o4++) {
const i4 = n4.route[o4], r4 = n4.route[o4 + 1];
E3(i4) && E3(r4) && i4.layer === r4.layer && t54.push({ points: [i4, r4], strokeColor: e4 === this.currentBlocker?.traceIndex ? "#1769d2" : "#777", strokeWidth: Math.max(i4.width, r4.width) });
}
}
for (const e4 of this.corridor)
t54.push({ points: [e4.start, e4.end], strokeColor: "rgba(255, 128, 0, 0.55)", strokeWidth: e4.width });
return { coordinateSystem: "cartesian", title: this.getSolverName(), lines: t54, points: [], rects: [], circles: [], texts: [] };
}
};
var O3 = 0.000001;
var k3 = (t54, e4) => Math.hypot(t54.x - e4.x, t54.y - e4.y);
var D3 = (t54, e4, n4) => {
const o4 = n4.x - e4.x, i4 = n4.y - e4.y, r4 = o4 * o4 + i4 * i4, s4 = r4 <= 0.000000000001 ? 0 : Math.max(0, Math.min(1, ((t54.x - e4.x) * o4 + (t54.y - e4.y) * i4) / r4));
return Math.hypot(t54.x - (e4.x + s4 * o4), t54.y - (e4.y + s4 * i4));
};
var L3 = (t54, e4, n4) => (e4.x - t54.x) * (n4.y - t54.y) - (e4.y - t54.y) * (n4.x - t54.x);
var z3 = (t54, e4, n4, o4) => ((t55, e6, n6, o6) => {
const i4 = L3(n6, o6, t55), r4 = L3(n6, o6, e6), s4 = L3(t55, e6, n6), a4 = L3(t55, e6, o6);
return (i4 > 0 && r4 < 0 || i4 < 0 && r4 > 0) && (s4 > 0 && a4 < 0 || s4 < 0 && a4 > 0);
})(t54, e4, n4, o4) ? 0 : Math.min(D3(t54, n4, o4), D3(e4, n4, o4), D3(n4, t54, e4), D3(o4, t54, e4));
var B3 = (t54) => {
const e4 = (t54.ccwRotationDegrees ?? 0) * Math.PI / 180, n4 = Math.cos(e4), o4 = Math.sin(e4);
return [{ x: -t54.width / 2, y: -t54.height / 2 }, { x: t54.width / 2, y: -t54.height / 2 }, { x: t54.width / 2, y: t54.height / 2 }, { x: -t54.width / 2, y: t54.height / 2 }].map((e6) => ({ x: t54.center.x + e6.x * n4 - e6.y * o4, y: t54.center.y + e6.x * o4 + e6.y * n4 }));
};
var F3 = (t54) => {
if (!(t54.type === "oval" || t54.shape === "circle"))
return false;
if (Math.abs(t54.width - t54.height) > O3)
throw new Error(`Physical connectivity does not yet support non-circular oval obstacle ${t54.obstacleId ?? "<unknown>"}`);
return true;
};
var j3 = (t54, e4) => {
for (let n6 = 0;n6 < e4.length; n6++)
if (D3(t54, e4[n6], e4[(n6 + 1) % e4.length]) <= O3)
return true;
let n4 = false;
for (let o4 = 0, i4 = e4.length - 1;o4 < e4.length; i4 = o4++) {
const r4 = e4[o4], s4 = e4[i4];
r4.y > t54.y != s4.y > t54.y && t54.x < (s4.x - r4.x) * (t54.y - r4.y) / (s4.y - r4.y) + r4.x && (n4 = !n4);
}
return n4;
};
var $3 = (t54, e4) => {
if (F3(e4))
return Math.max(0, k3(t54, e4.center) - e4.width / 2);
const n4 = B3(e4);
return j3(t54, n4) ? 0 : Math.min(...n4.map((e6, o4) => D3(t54, e6, n4[(o4 + 1) % n4.length])));
};
var Y3 = (t54, e4) => {
if (F3(t54))
return F3(e4) ? Math.max(0, k3(t54.center, e4.center) - t54.width / 2 - e4.width / 2) : Math.max(0, $3(t54.center, e4) - t54.width / 2);
if (F3(e4))
return Y3(e4, t54);
const n4 = B3(t54), o4 = B3(e4);
if (j3(n4[0], o4) || j3(o4[0], n4))
return 0;
let i4 = Number.POSITIVE_INFINITY;
for (let t55 = 0;t55 < n4.length; t55++)
for (let e6 = 0;e6 < o4.length; e6++)
i4 = Math.min(i4, z3(n4[t55], n4[(t55 + 1) % n4.length], o4[e6], o4[(e6 + 1) % o4.length]));
return i4;
};
var X3 = (t54, e4) => ({ minX: t54.minX - e4, minY: t54.minY - e4, maxX: t54.maxX + e4, maxY: t54.maxY + e4 });
var W3 = (t54) => ({ minX: t54.x, minY: t54.y, maxX: t54.x, maxY: t54.y });
var V3 = (t54) => {
if (F3(t54))
return X3(W3(t54.center), t54.width / 2);
const e4 = B3(t54);
return { minX: Math.min(...e4.map((t55) => t55.x)), minY: Math.min(...e4.map((t55) => t55.y)), maxX: Math.max(...e4.map((t55) => t55.x)), maxY: Math.max(...e4.map((t55) => t55.y)) };
};
var H3 = (t54, e4) => {
if (!((t55, e6) => t55.layers.some((t56) => e6.layers.includes(t56)))(t54, e4) || !((t55, e6) => t55.maxX + O3 >= e6.minX && e6.maxX + O3 >= t55.minX && t55.maxY + O3 >= e6.minY && e6.maxY + O3 >= t55.minY)(t54.bounds, e4.bounds))
return false;
if (t54.kind === "bridge-pad") {
const n4 = { kind: "obstacle", obstacle: t54.obstacle, layers: t54.layers, bounds: t54.bounds };
return e4.kind === "bridge-pad" ? H3(n4, { kind: "obstacle", obstacle: e4.obstacle, layers: e4.layers, bounds: e4.bounds }) : H3(n4, e4);
}
return e4.kind === "bridge-pad" ? H3(e4, t54) : t54.kind === "endpoint" ? e4.kind === "endpoint" ? k3(t54.point, e4.point) <= O3 : e4.kind === "obstacle" ? $3(t54.point, e4.obstacle) <= O3 : e4.kind === "segment" ? D3(t54.point, e4.start, e4.end) <= e4.width / 2 + O3 : k3(t54.point, e4.center) <= e4.diameter / 2 + O3 : e4.kind === "endpoint" ? H3(e4, t54) : t54.kind === "obstacle" ? e4.kind === "obstacle" ? Y3(t54.obstacle, e4.obstacle) <= O3 : e4.kind === "segment" ? ((t55, e6, n4) => {
if (F3(n4))
return Math.max(0, D3(n4.center, t55, e6) - n4.width / 2);
const o4 = B3(n4);
return j3(t55, o4) || j3(e6, o4) ? 0 : Math.min(...o4.map((n6, i4) => z3(t55, e6, n6, o4[(i4 + 1) % o4.length])));
})(e4.start, e4.end, t54.obstacle) <= e4.width / 2 + O3 : $3(e4.center, t54.obstacle) <= e4.diameter / 2 + O3 : e4.kind === "obstacle" ? H3(e4, t54) : t54.kind === "segment" ? e4.kind === "segment" ? z3(t54.start, t54.end, e4.start, e4.end) <= (t54.width + e4.width) / 2 + O3 : D3(e4.center, t54.start, t54.end) <= t54.width / 2 + e4.diameter / 2 + O3 : e4.kind === "segment" ? H3(e4, t54) : k3(t54.center, e4.center) <= (t54.diameter + e4.diameter) / 2 + O3;
};
var G3 = class {
parent;
constructor(t54) {
this.parent = Array.from({ length: t54 }, (t55, e4) => e4);
}
find(t54) {
const e4 = this.parent[t54];
if (e4 === t54)
return t54;
const n4 = this.find(e4);
return this.parent[t54] = n4, n4;
}
union(t54, e4) {
const n4 = this.find(t54), o4 = this.find(e4);
n4 !== o4 && (this.parent[o4] = n4);
}
};
var U3 = (t54, e4) => {
const n4 = e4.indexOf(t54.from_layer), o4 = e4.indexOf(t54.to_layer);
return n4 < 0 || o4 < 0 ? [...new Set([t54.from_layer, t54.to_layer])] : e4.slice(Math.min(n4, o4), Math.max(n4, o4) + 1);
};
var Z3 = (t54) => [t54.pcb_trace_id, t54.connection_name, t54.source_trace_id, t54.rootConnectionName, ...t54.mergedConnectionNames ?? [], ...t54.connectsTo ?? []].filter((t55) => Boolean(t55));
var q3 = (t54) => [t54.name, t54.source_trace_id, t54.rootConnectionName, ...t54.mergedConnectionNames ?? [], t54.netConnectionName, ...t54.pointsToConnect.flatMap((t55) => [t55.pointId, t55.pcb_port_id])].filter((t55) => Boolean(t55));
var J3 = (t54) => [t54.obstacleId, ...t54.connectedTo, ...t54.offBoardConnectsTo ?? []].filter((t55) => Boolean(t55));
var Q3 = (t54, e4, n4, o4) => ({ kind: "bridge-contact", center: { x: t54.x, y: t54.y }, diameter: e4, layers: n4, bridgeId: o4, bounds: X3(W3(t54), e4 / 2) });
var K3 = 0.01;
var t410 = { "0603": { horizontalWidth: 0.8, horizontalHeight: 0.95, centerSpacings: [1.65, 1.8] }, 1206: { horizontalWidth: 0.6, horizontalHeight: 1.6, centerSpacings: [3.2] }, "1206x4_pair": { horizontalWidth: 0.8, horizontalHeight: 0.5, centerSpacings: [2.7] } };
var e4 = (t54, e6, n4) => {
if (!t54.layer)
throw new Error(`Jumper ${n4} is missing its layer`);
const o4 = t410[t54.footprint];
if (!o4)
throw new Error(`Unsupported jumper footprint ${String(t54.footprint)} on ${n4}`);
const i4 = Math.abs(t54.end.x - t54.start.x), r4 = Math.abs(t54.end.y - t54.start.y), s4 = (t55) => o4.centerSpacings.some((e7) => Math.abs(t55 - e7) < K3), a4 = r4 < K3 && s4(i4), c4 = i4 < K3 && s4(r4);
if (!a4 && !c4)
throw new Error(`Jumper ${n4} does not match ${t54.footprint} pad spacing`);
const l4 = { type: "rect", center: { ...e6 }, width: a4 ? o4.horizontalWidth : o4.horizontalHeight, height: a4 ? o4.horizontalHeight : o4.horizontalWidth, layers: [t54.layer], connectedTo: [] };
return { kind: "bridge-pad", obstacle: l4, layers: l4.layers, bridgeId: n4, bounds: V3(l4) };
};
var n4 = (t54, e6, n6) => {
if (t54.layer !== n6.layer || e6.layer !== n6.layer)
return false;
const o4 = (t55, e7) => Math.abs(t55.x - e7.x) < K3 && Math.abs(t55.y - e7.y) < K3, i4 = o4(t54, n6.start) && o4(e6, n6.end), r4 = o4(t54, n6.end) && o4(e6, n6.start);
return i4 || r4;
};
var o4 = (t54, e6, n6, o6) => {
const i4 = [], r4 = t54.route.flatMap((t55, e7) => t55.route_type === "jumper" ? [{ routePoint: t55, routePointIndex: e7 }] : []), s4 = new Map;
for (const e7 of r4) {
const n7 = [];
for (let o8 = 1;o8 < t54.route.length; o8++) {
const i6 = t54.route[o8 - 1], r6 = t54.route[o8];
i6?.route_type === "wire" && r6?.route_type === "wire" && n4(i6, r6, e7.routePoint) && n7.push(o8);
}
if (n7.length !== 1)
throw new Error(`Jumper ${t54.pcb_trace_id}:${e7.routePointIndex} matched ${n7.length} placeholder wire segments`);
const o7 = n7[0];
if (s4.has(o7))
throw new Error(`Multiple jumpers matched placeholder segment ${o7} on ${t54.pcb_trace_id}`);
s4.set(o7, e7);
}
let a4;
for (let r6 = 0;r6 < t54.route.length; r6++) {
const c4 = t54.route[r6];
if (c4.route_type === "wire") {
if (a4 && a4.layer === c4.layer && k3(a4, c4) > O3) {
const t55 = a4;
if (s4.get(r6))
;
else {
const e7 = t55.width / 2;
i4.push({ kind: "segment", start: { x: t55.x, y: t55.y }, end: { x: c4.x, y: c4.y }, width: t55.width, layers: [t55.layer], bounds: X3({ minX: Math.min(t55.x, c4.x), minY: Math.min(t55.y, c4.y), maxX: Math.max(t55.x, c4.x), maxY: Math.max(t55.y, c4.y) }, e7) });
}
}
a4 = c4;
continue;
}
if (a4 = undefined, c4.route_type === "via") {
const o7 = t54.route[r6 - 1], s6 = t54.route[r6 + 1];
for (const e7 of [o7, s6])
if (e7?.route_type === "wire" && k3(e7, c4) > O3)
throw new Error(`Via ${t54.pcb_trace_id}:${r6} is adjacent to a non-colocated wire endpoint`);
const a6 = c4.via_diameter ?? n6;
i4.push({ kind: "via", center: { x: c4.x, y: c4.y }, diameter: a6, layers: U3(c4, e6), bounds: X3(W3(c4), a6 / 2) });
continue;
}
const l4 = `${t54.pcb_trace_id}:${r6}:${c4.route_type}`;
if (c4.route_type === "jumper") {
i4.push(e4(c4, c4.start, l4), e4(c4, c4.end, l4));
continue;
}
if (c4.route_type === "through_obstacle") {
if (!o6.find((t55) => t55.layers.includes(c4.from_layer) && t55.layers.includes(c4.to_layer) && $3(c4.start, t55) <= O3 && $3(c4.end, t55) <= O3))
throw new Error(`Through-obstacle marker ${l4} has no same-net multilayer obstacle witness`);
i4.push(Q3(c4.start, 0, [c4.from_layer], l4), Q3(c4.end, 0, [c4.to_layer], l4));
continue;
}
throw new Error(`Unsupported route primitive: ${String(c4.route_type)}`);
}
return i4;
};
var i4 = (t54, e6, n6) => {
const o6 = t54.pointsToConnect[n6];
return o6.pointId ?? o6.pcb_port_id ?? `${t54.name}[${e6}:${n6}]`;
};
var r4 = (t54) => {
const e6 = {}, n6 = {}, o6 = [];
for (let i6 = 0;i6 < t54.connections.length; i6++) {
const r6 = t54.connections[i6];
for (let t55 = 0;t55 < r6.pointsToConnect.length; t55++) {
const s4 = `${i6}:${t55}`;
e6[s4] = i4(r6, i6, t55), n6[s4] = s4, o6.push([s4]);
}
}
return { endpointCount: Object.keys(e6).length, endpointLabels: e6, componentByEndpointKey: n6, endpointComponents: o6 };
};
var s4 = (t54) => {
if (t54 === null || typeof t54 != "object")
return JSON.stringify(t54) ?? String(t54);
if (Array.isArray(t54))
return `[${t54.map((t55) => s4(t55)).join(",")}]`;
const e6 = t54;
return `{${Object.keys(e6).sort().map((t55) => `${JSON.stringify(t55)}:${s4(e6[t55])}`).join(",")}}`;
};
var a4 = (t54, e6) => {
const n6 = new t310(t54, e6, { includePhysicalPositionAliases: true }), o6 = (i6 = t54.layerCount) <= 1 ? ["top"] : i6 === 2 ? ["top", "bottom"] : ["top", ...Array.from({ length: i6 - 2 }, (t55, e7) => `inner${e7 + 1}`), "bottom"];
var i6;
const r6 = ((t55) => {
const e7 = t55.min_via_hole_diameter ?? t55.minViaHoleDiameter ?? 0;
return Math.max(e7, t55.min_via_pad_diameter ?? t55.minViaPadDiameter ?? t55.minViaDiameter ?? 0.6);
})(t54), s6 = new Map, a6 = new Map, c4 = {}, l4 = (t55, e7) => {
const n7 = s6.get(t55) ?? [];
n7.push(e7), s6.set(t55, n7);
};
for (let e7 = 0;e7 < t54.connections.length; e7++) {
const o7 = t54.connections[e7], i7 = n6.canonicalize(q3(o7));
if (i7.length !== 1)
throw new Error(`Connection ${o7.name} resolved to ${i7.length} canonical nets`);
for (let t55 = 0;t55 < o7.pointsToConnect.length; t55++) {
const n7 = o7.pointsToConnect[t55], r7 = `${e7}:${t55}`, s7 = i4(o7, e7, t55);
c4[r7] = s7;
const a7 = { kind: "endpoint", endpointKey: r7, endpointLabel: s7, point: { x: n7.x, y: n7.y }, layers: n7.layers ?? [n7.layer], bounds: W3(n7) };
for (const t56 of i7)
l4(t56, a7);
}
}
for (const e7 of t54.obstacles) {
const t55 = { kind: "obstacle", obstacle: e7, layers: e7.layers, bounds: V3(e7) };
for (const o7 of n6.canonicalize(J3(e7))) {
const n7 = a6.get(o7) ?? [];
n7.push(e7), a6.set(o7, n7), s6.has(o7) && l4(o7, t55);
}
}
for (const i7 of [...e6, ...t54.fixedTraces ?? []]) {
const t55 = n6.canonicalize(Z3(i7));
if (t55.length !== 1)
throw new Error(`Trace ${i7.pcb_trace_id} resolved to ${t55.length} canonical nets`);
const e7 = a6.get(t55[0]) ?? [], c6 = o4(i7, o6, r6, e7);
for (const e8 of t55)
if (s6.has(e8))
for (const t56 of c6)
l4(e8, t56);
}
const h4 = {}, d4 = [];
for (const t55 of s6.values()) {
const e7 = new G3(t55.length), n7 = new Map;
for (let o8 = 0;o8 < t55.length; o8++) {
const i8 = t55[o8];
if (i8.kind !== "bridge-contact" && i8.kind !== "bridge-pad")
continue;
const r7 = n7.get(i8.bridgeId);
r7 === undefined ? n7.set(i8.bridgeId, o8) : e7.union(r7, o8);
}
const o7 = t55.length > 0 ? new Ft(t55.length) : null;
if (o7) {
for (const e8 of t55)
o7.add(e8.bounds.minX, e8.bounds.minY, e8.bounds.maxX, e8.bounds.maxY);
o7.finish();
}
for (let n8 = 0;n8 < t55.length; n8++) {
const i8 = t55[n8], r7 = o7?.search(i8.bounds.minX - O3, i8.bounds.minY - O3, i8.bounds.maxX + O3, i8.bounds.maxY + O3) ?? [];
for (const o8 of r7)
o8 <= n8 || H3(i8, t55[o8]) && e7.union(n8, o8);
}
const i7 = new Map;
for (let n8 = 0;n8 < t55.length; n8++) {
const o8 = t55[n8];
if (o8.kind !== "endpoint")
continue;
const r7 = e7.find(n8), s7 = i7.get(r7) ?? [];
s7.push(o8.endpointKey), i7.set(r7, s7);
}
for (const t56 of i7.values()) {
t56.sort();
const e8 = t56[0];
d4.push(t56);
for (const n8 of t56) {
if (h4[n8] !== undefined)
throw new Error(`Endpoint ${n8} was assigned to multiple canonical nets`);
h4[n8] = e8;
}
}
}
return d4.sort(([t55 = ""], [e7 = ""]) => t55.localeCompare(e7)), { endpointCount: Object.keys(c4).length, endpointLabels: c4, componentByEndpointKey: h4, endpointComponents: d4 };
};
var c4 = class {
baseline;
inputProblem;
baselineCaptureError;
baselineTraceSignature;
constructor(t54, e6) {
this.inputProblem = t54, this.baselineTraceSignature = s4(e6);
try {
this.baseline = a4(t54, e6), this.baselineCaptureError = null;
} catch (e7) {
this.baseline = r4(t54), this.baselineCaptureError = e7 instanceof Error ? e7.message : String(e7);
}
}
validate(t54) {
if (this.baselineCaptureError) {
const e7 = s4(t54) === this.baselineTraceSignature;
return { safe: e7, candidate: this.baseline, regressions: [], validationError: e7 ? `Connectivity validation is limited to exact trace preservation: ${this.baselineCaptureError}` : `Connectivity validation failed closed: ${this.baselineCaptureError}` };
}
let e6;
try {
e6 = a4(this.inputProblem, t54);
} catch (t55) {
return { safe: false, candidate: r4(this.inputProblem), regressions: [], validationError: `Connectivity validation failed closed: ${t55 instanceof Error ? t55.message : String(t55)}` };
}
const n6 = [];
for (const t55 of this.baseline.endpointComponents) {
if (t55.length < 2)
continue;
const o6 = new Map;
for (const n7 of t55) {
const t56 = e6.componentByEndpointKey[n7] ?? `missing:${n7}`, i6 = o6.get(t56) ?? [];
i6.push(n7), o6.set(t56, i6);
}
o6.size <= 1 || n6.push({ baselineEndpointKeys: [...t55], baselineEndpointLabels: t55.map((t56) => this.baseline.endpointLabels[t56]), candidateComponents: [...o6.values()] });
}
return { safe: n6.length === 0, candidate: e6, regressions: n6 };
}
};
var l4 = [{ x: 0, y: 0 }, { x: 0.5, y: 0.5 }];
var h4 = [0.15, 0.2, 0.25, 0.3, 0.4, 0.5];
var d4 = (t54) => t54?.route_type === "wire";
var u4 = (t54) => t54?.route_type === "via";
var p4 = Array.from({ length: 24 }, (t54, e6) => {
const n6 = e6 * Math.PI / 12;
return { x: Math.cos(n6), y: Math.sin(n6) };
});
var m4 = (t54) => [...new Set(t54.map((t55) => Number(t55.toFixed(6))))].sort((t55, e6) => e6 - t55);
var g4 = class extends J5 {
inputProblem;
traces;
obstacleIndex;
phase = "repair-vias";
traceCursor = 0;
routeCursor = 0;
candidateCursor = 0;
clearanceTierCursor = 0;
attemptedCandidateCount = 0;
attemptedClearanceShoveCount = 0;
attemptedViaGridCount = 0;
committedClearanceShoveCount = 0;
viaPairCountRemoved = 0;
viaCountRemoved = 0;
simplifiedPathCount = 0;
normalizedSegmentCount = 0;
achievedExtraClearanceCount = 0;
relocatedViaCount = 0;
unresolvedViaCount = 0;
attemptedPushedViaRepairCount = 0;
committedPushedViaRepairCount = 0;
padClearanceRerouteCount = 0;
unresolvedPadClearanceCount = 0;
initialPadClearanceViolationCount = 0;
remainingPadClearanceViolationCount = 0;
initialPadClearanceViolationCountByClearance = {};
remainingPadClearanceViolationCountByClearance = {};
budgetLimited = false;
connectivityValidationCount = 0;
connectivityRollbackCount = 0;
connectivityRegressionEndpointIds = [];
connectivityValidationError = null;
connectivityRollbackMutationStats = null;
connectionNameResolver;
connectionByTraceId = new Map;
connectivityInvariant;
initialConnectivitySafeTraces;
mutableTraceIndices;
mutableTraceIndexSet;
viaRepairTraceIndices;
traceIndices;
maxRerouteLength;
clearancePaddingTiers;
desiredPadClearance;
initialTraceLengths = new Map;
candidates = [];
candidateShoveCount = 0;
rollbackTraces = null;
baseCandidateValidated = false;
activeShovePadding = 0;
viaGridAttempt = null;
candidateSetMayUseGridFallback = false;
pendingPushedViaRepair = null;
alternatePushedViaRepairs = [];
pushedViaRepairRollbackTraces = null;
connectivityFinalized = false;
finalizedMutatedTraceIndices = [];
resumePhase = "scan-via-pairs";
constructor(t54) {
super(), this.inputProblem = structuredClone(t54), this.traces = structuredClone(t54.traces), this.initialConnectivitySafeTraces = structuredClone(t54.traces), this.connectivityInvariant = new c4(this.inputProblem.simpleRouteJson, this.initialConnectivitySafeTraces), this.connectionNameResolver = new t310(t54.simpleRouteJson, this.traces), this.maxRerouteLength = t54.maxRerouteLength ?? 10, this.desiredPadClearance = t54.desiredPadClearance, this.clearancePaddingTiers = m4([...t54.clearancePaddingTiers ?? [0.1, 0.05, 0], 0]).filter((t55) => t55 >= 0);
const e6 = this.traces.map((t55, e7) => e7), n6 = (t55, e7, n7) => {
const o7 = [...new Set(t55 ?? n7)];
for (const t56 of o7)
if (!Number.isInteger(t56) || t56 < 0 || t56 >= this.traces.length)
throw new RangeError(`Invalid cleanup ${e7} index: ${t56}`);
return o7;
}, o6 = n6(t54.traceIndices, "trace", e6);
this.viaRepairTraceIndices = n6(t54.viaRepairTraceIndices, "via repair trace", o6), this.mutableTraceIndices = n6(t54.mutableTraceIndices, "mutable trace", o6), this.mutableTraceIndexSet = new Set(this.mutableTraceIndices), this.traceIndices = o6.filter((t55) => this.resolveNominalTraceWidth(this.traces[t55]) >= 0.499999);
for (const t55 of this.traceIndices)
this.initialTraceLengths.set(t55, this.measureTraceLength(this.traces[t55]));
this.obstacleIndex = this.createObstacleIndex(), this.initialPadClearanceViolationCount = this.countPadClearanceViolations(), this.remainingPadClearanceViolationCount = this.initialPadClearanceViolationCount, this.initialPadClearanceViolationCountByClearance = this.countPadClearanceViolationsByTier(), this.remainingPadClearanceViolationCountByClearance = { ...this.initialPadClearanceViolationCountByClearance }, this.activeSubSolver = null, this.MAX_ITERATIONS = 1e6, this.stats = this.createStats();
}
getSolverName() {
return "PowerTraceCleanupSolver";
}
_step() {
if (this.activeSubSolver)
return this.stepActiveShoveSolver(), void (this.stats = this.createStats());
switch (this.phase) {
case "repair-vias":
this.repairNextVia();
break;
case "scan-via-pairs":
this.scanNextViaPair();
break;
case "scan-pad-clearance":
this.scanNextPadClearance();
break;
case "scan-simplification":
this.scanNextSimplification();
break;
case "evaluate-candidate":
this.evaluateCurrentCandidate();
break;
case "shove-clearance":
break;
case "route-via-pair":
this.startNextViaGridCandidate();
break;
case "complete":
this.ensureConnectivitySafeOutput(), this.solved = true;
}
this.stats = this.createStats();
}
repairNextVia() {
const t54 = this.viaRepairTraceIndices[this.traceCursor], e6 = t54 === undefined ? undefined : this.traces[t54];
if (!e6)
return this.traceCursor = 0, this.routeCursor = 0, this.phase = "scan-via-pairs", void this.rebuildObstacleIndex();
const n6 = e6.route.findIndex((t55, e7) => e7 >= this.routeCursor && u4(t55));
if (n6 === -1)
return this.traceCursor++, void (this.routeCursor = 0);
this.routeCursor = n6 + 1;
const o6 = e6.route[n6], i6 = e6.route[n6 - 1], r6 = e6.route[n6 + 1];
if (!u4(o6) || !d4(i6) || !d4(r6))
return;
const s6 = this.getTraceConnectionNames(e6), a6 = this.getBaseObstacleClearance();
if (!this.obstacleIndex.collidesVia({ point: o6, layers: this.obstacleIndex.boardLayers, padDiameter: o6.via_diameter ?? 0.6, holeDiameter: o6.via_hole_diameter ?? this.obstacleIndex.defaultViaHoleDiameter, connectionNames: s6, ignoreTraceIndex: t54, ignoreRouteRange: { start: n6, end: n6 }, obstacleClearance: a6, blockSameNetObstacles: true, sameNetObstacleClearance: 0 }))
return;
const c6 = this.findViaRepair(e6, n6, a6);
if (!c6) {
const t55 = this.findPushableViaRepairs(e6, n6, a6), o7 = t55.shift();
return o7 ? (this.alternatePushedViaRepairs = t55, void this.startPushedViaRepair(o7)) : void this.unresolvedViaCount++;
}
e6.route.splice(c6.startIndex, c6.endIndex - c6.startIndex + 1, ...c6.route), this.relocatedViaCount++, this.routeCursor = c6.startIndex + c6.route.length, this.rebuildObstacleIndex();
}
findViaRepair(t54, e6, n6) {
const o6 = this.createViaRepairContext(t54, e6);
if (!o6)
return null;
const i6 = o6.candidates.map((t55) => ({ point: t55, movedLength: n3(o6.leftAnchor, t55) + n3(t55, o6.rightAnchor) })).filter(({ movedLength: t55 }) => t55 <= o6.originalLength + Math.min(6, this.maxRerouteLength) + e3);
i6.sort((t55, e7) => t55.movedLength - e7.movedLength || n3(t55.point, o6.via) - n3(e7.point, o6.via));
for (const t55 of i6)
if (this.isViaRepairPointSafe(o6, t55.point, n6))
return this.createViaRepairReplacement(o6, t55.point);
return null;
}
findPushableViaRepairs(t54, e6, n6) {
const o6 = this.viaRepairTraceIndices[this.traceCursor];
if (o6 === undefined)
return [];
const i6 = this.createViaRepairContext(t54, e6);
if (!i6)
return [];
const r6 = i6.candidates.flatMap((t55) => {
const e7 = n3(i6.leftAnchor, t55) + n3(t55, i6.rightAnchor);
if (e7 > i6.originalLength + Math.min(6, this.maxRerouteLength) + e3)
return [];
const r7 = new Set, s6 = this.getViaRepairCollisionQueries(i6, t55, n6);
for (const t56 of s6)
for (const e8 of this.obstacleIndex.findCollisions(t56)) {
if (e8.kind !== "trace" || e8.traceIndex === undefined || e8.traceIndex === o6 || !this.mutableTraceIndexSet.has(e8.traceIndex))
return [];
r7.add(e8.traceIndex);
}
if (r7.size === 0 || r7.size > 2)
return [];
const a6 = [...r7];
return this.isViaRepairPointSafe(i6, t55, n6, a6) ? [{ point: t55, movedLength: e7, blockerCount: r7.size, blockerKey: [...r7].sort((t56, e8) => t56 - e8).join(",") }] : [];
});
r6.sort((t55, e7) => t55.blockerCount - e7.blockerCount || t55.movedLength - e7.movedLength || n3(t55.point, i6.via) - n3(e7.point, i6.via));
return [...new Map([...r6].reverse().map((t55) => [t55.blockerKey, t55])).values(), ...r6].filter((t55, e7, n7) => n7.findIndex((e8) => e8.point.x === t55.point.x && e8.point.y === t55.point.y) === e7).slice(0, 12).map((t55) => ({ traceIndex: o6, viaIndex: e6, point: t55.point, padClearance: n6, corridor: [{ start: i6.leftAnchor, end: t55.point, layer: i6.leftWire.layer, width: i6.leftWire.width }, { start: t55.point, end: i6.rightAnchor, layer: i6.rightWire.layer, width: i6.rightWire.width }, ...this.obstacleIndex.boardLayers.map((e7) => ({ start: t55.point, end: t55.point, layer: e7, width: i6.viaDiameter }))] }));
}
createViaRepairContext(t54, e6) {
const n6 = t54.route[e6], o6 = t54.route[e6 - 1], i6 = t54.route[e6 + 1];
if (!u4(n6) || !d4(o6) || !d4(i6))
return null;
const r6 = e6 - 1 == 0 || !d4(t54.route[e6 - 2]), s6 = e6 + 1 === t54.route.length - 1 || !d4(t54.route[e6 + 2]), a6 = r6 ? o6 : t54.route[e6 - 2], c6 = s6 ? i6 : t54.route[e6 + 2], l6 = n3(a6, n6) + n3(n6, c6), h6 = this.getTraceConnectionNames(t54), d6 = n6.via_diameter ?? 0.6, u6 = n6.via_hole_diameter ?? this.obstacleIndex.defaultViaHoleDiameter, p6 = Math.max(0.3, u6 + this.obstacleIndex.minViaHoleEdgeToViaHoleEdgeClearance + 0.05), m6 = [p6, p6 + 0.15, p6 + 0.3, p6 + 0.5, p6 + 0.75, p6 + 1, p6 + 1.5, p6 + 2].flatMap((t55) => p4.map((e7) => ({ x: 0.025 * Math.round((n6.x + e7.x * t55) / 0.025), y: 0.025 * Math.round((n6.y + e7.y * t55) / 0.025) }))), g6 = [...m6, ...m6.flatMap((t55) => [{ x: t55.x, y: Math.floor(10 * n6.y) / 10 }, { x: t55.x, y: Math.ceil(10 * n6.y) / 10 }, { x: Math.floor(10 * n6.x) / 10, y: t55.y }, { x: Math.ceil(10 * n6.x) / 10, y: t55.y }])].filter((t55, e7, n7) => n7.findIndex((e8) => e8.x === t55.x && e8.y === t55.y) === e7);
return { trace: t54, viaIndex: e6, via: n6, leftWire: o6, rightWire: i6, leftIsEndpoint: r6, rightIsEndpoint: s6, leftAnchor: a6, rightAnchor: c6, originalLength: l6, connectionNames: h6, viaDiameter: d6, holeDiameter: u6, ignoreRouteRange: { start: Math.max(0, e6 - 2), end: Math.min(t54.route.length - 1, e6 + 2) }, candidates: g6 };
}
getViaRepairCollisionQueries(t54, e6, n6, o6) {
const i6 = this.viaRepairTraceIndices[this.traceCursor], r6 = { connectionNames: t54.connectionNames, ignoreTraceIndex: i6, ignoreTraceIndices: o6, ignoreRouteRange: t54.ignoreRouteRange, obstacleClearance: n6 };
return [...this.obstacleIndex.boardLayers.map((n7) => ({ ...r6, start: e6, end: e6, layer: n7, width: t54.viaDiameter, blockSameNetObstacles: true, sameNetObstacleClearance: 0 })), { ...r6, start: t54.leftAnchor, end: e6, layer: t54.leftWire.layer, width: t54.leftWire.width }, { ...r6, start: e6, end: t54.rightAnchor, layer: t54.rightWire.layer, width: t54.rightWire.width }];
}
isViaRepairPointSafe(t54, e6, n6, o6) {
const i6 = this.viaRepairTraceIndices[this.traceCursor];
return !this.obstacleIndex.collidesVia({ point: e6, layers: this.obstacleIndex.boardLayers, padDiameter: t54.viaDiameter, holeDiameter: t54.holeDiameter, connectionNames: t54.connectionNames, ignoreTraceIndex: i6, ignoreTraceIndices: o6, ignoreRouteRange: { start: t54.viaIndex, end: t54.viaIndex }, obstacleClearance: n6, blockSameNetObstacles: true, sameNetObstacleClearance: 0 }) && !this.getViaRepairCollisionQueries(t54, e6, n6, o6).slice(this.obstacleIndex.boardLayers.length).some((t55) => this.obstacleIndex.collides(t55));
}
createViaRepairReplacement(t54, e6) {
const n6 = { ...t54.leftWire, ...e6 }, o6 = { ...t54.via, ...e6 }, i6 = { ...t54.rightWire, ...e6 };
return { startIndex: t54.viaIndex - 1, endIndex: t54.viaIndex + 1, route: [...t54.leftIsEndpoint ? [t54.leftWire] : [], n6, o6, i6, ...t54.rightIsEndpoint ? [t54.rightWire] : []] };
}
startPushedViaRepair(t54) {
this.pendingPushedViaRepair = t54, this.pushedViaRepairRollbackTraces = structuredClone(this.traces), this.attemptedPushedViaRepairCount++, this.activeSubSolver = new A3({ simpleRouteJson: this.inputProblem.simpleRouteJson, traces: this.traces, powerTraceIndex: t54.traceIndex, nominalPowerWidth: Math.max(...t54.corridor.map((t55) => t55.width)), pushOnlyNominalWidthsBelow: Number.POSITIVE_INFINITY, mutableTraceIndices: this.mutableTraceIndices, corridor: t54.corridor, maxRerouteLength: this.maxRerouteLength }, this.connectionNameResolver);
}
finishPushedViaRepairSolver(t54) {
const e6 = this.pendingPushedViaRepair;
if (this.activeSubSolver = null, !e6)
return;
if (t54.solved) {
const n7 = t54.getOutput();
if (n7) {
this.traces = n7.traces, this.rebuildObstacleIndex();
const t55 = this.traces[e6.traceIndex], o6 = t55 ? this.createViaRepairContext(t55, e6.viaIndex) : null;
if (o6 && this.isViaRepairPointSafe(o6, e6.point, e6.padClearance)) {
const n8 = this.createViaRepairReplacement(o6, e6.point);
return t55.route.splice(n8.startIndex, n8.endIndex - n8.startIndex + 1, ...n8.route), this.relocatedViaCount++, this.committedPushedViaRepairCount++, this.routeCursor = n8.startIndex + n8.route.length, this.pendingPushedViaRepair = null, this.alternatePushedViaRepairs = [], this.pushedViaRepairRollbackTraces = null, void this.rebuildObstacleIndex();
}
}
}
this.pushedViaRepairRollbackTraces && (this.traces = this.pushedViaRepairRollbackTraces), this.pendingPushedViaRepair = null, this.pushedViaRepairRollbackTraces = null;
const n6 = this.alternatePushedViaRepairs.shift();
if (n6)
return this.rebuildObstacleIndex(), void this.startPushedViaRepair(n6);
this.alternatePushedViaRepairs = [], this.unresolvedViaCount++, this.rebuildObstacleIndex();
}
scanNextViaPair() {
const t54 = this.traceIndices[this.traceCursor];
if (t54 === undefined)
return this.traceCursor = 0, this.routeCursor = 0, void (this.phase = "scan-pad-clearance");
const e6 = this.traces[t54], n6 = e6.route.findIndex((t55, e7) => e7 >= this.routeCursor && t55.route_type === "via");
if (n6 === -1)
return void this.advanceTrace();
const o6 = e6.route.slice(n6 + 1).findIndex((t55) => t55.route_type === "via");
if (o6 === -1)
return void this.advanceTrace();
const i6 = n6 - 1, r6 = n6 + 1 + o6 + 1, s6 = e6.route[i6], a6 = e6.route[r6];
if (this.routeCursor = n6 + 1, !d4(s6) || !d4(a6) || s6.layer !== a6.layer || n3(s6, a6) > this.maxRerouteLength + e3)
return;
const c6 = this.createCandidates({ kind: "via-pair", traceIndex: t54, startIndex: i6, endIndex: r6 }), l6 = c6[0]?.width ?? Math.max(s6.width, a6.width), h6 = c6[0]?.padClearance ?? this.getCandidatePadClearance("via-pair", t54, i6, r6), d6 = (n7) => {
const o7 = e6.route[n7];
return !!d4(o7) && this.obstacleIndex.findCollisions({ start: o7, end: o7, layer: o7.layer, width: l6, connectionNames: this.getTraceConnectionNames(e6), ignoreTraceIndex: t54, ignoreRouteRange: { start: Math.max(0, i6 - 1), end: Math.min(e6.route.length - 1, r6 + 1) }, obstacleClearance: h6 }).some((t55) => t55.kind === "obstacle" && t55.obstacleKind === "pad");
}, u6 = e6.route[i6 - 1], p6 = e6.route[r6 + 1], m6 = c6.length > 0 && d6(i6) && d4(u6) && u6.layer === s6.layer ? i6 - 1 : i6, g6 = c6.length > 0 && d6(r6) && d4(p6) && p6.layer === a6.layer ? r6 + 1 : r6, f4 = [{ startIndex: i6, endIndex: r6 }, { startIndex: m6, endIndex: r6 }, { startIndex: i6, endIndex: g6 }, { startIndex: m6, endIndex: g6 }].filter((t55, e7, n7) => n7.findIndex((e8) => e8.startIndex === t55.startIndex && e8.endIndex === t55.endIndex) === e7).flatMap((e7) => e7.startIndex === i6 && e7.endIndex === r6 ? c6 : this.createCandidates({ kind: "via-pair", traceIndex: t54, startIndex: e7.startIndex, endIndex: e7.endIndex }));
f4.length !== 0 && this.beginCandidates(f4, "scan-via-pairs", true);
}
scanNextPadClearance() {
const t54 = this.traceIndices[this.traceCursor];
if (t54 === undefined)
return this.traceCursor = 0, this.routeCursor = 0, void (this.phase = "scan-simplification");
const e6 = this.traces[t54];
if (this.resolveNominalTraceWidth(e6) < 0.499999)
return void this.advanceTrace();
const n6 = this.routeCursor, o6 = e6.route[n6], i6 = e6.route[n6 + 1];
if (!d4(o6) || !d4(i6) || o6.layer !== i6.layer)
return void (n6 >= e6.route.length - 1 ? this.advanceTrace() : this.routeCursor++);
if (this.routeCursor++, !this.segmentHasPadClearanceViolation(t54, n6))
return;
const r6 = this.getPadClearanceIntervals(e6, n6).flatMap((e7) => this.getImprovedPadClearanceTiers(t54, e7.startIndex, e7.endIndex).flatMap((n7) => this.createCandidates({ kind: "pad-clearance", traceIndex: t54, startIndex: e7.startIndex, endIndex: e7.endIndex, padClearance: n7 }).slice(0, 8)));
r6.length !== 0 ? this.beginCandidates(r6.slice(0, 72), "scan-pad-clearance", true) : this.unresolvedPadClearanceCount++;
}
segmentHasPadClearanceViolation(t54, e6) {
const n6 = this.traces[t54], o6 = n6.route[e6], i6 = n6.route[e6 + 1];
return !(!d4(o6) || !d4(i6) || o6.layer !== i6.layer) && this.obstacleIndex.findCollisions({ start: o6, end: i6, layer: o6.layer, width: Math.max(o6.width, i6.width), connectionNames: this.getTraceConnectionNames(n6), ignoreTraceIndex: t54, ignoreRouteRange: { start: Math.max(0, e6 - 1), end: Math.min(n6.route.length - 1, e6 + 2) }, obstacleClearance: this.getPadClearanceForTrace(n6) }).some((t55) => t55.kind === "obstacle" && t55.obstacleKind === "pad");
}
getPadClearanceIntervals(t54, e6) {
const n6 = t54.route[e6];
if (!d4(n6))
return [];
const o6 = [e6];
let i6 = 0;
for (let r7 = e6 - 1;r7 >= 0; r7--) {
const e7 = t54.route[r7], s6 = t54.route[r7 + 1];
if (!d4(e7) || !d4(s6) || e7.layer !== n6.layer || s6.layer !== n6.layer)
break;
if (i6 += n3(e7, s6), i6 > this.maxRerouteLength / 2 + e3)
break;
o6.push(r7);
}
const r6 = [e6 + 1];
i6 = 0;
for (let o7 = e6 + 1;o7 < t54.route.length - 1; o7++) {
const e7 = t54.route[o7], s6 = t54.route[o7 + 1];
if (!d4(e7) || !d4(s6) || e7.layer !== n6.layer || s6.layer !== n6.layer)
break;
if (i6 += n3(e7, s6), i6 > this.maxRerouteLength / 2 + e3)
break;
r6.push(o7 + 1);
}
return o6.flatMap((e7) => r6.map((n7) => ({ startIndex: e7, endIndex: n7, length: this.measureRouteRange(t54, e7, n7).length }))).filter((t55) => t55.length <= this.maxRerouteLength + e3 && t55.startIndex < t55.endIndex).sort((t55, e7) => e7.length - t55.length).slice(0, 8);
}
scanNextSimplification() {
const t54 = this.traceIndices[this.traceCursor];
if (t54 === undefined)
return this.remainingPadClearanceViolationCount = this.countPadClearanceViolations(), this.remainingPadClearanceViolationCountByClearance = this.countPadClearanceViolationsByTier(), void (this.phase = "complete");
const e6 = this.traces[t54], n6 = this.routeCursor, o6 = e6.route[n6];
if (!d4(o6) || n6 >= e6.route.length - 1)
return void (n6 >= e6.route.length - 1 ? this.advanceTrace() : this.routeCursor++);
let i6 = 0;
const r6 = [];
for (let t55 = n6 + 1;t55 < e6.route.length; t55++) {
const s7 = e6.route[t55 - 1], a6 = e6.route[t55];
if (!d4(s7) || !d4(a6) || s7.layer !== o6.layer || a6.layer !== o6.layer)
break;
if (i6 += n3(s7, a6), i6 > this.maxRerouteLength + e3)
break;
const c6 = this.measureRouteRange(e6, n6, t55);
(c6.nonOctilinearSegmentCount > 0 || c6.pointCount > 3) && r6.push(t55);
}
const s6 = r6.slice(-6).reverse().flatMap((e7) => this.createCandidates({ kind: "simplification", traceIndex: t54, startIndex: n6, endIndex: e7 }));
s6.length !== 0 ? this.beginCandidates(s6, "scan-simplification") : this.routeCursor++;
}
createCandidates({ kind: t54, traceIndex: e6, startIndex: n6, endIndex: o6, padClearance: i6 }) {
const r6 = this.traces[e6], s6 = r6.route[n6], a6 = r6.route[o6];
if (!d4(s6) || !d4(a6) || s6.layer !== a6.layer)
return [];
const c6 = this.resolveNominalTraceWidth(r6), l6 = this.measureRouteRange(r6, n6, o6), h6 = i6 ?? this.getCandidatePadClearance(t54, e6, n6, o6), d6 = [], u6 = P3(s6, a6);
if (t54 === "pad-clearance" && I3([s6, a6]) === 0) {
const t55 = n3(s6, a6);
if (t55 > e3) {
const e7 = { x: -(a6.y - s6.y) / t55, y: (a6.x - s6.x) / t55 };
for (const t56 of [0.25, 0.5, 0.75, 1, 1.5, 2])
for (const n7 of [-1, 1])
u6.push([s6, { x: s6.x + e7.x * t56 * n7, y: s6.y + e7.y * t56 * n7 }, { x: a6.x + e7.x * t56 * n7, y: a6.y + e7.y * t56 * n7 }, a6]);
}
}
const p6 = new Map(u6.map((t55) => [t55.map((t56) => `${t56.x.toFixed(6)},${t56.y.toFixed(6)}`).join(";"), t55]));
for (const i7 of p6.values()) {
const u7 = S3(i7);
if (u7 > this.maxRerouteLength + e3 || t54 === "pad-clearance" && u7 > 1.35 * l6.length + 0.5 || t54 === "simplification" && (u7 > 1.1 * l6.length + e3 || this.measureTraceLength(r6) - l6.length + u7 > 1.01 * (this.initialTraceLengths.get(e6) ?? this.measureTraceLength(r6)) + e3))
continue;
const p7 = u7 <= e3 ? c6 : c6 - l6.deficitArea / u7;
if (p7 > c6 + e3)
continue;
const m6 = 0.05 * Math.ceil(Math.max(this.inputProblem.simpleRouteJson.minTraceWidth, p7) / 0.05 - e3), g6 = m4([c6, Math.min(c6, m6), Math.min(c6, Math.max(this.inputProblem.simpleRouteJson.minTraceWidth, p7))].map((t55) => Math.max(t55, s6.width)));
for (const r7 of g6) {
const u8 = this.measureCandidate(i7, r7, c6, a6.width, s6.width);
u8.deficitArea > l6.deficitArea + e3 || u8.conservativeDeficitArea > l6.conservativeDeficitArea + e3 || !this.preservesCoverage(u8, l6) || (t54 !== "simplification" || l6.nonOctilinearSegmentCount !== 0 || u8.pointCount < l6.pointCount && u8.length < l6.length - e3) && d6.push({ kind: t54, traceIndex: e6, startIndex: n6, endIndex: o6, layer: s6.layer, points: i7, width: r7, padClearance: h6, originalQuality: l6 });
}
}
return d6.slice(0, 18);
}
beginCandidates(t54, e6, n6 = false) {
this.candidates = t54, this.candidateCursor = 0, this.clearanceTierCursor = 0, this.candidateShoveCount = 0, this.rollbackTraces = null, this.baseCandidateValidated = false, this.resumePhase = e6, this.candidateSetMayUseGridFallback = n6, this.phase = "evaluate-candidate";
}
evaluateCurrentCandidate() {
const t54 = this.candidates[this.candidateCursor];
if (!t54)
return void this.finishCandidateSet(false);
if (!this.baseCandidateValidated) {
if (!this.candidateCollides(t54, 0))
return this.candidateShoveCount > 0 ? void this.applyCandidate(t54, 0) : (this.baseCandidateValidated = true, void (this.clearanceTierCursor = 0));
return this.getPushableTraceIndices(t54, 0) && this.candidateShoveCount < 2 && this.attemptedClearanceShoveCount < 48 ? void this.startClearanceShove(t54, 0) : void this.advanceCandidate();
}
const e6 = this.clearancePaddingTiers[this.clearanceTierCursor];
if (e6 === undefined || e6 <= e3)
return void this.applyCandidate(t54, 0);
if (this.attemptedCandidateCount++, !this.candidateCollides(t54, e6))
return void this.applyCandidate(t54, e6);
this.getPushableTraceIndices(t54, e6) && this.candidateShoveCount < 2 && this.attemptedClearanceShoveCount < 48 ? this.startClearanceShove(t54, e6) : (this.rollbackCandidateShoves(), this.clearanceTierCursor++, this.candidateShoveCount = 0);
}
advanceCandidate() {
this.rollbackCandidateShoves(), this.candidateCursor++, this.clearanceTierCursor = 0, this.candidateShoveCount = 0, this.baseCandidateValidated = false;
}
candidateCollides(t54, e6) {
const n6 = this.traces[t54.traceIndex], o6 = this.getTraceConnectionNames(n6);
for (let i6 = 0;i6 < t54.points.length - 1; i6++) {
const r6 = this.getCandidateSegmentWidth(t54, i6);
if (this.obstacleIndex.collides({ start: t54.points[i6], end: t54.points[i6 + 1], layer: t54.layer, width: r6 + 2 * e6, connectionNames: o6, ignoreTraceIndex: t54.traceIndex, ignoreRouteRange: { start: Math.max(0, t54.startIndex - 1), end: Math.min(n6.route.length - 1, t54.endIndex + 1) }, obstacleClearance: t54.padClearance }))
return true;
}
return false;
}
getPushableTraceIndices(t54, e6) {
const n6 = this.traces[t54.traceIndex], o6 = this.getTraceConnectionNames(n6), i6 = new Set;
for (let r6 = 0;r6 < t54.points.length - 1; r6++) {
const s6 = this.getCandidateSegmentWidth(t54, r6), a6 = { start: t54.points[r6], end: t54.points[r6 + 1], layer: t54.layer, width: s6 + 2 * e6, connectionNames: o6, ignoreTraceIndex: t54.traceIndex, ignoreRouteRange: { start: Math.max(0, t54.startIndex - 1), end: Math.min(n6.route.length - 1, t54.endIndex + 1) }, obstacleClearance: t54.padClearance };
if (!this.obstacleIndex.collides(a6))
continue;
const c6 = this.obstacleIndex.findCollisions(a6);
if (c6.length === 0)
return null;
for (const e7 of c6) {
if (e7.kind !== "trace" || e7.traceIndex === undefined || e7.traceIndex === t54.traceIndex || !this.mutableTraceIndexSet.has(e7.traceIndex))
return null;
const n7 = this.traces[e7.traceIndex];
if (!n7 || this.resolveNominalTraceWidth(n7) >= t54.width - e3)
return null;
i6.add(e7.traceIndex);
}
}
return i6.size > 0 && i6.size <= 2 ? [...i6] : null;
}
startClearanceShove(t54, e6) {
this.rollbackTraces ??= structuredClone(this.traces), this.activeShovePadding = e6;
const n6 = t54.width + 2 * e6, o6 = t54.points.slice(0, -1).map((n7, o7) => ({ start: n7, end: t54.points[o7 + 1], layer: t54.layer, width: this.getCandidateSegmentWidth(t54, o7) + 2 * e6 }));
this.attemptedClearanceShoveCount++, this.activeSubSolver = new A3({ simpleRouteJson: this.inputProblem.simpleRouteJson, traces: this.traces, powerTraceIndex: t54.traceIndex, nominalPowerWidth: n6, pushOnlyNominalWidthsBelow: t54.width, mutableTraceIndices: this.mutableTraceIndices, corridor: o6, maxRerouteLength: this.maxRerouteLength }, this.connectionNameResolver), this.phase = "shove-clearance";
}
getCandidateSegmentWidth(t54, e6) {
const n6 = this.traces[t54.traceIndex], o6 = n6.route[t54.startIndex], i6 = n6.route[t54.endIndex], r6 = e6 === 0 && d4(o6) ? o6.width : t54.width, s6 = e6 === t54.points.length - 2 && d4(i6) ? i6.width : t54.width;
return Math.max(r6, s6);
}
stepActiveShoveSolver() {
const t54 = this.activeSubSolver;
if (t54.step(), t54.solved || t54.failed)
if (this.pendingPushedViaRepair && t54 instanceof A3)
this.finishPushedViaRepairSolver(t54);
else if (t54 instanceof w3)
this.finishViaGridSolver(t54);
else {
if (this.activeSubSolver = null, this.phase = "evaluate-candidate", t54.solved) {
const e6 = t54.getOutput();
if (e6)
return this.traces = e6.traces, this.candidateShoveCount++, void this.rebuildObstacleIndex();
}
this.failedSubSolvers ??= [], this.failedSubSolvers.push(t54), this.rollbackCandidateShoves(), this.activeShovePadding <= e3 ? this.advanceCandidate() : this.clearanceTierCursor++, this.candidateShoveCount = 0;
}
}
rollbackCandidateShoves() {
this.rollbackTraces && (this.traces = this.rollbackTraces, this.rollbackTraces = null, this.rebuildObstacleIndex());
}
applyCandidate(t54, e6) {
const n6 = this.traces[t54.traceIndex], o6 = n6.route[t54.startIndex], i6 = n6.route[t54.endIndex], r6 = t54.points.map((e7, n7) => ({ ...n7 === 0 ? o6 : n7 === t54.points.length - 1 ? i6 : { route_type: "wire", layer: t54.layer, width: t54.width }, x: e7.x, y: e7.y, layer: t54.layer, width: n7 === 0 ? o6.width : n7 === t54.points.length - 1 ? i6.width : t54.width })), s6 = n6.route.slice(t54.startIndex, t54.endIndex + 1), a6 = t54.originalQuality.nonOctilinearSegmentCount;
if (n6.route.splice(t54.startIndex, t54.endIndex - t54.startIndex + 1, ...r6), t54.kind === "via-pair") {
const e7 = s6.filter((t55) => t55.route_type === "via").length;
this.viaPairCountRemoved++, this.viaCountRemoved += e7, this.routeCursor = Math.max(0, t54.startIndex - 1);
} else
t54.kind === "pad-clearance" ? (this.padClearanceRerouteCount++, this.routeCursor = t54.startIndex + Math.max(1, r6.length - 1)) : (this.simplifiedPathCount++, this.normalizedSegmentCount += a6, this.routeCursor = t54.startIndex + Math.max(1, r6.length - 1));
this.committedClearanceShoveCount += this.candidateShoveCount, e6 > e3 && this.achievedExtraClearanceCount++, this.rollbackTraces = null, this.candidateShoveCount = 0, this.rebuildObstacleIndex(), this.finishCandidateSet(true);
}
finishCandidateSet(t54) {
const e6 = this.candidates[0], n6 = m4(this.candidates.filter((t55) => t55.kind === e6?.kind).map((t55) => t55.width)), o6 = m4(this.candidates.filter((t55) => t55.kind === e6?.kind && t55.traceIndex === e6.traceIndex && t55.startIndex === e6.startIndex && t55.endIndex === e6.endIndex).map((t55) => t55.padClearance));
if (this.rollbackCandidateShoves(), this.candidates = [], this.candidateCursor = 0, this.clearanceTierCursor = 0, this.candidateShoveCount = 0, this.baseCandidateValidated = false, !t54 && this.candidateSetMayUseGridFallback && e6)
return this.candidateSetMayUseGridFallback = false, void this.beginViaGridAttempt(e6, n6, o6);
this.candidateSetMayUseGridFallback = false, t54 || this.routeCursor++, this.phase = this.resumePhase;
}
beginViaGridAttempt(t54, e6, n6 = [t54.padClearance]) {
this.viaGridAttempt = { kind: t54.kind, traceIndex: t54.traceIndex, startIndex: t54.startIndex, endIndex: t54.endIndex, layer: t54.layer, padClearances: n6, padClearanceCursor: 0, originalQuality: t54.originalQuality, widths: e6, widthCursor: 0, gridSizes: [], gridSizeCursor: 0, offsetCursor: 0 }, this.phase = "route-via-pair";
}
startNextViaGridCandidate() {
const t54 = this.viaGridAttempt;
if (!t54)
return void (this.phase = this.resumePhase);
if (t54.padClearanceCursor >= t54.padClearances.length)
return t54.kind === "pad-clearance" && this.unresolvedPadClearanceCount++, this.viaGridAttempt = null, this.routeCursor++, void (this.phase = this.resumePhase);
if (t54.widthCursor >= t54.widths.length)
return t54.padClearanceCursor++, t54.widthCursor = 0, t54.gridSizes = [], t54.gridSizeCursor = 0, void (t54.offsetCursor = 0);
const e6 = t54.widths[t54.widthCursor], n6 = t54.padClearances[t54.padClearanceCursor];
if (t54.gridSizes.length === 0 && (t54.gridSizes = m4([r3(e6 / 2, 0.2, 0.4), r3(e6 / 3, 0.15, 0.25)])), t54.gridSizeCursor >= t54.gridSizes.length)
return t54.widthCursor++, t54.gridSizes = [], t54.gridSizeCursor = 0, void (t54.offsetCursor = 0);
if (t54.offsetCursor >= l4.length)
return t54.gridSizeCursor++, void (t54.offsetCursor = 0);
const o6 = this.traces[t54.traceIndex], i6 = o6.route[t54.startIndex], r6 = o6.route[t54.endIndex];
if (!d4(i6) || !d4(r6))
return this.viaGridAttempt = null, this.routeCursor++, void (this.phase = this.resumePhase);
const s6 = t54.gridSizes[t54.gridSizeCursor], a6 = l4[t54.offsetCursor];
this.attemptedViaGridCount++, this.activeSubSolver = new w3({ start: i6, end: r6, layer: t54.layer, traceWidth: e6, gridSize: s6, gridOffset: { x: a6.x * s6, y: a6.y * s6 }, connectionNames: this.getTraceConnectionNames(o6), obstacleIndex: this.obstacleIndex, ignoreTraceIndex: t54.traceIndex, ignoreRouteRange: { start: Math.max(0, t54.startIndex - 1), end: Math.min(o6.route.length - 1, t54.endIndex + 1) }, bounds: this.inputProblem.simpleRouteJson.bounds, obstacleClearance: n6, searchPadding: Math.min(4, Math.max(2, n3(i6, r6) / 2, 3 * e6)), requireOctilinear: true });
}
finishViaGridSolver(t54) {
const e6 = this.viaGridAttempt;
if (this.activeSubSolver = null, t54.solved && e6) {
const n6 = t54.getOutput(), o6 = this.traces[e6.traceIndex];
if (n6 && o6) {
const t55 = this.resolveNominalTraceWidth(o6), i6 = this.measureCandidate(n6.points, n6.traceWidth, t55, o6.route[e6.endIndex].width, o6.route[e6.startIndex].width);
if (i6.nonOctilinearSegmentCount === 0 && i6.length <= this.maxRerouteLength + e3 && i6.deficitArea <= e6.originalQuality.deficitArea + e3 && i6.conservativeDeficitArea <= e6.originalQuality.conservativeDeficitArea + e3 && this.preservesCoverage(i6, e6.originalQuality)) {
const t56 = { kind: e6.kind, traceIndex: e6.traceIndex, startIndex: e6.startIndex, endIndex: e6.endIndex, layer: e6.layer, points: n6.points, width: n6.traceWidth, padClearance: e6.padClearances[e6.padClearanceCursor], originalQuality: e6.originalQuality };
return this.viaGridAttempt = null, void this.beginCandidates([t56], this.resumePhase, false);
}
}
}
t54.failed && (this.failedSubSolvers ??= [], this.failedSubSolvers.push(t54)), e6 && e6.offsetCursor++, this.phase = "route-via-pair";
}
measureRouteRange(t54, e6, n6) {
const o6 = this.resolveNominalTraceWidth(t54);
let i6 = 0, r6 = 0, s6 = 0, a6 = 0, c6 = 0, l6 = 0, h6 = 0;
for (let d6 = e6;d6 <= n6; d6++) {
if (d4(t54.route[d6]) && h6++, d6 >= n6)
continue;
const e7 = t54.route[d6], u6 = t54.route[d6 + 1];
if (!d4(e7) || !d4(u6) || e7.layer !== u6.layer)
continue;
const p6 = n3(e7, u6);
i6 += p6, r6 += p6 * Math.max(0, o6 - e7.width), e7.width >= o6 - e3 && (a6 += p6), s6 += p6 * Math.max(0, o6 - Math.min(e7.width, u6.width)), Math.min(e7.width, u6.width) >= o6 - e3 && (c6 += p6), l6 += I3([e7, u6]);
}
return { length: i6, deficitArea: r6, conservativeDeficitArea: s6, nominalLength: a6, conservativeNominalLength: c6, nonOctilinearSegmentCount: l6, pointCount: h6 };
}
measureTraceLength(t54) {
let e6 = 0;
for (let n6 = 0;n6 < t54.route.length - 1; n6++) {
const o6 = t54.route[n6], i6 = t54.route[n6 + 1];
d4(o6) && d4(i6) && o6.layer === i6.layer && (e6 += n3(o6, i6));
}
return e6;
}
measureCandidate(t54, e6, n6, o6 = e6, i6 = e6) {
const r6 = S3(t54);
let s6 = 0, a6 = 0, c6 = 0, l6 = 0;
for (let r7 = 0;r7 < t54.length - 1; r7++) {
const h6 = n3(t54[r7], t54[r7 + 1]), d6 = r7 === 0 ? i6 : e6, u6 = r7 === t54.length - 2 ? o6 : e6, p6 = Math.min(d6, u6);
s6 += h6 * Math.max(0, n6 - d6), a6 += h6 * Math.max(0, n6 - p6), d6 >= n6 - e3 && (c6 += h6), p6 >= n6 - e3 && (l6 += h6);
}
return { length: r6, deficitArea: s6, conservativeDeficitArea: a6, nominalLength: c6, conservativeNominalLength: l6, nonOctilinearSegmentCount: I3(t54), pointCount: t54.length };
}
preservesCoverage(t54, e6) {
const n6 = e6.length <= e3 ? 1 : e6.nominalLength / e6.length, o6 = t54.length <= e3 ? 1 : t54.nominalLength / t54.length, i6 = e6.length <= e3 ? 1 : e6.conservativeNominalLength / e6.length, r6 = t54.length <= e3 ? 1 : t54.conservativeNominalLength / t54.length;
return !(o6 + e3 < n6 || r6 + e3 < i6) && !(t54.length > e6.length + e3 && o6 < 0.999999);
}
advanceTrace() {
this.traceCursor++, this.routeCursor = 0, this.rebuildObstacleIndex();
}
createObstacleIndex() {
return new T3(this.inputProblem.simpleRouteJson, this.traces, this.phase === "repair-vias" ? undefined : this.traceIndices?.[this.traceCursor], [], this.connectionNameResolver);
}
rebuildObstacleIndex() {
this.obstacleIndex = this.createObstacleIndex();
}
resolveNominalTraceWidth(t54) {
const e6 = this.findConnectionForTrace(t54);
return Math.max(e6?.nominalTraceWidth ?? e6?.width ?? this.inputProblem.simpleRouteJson.nominalTraceWidth ?? this.inputProblem.simpleRouteJson.minTraceWidth, this.inputProblem.simpleRouteJson.minTraceWidth);
}
getPadClearanceForTrace(t54) {
const e6 = this.getBaseObstacleClearance();
return this.resolveNominalTraceWidth(t54) >= 0.499999 ? Math.max(e6, this.desiredPadClearance ?? this.resolveNominalTraceWidth(t54) / 2) : e6;
}
getBaseObstacleClearance() {
return Math.max(this.inputProblem.simpleRouteJson.defaultObstacleMargin ?? 0, this.inputProblem.simpleRouteJson.minTraceToPadEdgeClearance ?? 0, 0.1);
}
getCandidatePadClearance(t54, e6, n6, o6) {
const i6 = this.traces[e6], r6 = this.getBaseObstacleClearance(), s6 = this.getPadClearanceForTrace(i6);
if (t54 === "pad-clearance")
return s6;
const a6 = t54 === "via-pair" ? Math.min(s6, Math.max(r6, 0.15)) : s6;
return this.findExistingPadClearance(e6, n6, o6, r6, a6);
}
getImprovedPadClearanceTiers(t54, e6, n6) {
const o6 = this.traces[t54], i6 = this.getBaseObstacleClearance(), r6 = this.getPadClearanceForTrace(o6), s6 = this.findExistingPadClearance(t54, e6, n6, i6, r6), a6 = Math.max(0.025, Math.min(0.05, r6 / 10)), c6 = [r6];
for (let t55 = r6 - a6;t55 > s6 + a6 / 2; t55 -= a6)
c6.push(t55);
return m4(c6).filter((t55) => t55 > s6 + e3);
}
findExistingPadClearance(t54, e6, n6, o6, i6) {
if (this.routeRangeHasPadClearanceViolation(t54, e6, n6, o6))
return o6;
if (!this.routeRangeHasPadClearanceViolation(t54, e6, n6, i6))
return i6;
let r6 = o6, s6 = i6;
for (let o7 = 0;o7 < 7; o7++) {
const o8 = (r6 + s6) / 2;
this.routeRangeHasPadClearanceViolation(t54, e6, n6, o8) ? s6 = o8 : r6 = o8;
}
return Math.max(o6, Number((r6 - 0.001).toFixed(6)));
}
routeRangeHasPadClearanceViolation(t54, e6, n6, o6) {
const i6 = this.traces[t54], r6 = this.getTraceConnectionNames(i6);
for (let s6 = e6;s6 < n6; s6++) {
const a6 = i6.route[s6], c6 = i6.route[s6 + 1];
if (!d4(a6) || !d4(c6) || a6.layer !== c6.layer)
continue;
if (this.obstacleIndex.findCollisions({ start: a6, end: c6, layer: a6.layer, width: Math.max(a6.width, c6.width), connectionNames: r6, ignoreTraceIndex: t54, ignoreRouteRange: { start: Math.max(0, e6 - 1), end: Math.min(i6.route.length - 1, n6 + 1) }, obstacleClearance: o6 }).some((t55) => t55.kind === "obstacle" && t55.obstacleKind === "pad"))
return true;
}
return false;
}
countPadClearanceViolations(t54) {
let e6 = 0;
for (const n6 of this.traceIndices) {
const o6 = this.traces[n6];
if (!o6)
continue;
const i6 = this.getTraceConnectionNames(o6);
for (let r6 = 0;r6 < o6.route.length - 1; r6++) {
const s6 = o6.route[r6], a6 = o6.route[r6 + 1];
if (!d4(s6) || !d4(a6) || s6.layer !== a6.layer)
continue;
this.obstacleIndex.findCollisions({ start: s6, end: a6, layer: s6.layer, width: Math.max(s6.width, a6.width), connectionNames: i6, ignoreTraceIndex: n6, ignoreRouteRange: { start: Math.max(0, r6 - 1), end: Math.min(o6.route.length - 1, r6 + 2) }, obstacleClearance: t54 ?? this.getPadClearanceForTrace(o6) }).some((t55) => t55.kind === "obstacle" && t55.obstacleKind === "pad") && e6++;
}
}
return e6;
}
countPadClearanceViolationsByTier() {
return Object.fromEntries(h4.map((t54) => [t54.toFixed(2), this.countPadClearanceViolations(t54)]));
}
findConnectionForTrace(t54) {
const e6 = this.connectionByTraceId.get(t54.pcb_trace_id);
if (e6 !== undefined)
return e6 ?? undefined;
const n6 = new Set(this.connectionNameResolver.canonicalize(this.getTraceConnectionNames(t54))), o6 = this.inputProblem.simpleRouteJson.connections.find((t55) => this.connectionNameResolver.canonicalize(this.getConnectionNames(t55)).some((t56) => n6.has(t56))) ?? null;
return this.connectionByTraceId.set(t54.pcb_trace_id, o6), o6 ?? undefined;
}
getConnectionNames(t54) {
return [t54.name, t54.source_trace_id, t54.rootConnectionName, t54.netConnectionName, ...t54.mergedConnectionNames ?? []].filter((t55) => Boolean(t55));
}
getTraceConnectionNames(t54) {
return [t54.pcb_trace_id, t54.connection_name, t54.source_trace_id, t54.rootConnectionName, ...t54.mergedConnectionNames ?? [], ...t54.connectsTo ?? []].filter((t55) => Boolean(t55));
}
ensureConnectivitySafeOutput() {
if (!this.connectivityFinalized) {
this.connectivityFinalized = true, this.connectivityValidationCount++;
try {
const t54 = this.connectivityInvariant.validate(this.traces);
if (this.connectivityValidationError ??= t54.validationError ?? null, t54.safe)
return void (this.finalizedMutatedTraceIndices = this.getMutatedTraceIndices());
this.connectivityRegressionEndpointIds = [...new Set(t54.regressions.flatMap((t55) => t55.baselineEndpointLabels))];
} catch (t54) {
this.connectivityValidationError = t54 instanceof Error ? t54.message : String(t54);
}
this.connectivityRollbackCount++, this.connectivityRollbackMutationStats = { committedClearanceShoveCount: this.committedClearanceShoveCount, viaPairCountRemoved: this.viaPairCountRemoved, viaCountRemoved: this.viaCountRemoved, simplifiedPathCount: this.simplifiedPathCount, normalizedSegmentCount: this.normalizedSegmentCount, achievedExtraClearanceCount: this.achievedExtraClearanceCount, relocatedViaCount: this.relocatedViaCount, committedPushedViaRepairCount: this.committedPushedViaRepairCount, padClearanceRerouteCount: this.padClearanceRerouteCount }, this.committedClearanceShoveCount = 0, this.viaPairCountRemoved = 0, this.viaCountRemoved = 0, this.simplifiedPathCount = 0, this.normalizedSegmentCount = 0, this.achievedExtraClearanceCount = 0, this.relocatedViaCount = 0, this.committedPushedViaRepairCount = 0, this.padClearanceRerouteCount = 0, this.traces = structuredClone(this.initialConnectivitySafeTraces), this.obstacleIndex = new T3(this.inputProblem.simpleRouteJson, this.traces, undefined, [], this.connectionNameResolver), this.remainingPadClearanceViolationCount = this.countPadClearanceViolations(), this.remainingPadClearanceViolationCountByClearance = this.countPadClearanceViolationsByTier(), this.finalizedMutatedTraceIndices = this.getMutatedTraceIndices();
}
}
getMutatedTraceIndices() {
const t54 = Math.max(this.initialConnectivitySafeTraces.length, this.traces.length);
return Array.from({ length: t54 }, (t55, e6) => e6).filter((t55) => JSON.stringify(this.initialConnectivitySafeTraces[t55]) !== JSON.stringify(this.traces[t55]));
}
createStats() {
const t54 = this.candidates[this.candidateCursor], e6 = this.phase === "repair-vias" ? this.viaRepairTraceIndices : this.traceIndices;
return { phase: this.phase, budgetLimited: this.budgetLimited, completionReason: this.phase === "complete" || this.solved ? this.connectivityRollbackCount > 0 ? "connectivity_rollback" : this.budgetLimited ? "iteration_budget" : this.connectivityValidationError ? "connectivity_validation_unavailable" : "completed" : null, resultStatus: this.connectivityRollbackCount > 0 || this.budgetLimited || this.connectivityValidationError !== null ? "best_effort" : "complete", traceCursor: this.traceCursor, traceCount: e6.length, traceIndex: e6[this.traceCursor], routeCursor: this.routeCursor, candidateCursor: this.candidateCursor, candidateCount: this.candidates.length, candidateKind: t54?.kind, candidateWidth: t54?.width, candidatePointCount: t54?.points.length, clearancePadding: this.clearancePaddingTiers[this.clearanceTierCursor], candidateShoveCount: this.candidateShoveCount, attemptedCandidateCount: this.attemptedCandidateCount, attemptedClearanceShoveCount: this.attemptedClearanceShoveCount, attemptedViaGridCount: this.attemptedViaGridCount, committedClearanceShoveCount: this.committedClearanceShoveCount, viaPairCountRemoved: this.viaPairCountRemoved, viaCountRemoved: this.viaCountRemoved, simplifiedPathCount: this.simplifiedPathCount, normalizedSegmentCount: this.normalizedSegmentCount, achievedExtraClearanceCount: this.achievedExtraClearanceCount, relocatedViaCount: this.relocatedViaCount, unresolvedViaCount: this.unresolvedViaCount, attemptedPushedViaRepairCount: this.attemptedPushedViaRepairCount, committedPushedViaRepairCount: this.committedPushedViaRepairCount, padClearanceRerouteCount: this.padClearanceRerouteCount, unresolvedPadClearanceCount: this.unresolvedPadClearanceCount, initialPadClearanceViolationCount: this.initialPadClearanceViolationCount, remainingPadClearanceViolationCount: this.remainingPadClearanceViolationCount, initialPadClearanceViolationCountByClearance: { ...this.initialPadClearanceViolationCountByClearance }, remainingPadClearanceViolationCountByClearance: { ...this.remainingPadClearanceViolationCountByClearance }, connectivityValidationCount: this.connectivityValidationCount, connectivityRollbackCount: this.connectivityRollbackCount, connectivityRegressionEndpointIds: [...this.connectivityRegressionEndpointIds], connectivityValidationError: this.connectivityValidationError, connectivityRollbackMutationStats: this.connectivityRollbackMutationStats === null ? null : { ...this.connectivityRollbackMutationStats }, mutatedTraceIndices: [...this.finalizedMutatedTraceIndices], spatialIndexRectCount: this.obstacleIndex.items.length };
}
computeProgress() {
if (this.solved || this.phase === "complete")
return 1;
const t54 = this.phase === "repair-vias" ? this.viaRepairTraceIndices : this.traceIndices;
if (t54.length === 0)
return 1;
const e6 = this.resumePhase === "scan-via-pairs" ? 0 : 0.5;
return Math.min(0.99, e6 + this.traceCursor / t54.length * 0.5);
}
getConstructorParams() {
return [this.inputProblem];
}
tryFinalAcceptance() {
const t54 = this.pushedViaRepairRollbackTraces ?? this.rollbackTraces;
t54 && (this.traces = t54), this.activeSubSolver = null, this.rollbackTraces = null, this.pushedViaRepairRollbackTraces = null, this.pendingPushedViaRepair = null, this.alternatePushedViaRepairs = [], this.viaGridAttempt = null, this.candidates = [], this.candidateCursor = 0, this.clearanceTierCursor = 0, this.candidateShoveCount = 0, this.baseCandidateValidated = false, this.candidateSetMayUseGridFallback = false, this.ensureConnectivitySafeOutput(), this.obstacleIndex = new T3(this.inputProblem.simpleRouteJson, this.traces, undefined, [], this.connectionNameResolver), this.remainingPadClearanceViolationCount = this.countPadClearanceViolations(), this.remainingPadClearanceViolationCountByClearance = this.countPadClearanceViolationsByTier(), this.budgetLimited = true, this.phase = "complete", this.solved = true, this.progress = 1, this.stats = this.createStats();
}
getOutput() {
return structuredClone(this.solved ? this.traces : this.initialConnectivitySafeTraces);
}
visualize() {
const t54 = [], e6 = [], n6 = this.candidates[this.candidateCursor];
for (let n7 = 0;n7 < this.traces.length; n7++) {
const o6 = this.traces[n7];
for (const t55 of o6.route)
t55.route_type === "via" && e6.push({ center: t55, radius: (t55.via_diameter ?? 0.6) / 2, fill: "#d4a017", stroke: "#7a5700" });
for (let e7 = 0;e7 < o6.route.length - 1; e7++) {
const n8 = o6.route[e7], i6 = o6.route[e7 + 1];
d4(n8) && d4(i6) && n8.layer === i6.layer && t54.push({ points: [n8, i6], strokeColor: n8.layer === "bottom" ? "#376fc4" : "#777", strokeWidth: n8.width });
}
}
if (n6)
for (let e7 = 0;e7 < n6.points.length - 1; e7++)
t54.push({ points: [n6.points[e7], n6.points[e7 + 1]], strokeColor: "#ff7400", strokeWidth: n6.width + 2 * (this.clearancePaddingTiers[this.clearanceTierCursor] ?? 0) });
return { coordinateSystem: "cartesian", title: `Power trace cleanup: ${this.phase}`, lines: t54, points: [], circles: e6, rects: [], texts: [] };
}
};
var f4 = (t54) => t54?.route_type === "wire";
var y4 = class extends J5 {
inputProblem;
traces;
obstacleIndex;
traceCursor = 0;
routeCursor = 0;
repairedSegmentCount = 0;
repairedPadNeckSegmentCount = 0;
unresolvedSegmentCount = 0;
totalWidthReduction = 0;
budgetLimited = false;
connectivityValidationCount = 0;
connectivityRollbackCount = 0;
connectivityRegressionEndpointIds = [];
connectivityValidationError = null;
connectivityRollbackMutationStats = null;
connectionNameResolver;
nominalWidthByTraceId = new Map;
connectivityInvariant;
initialConnectivitySafeTraces;
minimumTraceWidth;
traceIndices;
connectivityFinalized = false;
constructor(t54) {
super(), this.inputProblem = structuredClone(t54), this.traces = structuredClone(t54.traces), this.initialConnectivitySafeTraces = structuredClone(t54.traces), this.connectivityInvariant = new c4(this.inputProblem.simpleRouteJson, this.initialConnectivitySafeTraces), this.connectionNameResolver = new t310(t54.simpleRouteJson, this.traces), this.minimumTraceWidth = t54.simpleRouteJson.minTraceWidth;
const e6 = t54.traceIndices ? [...new Set(t54.traceIndices)] : this.traces.map((t55, e7) => e7);
for (const t55 of e6)
if (!Number.isInteger(t55) || t55 < 0 || t55 >= this.traces.length)
throw new RangeError(`Invalid clearance-repair trace index: ${t55}`);
this.traceIndices = e6, this.obstacleIndex = this.createConservativeObstacleIndex();
const n6 = this.traceIndices.reduce((t55, e7) => t55 + Math.max(0, this.traces[e7].route.length - 1), 0);
this.MAX_ITERATIONS = Math.max(10, 8 * n6 + 2 * this.traceIndices.length), this.stats = this.createStats();
}
getSolverName() {
return "PowerTraceClearanceRepairSolver";
}
_step() {
const t54 = this.traceIndices[this.traceCursor], e6 = t54 === undefined ? undefined : this.traces[t54];
if (!e6)
return this.ensureConnectivitySafeOutput(), this.solved = true, void (this.stats = this.createStats());
if (this.routeCursor >= e6.route.length - 1)
return this.traceCursor++, this.routeCursor = 0, void (this.stats = this.createStats());
const n6 = this.routeCursor++, o6 = e6.route[n6], i6 = e6.route[n6 + 1];
if (!f4(o6) || !f4(i6) || o6.layer !== i6.layer)
return void (this.stats = this.createStats());
const r6 = Math.max(o6.width, i6.width), s6 = { start: o6, end: i6, layer: o6.layer, width: r6, connectionNames: this.getTraceConnectionNames(e6), ignoreTraceIndex: t54, ignoreRouteRange: { start: n6, end: n6 + 1 } };
if (this.repairConnectedPadNeck(e6, n6, s6))
return void (this.stats = this.createStats());
if (!this.segmentHasForeignTraceCollision(n6, r6))
return void (this.stats = this.createStats());
if (this.segmentHasForeignTraceCollision(n6, this.minimumTraceWidth))
return this.unresolvedSegmentCount++, void (this.stats = this.createStats());
let a6 = this.minimumTraceWidth, c6 = r6;
for (let t55 = 0;t55 < 10; t55++) {
const t56 = (a6 + c6) / 2;
this.segmentHasForeignTraceCollision(n6, t56) ? c6 = t56 : a6 = t56;
}
const l6 = r6 >= 0.5 ? 0.025 : 0.0125, h6 = Math.max(this.minimumTraceWidth, Math.floor((a6 + e3) / l6) * l6), d6 = this.segmentHasForeignTraceCollision(n6, h6) ? a6 : h6, u6 = o6.width, p6 = i6.width;
o6.width = Math.min(o6.width, d6), i6.width = Math.min(i6.width, d6);
const m6 = u6 - o6.width + (p6 - i6.width);
if (m6 <= e3)
return this.unresolvedSegmentCount++, void (this.stats = this.createStats());
this.repairedSegmentCount++, this.totalWidthReduction += m6, this.obstacleIndex = this.createConservativeObstacleIndex(), this.routeCursor = Math.max(0, n6 - 1), this.stats = this.createStats();
}
repairConnectedPadNeck(t54, e6, n6) {
const o6 = t54.route[e6], i6 = t54.route[e6 + 1];
if (!f4(o6) || !f4(i6))
return false;
let r6 = this.obstacleIndex.getConnectedPadWidthLimitAtPoint(n6, o6), s6 = this.obstacleIndex.getConnectedPadWidthLimitAtPoint(n6, i6);
e6 === 0 && (r6 = this.getSmallerLimit(r6, this.obstacleIndex.getConnectedPadEndpointWidthLimitAtPoint(n6, o6))), e6 + 1 === t54.route.length - 1 && (s6 = this.getSmallerLimit(s6, this.obstacleIndex.getConnectedPadEndpointWidthLimitAtPoint(n6, i6)));
const a6 = r6, c6 = s6;
if ((a6 === null || o6.width <= a6 + e3) && (c6 === null || i6.width <= c6 + e3))
return false;
const l6 = o6.width, h6 = i6.width;
if (a6 !== null && (o6.width = Math.min(o6.width, a6)), c6 !== null && (i6.width = Math.min(i6.width, c6)), a6 !== null && c6 === null)
this.insertPadBoundaryTransition(t54, e6, n6, "start", o6.width, h6);
else if (a6 === null && c6 !== null)
this.insertPadBoundaryTransition(t54, e6, n6, "end", i6.width, l6);
else if (a6 !== null && c6 !== null) {
const r7 = this.obstacleIndex.getConnectedPadBoundaryPoint(n6, "start"), s7 = this.obstacleIndex.getConnectedPadBoundaryPoint(n6, "end");
r7 && s7 && (this.insertPadBoundaryTransition(t54, e6, n6, "start", o6.width, h6), this.insertPadBoundaryTransition(t54, e6 + 2, n6, "end", i6.width, l6));
}
return this.totalWidthReduction += l6 - o6.width + (h6 - i6.width), this.repairedPadNeckSegmentCount++, this.obstacleIndex = this.createConservativeObstacleIndex(), this.routeCursor = Math.max(0, e6 - 1), true;
}
getSmallerLimit(t54, e6) {
return t54 === null ? e6 : e6 === null ? t54 : Math.min(t54, e6);
}
insertPadBoundaryTransition(t54, e6, n6, o6, i6, r6) {
const s6 = this.obstacleIndex.getConnectedPadBoundaryPoint(n6, o6);
if (!s6)
return;
const a6 = o6 === "start" ? n6.start : n6.end, c6 = o6 === "start" ? n6.end : n6.start, l6 = Math.hypot(c6.x - a6.x, c6.y - a6.y);
if (l6 <= 0.000000001)
return;
const h6 = Math.min(0.000001, l6 / 4), d6 = (c6.x - a6.x) / l6, u6 = (c6.y - a6.y) / l6, p6 = { route_type: "wire", x: s6.x - d6 * h6, y: s6.y - u6 * h6, width: i6, layer: n6.layer }, m6 = { ...p6, x: s6.x + d6 * h6, y: s6.y + u6 * h6, width: r6 }, g6 = o6 === "start" ? t54.route[e6 + 1] : t54.route[e6], f6 = o6 === "start" ? t54.route[e6 + 2] : t54.route[e6 - 1];
if (f4(g6) && f6?.route_type === "via") {
const e7 = this.resolveNominalTraceWidth(t54);
this.obstacleIndex.collides({ ...n6, start: g6, end: m6, width: e7 }) || (g6.width = Math.max(g6.width, e7), m6.width = g6.width);
}
t54.route.splice(e6 + 1, 0, ...o6 === "start" ? [p6, m6] : [m6, p6]);
}
resolveNominalTraceWidth(t54) {
const e6 = this.nominalWidthByTraceId.get(t54.pcb_trace_id);
if (e6 !== undefined)
return e6;
const n6 = new Set(this.connectionNameResolver.canonicalize(this.getTraceConnectionNames(t54))), o6 = this.inputProblem.simpleRouteJson.connections.find((t55) => this.connectionNameResolver.canonicalize([t55.name, t55.source_trace_id, t55.rootConnectionName, t55.netConnectionName, ...t55.mergedConnectionNames ?? []].filter((t56) => Boolean(t56))).some((t56) => n6.has(t56))), i6 = Math.max(o6?.nominalTraceWidth ?? o6?.width ?? this.inputProblem.simpleRouteJson.nominalTraceWidth ?? this.minimumTraceWidth, this.minimumTraceWidth);
return this.nominalWidthByTraceId.set(t54.pcb_trace_id, i6), i6;
}
segmentHasForeignTraceCollision(t54, e6) {
const n6 = this.traceIndices[this.traceCursor], o6 = n6 === undefined ? undefined : this.traces[n6], i6 = o6?.route[t54], r6 = o6?.route[t54 + 1];
return !!(o6 && f4(i6) && f4(r6) && i6.layer === r6.layer) && this.obstacleIndex.findCollisions({ start: i6, end: r6, layer: i6.layer, width: e6, connectionNames: this.getTraceConnectionNames(o6), ignoreTraceIndex: n6, ignoreRouteRange: { start: t54, end: t54 + 1 } }).some((t55) => t55.kind === "trace" && t55.traceIndex !== undefined && t55.traceIndex !== n6);
}
createConservativeObstacleIndex() {
const t54 = structuredClone(this.traces);
for (const e6 of t54)
for (let t55 = 0;t55 < e6.route.length - 1; t55++) {
const n6 = e6.route[t55], o6 = e6.route[t55 + 1];
f4(n6) && f4(o6) && n6.layer === o6.layer && (n6.width = Math.max(n6.width, o6.width));
}
return new T3(this.inputProblem.simpleRouteJson, t54, undefined, [], this.connectionNameResolver);
}
getTraceConnectionNames(t54) {
return [t54.pcb_trace_id, t54.connection_name, t54.source_trace_id, t54.rootConnectionName, ...t54.mergedConnectionNames ?? [], ...t54.connectsTo ?? []].filter((t55) => Boolean(t55));
}
ensureConnectivitySafeOutput() {
if (!this.connectivityFinalized) {
this.connectivityFinalized = true, this.connectivityValidationCount++;
try {
const t54 = this.connectivityInvariant.validate(this.traces);
if (this.connectivityValidationError ??= t54.validationError ?? null, t54.safe)
return;
this.connectivityRegressionEndpointIds = [...new Set(t54.regressions.flatMap((t55) => t55.baselineEndpointLabels))];
} catch (t54) {
this.connectivityValidationError = t54 instanceof Error ? t54.message : String(t54);
}
this.connectivityRollbackCount++, this.connectivityRollbackMutationStats = { repairedSegmentCount: this.repairedSegmentCount, repairedPadNeckSegmentCount: this.repairedPadNeckSegmentCount, totalWidthReduction: this.totalWidthReduction }, this.repairedSegmentCount = 0, this.repairedPadNeckSegmentCount = 0, this.totalWidthReduction = 0, this.traces = structuredClone(this.initialConnectivitySafeTraces), this.obstacleIndex = this.createConservativeObstacleIndex();
}
}
createStats() {
return { phase: this.solved ? "complete" : "repair-trace-clearance", budgetLimited: this.budgetLimited, completionReason: this.solved ? this.connectivityRollbackCount > 0 ? "connectivity_rollback" : this.budgetLimited ? "iteration_budget" : this.connectivityValidationError ? "connectivity_validation_unavailable" : "completed" : null, resultStatus: this.connectivityRollbackCount > 0 || this.budgetLimited || this.connectivityValidationError !== null ? "best_effort" : "complete", traceCursor: this.traceCursor, traceCount: this.traceIndices.length, traceIndex: this.traceIndices[this.traceCursor], routeCursor: this.routeCursor, repairedSegmentCount: this.repairedSegmentCount, repairedPadNeckSegmentCount: this.repairedPadNeckSegmentCount, unresolvedSegmentCount: this.unresolvedSegmentCount, totalWidthReduction: this.totalWidthReduction, connectivityValidationCount: this.connectivityValidationCount, connectivityRollbackCount: this.connectivityRollbackCount, connectivityRegressionEndpointIds: [...this.connectivityRegressionEndpointIds], connectivityValidationError: this.connectivityValidationError, connectivityRollbackMutationStats: this.connectivityRollbackMutationStats === null ? null : { ...this.connectivityRollbackMutationStats }, spatialIndexRectCount: this.obstacleIndex.items.length };
}
computeProgress() {
return this.solved || this.traceIndices.length === 0 ? 1 : Math.min(0.99, this.traceCursor / this.traceIndices.length);
}
tryFinalAcceptance() {
this.ensureConnectivitySafeOutput(), this.budgetLimited = true, this.solved = true, this.progress = 1, this.stats = this.createStats();
}
getConstructorParams() {
return [this.inputProblem];
}
getOutput() {
return structuredClone(this.solved ? this.traces : this.initialConnectivitySafeTraces);
}
visualize() {
const t54 = [];
for (let e6 = 0;e6 < this.traces.length; e6++) {
const n6 = this.traces[e6];
for (let o6 = 0;o6 < n6.route.length - 1; o6++) {
const i6 = n6.route[o6], r6 = n6.route[o6 + 1];
f4(i6) && f4(r6) && i6.layer === r6.layer && t54.push({ points: [i6, r6], strokeColor: e6 === this.traceIndices[this.traceCursor] && o6 === this.routeCursor ? "#ff7400" : i6.layer === "bottom" ? "#376fc4" : "#777", strokeWidth: Math.max(i6.width, r6.width) });
}
}
return { coordinateSystem: "cartesian", title: "Power trace direction-independent clearance repair", lines: t54, points: [], circles: [], rects: [], texts: [] };
}
};
var _4 = [{ x: 0, y: 0 }, { x: 0.5, y: 0 }, { x: 0, y: 0.5 }, { x: 0.5, y: 0.5 }];
var b4 = [{ offset: { x: 0, y: 0 }, strictNecking: true }, { offset: { x: 0.5, y: 0.5 }, strictNecking: true }, { offset: { x: 0, y: 0 }, strictNecking: false }, { offset: { x: 0.5, y: 0.5 }, strictNecking: false }];
var x4 = (t54) => [...new Set(t54.map((t55) => Number(t55.toFixed(6))))].sort((t55, e6) => e6 - t55);
var v4 = (t54) => t54?.route_type === "wire";
var I4 = class extends J5 {
inputProblem;
options;
traces;
obstacleIndex;
connectionNameResolver;
connectionByTraceId = new Map;
connectivityInvariant;
lastConnectivitySafeTraces;
traceOrder;
selectedOwnedTraceIndices;
selectedCleanupTraceIndices;
selectedViaRepairTraceIndices;
mutableBlockerTraceIndices;
immutableTraceIndices;
initialImmutableTraceSignatures = new Map;
traceOrderCursor = -1;
maxPassCount = 4;
previousWidthDeficit = 0;
passIndex = 0;
completedPassCount = 0;
lastNormalizedWidthDeficitGain = 0;
normalizedWidthDeficitGainByPass = [];
plateauReached = false;
phase = "scan-trace";
traceIndex = -1;
routeSegmentIndex = 0;
nominalTraceWidth = 0;
currentIntervals = [];
intervalCursor = 0;
candidateWidths = [];
widthCursor = 0;
gridResolutions = [];
resolutionCursor = 0;
offsetCursor = 0;
keptTraceCount = 0;
recreatedTraceCount = 0;
expandedSegmentCount = 0;
intermediateExpandedSegmentCount = 0;
pathWidthUpgradeCount = 0;
inPlaceWidthProbeCount = 0;
reroutedSegmentCount = 0;
unresolvedSegmentCount = 0;
attemptedGridCount = 0;
attemptedLayerGridCount = 0;
attemptedInflationCount = 0;
pushedTraceCount = 0;
elasticPushedTraceCount = 0;
layerReroutedTraceCount = 0;
insertedViaCount = 0;
neckedLayerSegmentCount = 0;
removedViaPairCount = 0;
removedViaCount = 0;
simplifiedPathCount = 0;
normalizedSegmentCount = 0;
cleanupClearanceShoveCount = 0;
relocatedViaCount = 0;
unresolvedViaCount = 0;
initialImmutableViaViolationCount = 0;
remainingImmutableViaViolationCount = 0;
initialImmutableViaViolationPairCount = 0;
remainingImmutableViaViolationPairCount = 0;
immutableTraceMutationIds = [];
lastSafeImmutableViaViolationSignatures = new Set;
immutableViaViolationRollbackCount = 0;
attemptedImmutableViaViolationCount = null;
attemptedImmutableViaViolationPairCount = null;
immutableViaViolationRegressionIds = [];
padClearanceRerouteCount = 0;
unresolvedPadClearanceCount = 0;
repairedTraceClearanceSegmentCount = 0;
repairedPadNeckSegmentCount = 0;
unresolvedTraceClearanceSegmentCount = 0;
sameNetContactRejectionCount = 0;
connectivityValidationCount = 0;
connectivityRollbackCount = 0;
connectivityRollbackPhases = [];
immutableSafetyRollbackCount = 0;
immutableSafetyRollbackPhases = [];
connectivityRegressionEndpointIds = [];
connectivityValidationError = null;
connectivityRollbackMutationStats = null;
immutableSafetyRollbackMutationStats = null;
discardedExpansionMutationStats = null;
initialPadClearanceViolationCount = 0;
remainingPadClearanceViolationCount = 0;
initialPadClearanceViolationCountByClearance = {};
remainingPadClearanceViolationCountByClearance = {};
budgetLimitedExpansion = false;
finalAcceptanceUsed = false;
cleanupCompleted = false;
clearanceRepairCompleted = false;
cleanupBestEffortAccepted = false;
clearanceRepairBestEffortAccepted = false;
cleanupIterationBudget = 0;
clearanceRepairIterationBudget = 0;
expansionPushedTraceIndices = new Set;
cleanupMutatedTraceIndices = [];
failedSubSolverCount = 0;
inflationAttemptsBySegment = new Map;
layerAttemptCountByTrace = new Map;
layerRerouteCountByTrace = new Map;
activeInflationKey = null;
activeInflationWidth = null;
layerAttempt = null;
pendingLayerOutput = null;
pendingLayerPushCount = 0;
constructor(t54, e6 = {}) {
super(), this.inputProblem = structuredClone(t54), this.options = structuredClone(e6), this.traces = structuredClone(t54.traces ?? []), this.connectionNameResolver = new t310(this.inputProblem, this.traces), this.lastConnectivitySafeTraces = structuredClone(this.traces), this.connectivityInvariant = new c4(this.inputProblem, this.lastConnectivitySafeTraces);
const n6 = e6.onlyConnectionNames ? new Set(this.connectionNameResolver.canonicalize([...e6.onlyConnectionNames])) : null, o6 = this.traces.flatMap((t55, e7) => {
if (!n6)
return [e7];
return this.connectionNameResolver.canonicalize(this.getTraceConnectionNames(t55)).some((t56) => n6.has(t56)) ? [e7] : [];
}), i6 = new Map(o6.map((t55) => [t55, this.getInitialTracePriority(this.traces[t55])]));
this.traceOrder = o6.sort((t55, e7) => i6.get(e7) - i6.get(t55) || t55 - e7), this.selectedOwnedTraceIndices = this.traceOrder.filter((t55) => this.findConnectionForTrace(this.traces[t55])), this.selectedCleanupTraceIndices = [...this.selectedOwnedTraceIndices], this.selectedViaRepairTraceIndices = [...this.selectedOwnedTraceIndices], this.mutableBlockerTraceIndices = this.traces.flatMap((t55, e7) => this.findConnectionForTrace(t55) ? [e7] : []);
const r6 = new Set(this.mutableBlockerTraceIndices);
this.immutableTraceIndices = this.traces.flatMap((t55, e7) => r6.has(e7) ? [] : (this.initialImmutableTraceSignatures.set(e7, JSON.stringify(t55)), [e7])), this.previousWidthDeficit = this.calculateWidthDeficit().deficit, this.obstacleIndex = new T3(this.inputProblem, this.traces, this.traceIndex >= 0 ? this.traceIndex : undefined, [], this.connectionNameResolver), this.lastSafeImmutableViaViolationSignatures = this.getImmutableViaViolationSignatures(this.traces), this.initialImmutableViaViolationCount = this.countViolatingImmutableVias(this.lastSafeImmutableViaViolationSignatures), this.remainingImmutableViaViolationCount = this.initialImmutableViaViolationCount, this.initialImmutableViaViolationPairCount = this.lastSafeImmutableViaViolationSignatures.size, this.remainingImmutableViaViolationPairCount = this.initialImmutableViaViolationPairCount, this.activeSubSolver = null, this.MAX_ITERATIONS = 8000000, this.stats = this.createStats();
}
getSolverName() {
return "PowerTraceExpanderSolver";
}
_step() {
if (this.shouldStartBudgetFinalization())
return this.startBudgetFinalization(), void (this.stats = this.createStats());
if (this.activeSubSolver)
return this.stepActiveGridSolver(), void (this.stats = this.createStats());
switch (this.phase) {
case "scan-trace":
this.scanNextTrace();
break;
case "evaluate-segment":
this.evaluateNextSegment();
break;
case "try-trace-inflation":
case "cleanup":
case "repair-trace-clearance":
break;
case "try-layer-candidate":
this.startNextLayerCandidate();
break;
case "try-grid-candidate":
this.startNextGridCandidate();
break;
case "complete":
this.acceptConnectivityCheckpoint(this.traces, "final"), this.solved = true;
}
this.stats = this.createStats();
}
scanNextTrace() {
if (this.traceOrderCursor++, this.routeSegmentIndex = 0, this.traceOrderCursor >= this.traceOrder.length)
return void this.finishOrStartNextPass();
this.traceIndex = this.traceOrder[this.traceOrderCursor];
const t54 = this.traces[this.traceIndex];
this.findConnectionForTrace(t54) ? (this.nominalTraceWidth = this.resolveNominalTraceWidth(t54), this.traceMeetsNominalWidth(t54, this.nominalTraceWidth) ? this.keptTraceCount++ : (this.rebuildObstacleIndex(), t54.route = function(t55, e6) {
if (t55.length < 2)
return t55.map((t56) => ({ ...t56 }));
const n6 = [];
for (let o6 = 0;o6 < t55.length - 1; o6++) {
const i6 = t55[o6], r6 = t55[o6 + 1];
if (n6.push({ ...i6 }), i6.route_type !== "wire" || r6.route_type !== "wire" || i6.layer !== r6.layer || i6.width >= e6 - e3)
continue;
const s6 = n3(i6, r6), a6 = Math.max(1, Math.ceil(s6 / e6));
for (let t56 = 1;t56 < a6; t56++) {
const e7 = t56 / a6;
n6.push({ route_type: "wire", x: i6.x + (r6.x - i6.x) * e7, y: i6.y + (r6.y - i6.y) * e7, width: i6.width, layer: i6.layer });
}
}
return n6.push({ ...t55[t55.length - 1] }), n6;
}(t54.route, this.nominalTraceWidth), this.recreatedTraceCount++, this.phase = "evaluate-segment")) : this.keptTraceCount++;
}
finishOrStartNextPass() {
const { deficit: t54, nominalArea: e6 } = this.calculateWidthDeficit(), n6 = this.previousWidthDeficit - t54;
if (this.lastNormalizedWidthDeficitGain = e6 <= e3 ? 0 : n6 / e6, this.normalizedWidthDeficitGainByPass.push(this.lastNormalizedWidthDeficitGain), this.plateauReached = this.lastNormalizedWidthDeficitGain < 0.001, this.completedPassCount = this.passIndex + 1, this.passIndex + 1 < this.maxPassCount && this.lastNormalizedWidthDeficitGain >= 0.001)
return this.previousWidthDeficit = t54, this.passIndex++, this.traceOrderCursor = -1, this.traceIndex = -1, this.routeSegmentIndex = 0, this.inflationAttemptsBySegment.clear(), void (this.phase = "scan-trace");
this.startCleanup();
}
startCleanup() {
this.acceptConnectivityCheckpoint(this.traces, "expansion"), this.traceIndex = this.traces.length, this.phase = "cleanup";
const t54 = new g4({ simpleRouteJson: this.inputProblem, traces: this.traces, traceIndices: this.selectedCleanupTraceIndices, viaRepairTraceIndices: this.selectedViaRepairTraceIndices, mutableTraceIndices: this.mutableBlockerTraceIndices, maxRerouteLength: 10, desiredPadClearance: this.options.powerTraceToPadClearance }), e6 = this.getRemainingParentIterationsAfterCurrentStep(), n6 = e6 === 0 ? 0 : Math.max(1, Math.floor(0.75 * e6));
t54.MAX_ITERATIONS = Math.min(t54.MAX_ITERATIONS, n6), this.cleanupIterationBudget = t54.MAX_ITERATIONS, this.activeSubSolver = t54;
}
shouldStartBudgetFinalization() {
return !this.budgetLimitedExpansion && (this.phase !== "cleanup" && this.phase !== "repair-trace-clearance" && this.phase !== "complete" && this.iterations >= this.getExpansionIterationBudget());
}
getFinalizationIterationReserve() {
return Math.min(Math.max(0, this.MAX_ITERATIONS - 1), Math.max(1, Math.floor(0.125 * this.MAX_ITERATIONS)));
}
getExpansionIterationBudget() {
return Math.max(1, this.MAX_ITERATIONS - this.getFinalizationIterationReserve());
}
startBudgetFinalization() {
this.budgetLimitedExpansion = true, this.activeSubSolver = null, this.pendingLayerOutput = null, this.pendingLayerPushCount = 0, this.activeInflationKey = null, this.activeInflationWidth = null, this.layerAttempt = null, this.discardInFlightExpansion(), this.startCleanup();
}
discardInFlightExpansion() {
this.discardedExpansionMutationStats = this.captureAndResetExpansionMutationStats(), this.restoreLastConnectivitySafeTraces();
}
rollbackConnectivityRegressedExpansion() {
this.connectivityRollbackMutationStats = this.captureAndResetExpansionMutationStats(), this.restoreLastConnectivitySafeTraces();
}
rollbackImmutableUnsafeExpansion() {
this.immutableSafetyRollbackMutationStats = this.captureAndResetExpansionMutationStats(), this.restoreLastConnectivitySafeTraces();
}
captureAndResetExpansionMutationStats() {
const t54 = { recreatedTraceCount: this.recreatedTraceCount, expandedSegmentCount: this.expandedSegmentCount, intermediateExpandedSegmentCount: this.intermediateExpandedSegmentCount, pathWidthUpgradeCount: this.pathWidthUpgradeCount, reroutedSegmentCount: this.reroutedSegmentCount, pushedTraceCount: this.pushedTraceCount, elasticPushedTraceCount: this.elasticPushedTraceCount, layerReroutedTraceCount: this.layerReroutedTraceCount, insertedViaCount: this.insertedViaCount, neckedLayerSegmentCount: this.neckedLayerSegmentCount };
return this.recreatedTraceCount = 0, this.expandedSegmentCount = 0, this.intermediateExpandedSegmentCount = 0, this.pathWidthUpgradeCount = 0, this.reroutedSegmentCount = 0, this.pushedTraceCount = 0, this.elasticPushedTraceCount = 0, this.layerReroutedTraceCount = 0, this.insertedViaCount = 0, this.neckedLayerSegmentCount = 0, this.expansionPushedTraceIndices.clear(), t54;
}
restoreLastConnectivitySafeTraces() {
this.traces = structuredClone(this.lastConnectivitySafeTraces), this.rebuildObstacleIndex();
}
getRemainingParentIterationsAfterCurrentStep() {
return Math.max(0, this.MAX_ITERATIONS - this.iterations - 1);
}
calculateWidthDeficit() {
let t54 = 0, e6 = 0;
for (const n6 of this.traceOrder) {
const o6 = this.traces[n6];
if (!this.findConnectionForTrace(o6))
continue;
const i6 = this.resolveNominalTraceWidth(o6);
for (let n7 = 0;n7 < o6.route.length - 1; n7++) {
const r6 = o6.route[n7], s6 = o6.route[n7 + 1];
if (!v4(r6) || !v4(s6) || r6.layer !== s6.layer)
continue;
const a6 = n3(r6, s6), c6 = r6.width;
e6 += a6 * i6, t54 += a6 * Math.max(0, i6 - c6);
}
}
return { deficit: t54, nominalArea: e6 };
}
getInitialTracePriority(t54) {
const e6 = this.resolveNominalTraceWidth(t54);
let n6 = 0;
for (let o6 = 0;o6 < t54.route.length - 1; o6++) {
const i6 = t54.route[o6], r6 = t54.route[o6 + 1];
v4(i6) && v4(r6) && i6.layer === r6.layer && (n6 += n3(i6, r6) * Math.max(0, e6 - Math.min(i6.width, r6.width)));
}
return e6 * n6;
}
evaluateNextSegment() {
const t54 = this.traces[this.traceIndex];
if (!t54)
return void (this.phase = "scan-trace");
const e6 = this.findNextUnderWidthSegment(t54, this.routeSegmentIndex, this.nominalTraceWidth);
if (e6 === -1)
return void (this.phase = "scan-trace");
this.routeSegmentIndex = e6;
const n6 = t54.route[e6], o6 = t54.route[e6 + 1];
if (!v4(n6) || !v4(o6))
return void this.routeSegmentIndex++;
const i6 = this.getTraceConnectionNames(t54), r6 = Math.min(n6.width, o6.width), s6 = this.findMaximumSafeInPlaceWidth(t54, e6, i6);
if (s6 > r6 + e3) {
if (n6.width = Math.max(n6.width, s6), o6.width = Math.max(o6.width, s6), s6 >= this.nominalTraceWidth - e3)
return this.expandedSegmentCount++, void this.routeSegmentIndex++;
this.intermediateExpandedSegmentCount++;
}
this.startTraceInflation(t54, e6) || this.prepareLayerRouteAttempt(t54, e6) || this.prepareRegularGridCandidates(t54, e6);
}
prepareRegularGridCandidates(t54, e6) {
if (this.currentIntervals = this.getExponentialIntervalCandidates(t54, e6, this.nominalTraceWidth), this.intervalCursor = 0, this.candidateWidths = this.getCandidateWidths(this.nominalTraceWidth), this.widthCursor = 0, this.gridResolutions = [], this.resolutionCursor = 0, this.offsetCursor = 0, this.currentIntervals.length === 0)
return this.unresolvedSegmentCount++, void this.routeSegmentIndex++;
this.phase = "try-grid-candidate";
}
prepareLayerRouteAttempt(t54, e6) {
if (this.nominalTraceWidth < 0.499999)
return false;
const n6 = this.options.allowNewVias !== false && this.inputProblem.layerCount >= 2, o6 = n6 ? 2 : this.maxPassCount, i6 = this.layerAttemptCountByTrace.get(this.traceIndex) ?? 0, r6 = this.layerRerouteCountByTrace.get(this.traceIndex) ?? 0;
if (r6 >= o6 || i6 >= o6 || i6 > this.passIndex || i6 > 0 && r6 === 0)
return false;
const s6 = t54.route[e6], a6 = t54.route[e6 + 1];
if (!v4(s6) || !v4(a6) || Math.min(s6.width, a6.width) >= 0.5 * this.nominalTraceWidth - e3)
return false;
const c6 = this.getExponentialIntervalCandidates(t54, e6, this.nominalTraceWidth).filter((e7) => this.intervalSupportsLayerRouting(t54, e7)).sort((e7, n7) => n7.endIndex - e7.endIndex || e7.startIndex - n7.startIndex || this.getRouteIntervalLength(t54, n7.startIndex, n7.endIndex) - this.getRouteIntervalLength(t54, e7.startIndex, e7.endIndex))[0];
if (!c6)
return false;
const l6 = this.getRouteQuality(t54.route.slice(c6.startIndex, c6.endIndex + 1));
if (l6.deficitArea < this.nominalTraceWidth)
return false;
if (i6 > 0 && l6.deficitArea / Math.max(l6.length, e3) < 0.25)
return false;
const h6 = t54.route[c6.startIndex], d6 = t54.route[c6.endIndex], u6 = this.getTraceConnectionNames(t54), p6 = n6 ? this.getEndpointLayers(h6, u6) : [h6.layer], m6 = n6 ? this.getEndpointLayers(d6, u6) : [d6.layer], g6 = Math.min(this.nominalTraceWidth, Math.max(h6.width, this.findMaximumSafeInPlaceWidth(t54, c6.startIndex, u6))), f6 = Math.min(this.nominalTraceWidth, Math.max(d6.width, this.findMaximumSafeInPlaceWidth(t54, c6.endIndex - 1, u6))), y6 = this.getSoftTraceIndices(this.nominalTraceWidth);
return this.layerAttemptCountByTrace.set(this.traceIndex, i6 + 1), this.layerAttempt = { interval: c6, minViaCount: n6 ? 1 : 0, maxViaCount: n6 ? 2 : 0, candidateWidths: [this.nominalTraceWidth], widthCursor: 0, gridResolutions: [r3(this.nominalTraceWidth / 4, 0.2, 0.3)], resolutionCursor: 0, offsetCursor: 0, startLayers: p6, endLayers: m6, startNeckWidth: g6, endNeckWidth: f6, softTraceIndices: y6 }, this.phase = "try-layer-candidate", true;
}
intervalSupportsLayerRouting(t54, e6) {
if (e6.startIndex >= e6.endIndex)
return false;
for (let n7 = e6.startIndex;n7 <= e6.endIndex; n7++) {
const e7 = t54.route[n7];
if (!v4(e7))
return false;
}
const n6 = t54.route[e6.startIndex], o6 = t54.route[e6.endIndex];
return n6.layer === o6.layer;
}
getEndpointLayers(t54, e6) {
return [...new Set([t54.layer, ...this.obstacleIndex.getConnectedLayersAtPoint({ x: t54.x, y: t54.y }, e6)])].filter((t55) => this.obstacleIndex.boardLayers.includes(t55));
}
getSoftTraceIndices(t54) {
const e6 = [];
for (let n6 = 0;n6 < this.traces.length; n6++) {
if (n6 === this.traceIndex)
continue;
const o6 = this.traces[n6], i6 = this.findConnectionForTrace(o6);
if (!i6)
continue;
Math.max(i6.nominalTraceWidth ?? i6.width ?? this.inputProblem.nominalTraceWidth ?? this.inputProblem.minTraceWidth, this.inputProblem.minTraceWidth) < t54 - e3 && e6.push(n6);
}
return e6;
}
startNextLayerCandidate() {
const t54 = this.layerAttempt, e6 = this.traces[this.traceIndex];
if (!t54 || !e6)
return this.layerAttempt = null, void (this.phase = "evaluate-segment");
if (t54.widthCursor >= t54.candidateWidths.length) {
const t55 = this.routeSegmentIndex;
return this.layerAttempt = null, void this.prepareRegularGridCandidates(e6, t55);
}
const n6 = t54.candidateWidths[t54.widthCursor];
if (t54.gridResolutions.length === 0 && (t54.gridResolutions = this.getGridResolutions(n6)), t54.resolutionCursor >= t54.gridResolutions.length)
return t54.widthCursor++, t54.gridResolutions = [], t54.resolutionCursor = 0, void (t54.offsetCursor = 0);
if (t54.offsetCursor >= b4.length)
return t54.resolutionCursor++, void (t54.offsetCursor = 0);
const o6 = e6.route[t54.interval.startIndex], i6 = e6.route[t54.interval.endIndex];
if (!v4(o6) || !v4(i6))
return this.layerAttempt = null, void this.prepareRegularGridCandidates(e6, this.routeSegmentIndex);
const r6 = t54.gridResolutions[t54.resolutionCursor], s6 = b4[t54.offsetCursor], a6 = s6.offset, c6 = Math.min(t54.startNeckWidth, t54.endNeckWidth), l6 = this.inputProblem.min_via_hole_diameter ?? this.inputProblem.minViaHoleDiameter ?? 0.3, h6 = Math.max(l6, this.inputProblem.min_via_pad_diameter ?? this.inputProblem.minViaPadDiameter ?? this.inputProblem.minViaDiameter ?? 0.6), d6 = Math.max(this.inputProblem.minTraceWidth, Math.min(s6.strictNecking ? t54.startNeckWidth : c6, n6)), u6 = Math.max(this.inputProblem.minTraceWidth, Math.min(s6.strictNecking ? t54.endNeckWidth : c6, n6)), p6 = r3(3 * this.nominalTraceWidth, 1.5, 3);
t54.maxViaCount > 0 ? this.attemptedLayerGridCount++ : this.attemptedGridCount++, this.activeSubSolver = new y3({ start: o6, end: i6, originalStartLayer: o6.layer, originalEndLayer: i6.layer, startLayers: t54.startLayers, endLayers: t54.endLayers, layers: this.obstacleIndex.boardLayers, traceWidth: n6, startNeckWidth: d6, endNeckWidth: u6, maxStartNeckLength: p6, maxEndNeckLength: p6, neckPenaltyExponent: s6.strictNecking ? 2 : 1, viaDiameter: h6, viaHoleDiameter: l6, minViaCount: t54.minViaCount, maxViaCount: t54.maxViaCount, viaCost: Math.max(1, 2 * this.nominalTraceWidth), gridSize: r6, gridOffset: { x: a6.x * r6, y: a6.y * r6 }, connectionNames: this.getTraceConnectionNames(e6), obstacleIndex: this.obstacleIndex, ignoreTraceIndex: this.traceIndex, ignoreRouteRange: { start: Math.max(0, t54.interval.startIndex - 1), end: Math.min(e6.route.length - 1, t54.interval.endIndex + 1) }, softTraceIndices: t54.softTraceIndices, fixedVias: this.getFixedViasOutsideInterval(e6, t54.interval), bounds: this.inputProblem.bounds, obstacleClearance: this.getDesiredPadClearance(n6), searchPadding: Math.min(5, Math.max(2.5, n3(o6, i6) / 2, 4 * n6)) });
}
startNextGridCandidate() {
const t54 = this.traces[this.traceIndex];
if (!t54)
return void (this.phase = "scan-trace");
if (this.widthCursor >= this.candidateWidths.length)
return this.unresolvedSegmentCount++, this.routeSegmentIndex++, void (this.phase = "evaluate-segment");
if (this.intervalCursor >= this.currentIntervals.length)
return this.widthCursor++, this.intervalCursor = 0, this.gridResolutions = [], this.resolutionCursor = 0, void (this.offsetCursor = 0);
const e6 = this.candidateWidths[this.widthCursor], n6 = t54.route[this.routeSegmentIndex], o6 = t54.route[this.routeSegmentIndex + 1];
if (v4(n6) && v4(o6) && e6 <= Math.min(n6.width, o6.width) + e3)
return void (this.widthCursor = this.candidateWidths.length);
if (this.gridResolutions.length === 0 && (this.gridResolutions = this.getGridResolutions(e6)), this.resolutionCursor >= this.gridResolutions.length)
return this.intervalCursor++, this.resolutionCursor = 0, void (this.offsetCursor = 0);
if (this.offsetCursor >= _4.length)
return this.resolutionCursor++, void (this.offsetCursor = 0);
const i6 = this.currentIntervals[this.intervalCursor], r6 = t54.route[i6.startIndex], s6 = t54.route[i6.endIndex];
if (!v4(r6) || !v4(s6) || r6.layer !== s6.layer)
return this.intervalCursor++, this.resolutionCursor = 0, void (this.offsetCursor = 0);
if (this.endpointCollides(t54, i6, r6, e6) || this.endpointCollides(t54, i6, s6, e6))
return this.intervalCursor++, this.resolutionCursor = 0, void (this.offsetCursor = 0);
const a6 = this.gridResolutions[this.resolutionCursor], c6 = _4[this.offsetCursor], l6 = { x: c6.x * a6, y: c6.y * a6 };
this.attemptedGridCount++, this.activeSubSolver = new w3({ start: r6, end: s6, layer: r6.layer, traceWidth: e6, gridSize: a6, gridOffset: l6, connectionNames: this.getTraceConnectionNames(t54), obstacleIndex: this.obstacleIndex, ignoreTraceIndex: this.traceIndex, ignoreRouteRange: { start: Math.max(0, i6.startIndex - 1), end: Math.min(t54.route.length - 1, i6.endIndex + 1) }, bounds: this.inputProblem.bounds, obstacleClearance: this.getDesiredPadClearance(e6), searchPadding: Math.min(5, Math.max(1.5, n3(r6, s6) / 2, 3 * e6)) });
}
endpointCollides(t54, e6, n6, o6) {
return this.obstacleIndex.collides({ start: n6, end: n6, layer: n6.layer, width: o6, connectionNames: this.getTraceConnectionNames(t54), ignoreTraceIndex: this.traceIndex, ignoreRouteRange: { start: Math.max(0, e6.startIndex - 1), end: Math.min(t54.route.length - 1, e6.endIndex + 1) }, obstacleClearance: this.getDesiredPadClearance(o6) });
}
stepActiveGridSolver() {
if (this.activeSubSolver instanceof y4)
return void this.stepActiveTraceClearanceRepairSolver();
if (this.activeSubSolver instanceof g4)
return void this.stepActiveCleanupSolver();
if (this.activeSubSolver instanceof A3)
return void this.stepActiveInflationSolver();
if (this.activeSubSolver instanceof y3)
return void this.stepActiveLayerSolver();
const t54 = this.activeSubSolver;
if (t54.step(), t54.solved || t54.failed) {
if (t54.solved) {
const e6 = t54.getOutput();
if (e6) {
const t55 = this.gridRouteReplacementCollides(e6) || this.gridRouteBoundaryCollides(e6);
if (!t55 && this.gridRoutePreservesSameNetContacts(e6))
return this.applyGridRoute(this.maximizeGridRouteWidth(e6)), void (this.activeSubSolver = null);
t55 || this.sameNetContactRejectionCount++;
}
}
this.retainFailedSubSolver(t54), this.activeSubSolver = null, this.offsetCursor++;
}
}
stepActiveCleanupSolver() {
const t54 = this.activeSubSolver;
if (t54.step(), t54.solved || t54.failed) {
if (t54.solved)
return this.adoptCleanupOutput(t54), this.activeSubSolver = null, void this.startTraceClearanceRepair();
this.retainFailedSubSolver(t54), this.activeSubSolver = null, this.startTraceClearanceRepair();
}
}
adoptCleanupOutput(t54) {
const e6 = this.acceptConnectivityCheckpoint(t54.getOutput(), "cleanup");
this.cleanupCompleted = !t54.budgetLimited;
const n6 = t54.stats;
this.connectivityValidationError ??= n6.connectivityValidationError ?? null, this.connectivityValidationCount += Number(n6.connectivityValidationCount ?? 0);
const o6 = Number(n6.connectivityRollbackCount ?? 0);
o6 > 0 && (this.connectivityRollbackCount += o6, this.connectivityRollbackPhases.includes("cleanup") || this.connectivityRollbackPhases.push("cleanup"), this.connectivityRegressionEndpointIds = [...new Set([...this.connectivityRegressionEndpointIds, ...n6.connectivityRegressionEndpointIds ?? []])]);
const i6 = e6 && o6 === 0;
this.cleanupBestEffortAccepted = t54.budgetLimited && i6, this.cleanupMutatedTraceIndices = i6 ? [...n6.mutatedTraceIndices ?? []] : [], this.removedViaPairCount = i6 ? Number(n6.viaPairCountRemoved ?? 0) : 0, this.removedViaCount = i6 ? Number(n6.viaCountRemoved ?? 0) : 0, this.simplifiedPathCount = i6 ? Number(n6.simplifiedPathCount ?? 0) : 0, this.normalizedSegmentCount = i6 ? Number(n6.normalizedSegmentCount ?? 0) : 0, this.cleanupClearanceShoveCount = i6 ? Number(n6.committedClearanceShoveCount ?? 0) : 0, this.relocatedViaCount = i6 ? Number(n6.relocatedViaCount ?? 0) : 0, this.unresolvedViaCount = Number(n6.unresolvedViaCount ?? 0), this.padClearanceRerouteCount = i6 ? Number(n6.padClearanceRerouteCount ?? 0) : 0, this.unresolvedPadClearanceCount = Number(n6.unresolvedPadClearanceCount ?? 0), this.initialPadClearanceViolationCount = Number(n6.initialPadClearanceViolationCount ?? 0), this.remainingPadClearanceViolationCount = Number(n6.remainingPadClearanceViolationCount ?? 0), this.initialPadClearanceViolationCountByClearance = { ...n6.initialPadClearanceViolationCountByClearance ?? {} }, this.remainingPadClearanceViolationCountByClearance = { ...n6.remainingPadClearanceViolationCountByClearance ?? {} }, this.rebuildObstacleIndex();
}
startTraceClearanceRepair() {
this.phase = "repair-trace-clearance";
const t54 = [...new Set([...this.getOwnedTraceIndices(), ...this.expansionPushedTraceIndices, ...this.cleanupMutatedTraceIndices])], e6 = new y4({ simpleRouteJson: this.inputProblem, traces: this.traces, traceIndices: t54 });
e6.MAX_ITERATIONS = Math.min(e6.MAX_ITERATIONS, this.getRemainingParentIterationsAfterCurrentStep()), this.clearanceRepairIterationBudget = e6.MAX_ITERATIONS, this.activeSubSolver = e6;
}
stepActiveTraceClearanceRepairSolver() {
const t54 = this.activeSubSolver;
if (t54.step(), t54.solved || t54.failed) {
if (t54.solved)
return this.adoptClearanceRepairOutput(t54), this.activeSubSolver = null, void (this.phase = "complete");
this.retainFailedSubSolver(t54), this.activeSubSolver = null, this.phase = "complete";
}
}
adoptClearanceRepairOutput(t54) {
const e6 = this.acceptConnectivityCheckpoint(t54.getOutput(), "clearance-repair");
this.clearanceRepairCompleted = !t54.budgetLimited;
const n6 = t54.stats;
this.connectivityValidationError ??= n6.connectivityValidationError ?? null, this.connectivityValidationCount += Number(n6.connectivityValidationCount ?? 0);
const o6 = Number(n6.connectivityRollbackCount ?? 0);
o6 > 0 && (this.connectivityRollbackCount += o6, this.connectivityRollbackPhases.includes("clearance-repair") || this.connectivityRollbackPhases.push("clearance-repair"), this.connectivityRegressionEndpointIds = [...new Set([...this.connectivityRegressionEndpointIds, ...n6.connectivityRegressionEndpointIds ?? []])]);
const i6 = e6 && o6 === 0;
this.clearanceRepairBestEffortAccepted = t54.budgetLimited && i6, this.repairedTraceClearanceSegmentCount = i6 ? Number(n6.repairedSegmentCount ?? 0) : 0, this.repairedPadNeckSegmentCount = i6 ? Number(n6.repairedPadNeckSegmentCount ?? 0) : 0, this.unresolvedTraceClearanceSegmentCount = Number(n6.unresolvedSegmentCount ?? 0), this.rebuildObstacleIndex();
}
stepActiveLayerSolver() {
const t54 = this.activeSubSolver;
if (t54.step(), t54.solved || t54.failed) {
if (t54.solved) {
const e6 = t54.getOutput();
if (e6) {
const t55 = !this.layerRouteReplacementCollides(e6, true) && this.layerRouteImprovesInterval(e6), n6 = t55 && this.layerRoutePreservesSameNetContacts(e6);
if (n6) {
if (this.activeSubSolver = null, this.pendingLayerOutput = e6, this.pendingLayerPushCount = 0, !this.layerRouteReplacementCollides(e6, false))
return void this.applyLayerRoute(e6);
if (this.startPendingLayerInflation())
return;
this.pendingLayerOutput = null;
}
t55 && !n6 && this.sameNetContactRejectionCount++;
}
}
this.retainFailedSubSolver(t54), this.activeSubSolver = null, this.layerAttempt && this.layerAttempt.offsetCursor++, this.phase = "try-layer-candidate";
}
}
layerRouteReplacementCollides(t54, e6) {
const n6 = this.traces[this.traceIndex], o6 = this.layerAttempt;
if (!n6 || !o6)
return true;
const i6 = this.getTraceConnectionNames(n6), r6 = e6 ? o6.softTraceIndices : undefined, s6 = { start: Math.max(0, o6.interval.startIndex - 1), end: Math.min(n6.route.length - 1, o6.interval.endIndex + 1) }, a6 = this.getFixedViasOutsideInterval(n6, o6.interval);
for (let e7 = 0;e7 < t54.route.length; e7++) {
const n7 = t54.route[e7];
if (n7?.route_type === "via") {
if (this.obstacleIndex.collidesVia({ point: n7, layers: this.obstacleIndex.boardLayers, padDiameter: n7.via_diameter ?? 0.6, holeDiameter: n7.via_hole_diameter ?? this.obstacleIndex.defaultViaHoleDiameter, connectionNames: i6, ignoreTraceIndex: this.traceIndex, ignoreTraceIndices: r6, otherNewViaPoints: t54.route.slice(0, e7).filter((t55) => t55.route_type === "via").map((t55) => ({ x: t55.x, y: t55.y })), fixedVias: a6, ignoreRouteRange: s6, obstacleClearance: this.getDesiredPadClearance(t54.traceWidth), blockSameNetObstacles: true, sameNetObstacleClearance: 0 }))
return true;
continue;
}
const o7 = t54.route[e7 + 1];
if (n7?.route_type === "wire" && o7?.route_type === "wire" && n7.layer === o7.layer && this.obstacleIndex.collides({ start: n7, end: o7, layer: n7.layer, width: Math.max(n7.width, o7.width), connectionNames: i6, ignoreTraceIndex: this.traceIndex, ignoreTraceIndices: r6, ignoreRouteRange: s6, obstacleClearance: this.getDesiredPadClearance(t54.traceWidth) }))
return true;
}
return this.layerRouteBoundaryCollides(t54, e6);
}
getFixedViasOutsideInterval(t54, e6) {
return t54.route.flatMap((t55, n6) => t55.route_type !== "via" || n6 >= e6.startIndex && n6 <= e6.endIndex ? [] : [{ point: { x: t55.x, y: t55.y }, padDiameter: t55.via_diameter ?? 0.6, holeDiameter: t55.via_hole_diameter ?? this.obstacleIndex.defaultViaHoleDiameter }]);
}
layerRouteBoundaryCollides(t54, e6) {
const n6 = this.traces[this.traceIndex], o6 = this.layerAttempt, i6 = t54.route.find((t55) => t55.route_type === "wire");
let r6;
for (let e7 = t54.route.length - 1;e7 >= 0; e7--) {
const n7 = t54.route[e7];
if (n7?.route_type === "wire") {
r6 = n7;
break;
}
}
if (!i6 || !r6)
return true;
const s6 = [{ outside: n6.route[o6.interval.startIndex - 1], inside: i6 }, { outside: n6.route[o6.interval.endIndex + 1], inside: r6 }];
for (const i7 of s6)
if (v4(i7.outside) && i7.outside.layer === i7.inside.layer && this.obstacleIndex.collides({ start: i7.outside, end: i7.inside, layer: i7.inside.layer, width: Math.max(i7.outside.width, i7.inside.width), connectionNames: this.getTraceConnectionNames(n6), ignoreTraceIndex: this.traceIndex, ignoreTraceIndices: e6 ? o6.softTraceIndices : undefined, ignoreRouteRange: { start: Math.max(0, o6.interval.startIndex - 1), end: Math.min(n6.route.length - 1, o6.interval.endIndex + 1) }, obstacleClearance: this.getDesiredPadClearance(t54.traceWidth) }))
return true;
return false;
}
layerRouteImprovesInterval(t54) {
const e6 = this.traces[this.traceIndex], n6 = this.layerAttempt.interval, o6 = this.getRouteQuality(e6.route.slice(n6.startIndex, n6.endIndex + 1)), i6 = this.getRouteQuality(t54.route);
return i6.length <= o6.length + 10 + e3 && i6.deficitArea <= o6.deficitArea - Math.max(0.05, 0.1 * o6.deficitArea);
}
getRouteQuality(t54) {
let e6 = 0, n6 = 0;
for (let o6 = 0;o6 < t54.length - 1; o6++) {
const i6 = t54[o6], r6 = t54[o6 + 1];
if (!v4(i6) || !v4(r6) || i6.layer !== r6.layer)
continue;
const s6 = n3(i6, r6), a6 = Math.min(i6.width, r6.width);
e6 += s6, n6 += s6 * Math.max(0, this.nominalTraceWidth - a6);
}
return { length: e6, deficitArea: n6 };
}
getLayerInflationCorridor(t54) {
const e6 = [];
for (let n6 = 0;n6 < t54.route.length; n6++) {
const o6 = t54.route[n6];
if (o6?.route_type === "via") {
for (const t55 of this.obstacleIndex.boardLayers)
e6.push({ start: o6, end: o6, layer: t55, width: o6.via_diameter ?? 0.6 });
continue;
}
const i6 = t54.route[n6 + 1];
o6?.route_type === "wire" && i6?.route_type === "wire" && o6.layer === i6.layer && e6.push({ start: o6, end: i6, layer: o6.layer, width: Math.max(o6.width, i6.width) });
}
return e6;
}
startPendingLayerInflation() {
const t54 = this.pendingLayerOutput;
if (!t54 || this.pendingLayerPushCount >= 2)
return false;
const e6 = this.getLayerInflationCorridor(t54);
return e6.length !== 0 && (this.pendingLayerPushCount++, this.attemptedInflationCount++, this.activeSubSolver = new A3({ simpleRouteJson: this.inputProblem, traces: this.traces, powerTraceIndex: this.traceIndex, nominalPowerWidth: t54.traceWidth, mutableTraceIndices: this.mutableBlockerTraceIndices, corridor: e6, maxRerouteLength: 10 }, this.connectionNameResolver), this.phase = "try-trace-inflation", true);
}
applyLayerRoute(t54) {
const e6 = this.traces[this.traceIndex], n6 = this.layerAttempt.interval, o6 = this.createLayerRouteReplacement(t54);
e6.route.splice(n6.startIndex, n6.endIndex - n6.startIndex + 1, ...o6), t54.viaCount > 0 && this.layerReroutedTraceCount++, this.layerRerouteCountByTrace.set(this.traceIndex, (this.layerRerouteCountByTrace.get(this.traceIndex) ?? 0) + 1), this.reroutedSegmentCount++, this.insertedViaCount += t54.viaCount, t54.viaCount > 0 && (this.neckedLayerSegmentCount += o6.filter((t55) => t55.route_type === "wire" && t55.width < this.nominalTraceWidth - e3).length), this.routeSegmentIndex = n6.startIndex, this.currentIntervals = [], this.layerAttempt = null, this.pendingLayerOutput = null, this.pendingLayerPushCount = 0, this.phase = "evaluate-segment";
}
createLayerRouteReplacement(t54) {
const e6 = this.traces[this.traceIndex], n6 = this.layerAttempt.interval, o6 = e6.route[n6.startIndex], i6 = e6.route[n6.endIndex], r6 = structuredClone(t54.route), s6 = r6.findIndex((t55) => t55.route_type === "wire");
let a6 = -1;
for (let t55 = r6.length - 1;t55 >= 0; t55--)
if (r6[t55]?.route_type === "wire") {
a6 = t55;
break;
}
return s6 >= 0 && (r6[s6] = { ...o6, ...r6[s6] }), a6 >= 0 && (r6[a6] = { ...i6, ...r6[a6] }), r6;
}
layerRoutePreservesSameNetContacts(t54) {
const e6 = this.traces[this.traceIndex], n6 = this.layerAttempt.interval;
return this.routeReplacementPreservesSameNetContacts(e6, n6, this.createLayerRouteReplacement(t54));
}
startTraceInflation(t54, e6) {
const n6 = t54.route[e6], o6 = t54.route[e6 + 1];
if (!v4(n6) || !v4(o6))
return false;
const i6 = Math.min(n6.width, o6.width), r6 = this.findBestPushableInflationWidth(t54, e6, i6);
if (!r6)
return false;
const s6 = this.getLocalInflationCorridor(t54, e6, r6);
if (s6.length === 0)
return false;
const a6 = [this.traceIndex, n6.x, n6.y, o6.x, o6.y].join(":"), c6 = this.inflationAttemptsBySegment.get(a6) ?? 0;
return !(c6 >= 2) && (this.inflationAttemptsBySegment.set(a6, c6 + 1), this.activeInflationKey = a6, this.activeInflationWidth = r6, this.attemptedInflationCount++, this.activeSubSolver = new A3({ simpleRouteJson: this.inputProblem, traces: this.traces, powerTraceIndex: this.traceIndex, nominalPowerWidth: r6, mutableTraceIndices: this.mutableBlockerTraceIndices, corridor: s6, maxRerouteLength: 10 }, this.connectionNameResolver), this.phase = "try-trace-inflation", true);
}
hasOnlyPushableTraceBlockers(t54, e6, n6) {
const o6 = Math.max(0, e6 - 1), i6 = Math.min(t54.route.length - 2, e6 + 1), r6 = new Set;
for (let e7 = o6;e7 <= i6; e7++) {
const s6 = t54.route[e7], a6 = t54.route[e7 + 1];
if (!v4(s6) || !v4(a6) || s6.layer !== a6.layer)
continue;
const c6 = { start: s6, end: a6, layer: s6.layer, width: n6, connectionNames: this.getTraceConnectionNames(t54), ignoreTraceIndex: this.traceIndex, ignoreRouteRange: { start: o6, end: i6 + 1 }, obstacleClearance: this.getDesiredPadClearance(n6) }, l6 = this.obstacleIndex.findCollisions(c6);
if (l6.length === 0 && this.obstacleIndex.collides(c6))
return false;
for (const t55 of l6) {
if (t55.kind !== "trace" || t55.traceIndex === undefined)
return false;
const e8 = this.traces[t55.traceIndex];
if (!e8)
return false;
const o7 = this.findConnectionForTrace(e8);
if (!o7 || (o7.nominalTraceWidth ?? o7.width ?? this.inputProblem.nominalTraceWidth ?? this.inputProblem.minTraceWidth) >= n6 - e3)
return false;
r6.add(t55.traceIndex);
}
}
return r6.size > 0 && r6.size <= 2;
}
findBestPushableInflationWidth(t54, e6, n6) {
const o6 = this.nominalTraceWidth >= 0.5 ? 0.05 : 0.0125;
for (let i6 = this.nominalTraceWidth;i6 > n6 + e3; i6 -= o6) {
const n7 = Number(i6.toFixed(6));
if (this.hasOnlyPushableTraceBlockers(t54, e6, n7))
return n7;
}
return null;
}
stepActiveInflationSolver() {
const t54 = this.activeSubSolver;
if (t54.step(), t54.solved || t54.failed) {
if (t54.solved) {
const e6 = t54.getOutput(), n6 = e6 && this.sameNetContactsArePreserved(this.traces[e6.pushedTraceIndex].route, e6.traces[e6.pushedTraceIndex].route, this.getTraceConnectionNames(this.traces[e6.pushedTraceIndex]), e6.pushedTraceIndex);
if (e6 && n6) {
if (this.traces = e6.traces, this.pushedTraceCount++, this.expansionPushedTraceIndices.add(e6.pushedTraceIndex), e6.strategy === "elastic" && this.elasticPushedTraceCount++, this.activeSubSolver = null, this.activeInflationKey = null, this.activeInflationWidth = null, this.rebuildObstacleIndex(), this.pendingLayerOutput) {
if (!this.layerRouteReplacementCollides(this.pendingLayerOutput, false) && this.layerRoutePreservesSameNetContacts(this.pendingLayerOutput))
return void this.applyLayerRoute(this.pendingLayerOutput);
if (this.startPendingLayerInflation())
return;
return this.pendingLayerOutput = null, this.pendingLayerPushCount = 0, this.layerAttempt && this.layerAttempt.offsetCursor++, void (this.phase = "try-layer-candidate");
}
return void (this.phase = "evaluate-segment");
}
e6 && !n6 && this.sameNetContactRejectionCount++;
}
if (this.retainFailedSubSolver(t54), this.activeInflationKey && this.inflationAttemptsBySegment.set(this.activeInflationKey, 2), this.activeInflationKey = null, this.activeInflationWidth = null, this.activeSubSolver = null, this.pendingLayerOutput)
return this.pendingLayerOutput = null, this.pendingLayerPushCount = 0, this.layerAttempt && this.layerAttempt.offsetCursor++, void (this.phase = "try-layer-candidate");
this.phase = "evaluate-segment";
}
}
getLocalInflationCorridor(t54, e6, n6) {
const o6 = t54.route[e6], i6 = t54.route[e6 + 1];
if (!v4(o6) || !v4(i6) || o6.layer !== i6.layer)
return [];
const r6 = r3(4 * n6, 2, 4), s6 = r6 / 2;
let a6 = e6, c6 = 0;
for (;a6 > 0; ) {
const e7 = t54.route[a6 - 1], n7 = t54.route[a6];
if (!v4(e7) || !v4(n7) || e7.layer !== n7.layer)
break;
const o7 = n3(e7, n7);
if (c6 + o7 > s6 + e3)
break;
c6 += o7, a6--;
}
let l6 = e6 + 1, h6 = 0;
for (;l6 < t54.route.length - 1; ) {
const e7 = t54.route[l6], n7 = t54.route[l6 + 1];
if (!v4(e7) || !v4(n7) || e7.layer !== n7.layer)
break;
const o7 = n3(e7, n7);
if (h6 + o7 > s6 + e3)
break;
h6 += o7, l6++;
}
let d6 = r6 - c6 - h6;
for (;d6 > e3 && a6 > 0; ) {
const e7 = t54.route[a6 - 1], n7 = t54.route[a6];
if (!v4(e7) || !v4(n7) || e7.layer !== n7.layer)
break;
const o7 = n3(e7, n7);
if (o7 > d6 + e3)
break;
d6 -= o7, a6--;
}
for (;d6 > e3 && l6 < t54.route.length - 1; ) {
const e7 = t54.route[l6], n7 = t54.route[l6 + 1];
if (!v4(e7) || !v4(n7) || e7.layer !== n7.layer)
break;
const o7 = n3(e7, n7);
if (o7 > d6 + e3)
break;
d6 -= o7, l6++;
}
const u6 = [];
for (let e7 = a6;e7 < l6; e7++) {
const o7 = t54.route[e7], i7 = t54.route[e7 + 1];
v4(o7) && v4(i7) && o7.layer === i7.layer && u6.push({ start: o7, end: i7, layer: o7.layer, width: n6 });
}
return u6;
}
applyGridRoute(t54) {
const e6 = this.traces[this.traceIndex], n6 = this.currentIntervals[this.intervalCursor], o6 = this.createGridRouteReplacement(t54);
e6.route.splice(n6.startIndex, n6.endIndex - n6.startIndex + 1, ...o6), this.reroutedSegmentCount++, this.routeSegmentIndex = n6.startIndex + o6.length - 1, this.currentIntervals = [], this.phase = "evaluate-segment";
}
createGridRouteReplacement(t54) {
const e6 = this.traces[this.traceIndex], n6 = this.currentIntervals[this.intervalCursor], o6 = e6.route[n6.startIndex], i6 = e6.route[n6.endIndex], r6 = t54.points.map((e7) => ({ route_type: "wire", x: e7.x, y: e7.y, width: t54.traceWidth, layer: o6.layer }));
return r6[0].width = Math.max(o6.width, t54.traceWidth), r6[r6.length - 1].width = Math.max(i6.width, t54.traceWidth), r6;
}
gridRoutePreservesSameNetContacts(t54) {
const e6 = this.traces[this.traceIndex], n6 = this.currentIntervals[this.intervalCursor];
return this.routeReplacementPreservesSameNetContacts(e6, n6, this.createGridRouteReplacement(t54));
}
routeReplacementPreservesSameNetContacts(t54, e6, n6) {
const o6 = this.getTraceConnectionNames(t54), i6 = this.getSameNetContactIds(t54.route.slice(e6.startIndex, e6.endIndex + 1), o6, this.traceIndex), r6 = new Set([...this.getSameNetContactIds(t54.route.slice(0, e6.startIndex + 1), o6, this.traceIndex), ...this.getSameNetContactIds(t54.route.slice(e6.endIndex), o6, this.traceIndex)]), s6 = new Set([...i6].filter((t55) => !r6.has(t55)));
if (s6.size === 0)
return true;
const a6 = this.getSameNetContactIds(n6, o6, this.traceIndex);
return [...s6].every((t55) => a6.has(t55));
}
sameNetContactsArePreserved(t54, e6, n6, o6) {
const i6 = this.getSameNetContactIds(t54, n6, o6);
if (i6.size === 0)
return true;
const r6 = this.getSameNetContactIds(e6, n6, o6);
return [...i6].every((t55) => r6.has(t55));
}
getSameNetContactIds(t54, e6, n6) {
const o6 = new Set;
for (let i6 = 0;i6 < t54.length; i6++) {
const r6 = t54[i6];
if (r6?.route_type === "via") {
for (const t55 of this.getViaLayers(r6))
for (const i7 of this.obstacleIndex.getSameNetCopperContactIds({ start: r6, end: r6, layer: t55, width: r6.via_diameter ?? 0.6, connectionNames: e6, ignoreTraceIndex: n6 }))
o6.add(i7);
continue;
}
const s6 = t54[i6 + 1];
if (r6?.route_type === "wire" && s6?.route_type === "wire" && r6.layer === s6.layer)
for (const t55 of this.obstacleIndex.getSameNetCopperContactIds({ start: r6, end: s6, layer: r6.layer, width: Math.min(r6.width, s6.width), connectionNames: e6, ignoreTraceIndex: n6 }))
o6.add(t55);
}
return o6;
}
getViaLayers(t54) {
const e6 = this.obstacleIndex.boardLayers.indexOf(t54.from_layer), n6 = this.obstacleIndex.boardLayers.indexOf(t54.to_layer);
return e6 < 0 || n6 < 0 ? this.obstacleIndex.boardLayers : this.obstacleIndex.boardLayers.slice(Math.min(e6, n6), Math.max(e6, n6) + 1);
}
gridRouteReplacementCollides(t54) {
const e6 = this.traces[this.traceIndex], n6 = this.currentIntervals[this.intervalCursor], o6 = e6.route[n6.startIndex], i6 = e6.route[n6.endIndex], r6 = this.getTraceConnectionNames(e6);
for (let s6 = 0;s6 < t54.points.length - 1; s6++) {
const a6 = Math.max(t54.traceWidth, s6 === 0 ? o6.width : 0, s6 === t54.points.length - 2 ? i6.width : 0);
if (this.obstacleIndex.collides({ start: t54.points[s6], end: t54.points[s6 + 1], layer: o6.layer, width: a6, connectionNames: r6, ignoreTraceIndex: this.traceIndex, ignoreRouteRange: { start: Math.max(0, n6.startIndex - 1), end: Math.min(e6.route.length - 1, n6.endIndex + 1) }, obstacleClearance: this.getDesiredPadClearance(a6) }))
return true;
}
return false;
}
gridRouteBoundaryCollides(t54) {
const e6 = this.traces[this.traceIndex], n6 = this.currentIntervals[this.intervalCursor], o6 = this.getTraceConnectionNames(e6), i6 = [{ startIndex: n6.startIndex - 1, endIndex: n6.startIndex }, { startIndex: n6.endIndex, endIndex: n6.endIndex + 1 }];
for (const n7 of i6) {
const i7 = e6.route[n7.startIndex], r6 = e6.route[n7.endIndex];
if (v4(i7) && v4(r6) && i7.layer === r6.layer && this.obstacleIndex.collides({ start: i7, end: r6, layer: i7.layer, width: Math.max(i7.width, r6.width, t54.traceWidth), connectionNames: o6, ignoreTraceIndex: this.traceIndex, ignoreRouteRange: { start: n7.startIndex, end: n7.endIndex }, obstacleClearance: this.getDesiredPadClearance(Math.max(i7.width, r6.width, t54.traceWidth)) }))
return true;
}
return false;
}
canExpandSegmentAndEndpoints(t54, e6, n6, o6 = this.nominalTraceWidth) {
const i6 = Math.max(0, e6 - 1), r6 = Math.min(t54.route.length - 2, e6 + 1);
for (let s6 = i6;s6 <= r6; s6++) {
const a6 = t54.route[s6], c6 = t54.route[s6 + 1];
if (!v4(a6) || !v4(c6) || a6.layer !== c6.layer)
continue;
const l6 = s6 <= e6 + 1 && s6 + 1 >= e6, h6 = Math.max(a6.width, c6.width, l6 ? o6 : 0);
if (this.obstacleIndex.collides({ start: a6, end: c6, layer: a6.layer, width: h6, connectionNames: n6, ignoreTraceIndex: this.traceIndex, ignoreRouteRange: { start: i6, end: r6 + 1 }, obstacleClearance: this.getDesiredPadClearance(h6) }))
return false;
}
return true;
}
findMaximumSafeInPlaceWidth(t54, e6, n6) {
const o6 = t54.route[e6], i6 = t54.route[e6 + 1];
if (!v4(o6) || !v4(i6))
return 0;
const r6 = Math.min(o6.width, i6.width);
if (this.probeInPlaceWidth(t54, e6, n6, this.nominalTraceWidth))
return this.nominalTraceWidth;
let s6 = r6, a6 = this.nominalTraceWidth;
for (let o7 = 0;o7 < 7; o7++) {
const o8 = (s6 + a6) / 2;
if (o8 <= s6 + e3)
break;
this.probeInPlaceWidth(t54, e6, n6, o8) ? s6 = o8 : a6 = o8;
}
const c6 = this.nominalTraceWidth >= 0.5 ? 0.025 : 0.0125, l6 = Math.max(r6, Math.floor((s6 + e3) / c6) * c6);
return l6 > r6 + e3 && this.probeInPlaceWidth(t54, e6, n6, l6) ? l6 : r6;
}
probeInPlaceWidth(t54, e6, n6, o6) {
return this.inPlaceWidthProbeCount++, this.canExpandSegmentAndEndpoints(t54, e6, n6, o6);
}
maximizeGridRouteWidth(t54) {
if (t54.traceWidth >= this.nominalTraceWidth - e3)
return t54;
let e6 = t54.traceWidth, n6 = this.nominalTraceWidth;
for (let o7 = 0;o7 < 7; o7++) {
const o8 = (e6 + n6) / 2, i7 = { ...t54, traceWidth: o8 };
this.gridRouteReplacementCollides(i7) || this.gridRouteBoundaryCollides(i7) ? n6 = o8 : e6 = o8;
}
const o6 = this.nominalTraceWidth >= 0.5 ? 0.025 : 0.0125, i6 = Math.max(t54.traceWidth, Math.floor((e6 + e3) / o6) * o6);
if (i6 > t54.traceWidth + e3) {
const e7 = { ...t54, traceWidth: i6 };
if (!this.gridRouteReplacementCollides(e7) && !this.gridRouteBoundaryCollides(e7))
return this.pathWidthUpgradeCount++, e7;
}
return t54;
}
getExponentialIntervalCandidates(t54, e6, n6) {
const o6 = this.getExponentialIndices(t54, e6, -1, n6, 5), i6 = this.getExponentialIndices(t54, e6, 1, n6, 10).filter((t55) => t55 > e6), r6 = [];
for (const e7 of o6)
for (const n7 of i6) {
const o7 = this.getRouteIntervalLength(t54, e7, n7);
o7 > 10.000001 || r6.push({ startIndex: e7, endIndex: n7, routeLength: o7 });
}
return r6.sort((t55, e7) => t55.routeLength - e7.routeLength).filter((t55, e7, n7) => n7.findIndex((e8) => e8.startIndex === t55.startIndex && e8.endIndex === t55.endIndex) === e7).slice(0, 10).map(({ startIndex: t55, endIndex: e7 }) => ({ startIndex: t55, endIndex: e7 }));
}
getExponentialIndices(t54, e6, n6, o6, i6) {
const r6 = [e6];
let s6 = 0, a6 = Math.max(o6, 0.3), c6 = e6, l6 = e6;
for (;; ) {
const e7 = c6 + n6;
if (e7 < 0 || e7 >= t54.route.length)
break;
const o7 = t54.route[c6], h6 = t54.route[e7];
if (!v4(o7) || !v4(h6) || o7.layer !== h6.layer)
break;
const d6 = n3(o7, h6);
if (s6 + d6 > i6 + e3)
break;
s6 += d6, c6 = e7, l6 = e7, s6 + e3 >= a6 && (r6.push(e7), a6 *= 2);
}
return r6.includes(l6) || r6.push(l6), r6;
}
getRouteIntervalLength(t54, e6, n6) {
let o6 = 0;
for (let i6 = e6;i6 < n6; i6++) {
const e7 = t54.route[i6], n7 = t54.route[i6 + 1];
if (!v4(e7) || !v4(n7) || e7.layer !== n7.layer)
return Number.POSITIVE_INFINITY;
o6 += n3(e7, n7);
}
return o6;
}
getCandidateWidths(t54) {
const e6 = this.inputProblem.minTraceWidth;
return x4([t54, 0.875 * t54, 0.75 * t54, 0.625 * t54, 0.5 * t54, 0.375 * t54, 0.25 * t54, e6]).filter((t55) => t55 >= e6 - e3);
}
getGridResolutions(t54) {
return x4([Math.max(0.1, Math.min(0.5, t54 / 2)), Math.max(0.1, Math.min(0.25, t54 / 3))]);
}
resolveNominalTraceWidth(t54) {
const e6 = this.findConnectionForTrace(t54);
return Math.max(e6?.nominalTraceWidth ?? e6?.width ?? this.inputProblem.nominalTraceWidth ?? this.inputProblem.minTraceWidth, this.inputProblem.minTraceWidth);
}
getDesiredPadClearance(t54 = this.nominalTraceWidth) {
const e6 = Math.max(this.inputProblem.defaultObstacleMargin ?? 0, this.inputProblem.minTraceToPadEdgeClearance ?? 0, 0.1);
return t54 < 0.499999 || this.phase !== "cleanup" ? e6 : Math.max(e6, this.options.powerTraceToPadClearance ?? t54 / 2);
}
findConnectionForTrace(t54) {
const e6 = this.connectionByTraceId.get(t54.pcb_trace_id);
if (e6 !== undefined)
return e6 ?? undefined;
const n6 = this.getTraceConnectionNames(t54), o6 = this.inputProblem.connections.find((t55) => this.connectionMatchesTrace(t55, n6)) ?? null;
return this.connectionByTraceId.set(t54.pcb_trace_id, o6), o6 ?? undefined;
}
getOwnedTraceIndices() {
return [...this.selectedOwnedTraceIndices];
}
connectionMatchesTrace(t54, e6) {
return [t54.name, t54.source_trace_id, t54.rootConnectionName, t54.netConnectionName, ...t54.mergedConnectionNames ?? []].filter((t55) => Boolean(t55)).some((t55) => e6.includes(t55));
}
getTraceConnectionNames(t54) {
return [t54.connection_name, t54.source_trace_id, t54.rootConnectionName, ...t54.mergedConnectionNames ?? []].filter((t55) => Boolean(t55));
}
traceMeetsNominalWidth(t54, e6) {
return t54.route.every((t55) => t55.route_type !== "wire" || t55.width >= e6 - e3);
}
findNextUnderWidthSegment(t54, e6, n6) {
for (let o6 = e6;o6 < t54.route.length - 1; o6++) {
const e7 = t54.route[o6], i6 = t54.route[o6 + 1];
if (v4(e7) && v4(i6) && e7.layer === i6.layer && (e7.width < n6 - e3 || i6.width < n6 - e3))
return o6;
}
return -1;
}
getMutatedImmutableTraceIds(t54) {
return this.immutableTraceIndices.flatMap((e6) => {
const n6 = t54[e6];
return JSON.stringify(n6) === this.initialImmutableTraceSignatures.get(e6) ? [] : [n6?.pcb_trace_id ?? this.traces[e6]?.pcb_trace_id ?? String(e6)];
});
}
getImmutableViaViolationSignatures(t54) {
const e6 = new Set;
if (this.immutableTraceIndices.length === 0)
return e6;
const n6 = new t310(this.inputProblem, t54), o6 = new T3(this.inputProblem, t54, undefined, [], n6);
for (const n7 of this.immutableTraceIndices) {
const i6 = t54[n7];
if (!i6)
continue;
const r6 = [i6.pcb_trace_id, i6.connection_name, i6.source_trace_id, i6.rootConnectionName, ...i6.mergedConnectionNames ?? [], ...i6.connectsTo ?? []].filter((t55) => Boolean(t55));
for (let t55 = 0;t55 < i6.route.length; t55++) {
const s6 = i6.route[t55];
if (s6?.route_type !== "via")
continue;
const a6 = `${i6.pcb_trace_id}:${t55}`, c6 = o6.getViaViolationSignatures({ point: s6, layers: o6.boardLayers, padDiameter: s6.via_diameter ?? this.inputProblem.min_via_pad_diameter ?? this.inputProblem.minViaPadDiameter ?? this.inputProblem.minViaDiameter ?? 0.6, holeDiameter: s6.via_hole_diameter ?? o6.defaultViaHoleDiameter, connectionNames: r6, ignoreTraceIndex: n7, ignoreRouteRange: { start: t55, end: t55 }, blockSameNetObstacles: true, sameNetObstacleClearance: 0 });
for (const t56 of c6)
e6.add(`${a6}|${t56}`);
}
}
return e6;
}
countViolatingImmutableVias(t54) {
return new Set([...t54].map((t55) => t55.split("|")[0])).size;
}
acceptConnectivityCheckpoint(t54, e6) {
this.connectivityValidationCount++;
let n6 = false, o6 = false;
try {
const e7 = this.connectivityInvariant.validate(t54), i6 = this.getMutatedImmutableTraceIds(t54), r6 = this.getImmutableViaViolationSignatures(t54), s6 = [...r6].filter((t55) => !this.lastSafeImmutableViaViolationSignatures.has(t55)), a6 = s6.length > 0;
if (n6 = !e7.safe, o6 = i6.length > 0 || a6, this.connectivityValidationError ??= e7.validationError ?? null, !n6 && !o6)
return this.traces = structuredClone(t54), this.lastConnectivitySafeTraces = structuredClone(t54), this.remainingImmutableViaViolationCount = this.countViolatingImmutableVias(r6), this.remainingImmutableViaViolationPairCount = r6.size, this.lastSafeImmutableViaViolationSignatures = r6, this.connectivityInvariant = new c4(this.inputProblem, this.lastConnectivitySafeTraces), true;
this.immutableTraceMutationIds = [...new Set([...this.immutableTraceMutationIds, ...i6])], a6 && (this.immutableViaViolationRollbackCount++, this.attemptedImmutableViaViolationCount = this.countViolatingImmutableVias(r6), this.attemptedImmutableViaViolationPairCount = r6.size, this.immutableViaViolationRegressionIds = [...new Set([...this.immutableViaViolationRegressionIds, ...s6])]), this.connectivityRegressionEndpointIds = [...new Set([...this.connectivityRegressionEndpointIds, ...e7.regressions.flatMap((t55) => t55.baselineEndpointLabels)])];
} catch (t55) {
n6 = true, this.connectivityValidationError = t55 instanceof Error ? t55.message : String(t55);
}
return n6 && (this.connectivityRollbackCount++, this.connectivityRollbackPhases.includes(e6) || this.connectivityRollbackPhases.push(e6)), o6 && (this.immutableSafetyRollbackCount++, this.immutableSafetyRollbackPhases.includes(e6) || this.immutableSafetyRollbackPhases.push(e6)), e6 === "expansion" ? n6 ? this.rollbackConnectivityRegressedExpansion() : this.rollbackImmutableUnsafeExpansion() : this.restoreLastConnectivitySafeTraces(), this.remainingImmutableViaViolationCount = this.countViolatingImmutableVias(this.lastSafeImmutableViaViolationSignatures), this.remainingImmutableViaViolationPairCount = this.lastSafeImmutableViaViolationSignatures.size, false;
}
rebuildObstacleIndex() {
this.obstacleIndex = new T3(this.inputProblem, this.traces, this.traceIndex, [], this.connectionNameResolver);
}
retainFailedSubSolver(t54) {
this.failedSubSolverCount++, this.failedSubSolvers ??= [], this.failedSubSolvers.length < 16 ? this.failedSubSolvers.push(t54) : this.failedSubSolvers[15] = t54;
}
tryFinalAcceptance() {
this.finalAcceptanceUsed = true;
let t54 = false;
this.activeSubSolver instanceof g4 ? (this.activeSubSolver.tryFinalAcceptance(), this.adoptCleanupOutput(this.activeSubSolver), t54 = true) : this.activeSubSolver instanceof y4 && (this.activeSubSolver.tryFinalAcceptance(), this.adoptClearanceRepairOutput(this.activeSubSolver), t54 = true), t54 || this.phase === "cleanup" || this.phase === "repair-trace-clearance" || this.phase === "complete" || this.discardInFlightExpansion(), this.activeSubSolver = null, this.pendingLayerOutput = null, this.pendingLayerPushCount = 0, this.activeInflationKey = null, this.activeInflationWidth = null, this.layerAttempt = null, this.acceptConnectivityCheckpoint(this.traces, "final"), this.traceIndex = this.traces.length, this.phase = "complete", this.rebuildObstacleIndex(), this.progress = 1, this.solved = true, this.stats = this.createStats();
}
createStats() {
return { phase: this.phase, pass: this.passIndex + 1, completedPassCount: this.completedPassCount, lastNormalizedWidthDeficitGain: this.lastNormalizedWidthDeficitGain, normalizedWidthDeficitGainByPass: [...this.normalizedWidthDeficitGainByPass], plateauReached: this.plateauReached, traceIndex: this.traceIndex, traceCount: this.traces.length, selectedTraceCount: this.traceOrder.length, routeSegmentIndex: this.routeSegmentIndex, nominalTraceWidth: this.nominalTraceWidth, intervalCursor: this.intervalCursor, intervalCount: this.currentIntervals.length, candidateWidth: this.candidateWidths[this.widthCursor], gridSize: this.gridResolutions[this.resolutionCursor], gridOffsetVariant: this.offsetCursor, keptTraceCount: this.keptTraceCount, recreatedTraceCount: this.recreatedTraceCount, expandedSegmentCount: this.expandedSegmentCount, intermediateExpandedSegmentCount: this.intermediateExpandedSegmentCount, pathWidthUpgradeCount: this.pathWidthUpgradeCount, inPlaceWidthProbeCount: this.inPlaceWidthProbeCount, reroutedSegmentCount: this.reroutedSegmentCount, unresolvedSegmentCount: this.unresolvedSegmentCount, attemptedGridCount: this.attemptedGridCount, attemptedLayerGridCount: this.attemptedLayerGridCount, attemptedInflationCount: this.attemptedInflationCount, activeInflationWidth: this.activeInflationWidth, pushedTraceCount: this.pushedTraceCount, elasticPushedTraceCount: this.elasticPushedTraceCount, layerReroutedTraceCount: this.layerReroutedTraceCount, insertedViaCount: this.insertedViaCount, neckedLayerSegmentCount: this.neckedLayerSegmentCount, removedViaPairCount: this.removedViaPairCount, removedViaCount: this.removedViaCount, simplifiedPathCount: this.simplifiedPathCount, normalizedSegmentCount: this.normalizedSegmentCount, cleanupClearanceShoveCount: this.cleanupClearanceShoveCount, relocatedViaCount: this.relocatedViaCount, unresolvedViaCount: this.unresolvedViaCount, initialImmutableViaViolationCount: this.initialImmutableViaViolationCount, remainingImmutableViaViolationCount: this.remainingImmutableViaViolationCount, initialImmutableViaViolationPairCount: this.initialImmutableViaViolationPairCount, remainingImmutableViaViolationPairCount: this.remainingImmutableViaViolationPairCount, skippedImmutableViaRepairCount: this.remainingImmutableViaViolationCount, immutableViaViolationRollbackCount: this.immutableViaViolationRollbackCount, attemptedImmutableViaViolationCount: this.attemptedImmutableViaViolationCount, attemptedImmutableViaViolationPairCount: this.attemptedImmutableViaViolationPairCount, immutableViaViolationRegressionIds: [...this.immutableViaViolationRegressionIds], immutableTraceMutationIds: [...this.immutableTraceMutationIds], padClearanceRerouteCount: this.padClearanceRerouteCount, unresolvedPadClearanceCount: this.unresolvedPadClearanceCount, repairedTraceClearanceSegmentCount: this.repairedTraceClearanceSegmentCount, repairedPadNeckSegmentCount: this.repairedPadNeckSegmentCount, unresolvedTraceClearanceSegmentCount: this.unresolvedTraceClearanceSegmentCount, sameNetContactRejectionCount: this.sameNetContactRejectionCount, connectivityValidationCount: this.connectivityValidationCount, connectivityRollbackCount: this.connectivityRollbackCount, connectivityRollbackPhases: [...this.connectivityRollbackPhases], immutableSafetyRollbackCount: this.immutableSafetyRollbackCount, immutableSafetyRollbackPhases: [...this.immutableSafetyRollbackPhases], connectivityRegressionEndpointIds: [...this.connectivityRegressionEndpointIds], connectivityValidationError: this.connectivityValidationError, connectivityRollbackMutationStats: this.connectivityRollbackMutationStats === null ? null : { ...this.connectivityRollbackMutationStats }, immutableSafetyRollbackMutationStats: this.immutableSafetyRollbackMutationStats === null ? null : { ...this.immutableSafetyRollbackMutationStats }, expansionPushedTraceIndices: [...this.expansionPushedTraceIndices], cleanupMutatedTraceIndices: [...this.cleanupMutatedTraceIndices], discardedExpansionMutationStats: this.discardedExpansionMutationStats === null ? null : { ...this.discardedExpansionMutationStats }, initialPadClearanceViolationCount: this.initialPadClearanceViolationCount, remainingPadClearanceViolationCount: this.remainingPadClearanceViolationCount, initialPadClearanceViolationCountByClearance: { ...this.initialPadClearanceViolationCountByClearance }, remainingPadClearanceViolationCountByClearance: { ...this.remainingPadClearanceViolationCountByClearance }, budgetLimitedExpansion: this.budgetLimitedExpansion, finalAcceptanceUsed: this.finalAcceptanceUsed, cleanupCompleted: this.cleanupCompleted, clearanceRepairCompleted: this.clearanceRepairCompleted, cleanupBestEffortAccepted: this.cleanupBestEffortAccepted, clearanceRepairBestEffortAccepted: this.clearanceRepairBestEffortAccepted, cleanupStatus: this.connectivityRollbackPhases.includes("cleanup") ? "connectivity_rollback" : this.immutableSafetyRollbackPhases.includes("cleanup") ? "immutable_safety_rollback" : this.cleanupBestEffortAccepted ? "budget_limited" : this.cleanupCompleted ? "completed" : this.phase === "cleanup" ? "in_progress" : "not_started", clearanceRepairStatus: this.connectivityRollbackPhases.includes("clearance-repair") ? "connectivity_rollback" : this.immutableSafetyRollbackPhases.includes("clearance-repair") ? "immutable_safety_rollback" : this.clearanceRepairBestEffortAccepted ? "budget_limited" : this.clearanceRepairCompleted ? "completed" : this.phase === "repair-trace-clearance" ? "in_progress" : "not_started", cleanupIterationBudget: this.cleanupIterationBudget, clearanceRepairIterationBudget: this.clearanceRepairIterationBudget, completionReason: this.phase === "complete" || this.solved ? this.connectivityRollbackCount > 0 ? "connectivity_rollback" : this.immutableSafetyRollbackCount > 0 ? "immutable_safety_rollback" : this.connectivityValidationError ? "connectivity_validation_unavailable" : this.finalAcceptanceUsed ? "total_iteration_budget" : this.budgetLimitedExpansion ? "expansion_budget" : this.cleanupBestEffortAccepted ? "cleanup_budget" : this.clearanceRepairBestEffortAccepted ? "clearance_repair_budget" : this.remainingImmutableViaViolationCount > 0 ? "immutable_via_violations_preserved" : "completed" : null, resultStatus: this.finalAcceptanceUsed || this.budgetLimitedExpansion || this.cleanupBestEffortAccepted || this.clearanceRepairBestEffortAccepted || this.connectivityRollbackCount > 0 || this.immutableSafetyRollbackCount > 0 || this.connectivityValidationError !== null || this.remainingImmutableViaViolationCount > 0 ? "best_effort" : "complete", failedSubSolverCount: this.failedSubSolverCount, retainedFailedSubSolverCount: this.failedSubSolvers?.length ?? 0, expansionIterationBudget: this.getExpansionIterationBudget(), finalizationIterationReserve: this.getFinalizationIterationReserve(), spatialIndexRectCount: this.obstacleIndex.items.length };
}
computeProgress() {
return this.solved || this.phase === "complete" ? 1 : this.budgetLimitedExpansion ? 0.99 : this.traceOrder.length === 0 ? 1 : Math.min(0.99, (this.passIndex + Math.max(0, this.traceOrderCursor) / this.traceOrder.length) / this.maxPassCount);
}
getConstructorParams() {
return [this.inputProblem, this.options];
}
getOutput() {
return structuredClone(this.lastConnectivitySafeTraces);
}
visualize() {
const t54 = [], e6 = [];
for (let n6 = 0;n6 < this.traces.length; n6++) {
const o6 = this.traces[n6], i6 = this.resolveNominalTraceWidth(o6);
for (const t55 of o6.route)
t55.route_type === "via" && e6.push({ center: t55, radius: (t55.via_diameter ?? 0.6) / 2, fill: "#d4a017", stroke: "#7a5700" });
for (let e7 = 0;e7 < o6.route.length - 1; e7++) {
const r6 = o6.route[e7], s6 = o6.route[e7 + 1];
if (!v4(r6) || !v4(s6) || r6.layer !== s6.layer)
continue;
const a6 = n6 === this.traceIndex && e7 === this.routeSegmentIndex, c6 = r6.width >= i6 - e3 && s6.width >= i6 - e3, l6 = r6.layer === "bottom";
t54.push({ points: [r6, s6], strokeColor: a6 ? "#ff8c00" : c6 ? l6 ? "#2468c7" : "#169c45" : l6 ? "#8b4bb8" : "#cc3344", strokeWidth: Math.max(r6.width, s6.width) });
}
}
return { coordinateSystem: "cartesian", title: `Power trace expander: ${this.phase}`, lines: t54, points: [], circles: e6, rects: this.obstacleIndex.items.filter((t55) => t55.kind === "obstacle").slice(0, 2000).map((t55) => ({ center: { x: (t55.minX + t55.maxX) / 2, y: (t55.minY + t55.maxY) / 2 }, width: t55.maxX - t55.minX, height: t55.maxY - t55.minY, fill: "rgba(80,80,80,0.12)", stroke: "rgba(80,80,80,0.35)" })), texts: [] };
}
};
var S4 = class extends si {
constructor(t54, e6 = {}) {
if (super(), this.inputSrj = t54, this.options = e6, this.powerTraceExpanderSolver = new I4(t54, e6), e6.onlyConnectionNames?.length === 0)
return this.MAX_ITERATIONS = 1, this.progress = 1, this.solved = true, void (this.stats = { selectedTraceCount: 0, bypassed: true });
this.MAX_ITERATIONS = this.powerTraceExpanderSolver.MAX_ITERATIONS + 1;
}
powerTraceExpanderSolver;
_step() {
const t54 = this.powerTraceExpanderSolver;
if (t54.step(), this.progress = t54.progress, this.stats = t54.stats, t54.failed)
return this.error = t54.error, void (this.failed = true);
t54.solved && (this.solved = true);
}
getConstructorParams() {
return [this.inputSrj, this.options];
}
getOutput() {
if (!this.solved)
throw new Error("Cannot get power trace expansion output before solving");
return this.powerTraceExpanderSolver.getOutput();
}
visualize() {
return Ho({ ...this.inputSrj, traces: this.getOutput() }, { traceColorMode: "layer" });
}
};
var C4 = ({ connections: t54, originalConnections: e6, layerCount: n6, obstacles: o6, defaultViaHoleDiameter: i6, connMap: r6 }) => {
const s6 = new Map;
for (const t55 of e6)
s6.has(t55.name) || s6.set(t55.name, t55.__netConnectionName);
const a6 = t54.map((t55) => {
if (t55.pointsToConnect.length !== 2)
throw new Error(`Expected Pipeline7 output connection "${t55.name}" to have two points, got ${t55.pointsToConnect.length}`);
const [e7, n7] = t55.pointsToConnect;
return { connection: t55, connectsTo: [e7?.pointId, n7?.pointId].filter((t56) => Boolean(t56)), outputConnectionName: t55.__netConnectionName ?? s6.get(t55.name) ?? t55.__rootConnectionNames?.[0] ?? t55.name };
}), c6 = o6.filter((t55) => (t55.__zLayers?.length ?? t55.layers?.length ?? 0) > 1), l6 = new Map, h6 = (t55) => {
let e7 = l6.get(t55.connectionName);
e7 || (e7 = new Map, l6.set(t55.connectionName, e7));
const n7 = e7.get(t55.rootConnectionName);
if (n7)
return n7;
const o7 = c6.filter((e8) => xo(e8, t55, r6));
return e7.set(t55.rootConnectionName, o7), o7;
};
return (t55) => {
const e7 = [], o7 = new Map;
for (const e8 of t55) {
const t56 = o7.get(e8.connectionName);
t56 ? t56.push(e8) : o7.set(e8.connectionName, [e8]);
}
for (const { connection: t56, connectsTo: s7, outputConnectionName: c7 } of a6) {
const a7 = o7.get(t56.name) ?? [];
for (let o8 = 0;o8 < a7.length; o8 += 1) {
const l7 = a7[o8];
e7.push({ type: "pcb_trace", pcb_trace_id: `${t56.name}_${o8}`, connection_name: c7, connectsTo: s7, route: To(l7, n6, { connectionPoints: t56.pointsToConnect, defaultViaHoleDiameter: i6, connectedMultilayerObstacles: h6(l7), connMap: r6 }) });
}
}
return e7;
};
};
var P4 = ({ connections: t54, originalConnections: e6, hdRoutes: n6, layerCount: o6, obstacles: i6, defaultViaHoleDiameter: r6, connMap: s6 }) => C4({ connections: t54, originalConnections: e6, layerCount: o6, obstacles: i6, defaultViaHoleDiameter: r6, connMap: s6 })(n6);
var M4 = (t54) => {
const e6 = Math.max(t54.minTraceWidth + 0.1, 2 * t54.minTraceWidth);
return t54.connections.flatMap((n6) => (n6.nominalTraceWidth ?? t54.nominalTraceWidth ?? t54.minTraceWidth) + 0.000001 >= e6 ? [n6.name] : []);
};
var N4 = (t54, e6, n6 = new Map(t54.map((t55) => [t55.connectionName, t55]))) => {
const o6 = new Map(e6.map((t55) => [t55.name, t55]));
return t54.map((t55) => {
if (t55.route.length === 0)
throw new Error(`Cannot lock PCB terminals for empty route "${t55.connectionName}"`);
const e7 = o6.get(t55.connectionName);
if (!e7)
throw new Error(`Cannot lock PCB terminals: connection "${t55.connectionName}" was not found`);
if (e7.pointsToConnect.length !== 2)
throw new Error(`Cannot lock PCB terminals for "${t55.connectionName}": expected 2 connection points, found ${e7.pointsToConnect.length}`);
const i6 = n6.get(t55.connectionName) ?? t55, r6 = new Map;
for (const n7 of e7.pointsToConnect)
if (n7.pcb_port_id) {
if (r6.has(n7.pcb_port_id))
throw new Error(`Cannot lock duplicate PCB terminal "${n7.pcb_port_id}" for "${t55.connectionName}"`);
r6.set(n7.pcb_port_id, n7);
}
if (r6.size === 0)
return t55;
const s6 = [i6.startPcbPortId, i6.endPcbPortId].filter((t56) => t56 !== undefined);
if (s6.length === 0)
return t55;
if (new Set(s6).size !== s6.length || s6.some((t56) => !r6.has(t56)))
throw new Error(`Cannot lock PCB terminals for "${t55.connectionName}": route endpoint IDs do not match connection terminal IDs`);
const a6 = i6.startPcbPortId ? r6.get(i6.startPcbPortId) : undefined, c6 = i6.endPcbPortId ? r6.get(i6.endPcbPortId) : undefined, l6 = t55.route.map((e8, n7) => {
if (n7 === 0 && a6)
return { ...e8, x: a6.x, y: a6.y, pcb_port_id: a6.pcb_port_id };
if (n7 === t55.route.length - 1 && c6)
return { ...e8, x: c6.x, y: c6.y, pcb_port_id: c6.pcb_port_id };
const o7 = { ...e8 };
return delete o7.pcb_port_id, o7;
});
return { ...t55, route: l6 };
});
};
var w4 = ({ originalSrj: t54, newlyRoutedTraces: e6, currentPreloadedTraces: n6, expandedConnectionNames: o6, resolveConnectedTraceAliases: i6 = false }) => {
const r6 = n6 ?? t54.traces ?? [], s6 = i6 ? T4({ originalSrj: t54, newlyRoutedTraces: e6, preloadedTraces: r6, expandedConnectionNames: o6 }) : new Set(r6.filter((t55) => o6.includes(t55.connection_name))), a6 = r6.filter((t55) => !s6.has(t55)), c6 = new Set([...e6.map((t55) => t55.pcb_trace_id), ...a6.map((t55) => t55.pcb_trace_id)]), l6 = r6.filter((t55) => s6.has(t55)).map((t55) => {
const e7 = t55.pcb_trace_id;
let n7 = e7, o7 = 2;
for (;c6.has(n7); )
n7 = `${e7}_power_expansion_${o7++}`;
return c6.add(n7), { ...t55, pcb_trace_id: n7, __replaces_pcb_trace_id: t55.__replaces_pcb_trace_id ?? t55.pcb_trace_id };
});
return { ...t54, traces: [...e6, ...l6], fixedTraces: a6 };
};
var T4 = ({ originalSrj: t54, newlyRoutedTraces: e6, preloadedTraces: n6, expandedConnectionNames: o6 }) => {
const i6 = new Set(n6.map((t55) => t55.pcb_trace_id)), r6 = new Set([...i6, ...e6.map((t55) => t55.pcb_trace_id)]), s6 = e6.map((t55, e7) => {
if (!i6.has(t55.pcb_trace_id))
return t55;
const n7 = `__pipeline7_new_trace_${e7}_${t55.pcb_trace_id}`;
let o7 = n7, s7 = 2;
for (;r6.has(o7); )
o7 = `${n7}_${s7++}`;
return r6.add(o7), { ...t55, pcb_trace_id: o7 };
}), a6 = new t310({ ...t54, traces: [...s6, ...n6] }), c6 = new Set(a6.canonicalize([...o6]));
return new Set(n6.filter((t55) => a6.canonicalize([t55.connection_name]).some((t56) => c6.has(t56))));
};
var F4 = (t54, e6) => {
const n6 = t54.filter((t55) => (t55.rootConnectionName ?? t55.connectionName) === e6);
if (n6.length !== 0)
return n6.reduce((t55, e7) => t55 + e7.route.slice(1).reduce((t56, n7, o6) => {
const i6 = e7.route[o6];
return t56 + Math.hypot(n7.x - i6.x, n7.y - i6.y);
}, 0), 0);
};
var j4 = (t54, e6) => {
const n6 = new Set(t54.flatMap((t55) => t55.maxLengthSkew === undefined ? [] : t55.connectionNames));
return e6.flatMap((t55) => {
if (!n6.has(t55.name))
return [];
const e7 = t55.pointsToConnect[0], o6 = t55.pointsToConnect.at(-1);
if (!e7 || !o6 || e7 === o6)
throw new Error(`Length matching: bus connection "${t55.name}" needs at least two points`);
return [{ ...t55, pointsToConnect: [e7, o6] }];
});
};
var $4 = class extends si {
constructor(t54) {
super(), this.params = t54, this.differentialPairSolver = new B1({ hdRoutes: t54.hdRoutes, differentialPairs: t54.differentialPairs, obstacles: t54.obstacles, bounds: t54.bounds, layerCount: t54.layerCount, minTraceToPadEdgeClearance: t54.obstacleMargin }), this.MAX_ITERATIONS = this.differentialPairSolver.MAX_ITERATIONS + 1e5 + 10;
}
differentialPairSolver;
busLengthMatchingSolver;
outputHdRoutes;
getSolverName() {
return "LengthMatchingPostProcessingSolver";
}
_step() {
if (!this.differentialPairSolver.solved)
return this.differentialPairSolver.step(), void (this.differentialPairSolver.failed && (this.failed = true, this.error = this.differentialPairSolver.error));
if (!this.busLengthMatchingSolver) {
const n6 = this.differentialPairSolver.getOutput().hdRoutes, o6 = (t54 = this.params.buses, e6 = n6, t54.flatMap((t55) => {
const n7 = t55.maxLengthSkew;
if (n7 === undefined || t55.connectionNames.length < 2)
return [];
const o7 = t55.connectionNames.map((n8) => {
const o8 = F4(e6, n8);
if (o8 === undefined)
throw new Error(`Length matching: bus "${t55.busId}" has no routed geometry for connection "${n8}"`);
return { connectionName: n8, length: o8 };
}), i6 = o7.reduce((t56, e7) => e7.length > t56.length ? e7 : t56);
return o7.flatMap((t56) => t56.connectionName === i6.connectionName ? [] : [{ connectionNames: [t56.connectionName, i6.connectionName], lengthTolerance: n7 }]);
}));
return o6.length === 0 ? (this.outputHdRoutes = n6, void (this.solved = true)) : void (this.busLengthMatchingSolver = new n1({ hdRoutes: n6, originalConnections: j4(this.params.buses, this.params.connections), differentialPairs: o6, obstacles: this.params.obstacles, bounds: this.params.bounds, layerCount: this.params.layerCount, obstacleMargin: this.params.obstacleMargin }));
}
var t54, e6;
if (this.busLengthMatchingSolver.step(), this.busLengthMatchingSolver.failed)
return this.failed = true, void (this.error = this.busLengthMatchingSolver.error);
this.busLengthMatchingSolver.solved && (this.outputHdRoutes = this.busLengthMatchingSolver.getOutput().matchedHdRoutes, ((t55, e7) => {
for (const n6 of t55) {
if (n6.maxLengthSkew === undefined || n6.connectionNames.length < 2)
continue;
const t56 = n6.connectionNames.map((t57) => {
const o7 = F4(e7, t57);
if (o7 === undefined)
throw new Error(`Length matching: bus "${n6.busId}" lost routed geometry for connection "${t57}"`);
return o7;
}), o6 = Math.max(...t56) - Math.min(...t56);
if (o6 > n6.maxLengthSkew + 0.000001)
throw new Error(`Length matching: bus "${n6.busId}" routed length skew ${o6.toFixed(4)}mm exceeds ${n6.maxLengthSkew.toFixed(4)}mm`);
}
})(this.params.buses, this.outputHdRoutes), this.solved = true);
}
getOutput() {
if (!this.solved || !this.outputHdRoutes)
throw new Error("LengthMatchingPostProcessingSolver output requested before completion");
return { hdRoutes: this.outputHdRoutes };
}
visualize() {
return this.busLengthMatchingSolver?.visualize() ?? this.differentialPairSolver.visualize();
}
};
var Y4 = 0.000000001;
var X4 = (t54, e6) => Math.abs(t54.x - e6.x) <= Y4 && Math.abs(t54.y - e6.y) <= Y4 && t54.z === e6.z;
var W4 = (t54, e6) => {
if (t54.length === 0)
return void t54.push(...e6.route);
const n6 = t54.at(-1);
if (e6.route[0] && X4(n6, e6.route[0]))
t54.push(...e6.route.slice(1));
else {
if (!e6.route.at(-1) || !X4(n6, e6.route.at(-1)))
throw new Error(`Pipeline9 could not reconnect mutated preloaded segment "${e6.connectionName}"`);
t54.push(...e6.route.slice(0, -1).reverse());
}
};
var V4 = (t54, e6) => {
const n6 = t54.preloadedRoutePositionStart ?? t54.preloadedRouteIndex, o6 = e6.preloadedRoutePositionStart ?? e6.preloadedRouteIndex, i6 = t54.preloadedRoutePositionEnd ?? n6, r6 = e6.preloadedRoutePositionEnd ?? o6;
return n6 - o6 || i6 - r6 || t54.preloadedRouteIndex - e6.preloadedRouteIndex || t54.connectionName.localeCompare(e6.connectionName);
};
var H4 = (t54) => {
const e6 = t54.route.flatMap((t55) => t55.route_type === "wire" || t55.route_type === "through_obstacle" ? [t55.width] : []);
return e6.length > 0 ? Math.max(...e6) : undefined;
};
var G4 = ({ trace: t54, updatedTraceRoutes: e6, layerCount: n6, defaultViaHoleDiameter: o6, obstacles: i6, connMap: r6 }) => {
if (e6.length === 0)
throw new Error(`Pipeline9 lost every fixed route for mutated trace "${t54.pcb_trace_id}"`);
const s6 = [];
let a6, c6 = 0, l6 = 0;
for (const t55 of [...e6].sort(V4))
W4(s6, t55), c6 = Math.max(c6, t55.traceThickness), l6 = Math.max(l6, t55.viaDiameter), a6 ??= t55.rootConnectionName;
const h6 = { connectionName: t54.connection_name, rootConnectionName: a6, traceThickness: H4(t54) ?? c6, viaDiameter: l6, route: s6, vias: s6.slice(0, -1).flatMap((t55, e7) => {
const n7 = s6[e7 + 1];
return t55.z !== n7.z && Math.abs(t55.x - n7.x) <= Y4 && Math.abs(t55.y - n7.y) <= Y4 ? [{ x: n7.x, y: n7.y }] : [];
}) };
return To(h6, n6, { defaultViaHoleDiameter: o6, obstacles: i6, connMap: r6 });
};
var U4 = (t54, e6) => t54.filter((t55) => {
if (t55.isThroughObstacle === true)
return false;
const { preloadedRoutePositionStart: n6, preloadedRoutePositionEnd: o6 } = t55;
if (n6 === undefined || o6 === undefined)
throw new Error(`Pipeline9 fixed route "${t55.connectionName}" is missing route-position metadata`);
const i6 = Math.min(n6, o6), r6 = Math.max(n6, o6);
return i6 >= e6.routePositionStart - Y4 && r6 <= e6.routePositionEnd + Y4;
});
var Z4 = ({ trace: t54, originalTraceRoutes: e6, updatedTraceRoutes: n6, layerCount: o6, defaultViaHoleDiameter: i6, obstacles: r6, connMap: s6 }) => {
if (n6.length === 0)
throw new Error(`Pipeline9 lost every fixed route for mutated trace "${t54.pcb_trace_id}"`);
const a6 = ((t55) => {
const e7 = [];
let n7 = 0;
for (let o7 = 0;o7 < t55.route.length; o7++)
t55.route[o7]?.route_type === "through_obstacle" && (n7 < o7 && e7.push({ routePositionStart: n7, routePositionEnd: o7 - 1 }), n7 = o7 + 1);
return n7 < t55.route.length && e7.push({ routePositionStart: n7, routePositionEnd: t55.route.length - 1 }), e7;
})(t54), c6 = n6.filter((t55) => t55.isThroughObstacle !== true);
for (const t55 of c6) {
if (a6.filter((e7) => U4([t55], e7).includes(t55)).length !== 1)
throw new Error(`Pipeline9 fixed route "${t55.connectionName}" crosses an immutable through-obstacle primitive`);
}
const l6 = [];
let h6 = 0;
for (const c7 of a6) {
l6.push(...t54.route.slice(h6, c7.routePositionStart));
const a7 = U4(e6, c7), d6 = U4(n6, c7);
if (a7.length > 0 && d6.length === 0)
throw new Error(`Pipeline9 lost every fixed route for an ordinary section of mutated trace "${t54.pcb_trace_id}"`);
l6.push(...d6.length > 0 ? G4({ trace: t54, updatedTraceRoutes: d6, layerCount: o6, defaultViaHoleDiameter: i6, obstacles: r6, connMap: s6 }) : t54.route.slice(c7.routePositionStart, c7.routePositionEnd + 1)), h6 = c7.routePositionEnd + 1;
}
return l6.push(...t54.route.slice(h6)), l6;
};
var q4 = (t54, e6) => {
const n6 = new Set(e6.map((t55) => t55.pcb_trace_id));
return t54.map((t55) => {
if (!n6.has(t55.pcb_trace_id))
return n6.add(t55.pcb_trace_id), t55;
const e7 = `${t55.pcb_trace_id}_routed`;
let o6 = e7, i6 = 2;
for (;n6.has(o6); )
o6 = `${e7}_${i6}`, i6 += 1;
return n6.add(o6), { ...t55, pcb_trace_id: o6 };
});
};
var J4 = (t54, e6, n6) => {
const o6 = (t55) => `${t55.x}:${t55.y}`, i6 = new Map;
for (const t55 of e6) {
const e7 = o6(t55.center), n7 = i6.get(e7) ?? [];
n7.push(t55), i6.set(e7, n7);
}
const r6 = new Map;
for (const e7 of t54)
for (const t55 of e7.pointsToConnect) {
if (!t55.pcb_port_id)
continue;
const e8 = r6.get(t55.pcb_port_id) ?? new Set, s6 = So(t55);
for (const t56 of s6)
e8.add(mo(t56, n6));
for (const r7 of i6.get(o6(t55)) ?? [])
if (!(r7.layers.length <= 1) && r7.connectedTo.includes(t55.pcb_port_id))
for (const t56 of r7.layers)
e8.add(mo(t56, n6));
r6.set(t55.pcb_port_id, e8);
}
return r6;
};
var Q4 = (t54, e6) => new Map(t54.flatMap((t55) => {
const n6 = e6.getNetConnectedToId(t55.connectionName) ?? (t55.rootConnectionName ? e6.getNetConnectedToId(t55.rootConnectionName) ?? (e6.netMap[t55.rootConnectionName] ? t55.rootConnectionName : undefined) : undefined);
return n6 ? [[t55.connectionName, n6]] : [];
}));
var K4 = 0.000000001;
var t92 = 0.000001;
var e9 = (t54, e6) => Math.abs(t54.x - e6.x) <= t92 && Math.abs(t54.y - e6.y) <= t92 && t54.z === e6.z;
var n9 = (t54) => new Map(t54.map((t55, e6) => [t55.pcb_trace_id, e6]));
var o9 = (t54, e6) => {
const n6 = t54[0], o6 = t54.at(-1);
if (!n6 || !o6)
throw new Error("Pipeline9 cannot split an empty preloaded route");
if (n6.z !== o6.z)
throw new Error("Pipeline9 cannot partially split a preloaded layer transition");
return { ...n6, x: n6.x + (o6.x - n6.x) * e6, y: n6.y + (o6.y - n6.y) * e6 };
};
var i9 = ({ traces: t54, fixedHdRoutes: e6, sections: n6 }) => {
const o6 = (({ traces: t55, sections: e7 }) => {
const n7 = n9(t55), o7 = new Map;
for (const t56 of e7) {
const e8 = n7.get(t56.traceId);
if (e8 === undefined)
throw new Error(`Pipeline9 hypergraph changed missing preloaded trace "${t56.traceId}"`);
const i6 = o7.get(e8) ?? [];
i6.push({ start: Math.min(t56.startRoutePosition, t56.endRoutePosition), end: Math.max(t56.startRoutePosition, t56.endRoutePosition) }), o7.set(e8, i6);
}
for (const t56 of o7.values())
t56.sort((t57, e8) => t57.start - e8.start || t57.end - e8.end);
return o7;
})({ traces: t54, sections: n6 });
return e6.flatMap((t55) => {
const e7 = o6.get(t55.preloadedTraceIndex);
if (!e7?.length)
return [t55];
const { preloadedRoutePositionStart: n7, preloadedRoutePositionEnd: i6 } = t55;
if (n7 === undefined || i6 === undefined)
throw new Error(`Pipeline9 fixed route "${t55.connectionName}" is missing route-position metadata`);
if (Math.abs(i6 - n7) <= K4)
return e7.some((t56) => t56.start - K4 <= n7 && n7 <= t56.end + K4) ? [] : [t55];
let r6 = [{ start: n7, end: i6 }];
for (const t56 of e7)
r6 = r6.flatMap((e8) => {
if (t56.end <= e8.start + K4 || t56.start >= e8.end - K4)
return [e8];
const n8 = [];
return t56.start > e8.start + K4 && n8.push({ start: e8.start, end: Math.min(t56.start, e8.end) }), t56.end < e8.end - K4 && n8.push({ start: Math.max(t56.end, e8.start), end: e8.end }), n8;
});
return r6.map((e8, o7) => {
const r7 = (e8.start - n7) / (i6 - n7), s6 = (e8.end - n7) / (i6 - n7);
return { ...t55, connectionName: `${t55.connectionName}_hypergraph_fixed_${o7}`, preloadedRoutePositionStart: e8.start, preloadedRoutePositionEnd: e8.end, route: [o9(t55.route, r7), o9(t55.route, s6)], vias: [] };
});
});
};
var r9 = ({ traces: t54, sections: e6, stitchedHdRoutes: n6, layerCount: o6 }) => {
const i6 = n9(t54);
return e6.map((t55, r6) => {
const s6 = i6.get(t55.traceId);
if (s6 === undefined)
throw new Error(`Pipeline9 cannot materialize missing preloaded trace "${t55.traceId}"`);
const [a6, c6] = ((t56, e7) => {
const n7 = t56.connection.pointsToConnect.map((t57) => ({ x: t57.x, y: t57.y, z: mo(Io(t57), e7) }));
if (!n7[0] || !n7[1])
throw new Error(`Pipeline9 changed section "${t56.connectionName}" is missing an endpoint`);
return [n7[0], n7[1]];
})(t55, o6), l6 = n6.flatMap((e7) => {
if (e7.connectionName !== t55.connectionName)
return [];
const n7 = (({ route: t56, sectionStart: e8, sectionEnd: n8 }) => {
const o7 = t56.route[0], i7 = t56.route.at(-1);
if (!o7 || !i7)
return null;
const r7 = o7.z === e8.z && i7.z === n8.z, s7 = o7.z === n8.z && i7.z === e8.z, a7 = r7 ? xe(o7, e8) + xe(i7, n8) : Number.POSITIVE_INFINITY, c7 = s7 ? xe(o7, n8) + xe(i7, e8) : Number.POSITIVE_INFINITY;
return Number.isFinite(a7) || Number.isFinite(c7) ? a7 <= c7 ? { score: a7, reverse: false } : { score: c7, reverse: true } : null;
})({ route: e7, sectionStart: a6, sectionEnd: c6 });
return n7 ? [{ route: e7, ...n7 }] : [];
});
l6.sort((t56, e7) => t56.score - e7.score);
const h6 = l6[0], d6 = l6[1];
if (!h6 || d6 && Math.abs(d6.score - h6.score) <= t92)
throw new Error(`Pipeline9 expected one nearest stitched route for changed preloaded section "${t55.connectionName}", got ${l6.length}`);
const u6 = (({ route: t56, reverse: e7, sectionStart: n7, sectionEnd: o7 }) => {
const i7 = e7 ? ((t57) => {
const e8 = [...t57].reverse().map((t58) => {
const { toNextSegmentType: e10, ...n8 } = t58;
return n8;
});
for (let n8 = 0;n8 < t57.length - 1; n8++) {
const o8 = t57[n8]?.toNextSegmentType;
o8 && (e8[t57.length - n8 - 2] = { ...e8[t57.length - n8 - 2], toNextSegmentType: o8 });
}
return e8;
})(t56.route) : [...t56.route];
if (!i7[0] || !i7.at(-1))
throw new Error(`Pipeline9 cannot materialize empty route "${t56.connectionName}"`);
return e9(i7[0], n7) || i7.unshift(n7), e9(i7.at(-1), o7) || i7.push(o7), { ...t56, route: i7 };
})({ route: h6.route, reverse: h6.reverse, sectionStart: a6, sectionEnd: c6 });
return { ...u6, preloadedTraceIndex: s6, preloadedRouteIndex: Number.MAX_SAFE_INTEGER - e6.length + r6, preloadedRoutePositionStart: t55.startRoutePosition, preloadedRoutePositionEnd: t55.endRoutePosition, isThroughObstacle: false };
});
};
var s9 = 0.000001;
var a9 = ({ hdRoute: t54, start: e6, end: n6 }) => {
if (Math.abs(e6.x - n6.x) <= s9 && Math.abs(e6.y - n6.y) <= s9)
return "colocated";
const o6 = t54.vias.some((t55) => Math.abs(t55.x - e6.x) <= s9 && Math.abs(t55.y - e6.y) <= s9), i6 = t54.vias.some((t55) => Math.abs(t55.x - n6.x) <= s9 && Math.abs(t55.y - n6.y) <= s9);
if (!o6 && !i6)
throw new Error(`Pipeline9 route "${t54.connectionName}" changes layers from z=${e6.z} to z=${n6.z} without an explicit via`);
if (o6 === i6)
throw new Error(`Pipeline9 route "${t54.connectionName}" has an ambiguous layer transition between (${e6.x}, ${e6.y}) and (${n6.x}, ${n6.y})`);
return o6 ? "start" : "end";
};
var c9 = (t54) => t54.map((t55) => {
const e6 = [];
for (const n6 of t55.route) {
const o6 = e6.at(-1);
if (!o6 || o6.z === n6.z || o6.toNextSegmentType === "through_obstacle") {
e6.push(n6);
continue;
}
const i6 = a9({ hdRoute: t55, start: o6, end: n6 });
i6 !== "colocated" ? (i6 === "start" ? e6.push({ x: o6.x, y: o6.y, z: n6.z }) : e6.push({ x: n6.x, y: n6.y, z: o6.z }), e6.push(n6)) : e6.push(n6);
}
return { ...t55, route: e6 };
});
var l9 = (t54) => c9(t54).map((t55) => ({ ...t55, route: t55.route.flatMap((e6, n6) => {
const o6 = t55.route[n6 - 1];
return !o6 || o6.z === e6.z || o6.toNextSegmentType === "through_obstacle" || o6.x === e6.x && o6.y === e6.y ? [e6] : [{ x: e6.x, y: e6.y, z: o6.z }, e6];
}) }));
var h9 = 0.000000001;
var d9 = (t54) => ({ minX: t54.center.x - t54.width / 2, maxX: t54.center.x + t54.width / 2, minY: t54.center.y - t54.height / 2, maxY: t54.center.y + t54.height / 2 });
var u9 = (t54, e6) => t54.x >= e6.minX - h9 && t54.x <= e6.maxX + h9 && t54.y >= e6.minY - h9 && t54.y <= e6.maxY + h9;
var p9 = (t54, e6, n6) => n6 <= h9 ? t54 : n6 >= 0.999999999 ? e6 : { x: t54.x + (e6.x - t54.x) * n6, y: t54.y + (e6.y - t54.y) * n6, z: t54.z };
var m9 = (t54, e6, n6) => {
const o6 = e6.x - t54.x, i6 = e6.y - t54.y;
if (Math.abs(o6) <= h9 && Math.abs(i6) <= h9)
return u9(t54, n6) && u9(e6, n6) ? { start: t54, end: e6 } : null;
let r6 = 0, s6 = 1;
const a6 = [[-o6, t54.x - n6.minX], [o6, n6.maxX - t54.x], [-i6, t54.y - n6.minY], [i6, n6.maxY - t54.y]];
for (const [t55, e7] of a6) {
if (Math.abs(t55) <= h9) {
if (e7 < 0)
return null;
continue;
}
const n7 = e7 / t55;
if (t55 < 0 ? r6 = Math.max(r6, n7) : s6 = Math.min(s6, n7), r6 > s6 + h9)
return null;
}
return { start: p9(t54, e6, r6), end: p9(t54, e6, s6) };
};
var g9 = (t54) => {
const e6 = t54.sourceRoutes[0], n6 = `pipeline9_fallback:${e6.connectionName}`, o6 = `${n6}:start`, i6 = `${n6}:end`;
return [{ ...t54.start.point, portPointId: o6, nextPortPointId: i6, connectionName: e6.connectionName, rootConnectionName: e6.rootConnectionName }, { ...t54.end.point, portPointId: i6, prevPortPointId: o6, connectionName: e6.connectionName, rootConnectionName: e6.rootConnectionName }];
};
var f9 = (t54, e6) => Math.abs(t54.x - e6.x) <= h9 && Math.abs(t54.y - e6.y) <= h9 && t54.z === e6.z;
var y9 = (t54, e6) => t54.sourceRoute.preloadedTraceIndex === e6.sourceRoute.preloadedTraceIndex && f9(t54.sourceRoute.route.at(-1), e6.sourceRoute.route[0]);
var _9 = (t54, e6, n6 = new Set) => {
const o6 = new Map, i6 = [], r6 = new Set(t54.portPoints.map((t55) => t55.z)), s6 = e6.map((e7) => ((t55, e8) => {
const n7 = d9(e8);
let o7, i7;
for (let e10 = 0;e10 < t55.route.length - 1; e10++) {
const r7 = m9(t55.route[e10], t55.route[e10 + 1], n7);
r7 && (o7 ??= { segmentIndex: e10, point: r7.start }, i7 = { segmentIndex: e10, point: r7.end });
}
return o7 && i7 ? { sourceRoute: t55, start: o7, end: i7 } : null;
})(e7, t54)).filter((t55) => t55 !== null), a6 = s6.filter((t55) => t55.sourceRoute.isThroughObstacle !== true && (((t56, e7) => e7.size === 0 || [t56.start.point, ...t56.sourceRoute.route.slice(t56.start.segmentIndex + 1, t56.end.segmentIndex + 1), t56.end.point].some((t57) => e7.has(t57.z)))(t55, r6) || n6.has(t55.sourceRoute.connectionName))).sort((t55, e7) => t55.sourceRoute.preloadedTraceIndex - e7.sourceRoute.preloadedTraceIndex || t55.sourceRoute.preloadedRouteIndex - e7.sourceRoute.preloadedRouteIndex), c6 = new Set(a6.map((t55) => t55.sourceRoute)), l6 = s6.map((t55) => t55.sourceRoute).filter((t55) => !c6.has(t55)), h6 = [];
for (let t55 = 0;t55 < a6.length; t55++) {
const e7 = a6[t55], n7 = a6[t55 - 1], o7 = h6.at(-1);
n7 && o7 && y9(n7, e7) ? (o7.sourceRoutes.push(e7.sourceRoute), o7.end = e7.end) : h6.push({ sourceRoutes: [e7.sourceRoute], start: e7.start, end: e7.end });
}
for (const t55 of h6) {
if (f9(t55.start.point, t55.end.point))
continue;
const e7 = t55.sourceRoutes[0].connectionName;
if (o6.has(e7))
throw new Error(`Pipeline9 regional fallback found duplicate fixed route section identity "${e7}"`);
o6.set(e7, t55), i6.push(g9(t55));
}
return { nodeWithPortPoints: { ...t54, portPoints: [...t54.portPoints, ...i6.flatMap((t55) => t55)], portPointsInPairs: [...t54.portPointsInPairs ?? [], ...i6] }, fixedRouteSectionsByConnectionName: o6, fixedObstacleRoutes: l6 };
};
var b9 = (t54) => {
const e6 = [];
for (let n6 = 0;n6 < t54.length - 1; n6++) {
const o6 = t54[n6], i6 = t54[n6 + 1];
o6.z !== i6.z && Math.abs(o6.x - i6.x) <= h9 && Math.abs(o6.y - i6.y) <= h9 && e6.push({ x: i6.x, y: i6.y });
}
return e6;
};
var x9 = (t54, e6) => v9({ section: t54, replacement: e6, sourceMutationMasks: new Map, replacementIsMutated: false }).route;
var v9 = ({ section: t54, replacement: e6, sourceMutationMasks: n6, replacementIsMutated: o6 }) => {
const i6 = t54.sourceRoutes[0], r6 = t54.sourceRoutes.at(-1), s6 = ((t55, e7) => {
const n7 = t55.route, o7 = n7[0], i7 = n7.at(-1);
if (!o7 || !i7)
throw new Error(`Pipeline9 regional fallback produced an empty replacement for "${e7.sourceRoutes[0].connectionName}"`);
const r7 = Math.hypot(o7.x - e7.start.point.x, o7.y - e7.start.point.y) + Math.hypot(i7.x - e7.end.point.x, i7.y - e7.end.point.y);
return Math.hypot(i7.x - e7.start.point.x, i7.y - e7.start.point.y) + Math.hypot(o7.x - e7.end.point.x, o7.y - e7.end.point.y) < r7 ? [...n7].reverse() : n7;
})(e6, t54), a6 = [], c6 = [], l6 = (t55, e7) => {
const o7 = n6.get(t55.connectionName);
if (o7 && o7.length !== t55.route.length - 1)
throw new Error(`Pipeline9 fixed route mutation mask for "${t55.connectionName}" has ${o7.length} segments, expected ${t55.route.length - 1}`);
return o7?.[e7] ?? false;
}, h6 = (t55, e7) => {
const n7 = a6.at(-1);
if (n7) {
if (!f9(n7, t55)) {
if (n7.z !== t55.z && (Math.abs(n7.x - t55.x) > h9 || Math.abs(n7.y - t55.y) > h9)) {
const o7 = { ...t55, z: n7.z };
f9(n7, o7) || (a6.push(o7), c6.push(e7));
}
f9(a6.at(-1), t55) || (a6.push(t55), c6.push(e7));
}
} else
a6.push(t55);
};
h6(i6.route[0], false);
for (let e7 = 1;e7 <= t54.start.segmentIndex; e7++)
h6(i6.route[e7], l6(i6, e7 - 1));
h6(t54.start.point, l6(i6, t54.start.segmentIndex));
const d6 = c6.length;
for (const t55 of s6.slice(1, -1))
h6(t55, o6);
h6(t54.end.point, o6);
const u6 = c6.length > d6;
for (let e7 = t54.end.segmentIndex + 1;e7 < r6.route.length; e7++)
h6(r6.route[e7], l6(r6, e7 - 1));
if (c6.length !== a6.length - 1)
throw new Error(`Pipeline9 produced an invalid mutation mask while splicing "${i6.connectionName}"`);
return { route: { ...i6, preloadedRoutePositionStart: i6.preloadedRoutePositionStart, preloadedRoutePositionEnd: r6.preloadedRoutePositionEnd, traceThickness: Math.max(...t54.sourceRoutes.map((t55) => t55.traceThickness)), viaDiameter: Math.max(...t54.sourceRoutes.map((t55) => t55.viaDiameter)), route: a6, vias: b9(a6) }, mutatedSegments: c6, replacementProducedSegment: u6 };
};
var I9 = 0.000001;
var S9 = (t54, e6) => Math.abs(t54.x - e6.x) <= I9 && Math.abs(t54.y - e6.y) <= I9 && t54.z === e6.z;
var C9 = (t54, e6) => {
for (const n6 of e6)
t54.at(-1) && S9(t54.at(-1), n6) || t54.push(n6);
};
var P9 = (t54) => t54.slice(0, -1).flatMap((e6, n6) => {
const o6 = t54[n6 + 1];
return e6.z !== o6.z && Math.abs(e6.x - o6.x) <= I9 && Math.abs(e6.y - o6.y) <= I9 ? [{ x: o6.x, y: o6.y }] : [];
});
var M9 = (t54) => {
const { preloadedRoutePositionStart: e6, preloadedRoutePositionEnd: n6 } = t54;
if (e6 === undefined || n6 === undefined)
throw new Error(`Pipeline9 fixed route "${t54.connectionName}" is missing route-position metadata`);
return { start: Math.min(e6, n6), end: Math.max(e6, n6) };
};
var N9 = (t54, e6) => {
const n6 = M9(t54), o6 = M9(e6);
return t54.preloadedTraceIndex - e6.preloadedTraceIndex || n6.start - o6.start || n6.end - o6.end || t54.preloadedRouteIndex - e6.preloadedRouteIndex || t54.connectionName.localeCompare(e6.connectionName);
};
var w9 = (t54, e6) => {
const n6 = t54.route.at(-1), o6 = e6.route[0];
return Boolean(n6 && o6 && t54.preloadedTraceIndex === e6.preloadedTraceIndex && S9(n6, o6));
};
var T9 = (t54, e6) => {
const n6 = t54.preloadedRoutePositionStart ?? t54.preloadedRouteIndex;
return n6 + ((t54.preloadedRoutePositionEnd ?? t54.preloadedRouteIndex) - n6) * e6 / (t54.route.length - 1);
};
var R9 = (t54, e6) => t54.route[e6].z !== t54.route[e6 + 1].z;
var E9 = ({ updatedFixedRoutes: t54, regionalMutationMasks: e6 }) => {
const n6 = [], o6 = (({ updatedFixedRoutes: t55, regionalMutationMasks: e7 }) => {
const n7 = new Map;
for (const o8 of t55) {
if (o8.route.length === 0)
throw new Error(`Pipeline9 cannot normalize empty fixed route "${o8.connectionName}"`);
const t56 = o8.route.length - 1;
if (n7.has(o8.connectionName))
throw new Error(`Pipeline9 cannot normalize duplicate fixed route "${o8.connectionName}"`);
const i7 = e7.get(o8.connectionName);
if (i7 && i7.length !== t56)
throw new Error(`Pipeline9 fixed route mutation mask for "${o8.connectionName}" has ${i7.length} segments, expected ${t56}`);
const r7 = o8.isThroughObstacle !== true && (o8.jumpers?.length ?? 0) === 0;
n7.set(o8.connectionName, Array.from({ length: t56 }, (t57, e8) => r7 && (i7?.[e8] ?? false)));
}
let o7 = [];
const i6 = () => {
for (;o7[0] && R9(o7[0].route, o7[0].segmentIndex); ) {
const t56 = o7.shift();
n7.get(t56.route.connectionName)[t56.segmentIndex] = false;
}
for (;o7.at(-1) && R9(o7.at(-1).route, o7.at(-1).segmentIndex); ) {
const t56 = o7.pop();
n7.get(t56.route.connectionName)[t56.segmentIndex] = false;
}
o7 = [];
};
let r6;
for (const e8 of [...t55].sort(N9)) {
r6 && !w9(r6, e8) && i6();
const t56 = n7.get(e8.connectionName);
if (t56.length !== 0) {
for (let n8 = 0;n8 < t56.length; n8++)
t56[n8] ? o7.push({ route: e8, segmentIndex: n8 }) : i6();
r6 = e8;
} else
i6(), r6 = e8;
}
return i6(), n7;
})({ updatedFixedRoutes: t54, regionalMutationMasks: e6 });
for (const e7 of t54) {
const t55 = e7.route.length - 1, i6 = o6.get(e7.connectionName);
if (t55 === 0) {
n6.push({ route: e7, mutated: false });
continue;
}
const r6 = [];
for (let e8 = 0;e8 < t55; e8++) {
const t56 = i6[e8], n7 = r6.at(-1);
n7?.mutated === t56 ? n7.end = e8 + 1 : r6.push({ start: e8, end: e8 + 1, mutated: t56 });
}
for (const [t56, o7] of r6.entries()) {
const i7 = e7.route.slice(o7.start, o7.end + 1), s6 = { ...e7, connectionName: r6.length === 1 ? e7.connectionName : `${e7.connectionName}_mutation_fragment_${t56}`, preloadedRouteIndex: e7.preloadedRouteIndex + t56 / (r6.length + 1), preloadedRoutePositionStart: T9(e7, o7.start), preloadedRoutePositionEnd: T9(e7, o7.end), route: i7, vias: P9(i7) };
n6.push({ route: s6, mutated: o7.mutated });
}
}
return n6;
};
var A9 = ({ updatedFixedRoutes: t54, regionalMutationMasks: e6 }) => {
const n6 = E9({ updatedFixedRoutes: t54, regionalMutationMasks: e6 }), o6 = n6.map(({ route: t55 }) => t55), i6 = ((t55) => {
const e7 = [];
let n7;
for (const o7 of [...t55].sort((t56, e8) => N9(t56.route, e8.route))) {
const t56 = o7.route;
if (!o7.mutated) {
n7 = undefined;
continue;
}
const i7 = t56.route[0], r7 = t56.route.at(-1);
if (!i7 || !r7 || t56.route.length < 2)
throw new Error(`Pipeline9 cannot simplify empty fixed route "${t56.connectionName}"`);
const s7 = n7?.sourceRoutes.at(-1);
n7 && s7 && w9(s7, t56) ? (n7.sourceRoutes.push(t56), n7.end = { segmentIndex: t56.route.length - 2, point: r7 }) : (n7 = { sourceRoutes: [t56], start: { segmentIndex: 0, point: i7 }, end: { segmentIndex: t56.route.length - 2, point: r7 } }, e7.push(n7));
}
return e7;
})(n6), r6 = i6.map((t55, e7) => {
const n7 = ((t56, e8) => {
const n8 = t56.sourceRoutes[0], o7 = t56.sourceRoutes.at(-1);
if (!n8 || !o7)
throw new Error("Pipeline9 cannot simplify an empty mutation section");
const i7 = [t56.start.point];
for (const [e10, n10] of t56.sourceRoutes.entries()) {
const o8 = e10 === 0, r7 = e10 === t56.sourceRoutes.length - 1, s7 = o8 ? t56.start.segmentIndex + 1 : 0, a6 = r7 ? t56.end.segmentIndex + 1 : n10.route.length;
C9(i7, n10.route.slice(s7, a6));
}
if (C9(i7, [t56.end.point]), i7.length < 2)
throw new Error(`Pipeline9 mutation section for "${n8.connectionName}" has no routable span`);
return { connectionName: `pipeline9_mutated_preload_${n8.preloadedTraceIndex}_${e8}`, rootConnectionName: n8.rootConnectionName, traceThickness: Math.max(...t56.sourceRoutes.map((t57) => t57.traceThickness)), viaDiameter: Math.max(...t56.sourceRoutes.map((t57) => t57.viaDiameter)), route: i7, vias: P9(i7) };
})(t55, e7);
return { connectionName: n7.connectionName, section: t55, hdRoute: n7 };
}), s6 = new Set(r6.flatMap(({ section: t55 }) => t55.sourceRoutes.map((t56) => t56.connectionName)));
return { sections: r6, immutableHdRoutes: o6.filter((t55) => !s6.has(t55.connectionName)), normalizedFixedRoutes: o6 };
};
var O9 = 0.000000001;
var k9 = (t54, e6, n6, o6, i6) => {
const r6 = i6.getNetConnectedToId(t54.connection_name) ?? t54.connection_name, s6 = [], a6 = (n7, i7, a7 = o6, c6 = [], l6, h6, d6 = false) => {
n7.length < 2 || s6.push({ connectionName: `${t54.connection_name}_fixed_${e6}_${s6.length}`, rootConnectionName: r6, preloadedTraceIndex: e6, preloadedRouteIndex: s6.length, preloadedRoutePositionStart: l6, preloadedRoutePositionEnd: h6, isThroughObstacle: d6, traceThickness: Math.max(O9, i7), viaDiameter: Math.max(O9, a7), route: n7, vias: c6 });
};
for (let e7 = 0;e7 < t54.route.length; e7++) {
const i7 = t54.route[e7];
if (i7.route_type === "via") {
a6([{ x: i7.x, y: i7.y, z: mo(i7.from_layer, n6) }, { x: i7.x, y: i7.y, z: mo(i7.to_layer, n6) }], O9, i7.via_diameter ?? o6, [{ x: i7.x, y: i7.y }], e7, e7);
continue;
}
if (i7.route_type === "through_obstacle") {
const t55 = mo(i7.from_layer, n6), r8 = mo(i7.to_layer, n6);
for (let n7 = Math.min(t55, r8);n7 <= Math.max(t55, r8); n7++)
a6([{ ...i7.start, z: n7 }, { ...i7.end, z: n7 }], i7.width, o6, [], e7, e7 + 1, true);
continue;
}
const r7 = t54.route[e7 + 1];
i7.route_type === "wire" && r7?.route_type === "wire" && i7.layer === r7.layer && a6([{ x: i7.x, y: i7.y, z: mo(i7.layer, n6) }, { x: r7.x, y: r7.y, z: mo(r7.layer, n6) }], Math.max(i7.width, r7.width), o6, [], e7, e7 + 1);
}
return s6;
};
function D9(t54, e6) {
return { x: t54.a * e6.x + t54.b * e6.y + t54.c, y: t54.d * e6.x + t54.e * e6.y + t54.f };
}
var L9 = { highResolutionCellSize: 0.1, highResolutionCellThickness: 8, lowResolutionCellSize: 0.4, traceMargin: 0.15, traceThickness: 0.1, viaDiameter: 0.3, viaMinDistFromBorder: 0.15 };
var z9 = { ...L9 };
var B9 = (t54, e6, n6) => {
const [o6, i6] = t54;
if (o6 === i6)
return;
const r6 = ((t55, e7) => {
const n7 = t55.portPointId ?? `${t55.connectionName}:${t55.x}:${t55.y}:${t55.z}`, o7 = e7.portPointId ?? `${e7.connectionName}:${e7.x}:${e7.y}:${e7.z}`;
return n7 < o7 ? `${n7}|${o7}` : `${o7}|${n7}`;
})(o6, i6);
e6.has(r6) || (e6.add(r6), n6.push(t54));
};
var F9 = (t54, e6, n6) => {
for (let o6 = 0;o6 < t54.length - 1; o6++)
B9([t54[o6], t54[o6 + 1]], e6, n6);
};
var j9 = (t54) => {
const e6 = [], n6 = new Set, o6 = ((t55) => {
const e7 = new Map;
for (const n7 of t55)
n7.portPointId && e7.set(n7.portPointId, n7);
return e7;
})(t54);
for (const i7 of t54) {
if (i7.prevPortPointId) {
const t55 = o6.get(i7.prevPortPointId);
t55 && t55.connectionName === i7.connectionName && B9([t55, i7], n6, e6);
}
if (i7.nextPortPointId) {
const t55 = o6.get(i7.nextPortPointId);
t55 && t55.connectionName === i7.connectionName && B9([i7, t55], n6, e6);
}
}
if (e6.length === 0)
return F9(t54, n6, e6), e6;
const i6 = ((t55) => {
const e7 = new Set;
for (const [n7, o7] of t55)
n7.portPointId && e7.add(n7.portPointId), o7.portPointId && e7.add(o7.portPointId);
return e7;
})(e6), r6 = t54.filter((t55) => !t55.portPointId || !i6.has(t55.portPointId));
return F9(r6, n6, e6), e6;
};
function $9(t54, e6, n6) {
return Math.max(e6, Math.min(n6, t54));
}
var Y9 = ["left", "top", "right", "bottom", "middle"];
var X9 = class {
f = new Float64Array(1024);
seq = new Uint32Array(1024);
id = new Int32Array(1024);
n = 0;
push(t54, e6, n6) {
this.ensureCapacity(this.n + 1);
let o6 = this.n++;
for (this.f[o6] = t54, this.seq[o6] = e6, this.id[o6] = n6;o6 > 0; ) {
const t55 = o6 - 1 >> 1;
if (this.less(t55, o6))
break;
this.swap(o6, t55), o6 = t55;
}
}
pop() {
const t54 = this.id[0];
return this.n--, this.n > 0 && (this.f[0] = this.f[this.n], this.seq[0] = this.seq[this.n], this.id[0] = this.id[this.n], this.siftDown(0)), t54;
}
get size() {
return this.n;
}
clear() {
this.n = 0;
}
ensureCapacity(t54) {
if (t54 <= this.f.length)
return;
let e6 = this.f.length;
for (;e6 < t54; )
e6 *= 2;
const n6 = new Float64Array(e6);
n6.set(this.f), this.f = n6;
const o6 = new Uint32Array(e6);
o6.set(this.seq), this.seq = o6;
const i6 = new Int32Array(e6);
i6.set(this.id), this.id = i6;
}
siftDown(t54) {
for (;; ) {
const e6 = 2 * t54 + 1, n6 = e6 + 1;
if (e6 >= this.n)
return;
let o6 = e6;
if (n6 < this.n && !this.less(e6, n6) && (o6 = n6), this.less(t54, o6))
return;
this.swap(t54, o6), t54 = o6;
}
}
less(t54, e6) {
const n6 = this.f[t54], o6 = this.f[e6];
return n6 !== o6 ? n6 < o6 : this.seq[t54] < this.seq[e6];
}
swap(t54, e6) {
const n6 = this.f[t54];
this.f[t54] = this.f[e6], this.f[e6] = n6;
const o6 = this.seq[t54];
this.seq[t54] = this.seq[e6], this.seq[e6] = o6;
const i6 = this.id[t54];
this.id[t54] = this.id[e6], this.id[e6] = i6;
}
};
var W9 = class {
z = new Int32Array(1024);
cellId = new Int32Array(1024);
g = new Float64Array(1024);
parent = new Int32Array(1024);
ripHead = new Int32Array(1024).fill(-1);
ripCount = new Int32Array(1024);
length = 0;
clear() {
this.length = 0;
}
push(t54, e6, n6, o6, i6, r6) {
this.ensureCapacity(this.length + 1);
const s6 = this.length++;
return this.z[s6] = t54, this.cellId[s6] = e6, this.g[s6] = n6, this.parent[s6] = o6, this.ripHead[s6] = i6, this.ripCount[s6] = r6, s6;
}
ensureCapacity(t54) {
if (t54 <= this.z.length)
return;
let e6 = this.z.length;
for (;e6 < t54; )
e6 *= 2;
const n6 = new Int32Array(e6);
n6.set(this.z), this.z = n6;
const o6 = new Int32Array(e6);
o6.set(this.cellId), this.cellId = o6;
const i6 = new Float64Array(e6);
i6.set(this.g), this.g = i6;
const r6 = new Int32Array(e6);
r6.set(this.parent), this.parent = r6;
const s6 = new Int32Array(e6);
s6.fill(-1), s6.set(this.ripHead.subarray(0, this.length)), this.ripHead = s6;
const a6 = new Int32Array(e6);
a6.set(this.ripCount.subarray(0, this.length)), this.ripCount = a6;
}
};
var V9 = class {
connId = new Int32Array(1024);
prev = new Int32Array(1024).fill(-1);
length = 0;
clear() {
this.length = 0;
}
append(t54, e6) {
this.ensureCapacity(this.length + 1);
const n6 = this.length++;
return this.connId[n6] = e6, this.prev[n6] = t54, n6;
}
contains(t54, e6) {
for (let n6 = t54;n6 >= 0; n6 = this.prev[n6])
if (this.connId[n6] === e6)
return true;
return false;
}
collect(t54, e6) {
e6.length = 0;
for (let n6 = t54;n6 >= 0; n6 = this.prev[n6])
e6.push(this.connId[n6]);
}
ensureCapacity(t54) {
if (t54 <= this.connId.length)
return;
let e6 = this.connId.length;
for (;e6 < t54; )
e6 *= 2;
const n6 = new Int32Array(e6);
n6.set(this.connId), this.connId = n6;
const o6 = new Int32Array(e6);
o6.fill(-1), o6.set(this.prev.subarray(0, this.length)), this.prev = o6;
}
};
function H9(t54, e6) {
return e6 ?? t54.replace(/_mst\d+$/, "");
}
function G9(t54, e6) {
const n6 = t54.x - e6.center.x, o6 = t54.y - e6.center.y, i6 = Math.cos(-e6.rotationRadians), r6 = Math.sin(-e6.rotationRadians);
return { x: n6 * i6 - o6 * r6, y: n6 * r6 + o6 * i6 };
}
function U9(t54) {
return { minX: -t54.width / 2, minY: -t54.height / 2, maxX: t54.width / 2, maxY: t54.height / 2 };
}
function Z9(t54, e6, n6) {
return Math.max(e6, Math.min(n6, t54));
}
function q9(t54, e6) {
for (let n6 = 0;n6 < t54.length; n6++)
if (t54[n6] === e6)
return;
t54.push(e6);
}
function J9(t54, e6) {
for (let n6 = 0;n6 < t54.length; n6++)
if (t54[n6].cellId === e6.cellId)
return;
t54.push(e6);
}
function Q9(t54, e6, n6, o6, i6, r6, s6) {
const a6 = t54 - Z9(t54, o6, r6), c6 = e6 - Z9(e6, i6, s6);
return a6 * a6 + c6 * c6 <= n6 * n6;
}
function K9(t54) {
const e6 = t54.segmentEnd.x - t54.segmentStart.x, n6 = t54.segmentEnd.y - t54.segmentStart.y, o6 = e6 ** 2 + n6 ** 2;
if (o6 === 0)
return (t54.point.x - t54.segmentStart.x) ** 2 + (t54.point.y - t54.segmentStart.y) ** 2;
const i6 = Z9(((t54.point.x - t54.segmentStart.x) * e6 + (t54.point.y - t54.segmentStart.y) * n6) / o6, 0, 1), r6 = t54.segmentStart.x + i6 * e6, s6 = t54.segmentStart.y + i6 * n6;
return (t54.point.x - r6) ** 2 + (t54.point.y - s6) ** 2;
}
function t62(t54) {
const e6 = Z9(t54.point.x, t54.rect.minX, t54.rect.maxX), n6 = Z9(t54.point.y, t54.rect.minY, t54.rect.maxY), o6 = t54.point.x - e6, i6 = t54.point.y - n6;
return o6 * o6 + i6 * i6;
}
function e6(t54) {
return (t54.second.x - t54.first.x) * (t54.third.y - t54.first.y) - (t54.second.y - t54.first.y) * (t54.third.x - t54.first.x);
}
function n6(t54) {
return !(Math.abs(e6({ first: t54.segmentStart, second: t54.segmentEnd, third: t54.point })) > 0.000000001) && (t54.point.x >= Math.min(t54.segmentStart.x, t54.segmentEnd.x) && t54.point.x <= Math.max(t54.segmentStart.x, t54.segmentEnd.x) && t54.point.y >= Math.min(t54.segmentStart.y, t54.segmentEnd.y) && t54.point.y <= Math.max(t54.segmentStart.y, t54.segmentEnd.y));
}
function o6(t54) {
const e7 = e6({ first: t54.firstStart, second: t54.firstEnd, third: t54.secondStart }), n7 = e6({ first: t54.firstStart, second: t54.firstEnd, third: t54.secondEnd }), o7 = e6({ first: t54.secondStart, second: t54.secondEnd, third: t54.firstStart }), i6 = e6({ first: t54.secondStart, second: t54.secondEnd, third: t54.firstEnd });
return e7 * n7 < 0 && o7 * i6 < 0 || (n6({ point: t54.secondStart, segmentStart: t54.firstStart, segmentEnd: t54.firstEnd }) || n6({ point: t54.secondEnd, segmentStart: t54.firstStart, segmentEnd: t54.firstEnd }) || n6({ point: t54.firstStart, segmentStart: t54.secondStart, segmentEnd: t54.secondEnd }) || n6({ point: t54.firstEnd, segmentStart: t54.secondStart, segmentEnd: t54.secondEnd }));
}
function i6(t54) {
return o6(t54) ? 0 : Math.min(K9({ point: t54.firstStart, segmentStart: t54.secondStart, segmentEnd: t54.secondEnd }), K9({ point: t54.firstEnd, segmentStart: t54.secondStart, segmentEnd: t54.secondEnd }), K9({ point: t54.secondStart, segmentStart: t54.firstStart, segmentEnd: t54.firstEnd }), K9({ point: t54.secondEnd, segmentStart: t54.firstStart, segmentEnd: t54.firstEnd }));
}
function r6(t54) {
if (function(t55) {
if (t62({ point: t55.segmentStart, rect: t55.rect }) === 0 || t62({ point: t55.segmentEnd, rect: t55.rect }) === 0)
return true;
const e8 = [{ x: t55.rect.minX, y: t55.rect.minY }, { x: t55.rect.maxX, y: t55.rect.minY }, { x: t55.rect.maxX, y: t55.rect.maxY }, { x: t55.rect.minX, y: t55.rect.maxY }];
for (let n7 = 0;n7 < e8.length; n7++) {
const o7 = (n7 + 1) % e8.length;
if (o6({ firstStart: t55.segmentStart, firstEnd: t55.segmentEnd, secondStart: e8[n7], secondEnd: e8[o7] }))
return true;
}
return false;
}(t54))
return true;
const e7 = t54.radius ** 2;
if (t62({ point: t54.segmentStart, rect: t54.rect }) <= e7 || t62({ point: t54.segmentEnd, rect: t54.rect }) <= e7)
return true;
return [{ x: t54.rect.minX, y: t54.rect.minY }, { x: t54.rect.maxX, y: t54.rect.minY }, { x: t54.rect.maxX, y: t54.rect.maxY }, { x: t54.rect.minX, y: t54.rect.maxY }].some((n7) => K9({ point: n7, segmentStart: t54.segmentStart, segmentEnd: t54.segmentEnd }) <= e7);
}
var s6 = class extends kt {
getSolverName() {
return "HighDensitySolverB01";
}
nodeWithPortPoints;
obstacles;
highResolutionCellSize;
highResolutionCellThickness;
lowResolutionCellSize;
viaDiameter;
MAX_RIPS;
maxCellCount;
traceThickness;
traceMargin;
obstacleClearanceMargin;
viaMinDistFromBorder;
showPenaltyMap;
showUsedCellMap;
effort;
stepMultiplier;
hyperParameters;
initialPenaltyFn;
boundsMinX;
boundsMaxX;
boundsMinY;
boundsMaxY;
gridToBoundsTransform;
availableZ;
zToLayer;
layerToZ;
layers;
fineRows;
fineCols;
lowScale;
bandRows;
bandCols;
regions;
planeSize;
cellCenterX;
cellCenterY;
cellMinX;
cellMinY;
cellMaxX;
cellMaxY;
cellWidth;
cellHeight;
cellRegion;
cellRow;
cellCol;
viaAllowed;
neighborOffset;
neighborIds;
neighborCosts;
usedCellsFlat;
sharedCellsFlat;
portOwnerFlat;
penalty2d;
ripStateBuckets;
visitedStamp;
bestGStamp;
bestGValue;
visitedFlatStamp;
sharedCrossRootPortFlat;
stamp = 0;
connNameToId;
connIdToName;
connIdToRootNet;
overlapFriendlyRootNets;
usedIndicesByConn;
unsolvedSegs;
solvedRoutes;
activeConnSeg = null;
activeConnId = -1;
nodePool;
heap;
ripChain;
seqCounter = 0;
_viaOccs = [];
_cellOccs = [];
_rippedIds = [];
ripCount;
totalRipEvents = 0;
searchIterations = 0;
consecutiveSkips = 0;
penaltyCap;
baseSearchBudgetIters;
_moveCost = 0;
_moveRippedHead = -1;
_moveRipCount = 0;
traceKeepoutRadius;
viaKeepoutRadius;
obstacleTraceRootIdsFlat;
obstacleViaRootIdsByCell;
obstacleRootNameToId;
obstacleRootNames;
obstacleTracePrimitives;
obstacleViaPrimitives;
obstacleRectPrimitives;
obstacleTraceBlockedCellCount = 0;
obstacleViaBlockedCellCount = 0;
get unsolvedConnections() {
return this.unsolvedSegs;
}
get solvedConnectionsMap() {
const t54 = new Map;
for (let e7 = 0;e7 < this.solvedRoutes.length; e7++) {
const n7 = this.getSolvedRoutesForConn(e7);
n7.length > 0 && t54.set(e7, n7);
}
return t54;
}
get activeConnection() {
if (!this.activeConnSeg)
return null;
const t54 = this.activeConnSeg.startCellId, e7 = this.activeConnSeg.endCellId;
return { connectionName: this.connIdToName[this.activeConnSeg.connId] ?? "", start: { cellId: t54, region: Y9[this.cellRegion[t54]], row: this.cellRow[t54], col: this.cellCol[t54], x: this.cellCenterX[t54], y: this.cellCenterY[t54], z: this.activeConnSeg.startZ }, end: { cellId: e7, region: Y9[this.cellRegion[e7]], row: this.cellRow[e7], col: this.cellCol[e7], x: this.cellCenterX[e7], y: this.cellCenterY[e7], z: this.activeConnSeg.endZ } };
}
get openSet() {
return { length: this.heap?.size ?? 0 };
}
get gridStats() {
return { cells: this.planeSize || 0, layers: this.layers || 0, states: (this.planeSize || 0) * (this.layers || 0), ripStateBuckets: this.ripStateBuckets || 0, neighborEdges: this.neighborIds?.length ?? 0, regionCounts: this.regions ? Object.fromEntries(this.regions.map((t54) => [t54.name, t54.rows * t54.cols])) : {}, obstacleTraceBlockedCells: this.obstacleTraceBlockedCellCount, obstacleViaBlockedCells: this.obstacleViaBlockedCellCount, obstacleRootCount: this.obstacleRootNames?.length ?? 0, obstacleRectCount: this.obstacleRectPrimitives?.length ?? 0 };
}
constructor(t54) {
super(), this.nodeWithPortPoints = t54.nodeWithPortPoints, this.obstacles = t54.obstacles, this.highResolutionCellSize = t54.highResolutionCellSize ?? 0.1, this.highResolutionCellThickness = Math.max(1, Math.floor(t54.highResolutionCellThickness ?? 8)), this.lowResolutionCellSize = t54.lowResolutionCellSize ?? 0.4, this.viaDiameter = t54.viaDiameter, this.maxCellCount = t54.maxCellCount, this.traceThickness = t54.traceThickness ?? 0.1, this.traceMargin = t54.traceMargin ?? 0.15, this.obstacleClearanceMargin = t54.obstacleClearanceMargin ?? 0, this.viaMinDistFromBorder = t54.viaMinDistFromBorder ?? 0.15, this.showPenaltyMap = t54.showPenaltyMap ?? false, this.showUsedCellMap = t54.showUsedCellMap ?? false, this.effort = t54.effort ?? 1, this.stepMultiplier = Math.max(1, Math.floor(t54.stepMultiplier ?? 1)), this.hyperParameters = { shuffleSeed: 0, ripCost: 8, ripTracePenalty: 0.5, ripViaPenalty: 0.75, viaBaseCost: 0.1, greedyMultiplier: 1.5, sameRootObstacleCostMultiplier: 1, ...t54.hyperParameters }, this.MAX_ITERATIONS = 1e8, this.MAX_RIPS = 200, this.initialPenaltyFn = t54.initialPenaltyFn;
}
getConstructorParams() {
return [{ nodeWithPortPoints: this.nodeWithPortPoints, obstacles: this.obstacles, highResolutionCellSize: this.highResolutionCellSize, highResolutionCellThickness: this.highResolutionCellThickness, lowResolutionCellSize: this.lowResolutionCellSize, viaDiameter: this.viaDiameter, maxCellCount: this.maxCellCount, stepMultiplier: this.stepMultiplier, traceThickness: this.traceThickness, traceMargin: this.traceMargin, obstacleClearanceMargin: this.obstacleClearanceMargin, viaMinDistFromBorder: this.viaMinDistFromBorder, showPenaltyMap: this.showPenaltyMap, showUsedCellMap: this.showUsedCellMap, effort: this.effort, hyperParameters: this.hyperParameters, initialPenaltyFn: this.initialPenaltyFn }];
}
_setup() {
const { nodeWithPortPoints: t54 } = this, { width: e7, height: n7, center: o7 } = t54;
if (e7 > 15 || n7 > 15)
return this.error = `HighDensitySolverB01 only supports routing windows up to 15x15mm; received ${e7}x${n7}mm`, void (this.failed = true);
const i7 = this.lowResolutionCellSize / this.highResolutionCellSize, r7 = Math.round(i7);
if (!Number.isFinite(i7) || i7 <= 0 || Math.abs(i7 - r7) > 0.000000001)
return this.error = "lowResolutionCellSize must be a positive integer multiple of highResolutionCellSize", void (this.failed = true);
this.lowScale = Math.max(1, r7), this.availableZ = t54.availableZ ?? [...new Set(t54.portPoints.map((t55) => t55.z))].sort((t55, e8) => t55 - e8), this.layers = this.availableZ.length, this.zToLayer = new Map, this.layerToZ = new Map;
for (let t55 = 0;t55 < this.availableZ.length; t55++) {
const e8 = this.availableZ[t55];
this.zToLayer.set(e8, t55), this.layerToZ.set(t55, e8);
}
this.boundsMinX = o7.x - e7 / 2, this.boundsMaxX = o7.x + e7 / 2, this.boundsMinY = o7.y - n7 / 2, this.boundsMaxY = o7.y + n7 / 2, this.traceKeepoutRadius = this.traceMargin + this.traceThickness / 2, this.viaKeepoutRadius = this.viaDiameter / 2 + this.traceKeepoutRadius, this.buildFiveRegionGrid(e7, n7), this.gridToBoundsTransform = this.computeGridToBoundsTransform();
const s7 = this.layers * this.planeSize;
if (this.maxCellCount !== undefined && s7 > this.maxCellCount)
return this.error = `Cell count ${s7} exceeds maxCellCount ${this.maxCellCount}`, void (this.failed = true);
this.connNameToId = new Map, this.connIdToName = [], this.connIdToRootNet = [], this.overlapFriendlyRootNets = new Set, this.unsolvedSegs = this.buildConnectionSegs(), this.penalty2d = new Float64Array(this.planeSize);
const a6 = e7 > 0 ? 1 / e7 : 0, c6 = n7 > 0 ? 1 / n7 : 0;
for (let t55 = 0;t55 < this.planeSize; t55++) {
let e8 = 0;
this.initialPenaltyFn && (e8 += this.initialPenaltyFn({ x: this.cellCenterX[t55], y: this.cellCenterY[t55], px: (this.cellCenterX[t55] - this.boundsMinX) * a6, py: (this.cellCenterY[t55] - this.boundsMinY) * c6, cellId: t55, region: Y9[this.cellRegion[t55]], row: this.cellRow[t55], col: this.cellCol[t55] })), this.penalty2d[t55] = e8;
}
this.usedCellsFlat = new Int32Array(s7).fill(-1), this.sharedCellsFlat = Array.from({ length: s7 }, () => {}), this.portOwnerFlat = new Int32Array(s7).fill(-1), this.sharedCrossRootPortFlat = new Uint8Array(s7), this.obstacleTraceRootIdsFlat = Array.from({ length: s7 }, () => {}), this.obstacleViaRootIdsByCell = Array.from({ length: this.planeSize }, () => {}), this.obstacleRootNameToId = new Map, this.obstacleRootNames = [], this.obstacleTracePrimitives = [], this.obstacleViaPrimitives = [], this.obstacleRectPrimitives = [];
const l6 = this.rasterizeObstacles();
if (l6)
return this.error = l6, void (this.failed = true);
this.ripStateBuckets = 1;
const h6 = s7;
this.visitedStamp = new Uint32Array(h6), this.bestGStamp = new Uint32Array(h6), this.bestGValue = new Float64Array(h6), this.visitedFlatStamp = new Uint32Array(s7), this.stamp = 0;
const d6 = new Map;
for (const t55 of this.nodeWithPortPoints.portPoints) {
const e8 = this.connNameToId.get(t55.connectionName);
if (e8 === undefined)
continue;
const n8 = this.pointToCell(t55), o8 = n8.z * this.planeSize + n8.cellId, i8 = this.connIdToRootNet[e8], r8 = d6.get(o8);
r8 === undefined ? d6.set(o8, i8) : r8 !== i8 && (this.sharedCrossRootPortFlat[o8] = 1);
const s8 = this.portOwnerFlat[o8];
this.portOwnerFlat[o8] = s8 === -1 || s8 === e8 ? e8 : -2;
}
this.solvedRoutes = [], this.usedIndicesByConn = [], this.ripCount = [], this.consecutiveSkips = 0, this.penaltyCap = 0.5 * this.hyperParameters.ripCost, this.shuffleConnections();
const u6 = function(t55) {
const e8 = t55.planeSize * t55.layers, n8 = t55.connectionCount, o8 = Math.sqrt(n8), i8 = Math.max(1, t55.maxIterations), r8 = $9(Math.round(e8 * (8 + 1.2 * o8)), 150000, 12000000), s8 = $9(Math.round(r8 * t55.effort), 150000, 12000000), a7 = $9(Math.round(0.2 * i8), 150000, 2000000);
return { maxIterationsIters: Math.max(1, Math.min(i8, Math.max(a7, s8))), baseSearchBudgetIters: $9(Math.round(e8 * (10 + 0.8 * o8) * t55.effort), 50000, 4000000) };
}({ planeSize: this.planeSize, layers: this.layers, connectionCount: this.unsolvedSegs.length, effort: this.effort, maxIterations: this.MAX_ITERATIONS });
this.baseSearchBudgetIters = u6.baseSearchBudgetIters, this.MAX_ITERATIONS = u6.maxIterationsIters, this.activeConnSeg = null, this.activeConnId = -1, this.nodePool = new W9, this.heap = new X9, this.ripChain = new V9, this.seqCounter = 0;
}
_step() {
for (let t54 = 0;t54 < this.stepMultiplier; t54++) {
if (this.solved || this.failed)
return;
this.stepOnce();
}
}
rasterizeObstacles() {
for (let t54 = 0;t54 < this.obstacles.length; t54++) {
const e7 = this.obstacles[t54];
if (e7.type === "rect") {
const n8 = this.rasterizeRectObstacle(e7, t54);
if (n8)
return n8;
continue;
}
if (e7.traceThickness <= 0 || e7.viaDiameter <= 0 || e7.route.length < 2)
return `Obstacle ${t54} must have positive trace/via sizes and at least two route points`;
const n7 = H9(e7.connectionName, e7.rootConnectionName), o7 = this.internObstacleRootName(n7);
for (let n8 = 1;n8 < e7.route.length; n8++) {
const i7 = e7.route[n8 - 1], r7 = e7.route[n8];
if (!(Number.isFinite(i7.x) && Number.isFinite(i7.y) && Number.isFinite(i7.z) && Number.isFinite(r7.x) && Number.isFinite(r7.y) && Number.isFinite(r7.z)))
return `Obstacle ${t54} contains non-finite route coordinates`;
if (i7.z === r7.z) {
const n10 = this.zToLayer.get(i7.z);
if (n10 === undefined)
return `Obstacle ${t54} uses unavailable layer z=${i7.z}`;
this.rasterizeObstacleTraceSegment({ segmentStart: i7, segmentEnd: r7, layer: n10, obstacleRootId: o7, obstacleTraceThickness: e7.traceThickness });
} else if (!e7.vias.some((t55) => t55.x === r7.x && t55.y === r7.y)) {
const n10 = this.rasterizeObstacleVia({ center: r7, obstacleRootId: o7, obstacleViaDiameter: e7.viaDiameter, zStart: i7.z, zEnd: r7.z, obstacleIndex: t54 });
if (n10)
return n10;
}
}
for (const n8 of e7.vias) {
if (!Number.isFinite(n8.x) || !Number.isFinite(n8.y))
return `Obstacle ${t54} contains non-finite via coordinates`;
const i7 = this.rasterizeObstacleVia({ center: n8, obstacleRootId: o7, obstacleViaDiameter: e7.viaDiameter, zStart: n8.zStart, zEnd: n8.zEnd, obstacleIndex: t54 });
if (i7)
return i7;
}
}
return this.obstacleTraceBlockedCellCount = this.obstacleTraceRootIdsFlat.reduce((t54, e7) => t54 + (e7 ? 1 : 0), 0), this.obstacleViaBlockedCellCount = this.obstacleViaRootIdsByCell.reduce((t54, e7) => t54 + (e7 ? 1 : 0), 0), null;
}
rasterizeRectObstacle(t54, e7) {
if (!Number.isFinite(t54.center.x) || !Number.isFinite(t54.center.y) || !Number.isFinite(t54.width) || !Number.isFinite(t54.height) || t54.width <= 0 || t54.height <= 0)
return `Rect obstacle ${e7} must have finite geometry and positive dimensions`;
const n7 = [];
for (const o8 of t54.zLayers) {
const t55 = this.zToLayer.get(o8);
if (t55 === undefined)
return `Rect obstacle ${e7} uses unavailable layer z=${o8}`;
q9(n7, t55);
}
if (n7.length === 0)
return `Rect obstacle ${e7} must apply to at least one layer`;
const o7 = this.internObstacleRootName(H9(t54.connectionName, t54.rootConnectionName)), i7 = { rootId: o7, center: t54.center, width: t54.width, height: t54.height, rotationRadians: (t54.ccwRotationDegrees ?? 0) * Math.PI / 180, layers: n7 };
this.obstacleRectPrimitives.push(i7);
const r7 = this.transformBoundsPointToGrid(t54.center), s7 = Math.hypot(t54.width / 2, t54.height / 2), a6 = this.getConservativeGridRadius(s7 + this.traceThickness / 2 + this.traceMargin);
this.forEachCellNearCircle(r7.x, r7.y, a6, (t55) => {
for (const e8 of n7)
this.addObstacleRootId({ rootIdsByCell: this.obstacleTraceRootIdsFlat, cellIndex: e8 * this.planeSize + t55, obstacleRootId: o7 });
});
const c6 = this.getConservativeGridRadius(s7 + this.viaDiameter / 2 + this.traceMargin);
return this.forEachCellNearCircle(r7.x, r7.y, c6, (t55) => {
this.addObstacleRootId({ rootIdsByCell: this.obstacleViaRootIdsByCell, cellIndex: t55, obstacleRootId: o7 });
}), null;
}
internObstacleRootName(t54) {
const e7 = this.obstacleRootNameToId.get(t54);
if (e7 !== undefined)
return e7;
const n7 = this.obstacleRootNames.length;
return this.obstacleRootNames.push(t54), this.obstacleRootNameToId.set(t54, n7), n7;
}
rasterizeObstacleTraceSegment(t54) {
this.obstacleTracePrimitives.push({ rootId: t54.obstacleRootId, layer: t54.layer, segmentStart: t54.segmentStart, segmentEnd: t54.segmentEnd, traceRadius: t54.obstacleTraceThickness / 2 });
const e7 = this.transformBoundsPointToGrid(t54.segmentStart), n7 = this.transformBoundsPointToGrid(t54.segmentEnd), o7 = this.getConservativeGridRadius(t54.obstacleTraceThickness / 2 + this.traceMargin), i7 = this.getConservativeGridRadius(t54.obstacleTraceThickness / 2 + this.viaDiameter / 2 + this.traceMargin);
this.forEachCellNearSegment({ segmentStart: e7, segmentEnd: n7, radius: o7 }, (e8) => {
this.addObstacleRootId({ rootIdsByCell: this.obstacleTraceRootIdsFlat, cellIndex: t54.layer * this.planeSize + e8, obstacleRootId: t54.obstacleRootId });
}), this.forEachCellNearSegment({ segmentStart: e7, segmentEnd: n7, radius: i7 }, (e8) => {
this.addObstacleRootId({ rootIdsByCell: this.obstacleViaRootIdsByCell, cellIndex: e8, obstacleRootId: t54.obstacleRootId });
});
}
rasterizeObstacleVia(t54) {
if (t54.zStart === undefined != (t54.zEnd === undefined))
return `Obstacle ${t54.obstacleIndex} via must provide both zStart and zEnd`;
let e7 = Array.from({ length: this.layers }, (t55, e8) => e8);
if (t54.zStart !== undefined && t54.zEnd !== undefined) {
if (!Number.isFinite(t54.zStart) || !Number.isFinite(t54.zEnd))
return `Obstacle ${t54.obstacleIndex} contains a non-finite via layer span`;
const n8 = Math.min(t54.zStart, t54.zEnd), o8 = Math.max(t54.zStart, t54.zEnd);
e7 = this.availableZ.flatMap((t55, e8) => t55 >= n8 && t55 <= o8 ? [e8] : []);
}
if (e7.length === 0)
return null;
this.obstacleViaPrimitives.push({ rootId: t54.obstacleRootId, center: t54.center, viaRadius: t54.obstacleViaDiameter / 2, layers: e7 });
const n7 = this.transformBoundsPointToGrid(t54.center), o7 = this.getConservativeGridRadius(t54.obstacleViaDiameter / 2 + this.traceThickness / 2 + this.traceMargin), i7 = this.getConservativeGridRadius(t54.obstacleViaDiameter / 2 + this.viaDiameter / 2 + this.traceMargin);
return this.forEachCellNearCircle(n7.x, n7.y, Math.max(o7, i7), (r7) => {
const s7 = this.getCellRect(r7);
if (Q9(n7.x, n7.y, o7, s7.minX, s7.minY, s7.maxX, s7.maxY))
for (const n8 of e7)
this.addObstacleRootId({ rootIdsByCell: this.obstacleTraceRootIdsFlat, cellIndex: n8 * this.planeSize + r7, obstacleRootId: t54.obstacleRootId });
Q9(n7.x, n7.y, i7, s7.minX, s7.minY, s7.maxX, s7.maxY) && this.addObstacleRootId({ rootIdsByCell: this.obstacleViaRootIdsByCell, cellIndex: r7, obstacleRootId: t54.obstacleRootId });
}), null;
}
forEachCellNearSegment(t54, e7) {
const n7 = { x: (t54.segmentStart.x + t54.segmentEnd.x) / 2, y: (t54.segmentStart.y + t54.segmentEnd.y) / 2 }, o7 = Math.hypot(t54.segmentEnd.x - t54.segmentStart.x, t54.segmentEnd.y - t54.segmentStart.y) / 2 + t54.radius;
this.forEachCellNearCircle(n7.x, n7.y, o7, (n8) => {
r6({ segmentStart: t54.segmentStart, segmentEnd: t54.segmentEnd, radius: t54.radius, rect: this.getCellRect(n8) }) && e7(n8);
});
}
getCellRect(t54) {
return { minX: this.cellMinX[t54], minY: this.cellMinY[t54], maxX: this.cellMaxX[t54], maxY: this.cellMaxY[t54] };
}
transformBoundsPointToGrid(t54) {
const e7 = this.gridToBoundsTransform;
return { x: (t54.x - e7.c) / e7.a, y: (t54.y - e7.f) / e7.e };
}
getConservativeGridRadius(t54) {
return t54 / Math.min(Math.abs(this.gridToBoundsTransform.a), Math.abs(this.gridToBoundsTransform.e));
}
addObstacleRootId(t54) {
let e7 = t54.rootIdsByCell[t54.cellIndex];
e7 || (e7 = [], t54.rootIdsByCell[t54.cellIndex] = e7), q9(e7, t54.obstacleRootId);
}
isBlockedByObstacleRoots(t54, e7) {
if (!t54)
return false;
const n7 = this.connIdToRootNet[e7];
for (const e8 of t54)
if (this.obstacleRootNames[e8] !== n7)
return true;
return false;
}
hasSameRootObstacle(t54, e7) {
if (!t54)
return false;
const n7 = this.connIdToRootNet[e7];
return t54.some((t55) => this.obstacleRootNames[t55] === n7);
}
isLateralMoveBlockedByObstacleGeometry(t54) {
const e7 = this.connIdToRootNet[t54.activeConn], n7 = this.activeConnSeg, o7 = n7 && t54.layer === n7.startZ && t54.fromCellId === n7.startCellId ? n7.startPoint : D9(this.gridToBoundsTransform, { x: this.cellCenterX[t54.fromCellId], y: this.cellCenterY[t54.fromCellId] }), i7 = n7 && t54.layer === n7.endZ && t54.toCellId === n7.endCellId ? n7.endPoint : D9(this.gridToBoundsTransform, { x: this.cellCenterX[t54.toCellId], y: this.cellCenterY[t54.toCellId] });
for (const n8 of this.obstacleTracePrimitives) {
if (n8.layer !== t54.layer || this.obstacleRootNames[n8.rootId] === e7)
continue;
const r7 = n8.traceRadius + this.traceThickness / 2 + this.obstacleClearanceMargin;
if (i6({ firstStart: o7, firstEnd: i7, secondStart: n8.segmentStart, secondEnd: n8.segmentEnd }) < r7 * r7)
return true;
}
for (const n8 of this.obstacleViaPrimitives) {
if (!n8.layers.includes(t54.layer) || this.obstacleRootNames[n8.rootId] === e7)
continue;
const r7 = n8.viaRadius + this.traceThickness / 2 + this.obstacleClearanceMargin;
if (K9({ point: n8.center, segmentStart: o7, segmentEnd: i7 }) < r7 * r7)
return true;
}
for (const n8 of this.obstacleRectPrimitives)
if (n8.layers.includes(t54.layer) && this.obstacleRootNames[n8.rootId] !== e7 && r6({ segmentStart: G9(o7, n8), segmentEnd: G9(i7, n8), radius: this.traceThickness / 2 + this.obstacleClearanceMargin, rect: U9(n8) }))
return true;
return false;
}
isViaMoveBlockedByObstacleGeometry(t54) {
const e7 = this.connIdToRootNet[t54.activeConn], n7 = D9(this.gridToBoundsTransform, { x: this.cellCenterX[t54.cellId], y: this.cellCenterY[t54.cellId] });
for (const t55 of this.obstacleTracePrimitives) {
if (this.obstacleRootNames[t55.rootId] === e7)
continue;
const o7 = t55.traceRadius + this.viaDiameter / 2 + this.obstacleClearanceMargin;
if (K9({ point: n7, segmentStart: t55.segmentStart, segmentEnd: t55.segmentEnd }) < o7 * o7)
return true;
}
for (const t55 of this.obstacleViaPrimitives) {
if (this.obstacleRootNames[t55.rootId] === e7)
continue;
const o7 = t55.viaRadius + this.viaDiameter / 2 + this.obstacleClearanceMargin;
if ((n7.x - t55.center.x) ** 2 + (n7.y - t55.center.y) ** 2 < o7 * o7)
return true;
}
for (const t55 of this.obstacleRectPrimitives) {
if (this.obstacleRootNames[t55.rootId] === e7)
continue;
const o7 = G9(n7, t55), i7 = this.viaDiameter / 2 + this.obstacleClearanceMargin;
if (t62({ point: o7, rect: U9(t55) }) < i7 * i7)
return true;
}
return false;
}
buildFiveRegionGrid(t54, e7) {
this.fineCols = Math.max(1, Math.ceil(t54 / this.highResolutionCellSize)), this.fineRows = Math.max(1, Math.ceil(e7 / this.highResolutionCellSize)), this.bandCols = Math.min(this.highResolutionCellThickness, Math.floor(this.fineCols / 2)), this.bandRows = Math.min(this.highResolutionCellThickness, Math.floor(this.fineRows / 2));
const n7 = Math.max(0, this.fineCols - 2 * this.bandCols), o7 = Math.max(0, this.fineRows - 2 * this.bandRows), i7 = n7, r7 = n7;
this.regions = [{ id: 0, name: "left", fineOriginRow: 0, fineOriginCol: 0, fineRows: this.fineRows, fineCols: this.bandCols, cellScale: 1, rows: this.fineRows, cols: this.bandCols, offset: 0 }, { id: 1, name: "top", fineOriginRow: 0, fineOriginCol: this.bandCols, fineRows: this.bandRows, fineCols: i7, cellScale: 1, rows: this.bandRows, cols: i7, offset: 0 }, { id: 2, name: "right", fineOriginRow: 0, fineOriginCol: this.fineCols - this.bandCols, fineRows: this.fineRows, fineCols: this.bandCols, cellScale: 1, rows: this.fineRows, cols: this.bandCols, offset: 0 }, { id: 3, name: "bottom", fineOriginRow: this.fineRows - this.bandRows, fineOriginCol: this.bandCols, fineRows: this.bandRows, fineCols: r7, cellScale: 1, rows: this.bandRows, cols: r7, offset: 0 }, { id: 4, name: "middle", fineOriginRow: this.bandRows, fineOriginCol: this.bandCols, fineRows: o7, fineCols: n7, cellScale: this.lowScale, rows: o7 > 0 ? Math.ceil(o7 / this.lowScale) : 0, cols: n7 > 0 ? Math.ceil(n7 / this.lowScale) : 0, offset: 0 }];
let s7 = 0;
for (let t55 = 0;t55 < this.regions.length; t55++)
this.regions[t55].offset = s7, s7 += this.regions[t55].rows * this.regions[t55].cols;
this.planeSize = s7, this.cellCenterX = new Float64Array(this.planeSize), this.cellCenterY = new Float64Array(this.planeSize), this.cellMinX = new Float64Array(this.planeSize), this.cellMinY = new Float64Array(this.planeSize), this.cellMaxX = new Float64Array(this.planeSize), this.cellMaxY = new Float64Array(this.planeSize), this.cellWidth = new Float64Array(this.planeSize), this.cellHeight = new Float64Array(this.planeSize), this.cellRegion = new Uint8Array(this.planeSize), this.cellRow = new Int32Array(this.planeSize), this.cellCol = new Int32Array(this.planeSize), this.viaAllowed = new Uint8Array(this.planeSize);
for (let t55 = 0;t55 < this.regions.length; t55++) {
const e8 = this.regions[t55];
for (let t56 = 0;t56 < e8.rows; t56++) {
const n8 = e8.fineOriginRow + t56 * e8.cellScale, o8 = Math.min(e8.fineOriginRow + e8.fineRows, n8 + e8.cellScale), i8 = this.boundsMinY + n8 * this.highResolutionCellSize, r8 = Math.min(this.boundsMaxY, this.boundsMinY + o8 * this.highResolutionCellSize);
for (let n10 = 0;n10 < e8.cols; n10++) {
const o10 = e8.fineOriginCol + n10 * e8.cellScale, s8 = Math.min(e8.fineOriginCol + e8.fineCols, o10 + e8.cellScale), a7 = this.boundsMinX + o10 * this.highResolutionCellSize, c7 = Math.min(this.boundsMaxX, this.boundsMinX + s8 * this.highResolutionCellSize), l7 = this.cellIdFor(e8.id, t56, n10);
this.cellCenterX[l7] = (a7 + c7) / 2, this.cellCenterY[l7] = (i8 + r8) / 2, this.cellMinX[l7] = a7, this.cellMinY[l7] = i8, this.cellMaxX[l7] = c7, this.cellMaxY[l7] = r8, this.cellWidth[l7] = c7 - a7, this.cellHeight[l7] = r8 - i8, this.cellRegion[l7] = e8.id, this.cellRow[l7] = t56, this.cellCol[l7] = n10;
const h7 = Math.min(this.cellCenterX[l7] - this.boundsMinX, this.boundsMaxX - this.cellCenterX[l7], this.cellCenterY[l7] - this.boundsMinY, this.boundsMaxY - this.cellCenterY[l7]);
this.viaAllowed[l7] = h7 >= this.viaMinDistFromBorder ? 1 : 0;
}
}
}
const a6 = Array.from({ length: this.planeSize }, () => []), c6 = (t55, e8) => {
if (t55 === e8 || t55 < 0 || e8 < 0)
return;
const n8 = this.cellCenterX[t55] - this.cellCenterX[e8], o8 = this.cellCenterY[t55] - this.cellCenterY[e8], i8 = Math.hypot(n8, o8);
J9(a6[t55], { cellId: e8, cost: i8 }), J9(a6[e8], { cellId: t55, cost: i8 });
};
for (let t55 = 0;t55 < this.regions.length; t55++) {
const e8 = this.regions[t55];
for (let t56 = 0;t56 < e8.rows; t56++)
for (let n8 = 0;n8 < e8.cols; n8++) {
const o8 = this.cellIdFor(e8.id, t56, n8);
t56 + 1 < e8.rows && c6(o8, this.cellIdFor(e8.id, t56 + 1, n8)), n8 + 1 < e8.cols && c6(o8, this.cellIdFor(e8.id, t56, n8 + 1));
}
}
const l6 = this.regions[0], h6 = this.regions[1], d6 = this.regions[2], u6 = this.regions[3], p6 = this.regions[4], m6 = l6.rows > 0 && l6.cols > 0, g6 = h6.rows > 0 && h6.cols > 0, f6 = d6.rows > 0 && d6.cols > 0, y6 = u6.rows > 0 && u6.cols > 0, _6 = p6.rows > 0 && p6.cols > 0;
if (m6 && g6)
for (let t55 = 0;t55 < this.bandRows; t55++)
c6(this.cellIdFor(0, t55, l6.cols - 1), this.cellIdFor(1, t55, 0));
if (g6 && f6)
for (let t55 = 0;t55 < this.bandRows; t55++)
c6(this.cellIdFor(1, t55, h6.cols - 1), this.cellIdFor(2, t55, 0));
if (m6 && y6)
for (let t55 = this.fineRows - this.bandRows;t55 < this.fineRows; t55++)
c6(this.cellIdFor(0, t55, l6.cols - 1), this.cellIdFor(3, t55 - (this.fineRows - this.bandRows), 0));
if (y6 && f6)
for (let t55 = this.fineRows - this.bandRows;t55 < this.fineRows; t55++)
c6(this.cellIdFor(3, t55 - (this.fineRows - this.bandRows), u6.cols - 1), this.cellIdFor(2, t55, 0));
if (m6 && _6)
for (let t55 = this.bandRows;t55 < this.fineRows - this.bandRows; t55++)
c6(this.cellIdFor(0, t55, l6.cols - 1), this.cellIdFor(4, Math.floor((t55 - this.bandRows) / this.lowScale), 0));
if (f6 && _6)
for (let t55 = this.bandRows;t55 < this.fineRows - this.bandRows; t55++)
c6(this.cellIdFor(4, Math.floor((t55 - this.bandRows) / this.lowScale), p6.cols - 1), this.cellIdFor(2, t55, 0));
if (g6 && _6)
for (let t55 = this.bandCols;t55 < this.fineCols - this.bandCols; t55++)
c6(this.cellIdFor(1, h6.rows - 1, t55 - this.bandCols), this.cellIdFor(4, 0, Math.floor((t55 - this.bandCols) / this.lowScale)));
if (y6 && _6)
for (let t55 = this.bandCols;t55 < this.fineCols - this.bandCols; t55++)
c6(this.cellIdFor(4, p6.rows - 1, Math.floor((t55 - this.bandCols) / this.lowScale)), this.cellIdFor(3, 0, t55 - this.bandCols));
if (!_6 && !g6 && !y6 && m6 && f6)
for (let t55 = 0;t55 < Math.min(l6.rows, d6.rows); t55++)
c6(this.cellIdFor(0, t55, l6.cols - 1), this.cellIdFor(2, t55, 0));
if (!_6 && !m6 && !f6 && g6 && y6)
for (let t55 = 0;t55 < Math.min(h6.cols, u6.cols); t55++)
c6(this.cellIdFor(1, h6.rows - 1, t55), this.cellIdFor(3, 0, t55));
const b6 = this.flattenNeighborLists(a6);
this.neighborOffset = b6.offset, this.neighborIds = b6.ids, this.neighborCosts = b6.costs;
}
cellIdFor(t54, e7, n7) {
const o7 = this.regions[t54];
return o7.offset + e7 * o7.cols + n7;
}
stepOnce() {
if (!this.activeConnSeg) {
if (this.unsolvedSegs.length === 0)
return void (this.solved = true);
const t55 = this.unsolvedSegs.shift();
this.activeConnSeg = t55, this.activeConnId = t55.connId, this.nodePool.clear(), this.ripChain.clear(), this.heap.clear(), this.seqCounter = 0, this.searchIterations = 0, this.nextStamp();
const e8 = this.computeH(t55.startZ, t55.startCellId, t55.endZ, t55.endCellId) * this.hyperParameters.greedyMultiplier, n8 = this.nodePool.push(t55.startZ, t55.startCellId, 0, -1, -1, 0), o8 = t55.startZ * this.planeSize + t55.startCellId, i8 = this.getSearchStateIdx(o8, 0);
return this.bestGStamp[i8] = this.stamp, this.bestGValue[i8] = 0, void this.heap.push(e8, this.seqCounter++, n8);
}
this.searchIterations++;
const t54 = this.ripCount[this.activeConnId] ?? 0, e7 = Math.round(this.baseSearchBudgetIters * (1 + 0.25 * Math.min(t54, 10)));
if (this.searchIterations > e7) {
const t55 = this.penalty2d;
for (let e8 = 0;e8 < t55.length; e8++)
t55[e8] = 0.9 * t55[e8];
return this.unsolvedSegs.push(this.activeConnSeg), this.activeConnSeg = null, this.activeConnId = -1, this.heap.clear(), this.nodePool.clear(), this.consecutiveSkips++, void (this.consecutiveSkips >= Math.max(3, 3 * this.unsolvedSegs.length) && (this.error = `Convergence failure: ${this.unsolvedSegs.length} connections stuck`, this.failed = true));
}
if (this.heap.size === 0)
return this.error = `No path found for ${this.connIdToName[this.activeConnId]}`, void (this.failed = true);
const n7 = this.heap.pop(), o7 = this.nodePool.z[n7], i7 = this.nodePool.cellId[n7], r7 = this.nodePool.g[n7], s7 = this.nodePool.ripHead[n7], a6 = this.nodePool.ripCount[n7], c6 = o7 * this.planeSize + i7, l6 = this.getSearchStateIdx(c6, a6);
if (this.visitedStamp[l6] === this.stamp)
return;
this.visitedStamp[l6] = this.stamp, this.visitedFlatStamp[c6] = this.stamp;
const h6 = this.activeConnSeg;
if (o7 === h6.endZ && i7 === h6.endCellId)
return this.finalizeRoute(n7), this.activeConnSeg = null, void (this.activeConnId = -1);
const d6 = this.visitedStamp, u6 = this.stamp, p6 = this.activeConnId, m6 = h6.endZ, g6 = h6.endCellId, f6 = this.neighborOffset[i7], y6 = this.neighborOffset[i7 + 1];
for (let t55 = f6;t55 < y6; t55++) {
const e8 = this.neighborIds[t55], c7 = o7 * this.planeSize + e8;
if (this.computeMoveCostAndRips(p6, o7, i7, e8, false, s7, a6, this.neighborCosts[t55]), this._moveCost < 0)
continue;
const l7 = this.getSearchStateIdx(c7, this._moveRipCount);
if (d6[l7] === u6)
continue;
const h7 = r7 + this._moveCost;
if (this.bestGStamp[l7] === u6 && h7 >= this.bestGValue[l7])
continue;
this.bestGStamp[l7] = u6, this.bestGValue[l7] = h7;
const f7 = h7 + this.computeH(o7, e8, m6, g6) * this.hyperParameters.greedyMultiplier, y7 = this.nodePool.push(o7, e8, h7, n7, this._moveRippedHead, this._moveRipCount);
this.heap.push(f7, this.seqCounter++, y7);
}
if (this.viaAllowed[i7])
for (let t55 = 0;t55 < this.layers; t55++) {
if (t55 === o7)
continue;
const e8 = t55 * this.planeSize + i7;
if (this.computeMoveCostAndRips(p6, t55, i7, i7, true, s7, a6, 0), this._moveCost < 0)
continue;
const c7 = this.getSearchStateIdx(e8, this._moveRipCount);
if (d6[c7] === u6)
continue;
const l7 = r7 + this._moveCost;
if (this.bestGStamp[c7] === u6 && l7 >= this.bestGValue[c7])
continue;
this.bestGStamp[c7] = u6, this.bestGValue[c7] = l7;
const h7 = l7 + this.computeH(t55, i7, m6, g6) * this.hyperParameters.greedyMultiplier, f7 = this.nodePool.push(t55, i7, l7, n7, this._moveRippedHead, this._moveRipCount);
this.heap.push(h7, this.seqCounter++, f7);
}
}
computeMoveCostAndRips(t54, e7, n7, o7, i7, r7, s7, a6) {
let c6 = 0, l6 = r7, h6 = s7;
const d6 = e7 * this.planeSize + o7, u6 = i7 ? this.obstacleViaRootIdsByCell[o7] : [...this.obstacleTraceRootIdsFlat[e7 * this.planeSize + n7] ?? [], ...this.obstacleTraceRootIdsFlat[d6] ?? []];
if (this.isBlockedByObstacleRoots(u6, t54) && (i7 ? this.isViaMoveBlockedByObstacleGeometry({ activeConn: t54, cellId: o7 }) : this.isLateralMoveBlockedByObstacleGeometry({ activeConn: t54, layer: e7, fromCellId: n7, toCellId: o7 })))
return this._moveCost = -1, this._moveRippedHead = l6, void (this._moveRipCount = h6);
const p6 = this.hasSameRootObstacle(u6, t54);
if (i7) {
c6 += this.hyperParameters.viaBaseCost, c6 += Math.min(this.penalty2d[o7], this.penaltyCap);
const n8 = this.portOwnerFlat[d6], i8 = this.allowSharedUse(t54, n8), r8 = this.activeConnSeg, s8 = !!r8 && e7 === r8.endZ && o7 === r8.endCellId;
if (n8 >= 0 && n8 !== t54 && !i8 && !s8)
return this._moveCost = -1, void (this._moveRippedHead = l6);
this.fillViaOccupants(o7, t54);
const a7 = this._viaOccs;
for (let t55 = 0;t55 < a7.length; t55++) {
const e8 = a7[t55];
this.ripChain.contains(l6, e8) || (c6 += this.hyperParameters.ripCost, l6 = this.ripChain.append(l6, e8), h6++), c6 += this.hyperParameters.ripViaPenalty;
}
} else {
c6 += a6, c6 += Math.min(this.penalty2d[o7], this.penaltyCap);
const n8 = this.portOwnerFlat[d6], i8 = this.allowSharedUse(t54, n8), r8 = this.activeConnSeg, s8 = !!r8 && e7 === r8.endZ && o7 === r8.endCellId;
if (n8 >= 0 && n8 !== t54 && !i8 && !s8)
return this._moveCost = -1, void (this._moveRippedHead = l6);
this.fillTraceOccupants(d6, t54, this._cellOccs);
for (let t55 = 0;t55 < this._cellOccs.length; t55++) {
const e8 = this._cellOccs[t55];
this.ripChain.contains(l6, e8) || (c6 += this.hyperParameters.ripCost, l6 = this.ripChain.append(l6, e8), h6++), c6 += this.hyperParameters.ripTracePenalty;
}
}
p6 && (c6 *= this.hyperParameters.sameRootObstacleCostMultiplier), this._moveCost = c6, this._moveRippedHead = l6, this._moveRipCount = h6;
}
fillViaOccupants(t54, e7) {
const n7 = this._viaOccs;
n7.length = 0;
const o7 = this.cellCenterX[t54], i7 = this.cellCenterY[t54];
this.forEachCellNearCircle(o7, i7, this.viaKeepoutRadius, (t55) => {
if (Q9(o7, i7, this.viaKeepoutRadius, this.cellMinX[t55], this.cellMinY[t55], this.cellMaxX[t55], this.cellMaxY[t55]))
for (let o8 = 0;o8 < this.layers; o8++)
this.pushFlatOccupants(o8 * this.planeSize + t55, e7, n7);
});
}
fillTraceOccupants(t54, e7, n7) {
n7.length = 0, this.pushFlatOccupants(t54, e7, n7);
}
pushFlatOccupants(t54, e7, n7) {
const o7 = this.usedCellsFlat[t54];
o7 === -1 || o7 === e7 || this.allowSharedUse(e7, o7) || q9(n7, o7);
const i7 = this.sharedCellsFlat[t54];
if (i7)
for (let t55 = 0;t55 < i7.length; t55++) {
const o8 = i7[t55];
o8 !== e7 && (this.allowSharedUse(e7, o8) || q9(n7, o8));
}
}
addSharedOccupant(t54, e7) {
if (this.usedCellsFlat[t54] === e7)
return;
let n7 = this.sharedCellsFlat[t54];
n7 || (n7 = [], this.sharedCellsFlat[t54] = n7), q9(n7, e7);
}
replaceOccupants(t54, e7) {
this.usedCellsFlat[t54] = e7, this.sharedCellsFlat[t54] = undefined;
}
removeOccupant(t54, e7) {
const n7 = this.sharedCellsFlat[t54];
if (this.usedCellsFlat[t54] === e7)
return void (n7 && n7.length > 0 ? (this.usedCellsFlat[t54] = n7.pop(), n7.length === 0 && (this.sharedCellsFlat[t54] = undefined)) : this.usedCellsFlat[t54] = -1);
if (!n7)
return;
const o7 = n7.indexOf(e7);
o7 !== -1 && (n7.splice(o7, 1), n7.length === 0 && (this.sharedCellsFlat[t54] = undefined));
}
allowSharedUse(t54, e7) {
if (e7 < 0)
return false;
return this.connIdToRootNet[e7] === this.connIdToRootNet[t54];
}
shouldSkipFixedPortHalo(t54, e7) {
const n7 = this.portOwnerFlat[t54];
return n7 !== e7 && (n7 === -2 || !(n7 < 0) && !this.allowSharedUse(e7, n7));
}
nextStamp() {
this.stamp = this.stamp + 1 >>> 0, this.stamp === 0 && (this.visitedStamp.fill(0), this.bestGStamp.fill(0), this.visitedFlatStamp.fill(0), this.stamp = 1);
}
getSearchStateIdx(t54, e7) {
return t54;
}
computeH(t54, e7, n7, o7) {
const i7 = Math.hypot(this.cellCenterX[e7] - this.cellCenterX[o7], this.cellCenterY[e7] - this.cellCenterY[o7]);
return t54 === n7 ? i7 : i7 + this.hyperParameters.viaBaseCost;
}
internConn(t54, e7) {
const n7 = this.connNameToId.get(t54);
if (n7 !== undefined)
return n7;
const o7 = this.connIdToName.length;
return this.connIdToName.push(t54), this.connIdToRootNet.push(H9(t54, e7)), this.connNameToId.set(t54, o7), o7;
}
buildConnectionSegs() {
const t54 = new Map;
for (const e8 of this.nodeWithPortPoints.portPoints) {
const n8 = e8.connectionName;
t54.has(n8) || t54.set(n8, { points: [], rootConnectionName: e8.rootConnectionName }), t54.get(n8).points.push(e8);
}
const e7 = [], n7 = new Map;
for (const [o7, i7] of t54) {
const t55 = i7.points, r7 = j9(t55);
if (r7.length === 0)
continue;
const s7 = this.internConn(o7, i7.rootConnectionName);
for (const [t56, i8] of r7) {
const r8 = this.pointToCell(t56), a6 = this.pointToCell(i8), c6 = `${r8.z}:${r8.cellId}`, l6 = `${a6.z}:${a6.cellId}`, h6 = c6 < l6 ? `${c6}|${l6}` : `${l6}|${c6}`, d6 = this.connIdToRootNet[s7], u6 = `${d6}|${h6}`, p6 = n7.get(u6);
if (p6) {
if (this.overlapFriendlyRootNets.add(d6), !p6.connectionAliases.some((t57) => t57.connectionName === o7)) {
const e8 = p6.startZ === r8.z && p6.startCellId === r8.cellId && p6.endZ === a6.z && p6.endCellId === a6.cellId, n8 = p6.startZ === a6.z && p6.startCellId === a6.cellId && p6.endZ === r8.z && p6.endCellId === r8.cellId;
if (!e8 && !n8)
throw new Error(`Connection alias ${o7} does not match canonical segment ${u6}`);
p6.connectionAliases.push({ connectionName: o7, rootConnectionName: d6, startPoint: t56, endPoint: i8, reversedFromCanonical: !e8 && n8 });
}
continue;
}
const m6 = { connId: s7, startZ: r8.z, startCellId: r8.cellId, startPoint: t56, endZ: a6.z, endCellId: a6.cellId, endPoint: i8, connectionAliases: [{ connectionName: o7, rootConnectionName: d6, startPoint: t56, endPoint: i8, reversedFromCanonical: false }] };
n7.set(u6, m6), e7.push(m6);
}
}
return e7;
}
pointToCell(t54) {
const e7 = Z9(Math.floor((t54.x - this.boundsMinX) / this.highResolutionCellSize), 0, this.fineCols - 1), n7 = Z9(Math.floor((t54.y - this.boundsMinY) / this.highResolutionCellSize), 0, this.fineRows - 1);
let o7 = 4;
e7 < this.bandCols ? o7 = 0 : e7 >= this.fineCols - this.bandCols ? o7 = 2 : n7 < this.bandRows ? o7 = 1 : n7 >= this.fineRows - this.bandRows && (o7 = 3);
const i7 = this.regions[o7], r7 = n7 - i7.fineOriginRow, s7 = e7 - i7.fineOriginCol, a6 = Z9(Math.floor(r7 / i7.cellScale), 0, Math.max(0, i7.rows - 1)), c6 = Z9(Math.floor(s7 / i7.cellScale), 0, Math.max(0, i7.cols - 1));
return { z: this.zToLayer.get(t54.z) ?? 0, cellId: this.cellIdFor(o7, a6, c6) };
}
shuffleConnections() {
const t54 = this.unsolvedSegs;
let e7 = this.hyperParameters.shuffleSeed >>> 0;
const n7 = () => (e7 = Math.imul(e7, 1664525) + 1013904223 >>> 0, e7 / 4294967295);
for (let e8 = t54.length - 1;e8 > 0; e8--) {
const o7 = Math.floor(n7() * (e8 + 1)), i7 = t54[e8];
t54[e8] = t54[o7], t54[o7] = i7;
}
}
finalizeRoute(t54) {
this.consecutiveSkips = Math.max(0, this.consecutiveSkips - 1);
const e7 = [];
let n7 = t54;
for (;n7 >= 0; ) {
const t55 = this.nodePool.z[n7], o8 = this.nodePool.cellId[n7];
e7.push(t55 * this.planeSize + o8), n7 = this.nodePool.parent[n7];
}
for (e7.reverse();e7.length > 1 && this.sharedCrossRootPortFlat[e7[0]]; )
e7.shift();
for (;e7.length > 1 && this.sharedCrossRootPortFlat[e7[e7.length - 1]]; )
e7.pop();
const o7 = this.extractViaCellIds(e7), i7 = this.activeConnId;
this.ripChain.collect(this.nodePool.ripHead[t54], this._rippedIds);
for (let t55 = 0;t55 < this._rippedIds.length; t55++)
if (this.ripTrace(this._rippedIds[t55]), this.failed)
return;
const r7 = [];
for (let t55 = 0;t55 < e7.length; t55++) {
const n8 = e7[t55], o8 = Math.floor(n8 / this.planeSize), s8 = n8 - o8 * this.planeSize;
this.markTraceFootprint(i7, o8, s8, r7);
}
const s7 = [];
for (let t55 = 0;t55 < o7.length; t55++)
this.markViaFootprint(i7, o7[t55], r7, s7);
for (;this.usedIndicesByConn.length <= i7; )
this.usedIndicesByConn.push(undefined);
const a6 = this.usedIndicesByConn[i7] ?? [];
for (a6.push(...r7), this.usedIndicesByConn[i7] = a6;this.solvedRoutes.length <= i7; )
this.solvedRoutes.push(undefined);
const c6 = this.solvedRoutes[i7] ?? [];
c6.push({ connId: i7, states: Int32Array.from(e7), viaCellIds: Int32Array.from(o7), startPoint: this.activeConnSeg.startPoint, endPoint: this.activeConnSeg.endPoint, connectionAliases: this.activeConnSeg.connectionAliases }), this.solvedRoutes[i7] = c6;
for (let t55 = 0;t55 < s7.length; t55++)
if (this.ripTrace(s7[t55]), this.failed)
return;
if (this._rippedIds.length > 0 || s7.length > 0) {
const t55 = this.penalty2d, e8 = this.penaltyCap;
if (this.totalRipEvents > 50)
for (let e10 = 0;e10 < t55.length; e10++)
t55[e10] = 0.99 * t55[e10];
else
for (let n8 = 0;n8 < t55.length; n8++)
t55[n8] > e8 && (t55[n8] = 0.5 * t55[n8]);
}
}
extractViaCellIds(t54) {
const e7 = [];
for (let n7 = 1;n7 < t54.length; n7++) {
const o7 = t54[n7 - 1], i7 = t54[n7], r7 = Math.floor(o7 / this.planeSize), s7 = Math.floor(i7 / this.planeSize);
r7 !== s7 && e7.push(i7 - s7 * this.planeSize);
}
return e7;
}
markTraceFootprint(t54, e7, n7, o7) {
const i7 = this.cellCenterX[n7], r7 = this.cellCenterY[n7];
this.forEachCellNearCircle(i7, r7, this.traceKeepoutRadius, (s7) => {
if (!Q9(i7, r7, this.traceKeepoutRadius, this.cellMinX[s7], this.cellMinY[s7], this.cellMaxX[s7], this.cellMaxY[s7]))
return;
const a6 = e7 * this.planeSize + s7;
if (s7 !== n7 && this.shouldSkipFixedPortHalo(a6, t54))
return;
const c6 = this.usedCellsFlat[a6], l6 = this.allowSharedUse(t54, c6);
(c6 === -1 || c6 === t54 || l6) && (c6 !== -1 && c6 !== t54 ? this.addSharedOccupant(a6, t54) : this.usedCellsFlat[a6] = t54, o7.push(a6));
});
}
markViaFootprint(t54, e7, n7, o7) {
const i7 = this.cellCenterX[e7], r7 = this.cellCenterY[e7];
this.forEachCellNearCircle(i7, r7, this.viaKeepoutRadius, (s7) => {
if (Q9(i7, r7, this.viaKeepoutRadius, this.cellMinX[s7], this.cellMinY[s7], this.cellMaxX[s7], this.cellMaxY[s7]))
for (let i8 = 0;i8 < this.layers; i8++) {
const r8 = i8 * this.planeSize + s7;
if (s7 !== e7 && this.shouldSkipFixedPortHalo(r8, t54))
continue;
if (this.fillTraceOccupants(r8, t54, this._cellOccs), this._cellOccs.length > 0) {
for (let t55 = 0;t55 < this._cellOccs.length; t55++)
q9(o7, this._cellOccs[t55]);
this.replaceOccupants(r8, t54), n7.push(r8);
continue;
}
const a6 = this.usedCellsFlat[r8];
a6 !== -1 && a6 !== t54 ? this.addSharedOccupant(r8, t54) : this.usedCellsFlat[r8] = t54, n7.push(r8);
}
});
}
forEachCellNearCircle(t54, e7, n7, o7) {
const i7 = Z9(Math.floor((t54 - n7 - this.boundsMinX) / this.highResolutionCellSize), 0, this.fineCols - 1), r7 = Z9(Math.floor((t54 + n7 - this.boundsMinX) / this.highResolutionCellSize), 0, this.fineCols - 1), s7 = Z9(Math.floor((e7 - n7 - this.boundsMinY) / this.highResolutionCellSize), 0, this.fineRows - 1), a6 = Z9(Math.floor((e7 + n7 - this.boundsMinY) / this.highResolutionCellSize), 0, this.fineRows - 1);
for (let t55 = 0;t55 < this.regions.length; t55++) {
const e8 = this.regions[t55];
if (e8.rows === 0 || e8.cols === 0)
continue;
const n8 = Math.max(s7, e8.fineOriginRow), c6 = Math.min(a6, e8.fineOriginRow + e8.fineRows - 1), l6 = Math.max(i7, e8.fineOriginCol), h6 = Math.min(r7, e8.fineOriginCol + e8.fineCols - 1);
if (n8 > c6)
continue;
if (l6 > h6)
continue;
const d6 = Math.floor((n8 - e8.fineOriginRow) / e8.cellScale), u6 = Math.floor((c6 - e8.fineOriginRow) / e8.cellScale), p6 = Math.floor((l6 - e8.fineOriginCol) / e8.cellScale), m6 = Math.floor((h6 - e8.fineOriginCol) / e8.cellScale);
for (let t56 = d6;t56 <= u6; t56++)
for (let n10 = p6;n10 <= m6; n10++)
o7(this.cellIdFor(e8.id, t56, n10));
}
}
ripTrace(t54) {
for (;this.ripCount.length <= t54; )
this.ripCount.push(0);
if (this.ripCount[t54]++, this.totalRipEvents++, this.totalRipEvents >= this.MAX_RIPS)
return this.error = `Convergence failure: exceeded MAX_RIPS ${this.MAX_RIPS}`, void (this.failed = true);
const e7 = this.getSolvedRoutesForConn(t54);
if (e7.length > 0)
for (const t55 of e7) {
for (let e8 = 0;e8 < t55.states.length; e8++) {
const n8 = t55.states[e8] % this.planeSize;
this.penalty2d[n8] = this.penalty2d[n8] + this.hyperParameters.ripTracePenalty;
}
for (let e8 = 0;e8 < t55.viaCellIds.length; e8++) {
const n8 = t55.viaCellIds[e8];
this.penalty2d[n8] = this.penalty2d[n8] + this.hyperParameters.ripViaPenalty;
}
}
const n7 = this.usedIndicesByConn[t54];
if (n7) {
for (let e8 = 0;e8 < n7.length; e8++)
this.removeOccupant(n7[e8], t54);
this.usedIndicesByConn[t54] = undefined;
}
if (e7.length > 0) {
this.solvedRoutes[t54] = undefined;
for (const n8 of e7) {
const e8 = n8.states[0], o7 = n8.states[n8.states.length - 1], i7 = Math.floor(e8 / this.planeSize), r7 = Math.floor(o7 / this.planeSize);
this.unsolvedSegs.push({ connId: t54, startZ: i7, startCellId: e8 - i7 * this.planeSize, startPoint: n8.startPoint, endZ: r7, endCellId: o7 - r7 * this.planeSize, endPoint: n8.endPoint, connectionAliases: n8.connectionAliases });
}
}
}
flattenNeighborLists(t54) {
const e7 = new Int32Array(t54.length + 1);
let n7 = 0;
for (let o8 = 0;o8 < t54.length; o8++)
e7[o8] = n7, n7 += t54[o8].length;
e7[t54.length] = n7;
const o7 = new Int32Array(n7), i7 = new Float32Array(n7);
let r7 = 0;
for (let e8 = 0;e8 < t54.length; e8++) {
const n8 = t54[e8];
for (let t55 = 0;t55 < n8.length; t55++) {
const e10 = n8[t55];
o7[r7] = e10.cellId, i7[r7] = e10.cost, r7++;
}
}
return { offset: e7, ids: o7, costs: i7 };
}
visualize() {
const t54 = ["red", "blue", "orange", "green"], e7 = this.gridToBoundsTransform, n7 = [], o7 = [], i7 = [], r7 = [];
r7.push({ center: { x: this.nodeWithPortPoints.center.x, y: this.nodeWithPortPoints.center.y }, width: this.nodeWithPortPoints.width, height: this.nodeWithPortPoints.height, stroke: "gray" });
const s7 = ({ route: e8, connectionName: n8, strokeWidth: i8, strokeDash: r8, labelPrefix: s8 }) => {
if (e8.length < 2)
return;
let a7 = 0;
for (let c7 = 1;c7 < e8.length; c7 += 1) {
const l6 = e8[c7 - 1];
e8[c7].z !== l6.z && (c7 - a7 >= 2 && o7.push({ points: e8.slice(a7, c7).map((t55) => ({ x: t55.x, y: t55.y })), strokeColor: t54[l6.z] ?? "rgba(128,128,128,0.75)", strokeWidth: i8, strokeDash: r8, label: `${s8} ${n8} z=${l6.z}` }), a7 = c7);
}
if (e8.length - a7 < 2)
return;
const c6 = e8[a7].z;
o7.push({ points: e8.slice(a7).map((t55) => ({ x: t55.x, y: t55.y })), strokeColor: t54[c6] ?? "rgba(128,128,128,0.75)", strokeWidth: i8, strokeDash: r8, label: `${s8} ${n8} z=${c6}` });
};
for (const t55 of this.obstacles)
if (t55.type !== "rect") {
s7({ route: t55.route, connectionName: t55.connectionName, strokeWidth: t55.traceThickness, strokeDash: [0.12, 0.08], labelPrefix: "fixed obstacle" });
for (const e8 of t55.vias)
i7.push({ center: { x: e8.x, y: e8.y }, radius: t55.viaDiameter / 2, fill: "rgba(128,0,128,0.25)", stroke: "purple", label: `fixed obstacle ${t55.connectionName} via` });
} else
r7.push({ center: t55.center, width: t55.width, height: t55.height, fill: "rgba(128,0,128,0.12)", stroke: "purple", label: `fixed obstacle ${t55.connectionName}` });
if (this.showPenaltyMap && this.penalty2d) {
let t55 = 0;
for (let e8 = 0;e8 < this.penalty2d.length; e8++)
this.penalty2d[e8] > t55 && (t55 = this.penalty2d[e8]);
if (t55 > 0)
for (let n8 = 0;n8 < this.planeSize; n8++) {
const o8 = this.penalty2d[n8];
if (o8 <= 0)
continue;
const i8 = D9(e7, { x: this.cellCenterX[n8], y: this.cellCenterY[n8] }), s8 = Math.min(0.6, o8 / t55 * 0.6);
r7.push({ center: i8, width: this.cellWidth[n8] * e7.a, height: this.cellHeight[n8] * e7.e, fill: `rgba(255,165,0,${s8.toFixed(3)})` });
}
}
if (this.showUsedCellMap && this.usedCellsFlat)
for (let t55 = 0;t55 < this.layers; t55++) {
const n8 = t55 * this.planeSize;
for (let t56 = 0;t56 < this.planeSize; t56++) {
if (this.usedCellsFlat[n8 + t56] === -1)
continue;
const o8 = D9(e7, { x: this.cellCenterX[t56], y: this.cellCenterY[t56] });
r7.push({ center: o8, width: this.cellWidth[t56] * e7.a, height: this.cellHeight[t56] * e7.e, fill: "rgba(0,0,255,0.5)" });
}
}
for (const e8 of this.nodeWithPortPoints.portPoints)
n7.push({ x: e8.x, y: e8.y, color: t54[e8.z] ?? "gray", label: e8.connectionName });
const a6 = this.getOutput();
for (const t55 of a6)
s7({ route: t55.route, connectionName: t55.connectionName, strokeWidth: this.traceThickness, labelPrefix: "B01 route" });
for (const t55 of a6)
for (const e8 of t55.vias)
i7.push({ center: { x: e8.x, y: e8.y }, radius: this.viaDiameter / 2, fill: "rgba(0,0,0,0.3)", stroke: "black", label: `B01 route ${t55.connectionName} via` });
if (this.activeConnSeg && this.visitedFlatStamp) {
const t55 = this.stamp;
for (let o8 = 0;o8 < this.layers; o8++) {
const i8 = o8 * this.planeSize;
for (let o10 = 0;o10 < this.planeSize; o10++) {
if (this.visitedFlatStamp[i8 + o10] !== t55)
continue;
const r8 = D9(e7, { x: this.cellCenterX[o10], y: this.cellCenterY[o10] });
n7.push({ x: r8.x, y: r8.y, color: "rgba(0,0,255,0.2)" });
}
}
}
return { points: n7, lines: o7, circles: i7, rects: r7, coordinateSystem: "cartesian", title: `HighDensityB01 [${this.getSolvedRouteCount()} solved, ${this.unsolvedSegs?.length ?? 0} remaining]` };
}
getOutput() {
const t54 = this.gridToBoundsTransform, e7 = [];
for (let n7 = 0;n7 < this.solvedRoutes.length; n7++) {
const o7 = this.getSolvedRoutesForConn(n7);
if (o7.length !== 0)
for (const n8 of o7) {
const o8 = Array.from(n8.states, (e8) => {
const n10 = Math.floor(e8 / this.planeSize), o10 = e8 - n10 * this.planeSize, i8 = D9(t54, { x: this.cellCenterX[o10], y: this.cellCenterY[o10] });
return { x: i8.x, y: i8.y, z: this.layerToZ.get(n10) ?? n10 };
}), i7 = Array.from(n8.viaCellIds, (e8) => D9(t54, { x: this.cellCenterX[e8], y: this.cellCenterY[e8] }));
for (const t55 of n8.connectionAliases) {
const n10 = (t55.reversedFromCanonical ? [...o8].reverse() : o8).map((t56) => ({ ...t56 }));
n10.length > 0 && (n10[0] = { ...t55.startPoint }, n10.length > 1 && (n10[n10.length - 1] = { ...t55.endPoint })), e7.push({ connectionName: t55.connectionName, rootConnectionName: t55.rootConnectionName, regionId: this.nodeWithPortPoints.capacityMeshNodeId, traceThickness: this.traceThickness, viaDiameter: this.viaDiameter, route: n10, vias: i7.map((t56) => ({ ...t56 })) });
}
}
}
return e7;
}
getSolvedRoutesForConn(t54) {
const e7 = this.solvedRoutes[t54];
return e7 ? Array.isArray(e7) ? e7 : [e7] : [];
}
getSolvedRouteCount() {
let t54 = 0;
for (let e7 = 0;e7 < this.solvedRoutes.length; e7++)
t54 += this.getSolvedRoutesForConn(e7).length;
return t54;
}
computeGridToBoundsTransform() {
let t54 = 1 / 0, e7 = -1 / 0, n7 = 1 / 0, o7 = -1 / 0;
for (let i8 = 0;i8 < this.planeSize; i8++) {
const r8 = this.cellCenterX[i8], s8 = this.cellCenterY[i8];
r8 < t54 && (t54 = r8), r8 > e7 && (e7 = r8), s8 < n7 && (n7 = s8), s8 > o7 && (o7 = s8);
}
const i7 = e7 - t54, r7 = o7 - n7, s7 = this.boundsMaxX - this.boundsMinX, a6 = this.boundsMaxY - this.boundsMinY, c6 = i7 > 0 ? s7 / i7 : 1, l6 = r7 > 0 ? a6 / r7 : 1;
return { a: c6, b: 0, c: i7 > 0 ? this.boundsMinX - c6 * t54 : (this.boundsMinX + this.boundsMaxX) / 2 - t54, d: 0, e: l6, f: r7 > 0 ? this.boundsMinY - l6 * n7 : (this.boundsMinY + this.boundsMaxY) / 2 - n7 };
}
};
var a6 = new WeakMap;
var c6 = (t54) => {
const e7 = a6.get(t54);
if (e7)
return e7;
const n7 = [], o7 = [];
for (let e8 = 1;e8 < t54.route.length; e8++) {
const i8 = t54.route[e8 - 1], r7 = t54.route[e8], s7 = Math.hypot(r7.x - i8.x, r7.y - i8.y), a7 = Math.max(i8.traceThickness ?? t54.traceThickness, r7.traceThickness ?? t54.traceThickness);
if (i8.z !== r7.z && i8.toNextSegmentType === "through_obstacle") {
const e10 = Math.min(i8.z, r7.z), c8 = Math.max(i8.z, r7.z);
if (s7 <= 0.000000001) {
const n8 = t54.vias.some((t55) => Math.hypot(t55.x - r7.x, t55.y - r7.y) <= 0.000000001);
o7.push({ center: { x: r7.x, y: r7.y }, minZ: e10, maxZ: c8, diameter: n8 ? t54.viaDiameter : a7 });
continue;
}
for (let t55 = e10;t55 <= c8; t55++)
n7.push({ start: { ...i8, z: t55 }, end: { ...r7, z: t55 }, z: t55, width: a7 });
continue;
}
const c7 = i8.z === r7.z ? undefined : a9({ hdRoute: t54, start: i8, end: r7 }), l6 = c7 === "start" ? r7.z : i8.z;
if (s7 > 0.000000001 && n7.push({ start: i8.z === l6 ? i8 : { ...i8, z: l6 }, end: r7.z === l6 ? r7 : { ...r7, z: l6 }, z: l6, width: a7 }), i8.z === r7.z)
continue;
const h6 = c7 === "start" ? i8 : r7;
o7.push({ center: { x: h6.x, y: h6.y }, minZ: Math.min(i8.z, r7.z), maxZ: Math.max(i8.z, r7.z), diameter: t54.viaDiameter });
}
const i7 = { wireSegments: n7, viaSpans: o7 };
return a6.set(t54, i7), i7;
};
var l6 = (t54, e7, n7) => {
const o7 = t54.end.x - t54.start.x, i7 = t54.end.y - t54.start.y, r7 = Math.hypot(o7, i7), s7 = { x: (t54.start.x + t54.end.x) / 2, y: (t54.start.y + t54.end.y) / 2 };
return Math.abs(o7) <= 0.000000001 || Math.abs(i7) <= 0.000000001 ? [{ center: s7, width: Math.abs(o7) > Math.abs(i7) ? r7 : t54.width, height: Math.abs(o7) > Math.abs(i7) ? t54.width : r7 }] : Rq({ center: s7, width: r7, height: t54.width, rotation: 180 * Math.atan2(i7, o7) / Math.PI }, Math.max(n7, Math.ceil(r7 / e7)));
};
var h6 = ({ fixedObstacleRoutes: t54, layerCount: e7 }) => t54.flatMap((t55, n7) => {
const o7 = [t55.connectionName, t55.rootConnectionName].filter((t56) => typeof t56 == "string"), i7 = c6(t55);
return [...i7.wireSegments.flatMap((t56, i8) => l6(t56, 0.75, 2).map((r7, s7) => ({ obstacleId: `pipeline9_fixed_obstacle_${n7}_wire_${i8}_${s7}`, type: "rect", layers: [Co(t56.z, e7)], center: r7.center, width: r7.width, height: r7.height, connectedTo: o7 }))), ...i7.viaSpans.map((t56, i8) => ({ obstacleId: `pipeline9_fixed_obstacle_${n7}_via_${i8}`, type: "rect", layers: Array.from({ length: t56.maxZ - t56.minZ + 1 }, (n8, o8) => Co(t56.minZ + o8, e7)), center: t56.center, width: t56.diameter, height: t56.diameter, connectedTo: o7 }))];
});
var d6 = (t54, e7, n7) => {
const o7 = [t54.connectionName, t54.rootConnectionName].filter((t55) => typeof t55 == "string"), i7 = [e7.connectionName, e7.rootConnectionName].filter((t55) => typeof t55 == "string");
return o7.some((t55) => i7.some((e8) => t55 === e8 || n7.areIdsConnected(t55, e8)));
};
var u6 = (t54, e7) => t54.minX <= e7.maxX && t54.maxX >= e7.minX && t54.minY <= e7.maxY && t54.maxY >= e7.minY;
var p6 = ({ left: t54, right: e7, clearance: n7, leftBounds: o7 }) => {
const i7 = c6(t54), r7 = c6(e7), s7 = o7 ? i7.wireSegments.filter((t55) => ((t56, e8) => {
const n8 = { minX: Math.min(t56.start.x, t56.end.x) - t56.width / 2, maxX: Math.max(t56.start.x, t56.end.x) + t56.width / 2, minY: Math.min(t56.start.y, t56.end.y) - t56.width / 2, maxY: Math.max(t56.start.y, t56.end.y) + t56.width / 2 };
return u6(n8, e8);
})(t55, o7)) : i7.wireSegments, a7 = o7 ? i7.viaSpans.filter((t55) => ((t56, e8) => {
const n8 = { minX: t56.center.x - t56.diameter / 2, maxX: t56.center.x + t56.diameter / 2, minY: t56.center.y - t56.diameter / 2, maxY: t56.center.y + t56.diameter / 2 };
return u6(n8, e8);
})(t55, o7)) : i7.viaSpans;
for (const t55 of s7) {
for (const e8 of r7.wireSegments) {
if (t55.z !== e8.z)
continue;
const o8 = t55.width / 2 + e8.width / 2 + n7;
if (Mk(t55.start, t55.end, e8.start, e8.end) < o8)
return true;
}
for (const e8 of r7.viaSpans) {
if (t55.z < e8.minZ || t55.z > e8.maxZ)
continue;
const o8 = t55.width / 2 + e8.diameter / 2 + n7;
if (Mk(t55.start, t55.end, e8.center, e8.center) < o8)
return true;
}
}
for (const t55 of a7) {
for (const e8 of r7.wireSegments) {
if (e8.z < t55.minZ || e8.z > t55.maxZ)
continue;
const o8 = t55.diameter / 2 + e8.width / 2 + n7;
if (Mk(t55.center, t55.center, e8.start, e8.end) < o8)
return true;
}
for (const e8 of r7.viaSpans) {
if (t55.minZ > e8.maxZ || e8.minZ > t55.maxZ)
continue;
const o8 = t55.diameter / 2 + e8.diameter / 2 + n7;
if (Math.hypot(t55.center.x - e8.center.x, t55.center.y - e8.center.y) < o8)
return true;
}
}
return false;
};
var m6 = ({ routes: t54, movablePreloadedConnectionNames: e7, boardObstacles: n7, connMap: o7, layerCount: i7, viaToPadClearance: r7 }) => t54.some((t55) => {
if (!e7.has(t55.connectionName))
return false;
return c6(t55).viaSpans.some((e8) => n7.some((n8) => {
if ((({ obstacle: t56, route: e10, connMap: n10 }) => {
if (xo(t56, e10, n10))
return true;
if (!e10.rootConnectionName)
return false;
const o8 = n10.getNetConnectedToId(e10.connectionName) ?? n10.getNetConnectedToId(e10.rootConnectionName) ?? (n10.netMap[e10.rootConnectionName] ? e10.rootConnectionName : undefined);
return !!o8 && t56.connectedTo.some((t57) => (n10.getNetConnectedToId(t57) ?? (n10.netMap[t57] ? t57 : undefined)) === o8);
})({ obstacle: n8, route: t55, connMap: o7 }))
return false;
const s7 = ((t56, e10) => {
const n10 = t56.__zLayers ?? t56.zLayers;
return n10 || t56.layers.map((t57) => mo(t57, e10));
})(n8, i7);
return !!s7.some((t56) => t56 >= e8.minZ && t56 <= e8.maxZ) && ((t56, e10) => {
const n10 = -1 * (e10.ccwRotationDegrees ?? 0) * Math.PI / 180, o8 = t56.x - e10.center.x, i8 = t56.y - e10.center.y, r8 = o8 * Math.cos(n10) - i8 * Math.sin(n10), s8 = o8 * Math.sin(n10) + i8 * Math.cos(n10), a7 = Math.max(Math.abs(r8) - e10.width / 2, 0), c7 = Math.max(Math.abs(s8) - e10.height / 2, 0);
return Math.hypot(a7, c7);
})(e8.center, n8) < e8.diameter / 2 + r7;
}));
});
var g6 = class extends si {
params;
highDensitySolver;
forceImproveSolver;
repairSolver;
phase = "route";
constructor(t54) {
super(), this.params = t54, this.stats = { preloadedViaCandidateRejectionCount: 0, forceImproveCandidateRejectionCount: 0, repairCandidateRejectionCount: 0 }, this.highDensitySolver = new OO({ nodePortPoints: [t54.nodeWithPortPoints], colorMap: t54.colorMap, connMap: t54.connMap, viaDiameter: t54.viaDiameter, traceWidth: t54.traceWidth, obstacleMargin: t54.obstacleMargin, effort: t54.effort, nodePfById: t54.nodePfById, obstacles: t54.obstacles, layerCount: t54.layerCount, useGrowShrinkHighDensityIntraNodeSolver: true, preserveTerminalPcbPortIds: false, growShrinkFallbackToInvalidGeometryOnFailure: false, growShrinkSolutionValidator: t54.boardObstacles && t54.movablePreloadedConnectionNames && t54.viaToPadClearance !== undefined ? (t55) => this.validateCandidateRoutes(t55) : undefined }), this.activeSubSolver = this.highDensitySolver, this.MAX_ITERATIONS = 1e8 * t54.effort;
}
getSolverName() {
return "Pipeline9RegionalFallbackSolver";
}
validateCandidateRoutes(t54) {
const { boardObstacles: e7, movablePreloadedConnectionNames: n7, viaToPadClearance: o7 } = this.params;
if (!e7 || !n7 || o7 === undefined)
return true;
const i7 = m6({ routes: t54, movablePreloadedConnectionNames: n7, boardObstacles: e7, connMap: this.params.connMap, layerCount: this.params.layerCount, viaToPadClearance: o7 });
return i7 && (this.stats.preloadedViaCandidateRejectionCount = Number(this.stats.preloadedViaCandidateRejectionCount ?? 0) + 1), !i7;
}
_step() {
if (this.phase === "route") {
if (this.highDensitySolver.step(), this.highDensitySolver.failed)
return this.error = this.highDensitySolver.error, void (this.failed = true);
if (!this.highDensitySolver.solved)
return;
const t54 = c9(this.highDensitySolver.routes);
return this.validateCandidateRoutes(t54) ? (this.forceImproveSolver = new zW({ nodeWithPortPoints: [this.params.nodeWithPortPoints], hdRoutes: t54, colorMap: this.params.colorMap, totalStepsPerNode: Math.max(12, Math.round(20 * this.params.effort)), nodeAssignmentMargin: this.params.obstacleMargin }), this.activeSubSolver = this.forceImproveSolver, void (this.phase = "improve")) : (this.error = "Pipeline9 regional route output failed its candidate validator", void (this.failed = true));
}
if (this.phase === "improve") {
if (this.forceImproveSolver.step(), this.forceImproveSolver.failed)
return this.error = this.forceImproveSolver.error, void (this.failed = true);
if (!this.forceImproveSolver.solved)
return;
const t54 = this.forceImproveSolver.getOutput();
return this.validateCandidateRoutes(t54) ? (this.repairSolver = new iq({ nodeWithPortPoints: [this.params.nodeWithPortPoints], hdRoutes: t54, obstacles: this.params.obstacles, colorMap: this.params.colorMap, repairMargin: this.params.obstacleMargin, minimumTraceWidth: this.params.traceWidth, connMap: this.params.connMap }), this.activeSubSolver = this.repairSolver, void (this.phase = "repair")) : (this.stats.forceImproveCandidateRejectionCount = Number(this.stats.forceImproveCandidateRejectionCount ?? 0) + 1, this.error = "Pipeline9 regional force-improve output failed its candidate validator", void (this.failed = true));
}
if (this.phase === "repair") {
if (this.repairSolver.step(), this.repairSolver.failed)
return this.error = this.repairSolver.error, void (this.failed = true);
if (!this.repairSolver.solved)
return;
const t54 = this.repairSolver.getOutput();
return this.validateCandidateRoutes(t54) ? (this.activeSubSolver = null, this.phase = "done", void (this.solved = true)) : (this.stats.repairCandidateRejectionCount = Number(this.stats.repairCandidateRejectionCount ?? 0) + 1, this.error = "Pipeline9 regional repair output failed its candidate validator", void (this.failed = true));
}
}
getOutput() {
return this.repairSolver?.getOutput() ?? this.forceImproveSolver?.getOutput() ?? this.highDensitySolver.routes;
}
visualize() {
return this.repairSolver?.visualize() ?? this.forceImproveSolver?.visualize() ?? this.highDensitySolver.visualize();
}
};
var f6 = (t54, e7) => ({ minX: t54.center.x - t54.width / 2 - e7, maxX: t54.center.x + t54.width / 2 + e7, minY: t54.center.y - t54.height / 2 - e7, maxY: t54.center.y + t54.height / 2 + e7 });
var y6 = (t54, e7, n7) => {
const o7 = Math.max(n7.minX - t54.x, 0, t54.x - n7.maxX), i7 = Math.max(n7.minY - t54.y, 0, t54.y - n7.maxY);
return o7 * o7 + i7 * i7 <= e7 * e7;
};
var _6 = (t54, e7, n7, o7) => Math.min(t54.x, e7.x) - n7 <= o7.maxX && Math.max(t54.x, e7.x) + n7 >= o7.minX && Math.min(t54.y, e7.y) - n7 <= o7.maxY && Math.max(t54.y, e7.y) + n7 >= o7.minY;
var b6 = (t54, e7) => {
const n7 = (t55) => ({ ...t55, rootConnectionName: e7.getNetConnectedToId(t55.rootConnectionName ?? t55.connectionName) ?? t55.rootConnectionName ?? t55.connectionName });
return { ...t54, portPoints: t54.portPoints.map(n7), portPointsInPairs: t54.portPointsInPairs?.map(([t55, e8]) => [n7(t55), n7(e8)]) };
};
var x6 = ({ nodeWithPortPoints: t54, connMap: e7, colorMap: n7, viaDiameter: o7, traceWidth: i7, obstacleMargin: r7, effort: s7, nodePfById: a7, obstacles: c7, boardGeometry: l7, layerCount: h7 }) => new OO({ nodePortPoints: [b6(t54, e7)], colorMap: n7, connMap: e7, viaDiameter: o7, traceWidth: i7, obstacleMargin: r7, effort: s7, nodePfById: a7, obstacles: c7, layerCount: h7, useGrowShrinkHighDensityIntraNodeSolver: true, enableNegotiatedSearch: true, gridSearchSegmentWork: 500, gridSearchWorkScale: h7 > 2 ? 0.25 : 1, rejectOverlappingTerminals: h7 > 2, boardGeometry: l7, preserveTerminalPcbPortIds: false, growShrinkFallbackToInvalidGeometryOnFailure: false, captureSearchDebug: false });
var v6 = class extends si {
fixedHdRoutes;
connMap;
colorMap;
obstacles;
boardGeometry;
layerCount;
viaDiameter;
traceWidth;
obstacleMargin;
viaToPadClearance;
effort;
nodePfById;
preserveTerminalPcbPortIds;
includeBoardObstacles;
enableRegionalFallback;
maxB01Rips;
routes = [];
failedSolvers = [];
unsolvedNodePortPoints;
fixedRouteReplacements = new Map;
removedFixedRouteConnectionNames = new Set;
preloadedTraceMutationMasks = new Map;
activeRegularSolver = null;
activeB01Solver = null;
activeFallbackSolver = null;
activeFallbackFixedRouteSections = new Map;
activeFallbackFixedObstacleRoutes = [];
activeFallbackPromotedFixedRouteConnectionNames = new Set;
activeFallbackReason = null;
activeNode = null;
constructor(t54) {
super(), this.fixedHdRoutes = t54.fixedHdRoutes, this.connMap = t54.connMap, this.colorMap = t54.colorMap ?? {}, this.obstacles = t54.obstacles, this.boardGeometry = t54.boardGeometry, this.layerCount = t54.layerCount, this.viaDiameter = t54.viaDiameter, this.traceWidth = t54.traceWidth, this.obstacleMargin = t54.obstacleMargin, this.viaToPadClearance = t54.viaToPadClearance, this.effort = t54.effort, this.nodePfById = t54.nodePfById instanceof Map ? new Map(t54.nodePfById) : new Map(Object.entries(t54.nodePfById ?? {})), this.preserveTerminalPcbPortIds = t54.preserveTerminalPcbPortIds ?? false, this.includeBoardObstacles = t54.includeBoardObstacles ?? false, this.enableRegionalFallback = t54.enableRegionalFallback ?? true, this.maxB01Rips = t54.maxB01Rips, this.unsolvedNodePortPoints = [...t54.nodePortPoints], this.MAX_ITERATIONS = 1e8 * this.effort, this.stats = { nodeCount: t54.nodePortPoints.length, solvedNodeCount: 0, fixedObstacleCount: t54.fixedHdRoutes.length, fixedObstacleUses: 0, boardObstacleUses: 0, fallbackNodeCount: 0, regularNodeCount: 0, b01NodeCount: 0, reroutedFixedRouteCount: 0, reroutedFixedRouteSectionCount: 0, promotedFallbackAttemptCount: 0, promotedFixedRouteCount: 0, regionalPreloadedViaCandidateRejectionCount: 0, regionalForceImproveCandidateRejectionCount: 0, regionalRepairCandidateRejectionCount: 0 };
}
getSolverName() {
return "Pipeline9HighDensitySolver";
}
getUpdatedFixedHdRoutes() {
return this.fixedHdRoutes.flatMap((t54) => this.removedFixedRouteConnectionNames.has(t54.connectionName) ? [] : [this.fixedRouteReplacements.get(t54.connectionName) ?? t54]);
}
finishActiveNode(t54) {
const e7 = this.activeNode ? ((t55, e8) => t55.map((t56) => ({ ...t56, rootConnectionName: e8.portPoints.find((e10) => e10.connectionName === t56.connectionName)?.rootConnectionName ?? t56.rootConnectionName })))(t54, this.activeNode) : t54;
this.routes.push(...this.preserveTerminalPcbPortIds && this.activeNode ? ((t55, e8) => {
const n7 = e8.portPoints.filter((t56) => t56.pcb_port_id !== undefined);
return t55.map((t56) => {
const e10 = t56.route[0], o7 = t56.route.at(-1), i7 = n7.find((n8) => e10 !== undefined && n8.connectionName === t56.connectionName && n8.x === e10.x && n8.y === e10.y && n8.z === e10.z), r7 = n7.find((e11) => o7 !== undefined && e11.connectionName === t56.connectionName && e11.x === o7.x && e11.y === o7.y && e11.z === o7.z);
return { ...t56, startPcbPortId: i7?.pcb_port_id, endPcbPortId: r7?.pcb_port_id };
});
})(e7, this.activeNode) : e7), this.stats.solvedNodeCount = Number(this.stats.solvedNodeCount ?? 0) + 1, this.activeB01Solver = null, this.activeRegularSolver = null, this.activeFallbackSolver = null, this.activeFallbackFixedRouteSections.clear(), this.activeFallbackFixedObstacleRoutes = [], this.activeFallbackPromotedFixedRouteConnectionNames.clear(), this.activeFallbackReason = null, this.activeNode = null;
}
startRegularSolver(t54) {
this.activeNode = t54, this.activeRegularSolver = x6({ nodeWithPortPoints: t54, colorMap: this.colorMap, connMap: this.connMap, viaDiameter: this.viaDiameter, traceWidth: this.traceWidth, obstacleMargin: this.obstacleMargin, effort: this.effort, nodePfById: this.nodePfById, obstacles: this.obstacles, boardGeometry: this.boardGeometry, layerCount: this.layerCount }), this.stats.regularNodeCount = Number(this.stats.regularNodeCount ?? 0) + 1;
}
startRegionalFallback(t54 = new Set) {
if (!this.activeNode)
throw new Error("Pipeline9 cannot start a regional fallback without an active node");
const e7 = { ...b6(this.activeNode, this.connMap), availableZ: Array.from({ length: this.layerCount }, (t55, e8) => e8) }, n7 = _9(e7, this.getUpdatedFixedHdRoutes(), t54), o7 = new Set([...n7.fixedRouteSectionsByConnectionName.values()].flatMap((t55) => t55.sourceRoutes.map((t56) => t56.connectionName)));
for (const e8 of t54)
if (!o7.has(e8))
throw new Error(`Pipeline9 could not promote fixed route "${e8}" into the active regional fallback`);
const i7 = [...t54].filter((t55) => !this.activeFallbackPromotedFixedRouteConnectionNames.has(t55)).length;
this.activeFallbackFixedRouteSections = n7.fixedRouteSectionsByConnectionName, this.activeFallbackFixedObstacleRoutes = n7.fixedObstacleRoutes, this.activeFallbackPromotedFixedRouteConnectionNames = new Set(t54);
const r7 = h6({ fixedObstacleRoutes: this.activeFallbackFixedObstacleRoutes, layerCount: this.layerCount });
this.activeFallbackSolver = new g6({ nodeWithPortPoints: n7.nodeWithPortPoints, colorMap: this.colorMap, connMap: this.connMap, viaDiameter: this.viaDiameter, traceWidth: this.traceWidth, obstacleMargin: this.obstacleMargin, effort: this.effort, nodePfById: this.nodePfById, obstacles: [...this.obstacles, ...r7], boardObstacles: this.obstacles, movablePreloadedConnectionNames: o7, viaToPadClearance: this.viaToPadClearance, layerCount: this.layerCount }), t54.size === 0 ? this.stats.fallbackNodeCount = Number(this.stats.fallbackNodeCount ?? 0) + 1 : (this.stats.promotedFallbackAttemptCount = Number(this.stats.promotedFallbackAttemptCount ?? 0) + 1, this.stats.promotedFixedRouteCount = Number(this.stats.promotedFixedRouteCount ?? 0) + i7);
}
finishRegionalFallback() {
if (!this.activeFallbackSolver)
return;
if (!this.activeNode)
throw new Error("Pipeline9 cannot finish a regional fallback without an active node");
this.recordRegionalCandidateRejections();
const t54 = [], e7 = new Map;
for (const n8 of this.activeFallbackSolver.getOutput()) {
if (!this.activeFallbackFixedRouteSections.has(n8.connectionName)) {
t54.push(n8);
continue;
}
const o8 = e7.get(n8.connectionName) ?? [];
o8.push(n8), e7.set(n8.connectionName, o8);
}
const n7 = [], o7 = [];
for (const [t55, i8] of this.activeFallbackFixedRouteSections) {
const r8 = e7.get(t55) ?? [];
if (r8.length === 0) {
o7.push(i8);
continue;
}
if (r8.length > 1)
return this.error = `Pipeline9 regional fallback expected one replacement for fixed route "${t55}", got ${r8.length}`, void (this.failed = true);
const s8 = v9({ section: i8, replacement: r8[0], sourceMutationMasks: this.preloadedTraceMutationMasks, replacementIsMutated: true });
n7.push({ connectionName: t55, section: i8, replacement: s8.route, mutatedSegments: s8.mutatedSegments, replacementProducedSegment: s8.replacementProducedSegment });
}
const i7 = [...t54, ...n7.map(({ replacement: t55 }) => t55)], r7 = [...this.activeFallbackFixedObstacleRoutes, ...o7.flatMap((t55) => t55.sourceRoutes)], s7 = f6(this.activeNode, this.obstacleMargin + Math.max(this.traceWidth, this.viaDiameter) / 2), a7 = new Map;
for (const t55 of i7)
for (const e8 of r7)
d6(t55, e8, this.connMap) || p6({ left: t55, right: e8, clearance: this.obstacleMargin, leftBounds: s7 }) && a7.set(e8.connectionName, e8);
if (a7.size > 0) {
const t55 = [...a7.keys()], e8 = [...a7].flatMap(([t56, e10]) => e10.isThroughObstacle === true ? [] : [t56]), n8 = new Set(this.activeFallbackPromotedFixedRouteConnectionNames);
for (const t56 of e8)
n8.add(t56);
if (n8.size === this.activeFallbackPromotedFixedRouteConnectionNames.size) {
const e10 = [...a7].flatMap(([t56, e11]) => e11.isThroughObstacle === true ? [t56] : []);
return this.error = e10.length > 0 ? `Pipeline9 regional fallback conflicts with immutable through-obstacle route(s): ${e10.join(", ")}` : `Pipeline9 promoted regional fallback could not resolve immutable fixed route conflict(s): ${t55.join(", ")}`, void (this.failed = true);
}
return void this.startRegionalFallback(n8);
}
const c7 = new Map;
for (const { section: t55, replacementProducedSegment: e8 } of n7)
if (e8)
for (const e10 of t55.sourceRoutes) {
const { preloadedRoutePositionStart: t56, preloadedRoutePositionEnd: n8 } = e10;
if (t56 === undefined != (n8 === undefined))
throw new Error(`Pipeline9 fixed route "${e10.connectionName}" has incomplete route-position metadata`);
const o8 = Math.min(t56 ?? e10.preloadedRouteIndex, n8 ?? e10.preloadedRouteIndex), i8 = Math.max(t56 ?? e10.preloadedRouteIndex, n8 ?? e10.preloadedRouteIndex), r8 = c7.get(e10.preloadedTraceIndex);
c7.set(e10.preloadedTraceIndex, { start: Math.min(r8?.start ?? o8, o8), end: Math.max(r8?.end ?? i8, i8) });
}
for (const { connectionName: t55, section: e8, replacement: o8, mutatedSegments: i8 } of n7) {
this.fixedRouteReplacements.set(t55, o8), this.preloadedTraceMutationMasks.set(t55, i8);
for (const t56 of e8.sourceRoutes.slice(1))
this.removedFixedRouteConnectionNames.add(t56.connectionName), this.preloadedTraceMutationMasks.delete(t56.connectionName);
}
const l7 = _9({ ...b6(this.activeNode, this.connMap), portPoints: [], portPointsInPairs: [], availableZ: Array.from({ length: this.layerCount }, (t55, e8) => e8) }, this.getUpdatedFixedHdRoutes()), h7 = new Set;
for (const t55 of l7.fixedRouteSectionsByConnectionName.values()) {
const e8 = t55.sourceRoutes[0];
if (!e8)
continue;
const n8 = c7.get(e8.preloadedTraceIndex);
if (n8)
for (const [o8, i8] of t55.sourceRoutes.entries()) {
const r8 = i8.preloadedRoutePositionStart ?? i8.preloadedRouteIndex, s8 = i8.preloadedRoutePositionEnd ?? i8.preloadedRouteIndex, a8 = { start: Math.min(r8, s8), end: Math.max(r8, s8) }, c8 = a8.start === a8.end, l8 = n8.start === n8.end;
if (!(c8 || l8 ? a8.start <= n8.end && n8.start <= a8.end : a8.start < n8.end && n8.start < a8.end))
continue;
h7.add(e8.preloadedTraceIndex);
const d8 = [...this.preloadedTraceMutationMasks.get(i8.connectionName) ?? Array(i8.route.length - 1).fill(false)];
if (d8.length !== i8.route.length - 1)
throw new Error(`Pipeline9 fixed route mutation mask for "${i8.connectionName}" has ${d8.length} segments, expected ${i8.route.length - 1}`);
const u7 = o8 === 0 ? t55.start.segmentIndex : 0, p7 = o8 === t55.sourceRoutes.length - 1 ? t55.end.segmentIndex : i8.route.length - 2;
for (let t56 = u7;t56 <= p7; t56++)
d8[t56] = true;
this.preloadedTraceMutationMasks.set(i8.connectionName, d8);
}
}
for (const t55 of c7.keys())
if (!h7.has(t55))
throw new Error(`Pipeline9 could not capture accepted mutation provenance for trace ${t55}`);
const d7 = n7.reduce((t55, { section: e8 }) => t55 + e8.sourceRoutes.length, 0);
this.stats.reroutedFixedRouteCount = Number(this.stats.reroutedFixedRouteCount ?? 0) + d7, this.stats.reroutedFixedRouteSectionCount = Number(this.stats.reroutedFixedRouteSectionCount ?? 0) + n7.length, this.finishActiveNode(t54);
}
recordRegionalCandidateRejections() {
if (!this.activeFallbackSolver)
return;
const t54 = this.activeFallbackSolver.stats;
this.stats.regionalPreloadedViaCandidateRejectionCount = Number(this.stats.regionalPreloadedViaCandidateRejectionCount ?? 0) + Number(t54.preloadedViaCandidateRejectionCount ?? 0), this.stats.regionalForceImproveCandidateRejectionCount = Number(this.stats.regionalForceImproveCandidateRejectionCount ?? 0) + Number(t54.forceImproveCandidateRejectionCount ?? 0), this.stats.regionalRepairCandidateRejectionCount = Number(this.stats.regionalRepairCandidateRejectionCount ?? 0) + Number(t54.repairCandidateRejectionCount ?? 0);
}
finishRegularSolverFailure(t54) {
if (this.activeFallbackReason = `regular high-density routing failed: ${t54}`, this.activeRegularSolver = null, !this.enableRegionalFallback)
return this.error = `Pipeline9 ${this.activeFallbackReason}`, this.failed = true, void (this.activeNode = null);
this.startRegionalFallback();
}
_step() {
this.stepNodeRouting(), this.activeSubSolver = this.activeFallbackSolver ?? this.activeRegularSolver ?? this.activeB01Solver;
}
computeProgress() {
if (this.solved)
return 1;
const t54 = Number(this.stats.nodeCount);
if (t54 === 0)
return 0;
const e7 = Math.max(0, Math.min(1, this.activeSubSolver?.progress ?? 0));
return Math.max(this.progress, (Number(this.stats.solvedNodeCount) + e7) / t54);
}
stepNodeRouting() {
if (this.activeFallbackSolver) {
if (this.activeFallbackSolver.step(), this.activeFallbackSolver.failed)
return this.recordRegionalCandidateRejections(), this.error = [`Pipeline9 primary high-density routing failed: ${this.activeFallbackReason ?? "unknown error"}`, `regional fallback failed: ${this.activeFallbackSolver.error ?? "unknown error"}`].join("; "), this.failed = true, this.activeFallbackSolver = null, this.activeFallbackFixedRouteSections.clear(), this.activeFallbackFixedObstacleRoutes = [], this.activeFallbackPromotedFixedRouteConnectionNames.clear(), void (this.activeNode = null);
if (!this.activeFallbackSolver.solved)
return;
return void this.finishRegionalFallback();
}
if (this.activeRegularSolver) {
if (this.activeRegularSolver.step(), this.activeRegularSolver.failed)
return void this.finishRegularSolverFailure(this.activeRegularSolver.error ?? "unknown error");
if (!this.activeRegularSolver.solved)
return;
return void this.finishActiveNode(this.activeRegularSolver.routes);
}
if (this.activeB01Solver) {
if (this.activeB01Solver.step(), this.activeB01Solver.failed)
return this.failedSolvers.push(this.activeB01Solver), this.activeFallbackReason = `B01 failed: ${this.activeB01Solver.error ?? "unknown error"}`, this.activeB01Solver = null, this.enableRegionalFallback ? void this.startRegionalFallback() : (this.error = `Pipeline9 ${this.activeFallbackReason}`, this.failed = true, void (this.activeNode = null));
if (!this.activeB01Solver.solved)
return;
return void this.finishActiveNode(this.activeB01Solver.getOutput());
}
const t54 = this.unsolvedNodePortPoints.pop();
if (!t54)
return void (this.solved = true);
const e7 = f6(t54, this.obstacleMargin), n7 = Math.max(this.traceWidth, this.viaDiameter) / 2, o7 = this.getUpdatedFixedHdRoutes().filter((o8) => ((t55, e8, n8, o10) => {
const i8 = new Set(e8.availableZ ?? e8.portPoints.map((t56) => t56.z));
for (let e10 = 1;e10 < t55.route.length; e10++) {
const r8 = t55.route[e10 - 1], s7 = t55.route[e10];
if (r8.z === s7.z) {
if (i8.has(r8.z) && _6(r8, s7, t55.traceThickness / 2 + o10, n8))
return true;
continue;
}
const a7 = Math.min(r8.z, s7.z), c7 = Math.max(r8.z, s7.z);
if ([...i8].some((t56) => t56 >= a7 && t56 <= c7) && y6(s7, t55.viaDiameter / 2 + o10, n8))
return true;
}
return false;
})(o8, t54, e7, n7)).flatMap((e8) => ((t55, e10) => {
const n8 = new Set(e10.availableZ ?? e10.portPoints.map((t56) => t56.z));
if (n8.size === 0)
throw new Error(`Pipeline9 B01 node "${e10.capacityMeshNodeId}" has no available layers`);
const o8 = { type: "route", connectionName: t55.connectionName, rootConnectionName: t55.rootConnectionName, traceThickness: t55.traceThickness, viaDiameter: t55.viaDiameter }, i8 = [];
for (let e11 = 1;e11 < t55.route.length; e11++) {
const r8 = t55.route[e11 - 1], s7 = t55.route[e11];
if (r8.z === s7.z) {
if (!n8.has(r8.z))
continue;
i8.push({ ...o8, route: [r8, s7], vias: [] });
continue;
}
const a7 = Math.min(r8.z, s7.z), c7 = Math.max(r8.z, s7.z);
[...n8].some((t56) => t56 >= a7 && t56 <= c7) && i8.push({ ...o8, route: [r8, s7], vias: [{ x: s7.x, y: s7.y, zStart: r8.z, zEnd: s7.z }] });
}
return i8;
})(e8, t54));
if (this.stats.fixedObstacleUses = Number(this.stats.fixedObstacleUses ?? 0) + o7.length, o7.length === 0)
return void this.startRegularSolver(t54);
const i7 = (this.includeBoardObstacles ? this.obstacles : []).filter((t55) => ((t56, e8) => {
const n8 = (t56.ccwRotationDegrees ?? 0) * Math.PI / 180, o8 = Math.abs(Math.cos(n8)), i8 = Math.abs(Math.sin(n8)), r8 = t56.width / 2 * o8 + t56.height / 2 * i8, s7 = t56.width / 2 * i8 + t56.height / 2 * o8;
return t56.center.x - r8 <= e8.maxX && t56.center.x + r8 >= e8.minX && t56.center.y - s7 <= e8.maxY && t56.center.y + s7 >= e8.minY;
})(t55, e7)).map((e8) => (({ obstacle: t55, node: e10, connMap: n8, layerCount: o8 }) => {
const i8 = new Set(e10.availableZ ?? e10.portPoints.map((t56) => t56.z)), r8 = (t55.zLayers ?? t55.layers.map((t56) => mo(t56, o8))).filter((t56) => i8.has(t56));
if (r8.length === 0)
return;
const s7 = t55.connectedTo[0] ?? t55.obstacleId ?? `pipeline9_obstacle_${t55.center.x}_${t55.center.y}`;
return { type: "rect", connectionName: s7, rootConnectionName: n8.getNetConnectedToId(s7) ?? s7, center: t55.center, width: t55.width, height: t55.height, ccwRotationDegrees: t55.ccwRotationDegrees, zLayers: r8 };
})({ obstacle: e8, node: t54, connMap: this.connMap, layerCount: this.layerCount })).filter((t55) => t55 !== undefined);
if (this.stats.boardObstacleUses = Number(this.stats.boardObstacleUses ?? 0) + i7.length, this.activeNode = t54, t54.width > 15 || t54.height > 15)
return this.activeFallbackReason = `B01 node "${t54.capacityMeshNodeId}" exceeds the 15x15mm routing limit (${t54.width}x${t54.height}mm)`, void this.startRegionalFallback();
const r7 = b6(t54, this.connMap);
this.stats.b01NodeCount = Number(this.stats.b01NodeCount ?? 0) + 1, this.activeB01Solver = new s6({ ...z9, nodeWithPortPoints: r7, obstacles: [...o7, ...i7], viaDiameter: this.viaDiameter, viaMinDistFromBorder: this.viaDiameter / 2, traceThickness: this.traceWidth, traceMargin: this.obstacleMargin, obstacleClearanceMargin: 0.15, effort: this.effort }), this.maxB01Rips !== undefined && (this.activeB01Solver.MAX_RIPS = this.maxB01Rips);
}
visualize() {
return this.activeFallbackSolver?.visualize() ?? this.activeRegularSolver?.visualize() ?? this.activeB01Solver?.visualize() ?? { lines: this.routes.flatMap((t54) => t54.route.slice(0, -1).map((e7, n7) => ({ points: [e7, t54.route[n7 + 1]], strokeWidth: t54.traceThickness, layer: `z${e7.z}`, label: t54.connectionName }))), points: [], rects: [], circles: [] };
}
};
var I6 = { traceClearance: 0.1, viaClearance: 0.1 };
var S6 = (t54, e7) => {
const n7 = new Set(e7.flatMap((t55) => t55.__replaces_pcb_trace_id ? [t55.__replaces_pcb_trace_id] : []));
return [...t54.filter((t55) => !n7.has(t55.pcb_trace_id)), ...e7];
};
var C6 = ({ inputSrj: t54, srjWithPointPairs: e7, routedTraces: n7, drcOptions: o7, includeBoardClearance: i7 = false, connectivityMaps: r7 }) => {
const s7 = t54.traces ?? [], a7 = hO(e7, S6(s7, n7), { minTraceWidth: t54.minTraceWidth, minViaDiameter: t54.minViaDiameter, originalSrj: t54, includeOriginalConnections: true, connectivityMaps: r7 });
return i7 && a7.push(lO({ ...t54, minBoardEdgeClearance: t54.minBoardEdgeClearance ?? 0 })), { circuitJson: a7, ...VS(a7, { ...I6, ...o7 }) };
};
var P6 = (t54, e7) => {
const n7 = t54({ hdRoutes: e7, traces: [] });
return Array.isArray(n7) ? n7 : n7.errorsWithCenters ?? n7.errors;
};
var M6 = (t54) => {
const e7 = typeof t54.pcb_trace_id == "string" ? t54.pcb_trace_id : undefined, n7 = Array.isArray(t54.pcb_trace_ids) ? t54.pcb_trace_ids.filter((t55) => typeof t55 == "string") : [], o7 = [...typeof t54.pcb_via_id == "string" ? [t54.pcb_via_id] : [], ...Array.isArray(t54.pcb_via_ids) ? t54.pcb_via_ids : []].filter((t55) => typeof t55 == "string"), i7 = e7 ? `overlap_${e7}_` : undefined, r7 = i7 && typeof t54.pcb_trace_error_id == "string" && t54.pcb_trace_error_id.startsWith(i7) ? t54.pcb_trace_error_id.slice(i7.length) : undefined;
if (n7.length > 0) {
const t55 = e7 && !n7.includes(e7) ? [e7, ...n7] : [...n7];
return t55.length < 2 && r7 && !o7.includes(r7) && t55.push(r7), t55;
}
return [e7, r7].filter((t55) => typeof t55 == "string" && !o7.includes(t55));
};
var N6 = (t54) => M6(t54).filter((t55, e7, n7) => n7.indexOf(t55) === e7);
var w6 = (t54) => t54.reduce((t55, e7) => {
if (typeof e7.actual_clearance == "number" && typeof e7.minimum_clearance == "number")
return t55 + Math.max(0, e7.minimum_clearance - e7.actual_clearance);
const n7 = (typeof e7.message == "string" ? e7.message : "").match(/gap: (-?\d+(?:\.\d+)?)mm/);
return n7 ? t55 + Math.max(0, 0.1 - Number.parseFloat(n7[1])) : t55 + 1;
}, 0);
var T6 = (t54, e7) => t54.length < e7.length || t54.length === e7.length && w6(t54) < w6(e7) - 0.000000001;
var R6 = ({ routes: t54, newConnections: e7, syntheticConnectionNames: n7 }) => {
const o7 = new Set([...e7.map((t55) => t55.name), ...n7]), i7 = new Map, r7 = new Map;
for (let e8 = 0;e8 < t54.length; e8++) {
const n8 = t54[e8];
if (!o7.has(n8.connectionName))
continue;
const s7 = i7.get(n8.connectionName) ?? 0;
i7.set(n8.connectionName, s7 + 1), r7.set(`${n8.connectionName}_${s7}`, e8);
}
return r7;
};
var E6 = [0.03, 0.1, 0.25];
var A6 = (t54) => {
let e7 = 0;
for (const n7 of t54) {
if (typeof n7.actual_clearance != "number" || !Number.isFinite(n7.actual_clearance) || typeof n7.minimum_clearance != "number" || !Number.isFinite(n7.minimum_clearance))
return;
if (e7 += Math.max(0, n7.minimum_clearance - n7.actual_clearance), !Number.isFinite(e7))
return;
}
return e7;
};
var O6 = ({ errors: t54, errorsWithCenters: e7, routeIndexByTraceId: n7, padPositionById: o7 }) => {
const i7 = [];
let r7 = 0;
for (const s7 of t54) {
const t55 = s7.type === "pcb_via_trace_clearance_error", a7 = s7.type === "pcb_pad_trace_clearance_error";
if (!t55 && !a7 || typeof s7.pcb_trace_id != "string" || !n7.has(s7.pcb_trace_id) || typeof s7.actual_clearance != "number" || !Number.isFinite(s7.actual_clearance) || typeof s7.minimum_clearance != "number" || !Number.isFinite(s7.minimum_clearance))
return;
const c7 = N6(s7);
if (t55 && c7.length < 2 || c7.some((t56) => !n7.has(t56)))
return;
const l7 = e7.find((t56) => t56.type === s7.type && t56.pcb_trace_id === s7.pcb_trace_id && t56.pcb_pad_id === s7.pcb_pad_id && t56.pcb_via_id === s7.pcb_via_id), h7 = a7 ? typeof s7.pcb_pad_id == "string" ? o7.get(s7.pcb_pad_id) : undefined : l7?.center ?? s7.center;
if (!h7 || typeof h7 != "object")
return;
if (!(("x" in h7) && ("y" in h7) && typeof h7.x == "number" && Number.isFinite(h7.x) && typeof h7.y == "number" && Number.isFinite(h7.y)))
return;
const d7 = { ...s7, pcb_trace_id: s7.pcb_trace_id, actual_clearance: s7.actual_clearance, minimum_clearance: s7.minimum_clearance, center: { x: h7.x, y: h7.y } };
if (t55) {
if (typeof s7.pcb_via_id != "string")
return;
i7.push({ ...d7, type: "pcb_via_trace_clearance_error", pcb_via_id: s7.pcb_via_id, pcb_pad_id: undefined });
} else {
if (typeof s7.pcb_pad_id != "string")
return;
i7.push({ ...d7, type: "pcb_pad_trace_clearance_error", pcb_pad_id: s7.pcb_pad_id, pcb_via_id: undefined });
}
if (r7 += Math.max(0, s7.minimum_clearance - s7.actual_clearance), !Number.isFinite(r7))
return;
}
return { errors: i7, deficit: r7 };
};
var k6 = (t54) => ((t55) => {
const e7 = typeof t55.pcb_trace_id == "string" ? t55.pcb_trace_id : undefined, n7 = Array.isArray(t55.pcb_trace_ids) ? t55.pcb_trace_ids.filter((t56) => typeof t56 == "string") : [], o7 = [...typeof t55.pcb_via_id == "string" ? [t55.pcb_via_id] : [], ...Array.isArray(t55.pcb_via_ids) ? t55.pcb_via_ids : []].filter((t56) => typeof t56 == "string"), i7 = e7 ? `overlap_${e7}_` : undefined, r7 = i7 && typeof t55.pcb_trace_error_id == "string" && t55.pcb_trace_error_id.startsWith(i7) ? t55.pcb_trace_error_id.slice(i7.length) : undefined;
if (n7.length > 0) {
const t56 = e7 && !n7.includes(e7) ? [e7, ...n7] : [...n7];
return t56.length < 2 && r7 && !o7.includes(r7) && t56.push(r7), t56;
}
return [e7, r7].filter((t56) => typeof t56 == "string" && !o7.includes(t56));
})(t54).filter((t55, e7, n7) => n7.indexOf(t55) === e7);
var D6 = ({ originalSrj: t54, routes: e7, drcEvaluator: n7 }) => {
const o7 = n7({ traces: [], routes: e7, hdRoutes: e7 }), i7 = Array.isArray(o7) ? o7 : o7.errors;
if (i7.length === 0)
return e7;
const r7 = { ...$q(t54), traces: undefined }, s7 = l9(e7), a7 = function(t55) {
const e8 = structuredClone(t55.routes), n8 = xI(t55.srj, e8), o8 = t55.traceClearance ?? 0.1, i8 = t55.viaClearance ?? 0.1, r8 = { minX: t55.bounds.minX + t55.boundaryMargin, maxX: t55.bounds.maxX - t55.boundaryMargin, minY: t55.bounds.minY + t55.boundaryMargin, maxY: t55.bounds.maxY - t55.boundaryMargin }, s8 = TI(t55.srj, e8, t55.bounds), a8 = new Map, c8 = e8.map((e10, o10) => e10.route.map((i10, c10) => {
const l10 = `${n8.get(e10.connectionName)}:${i10.x}:${i10.y}`;
let h8 = a8.get(l10);
return h8 || (h8 = { x: i10.x, y: i10.y, original: { x: i10.x, y: i10.y }, locked: false, radius: 0, revision: 0, bounds: r8, points: [] }, a8.set(l10, h8)), h8.points.push(i10), h8.locked ||= Boolean(t55.lockedPointIndices[o10][c10] || s8[o10].segmentTimes.has(c10) || s8[o10].segmentTimes.has(c10 - 1) || s8[o10].viaPositions.some((t56) => Math.hypot(t56.x - i10.x, t56.y - i10.y) <= Hs) || c10 === 0 || c10 === e10.route.length - 1 || i10.pcb_port_id || i10.insideJumperPad || i10.toNextSegmentType || i10.x <= r8.minX || i10.x >= r8.maxX || i10.y <= r8.minY || i10.y >= r8.maxY), h8;
})), l8 = [];
for (let o10 = 0;o10 < e8.length; o10++) {
const i10 = e8[o10];
for (let e10 = 1;e10 < i10.route.length; e10++) {
const r10 = i10.route[e10 - 1], s10 = i10.route[e10];
if (r10.toNextSegmentType || r10.insideJumperPad || s10.insideJumperPad)
continue;
const a10 = c8[o10][e10 - 1], h8 = c8[o10][e10], d8 = r10.z !== s10.z;
d8 && t55.allowViaMovement !== true && (a10.locked = h8.locked = true), l8.push({ a: a10, b: h8, initialBounds: { minX: Math.min(a10.x, h8.x), maxX: Math.max(a10.x, h8.x), minY: Math.min(a10.y, h8.y), maxY: Math.max(a10.y, h8.y) }, ...Ys(t55.srj, r10, s10), radius: d8 ? i10.viaDiameter / 2 : Math.max(r10.traceThickness ?? i10.traceThickness, s10.traceThickness ?? i10.traceThickness) / 2, net: n8.get(i10.connectionName), routeIndex: o10, via: d8 });
}
}
for (const t56 of l8)
t56.a.radius = Math.max(t56.a.radius, t56.radius), t56.b.radius = Math.max(t56.b.radius, t56.radius);
if (t55.boardEdgeClearance !== undefined) {
const e10 = t55.srj.bounds;
for (const n10 of a8.values()) {
const o10 = n10.radius + t55.boardEdgeClearance;
n10.bounds = { minX: Math.max(r8.minX, Math.min(n10.original.x, e10.minX + o10)), maxX: Math.min(r8.maxX, Math.max(n10.original.x, e10.maxX - o10)), minY: Math.max(r8.minY, Math.min(n10.original.y, e10.minY + o10)), maxY: Math.min(r8.maxY, Math.max(n10.original.y, e10.maxY - o10)) };
}
}
const h7 = [];
for (let t56 = 0;t56 < l8.length; t56++) {
const e10 = l8[t56];
for (let n10 = t56 + 1;n10 < l8.length; n10++) {
const t57 = l8[n10];
if (e10.net === t57.net || e10.maxZ < t57.minZ || t57.maxZ < e10.minZ)
continue;
const r10 = e10.radius + t57.radius + Math.max(o8, i8) + 2 * Math.SQRT2 * YI;
$I(e10.initialBounds, t57.initialBounds, r10) || Oe(e10.a, e10.b, t57.a, t57.b) <= r10 && h7.push({ a: e10, b: t57, revisions: [-1, -1, -1, -1], contact: null });
}
}
const d7 = [], u7 = new Map;
for (const e10 of t55.srj.obstacles) {
const r10 = (e10.ccwRotationDegrees ?? 0) * Math.PI / 180, s10 = Math.cos(r10), a10 = Math.sin(r10), c10 = new Set(e10.connectedTo.map((t56) => n8.get(t56) ?? t56)), h8 = e10.__zLayers ?? e10.zLayers ?? e10.layers.map((e11) => e11 === "top" ? 0 : e11 === "bottom" ? t55.srj.layerCount - 1 : Number(e11.slice(5))), p8 = [[-1, -1], [1, -1], [1, 1], [-1, 1]].map(([t56, n10]) => ({ x: e10.center.x + s10 * t56 * e10.width / 2 - a10 * n10 * e10.height / 2, y: e10.center.y + a10 * t56 * e10.width / 2 + s10 * n10 * e10.height / 2 })), m7 = { minX: Math.min(...p8.map((t56) => t56.x)), maxX: Math.max(...p8.map((t56) => t56.x)), minY: Math.min(...p8.map((t56) => t56.y)), maxY: Math.max(...p8.map((t56) => t56.y)) };
for (const n10 of l8) {
if (!n10.via && c10.has(n10.net) || !h8.some((t56) => t56 >= n10.minZ && t56 <= n10.maxZ))
continue;
const r11 = n10.radius + Math.max(o8, i8, t55.srj.defaultObstacleMargin ?? 0, t55.srj.minTraceToPadEdgeClearance ?? 0, t55.srj.minViaEdgeToPadEdgeClearance ?? 0) + Math.SQRT2 * YI;
if ($I(n10.initialBounds, m7, r11))
continue;
if (Math.min(...p8.map((t56, e11) => Oe(n10.a, n10.b, t56, p8[(e11 + 1) % 4]))) > r11)
continue;
const l10 = n10.radius + (n10.via ? Vs(t55.srj, i8, c10.has(n10.net)) : Math.max(o8, t55.srj.defaultObstacleMargin ?? 0, t55.srj.minTraceToPadEdgeClearance ?? 0));
if (d7.push({ segment: n10, corners: p8, required: l10, revisions: [-1, -1], contact: null }), n10.via) {
const t56 = { center: e10.center, cosine: s10, sine: a10, shape: _I(e10), clearance: l10 }, o10 = n10.a.original.x - e10.center.x, i10 = n10.a.original.y - e10.center.y, r12 = { x: o10 * s10 + i10 * a10, y: -o10 * a10 + i10 * s10 };
t56.clearance = Math.min(t56.clearance, bI(r12, r12, t56.shape));
for (const e11 of new Set([n10.a, n10.b])) {
const n11 = u7.get(e11);
n11 ? n11.push(t56) : u7.set(e11, [t56]);
}
}
}
}
const p7 = (t56, e10, n10, o10) => {
const i10 = new Map;
for (const [e11, n11] of t56)
e11.locked || i10.set(e11, (i10.get(e11) ?? 0) + n11);
const r10 = [...i10.values()].reduce((t57, e11) => t57 + e11 * e11, 0);
if (r10 < 0.000000000000001)
return;
const s10 = Math.min(0.05, 0.7 * o10) / r10;
for (const [t57, o11] of i10) {
const i11 = Math.max(t57.bounds.minX, t57.original.x - YI, Math.min(t57.bounds.maxX, t57.original.x + YI, t57.x + e10 * s10 * o11)), r11 = Math.max(t57.bounds.minY, t57.original.y - YI, Math.min(t57.bounds.maxY, t57.original.y + YI, t57.y + n10 * s10 * o11));
u7.get(t57)?.some((t58) => {
const e11 = i11 - t58.center.x, n11 = r11 - t58.center.y, o12 = { x: e11 * t58.cosine + n11 * t58.sine, y: -e11 * t58.sine + n11 * t58.cosine };
return bI(o12, o12, t58.shape) < t58.clearance;
}) || (t57.x === i11 && t57.y === r11 || t57.revision++, t57.x = i11, t57.y = r11);
}
};
for (let t56 = 0;t56 < 256; t56++) {
for (const t57 of h7) {
const { a: e10, b: n10, revisions: r10 } = t57;
e10.a.revision === r10[0] && e10.b.revision === r10[1] && n10.a.revision === r10[2] && n10.b.revision === r10[3] || (t57.contact = XI(e10.a, e10.b, n10.a, n10.b), r10[0] = e10.a.revision, r10[1] = e10.b.revision, r10[2] = n10.a.revision, r10[3] = n10.b.revision);
const s10 = t57.contact, a10 = e10.radius + n10.radius + (e10.via && n10.via ? i8 : o8);
s10.distance >= a10 || s10.distance < 0.0000000001 || p7([[e10.a, 1 - s10.s], [e10.b, s10.s], [n10.a, s10.t - 1], [n10.b, -s10.t]], s10.x / s10.distance, s10.y / s10.distance, a10 - s10.distance);
}
for (const t57 of d7) {
const { segment: e10, corners: n10, required: o10 } = t57, i10 = e10.a === e10.b ? 1 : 2;
for (let t58 = 0;t58 < i10; t58++) {
const i11 = t58 === 0 ? e10.a : e10.b, r11 = WI(i11, n10);
r11 && p7([[i11, 1]], r11.x, r11.y, o10 + r11.depth);
}
if (e10.a.revision !== t57.revisions[0] || e10.b.revision !== t57.revisions[1]) {
let o11 = XI(e10.a, e10.b, n10[0], n10[1]);
for (let t58 = 1;t58 < n10.length; t58++) {
const i11 = XI(e10.a, e10.b, n10[t58], n10[(t58 + 1) % n10.length]);
o11 = o11.distance < i11.distance ? o11 : i11;
}
t57.contact = o11, t57.revisions[0] = e10.a.revision, t57.revisions[1] = e10.b.revision;
}
const r10 = t57.contact;
r10.distance < 0.0000000001 || r10.distance >= o10 || p7([[e10.a, 1 - r10.s], [e10.b, r10.s]], r10.x / r10.distance, r10.y / r10.distance, o10 - r10.distance);
}
}
for (const t56 of a8.values())
for (const e10 of t56.points)
e10.x = t56.x, e10.y = t56.y;
for (const t56 of e8) {
t56.vias = [];
for (let e10 = 1;e10 < t56.route.length; e10++) {
const n10 = t56.route[e10 - 1], o10 = t56.route[e10];
n10.z === o10.z || n10.toNextSegmentType === "through_obstacle" || t56.vias.some((t57) => t57.x === o10.x && t57.y === o10.y) || t56.vias.push({ x: o10.x, y: o10.y });
}
}
return e8;
}({ srj: r7, routes: s7, bounds: r7.bounds, boundaryMargin: 0, boardEdgeClearance: t54.minBoardEdgeClearance ?? 0, lockedPointIndices: s7.map((t55) => t55.route.map(() => false)), allowViaMovement: true, traceClearance: t54.minTraceToPadEdgeClearance ?? I6.traceClearance, viaClearance: I6.viaClearance }), c7 = new Map(SI({ srj: r7, routes: s7 }).map((t55) => [t55.key, t55.severity]));
if (SI({ srj: r7, routes: a7 }).some(({ key: t55, severity: e8 }) => !c7.has(t55) || e8 > c7.get(t55) + 0.00000001) || PI({ srj: r7, previousRoutes: s7, routes: a7 }).length > 0)
return e7;
const l7 = n7({ traces: [], routes: a7, hdRoutes: a7 });
return (Array.isArray(l7) ? l7 : l7.errors).length < i7.length ? a7 : e7;
};
var L6 = { maxRegions: 4, maxCandidateAttempts: 1024, maxPathSearchNodes: 480000 };
var z6 = [10, 16];
var B6 = ({ originalSrj: t54, connMap: e7, routes: n7, syntheticConnectionNames: o7, drcEvaluator: i7, viaHoleDiameter: r7, budget: s7 = L6 }) => {
const a7 = { routes: n7, attemptedRegionCount: 0, acceptedRegionCount: 0, candidateAttemptCount: 0, pathSearchNodeCount: 0, referenceValidationCount: 0, initialDrcIssueCount: undefined, finalDrcIssueCount: undefined, publishedDrcIssueCount: undefined, repaired: false };
if (t54.traces?.length || o7.size > 0)
return a7;
const c7 = Math.max(t54.defaultObstacleMargin ?? 0.2, t54.minTraceToPadEdgeClearance ?? 0, t54.minViaEdgeToPadEdgeClearance ?? 0);
let l7 = Math.max(t54.minTraceWidth, t54.minViaDiameter ?? 0);
for (const t55 of n7) {
l7 = Math.max(l7, t55.traceThickness, t55.viaDiameter);
for (const e8 of t55.route)
l7 = Math.max(l7, e8.traceThickness ?? 0);
}
const h7 = Math.max(0.5, l7 + c7), d7 = z6.filter((t55) => !Number.isFinite(h7) || 2 * h7 < t55);
if (d7.length === 0)
return a7;
let u7 = n7, p7 = i7({ traces: [], routes: n7, hdRoutes: n7 });
a7.referenceValidationCount++;
let m7 = Array.isArray(p7) ? p7 : p7.errors;
const g7 = m7;
if (a7.publishedDrcIssueCount = m7.length, a7.initialDrcIssueCount = m7.length, a7.finalDrcIssueCount = m7.length, m7.length === 0)
return a7;
const f7 = D6({ originalSrj: t54, routes: u7, drcEvaluator: (t55) => (a7.referenceValidationCount++, i7(t55)) });
if (f7 !== u7 && (u7 = f7, p7 = i7({ traces: [], routes: u7, hdRoutes: u7 }), a7.referenceValidationCount++, m7 = Array.isArray(p7) ? p7 : p7.errors, a7.finalDrcIssueCount = m7.length, m7.length === 0))
return a7.routes = u7, a7.publishedDrcIssueCount = 0, a7.repaired = true, a7;
const y7 = { ...$q(t54), traces: undefined }, _7 = new Map;
for (const e8 of t54.obstacles)
for (const t55 of [e8.obstacleId, e8.circuitJsonMetadata?.pcb_smtpad_id, e8.circuitJsonMetadata?.pcb_plated_hole_id, e8.connectedTo[0]])
typeof t55 == "string" && _7.set(t55, e8.center);
const b7 = [];
u7 = l9(u7);
let x7 = new Map(SI({ srj: y7, routes: u7 }).map((t55) => [t55.key, t55.severity]));
for (;a7.attemptedRegionCount < s7.maxRegions && a7.candidateAttemptCount < s7.maxCandidateAttempts && a7.pathSearchNodeCount < s7.maxPathSearchNodes; ) {
const n8 = (Array.isArray(p7) ? p7 : p7.errorsWithCenters ?? p7.errors).map((t55) => {
const e8 = `overlap_${t55.pcb_trace_id}_`, n10 = typeof t55.pcb_pad_id == "string" ? t55.pcb_pad_id : typeof t55.pcb_trace_error_id == "string" && t55.pcb_trace_error_id.startsWith(e8) ? t55.pcb_trace_error_id.slice(e8.length) : undefined;
return (n10 ? _7.get(n10) : undefined) ?? t55.center ?? t55.pcb_center;
}).filter((t55) => t55 !== null && typeof t55 == "object" && ("x" in t55) && ("y" in t55) && typeof t55.x == "number" && typeof t55.y == "number" && Number.isFinite(t55.x) && Number.isFinite(t55.y));
let o8;
for (const t55 of d7) {
const e8 = n8.filter(({ x: e10, y: n10 }) => !b7.some(({ bounds: o10, size: i10 }) => t55 === i10 && e10 >= o10.minX && e10 <= o10.maxX && n10 >= o10.minY && n10 <= o10.maxY)), i8 = e8[0];
if (i8) {
let { x: n10, x: r8, y: s8, y: a8 } = i8;
const c10 = t55 - 2 * h7;
for (const t56 of e8.slice(1)) {
const e10 = Math.min(n10, t56.x), o10 = Math.max(r8, t56.x), i10 = Math.min(s8, t56.y), l10 = Math.max(a8, t56.y);
o10 - e10 >= c10 || l10 - i10 >= c10 || (n10 = e10, r8 = o10, s8 = i10, a8 = l10);
}
o8 = { center: { x: (n10 + r8) / 2, y: (s8 + a8) / 2 }, size: t55 };
break;
}
}
if (!o8)
break;
const { center: c8, size: l8 } = o8, g8 = OI({ srj: y7, routes: u7, bounds: { minX: c8.x - l8 / 2, maxX: c8.x + l8 / 2, minY: c8.y - l8 / 2, maxY: c8.y + l8 / 2 } });
if (b7.push({ bounds: g8.mutableBounds, size: l8 }), a7.attemptedRegionCount++, g8.routes.length === 0)
continue;
const f8 = new Set(m7.flatMap(k6)), v7 = g8.routes.flatMap((t55, e8) => [...f8].some((e10) => e10 === t55.connectionName || e10.startsWith(`${t55.connectionName}_`)) ? [e8] : []), I7 = HI({ srj: g8.srj, routes: g8.routes, bounds: g8.mutableBounds, dirtyRouteIndices: v7, isLocked: (t55, e8) => g8.lockedPointIndices[t55][e8], maxPathSearchCalls: Math.min(s7.maxCandidateAttemptsPerRegion ?? (s7.revisitChangedRegions ? Math.ceil(s7.maxCandidateAttempts / 2) : s7.maxCandidateAttempts), s7.maxCandidateAttempts - a7.candidateAttemptCount), maxPathSearchNodes: s7.maxPathSearchNodes - a7.pathSearchNodeCount, maxPathSearchNodesPerCall: s7.maxPathSearchNodesPerCall, pathHeuristicWeight: s7.pathHeuristicWeight, pathGridSizeScale: m7.length > 10 ? s7.pathGridSizeScale : undefined, allowLayerChanges: true, traceClearance: I6.traceClearance, viaClearance: I6.viaClearance, viaHoleDiameter: r7 }), { pathSearchCalls: S7, pathSearchNodes: C7 } = I7;
if (!Number.isSafeInteger(S7) || S7 < 0 || S7 + a7.candidateAttemptCount > s7.maxCandidateAttempts || !Number.isSafeInteger(C7) || C7 < 0 || C7 + a7.pathSearchNodeCount > s7.maxPathSearchNodes)
throw new Error("Pipeline9 bounded regional repair exceeded its work budget");
a7.candidateAttemptCount += S7, a7.pathSearchNodeCount += C7;
const P7 = jI({ routes: u7, region: g8, repairedRoutes: I7.routes });
if (P7.every((t55, e8) => t55 === u7[e8]))
continue;
let M7, N7 = D6({ originalSrj: t54, routes: P7, drcEvaluator: (t55) => (a7.referenceValidationCount++, i7(t55)) });
if (e7) {
const t55 = i7({ traces: [], routes: N7, hdRoutes: N7 });
a7.referenceValidationCount++, M7 = t55;
const n10 = Array.isArray(t55) ? t55 : t55.errors, o10 = n10.filter((t56) => t56.type === "pcb_via_clearance_error"), r8 = o10.flatMap(k6), s8 = N7.filter((t56) => r8.some((e8) => e8 === t56.connectionName || e8.startsWith(`${t56.connectionName}_`)));
if (s8.length > 0 && o10.length === n10.length) {
const t56 = new Set(s8), n11 = new qk({ inputHdRoutes: s8, otherHdRoutes: N7.filter((e8) => !t56.has(e8)), netByConnectionName: Q4(N7, e7), obstacles: y7.obstacles, layerCount: y7.layerCount, connMap: e7, colorMap: {}, preserveRouteEndpoints: true });
if (n11.solve(), !n11.solved || n11.failed)
throw new Error(`Regional via merge failed: ${n11.error}`);
const o11 = new Map(n11.mergedViaHdRoutes.map((t57) => [t57.connectionName, t57]));
M7 = undefined, N7 = N7.map((t57) => o11.get(t57.connectionName) ?? t57);
}
}
const w7 = SI({ srj: y7, routes: N7 });
if (!w7.every(({ key: t55, severity: e8 }) => x7.has(t55) && e8 <= x7.get(t55) + 0.00000001) || PI({ srj: y7, previousRoutes: u7, routes: N7 }).length > 0)
continue;
M7 === undefined && (M7 = i7({ traces: [], routes: N7, hdRoutes: N7 }), a7.referenceValidationCount++);
const T7 = Array.isArray(M7) ? M7 : M7.errors;
if (!(T7.length >= m7.length) && (u7 = N7, m7 = T7, p7 = M7, x7 = new Map(w7.map((t55) => [t55.key, t55.severity])), a7.acceptedRegionCount++, s7.revisitChangedRegions && (b7.length = 0), a7.finalDrcIssueCount = m7.length, m7.length === 0))
return a7.routes = u7, a7.publishedDrcIssueCount = 0, a7.repaired = true, a7;
}
return (({ originalSrj: t55, initialErrors: e8, remainingErrors: n8 }) => {
if (n8.length >= e8.length)
return false;
const o8 = new Set(t55.obstacles.flatMap((t56) => {
const e10 = t56.circuitJsonMetadata;
return [e10?.pcb_smtpad_id, e10?.pcb_plated_hole_id].filter((t57) => typeof t57 == "string");
})), i8 = [...e8];
for (const t56 of n8) {
if (typeof t56.pcb_trace_id != "string")
return false;
const e10 = `overlap_${t56.pcb_trace_id}_`, n10 = t56.type === "pcb_trace_error" && typeof t56.pcb_trace_error_id == "string" && t56.pcb_trace_error_id.startsWith(e10) ? t56.pcb_trace_error_id.slice(e10.length) : undefined, r8 = t56.type === "pcb_pad_trace_clearance_error", s8 = r8 ? t56.pcb_pad_id : n10;
if (typeof s8 != "string" || !o8.has(s8))
return false;
const a8 = i8.findIndex((e11) => e11.type === t56.type && e11.pcb_trace_id === t56.pcb_trace_id && (r8 ? e11.pcb_pad_id === s8 : e11.pcb_trace_error_id === t56.pcb_trace_error_id));
if (a8 === -1)
return false;
const c8 = i8.splice(a8, 1)[0];
if (r8 && (typeof t56.actual_clearance != "number" || !Number.isFinite(t56.actual_clearance) || typeof c8.actual_clearance != "number" || !Number.isFinite(c8.actual_clearance) || typeof t56.minimum_clearance != "number" || !Number.isFinite(t56.minimum_clearance) || t56.minimum_clearance !== c8.minimum_clearance || t56.actual_clearance < c8.actual_clearance))
return false;
}
return true;
})({ originalSrj: t54, initialErrors: g7, remainingErrors: m7 }) && (a7.routes = u7, a7.publishedDrcIssueCount = m7.length), a7;
};
var F6 = [3, 4, 5, 6, 8];
var j6 = (t54, e7) => {
const n7 = typeof t54.pcb_pad_id == "string" ? t54.pcb_pad_id : typeof t54.pcb_trace_error_id == "string" ? t54.pcb_trace_error_id.match(/(pcb_(?:smtpad|plated_hole|hole|keepout)_\d+)$/)?.[1] : undefined;
if (n7) {
const t55 = e7.obstacles.find((t56) => t56.obstacleId === n7 || t56.connectedTo[0] === n7);
if (t55)
return t55.center;
}
return ((t55) => {
const e8 = t55.center;
return e8 && typeof e8 == "object" && "x" in e8 && "y" in e8 && typeof e8.x == "number" && typeof e8.y == "number" ? { x: e8.x, y: e8.y } : undefined;
})(t54);
};
var $6 = ({ error: t54, routeIndexByTraceId: e7 }) => {
const n7 = typeof t54.pcb_trace_id == "string" ? t54.pcb_trace_id : undefined, o7 = [...typeof t54.pcb_via_id == "string" ? [t54.pcb_via_id] : [], ...Array.isArray(t54.pcb_via_ids) ? t54.pcb_via_ids.filter((t55) => typeof t55 == "string") : []], i7 = n7 ? `overlap_${n7}_` : undefined, r7 = i7 && typeof t54.pcb_trace_error_id == "string" && t54.pcb_trace_error_id.startsWith(i7) ? t54.pcb_trace_error_id.slice(i7.length) : undefined, s7 = r7 !== undefined && o7.includes(r7);
return [n7, ...Array.isArray(t54.pcb_trace_ids) ? t54.pcb_trace_ids : [], s7 ? undefined : r7].filter((t55) => typeof t55 == "string" && e7.has(t55)).filter((t55, e8, n8) => n8.indexOf(t55) === e8);
};
var Y6 = (t54) => t54.filter((t55) => t55.type === "pcb_via_clearance_error" || Array.isArray(t55.pcb_via_ids)).length;
var X6 = (t54, e7) => {
const n7 = new Map;
for (const e8 of t54)
n7.set(e8.connectionName, (n7.get(e8.connectionName) ?? 0) + 1);
return t54.map((t55, o7) => {
const i7 = n7.get(t55.connectionName) > 1 ? `${t55.connectionName}_regional_${o7}` : t55.connectionName;
return i7 !== t55.connectionName && e7.addConnections([[i7, t55.connectionName, t55.rootConnectionName ?? t55.connectionName]]), { ...t55, connectionName: i7, preloadedTraceId: `pipeline9_joint_candidate_${o7}`, preloadedTraceIndex: o7, preloadedRouteIndex: 0, isThroughObstacle: false };
});
};
var W6 = (t54, e7) => t54.minX <= e7.maxX && t54.maxX >= e7.minX && t54.minY <= e7.maxY && t54.maxY >= e7.minY;
var V6 = (t54) => ({ minX: t54.center.x - t54.diameter / 2, maxX: t54.center.x + t54.diameter / 2, minY: t54.center.y - t54.diameter / 2, maxY: t54.center.y + t54.diameter / 2 });
var H6 = (t54) => ({ minX: t54.center.x - t54.width / 2, maxX: t54.center.x + t54.width / 2, minY: t54.center.y - t54.height / 2, maxY: t54.center.y + t54.height / 2 });
var G6 = (t54, e7) => {
const n7 = c6(t54);
return n7.wireSegments.some((t55) => W6(((t56) => ({ minX: Math.min(t56.start.x, t56.end.x) - t56.width / 2, maxX: Math.max(t56.start.x, t56.end.x) + t56.width / 2, minY: Math.min(t56.start.y, t56.end.y) - t56.width / 2, maxY: Math.max(t56.start.y, t56.end.y) + t56.width / 2 }))(t55), e7)) || n7.viaSpans.some((t55) => W6(V6(t55), e7));
};
var U6 = ({ routes: t54, fixedObstacleRoutes: e7, routeIndex: n7, center: o7, regionSize: i7, srj: r7, connMap: s7, colorMap: a7, viaDiameter: c7, traceWidth: l7, obstacleMargin: h7, effort: d7 }) => {
const u7 = X6(t54, s7), p7 = u7[n7];
if (!p7)
return;
const m7 = { capacityMeshNodeId: `pipeline9_joint_drc_${n7}_${i7}`, center: o7, width: i7, height: i7, availableZ: Array.from({ length: r7.layerCount }, (t55, e8) => e8), portPoints: [], portPointsInPairs: [] }, g7 = _9(m7, [p7]), f7 = g7.fixedRouteSectionsByConnectionName.get(p7.connectionName);
if (!f7)
return;
const y7 = u7.filter((t55, e8) => e8 !== n7), _7 = new v6({ nodePortPoints: [g7.nodeWithPortPoints], fixedHdRoutes: [...y7, ...e7].map((t55) => ({ ...t55, rootConnectionName: s7.getNetConnectedToId(t55.rootConnectionName ?? t55.connectionName) ?? t55.rootConnectionName ?? t55.connectionName })), connMap: s7, colorMap: a7, obstacles: r7.obstacles, layerCount: r7.layerCount, viaDiameter: c7, traceWidth: l7, obstacleMargin: h7, effort: d7, preserveTerminalPcbPortIds: true, includeBoardObstacles: true, enableRegionalFallback: false, maxB01Rips: 120 });
if (_7.solve(), !_7.solved || _7.failed)
return;
const b7 = _7.routes.find((t55) => t55.connectionName === p7.connectionName);
return b7 ? { routes: t54.map((t55, e8) => e8 === n7 ? { ...x9(f7, b7), connectionName: t55.connectionName } : t55), usedFallback: Number(_7.stats.fallbackNodeCount ?? 0) > 0 } : undefined;
};
var Z6 = ({ routes: t54, fixedRouteCopperSpatialIndex: e7, center: n7, regionSize: o7, srj: i7, connMap: r7, colorMap: s7, viaDiameter: a7, traceWidth: c7, obstacleMargin: l7, effort: h7 }) => {
const d7 = X6(t54, r7), u7 = { capacityMeshNodeId: "pipeline9_joint_drc_regular_fallback", center: n7, width: o7, height: o7, availableZ: Array.from({ length: i7.layerCount }, (t55, e8) => e8), portPoints: [], portPointsInPairs: [] }, p7 = _9(u7, d7);
if (p7.fixedRouteSectionsByConnectionName.size === 0)
return;
if (!((t55) => {
const e8 = d9(t55);
return t55.portPoints.every((t56) => Ts({ point: t56, bounds: e8 }) === "on-boundary");
})(p7.nodeWithPortPoints))
return;
const m7 = [...p7.fixedRouteSectionsByConnectionName.values()].flatMap((t55) => t55.sourceRoutes).reduce((t55, e8) => {
const n8 = c6(e8);
return Math.max(t55, e8.viaDiameter / 2, ...n8.wireSegments.map((t56) => t56.width / 2), ...n8.viaSpans.map((t56) => t56.diameter / 2));
}, Math.max(c7 / 2, a7 / 2)), g7 = { minX: n7.x - o7 / 2 - l7 - m7, maxX: n7.x + o7 / 2 + l7 + m7, minY: n7.y - o7 / 2 - l7 - m7, maxY: n7.y + o7 / 2 + l7 + m7 }, f7 = e7.getRoutesOverlappingBounds(g7), y7 = h6({ fixedObstacleRoutes: f7, layerCount: i7.layerCount }), _7 = new g6({ nodeWithPortPoints: p7.nodeWithPortPoints, colorMap: s7, connMap: r7, viaDiameter: a7, traceWidth: c7, obstacleMargin: l7, effort: h7, obstacles: [...i7.obstacles, ...y7], layerCount: i7.layerCount });
if (_7.solve(), !_7.solved || _7.failed)
return;
const b7 = _7.getOutput(), x7 = new Map(b7.map((t55) => [t55.connectionName, t55])), v7 = new Map, I7 = new Set;
for (const [t55, e8] of p7.fixedRouteSectionsByConnectionName) {
const n8 = x7.get(t55);
if (!n8)
return;
v7.set(e8.sourceRoutes[0].preloadedTraceIndex, x9(e8, n8));
for (const t56 of e8.sourceRoutes.slice(1))
I7.add(t56.preloadedTraceIndex);
}
const S7 = d7.flatMap((e8, n8) => I7.has(n8) ? [] : [{ ...v7.get(n8) ?? e8, connectionName: t54[n8].connectionName }]);
return (({ candidateRoutes: t55, fixedObstacleRoutes: e8, obstacleMargin: n8, connMap: o8, candidateBounds: i8 }) => {
for (const r8 of t55)
for (const t56 of e8)
if (!d6(r8, t56, o8) && p6({ left: r8, right: t56, clearance: n8, leftBounds: i8 }))
return true;
return false;
})({ candidateRoutes: S7, fixedObstacleRoutes: f7, obstacleMargin: l7, connMap: r7, candidateBounds: g7 }) ? undefined : S7;
};
var q6 = ({ srj: t54, routes: e7, fixedObstacleRoutes: n7, newConnections: o7, syntheticConnectionNames: i7, drcEvaluator: r7, initialErrors: s7, allowTracePairRepair: a7 = false, preloadRepairTraceIds: c7, connMap: l7, colorMap: h7, viaDiameter: d7, traceWidth: u7, obstacleMargin: p7, effort: m7 }) => {
let g7 = e7, f7 = s7 ?? P6(r7, g7), y7 = 0, _7 = 0, b7 = 0, x7 = 0, v7 = false;
const I7 = ((t55) => {
if (!Number.isInteger(t55) || t55 < 0)
throw new Error("Pipeline9 regional repair route count must be nonnegative");
const e8 = Math.floor(7000 / Math.max(1, t55));
return Math.max(16, Math.min(192, e8));
})(e7.length), S7 = f7.filter((t55) => (({ error: t56, preloadRepairTraceIds: e8 }) => !!M6(t56).some((t57) => e8.has(t57)) || (t56.__collapsed_trace_participants ?? []).flatMap((t57) => new Set(t57.evaluationTraceIds).size > 1 ? [t57.solverTraceId] : []).some((t57) => e8.collidingFixedTraceIds?.has(t57)))({ error: t55, preloadRepairTraceIds: c7 })).length, C7 = R6({ routes: g7, newConnections: o7, syntheticConnectionNames: i7 }), P7 = a7 && f7.some((t55) => ((t56, e8) => !(t56.type !== "pcb_trace_error" || typeof t56.pcb_via_id == "string" || Array.isArray(t56.pcb_via_ids) && t56.pcb_via_ids.length > 0) && $6({ error: t56, routeIndexByTraceId: e8 }).length === 2)(t55, C7));
if (S7 === 0 && !P7)
return { routes: g7, attemptedCandidateCount: y7, acceptedCandidateCount: _7, fallbackCandidateCount: b7, candidateSearchCount: x7, candidateSearchBudget: I7, candidateSearchBudgetExhausted: v7, safeTraceLayerRepairSkippedForBudget: false, remainingDrcIssueCount: f7.length, preloadEligibleDrcIssueCount: S7, preloadRepairAttempted: false };
const M7 = ((t55) => {
const e8 = new Map, n8 = (t56, n10) => {
const o8 = Math.floor(n10.minX / 4), i8 = Math.floor(n10.maxX / 4), r8 = Math.floor(n10.minY / 4), s8 = Math.floor(n10.maxY / 4);
for (let n11 = o8;n11 <= i8; n11++)
for (let o10 = r8;o10 <= s8; o10++) {
const i10 = `${n11}:${o10}`, r10 = e8.get(i10) ?? new Set;
r10.add(t56), e8.set(i10, r10);
}
};
for (let e10 = 0;e10 < t55.length; e10++) {
const o8 = c6(t55[e10]);
for (const t56 of o8.wireSegments)
for (const o10 of l6(t56, 4, 1))
n8(e10, H6(o10));
for (const t56 of o8.viaSpans)
n8(e10, V6(t56));
}
return { getRoutesOverlappingBounds: (n10) => {
const o8 = new Set, i8 = Math.floor(n10.minX / 4), r8 = Math.floor(n10.maxX / 4), s8 = Math.floor(n10.minY / 4), a8 = Math.floor(n10.maxY / 4);
for (let t56 = i8;t56 <= r8; t56++)
for (let n11 = s8;n11 <= a8; n11++)
for (const i10 of e8.get(`${t56}:${n11}`) ?? [])
o8.add(i10);
return [...o8].sort((t56, e10) => t56 - e10).map((e10) => t55[e10]).filter((t56) => G6(t56, n10));
} };
})(n7);
for (let e8 = 0;e8 < 2 && !v7; e8++) {
let e10 = false;
const s8 = R6({ routes: g7, newConnections: o7, syntheticConnectionNames: i7 }), a8 = f7.filter((t55) => (t55.type === "pcb_trace_error" || t55.type === "pcb_pad_trace_clearance_error" || t55.type === "pcb_via_trace_clearance_error" || t55.type === "pcb_via_clearance_error") && typeof t55.pcb_trace_id == "string");
for (const o8 of a8) {
if (v7)
break;
const i8 = j6(o8, t54), a10 = $6({ error: o8, routeIndexByTraceId: s8 });
if (!i8)
continue;
let c8 = g7, S8 = f7;
for (const e11 of a10.slice(0, 2)) {
if (v7)
break;
const o10 = s8.get(e11);
if (o10 !== undefined) {
for (const e12 of F6) {
if (x7 >= I7) {
v7 = true;
break;
}
x7++;
const s10 = U6({ routes: g7, fixedObstacleRoutes: n7, routeIndex: o10, center: i8, regionSize: e12, srj: t54, connMap: l7, colorMap: h7, viaDiameter: d7, traceWidth: u7, obstacleMargin: p7, effort: m7 });
if (!s10)
continue;
y7++, s10.usedFallback && b7++;
const a11 = P6(r7, s10.routes);
if (T6(a11, S8) && (c8 = s10.routes, S8 = a11), S8.length === 0)
break;
}
if (S8.length === 0)
break;
}
}
if (c8 !== g7 || v7 || (x7 >= I7 ? v7 = true : x7++), c8 === g7 && !v7) {
const e11 = Z6({ routes: g7, fixedRouteCopperSpatialIndex: M7, center: i8, regionSize: 3, srj: t54, connMap: l7, colorMap: h7, viaDiameter: d7, traceWidth: u7, obstacleMargin: p7, effort: m7 });
if (e11) {
y7++, b7++;
const t55 = P6(r7, e11);
T6(t55, S8) && (c8 = e11, S8 = t55);
}
}
if (c8 !== g7 && (g7 = c8, f7 = S8, _7++, e10 = true), v7)
break;
}
if (!e10 || f7.length === 0)
break;
}
if (_7 > 0 && f7.length > 0) {
const e8 = NE({ ...t54}, g7, m7, 1, l7);
if (e8 !== g7) {
const t55 = P6(r7, e8);
Y6(t55) <= Y6(f7) && T6(t55, f7) && (g7 = e8, f7 = t55);
}
}
const N7 = f7.some((t55) => t55.type === "pcb_trace_error" || t55.type === "pcb_pad_trace_clearance_error"), w7 = N7 && v7;
if (N7 && !v7) {
const e8 = new ZA({ srj: { ...t54, traces: undefined }, hdRoutes: g7, connMap: l7, effort: m7, drcEvaluator: r7, maxIterations: 8, enableLargeBoardBroadFallback: false, enableTargetedErrorSweep: false, enablePostSolveClearanceRelaxation: false, enableSafeTraceLayerMoves: true, enableViaInPadLayerMoves: false });
if (e8.solve(), e8.failed)
throw new Error(`Pipeline9 post-regional safe trace-layer repair failed: ${e8.error ?? "unknown error"}`);
const n8 = e8.getOutput(), o8 = P6(r7, n8);
T6(o8, f7) && (g7 = n8, f7 = o8);
}
return { routes: g7, attemptedCandidateCount: y7, acceptedCandidateCount: _7, fallbackCandidateCount: b7, candidateSearchCount: x7, candidateSearchBudget: I7, candidateSearchBudgetExhausted: v7, safeTraceLayerRepairSkippedForBudget: w7, remainingDrcIssueCount: f7.length, preloadEligibleDrcIssueCount: S7, preloadRepairAttempted: S7 > 0 };
};
var J6 = [0.9, 0.72];
var Q6 = Array.from({ length: 16 }, (t54, e7) => e7 * Math.PI / 8);
var K6 = (t54) => t54.type === "pcb_pad_trace_clearance_error" || t54.type === "pcb_trace_error" && !(Array.isArray(t54.pcb_trace_ids) && t54.pcb_trace_ids.length >= 2);
var t82 = (t54) => {
if (typeof t54.pcb_pad_id == "string")
return t54.pcb_pad_id;
if (typeof t54.pcb_trace_error_id == "string") {
const e8 = t54.pcb_trace_error_id.match(/(pcb_(?:smtpad|plated_hole|hole|keepout)_\d+)$/)?.[1];
if (e8)
return e8;
}
const e7 = typeof t54.message == "string" ? t54.message : "";
return e7.match(/(?:pcb_smtpad|pcb_plated_hole|pcb_hole|pcb_keepout)\[#?([^\]"]+)\]/)?.[1];
};
var e8 = (t54, e7) => {
if (!e7)
return;
const n7 = e7.startsWith("pcb_") ? e7 : `pcb_${e7}`;
return t54.obstacles.find((t55) => t55.obstacleId === n7 || t55.connectedTo[0] === n7);
};
var n8 = ({ srj: t54, pcbPortId: e7, z: n7, portPositionMap: o7 }) => {
const i7 = Co(n7, t54.layerCount), r7 = o7.get(e7), s7 = t54.obstacles.filter((t55) => t55.layers.includes(i7) && t55.connectedTo.includes(e7));
return r7 ? s7.reduce((t55, e10) => t55 ? Math.hypot(e10.center.x - r7.x, e10.center.y - r7.y) < Math.hypot(t55.center.x - r7.x, t55.center.y - r7.y) ? e10 : t55 : e10, undefined) : s7[0];
};
var o8 = ({ terminalObstacle: t54, conflictingObstacle: e7, traceRadius: n7 }) => {
const o7 = Math.max(0, t54.width / 2 - n7), i7 = Math.max(0, t54.height / 2 - n7), r7 = (t54.ccwRotationDegrees ?? 0) * Math.PI / 180;
return J6.flatMap((e10) => Q6.map((n10) => {
const s7 = { x: Math.cos(n10) * o7 * e10, y: Math.sin(n10) * i7 * e10 }, a7 = (l7 = r7, { x: (c7 = s7).x * Math.cos(l7) - c7.y * Math.sin(l7), y: c7.x * Math.sin(l7) + c7.y * Math.cos(l7) });
var c7, l7;
return { x: t54.center.x + a7.x, y: t54.center.y + a7.y };
})).sort((t55, n10) => Math.hypot(n10.x - e7.center.x, n10.y - e7.center.y) - Math.hypot(t55.x - e7.center.x, t55.y - e7.center.y)).slice(0, 16);
};
var i8 = ({ routes: t54, routeIndex: e7, endpointIndex: n7, point: o7, bounds: i7, collapseAdjacent: r7 }) => {
const s7 = ((t55) => t55.map((t56) => ({ ...t56, route: t56.route.map((t57) => ({ ...t57 })), vias: t56.vias.map((t57) => ({ ...t57 })) })))(t54), a7 = s7[e7];
if (!a7 || a7.route.length < 2)
return;
const c7 = n7 === 0 ? 0 : a7.route.length - 1, l7 = n7 === 0 ? 1 : c7 - 1, h7 = a7.route[c7], d7 = a7.route[l7];
if (!h7 || !d7 || h7.z !== d7.z)
return;
const u7 = a7.traceThickness / 2;
if (!(o7.x - u7 < i7.minX || o7.x + u7 > i7.maxX || o7.y - u7 < i7.minY || o7.y + u7 > i7.maxY)) {
if (a7.route[c7] = { ...h7, ...o7 }, r7) {
const t55 = n7 === 0 ? l7 + 1 : l7 - 1, e10 = a7.route[t55], i10 = a7.vias.some((t56) => t56.x === d7.x && t56.y === d7.y);
if (!e10 || e10.z !== h7.z || d7.pcb_port_id !== undefined || i10)
return;
a7.route[l7] = { ...d7, ...o7 };
}
return s7;
}
};
var r8 = ({ srj: t54, originalSrj: e7, routes: n7, newConnections: o7, syntheticConnectionNames: i7, drcEvaluator: r7, effort: s7 = 1 }) => {
let a7 = n7, c7 = P6(r7, a7), l7 = 0, h7 = 0;
const d7 = c7.length < 20 || n7.length <= 120 ? 256 : Math.max(32, Math.min(256, Math.floor(16384 * Math.max(1, s7) / n7.length))), u7 = ((t55) => {
const e10 = new Map;
for (const n10 of t55.connections)
for (const t56 of n10.pointsToConnect)
t56.pcb_port_id && e10.set(t56.pcb_port_id, t56);
return e10;
})(e7);
for (let n10 = 0;n10 < 2; n10++) {
let n11 = false;
const s8 = R6({ routes: a7, newConnections: o7, syntheticConnectionNames: i7 });
for (const o10 of c7.filter(K6)) {
if (l7 >= d7)
break;
if (typeof o10.pcb_trace_id != "string")
continue;
const i10 = s8.get(o10.pcb_trace_id), p7 = e8(t54, t82(o10));
if (i10 === undefined || !p7)
continue;
const m7 = a7[i10];
let g7 = a7, f7 = c7;
t:
for (const n12 of [0, -1]) {
const o11 = n12 === 0 ? m7.route[0] : m7.route.at(-1);
if (!o11 || typeof o11.pcb_port_id != "string")
continue;
const s10 = n8({ srj: e7, pcbPortId: o11.pcb_port_id, z: o11.z, portPositionMap: u7 });
if (!s10 || s10 === p7)
continue;
const c8 = Math.hypot(p7.width, p7.height) / 2 + Math.hypot(s10.width, s10.height) / 2 + 0.5;
if (!(Math.hypot(o11.x - p7.center.x, o11.y - p7.center.y) > c8))
for (const e10 of o8({ terminalObstacle: s10, conflictingObstacle: p7, traceRadius: m7.traceThickness / 2 }))
for (const o12 of [false, true]) {
if (l7 >= d7)
break t;
const s11 = i8({ routes: a7, routeIndex: i10, endpointIndex: n12, point: e10, bounds: t54.bounds, collapseAdjacent: o12 });
if (!s11)
continue;
l7++;
const c10 = P6(r7, s11);
T6(c10, f7) && (g7 = s11, f7 = c10);
}
}
g7 !== a7 && (a7 = g7, c7 = f7, h7++, n11 = true);
}
if (!n11 || c7.length === 0)
break;
}
return { routes: a7, attemptedCandidateCount: l7, acceptedCandidateCount: h7, remainingErrors: c7 };
};
var s8 = ["pcb_trace_error_id", "pcb_error_id", "pcb_via_trace_clearance_error_id", "pcb_pad_trace_clearance_error_id"];
var a8 = (t54, e7) => {
let n7 = t54;
const o7 = [...e7].sort(([t55], [e10]) => e10.length - t55.length);
for (const [t55, e10] of o7)
n7 = n7.replaceAll(t55, e10);
return n7;
};
var c8 = (t54, e7) => {
const n7 = String(t54.type ?? t54.error_type ?? "unknown");
if (n7 === "pcb_via_clearance_error")
return ((t55, e10) => {
const n10 = [...typeof t55.pcb_trace_id == "string" ? [t55.pcb_trace_id] : [], ...Array.isArray(t55.pcb_trace_ids) ? t55.pcb_trace_ids.filter((t56) => typeof t56 == "string") : []].map((t56) => a8(t56, e10)).filter((t56, e11, n11) => n11.indexOf(t56) === e11).sort(), o10 = t55.center && typeof t55.center == "object" ? t55.center : t55.pcb_center && typeof t55.pcb_center == "object" ? t55.pcb_center : undefined, i7 = typeof o10?.x == "number" && typeof o10.y == "number" ? { x: o10.x, y: o10.y } : undefined, r7 = typeof t55.pcb_via_pair_net_relation == "string" ? t55.pcb_via_pair_net_relation : undefined;
if (n10.length !== 0 && i7 && r7)
return `pcb_via_clearance_error:${JSON.stringify({ traceIds: n10, center: i7, netRelation: r7 })}`;
})(t54, e7);
for (const o10 of s8) {
const i7 = t54[o10];
if (typeof i7 == "string")
return `${n7}:${a8(i7, e7)}`;
}
const o7 = Object.fromEntries(Object.entries(t54).filter(([t55, e10]) => (t55.endsWith("_id") || t55.endsWith("_ids")) && (typeof e10 == "string" || Array.isArray(e10))).sort(([t55], [e10]) => t55.localeCompare(e10)).map(([t55, n10]) => [t55, typeof n10 == "string" ? a8(n10, e7) : n10]));
return `${n7}:${JSON.stringify(o7)}`;
};
var l8 = ({ errors: t54, baselineErrors: e7, originalTraceIdByPreparedTraceId: n7 = new Map }) => {
const o7 = new Set(e7.filter((t55) => !((t56) => typeof t56.pcb_trace_error_id == "string" && t56.pcb_trace_error_id.startsWith("missing_connection_"))(t55)).map((t55) => c8(t55, new Map)));
return o7.delete(undefined), t54.filter((t55) => {
const e10 = c8(t55, n7);
return e10 === undefined || !o7.has(e10);
});
};
var h8 = 1.5;
var d8 = ({ errorsWithCenters: t54, traces: e7, layerCount: n7, defaultViaDiameter: o7, connMap: i7 }) => {
const r7 = ((t55) => t55.flatMap((t56) => {
if (t56.type !== "pcb_trace_error" || !Array.isArray(t56.pcb_port_ids) || t56.pcb_port_ids.length < 4)
return [];
const e10 = t56.center;
return e10 && typeof e10 == "object" && "x" in e10 && "y" in e10 && typeof e10.x == "number" && typeof e10.y == "number" ? [{ x: e10.x, y: e10.y }] : [];
}))(t54), s7 = new Set;
for (let t55 = 0;t55 < e7.length; t55++) {
const a7 = e7[t55], c7 = k9(a7, t55, n7, o7, i7);
r7.some((t56) => c7.some((e10) => {
const n10 = e10.route.map((t57) => t57.x), o10 = e10.route.map((t57) => t57.y);
return Math.min(...n10) <= t56.x + h8 && Math.max(...n10) >= t56.x - h8 && Math.min(...o10) <= t56.y + h8 && Math.max(...o10) >= t56.y - h8;
})) && s7.add(a7.pcb_trace_id);
}
return s7;
};
var u8 = ({ routes: t54, otherHdRoutes: e7, obstacles: n7, colorMap: o7, layerCount: i7, connMap: r7 }) => {
const s7 = Q4([...t54, ...e7], r7), a7 = new qk({ inputHdRoutes: t54, otherHdRoutes: e7, netByConnectionName: s7, obstacles: n7, colorMap: o7, layerCount: i7, connMap: r7 });
if (a7.solve(), a7.failed)
throw new Error(`Pipeline9 could not merge movable preloaded vias: ${a7.error ?? "unknown error"}`);
return a7.getMergedViaHdRoutes() ?? t54;
};
var p8 = ({ errors: t54, circuitJson: e7, newTraceIds: n7 }) => {
const o7 = new Map(e7.flatMap((t55) => t55.type === "pcb_via" && typeof t55.pcb_via_id == "string" && typeof t55.pcb_trace_id == "string" ? [[t55.pcb_via_id, t55.pcb_trace_id]] : []));
return t54.map((t55) => {
const e10 = typeof t55.pcb_trace_id == "string" ? t55.pcb_trace_id : undefined, i7 = Array.isArray(t55.pcb_trace_ids) ? t55.pcb_trace_ids.filter((t56) => typeof t56 == "string") : [], r7 = [...typeof t55.pcb_via_id == "string" ? [t55.pcb_via_id] : [], ...Array.isArray(t55.pcb_via_ids) ? t55.pcb_via_ids.filter((t56) => typeof t56 == "string") : []].filter((t56, e11, n10) => n10.indexOf(t56) === e11);
if (e10 && typeof t55.pcb_trace_error_id == "string") {
const s10 = `overlap_${e10}_`, a10 = t55.pcb_trace_error_id.startsWith(s10) ? t55.pcb_trace_error_id.slice(s10.length) : undefined, c10 = a10 !== undefined && (r7.includes(a10) || o7.has(a10) && !i7.includes(a10)), l7 = i7.find((t56) => t56 !== e10 && n7.has(t56)) ?? (a10 && !c10 ? a10 : undefined);
if (!n7.has(e10) && r7.length === 0 && l7 && n7.has(l7)) {
const n10 = [l7, e10, ...i7].filter((t56, e11, n11) => n11.indexOf(t56) === e11);
return { ...t55, pcb_trace_id: l7, pcb_trace_ids: n10, pcb_trace_error_id: `overlap_${l7}_${e10}` };
}
}
const s7 = r7.flatMap((t56) => {
const e11 = o7.get(t56);
return e11 ? [e11] : [];
}).filter((t56, e11, n10) => n10.indexOf(t56) === e11), a7 = s7.length > 0 ? s7 : i7.filter((t56) => t56 !== e10), c7 = a7.find((t56) => n7.has(t56));
if (c7 && (!e10 || !n7.has(e10))) {
const n10 = [c7, ...e10 ? [e10] : [], ...i7, ...a7].filter((t56, e11, n11) => n11.indexOf(t56) === e11);
return { ...t55, pcb_trace_id: c7, pcb_trace_ids: n10, pcb_via_id: r7[0], pcb_via_ids: r7 };
}
if (r7.length > 0) {
const n10 = [...e10 ? [e10] : [], ...i7, ...a7].filter((t56, e11, n11) => n11.indexOf(t56) === e11);
return { ...t55, pcb_trace_ids: n10, pcb_via_id: r7[0], pcb_via_ids: r7 };
}
return t55;
});
};
var m8 = 0.000000001;
var g8 = (t54) => {
const e7 = new Set, n7 = [];
for (const o7 of t54)
for (const t55 of o7.route) {
if (t55.route_type !== "via")
continue;
const i7 = `${t55.x},${t55.y},${t55.from_layer},${t55.to_layer}`;
e7.has(i7) || (e7.add(i7), n7.push({ type: "pcb_via", pcb_via_id: `via_${n7.length}`, pcb_trace_id: o7.pcb_trace_id }));
}
return n7;
};
var f8 = ({ errors: t54, circuitJson: e7, evaluatedTraceIds: n7 }) => {
const o7 = new Map(e7.flatMap((t55) => t55.type === "pcb_via" && typeof t55.pcb_via_id == "string" && typeof t55.pcb_trace_id == "string" ? [[t55.pcb_via_id, t55.pcb_trace_id]] : []));
return t54.map((t55) => {
const e10 = [...typeof t55.pcb_via_id == "string" ? [t55.pcb_via_id] : [], ...Array.isArray(t55.pcb_via_ids) ? t55.pcb_via_ids.filter((t56) => typeof t56 == "string") : []], i7 = typeof t55.pcb_trace_id == "string" ? t55.pcb_trace_id : undefined, r7 = i7 ? `overlap_${i7}_` : undefined, s7 = r7 && typeof t55.pcb_trace_error_id == "string" && t55.pcb_trace_error_id.startsWith(r7) ? t55.pcb_trace_error_id.slice(r7.length) : undefined, a7 = typeof t55.pcb_trace_error_id == "string" ? t55.pcb_trace_error_id.match(/_(via_\d+)$/)?.[1] : undefined, c7 = e10.length !== 0 || !a7 || !o7.has(a7) || s7 && n7.has(s7) ? undefined : a7, l7 = [...e10, ...c7 ? [c7] : []].filter((t56, e11, n10) => n10.indexOf(t56) === e11), h7 = [...typeof t55.pcb_trace_id == "string" ? [t55.pcb_trace_id] : [], ...Array.isArray(t55.pcb_trace_ids) ? t55.pcb_trace_ids.filter((t56) => typeof t56 == "string") : [], ...l7.flatMap((t56) => {
const e11 = o7.get(t56);
return e11 ? [e11] : [];
})].filter((t56, e11, n10) => n10.indexOf(t56) === e11);
return { ...t55, ...l7.length > 0 ? { pcb_via_id: l7[0], pcb_via_ids: l7 } : {}, ...l7.length > 0 && h7.length > 0 ? { pcb_trace_ids: h7 } : {} };
});
};
var y8 = (t54, e7) => Math.abs(t54.x - e7.x) <= m8 && Math.abs(t54.y - e7.y) <= m8 && t54.z === e7.z;
var _8 = ({ trace: t54, sectionGroup: e7, syntheticConnectionName: n7, connMap: o7 }) => {
const i7 = e7.routes;
if (i7.length === 0)
throw new Error(`Pipeline9 cannot exactly repair empty preloaded section for trace "${t54.pcb_trace_id}"`);
const r7 = [];
for (const e10 of i7) {
if (r7.length === 0) {
r7.push(...e10.route);
continue;
}
const n10 = r7.at(-1);
if (e10.route[0] && y8(n10, e10.route[0]))
r7.push(...e10.route.slice(1));
else {
if (!e10.route.at(-1) || !y8(n10, e10.route.at(-1)))
throw new Error(`Pipeline9 cannot reconnect preloaded trace "${t54.pcb_trace_id}" for exact repair`);
r7.push(...e10.route.slice(0, -1).reverse());
}
}
const s7 = e7.routePositionStart === 0, a7 = e7.routePositionEnd === t54.route.length - 1, c7 = s7 ? t54.connectsTo?.[0] : null, l7 = a7 ? t54.connectsTo?.at(-1) : null;
return c7 && r7[0] && (r7[0] = { ...r7[0], pcb_port_id: c7 }), l7 && r7.at(-1) && (r7[r7.length - 1] = { ...r7.at(-1), pcb_port_id: l7 }), { connectionName: n7, rootConnectionName: o7.getNetConnectedToId(t54.connection_name) ?? t54.connection_name, traceThickness: Math.max(...i7.map((t55) => t55.traceThickness)), viaDiameter: Math.max(...i7.map((t55) => t55.viaDiameter)), route: r7, vias: r7.slice(0, -1).flatMap((t55, e10) => {
const n10 = r7[e10 + 1];
return t55.z !== n10.z && (o10 = t55, i10 = n10, Math.abs(o10.x - i10.x) <= m8 && Math.abs(o10.y - i10.y) <= m8) ? [{ x: n10.x, y: n10.y }] : [];
var o10, i10;
}) };
};
var b8 = ({ trace: t54, traceIndex: e7, layerCount: n7, defaultViaDiameter: o7, connMap: i7 }) => {
const r7 = t54.route.flatMap((t55, e10) => t55.route_type === "through_obstacle" ? [e10] : []), s7 = new Map, a7 = k9(t54, e7, n7, o7, i7);
for (const e10 of a7) {
const { preloadedRoutePositionStart: n10, preloadedRoutePositionEnd: o10 } = e10;
if (n10 === undefined || o10 === undefined)
throw new Error(`Pipeline9 preloaded trace section is missing route positions for "${t54.pcb_trace_id}"`);
if (t54.route[n10]?.route_type === "through_obstacle")
continue;
const i10 = r7.filter((t55) => t55 < n10).length, a10 = s7.get(i10) ?? { routePositionStart: n10, routePositionEnd: o10, routes: [] };
a10.routePositionStart = Math.min(a10.routePositionStart, n10), a10.routePositionEnd = Math.max(a10.routePositionEnd, o10), a10.routes.push(e10), s7.set(i10, a10);
}
return [...s7.values()];
};
var x8 = (t54, e7) => t54.map((t55) => {
const n7 = Array.isArray(t55.pcb_trace_ids) ? t55.pcb_trace_ids.filter((t56) => typeof t56 == "string") : [], o7 = typeof t55.pcb_trace_id == "string" ? t55.pcb_trace_id : undefined, i7 = o7 ? `overlap_${o7}_` : undefined, r7 = i7 && typeof t55.pcb_trace_error_id == "string" && t55.pcb_trace_error_id.startsWith(i7) ? t55.pcb_trace_error_id.slice(i7.length) : undefined, s7 = [...typeof t55.pcb_via_id == "string" ? [t55.pcb_via_id] : [], ...Array.isArray(t55.pcb_via_ids) ? t55.pcb_via_ids.filter((t56) => typeof t56 == "string") : []], a7 = r7 !== undefined && s7.includes(r7), c7 = [o7, ...n7, a7 ? undefined : r7].filter((t56) => typeof t56 == "string"), l7 = new Map;
for (const t56 of c7) {
const n10 = e7.get(t56) ?? t56, o10 = l7.get(n10) ?? new Set;
o10.add(t56), l7.set(n10, o10);
}
const h7 = [...l7].flatMap(([t56, e10]) => e10.size > 1 ? [{ solverTraceId: t56, evaluationTraceIds: [...e10] }] : []), d7 = o7 ? e7.get(o7) ?? o7 : undefined, u7 = n7.map((t56) => e7.get(t56) ?? t56), p7 = r7 ? a7 ? r7 : e7.get(r7) ?? r7 : undefined;
return d7 !== o7 || u7.some((t56, e10) => t56 !== n7[e10]) || p7 !== r7 ? { ...t55, ...o7 ? { pcb_trace_id: d7 } : {}, ...Array.isArray(t55.pcb_trace_ids) ? { pcb_trace_ids: u7 } : {}, ...d7 && p7 ? { pcb_trace_error_id: `overlap_${d7}_${p7}` } : {}, ...h7.length > 0 ? { __collapsed_trace_participants: h7 } : {} } : t55;
});
var v8 = (t54, e7) => {
const n7 = t54.hdRoute.route[0], o7 = t54.hdRoute.route.at(-1);
return { name: t54.syntheticConnectionName, rootConnectionName: t54.hdRoute.rootConnectionName, __netConnectionName: t54.originalTrace.connection_name, nominalTraceWidth: t54.hdRoute.traceThickness, pointsToConnect: [{ x: n7.x, y: n7.y, layer: Co(n7.z, e7), pointId: `${t54.syntheticConnectionName}:start` }, { x: o7.x, y: o7.y, layer: Co(o7.z, e7), pointId: `${t54.syntheticConnectionName}:end` }] };
};
var I8 = ({ originalTrace: t54, repairedSections: e7 }) => {
const n7 = [];
let o7 = 0;
for (const i7 of [...e7].sort((t55, e10) => t55.routePositionStart - e10.routePositionStart)) {
if (i7.routePositionStart < o7)
throw new Error(`Pipeline9 found overlapping repaired sections for preloaded trace "${t54.pcb_trace_id}"`);
n7.push(...t54.route.slice(o7, i7.routePositionStart), ...i7.route), o7 = i7.routePositionEnd + 1;
}
return n7.push(...t54.route.slice(o7)), { ...t54, __replaces_pcb_trace_id: t54.pcb_trace_id, route: n7 };
};
var S8 = class extends si {
params;
inputNewHdRoutes;
inputUpdatedPreloadedTraces;
movablePreloadedSections;
fixedPreloadedObstacleRoutes;
syntheticConnectionNames;
exactRepairSolver;
drcEvaluator;
cachedReferenceDrcEvaluator;
clearancePrecisionDrcEvaluator;
clearancePrecisionIndexedDrcEvaluator;
clearanceMarginDrcEvaluator;
referenceDrcValidationCount = 0;
referenceDrcFalseNegativeCount = 0;
indexedDrcEvaluationCount = 0;
indexedDrcCacheHitCount = 0;
indexedDrcEvaluationTimeMs = 0;
indexedDrcCandidateCache = new Map;
combinedOutput;
cacheIndexedDrcResult(t54, e7) {
if (this.indexedDrcCandidateCache.size >= 64) {
const t55 = this.indexedDrcCandidateCache.keys().next().value;
t55 !== undefined && this.indexedDrcCandidateCache.delete(t55);
}
this.indexedDrcCandidateCache.set(t54, e7);
}
constructor(t54) {
super(), this.params = t54, this.inputNewHdRoutes = t54.newHdRoutes, this.inputUpdatedPreloadedTraces = t54.updatedPreloadedTraces;
const e7 = t54.updatedPreloadedTraces.filter((e10) => t54.mutatedPreloadedTraceIds.has(e10.pcb_trace_id)), n7 = C4({ connections: t54.newConnections, originalConnections: t54.originalSrj.connections, layerCount: t54.layerCount, obstacles: t54.obstacles, defaultViaHoleDiameter: t54.defaultViaHoleDiameter, connMap: t54.connMap }), o7 = n7(t54.newHdRoutes), i7 = new Set(o7.map((t55) => t55.pcb_trace_id)), r7 = (({ originalPreloadedTraces: t55, mutatedPreloadedTraces: e10, newTraces: n10 }) => {
const o10 = new Set(n10.map((t56) => t56.pcb_trace_id)), i10 = new Map(e10.map((t56) => [t56.pcb_trace_id, t56])), r10 = new Set([...t55.map((t56) => t56.pcb_trace_id), ...o10]), s10 = new Map;
return { routedTraces: [...t55.filter((t56) => o10.has(t56.pcb_trace_id)).map((t56) => {
const e11 = i10.get(t56.pcb_trace_id) ?? t56, n11 = `${t56.pcb_trace_id}_preloaded`;
let o11 = n11, a10 = 2;
for (;r10.has(o11); )
o11 = `${n11}_${a10}`, a10 += 1;
return r10.add(o11), s10.set(o11, t56.pcb_trace_id), { ...e11, pcb_trace_id: o11, __replaces_pcb_trace_id: t56.pcb_trace_id };
}), ...e10.filter((t56) => !o10.has(t56.pcb_trace_id)), ...n10], originalPreloadedTraceIdByPreparedTraceId: s10 };
})({ originalPreloadedTraces: t54.originalSrj.traces ?? [], mutatedPreloadedTraces: e7, newTraces: o7 }), s7 = t54.originalSrj.minTraceToPadEdgeClearance ?? I6.traceClearance ?? 0.1, a7 = I6.viaClearance, c7 = C6({ includeBoardClearance: true, inputSrj: t54.originalSrj, srjWithPointPairs: t54.srjWithPointPairs, routedTraces: [], drcOptions: { traceClearance: s7 } }), l7 = new Set((t54.originalSrj.traces ?? []).map((t55) => t55.pcb_trace_id)), h7 = f8({ errors: c7.errors, circuitJson: c7.circuitJson, evaluatedTraceIds: l7 }), d7 = f8({ errors: c7.errorsWithCenters, circuitJson: c7.circuitJson, evaluatedTraceIds: l7 }), u7 = C6({ includeBoardClearance: true, inputSrj: t54.originalSrj, srjWithPointPairs: t54.srjWithPointPairs, routedTraces: r7.routedTraces, drcOptions: { traceClearance: s7 } }), p7 = new Set(S6(t54.originalSrj.traces ?? [], r7.routedTraces).map((t55) => t55.pcb_trace_id)), m7 = f8({ errors: u7.errors, circuitJson: u7.circuitJson, evaluatedTraceIds: p7 }), g7 = f8({ errors: u7.errorsWithCenters, circuitJson: u7.circuitJson, evaluatedTraceIds: p7 }), f7 = { ...u7, errors: l8({ errors: m7, baselineErrors: h7, originalTraceIdByPreparedTraceId: r7.originalPreloadedTraceIdByPreparedTraceId }), errorsWithCenters: l8({ errors: g7, baselineErrors: d7, originalTraceIdByPreparedTraceId: r7.originalPreloadedTraceIdByPreparedTraceId }) }, y7 = (({ errors: t55, circuitJson: e10 }) => {
const n10 = new Map(e10.flatMap((t56) => t56.type === "pcb_via" && typeof t56.pcb_via_id == "string" && typeof t56.pcb_trace_id == "string" ? [[t56.pcb_via_id, t56.pcb_trace_id]] : [])), o10 = new Set;
for (const e11 of t55) {
const t56 = typeof e11.pcb_trace_id == "string" ? e11.pcb_trace_id : undefined, i10 = [...typeof e11.pcb_via_id == "string" ? [e11.pcb_via_id] : [], ...Array.isArray(e11.pcb_via_ids) ? e11.pcb_via_ids.filter((t57) => typeof t57 == "string") : []];
if (typeof e11.pcb_trace_id == "string" && o10.add(e11.pcb_trace_id), Array.isArray(e11.pcb_trace_ids))
for (const t57 of e11.pcb_trace_ids)
typeof t57 == "string" && o10.add(t57);
if (typeof e11.pcb_via_id == "string") {
const t57 = n10.get(e11.pcb_via_id);
t57 && o10.add(t57);
}
if (Array.isArray(e11.pcb_via_ids))
for (const t57 of e11.pcb_via_ids) {
if (typeof t57 != "string")
continue;
const e12 = n10.get(t57);
e12 && o10.add(e12);
}
const r10 = t56 ? `overlap_${t56}_` : undefined;
if (r10 && typeof e11.pcb_trace_error_id == "string" && e11.pcb_trace_error_id.startsWith(r10)) {
const t57 = e11.pcb_trace_error_id.slice(r10.length);
i10.includes(t57) || o10.add(t57);
}
}
return o10;
})({ errors: f7.errors, circuitJson: f7.circuitJson }), _7 = new Map(t54.updatedPreloadedTraces.map((t55) => [t55.pcb_trace_id, t55])), b7 = new Set;
for (const t55 of y7) {
const e10 = r7.originalPreloadedTraceIdByPreparedTraceId.get(t55);
e10 && _7.has(e10) ? b7.add(e10) : !i7.has(t55) && _7.has(t55) && b7.add(t55);
}
for (const e10 of d8({ errorsWithCenters: f7.errorsWithCenters, traces: t54.updatedPreloadedTraces, layerCount: t54.layerCount, defaultViaDiameter: t54.defaultViaDiameter, connMap: t54.connMap }))
b7.add(e10);
this.movablePreloadedSections = [];
for (const e10 of b7) {
const n10 = _7.get(e10);
if (!n10)
throw new Error(`Pipeline9 cannot find preloaded trace "${e10}" selected for exact repair`);
const o10 = t54.updatedPreloadedTraces.findIndex((t55) => t55.pcb_trace_id === e10), i10 = b8({ trace: n10, traceIndex: o10, layerCount: t54.layerCount, defaultViaDiameter: t54.defaultViaDiameter, connMap: t54.connMap });
for (const [e11, o11] of i10.entries()) {
const i11 = `pipeline9_preloaded_drc_${this.movablePreloadedSections.length}`;
this.movablePreloadedSections.push({ originalTrace: n10, originalRoutePositionStart: o11.routePositionStart, originalRoutePositionEnd: o11.routePositionEnd, syntheticConnectionName: i11, evaluationTraceId: `${n10.pcb_trace_id}__pipeline9_section_${e11}`, hdRoute: _8({ trace: n10, sectionGroup: o11, syntheticConnectionName: i11, connMap: t54.connMap }) });
}
}
this.syntheticConnectionNames = new Set(this.movablePreloadedSections.map((t55) => t55.syntheticConnectionName));
const x7 = new Set(this.movablePreloadedSections.map((t55) => t55.originalTrace.pcb_trace_id));
this.fixedPreloadedObstacleRoutes = t54.updatedPreloadedTraces.flatMap((e10, n10) => {
const o10 = k9(e10, n10, t54.layerCount, t54.defaultViaDiameter, t54.connMap);
return x7.has(e10.pcb_trace_id) ? o10.filter((t55) => {
const n11 = t55.preloadedRoutePositionStart;
return n11 !== undefined && e10.route[n11]?.route_type === "through_obstacle";
}) : o10;
});
const v7 = new Map;
for (const [t55, e10] of this.movablePreloadedSections.entries()) {
const n10 = e10.originalTrace.pcb_trace_id, o10 = v7.get(n10) ?? [];
o10.push(t55), v7.set(n10, o10);
}
for (const e10 of (({ errors: t55, circuitJson: e11, originalTraceIdByPreparedTraceId: n10 }) => {
const o10 = new Map(e11.flatMap((t56) => t56.type === "pcb_via" && typeof t56.pcb_via_id == "string" && typeof t56.pcb_trace_id == "string" ? [[t56.pcb_via_id, t56.pcb_trace_id]] : []));
return t55.flatMap((t56) => {
if (t56.type !== "pcb_via_clearance_error" || !Array.isArray(t56.pcb_via_ids) || typeof t56.actual_clearance != "number" || t56.actual_clearance >= 0)
return [];
const e12 = t56.pcb_via_ids.flatMap((t57) => {
if (typeof t57 != "string")
return [];
const e13 = o10.get(t57);
return e13 ? [n10.get(e13) ?? e13] : [];
}).filter((t57, e13, n11) => n11.indexOf(t57) === e13);
return e12.length > 0 ? [e12] : [];
});
})({ errors: f7.errors, circuitJson: f7.circuitJson, originalTraceIdByPreparedTraceId: r7.originalPreloadedTraceIdByPreparedTraceId })) {
const n10 = e10.flatMap((t55) => v7.get(t55) ?? []).filter((t55, e11, n11) => n11.indexOf(t55) === e11);
if (n10.length === 0)
continue;
const o10 = new Set(n10), i10 = u8({ routes: n10.map((t55) => this.movablePreloadedSections[t55].hdRoute), otherHdRoutes: [...t54.newHdRoutes, ...this.fixedPreloadedObstacleRoutes, ...this.movablePreloadedSections.flatMap((t55, e11) => o10.has(e11) ? [] : [t55.hdRoute])], obstacles: t54.obstacles, colorMap: t54.colorMap, layerCount: t54.layerCount, connMap: t54.connMap });
for (let t55 = 0;t55 < n10.length; t55++)
this.movablePreloadedSections[n10[t55]].hdRoute = i10[t55];
}
const I7 = t54.newHdRoutes.length + this.movablePreloadedSections.length, S7 = f7.errors.length >= 20 && I7 > 120 ? Math.min(1, 120 * Math.max(1, t54.effort) / I7) : 1, C7 = f7.errors.length >= 200 ? S7 ** 2 : S7, P7 = Math.max(f7.errors.length >= 200 ? 2 : 8, Math.floor(32 * C7)), M7 = Math.max(f7.errors.length >= 200 ? 1 : 4, Math.floor(12 * C7));
if (this.stats = { initialJointDrcIssueCount: f7.errors.length, baselineJointDrcIssueCount: c7.errors.length, initialJointDrcIssueCountByType: f7.errors.reduce((t55, e10) => {
const n10 = String(e10.type ?? e10.error_type ?? "unknown");
return t55[n10] = (t55[n10] ?? 0) + 1, t55;
}, {}), movablePreloadedTraceCount: x7.size, movablePreloadedSectionCount: this.movablePreloadedSections.length, exactRepairConfiguredMaxIterations: P7, exactRepairConfiguredViaInPadMaxIterations: P7, exactRepairConfiguredBroadMaxIterations: M7 }, f7.errors.length === 0)
return void (this.solved = true);
const N7 = new Set(this.movablePreloadedSections.map((t55) => t55.originalTrace.pcb_trace_id)), w7 = e7.filter((t55) => !N7.has(t55.pcb_trace_id)), T7 = new Map(this.movablePreloadedSections.map((e10) => [e10.syntheticConnectionName, v8(e10, t54.layerCount)])), { traces: R7, ...E7 } = t54.srjWithPointPairs, A7 = { ...E7, connections: [...t54.srjWithPointPairs.connections, ...T7.values()] }, O7 = new cC({ ...A7, obstacles: t54.originalSrj.obstacles, minTraceWidth: t54.originalSrj.minTraceWidth, minViaDiameter: t54.originalSrj.minViaDiameter ?? t54.defaultViaDiameter }, { connMap: t54.connMap, traceClearance: s7, viaClearance: a7, includeTraceViaOwnerMetadata: true, spatialCellSize: Math.max(t54.defaultViaDiameter, t54.originalSrj.minTraceWidth) + Math.max(s7, a7) }), k7 = O7.evaluate(t54.originalSrj.traces ?? []), D7 = g8(t54.originalSrj.traces ?? []), L7 = { ...k7, errors: f8({ errors: k7.errors, circuitJson: D7, evaluatedTraceIds: l7 }), errorsWithCenters: f8({ errors: k7.errorsWithCenters, circuitJson: D7, evaluatedTraceIds: l7 }) };
let z7;
const B7 = (e10) => {
const o10 = e10.filter((t55) => !this.syntheticConnectionNames.has(t55.connectionName)), i10 = n7(o10), r10 = q4(i10, t54.originalSrj.traces ?? []), s10 = new Set, a10 = new Map, c10 = this.movablePreloadedSections.map((n10) => {
const o11 = e10.find((t55) => t55.connectionName === n10.syntheticConnectionName);
if (!o11)
throw new Error(`Pipeline9 joint DRC repair lost preloaded section "${n10.syntheticConnectionName}"`);
const i11 = n10.originalTrace.pcb_trace_id;
a10.set(n10.evaluationTraceId, i11);
const r11 = !s10.has(i11);
return s10.add(i11), { ...n10.originalTrace, pcb_trace_id: n10.evaluationTraceId, ...r11 ? { __replaces_pcb_trace_id: i11 } : { __replaces_pcb_trace_id: undefined }, route: To(o11, t54.layerCount, { defaultViaHoleDiameter: t54.defaultViaHoleDiameter, obstacles: t54.obstacles, connMap: t54.connMap }) };
}), l10 = new Map;
for (let t55 = 0;t55 < i10.length; t55++)
l10.set(r10[t55].pcb_trace_id, i10[t55].pcb_trace_id);
for (const t55 of this.movablePreloadedSections)
l10.set(t55.evaluationTraceId, `${t55.syntheticConnectionName}_0`);
const h10 = new Set(l10.values()), d10 = [...w7, ...c10, ...r10];
return { evaluatedTraces: S6(t54.originalSrj.traces ?? [], d10), movableTraceIds: h10, originalTraceIdByEvaluationTraceId: a10, routedTraces: d10, solverTraceIdByEvaluationTraceId: l10 };
}, F7 = ({ errors: t55, errorsWithCenters: e10, circuitJson: n10, movableTraceIds: o10, solverTraceIdByEvaluationTraceId: i10 }) => {
const r10 = n10.map((t56) => {
if (!("pcb_trace_id" in t56) || typeof t56.pcb_trace_id != "string")
return t56;
const e11 = i10.get(t56.pcb_trace_id);
return e11 ? { ...t56, pcb_trace_id: e11 } : t56;
});
return { errors: p8({ errors: x8(t55, i10), circuitJson: r10, newTraceIds: o10 }), errorsWithCenters: p8({ errors: x8(e10, i10), circuitJson: r10, newTraceIds: o10 }) };
}, j7 = { source: ii(t54.originalSrj === t54.srjWithPointPairs ? t54.originalSrj : { ...t54.originalSrj, connections: [...t54.srjWithPointPairs.connections, ...t54.originalSrj.connections] }), route: ii(t54.srjWithPointPairs) }, $ = ({ routes: e10, hdRoutes: n10 }, o10 = true) => {
const i10 = e10 ?? n10;
if (!i10)
throw new Error("Pipeline9 reference DRC repair requires HD routes");
const r10 = B7(i10), a10 = C6({ includeBoardClearance: true, connectivityMaps: j7, inputSrj: t54.originalSrj, srjWithPointPairs: t54.srjWithPointPairs, routedTraces: r10.routedTraces, drcOptions: { traceClearance: s7, includeTraceContinuity: o10 } }), c10 = new Set(r10.evaluatedTraces.map((t55) => t55.pcb_trace_id)), l10 = f8({ errors: a10.errors, circuitJson: a10.circuitJson, evaluatedTraceIds: c10 }), u10 = f8({ errors: a10.errorsWithCenters, circuitJson: a10.circuitJson, evaluatedTraceIds: c10 }), p10 = l8({ errors: l10, baselineErrors: h7, originalTraceIdByPreparedTraceId: r10.originalTraceIdByEvaluationTraceId }), m10 = l8({ errors: u10, baselineErrors: d7, originalTraceIdByPreparedTraceId: r10.originalTraceIdByEvaluationTraceId });
return F7({ errors: p10, errorsWithCenters: m10, circuitJson: a10.circuitJson, movableTraceIds: r10.movableTraceIds, solverTraceIdByEvaluationTraceId: r10.solverTraceIdByEvaluationTraceId });
}, Y7 = ({ routes: t55, hdRoutes: e10 }) => {
const n10 = t55 ?? e10;
if (!n10)
throw new Error("Pipeline9 cached reference DRC requires HD routes");
const o10 = JSON.stringify(n10);
if (z7?.candidateKey === o10)
return z7.result;
this.referenceDrcValidationCount += 1;
const i10 = $({ routes: n10, hdRoutes: n10 });
return z7 = { candidateKey: o10, result: i10 }, i10;
};
this.cachedReferenceDrcEvaluator = Y7, this.clearancePrecisionDrcEvaluator = ({ routes: t55, hdRoutes: e10 }) => $({ routes: t55, hdRoutes: e10 }, false);
const X7 = (e10) => {
const n10 = B7(e10);
return hO(t54.srjWithPointPairs, n10.routedTraces, { minTraceWidth: t54.originalSrj.minTraceWidth, minViaDiameter: t54.originalSrj.minViaDiameter, originalSrj: t54.originalSrj, includeOriginalConnections: true, connectivityMaps: j7 });
};
let W7;
this.clearanceMarginDrcEvaluator = (t55, e10, n10) => (W7?.routes !== n10 && (W7 = { routes: n10, circuitJson: X7(n10) }), (({ circuitJson: t56, originalCircuitJson: e11, targets: n11 }) => {
const o10 = new Map(t56.filter((t57) => t57.type === "pcb_trace").map((t57) => [t57.pcb_trace_id, t57])), i10 = new Map(e11.filter((t57) => t57.type === "pcb_trace").map((t57) => [t57.pcb_trace_id, t57])), r10 = t56.filter((t57) => t57.type === "pcb_via"), s10 = new Map;
for (const e12 of t56)
e12.type === "pcb_via" ? s10.set(e12.pcb_via_id, e12) : e12.type === "pcb_smtpad" ? s10.set(e12.pcb_smtpad_id, e12) : e12.type === "pcb_plated_hole" && s10.set(e12.pcb_plated_hole_id, e12);
const a10 = [];
for (const t57 of n11) {
const n12 = t57.type === "pcb_via_trace_clearance_error", c10 = n12 ? t57.pcb_via_id : t57.pcb_pad_id;
if (!n12 && t57.type !== "pcb_pad_trace_clearance_error" || typeof t57.pcb_trace_id != "string" || typeof c10 != "string" || typeof t57.minimum_clearance != "number" || !Number.isFinite(t57.minimum_clearance) || t57.minimum_clearance <= 0)
throw new Error("Pipeline9 clearance margin requires a valid target pair");
const l10 = i10.get(t57.pcb_trace_id), h10 = e11.find((t58) => n12 ? t58.type === "pcb_via" && t58.pcb_via_id === c10 : t58.type === "pcb_smtpad" && t58.pcb_smtpad_id === c10 || t58.type === "pcb_plated_hole" && t58.pcb_plated_hole_id === c10);
if (!l10 || !h10)
throw new Error(`Pipeline9 clearance margin has no original target ${c10}/${t57.pcb_trace_id}`);
const d10 = o10.get(t57.pcb_trace_id);
let u10 = s10.get(c10);
if (n12) {
if (h10.type !== "pcb_via" || typeof h10.pcb_trace_id != "string")
throw new Error("Pipeline9 clearance margin requires the original via owner");
const t58 = i10.get(h10.pcb_trace_id);
if (!t58)
throw new Error("Pipeline9 clearance margin lost the original via owner");
const e12 = t58.route.filter((t59) => t59.route_type === "via"), n13 = e12.map((t59, e13) => ({ segment: t59, index: e13 })).filter(({ segment: t59 }) => t59.x === h10.x && t59.y === h10.y && h10.layers.includes(t59.from_layer) && h10.layers.includes(t59.to_layer) && (t59.from_layer === h10.layers[0] && t59.to_layer === h10.layers.at(-1) || t59.to_layer === h10.layers[0] && t59.from_layer === h10.layers.at(-1))).filter(({ segment: t59 }, e13, n14) => n14.findIndex((e14) => e14.segment.from_layer === t59.from_layer && e14.segment.to_layer === t59.to_layer) === e13);
if (n13.length === 0)
throw new Error("Pipeline9 clearance margin lost the original via transition");
if (n13.length !== 1)
return { status: "unsupported-identity" };
const s11 = n13[0].index, a11 = o10.get(h10.pcb_trace_id), c11 = a11?.route.filter((t59) => t59.route_type === "via");
if (!c11 || c11.length !== e12.length || c11.some((t59, n14) => t59.from_layer !== e12[n14].from_layer || t59.to_layer !== e12[n14].to_layer))
return { status: "unsupported-identity" };
const l11 = c11[s11];
u10 = r10.filter((t59) => t59.x === l11.x && t59.y === l11.y && t59.layers.join() === h10.layers.join()).reduce((t59, e13) => !t59 || e13.outer_diameter > t59.outer_diameter ? e13 : t59, undefined);
}
if (!(d10 && u10 && ("x" in u10) && ("y" in u10)))
return { status: "unsupported-identity" };
const p10 = { minClearance: t57.minimum_clearance + 1 }, m10 = n12 ? WS([d10, u10], p10) : XS([d10, u10], p10), g10 = t57.minimum_clearance + 0.01;
for (const e12 of m10) {
const n13 = e12.actual_clearance;
if (typeof n13 != "number" || !Number.isFinite(n13))
throw new Error("Pipeline9 clearance margin requires a finite measurement");
n13 >= g10 || a10.push({ ...t57, ...u10.type === "pcb_via" ? { pcb_via_id: u10.pcb_via_id, pcb_via_ids: [u10.pcb_via_id] } : {}, actual_clearance: n13, minimum_clearance: g10, center: { x: u10.x, y: u10.y } });
}
}
return { status: "measured", errors: a10 };
})({ circuitJson: X7(t55), originalCircuitJson: W7.circuitJson, targets: e10 })), this.clearancePrecisionIndexedDrcEvaluator = ({ routes: t55, hdRoutes: e10 }) => {
const n10 = t55 ?? e10;
if (!n10)
throw new Error("Pipeline9 clearance ranking requires HD routes");
const o10 = B7(n10);
return O7.evaluate(o10.evaluatedTraces);
};
const V7 = ({ routes: t55, hdRoutes: e10 }) => {
const n10 = t55 ?? e10;
if (!n10)
throw new Error("Pipeline9 joint DRC repair requires HD routes");
const o10 = JSON.stringify(n10), i10 = this.indexedDrcCandidateCache.get(o10);
if (i10 !== undefined)
return this.indexedDrcCacheHitCount += 1, i10;
const r10 = performance.now();
this.indexedDrcEvaluationCount += 1;
const s10 = B7(n10), a10 = O7.evaluate(s10.evaluatedTraces), c10 = g8(s10.evaluatedTraces), l10 = new Set(s10.evaluatedTraces.map((t56) => t56.pcb_trace_id)), h10 = f8({ errors: a10.errors, circuitJson: c10, evaluatedTraceIds: l10 }), d10 = f8({ errors: a10.errorsWithCenters, circuitJson: c10, evaluatedTraceIds: l10 }), u10 = l8({ errors: h10, baselineErrors: L7.errors, originalTraceIdByPreparedTraceId: s10.originalTraceIdByEvaluationTraceId }), p10 = l8({ errors: d10, baselineErrors: L7.errorsWithCenters, originalTraceIdByPreparedTraceId: s10.originalTraceIdByEvaluationTraceId });
if (u10.length === 0) {
const t56 = this.referenceDrcValidationCount, e11 = Y7({ routes: n10, hdRoutes: n10 }), i11 = Array.isArray(e11) ? e11 : e11.errors;
return this.referenceDrcValidationCount > t56 && i11.length > 0 && (this.referenceDrcFalseNegativeCount += 1), this.indexedDrcEvaluationTimeMs += performance.now() - r10, this.cacheIndexedDrcResult(o10, e11), e11;
}
const m10 = F7({ errors: u10, errorsWithCenters: p10, circuitJson: c10, movableTraceIds: s10.movableTraceIds, solverTraceIdByEvaluationTraceId: s10.solverTraceIdByEvaluationTraceId });
return this.indexedDrcEvaluationTimeMs += performance.now() - r10, this.cacheIndexedDrcResult(o10, m10), m10;
};
this.drcEvaluator = V7, this.exactRepairSolver = new qA({ srj: A7, hdRoutes: [...t54.newHdRoutes, ...this.movablePreloadedSections.map((t55) => t55.hdRoute)], connMap: t54.connMap, effort: t54.effort, viaHoleDiameter: t54.defaultViaHoleDiameter, drcEvaluator: V7, viaInPadDrcEvaluator: V7, maxIterations: P7, enableBroadFallback: false, enableLargeBoardBroadFallback: false, enableTargetedErrorSweep: true, enableTraceViaOwnerTargeting: true, enablePostSolveClearanceRelaxation: false, enableSafeTraceLayerMoves: true, enableViaInPadLayerMoves: t54.originalSrj.allowViaInPad ?? false, viaInPadMaxIterations: P7, broadMaxIterations: M7, broadPassMultiplier: 3 * C7 }), this.activeSubSolver = this.exactRepairSolver, this.MAX_ITERATIONS = this.exactRepairSolver.MAX_ITERATIONS + 1;
}
getSolverName() {
return "Pipeline9JointDrcRepairSolver";
}
_step() {
if (!this.exactRepairSolver)
return void (this.solved = true);
if (this.exactRepairSolver.step(), this.progress = this.exactRepairSolver.progress, this.exactRepairSolver.failed)
return this.failed = true, void (this.error = this.exactRepairSolver.error);
if (!this.exactRepairSolver.solved)
return;
let t54 = this.exactRepairSolver.getOutput();
const e7 = this.exactRepairSolver.stats.finalDrcIssueCount, n7 = typeof e7 == "number" && Number.isFinite(e7) && e7 >= 0 ? e7 : undefined;
let o7, i7 = 0, r7 = 0, s7 = 0, a7 = false;
const c7 = this.cachedReferenceDrcEvaluator({ traces: [], routes: t54, hdRoutes: t54 }), l7 = Array.isArray(c7) ? c7 : c7.errors;
if (o7 = l7.length, l7.length > 0) {
const e10 = (({ srj: t55, routes: e11, newConnections: n10, syntheticConnectionNames: o10, connMap: i10, indexedDrcEvaluator: r10, candidateDrcEvaluator: s10, marginDrcEvaluator: a10, drcEvaluator: c10, initialErrors: l10, initialErrorsWithCenters: h10 = l10 }) => {
const d10 = { routes: e11, attemptedCandidateCount: 0, candidateValidationCount: 0, referenceValidationCount: 0, repaired: false };
if ((t55.traces?.length ?? 0) > 0 || o10.size > 0)
return d10;
if (l10.length === 0)
return d10;
const u10 = R6({ routes: e11, newConnections: n10, syntheticConnectionNames: o10 }), p10 = new Map;
for (const e12 of t55.obstacles)
for (const t56 of [e12.obstacleId, e12.circuitJsonMetadata?.pcb_smtpad_id, e12.circuitJsonMetadata?.pcb_plated_hole_id, e12.connectedTo[0]])
typeof t56 == "string" && p10.set(t56, e12.center);
const m10 = O6({ errors: l10, errorsWithCenters: h10, routeIndexByTraceId: u10, padPositionById: p10 });
if (!m10)
return d10;
let g10 = m10;
const f10 = m10.errors, y7 = m10.errors.map((t56) => ({ ...t56, minimum_clearance: t56.minimum_clearance + 0.01 })), _7 = A6(y7);
if (_7 === undefined)
return d10;
let b7 = { errors: y7, deficit: _7 }, x7 = e11, v7 = 0, I7 = 0, S7 = 0;
for (let n11 = 0;n11 < 8; n11++) {
const n12 = new Map;
for (const t56 of [...b7.errors, ...g10.errors]) {
const e12 = JSON.stringify([t56.type, t56.pcb_trace_id, t56.pcb_pad_id, t56.pcb_via_id]);
n12.set(e12, t56);
}
const o11 = [...n12.values()];
let l11;
for (const e12 of E6) {
const n13 = oR(x7);
if (!hA(t55, n13, o11, u10, e12, i10, true, true, true, false))
continue;
const s11 = RE(n13);
v7++;
const a11 = r10({ traces: [], routes: s11, hdRoutes: s11 }), c11 = A6(Array.isArray(a11) ? a11 : a11.errors);
c11 !== undefined && (!l11 || c11 < l11.deficit) && (l11 = { routes: s11, deficit: c11 });
}
if (!l11)
break;
I7++;
const h11 = s10({ traces: [], routes: l11.routes, hdRoutes: l11.routes }), d11 = Array.isArray(h11) ? h11 : h11.errors, m11 = O6({ errors: d11, errorsWithCenters: Array.isArray(h11) ? h11 : h11.errorsWithCenters ?? h11.errors, routeIndexByTraceId: u10, padPositionById: p10 });
if (!m11)
break;
const y10 = a10(l11.routes, f10, e11);
if (y10.status === "unsupported-identity")
break;
const _10 = y10.errors, C7 = O6({ errors: _10, errorsWithCenters: _10, routeIndexByTraceId: u10, padPositionById: p10 });
if (!C7)
break;
if (d11.length === 0 && _10.length === 0) {
S7++;
const t56 = c10({ traces: [], routes: l11.routes, hdRoutes: l11.routes });
if ((Array.isArray(t56) ? t56 : t56.errors).length === 0)
return { routes: l11.routes, attemptedCandidateCount: v7, candidateValidationCount: I7, referenceValidationCount: S7, repaired: true };
break;
}
if (m11.deficit + C7.deficit >= g10.deficit + b7.deficit - 0.000000001)
break;
x7 = l11.routes, g10 = m11, b7 = C7;
}
return { routes: e11, attemptedCandidateCount: v7, candidateValidationCount: I7, referenceValidationCount: S7, repaired: false };
})({ srj: this.params.srj, routes: t54, newConnections: this.params.newConnections, syntheticConnectionNames: this.syntheticConnectionNames, connMap: this.params.connMap, indexedDrcEvaluator: this.clearancePrecisionIndexedDrcEvaluator, candidateDrcEvaluator: this.clearancePrecisionDrcEvaluator, marginDrcEvaluator: this.clearanceMarginDrcEvaluator, drcEvaluator: this.cachedReferenceDrcEvaluator, initialErrors: l7, initialErrorsWithCenters: Array.isArray(c7) ? c7 : c7.errorsWithCenters ?? c7.errors });
i7 = e10.attemptedCandidateCount, r7 = e10.candidateValidationCount, s7 = e10.referenceValidationCount, a7 = e10.repaired, e10.repaired && (t54 = e10.routes, o7 = 0);
}
if (o7 === 0)
return this.combinedOutput = t54, this.stats = { ...this.stats, ...this.exactRepairSolver.stats, postExactIndexedDrcIssueCount: n7, postExactReferenceValidationAttempted: true, postExactReferenceDrcIssueCount: 0, postExactReferenceAccepted: true, clearancePrecisionCandidateCount: i7, clearancePrecisionCandidateValidationCount: r7, clearancePrecisionReferenceValidationCount: s7, clearancePrecisionRepaired: a7, boundedRegionalRepairAttemptedRegionCount: 0, boundedRegionalRepairAcceptedRegionCount: 0, boundedRegionalRepairCandidateAttemptCount: 0, boundedRegionalRepairPathSearchNodeCount: 0, boundedRegionalRepairReferenceValidationCount: 0, boundedRegionalRepairRepaired: false, boundedRegionalRepairTimeMs: 0, regionalB01RepairCandidateCount: 0, regionalB01RepairAcceptedCount: 0, regionalB01RepairFallbackCandidateCount: 0, regionalB01RepairCandidateSearchCount: 0, regionalB01RepairCandidateSearchBudget: 0, regionalB01RepairCandidateSearchBudgetExhausted: false, regionalB01RepairSafeTraceLayerSkippedForBudget: false, regionalB01RepairRemainingDrcIssueCount: 0, regionalB01RepairPreloadEligibleDrcIssueCount: 0, regionalB01RepairAttempted: false, regionalB01RepairTraceIdCount: 0, terminalEscapeCandidateCount: 0, terminalEscapeAcceptedCount: 0, referenceDrcValidationCount: this.referenceDrcValidationCount, referenceDrcFalseNegativeCount: this.referenceDrcFalseNegativeCount, indexedDrcEvaluationCount: this.indexedDrcEvaluationCount, indexedDrcCacheHitCount: this.indexedDrcCacheHitCount, indexedDrcEvaluationTimeMs: this.indexedDrcEvaluationTimeMs, indexedDrcCandidateCacheSize: this.indexedDrcCandidateCache.size, indexedDrcCandidateCacheCapacity: 64 }, void (this.solved = true);
const h7 = r8({ srj: this.params.srj, originalSrj: this.params.originalSrj, routes: t54, newConnections: this.params.newConnections, syntheticConnectionNames: this.syntheticConnectionNames, drcEvaluator: this.drcEvaluator, effort: this.params.effort }), d7 = (({ routes: t55, newConnections: e10, syntheticConnectionNames: n10, fixedPreloadedObstacleRoutes: o10, updatedPreloadedTraces: i10 }) => {
const r10 = new Set, s10 = Object.assign(new Set, { collidingFixedTraceIds: r10 }), a10 = R6({ routes: t55, newConnections: e10, syntheticConnectionNames: n10 }), c10 = new Set;
for (const [e11, o11] of a10)
n10.has(t55[o11].connectionName) ? s10.add(e11) : c10.add(e11);
for (const t56 of o10) {
const e11 = i10[t56.preloadedTraceIndex];
if (!e11)
throw new Error(`Pipeline9 fixed preload route has invalid trace index ${t56.preloadedTraceIndex}`);
c10.has(e11.pcb_trace_id) ? r10.add(e11.pcb_trace_id) : s10.add(e11.pcb_trace_id);
}
return s10;
})({ routes: h7.routes, newConnections: this.params.newConnections, syntheticConnectionNames: this.syntheticConnectionNames, fixedPreloadedObstacleRoutes: this.fixedPreloadedObstacleRoutes, updatedPreloadedTraces: this.params.updatedPreloadedTraces }), u7 = q6({ srj: this.params.srj, routes: h7.routes, fixedObstacleRoutes: this.fixedPreloadedObstacleRoutes, newConnections: this.params.newConnections, syntheticConnectionNames: this.syntheticConnectionNames, drcEvaluator: this.drcEvaluator, initialErrors: h7.remainingErrors, allowTracePairRepair: true, preloadRepairTraceIds: d7, connMap: this.params.connMap, colorMap: this.params.colorMap, viaDiameter: this.params.defaultViaDiameter, traceWidth: this.params.srj.minTraceWidth, obstacleMargin: this.params.srj.defaultObstacleMargin ?? this.params.srj.minTraceToPadEdgeClearance ?? 0.15, effort: this.params.effort }), p7 = this.cachedReferenceDrcEvaluator({ traces: [], routes: u7.routes, hdRoutes: u7.routes }), m7 = ((t55, e10, n10) => {
const o10 = e10 >= 10 && t55 > 120, i10 = o10 ? Math.min(1, 120 * Math.max(1, n10) / t55) : 1, r10 = o10 && e10 > t55 / 4, s10 = Math.max(1, Math.floor(L6.maxCandidateAttempts * i10));
return { maxRegions: o10 ? 8 : L6.maxRegions, maxCandidateAttempts: s10 * (r10 ? 2 : 1), maxPathSearchNodes: Math.max(1, Math.floor(o10 ? 1e7 * i10 : L6.maxPathSearchNodes)), ...r10 ? { maxCandidateAttemptsPerRegion: Math.ceil(s10 / 2), pathGridSizeScale: 2 } : {}, ...o10 ? { maxPathSearchNodesPerCall: 500000, pathHeuristicWeight: e10 > t55 / 4 ? 3 : 2, revisitChangedRegions: true } : {} };
})(u7.routes.length, (Array.isArray(p7) ? p7 : p7.errors).length, this.params.effort), g7 = performance.now(), f7 = B6({ connMap: this.params.connMap, originalSrj: { ...this.params.originalSrj, connections: [...this.params.originalSrj.connections, ...this.params.newConnections] }, routes: u7.routes, viaHoleDiameter: this.params.defaultViaHoleDiameter, syntheticConnectionNames: this.syntheticConnectionNames, drcEvaluator: this.cachedReferenceDrcEvaluator, budget: m7 });
this.combinedOutput = f7.routes, this.stats = { ...this.stats, ...this.exactRepairSolver.stats, postExactIndexedDrcIssueCount: n7, postExactReferenceValidationAttempted: true, postExactReferenceDrcIssueCount: o7, postExactReferenceAccepted: false, clearancePrecisionCandidateCount: i7, clearancePrecisionCandidateValidationCount: r7, clearancePrecisionReferenceValidationCount: s7, clearancePrecisionRepaired: a7, boundedRegionalRepairAttemptedRegionCount: f7.attemptedRegionCount, boundedRegionalRepairAcceptedRegionCount: f7.acceptedRegionCount, boundedRegionalRepairCandidateAttemptCount: f7.candidateAttemptCount, boundedRegionalRepairPathSearchNodeCount: f7.pathSearchNodeCount, boundedRegionalRepairReferenceValidationCount: f7.referenceValidationCount, boundedRegionalRepairRepaired: f7.repaired, boundedRegionalRepairPublishedDrcIssueCount: f7.publishedDrcIssueCount, boundedRegionalRepairTimeMs: performance.now() - g7, regionalB01RepairCandidateCount: u7.attemptedCandidateCount, regionalB01RepairAcceptedCount: u7.acceptedCandidateCount, regionalB01RepairFallbackCandidateCount: u7.fallbackCandidateCount, regionalB01RepairCandidateSearchCount: u7.candidateSearchCount, regionalB01RepairCandidateSearchBudget: u7.candidateSearchBudget, regionalB01RepairCandidateSearchBudgetExhausted: u7.candidateSearchBudgetExhausted, regionalB01RepairSafeTraceLayerSkippedForBudget: u7.safeTraceLayerRepairSkippedForBudget, regionalB01RepairRemainingDrcIssueCount: u7.remainingDrcIssueCount, regionalB01RepairPreloadEligibleDrcIssueCount: u7.preloadEligibleDrcIssueCount, regionalB01RepairAttempted: u7.preloadRepairAttempted, regionalB01RepairTraceIdCount: d7.size + (d7.collidingFixedTraceIds?.size ?? 0), terminalEscapeCandidateCount: h7.attemptedCandidateCount, terminalEscapeAcceptedCount: h7.acceptedCandidateCount, referenceDrcValidationCount: this.referenceDrcValidationCount, referenceDrcFalseNegativeCount: this.referenceDrcFalseNegativeCount, indexedDrcEvaluationCount: this.indexedDrcEvaluationCount, indexedDrcCacheHitCount: this.indexedDrcCacheHitCount, indexedDrcEvaluationTimeMs: this.indexedDrcEvaluationTimeMs, indexedDrcCandidateCacheSize: this.indexedDrcCandidateCache.size, indexedDrcCandidateCacheCapacity: 64 }, this.solved = true;
}
getCombinedOutput() {
return this.combinedOutput ?? this.exactRepairSolver?.getOutput() ?? this.inputNewHdRoutes;
}
getOutput() {
return this.getCombinedOutput().filter((t54) => !this.syntheticConnectionNames.has(t54.connectionName));
}
getUpdatedPreloadedTraces() {
const t54 = new Map(this.getCombinedOutput().map((t55) => [t55.connectionName, t55])), e7 = new Map;
for (const n10 of this.movablePreloadedSections) {
const o7 = t54.get(n10.syntheticConnectionName);
if (!o7)
throw new Error(`Pipeline9 joint DRC repair output is missing "${n10.syntheticConnectionName}"`);
const i7 = n10.originalTrace.pcb_trace_id, r7 = e7.get(i7) ?? [];
r7.push({ routePositionStart: n10.originalRoutePositionStart, routePositionEnd: n10.originalRoutePositionEnd, route: To(o7, this.params.layerCount, { defaultViaHoleDiameter: this.params.defaultViaHoleDiameter, obstacles: this.params.obstacles, connMap: this.params.connMap }) }), e7.set(i7, r7);
}
const n7 = new Map([...e7].map(([t55, e10]) => {
const n10 = this.inputUpdatedPreloadedTraces.find((e11) => e11.pcb_trace_id === t55);
if (!n10)
throw new Error(`Pipeline9 cannot find preloaded trace "${t55}" while rebuilding repaired sections`);
return [t55, I8({ originalTrace: n10, repairedSections: e10 })];
}));
return this.inputUpdatedPreloadedTraces.map((t55) => n7.get(t55.pcb_trace_id) ?? t55);
}
getMutatedPreloadedTraces() {
const t54 = new Set([...this.params.mutatedPreloadedTraceIds, ...this.movablePreloadedSections.map((t55) => t55.originalTrace.pcb_trace_id)]);
return this.getUpdatedPreloadedTraces().filter((e7) => t54.has(e7.pcb_trace_id));
}
visualize() {
return this.exactRepairSolver?.visualize() ?? {};
}
};
var C8 = 0.000001;
var P8 = (t54, e7, n7) => {
const o7 = mo(t54, n7), i7 = mo(e7, n7);
return Array.from({ length: Math.abs(i7 - o7) + 1 }, (t55, e10) => Math.min(o7, i7) + e10);
};
var M8 = (t54) => t54.route_type === "wire";
var N8 = (t54, e7, n7) => t54.portPoints.filter((t55) => t55.availableZ.includes(n7) && !(t55._preloadedTracePortAssignments ?? []).some((t56) => t56.z === n7 && t56.fixedNetId !== e7.fixedNetId)).map((t55) => ({ portPoint: t55, distance: be(t55, e7.start, e7.end) })).sort((t55, e10) => t55.distance - e10.distance || t55.portPoint.distToCentermostPortOnZ - e10.portPoint.distToCentermostPortOnZ || t55.portPoint.segmentPortPointId.localeCompare(e10.portPoint.segmentPortPointId))[0]?.portPoint;
var w8 = (t54, e7, n7) => {
t54._preloadedFixedNetIds = [...new Set([...t54._preloadedFixedNetIds ?? [], e7.fixedNetId])].sort();
const o7 = e7.end.x - e7.start.x, i7 = e7.end.y - e7.start.y, r7 = o7 * o7 + i7 * i7, s7 = r7 === 0 ? 0 : Math.max(0, Math.min(1, ((t54.x - e7.start.x) * o7 + (t54.y - e7.start.y) * i7) / r7)), a7 = { traceId: e7.traceId, fixedNetId: e7.fixedNetId, routePosition: e7.routePositionStart + s7 * (e7.routePositionEnd - e7.routePositionStart), tracePoint: { x: e7.start.x + s7 * o7, y: e7.start.y + s7 * i7 }, z: n7 }, c7 = t54._preloadedTracePortAssignments ?? [];
c7.some((t55) => t55.traceId === a7.traceId && t55.fixedNetId === a7.fixedNetId && t55.z === a7.z && Math.abs(t55.routePosition - a7.routePosition) <= C8) || (t54._preloadedTracePortAssignments = [...c7, a7].sort((t55, e10) => t55.traceId.localeCompare(e10.traceId) || t55.routePosition - e10.routePosition || t55.z - e10.z));
};
var T8 = class extends si {
constructor(t54, e7) {
super(), this.sharedEdgeSegments = t54, this.srj = e7, this.MAX_ITERATIONS = 1, this.primitives = ((t55) => {
const e10 = [], n7 = ii(t55);
for (const o7 of t55.traces ?? []) {
if (!o7.connection_name)
throw new Error(`Preloaded trace "${o7.pcb_trace_id}" is missing a connection name`);
const i7 = n7.getNetConnectedToId(o7.connection_name) ?? o7.connection_name;
for (const [n10, r7] of o7.route.entries())
if (r7.route_type === "via")
e10.push({ traceId: o7.pcb_trace_id, fixedNetId: i7, connectionName: o7.connection_name, routePositionStart: n10, routePositionEnd: n10, zLayers: P8(r7.from_layer, r7.to_layer, t55.layerCount), start: r7, end: r7 });
else if (r7.route_type === "through_obstacle")
e10.push({ traceId: o7.pcb_trace_id, fixedNetId: i7, connectionName: o7.connection_name, routePositionStart: n10, routePositionEnd: n10 + 1, zLayers: P8(r7.from_layer, r7.to_layer, t55.layerCount), start: r7.start, end: r7.end });
else if (r7.route_type === "jumper") {
const s7 = mo(r7.layer, t55.layerCount);
for (const [t56, a7] of [r7.start, r7.end].entries())
e10.push({ traceId: o7.pcb_trace_id, fixedNetId: i7, connectionName: o7.connection_name, routePositionStart: n10 + t56, routePositionEnd: n10 + t56, zLayers: [s7], start: a7, end: a7 });
}
for (let n10 = 0;n10 < o7.route.length - 1; n10++) {
const r7 = o7.route[n10], s7 = o7.route[n10 + 1];
M8(r7) && M8(s7) && r7.layer === s7.layer && e10.push({ traceId: o7.pcb_trace_id, fixedNetId: i7, connectionName: o7.connection_name, routePositionStart: n10, routePositionEnd: n10 + 1, zLayers: [mo(r7.layer, t55.layerCount)], start: r7, end: s7 });
}
}
return e10;
})(e7);
}
primitives;
getSolverName() {
return "PreloadedTraceGraphSolver";
}
_step() {
for (const t55 of this.primitives)
for (const e10 of this.sharedEdgeSegments)
if (!(Mk(t55.start, t55.end, e10.start, e10.end) > C8))
for (const n7 of t55.zLayers) {
if (!e10.availableZ.includes(n7))
continue;
const o7 = N8(e10, t55, n7);
o7 && w8(o7, t55, n7);
}
const t54 = this.sharedEdgeSegments.flatMap((t55) => t55.portPoints), e7 = t54.filter((t55) => (t55._preloadedFixedNetIds?.length ?? 0) > 0);
this.stats = { preloadedTraceCount: this.srj.traces?.length ?? 0, preloadedTraceShapeCount: this.primitives.length, inputBoundaryCount: this.sharedEdgeSegments.length, outputBoundaryCount: this.sharedEdgeSegments.length, inputPortCount: t54.length, outputPortCount: t54.length, preloadedPortCount: e7.length, tracePortAssignmentCount: e7.reduce((t55, e10) => t55 + (e10._preloadedTracePortAssignments?.length ?? 0), 0), topologyChanged: false }, this.solved = true;
}
getOutput() {
if (!this.solved)
throw new Error("PreloadedTraceGraphSolver has not solved yet");
return this.sharedEdgeSegments;
}
};
var R8 = class extends Wq {
_step() {
if (this.error = Xq(this.inputSrj), this.error)
return void (this.failed = true);
const { traces: t54, ...e7 } = this.inputSrj, n7 = $q(e7), o7 = $q(Aq(Yq(n7)));
this.outputSrj = t54 === undefined ? o7 : { ...o7, traces: t54 }, this.solved = true;
}
};
function E8(t54) {
return new Set((t54 ?? []).filter((t55) => t55._isComponentTopologyNode).map((t55) => t55.capacityMeshNodeId));
}
function A8(t54, e7) {
return t54.nodeIds.some((t55) => e7.has(t55));
}
function O8({ sharedEdgeSegments: t54, componentCapacityMeshNodeIds: e7 }) {
return t54.filter((t55) => !A8(t55, e7));
}
function k8(t54, e7, n7, o7 = {}) {
return { solverName: t54, solverClass: e7, getConstructorParams: n7, onSolved: o7.onSolved };
}
var D8 = class extends si {
constructor(t54, e7 = {}) {
super(), this.srj = t54, this.opts = e7;
const n7 = $q(t54);
this.originalSrj = n7, this.opts = { ...e7 };
const o7 = this.opts;
if (this.effort = o7.effort ?? 1, this.MAX_ITERATIONS = 1e8 * this.effort, this.maxNodeDimension = o7.maxNodeDimension ?? 15, this.maxNodeRatio = o7.maxNodeRatio ?? 6, this.minNodeArea = o7.minNodeArea ?? 0.1 ** 2, this.visualizationTraceColorMode = o7.visualizationTraceColorMode ?? "layer", this.setSimpleRouteJson(n7), o7.capacityDepth === undefined) {
const t55 = this.srj.bounds.maxX - this.srj.bounds.minX, e10 = this.srj.bounds.maxY - this.srj.bounds.minY, n10 = Math.max(t55, e10), i7 = o7.targetMinCapacity ?? 0.5;
o7.capacityDepth = zO(n10, i7);
}
this.cacheProvider = o7.cacheProvider === undefined ? oo() : o7.cacheProvider === null ? null : o7.cacheProvider, this.startTimeOfPhase = {}, this.endTimeOfPhase = {}, this.timeSpentOnPhase = {};
}
getSolverName() {
return "AutoroutingPipelineSolver9_PreloadedTraceGraph";
}
preprocessSimpleRouteJsonSolver;
escapeViaLocationSolver;
netToPointPairsSolver;
componentTopologyGeneratorSolver;
topologyPlanningSolver;
topologyMergingSolver;
globalTopologyGeneratorSolver;
nodeDimensionSubdivisionSolver;
nodeTargetMerger;
edgeSolver;
colorMap;
highDensityRouteSolver;
highDensityForceImproveSolver;
highDensityRepairSolver;
highDensityStitchSolver;
globalDrcForceImproveSolver;
pipeline9JointDrcRepairSolver;
singleLayerNodeMerger;
strawSolver;
deadEndSolver;
traceSimplificationSolver;
mutatedPreloadedTraceSimplificationSolver;
lengthMatchingPostProcessingSolver;
powerTraceExpansionSolver;
availableSegmentPointSolver;
portPointPathingSolver;
multiSectionPortPointOptimizer;
uniformPortDistributionSolver;
traceWidthSolver;
necessaryCrampedPortPointSolver;
preloadedTraceGraphSolver;
componentDetectionSolver;
viaDiameter;
viaHoleDiameter;
minTraceWidth;
effort;
maxNodeDimension;
maxNodeRatio;
minNodeArea;
visualizationTraceColorMode;
startTimeOfPhase;
endTimeOfPhase;
timeSpentOnPhase;
activeSubSolver = null;
connMap;
srjWithEscapeViaLocations;
srjWithPointPairs;
originalSrj;
capacityNodes = null;
capacityEdges = null;
sharedEdgeSegmentsWithNecessaryCrampedPortPoints;
highDensityNodePortPoints;
cacheProvider = null;
pipelineDef = [k8("preprocessSimpleRouteJsonSolver", R8, (t54) => [t54.originalSrj, { traceColorMode: t54.visualizationTraceColorMode }], { onSolved: (t54) => {
t54.setSimpleRouteJson(t54.preprocessSimpleRouteJsonSolver.getOutputSimpleRouteJson());
} }), k8("componentDetectionSolver", S5, (t54) => [{ inputSrj: t54.srj }]), k8("escapeViaLocationSolver", rU, (t54) => [t54.srj, { viaDiameter: t54.viaDiameter, minTraceWidth: t54.minTraceWidth, obstacleMargin: t54.srj.defaultObstacleMargin ?? 0.15 }], { onSolved: (t54) => {
t54.srjWithEscapeViaLocations = t54.escapeViaLocationSolver?.getOutputSimpleRouteJson();
} }), k8("netToPointPairsSolver", dk, (t54) => {
const e7 = t54.srjWithEscapeViaLocations ?? t54.srj;
return [e7, t54.colorMap, ri(e7)];
}, { onSolved: (t54) => {
t54.srjWithPointPairs = t54.netToPointPairsSolver?.getNewSimpleRouteJson(), t54.colorMap = Eo(t54.srjWithPointPairs, t54.connMap), t54.connMap = ii(t54.srjWithPointPairs);
} }), k8("topologyPlanningSolver", G5, (t54) => [{ inputSrj: t54.srjWithPointPairs, componentDetectionOutput: t54.componentDetectionSolver.getOutput(), viaDiameter: t54.viaDiameter, obstacleMargin: t54.srj.defaultObstacleMargin ?? 0.15 }], { onSolved: (t54) => {
t54.topologyPlanningSolver.getOutput();
t54.globalTopologyGeneratorSolver = t54.topologyPlanningSolver.globalTopologySolver, t54.componentTopologyGeneratorSolver = new q5(t54.topologyPlanningSolver);
} }), k8("topologyMergingSolver", V5, (t54) => {
const e7 = t54.topologyPlanningSolver.getOutput();
return [{ layerCount: t54.srj.layerCount, nodeGroups: [{ groupId: "global", nodes: e7.globalMeshNodes, isComponent: false }, ...e7.componentMeshNodes.map((t55, e10) => ({ groupId: `component-${e10}`, nodes: t55, isComponent: true }))] }];
}, { onSolved: (t54) => {
t54.capacityNodes = t54.topologyMergingSolver.getOutput();
} }), k8("nodeDimensionSubdivisionSolver", FW, (t54) => [t54.capacityNodes, t54.maxNodeDimension, t54.maxNodeRatio, t54.minNodeArea], { onSolved: (t54) => {
t54.capacityNodes = t54.nodeDimensionSubdivisionSolver.outputNodes;
} }), k8("edgeSolver", ui, (t54) => [t54.capacityNodes], { onSolved: (t54) => {
t54.capacityEdges = t54.edgeSolver?.edges;
} }), k8("availableSegmentPointSolver", ci, (t54) => [{ nodes: t54.capacityNodes, edges: t54.capacityEdges || [], traceWidth: t54.minTraceWidth, colorMap: t54.colorMap, shouldReturnCrampedPortPoints: true }]), k8("necessaryCrampedPortPointSolver", eX, (t54) => {
const e7 = E8(t54.capacityNodes);
return [{ capacityMeshNodes: t54.capacityNodes.filter((t55) => !e7.has(t55.capacityMeshNodeId)), sharedEdgeSegments: O8({ sharedEdgeSegments: t54.availableSegmentPointSolver.getOutput(), componentCapacityMeshNodeIds: e7 }), simpleRouteJson: t54.srjWithPointPairs }];
}, { onSolved: (t54) => {
const e7 = E8(t54.capacityNodes);
t54.sharedEdgeSegmentsWithNecessaryCrampedPortPoints = function({ originalSharedEdgeSegments: t55, filteredSharedEdgeSegments: e10, componentCapacityMeshNodeIds: n7 }) {
const o7 = new Map(e10.map((t56) => [t56.edgeId, t56]));
return t55.map((t56) => A8(t56, n7) ? t56 : o7.get(t56.edgeId) ?? t56);
}({ originalSharedEdgeSegments: t54.availableSegmentPointSolver.getOutput(), filteredSharedEdgeSegments: t54.necessaryCrampedPortPointSolver.getOutput(), componentCapacityMeshNodeIds: e7 });
} }), k8("preloadedTraceGraphSolver", T8, (t54) => [t54.sharedEdgeSegmentsWithNecessaryCrampedPortPoints, t54.srjWithPointPairs]), k8("portPointPathingSolver", JG, (t54) => {
const e7 = t54.sharedEdgeSegmentsWithNecessaryCrampedPortPoints ?? t54.necessaryCrampedPortPointSolver?.getOutput() ?? t54.availableSegmentPointSolver.getOutput(), { graph: n7, connections: o7 } = mX({ capacityMeshNodes: t54.capacityNodes, layerCount: t54.srj.layerCount, connectivityMap: t54.connMap, segmentPortPoints: e7.flatMap((t55) => t55.portPoints), simpleRouteJsonConnections: t54.srjWithPointPairs.connections });
return [{ graph: n7, connections: o7, layerCount: t54.srj.layerCount, effort: t54.effort, preserveTerminalPcbPortIds: true, minViaPadDiameter: t54.viaDiameter, flags: { FORCE_CENTER_FIRST: true, RIPPING_ENABLED: true, USE_SELECTIVE_RERIP_ROUTING: true, USE_PARTIAL_RIP_ROUTING_WITH_PRELOADED_TRACES: true }, weights: { SHUFFLE_SEED: 0, MEMORY_PF_FACTOR: 4, CENTER_OFFSET_DIST_PENALTY_FACTOR: 0, CENTER_OFFSET_FOCUS_SHIFT: 0, NODE_PF_FACTOR: 0, LAYER_CHANGE_COST: 0, RIPPING_PF_COST: 0, NODE_PF_MAX_PENALTY: 100, BASE_CANDIDATE_COST: 0.6, MAX_ITERATIONS_PER_PATH: 0, RANDOM_WALK_DISTANCE: 0, START_RIPPING_PF_THRESHOLD: 0.3, END_RIPPING_PF_THRESHOLD: 1, MAX_RIPS: 1000, RANDOM_RIP_FRACTION: 0.3, STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR: 4, GREEDY_MULTIPLIER: 0.7, MIN_ALLOWED_BOARD_SCORE: -1e4 } }];
}), k8("uniformPortDistributionSolver", bo, (t54) => [{ nodeWithPortPoints: t54.portPointPathingSolver?.getOutput().nodesWithPortPoints ?? [], inputNodesWithPortPoints: t54.portPointPathingSolver?.getOutput().inputNodeWithPortPoints ?? [], minTraceWidth: t54.minTraceWidth, obstacles: t54.srj.obstacles, layerCount: t54.srj.layerCount, useLayerAwareGeometry: t54.srj.layerCount > 2, preserveSolitaryPorts: Boolean(t54.srj.traces?.length) }]), k8("highDensityRouteSolver", v6, (t54) => {
const e7 = t54.portPointPathingSolver;
if (!e7)
throw new Error("Pipeline9 invariant violated: high-density routing requires the completed port-point pathing solver");
const n7 = e7.getOutput(), o7 = t54.uniformPortDistributionSolver?.getOutput() ?? [], i7 = n7.nodesWithPortPoints, r7 = o7.length > 0 ? o7 : i7;
t54.highDensityNodePortPoints = structuredClone(r7);
const s7 = (t54.originalSrj.traces ?? []).flatMap((e10, n10) => k9(e10, n10, t54.originalSrj.layerCount, t54.viaDiameter, t54.connMap)), a7 = i9({ traces: t54.originalSrj.traces ?? [], fixedHdRoutes: s7, sections: t54.getChangedPreloadedTraceSections() });
return [{ nodePortPoints: r7, boardGeometry: { bounds: t54.originalSrj.bounds, outline: t54.originalSrj.outline, minBoardEdgeClearance: t54.originalSrj.minBoardEdgeClearance }, fixedHdRoutes: a7, connMap: t54.connMap, colorMap: t54.colorMap, obstacles: t54.srj.obstacles, layerCount: t54.srj.layerCount, viaDiameter: t54.viaDiameter, traceWidth: t54.minTraceWidth, obstacleMargin: t54.srj.defaultObstacleMargin ?? 0.15, viaToPadClearance: t54.srj.minViaEdgeToPadEdgeClearance, effort: t54.effort, includeBoardObstacles: true, nodePfById: e7.computeNodePfMap(), preserveTerminalPcbPortIds: true }];
}), k8("highDensityForceImproveSolver", zW, (t54) => [{ nodeWithPortPoints: t54.highDensityNodePortPoints ?? [], hdRoutes: c9(t54.highDensityRouteSolver.routes), colorMap: t54.colorMap, totalStepsPerNode: Math.max(12, Math.round(20 * t54.effort)), nodeAssignmentMargin: t54.srj.defaultObstacleMargin ?? 0.2 }]), k8("highDensityRepairSolver", iq, (t54) => [{ nodeWithPortPoints: t54.highDensityNodePortPoints ?? [], hdRoutes: t54.highDensityForceImproveSolver?.getOutput() ?? t54.highDensityRouteSolver.routes, obstacles: t54.srj.obstacles, colorMap: t54.colorMap, repairMargin: t54.srj.defaultObstacleMargin ?? 0.2, minimumTraceWidth: t54.srj.minTraceWidth, connMap: t54.connMap }]), k8("highDensityStitchSolver", Cq, (t54) => [{ connections: [...t54.srjWithPointPairs.connections, ...t54.getChangedPreloadedTraceSections().map((t55) => t55.connection)], hdRoutes: t54.highDensityRepairSolver?.getOutput() ?? t54.highDensityForceImproveSolver?.getOutput() ?? t54.highDensityRouteSolver.routes, colorMap: t54.colorMap, layerCount: t54.srj.layerCount, defaultViaDiameter: t54.viaDiameter, preserveTerminalPcbPortIds: true, preferSameLayerTerminalEndpoints: true }]), k8("traceSimplificationSolver", yD, (t54) => {
const e7 = t54.getPreloadedTraceUpdatesAfterHighDensity().updatedPreloadedTraces.flatMap((e10, n10) => k9(e10, n10, t54.originalSrj.layerCount, t54.viaDiameter, t54.connMap).map((t55) => ({ ...t55, rootConnectionName: e10.connection_name }))), n7 = new Set(t54.getChangedPreloadedTraceSections().map((t55) => t55.connectionName)), o7 = t54.highDensityStitchSolver.mergedHdRoutes.filter((t55) => !n7.has(t55.connectionName)), i7 = Q4([...o7, ...e7], t54.connMap);
return [{ hdRoutes: o7, obstacles: t54.srj.obstacles, connMap: t54.connMap, colorMap: t54.colorMap, outline: t54.srj.outline, defaultViaDiameter: t54.viaDiameter, layerCount: t54.srj.layerCount, minTraceToPadEdgeClearance: t54.srj.minTraceToPadEdgeClearance, minBoardEdgeClearance: t54.srj.minBoardEdgeClearance, otherHdRoutes: e7, netByConnectionName: i7, enableCrossingViaReduction: true, terminalLayerIndicesByPcbPortId: J4(t54.srj.connections, t54.srj.obstacles, t54.srj.layerCount), iterations: 2 }];
}), k8("mutatedPreloadedTraceSimplificationSolver", yD, (t54) => {
const e7 = t54.getPreparedMutatedPreloadedTraceSections(), n7 = e7.sections.map((t55) => t55.hdRoute), o7 = [...e7.immutableHdRoutes, ...t54.traceSimplificationSolver.simplifiedHdRoutes];
return [{ hdRoutes: n7, obstacles: t54.srj.obstacles, connMap: t54.connMap, colorMap: t54.colorMap, outline: t54.srj.outline, defaultViaDiameter: t54.viaDiameter, layerCount: t54.srj.layerCount, minTraceToPadEdgeClearance: t54.srj.minTraceToPadEdgeClearance, minBoardEdgeClearance: t54.srj.minBoardEdgeClearance, otherHdRoutes: o7, netByConnectionName: Q4([...n7, ...o7], t54.connMap), enableCrossingViaReduction: true, preserveRouteEndpoints: true, iterations: 2 }];
}), k8("traceWidthSolver", bD, (t54) => [{ hdRoutes: t54.traceSimplificationSolver.simplifiedHdRoutes, obstacles: t54.srj.obstacles, connMap: t54.connMap, colorMap: t54.colorMap, minTraceWidth: t54.minTraceWidth, connection: t54.srjWithPointPairs.connections, obstacleMargin: t54.srj.minTraceToPadEdgeClearance ?? 0.15, layerCount: t54.srj.layerCount }]), k8("globalDrcForceImproveSolver", ZA, (t54) => [{ srj: t54.getSrjWithMaterializedPreloadedTraces(), hdRoutes: N4(t54.traceWidthSolver.getHdRoutesWithWidths(), t54.netToPointPairsSolver?.newConnections ?? [], new Map((t54.highDensityStitchSolver?.mergedHdRoutes ?? []).map((t55) => [t55.connectionName, t55]))), connMap: t54.connMap, effort: t54.effort, maxIterations: 16, enableLargeBoardBroadFallback: false, enablePostSolveClearanceRelaxation: false }]), k8("pipeline9JointDrcRepairSolver", S8, (t54) => {
const e7 = t54.getPreloadedTraceUpdatesAfterHighDensity(), n7 = t54.getSrjWithMaterializedPreloadedTraces();
return [{ srj: n7, srjWithPointPairs: n7, originalSrj: t54.originalSrj, newConnections: t54.netToPointPairsSolver?.newConnections ?? [], newHdRoutes: t54.globalDrcForceImproveSolver.getOutput(), updatedPreloadedTraces: e7.updatedPreloadedTraces, mutatedPreloadedTraceIds: new Set(e7.mutatedPreloadedTraces.map((t55) => t55.pcb_trace_id)), connMap: t54.connMap, obstacles: t54.srj.obstacles, layerCount: t54.srj.layerCount, defaultViaDiameter: t54.viaDiameter, defaultViaHoleDiameter: t54.viaHoleDiameter, effort: t54.effort, colorMap: t54.colorMap }];
}), k8("lengthMatchingPostProcessingSolver", $4, (t54) => {
const e7 = t54.netToPointPairsSolver;
if (!e7)
throw new Error("Pipeline9: length-matching post-processing requires NetToPointPairsSolver output");
const n7 = e7.newConnections, o7 = new Map;
for (const e10 of t54.srj.differentialPairs ?? [])
for (const t55 of e10.connectionNames) {
const e11 = n7.filter((e12) => e12.name === t55 || e12.__rootConnectionNames?.includes(t55) || e12.__netConnectionName === t55);
if (e11.length !== 1)
throw new Error(`Pipeline9: differential pair connection "${t55}" must resolve to exactly one final point-pair connection, got ${e11.length}`);
o7.set(t55, e11[0].name);
}
const i7 = t54.pipeline9JointDrcRepairSolver.getOutput(), r7 = (t54.srj.differentialPairs ?? []).map((t55) => {
const e10 = t55.connectionNames.map((t56) => {
const e11 = o7.get(t56);
if (!e11)
throw new Error(`Pipeline9: differential pair connection "${t56}" is missing from final routed output`);
return e11;
});
if (e10[0] === e10[1])
throw new Error(`Pipeline9: differential pair ${t55.connectionNames.join("/")} resolves both members to "${e10[0]}"`);
const n10 = { connectionNames: e10, lengthTolerance: t55.lengthTolerance };
if (t55.maxUncoupledLength !== undefined && (n10.maxUncoupledLength = t55.maxUncoupledLength), t55.traceGap === undefined)
return n10;
const r10 = e10.map((t56) => {
const e11 = i7.filter((e12) => e12.connectionName === t56);
if (e11.length !== 1)
throw new Error(`Pipeline9: differential pair connection "${t56}" must resolve to exactly one final HD route, got ${e11.length}`);
return e11[0];
}), s7 = t55.traceGap + r10.reduce((t56, e11) => t56 + e11.traceThickness / 2, 0);
return { ...n10, minimumCenterlineDistance: s7, maximumCenterlineDistance: s7 };
});
return [{ hdRoutes: i7, differentialPairs: r7, buses: t54.srj.buses ?? [], connections: t54.srj.connections, obstacles: t54.srj.obstacles, bounds: t54.srj.bounds, layerCount: t54.srj.layerCount, obstacleMargin: t54.srj.minTraceToPadEdgeClearance ?? 0.15 }];
}), k8("powerTraceExpansionSolver", S4, (t54) => {
const e7 = t54.opts.powerTraceExpansion ?? {}, n7 = e7.onlyConnectionNames ?? M4(t54.originalSrj);
return [w4({ originalSrj: t54.originalSrj, newlyRoutedTraces: t54.getNewTracesBeforePowerExpansion(), currentPreloadedTraces: t54.getUpdatedPreloadedTraces(), expandedConnectionNames: n7, resolveConnectedTraceAliases: true }), { allowNewVias: false, ...e7, onlyConnectionNames: n7 }];
})];
setSimpleRouteJson(t54) {
this.srj = t54;
const e7 = Yo(this.srj);
this.viaDiameter = e7.padDiameter, this.viaHoleDiameter = e7.holeDiameter, this.minTraceWidth = this.srj.minTraceWidth, this.connMap = ii(this.srj), this.colorMap = Eo(this.srj, this.connMap);
}
getConstructorParams() {
return [this.srj, this.opts];
}
currentPipelineStepIndex = 0;
computeProgress() {
const t54 = this.activeSubSolver?.progress ?? 0;
return (this.currentPipelineStepIndex + t54) / this.pipelineDef.length;
}
_step() {
const t54 = this.pipelineDef[this.currentPipelineStepIndex];
if (!t54)
return void (this.solved = true);
if (this.activeSubSolver)
return this.activeSubSolver.step(), void (this.activeSubSolver.solved ? (this.endTimeOfPhase[t54.solverName] = performance.now(), this.timeSpentOnPhase[t54.solverName] = this.endTimeOfPhase[t54.solverName] - this.startTimeOfPhase[t54.solverName], t54.onSolved?.(this), this.activeSubSolver = null, this.currentPipelineStepIndex++) : this.activeSubSolver.failed && (this.error = this.activeSubSolver?.error, this.failed = true, this.activeSubSolver = null));
const e7 = t54.getConstructorParams(this);
this.activeSubSolver = new t54.solverClass(...e7), t54.solverName !== "lengthMatchingPostProcessingSolver" && t54.solverName !== "powerTraceExpansionSolver" || (this.MAX_ITERATIONS = Math.max(this.MAX_ITERATIONS, this.iterations + this.activeSubSolver.MAX_ITERATIONS + 1)), this[t54.solverName] = this.activeSubSolver, this.timeSpentOnPhase[t54.solverName] = 0, this.startTimeOfPhase[t54.solverName] = performance.now();
}
solveUntilPhase(t54) {
for (;this.getCurrentPhase() !== t54; )
this.step();
}
getCurrentPhase() {
return this.pipelineDef[this.currentPipelineStepIndex]?.solverName ?? "none";
}
visualize() {
if (!this.solved && this.activeSubSolver)
return this.visualizeStage(this.activeSubSolver);
const t54 = this.escapeViaLocationSolver?.visualize(), e7 = this.netToPointPairsSolver?.visualize(), n7 = this.componentDetectionSolver?.visualize(), o7 = this.componentTopologyGeneratorSolver?.visualize(), i7 = this.globalTopologyGeneratorSolver?.visualize(), r7 = this.topologyMergingSolver?.visualize(), s7 = this.nodeDimensionSubdivisionSolver?.visualize(), a7 = this.nodeTargetMerger?.visualize(), c7 = this.singleLayerNodeMerger?.visualize(), l7 = this.strawSolver?.visualize(), h7 = this.edgeSolver?.visualize(), d7 = this.deadEndSolver?.visualize(), u7 = this.availableSegmentPointSolver?.visualize(), p7 = this.portPointPathingSolver?.visualize(), m7 = this.multiSectionPortPointOptimizer?.visualize(), g7 = this.uniformPortDistributionSolver?.visualize(), f7 = this.highDensityRouteSolver?.visualize(), y7 = this.highDensityForceImproveSolver?.visualize(), _7 = this.highDensityRepairSolver?.visualize(), b7 = this.highDensityStitchSolver?.visualize(), x7 = this.traceSimplificationSolver?.visualize(), v7 = this.mutatedPreloadedTraceSimplificationSolver?.visualize(), I7 = this.lengthMatchingPostProcessingSolver?.visualize(), S7 = this.powerTraceExpansionSolver?.visualize(), C7 = this.traceWidthSolver?.visualize(), P7 = this.necessaryCrampedPortPointSolver?.visualize(), M7 = (this.highDensityRouteSolver?.visualize(), this.originalSrj), N7 = M7.outline, w7 = [];
if (w7.push({ points: [{ x: M7.bounds?.minX ?? -50, y: M7.bounds?.minY ?? -50 }, { x: M7.bounds?.maxX ?? 50, y: M7.bounds?.minY ?? -50 }, { x: M7.bounds?.maxX ?? 50, y: M7.bounds?.maxY ?? 50 }, { x: M7.bounds?.minX ?? -50, y: M7.bounds?.maxY ?? 50 }, { x: M7.bounds?.minX ?? -50, y: M7.bounds?.minY ?? -50 }], strokeColor: "rgba(255,0,0,0.25)" }), N7 && N7.length >= 2) {
const t55 = N7.map((t56) => ({ x: t56.x, y: t56.y }));
t55.push({ ...t55[0] }), w7.push({ points: t55, strokeColor: "rgba(0, 136, 255, 0.95)" });
}
const T7 = Lo(M7), R7 = { points: [...M7.connections.flatMap((t55) => t55.pointsToConnect.map((e10) => ({ ...e10, layer: Bo(e10, M7.layerCount), label: `${t55.name} ${e10.pcb_port_id ?? ""}` })))], rects: [...(M7.obstacles ?? []).filter((t55) => !t55.isCopperPour).map((t55) => ({ ...t55, fill: t55.layers?.includes("top") ? "rgba(255,0,0,0.25)" : t55.layers?.includes("bottom") ? "rgba(0,0,255,0.25)" : "rgba(255,0,0,0.25)", layer: jo(t55, M7.layerCount), label: T7(t55) }))], lines: w7 }, E7 = { traceColorMode: this.visualizationTraceColorMode }, A7 = KG({ srj: M7, visualizationOptions: E7 }), O7 = pi(R7, A7), k7 = this.preprocessSimpleRouteJsonSolver?.visualize(), D7 = this.globalDrcForceImproveSolver?.visualize(), L7 = this.pipeline9JointDrcRepairSolver?.visualize(), z7 = [O7, k7, n7, o7, t54, e7, i7, r7, s7, a7, c7, l7, h7, d7, u7, P7, p7, m7, g7, f7 ? pi(R7, f7) : null, y7, _7, b7, x7, v7, C7, D7, L7, I7, S7, this.solved ? pi({ lines: w7 }, KG({ srj: this.originalSrj, visualizationOptions: E7 }), this.visualizeFinalOutput()) : null].filter(Boolean), B7 = pi(...z7);
return this.visualizationTraceColorMode === "net" ? Z5(B7, this.colorMap) : B7;
}
visualizeStage(t54) {
const e7 = t54.visualize();
return this.visualizationTraceColorMode === "net" ? Z5(e7, this.colorMap) : e7;
}
visualizeFinalOutput() {
const t54 = this.visualizationTraceColorMode, e7 = this.getOutputSimpleRouteJson();
return Ho(e7, { traceColorMode: t54 });
}
preview() {
if (this.highDensityRouteSolver) {
const t54 = [];
for (let e7 = this.highDensityRouteSolver.routes.length - 1;e7 >= 0; e7--) {
const n7 = this.highDensityRouteSolver.routes[e7];
if (t54.push({ points: n7.route.map((t55) => ({ x: t55.x, y: t55.y })), strokeColor: this.colorMap[n7.connectionName] }), t54.length > 200)
break;
}
return { lines: t54 };
}
return this.portPointPathingSolver ? this.portPointPathingSolver.preview() : this.netToPointPairsSolver ? this.netToPointPairsSolver.visualize() : this.escapeViaLocationSolver ? this.escapeViaLocationSolver.visualize() : this.componentTopologyGeneratorSolver ? this.componentTopologyGeneratorSolver.visualize() : this.componentDetectionSolver ? this.componentDetectionSolver.visualize() : this.preprocessSimpleRouteJsonSolver ? this.preprocessSimpleRouteJsonSolver.visualize() : {};
}
_getOutputHdRoutes() {
if (((this.originalSrj.differentialPairs?.length ?? 0) > 0 || (this.originalSrj.buses ?? []).some((t54) => t54.maxLengthSkew !== undefined)) && this.lengthMatchingPostProcessingSolver) {
const { hdRoutes: t54 } = this.lengthMatchingPostProcessingSolver.getOutput();
return t54;
}
return this.pipeline9JointDrcRepairSolver?.getOutput() ?? this.globalDrcForceImproveSolver?.getOutput() ?? this.traceWidthSolver?.getHdRoutesWithWidths() ?? this.traceSimplificationSolver?.simplifiedHdRoutes ?? this.highDensityStitchSolver.mergedHdRoutes;
}
getOriginalFixedHdRoutes() {
return (this.originalSrj.traces ?? []).flatMap((t54, e7) => k9(t54, e7, this.originalSrj.layerCount, this.viaDiameter, this.connMap));
}
getChangedPreloadedTraceSections() {
return this.portPointPathingSolver?.getOutput().changedPreloadedTraceSections ?? [];
}
getPreloadedFixedRouteStateAfterHighDensity() {
const t54 = this.getOriginalFixedHdRoutes(), e7 = this.getChangedPreloadedTraceSections(), n7 = i9({ traces: this.originalSrj.traces ?? [], fixedHdRoutes: t54, sections: e7 }), o7 = e7.length === 0 ? [] : r9({ traces: this.originalSrj.traces ?? [], sections: e7, stitchedHdRoutes: this.highDensityStitchSolver?.mergedHdRoutes ?? [], layerCount: this.originalSrj.layerCount }), i7 = new Set(e7.map((t55) => t55.traceId)), r7 = t54.filter((t55) => i7.has(this.originalSrj.traces?.[t55.preloadedTraceIndex]?.pcb_trace_id ?? "")).map((t55) => t55.connectionName);
return { originalFixedRoutes: t54, updatedFixedRoutes: [...this.highDensityRouteSolver?.getUpdatedFixedHdRoutes() ?? n7, ...o7], replacedConnectionNames: new Set([...this.highDensityRouteSolver?.fixedRouteReplacements.keys() ?? [], ...r7]), mutationMasks: new Map([...this.highDensityRouteSolver?.preloadedTraceMutationMasks ?? [], ...o7.map((t55) => [t55.connectionName, Array(t55.route.length - 1).fill(true)])]) };
}
getPreparedMutatedPreloadedTraceSections() {
const t54 = this.getPreloadedFixedRouteStateAfterHighDensity();
return A9({ updatedFixedRoutes: t54.updatedFixedRoutes, regionalMutationMasks: t54.mutationMasks });
}
getPreloadedTraceUpdatesAfterHighDensity() {
const t54 = this.getPreloadedFixedRouteStateAfterHighDensity(), e7 = this.getPreparedMutatedPreloadedTraceSections(), n7 = this.mutatedPreloadedTraceSimplificationSolver?.solved === true ? (({ updatedFixedRoutes: t55, sections: e10, simplifiedHdRoutes: n10 }) => {
const o7 = new Set(e10.map((t56) => t56.connectionName)), i7 = new Map(n10.map((t56) => [t56.connectionName, t56]));
if (i7.size !== e10.length || n10.some((t56) => !o7.has(t56.connectionName)))
throw new Error(`Pipeline9 trace simplification changed the mutation-section set (expected ${e10.length}, got ${n10.length})`);
const r7 = new Map, s7 = new Set;
for (const t56 of e10) {
const e11 = i7.get(t56.connectionName);
if (!e11)
throw new Error(`Pipeline9 trace simplification lost mutation section "${t56.connectionName}"`);
const n11 = e11.route[0], o10 = e11.route.at(-1);
if (!(n11 && o10 && S9(n11, t56.section.start.point) && S9(o10, t56.section.end.point)))
throw new Error(`Pipeline9 trace simplification changed mutation-section boundary "${t56.connectionName}"`);
const a7 = x9(t56.section, e11), c7 = t56.section.sourceRoutes[0];
s7.add(c7.connectionName);
for (const e12 of t56.section.sourceRoutes) {
if (r7.has(e12.connectionName))
throw new Error(`Pipeline9 attempted to simplify fixed route "${e12.connectionName}" more than once`);
r7.set(e12.connectionName, a7);
}
}
return t55.flatMap((t56) => {
const e11 = r7.get(t56.connectionName);
return e11 ? s7.has(t56.connectionName) ? [e11] : [] : [t56];
});
})({ updatedFixedRoutes: e7.normalizedFixedRoutes, sections: e7.sections, simplifiedHdRoutes: this.mutatedPreloadedTraceSimplificationSolver.simplifiedHdRoutes }) : t54.updatedFixedRoutes;
return (({ originalTraces: t55, originalFixedRoutes: e10, updatedFixedRoutes: n10, replacedConnectionNames: o7, layerCount: i7, defaultViaHoleDiameter: r7, obstacles: s7, connMap: a7 }) => {
const c7 = new Map, l7 = new Map;
for (const t56 of e10) {
const e11 = c7.get(t56.preloadedTraceIndex) ?? [];
e11.push(t56), c7.set(t56.preloadedTraceIndex, e11);
}
for (const t56 of n10) {
const e11 = l7.get(t56.preloadedTraceIndex) ?? [];
e11.push(t56), l7.set(t56.preloadedTraceIndex, e11);
}
const h7 = [];
return { updatedPreloadedTraces: t55.map((t56, e11) => {
const n11 = (c7.get(e11) ?? []).sort(V4);
if (!n11.some((t57) => o7.has(t57.connectionName)))
return t56;
const d7 = (l7.get(e11) ?? []).sort(V4), u7 = t56.route.some((t57) => t57.route_type === "through_obstacle"), p7 = { ...t56, __replaces_pcb_trace_id: t56.pcb_trace_id, route: u7 ? Z4({ trace: t56, originalTraceRoutes: n11, updatedTraceRoutes: d7, layerCount: i7, defaultViaHoleDiameter: r7, obstacles: s7, connMap: a7 }) : G4({ trace: t56, updatedTraceRoutes: d7, layerCount: i7, defaultViaHoleDiameter: r7, obstacles: s7, connMap: a7 }) };
return h7.push(p7), p7;
}), mutatedPreloadedTraces: h7 };
})({ originalTraces: this.originalSrj.traces ?? [], originalFixedRoutes: t54.originalFixedRoutes, updatedFixedRoutes: n7, replacedConnectionNames: t54.replacedConnectionNames, layerCount: this.originalSrj.layerCount, defaultViaHoleDiameter: this.viaHoleDiameter, obstacles: this.originalSrj.obstacles, connMap: this.connMap });
}
getSrjWithMaterializedPreloadedTraces() {
return { ...this.srjWithPointPairs, traces: this.getPreloadedTraceUpdatesAfterHighDensity().updatedPreloadedTraces };
}
getUpdatedPreloadedTraces() {
return this.pipeline9JointDrcRepairSolver?.getUpdatedPreloadedTraces() ?? this.getPreloadedTraceUpdatesAfterHighDensity().updatedPreloadedTraces;
}
getMutatedPreloadedTraces() {
return this.pipeline9JointDrcRepairSolver?.getMutatedPreloadedTraces() ?? this.getPreloadedTraceUpdatesAfterHighDensity().mutatedPreloadedTraces;
}
getNewTracesBeforePowerExpansion() {
if (!this.highDensityRouteSolver)
throw new Error("Cannot get new traces before high-density routing");
const t54 = P4({ connections: this.netToPointPairsSolver?.newConnections ?? [], originalConnections: this.originalSrj.connections, hdRoutes: l9(this._getOutputHdRoutes()), layerCount: this.srj.layerCount, obstacles: this.srj.obstacles, defaultViaHoleDiameter: this.viaHoleDiameter, connMap: this.connMap });
return q4(t54, this.originalSrj.traces ?? []);
}
getPowerTraceExpansionFixedTraces() {
if (!this.powerTraceExpansionSolver)
throw new Error("Pipeline9 invariant violated: solved pipeline is missing the unconditional power-trace expansion solver");
return this.powerTraceExpansionSolver.inputSrj.fixedTraces;
}
getOutputSimplifiedPcbTraces() {
if (!this.solved)
throw new Error("Cannot get output before solving is complete");
if (!this.powerTraceExpansionSolver)
throw new Error("Pipeline9 invariant violated: solved pipeline is missing the unconditional power-trace expansion solver");
return [...this.getPowerTraceExpansionFixedTraces().filter((t54) => t54.__replaces_pcb_trace_id !== undefined), ...this.powerTraceExpansionSolver.getOutput()];
}
getOutputSimpleRouteJson() {
if (!this.solved)
throw new Error("Cannot get output before solving is complete");
if (!this.powerTraceExpansionSolver)
throw new Error("Pipeline9 invariant violated: solved pipeline is missing the unconditional power-trace expansion solver");
const t54 = [...this.getPowerTraceExpansionFixedTraces(), ...this.powerTraceExpansionSolver.getOutput()];
return { ...this.originalSrj, traces: t54 };
}
};
globalThis.process?.env?.FANOUT_FLOW_DEBUG === "1";
/*! Bundled license information:
is-buffer/index.js:
(*!
* Determine if an object is a Buffer
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*)
deep-rename-keys/index.js:
(*!
* deep-rename-keys <https://github.com/jonschlinkert/deep-rename-keys>
*
* Copyright (c) 2015 Jon Schlinkert, contributors.
* Licensed under the MIT license.
*)
@tscircuit/curvy-trace-solver/dist/index.js:
@tscircuit/find-convex-regions/dist/index.js:
(*! Bundled license information:
is-buffer/index.js:
(*!
* Determine if an object is a Buffer
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*)
deep-rename-keys/index.js:
(*!
* deep-rename-keys <https://github.com/jonschlinkert/deep-rename-keys>
*
* Copyright (c) 2015 Jon Schlinkert, contributors.
* Licensed under the MIT license.
*)
*)
@tscircuit/hypergraph/dist/index.js:
(*! Bundled license information:
@tscircuit/find-convex-regions/dist/index.js:
(*! Bundled license information:
is-buffer/index.js:
(*!
* Determine if an object is a Buffer
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*)
deep-rename-keys/index.js:
(*!
* deep-rename-keys <https://github.com/jonschlinkert/deep-rename-keys>
*
* Copyright (c) 2015 Jon Schlinkert, contributors.
* Licensed under the MIT license.
*)
*)
*)
*/
// coil-aware-router.ts
async function coilAwareRouter(input) {
const corrected = structuredClone(input);
for (const o10 of corrected.obstacles) {
if (o10.connectedTo?.some((id2) => /^pcb_trace_[0-3]$/.test(id2))) {
if (o10.width === 0.1) {
o10.width = 0.2;
o10.height += 0.2;
} else if (o10.height === 0.1) {
o10.height = 0.2;
o10.width += 0.2;
}
}
}
const solver = new D8(corrected);
const handlers = {};
return {
on(event, fn2) {
(handlers[event] ??= []).push(fn2);
},
start() {
try {
solver.solve();
if (solver.failed)
throw new Error(solver.error ?? "Routing failed");
for (const f10 of handlers.complete ?? [])
f10({ traces: solver.getOutputSimpleRouteJson().traces ?? [] });
} catch (error) {
for (const f10 of handlers.error ?? [])
f10({ error });
}
},
stop() {},
getOutputSimpleRouteJson() {
return solver.getOutputSimpleRouteJson();
}
};
}
const pinLabels = {
pin1: ["SCL"],
pin2: ["SDA"],
pin3: ["CLKIN"],
pin4: ["ADDR"],
pin5: ["INTB"],
pin6: ["SD"],
pin7: ["VDD"],
pin8: ["GND"],
pin9: ["IN0A"],
pin10: ["IN0B"],
pin11: ["IN1A"],
pin12: ["IN1B"],
pin13: ["IN2A"],
pin14: ["IN2B"],
pin15: ["IN3A"],
pin16: ["IN3B"],
pin17: ["EP"]
};
const LDC1614RGHR = (props) => {
return (jsx("chip", { pinLabels: pinLabels, supplierPartNumbers: {
"jlcpcb": [
"C968448"
]
}, manufacturerPartNumber: "LDC1614RGHR", footprint: jsxs("footprint", { children: [jsx("smtpad", { portHints: ["pin17"], pcbX: "0mm", pcbY: "0mm", width: "2.5999948mm", height: "2.5999948mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin16"], pcbX: "-0.750062mm", pcbY: "1.90754mm", width: "0.2800096mm", height: "0.6649974mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin15"], pcbX: "-0.249936mm", pcbY: "1.90754mm", width: "0.2800096mm", height: "0.6649974mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin14"], pcbX: "0.249936mm", pcbY: "1.90754mm", width: "0.2800096mm", height: "0.6649974mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin13"], pcbX: "0.750062mm", pcbY: "1.90754mm", width: "0.2800096mm", height: "0.6649974mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin12"], pcbX: "1.90754mm", pcbY: "0.750062mm", width: "0.6649974mm", height: "0.2800096mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin11"], pcbX: "1.90754mm", pcbY: "0.249936mm", width: "0.6649974mm", height: "0.2800096mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin10"], pcbX: "1.90754mm", pcbY: "-0.249936mm", width: "0.6649974mm", height: "0.2800096mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin9"], pcbX: "1.90754mm", pcbY: "-0.750062mm", width: "0.6649974mm", height: "0.2800096mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin8"], pcbX: "0.750062mm", pcbY: "-1.90754mm", width: "0.2800096mm", height: "0.6649974mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin7"], pcbX: "0.249936mm", pcbY: "-1.90754mm", width: "0.2800096mm", height: "0.6649974mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin6"], pcbX: "-0.249936mm", pcbY: "-1.90754mm", width: "0.2800096mm", height: "0.6649974mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin5"], pcbX: "-0.750062mm", pcbY: "-1.90754mm", width: "0.2800096mm", height: "0.6649974mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin4"], pcbX: "-1.90754mm", pcbY: "-0.750062mm", width: "0.6649974mm", height: "0.2800096mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin3"], pcbX: "-1.90754mm", pcbY: "-0.249936mm", width: "0.6649974mm", height: "0.2800096mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin2"], pcbX: "-1.90754mm", pcbY: "0.249936mm", width: "0.6649974mm", height: "0.2800096mm", shape: "rect" }), jsx("smtpad", { portHints: ["pin1"], pcbX: "-1.90754mm", pcbY: "0.750062mm", width: "0.6649974mm", height: "0.2800096mm", shape: "rect" }), jsx("silkscreenpath", { route: [{ "x": -2.0761959999999817, "y": 1.042390599999976 }, { "x": -2.0761959999999817, "y": 2.0761959999999817 }, { "x": -1.0423906000000898, "y": 2.0761959999999817 }] }), jsx("silkscreenpath", { route: [{ "x": 2.0761960000000954, "y": 1.042390599999976 }, { "x": 2.0761960000000954, "y": 2.0761959999999817 }, { "x": 1.042390599999976, "y": 2.0761959999999817 }] }), jsx("silkscreenpath", { route: [{ "x": 2.0761960000000954, "y": -1.042390599999976 }, { "x": 2.0761960000000954, "y": -2.0761959999999817 }, { "x": 1.042390599999976, "y": -2.0761959999999817 }] }), jsx("silkscreenpath", { route: [{ "x": -2.0761959999999817, "y": -1.042390599999976 }, { "x": -2.0761959999999817, "y": -2.0761959999999817 }, { "x": -1.0423906000000898, "y": -2.0761959999999817 }] }), jsx("silkscreenpath", { route: [{ "x": -2.4782780000000457, "y": 0.7619999999999436 }, { "x": -2.480381126149723, "y": 0.746025170898065 }, { "x": -2.486547180027628, "y": 0.7311389999999847 }, { "x": -2.4963559552516017, "y": 0.7183559552515817 }, { "x": -2.5091390000000047, "y": 0.7085471800276082 }, { "x": -2.5240251708981987, "y": 0.702381126149703 }, { "x": -2.5400000000000773, "y": 0.7002780000000257 }, { "x": -2.5559748291018423, "y": 0.702381126149703 }, { "x": -2.5708610000000363, "y": 0.7085471800276082 }, { "x": -2.5836440447484392, "y": 0.7183559552515817 }, { "x": -2.5934528199724127, "y": 0.7311389999999847 }, { "x": -2.599618873850318, "y": 0.746025170898065 }, { "x": -2.601721999999995, "y": 0.7619999999999436 }, { "x": -2.599618873850318, "y": 0.7779748291018223 }, { "x": -2.5934528199724127, "y": 0.7928610000000162 }, { "x": -2.5836440447484392, "y": 0.8056440447484192 }, { "x": -2.5708610000000363, "y": 0.815452819972279 }, { "x": -2.5559748291018423, "y": 0.8216188738501842 }, { "x": -2.5400000000000773, "y": 0.8237219999998615 }, { "x": -2.5240251708981987, "y": 0.8216188738501842 }, { "x": -2.5091390000000047, "y": 0.815452819972279 }, { "x": -2.4963559552516017, "y": 0.8056440447484192 }, { "x": -2.486547180027628, "y": 0.7928610000000162 }, { "x": -2.480381126149723, "y": 0.7779748291018223 }, { "x": -2.4782780000000457, "y": 0.7619999999999436 }] }), jsx("silkscreentext", { text: "{NAME}", pcbX: "-0.1651mm", pcbY: "3.2352mm", anchorAlignment: "center", fontSize: "1mm" }), jsx("courtyardoutline", { outline: [{ "x": -2.8407999999999447, "y": 2.485200000000077 }, { "x": 2.5106000000000677, "y": 2.485200000000077 }, { "x": 2.5106000000000677, "y": -2.4851999999999634 }, { "x": -2.8407999999999447, "y": -2.4851999999999634 }, { "x": -2.8407999999999447, "y": 2.485200000000077 }] })] }), cadModel: {
objUrl: "https://modelcdn.tscircuit.com/easyeda_models/assets/C968448.obj?uuid=0bfbea00a90648588cbb28ccdefac02e",
stepUrl: "https://modelcdn.tscircuit.com/easyeda_models/assets/C968448.step?uuid=0bfbea00a90648588cbb28ccdefac02e",
pcbRotationOffset: 0,
modelOriginPosition: { x: 0, y: 0, z: -0.8 },
}, ...props }));
};
// 18 mm square, 12 turns, 0.20 mm trace / 0.20 mm spacing.
// Nominal inductance is an estimate; measure with actual target installed.
function spiral() {
const p = [{ x: -9, y: -10 }, { x: -9, y: -9 }];
for (let i = 0; i < 12; i++) {
const r = 9 - i * 0.4;
p.push({ x: r, y: -r }, { x: r, y: r }, { x: -r, y: r }, { x: -r, y: -r + 0.4 });
}
p.push({ x: -3.6, y: -4.2 }, { x: -3.6, y: -3.6 });
return p;
}
const coil = spiral();
const last = coil[coil.length - 1];
function CoilFootprint({ channel }) {
return jsxs("footprint", { children: [jsx("smtpad", { portHints: ["pin1"], pcbX: -9, pcbY: -10, width: 0.5, height: 0.5, shape: "rect", coveredWithSolderMask: true }), jsx("platedhole", { portHints: ["pin2"], pcbX: last.x, pcbY: last.y, holeDiameter: 0.3, outerDiameter: 0.6, shape: "circle", coveredWithSolderMask: true }), jsx("pcbtrace", { layer: "top", thickness: 0.2, route: coil.map(p => ({ ...p, route_type: "wire", width: 0.2, layer: "top" })) })] });
}
const sensors = [
{ x: 18, y: -15, cx: 7, cy: -7 }, { x: 18, y: 15, cx: 7, cy: 7 },
{ x: -18, y: 15, cx: -7, cy: 7 }, { x: -18, y: -15, cx: -7, cy: -7 },
];
function MetalTouchPanel() {
return jsxs("board", { width: 72, height: 64, layers: 2, title: "Metal Touch / 4-channel LDC1614", autorouter: { algorithmFn: coilAwareRouter }, minTraceWidth: 0.15, minViaHoleDiameter: 0.3, minViaPadDiameter: 0.6, minViaEdgeToPadEdgeClearance: 0.15, children: [jsx("schematicsection", { name: "AFE", displayName: "Inductance converter" }), jsx("schematicsection", { name: "Power", displayName: "3.3 V host interface" }), jsx("schematicsection", { name: "Sensors", displayName: "Printed sensing coils / tune on bench" }), jsx(LDC1614RGHR, { name: "U1", layer: "bottom", schHeight: 1.8, pcbX: 0, pcbY: 0, schX: 0, schY: 0, schSectionName: "AFE" }), jsx("capacitor", { layer: "bottom", schOrientation: "vertical", name: "C5", capacitance: "100nF", footprint: "0603", pcbRotation: 90, pcbX: -0.25, pcbY: -4.2, schX: -9, schY: -4, schSectionName: "Power" }), jsx("capacitor", { layer: "bottom", schOrientation: "vertical", name: "C6", capacitance: "1uF", footprint: "0603", pcbX: 4, pcbY: -4, schX: -6, schY: -4, schSectionName: "Power" }), jsx("resistor", { layer: "bottom", schRotation: -90, name: "R1", resistance: "4.7k", footprint: "0603", pcbX: -6, pcbY: 1, schX: -9, schY: 0, schSectionName: "Power" }), jsx("resistor", { layer: "bottom", schRotation: -90, name: "R2", resistance: "4.7k", footprint: "0603", pcbX: -6, pcbY: -2, schX: -6, schY: 0, schSectionName: "Power" }), jsx("pinheader", { layer: "bottom", name: "J1", pinCount: 5, pitch: "2.54mm", pcbX: 0, pcbY: -28, schX: -12, schY: -2, schSectionName: "Power" }), sensors.map((s, i) => jsxs(Fragment, { children: [jsx("inductor", { name: `L${i + 1}`, inductance: "3uH", doNotPlace: true, footprint: jsx(CoilFootprint, { channel: i }), pcbX: s.x, pcbY: s.y, schX: 9 + (i % 2) * 5, schY: 4 - Math.floor(i / 2) * 8, schSectionName: "Sensors" }), jsx("capacitor", { layer: "bottom", schOrientation: "vertical", name: `C${i + 1}`, pcbRotation: i === 1 ? 180 : 0, capacitance: "1nF", footprint: "0603", pcbX: s.cx, pcbY: s.cy, schX: 9 + (i % 2) * 5, schY: 1 - Math.floor(i / 2) * 8, schSectionName: "Sensors" }), jsx("trace", { from: `U1.IN${i}A`, to: `L${i + 1}.pin1` }), jsx("trace", { from: `U1.IN${i}B`, to: `L${i + 1}.pin2` }), jsx("trace", { from: `C${i + 1}.pin1`, to: `L${i + 1}.pin1` }), jsx("trace", { from: `C${i + 1}.pin2`, to: `L${i + 1}.pin2` }), jsx("silkscreentext", { text: `KEY ${i + 1}`, pcbX: s.x, pcbY: s.y, fontSize: 1.3 })] }, i)), ["U1.GND", "U1.EP", "U1.CLKIN", "U1.ADDR", "U1.SD", "C5.pin2", "C6.pin2", "J1.pin2"].map(p => jsx("trace", { from: p, to: "net.GND" }, p)), ["U1.VDD", "C5.pin1", "C6.pin1", "R1.pin1", "R2.pin1", "J1.pin1"].map(p => jsx("trace", { from: p, to: "net.V3V3" }, p)), jsx("trace", { from: "U1.SCL", to: "J1.pin4" }), jsx("trace", { from: "U1.SDA", to: "J1.pin3" }), jsx("trace", { from: "R1.pin2", to: "U1.SCL" }), jsx("trace", { from: "R2.pin2", to: "U1.SDA" }), jsx("trace", { from: "U1.INTB", to: "J1.pin5" }), [-32, 32].flatMap(x => [-28, 28].map(y => jsx(Fragment, { children: jsx("hole", { diameter: 3.2, pcbX: x, pcbY: y }) }, `${x},${y}`))), jsx("silkscreentext", { text: "METAL TOUCH / REV A", pcbX: 0, pcbY: 29, fontSize: 1.2 }), ["3V3", "GND", "SDA", "SCL", "INT"].map((label, i) => jsx(Fragment, { children: jsx("silkscreentext", { text: label, pcbX: 5.08 - i * 2.54, pcbY: -30, fontSize: 0.65 }) }, label))] });
}
export { MetalTouchPanel as default };
