@tscircuit/capacity-autorouter 0.0.179 → 0.0.180
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +9 -12
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var t=(...t)=>{const e={points:[],lines:[],circles:[],rects:[]};return t.forEach((t,s)=>{t&&(t.lines&&(e.lines=[...e.lines||[],...t.lines.map(t=>({...t,step:s}))]),t.points&&(e.points=[...e.points||[],...t.points.map(t=>({...t,step:s}))]),t.circles&&(e.circles=[...e.circles||[],...t.circles.map(t=>({...t,step:s}))]),t.rects&&(e.rects=[...e.rects||[],...t.rects.map(t=>({...t,step:s}))]))}),e},e=class{MAX_ITERATIONS=1e3;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};cacheHit;cacheKey;cacheToSolveSpaceTransform;step(){if(!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,console.error(this.error),this.failed=!0,t}!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 (MAX_ITERATIONS=${this.MAX_ITERATIONS})`,console.error(this.error),this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}};function s(t){const e=new Map;for(const s of t)for(const t of s.nodeIds)e.set(t,[...e.get(t)??[],s]);return e}function n(){return n=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var n in s)({}).hasOwnProperty.call(s,n)&&(t[n]=s[n])}return t},n.apply(null,arguments)}function i(t,e){return(i=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t})(t,e)}function o(t){return(o=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function a(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(a=function(){return!!t})()}function r(t){var e="function"==typeof Map?new Map:void 0;return r=function(t){if(null===t||!function(t){try{return-1!==Function.toString.call(t).indexOf("[native code]")}catch(e){return"function"==typeof t}}(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,s)}function s(){return function(t,e,s){if(a())return Reflect.construct.apply(null,arguments);var n=[null];n.push.apply(n,e);var o=new(t.bind.apply(t,n));return s&&i(o,s.prototype),o}(t,arguments,o(this).constructor)}return s.prototype=Object.create(t.prototype,{constructor:{value:s,enumerable:!1,writable:!0,configurable:!0}}),i(s,t)},r(t)}var h={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 }).\n\n",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 }).\n\n",3:"Passed an incorrect argument to a color function, please pass a string representation of a color.\n\n",4:"Couldn't generate valid rgb string from %s, it returned %s.\n\n",5:"Couldn't parse the color string. Please provide the color as a string in hex, rgb, rgba, hsl or hsla notation.\n\n",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 }).\n\n",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 }).\n\n",8:"Passed invalid argument to toColorString, please pass a RgbColor, RgbaColor, HslColor or HslaColor object.\n\n",9:"Please provide a number of steps to the modularScale helper.\n\n",10:"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\n\n",11:'Invalid value passed as base to modularScale, expected number or em string but got "%s"\n\n',12:'Expected a string ending in "px" or a number passed as the first argument to %s(), got "%s" instead.\n\n',13:'Expected a string ending in "px" or a number passed as the second argument to %s(), got "%s" instead.\n\n',14:'Passed invalid pixel value ("%s") to %s(), please pass a value like "12px" or 12.\n\n',15:'Passed invalid base value ("%s") to %s(), please pass a value like "12px" or 12.\n\n',16:"You must provide a template to this method.\n\n",17:"You passed an unsupported selector state to this method.\n\n",18:"minScreen and maxScreen must be provided as stringified numbers with the same units.\n\n",19:"fromSize and toSize must be provided as stringified numbers with the same units.\n\n",20:"expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\n\n",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.\n\n",24:"fontFace expects either the path to the font file(s) or a name of a local copy.\n\n",25:"fontFace expects localFonts to be an array.\n\n",26:"fontFace expects fileFormats to be an array.\n\n",27:"radialGradient requries at least 2 color-stops to properly render.\n\n",28:"Please supply a filename to retinaImage() as the first argument.\n\n",29:"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\n\n",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\n\n",32:"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')\n\n",33:"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation\n\n",34:"borderRadius expects a radius value as a string or number as the second argument.\n\n",35:'borderRadius expects one of "top", "bottom", "left" or "right" as the first argument.\n\n',36:"Property must be a string value.\n\n",37:"Syntax Error at %s.\n\n",38:"Formula contains a function that needs parentheses at %s.\n\n",39:"Formula is missing closing parenthesis at %s.\n\n",40:"Formula has too many closing parentheses at %s.\n\n",41:"All values in a formula must have the same unit or be unitless.\n\n",42:"Please provide a number of steps to the modularScale helper.\n\n",43:"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\n\n",44:"Invalid value passed as base to modularScale, expected number or em/rem string but got %s.\n\n",45:"Passed invalid argument to hslToColorString, please pass a HslColor or HslaColor object.\n\n",46:"Passed invalid argument to rgbToColorString, please pass a RgbColor or RgbaColor object.\n\n",47:"minScreen and maxScreen must be provided as stringified numbers with the same units.\n\n",48:"fromSize and toSize must be provided as stringified numbers with the same units.\n\n",49:"Expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\n\n",50:"Expects the objects in the first argument array to have the properties prop, fromSize, and toSize.\n\n",51:"Expects the first argument object to have the properties prop, fromSize, and toSize.\n\n",52:"fontFace expects either the path to the font file(s) or a name of a local copy.\n\n",53:"fontFace expects localFonts to be an array.\n\n",54:"fontFace expects fileFormats to be an array.\n\n",55:"fontFace expects a name of a font-family.\n\n",56:"linearGradient requries at least 2 color-stops to properly render.\n\n",57:"radialGradient requries at least 2 color-stops to properly render.\n\n",58:"Please supply a filename to retinaImage() as the first argument.\n\n",59:"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\n\n",60:"Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\n\n",61:"Property must be a string value.\n\n",62:"borderRadius expects a radius value as a string or number as the second argument.\n\n",63:'borderRadius expects one of "top", "bottom", "left" or "right" as the first argument.\n\n',64:"The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation.\n\n",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').\n\n",66:"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation.\n\n",67:"You must provide a template to this method.\n\n",68:"You passed an unsupported selector state to this method.\n\n",69:'Expected a string ending in "px" or a number passed as the first argument to %s(), got %s instead.\n\n',70:'Expected a string ending in "px" or a number passed as the second argument to %s(), got %s instead.\n\n',71:'Passed invalid pixel value %s to %s(), please pass a value like "12px" or 12.\n\n',72:'Passed invalid base value %s to %s(), please pass a value like "12px" or 12.\n\n',73:"Please provide a valid CSS variable.\n\n",74:"CSS variable not found and no default was provided.\n\n",75:"important requires a valid style object, got a %s instead.\n\n",76:"fromSize and toSize must be provided as stringified numbers with the same units as minScreen and maxScreen.\n\n",77:'remToPx expects a value in "rem" but you provided it in "%s".\n\n',78:'base must be set in "px" or "%" but you set it in "%s".\n'};function c(){for(var t=arguments.length,e=new Array(t),s=0;s<t;s++)e[s]=arguments[s];var n,i=e[0],o=[];for(n=1;n<e.length;n+=1)o.push(e[n]);return o.forEach(function(t){i=i.replace(/%[a-z]/,t)}),i}var d=function(t){var e,s;function n(e){var s;if("production"===process.env.NODE_ENV)s=t.call(this,"An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#"+e+" for more information.")||this;else{for(var n=arguments.length,i=new Array(n>1?n-1:0),o=1;o<n;o++)i[o-1]=arguments[o];s=t.call(this,c.apply(void 0,[h[e]].concat(i)))||this}return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(s)}return s=t,(e=n).prototype=Object.create(s.prototype),e.prototype.constructor=e,i(e,s),n}(r(Error));function l(t,e){return t.substr(-e.length)===e}var u=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;function p(t){return"string"!=typeof t?t:t.match(u)?parseFloat(t):t}var f=function(t){return function(e,s){void 0===s&&(s="16px");var n=e,i=s;if("string"==typeof e){if(!l(e,"px"))throw new d(69,t,e);n=p(e)}if("string"==typeof s){if(!l(s,"px"))throw new d(70,t,s);i=p(s)}if("string"==typeof n)throw new d(71,e,t);if("string"==typeof i)throw new d(72,s,t);return""+n/i+t}};f("em"),f("rem");function g(t){return Math.round(255*t)}function m(t,e,s){return g(t)+","+g(e)+","+g(s)}function y(t,e,s,n){if(void 0===n&&(n=m),0===e)return n(s,s,s);var i=(t%360+360)%360/60,o=(1-Math.abs(2*s-1))*e,a=o*(1-Math.abs(i%2-1)),r=0,h=0,c=0;i>=0&&i<1?(r=o,h=a):i>=1&&i<2?(r=a,h=o):i>=2&&i<3?(h=o,c=a):i>=3&&i<4?(h=a,c=o):i>=4&&i<5?(r=a,c=o):i>=5&&i<6&&(r=o,c=a);var d=s-o/2;return n(r+d,h+d,c+d)}var x={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 v=/^#[a-fA-F0-9]{6}$/,M=/^#[a-fA-F0-9]{8}$/,S=/^#[a-fA-F0-9]{3}$/,b=/^#[a-fA-F0-9]{4}$/,N=/^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i,I=/^rgb(?:a)?\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i,P=/^hsl\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*\)$/i,C=/^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 _(t){if("string"!=typeof t)throw new d(3);var e=function(t){if("string"!=typeof t)return t;var e=t.toLowerCase();return x[e]?"#"+x[e]:t}(t);if(e.match(v))return{red:parseInt(""+e[1]+e[2],16),green:parseInt(""+e[3]+e[4],16),blue:parseInt(""+e[5]+e[6],16)};if(e.match(M)){var s=parseFloat((parseInt(""+e[7]+e[8],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[2],16),green:parseInt(""+e[3]+e[4],16),blue:parseInt(""+e[5]+e[6],16),alpha:s}}if(e.match(S))return{red:parseInt(""+e[1]+e[1],16),green:parseInt(""+e[2]+e[2],16),blue:parseInt(""+e[3]+e[3],16)};if(e.match(b)){var n=parseFloat((parseInt(""+e[4]+e[4],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[1],16),green:parseInt(""+e[2]+e[2],16),blue:parseInt(""+e[3]+e[3],16),alpha:n}}var i=N.exec(e);if(i)return{red:parseInt(""+i[1],10),green:parseInt(""+i[2],10),blue:parseInt(""+i[3],10)};var o=I.exec(e.substring(0,50));if(o)return{red:parseInt(""+o[1],10),green:parseInt(""+o[2],10),blue:parseInt(""+o[3],10),alpha:parseFloat(""+o[4])>1?parseFloat(""+o[4])/100:parseFloat(""+o[4])};var a=P.exec(e);if(a){var r="rgb("+y(parseInt(""+a[1],10),parseInt(""+a[2],10)/100,parseInt(""+a[3],10)/100)+")",h=N.exec(r);if(!h)throw new d(4,e,r);return{red:parseInt(""+h[1],10),green:parseInt(""+h[2],10),blue:parseInt(""+h[3],10)}}var c=C.exec(e.substring(0,50));if(c){var l="rgb("+y(parseInt(""+c[1],10),parseInt(""+c[2],10)/100,parseInt(""+c[3],10)/100)+")",u=N.exec(l);if(!u)throw new d(4,e,l);return{red:parseInt(""+u[1],10),green:parseInt(""+u[2],10),blue:parseInt(""+u[3],10),alpha:parseFloat(""+c[4])>1?parseFloat(""+c[4])/100:parseFloat(""+c[4])}}throw new d(5)}function E(t){return function(t){var e,s=t.red/255,n=t.green/255,i=t.blue/255,o=Math.max(s,n,i),a=Math.min(s,n,i),r=(o+a)/2;if(o===a)return void 0!==t.alpha?{hue:0,saturation:0,lightness:r,alpha:t.alpha}:{hue:0,saturation:0,lightness:r};var h=o-a,c=r>.5?h/(2-o-a):h/(o+a);switch(o){case s:e=(n-i)/h+(n<i?6:0);break;case n:e=(i-s)/h+2;break;default:e=(s-n)/h+4}return e*=60,void 0!==t.alpha?{hue:e,saturation:c,lightness:r,alpha:t.alpha}:{hue:e,saturation:c,lightness:r}}(_(t))}var T=function(t){return 7===t.length&&t[1]===t[2]&&t[3]===t[4]&&t[5]===t[6]?"#"+t[1]+t[3]+t[5]:t};function w(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function z(t){return w(Math.round(255*t))}function A(t,e,s){return T("#"+z(t)+z(e)+z(s))}function R(t,e,s){return y(t,e,s,A)}function O(t,e,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s)return T("#"+w(t)+w(e)+w(s));if("object"==typeof t&&void 0===e&&void 0===s)return T("#"+w(t.red)+w(t.green)+w(t.blue));throw new d(6)}function L(t,e,s,n){if("string"==typeof t&&"number"==typeof e){var i=_(t);return"rgba("+i.red+","+i.green+","+i.blue+","+e+")"}if("number"==typeof t&&"number"==typeof e&&"number"==typeof s&&"number"==typeof n)return n>=1?O(t,e,s):"rgba("+t+","+e+","+s+","+n+")";if("object"==typeof t&&void 0===e&&void 0===s&&void 0===n)return t.alpha>=1?O(t.red,t.green,t.blue):"rgba("+t.red+","+t.green+","+t.blue+","+t.alpha+")";throw new d(7)}function D(t){if("object"!=typeof t)throw new d(8);if(function(t){return"number"==typeof t.red&&"number"==typeof t.green&&"number"==typeof t.blue&&"number"==typeof t.alpha}(t))return L(t);if(function(t){return"number"==typeof t.red&&"number"==typeof t.green&&"number"==typeof t.blue&&("number"!=typeof t.alpha||void 0===t.alpha)}(t))return O(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&"number"==typeof t.alpha}(t))return function(t,e,s,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s&&"number"==typeof n)return n>=1?R(t,e,s):"rgba("+y(t,e,s)+","+n+")";if("object"==typeof t&&void 0===e&&void 0===s&&void 0===n)return t.alpha>=1?R(t.hue,t.saturation,t.lightness):"rgba("+y(t.hue,t.saturation,t.lightness)+","+t.alpha+")";throw new d(2)}(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&("number"!=typeof t.alpha||void 0===t.alpha)}(t))return function(t,e,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s)return R(t,e,s);if("object"==typeof t&&void 0===e&&void 0===s)return R(t.hue,t.saturation,t.lightness);throw new d(1)}(t);throw new d(8)}function $(t,e,s){return function(){var n=s.concat(Array.prototype.slice.call(arguments));return n.length>=e?t.apply(this,n):$(t,e,n)}}function F(t){return $(t,t.length,[])}F(function(t,e){if("transparent"===e)return e;var s=E(e);return D(n({},s,{hue:s.hue+parseFloat(t)}))});function k(t,e,s){return Math.max(t,Math.min(e,s))}F(function(t,e){if("transparent"===e)return e;var s=E(e);return D(n({},s,{lightness:k(0,1,s.lightness-parseFloat(t))}))});F(function(t,e){if("transparent"===e)return e;var s=E(e);return D(n({},s,{saturation:k(0,1,s.saturation-parseFloat(t))}))});F(function(t,e){if("transparent"===e)return e;var s=E(e);return D(n({},s,{lightness:k(0,1,s.lightness+parseFloat(t))}))});var B=F(function(t,e,s){if("transparent"===e)return s;if("transparent"===s)return e;if(0===t)return s;var i=_(e),o=n({},i,{alpha:"number"==typeof i.alpha?i.alpha:1}),a=_(s),r=n({},a,{alpha:"number"==typeof a.alpha?a.alpha:1}),h=o.alpha-r.alpha,c=2*parseFloat(t)-1,d=((c*h===-1?c:c+h)/(1+c*h)+1)/2,l=1-d;return L({red:Math.floor(o.red*d+r.red*l),green:Math.floor(o.green*d+r.green*l),blue:Math.floor(o.blue*d+r.blue*l),alpha:o.alpha*parseFloat(t)+r.alpha*(1-parseFloat(t))})});F(function(t,e){if("transparent"===e)return e;var s=_(e);return L(n({},s,{alpha:k(0,1,(100*("number"==typeof s.alpha?s.alpha:1)+100*parseFloat(t))/100)}))});F(function(t,e){if("transparent"===e)return e;var s=E(e);return D(n({},s,{saturation:k(0,1,s.saturation+parseFloat(t))}))});F(function(t,e){return"transparent"===e?e:D(n({},E(e),{hue:parseFloat(t)}))});F(function(t,e){return"transparent"===e?e:D(n({},E(e),{lightness:parseFloat(t)}))});F(function(t,e){return"transparent"===e?e:D(n({},E(e),{saturation:parseFloat(t)}))});F(function(t,e){return"transparent"===e?e:B(parseFloat(t),"rgb(0, 0, 0)",e)});F(function(t,e){return"transparent"===e?e:B(parseFloat(t),"rgb(255, 255, 255)",e)});var X=F(function(t,e){if("transparent"===e)return e;var s=_(e);return L(n({},s,{alpha:k(0,1,+(100*("number"==typeof s.alpha?s.alpha:1)-100*parseFloat(t)).toFixed(2)/100)}))}),Y=["blue","orange","purple","cyan","magenta","yellowgreen","darkgoldenrod","deeppink"],H=(t,e)=>{const s={};for(let n=0;n<t.connections.length;n++){const i=t.connections[n],o=e?.getNetConnectedToId(i.name);o&&!s[o]&&(s[o]=`hsl(${300*n/t.connections.length}, 100%, 50%)`),s[i.name]=(o?s[o]:null)??`hsl(${340*n/t.connections.length}, 100%, 50%)`}return s},V=(t,e)=>{try{return X(e,t)}catch(e){return console.error(e),t}},j=class extends e{nodes;edges;capacityPaths;nodeMap;nodeEdgeMap;unprocessedNodeIds;nodePortSegments;colorMap;constructor({nodes:t,edges:e,capacityPaths:n,colorMap:i}){super(),this.nodes=t,this.edges=e,this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=s(e),this.capacityPaths=n,this.colorMap=i??{},this.unprocessedNodeIds=[...new Set(n.flatMap(t=>t.nodeIds))],this.nodePortSegments=new Map}step(){const t=this.unprocessedNodeIds.pop();if(!t)return void(this.solved=!0);const e=[];for(const s of this.capacityPaths){const n=s.nodeIds.indexOf(t);-1!==n&&e.push({path:s,indexOfNodeInPath:n})}const s=this.nodeMap.get(t),n=[];for(const{path:i,indexOfNodeInPath:o}of e){const e=i.nodeIds[o-1],a=i.nodeIds[o+1];for(const o of[e,a]){const e=this.nodeMap.get(o);if(!e)continue;const a=Z(s,e),r=e.availableZ.filter(t=>s.availableZ.includes(t));if(0===r.length)continue;const h={capacityMeshNodeId:t,start:a.start,end:a.end,connectionNames:[i.connectionName],availableZ:r};n.push(h)}}const i=function(t){const e=[],s=t.map(t=>({...t,connectionNames:[...t.connectionNames],availableZ:[...t.availableZ].sort((t,e)=>t-e)}));for(;s.length>0;){const t=s.pop();let n=!1;for(let s=0;s<e.length;s++){const i=e[s],o=U(i.start,t.start)&&U(i.end,t.end)||U(i.start,t.end)&&U(i.end,t.start),a=G(i.availableZ,t.availableZ);if(o&&a){const e=new Set(i.connectionNames);t.connectionNames.forEach(t=>e.add(t)),i.connectionNames=Array.from(e),n=!0;break}}n||e.push(t)}return e}(n);this.nodePortSegments.set(t,i)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};return this.nodePortSegments.forEach((e,s)=>{this.nodeMap.get(s);e.forEach(e=>{e.start.x,e.end.x;for(let n=0;n<e.connectionNames.length;n++){const i={x:.05*Math.max(...e.availableZ),y:.05*Math.max(...e.availableZ)},o={x:(e.start.x+e.end.x)/2,y:(e.start.y+e.end.y)/2},a={x:o.x+i.x,y:o.y+i.y};i.x>0&&t.lines.push({points:[o,a],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5"}),t.points.push({x:a.x,y:a.y,label:`${s}: ${e.connectionNames.join(", ")}\navailableZ: ${e.availableZ.join(",")}\nnodePortSegmentId: ${e.nodePortSegmentId}`}),t.lines.push({points:[e.start,e.end],strokeColor:V(this.colorMap[e.connectionNames[n]],.6)})}})}),t}};function Z(t,e){const s={start:Math.max(t.center.x-t.width/2,e.center.x-e.width/2),end:Math.min(t.center.x+t.width/2,e.center.x+e.width/2)},n={start:Math.max(t.center.y-t.height/2,e.center.y-e.height/2),end:Math.min(t.center.y+t.height/2,e.center.y+e.height/2)};if(s.end-s.start<n.end-n.start){const t=(s.start+s.end)/2;return{start:{x:t,y:n.start},end:{x:t,y:n.end}}}{const t=(n.start+n.end)/2;return{start:{x:s.start,y:t},end:{x:s.end,y:t}}}}var W=1e-9;function U(t,e){return Math.abs(t.x-e.x)<W&&Math.abs(t.y-e.y)<W}function G(t,e){if(t.length!==e.length)return!1;for(let s=0;s<t.length;s++)if(t[s]!==e[s])return!1;return!0}var q=class extends e{unsolvedSegments;solvedSegments;nodeMap;colorMap;constructor({segments:t,colorMap:e,nodes:s}){super(),this.MAX_ITERATIONS=1e5,this.unsolvedSegments=t,this.solvedSegments=[],this.colorMap=e??{},this.nodeMap=Object.fromEntries(s.map(t=>[t.capacityMeshNodeId,t]))}_step(){let t=!1;const e=[...this.unsolvedSegments];for(const s of e){const e=s.connectionNames.length;if((!("assignedPoints"in s)||s.assignedPoints?.length!==e)&&1===e){const e={x:(s.start.x+s.end.x)/2,y:(s.start.y+s.end.y)/2,z:s.availableZ[0]};s.assignedPoints=[{connectionName:s.connectionNames[0],point:e}],this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(s),1),this.solvedSegments.push(s),t=!0}}if(!t&&e.length>0){let s=e[0];for(const t of e)t.connectionNames.length<s.connectionNames.length&&(s=t);const n=[...s.connectionNames].sort(),i=s.end.x-s.start.x,o=s.end.y-s.start.y,a=n.length,r=[];for(let t=1;t<=a;t++){const e=t/(a+1);r.push({x:s.start.x+i*e,y:s.start.y+o*e,z:s.availableZ[0]})}s.assignedPoints=n.map((t,e)=>({connectionName:t,point:r[e]})),this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(s),1),this.solvedSegments.push(s),t=!0}0===this.unsolvedSegments.length&&(this.solved=!0)}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.solvedSegments){const s=e.capacityMeshNodeId,n=this.nodeMap[s];t.has(s)||t.set(s,{capacityMeshNodeId:s,portPoints:[],center:n.center,width:n.width,height:n.height}),t.get(s).portPoints.push(...e.assignedPoints.map(t=>({...t.point,connectionName:t.connectionName})))}return Array.from(t.values())}visualize(){const t={points:[],lines:this.solvedSegments.map(t=>({points:[t.start,t.end],step:4})),rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Segment to Point Solver"};for(let e=0;e<this.solvedSegments.length;e++){const s=this.solvedSegments[e];for(let e=0;e<s.assignedPoints.length;e++){const n=s.assignedPoints[e],i={x:n.point.x,y:n.point.y},o={x:n.point.x+.05*n.point.z,y:n.point.y+.05*n.point.z};0!==n.point.z&&t.lines.push({points:[i,o],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5",step:4}),t.points.push({x:o.x,y:o.y,label:[`${s.capacityMeshNodeId}-${n.connectionName}`,`z: ${s.availableZ.join(",")}`,`nodePortSegmentId: ${s.nodePortSegmentId}`].join("\n"),color:this.colorMap[n.connectionName],step:4})}}const e=[],s={};for(const t of this.solvedSegments){const e=t.capacityMeshNodeId;s[e]||(s[e]={});for(const n of t.assignedPoints)s[e][n.connectionName]||(s[e][n.connectionName]=[]),s[e][n.connectionName].push({x:n.point.x,y:n.point.y})}for(const t in s)for(const n in s[t]){const i=s[t][n];i.length>1&&e.push({points:i,step:4,strokeDash:"5 5",strokeColor:this.colorMap[n]||"#000"})}return t.lines.push(...e),t}};import K from"object-hash";var J=class{cacheHitsByPrefix={};cacheMissesByPrefix={};isSyncCache=!0;cacheHits=0;cacheMisses=0;cache=new Map;getCachedSolutionSync(t){const e=this.cache.get(t);if(void 0!==e){this.cacheHits++;const s=t.split(":")[0];return this.cacheHitsByPrefix[s]=(this.cacheHitsByPrefix[s]||0)+1,structuredClone(e)}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){this.cache.set(t,structuredClone(e))}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){this.cache.clear(),this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}getAllCacheKeys(){return Array.from(this.cache.keys())}},Q="tscircuit_autorouter_cache_",tt=class{isSyncCache=!0;cacheHits=0;cacheMisses=0;cacheHitsByPrefix={};cacheMissesByPrefix={};constructor(){}getKey(t){return`${Q}${t}`}getCachedSolutionSync(t){if("undefined"==typeof localStorage)return;const e=this.getKey(t);try{const s=localStorage.getItem(e);if(null!==s){const e=JSON.parse(s);this.cacheHits++;const n=t.split(":")[0];return this.cacheHitsByPrefix[n]=(this.cacheHitsByPrefix[n]||0)+1,e}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}catch(s){console.error(`Error getting cached solution sync for ${e}:`,s),this.cacheMisses++;const n=t.split(":")[0];return void(this.cacheMissesByPrefix[n]=(this.cacheMissesByPrefix[n]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){if("undefined"==typeof localStorage)return;const s=this.getKey(t);try{const t=JSON.stringify(e);localStorage.setItem(s,t)}catch(t){console.error(`Error setting cached solution sync for ${s}:`,t),t instanceof DOMException&&("QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&console.warn(`LocalStorage quota exceeded. Failed to cache solution for ${s}. Consider clearing the cache.`)}}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){if("undefined"!=typeof localStorage)try{const t=[];for(let e=0;e<localStorage.length;e++){const s=localStorage.key(e);s?.startsWith(Q)&&t.push(s)}t.forEach(t=>localStorage.removeItem(t)),console.log(`Cleared ${t.length} items from LocalStorage cache.`)}catch(t){console.error("Error clearing LocalStorage cache:",t)}finally{this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}}getAllCacheKeys(){const t=[];for(let e=0;e<1e4;e++){const s=localStorage.key(e);if(!s)break;s.includes(Q)&&t.push(s)}return t}};function et(){return globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE||nt(),globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE}function st(){return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE||nt(),globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE}function nt(){globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE??=new tt,globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE??=new J}function it(t){const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-s,maxY:t.center.y+s}}function ot(t,e,s){return Math.max(e,Math.min(s,t))}function at(t,e,s,n){const i=rt(t,e,s),o=rt(t,e,n),a=rt(s,n,t),r=rt(s,n,e);return i!==o&&a!==r||(!(0!==i||!ht(t,s,e))||(!(0!==o||!ht(t,n,e))||(!(0!==a||!ht(s,t,n))||!(0!==r||!ht(s,e,n)))))}function rt(t,e,s){const n=(e.y-t.y)*(s.x-e.x)-(e.x-t.x)*(s.y-e.y);return 0===n?0:n>0?1:2}function ht(t,e,s){return e.x<=Math.max(t.x,s.x)&&e.x>=Math.min(t.x,s.x)&&e.y<=Math.max(t.y,s.y)&&e.y>=Math.min(t.y,s.y)}function ct(t,e,s){const n=(s.x-e.x)**2+(s.y-e.y)**2;if(0===n)return dt(t,e);let i=((t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y))/n;i=Math.max(0,Math.min(1,i));return dt(t,{x:e.x+i*(s.x-e.x),y:e.y+i*(s.y-e.y)})}function dt(t,e){const s=t.x-e.x,n=t.y-e.y;return Math.sqrt(s*s+n*n)}function lt(t,e,s,n){const i=e.x-t.x,o=e.y-t.y,a=n.x-s.x,r=n.y-s.y,h=t.x-s.x,c=t.y-s.y,d=i*r-o*a;if(Math.abs(d)<1e-10)return null;const l=(c*a-h*r)/d,u=(i*c-o*h)/d,p=1e-9;if(l>=-1e-9&&l<=1+p&&u>=-1e-9&&u<=1+p){return{x:t.x+l*i,y:t.y+l*o}}return null}function ut(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var pt=t=>{if("minX"in t)return t;const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,minY:t.center.y-s,maxX:t.center.x+e,maxY:t.center.y+s}},ft=t=>[{x:t.minX,y:t.minY},{x:t.maxX,y:t.minY},{x:t.maxX,y:t.maxY},{x:t.minX,y:t.maxY}],gt=t=>{const e=[];for(let s=0;s<t.length;s++){const n=t[s],i=t[(s+1)%t.length];e.push([n,i])}return e},mt=(t,e,s)=>{const n=(t.y-e.y)*(s.x-e.x)-(t.x-e.x)*(s.y-e.y);if(Math.abs(n)>1e-9)return!1;const i=(t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y);if(i<0)return!1;return!(i>(s.x-e.x)**2+(s.y-e.y)**2)},yt=(t,e)=>{if(e.length<3)return!1;const s=gt(e);for(const[e,n]of s)if(mt(t,e,n))return!0;let n=!1;for(let s=0,i=e.length-1;s<e.length;i=s++){const o=e[s].x,a=e[s].y,r=e[i].x,h=e[i].y;a>t.y!=h>t.y&&t.x<(r-o)*(t.y-a)/(h-a)+o&&(n=!n)}return n},xt=(t,e)=>{const s=ft(t),n=[[s[0],s[1]],[s[1],s[2]],[s[2],s[3]],[s[3],s[0]]],i=gt(e);for(const[t,e]of i)for(const[s,i]of n)if(at(t,e,s,i))return!0;return!1},vt=(t,e)=>((t,e)=>!(e.length<3)&&(!!e.some(e=>((t,e)=>t.x>=e.minX&&t.x<=e.maxX&&t.y>=e.minY&&t.y<=e.maxY)(e,t))||(!!ft(t).some(t=>yt(t,e))||xt(t,e))))(pt(t),e),Mt=(t,e)=>((t,e)=>!(e.length<3)&&(!!ft(t).every(t=>yt(t,e))&&!xt(t,e)))(pt(t),e);function St(t,e,s,n){if(t.x===e.x&&t.y===e.y)return ct(t,s,n);if(s.x===n.x&&s.y===n.y)return ct(s,t,e);if(at(t,e,s,n))return 0;const i=[ct(t,s,n),ct(e,s,n),ct(s,t,e),ct(n,t,e)];return Math.min(...i)}function bt(t,e,s){const n=s.width/2,i=s.height/2;return function(t,e,s){const n={x:s.minX,y:s.minY},i={x:s.maxX,y:s.minY},o={x:s.minX,y:s.maxY},a={x:s.maxX,y:s.maxY};if(at(t,e,n,i)||at(t,e,i,a)||at(t,e,a,o)||at(t,e,o,n))return 0;if(t.x>=s.minX&&t.x<=s.maxX&&t.y>=s.minY&&t.y<=s.maxY&&e.x>=s.minX&&e.x<=s.maxX&&e.y>=s.minY&&e.y<=s.maxY)return 0;const r=[ct(n,t,e),ct(i,t,e),ct(o,t,e),ct(a,t,e)];if(t.x>=s.minX&&t.x<=s.maxX&&t.y>=s.minY&&t.y<=s.maxY)return 0;if(e.x>=s.minX&&e.x<=s.maxX&&e.y>=s.minY&&e.y<=s.maxY)return 0;if(t.x<s.minX||t.x>s.maxX||t.y<s.minY||t.y>s.maxY){const e=ot(t.x,s.minX,s.maxX),n=ot(t.y,s.minY,s.maxY);r.push(dt(t,{x:e,y:n}))}if(e.x<s.minX||e.x>s.maxX||e.y<s.minY||e.y>s.maxY){const t=ot(e.x,s.minX,s.maxX),n=ot(e.y,s.minY,s.maxY);r.push(dt(e,{x:t,y:n}))}return Math.min(...r)}(t,e,{minX:s.center.x-n,maxX:s.center.x+n,minY:s.center.y-i,maxY:s.center.y+i})}function Nt(t,e,s){const n=s.x-e.x,i=s.y-e.y,o=n*n+i*i;if(0===o)return{x:e.x,y:e.y};let a=((t.x-e.x)*n+(t.y-e.y)*i)/o;a=Math.max(0,Math.min(1,a));return{x:e.x+a*n,y:e.y+a*i}}var It=class{heap=[];constructor(t){this.heap=[];for(const e of t)this.enqueue(e)}getLeftChildIndex(t){return 2*t+1}getRightChildIndex(t){return 2*t+2}getParentIndex(t){return Math.floor((t-1)/2)}hasLeftChild(t){return this.getLeftChildIndex(t)<this.heap.length}hasRightChild(t){return this.getRightChildIndex(t)<this.heap.length}hasParent(t){return this.getParentIndex(t)>=0}leftChild(t){return this.heap[this.getLeftChildIndex(t)]}rightChild(t){return this.heap[this.getRightChildIndex(t)]}parent(t){return this.heap[this.getParentIndex(t)]}swap(t,e){const s=this.heap[t];this.heap[t]=this.heap[e],this.heap[e]=s}dequeue(){if(0===this.heap.length)return null;const t=this.heap[0];return this.heap[0]=this.heap[this.heap.length-1],this.heap.pop(),this.heapifyDown(),t}peek(){return 0===this.heap.length?null:this.heap[0]}enqueue(t){this.heap.push(t),this.heapifyUp()}heapifyUp(){let t=this.heap.length-1;for(;this.hasParent(t)&&this.parent(t).f>this.heap[t].f;)this.swap(this.getParentIndex(t),t),t=this.getParentIndex(t)}heapifyDown(){let t=0;for(;this.hasLeftChild(t);){let e=this.getLeftChildIndex(t);if(this.hasRightChild(t)&&this.rightChild(t).f<this.leftChild(t).f&&(e=this.getRightChildIndex(t)),this.heap[t].f<this.heap[e].f)break;this.swap(t,e),t=e}}},Pt=class extends e{obstacleRoutes;bounds;boundsSize;boundsCenter;A;B;straightLineDistance;viaDiameter;traceThickness;obstacleMargin;layerCount;minCellSize=.05;cellStep=.05;GREEDY_MULTIPLER=1.1;numRoutes;VIA_PENALTY_FACTOR=.3;CELL_SIZE_FACTOR;exploredNodes;candidates;connectionName;solvedPath=null;futureConnections;hyperParameters;connMap;debug_exploredNodesOrdered;debug_nodesTooCloseToObstacle;debug_nodePathToParentIntersectsObstacle;debugEnabled=!0;initialNodeGridOffset;constructor(t){super(),this.bounds=t.bounds,this.connMap=t.connMap,this.hyperParameters=t.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=t.connectionName,this.obstacleRoutes=t.obstacleRoutes,this.A=t.A,this.B=t.B,this.viaDiameter=t.viaDiameter??.6,this.traceThickness=t.traceThickness??.15,this.obstacleMargin=t.obstacleMargin??.2,this.layerCount=t.layerCount??2,this.exploredNodes=new Set,this.straightLineDistance=dt(this.A,this.B),this.futureConnections=t.futureConnections??[],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;const e=Math.ceil(5*(this.numRoutes+1));let s=this.boundsSize.width/this.cellStep,n=this.boundsSize.height/this.cellStep;for(;s*n>e**2&&!(2*this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,s=this.boundsSize.width/this.cellStep,n=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR;const i=Math.abs(this.A.x-this.bounds.minX)<.001&&Math.abs(this.B.x-this.bounds.minX)<.001||Math.abs(this.A.x-this.bounds.maxX)<.001&&Math.abs(this.B.x-this.bounds.maxX)<.001||Math.abs(this.A.y-this.bounds.minY)<.001&&Math.abs(this.B.y-this.bounds.minY)<.001||Math.abs(this.A.y-this.bounds.maxY)<.001&&Math.abs(this.B.y-this.bounds.maxY)<.001;this.futureConnections&&0===this.futureConnections.length&&0===this.obstacleRoutes.length&&!i&&this.handleSimpleCases();const o={x:Math.round(t.A.x/(this.cellStep/2))*(this.cellStep/2),y:Math.round(t.A.y/(this.cellStep/2))*(this.cellStep/2)};this.initialNodeGridOffset={x:o.x-Math.round(t.A.x/this.cellStep)*this.cellStep,y:o.y-Math.round(t.A.y/this.cellStep)*this.cellStep},this.candidates=new It([{...t.A,...o,z:t.A.z??0,g:0,h:0,f:0,parent:{...t.A,z:t.A.z??0,g:0,h:0,f:0,parent:null}}])}handleSimpleCases(){this.solved=!0;const{A:t,B:e}=this,s=t.z===e.z?[t,e]:[t,{...this.boundsCenter,z:this.A.z},{...this.boundsCenter,z:e.z},e];this.solvedPath={connectionName:this.connectionName,route:s,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(t,e,s){if(e??=this.obstacleMargin,s&&t.parent){const s=this.getViasInNodePath(t.parent);for(const n of s)if(dt(t,n)<this.viaDiameter/2+e)return!0}for(const n of this.obstacleRoutes){const i=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!i){const i=Ct(n);for(const n of i)if((s||n.z===t.z)&&ct(t,n.A,n.B)<this.traceThickness+e)return!0}for(const s of n.vias)if(dt(t,s)<this.viaDiameter/2+this.traceThickness/2+e)return!0}return!1}isNodeTooCloseToEdge(t,e){const s=e?this.viaDiameter/2+this.obstacleMargin/2:this.obstacleMargin/2,n=t.x<this.bounds.minX+s||t.x>this.bounds.maxX-s||t.y<this.bounds.minY+s||t.y>this.bounds.maxY-s;return!(n&&!e&&(dt(t,this.B)<2*s||dt(t,this.A)<2*s))&&n}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const s of this.obstacleRoutes){const n=this.connMap?.areIdsConnected?.(this.connectionName,s.connectionName);if(!n)for(const n of Ct(s))if(n.z===t.z&&at(t,e,n.A,n.B))return!0}return!1}computeH(t){return dt(t,this.B)+(t.z!==this.B.z?this.viaPenaltyDistance:0)}computeG(t){return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+dt(t,t.parent)}computeF(t,e){return t+e*this.GREEDY_MULTIPLER}getNodeKey(t){return`${Math.round(t.x/this.cellStep)*this.cellStep},${Math.round(t.y/this.cellStep)*this.cellStep},${t.z}`}getNeighbors(t){const e=[],{maxX:s,minX:n,maxY:i,minY:o}=this.bounds;for(let a=-1;a<=1;a++)for(let r=-1;r<=1;r++){if(0===a&&0===r)continue;const h={...t,parent:t,x:_t(t.x+a*this.cellStep,n,s),y:_t(t.y+r*this.cellStep,o,i)},c=this.getNodeKey(h);this.exploredNodes.has(c)||(this.isNodeTooCloseToObstacle(h)?(this.debug_nodesTooCloseToObstacle.add(c),this.exploredNodes.add(c)):this.isNodeTooCloseToEdge(h,!1)?this.exploredNodes.add(c):this.doesPathToParentIntersectObstacle(h)?(this.debug_nodePathToParentIntersectsObstacle.add(c),this.exploredNodes.add(c)):(h.g=this.computeG(h),h.h=this.computeH(h),h.f=this.computeF(h.g,h.h),e.push(h)))}for(let s=0;s<this.layerCount;s++){if(s===t.z)continue;const n={...t,parent:t,z:s};this.exploredNodes.has(this.getNodeKey(n))||this.isNodeTooCloseToObstacle(n,this.viaDiameter/2+this.obstacleMargin/2,!0)||this.isNodeTooCloseToEdge(n,!0)||(n.g=this.computeG(n),n.h=this.computeH(n),n.f=this.computeF(n.g,n.h),e.push(n))}return e}getNodePath(t){const e=[];for(;t;)e.push(t),t=t.parent;return e}getViasInNodePath(t){const e=this.getNodePath(t),s=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&s.push({x:e[t].x,y:e[t].y});return s}setSolvedPath(t){const e=this.getNodePath(t);e.reverse();const s=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&s.push({x:e[t].x,y:e[t].y});this.solvedPath={connectionName:this.connectionName,traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,route:e.map(t=>({x:t.x,y:t.y,z:t.z})).concat([this.B]),vias:s}}computeProgress(t,e,s){s||(e+=this.viaPenaltyDistance);const n=1-e/this.straightLineDistance;return Math.max(this.progress||0,2/Math.PI*Math.atan(.112*n/(1-n)))}_step(){let t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;for(;t&&e&&this.exploredNodes.has(e);)t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;if(!t||!e)return void(this.failed=!0);this.exploredNodes.add(e),this.debug_exploredNodesOrdered.push(e);const s=dt(t,this.B);this.progress=this.computeProgress(t,s,t.z===this.B.z),s<=this.cellStep*Math.SQRT2&&t.z===this.B.z&&!this.doesPathToParentIntersectObstacle({...t,parent:t,x:this.B.x,y:this.B.y})&&(this.solved=!0,this.setSolvedPath(t));const n=this.getNeighbors(t);for(const t of n)this.candidates.enqueue(t)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.points.push({x:this.A.x,y:this.A.y,label:`Input A\nz: ${this.A.z}`,color:"orange"}),t.points.push({x:this.B.x,y:this.B.y,label:`Input B\nz: ${this.B.z}`,color:"orange"}),t.lines.push({points:[this.A,this.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:"Direct Input Connection"});for(let e=0;e<this.obstacleRoutes.length;e++){const s=this.obstacleRoutes[e];for(let n=0;n<s.route.length-1;n++){const i=s.route[n].z;t.lines.push({points:[s.route[n],s.route[n+1]],strokeColor:0===i?"rgba(255, 0, 0, 0.75)":"rgba(255, 128, 0, 0.25)",strokeWidth:s.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`})}}for(let e=0;e<this.debug_exploredNodesOrdered.length;e++){const s=this.debug_exploredNodesOrdered[e],[n,i,o]=s.split(",").map(Number);this.debug_nodesTooCloseToObstacle.has(s)||(this.debug_nodePathToParentIntersectsObstacle.has(s)||t.rects.push({center:{x:n+this.initialNodeGridOffset.x+o*this.cellStep/20,y:i+this.initialNodeGridOffset.y+o*this.cellStep/20},fill:0===o?`rgba(255,0,255,${.3-e/this.debug_exploredNodesOrdered.length*.2})`:`rgba(0,0,255,${.3-e/this.debug_exploredNodesOrdered.length*.2})`,width:.9*this.cellStep,height:.9*this.cellStep,label:`Explored (z=${o})`}))}if(this.candidates.peek()){const e=this.candidates.peek();t.rects.push({center:{x:e.x+e.z*this.cellStep/20,y:e.y+e.z*this.cellStep/20},fill:"rgba(0, 255, 0, 0.8)",width:.9*this.cellStep,height:.9*this.cellStep,label:`Next (z=${e.z})`})}for(const e of this.obstacleRoutes)for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:this.viaDiameter/2,fill:"rgba(255, 0, 0, 0.5)",label:"Via"});if(this.solvedPath){t.lines.push({points:this.solvedPath.route,strokeColor:"green",label:"Solved Route"});for(const e of this.solvedPath.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"green",label:"Via"})}return t}};function Ct(t){const e=[];for(let s=0;s<t.route.length-1;s++)t.route[s].z===t.route[s+1].z&&e.push({z:t.route[s].z,A:t.route[s],B:t.route[s+1]});return e}function _t(t,e,s){return Math.max(e,Math.min(t,s))}var Et=class extends Pt{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=!1;constructor(t){super(t);for(const e in t.hyperParameters)this[e]=t.hyperParameters[e];const e=this.boundsSize.width/this.viaDiameter,s=Math.max(1,this.numRoutes);this.VIA_PENALTY_FACTOR=e/s*.3*this.VIA_PENALTY_FACTOR_2}getClosestFutureConnectionPoint(t){let e=1/0,s=null;for(const n of this.futureConnections)for(const i of n.points){const n=dt(t,i)+(t.z!==i.z?this.viaPenaltyDistance:0);n<e&&(e=n,s=i)}return s}diminishCloseToGoal(t){const e=dt(t,this.B);return 1-Math.exp(-e/this.straightLineDistance*5)}getFutureConnectionPenalty(t,e){let s=0;const n=this.getClosestFutureConnectionPoint(t),i=dt(t,this.B);if(n){const o=dt(t,n);if(i<=o)return 0;const a=o/(this.viaDiameter*this.FUTURE_CONNECTION_PROXIMITY_VD);s=(e?this.straightLineDistance*this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR:this.straightLineDistance*this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR)*Math.exp(5*-a)}return s}computeH(t){const e=dt(t,this.B)**1.6;this.straightLineDistance;return e+(t.z!==this.B.z?this.viaPenaltyDistance:0)+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}computeG(t){const e=Math.abs(t.x-t.parent.x),s=Math.abs(t.y-t.parent.y),n=Math.sqrt(e**2+s**2),i=t.z%2==0,o=this.FLIP_TRACE_ALIGNMENT_DIRECTION?i?e:s:i?s:e;return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+n+o*this.MISALIGNED_DIST_PENALTY_FACTOR+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}};function Tt(t){let e=t;for(let t=0;t<10;t++)e=16807*e%2147483647;let s=e;e=(69069*t+1)%2147483647;for(let t=0;t<10;t++)e=48271*e%2147483647;let n=e;return()=>{let t=s;s=n,t^=t<<23,t^=t>>>17,t^=n,t^=n>>>26,n=t;const e=(s+n)/4294967296;return e-Math.floor(e)}}var wt={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 zt(t,e){if(0===e)return t;if(t.length<=4){const s=wt[t.length];return s[e%s.length].map(e=>t[e])}const s=Tt(e),n=t.slice();for(let t=0;t<n.length;t++){const e=Math.floor(s()*n.length),i=Math.floor(s()*(t+1));[n[e],n[i]]=[n[i],n[e]]}return n}function At(t){const e={minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2};for(const s of t.portPoints)s.x<e.minX&&(e.minX=s.x),s.x>e.maxX&&(e.maxX=s.x),s.y<e.minY&&(e.minY=s.y),s.y>e.maxY&&(e.maxY=s.y);return e}var Rt=class extends e{nodeWithPortPoints;colorMap;unsolvedConnections;totalConnections;solvedRoutes;failedSubSolvers;hyperParameters;minDistBetweenEnteringPoints;viaDiameter;traceWidth;activeSubSolver=null;connMap;get failedSolvers(){return this.failedSubSolvers}get activeSolver(){return this.activeSubSolver}constructor(t){const{nodeWithPortPoints:e,colorMap:s}=t;super(),this.nodeWithPortPoints=e,this.colorMap=s??{},this.solvedRoutes=[],this.hyperParameters=t.hyperParameters??{},this.failedSubSolvers=[],this.connMap=t.connMap,this.viaDiameter=t.viaDiameter??.6,this.traceWidth=t.traceWidth??.15;const n=new Map;for(const{connectionName:t,x:s,y:i,z:o}of e.portPoints)n.set(t,[...n.get(t)??[],{x:s,y:i,z:o??0}]);this.unsolvedConnections=Array.from(n.entries().map(([t,e])=>({connectionName:t,points:e}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=zt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},s)=>({...e,points:zt(t,7117*s+(this.hyperParameters.SHUFFLE_SEED??0))}))),this.totalConnections=this.unsolvedConnections.length,this.MAX_ITERATIONS=1e3*this.totalConnections**1.5,this.minDistBetweenEnteringPoints=(t=>{let e=1/0;const s=t.portPoints;for(let t=0;t<s.length;t++)for(let n=t+1;n<s.length;n++){if(s[t].z!==s[n].z)continue;const i=s[t],o=s[n],a=Math.sqrt((i.x-o.x)**2+(i.y-o.y)**2);e=Math.min(e,a)}return e===1/0?0:e})(this.nodeWithPortPoints)}computeProgress(){return(this.solvedRoutes.length+(this.activeSubSolver?.progress||0))/this.totalConnections}_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(t=>t.error).join("\n"),this.failed=!0));const t=this.unsolvedConnections.pop();if(this.progress=this.computeProgress(),!t)return void(this.solved=0===this.failedSubSolvers.length);if(1===t.points.length)return;if(2===t.points.length){const[e,s]=t.points;if(e.x===s.x&&e.y===s.y&&e.z===s.z)return}const{connectionName:e,points:s}=t;this.activeSubSolver=new Et({connectionName:e,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:At(this.nodeWithPortPoints),A:{x:s[0].x,y:s[0].y,z:s[0].z},B:{x:s[s.length-1].x,y:s[s.length-1].y,z:s[s.length-1].z},obstacleRoutes:this.connMap?this.solvedRoutes.filter(t=>!this.connMap.areIdsConnected(t.connectionName,e)):this.solvedRoutes,futureConnections:this.unsolvedConnections,layerCount:this.nodeWithPortPoints.portPoints.reduce((t,e)=>Math.max(t,(e.z??0)+1),2),hyperParameters:this.hyperParameters,connMap:this.connMap,viaDiameter:this.viaDiameter,traceThickness:this.traceWidth})}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:[e.connectionName,`layer: ${e.z}`].join("\n"),color:this.colorMap[e.connectionName]??"blue"});for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e];if(s.route.length>0){const n=this.colorMap[s.connectionName]??"blue";for(let i=0;i<s.route.length-1;i++){const o=s.route[i],a=s.route[i+1];t.lines.push({points:[o,a],strokeColor:0===o.z?V(n,.2):V(n,.8),layer:`route-layer-${o.z}`,step:e,strokeWidth:s.traceThickness})}for(const i of s.vias)t.circles.push({center:{x:i.x,y:i.y},radius:s.viaDiameter/2,fill:V(n,.5),layer:"via",step:e})}}const e=At(this.nodeWithPortPoints),{minX:s,minY:n,maxX:i,maxY:o}=e;return t.lines.push({points:[{x:s,y:n},{x:i,y:n},{x:i,y:o},{x:s,y:o},{x:s,y:n}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}},Ot=t=>Math.round(200*t)/200,Lt=t=>"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t));nt();var Dt=class extends Rt{cacheProvider;cacheHit=!1;hasAttemptedToUseCache=!1;initialUnsolvedConnections;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?st():t.cacheProvider,this.initialUnsolvedConnections=Lt(this.unsolvedConnections),(this.solved||this.failed)&&this.cacheProvider&&!this.cacheHit&&this.saveToCacheSync()}_step(){if(!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync())return;const t=this.solved,e=this.failed;super._step(),!this.cacheProvider||this.cacheHit||!this.solved&&!this.failed||t||e||this.saveToCacheSync()}computeCacheKeyAndTransform(){const t=this.nodeWithPortPoints.center,e=this.initialUnsolvedConnections.map(({connectionName:e,points:s})=>({connectionName:e,points:s.map(s=>({connectionName:e,x:Ot(s.x-t.x),y:Ot(s.y-t.y),z:s.z??0}))})),s=Object.fromEntries(Object.entries(this.hyperParameters??{}).filter(([,t])=>void 0!==t).sort(([t],[e])=>t.localeCompare(e))),n=this.connMap?this.initialUnsolvedConnections.map(({connectionName:t})=>({connectionName:t,connectedIds:[...new Set(this.connMap.getIdsConnectedToNet(t)??[])].sort()})):void 0,i={node:{width:Ot(this.nodeWithPortPoints.width),height:Ot(this.nodeWithPortPoints.height),center:{x:Ot(this.nodeWithPortPoints.center.x),y:Ot(this.nodeWithPortPoints.center.y)},availableZ:this.nodeWithPortPoints.availableZ?[...this.nodeWithPortPoints.availableZ].sort():void 0},normalizedConnections:e,normalizedHyperParameters:s,minDistBetweenEnteringPoints:Ot(this.minDistBetweenEnteringPoints),normalizedConnMap:n},o=`intranode-solver:${K(i)}`,a={};return this.cacheKey=o,this.cacheToSolveSpaceTransform=a,{cacheKey:o,cacheToSolveSpaceTransform:a}}applyCachedSolution(t){t.success?(this.solvedRoutes=Lt(t.solvedRoutes),this.solved=!0,this.failed=!1):(this.solvedRoutes=[],this.failedSubSolvers=[],this.solved=!1,this.failed=!0,this.error=t.error??this.error),this.unsolvedConnections=[],this.activeSubSolver=null,this.cacheHit=!0,this.progress=1}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return!1;if(!this.cacheKey)try{this.computeCacheKeyAndTransform()}catch(t){return console.error("Error computing cache key:",t),!1}if(!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(null!=t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(!this.cacheProvider?.isSyncCache)return;if(!this.cacheKey)try{this.computeCacheKeyAndTransform()}catch(t){return void console.error("Error computing cache key during save:",t)}if(!this.cacheKey)return void console.error("Failed to compute cache key before saving.");const t=this.failed?{success:!1,error:this.error??void 0}:{success:!0,solvedRoutes:Lt(this.solvedRoutes)};try{this.cacheProvider.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}},$t=class extends e{GREEDY_MULTIPLIER=1.2;MIN_SUBSTEPS=1;supervisedSolvers;winningSolver;getHyperParameterDefs(){throw new Error("Not implemented")}getCombinationDefs(){return null}getHyperParameterCombinations(t){t||(t=this.getHyperParameterDefs());const e=[];if(0===t.length)return[{}];const[s,...n]=t,i=this.getHyperParameterCombinations(n);return s.possibleValues.forEach(t=>{i.forEach(s=>{e.push({...s,...t})})}),e}initializeSolvers(){const t=this.getHyperParameterDefs(),e=this.getCombinationDefs()??[t.map(t=>t.name)];this.supervisedSolvers=[];for(const s of e){const e=this.getHyperParameterCombinations(t.filter(t=>s.includes(t.name)));for(const t of e){const e=this.generateSolver(t),s=this.computeG(e);this.supervisedSolvers.push({hyperParameters:t,solver:e,h:0,g:s,f:s})}}}generateSolver(t){throw new Error("Not implemented")}computeG(t){return t.iterations/t.MAX_ITERATIONS}computeH(t){return 1-(t.progress||0)}computeF(t,e){return t+e*this.GREEDY_MULTIPLIER}getSupervisedSolverWithBestFitness(){let t=1/0,e=null;for(const s of this.supervisedSolvers??[]){if(s.solver.solved)return s;if(s.solver.failed)continue;const n=s.f;n<t&&(t=n,e=s)}return e}getFailureMessage(){return"All solvers failed in hyper solver."}_step(){this.supervisedSolvers||this.initializeSolvers();const t=this.getSupervisedSolverWithBestFitness();if(!t)return this.failed=!0,void(this.error=this.getFailureMessage());for(let e=0;e<this.MIN_SUBSTEPS;e++)t.solver.step();t.g=this.computeG(t.solver),t.h=this.computeH(t.solver),t.f=this.computeF(t.g,t.h),t.solver.solved&&(this.solved=!0,this.winningSolver=t.solver,this.onSolve?.(t))}onSolve(t){}visualize(){const t=this.getSupervisedSolverWithBestFitness();let e={lines:[],circles:[],points:[],rects:[]};return t&&(e=t.solver.visualize()),e}};function Ft({A:t,B:e,C:s,D:n,E:i,F:o,radius:a,margin:r,subdivisions:h=0}){const c=(t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}),d=(t,e,s)=>{const n=e.x-t.x,i=e.y-t.y,o=Math.sqrt(n*n+i*i),a=n/o,r=i/o,h=-r,c=a;return{midpoint:{x:(t.x+e.x)/2,y:(t.y+e.y)/2},A_Opp:{x:t.x-a*s,y:t.y-r*s},A_Right:{x:t.x+h*s,y:t.y+c*s},A_Left:{x:t.x-h*s,y:t.y-c*s},B_Opp:{x:e.x+a*s,y:e.y+r*s},B_Right:{x:e.x+h*s,y:e.y+c*s},B_Left:{x:e.x-h*s,y:e.y-c*s}}},l=(t,e)=>{const s=dt(t,e.start),n=dt(t,e.end),i=dt(e.start,e.end);return Math.abs(s+n-i)<1e-4},u=(t,e)=>{const{start:s,end:n}=t,{start:i,end:o}=e;if(l(s,e)||l(n,e)||l(i,t)||l(o,t))return!0;const a=n.x-s.x,r=n.y-s.y,h=o.x-i.x,c=o.y-i.y,d=a*c-r*h;if(Math.abs(d)<1e-4)return!1;const u=i.x-s.x,p=i.y-s.y,f=(u*c-p*h)/d,g=(u*r-p*a)/d;return f>0&&f<1&&g>0&&g<1},p=(t,e)=>{const s=[];for(let e=0;e<t.length-1;e++)s.push({start:t[e],end:t[e+1]});const n=[];for(let t=0;t<e.length-1;t++)n.push({start:e[t],end:e[t+1]});for(const t of s)for(const e of n)if(u(t,e))return!0;return!1},f=t=>{let e=0;for(let s=1;s<t.length;s++){const n=t[s].x-t[s-1].x,i=t[s].y-t[s-1].y;e+=Math.sqrt(n*n+i*i)}return e},g=(t,e)=>{const{start:s,end:n}=t,i=n.x-s.x,o=n.y-s.y,a=i*i+o*o;if(0===a)return{...s,t:0};const r=Math.max(0,Math.min(1,((e.x-s.x)*i+(e.y-s.y)*o)/a));return{x:s.x+r*i,y:s.y+r*o,t:r}},m=(e,s,n)=>{const i=g(e,s);if(dt(i,s)>=n)return i;const o=i.x-s.x,a=i.y-s.y,r=Math.sqrt(o*o+a*a);if(0===r){const o=e.end.x-e.start.x,a=e.end.y-e.start.y,r=Math.sqrt(o*o+a*a);return{x:s.x+n*o/r,y:s.y+n*a/r,t:i.t,isSpecial:!0,specialType:s===t?"A":"B"}}return{x:s.x+n*o/r,y:s.y+n*a/r,t:i.t,isSpecial:!0,specialType:s===t?"A":"B"}},y=d(t,e,a),x=d(t,e,a+r),v=(t,e,s,n,i)=>{const o=t.points;if(o.length<2)return o;const r=s+n,h=[o[0]];for(let t=0;t<o.length-1;t++){const s={start:o[t],end:o[t+1]};if(ct(e,s.start,s.end)<r){const t=g(s,e),n=t.x-e.x,i=t.y-e.y,o=Math.sqrt(n*n+i*i);let c=null;if(o>1e-6)c={x:e.x+r*n/o,y:e.y+r*i/o};else{const t=s.end.x-s.start.x,n=s.end.y-s.start.y,i=Math.sqrt(t*t+n*n);i>1e-6&&(c={x:e.x+r*t/i,y:e.y+r*n/i})}c&&dt(s.start,c)>a/10&&h.push(c)}dt(h[h.length-1],s.end)>a/10&&h.push(s.end)}if(h.length>1){const t=[h[0]];for(let e=1;e<h.length;e++)dt(t[t.length-1],h[e])>a/10&&t.push(h[e]);return t}return h},M=(()=>{const t=[[s,y.B_Left,y.B_Opp,y.B_Right,c(y.midpoint,c(y.B_Right,y.A_Right)),c(y.midpoint,c(y.A_Left,y.B_Left)),y.A_Left,y.A_Opp,y.A_Right,n],[s,y.B_Right,y.B_Opp,y.B_Left,c(y.midpoint,c(y.A_Left,y.B_Left)),c(y.midpoint,c(y.A_Right,y.B_Right)),y.A_Right,y.A_Opp,y.A_Left,n],[n,y.B_Left,y.B_Opp,y.B_Right,c(y.midpoint,c(y.A_Right,y.B_Right)),c(y.midpoint,c(y.A_Left,y.B_Left)),y.A_Left,y.A_Opp,y.A_Right,s],[n,y.B_Right,y.B_Opp,y.B_Left,c(y.midpoint,c(y.A_Left,y.B_Left)),c(y.midpoint,c(y.A_Right,y.B_Right)),y.A_Right,y.A_Opp,y.A_Left,s]],e=[];for(let s=0;s<t.length;s++){const n=t[s],i={start:n[0],end:n[1]},o={start:n[n.length-2],end:n[n.length-1]},a={start:n[3],end:n[4]};u(i,o)||u(i,a)||u(o,a)||e.push({index:s+1,path:n,length:f(n)})}if(0===e.length)return{index:0,path:[]};const i=e.sort((t,e)=>t.length-e.length)[0],o=[...i.path],a=o[0],r=dt(a,o[2]),h=dt(a,o[3]),d=r<h?2:3;(r<dt(a,o[1])||h<dt(a,o[1]))&&o.splice(1,d-1);const l=o[o.length-1],p=dt(l,o[o.length-3]),g=dt(l,o[o.length-4]),m=p<g?o.length-3:o.length-4;return(p<dt(l,o[o.length-2])||g<dt(l,o[o.length-2]))&&o.splice(m+1,o.length-m-2),{index:i.index,path:o,startsAt:o[0]===s?"C":"D",goesTo:o[o.length-1]===s?"C":"D"}})(),S=h>0?((s,n)=>{if(s.length<2)return s;const i=[s[0]];for(let o=0;o<s.length-1;o++){const r={start:s[o],end:s[o+1]},h={x:(r.start.x+r.end.x)/2,y:(r.start.y+r.end.y)/2},c=dt(h,t),d=dt(h,e);if((c<=a||d<=a)&&Math.abs(c-d)>1e-4){const s=g(r,t),o=g(r,e),h=dt(s,t),c=dt(o,e)<a,d=h<a?m(r,t,a):null,l=c?m(r,e,a):null;let u=[];if(dt(r.start,r.end)>a/2&&n>0)for(let s=1;s<=n;s++){const i=s/(n+1),o={x:r.start.x+i*(r.end.x-r.start.x),y:r.start.y+i*(r.end.y-r.start.y),t:i,isSpecial:!1},h=dt(o,t),c=dt(o,e);h<a||c<a||(d&&Math.abs(o.t-d.t)<.1||l&&Math.abs(o.t-l.t)<.1||u.push(o))}if(d&&u.push(d),l&&u.push(l),u.sort((t,e)=>t.t-e.t),u.length>1){const t=[u[0]];for(let e=1;e<u.length;e++){const s=t[t.length-1],n=u[e];dt(s,n)>a/10&&t.push(n)}u=t}u.forEach(t=>i.push(t))}i.push(s[o+1])}if(i.length>1){const t=[i[0]];for(let e=1;e<i.length;e++){const s=t[t.length-1],n=i[e];dt(s,n)>a/10&&t.push(n)}return t}return i})(M.path,h):M.path;let b=(()=>{if(0===M.path.length)return null;const s=(()=>{const s=c(y.A_Right,y.B_Right),n=c(y.B_Left,y.A_Left);return[{startsAt:"E",goesTo:"B",points:[i,e]},{startsAt:"E",goesTo:"A",points:[i,t]},{startsAt:"F",goesTo:"B",points:[o,e]},{startsAt:"F",goesTo:"A",points:[o,t]},{startsAt:"E",goesTo:"B",points:[i,s,e]},{startsAt:"E",goesTo:"A",points:[i,s,t]},{startsAt:"F",goesTo:"B",points:[o,s,e]},{startsAt:"F",goesTo:"A",points:[o,s,t]},{startsAt:"E",goesTo:"B",points:[i,n,e]},{startsAt:"E",goesTo:"A",points:[i,n,t]},{startsAt:"F",goesTo:"B",points:[o,n,e]},{startsAt:"F",goesTo:"A",points:[o,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Right,s,e]},{startsAt:"F",goesTo:"B",points:[o,x.B_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Left,n,t]},{startsAt:"F",goesTo:"A",points:[o,x.A_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Right,s,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Opp,x.A_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Opp,x.B_Left,n,t]},{startsAt:"F",goesTo:"B",points:[o,x.A_Opp,x.A_Left,n,e]},{startsAt:"F",goesTo:"A",points:[o,x.B_Opp,x.B_Right,s,t]},{startsAt:"F",goesTo:"A",points:[o,x.B_Opp,x.B_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Opp,x.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Opp,x.B_Right,s,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Left,x.A_Opp,x.A_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Right,x.B_Opp,x.B_Left,n,t]},{startsAt:"F",goesTo:"B",points:[o,x.A_Right,x.A_Opp,x.A_Left,n,e]},{startsAt:"F",goesTo:"A",points:[o,x.B_Left,x.B_Opp,x.B_Right,s,t]},{startsAt:"F",goesTo:"A",points:[o,x.B_Right,x.B_Opp,x.B_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Right,x.A_Opp,x.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Left,x.B_Opp,x.B_Right,s,t]}].map((t,e)=>({...t,index:e}))})(),n=s.filter(t=>"E"===t.startsAt),a=s.filter(t=>"F"===t.startsAt),r=[],h=[];for(const t of n)if(!p(t.points,M.path)){r.push(t);break}for(const t of a)if(!p(t.points,M.path)){h.push(t);break}return 0===r.length||0===h.length?null:{line1:r[0],line2:h[0]}})();if(b){const s="A"===b.line1.goesTo?e:t,n="A"===b.line2.goesTo?e:t,i=v(b.line1,s,a,r),o=v(b.line2,n,a,r);b={line1:{...b.line1,points:i},line2:{...b.line2,points:o}}}return{jPair:b,optimalPath:{startsAt:M.startsAt,goesTo:M.goesTo,points:S}}}var kt=class extends e{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;escapeLayer=1;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return void(this.failed=!0);const[e,s]=this.routes;if(!(e.startPort.z===e.endPort.z))return void(this.failed=!0);if(!(s.startPort.z===s.endPort.z))return void(this.failed=!0);e.startPort.z===s.startPort.z?0===e.startPort.z?this.escapeLayer=1:this.escapeLayer=0:this.failed=!0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,s=new Map;for(const t of e){const{connectionName:e}=t;s.has(e)||s.set(e,[]),s.get(e)?.push(t)}for(const[e,n]of s.entries())2===n.length&&t.push({startPort:{...n[0],z:n[0].z??0},endPort:{...n[1],z:n[1].z??0},connectionName:e});return t}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(t,e){return at(t.startPort,t.endPort,e.startPort,e.endPort)}calculateViaPositions(t,e){const s=this.bounds.maxX-this.bounds.minX,n=this.bounds.maxY-this.bounds.minY,i=this.bounds.minX,o=this.bounds.minY,a={width:s-2*this.obstacleMargin-this.viaDiameter,height:n-2*this.obstacleMargin-this.viaDiameter,x:i+this.obstacleMargin+this.viaDiameter/2,y:o+this.obstacleMargin+this.viaDiameter/2},r=this.viaDiameter+this.obstacleMargin,h=e.startPort,c=e.endPort,d=[{x:a.x,y:a.y},{x:a.x+a.width,y:a.y},{x:a.x+a.width,y:a.y+a.height},{x:a.x,y:a.y+a.height}],l=(t,e)=>dt(t,e),u=[];d.forEach((t,e)=>{l(t,h)>=r&&l(t,c)>=r&&u.push({...t,type:"corner",index:e})});const p=[{p1:d[0],p2:d[1]},{p1:d[1],p2:d[2]},{p1:d[2],p2:d[3]},{p1:d[3],p2:d[0]}];if([h,c].forEach((t,e)=>{p.forEach((s,n)=>{((t,e)=>{const s=t.x,n=t.y,i=t.r,o=e.p1.x,a=e.p1.y,r=e.p2.x,h=e.p2.y;if(Math.abs(r-o)<.001){const t=o,e=i*i-(t-s)**2;if(e<0)return[];if(Math.abs(e)<.001){const e=n;return e>=Math.min(a,h)&&e<=Math.max(a,h)?[{x:t,y:e}]:[]}const r=n+Math.sqrt(e),c=n-Math.sqrt(e),d=[];return r>=Math.min(a,h)&&r<=Math.max(a,h)&&d.push({x:t,y:r}),c>=Math.min(a,h)&&c<=Math.max(a,h)&&d.push({x:t,y:c}),d}const c=(h-a)/(r-o),d=a-c*o,l=1+c*c,u=2*(c*d-c*n-s),p=u*u-4*l*(s*s+(d-n)*(d-n)-i*i);if(p<0)return[];if(Math.abs(p)<.001){const t=-u/(2*l),e=c*t+d;return t>=Math.min(o,r)&&t<=Math.max(o,r)&&e>=Math.min(a,h)&&e<=Math.max(a,h)?[{x:t,y:e}]:[]}const f=(-u+Math.sqrt(p))/(2*l),g=(-u-Math.sqrt(p))/(2*l),m=c*f+d,y=c*g+d,x=[];return f>=Math.min(o,r)&&f<=Math.max(o,r)&&m>=Math.min(a,h)&&m<=Math.max(a,h)&&x.push({x:f,y:m}),g>=Math.min(o,r)&&g<=Math.max(o,r)&&y>=Math.min(a,h)&&y<=Math.max(a,h)&&x.push({x:g,y:y}),x})({...t,r:r},s).forEach(t=>{l(t,0===e?c:h)>=r&&u.push({...t,type:"intersection",circle:e,edge:n})})})}),u.length<2){const t=.8*r;if(d.forEach((e,s)=>{l(e,h)>=t&&l(e,c)>=t&&!u.some(t=>t.x===e.x&&t.y===e.y)&&u.push({...e,type:"relaxed_corner",index:s})}),u.length<2){const t=[...d].sort((t,e)=>{const s=Math.min(l(t,h),l(t,c));return Math.min(l(e,h),l(e,c))-s});for(const e of t)if(!u.some(t=>t.x===e.x&&t.y===e.y)&&(u.push({...e,type:"forced_corner"}),u.length>=2))break}}if(u.length<2)return null;let f=0,g=[u[0],u[u.length>1?1:0]];for(let t=0;t<u.length;t++)for(let e=t+1;e<u.length;e++){const s=l(u[t],u[e]);s>f&&(f=s,g=[u[t],u[e]])}let m={x:g[0].x,y:g[0].y},y={x:g[1].x,y:g[1].y};const x=dt(m,t.startPort);return dt(y,t.startPort)<x&&([m,y]=[y,m]),{via1:m,via2:y}}trySolveAOverB(t,e,s=!1){const n=s?this.calculateViaPositions(t,e):this.calculateViaPositions(e,t);if(!n)return!1;this.debugViaPositions.push(n);const{via1:i,via2:o}=this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(n));this.debugViaPositions.push({via1:i,via2:o});const{jPair:a,optimalPath:r}=Ft({A:i,B:o,C:t.startPort,D:t.endPort,E:e.startPort,F:e.endPort,radius:this.viaDiameter/2+this.obstacleMargin+this.traceThickness/2*1.5,margin:2*this.obstacleMargin+this.traceThickness/2*1.5,subdivisions:1});if(!a)return!1;const h={connectionName:t.connectionName,route:r.points.map(e=>({x:e.x,y:e.y,z:t.startPort.z??0})),traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};a.line2.points.reverse();const c={connectionName:e.connectionName,route:[...a.line1.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0})),{...a.line1.points[a.line1.points.length-1],z:this.escapeLayer},{...a.line2.points[0],z:this.escapeLayer},...a.line2.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0}))],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[i,o]};return this.solvedRoutes.push(h,c),!0}pushViasFromEndpoints(t){const e={...t.via1},s={...t.via2},n=[this.routes[0].startPort,this.routes[0].endPort,this.routes[1].startPort,this.routes[1].endPort],i=this.getMinDistanceBetweenViaCenters(),o=this.viaDiameter/2+2*this.traceThickness+2*this.obstacleMargin;for(let t=0;t<10;t++){let a=!1,r=!1;const h=.9**t;for(const t of n){const n=dt(e,t);if(n<o){const s=(o-n)*h,i=e.x-t.x,r=e.y-t.y,c=Math.sqrt(i*i+r*r);c>1e-6&&(e.x+=i/c*s,e.y+=r/c*s,a=!0)}const i=dt(s,t);if(i<o){const e=(o-i)*h,n=s.x-t.x,a=s.y-t.y,c=Math.sqrt(n*n+a*a);c>1e-6&&(s.x+=n/c*e,s.y+=a/c*e,r=!0)}}const c=dt(e,s);if(c<i){const t=(i-c)/2,n=s.x-e.x,o=s.y-e.y,h=Math.sqrt(n*n+o*o);h>1e-6?(e.x-=n/h*t,e.y-=o/h*t,s.x+=n/h*t,s.y+=o/h*t,a=!0,r=!0):(e.x-=t,s.x+=t,a=!0,r=!0)}if(!a&&!r)break}const a=dt(e,s);if(a<i){const t=(i-a)/2,n=s.x-e.x,o=s.y-e.y,r=Math.sqrt(n*n+o*o);r>1e-6?(e.x-=n/r*t,e.y-=o/r*t,s.x+=n/r*t,s.y+=o/r*t):(e.x-=t,s.x+=t)}return{via1:e,via2:s}}getMinDistanceBetweenViaCenters(){return this.viaDiameter+this.traceThickness+2*this.obstacleMargin}moveViasAsCloseAsPossible(t){const{via1:e,via2:s}=t,n=this.getMinDistanceBetweenViaCenters(),i=dt(e,s);if(i<=n)return t;const o=s.x-e.x,a=s.y-e.y,r=Math.sqrt(o*o+a*a),h=o/r,c=a/r,d=(e.x,s.x,e.y,s.y,(i-n)/2);return{via1:{x:e.x+h*d,y:e.y+c*d},via2:{x:s.x-h*d,y:s.y-c*d}}}handleRoutesDontCross(){const[t,e]=this.routes,s={connectionName:t.connectionName,route:[{x:t.startPort.x,y:t.startPort.y,z:t.startPort.z??0},{x:t.endPort.x,y:t.endPort.y,z:t.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]},n={connectionName:e.connectionName,route:[{x:e.startPort.x,y:e.startPort.y,z:e.startPort.z??0},{x:e.endPort.x,y:e.endPort.y,z:e.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};this.solvedRoutes.push(s,n),this.solved=!0}_step(){if(2!==this.routes.length)return void(this.failed=!0);const[t,e]=this.routes;this.doRoutesCross(t,e)?this.trySolveAOverB(t,e)||this.trySolveAOverB(e,t)||this.trySolveAOverB(t,e,!0)||this.trySolveAOverB(e,t,!0)?this.solved=!0:this.failed=!0:this.handleRoutesDontCross()}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.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[e,s]of[["Route A",this.routes[0]],["Route B",this.routes[1]]])t.points.push({x:s.startPort.x,y:s.startPort.y,label:`${e}\n${s.connectionName} start`,color:"orange"}),t.points.push({x:s.endPort.x,y:s.endPort.y,label:`${e}\n${s.connectionName} end`,color:"orange"}),t.lines.push({points:[s.startPort,s.endPort],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e}\n${s.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via1:s,via2:n}=this.debugViaPositions[e],i=["rgba(255, 165, 0, 0.3)","rgba(128, 0, 128, 0.3)"],o=i[e%i.length];t.circles.push({center:s,radius:this.viaDiameter/2,fill:o,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via A (attempt ${e+1})`}),t.circles.push({center:n,radius:this.viaDiameter/2,fill:o,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via B (attempt ${e+1})`});const a=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:s,radius:a,stroke:o,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 1 Safety Margin (attempt ${e+1})`}),t.circles.push({center:n,radius:a,stroke:o,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 2 Safety Margin (attempt ${e+1})`}),t.lines.push({points:[this.routes[e%2].startPort,s,n,this.routes[e%2].endPort],strokeColor:`${o.substring(0,o.lastIndexOf(","))}, 0.3)`,strokeDash:[5,5],label:`Potential Route (attempt ${e+1})`})}for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e],n=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1];t.lines.push({points:[i,o],strokeColor:n,strokeDash:1===i.z?[.2,.2]:void 0,strokeWidth:s.traceThickness,label:`${s.connectionName} z=${i.z}`}),i._label&&t.points.push({x:i.x,y:i.y,label:i._label})}for(const e of s.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Solved Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}};function Bt(t,e,s,n,i){const o={x:(t.x+e.x+s.x)/3,y:(t.y+e.y+s.y)/3},a=(t,e)=>Math.sqrt((e.x-t.x)**2+(e.y-t.y)**2),r=o=>{const r=a(o,t),h=a(o,e),c=a(o,s),d=o.x>=i.minX&&o.x<=i.maxX&&o.y>=i.minY&&o.y<=i.maxY;return r>=n&&h>=n&&c>=n&&d};if(r(o))return o;const h=(t,e,s)=>{const n=t.x-e.x,i=t.y-e.y,o=Math.sqrt(n*n+i*i);return o<1e-10?{x:e.x+s,y:e.y}:{x:e.x+n/o*s,y:e.y+i/o*s}},c=(t,e,s)=>{const n=e.x-t.x,i=e.y-t.y,o=Math.sqrt(n*n+i*i);if(o>2*s-1e-10||o<1e-10)return[];const r=o*o/(2*o),h=Math.sqrt(Math.max(0,s*s-r*r)),c=t.x+n*r/o,d=t.y+i*r/o,l={x:c+h*i/o,y:d-h*n/o},u={x:c-h*i/o,y:d+h*n/o},p=[],f=1e-6;return Math.abs(a(l,t)-s)<f&&Math.abs(a(l,e)-s)<f&&p.push(l),Math.abs(a(u,t)-s)<f&&Math.abs(a(u,e)-s)<f&&p.push(u),p},d=[h(o,t,n),h(o,e,n),h(o,s,n),...c(t,e,n),...c(e,s,n),...c(s,t,n)],l=d.filter(r);if(l.length>0){const t=l.filter(t=>!(t=>{const e=1e-6;return Math.abs(t.x-i.minX)<e||Math.abs(t.x-i.maxX)<e||Math.abs(t.y-i.minY)<e||Math.abs(t.y-i.maxY)<e})(t));if(t.length>0)return t.sort((t,e)=>a(t,o)-a(e,o)),t[0]}let u=null,p=1/0;for(let t=i.minX+1;t<i.maxX;t+=5)for(let e=i.minY+1;e<i.maxY;e+=5){const s={x:t,y:e};if(r(s)){const t=a(s,o);t<p&&(p=t,u=s)}}if(null!==u)return u;const f=[];for(let t=0;t<=100;t++){const e=t/100;f.push({x:i.minX+e*(i.maxX-i.minX),y:i.minY}),f.push({x:i.maxX,y:i.minY+e*(i.maxY-i.minY)}),f.push({x:i.maxX-e*(i.maxX-i.minX),y:i.maxY}),f.push({x:i.minX,y:i.maxY-e*(i.maxY-i.minY)})}const g=f.filter(r);if(g.length>0)return g.sort((t,e)=>a(t,o)-a(e,o)),g[0];let m=1/0,y={x:i.minX,y:i.minY};for(const o of[...d,...f])if(o.x>=i.minX&&o.x<=i.maxX&&o.y>=i.minY&&o.y<=i.maxY){const i=Math.max(0,n-a(o,t))+Math.max(0,n-a(o,e))+Math.max(0,n-a(o,s));i<m&&(m=i,y=o)}return y}function Xt(t,e,s){const n=Yt(e,t,s.center,s.radius),i=Yt(t,e,s.center,s.radius),o=Ht(n,e),a=Ht(t,i),r=1e-6;let h;if(o>r&&a>r){h={x:(n.x+i.x)/2,y:(n.y+i.y)/2};const o=Ht(n,h),a=Ht(i,h);if(Math.abs(o-a)>.5*Math.min(o,a)){const s=Ht(t,n),o=Ht(e,i),a=s+o;if(a>r){const t=o/a,e=s/a;h={x:n.x*t+i.x*e,y:n.y*t+i.y*e}}}const c=Ht(h,s.center);if(c<1.05*s.radius){const t={x:(h.x-s.center.x)/c,y:(h.y-s.center.y)/c};h={x:s.center.x+t.x*s.radius*1.2,y:s.center.y+t.y*s.radius*1.2}}}else{const n={x:(t.x+e.x)/2,y:(t.y+e.y)/2},i=Ht(n,s.center);if(i<1.1*s.radius){const t={x:(n.x-s.center.x)/i,y:(n.y-s.center.y)/i};h={x:s.center.x+t.x*s.radius*1.2,y:s.center.y+t.y*s.radius*1.2}}else h=n}return{B:n,D:i,E:h}}function Yt(t,e,s,n){const i=[s.x-t.x,s.y-t.y],o=Math.sqrt(i[0]*i[0]+i[1]*i[1]);if(o<=n){if(o<1e-8){const i=[e.x-t.x,e.y-t.y],o=Math.sqrt(i[0]*i[0]+i[1]*i[1]);return o<1e-8?{x:s.x+n,y:s.y}:{x:s.x+i[0]/o*n,y:s.y+i[1]/o*n}}const a=[i[0]/o,i[1]/o];return{x:s.x-a[0]*n,y:s.y-a[1]*n}}const a=[e.x-t.x,e.y-t.y],r=Math.sqrt(o*o-n*n),h=[i[0]/o,i[1]/o],c=[-h[1],h[0]],d=[h[1],-h[0]],l=a[0]*c[0]+a[1]*c[1]>a[0]*d[0]+a[1]*d[1]?c:d,u=n/o,p=r/o,f=[h[0]*p+l[0]*u,h[1]*p+l[1]*u];return{x:t.x+r*f[0],y:t.y+r*f[1]}}function Ht(t,e){const s=e.x-t.x,n=e.y-t.y;return Math.sqrt(s*s+n*n)}var Vt=1e-9;function jt(t,e,s,n="cw"){const i=Zt(t,s),o=Zt(e,s);return Math.abs(o-i)<Vt?{left:0,top:0,right:0,bottom:0}:function(t,e,s,n){const i=s.maxX-s.minX,o=s.maxY-s.minY;if(i<Vt&&o<Vt)return{left:0,top:0,right:0,bottom:0};const a=2*(i+o);if(a<Vt)return{left:0,top:0,right:0,bottom:0};const r=i/a*(2*Math.PI),h=(i+o)/a*(2*Math.PI),c=(i+i+o)/a*(2*Math.PI),d=2*Math.PI,l=[{name:"top",start:0,end:r,length:i},{name:"right",start:r,end:h,length:o},{name:"bottom",start:h,end:c,length:i},{name:"left",start:c,end:d,length:o}],u={left:0,top:0,right:0,bottom:0},p=(t,e,s,n,i)=>{const o=e>2*Math.PI-Vt?2*Math.PI:e;if(o<=t+Vt)return 0;if(i){const e=Math.max(t,s),i=Math.min(o,2*Math.PI),a=Math.max(0,i-e),r=Math.max(t,0),h=Math.min(o,n);return a+Math.max(0,h-r)}{const e=Math.max(t,s),i=Math.min(o,n);return Math.max(0,i-e)}};for(const s of l){const i=s.end-s.start;if(i<Vt||s.length<Vt)continue;let o=0;if("cw"===n){const n=t>e+Vt;o=p(s.start,s.end,t,e,n)}else{const n=e>t+Vt;o=p(s.start,s.end,e,t,n)}if(o>Vt){const t=o/i;u[s.name]+=Math.max(0,Number.isFinite(t)?t:0)}}for(const t in u)u[t]=Math.max(0,Math.min(1,u[t]));return u}(i,o,s,n)}function Zt(t,e){const s=e.maxX-e.minX,n=e.maxY-e.minY;if(s<Vt&&n<Vt)return 0;const i=2*(s+n);if(i<Vt)return 0;let o=0;if(Math.abs(t.y-e.maxY)<Vt&&t.x>=e.minX-Vt&&t.x<=e.maxX+Vt)o=Math.max(0,Math.min(s,t.x-e.minX));else if(Math.abs(t.x-e.maxX)<Vt&&t.y>=e.minY-Vt&&t.y<=e.maxY+Vt)o=s+Math.max(0,Math.min(n,e.maxY-t.y));else if(Math.abs(t.y-e.minY)<Vt&&t.x>=e.minX-Vt&&t.x<=e.maxX+Vt)o=s+n+Math.max(0,Math.min(s,e.maxX-t.x));else{if(!(Math.abs(t.x-e.minX)<Vt&&t.y>=e.minY-Vt&&t.y<=e.maxY+Vt))throw new Error(`Point (${t.x}, ${t.y}) does not lie on the boundary defined by ${JSON.stringify(e)}`);o=s+n+s+Math.max(0,Math.min(n,t.y-e.minY))}return o=Math.max(0,Math.min(i,o)),i>Vt?o/i*(2*Math.PI):0}function Wt(t,e,s,n){return function({angleA:t,angleB:e,angleC:s}){const n=Math.cos(t),i=Math.sin(t),o=Math.cos(e),a=Math.sin(e),r=Math.cos(s);return(o-n)*(Math.sin(s)-i)-(a-i)*(r-n)<0?"ccw":"cw"}({angleA:Zt(t,n),angleB:Zt(e,n),angleC:Zt(s,n)})}var Ut=class extends e{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return void(this.failed=!0);const[e,s]=this.routes,n=e.A.z!==e.B.z,i=s.A.z!==s.B.z;(n&&i||!n&&!i)&&(this.failed=!0)}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,s=new Map;for(const t of e){const{connectionName:e}=t;s.has(e)||s.set(e,[]),s.get(e)?.push(t)}for(const[e,n]of s.entries())2===n.length&&t.push({A:{...n[0],z:n[0].z??0},B:{...n[1],z:n[1].z??0},connectionName:e});return t}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(t,e){return at(t.A,t.B,e.A,e.B)}calculateViaPosition(t,e){const s=e.A.z,n=t.A.z!==s?t.A:t.B,i=2*this.obstacleMargin+this.viaDiameter/2+this.traceThickness,o=this.obstacleMargin+this.viaDiameter/2,a=e.A,r=n,h=e.B,c=Wt(a,r,h,this.bounds),d=function(t,e,s,n,i){const o=jt(t,e,n,i),a=jt(e,s,n,i),r={left:Math.min(1,o.left+a.left),top:Math.min(1,o.top+a.top),right:Math.min(1,o.right+a.right),bottom:Math.min(1,o.bottom+a.bottom)};for(const t in r)Math.abs(r[t])<Vt&&(r[t]=0);return r}(a,r,h,this.bounds,c),l={minX:this.bounds.minX+(d.left>.5?i:o),minY:this.bounds.minY+(d.bottom>.5?i:o),maxX:this.bounds.maxX-(d.right>.5?i:o),maxY:this.bounds.maxY-(d.top>.5?i:o)};return l.maxY<l.minY&&(l.minY=(l.minY+l.maxY)/2,l.maxY=l.minY),l.maxX<l.minX&&(l.minX=(l.minX+l.maxX)/2,l.maxX=l.minX),Bt(a,r,h,i,l)}createTransitionRoute(t,e,s,n){return{connectionName:n,route:[{x:t.x,y:t.y,z:t.z??0},{x:s.x,y:s.y,z:t.z??0},{x:s.x,y:s.y,z:e.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[s]}}createFlatRoute(t,e,s,n,i,o){n.z,t.z;const a=this.viaDiameter/2+this.traceThickness/2+this.obstacleMargin,r=((t,e,s,n)=>{const i=s.x-t.x,o=s.y-t.y;return((t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}))({x:t.x+i*e,y:t.y+o*e},{x:s.x-i*n,y:s.y-o*n})})(s,this.viaDiameter,n.z!==t.z?n:i,this.traceThickness),h={center:{x:s.x,y:s.y},radius:a},c=Xt(t,r,h).E,d=Xt(r,e,h).E,l=Xt(t,c,h).E,u=Xt(c,r,h).E,p=Xt(r,d,h).E,f=Xt(d,e,h).E,g=Xt(u,p,h).E;return{connectionName:o,route:[{x:t.x,y:t.y,z:t.z??0},{x:l.x,y:l.y,z:t.z??0},{x:c.x,y:c.y,z:t.z??0},{x:u.x,y:u.y,z:t.z??0},{x:g.x,y:g.y,z:t.z??0},{x:p.x,y:p.y,z:t.z??0},{x:d.x,y:d.y,z:t.z??0},{x:f.x,y:f.y,z:t.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]}}trySolve(){const[t,e]=this.routes,s=t.A.z!==t.B.z,n=s?t:e,i=s?e:t,o=this.calculateViaPosition(n,i);if(!o)return!1;this.debugViaPositions.push({via:o});const a=this.createTransitionRoute(n.A,n.B,o,n.connectionName),r=this.createFlatRoute(i.A,i.B,o,n.A,n.B,i.connectionName);return this.solvedRoutes.push(a,r),!0}_step(){if(!this.doRoutesCross(this.routes[0],this.routes[1]))return this.failed=!0,void(this.error="Can only solve routes that have a single transition crossing");this.trySolve()?this.solved=!0:this.failed=!0}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.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 e of this.routes)t.points.push({x:e.A.x,y:e.A.y,label:`${e.connectionName} start (z=${e.A.z})`,color:"orange"}),t.points.push({x:e.B.x,y:e.B.y,label:`${e.connectionName} end (z=${e.B.z})`,color:"orange"}),t.lines.push({points:[e.A,e.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via:s}=this.debugViaPositions[e];t.circles.push({center:s,radius:this.viaDiameter/2,fill:"rgba(255, 165, 0, 0.7)",stroke:"rgba(0, 0, 0, 0.5)",label:`Computed Via (attempt ${e+1})`});const n=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:s,radius:n,stroke:"rgba(255, 165, 0, 0.7)",fill:"rgba(0, 0, 0, 0)",label:"Safety Margin"})}for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e],n=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1];t.lines.push({points:[i,o],strokeColor:n,strokeDash:i.z!==s.route[0].z?[.2,.2]:void 0,strokeWidth:s.traceThickness,label:`${s.connectionName} z=${i.z}`})}for(const e of s.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}},Gt=(t,e)=>{const s={};return t.portPoints.forEach((e,n)=>{s[e.connectionName]=`hsl(${360*n/t.portPoints.length}, 100%, 50%)`}),s},qt=class extends e{bounds;maxViaCount;portPairMap;colorMap;nodeWidth;availableZ;hyperParameters;VIA_INTERSECTION_BUFFER_DISTANCE=.05;PLACEHOLDER_WALL_BUFFER_DISTANCE=.1;NEW_HEAD_WALL_BUFFER_DISTANCE=.05;viaDiameter;unprocessedConnections;completedPaths=new Map;placeholderPaths=new Map;currentHead;currentConnectionName;currentPath;currentViaCount;constructor({nodeWithPortPoints:t,colorMap:e,hyperParameters:s,viaDiameter:n}){super(),this.MAX_ITERATIONS=1e5,this.colorMap=e??Gt(t),this.maxViaCount=5,this.bounds=At(t),this.nodeWidth=this.bounds.maxX-this.bounds.minX,this.portPairMap=(t=>{const e=new Map;return t.portPoints.forEach(t=>{e.has(t.connectionName)?e.get(t.connectionName).end=t:e.set(t.connectionName,{start:t,end:null,connectionName:t.connectionName})}),e})(t),this.stats.solutionsFound=0,this.availableZ=t.availableZ??[0,1],this.hyperParameters=s??{SHUFFLE_SEED:0},this.viaDiameter=n??.6,this.unprocessedConnections=Array.from(this.portPairMap.keys()).sort(),s?.SHUFFLE_SEED&&(this.unprocessedConnections=zt(this.unprocessedConnections,s.SHUFFLE_SEED));for(const[t,{start:e,end:s}]of this.portPairMap.entries())if(e.z===s.z){const n=Math.abs(e.x-s.x)<1e-9,i=Math.abs(e.y-s.y)<1e-9;n||i?this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),this._padByPlaceholderWallBuffer(s),s]):this.placeholderPaths.set(t,[e,s])}else{const n=(e.x+s.x)/2,i=(e.y+s.y)/2,o=this._padByPlaceholderWallBuffer({x:n,y:i,z:e.z}),a=this._padByPlaceholderWallBuffer({x:n,y:i,z:s.z});this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),o,a,this._padByPlaceholderWallBuffer(s),s])}this.currentConnectionName=this.unprocessedConnections.pop();const i=this.portPairMap.get(this.currentConnectionName).start;this.currentHead=this._padByNewHeadWallBuffer(i),this.currentPath=[i,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}_padByNewHeadWallBuffer(t){return{x:ot(t.x,this.bounds.minX+this.NEW_HEAD_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.NEW_HEAD_WALL_BUFFER_DISTANCE),y:ot(t.y,this.bounds.minY+this.NEW_HEAD_WALL_BUFFER_DISTANCE,this.bounds.maxY-this.NEW_HEAD_WALL_BUFFER_DISTANCE),z:t.z}}_padByPlaceholderWallBuffer(t){return{x:ot(t.x,this.bounds.minX+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),y:ot(t.y,this.bounds.minY+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxY-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),z:t.z}}_step(){if(this.solved)return;const t=this.portPairMap.get(this.currentConnectionName).end,e=[this.currentHead,t];let s=null,n=null;const i=t=>{for(const i of t.values())for(let t=0;t<i.length-1;t++){const o=[i[t],i[t+1]];if(o[0].x===o[1].x&&o[0].y===o[1].y)continue;if(o[0].z!==this.currentHead.z)continue;const a=lt(e[0],e[1],o[0],o[1]);if(a){const t=dt(this.currentHead,a);if(t<1e-6)continue;(!s||t<s.dist)&&(s={point:a,dist:t},n=o[0].z)}}};i(this.completedPaths),i(this.placeholderPaths);const o=this.currentHead.z!==t.z;if((s||o)&&(this.currentViaCount++,this.currentViaCount>=this.maxViaCount))this.failed=!0;else if(s){let t;const e=s.dist;if(e<=this.VIA_INTERSECTION_BUFFER_DISTANCE+1e-6)t=ut(this.currentHead,s.point);else{const n=s.point,i=n.x-this.currentHead.x,o=n.y-this.currentHead.y,a=(e-this.VIA_INTERSECTION_BUFFER_DISTANCE)/e;t={x:this.currentHead.x+i*a,y:this.currentHead.y+o*a}}const i=this.availableZ.find(t=>t!==n);if(void 0===i)return console.error("Could not determine next Z level for via placement!"),void(this.failed=!0);const o={...t,z:this.currentHead.z},a={...t,z:i};this.currentPath.push(o,a),this.currentHead=a}else if(o){let e;const s=dt(this.currentHead,t);if(s<this.VIA_INTERSECTION_BUFFER_DISTANCE)e=ut(this.currentHead,t);else{const n=t.x-this.currentHead.x,i=t.y-this.currentHead.y,o=(s-this.VIA_INTERSECTION_BUFFER_DISTANCE)/s;e={x:this.currentHead.x+n*o,y:this.currentHead.y+i*o}}const n=t.z,i={...e,z:this.currentHead.z},o={...e,z:n};this.currentPath.push(i,o),this.currentHead=o}else if(this.currentPath.push(t),this.completedPaths.set(this.currentConnectionName,this.currentPath),0===this.unprocessedConnections.length)this.solved=!0,this.stats.solutionsFound=1;else{this.currentConnectionName=this.unprocessedConnections.pop();const{start:t}=this.portPairMap.get(this.currentConnectionName);this.currentHead=this._padByNewHeadWallBuffer(t),this.currentPath=[t,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}}visualize(){const t={points:[],lines:[],circles:[],rects:[],title:"Via Possibilities Solver State",coordinateSystem:"cartesian"},e=this.colorMap;t.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:.01});for(const[e,{start:s,end:n}]of this.portPairMap.entries()){const i=this.colorMap[e]??"black";t.points.push({x:s.x,y:s.y,color:i,label:`Port: ${e} Start (z${s.z})`}),t.points.push({x:n.x,y:n.y,color:i,label:`Port: ${e} End (z${n.z})`})}const s=(s,n)=>{for(const[i,o]of s.entries()){const s=e[i]??"black";for(let e=0;e<o.length-1;e++){const a=o[e],r=o[e+1];a.x===r.x&&a.y===r.y&&a.z!==r.z?t.circles.push({center:{x:a.x,y:a.y},radius:this.viaDiameter/2,fill:V(s,.5),label:`${n}: ${i} Via (z${a.z}->z${r.z})`}):t.lines.push({points:[a,r],strokeColor:V(s,.5),strokeDash:0===a.z?void 0:[.1,.1],strokeWidth:.1,label:`${n}: ${i} (z${a.z})`})}}};if(s(this.placeholderPaths,"Placeholder"),s(this.completedPaths,"Completed"),this.currentPath&&this.currentPath.length>0){const s=e[this.currentConnectionName]??"orange";for(let e=0;e<this.currentPath.length-1;e++){const n=this.currentPath[e],i=this.currentPath[e+1];n.x===i.x&&n.y===i.y&&n.z!==i.z?t.circles.push({center:{x:n.x,y:n.y},radius:this.viaDiameter/2,fill:V(s,.5),label:`Current: ${this.currentConnectionName} Via (z${n.z}->z${i.z})`}):t.lines.push({points:[n,i],strokeColor:V(s,.5),strokeWidth:.15,strokeDash:"2,2",label:`Current: ${this.currentConnectionName} (z${n.z})`})}t.points.push({x:this.currentHead.x,y:this.currentHead.y,color:"green",label:`Current Head: ${this.currentConnectionName} (z${this.currentHead.z})`})}return t}},Kt=1e-9;function Jt(t,e,s=Kt){return Math.abs(t-e)<s}function Qt(t,e,s,n){return t*n-e*s}function te(t,e,s,n){const i={x:e.x-t.x,y:e.y-t.y},o={x:n.x-s.x,y:n.y-s.y},a=Qt(i.x,i.y,o.x,o.y);if(Jt(a,0))return null;const r={x:s.x-t.x,y:s.y-t.y},h=Qt(r.x,r.y,o.x,o.y)/a,c=Qt(r.x,r.y,i.x,i.y)/a;return h<-Kt||h>1+Kt||c<-Kt||c>1+Kt?null:{x:t.x+h*i.x,y:t.y+h*i.y}}function ee(t){let e=0;for(let s=0,n=t.length;s<n;++s){const i=(s+1)%n;e+=t[s].x*t[i].y-t[i].x*t[s].y}return.5*e}function se(t){let e=0,s=0,n=0;for(let i=0,o=t.length;i<o;++i){const a=(i+1)%o,r=t[i].x*t[a].y-t[a].x*t[i].y;e+=r,s+=(t[i].x+t[a].x)*r,n+=(t[i].y+t[a].y)*r}return e*=.5,Jt(e,0)?null:(s/=6*e,n/=6*e,{x:s,y:n})}var ne=class{x;y;out;connectionNames;constructor(t,e){this.x=t,this.y=e,this.out=[],this.connectionNames=new Set}},ie=class{orig;dest;twin;next;visited;constructor(t,e){this.orig=t,this.dest=e,this.twin=null,this.next=null,this.visited=!1}};function oe(t,e){const s=[...e,...[{start:{x:t.minX,y:t.minY},end:{x:t.maxX,y:t.minY}},{start:{x:t.maxX,y:t.minY},end:{x:t.maxX,y:t.maxY}},{start:{x:t.maxX,y:t.maxY},end:{x:t.minX,y:t.maxY}},{start:{x:t.minX,y:t.maxY},end:{x:t.minX,y:t.minY}}]],n=s.map(()=>[]);for(let t=0;t<s.length;++t){const e=s[t];n[t].push(e.start,e.end)}for(let t=0;t<s.length;++t)for(let e=t+1;e<s.length;++e){const i=te(s[t].start,s[t].end,s[e].start,s[e].end);i&&(n[t].push(i),n[e].push(i))}const i=new Map,o=[];function a(t){const e=function(t,e=Kt){return`${Math.round(t.x/e)}:${Math.round(t.y/e)}`}(t);if(!i.has(e)){const s=o.length;return i.set(e,s),o.push(new ne(t.x,t.y)),s}return i.get(e)}const r=[];for(let t=0;t<s.length;++t){const e=s[t],i=n[t].slice();i.sort((t,s)=>{const n=e.end.x-e.start.x,i=e.end.y-e.start.y;return(Jt(Math.abs(n),0)?(t.y-e.start.y)/i:(t.x-e.start.x)/n)-(Jt(Math.abs(n),0)?(s.y-e.start.y)/i:(s.x-e.start.x)/n)});for(let t=0;t<i.length-1;++t){const s=i[t],n=i[t+1],h=a(s),c=a(n);h!==c&&(r.push([h,c]),e.connectionName&&(o[h].connectionNames.add(e.connectionName),o[c].connectionNames.add(e.connectionName)))}}const h=[];for(const[t,e]of r){const s=new ie(t,e),n=new ie(e,t);s.twin=h.length+1,n.twin=h.length;const i=h.length;h.push(s,n),o[t].out.push(i),o[e].out.push(i+1)}for(let t=0;t<o.length;++t){const e=o[t];e.out.sort((t,s)=>{const n=h[t],i=h[s],a=o[n.dest],r=o[i.dest];return Math.atan2(a.y-e.y,a.x-e.x)-Math.atan2(r.y-e.y,r.x-e.x)});const s=e.out.length;for(let t=0;t<s;++t){const n=e.out[t],i=e.out[(t-1+s)%s],o=h[n];null!==o.twin&&(h[o.twin].next=i)}}const c=[],d=[];for(let t=0;t<h.length;++t){if(h[t].visited)continue;let e=t;const s=[],n=[];do{if(null===e)break;const t=h[e];t.visited=!0,s.push(o[t.orig]),n.push(e),e=t.next}while(null!==e&&e!==t&&!h[e].visited);if(s.length<3)continue;if(ee(s)>Kt){const t=se(s);t&&(c.push(t),d.push({vertices:s.map(t=>({x:t.x,y:t.y,connectionNames:t.connectionNames.size>0?t.connectionNames:void 0})),centroid:t}))}}return{centroids:c,faces:d,allVertices:o}}function ae(t,e){if(t>e)throw new Error("oneCount cannot be greater than length");if(t<0||e<0)throw new Error("oneCount and length must be non-negative");const s=[];return function t(n,i,o){o!==e?(n[o]=0,t(n,i,o+1),i>0&&(n[o]=1,t(n,i-1,o+1))):0===i&&s.push([...n])}(Array(e).fill(0),t,0),s}var re=t=>{if(0===t.length)return[[]];const e=[];for(let s=0;s<t.length;s++){const n=t[s],i=[...t.slice(0,s),...t.slice(s+1)],o=re(i);for(const t of o)e.push([n,...t])}return e};var he=t=>{const{start:e,end:s,segmentsPerPolyline:n,viaPositions:i,viaCount:o,availableZ:a}=t,r=function(t,e){const s=new Array(t).fill(0);if(0===e)return s;if(e===t)return s.fill(1);if(e<=t/2){const n=Math.floor(t/e),i=Math.floor((t-(n*(e-1)+1))/2);for(let t=0;t<e;t++)s[i+t*n]=1}else{const n=t-e,i=Math.floor(t/n),o=Math.floor((t-(i*(n-1)+1))/2);s.fill(1);for(let t=0;t<n;t++)s[o+t*i]=0}return s}(n,o),h=r.map(()=>null);let c=0,d=e.z1;const l=a.indexOf(e.z1);for(let t=0;t<r.length;t++)if(1===r[t]){const e=a[(l+c+1)%a.length];h[t]={...i[c],z1:d,z2:e},d=e,c++}let u=e;for(let t=0;t<h.length;t++){if(h[t]){u=h[t];continue}let e=s,n=h.length;for(let s=t+1;s<h.length;s++)if(h[s]){e=h[s],n=s;break}const i=n-t,o=e.x-u.x,a=e.y-u.y;for(let e=1/(i+1),s=0;t+s!==n;e+=1/(i+1),s++)h[t+s]={x:u.x+o*e,y:u.y+a*e,z1:u.z2,z2:u.z2}}return h},ce=1e-9;function de(t,e){return Math.abs(t-e)<ce}function le(t){return`${Math.round(t.x/ce)}:${Math.round(t.y/ce)}`}function ue(t,e,s,n){return t*n-e*s}function pe(t,e,s,n){const i={x:e.x-t.x,y:e.y-t.y},o={x:n.x-s.x,y:n.y-s.y},a=ue(i.x,i.y,o.x,o.y),r={x:s.x-t.x,y:s.y-t.y};if(de(a,0))return null;const h=ue(r.x,r.y,o.x,o.y)/a,c=ue(r.x,r.y,i.x,i.y)/a;return h>=-1e-9&&h<=1+ce&&c>=-1e-9&&c<=1+ce?{x:t.x+h*i.x,y:t.y+h*i.y}:null}function fe(t,e,s){return de(Math.hypot(t.x-e.x,t.y-e.y)+Math.hypot(t.x-s.x,t.y-s.y),Math.hypot(e.x-s.x,e.y-s.y))}function ge(t,e){const s=[],n=new Map;for(const e of t){const t=[e.start,...e.mPoints,e.end];for(let i=0;i<t.length-1;i++){const o=t[i],a=t[i+1],r=o.z2;if(s.push({start:{x:o.x,y:o.y},end:{x:a.x,y:a.y},connectionName:e.connectionName,layer:r}),o.z1!==o.z2){const t=le(o);n.has(t)||n.set(t,{point:o,connectionName:e.connectionName})}}const i=t[t.length-1];if(i.z1!==i.z2){const t=le(i);n.has(t)||n.set(t,{point:i,connectionName:e.connectionName})}}const i=[{start:{x:e.minX,y:e.minY},end:{x:e.maxX,y:e.minY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.minY},end:{x:e.maxX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.maxY},end:{x:e.minX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.minX,y:e.maxY},end:{x:e.minX,y:e.minY},connectionName:null,layer:0}];s.push(...i);const o=new Map;let a=0;function r(t,e){const s=le(t);let i=o.get(s);if(!i){const e=n.has(s);i={id:a++,x:t.x,y:t.y,isVia:e,connectionNames:new Set,outgoingEdges:[]},o.set(s,i),e&&n.get(s)&&i.connectionNames.add(n.get(s).connectionName)}return e&&i.connectionNames.add(e),i}for(const t of s)r(t.start,t.connectionName),r(t.end,t.connectionName);const h=new Map;for(const t of s)h.set(t,[]);for(let t=0;t<s.length;t++)for(let e=t+1;e<s.length;e++){if(s[t].layer!==s[e].layer)continue;const n=pe(s[t].start,s[t].end,s[e].start,s[e].end);n&&(r(n),fe(n,s[t].start,s[t].end)&&h.get(s[t]).push(n),fe(n,s[e].start,s[e].end)&&h.get(s[e]).push(n))}const c=[];let d=0;for(const t of s){const e=[t.start,...h.get(t),t.end];e.sort((e,s)=>{const n=t.end.x-t.start.x,i=t.end.y-t.start.y;return Math.abs(n)>Math.abs(i)?(e.x-t.start.x)/n-(s.x-t.start.x)/n:Math.abs(i)<ce?0:(e.y-t.start.y)/i-(s.y-t.start.y)/i});const s=[];if(e.length>0){s.push(e[0]);for(let t=1;t<e.length;t++)de(e[t].x,e[t-1].x)&&de(e[t].y,e[t-1].y)||s.push(e[t])}for(let e=0;e<s.length-1;e++){const n=s[e],i=s[e+1],o=r(n,t.connectionName),a=r(i,t.connectionName);if(o===a)continue;const h={id:d++,origin:o,twin:null,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1},l={id:d++,origin:a,twin:h,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1};h.twin=l,c.push(h,l),o.outgoingEdges.push(h),a.outgoingEdges.push(l)}}for(const t of o.values()){t.outgoingEdges.sort((e,s)=>{const n=e.twin.origin,i=s.twin.origin;return Math.atan2(n.y-t.y,n.x-t.x)-Math.atan2(i.y-t.y,i.x-t.x)});const e=t.outgoingEdges.length;for(let s=0;s<e;s++){const n=t.outgoingEdges[s],i=t.outgoingEdges[(s-1+e)%e];n.twin&&(n.twin.next=i)}}const l=[];let u=0,p=null,f=-1/0;for(const t of c){if(t.visited)continue;const e={id:u++,outerComponent:t,innerComponents:[],isOuterFace:!1};l.push(e);let s=t;const n=[],i=[],o=new Set;let a=0;do{if(!s||s.visited){console.warn("Face traversal encountered visited edge or null, breaking loop.",e.id),n.length=0;break}s.visited=!0,s.face=e,n.push(s),i.push(s.origin),null!==s.connectionName&&o.add(s.connectionName);const t=s.origin,r=s.twin.origin;a+=t.x*r.y-r.x*t.y,s=s.next}while(s!==t&&null!==s);if(s===t){if(a=.5*Math.abs(a),a>f&&(f=a,p&&(p.isOuterFace=!1),p=e,e.isOuterFace=!0),!e.isOuterFace&&n.length>0){if([...o].filter(t=>null!==t).length>1){let t=!1;for(const e of i)if(e.isVia){t=!0;break}if(!t)return!0}}}else console.warn(`Face ${e.id} did not close properly.`),l.pop(),u--}return!1}var me=class extends e{nodeWithPortPoints;colorMap;hyperParameters;connMap;candidates;bounds;solvedRoutes=[];unsolvedConnections=[];SEGMENTS_PER_POLYLINE;cellSize;MAX_CANDIDATES=5e4;viaDiameter=.6;obstacleMargin=.1;traceWidth=.15;availableZ=[];uniqueConnections=0;BOUNDARY_PADDING;lastCandidate=null;maxViaCount;minViaCount;phase="setup";progress=0;constructor(t){super(),this.MAX_ITERATIONS=1e4,this.nodeWithPortPoints=t.nodeWithPortPoints,this.colorMap=t.colorMap??Gt(t.nodeWithPortPoints),this.hyperParameters=t.hyperParameters??{},this.SEGMENTS_PER_POLYLINE=t.hyperParameters?.SEGMENTS_PER_POLYLINE??3,this.BOUNDARY_PADDING=t.hyperParameters?.BOUNDARY_PADDING??.05,this.connMap=t.connMap,this.viaDiameter=t.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 e=this.nodeWithPortPoints.width*this.nodeWithPortPoints.height,s=(this.viaDiameter+2*this.obstacleMargin+this.traceWidth/2)**2,n=new Set(this.nodeWithPortPoints.portPoints.map(t=>t.connectionName)).size;this.uniqueConnections=n;const{numSameLayerCrossings:i,numTransitions:o}=(t=>{let e=0,s=[];const n=[];let i=0;for(const e of t.portPoints){if(s.some(t=>t.connectionName===e.connectionName))continue;if(n.some(t=>t.connectionName===e.connectionName))continue;const o={connectionName:e.connectionName,z:e.z,points:[{x:e.x,y:e.y,z:e.z}]};for(const s of t.portPoints)e.connectionName===s.connectionName&&(e.x===s.x&&e.y===s.y||o.points.push({x:s.x,y:s.y,z:s.z}));o.points.some(t=>t.z!==o.z)?(i++,n.push(o)):s.push(o)}s=s.filter(t=>t.points.length>1);for(let t=0;t<s.length;t++)for(let n=t+1;n<s.length;n++){const i=s[t],o=s[n];i.z===o.z&&at(i.points[0],i.points[1],o.points[0],o.points[1])&&e++}let o=0;for(let t=0;t<n.length;t++)for(let e=t+1;e<n.length;e++){const s=n[t],i=n[e];at(s.points[0],s.points[1],i.points[0],i.points[1])&&o++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:i,numTransitionPairCrossings:o,numTransitions:n.length}})(this.nodeWithPortPoints);if(this.minViaCount=2*i+o,this.maxViaCount=Math.min(Math.floor(e/s),Math.ceil(1.5*n)),this.minViaCount>this.SEGMENTS_PER_POLYLINE*(n/2))return this.failed=!0,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(t){const e=[],s=[],n=[];for(let e=0;e<t.length;e++){const i=t[e],o=[i.start,...i.mPoints,i.end],a=new Map(this.availableZ.map(t=>[t,[]]));for(let t=0;t<o.length-1;t++){const e=[o[t],o[t+1]],s=e[0].z2;a.has(s)||a.set(s,[]),a.get(s).push(e)}s.push(a),n.push(o.filter(t=>t.z1!==t.z2))}for(let i=0;i<t.length;i++){const o=s[i],a=n[i];for(let r=i+1;r<t.length;r++){if(this.connMap?.areIdsConnected(t[i].connectionName,t[r].connectionName))continue;const h=s[r],c=n[r];let d=1;for(const t of this.availableZ){const e=o.get(t)??[],s=h.get(t)??[];for(const t of e)for(const e of s)d=Math.min(d,St(t[0],t[1],e[0],e[1])-this.traceWidth);for(const t of a)for(const e of s)d=Math.min(d,ct(t,e[0],e[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of c)for(const s of e)d=Math.min(d,ct(t,s[0],s[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of a)for(const e of c)d=Math.min(d,dt(t,e)-this.viaDiameter)}e.push(d)}}return e}insertCandidate(t){let e=0,s=this.candidates.length-1;for(;e<=s;){const n=Math.floor((e+s)/2);this.candidates[n].f<t.f?e=n+1:s=n-1}this.candidates.splice(e,0,t)}setupInitialPolyLines(){const t=new Map;this.nodeWithPortPoints.portPoints.forEach(e=>{t.has(e.connectionName)?t.get(e.connectionName).end={...e,z1:e.z??0,z2:e.z??0}:t.set(e.connectionName,{start:{...e,z1:e.z??0,z2:e.z??0},end:null})});for(const[e,s]of t.entries())null===s.end&&t.delete(e);if(0===t.size)return this.failed=!0,void(this.error="No port pairs found, can't solve");const e=Array.from(t.entries()),s=((t,e,s,n)=>{const i=[];for(const[,s]of t){const t=s.start.z1!==s.end.z1,n=[];for(let s=0;s<=e;s++){const e=s%2!=0;t&&e?n.push(s):t||e||n.push(s)}i.push(n)}if(0===i.length)return[[]];let o=(t=>{if(!t||0===t.length)return[[]];let e=[[]];for(const s of t){const t=[];for(const n of e)for(const e of s)t.push([...n,e]);e=t}return e})(i).filter(t=>{for(let e=0;e<t.length;e++)if(t.reduce((t,e)=>t+e,0)<n)return!1;return!0});return o=o.filter(e=>{for(let s=0;s<t.length;s++){const[,n]=t[s];if(n.start.z1!==n.start.z2&&0===e[s])return!1}return!0}),o=o.filter(e=>{for(let s=0;s<t.length;s++){const[,n]=t[s];if(t[s][1].start.z1===t[s][1].start.z2)for(let i=s+1;i<t.length;i++){if(t[i][1].start.z1!==t[i][1].start.z2)continue;const[,o]=t[i];if(n.start.z1===n.end.z1&&o.start.z1===o.end.z1&&n.start.z1===o.start.z1&&at(n.start,n.end,o.start,o.end)&&e[s]+e[i]<2)return!1}}return!0}),o=o.filter(t=>!(t.reduce((t,e)=>t+e,0)>s)),o})(e,this.SEGMENTS_PER_POLYLINE,this.maxViaCount,this.minViaCount),n=(t=>{const{bounds:e,portPairsEntries:s,viaCountVariants:n}=t,{centroids:i}=oe(e,s.map(([t,e])=>e)),o=[];for(const t of n){const s=t.reduce((t,e)=>t+e,0);let n=i;if(i.length<s){n=[];const t=Math.ceil(Math.sqrt(s)),i=t;for(let s=0;s<t;s++)for(let o=0;o<i;o++)n.push({x:e.minX+(o+1)/(i+1)*(e.maxX-e.minX),y:e.minY+(s+1)/(t+1)*(e.maxY-e.minY)})}const a=ae(s,n.length);for(const e of a){const s=[];for(let t=0;t<e.length;t++)1===e[t]&&s.push(n[t]);o.push({viaPositions:s,viaCountVariant:t})}}return o})({portPairsEntries:e,viaCountVariants:s,bounds:this.bounds}),i=[];for(const{viaCountVariant:t,viaPositions:e}of n){const s=re(e);for(const e of s)i.push({viaCountVariant:t,viaPositions:e})}for(const{viaPositions:t,viaCountVariant:s}of i){const n=[];let i=0;for(let o=0;o<e.length;o++){const[a,r]=e[o],h=s[o],c=t.slice(i,i+h),d=he({start:r.start,end:r.end,segmentsPerPolyline:this.SEGMENTS_PER_POLYLINE,viaPositions:c,viaCount:h,availableZ:this.availableZ});i+=h,n.push({connectionName:a,start:r.start,end:r.end,mPoints:d})}if(ge(n,this.bounds))continue;const o=this.computeMinGapBtwPolyLines(n),a=this.computeH({minGaps:o,forces:[]}),r={polyLines:n,g:0,h:a,f:a,viaCount:s.reduce((t,e)=>t+e,0),minGaps:o};if(this.checkIfSolved(r))return void(this.candidates=[r]);if(this.candidates.push(r),this.candidates.length>this.MAX_CANDIDATES)return}this.candidates.sort((t,e)=>t.f-e.f)}computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){let e=0;for(const s of t.forces??[])for(const t of s)for(const s of t.values())e+=s.fx*s.fx+s.fy*s.fy;return e}getNeighbors(t){const{polyLines:e}=t,s=e.length,n=.02,i=.008,o=1e-6,a=Array.from({length:s},(t,s)=>Array.from({length:e[s].mPoints.length},()=>new Map)),r=(t,s,n,i,o)=>{if(s>0&&s<e[t].mPoints.length+1){const e=s-1,r=a[t][e],h=r.get(n)||{fx:0,fy:0};r.set(n,{fx:h.fx+i,fy:h.fy+o})}};for(let t=0;t<s;t++)for(let i=t+1;i<s;i++){const s=e[t],a=e[i],h=[s.start,...s.mPoints,s.end],c=[a.start,...a.mPoints,a.end],d=[],l=[];for(let t=0;t<h.length-1;t++)d.push({p1:h[t],p2:h[t+1],layer:h[t].z2,p1Idx:t,p2Idx:t+1});h.forEach((t,e)=>{t.z1!==t.z2&&l.push({point:t,layers:[t.z1,t.z2],index:e})});const u=[],p=[];for(let t=0;t<c.length-1;t++)u.push({p1:c[t],p2:c[t+1],layer:c[t].z2,p1Idx:t,p2Idx:t+1});c.forEach((t,e)=>{t.z1!==t.z2&&p.push({point:t,layers:[t.z1,t.z2],index:e})});for(const e of d)for(const s of u)if(e.layer===s.layer){if(St(e.p1,e.p2,s.p1,s.p2)<o)continue;const n={x:(e.p1.x+e.p2.x)/2,y:(e.p1.y+e.p2.y)/2},a={x:(s.p1.x+s.p2.x)/2,y:(s.p1.y+s.p2.y)/2},h=n.x-a.x,c=n.y-a.y,d=h*h+c*c;if(d>o){const n=Math.sqrt(d),a=(Math.exp(-6*n),`seg:${i}:${s.p1Idx}:${s.p2Idx}`),h=`seg:${t}:${e.p1Idx}:${e.p2Idx}`,c=(t,e,s,n,i,a,h)=>{const c=Nt(t,s.p1,s.p2),d=t.x-c.x,l=t.y-c.y,u=d*d+l*l;if(u<=o)return;const p=Math.sqrt(u),f=.02*Math.exp(-6*p),g=d/p*f,m=l/p*f;r(n,e,a,g,m),r(i,s.p1Idx,h,-g/2,-m/2),r(i,s.p2Idx,h,-g/2,-m/2)};c(e.p1,e.p1Idx,s,t,i,a,h),c(e.p2,e.p2Idx,s,t,i,a,h),c(s.p1,s.p1Idx,e,i,t,h,a),c(s.p2,s.p2Idx,e,i,t,h,a)}}for(const e of l)for(const s of u)if(e.layers.includes(s.layer)){const a=Nt(e.point,s.p1,s.p2),h=e.point.x-a.x,c=e.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,g=c/a*p,m=`seg:${i}:${s.p1Idx}:${s.p2Idx}`;r(t,e.index,m,f,g);const y=`via:${t}:${e.index}`;r(i,s.p1Idx,y,-f/2,-g/2),r(i,s.p2Idx,y,-f/2,-g/2)}}for(const e of p)for(const s of d)if(e.layers.includes(s.layer)){const a=Nt(e.point,s.p1,s.p2),h=e.point.x-a.x,c=e.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,g=c/a*p,m=`seg:${t}:${s.p1Idx}:${s.p2Idx}`;r(i,e.index,m,f,g);const y=`via:${i}:${e.index}`;r(t,s.p1Idx,y,-f/2,-g/2),r(t,s.p2Idx,y,-f/2,-g/2)}}for(const e of l)for(const s of p){if(e.layers.filter(t=>s.layers.includes(t)).length>0){const a=e.point.x-s.point.x,h=e.point.y-s.point.y,c=a*a+h*h;if(c>o){const d=Math.sqrt(c);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(o,d)):u=Math.max(o,d-this.viaDiameter);const p=l*n*Math.exp(-6*u),f=a/d*p,g=h/d*p,m=`via:${i}:${s.index}`,y=`via:${t}:${e.index}`;r(t,e.index,m,f,g),r(i,s.index,y,-f,-g)}}}}for(let t=0;t<s;t++){const s=e[t],i=[s.start,...s.mPoints,s.end],a=[];if(i.forEach((t,e)=>{t.z1!==t.z2&&a.push({point:t,layers:[t.z1,t.z2],index:e})}),!(a.length<2))for(let e=0;e<a.length;e++)for(let s=e+1;s<a.length;s++){const i=a[e],h=a[s],c=i.point.x-h.point.x,d=i.point.y-h.point.y,l=c*c+d*d;if(l>o){const e=Math.sqrt(l);let s=2,a=e;e<this.viaDiameter?(s*=4,a=Math.max(o,e)):a=Math.max(o,e-this.viaDiameter);const u=s*n*Math.exp(-6*a),p=c/e*u,f=d/e*u,g=`via:${t}:${h.index}`,m=`via:${t}:${i.index}`;r(t,i.index,g,p,f),r(t,h.index,m,-p,-f)}}}const h=e.map(t=>({...t,mPoints:t.mPoints.map(t=>({...t}))}));let c=!1;for(let t=0;t<s;t++)for(let e=0;e<h[t].mPoints.length;e++){const s=h[t].mPoints[e],n=a[t][e],r={fx:0,fy:0};for(const t of n.values())r.fx+=t.fx,r.fy+=t.fy;const d=s.z1!==s.z2;let l=s.x+r.fx,u=s.y+r.fy;if(d){const t=this.viaDiameter/2;let e=0,n=0;const o=this.viaDiameter/2+this.BOUNDARY_PADDING,a=this.bounds.minX+o,h=this.bounds.maxX-o,c=this.bounds.minY+o,d=this.bounds.maxY-o,p=a+t-s.x,f=s.x-(h-t),g=c+t-s.y,m=s.y-(d-t);p>0?e=i*(Math.exp(p/(2*this.obstacleMargin))-1):f>0&&(e=-.008*(Math.exp(f/(2*this.obstacleMargin))-1)),g>0?n=i*(Math.exp(g/(2*this.obstacleMargin))-1):m>0&&(n=-.008*(Math.exp(m/(2*this.obstacleMargin))-1)),r.fx+=e,r.fy+=n,l=s.x+r.fx,u=s.y+r.fy}else{const t=this.traceWidth/2+this.BOUNDARY_PADDING;l=Math.max(this.bounds.minX+t,Math.min(this.bounds.maxX-t,l)),u=Math.max(this.bounds.minY+t,Math.min(this.bounds.maxY-t,u))}Math.abs(r.fx)<o&&Math.abs(r.fy)<o||(Math.abs(s.x-l)>o||Math.abs(s.y-u)>o)&&(s.x=l,s.y=u,c=!0)}if(!c)return[];const d=this.computeMinGapBtwPolyLines(h),l=this.computeG(h,t),u=this.computeH({minGaps:d,forces:a});return[{polyLines:h,g:l,h:u,f:Math.round(5*l)/5+u,minGaps:d,forces:a,viaCount:t.viaCount}]}checkIfSolved(t){const e=t.minGaps.every(t=>t>=this.obstacleMargin),s=t.polyLines.every(t=>t.mPoints.every(t=>{const e=(t.z1!==t.z2?this.viaDiameter/2:this.traceWidth/2)+this.BOUNDARY_PADDING;return((t,e,s=0)=>t.x>=e.minX+s&&t.x<=e.maxX-s&&t.y>=e.minY+s&&t.y<=e.maxY-s)(t,this.bounds,e)}));return e&&s}tryFinalAcceptance(){const t=this.hyperParameters?.MINIMUM_FINAL_ACCEPTANCE_GAP??void 0;if(void 0===t||null===this.lastCandidate||0===this.lastCandidate.minGaps.length)return;return Math.min(...this.lastCandidate.minGaps)>=t?(this.solved=!0,void this._setSolvedRoutes()):void 0}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return this.failed=!0,void(this.error="No candidates left")}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();if(!t)return void(this.failed=!0);const e=this.getNeighbors(t);for(const t of e)this.insertCandidate(t)}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"MultiHeadPolyLineIntraNodeSolver Visualization"};t.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 e=this.lastCandidate??this.candidates[0];if(e?.hasClosedSameLayerFace){const e=.1*(this.bounds.maxX-this.bounds.minX),s=.1*(this.bounds.maxY-this.bounds.minY);t.rects.push({center:{x:this.bounds.maxX+.6*e,y:this.bounds.maxY+.6*s},width:e,height:s,fill:"red",label:"HAS CLOSED FACE"})}for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:`${e.connectionName} (Port z=${e.z??0})`,color:this.colorMap[e.connectionName]??"blue"});return e&&e.polyLines.forEach((s,n)=>{const i=this.colorMap[s.connectionName]??"purple",o=[s.start,...s.mPoints,s.end];for(let e=0;e<o.length-1;e++){const n=o[e],a=o[e+1],r=n.z2,h=0===r,c=h?i:V(i,.5);t.lines.push({points:[n,a],strokeColor:c,strokeWidth:this.traceWidth,strokeDash:h?void 0:[.15,.15],label:`${s.connectionName} segment (z=${r})`})}o.forEach((a,r)=>{const h=a.z1!==a.z2,c=a.z1,d=r>0&&r<o.length-1;let l="",u="";if(d){const i=r-1,o=e.forces?.[n]?.[i];if(o&&o.size>0){const n={fx:0,fy:0};o.forEach((o,r)=>{if(n.fx+=o.fx,n.fy+=o.fy,Math.abs(o.fx)>1e-6||Math.abs(o.fy)>1e-6){const n=r.split(":"),h=n[0],c=parseInt(n[1],10),d=e.polyLines[c],l=this.colorMap[d.connectionName]??"gray",u=20,p={x:a.x+o.fx*u,y:a.y+o.fy*u};let f=d.connectionName;if("via"===h){f+=` Via ${parseInt(n[2],10)}`}else if("seg"===h){f+=` Seg ${parseInt(n[2],10)}-${parseInt(n[3],10)}`}t.lines.push({points:[a,p],strokeColor:l,strokeWidth:.02,strokeDash:"2,2",label:`Force by ${f} on ${s.connectionName} mPoint ${i}`})}}),(Math.abs(n.fx)>1e-6||Math.abs(n.fy)>1e-6)&&(u=`\nNet Force: (${n.fx.toFixed(3)}, ${n.fy.toFixed(3)})`)}}if(h)l=`Via (${s.connectionName} z=${a.z1} -> z=${a.z2})${u}`,t.circles.push({center:a,radius:this.viaDiameter/2,fill:V(i,.5),label:l});else if(d){const e=0===c?i:V(i,.5);l=`mPoint (${s.connectionName} z=${c})${u}`,t.circles.push({center:a,radius:this.cellSize/8,fill:e,label:l})}})}),t}_setSolvedRoutes(){if(!this.solved||!this.lastCandidate)return[];const t=[];for(const e of this.lastCandidate.polyLines){const s=[],n=[],i=[e.start,...e.mPoints,e.end];for(let t=0;t<i.length;t++){const e=i[t];s.push({x:e.x,y:e.y,z:e.z1}),e.z1!==e.z2&&(n.push({x:e.x,y:e.y}),s.push({x:e.x,y:e.y,z:e.z2}))}t.push({connectionName:e.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:s,vias:n})}this.solvedRoutes=t}},ye=class extends me{computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){const{minGaps:e}=t;let s=0;for(const t of e)t<0&&(s+=this.obstacleMargin),t<this.obstacleMargin&&(s+=this.obstacleMargin-t);return.011*s}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return void(this.failed=!0)}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();let e=!1,s=0;const n=void 0===t.magForceApplied?1:10;for(let i=0;i<n;i++){const n=this.applyForcesToPolyLines(t.polyLines);if(s+=n.magForceApplied,e=n.lastStepMoved,!n.lastStepMoved)break}if(t.magForceApplied=s,t.minGaps=this.computeMinGapBtwPolyLines(t.polyLines),this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();t.g=this.computeG(t.polyLines,t),t.h=this.computeH(t),t.f=t.g+t.h,e&&this.insertCandidate(t)}applyForcesToPolyLines(t){let e=0;const s=t.length,n=.02,i=.008,o=1e-6,a=Array.from({length:s},(e,s)=>Array.from({length:t[s].mPoints.length},()=>({fx:0,fy:0}))),r=(e,s,n,i)=>{if(s>0&&s<t[e].mPoints.length+1){const t=s-1;a[e][t].fx+=n,a[e][t].fy+=i}},h=(t,e,s,n,i)=>{const a=Nt(t,s.p1,s.p2),h=t.x-a.x,c=t.y-a.y,d=h*h+c*c;if(d<=o)return;const l=Math.sqrt(d),u=.02*Math.exp(-6*l),p=h/l*u,f=c/l*u;r(n,e,p,f),r(i,s.p1Idx,-p/2,-f/2),r(i,s.p2Idx,-p/2,-f/2)};for(let e=0;e<s;e++)for(let i=e+1;i<s;i++){const s=t[e],a=t[i],c=[s.start,...s.mPoints,s.end],d=[a.start,...a.mPoints,a.end],l=[],u=[];for(let t=0;t<c.length-1;t++)l.push({p1:c[t],p2:c[t+1],layer:c[t].z2,p1Idx:t,p2Idx:t+1});c.forEach((t,e)=>{t.z1!==t.z2&&u.push({point:t,layers:[t.z1,t.z2],index:e})});const p=[],f=[];for(let t=0;t<d.length-1;t++)p.push({p1:d[t],p2:d[t+1],layer:d[t].z2,p1Idx:t,p2Idx:t+1});d.forEach((t,e)=>{t.z1!==t.z2&&f.push({point:t,layers:[t.z1,t.z2],index:e})});for(const t of l)for(const s of p)if(t.layer===s.layer){St(t.p1,t.p2,s.p1,s.p2);h(t.p1,t.p1Idx,s,e,i),h(t.p2,t.p2Idx,s,e,i),h(s.p1,s.p1Idx,t,i,e),h(s.p2,s.p2Idx,t,i,e)}for(const t of u)for(const s of p)if(t.layers.includes(s.layer)){const a=Nt(t.point,s.p1,s.p2),h=t.point.x-a.x,c=t.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,g=c/a*p;r(e,t.index,f,g),r(i,s.p1Idx,-f/2,-g/2),r(i,s.p2Idx,-f/2,-g/2)}}for(const t of f)for(const s of l)if(t.layers.includes(s.layer)){const a=Nt(t.point,s.p1,s.p2),h=t.point.x-a.x,c=t.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,g=c/a*p;r(i,t.index,f,g),r(e,s.p1Idx,-f/2,-g/2),r(e,s.p2Idx,-f/2,-g/2)}}for(const t of u)for(const s of f){if(t.layers.filter(t=>s.layers.includes(t)).length>0){const a=t.point.x-s.point.x,h=t.point.y-s.point.y,c=a*a+h*h;if(c>o){const d=Math.sqrt(c);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(o,d)):u=Math.max(o,d-this.viaDiameter);const p=l*n*Math.exp(-6*u),f=a/d*p,g=h/d*p;r(e,t.index,f,g),r(i,s.index,-f,-g)}}}}for(let e=0;e<s;e++){const s=t[e],i=[s.start,...s.mPoints,s.end],a=[];if(i.forEach((t,e)=>{t.z1!==t.z2&&a.push({point:t,layers:[t.z1,t.z2],index:e})}),!(a.length<2))for(let t=0;t<a.length;t++)for(let s=t+1;s<a.length;s++){const i=a[t],h=a[s],c=i.point.x-h.point.x,d=i.point.y-h.point.y,l=c*c+d*d;if(l>o){const t=Math.sqrt(l);let s=2,a=t;t<this.viaDiameter?(s*=4,a=Math.max(o,t)):a=Math.max(o,t-this.viaDiameter);const u=s*n*Math.exp(-6*a),p=c/t*u,f=d/t*u;r(e,i.index,p,f),r(e,h.index,-p,-f)}}}let c=!1;for(let n=0;n<s;n++)for(let s=0;s<t[n].mPoints.length;s++){const r=t[n].mPoints[s],h=a[n][s],d=r.z1!==r.z2;let l=h.fx,u=h.fy,p=r.x+l,f=r.y+u;if(d){const t=this.viaDiameter/2;let e=0,s=0;const n=this.viaDiameter/2+this.BOUNDARY_PADDING,o=this.bounds.minX+n,a=this.bounds.maxX-n,h=this.bounds.minY+n,c=this.bounds.maxY-n,d=o+t-r.x,g=r.x-(a-t),m=h+t-r.y,y=r.y-(c-t);d>0?e=i*(Math.exp(d/(2*this.obstacleMargin))-1):g>0&&(e=-.008*(Math.exp(g/(2*this.obstacleMargin))-1)),m>0?s=i*(Math.exp(m/(2*this.obstacleMargin))-1):y>0&&(s=-.008*(Math.exp(y/(2*this.obstacleMargin))-1)),l+=e,u+=s,p=r.x+l,f=r.y+u}else{const t=this.traceWidth/2+this.BOUNDARY_PADDING;p=Math.max(this.bounds.minX+t,Math.min(this.bounds.maxX-t,p)),f=Math.max(this.bounds.minY+t,Math.min(this.bounds.maxY-t,f))}if(Math.abs(l)<o&&Math.abs(u)<o)continue;e+=Math.sqrt(l*l+u*u),(Math.abs(r.x-p)>o||Math.abs(r.y-f)>o)&&(r.x=p,r.y=f,c=!0)}return{lastStepMoved:c,magForceApplied:e}}},xe=t=>t.flatMap(t=>`${t.connectionName}-${t.mPoints.map(t=>`${t.x.toFixed(2)},${t.y.toFixed(2)},${t.z1},${t.z2}`)}`).sort().join("|");var ve=class extends ye{constructor(t){super(t),this.MAX_ITERATIONS=1e3}createInitialCandidateFromSeed(t){const e=new qt({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,hyperParameters:{SHUFFLE_SEED:t},viaDiameter:this.viaDiameter});if(e.solve(),e.failed||!e.solved)return null;const s=[];let n=0;for(const[t,i]of e.completedPaths.entries()){if(i.length<2){console.warn(`Skipping connection "${t}" due to insufficient points (${i.length}) in ViaPossibilitiesSolver2 path.`);continue}const e=i[0],o=i[i.length-1],a=i.slice(1,-1),r=[];let h=0,c=e.z;for(let t=0;t<a.length;t++){const e=a[t],s=t+1<a.length?a[t+1]:o,n=c,i=t+1<a.length&&e.x===s.x&&e.y===s.y&&e.z!==s.z?s.z:e.z;r.push({x:e.x,y:e.y,z1:n,z2:i}),n!==i?(h++,t++,c=i):c=e.z}n+=h;const d=this.SEGMENTS_PER_POLYLINE;let l=r.length+1;for(;l<d;){let s=-1,n=-1,i=null,a=null;const h=[{...e,z1:e.z,z2:e.z,connectionName:t},...r,{...o,z1:o.z,z2:o.z,connectionName:t}];for(let t=0;t<h.length-1;t++){const e=h[t],o=h[t+1];if(e.x===o.x&&e.y===o.y)continue;const r=dt(e,o);r>s&&(s=r,n=t,i=e,a=o)}if(-1===n||!i||!a){console.warn(`Could not find longest segment for ${t} while trying to reach ${d} segments.`);break}const c=(i.x+a.x)/2,u=(i.y+a.y)/2,p=i.z2,f={x:c,y:u,z1:p,z2:p};r.splice(n,0,f),l++}s.push({connectionName:t,start:{...e,z1:e.z,z2:e.z},end:{...o,z1:o.z,z2:o.z},mPoints:r})}if(0===s.length)return this.failed=!0,this.error="No valid polylines generated from ViaPossibilitiesSolver2.",console.error(this.error),null;const i=this.computeMinGapBtwPolyLines(s),o=this.computeH({minGaps:i,forces:[]}),a={polyLines:s,g:0,h:o,f:0+o,viaCount:n,minGaps:i};return a.g=this.computeG(s,a),a.f=a.g+a.h,a}setupInitialPolyLines(){this.candidates=[];const t=Math.min(2e3,function(t){if(!Number.isInteger(t)||t<0)throw new RangeError("n must be a non-negative integer");let e=1;for(let s=2;s<=t;s++)e*=s;return e}(this.uniqueConnections)),e=new Set;for(let s=0;s<t;s++){const t=this.createInitialCandidateFromSeed(s);if(!t)continue;const n=xe(t.polyLines);e.has(n)||(e.add(n),this.candidates.push(t))}this.candidates.sort((t,e)=>t.f-e.f)}},Me=class extends $t{constructorParams;solvedRoutes=[];nodeWithPortPoints;connMap;constructor(t){super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.connMap=t.connMap,this.constructorParams=t,this.MAX_ITERATIONS=25e4,this.GREEDY_MULTIPLIER=5,this.MIN_SUBSTEPS=100}getCombinationDefs(){return[["multiHeadPolyLine"],["majorCombinations","orderings6","cellSizeFactor"],["noVias"],["orderings50"],["flipTraceAlignmentDirection","orderings6"],["closedFormTwoTrace"]]}getHyperParameterDefs(){return[{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:.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:[{SHUFFLE_SEED:0},{SHUFFLE_SEED:1},{SHUFFLE_SEED:2},{SHUFFLE_SEED:3},{SHUFFLE_SEED:4},{SHUFFLE_SEED:5}]},{name:"cellSizeFactor",possibleValues:[{CELL_SIZE_FACTOR:.5},{CELL_SIZE_FACTOR:1}]},{name:"flipTraceAlignmentDirection",possibleValues:[{FLIP_TRACE_ALIGNMENT_DIRECTION:!0}]},{name:"noVias",possibleValues:[{CELL_SIZE_FACTOR:2,VIA_PENALTY_FACTOR_2:10}]},{name:"orderings50",possibleValues:Array.from({length:50},(t,e)=>({SHUFFLE_SEED:100+e}))},{name:"closedFormTwoTrace",possibleValues:[{CLOSED_FORM_TWO_TRACE_SAME_LAYER:!0},{CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING:!0}]},{name:"multiHeadPolyLine",possibleValues:[{MULTI_HEAD_POLYLINE_SOLVER:!0,SEGMENTS_PER_POLYLINE:6,BOUNDARY_PADDING:.05},{MULTI_HEAD_POLYLINE_SOLVER:!0,SEGMENTS_PER_POLYLINE:6,BOUNDARY_PADDING:-.05,ITERATION_PENALTY:1e4,MINIMUM_FINAL_ACCEPTANCE_GAP:.001}]}]}computeG(t){return t?.hyperParameters?.MULTI_HEAD_POLYLINE_SOLVER?1e3+((t.hyperParameters?.ITERATION_PENALTY??0)+t.iterations)/1e4+1e4*(t.hyperParameters.SEGMENTS_PER_POLYLINE-3):t.iterations/1e4}computeH(t){return 1-(t.progress||0)}generateSolver(t){return t.CLOSED_FORM_TWO_TRACE_SAME_LAYER?new kt({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING?new Ut({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.MULTI_HEAD_POLYLINE_SOLVER?new ve({nodeWithPortPoints:this.nodeWithPortPoints,connMap:this.connMap,hyperParameters:t,viaDiameter:this.constructorParams.viaDiameter}):new Dt({...this.constructorParams,hyperParameters:t})}onSolve(t){this.solvedRoutes=t.solver.solvedRoutes}};function Se(t,e,s){const n=[];let i=null;for(let o=0;o<t.length;o++){const a=t[o];i?i.z===a.z?i.points.push({x:a.x,y:a.y}):(n.push(i),i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:s}):i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:s},o===t.length-1&&i&&n.push(i)}return n}var be=class extends e{unsolvedNodePortPoints;routes;colorMap;defaultViaDiameter=.6;defaultTraceThickness=.15;viaDiameter;traceWidth;failedSolvers;activeSubSolver=null;connMap;constructor({nodePortPoints:t,colorMap:e,connMap:s,viaDiameter:n,traceWidth:i}){super(),this.unsolvedNodePortPoints=t,this.colorMap=e??{},this.connMap=s,this.routes=[],this.failedSolvers=[],this.MAX_ITERATIONS=1e6,this.viaDiameter=n??this.defaultViaDiameter,this.traceWidth=i??this.defaultTraceThickness}_step(){if(this.updateCacheStats(),this.activeSubSolver)return this.activeSubSolver.step(),this.activeSubSolver.solved?(this.routes.push(...this.activeSubSolver.solvedRoutes),this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSolvers.push(this.activeSubSolver),this.activeSubSolver=null),void this.updateCacheStats();if(0===this.unsolvedNodePortPoints.length)return this.failedSolvers.length>0?(this.solved=!1,this.failed=!0,this.error=`Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0,5).map(t=>t.nodeWithPortPoints.capacityMeshNodeId)}. err0: ${this.failedSolvers[0].error}.`,void this.updateCacheStats()):(this.solved=!0,void this.updateCacheStats());const t=this.unsolvedNodePortPoints.pop();this.activeSubSolver=new Me({nodeWithPortPoints:t,colorMap:this.colorMap,connMap:this.connMap,viaDiameter:this.viaDiameter,traceWidth:this.traceWidth}),this.updateCacheStats()}updateCacheStats(){const t=st();this.stats.intraNodeCacheHits=t.cacheHits,this.stats.intraNodeCacheMisses=t.cacheMisses}visualize(){let e={lines:[],points:[],rects:[],circles:[]};for(const t of this.routes){const s=Se(t.route,t.connectionName,this.colorMap[t.connectionName]);for(const n of s)e.lines.push({points:n.points,label:n.connectionName,strokeColor:0===n.z?n.color:V(n.color,.75),layer:`z${n.z}`,strokeWidth:t.traceThickness,strokeDash:0!==n.z?"10, 5":void 0});for(const s of t.vias)e.circles.push({center:s,layer:"z0,1",radius:t.viaDiameter/2,fill:this.colorMap[t.connectionName],label:`${t.connectionName} via`})}for(const t of this.failedSolvers){const s=t.nodeWithPortPoints,n=.1*s.width,i=.1*s.height;e.rects.push({center:{x:s.center.x-n/2,y:s.center.y-i/2},layer:"did_not_connect",width:n,height:i,fill:"red",label:`Failed: ${s.capacityMeshNodeId}`});const o={};for(const t of s.portPoints)o[t.connectionName]||(o[t.connectionName]=[]),o[t.connectionName].push({x:t.x,y:t.y,z:t.z});for(const[t,s]of Object.entries(o))for(let t=0;t<s.length-1;t++){const n=s[t],i=s[t+1];e.lines.push({points:[n,i],strokeColor:"red",strokeDash:"10, 5",layer:"did_not_connect"})}}return this.activeSubSolver&&(e=t(e,this.activeSubSolver.visualize())),e}},Ne=class{netMap;idToNetMap;constructor(t){this.netMap=t,this.idToNetMap={};for(const[e,s]of Object.entries(t))for(const t of s)this.idToNetMap[t]=e}addConnections(t){for(const e of t){const t=new Set;for(const s of e){const e=this.idToNetMap[s];e&&t.add(e)}let s;if(0===t.size)s=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[s]=[];else if(1===t.size)s=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{s=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(const e of t)if(e!==s){this.netMap[s].push(...this.netMap[e]),this.netMap[e]=this.netMap[s];for(const t of this.netMap[s])this.idToNetMap[t]=s}}for(const t of e)this.netMap[s].includes(t)||this.netMap[s].push(t),this.idToNetMap[t]=s}}getIdsConnectedToNet(t){return this.netMap[t]||[]}getNetConnectedToId(t){return this.idToNetMap[t]}areIdsConnected(t,e){if(t===e)return!0;const s=this.getNetConnectedToId(t);if(!s)return!1;const n=this.getNetConnectedToId(e);return!!n&&(s===n||n===t||n===t)}areAllIdsConnected(t){const e=this.getNetConnectedToId(t[0]);for(const s of t){const t=this.getNetConnectedToId(s);if(void 0===t)return!1;if(t!==e)return!1}return!0}},Ie=t=>{const e=new Ne({});for(const s of t.connections)for(const t of s.pointsToConnect)"pcb_port_id"in t&&t.pcb_port_id&&e.addConnections([[s.name,t.pcb_port_id]]);for(const s of t.obstacles){const t=s.offBoardConnectsTo??[],n=Array.from(new Set([...s.connectedTo,...t]));n.length>0&&e.addConnections([n])}return e},Pe=(t,e=1,s={})=>{const n=s.viaDiameter??.6,i=s.obstacleMargin??.2,o=(("width"in t?t.width:t)/(n/2+i)/2)**1.1*e;return 1===t.availableZ?.length&&o>1?1:o},Ce=(t,e=.5,s=16)=>{let n=0,i=t;for(;n<s;){if(Pe({width:i})<=e)break;i/=2,n++}return Math.max(1,n)},_e=(t,e)=>{if(t<0||t>=e)throw new Error(`Invalid z "${t}" for layer count: ${e}`);return 0===t?"top":t===e-1?"bottom":`inner${t}`},Ee=(t,e)=>{const s=[];if(0===t.route.length)return s;let n=[],i=t.route[0].z;for(let o=0;o<t.route.length;o++){const a=t.route[o];if(a.z!==i){const o=_e(i,e);for(const e of n)s.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:o});if(t.vias.some(t=>Math.abs(t.x-a.x)<.001&&Math.abs(t.y-a.y)<.001)){const t=_e(i,e),n=_e(a.z,e);s.push({route_type:"via",x:a.x,y:a.y,from_layer:t,to_layer:n})}n=[a],i=a.z}else n.push(a)}const o=_e(i,e);for(const e of n)s.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:o});return s};function Te(t){return"layers"in t&&Array.isArray(t.layers)}function we(t){return Te(t)?t.layers[0]:t.layer}function ze(t){return Te(t)?t.layers:[t.layer]}var Ae=(t,e)=>"top"===t?0:"bottom"===t?e-1:parseInt(t.slice(5)),Re=1e5,Oe=.001,Le=class extends e{mergedHdRoute;remainingHdRoutes;start;end;colorMap;constructor(t){if(super(),this.remainingHdRoutes=[...t.hdRoutes],this.colorMap=t.colorMap??{},0===t.hdRoutes.length){this.start=t.start,this.end=t.end;const e=[{x:t.start.x,y:t.start.y,z:t.start.z}],s=[];return t.start.z!==t.end.z&&(e.push({x:t.start.x,y:t.start.y,z:t.end.z}),s.push({x:t.start.x,y:t.start.y})),e.push({x:t.end.x,y:t.end.y,z:t.end.z}),this.mergedHdRoute={connectionName:t.connectionName,route:e,vias:s,viaDiameter:t.defaultViaDiameter??.6,traceThickness:t.defaultTraceThickness??.15},void(this.solved=!0)}let e=1/0,s=t.hdRoutes[0],n="start-to-end";for(const i of t.hdRoutes){const o=i.route[0],a=i.route[i.route.length-1],r=dt(t.start,o),h=dt(t.start,a),c=dt(t.end,o),d=dt(t.end,a),l=Math.min(r,h,c,d);l<e&&(e=l,s=i,n=Math.min(c,d)<Math.min(r,h)?"end-to-start":"start-to-end")}"start-to-end"===n?(this.start=t.start,this.end=t.end):(this.start=t.end,this.end=t.start);const i=s.route[0],o=s.route[s.route.length-1],a=dt(this.start,i)<=dt(this.start,o)?i:o;this.mergedHdRoute={connectionName:t.connectionName,route:[{x:this.start.x,y:this.start.y,z:a.z}],vias:[],viaDiameter:s.viaDiameter,traceThickness:s.traceThickness}}getDisjointedRoute(){for(const t of this.remainingHdRoutes){if([t.route[0],t.route[t.route.length-1]].some(e=>!this.remainingHdRoutes.some(s=>{if(s===t)return!1;return[s.route[0],s.route[s.route.length-1]].some(t=>t.z===e.z&&dt(e,t)<.001)})))return{firstRoute:t}}return{firstRoute:this.remainingHdRoutes[0]}}_step(){if(0===this.remainingHdRoutes.length){const t=this.mergedHdRoute.route[this.mergedHdRoute.route.length-1];return this.mergedHdRoute.route.push({x:this.end.x,y:this.end.y,z:t.z}),void(this.solved=!0)}const t=this.mergedHdRoute.route[this.mergedHdRoute.route.length-1];let e=-1,s="first",n=1/0;for(let i=0;i<this.remainingHdRoutes.length;i++){const o=this.remainingHdRoutes[i],a=o.route[0],r=o.route[o.route.length-1],h=dt(t,a),c=dt(t,r);let d=1/0;d=t.z===a.z?h<Oe?h:Re+h:h<Oe?1e3+h:Re+h,d<n&&(n=d,e=i,s="first");let l=1/0;l=t.z===r.z?c<Oe?c:Re+c:c<Oe?1e3+c:Re+c,l<n&&(n=l,e=i,s="last")}if(-1===e)return void(this.remainingHdRoutes=[]);const i=this.remainingHdRoutes[e];let o;this.remainingHdRoutes.splice(e,1),o="first"===s?i.route:[...i.route].reverse(),o.length>0&&dt(t,o[0])<Oe&&t.z===o[0].z?this.mergedHdRoute.route.push(...o.slice(1)):this.mergedHdRoute.route.push(...o),this.mergedHdRoute.vias.push(...i.vias)}visualize(){const t={points:[],lines:[],circles:[],title:"Single High Density Route Stitch Solver"};if(t.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){t.lines?.push({points:this.mergedHdRoute.route.map(t=>({x:t.x,y:t.y})),strokeColor:"green"});for(const e of this.mergedHdRoute.route)t.points?.push({x:e.x,y:e.y,color:"green"});for(const e of this.mergedHdRoute.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:this.mergedHdRoute.viaDiameter/2,fill:"green"})}for(const[e,s]of this.remainingHdRoutes.entries()){const n=this.colorMap[s.connectionName]??"gray";s.route.length>1&&t.lines?.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:n});for(let i=0;i<s.route.length;i++){const o=s.route[i];t.points?.push({x:o.x+(e%2-.5)/500+(i%8-4)/1e3,y:o.y+(e%2-.5)/500+(i%8-4)/1e3,color:n,label:`Route ${s.connectionName} ${o===s.route[0]?"First":o===s.route[s.route.length-1]?"Last":""}`})}for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n})}return t}},De=class extends e{unsolvedRoutes;activeSolver=null;mergedHdRoutes=[];colorMap={};defaultTraceThickness;defaultViaDiameter;constructor(t){super(),this.colorMap=t.colorMap??{};const e=t.hdRoutes[0];this.defaultTraceThickness=e?.traceThickness??.15,this.defaultViaDiameter=e?.viaDiameter??t.defaultViaDiameter??.6,this.unsolvedRoutes=t.connections.map(e=>({connectionName:e.name,hdRoutes:t.hdRoutes.filter(t=>t.connectionName===e.name),start:{...e.pointsToConnect[0],z:Ae(we(e.pointsToConnect[0]),t.layerCount)},end:{...e.pointsToConnect[1],z:Ae(we(e.pointsToConnect[1]),t.layerCount)}})),this.MAX_ITERATIONS=1e5}_step(){if(this.activeSolver)return this.activeSolver.step(),void(this.activeSolver.solved?(this.activeSolver instanceof Le&&this.mergedHdRoutes.push(this.activeSolver.mergedHdRoute),this.activeSolver=null):this.activeSolver.failed&&(this.failed=!0,this.error=this.activeSolver.error));const t=this.unsolvedRoutes.pop();t?this.activeSolver=new Le({connectionName:t.connectionName,hdRoutes:t.hdRoutes,start:t.start,end:t.end,colorMap:this.colorMap,defaultTraceThickness:this.defaultTraceThickness,defaultViaDiameter:this.defaultViaDiameter}):this.solved=!0}visualize(){const t={points:[],lines:[],circles:[],title:"Multiple High Density Route Stitch Solver"};if(this.activeSolver){const e=this.activeSolver.visualize();e.points?.length&&t.points?.push(...e.points),e.lines?.length&&t.lines?.push(...e.lines),e.circles?.length&&t.circles?.push(...e.circles),e.rects?.length&&(t.rects||(t.rects=[]),t.rects.push(...e.rects))}for(const[e,s]of this.mergedHdRoutes.entries()){const n=this.colorMap[s.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1],a=0!==i.z?V(n,.5):n;t.lines?.push({points:[{x:i.x,y:i.y},{x:o.x,y:o.y}],strokeColor:a,strokeWidth:s.traceThickness})}for(const e of s.route){const s=0!==e.z?V(n,.5):n;t.points?.push({x:e.x,y:e.y,color:s})}for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n})}for(const e of this.unsolvedRoutes){const s=this.colorMap[e.connectionName]??"gray";t.points?.push({x:e.start.x,y:e.start.y,color:s,label:`${e.connectionName} Start (z=${e.start.z})`},{x:e.end.x,y:e.end.y,color:s,label:`${e.connectionName} End (z=${e.end.z})`}),t.lines?.push({points:[{x:e.start.x,y:e.start.y},{x:e.end.x,y:e.end.y}],strokeColor:s,strokeDash:"2 2"});for(const n of e.hdRoutes){n.route.length>1&&t.lines?.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:V(s,.5),strokeDash:"10 5"});for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s})}}return t}},$e=t=>{const e=[],s=[],n=[],i=H(t),o=(t.minViaDiameter??.6)/2;if(t.connections)for(const e of t.connections)for(const t of e.pointsToConnect){const s=ze(t);n.push({x:t.x,y:t.y,color:i[e.name],layer:s[0]??("z"in t?_e(t.z,2):"top"),label:`${e.name} (${s.join(",")})`})}if(t.traces)for(const n of t.traces)for(let t=0;t<n.route.length-1;t++){const i=n.route[t],a=n.route[t+1];"via"===i.route_type?s.push({center:{x:i.x,y:i.y},radius:o,fill:"blue",stroke:"none",layer:"z0,1"}):"wire"===i.route_type&&"wire"===a.route_type&&a.layer===i.layer&&e.push({points:[{x:i.x,y:i.y},{x:a.x,y:a.y}],layer:`z${Ae(i.layer,2)}`,strokeWidth:.15,strokeColor:V({top:"red",bottom:"blue",inner1:"green",inner2:"yellow"}[i.layer],.5)})}return{rects:t.obstacles.map(t=>({center:t.center,width:t.width,height:t.height,fill:"rgba(255,0,0,0.5)",layer:`z${t.layers.map(Ae).join(",")}`})),circles:s,lines:e,points:n}};function Fe(t){const{nodeId:e,nodeIdToSegmentIds:s,segmentIdToNodeIds:n,hops:i}=t;if(0===i)return[e];const o=new Set([e]),a=[{nodeId:e,remainingHops:i}];for(;a.length>0;){const{nodeId:t,remainingHops:e}=a.shift();if(0===e)continue;const i=s.get(t)||[];for(const t of i){const s=n.get(t)||[];for(const t of s)o.has(t)||(o.add(t),a.push({nodeId:t,remainingHops:e-1}))}}return Array.from(o)}var ke=t=>Array.from(t.entries()).map(([t,{x:e,y:s,z:n}])=>`${t}(${e?.toFixed(3)??""},${s?.toFixed(3)??""},${n??""})`).sort().join("&"),Be=(t,e,s,n)=>{const i=Math.min(t,e),o=Math.max(t,e),a=Math.min(s,n);return i<=Math.max(s,n)&&o>=a},Xe=(t,e,s,n)=>{const i=[],o=new Map(t.originalPointMap);for(const[t,e]of s.entries()){const s=o.get(t);o.set(t,{x:e.x??s.x,y:e.y??s.y,z:e.z??s.z})}for(const s of t.allNodeIds){if(!e.get(s))continue;const a=t.segmentPairsInNode.get(s);for(const t of a){const e=o.get(t[0]),n=o.get(t[1]);e.z!==n.z&&i.push({type:"transition_via",segmentPoints:t,capacityMeshNodeId:s,probabilityOfFailure:0})}for(let t=0;t<a.length;t++)for(let e=t+1;e<a.length;e++){if(n?.areIdsConnected(a[t][0],a[t][1]))continue;const r=a[t],h=a[e],c=o.get(r[0]),d=o.get(r[1]),l=o.get(h[0]),u=o.get(h[1]);if(!Be(c.z,d.z,l.z,u.z))continue;const p=at(c,d,l,u),f=c.z===d.z&&l.z===u.z&&c.z===l.z;p&&(f?i.push({type:"same_layer_crossing",segmentPoints:[r,h],capacityMeshNodeId:s,crossingLine1:r,crossingLine2:h,probabilityOfFailure:0}):c.z===d.z&&l.z!==u.z?i.push({type:"single_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:s,sameLayerCrossingLine:r,transitionCrossingLine:h,probabilityOfFailure:0}):c.z!==d.z&&l.z===u.z?i.push({type:"single_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:s,sameLayerCrossingLine:h,transitionCrossingLine:r,probabilityOfFailure:0}):c.z!==d.z&&l.z!==u.z&&i.push({type:"double_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:s,crossingLine1:r,crossingLine2:h,probabilityOfFailure:0}))}}return i},Ye=(t,e,s)=>{if("change_layer"===e.type)for(const s of e.segmentPointIds){const n=t.get(s)||{};t.set(s,{...n,z:e.newZ})}else if("swap_position_on_segment"===e.type){const[n,i]=e.segmentPointIds,o=s(n),a=s(i),r=t.get(n)||{},h=t.get(i)||{};t.set(n,{...r,x:a.x,y:a.y}),t.set(i,{...h,x:o.x,y:o.y})}else if("combined"===e.type)for(const n of e.operations)Ye(t,n,s)},He=(t,e)=>{const s=new Map,n=new Map,i=new Map,o=[];let a=0;for(const r of t)for(const t of r.assignedPoints){const h={segmentPointId:"SP"+a++,segmentId:r.nodePortSegmentId,capacityMeshNodeIds:e.get(r.nodePortSegmentId),connectionName:t.connectionName,x:t.point.x,y:t.point.y,z:t.point.z,directlyConnectedSegmentPointIds:[]};s.set(h.segmentPointId,h);for(const t of h.capacityMeshNodeIds)n.set(t,[...n.get(t)??[],h.segmentPointId]);i.set(r.nodePortSegmentId,[...i.get(r.nodePortSegmentId)??[],h.segmentPointId]),o.push(h)}return{segmentPointMap:s,nodeToSegmentPointMap:n,segmentToSegmentPointMap:i}},Ve=(t,e,s,n)=>{if(t?._containsTarget)return 0;return((.82*e+.41*s+.2*n)/2)**1.1/Pe(t)},je=class extends e{nodeMap;dedupedSegments;dedupedSegmentMap;MUTABLE_HOPS=1;unravelSection;candidates=[];lastProcessedCandidate=null;bestCandidate=null;originalCandidate;rootNodeId;nodeIdToSegmentIds;segmentIdToNodeIds;colorMap;tunedNodeCapacityMap;MAX_CANDIDATES=500;iterationsSinceImprovement=0;hyperParameters;selectedCandidateIndex=null;queuedOrExploredCandidatePointModificationHashes=new Set;constructorParams;constructor(t){if(super(),this.constructorParams=t,this.MUTABLE_HOPS=t.MUTABLE_HOPS??this.MUTABLE_HOPS,this.MAX_ITERATIONS=5e4,this.hyperParameters={...t.hyperParameters,MAX_ITERATIONS_WITHOUT_IMPROVEMENT:200},this.nodeMap=t.nodeMap,this.dedupedSegments=t.dedupedSegments,t.dedupedSegmentMap)this.dedupedSegmentMap=t.dedupedSegmentMap;else{this.dedupedSegmentMap=new Map;for(const t of this.dedupedSegments)this.dedupedSegmentMap.set(t.nodePortSegmentId,t)}this.nodeIdToSegmentIds=t.nodeIdToSegmentIds,this.segmentIdToNodeIds=t.segmentIdToNodeIds,this.rootNodeId=t.rootNodeId,this.colorMap=t.colorMap??{},this.unravelSection=this.createUnravelSection({segmentPointMap:t.segmentPointMap,nodeToSegmentPointMap:t.nodeToSegmentPointMap,segmentToSegmentPointMap:t.segmentToSegmentPointMap}),this.tunedNodeCapacityMap=new Map;for(const t of this.unravelSection.allNodeIds)this.tunedNodeCapacityMap.set(t,Pe(this.nodeMap.get(t)));this.originalCandidate=this.createInitialCandidate(),this.candidates=[this.originalCandidate]}getConstructorParams(){return{...this.constructorParams,segmentPointMap:this.unravelSection.segmentPointMap,nodeToSegmentPointMap:this.unravelSection.segmentPointsInNode,segmentToSegmentPointMap:this.unravelSection.segmentPointsInSegment}}createUnravelSection(t){const e=Fe({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS}),s=Fe({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS+1}),n=Array.from(new Set(s).difference(new Set(e)));t?.segmentPointMap||(t=He(this.dedupedSegments,this.segmentIdToNodeIds));const i=new Map;for(const e of s)i.set(e,t.nodeToSegmentPointMap.get(e));const o=new Map;for(const e of s)for(const s of i.get(e)){const e=t.segmentPointMap.get(s);o.set(s,e)}const a=Array.from(o.values()),r=new Map;for(const t of a)r.set(t.segmentId,[...r.get(t.segmentId)??[],t.segmentPointId]);for(const[e,s]of i.entries())for(let e=0;e<s.length;e++){const n=t.segmentPointMap.get(s[e]);for(let i=e+1;i<s.length;i++){const e=t.segmentPointMap.get(s[i]);e.segmentPointId!==n.segmentPointId&&(e.segmentId!==n.segmentId&&e.connectionName===n.connectionName&&(e.directlyConnectedSegmentPointIds.includes(n.segmentPointId)||(n.directlyConnectedSegmentPointIds.push(e.segmentPointId),e.directlyConnectedSegmentPointIds.push(n.segmentPointId))))}}const h=new Map;for(const t of s)h.set(t,[]);for(const e of a)for(const s of e.capacityMeshNodeIds){const n=h.get(s);if(n)for(const i of e.directlyConnectedSegmentPointIds){const o=t.segmentPointMap.get(i);o.segmentPointId!==e.segmentPointId&&(o.capacityMeshNodeIds.some(t=>t===s)&&(n.some(([t,s])=>t===e.segmentPointId&&s===o.segmentPointId||t===o.segmentPointId&&s===e.segmentPointId)||n.push([e.segmentPointId,o.segmentPointId])))}}const c=new Set;for(const t of e)for(const e of this.nodeIdToSegmentIds.get(t)){this.segmentIdToNodeIds.get(e).every(t=>!this.nodeMap.get(t)._containsTarget)&&c.add(e)}const d=new Set;for(const t of a){const s=t.capacityMeshNodeIds.some(t=>e.includes(t)),n=this.dedupedSegmentMap.get(t.segmentId),i=n&&n.availableZ.length>1;(s||i)&&d.add(t.segmentPointId)}const l=new Set;for(const t of a){if(t.capacityMeshNodeIds.some(t=>this.nodeMap.get(t)?._containsTarget)){const e=this.dedupedSegmentMap.get(t.segmentId);e&&1===e.availableZ.length&&l.add(t.segmentPointId)}}return{allNodeIds:s,mutableNodeIds:e,immutableNodeIds:n,mutableSegmentIds:c,segmentPairsInNode:h,segmentPointMap:o,segmentPointsInNode:i,segmentPointsInSegment:r,originalPointMap:o,mutableSegmentPointIds:d,zLockedSegmentPointIds:l}}createInitialCandidate(){const t=new Map,e=Xe(this.unravelSection,this.nodeMap,t),s=this.computeG({issues:e,originalCandidate:{},operationsPerformed:0,operation:{}});return{pointModifications:t,g:s,h:0,f:s,operationsPerformed:0,candidateHash:ke(t),issues:Xe(this.unravelSection,this.nodeMap,t)}}get nextCandidate(){return this.candidates[0]??null}getPointInCandidate(t,e){const s=this.unravelSection.segmentPointMap.get(e),n=t.pointModifications.get(e);return{x:n?.x??s.x,y:n?.y??s.y,z:n?.z??s.z,segmentId:s.segmentId}}getConnectionSegmentPointIds(t){const e=[];for(const[s,n]of this.unravelSection.segmentPointMap.entries())n.connectionName===t&&e.push(s);return e}canConnectionUseLayer(t,e){for(const s of t){const t=this.unravelSection.segmentPointMap.get(s),n=this.dedupedSegmentMap.get(t.segmentId);if(!n||!n.availableZ.includes(e))return!1}return!0}getOperationsForIssue(t,e){const s=[];if("transition_via"===e.type){const[n,i]=e.segmentPoints,o=this.getPointInCandidate(t,n),a=this.getPointInCandidate(t,i),r=this.unravelSection.segmentPointMap.get(n),h=(this.unravelSection.segmentPointMap.get(i),this.dedupedSegmentMap.get(o.segmentId).availableZ),c=this.dedupedSegmentMap.get(a.segmentId).availableZ,d=this.unravelSection.zLockedSegmentPointIds.has(n),l=this.unravelSection.zLockedSegmentPointIds.has(i),u=this.getConnectionSegmentPointIds(r.connectionName);if(this.canConnectionUseLayer(u,a.z)){const t=u.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));t.length>0&&s.push({type:"change_layer",newZ:a.z,segmentPointIds:t})}if(this.canConnectionUseLayer(u,o.z)){const t=u.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));t.length>0&&s.push({type:"change_layer",newZ:o.z,segmentPointIds:t})}this.unravelSection.mutableSegmentPointIds.has(n)&&!d&&h.includes(a.z)&&s.push({type:"change_layer",newZ:a.z,segmentPointIds:[n]}),this.unravelSection.mutableSegmentPointIds.has(i)&&!l&&c.includes(o.z)&&s.push({type:"change_layer",newZ:o.z,segmentPointIds:[i]})}if("same_layer_crossing"===e.type){const[t,n]=e.crossingLine1,[i,o]=e.crossingLine2,a=[],r=this.unravelSection.segmentPointMap.get(t),h=this.unravelSection.segmentPointMap.get(n),c=this.unravelSection.segmentPointMap.get(i),d=this.unravelSection.segmentPointMap.get(o),l=this.unravelSection.mutableSegmentPointIds.has(t),u=this.unravelSection.mutableSegmentPointIds.has(n),p=this.unravelSection.mutableSegmentPointIds.has(i),f=this.unravelSection.mutableSegmentPointIds.has(o),g=this.unravelSection.zLockedSegmentPointIds.has(t),m=this.unravelSection.zLockedSegmentPointIds.has(n),y=this.unravelSection.zLockedSegmentPointIds.has(i),x=this.unravelSection.zLockedSegmentPointIds.has(o);l&&p&&r.segmentId===c.segmentId&&a.push([t,i]),l&&f&&r.segmentId===d.segmentId&&a.push([t,o]),u&&p&&h.segmentId===c.segmentId&&a.push([n,i]),u&&f&&h.segmentId===d.segmentId&&a.push([n,o]);for(const[t,e]of a)s.push({type:"swap_position_on_segment",segmentPointIds:[t,e]});const v=this.getConnectionSegmentPointIds(r.connectionName),M=this.getConnectionSegmentPointIds(c.connectionName),S=new Set;for(const t of this.unravelSection.segmentPointMap.values()){const e=this.dedupedSegmentMap.get(t.segmentId);if(e)for(const t of e.availableZ)S.add(t)}for(const t of S)if(t!==r.z&&this.canConnectionUseLayer(v,t)){const e=v.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));e.length>0&&s.push({type:"change_layer",newZ:t,segmentPointIds:e})}for(const t of S)if(t!==c.z&&this.canConnectionUseLayer(M,t)){const e=M.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));e.length>0&&s.push({type:"change_layer",newZ:t,segmentPointIds:e})}const b=this.dedupedSegmentMap.get(r.segmentId),N=this.dedupedSegmentMap.get(h.segmentId),I=this.dedupedSegmentMap.get(c.segmentId),P=this.dedupedSegmentMap.get(d.segmentId),C=(t,e)=>t.every(t=>t.availableZ.includes(e));if(l&&u&&!g&&!m){const e=0===r.z?1:0;C([b,N],e)&&s.push({type:"change_layer",newZ:e,segmentPointIds:[t,n]})}if(p&&f&&!y&&!x){const t=0===c.z?1:0;C([I,P],t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[i,o]})}if(l&&!g){const e=0===r.z?1:0;b.availableZ.includes(e)&&s.push({type:"change_layer",newZ:e,segmentPointIds:[t]})}if(u&&!m){const t=0===h.z?1:0;N.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[n]})}if(p&&!y){const t=0===c.z?1:0;I.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[i]})}if(f&&!x){const t=0===d.z?1:0;P.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[o]})}}return s}computeG(t){const{issues:e,originalCandidate:s,operationsPerformed:n,operation:i}=t,o=new Map;for(const t of e){o.has(t.capacityMeshNodeId)||o.set(t.capacityMeshNodeId,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0});const e=o.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"===t.type||"single_transition_crossing"===t.type?e.numEntryExitLayerChanges++:t.type}let a=0;for(const[t,{numEntryExitLayerChanges:e,numSameLayerCrossings:s,numTransitionCrossings:n}]of o){const i=this.nodeMap.get(t),o=Math.min(Ve(i,s,e,n),.999999);a+=Math.log(1-o)}var r;return(r=a)<-Math.LN2?Math.log(1-Math.exp(r)):Math.log(-Math.expm1(r))}getUnexploredNeighborByApplyingOperation(t,e){const s=new Map(t.pointModifications);Ye(s,e,e=>this.getPointInCandidate(t,e));const n=ke(s);if(this.queuedOrExploredCandidatePointModificationHashes.has(n))return null;const i=Xe(this.unravelSection,this.nodeMap,s),o=t.operationsPerformed+1,a=this.computeG({issues:i,originalCandidate:t,operationsPerformed:o,operation:e});return{issues:i,g:a,h:0,f:a,pointModifications:s,candidateHash:n,operationsPerformed:o}}getNeighborOperationsForCandidate(t){return t.issues.flatMap(e=>this.getOperationsForIssue(t,e))}getNeighbors(t){const e=[],s=this.getNeighborOperationsForCandidate(t);for(const n of s){const s=this.getUnexploredNeighborByApplyingOperation(t,n);s&&e.push(s)}return e}_step(){const t=this.candidates.shift();this.iterationsSinceImprovement++,this.iterationsSinceImprovement>this.hyperParameters.MAX_ITERATIONS_WITHOUT_IMPROVEMENT?this.solved=!0:t?(this.lastProcessedCandidate=t,t.f<(this.bestCandidate?.f??1/0)&&(this.bestCandidate=t,this.iterationsSinceImprovement=0),this.getNeighbors(t).forEach(t=>{this.queuedOrExploredCandidatePointModificationHashes.has(t.candidateHash)||(this.queuedOrExploredCandidatePointModificationHashes.add(t.candidateHash),this.candidates.push(t))}),this.candidates.sort((t,e)=>t.f-e.f),this.candidates.length=Math.min(this.candidates.length,this.MAX_CANDIDATES)):this.solved=!0}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Section Solver"};let e=null;if(e=null!==this.selectedCandidateIndex?"best"===this.selectedCandidateIndex?this.bestCandidate:"original"===this.selectedCandidateIndex?this.originalCandidate:this.candidates[this.selectedCandidateIndex]:this.solved?this.bestCandidate:this.lastProcessedCandidate||this.candidates[0],!e)return t;const s=new Map;for(const[t,n]of this.unravelSection.segmentPointMap){const i={...n},o=e.pointModifications.get(t);o&&(void 0!==o.x&&(i.x=o.x),void 0!==o.y&&(i.y=o.y),void 0!==o.z&&(i.z=o.z)),s.set(t,i)}for(const[e,n]of s)t.points.push({x:n.x,y:n.y,label:`${e}\nSegment: ${n.segmentId} ${this.unravelSection.mutableSegmentIds.has(n.segmentId)?"MUTABLE":"IMMUTABLE"}\nLayer: ${n.z}`,color:this.colorMap[n.connectionName]||"#000"});const n=new Map;for(const t of this.unravelSection.allNodeIds)n.set(t,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0,estPf:0});for(const t of e.issues){const e=n.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"!==t.type&&"single_transition_crossing"!==t.type||e.numEntryExitLayerChanges++}for(const[t,e]of n.entries()){const s=this.nodeMap.get(t);e.estPf=Ve(s,e.numSameLayerCrossings,e.numEntryExitLayerChanges,e.numTransitionCrossings)}for(const e of this.unravelSection.allNodeIds){const s=this.nodeMap.get(e),i=this.unravelSection.mutableNodeIds.includes(e),o=n.get(e),a=[`${e} (${i?"MUT":"IMM"})`,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Pf: ${o.estPf.toFixed(3)}`,`TC: ${o.numTransitionCrossings}`,`SLC: ${o.numSameLayerCrossings}`,`EELC: ${o.numEntryExitLayerChanges}`].join("\n");t.rects.push({center:s.center,label:a,color:i?"green":"red",width:s.width/8,height:s.height/8})}for(const[e,n]of this.unravelSection.segmentPointsInSegment){if(n.length<=1)continue;const i=n.map(t=>s.get(t));for(let s=0;s<i.length-1;s++)t.lines.push({points:[{x:i[s].x,y:i[s].y},{x:i[s+1].x,y:i[s+1].y}],strokeColor:this.colorMap[e]||"#000"})}for(const[e,n]of s)for(const i of n.directlyConnectedSegmentPointIds)if(e<i){const e=s.get(i);if(!e)continue;const o=n.z===e.z,a=n.z;let r;r=o?0===a?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:n.x,y:n.y},{x:e.x,y:e.y}],strokeDash:r,strokeColor:this.colorMap[n.connectionName]||"#000"})}for(const n of e.issues){const e=this.nodeMap.get(n.capacityMeshNodeId);if("transition_via"===n.type)for(const i of n.segmentPoints){const n=s.get(i);t.circles.push({center:{x:n.x,y:n.y},radius:e.width/16,stroke:"#ff0000",fill:"rgba(255, 0, 0, 0.2)",label:`Via Issue\n${i}\nLayer: ${n.z}`})}else if("same_layer_crossing"===n.type)for(const[i,o]of[n.crossingLine1,n.crossingLine2]){const n=s.get(i),a=s.get(o);t.lines.push({points:[{x:n.x,y:n.y},{x:a.x,y:a.y}],strokeColor:"rgba(255,0,0,0.2)",strokeWidth:e.width/32})}}for(const[n,i]of e.pointModifications){const e=s.get(n),i=this.unravelSection.segmentPointMap.get(n);t.circles.push({center:{x:e.x,y:e.y},radius:.05,stroke:"#0000ff",fill:"rgba(0, 0, 255, 0.2)",label:`${n}\nOriginal: (${i.x.toFixed(2)}, ${i.y.toFixed(2)}, ${i.z})\nNew: (${e.x.toFixed(2)}, ${e.y.toFixed(2)}, ${e.z})`})}return t}};import Ze from"object-hash";function We(t,e){return Array.isArray(e)?[t.a*e[0]+t.c*e[1]+t.e,t.b*e[0]+t.d*e[1]+t.f]:{x:t.a*e.x+t.c*e.y+t.e,y:t.b*e.x+t.d*e.y+t.f}}var{cos:Ue,sin:Ge,PI:qe}=Math,{tan:Ke}=Math,Je=t=>(Math.round(20*t)/20).toFixed(2),Qe=t=>(Math.round(1e3*t)/1e3).toFixed(3);nt();var ts=class extends je{cacheHit=!1;cacheProvider;hasAttemptedToUseCache=!1;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?et():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}computeCacheKeyAndTransform(){const t=this.nodeMap.get(this.rootNodeId),e=function(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}(-t.center.x,-t.center.y),s=new Map,n=new Map,i=new Map,o=new Map,a=new Map,r=new Map;let h=0,c=0,d=0;const l=[...this.unravelSection.allNodeIds].sort((t,e)=>{const s=this.nodeMap.get(t),n=this.nodeMap.get(e);return s.center.x!==n.center.x?s.center.x-n.center.x:s.center.y-n.center.y});for(const t of l){const e="node_"+h++;s.set(t,e),n.set(e,t)}const u=[...Array.from(this.unravelSection.segmentPointMap.entries()).sort(([,t],[,e])=>t.x!==e.x?t.x-e.x:t.y-e.y).map(([t])=>t)].sort();for(const t of u){const e="sp_"+d++;a.set(t,e),r.set(e,t);const s=this.unravelSection.segmentPointMap.get(t).segmentId;if(!i.has(s)){const t="seg_"+c++;i.set(s,t),o.set(t,s)}}const p={};for(const[t,n]of s.entries()){const s=this.nodeMap.get(t),i=We(e,s.center);p[n]={width:s.width,height:s.height,availableZ:s.availableZ,center:{x:Je(i.x),y:Je(i.y)}}}const f={};for(const[t,s]of a.entries()){const n=this.unravelSection.segmentPointMap.get(t),i=We(e,{x:n.x,y:n.y});f[s]={x:Je(i.x),y:Je(i.y),z:n.z}}const g={hyperParameters:this.hyperParameters,normalizedNodes:p,normalizedSegmentPoints:f,mutableHops:this.MUTABLE_HOPS},m=`unravelsec:${Ze(g)}`,y={realToCacheTransform:e,nodeIdMap:s,segmentIdMap:i,segmentPointIdMap:a,reverseNodeIdMap:n,reverseSegmentIdMap:o,reverseSegmentPointIdMap:r};return this.cacheKey=m,this.cacheToSolveSpaceTransform=y,{cacheKey:m,cacheToSolveSpaceTransform:y}}applyCachedSolution(t){if(!1===t.success)return void(this.failed=!0);if(!this.cacheToSolveSpaceTransform)return void console.error("Cache transform not available to apply cached solution.");const{reverseSegmentPointIdMap:e,reverseNodeIdMap:s}=this.cacheToSolveSpaceTransform,n=new Map;for(const[s,i]of t.bestCandidatePointModificationsDelta){const t=e.get(s);if(!t){console.warn(`Could not find original ID for normalized SP ID: ${s} when applying cache.`);continue}const o=this.unravelSection.segmentPointMap.get(t);if(!o){console.warn(`Could not find original segment point for ID: ${t} when applying cache.`);continue}const a={};if(void 0!==i.dx){const t=parseFloat(i.dx);Number.isNaN(t)?console.warn(`Failed to parse cached dx coordinate: ${i.dx}`):a.x=o.x+t}if(void 0!==i.dy){const t=parseFloat(i.dy);Number.isNaN(t)?console.warn(`Failed to parse cached dy coordinate: ${i.dy}`):a.y=o.y+t}void 0!==i.dz&&(a.z=o.z+i.dz),Object.keys(a).length>0&&n.set(t,a)}const i=Xe(this.unravelSection,this.nodeMap,n);this.bestCandidate={pointModifications:n,issues:i,f:t.bestCandidateF,g:t.bestCandidateF,h:0,operationsPerformed:-1,candidateHash:ke(n)},this.cacheHit=!0,this.solved=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(this.failed)return void this.cacheProvider?.setCachedSolutionSync(this.cacheKey,{success:!1});if(!this.bestCandidate)return;const{segmentPointIdMap:t}=this.cacheToSolveSpaceTransform,e=[];for(const[s,n]of this.bestCandidate.pointModifications.entries()){const i=t.get(s);if(!i){console.warn(`Could not find normalized ID for original SP ID: ${s} when saving to cache.`);continue}const o=this.unravelSection.segmentPointMap.get(s);if(!o){console.warn(`Could not find original segment point for ID: ${s} when saving cache.`);continue}const a={};let r=!1;if(void 0!==n.x){const t=n.x-o.x,e=Qe(t);0!==parseFloat(e)&&(a.dx=e,r=!0)}if(void 0!==n.y){const t=n.y-o.y,e=Qe(t);0!==parseFloat(e)&&(a.dy=e,r=!0)}if(void 0!==n.z){const t=n.z-o.z;0!==t&&(a.dz=t,r=!0)}r&&e.push([i,a])}const s={success:!0,bestCandidatePointModificationsDelta:e,bestCandidateF:this.bestCandidate.f};this.cacheProvider?.setCachedSolutionSync(this.cacheKey,s)}},es=class extends e{nodeMap;dedupedSegmentMap;dedupedSegments;nodeIdToSegmentIds;segmentIdToNodeIds;nodeToSegmentPointMap;segmentToSegmentPointMap;colorMap;tunedNodeCapacityMap;MAX_NODE_ATTEMPTS=2;MUTABLE_HOPS=1;ACCEPTABLE_PF=.05;MAX_ITERATIONS_WITHOUT_IMPROVEMENT=200;nodePfMap;attemptsToFixNode;activeSubSolver=null;segmentPointMap;cacheProvider=null;constructor({assignedSegments:t,colorMap:e,nodes:s,cacheProvider:n}){super(),this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.cacheHits=0,this.stats.cacheMisses=0,this.cacheProvider=n??null,this.MAX_ITERATIONS=1e6,this.dedupedSegments=(t=>{const e=[],s=new Map;let n=-1;for(const i of t){const t=`${i.start.x}-${i.start.y}-${i.end.x}-${i.end.y}-${i.availableZ.join(",")}`,o=s.get(t);o?i.nodePortSegmentId=o.nodePortSegmentId:(n++,i.nodePortSegmentId=`SEG${n}`,s.set(t,i),e.push(i))}return e})(t),this.dedupedSegmentMap=new Map;for(const t of this.dedupedSegments)this.dedupedSegmentMap.set(t.nodePortSegmentId,t);this.nodeMap=new Map;for(const t of s)this.nodeMap.set(t.capacityMeshNodeId,t);this.nodeIdToSegmentIds=new Map,this.segmentIdToNodeIds=new Map,this.attemptsToFixNode=new Map;for(const e of t)this.segmentIdToNodeIds.set(e.nodePortSegmentId,[...this.segmentIdToNodeIds.get(e.nodePortSegmentId)??[],e.capacityMeshNodeId]),this.nodeIdToSegmentIds.set(e.capacityMeshNodeId,[...this.nodeIdToSegmentIds.get(e.capacityMeshNodeId)??[],e.nodePortSegmentId]);this.colorMap=e??{},this.tunedNodeCapacityMap=new Map;for(const[t,e]of this.nodeMap)this.tunedNodeCapacityMap.set(t,Pe(e));const{segmentPointMap:i,nodeToSegmentPointMap:o,segmentToSegmentPointMap:a}=He(this.dedupedSegments,this.segmentIdToNodeIds);this.segmentPointMap=i,this.nodeToSegmentPointMap=o,this.segmentToSegmentPointMap=a,this.nodePfMap=this.computeInitialPfMap()}computeInitialPfMap(){const t=new Map;for(const[e,s]of this.nodeMap.entries())t.set(e,this.computeNodePf(s));return t}computeNodePf(t){const{numSameLayerCrossings:e,numEntryExitLayerChanges:s,numTransitionCrossings:n}=(t=>{let e=0,s=0,n=0;const i=new Map;for(const e of t)i.has(e.connectionName)||i.set(e.connectionName,[]),i.get(e.connectionName).push(e);const o=[],a=[];for(const[t,e]of i.entries()){if(e.length<2)continue;const n=e[0];for(let i=1;i<e.length;i++){const r=e[i],h={connectionName:t,z:n.z,points:[n,r]};n.z!==r.z?(s++,a.push({connectionName:t,points:[n,r]})):o.push(h)}}for(let t=0;t<o.length;t++)for(let s=t+1;s<o.length;s++){const n=o[t],i=o[s];n.z===i.z&&at(n.points[0],n.points[1],i.points[0],i.points[1])&&e++}for(let t=0;t<a.length;t++)for(let e=t+1;e<a.length;e++){const s=a[t],i=a[e];at(s.points[0],s.points[1],i.points[0],i.points[1])&&n++}for(let t=0;t<a.length;t++)for(let e=0;e<o.length;e++){const s=a[t],i=o[e];at(s.points[0],s.points[1],i.points[0],i.points[1])&&n++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:s,numTransitionCrossings:n}})((this.nodeToSegmentPointMap.get(t.capacityMeshNodeId)??[]).map(t=>this.segmentPointMap.get(t)));return Ve(t,e,s,n)}_step(){if(this.iterations>=this.MAX_ITERATIONS-1)return void(this.solved=!0);if(!this.activeSubSolver){let t=null,e=0;for(const[s,n]of this.nodePfMap.entries()){n*(1-(this.attemptsToFixNode.get(s)??0)/this.MAX_NODE_ATTEMPTS)>e&&(e=n,t=s)}if(!t||e<this.ACCEPTABLE_PF)return void(this.solved=!0);this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.activeSubSolver=new ts({dedupedSegments:this.dedupedSegments,dedupedSegmentMap:this.dedupedSegmentMap,nodeMap:this.nodeMap,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,colorMap:this.colorMap,rootNodeId:t,MUTABLE_HOPS:this.MUTABLE_HOPS,segmentPointMap:this.segmentPointMap,nodeToSegmentPointMap:this.nodeToSegmentPointMap,segmentToSegmentPointMap:this.segmentToSegmentPointMap,cacheProvider:this.cacheProvider})}this.activeSubSolver.step();const{bestCandidate:t,originalCandidate:e,lastProcessedCandidate:s}=this.activeSubSolver;if(this.activeSubSolver.failed)return this.stats.failedOptimizations+=1,void(this.activeSubSolver=null);if(this.activeSubSolver.solved){this.activeSubSolver.cacheHit?this.stats.cacheHits+=1:this.stats.cacheMisses+=1;if(t&&t.g<e.g){this.stats.successfulOptimizations+=1;for(const[e,s]of t.pointModifications.entries()){const t=this.segmentPointMap.get(e);t.x=s.x??t.x,t.y=s.y??t.y,t.z=s.z??t.z}for(const t of this.activeSubSolver.unravelSection.allNodeIds)this.nodePfMap.set(t,this.computeNodePf(this.nodeMap.get(t)))}else this.stats.failedOptimizations+=1;this.activeSubSolver=null}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Multi Section Solver"};for(const[e,s]of this.nodeMap.entries()){const n=this.nodePfMap.get(e)||0,i=Math.min(n,1),o=`rgb(${Math.floor(255*i)}, ${Math.floor(255*(1-i))}, 0)`;0===(this.attemptsToFixNode.get(e)??0)&&0===i||t.rects.push({center:s.center,label:[e,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Pf: ${n.toFixed(3)}`].join("\n"),color:o,width:s.width/8,height:s.height/8})}for(const e of this.segmentPointMap.values()){const s=this.dedupedSegmentMap.get(e.segmentId);t.points.push({x:e.x,y:e.y,label:[e.segmentPointId,e.segmentId,`z: ${e.z}`,`segment.availableZ: ${s?.availableZ.join(",")}`].join("\n"),color:this.colorMap[e.connectionName]||"#000"})}const e=new Map;for(const t of this.segmentPointMap.values())e.has(t.segmentId)||e.set(t.segmentId,[]),e.get(t.segmentId).push(t);for(const[s,n]of e.entries()){if(n.length<2)continue;const e=[...n].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y);for(let n=0;n<e.length-1;n++)t.lines.push({points:[{x:e[n].x,y:e[n].y},{x:e[n+1].x,y:e[n+1].y}],strokeColor:this.colorMap[s]||"#000"})}const s=new Set,n=Array.from(this.segmentPointMap.values());for(let e=0;e<n.length;e++){const i=n[e];for(let o=e+1;o<n.length;o++){const e=n[o];if(i.connectionName!==e.connectionName||i.segmentId===e.segmentId)continue;if(i.capacityMeshNodeIds.some(t=>e.capacityMeshNodeIds.includes(t))){const n=`${i.segmentPointId}-${e.segmentPointId}`;if(s.has(n))continue;s.add(n);const o=i.z===e.z,a=i.z;let r;r=o?0===a?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:i.x,y:i.y},{x:e.x,y:e.y}],strokeDash:r,strokeColor:this.colorMap[i.connectionName]||"#666"})}}}return t}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.dedupedSegments){const s=e.nodePortSegmentId;for(const e of this.segmentIdToNodeIds.get(s)){const s=this.nodeMap.get(e);t.has(e)||t.set(e,{capacityMeshNodeId:e,portPoints:[],center:s.center,width:s.width,height:s.height})}}for(const e of this.segmentPointMap.values())for(const s of e.capacityMeshNodeIds){const n=t.get(s);n&&n.portPoints.push({x:e.x,y:e.y,z:e.z,connectionName:e.connectionName})}return Array.from(t.values())}},ss=(t,e={})=>{const s=Math.min(...t.availableZ);return{center:!e.rectMargin||e.zOffset?{x:t.center.x+s*t.width*(e.zOffset??.05),y:t.center.y-s*t.width*(e.zOffset??.05)}:t.center,width:e.rectMargin?t.width-2*e.rectMargin:Math.max(t.width-.5,.8*t.width),height:e.rectMargin?t.height-2*e.rectMargin:Math.max(t.height-.5,.8*t.height),fill:t._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)"}[t.availableZ.join(",")]??"rgba(0,200,200,0.1)",layer:`z${t.availableZ.join(",")}`,label:[t.capacityMeshNodeId,`availableZ: ${t.availableZ.join(",")}`,""+(t._containsTarget?"containsTarget":""),""+(t._containsObstacle?"containsObstacle":"")].filter(Boolean).join("\n")}},ns=class extends e{connectionsWithNodes;usedNodeCapacityMap;simpleRouteJson;nodes;edges;GREEDY_MULTIPLIER=1.1;MAX_CANDIDATES_IN_MEMORY=1e5;nodeMap;nodeEdgeMap;connectionNameToGoalNodeIds;colorMap;maxDepthOfNodes;activeCandidateStraightLineDistance;debug_lastNodeCostMap;hyperParameters;constructor({simpleRouteJson:t,nodes:e,edges:n,colorMap:i,MAX_ITERATIONS:o=1e6,hyperParameters:a={}}){super(),this.MAX_ITERATIONS=o,this.simpleRouteJson=t,this.nodes=e,this.edges=n,this.colorMap=i??{};const{connectionsWithNodes:r,connectionNameToGoalNodeIds:h}=this.getConnectionsWithNodes();this.connectionsWithNodes=r,this.connectionNameToGoalNodeIds=h,this.hyperParameters=a,this.usedNodeCapacityMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,0])),this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=s(this.edges),this.maxDepthOfNodes=Math.max(...this.nodes.map(t=>t._depth??0)),this.debug_lastNodeCostMap=new Map}getTotalCapacity(t){const e=t._depth??0;return(this.maxDepthOfNodes-e+1)**2}getConnectionsWithNodes(){const t=[],e=this.nodes.filter(t=>t._containsTarget),s=new Map;for(const n of this.simpleRouteJson.connections){const i=[];for(const t of n.pointsToConnect){let s=this.nodes[0],n=Number.MAX_VALUE;for(const i of e){const e=Math.sqrt((i.center.x-t.x)**2+(i.center.y-t.y)**2);e<n&&(n=e,s=i)}i.push(s)}if(i.length<2)throw new Error(`Not enough nodes for connection "${n.name}", only ${i.length} found`);s.set(n.name,i.map(t=>t.capacityMeshNodeId)),t.push({connection:n,nodes:i,pathFound:!1,straightLineDistance:dt(i[0].center,i[i.length-1].center)})}return t.sort((t,e)=>t.straightLineDistance-e.straightLineDistance),{connectionsWithNodes:t,connectionNameToGoalNodeIds:s}}currentConnectionIndex=0;candidates;visitedNodes;computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)}getBacktrackedPath(t){const e=[];let s=t;for(;s;)e.push(s.node),s=s.prevCandidate;return e}getNeighboringNodes(t){return this.nodeEdgeMap.get(t.capacityMeshNodeId).flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t))}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const s=e.path;s&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:s.map(t=>t.capacityMeshNodeId)})}return t}doesNodeHaveCapacityForTrace(t,e){const s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=this.getTotalCapacity(t);if(1===t.availableZ.length&&!t._containsTarget&&s>0)return!1;let i=0;return t.availableZ.length>1&&1===e.availableZ.length&&(i+=.5),s+i<n}canTravelThroughObstacle(t,e){const s=this.connectionNameToGoalNodeIds.get(e);return s?.includes(t.capacityMeshNodeId)??!1}getDistanceBetweenNodes(t,e){return Math.sqrt((t.center.x-e.center.x)**2+(t.center.y-e.center.y)**2)}reduceCapacityAlongPath(t){for(const e of t.path??[])this.usedNodeCapacityMap.set(e.capacityMeshNodeId,this.usedNodeCapacityMap.get(e.capacityMeshNodeId)+1)}isConnectedToEndGoal(t,e){return this.nodeEdgeMap.get(t.capacityMeshNodeId).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}_step(){const t=this.connectionsWithNodes[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const[e,s]=t.nodes;this.candidates||(this.candidates=[{prevCandidate:null,node:e,f:0,g:0,h:0}],this.debug_lastNodeCostMap=new Map,this.visitedNodes=new Set([e.capacityMeshNodeId]),this.activeCandidateStraightLineDistance=dt(e.center,s.center)),this.candidates.sort((t,e)=>t.f-e.f);const n=this.candidates.shift();if(this.candidates.length>this.MAX_CANDIDATES_IN_MEMORY&&this.candidates.splice(this.MAX_CANDIDATES_IN_MEMORY,this.candidates.length-this.MAX_CANDIDATES_IN_MEMORY),!n)return console.error(`Ran out of candidates on connection ${t.connection.name}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,void(this.failed=!0);if(this.isConnectedToEndGoal(n.node,s))return t.path=this.getBacktrackedPath({prevCandidate:n,node:s,f:0,g:0,h:0}),this.reduceCapacityAlongPath(t),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);const i=this.getNeighboringNodes(n.node);for(const t of i){if(this.visitedNodes?.has(t.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(t,n.node))continue;const e=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;if(t._containsObstacle&&!this.canTravelThroughObstacle(t,e))continue;const i=this.computeG(n,t,s),o=this.computeH(n,t,s),a=i+o*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:a,g:i,h:o});const r={prevCandidate:n,node:t,f:a,g:i,h:o};this.candidates.push(r)}this.visitedNodes.add(n.node.capacityMeshNodeId)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(this.connectionsWithNodes)for(let e=0;e<this.connectionsWithNodes.length;e++){const s=this.connectionsWithNodes[e];if(s.path&&s.path.length>0){const n=s.path.map(({center:{x:t,y:s},width:n,availableZ:i})=>({x:t+.005*n*(e%10+e%19),y:s+.005*n*(e%10+e%19),availableZ:i}));t.lines.push({points:n,strokeColor:this.colorMap[s.connection.name]});for(let e=0;e<n.length;e++){const i=n[e];t.points.push({x:i.x,y:i.y,label:[`conn: ${s.connection.name}`,`node: ${s.path[e].capacityMeshNodeId}`,`z: ${i.availableZ.join(",")}`].join("\n")})}}}for(const e of this.nodes){const s=this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,n=this.getTotalCapacity(e),i=this.debug_lastNodeCostMap.get(e.capacityMeshNodeId);t.rects.push({...ss(e,{rectMargin:.025,zOffset:.01}),label:[`${e.capacityMeshNodeId}`,`${s}/${n}`,`${e.width.toFixed(2)}x${e.height.toFixed(2)}`,`g: ${void 0!==i?.g?i.g.toFixed(2):"?"}`,`h: ${void 0!==i?.h?i.h.toFixed(2):"?"}`,`f: ${void 0!==i?.f?i.f.toFixed(2):"?"}`,`z: ${e.availableZ.join(", ")}`].join("\n"),stroke:s>n+.5?"red":void 0})}if(this.connectionsWithNodes)for(const e of this.connectionsWithNodes)if(e.connection?.pointsToConnect)for(const s of e.connection.pointsToConnect)t.points.push({x:s.x,y:s.y,label:[`pointsToConnect ${e.connection.name}`].join("\n")});let e=this.connectionsWithNodes[this.currentConnectionIndex];if(!this.candidates&&this.currentConnectionIndex>0&&!this.connectionsWithNodes[this.currentConnectionIndex-1].path&&(e=this.connectionsWithNodes[this.currentConnectionIndex-1]),e){const[s,n]=e.connection.pointsToConnect;t.lines.push({points:[{x:s.x,y:s.y},{x:n.x,y:n.y}],strokeColor:"red",strokeDash:"10 5"})}if(this.candidates){const e=this.candidates.slice(0,5),s=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;e.forEach((e,n)=>{const i=.5*(1-n/5),o=this.getBacktrackedPath(e);t.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:V(this.colorMap[s]??"red",1-i)})})}return t}},is=class extends ns{NEGATIVE_CAPACITY_PENALTY_FACTOR=1;REDUCED_CAPACITY_PENALTY_FACTOR=1;constructor(...t){super(...t),this.GREEDY_MULTIPLIER=2.5}get maxCapacityFactor(){return this.hyperParameters.MAX_CAPACITY_FACTOR??1}getTotalCapacity(t){return Pe(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){const e=t.width+t.height,s=.05,n=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0);if(n>2)return s;return(e-s)*Math.max(1,(2-n)/(e-s))+s}getDistanceBetweenNodes(t,e){const s=t.center.x-e.center.x,n=t.center.y-e.center.y;return Math.sqrt(s**2+n**2)}computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)+this.getNodeCapacityPenalty(e)}},os=class extends is{doesNodeHaveCapacityForTrace(t,e){return!0}getNodeCapacityPenalty(t){const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let s=1;return 1===t.availableZ.length&&(s=10),(.05+2*Math.abs(e))*s}};function as(t,e,s){const n=e.x-t.x,i=e.y-t.y;if(Math.abs(n)<1e-9&&Math.abs(i)<1e-9)return t;const o=s.width/2,a=s.height/2,r=s.center.x-o,h=s.center.x+o,c=s.center.y-a,d=s.center.y+a;let l=0,u=1/0;if(Math.abs(n)>1e-9){const e=(r-t.x)/n,s=(h-t.x)/n;l=Math.max(l,Math.min(e,s)),u=Math.min(u,Math.max(e,s))}else if(t.x<r||t.x>h)return t;if(Math.abs(i)>1e-9){const e=(c-t.y)/i,s=(d-t.y)/i;l=Math.max(l,Math.min(e,s)),u=Math.min(u,Math.max(e,s))}else if(t.y<c||t.y>d)return t;if(u<l||l===1/0||l<-1e9)return t;return{x:t.x+n*l,y:t.y+i*l}}function rs(t,e){const s=t.center,n=e.center,i=as(s,n,t),o=as(n,s,e),a=n.x-s.x,r=n.y-s.y,h=Math.sqrt(a*a+r*r);let c=i,d=o;if(h>1e-9){const s={x:a/h,y:r/h},n=.3*t.width,l=.3*e.width;n+l<Math.sqrt((o.x-i.x)**2+(o.y-i.y)**2)?(c={x:i.x+s.x*n,y:i.y+s.y*n},d={x:o.x-s.x*l,y:o.y-s.y*l}):(c=i,d=o)}return{lineStart:c,lineEnd:d}}var hs=(t,e,s)=>{if(t<e)return 0;if(e<1&&t<=1)return 0;if(1===s&&t>1)return 1-.01**t;const n=t/e-1;return 1-Math.exp(-2*n)},cs=(t,e,s)=>{if(s._containsTarget)return 0;if(t<=e)return 0;const n=1-hs(t,e,s.availableZ.length);return n<=0?-1e9:Math.log(n)},ds=({totalNodeCapacityMap:t,usedNodeCapacityMap:e,nodeMap:s,sectionNodeIds:n})=>{let i=0;const o=n??new Set(e.keys());for(const n of o){if(!t.has(n))continue;const o=s.get(n);if(!o)continue;const a=t.get(n),r=e.get(n)??0;i+=cs(r,a,o)}return i};function ls({sectionNodes:t,sectionEdges:e,sectionConnectionTerminals:s,completedPaths:n,nodeMap:i,colorMap:o,centerNodeId:a,title:r,nodeOpacity:h=.1,usedNodeCapacityMap:c,totalCapacityMap:d}){const l={points:[],lines:[],rects:[],circles:[],title:r},u=new Set(t.map(t=>t.capacityMeshNodeId));for(const e of t){let t=`rgba(128, 128, 128, ${h})`,s=`rgba(128, 128, 128, ${h})`;const n=e.availableZ??[],i=n.includes(0),o=n.includes(1);i&&o?(t=`rgba(128, 0, 128, ${h})`,s=`rgba(128, 0, 128, ${h})`):i?(t=`rgba(0, 0, 255, ${h})`,s=`rgba(0, 0, 255, ${h})`):o&&(t=`rgba(255, 0, 0, ${h})`,s=`rgba(255, 0, 0, ${h})`),a&&e.capacityMeshNodeId===a&&(t=`rgba(0, 255, 0, ${h})`,s=`rgba(0, 128, 0, ${h})`),l.rects.push({...ss(e),fill:t,stroke:s,label:`${e.capacityMeshNodeId}\n(Section Node)\nZ: ${n.join(",")}`});const r=l.rects.length-1;if(c&&d){const t=c.get(e.capacityMeshNodeId)??0,s=d.get(e.capacityMeshNodeId)??0,n=s>0?(t/s*100).toFixed(1):"N/A",i=hs(t,s,e.availableZ.length);l.rects[r].label+=`\n${t.toFixed(1)} / ${s.toFixed(1)}\n${n}% (Pf: ${(100*i).toFixed(1)}%)`,i>.2&&(l.rects[r].stroke=V("red",.7*(.8+h)))}}for(const t of e){const[e,s]=t.nodeIds,n=i.get(e),o=i.get(s);if(n&&o){const{lineStart:t,lineEnd:e}=rs(n,o);l.lines.push({points:[t,e],strokeColor:`rgba(0, 0, 0, ${.2*Math.min(1,h/.1)})`})}}return s.forEach((t,e)=>{const s=i.get(t.startNodeId),n=i.get(t.endNodeId),a=o[t.connectionName]??"black",r=s&&u.has(s.capacityMeshNodeId),h=n&&u.has(n.capacityMeshNodeId),c=(e+e/50)%5;let d=0,p=0,f=0,g=0;if(r&&s){const e=.02*Math.min(s.width,s.height);d=e*c,p=e*c,l.points.push({x:s.center.x+d,y:s.center.y+p,color:a,label:`Start: ${t.connectionName}\n(${t.startNodeId})`}),l.lines.push({points:[{x:s.center.x,y:s.center.y},{x:s.center.x+d,y:s.center.y+p}],strokeColor:"gray",strokeDash:"2 2"})}if(h&&n){const e=.02*Math.min(n.width,n.height);f=e*c,g=e*c,l.points.push({x:n.center.x+f,y:n.center.y+g,color:a,label:`End: ${t.connectionName}\n(${t.endNodeId})`}),l.lines.push({points:[{x:n.center.x,y:n.center.y},{x:n.center.x+f,y:n.center.y+g}],strokeColor:"gray",strokeDash:"2 2"})}r&&h&&s&&n&&l.lines.push({points:[{x:s.center.x+d,y:s.center.y+p},{x:n.center.x+f,y:n.center.y+g}],strokeColor:a,strokeDash:"5 5"})}),n&&n.forEach((t,e)=>{if(t.path&&t.path.length>0){const s=o[t.connectionName]??"gray",n={x:(e+e/50)%5*.03,y:(e+e/50)%5*.03};l.lines.push({points:t.path.map(({center:{x:t,y:e}})=>({x:t+n.x,y:e+n.y})),strokeColor:V(s,.2)})}}),l}var us=class extends e{GREEDY_MULTIPLIER=1.5;sectionNodes;sectionEdges;sectionConnectionTerminals;nodeMap;nodeEdgeMap;colorMap;usedNodeCapacityMap;totalNodeCapacityMap;centerNodeId;currentSectionScore=0;MAX_CANDIDATES_IN_MEMORY=1e4;currentConnectionIndex=0;candidates=null;visitedNodes=null;queuedNodes=null;activeCandidateStraightLineDistance;debug_lastNodeCostMap=new Map;maxCapacityFactor=1;constructor(t){super(),this.MAX_ITERATIONS=1e4,this.centerNodeId=t.centerNodeId,this.sectionNodes=t.sectionNodes,this.sectionEdges=t.sectionEdges,this.sectionConnectionTerminals=t.sectionConnectionTerminals.map(t=>({...t,path:void 0})),this.nodeMap=t.nodeMap??new Map(this.sectionNodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=t.nodeEdgeMap??s(this.sectionEdges),this.colorMap=t.colorMap??{},this.usedNodeCapacityMap=new Map(this.sectionNodes.map(t=>[t.capacityMeshNodeId,0])),this.totalNodeCapacityMap=new Map(this.sectionNodes.map(t=>[t.capacityMeshNodeId,this.getTotalCapacity(t)]));const e=new Set(this.sectionNodes.map(t=>t.capacityMeshNodeId));this.currentSectionScore=ds({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:e}),t.hyperParameters?.SHUFFLE_SEED&&(this.sectionConnectionTerminals=zt(this.sectionConnectionTerminals,t.hyperParameters?.SHUFFLE_SEED))}getTotalCapacity(t){return Pe(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){if(!this.nodeMap.has(t.capacityMeshNodeId))return 1/0;const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let s=1;return 1===t.availableZ.length&&(s=10),(.05+e**2*4)*s}getDistanceBetweenNodes(t,e){const s=t.center.x-e.center.x,n=t.center.y-e.center.y;return Math.sqrt(s**2+n**2)}computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)+this.getNodeCapacityPenalty(e)}getBacktrackedPath(t){const e=[];let s=t;for(;s;){if(e.push(s.node),!this.nodeMap.has(s.node.capacityMeshNodeId)){console.warn("Backtracked path went outside section bounds");break}s=s.prevCandidate}return e.reverse()}getNeighboringNodes(t){return this.nodeMap.has(t.capacityMeshNodeId)?this.nodeEdgeMap.get(t.capacityMeshNodeId)?.flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t)).filter(Boolean)??[]:[]}isConnectedToEndGoal(t,e){return!(!this.nodeMap.has(t.capacityMeshNodeId)||!this.nodeMap.has(e.capacityMeshNodeId))&&(this.nodeEdgeMap.get(t.capacityMeshNodeId)??[]).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}doesNodeHaveCapacityForTrace(t,e){return!0}reduceCapacityAlongPath(t){for(const e of t)if(this.usedNodeCapacityMap.has(e.capacityMeshNodeId)){const t=e.capacityMeshNodeId,s=this.nodeMap.get(t);if(!s){console.warn(`Node ${t} from path not found in section's nodeMap during score update.`);continue}const n=this.totalNodeCapacityMap.get(t),i=this.usedNodeCapacityMap.get(t)??0,o=cs(i,n,s);this.currentSectionScore-=o;const a=i+1;this.usedNodeCapacityMap.set(t,a);const r=cs(a,n,s);this.currentSectionScore+=r}}getSolvedSectionScore(){return this.currentSectionScore}_step(){const t=this.sectionConnectionTerminals[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const e=this.nodeMap.get(t.startNodeId),s=this.nodeMap.get(t.endNodeId);if(!e||!s)return console.error(`Start or end node not found in section for connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);this.candidates||this._setupAStar(e,s);const n=this.candidates;if(0===n.length)return void this._handleCandidatesExhausted(t);n.sort((t,e)=>t.f-e.f);const i=n.shift();if(n.length>this.MAX_CANDIDATES_IN_MEMORY&&n.splice(this.MAX_CANDIDATES_IN_MEMORY,n.length-this.MAX_CANDIDATES_IN_MEMORY),this.visitedNodes.add(i.node.capacityMeshNodeId),i.node.capacityMeshNodeId===s.capacityMeshNodeId)return void this._handleGoalReached(i,t,s);const o=this.getNeighboringNodes(i.node);for(const e of o){if(this.queuedNodes?.has(e.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(e,i.node))continue;if(e._containsObstacle){const s=e.capacityMeshNodeId===t.startNodeId,n=e.capacityMeshNodeId===t.endNodeId;if(!s&&!n)continue}const o=this.computeG(i,e,s),a=this.computeH(i,e,s),r=o+a*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(e.capacityMeshNodeId,{f:r,g:o,h:a});const h={prevCandidate:i,node:e,f:r,g:o,h:a};this.queuedNodes?.add(e.capacityMeshNodeId),n.push(h)}}computeProgress(){const t=this.sectionConnectionTerminals.length;if(0===t)return 1;let e=this.currentConnectionIndex/t;if(this.currentConnectionIndex<t&&this.candidates&&this.candidates.length>0&&this.activeCandidateStraightLineDistance&&this.activeCandidateStraightLineDistance>0){const s=this.candidates.reduce((t,e)=>e.f<t.f?e:t);e+=Math.max(0,Math.min(1,1-s.h/this.activeCandidateStraightLineDistance))/t}else this.solved&&(e=1);return Math.min(1,e)}_setupAStar(t,e){this.candidates=[{prevCandidate:null,node:t,f:0,g:0,h:0}],this.visitedNodes=new Set([t.capacityMeshNodeId]),this.debug_lastNodeCostMap=new Map,this.activeCandidateStraightLineDistance=dt(t.center,e.center);const s=this.computeH(null,t,e);this.candidates[0].h=s,this.candidates[0].f=s*this.GREEDY_MULTIPLIER,this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:this.candidates[0].f,g:0,h:s}),this.queuedNodes=new Set([t.capacityMeshNodeId])}_handleCandidatesExhausted(t){console.error(`Ran out of candidates for section connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}_handleGoalReached(t,e,s){const n=this.getBacktrackedPath(t);e.path=n,this.reduceCapacityAlongPath(n),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}visualize(){const t=this.sectionConnectionTerminals.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connectionName,path:t.path})),e=ls({sectionNodes:this.sectionNodes,sectionEdges:this.sectionEdges,sectionConnectionTerminals:this.sectionConnectionTerminals,completedPaths:t,nodeMap:this.nodeMap,colorMap:this.colorMap,centerNodeId:null,title:`Section Pathing: Conn ${this.currentConnectionIndex+1}/${this.sectionConnectionTerminals.length} (${this.sectionNodes.length} nodes)`,nodeOpacity:.1});for(const t of this.sectionNodes){const s=e.rects.findIndex(e=>e.label?.includes(t.capacityMeshNodeId));if(-1!==s){const n=this.debug_lastNodeCostMap.get(t.capacityMeshNodeId),i=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,o=this.getTotalCapacity(t),a=`${i.toFixed(1)}/${o.toFixed(1)}`,r=n?`f:${n.f.toFixed(1)} g:${n.g.toFixed(1)} h:${n.h.toFixed(1)}`:"cost:?";e.rects[s].label=[t.capacityMeshNodeId,`Cap: ${a}`,r,`Z: ${t.availableZ.join(",")}`].join("\n"),i>o&&(e.rects[s].stroke=V("red",.7))}}if(this.candidates&&this.candidates.length>0){const t=this.candidates.slice().sort((t,e)=>t.f-e.f).slice(0,5),s=this.sectionConnectionTerminals[this.currentConnectionIndex],n=s?.connectionName??"unknown",i=this.colorMap[n]??"purple";t.forEach((t,s)=>{const n=.8*(1-s/5),o=this.getBacktrackedPath(t);o.length>0&&e.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:V(i,1-n),strokeWidth:.05})})}return e}},ps=t=>Array.from({length:t},(t,e)=>e),fs=class extends $t{constructorParams;constructor(t){super(),this.MAX_ITERATIONS=1e5,this.constructorParams=t}computeG(t){return-t.getSolvedSectionScore()}computeH(t){return 0}getCombinationDefs(){const t=this.constructorParams.sectionConnectionTerminals.length;return 2===t?[["orderings2_for2"]]:3===t?[["orderings6_for3"]]:4===t?[["orderings24_for4"]]:[["orderings30"]]}getFailureMessage(){return`All CapacityPathingSingleSection solvers failed for "${this.centerNodeId}"`}getHyperParameterDefs(){return[{name:"orderings2_for2",possibleValues:ps(2).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings6_for3",possibleValues:ps(6).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings24_for4",possibleValues:ps(24).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings30",possibleValues:ps(30).map(t=>({SHUFFLE_SEED:t}))}]}generateSolver(t){return new us({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}onSolve({solver:t}){this.winningSolver=t}get centerNodeId(){return this.constructorParams.centerNodeId}get sectionNodes(){return this.constructorParams.sectionNodes}get sectionConnectionTerminals(){return this.winningSolver?.sectionConnectionTerminals}};import gs from"object-hash";var ms=t=>Math.floor(10*t)/10,ys=class extends fs{cacheHit=!1;cacheProvider;hasAttemptedToUseCache=!1;sectionNodeIdSet;cachedSectionConnectionTerminals=null;sectionScore=0;constructor(t){t.nodeMap=t.nodeMap??new Map(t.sectionNodes.map(t=>[t.capacityMeshNodeId,t])),super(t),this.sectionNodeIdSet=new Set(t.sectionNodes.map(t=>t.capacityMeshNodeId)),this.cacheProvider=void 0===t.cacheProvider?st():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}_computeBfsOrderingOfNodesInSection(){const t=new Set(this.constructorParams.centerNodeId),e=[],s=[{ancestorCapacitySum:0,capacity:0,g:0,capacityMeshNodeId:this.constructorParams.centerNodeId}];for(;s.length>0;){s.sort((t,e)=>e.g-t.g);const n=s.pop();if(!n)break;e.push(n.capacityMeshNodeId);const i=this.constructorParams.nodeEdgeMap.get(n.capacityMeshNodeId).flatMap(t=>t.nodeIds).filter(e=>!t.has(e)).filter(t=>this.sectionNodeIdSet.has(t));for(const e of i){t.add(e);const i=this.constructorParams.nodeMap.get(e),o=Pe(i);s.push({ancestorCapacitySum:n.g,capacity:o,g:n.g+o,capacityMeshNodeId:e})}}return e}computeCacheKeyAndTransform(){const t=this._computeBfsOrderingOfNodesInSection(),e=new Map,s=new Map;t.forEach((t,n)=>{const i=`node${n}`;e.set(t,i),s.set(i,t)});const n={};for(const s of t){const t=e.get(s),i=this.constructorParams.nodeMap.get(s),o=Pe(i);n[t]=ms(o).toFixed(1)}const i=new Set,o=[];for(const s of t){const t=e.get(s),n=this.constructorParams.nodeEdgeMap.get(s)??[];for(const a of n){const n=a.nodeIds.find(t=>t!==s);if(this.sectionNodeIdSet.has(n)){const s=[t,e.get(n)].sort(),a=`${s[0]}-${s[1]}`;i.has(a)||(o.push(s),i.add(a))}}}o.sort((t,e)=>t[0]!==e[0]?t[0].localeCompare(e[0]):t[1].localeCompare(e[1]));const a={},r=new Map,h=new Map;for(const t of this.constructorParams.sectionConnectionTerminals){const s=e.get(t.startNodeId),n=e.get(t.endNodeId),[i,o]=[s,n].sort(),c=`${i}->${o}`,d=h.get(c)??0;h.set(c,d+1);const l=`${i}->${o}::${d}`;a[l]={start:i,end:o},r.set(l,t.connectionName)}const c=`capacitypathing:${gs({node_capacity_map:n,node_edge_map:o,terminals:a})}`,d={cacheSpaceToRealConnectionId:r,cacheSpaceToRealNodeId:s};return this.cacheKey=c,this.cacheToSolveSpaceTransform=d,{cacheKey:c,cacheToSolveSpaceTransform:d}}applyCachedSolution(t){if(!this.cacheToSolveSpaceTransform)return console.error("Cache transform not available, cannot apply cached solution."),void(this.failed=!0);if(!t.success)return this.failed=!0,void(this.cacheHit=!0);this.cachedSectionConnectionTerminals=[];const{cacheSpaceToRealNodeId:e,cacheSpaceToRealConnectionId:s}=this.cacheToSolveSpaceTransform;for(const[n,i]of Object.entries(t.solutionPaths)){const t=s.get(n);if(!t){console.warn(`Could not find real connection name for ${n}`);continue}const o=this.constructorParams.sectionConnectionTerminals.find(e=>e.connectionName===t);if(!o){console.warn(`Could not find original terminal for connection name ${t}`);continue}const a=i.map(s=>{const n=e.get(s);if(!n)throw new Error(`Could not map cache node ID ${s} to real node ID for connection ${t}`);const i=this.constructorParams.nodeMap.get(n);if(!i)throw new Error(`Could not find node with ID ${n} in nodeMap for connection ${t}`);return i});this.cachedSectionConnectionTerminals.push({...o,path:a})}this.sectionScore=t.sectionScore,this.solved=!0,this.cacheHit=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(!this.cacheKey)return void console.error("Cannot save to cache without cache key.");if(!this.cacheToSolveSpaceTransform)return void console.error("Cache transform not available, cannot save solution to cache.");let t;if(this.failed)t={success:!1};else{if(!this.solved)return;{const e={},{cacheSpaceToRealNodeId:s,cacheSpaceToRealConnectionId:n}=this.cacheToSolveSpaceTransform,i=new Map;for(const[t,e]of s)i.set(e,t);const o=new Map;for(const[t,e]of n)o.set(e,t);const a=[];if(super.sectionConnectionTerminals)for(const t of super.sectionConnectionTerminals)if(t.path&&t.path.length>0){const e=t.path.map(t=>t.capacityMeshNodeId);a.push([t.connectionName,e])}for(const[t,s]of a){const n=o.get(t);if(!n){console.warn(`Could not find cache space connection ID for ${t} when saving to cache.`);continue}const a=s.map(e=>{const s=i.get(e);if(!s)throw new Error(`Could not map real node ID ${e} to cache node ID for connection ${t} when saving to cache.`);return s});e[n]=a}t={success:!0,sectionScore:this.sectionScore,solutionPaths:e}}}try{this.cacheProvider?.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}get sectionConnectionTerminals(){return this.cacheHit&&this.solved&&this.cachedSectionConnectionTerminals?(console.log("returning the cached section connection terminals"),this.cachedSectionConnectionTerminals):super.sectionConnectionTerminals}visualize(){if(!this.cacheHit)return super.visualize();return ls({sectionNodes:this.constructorParams.sectionNodes,sectionEdges:this.constructorParams.sectionEdges,sectionConnectionTerminals:this.cachedSectionConnectionTerminals,completedPaths:this.cachedSectionConnectionTerminals.map(t=>({connectionName:t.connectionName,path:t.path})),nodeMap:this.constructorParams.nodeMap,colorMap:this.constructorParams.colorMap,title:"CachedHyperCapacityPathingSingleSectionSolver"})}},xs=class extends e{simpleRouteJson;nodes;edges;nodeEdgeMap;connectionsWithNodes=[];colorMap;initialSolver;cacheProvider;stage="initialization";nodeMap=new Map;allNodeIdsSet;usedNodeCapacityMap=new Map;totalNodeCapacityMap=new Map;nodeCapacityPercentMap=new Map;nodeOptimizationAttemptCountMap=new Map;currentSection=null;sectionSolver=null;currentScheduleIndex=0;stats;OPTIMIZATION_SCHEDULE=[{MAX_ATTEMPTS_PER_NODE:1,MAX_EXPANSION_DEGREES:3,MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE:.05},{MAX_ATTEMPTS_PER_NODE:2,MAX_EXPANSION_DEGREES:5,MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE:.2},{MAX_ATTEMPTS_PER_NODE:3,MAX_EXPANSION_DEGREES:7,MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE:.9}];get currentSchedule(){return this.OPTIMIZATION_SCHEDULE[this.currentScheduleIndex]??null}constructor(t){super(),this.stats={successfulOptimizations:0,failedOptimizations:0,failedSectionSolvers:0,startingScore:0,scheduleScores:this.OPTIMIZATION_SCHEDULE.map(({MAX_EXPANSION_DEGREES:t})=>({maxExpansionDegrees:t,endingScore:0,endingHighestNodePf:0,sectionAttempts:0})),cacheHits:0,cacheMisses:0},this.MAX_ITERATIONS=t.MAX_ITERATIONS??1e7,this.cacheProvider=t.cacheProvider,this.simpleRouteJson=t.simpleRouteJson,this.nodes=t.nodes,this.edges=t.edges,this.nodeEdgeMap=s(this.edges),this.colorMap=t.colorMap??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=s(this.edges),this.initialSolver=t.initialPathingSolver||new os({simpleRouteJson:this.simpleRouteJson,nodes:this.nodes,edges:this.edges,colorMap:this.colorMap}),this.activeSubSolver=this.initialSolver;for(const t of this.nodes){const e=this.initialSolver.getTotalCapacity(t);this.totalNodeCapacityMap.set(t.capacityMeshNodeId,e)}this.allNodeIdsSet=new Set(this.nodes.map(t=>t.capacityMeshNodeId))}_stepInitialization(){if(this.initialSolver?.step(),this.initialSolver?.failed)return this.failed=!0,void(this.error=this.initialSolver.error);if(this.initialSolver?.solved){this.usedNodeCapacityMap=new Map(this.initialSolver.usedNodeCapacityMap);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=e>0?s/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,n),this.nodeOptimizationAttemptCountMap.set(t.capacityMeshNodeId,0)}this.connectionsWithNodes=this.initialSolver.connectionsWithNodes,this.stats.startingScore=ds({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet}),this.stage="section-optimization"}}_getNextNodeToOptimize(){let t=0,e=0,s=null;for(const n of this.nodes){if(n._containsTarget)continue;const i=this.nodeOptimizationAttemptCountMap.get(n.capacityMeshNodeId),o=this.totalNodeCapacityMap.get(n.capacityMeshNodeId),a=hs(this.usedNodeCapacityMap.get(n.capacityMeshNodeId)??0,o,n.availableZ.length),r=a/(i+1);i<this.currentSchedule.MAX_ATTEMPTS_PER_NODE&&r>t&&a>this.currentSchedule.MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE&&(t=r,e=a,s=n.capacityMeshNodeId)}return s}getOverallScore(){let t=0;for(const e of this.nodes){if(e._containsTarget)continue;const s=this.totalNodeCapacityMap.get(e.capacityMeshNodeId),n=hs(this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,s,e.availableZ.length);n>t&&(t=n)}return{highestNodePf:t,score:ds({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet})}}_stepSectionOptimization(){if(!this.sectionSolver){const t=this._getNextNodeToOptimize();if(!t){const{highestNodePf:t,score:e}=this.getOverallScore();return this.stats.scheduleScores[this.currentScheduleIndex].endingHighestNodePf=t,this.stats.scheduleScores[this.currentScheduleIndex].endingScore=e,this.currentScheduleIndex++,void(this.currentSchedule||(this.solved=!0))}const e=(t=>{const{centerNodeId:e,connectionsWithNodes:s,nodeMap:n,edges:i,nodeEdgeMap:o,expansionDegrees:a}=t,r=new Set,h=[{nodeId:e,depth:0}];r.add(e);let c=0;for(;c<h.length;){const{nodeId:t,depth:e}=h[c++];if(e>=a)continue;const s=o.get(t)?.flatMap(e=>e.nodeIds.filter(e=>e!==t))??[];for(const t of s)r.has(t)||(r.add(t),h.push({nodeId:t,depth:e+1}))}const d=Array.from(r).map(t=>n.get(t)),l=i.filter(t=>{const[e,s]=t.nodeIds;return r.has(e)&&r.has(s)}),u=[];for(const t of s){if(!t.path)continue;let e=null,s=null;for(const s of t.path)if(r.has(s.capacityMeshNodeId)){e=s.capacityMeshNodeId;break}for(let e=t.path.length-1;e>=0;e--){const n=t.path[e];if(r.has(n.capacityMeshNodeId)){s=n.capacityMeshNodeId;break}}e&&s&&u.push({connectionName:t.connection.name,startNodeId:e,endNodeId:s})}return{sectionConnectionTerminals:u,sectionNodes:d,sectionEdges:l,centerNodeId:e}})({centerNodeId:t,connectionsWithNodes:this.connectionsWithNodes,nodeMap:this.nodeMap,edges:this.edges,expansionDegrees:this.currentSchedule.MAX_EXPANSION_DEGREES,nodeEdgeMap:this.nodeEdgeMap});this.stats.scheduleScores[this.currentScheduleIndex].sectionAttempts++,this.currentSection=e,this.sectionSolver=new ys({sectionNodes:this.currentSection.sectionNodes,sectionEdges:this.currentSection.sectionEdges,sectionConnectionTerminals:this.currentSection.sectionConnectionTerminals,colorMap:this.colorMap,centerNodeId:this.currentSection.centerNodeId,nodeEdgeMap:this.nodeEdgeMap,hyperParameters:{EXPANSION_DEGREES:this.currentSchedule.MAX_EXPANSION_DEGREES},cacheProvider:this.cacheProvider}),this.activeSubSolver=this.sectionSolver,this.nodeOptimizationAttemptCountMap.set(t,(this.nodeOptimizationAttemptCountMap.get(t)??0)+1)}if(this.sectionSolver.step(),(this.sectionSolver.failed||this.sectionSolver.solved)&&(this.sectionSolver.cacheHit?this.stats.cacheHits++:this.stats.cacheMisses++),this.sectionSolver.failed)return console.warn(`Section solver failed for node ${this.currentSection.centerNodeId}. Error: ${this.sectionSolver.error}`),this.stats.failedSectionSolvers++,this.stats.failedOptimizations++,this.sectionSolver=null,void(this.activeSubSolver=null);if(this.sectionSolver.solved){const t=this.sectionSolver.sectionConnectionTerminals,e=this.sectionSolver.sectionNodes,s=this.sectionSolver.centerNodeId;if(this.sectionSolver=null,this.activeSubSolver=null,!t)return void console.warn(`Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`);const n=new Set(e.map(t=>t.capacityMeshNodeId)),i=ds({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:n}),o=new Map(this.usedNodeCapacityMap),a=t;for(const t of a){const e=this.connectionsWithNodes.find(e=>e.connection.name===t.connectionName);if(e?.path)for(const t of e.path)if(n.has(t.capacityMeshNodeId)){const e=o.get(t.capacityMeshNodeId)??0;o.set(t.capacityMeshNodeId,Math.max(0,e-1))}}for(const t of a)if(t.path)for(const e of t.path)n.has(e.capacityMeshNodeId)&&o.set(e.capacityMeshNodeId,(o.get(e.capacityMeshNodeId)??0)+1);ds({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:o,nodeMap:this.nodeMap,sectionNodeIds:n})>i?(this.stats.successfulOptimizations++,this._mergeSolvedSectionPaths({centerNodeId:s,sectionConnectionTerminals:t}),this._recalculateNodeCapacityUsage()):this.stats.failedOptimizations++}}_mergeSolvedSectionPaths({centerNodeId:t,sectionConnectionTerminals:e}){for(const s of e){if(!s.path){console.warn(`No path found for connection ${s.connectionName} in section ${t}`);continue}const e=this.connectionsWithNodes.find(t=>t.connection.name===s.connectionName);if(!e||!e.path){console.warn(`Original connection or path not found for ${s.connectionName} while merging section ${t}`);continue}const n=e.path,i=s.path,o=n.findIndex(t=>t.capacityMeshNodeId===s.startNodeId),a=n.findIndex(t=>t.capacityMeshNodeId===s.endNodeId);if(-1===o||-1===a){console.warn(`Could not find start/end nodes (${s.startNodeId}/${s.endNodeId}) in original path for ${s.connectionName}`);continue}const[r,h]=o<=a?[o,a]:[a,o],c=n.slice(0,r),d=n.slice(h+1);let l=i;if(i.length>0&&n[r]&&i[0].capacityMeshNodeId!==n[r].capacityMeshNodeId){if(i[i.length-1].capacityMeshNodeId!==n[r].capacityMeshNodeId){console.warn(`New section path for ${s.connectionName} doesn't align with original path boundaries. Skipping merge for this connection.`);continue}l=[...i].reverse()}e.path=[...c,...l,...d]}}_recalculateNodeCapacityUsage(){this.usedNodeCapacityMap.clear();for(const t of this.connectionsWithNodes)if(t.path)for(const e of t.path)this.usedNodeCapacityMap.set(e.capacityMeshNodeId,(this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0)+1);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=e>0?s/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,n)}}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const s=e.path;s&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:s.map(t=>t.capacityMeshNodeId)})}return t}_step(){this.iterations>=this.MAX_ITERATIONS-1?this.solved=!0:"initialization"===this.stage?this._stepInitialization():"section-optimization"===this.stage&&this._stepSectionOptimization()}visualize(){const t=this.connectionsWithNodes.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connection.name,path:t.path}));return ls({nodeMap:this.nodeMap,sectionConnectionTerminals:this.connectionsWithNodes.map(t=>({connectionName:t.connection.name,startNodeId:t.path?.[0]?.capacityMeshNodeId,endNodeId:t.path?.[t.path.length-1]?.capacityMeshNodeId})),completedPaths:t,sectionNodes:this.nodes,sectionEdges:this.edges,colorMap:this.colorMap,totalCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeOpacity:.05,title:"Capacity Pathing Multi-Section Solver (Solved)"})}},vs=class extends e{multiLayerNodes;strawNodes;skippedNodes;unprocessedNodes;strawSize;nodeIdCounter;constructor(t){super(),this.MAX_ITERATIONS=1e5,this.strawSize=t.strawSize??.5,this.multiLayerNodes=[],this.strawNodes=[],this.skippedNodes=[],this.nodeIdCounter=0,this.unprocessedNodes=[];for(const e of t.nodes)1===e.availableZ.length?this.unprocessedNodes.push(e):this.multiLayerNodes.push(e)}getCapacityOfMultiLayerNodesWithinBounds(t){let e=0;for(const s of this.multiLayerNodes){const n=s.center.x-s.width/2,i=s.center.x+s.width/2,o=s.center.y-s.height/2,a=s.center.y+s.height/2,r=Math.max(t.minX,n),h=Math.min(t.maxX,i),c=Math.max(t.minY,o),d=Math.min(t.maxY,a);if(r<h&&c<d){const t=(h-r)*(d-c)/(s.width*s.height);e+=Pe(s)*t}}return e}getSurroundingCapacities(t){const e=Math.min(t.width,t.height);return{leftSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2-e,maxX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),rightSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x+t.width/2,maxX:t.center.x+t.width/2+e,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),topSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2-e,maxY:t.center.y-t.height/2}),bottomSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y+t.height/2,maxY:t.center.y+t.height/2+e})}}createStrawsForNode(t){const e=[],{leftSurroundingCapacity:s,rightSurroundingCapacity:n,topSurroundingCapacity:i,bottomSurroundingCapacity:o}=this.getSurroundingCapacities(t);if(1*(s+n)>i+o){const s=Math.floor(t.height/this.strawSize),n=t.height/s;for(let i=0;i<s;i++){const s=t.center.y-t.height/2+i*n+n/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:t.center.x,y:s},width:t.width,height:n,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}else{const s=Math.floor(t.width/this.strawSize),n=t.width/s;for(let i=0;i<s;i++){const s=t.center.x-t.width/2+i*n+n/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:s,y:t.center.y},width:n,height:t.height,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}return e}getResultNodes(){return[...this.multiLayerNodes,...this.strawNodes,...this.skippedNodes]}_step(){const t=this.unprocessedNodes.pop();if(!t)return void(this.solved=!0);if(t.width<this.strawSize&&t.height<this.strawSize)return void this.skippedNodes.push(t);if(t._containsTarget)return void this.skippedNodes.push(t);const e=this.createStrawsForNode(t);this.strawNodes.push(...e),0===e.length&&this.strawNodes.push(t)}visualize(){const t={rects:[],lines:[],points:[],circles:[],title:"Straw Solver"};for(const e of this.unprocessedNodes)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(200, 200, 200, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nUnprocessed\n${e.width}x${e.height}`});for(const e of this.strawNodes){const s=0===e.availableZ[0]?"rgba(0, 150, 255, 0.5)":"rgba(255, 100, 0, 0.5)";t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nLayer: ${e.availableZ[0]}\n${e.width}x${e.height}`,layer:`z${e.availableZ.join(",")}`})}for(const e of this.multiLayerNodes)t.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,fill:"rgba(100, 255, 100, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",layer:`z${e.availableZ.join(",")}`,label:`${e.capacityMeshNodeId}\nLayers: ${e.availableZ.join(",")}\n${e.width}x${e.height}`});return t}};function Ms(t,e){const s=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2,a=e.center.x-e.width/2,r=e.center.x+e.width/2,h=e.center.y-e.height/2,c=e.center.y+e.height/2,d=.001,l=(Math.abs(n-a)<d||Math.abs(s-r)<d)&&Math.min(o,c)-Math.max(i,h)>=d,u=(Math.abs(o-h)<d||Math.abs(i-c)<d)&&Math.min(n,r)-Math.max(s,a)>=d;return l||u}var Ss=class extends e{constructor(t){super(),this.nodes=t,this.edges=[]}edges;nodeMap;getNextCapacityMeshEdgeId(){return`ce${this.edges.length}`}_step(){this.edges=[];for(let t=0;t<this.nodes.length;t++)for(let e=t+1;e<this.nodes.length;e++){!(this.nodes[t]._strawNode&&this.nodes[e]._strawNode&&this.nodes[t]._strawParentCapacityMeshNodeId===this.nodes[e]._strawParentCapacityMeshNodeId)&&Ms(this.nodes[t],this.nodes[e])&&this.doNodesHaveSharedLayer(this.nodes[t],this.nodes[e])&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[this.nodes[t].capacityMeshNodeId,this.nodes[e].capacityMeshNodeId]})}this.handleTargetNodes(),this.solved=!0}handleTargetNodes(){const t=this.nodes.filter(t=>t._containsTarget);for(const e of t){if(this.edges.some(t=>t.nodeIds.includes(e.capacityMeshNodeId)))continue;let t=null,s=1/0;for(const n of this.nodes){if(n._containsObstacle)continue;if(n._containsTarget)continue;const i=dt(e.center,n.center);i<s&&(s=i,t=n)}t&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[e.capacityMeshNodeId,t.capacityMeshNodeId]})}}doNodesHaveSharedLayer(t,e){return t.availableZ.some(t=>e.availableZ.includes(t))}visualize(){const t=new Map;for(const e of this.edges)for(const s of e.nodeIds)t.set(s,1+(t.get(s)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const s=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+s*e.width*.05,y:e.center.y-s*e.width*.05},fill:e._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)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}for(const t of this.edges){const s=this.nodeMap.get(t.nodeIds[0]),n=this.nodeMap.get(t.nodeIds[1]);if(s?.center&&n?.center){const t=Math.min(...s.availableZ),i=Math.min(...n.availableZ),o={x:s.center.x+t*s.width*.05,y:s.center.y-t*s.width*.05},a={x:n.center.x+i*n.width*.05,y:n.center.y-i*n.width*.05},r=Array.from(new Set([...s.availableZ,...n.availableZ])).sort();e.lines.push({layer:`z${r.join(",")}`,points:[o,a],strokeDash:s.availableZ.join(",")===n.availableZ.join(",")?void 0:"10 5"})}}return e}},bs=class{constructor(t){this.nodes=t,this.buckets=new Map;for(const e of t){const t=e.center.x-e.width/2,s=e.center.y-e.height/2,n=e.center.x+e.width/2,i=e.center.y+e.height/2;for(let o=t;o<=n;o+=this.CELL_SIZE)for(let t=s;t<=i;t+=this.CELL_SIZE){const s=this.getBucketKey(o,t),n=this.buckets.get(s);n?n.push(e):this.buckets.set(s,[e])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,s,n){const i=[],o=new Set,a=e-n/2,r=t+s/2,h=e+n/2;for(let e=t-s/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const s=this.getBucketKey(e,t),n=this.buckets.get(s)||[];for(const t of n)o.has(t.capacityMeshNodeId)||(o.add(t.capacityMeshNodeId),i.push(t))}return i}},Ns=class extends Ss{constructor(t){super(t),this.nodes=t,this.MAX_ITERATIONS=1e7,this.nodeTree=new bs(this.nodes),this.currentNodeIndex=0,this.edgeSet=new Set}nodeTree;currentNodeIndex;edgeSet;_step(){if(this.currentNodeIndex>=this.nodes.length)return this.handleTargetNodes(),void(this.solved=!0);const t=this.nodes[this.currentNodeIndex],e=this.nodeTree.getNodesInArea(t.center.x,t.center.y,2*t.width,2*t.height);for(const s of e){if(!Ms(t,s))continue;const e=t._strawNode&&s._strawNode&&t._strawParentCapacityMeshNodeId===s._strawParentCapacityMeshNodeId;t.capacityMeshNodeId===s.capacityMeshNodeId||e||!this.doNodesHaveSharedLayer(t,s)||this.edgeSet.has(`${t.capacityMeshNodeId}-${s.capacityMeshNodeId}`)||(this.edgeSet.add(`${t.capacityMeshNodeId}-${s.capacityMeshNodeId}`),this.edgeSet.add(`${s.capacityMeshNodeId}-${t.capacityMeshNodeId}`),this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[t.capacityMeshNodeId,s.capacityMeshNodeId]}))}this.currentNodeIndex++}},Is=class extends e{removedNodeIds;targetNodeIds;leaves;leavesIndex;adjacencyList;nodeMap;nodes;edges;constructor({nodes:t,edges:e}){super(),this.MAX_ITERATIONS=t.length,this.nodes=t,this.edges=e,this.removedNodeIds=new Set,this.targetNodeIds=new Set(t.filter(t=>t._containsTarget).map(t=>t.capacityMeshNodeId)),this.adjacencyList=new Map(t.map(({capacityMeshNodeId:t})=>[t,new Set]));for(const{nodeIds:[t,s]}of e)this.adjacencyList.get(t).add(s),this.adjacencyList.get(s).add(t);this.leavesIndex=0,this.leaves=[...this.adjacencyList.entries()].filter(([t,e])=>1===e.size).filter(([t,e])=>!this.targetNodeIds.has(t)).map(([t,e])=>t)}_step(){if(this.leavesIndex===this.leaves.length)return void(this.solved=!0);const t=this.leaves[this.leavesIndex],e=this.adjacencyList.get(t);if(!e||0===e.size)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));const[s]=e,n=s?this.adjacencyList.get(s):void 0;if(!s||!n)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));n.delete(t),this.removedNodeIds.add(t),this.adjacencyList.delete(t),1!==n.size||this.targetNodeIds.has(s)||this.leaves.push(s),this.leavesIndex+=1,this.leavesIndex===this.leaves.length&&(this.solved=!0)}visualize(){if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}const t=new Map;for(const e of this.edges)for(const s of e.nodeIds)t.set(s,1+(t.get(s)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const s=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+s*e.width*.05,y:e.center.y-s*e.width*.05},fill:e._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)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};for(const t of this.edges){const s=this.nodeMap.get(t.nodeIds[0]),n=this.nodeMap.get(t.nodeIds[1]);if(s?.center&&n?.center){const i=Math.min(...s.availableZ),o=Math.min(...n.availableZ),a={x:s.center.x+i*s.width*.05,y:s.center.y-i*s.width*.05},r={x:n.center.x+o*n.width*.05,y:n.center.y-o*n.width*.05},h=Array.from(new Set([...s.availableZ,...n.availableZ])).sort();e.lines.push({layer:`z${h.join(",")}`,points:[a,r],strokeDash:s.availableZ.join(",")===n.availableZ.join(",")?void 0:"10 5",strokeColor:t.nodeIds.some(t=>this.removedNodeIds.has(t))?V("black",.9):void 0})}}return e}},Ps=class{parent={};constructor(t){for(const e of t)this.parent[e]=e}find(t){return this.parent[t]===t?t:this.parent[t]=this.find(this.parent[t])}union(t,e){const s=this.find(t),n=this.find(e);s!==n&&(this.parent[n]=s)}getGroup(t){const e=this.find(t),s=[];for(const t in this.parent)this.find(t)===e&&s.push(t);return s}},Cs=class{point;left=null;right=null;constructor(t){this.point=t}},_s=class{root=null;constructor(t){t.length>0&&(this.root=this.buildTree(t,0))}buildTree(t,e){const s=e%2==0?"x":"y";t.sort((t,e)=>t[s]-e[s]);const n=Math.floor(t.length/2),i=new Cs(t[n]);return n>0&&(i.left=this.buildTree(t.slice(0,n),e+1)),n<t.length-1&&(i.right=this.buildTree(t.slice(n+1),e+1)),i}findNearestNeighbor(t){if(!this.root)throw new Error("Tree is empty");const e=this.root.point,s=this.distance(t,e);return this.nearestNeighborSearch(this.root,t,0,e,s),e}nearestNeighborSearch(t,e,s,n,i){if(!t)return n;const o=s%2?"x":"y",a=this.distance(e,t.point);a<i&&(n=t.point,i=a);const r=e[o]-t.point[o],h=r<=0?t.left:t.right,c=r<=0?t.right:t.left;return n=this.nearestNeighborSearch(h,e,s+1,n,i),i=this.distance(e,n),Math.abs(r)<i&&(n=this.nearestNeighborSearch(c,e,s+1,n,i)),n}findKNearestNeighbors(t,e){if(!this.root)return[];const s=[];return this.kNearestNeighborSearch(this.root,t,0,s,e),s.sort((t,e)=>t.distance-e.distance).slice(0,e).map(t=>t.point)}kNearestNeighborSearch(t,e,s,n,i){if(!t)return;const o=s%2?"x":"y",a=this.distance(e,t.point);n.push({point:t.point,distance:a});const r=e[o]-t.point[o],h=r<=0?t.left:t.right,c=r<=0?t.right:t.left;this.kNearestNeighborSearch(h,e,s+1,n,i);let d=1/0;n.length>=i&&(n.sort((t,e)=>t.distance-e.distance),d=n[i-1]?.distance||1/0),(Math.abs(r)<d||n.length<i)&&this.kNearestNeighborSearch(c,e,s+1,n,i)}distance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}},Es=class{parent=new Map;rank=new Map;constructor(t){for(const e of t){const t=this.pointToKey(e);this.parent.set(t,t),this.rank.set(t,0)}}pointToKey(t){return`${t.x},${t.y}`}find(t){const e=this.pointToKey(t);if(!this.parent.has(e))throw new Error(`Point ${e} not found in DisjointSet`);let s=e;for(;s!==this.parent.get(s);)s=this.parent.get(s);let n=e;for(;n!==s;){const t=this.parent.get(n);this.parent.set(n,s),n=t}return s}union(t,e){const s=this.find(t),n=this.find(e);if(s===n)return!1;const i=this.rank.get(s)||0,o=this.rank.get(n)||0;return i<o?this.parent.set(s,n):i>o?this.parent.set(n,s):(this.parent.set(n,s),this.rank.set(s,i+1)),!0}};function Ts(t){if(t.length<=1)return[];const e=new _s(t),s=[],n=Math.min(10,t.length-1);for(const i of t){const t=e.findKNearestNeighbors(i,n+1);for(const e of t){if(i.x===e.x&&i.y===e.y)continue;const t=Math.sqrt((i.x-e.x)**2+(i.y-e.y)**2);s.push({from:i,to:e,weight:t})}}s.sort((t,e)=>t.weight-e.weight);const i=new Es(t),o=[];for(const e of s)if(i.union(e.from,e.to)&&(o.push(e),o.length===t.length-1))break;return o}function ws(t){if(t.pointId)return t.pointId;let e="";var s;return"layer"in(s=t)&&"string"==typeof s.layer?e=t.layer:Te(t)&&t.layers&&(e=t.layers.sort().join("-")),`${t.x.toFixed(4)},${t.y.toFixed(4)},${e}`}var zs=class extends e{constructor(t,e={}){super(),this.ogSrj=t,this.colorMap=e,this.unprocessedConnections=function(t){if(0===t.length)return[];const e=t.map((t,e)=>`conn_${e}`),s=new Ps(e),n=new Map;t.forEach((t,e)=>{const s=`conn_${e}`;t.pointsToConnect.forEach(t=>{const e=ws(t);n.has(e)||n.set(e,[]),n.get(e).push(s)})});for(const t of n.values())if(t.length>1){const e=t[0];for(let n=1;n<t.length;n++)s.union(e,t[n])}const i=new Map;t.forEach((t,e)=>{const n=`conn_${e}`,o=s.find(n);i.has(o)||i.set(o,[]),i.get(o).push(t)});const o=[];for(const t of i.values()){if(1===t.length){o.push(t[0]);continue}const e=new Map,s=new Set;let n=!1;const i=[],a=new Set;let r;t.forEach(t=>{t.pointsToConnect.forEach(t=>e.set(ws(t),t)),s.add(t.name),t.isOffBoard&&(n=!0),t.externallyConnectedPointIds&&i.push(...t.externallyConnectedPointIds),t.netConnectionName&&a.add(t.netConnectionName),void 0===r&&void 0!==t.nominalTraceWidth&&(r=t.nominalTraceWidth)});const h={name:Array.from(s).join("__"),pointsToConnect:Array.from(e.values()),isOffBoard:n,externallyConnectedPointIds:i.length>0?i:void 0,netConnectionName:a.size>0?Array.from(a).join("__"):void 0,nominalTraceWidth:r};o.push(h)}return o}([...t.connections]),this.newConnections=[]}unprocessedConnections;newConnections;_step(){if(0===this.unprocessedConnections.length)return void(this.solved=!0);const t=this.unprocessedConnections.pop(),e=t.externallyConnectedPointIds??[],s=new Map;e.forEach((t,e)=>t.forEach(t=>s.set(t,e)));const n=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const n=s.get(t.pointId),i=s.get(e.pointId);return void 0!==n&&n===i};if(2===t.pointsToConnect.length){if(n(t.pointsToConnect[0],t.pointsToConnect[1]))return;return void this.newConnections.push(t)}const i=Ts(t.pointsToConnect);let o=0;for(const e of i)n(e.from,e.to)||this.newConnections.push({pointsToConnect:[e.from,e.to],name:`${t.name}_mst${o++}`,netConnectionName:t.netConnectionName})}getNewSimpleRouteJson(){return{...this.ogSrj,connections:this.newConnections}}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Net To Point Pairs Visualization"};return this.unprocessedConnections.forEach(e=>{e.pointsToConnect.forEach(s=>{t.points.push({x:s.x,y:s.y,color:"red",label:e.name})});const s=e.pointsToConnect.length**2,n=Tt(0),i=new Set;for(let o=0;o<Math.max(s,2*e.pointsToConnect.length);o++){const s=Math.floor(n()*e.pointsToConnect.length),o=Math.floor(n()*e.pointsToConnect.length);i.has(`${s}-${o}`)||(i.add(`${s}-${o}`),t.lines.push({points:[e.pointsToConnect[s],e.pointsToConnect[o]],strokeColor:"rgba(255,0,0,0.25)"}))}}),this.newConnections.forEach(e=>{const s=this.colorMap?.[e.name]||"blue";e.pointsToConnect.forEach(n=>{t.points.push({x:n.x,y:n.y,color:s,label:e.name})});for(let n=0;n<e.pointsToConnect.length-1;n++)for(let i=n+1;i<e.pointsToConnect.length;i++)t.lines.push({points:[e.pointsToConnect[n],e.pointsToConnect[i]],strokeColor:s})}),t}},As=class extends zs{constructor(t,e={}){const s=t.connections.flatMap(t=>t.pointsToConnect),n=new Map;for(const t of s)t.pointId&&n.set(t.pointId,t);const i=s.map(t=>t.pointId).filter(t=>!!t),o=new Ps(i),a=[];for(const e of t.connections)e.isOffBoard?e.pointsToConnect.length>=2&&e.pointsToConnect[0].pointId&&e.pointsToConnect[1].pointId&&o.union(e.pointsToConnect[0].pointId,e.pointsToConnect[1].pointId):a.push(e);super({...t,connections:a},e),this.ogSrj=t,this.colorMap=e,this.connectionPointDsu=o,this.connectionPointMap=n,this.ogSrj=t}connectionPointDsu;connectionPointMap;_findBestConnectionPointsFromDisjointSets(t,e){if(!t.pointId||!e.pointId)return{pointsToConnect:[t,e]};const s=this.connectionPointDsu.getGroup(t.pointId).map(t=>this.connectionPointMap.get(t)),n=this.connectionPointDsu.getGroup(e.pointId).map(t=>this.connectionPointMap.get(t));let i=t,o=e,a=1/0;for(const t of s)for(const e of n){const s=Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));s<a&&(a=s,i=t,o=e)}return{pointsToConnect:[i,o]}}_step(){if(0===this.unprocessedConnections.length)return void(this.solved=!0);const t=this.unprocessedConnections.pop(),e=t.externallyConnectedPointIds??[],s=new Map;e.forEach((t,e)=>t.forEach(t=>s.set(t,e)));const n=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const n=s.get(t.pointId),i=s.get(e.pointId);return void 0!==n&&n===i};if(2===t.pointsToConnect.length){if(n(t.pointsToConnect[0],t.pointsToConnect[1]))return;const e=this._findBestConnectionPointsFromDisjointSets(t.pointsToConnect[0],t.pointsToConnect[1]);return void this.newConnections.push({...t,pointsToConnect:e.pointsToConnect})}const i=Ts(t.pointsToConnect);let o=0;for(const e of i){if(n(e.from,e.to))continue;const s=this._findBestConnectionPointsFromDisjointSets(e.from,e.to);this.newConnections.push({pointsToConnect:s.pointsToConnect,name:`${t.name}_mst${o++}`,netConnectionName:t.netConnectionName})}}},Rs=class{MAX_ITERATIONS=1e5;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};_setupDone=!1;setup(){this._setupDone||(this._setup(),this._setupDone=!0)}_setup(){}step(){if(this._setupDone||this.setup(),!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,console.error(this.error),this.failed=!0,t}!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`,console.error(this.error),this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}getOutput(){return null}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}},Os=1e-9,Ls=(t,e,s)=>Math.max(e,Math.min(s,t)),Ds=(t,e)=>t>e+Os,$s=(t,e)=>t>e-Os,Fs=(t,e)=>t<e-Os,ks=(t,e)=>t<e+Os;function Bs(t,e){return!(t.x+t.width<=e.x+Os||e.x+e.width<=t.x+Os||t.y+t.height<=e.y+Os||e.y+e.height<=t.y+Os)}function Xs(t,e,s){return e>=t.x-Os&&e<=t.x+t.width+Os&&s>=t.y-Os&&s<=t.y+t.height+Os}function Ys(t,e,s){const n=[[s.x,s.y,s.x+s.width,s.y],[s.x+s.width,s.y,s.x+s.width,s.y+s.height],[s.x+s.width,s.y+s.height,s.x,s.y+s.height],[s.x,s.y+s.height,s.x,s.y]];let i=1/0;for(const[s,o,a,r]of n){const n=a-s,h=r-o,c=n*n+h*h;let d=0!==c?((t-s)*n+(e-o)*h)/c:0;d=Ls(d,0,1);const l=s+d*n,u=o+d*h;i=Math.min(i,Math.hypot(t-l,e-u))}return i}function Hs(t,e,s,n){let i=e.x+e.width-t.x;for(const e of s){if(t.y+t.height>e.y+Os&&e.y+e.height>t.y+Os)if($s(e.x,t.x+t.width))i=Math.min(i,e.x-t.x);else if(e.x+e.width>t.x+t.width-Os&&e.x<t.x+t.width+Os)return 0}let o=Math.max(0,i-t.width);if(o<=0)return 0;if(null!=n){const e=t.width,s=t.height;e>=s&&(o=Math.min(o,n*s-e))}return Math.max(0,o)}function Vs(t,e,s,n){let i=e.y+e.height-t.y;for(const e of s){if(t.x+t.width>e.x+Os&&e.x+e.width>t.x+Os)if($s(e.y,t.y+t.height))i=Math.min(i,e.y-t.y);else if(e.y+e.height>t.y+t.height-Os&&e.y<t.y+t.height+Os)return 0}let o=Math.max(0,i-t.height);if(o<=0)return 0;if(null!=n){const e=t.width,s=t.height;s>=e&&(o=Math.min(o,n*e-s))}return Math.max(0,o)}function js(t,e,s,n){let i=e.x;for(const e of s){if(t.y+t.height>e.y+Os&&e.y+e.height>t.y+Os)if(ks(e.x+e.width,t.x))i=Math.max(i,e.x+e.width);else if(e.x<t.x+Os&&e.x+e.width>t.x-Os)return 0}let o=Math.max(0,t.x-i);if(o<=0)return 0;if(null!=n){const e=t.width,s=t.height;e>=s&&(o=Math.min(o,n*s-e))}return Math.max(0,o)}function Zs(t,e,s,n){let i=e.y;for(const e of s){if(t.x+t.width>e.x+Os&&e.x+e.width>t.x+Os)if(ks(e.y+e.height,t.y))i=Math.max(i,e.y+e.height);else if(e.y<t.y+Os&&e.y+e.height>t.y-Os)return 0}let o=Math.max(0,t.y-i);if(o<=0)return 0;if(null!=n){const e=t.width,s=t.height;s>=e&&(o=Math.min(o,n*e-s))}return Math.max(0,o)}function Ws(t){const{startX:e,startY:s,gridSize:n,bounds:i,blockers:o,initialCellRatio:a,maxAspectRatio:r,minReq:h}=t,c=Math.max(1e-9,n*a),d=Math.max(c,h.width),l=Math.max(c,h.height),u=[{ox:0,oy:0},{ox:-d,oy:0},{ox:0,oy:-l},{ox:-d,oy:-l},{ox:-d/2,oy:-l/2}];let p=null,f=0;t:for(const t of u){let n={x:e+t.ox,y:s+t.oy,width:d,height:l};if(Fs(n.x,i.x)||Fs(n.y,i.y)||Ds(n.x+n.width,i.x+i.width)||Ds(n.y+n.height,i.y+i.height))continue;for(const t of o)if(Bs(n,t))continue t;let a=!0;for(;a;){a=!1;const t=Hs(n,i,o,r);t>0&&(n={...n,width:n.width+t},a=!0);const e=Vs(n,i,o,r);e>0&&(n={...n,height:n.height+e},a=!0);const s=js(n,i,o,r);s>0&&(n={x:n.x-s,y:n.y,width:n.width+s,height:n.height},a=!0);const h=Zs(n,i,o,r);h>0&&(n={x:n.x,y:n.y-h,width:n.width,height:n.height+h},a=!0)}if(n.width+Os>=h.width&&n.height+Os>=h.height){const t=n.width*n.height;t>f&&(p=n,f=t)}}return p}function Us(t,e,s,n){const i=Math.max(t,s),o=Math.min(e,n);return o>i+Os?[i,o]:null}function Gs(t,e){if(!Bs(t,e))return[t];const s=Us(t.x,t.x+t.width,e.x,e.x+e.width),n=Us(t.y,t.y+t.height,e.y,e.y+e.height);if(!s||!n)return[t];const[i,o]=s,[a,r]=n,h=[];i>t.x+Os&&h.push({x:t.x,y:t.y,width:i-t.x,height:t.height}),t.x+t.width>o+Os&&h.push({x:o,y:t.y,width:t.x+t.width-o,height:t.height});const c=Math.max(0,o-i);return c>Os&&a>t.y+Os&&h.push({x:i,y:t.y,width:c,height:a-t.y}),c>Os&&t.y+t.height>r+Os&&h.push({x:i,y:r,width:c,height:t.y+t.height-r}),h.filter(t=>t.width>Os&&t.height>Os)}function qs(t){const{x:e,y:s,layerCount:n,obstaclesByLayer:i,placedByLayer:o}=t;for(let t=0;t<n;t++){const n=i[t]??[],a=o[t]??[];if(!(n.some(t=>Xs(t,e,s))||a.some(t=>Xs(t,e,s))))return!1}return!0}function Ks(t){const{x:e,y:s,z:n,layerCount:i,minSpan:o,maxSpan:a,obstaclesByLayer:r,placedByLayer:h}=t,c=t=>![...r[t]??[],...h[t]??[]].some(t=>Xs(t,e,s));let d=n,l=n;for(;d-1>=0&&c(d-1);)d--;for(;l+1<i&&c(l+1);)l++;if("number"==typeof a){const t=Ls(a,1,i);for(;l-d+1>t;)n-d>l-n?d++:l--}const u=[];for(let t=d;t<=l;t++)u.push(t);return u.length>=o?u:[]}function Js(t){const e=Math.max(t.width,t.height);return[e/8,e/16,e/32]}function Qs(t){const{lineStart:e,lineEnd:s,coveringIntervals:n,minSegmentLength:i}=t;if(0===n.length){return[{start:e,end:s,center:(e+s)/2}]}const o=[...n].sort((t,e)=>t.start-e.start),a=[];let r={...o[0]};for(let t=1;t<o.length;t++){const e=o[t];e.start<=r.end+Os?r.end=Math.max(r.end,e.end):(a.push(r),r={...e})}a.push(r);const h=[];if(a[0].start>e+Os){const t=e,s=a[0].start;s-t>=i&&h.push({start:t,end:s,center:(t+s)/2})}for(let t=0;t<a.length-1;t++){const e=a[t].end,s=a[t+1].start;s-e>=i&&h.push({start:e,end:s,center:(e+s)/2})}if(a[a.length-1].end<s-Os){const t=a[a.length-1].end,e=s;e-t>=i&&h.push({start:t,end:e,center:(t+e)/2})}return h}function tn(t){const{bounds:e,minSize:s,layerCount:n,obstaclesByLayer:i,placedByLayer:o,hardPlacedByLayer:a}=t,r=[],h=Math.max(.15*s,3*Os),c=new Set;function d(t,s,h){if(t<e.x+Os||s<e.y+Os||t>e.x+e.width-Os||s>e.y+e.height-Os)return;if(function(t,e){return qs({x:t,y:e,layerCount:n,obstaclesByLayer:i,placedByLayer:o})}(t,s))return;const d=[...i[h]??[],...a[h]??[]],l=Math.min(Ys(t,s,e),...d.length?d.map(e=>Ys(t,s,e)):[1/0]),u=((t,e,s)=>`${s}|${t.toFixed(6)}|${e.toFixed(6)}`)(t,s,h);if(c.has(u))return;c.add(u);const p=Ks({x:t,y:s,z:h,layerCount:n,minSpan:1,maxSpan:void 0,obstaclesByLayer:i,placedByLayer:a});r.push({x:t,y:s,z:h,distance:l,zSpanLen:p.length,isEdgeSeed:!0})}for(let t=0;t<n;t++){const n=[...i[t]??[],...a[t]??[]],o=[{x:e.x+h,y:e.y+h},{x:e.x+e.width-h,y:e.y+h},{x:e.x+h,y:e.y+e.height-h},{x:e.x+e.width-h,y:e.y+e.height-h}];for(const e of o)d(e.x,e.y,t);const r=e.y+h,c=n.filter(t=>t.y<=r&&t.y+t.height>=r).map(t=>({start:Math.max(e.x,t.x),end:Math.min(e.x+e.width,t.x+t.width)})),l=Qs({lineStart:e.x+h,lineEnd:e.x+e.width-h,coveringIntervals:c,minSegmentLength:.5*s});for(const e of l){const n=e.end-e.start;n>=s&&(d(e.center,r,t),n>1.5*s&&(d(e.start+.4*s,r,t),d(e.end-.4*s,r,t)))}const u=e.y+e.height-h,p=n.filter(t=>t.y<=u&&t.y+t.height>=u).map(t=>({start:Math.max(e.x,t.x),end:Math.min(e.x+e.width,t.x+t.width)})),f=Qs({lineStart:e.x+h,lineEnd:e.x+e.width-h,coveringIntervals:p,minSegmentLength:.5*s});for(const e of f){const n=e.end-e.start;n>=s&&(d(e.center,u,t),n>1.5*s&&(d(e.start+.4*s,u,t),d(e.end-.4*s,u,t)))}const g=e.x+h,m=n.filter(t=>t.x<=g&&t.x+t.width>=g).map(t=>({start:Math.max(e.y,t.y),end:Math.min(e.y+e.height,t.y+t.height)})),y=Qs({lineStart:e.y+h,lineEnd:e.y+e.height-h,coveringIntervals:m,minSegmentLength:.5*s});for(const e of y){const n=e.end-e.start;n>=s&&(d(g,e.center,t),n>1.5*s&&(d(g,e.start+.4*s,t),d(g,e.end-.4*s,t)))}const x=e.x+e.width-h,v=n.filter(t=>t.x<=x&&t.x+t.width>=x).map(t=>({start:Math.max(e.y,t.y),end:Math.min(e.y+e.height,t.y+t.height)})),M=Qs({lineStart:e.y+h,lineEnd:e.y+e.height-h,coveringIntervals:v,minSegmentLength:.5*s});for(const e of M){const n=e.end-e.start;n>=s&&(d(x,e.center,t),n>1.5*s&&(d(x,e.start+.4*s,t),d(x,e.end-.4*s,t)))}for(const i of n){const o=i.x-h;if(o>e.x+Os&&o<e.x+e.width-Os){const e=n.filter(t=>t!==i&&t.x<=o&&t.x+t.width>=o).map(t=>({start:Math.max(i.y,t.y),end:Math.min(i.y+i.height,t.y+t.height)})),a=Qs({lineStart:i.y,lineEnd:i.y+i.height,coveringIntervals:e,minSegmentLength:.5*s});for(const e of a)d(o,e.center,t)}const a=i.x+i.width+h;if(a>e.x+Os&&a<e.x+e.width-Os){const e=n.filter(t=>t!==i&&t.x<=a&&t.x+t.width>=a).map(t=>({start:Math.max(i.y,t.y),end:Math.min(i.y+i.height,t.y+t.height)})),o=Qs({lineStart:i.y,lineEnd:i.y+i.height,coveringIntervals:e,minSegmentLength:.5*s});for(const e of o)d(a,e.center,t)}const r=i.y-h;if(r>e.y+Os&&r<e.y+e.height-Os){const e=n.filter(t=>t!==i&&t.y<=r&&t.y+t.height>=r).map(t=>({start:Math.max(i.x,t.x),end:Math.min(i.x+i.width,t.x+t.width)})),o=Qs({lineStart:i.x,lineEnd:i.x+i.width,coveringIntervals:e,minSegmentLength:.5*s});for(const e of o)d(e.center,r,t)}const c=i.y+i.height+h;if(c>e.y+Os&&c<e.y+e.height-Os){const e=n.filter(t=>t!==i&&t.y<=c&&t.y+t.height>=c).map(t=>({start:Math.max(i.x,t.x),end:Math.min(i.x+i.width,t.x+t.width)})),o=Qs({lineStart:i.x,lineEnd:i.x+i.width,coveringIntervals:e,minSegmentLength:.5*s});for(const e of o)d(e.center,c,t)}}}return r.sort((t,e)=>e.zSpanLen-t.zSpanLen||e.distance-t.distance),r}function en(t,e){let s=!1;for(let n=0,i=e.length-1;n<e.length;i=n++){const o=e[n].x,a=e[n].y,r=e[i].x,h=e[i].y;a>t.y!=h>t.y&&t.x<(r-o)*(t.y-a)/(h-a)+o&&(s=!s)}return s}function sn(t){const e=t.toLowerCase();if("top"===e)return-1e6;if("bottom"===e)return 1e6;const s=/^inner(\d+)$/i.exec(e);return s?parseInt(s[1],10)||0:100+e.charCodeAt(0)}function nn(t){const e=function(t){return Array.from(new Set(t)).sort((t,e)=>{const s=sn(t),n=sn(e);return s!==n?s-n:t.localeCompare(e)})}((t.obstacles??[]).flatMap(t=>t.layers??[])),s=Math.max(1,t.layerCount||e.length||1),n=Array.from({length:s},(t,e)=>0===e?"top":e===s-1?"bottom":`inner${e}`),i=[],o=new Set,a=t=>{const e=t.toLowerCase();o.has(e)||(o.add(e),i.push(t))};n.forEach(a),e.forEach(a);const r=i.slice(0,s),h=new Map;return r.forEach((t,e)=>h.set(t.toLowerCase(),e)),i.slice(r.length).forEach(t=>{const e=t.toLowerCase();h.set(e,(t=>{if(r.length<=1)return 0;if("top"===t)return 0;if("bottom"===t)return r.length-1;const e=/^inner(\d+)$/i.exec(t);if(e){if(r.length<=2)return r.length-1;const t=parseInt(e[1],10),s=r.length-2;return Math.min(s,Math.max(1,Number.isFinite(t)?t:1))}return 0})(e))}),{layerNames:r,zIndexByName:h}}function on(t,e){if(t.zLayers?.length)return Array.from(new Set(t.zLayers)).sort((t,e)=>t-e);const s=(t.layers??[]).map(t=>e.get(t.toLowerCase())).filter(t=>"number"==typeof t);return Array.from(new Set(s)).sort((t,e)=>t-e)}function an(t){const e=t.width,s=t.height;return"number"!=typeof e||"number"!=typeof s?null:{x:t.center.x-e/2,y:t.center.y-s/2,width:e,height:s}}function rn(t,e){const{layerNames:s,zIndexByName:n}=nn(t),i=Math.max(1,s.length,t.layerCount||1),o={x:t.bounds.minX,y:t.bounds.minY,width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},a=Array.from({length:i},()=>[]);let r=[];if(t.outline&&t.outline.length>2){r=function(t,e){if(!e||e.length<3)return[];const s=new Set([t.x,t.x+t.width]),n=new Set([t.y,t.y+t.height]);for(const t of e)s.add(t.x),n.add(t.y);const i=Array.from(s).sort((t,e)=>t-e),o=Array.from(n).sort((t,e)=>t-e),a=[];for(let s=0;s<i.length-1;s++)for(let n=0;n<o.length-1;n++){const r=i[s],h=i[s+1],c=o[n],d=o[n+1],l=(r+h)/2,u=(c+d)/2;l>=t.x&&l<=t.x+t.width&&u>=t.y&&u<=t.y+t.height&&(en({x:l,y:u},e)||a.push({x:r,y:c,width:h-r,height:d-c}))}const r=[];a.sort((t,e)=>Math.abs(t.y-e.y)>Os?t.y-e.y:t.x-e.x);let h=null;for(const t of a){if(!h){h=t;continue}const e=Math.abs(h.y-t.y)<Os,s=Math.abs(h.height-t.height)<Os,n=Math.abs(h.x+h.width-t.x)<Os;e&&s&&n?h.width+=t.width:(r.push(h),h=t)}h&&r.push(h),r.sort((t,e)=>Math.abs(t.x-e.x)>Os?t.x-e.x:t.y-e.y);const c=[];h=null;for(const t of r){if(!h){h=t;continue}const e=Math.abs(h.x-t.x)<Os,s=Math.abs(h.width-t.width)<Os,n=Math.abs(h.y+h.height-t.y)<Os;e&&s&&n?h.height+=t.height:(c.push(h),h=t)}return h&&c.push(h),c}(o,t.outline);for(const t of r)for(let e=0;e<i;e++)a[e].push(t)}for(const e of t.obstacles??[]){const t=an(e);if(!t)continue;const s=on(e,n),o=s.filter(t=>t<0||t>=i);if(o.length)throw new Error(`RectDiffSolver: obstacle uses z-layer indices ${o.join(",")} outside 0-${i-1}`);e.zLayers&&0!==e.zLayers.length||!s.length||(e.zLayers=s);for(const e of s)a[e].push(t)}const h=Math.max(.01,t.minTraceWidth||.15),c={gridSizes:Js(o),initialCellRatio:.2,maxAspectRatio:3,minSingle:{width:2*h,height:2*h},minMulti:{width:4*h,height:4*h,minLayers:Math.min(2,Math.max(1,t.layerCount||1))},preferMultiLayer:!0,maxMultiLayerSpan:void 0},d={...c,...e,gridSizes:e.gridSizes??c.gridSizes},l=Array.from({length:i},()=>[]);return{srj:t,layerNames:s,layerCount:i,bounds:o,options:d,obstaclesByLayer:a,boardVoidRects:r,phase:"GRID",gridIndex:0,candidates:[],placed:[],placedByLayer:l,expansionIndex:0,edgeAnalysisDone:!1,totalSeedsThisGrid:0,consumedSeedsThisGrid:0}}function hn(t){const e=Array.from({length:t.layerCount},()=>[]);for(const s of t.placed)if(s.zLayers.length>=t.layerCount)for(const t of s.zLayers)e[t].push(s.rect);return e}function cn(t,e){for(let s=0;s<t.layerCount;s++){const n=t.obstaclesByLayer[s]??[],i=t.placedByLayer[s]??[];if(!(n.some(t=>Xs(t,e.x,e.y))||i.some(t=>Xs(t,e.x,e.y))))return!1}return!0}function dn(t,e){const s=t.placed[e],{rect:n,zLayers:i}=s,o=t.layerCount,a=[],r=[];for(let s=0;s<t.placed.length;s++){if(s===e)continue;const h=t.placed[s];if(h.zLayers.length>=o)continue;const c=h.zLayers.filter(t=>i.includes(t));if(0===c.length)continue;if(!Bs(h.rect,n))continue;const d=Gs(h.rect,n);a.push(s);const l=h.zLayers.filter(t=>!i.includes(t));l.length>0&&r.push({rect:h.rect,zLayers:l});const u=Math.min(t.options.minSingle.width,t.options.minMulti.width),p=Math.min(t.options.minSingle.height,t.options.minMulti.height);for(const t of d)t.width+Os>=u&&t.height+Os>=p&&r.push({rect:t,zLayers:c.slice()})}a.sort((t,e)=>e-t).forEach(e=>{const s=t.placed.splice(e,1)[0];for(const e of s.zLayers){const n=t.placedByLayer[e],i=n.findIndex(t=>t===s.rect);i>=0&&n.splice(i,1)}});for(const e of r){t.placed.push(e);for(const s of e.zLayers)t.placedByLayer[s].push(e.rect)}}function ln(t){const{gridSizes:e,initialCellRatio:s,maxAspectRatio:n,minSingle:i,minMulti:o,preferMultiLayer:a,maxMultiLayerSpan:r}=t.options,h=e[t.gridIndex],c=hn(t);if(0===t.candidates.length&&0===t.consumedSeedsThisGrid&&(t.candidates=function(t){const{bounds:e,gridSize:s,layerCount:n,obstaclesByLayer:i,placedByLayer:o,hardPlacedByLayer:a}=t,r=new Map;for(let t=e.x;t<e.x+e.width;t+=s)for(let h=e.y;h<e.y+e.height;h+=s){if(Math.abs(t-e.x)<Os||Math.abs(h-e.y)<Os||t>e.x+e.width-s-Os||h>e.y+e.height-s-Os)continue;if(qs({x:t,y:h,layerCount:n,obstaclesByLayer:i,placedByLayer:o}))continue;let c=[],d=0;for(let e=0;e<n;e++){const s=Ks({x:t,y:h,z:e,layerCount:n,minSpan:1,maxSpan:void 0,obstaclesByLayer:i,placedByLayer:a});s.length>c.length&&(c=s,d=e)}const l=c.length?c[Math.floor(c.length/2)]:d,u=[...i[l]??[],...a[l]??[]],p=Math.min(Ys(t,h,e),...u.length?u.map(e=>Ys(t,h,e)):[1/0]),f=`${t.toFixed(6)}|${h.toFixed(6)}`,g={x:t,y:h,z:l,distance:p,zSpanLen:c.length},m=r.get(f);(!m||g.zSpanLen>(m.zSpanLen??0)||g.zSpanLen===m.zSpanLen&&g.distance>m.distance)&&r.set(f,g)}const h=Array.from(r.values());return h.sort((t,e)=>e.zSpanLen-t.zSpanLen||e.distance-t.distance),h}({bounds:t.bounds,gridSize:h,layerCount:t.layerCount,obstaclesByLayer:t.obstaclesByLayer,placedByLayer:t.placedByLayer,hardPlacedByLayer:c}),t.totalSeedsThisGrid=t.candidates.length,t.consumedSeedsThisGrid=0),0===t.candidates.length){if(t.gridIndex+1<e.length)return t.gridIndex+=1,t.totalSeedsThisGrid=0,void(t.consumedSeedsThisGrid=0);if(!t.edgeAnalysisDone){const e=Math.min(i.width,i.height);return t.candidates=tn({bounds:t.bounds,minSize:e,layerCount:t.layerCount,obstaclesByLayer:t.obstaclesByLayer,placedByLayer:t.placedByLayer,hardPlacedByLayer:c}),t.edgeAnalysisDone=!0,t.totalSeedsThisGrid=t.candidates.length,void(t.consumedSeedsThisGrid=0)}return t.phase="EXPANSION",void(t.expansionIndex=0)}const d=t.candidates.shift();t.consumedSeedsThisGrid+=1;const l=Ks({x:d.x,y:d.y,z:d.z,layerCount:t.layerCount,minSpan:o.minLayers,maxSpan:r,obstaclesByLayer:t.obstaclesByLayer,placedByLayer:c}),u=[];l.length>=o.minLayers&&u.push({kind:"multi",layers:l,minReq:{width:o.width,height:o.height}}),u.push({kind:"single",layers:[d.z],minReq:{width:i.width,height:i.height}});const p=a?u:u.reverse();for(const e of p){const i=[];for(const s of e.layers)t.obstaclesByLayer[s]&&i.push(...t.obstaclesByLayer[s]),c[s]&&i.push(...c[s]);const o=Ws({startX:d.x,startY:d.y,gridSize:h,bounds:t.bounds,blockers:i,initialCellRatio:s,maxAspectRatio:n,minReq:e.minReq});if(!o)continue;const a={rect:o,zLayers:[...e.layers]},r=t.placed.push(a)-1;for(const s of e.layers)t.placedByLayer[s].push(o);return dn(t,r),void(t.candidates=t.candidates.filter(e=>!cn(t,{x:e.x,y:e.y})))}}var un=class extends Rs{srj;gridOptions;state;_meshNodes=[];constructor(t){super(),this.srj=t.simpleRouteJson,this.gridOptions=t.gridOptions??{}}_setup(){this.state=rn(this.srj,this.gridOptions),this.stats={phase:this.state.phase,gridIndex:this.state.gridIndex}}_step(){if("GRID"===this.state.phase)ln(this.state);else if("EXPANSION"===this.state.phase)!function(t){if(t.expansionIndex>=t.placed.length)return void(t.phase="GAP_FILL");const e=t.expansionIndex,s=t.placed[e],n=t.options.gridSizes[t.options.gridSizes.length-1],i=hn(t),o=[];for(const e of s.zLayers)o.push(...t.obstaclesByLayer[e]??[]),o.push(...i[e]??[]);const a=s.rect,r=Ws({startX:s.rect.x+s.rect.width/2,startY:s.rect.y+s.rect.height/2,gridSize:n,bounds:t.bounds,blockers:o,initialCellRatio:0,maxAspectRatio:null,minReq:{width:s.rect.width,height:s.rect.height}});if(r){t.placed[e]={rect:r,zLayers:s.zLayers};for(const e of s.zLayers){const s=t.placedByLayer[e],n=s.findIndex(t=>t===a);n>=0&&(s[n]=r)}dn(t,e)}t.expansionIndex+=1}(this.state);else if("GAP_FILL"===this.state.phase)this.state.phase="DONE";else if("DONE"===this.state.phase){if(!this.solved){const t=function(t){const e=t.placed.map(t=>({minX:t.rect.x,minY:t.rect.y,maxX:t.rect.x+t.rect.width,maxY:t.rect.y+t.rect.height,zLayers:[...t.zLayers].sort((t,e)=>t-e)})),s=new Map;t.obstaclesByLayer.forEach((t,e)=>{for(const n of t){const t=s.get(n)??[];t.push(e),s.set(n,t)}});const n=new Set(t.boardVoidRects||[]);for(const[t,i]of s.entries())n.has(t)||e.push({minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height,zLayers:i.sort((t,e)=>t-e),isObstacle:!0});return e}(this.state);this._meshNodes=function(t){let e=0;const s=[];for(const n of t){const t=Math.max(0,n.maxX-n.minX),i=Math.max(0,n.maxY-n.minY);t<=0||i<=0||0===n.zLayers.length||s.push({capacityMeshNodeId:"cmn_"+e++,center:{x:(n.minX+n.maxX)/2,y:(n.minY+n.maxY)/2},width:t,height:i,layer:"top",availableZ:n.zLayers.slice(),_containsObstacle:n.isObstacle,_containsTarget:n.isObstacle})}return s}(t),this.solved=!0}return}this.stats.phase=this.state.phase,this.stats.gridIndex=this.state.gridIndex,this.stats.placed=this.state.placed.length}computeProgress(){return this.solved||"DONE"===this.state.phase?1:function(t){const e=t.options.gridSizes.length;if("GRID"===t.phase){const s=t.gridIndex/(e+1),n=Math.max(1,t.totalSeedsThisGrid),i=n?t.consumedSeedsThisGrid/n:1;return Math.min(.999,s+i*(1/(e+1)))}if("EXPANSION"===t.phase){const s=e/(e+1),n=Math.max(1,t.placed.length),i=n?t.expansionIndex/n:1;return Math.min(.999,s+i*(1/(e+1)))}return 1}(this.state)}getOutput(){return{meshNodes:this._meshNodes}}getCoverage(t=.05){return function({sampleResolution:t=.1},e){const{bounds:s,layerCount:n,obstaclesByLayer:i,placedByLayer:o}=e;let a=0,r=0;for(let e=0;e<n;e++){const n=[...i[e]??[],...o[e]??[]];for(let e=s.x;e<=s.x+s.width;e+=t)for(let i=s.y;i<=s.y+s.height;i+=t)a++,n.some(t=>e>=t.x&&e<=t.x+t.width&&i>=t.y&&i<=t.y+t.height)&&r++}return a>0?r/a:1}({sampleResolution:t},{bounds:this.state.bounds,layerCount:this.state.layerCount,obstaclesByLayer:this.state.obstaclesByLayer,placedByLayer:this.state.placedByLayer})}getUncoveredPoints(t=.05){return function({sampleResolution:t=.05},e){const{bounds:s,layerCount:n,obstaclesByLayer:i,placedByLayer:o}=e,a=[];for(let e=0;e<n;e++){const n=[...i[e]??[],...o[e]??[]];for(let i=s.x;i<=s.x+s.width;i+=t)for(let o=s.y;o<=s.y+s.height;o+=t)n.some(t=>i>=t.x&&i<=t.x+t.width&&o>=t.y&&o<=t.y+t.height)||a.push({x:i,y:o,z:e})}return a}({sampleResolution:t},{bounds:this.state.bounds,layerCount:this.state.layerCount,obstaclesByLayer:this.state.obstaclesByLayer,placedByLayer:this.state.placedByLayer})}getColorForZLayer(t){const e=[{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 e[Math.min(...t)%e.length]}visualize(){const t=[],e=[],s=[],n=this.srj.bounds.minX,i=this.srj.bounds.maxX,o=this.srj.bounds.minY,a=this.srj.bounds.maxY;this.srj.outline&&this.srj.outline.length>1?s.push({points:[...this.srj.outline,this.srj.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):t.push({center:{x:(n+i)/2,y:(o+a)/2},width:i-n,height:a-o,fill:"none",stroke:"#111827",label:"board"});for(const e of this.srj.obstacles??[])"rect"!==e.type&&"oval"!==e.type||t.push({center:{x:e.center.x,y:e.center.y},width:e.width,height:e.height,fill:"#fee2e2",stroke:"#ef4444",layer:"obstacle",label:"obstacle"});if(this.state?.boardVoidRects){let e=null;if(this.srj.outline&&this.srj.outline.length>0){const t=this.srj.outline.map(t=>t.x),s=this.srj.outline.map(t=>t.y),n=Math.min(...t),i=Math.min(...s);e={x:n,y:i,width:Math.max(...t)-n,height:Math.max(...s)-i}}for(const s of this.state.boardVoidRects)e&&!Bs(s,e)||t.push({center:{x:s.x+s.width/2,y:s.y+s.height/2},width:s.width,height:s.height,fill:"rgba(0, 0, 0, 0.5)",stroke:"none",label:"void"})}if(this.state?.candidates?.length)for(const t of this.state.candidates)e.push({x:t.x,y:t.y,fill:"#9333ea",stroke:"#6b21a8",label:`z:${t.z}`});if(this.state?.placed?.length)for(const e of this.state.placed){const s=this.getColorForZLayer(e.zLayers);t.push({center:{x:e.rect.x+e.rect.width/2,y:e.rect.y+e.rect.height/2},width:e.rect.width,height:e.rect.height,fill:s.fill,stroke:s.stroke,label:`free\nz:${e.zLayers.join(",")}`})}return{title:`RectDiff (${this.state?.phase??"init"})`,coordinateSystem:"cartesian",rects:t,points:e,lines:s}}};function pn(t,e,s=0,n=t.length-1,i=gn){for(;n>s;){if(n-s>600){const o=n-s+1,a=e-s+1,r=Math.log(o),h=.5*Math.exp(2*r/3),c=.5*Math.sqrt(r*h*(o-h)/o)*(a-o/2<0?-1:1);pn(t,e,Math.max(s,Math.floor(e-a*h/o+c)),Math.min(n,Math.floor(e+(o-a)*h/o+c)),i)}const o=t[e];let a=s,r=n;for(fn(t,s,e),i(t[n],o)>0&&fn(t,s,n);a<r;){for(fn(t,a,r),a++,r--;i(t[a],o)<0;)a++;for(;i(t[r],o)>0;)r--}0===i(t[s],o)?fn(t,s,r):(r++,fn(t,r,n)),r<=e&&(s=r+1),e<=r&&(n=r-1)}}function fn(t,e,s){const n=t[e];t[e]=t[s],t[s]=n}function gn(t,e){return t<e?-1:t>e?1:0}var mn=class{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(.4*this._maxEntries)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const s=[];if(!En(t,e))return s;const n=this.toBBox,i=[];for(;e;){for(let o=0;o<e.children.length;o++){const a=e.children[o],r=e.leaf?n(a):a;En(t,r)&&(e.leaf?s.push(a):_n(t,r)?this._all(a,s):i.push(a))}e=i.pop()}return s}collides(t){let e=this.data;if(!En(t,e))return!1;const s=[];for(;e;){for(let n=0;n<e.children.length;n++){const i=e.children[n],o=e.leaf?this.toBBox(i):i;if(En(t,o)){if(e.leaf||_n(t,o))return!0;s.push(i)}}e=s.pop()}return!1}load(t){if(!t||!t.length)return this;if(t.length<this._minEntries){for(let e=0;e<t.length;e++)this.insert(t[e]);return this}let e=this._build(t.slice(),0,t.length-1,0);if(this.data.children.length)if(this.data.height===e.height)this._splitRoot(this.data,e);else{if(this.data.height<e.height){const t=this.data;this.data=e,e=t}this._insert(e,this.data.height-e.height-1,!0)}else this.data=e;return this}insert(t){return t&&this._insert(t,this.data.height-1),this}clear(){return this.data=Tn([]),this}remove(t,e){if(!t)return this;let s=this.data;const n=this.toBBox(t),i=[],o=[];let a,r,h;for(;s||i.length;){if(s||(s=i.pop(),r=i[i.length-1],a=o.pop(),h=!0),s.leaf){const n=yn(t,s.children,e);if(-1!==n)return s.children.splice(n,1),i.push(s),this._condense(i),this}h||s.leaf||!_n(s,n)?r?(a++,s=r.children[a],h=!1):s=null:(i.push(s),o.push(a),a=0,r=s,s=s.children[0])}return this}toBBox(t){return t}compareMinX(t,e){return t.minX-e.minX}compareMinY(t,e){return t.minY-e.minY}toJSON(){return this.data}fromJSON(t){return this.data=t,this}_all(t,e){const s=[];for(;t;)t.leaf?e.push(...t.children):s.push(...t.children),t=s.pop();return e}_build(t,e,s,n){const i=s-e+1;let o,a=this._maxEntries;if(i<=a)return o=Tn(t.slice(e,s+1)),xn(o,this.toBBox),o;n||(n=Math.ceil(Math.log(i)/Math.log(a)),a=Math.ceil(i/Math.pow(a,n-1))),o=Tn([]),o.leaf=!1,o.height=n;const r=Math.ceil(i/a),h=r*Math.ceil(Math.sqrt(a));wn(t,e,s,h,this.compareMinX);for(let i=e;i<=s;i+=h){const e=Math.min(i+h-1,s);wn(t,i,e,r,this.compareMinY);for(let s=i;s<=e;s+=r){const i=Math.min(s+r-1,e);o.children.push(this._build(t,s,i,n-1))}}return xn(o,this.toBBox),o}_chooseSubtree(t,e,s,n){for(;n.push(e),!e.leaf&&n.length-1!==s;){let s,n=1/0,i=1/0;for(let o=0;o<e.children.length;o++){const a=e.children[o],r=Nn(a),h=Pn(t,a)-r;h<i?(i=h,n=r<n?r:n,s=a):h===i&&r<n&&(n=r,s=a)}e=s||e.children[0]}return e}_insert(t,e,s){const n=s?t:this.toBBox(t),i=[],o=this._chooseSubtree(n,this.data,e,i);for(o.children.push(t),Mn(o,n);e>=0&&i[e].children.length>this._maxEntries;)this._split(i,e),e--;this._adjustParentBBoxes(n,i,e)}_split(t,e){const s=t[e],n=s.children.length,i=this._minEntries;this._chooseSplitAxis(s,i,n);const o=this._chooseSplitIndex(s,i,n),a=Tn(s.children.splice(o,s.children.length-o));a.height=s.height,a.leaf=s.leaf,xn(s,this.toBBox),xn(a,this.toBBox),e?t[e-1].children.push(a):this._splitRoot(s,a)}_splitRoot(t,e){this.data=Tn([t,e]),this.data.height=t.height+1,this.data.leaf=!1,xn(this.data,this.toBBox)}_chooseSplitIndex(t,e,s){let n,i=1/0,o=1/0;for(let a=e;a<=s-e;a++){const e=vn(t,0,a,this.toBBox),r=vn(t,a,s,this.toBBox),h=Cn(e,r),c=Nn(e)+Nn(r);h<i?(i=h,n=a,o=c<o?c:o):h===i&&c<o&&(o=c,n=a)}return n||s-e}_chooseSplitAxis(t,e,s){const n=t.leaf?this.compareMinX:Sn,i=t.leaf?this.compareMinY:bn;this._allDistMargin(t,e,s,n)<this._allDistMargin(t,e,s,i)&&t.children.sort(n)}_allDistMargin(t,e,s,n){t.children.sort(n);const i=this.toBBox,o=vn(t,0,e,i),a=vn(t,s-e,s,i);let r=In(o)+In(a);for(let n=e;n<s-e;n++){const e=t.children[n];Mn(o,t.leaf?i(e):e),r+=In(o)}for(let n=s-e-1;n>=e;n--){const e=t.children[n];Mn(a,t.leaf?i(e):e),r+=In(a)}return r}_adjustParentBBoxes(t,e,s){for(let n=s;n>=0;n--)Mn(e[n],t)}_condense(t){for(let e,s=t.length-1;s>=0;s--)0===t[s].children.length?s>0?(e=t[s-1].children,e.splice(e.indexOf(t[s]),1)):this.clear():xn(t[s],this.toBBox)}};function yn(t,e,s){if(!s)return e.indexOf(t);for(let n=0;n<e.length;n++)if(s(t,e[n]))return n;return-1}function xn(t,e){vn(t,0,t.children.length,e,t)}function vn(t,e,s,n,i){i||(i=Tn(null)),i.minX=1/0,i.minY=1/0,i.maxX=-1/0,i.maxY=-1/0;for(let o=e;o<s;o++){const e=t.children[o];Mn(i,t.leaf?n(e):e)}return i}function Mn(t,e){return t.minX=Math.min(t.minX,e.minX),t.minY=Math.min(t.minY,e.minY),t.maxX=Math.max(t.maxX,e.maxX),t.maxY=Math.max(t.maxY,e.maxY),t}function Sn(t,e){return t.minX-e.minX}function bn(t,e){return t.minY-e.minY}function Nn(t){return(t.maxX-t.minX)*(t.maxY-t.minY)}function In(t){return t.maxX-t.minX+(t.maxY-t.minY)}function Pn(t,e){return(Math.max(e.maxX,t.maxX)-Math.min(e.minX,t.minX))*(Math.max(e.maxY,t.maxY)-Math.min(e.minY,t.minY))}function Cn(t,e){const s=Math.max(t.minX,e.minX),n=Math.max(t.minY,e.minY),i=Math.min(t.maxX,e.maxX),o=Math.min(t.maxY,e.maxY);return Math.max(0,i-s)*Math.max(0,o-n)}function _n(t,e){return t.minX<=e.minX&&t.minY<=e.minY&&e.maxX<=t.maxX&&e.maxY<=t.maxY}function En(t,e){return e.minX<=t.maxX&&e.minY<=t.maxY&&e.maxX>=t.minX&&e.maxY>=t.minY}function Tn(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function wn(t,e,s,n,i){const o=[e,s];for(;o.length;){if((s=o.pop())-(e=o.pop())<=n)continue;const a=e+Math.ceil((s-e)/n/2)*n;pn(t,a,e,s,i),o.push(e,a,a,s)}}var zn=class{tree;constructor(t=9){this.tree=new mn(t)}insert(t,e,s,n,i){this.tree.insert({minX:e,minY:s,maxX:n,maxY:i,data:t})}bulkLoad(t){const e=t.map(({item:t,minX:e,minY:s,maxX:n,maxY:i})=>({minX:e,minY:s,maxX:n,maxY:i,data:t}));this.tree.load(e)}search(t,e,s,n){return this.tree.search({minX:t,minY:e,maxX:s,maxY:n}).map(t=>t.data)}clear(){this.tree.clear()}},An=class{constructor(){this.ids=[],this.values=[],this.length=0}clear(){this.length=0}push(t,e){let s=this.length++;for(;s>0;){const t=s-1>>1,n=this.values[t];if(e>=n)break;this.ids[s]=this.ids[t],this.values[s]=n,s=t}this.ids[s]=t,this.values[s]=e}pop(){if(0===this.length)return;const t=this.ids,e=this.values,s=t[0],n=--this.length;if(n>0){const s=t[n],i=e[n];let o=0;const a=n>>1;for(;o<a;){const s=1+(o<<1),a=s+1,r=s+(+(a<n)&+(e[a]<e[s]));if(e[r]>=i)break;t[o]=t[r],e[o]=e[r],o=r}t[o]=s,e[o]=i}return s}peek(){return this.length>0?this.ids[0]:void 0}peekValue(){return this.length>0?this.values[0]:void 0}shrink(){this.ids.length=this.values.length=this.length}},Rn=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],On=class t{static from(e,s=0){if(s%8!=0)throw new Error("byteOffset must be 8-byte aligned.");if(!e||void 0===e.byteLength||e.buffer)throw new Error("Data must be an instance of ArrayBuffer or SharedArrayBuffer.");const[n,i]=new Uint8Array(e,s+0,2);if(251!==n)throw new Error("Data does not appear to be in a Flatbush format.");const o=i>>4;if(3!==o)throw new Error(`Got v${o} data when expected v3.`);const a=Rn[15&i];if(!a)throw new Error("Unrecognized array type.");const[r]=new Uint16Array(e,s+2,1),[h]=new Uint32Array(e,s+4,1);return new t(h,r,a,void 0,e,s)}constructor(t,e=16,s=Float64Array,n=ArrayBuffer,i,o=0){if(void 0===t)throw new Error("Missing required argument: numItems.");if(isNaN(t)||t<=0)throw new Error(`Unexpected numItems value: ${t}.`);this.numItems=+t,this.nodeSize=Math.min(Math.max(+e,2),65535),this.byteOffset=o;let a=t,r=a;this._levelBounds=[4*a];do{a=Math.ceil(a/this.nodeSize),r+=a,this._levelBounds.push(4*r)}while(1!==a);this.ArrayType=s,this.IndexArrayType=r<16384?Uint16Array:Uint32Array;const h=Rn.indexOf(s),c=4*r*s.BYTES_PER_ELEMENT;if(h<0)throw new Error(`Unexpected typed array class: ${s}.`);if(i)this.data=i,this._boxes=new s(i,o+8,4*r),this._indices=new this.IndexArrayType(i,o+8+c,r),this._pos=4*r,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 i=this.data=new n(8+c+r*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new s(i,8,4*r),this._indices=new this.IndexArrayType(i,8+c,r),this._pos=0,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,new Uint8Array(i,0,2).set([251,48+h]),new Uint16Array(i,2,1)[0]=e,new Uint32Array(i,4,1)[0]=t}this._queue=new An}add(t,e,s=t,n=e){const i=this._pos>>2,o=this._boxes;return this._indices[i]=i,o[this._pos++]=t,o[this._pos++]=e,o[this._pos++]=s,o[this._pos++]=n,t<this.minX&&(this.minX=t),e<this.minY&&(this.minY=e),s>this.maxX&&(this.maxX=s),n>this.maxY&&(this.maxY=n),i}finish(){if(this._pos>>2!==this.numItems)throw new Error(`Added ${this._pos>>2} items when expected ${this.numItems}.`);const t=this._boxes;if(this.numItems<=this.nodeSize)return t[this._pos++]=this.minX,t[this._pos++]=this.minY,t[this._pos++]=this.maxX,void(t[this._pos++]=this.maxY);const e=this.maxX-this.minX||1,s=this.maxY-this.minY||1,n=new Uint32Array(this.numItems);for(let i=0,o=0;i<this.numItems;i++){const a=t[o++],r=t[o++],h=t[o++],c=t[o++],d=Math.floor(65535*((a+h)/2-this.minX)/e),l=Math.floor(65535*((r+c)/2-this.minY)/s);n[i]=Fn(d,l)}Dn(n,t,this._indices,0,this.numItems-1,this.nodeSize);for(let e=0,s=0;e<this._levelBounds.length-1;e++){const n=this._levelBounds[e];for(;s<n;){const e=s;let i=t[s++],o=t[s++],a=t[s++],r=t[s++];for(let e=1;e<this.nodeSize&&s<n;e++)i=Math.min(i,t[s++]),o=Math.min(o,t[s++]),a=Math.max(a,t[s++]),r=Math.max(r,t[s++]);this._indices[this._pos>>2]=e,t[this._pos++]=i,t[this._pos++]=o,t[this._pos++]=a,t[this._pos++]=r}}}search(t,e,s,n,i){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let o=this._boxes.length-4;const a=[],r=[];for(;void 0!==o;){const h=Math.min(o+4*this.nodeSize,Ln(o,this._levelBounds));for(let c=o;c<h;c+=4){const h=this._boxes[c];if(s<h)continue;const d=this._boxes[c+1];if(n<d)continue;const l=this._boxes[c+2];if(t>l)continue;const u=this._boxes[c+3];if(e>u)continue;const p=0|this._indices[c>>2];o>=4*this.numItems?a.push(p):(void 0===i||i(p,h,d,l,u))&&r.push(p)}o=a.pop()}return r}neighbors(t,e,s=1/0,n=1/0,i){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let o=this._boxes.length-4;const a=this._queue,r=[],h=n*n;t:for(;void 0!==o;){const n=Math.min(o+4*this.nodeSize,Ln(o,this._levelBounds));for(let s=o;s<n;s+=4){const n=0|this._indices[s>>2],r=this._boxes[s],c=this._boxes[s+1],d=this._boxes[s+2],l=this._boxes[s+3],u=t<r?r-t:t>d?t-d:0,p=e<c?c-e:e>l?e-l:0,f=u*u+p*p;f>h||(o>=4*this.numItems?a.push(n<<1,f):(void 0===i||i(n))&&a.push(1+(n<<1),f))}for(;a.length&&1&a.peek();){if(a.peekValue()>h)break t;if(r.push(a.pop()>>1),r.length===s)break t}o=a.length?a.pop()>>1:void 0}return a.clear(),r}};function Ln(t,e){let s=0,n=e.length-1;for(;s<n;){const i=s+n>>1;e[i]>t?n=i:s=i+1}return e[s]}function Dn(t,e,s,n,i,o){if(Math.floor(n/o)>=Math.floor(i/o))return;const a=t[n],r=t[n+i>>1],h=t[i];let c=h;const d=Math.max(a,r);h>d?c=d:d===a?c=Math.max(r,h):d===r&&(c=Math.max(a,h));let l=n-1,u=i+1;for(;;){do{l++}while(t[l]<c);do{u--}while(t[u]>c);if(l>=u)break;$n(t,e,s,l,u)}Dn(t,e,s,n,u,o),Dn(t,e,s,u+1,i,o)}function $n(t,e,s,n,i){const o=t[n];t[n]=t[i],t[i]=o;const a=4*n,r=4*i,h=e[a],c=e[a+1],d=e[a+2],l=e[a+3];e[a]=e[r],e[a+1]=e[r+1],e[a+2]=e[r+2],e[a+3]=e[r+3],e[r]=h,e[r+1]=c,e[r+2]=d,e[r+3]=l;const u=s[n];s[n]=s[i],s[i]=u}function Fn(t,e){let s=t^e,n=65535^s,i=65535^(t|e),o=t&(65535^e),a=s|n>>1,r=s>>1^s,h=i>>1^n&o>>1^i,c=s&i>>1^o>>1^o;s=a,n=r,i=h,o=c,a=s&s>>2^n&n>>2,r=s&n>>2^n&(s^n)>>2,h^=s&i>>2^n&o>>2,c^=n&i>>2^(s^n)&o>>2,s=a,n=r,i=h,o=c,a=s&s>>4^n&n>>4,r=s&n>>4^n&(s^n)>>4,h^=s&i>>4^n&o>>4,c^=n&i>>4^(s^n)&o>>4,s=a,n=r,i=h,o=c,h^=s&i>>8^n&o>>8,c^=n&i>>8^(s^n)&o>>8,s=h^h>>1,n=c^c>>1;let d=t^e,l=n|65535^(d|s);return d=16711935&(d|d<<8),d=252645135&(d|d<<4),d=858993459&(d|d<<2),d=1431655765&(d|d<<1),l=16711935&(l|l<<8),l=252645135&(l|l<<4),l=858993459&(l|l<<2),l=1431655765&(l|l<<1),(l<<1|d)>>>0}var kn=class{index;items=[];currentIndex=0;capacity;constructor(t){this.capacity=Math.max(1,t),this.index=new On(this.capacity)}insert(t,e,s,n,i){if(this.currentIndex>=this.index.numItems)throw new Error("Exceeded initial capacity");this.items[this.currentIndex]=t,this.index.add(e,s,n,i),this.currentIndex++}finish(){this.index.finish()}search(t,e,s,n){return this.index.search(t,e,s,n).map(t=>this.items[t]||null).filter(Boolean)}clear(){this.items=[],this.currentIndex=0,this.index=new On(this.capacity)}},Bn=class{idx;storage=[];constructor(t="native",e=[]){"flatbush"===t?0===e.length?(this.idx=new zn,t="rbush"):this.idx=new kn(e.length):this.idx="rbush"===t?new zn:new class{shi=new Xn(e);insert(t){}search(t,e,s,n){const i=(t+s)/2,o=(e+n)/2,a=s-t,r=n-e;return this.shi.getNodesInArea(i,o,a,r)}clear(){}},e.forEach(t=>this.insert(t)),"flatbush"===t&&e.length>0&&this.idx.finish?.()}insert(t){this.storage.push(t),this.idx.insert(t,t.center.x-t.width/2,t.center.y-t.height/2,t.center.x+t.width/2,t.center.y+t.height/2)}search(t){return this.idx.search(t.minX,t.minY,t.maxX,t.maxY)}searchArea(t,e,s,n){return this.search({minX:t-s/2,minY:e-n/2,maxX:t+s/2,maxY:e+n/2})}},Xn=class{constructor(t){this.obstacles=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const s=t[e],n=s.center.x-s.width/2,i=s.center.y-s.height/2,o=s.center.x+s.width/2,a=s.center.y+s.height/2;for(let t=n;t<=o;t+=this.CELL_SIZE)for(let n=i;n<=a;n+=this.CELL_SIZE){const i=this.getBucketKey(t,n),o=this.buckets.get(i);o?o.push([s,e]):this.buckets.set(i,[[s,e]])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,s,n){const i=[],o=new Set,a=e-n/2,r=t+s/2,h=e+n/2;for(let e=t-s/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const s=this.getBucketKey(e,t),n=this.buckets.get(s)||[];for(const t of n)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},Yn=t=>({minX:Math.min(t[0].x,t[1].x),maxX:Math.max(t[0].x,t[1].x),minY:Math.min(t[0].y,t[1].y),maxY:Math.max(t[0].y,t[1].y)});function Hn(t,e){const s=t.x-e.x,n=t.y-e.y;return s*s+n*n}function Vn(t,e,s){const n=Hn(e,s);if(0===n)return Hn(t,e);let i=((t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y))/n;i=Math.max(0,Math.min(1,i));return Hn(t,{x:e.x+i*(s.x-e.x),y:e.y+i*(s.y-e.y)})}function jn(t,e,s,n){if(at(t,e,s,n))return 0;const i={x:t.x,y:t.y},o={x:e.x,y:e.y},a={x:s.x,y:s.y},r={x:n.x,y:n.y};return Math.min(Vn(i,a,r),Vn(o,a,r),Vn(a,i,o),Vn(r,i,o))}var Zn=class{segmentBuckets;viaBuckets;routes;CELL_SIZE;constructor(t,e=1){this.segmentBuckets=new Map,this.viaBuckets=new Map,this.routes=new Map,this.CELL_SIZE=e;for(const e of t)if(e&&e.connectionName)if(this.routes.has(e.connectionName))console.warn(`Skipping duplicate route connectionName: ${e.connectionName}`);else{if(this.routes.set(e.connectionName,e),e.route&&e.route.length>=2)for(let t=0;t<e.route.length-1;t++){const s=e.route[t],n=e.route[t+1];if(s.x===n.x&&s.y===n.y)continue;const i=[s,n],o=Yn(i),a={segmentId:`${e.connectionName}-seg-${t}`,segment:i,parentRoute:e},r=Math.floor(o.minX/this.CELL_SIZE),h=Math.floor((o.maxX+1e-9)/this.CELL_SIZE),c=Math.floor(o.minY/this.CELL_SIZE),d=Math.floor((o.maxY+1e-9)/this.CELL_SIZE);for(let t=r;t<=h;t++)for(let e=c;e<=d;e++){const s=`${t}x${e}`;let n=this.segmentBuckets.get(s);n||(n=[],this.segmentBuckets.set(s,n)),n.push(a)}}if(e.vias&&e.vias.length>0)for(let t=0;t<e.vias.length;t++){const s=e.vias[t];if(null==s)continue;const n={viaId:`${e.connectionName}-via-${t}`,x:s.x,y:s.y,parentRoute:e},i=`${Math.floor(s.x/this.CELL_SIZE)}x${Math.floor(s.y/this.CELL_SIZE)}`;let o=this.viaBuckets.get(i);o||(o=[],this.viaBuckets.set(i,o)),o.push(n)}}else console.warn("Skipping route with missing data:",e)}getConflictingRoutesForSegment(t,e,s){const n=Yn([t,e]),i=n.minX-s,o=n.minY-s,a=n.maxX+s,r=n.maxY+s,h=Math.floor(i/this.CELL_SIZE),c=Math.floor((a+1e-9)/this.CELL_SIZE),d=Math.floor(o/this.CELL_SIZE),l=Math.floor((r+1e-9)/this.CELL_SIZE),u=new Map,p=new Set,f=new Set,g={x:t.x,y:t.y},m={x:e.x,y:e.y};for(let n=h;n<=c;n++)for(let i=d;i<=l;i++){const o=`${n}x${i}`,a=this.segmentBuckets.get(o);if(a)for(const n of a){if(p.has(n.segmentId))continue;p.add(n.segmentId);const i=n.parentRoute,[o,a]=n.segment,r=s+i.traceThickness/2,h=r*r,c=jn(t,e,o,a);if(c<h){const t=i.connectionName,e=u.get(t);(!e||c<e.minDistSq)&&u.set(t,{route:i,minDistSq:c})}}const r=this.viaBuckets.get(o);if(r)for(const t of r){if(f.has(t.viaId))continue;f.add(t.viaId);const e=t.parentRoute,n={x:t.x,y:t.y},i=s+e.viaDiameter/2,o=i*i,a=Vn(n,g,m);if(a<o){const t=e.connectionName,s=u.get(t);(!s||a<s.minDistSq)&&u.set(t,{route:e,minDistSq:a})}}}const y=[];for(const t of u.values())y.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return y}getConflictingRoutesNearPoint(t,e){const s=t.x-e,n=t.y-e,i=t.x+e,o=t.y+e,a=Math.floor(s/this.CELL_SIZE),r=Math.floor((i+1e-9)/this.CELL_SIZE),h=Math.floor(n/this.CELL_SIZE),c=Math.floor((o+1e-9)/this.CELL_SIZE),d=new Map,l=new Set,u=new Set;for(let s=a;s<=r;s++)for(let n=h;n<=c;n++){const i=`${s}x${n}`,o=this.segmentBuckets.get(i);if(o)for(const s of o){if(l.has(s.segmentId))continue;l.add(s.segmentId);const n=s.parentRoute,i={x:s.segment[0].x,y:s.segment[0].y},o={x:s.segment[1].x,y:s.segment[1].y},a=e+n.traceThickness/2,r=a*a,h=Vn(t,i,o);if(h<r){const t=n.connectionName,e=d.get(t);(!e||h<e.minDistSq)&&d.set(t,{route:n,minDistSq:h})}}const a=this.viaBuckets.get(i);if(a)for(const s of a){if(u.has(s.viaId))continue;u.add(s.viaId);const n=s.parentRoute,i={x:s.x,y:s.y},o=e+n.viaDiameter/2,a=o*o,r=Hn(t,i);if(r<a){const t=n.connectionName,e=d.get(t);(!e||r<e.minDistSq)&&d.set(t,{route:n,minDistSq:r})}}}const p=[];for(const t of d.values())p.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return p}},Wn=class extends e{obstacleSHI;hdRouteSHI;unsimplifiedRoute;routeSections;currentSectionIndex;TRACE_THICKNESS=.15;OBSTACLE_MARGIN=.1;constructor(t){super(),this.currentSectionIndex=0,this.obstacleSHI=t.obstacleSHI,this.hdRouteSHI=t.hdRouteSHI,this.unsimplifiedRoute=t.unsimplifiedRoute,this.routeSections=this.breakRouteIntoSections(this.unsimplifiedRoute)}breakRouteIntoSections(t){const e=[],s=t.route;if(0===s.length)return[];let n={startIndex:0,endIndex:-1,z:s[0].z,points:[s[0]]};for(let t=1;t<s.length;t++)s[t].z===n.z?n.points.push(s[t]):(n.endIndex=t-1,e.push(n),n={startIndex:t,endIndex:-1,z:s[t].z,points:[s[t]]});return n.endIndex=s.length-1,e.push(n),e}_step(){if(this.currentSectionIndex>=this.routeSections.length)return void(this.solved=!0);if(0===this.currentSectionIndex&&this.routeSections.length>1){const t=this.routeSections[0],e=this.routeSections[1];if(t.z!==e.z){const s=e.z,n=t.points[0];if(this.canEndpointConnectOnLayer(n.x,n.y,s)&&this.canSectionMoveToLayer({currentSection:t,targetZ:s}))return t.z=s,t.points=t.points.map(t=>({...t,z:s})),void(this.currentSectionIndex=2)}return void this.currentSectionIndex++}if(this.currentSectionIndex===this.routeSections.length-1){if(this.routeSections.length>=2){const t=this.routeSections[this.routeSections.length-1],e=this.routeSections[this.routeSections.length-2];if(t.z!==e.z){const s=e.z,n=t.points[t.points.length-1];this.canEndpointConnectOnLayer(n.x,n.y,s)&&this.canSectionMoveToLayer({currentSection:t,targetZ:s})&&(t.z=s,t.points=t.points.map(t=>({...t,z:s})))}}return void(this.solved=!0)}const t=this.routeSections[this.currentSectionIndex-1],e=this.routeSections[this.currentSectionIndex],s=this.routeSections[this.currentSectionIndex+1];if(t.z!==s.z)return void this.currentSectionIndex++;const n=t.z;if(this.canSectionMoveToLayer({currentSection:e,targetZ:n}))return e.z=n,e.points=e.points.map(t=>({...t,z:n})),void(this.currentSectionIndex+=2);this.currentSectionIndex++}canEndpointConnectOnLayer(t,e,s){const n=this.obstacleSHI.searchArea(t,e,2,2).filter(s=>{if(!s.connectedTo?.includes(this.unsimplifiedRoute.connectionName))return!1;const n=s.width/2+.05,i=s.height/2+.05,o=Math.abs(t-s.center.x)<=n,a=Math.abs(e-s.center.y)<=i;return o&&a});return!(n.length>0)||n.some(t=>t.zLayers?.includes(s))}canSectionMoveToLayer({currentSection:t,targetZ:e}){for(let s=0;s<t.points.length-1;s++){const n={...t.points[s],z:e},i={...t.points[s+1],z:e},o=this.hdRouteSHI.getConflictingRoutesForSegment(n,i,this.TRACE_THICKNESS);for(const{conflictingRoute:t,distance:e}of o)if(t.connectionName!==this.unsimplifiedRoute.connectionName&&e<this.TRACE_THICKNESS+t.traceThickness)return!1;const a={centerX:(n.x+i.x)/2,centerY:(n.y+i.y)/2,width:Math.abs(n.x-i.x),height:Math.abs(n.y-i.y)},r=this.obstacleSHI.searchArea(a.centerX,a.centerY,a.width+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN),a.height+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN));for(const t of r){if(t.connectedTo?.includes(this.unsimplifiedRoute.connectionName))continue;if(t.zLayers?.includes(e)){if(Math.abs(n.x-t.center.x)<.01&&Math.abs(n.y-t.center.y)<.01||Math.abs(i.x-t.center.x)<.01&&Math.abs(i.y-t.center.y)<.01)continue}if(bt(n,i,t)<this.TRACE_THICKNESS+this.OBSTACLE_MARGIN)return!1}}return!0}getConstructorParams(){return{obstacleSHI:this.obstacleSHI,hdRouteSHI:this.hdRouteSHI,unsimplifiedRoute:this.unsimplifiedRoute}}getOptimizedHdRoute(){const t=this.routeSections.flatMap(t=>t.points),e=[];for(let s=0;s<t.length-1;s++)t[s].z!==t[s+1].z&&e.push({x:t[s].x,y:t[s].y});return{connectionName:this.unsimplifiedRoute.connectionName,route:t,traceThickness:this.unsimplifiedRoute.traceThickness,vias:e,viaDiameter:this.unsimplifiedRoute.viaDiameter}}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Single Route Useless Via Removal Solver"};for(let e=0;e<this.routeSections.length;e++){const s=this.routeSections[e];t.lines.push({points:s.points,strokeWidth:this.TRACE_THICKNESS,strokeColor:e===this.currentSectionIndex?"orange":0===s.z?"red":"blue"})}return t}},Un=class extends e{constructor(t){super(),this.input=t,this.MAX_ITERATIONS=1e6,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.optimizedHdRoutes=[],this.unprocessedRoutes=[...t.unsimplifiedHdRoutes],this.obstacleSHI=new Bn("flatbush",t.obstacles),this.hdRouteSHI=new Zn(this.unsimplifiedHdRoutes)}unsimplifiedHdRoutes;optimizedHdRoutes;unprocessedRoutes;activeSubSolver=null;obstacleSHI=null;hdRouteSHI=null;_step(){if(this.activeSubSolver)return this.activeSubSolver.step(),void(this.activeSubSolver.solved?(this.optimizedHdRoutes.push(this.activeSubSolver.getOptimizedHdRoute()),this.activeSubSolver=null):(this.activeSubSolver.failed||this.activeSubSolver.error)&&(this.error=this.activeSubSolver.error,this.failed=!0));const t=this.unprocessedRoutes.shift();t?this.activeSubSolver=new Wn({hdRouteSHI:this.hdRouteSHI,obstacleSHI:this.obstacleSHI,unsimplifiedRoute:t}):this.solved=!0}getOptimizedHdRoutes(){return this.optimizedHdRoutes}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Useless Via Removal Solver"};for(const e of this.input.obstacles){let s="rgba(128, 128, 128, 0.2)";const n=e.zLayers?.includes(0),i=e.zLayers?.includes(1);n&&i?s="rgba(128, 0, 128, 0.2)":n?s="rgba(255, 0, 0, 0.2)":i&&(s="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.optimizedHdRoutes){if(0===e.route.length)continue;this.input.colorMap[e.connectionName];for(let s=0;s<e.route.length-1;s++){const n=e.route[s],i=e.route[s+1];n.z===i.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:i.x,y:i.y}],strokeColor:0===n.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${n.z})`})}for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`})}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},Gn=class extends e{newRoute;newVias;headIndex=0;tailIndex=0;inputRoute;otherHdRoutes;obstacles;connMap;colorMap;outline;constructor(t){super(),this.inputRoute=t.inputRoute,this.otherHdRoutes=t.otherHdRoutes,this.obstacles=t.obstacles,this.connMap=t.connMap,this.colorMap=t.colorMap,this.outline=t.outline,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}}get simplifiedRoute(){return{connectionName:this.inputRoute.connectionName,traceThickness:this.inputRoute.traceThickness,viaDiameter:this.inputRoute.viaDiameter,route:this.newRoute,vias:this.newVias}}isValidPath(t){throw new Error("Not implemented")}_step(){throw new Error("Not implemented")}getVisualsForNewRouteAndObstacles(){const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Simplified Path Solver"};for(let e=0;e<this.inputRoute.route.length-1;e++)t.lines.push({points:[{x:this.inputRoute.route[e].x,y:this.inputRoute.route[e].y},{x:this.inputRoute.route[e+1].x,y:this.inputRoute.route[e+1].y}],strokeColor:"rgba(255, 0, 0, 0.8)",strokeDash:1===this.inputRoute.route[e].z?"5, 5":void 0,layer:`z${this.inputRoute.route[e].z.toString()}`});for(let e=0;e<this.newRoute.length;e++)e<this.newRoute.length-1&&t.lines.push({points:[{x:this.newRoute[e].x,y:this.newRoute[e].y},{x:this.newRoute[e+1].x,y:this.newRoute[e+1].y}],strokeWidth:.15,strokeColor:"rgba(0, 255, 0, 0.8)",strokeDash:1===this.newRoute[e].z?[.4,.4]:void 0,layer:`z${this.newRoute[e].z.toString()}`}),t.points.push({x:this.newRoute[e].x,y:this.newRoute[e].y,color:"rgba(0, 255, 0, 0.8)",label:`z: ${this.newRoute[e].z}`,layer:`z${this.newRoute[e].z.toString()}`});for(const e of this.newVias)t.circles.push({center:e,radius:this.inputRoute.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)"});for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});for(const e of this.otherHdRoutes)for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeWidth:.15,strokeColor:0===e.route[s].z?"rgba(255, 0, 255, 0.5)":1===e.route[s].z?"rgba(128, 0, 128, 0.5)":"rgba(0, 0, 255, 0.5)",layer:`z${e.route[s].z.toString()}`});if("filteredObstaclePathSegments"in this){const e=this.filteredObstaclePathSegments;for(const[s,n]of e)t.lines.push({points:[s,n]})}return t}};function qn(t,e,s,n){if(function(t,e,s,n){const i=ti(t,e,s),o=ti(t,e,n),a=ti(s,n,t),r=ti(s,n,e);return i!==o&&a!==r||(!(0!==i||!ei(t,s,e))||(!(0!==o||!ei(t,n,e))||(!(0!==a||!ei(s,t,n))||!(0!==r||!ei(s,e,n)))))}(t,e,s,n))return 0;const i=Kn(t,s,n),o=Kn(e,s,n),a=Kn(s,t,e),r=Kn(n,t,e);return Math.min(i,o,a,r)}function Kn(t,e,s){const n={x:s.x-e.x,y:s.y-e.y},i=Jn({x:t.x-e.x,y:t.y-e.y},n);if(i<=0)return Qn(t,e);const o=Jn(n,n);if(o<=i)return Qn(t,s);const a=i/o;return Qn(t,{x:e.x+a*n.x,y:e.y+a*n.y})}function Jn(t,e){return t.x*e.x+t.y*e.y}function Qn(t,e){const s=e.x-t.x,n=e.y-t.y;return Math.sqrt(s*s+n*n)}function ti(t,e,s){const n=(e.y-t.y)*(s.x-e.x)-(e.x-t.x)*(s.y-e.y);return 0===n?0:n>0?1:2}function ei(t,e,s){return e.x<=Math.max(t.x,s.x)&&e.x>=Math.min(t.x,s.x)&&e.y<=Math.max(t.y,s.y)&&e.y>=Math.min(t.y,s.y)}var si=t=>({minX:Math.min(t[0].x,t[1].x),maxX:Math.max(t[0].x,t[1].x),minY:Math.min(t[0].y,t[1].y),maxY:Math.max(t[0].y,t[1].y)}),ni=class{constructor(t){this.segments=t,this.buckets=new Map;const e=new Map;for(const s of t){const t=this.getSegmentKey(s);if(e.has(t))continue;e.set(t,s);const n=si(s),i=Math.floor(n.minX/this.CELL_SIZE),o=Math.floor(n.maxX/this.CELL_SIZE),a=Math.floor(n.minY/this.CELL_SIZE),r=Math.floor(n.maxY/this.CELL_SIZE);for(let e=i;e<=o;e++)for(let n=a;n<=r;n++){const i=`${e}x${n}`,o=this.buckets.get(i),a=[s[0],s[1],t];o?o.push(a):this.buckets.set(i,[a])}}}buckets;CELL_SIZE=.4;SEGMENT_MARGIN=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getSegmentKey(t){return`${t[0].x}-${t[0].y}-${t[0].z}-${t[1].x}-${t[1].y}-${t[1].z}`}getSegmentsThatCouldIntersect(t,e){const s=[],n=new Set,i=Math.min(t.x,e.x)-this.SEGMENT_MARGIN,o=Math.min(t.y,e.y)-this.SEGMENT_MARGIN,a=Math.max(t.x,e.x)+this.SEGMENT_MARGIN,r=Math.max(t.y,e.y)+this.SEGMENT_MARGIN,h=Math.floor(i/this.CELL_SIZE),c=Math.floor(a/this.CELL_SIZE),d=Math.floor(o/this.CELL_SIZE),l=Math.floor(r/this.CELL_SIZE);for(let t=h;t<=c;t++)for(let e=d;e<=l;e++){const i=`${t}x${e}`,o=this.buckets.get(i);if(o)for(const t of o){const e=t[2];n.has(e)||(n.add(e),s.push(t))}}return s}},ii=1e-6,oi=(t,e,s)=>ct(t,e,s)<=ii,ai=(t,e)=>Math.abs(t.x-e.x)<=ii&&Math.abs(t.y-e.y)<=ii,ri=(t,e)=>{if(!e||e.length<3)return!1;for(let s=0;s<e.length;s++){const n=e[s],i=e[(s+1)%e.length];if(oi(t,n,i))return!0}let s=!1;for(let n=0,i=e.length-1;n<e.length;i=n++){const o=e[n],a=e[i];o.y>t.y!=a.y>t.y&&t.x<(a.x-o.x)*(t.y-o.y)/(a.y-o.y)+o.x&&(s=!s)}return s},hi=class extends Gn{pathSegments=[];totalPathLength=0;headDistanceAlongPath=0;tailDistanceAlongPath=0;minStepSize=.25;lastValidPath=null;lastValidPathHeadDistance=0;STEP_SIZE_REDUCTION_FACTOR=.25;maxStepSize=4;currentStepSize=this.maxStepSize;lastHeadMoveDistance=0;cachedValidPathSegments;filteredObstacles=[];filteredObstaclePathSegments=[];filteredVias=[];segmentTree;OBSTACLE_MARGIN=.1;TRACE_THICKNESS=.15;TAIL_JUMP_RATIO=.8;constructor(t){if(super(t),this.cachedValidPathSegments=new Set,this.inputRoute.route.length<=1)return this.newRoute=[...this.inputRoute.route],void(this.solved=!0);const e=this.inputRoute.route.reduce((t,e)=>(t.minX=Math.min(t.minX,e.x),t.maxX=Math.max(t.maxX,e.x),t.minY=Math.min(t.minY,e.y),t.maxY=Math.max(t.maxY,e.y),t),{minX:1/0,maxX:-1/0,minY:1/0,maxY:-1/0}),s={center:{x:(e.minX+e.maxX)/2,y:(e.minY+e.maxY)/2},width:e.maxX-e.minX,height:e.maxY-e.minY};this.filteredObstacles=this.obstacles.filter(t=>!t.connectedTo.some(t=>this.connMap.areIdsConnected(this.inputRoute.connectionName,t))).filter(t=>{if(t.connectedTo.some(t=>this.connMap.areIdsConnected(this.inputRoute.connectionName,t)))return!1;return function(t,e){const s=it(t),n=it(e),i=Math.max(s.minX-n.maxX,n.minX-s.maxX,0),o=Math.max(s.minY-n.maxY,n.minY-s.maxY,0);return Math.hypot(i,o)}(s,t)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2}),this.filteredObstaclePathSegments=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const s=t.route,n=[];for(let t=0;t<s.length-1;t++){const i=s[t],o=s[t+1],a=Math.min(i.x,o.x),r=Math.max(i.x,o.x),h=Math.min(i.y,o.y),c=Math.max(i.y,o.y);a<=e.maxX&&r>=e.minX&&h<=e.maxY&&c>=e.minY&&n.push([i,o])}return n}),this.segmentTree=new ni(this.filteredObstaclePathSegments),this.filteredVias=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const s=t.vias,n=[];for(const i of s){const s=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2+t.viaDiameter/2,o=i.x-s,a=i.x+s,r=i.y-s,h=i.y+s;o<=e.maxX&&a>=e.minX&&r<=e.maxY&&h>=e.minY&&n.push({...i,diameter:t.viaDiameter})}return n}),this.computePathSegments()}computePathSegments(){let t=0;for(let e=0;e<this.inputRoute.route.length-1;e++){const s=this.inputRoute.route[e],n=this.inputRoute.route[e+1],i=Math.sqrt((n.x-s.x)**2+(n.y-s.y)**2)+e/1e4;this.pathSegments.push({start:s,end:n,length:i,startDistance:t,endDistance:t+i}),t+=i}this.totalPathLength=t}arePointsEqual(t,e){return t.x===e.x&&t.y===e.y&&t.z===e.z}getPointAtDistance(t){t=Math.max(0,Math.min(t,this.totalPathLength));const e=this.pathSegments.find(e=>t>=e.startDistance&&t<=e.endDistance);if(!e)return this.inputRoute.route[this.inputRoute.route.length-1];const s=(t-e.startDistance)/e.length;return{x:e.start.x+s*(e.end.x-e.start.x),y:e.start.y+s*(e.end.y-e.start.y),z:s<.5?e.start.z:e.end.z}}getNearestIndexForDistance(t){if(t<=0)return 0;if(t>=this.totalPathLength)return this.inputRoute.route.length-1;const e=this.pathSegments.findIndex(e=>t>=e.startDistance&&t<=e.endDistance);if(-1===e)return 0;const s=this.pathSegments[e],n=(s.startDistance+s.endDistance)/2;return t>n?e+1:e}isValidPathSegment(t,e){for(const s of this.filteredObstacles){if(!s.zLayers?.includes(t.z))continue;if(bt(t,e,s)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2)return!1}const s=this.segmentTree.getSegmentsThatCouldIntersect(t,e);for(const[n,i,o]of s)if(n.z===t.z&&i.z===t.z){if(qn({x:t.x,y:t.y},{x:e.x,y:e.y},{x:n.x,y:n.y},{x:i.x,y:i.y})<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS)return!1}for(const s of this.filteredVias)if(ct(s,t,e)<this.OBSTACLE_MARGIN+s.diameter/2+this.TRACE_THICKNESS/2)return!1;if(this.outline&&this.outline.length>=3){const s=(({start:t,end:e,polygon:s,margin:n=.2})=>{if(!s||s.length<3)return!1;const i=ri(t,s),o=ri(e,s);if(!i||!o)return!0;for(let i=0;i<s.length;i++){const o=s[i],a=s[(i+1)%s.length],r=oi(t,o,a),h=oi(e,o,a);if(r&&h)continue;if(!at(t,e,o,a)){if(!r&&!h&&qn(t,e,o,a)<n-ii)return!0;continue}const c=lt(t,e,o,a);if(!(c&&(r&&ai(c,t)||h&&ai(c,e))||c&&(ai(c,t)||ai(c,e))))return!0}return!1})({start:{x:t.x,y:t.y},end:{x:e.x,y:e.y},polygon:this.outline});if(s)return!1}return!0}isValidPath(t){if(t.length<2)return!0;for(let e=0;e<t.length-1;e++)if(t[e].z!==t[e+1].z)return!1;for(let e=0;e<t.length-1;e++)if(!this.isValidPathSegment(t[e],t[e+1]))return!1;return!0}find45DegreePath(t,e){if(this.arePointsEqual(t,e))return[t];if(t.z!==e.z)return null;const s=((t,e)=>{const s=[],n=Math.abs(e.x-t.x),i=Math.abs(e.y-t.y),o=e.x>t.x?1:-1,a=e.y>t.y?1:-1,r={x:e.x-o*Math.abs(e.y-t.y),y:t.y};(r.x-t.x)*o>=0&&(r.x-e.x)*o<=0&&s.push([t,r,e]);const h={x:t.x,y:e.y-a*Math.abs(e.x-t.x)};(h.y-t.y)*a>=0&&(h.y-e.y)*a<=0&&s.push([t,h,e]);const c=Math.min(n,i),d={x:t.x+o*c,y:t.y+a*c};return(d.x-t.x)*o>=0&&(d.x-e.x)*o<=0&&(d.y-t.y)*a>=0&&(d.y-e.y)*a<=0&&s.push([t,d,e]),s})({x:t.x,y:t.y},{x:e.x,y:e.y});for(const e of s){const s=e.map(e=>({x:e.x,y:e.y,z:t.z}));if(this.isValidPath(s))return s}return null}addPathToResult(t){if(0!==t.length){for(let e=0;e<t.length;e++)0===e&&this.newRoute.length>0&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t[e])||this.newRoute.push(t[e]);this.currentStepSize=this.maxStepSize}}moveHead(t){this.lastHeadMoveDistance=t,this.headDistanceAlongPath=Math.min(this.headDistanceAlongPath+t,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 t=this.tailDistanceAlongPath>=this.totalPathLength,e=this.headDistanceAlongPath>=this.totalPathLength;if(t){const t=this.inputRoute.route[this.inputRoute.route.length-1];return 0!==this.newRoute.length&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t)||this.newRoute.push(t),void(this.solved=!0)}if(e){const t=this.getPointAtDistance(this.tailDistanceAlongPath),e=this.inputRoute.route[this.inputRoute.route.length-1],s=this.find45DegreePath(t,e);if(s)return this.addPathToResult(s),void(this.solved=!0);this.lastValidPath=null,this.tailDistanceAlongPath=this.totalPathLength,this.headDistanceAlongPath=this.totalPathLength;const n=[];for(const t of this.inputRoute.route)0!==n.length&&this.arePointsEqual(n[n.length-1],t)||n.push(t);return this.newRoute=n,this.newVias=[...this.inputRoute.vias],void(this.solved=!0)}this.moveHead(this.currentStepSize);const s=this.getPointAtDistance(this.tailDistanceAlongPath),n=this.getPointAtDistance(this.headDistanceAlongPath),i=this.getNearestIndexForDistance(this.tailDistanceAlongPath),o=this.getNearestIndexForDistance(this.headDistanceAlongPath);let a=!1,r=-1;for(let t=i;t<o;t++)if(t+1<this.inputRoute.route.length&&this.inputRoute.route[t].z!==this.inputRoute.route[t+1].z){a=!0;const e=t;r=this.pathSegments[e].startDistance;break}if(a&&this.lastHeadMoveDistance>this.minStepSize)return void this.stepBackAndReduceStepSize();if(a&&r>0){const t=this.getNearestIndexForDistance(r)+1,e=this.inputRoute.route[t],s={x:e.x,y:e.y};this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null);const n=this.newRoute[this.newRoute.length-1];n.x===s.x&&n.y===s.y||this.newRoute.push({x:s.x,y:s.y,z:n.z}),this.newVias.push(s),this.newRoute.push({x:s.x,y:s.y,z:e.z}),this.currentStepSize=this.maxStepSize;const i=this.pathSegments.findIndex(t=>t.start===e);if(-1!==i)this.tailDistanceAlongPath=this.pathSegments[i].startDistance,this.headDistanceAlongPath=this.tailDistanceAlongPath,this.lastValidPath=null,this.lastValidPathHeadDistance=this.tailDistanceAlongPath;else if(t<this.inputRoute.route.length){if(t===this.inputRoute.route.length-1)return void(this.solved=!0);console.warn("Fallback used for tailDistanceAlongPath after layer change");const e=this.pathSegments.find(e=>e.start===this.inputRoute.route[t]);e?(this.tailDistanceAlongPath=e.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.\n Index sought: ${t}, Point: (${this.inputRoute.route[t].x.toFixed(3)}, ${this.inputRoute.route[t].y.toFixed(3)}, z=${this.inputRoute.route[t].z})\n Route Length: ${this.inputRoute.route.length}, Path Segments: ${this.pathSegments.length}`),this.solved=!0)}else console.warn("Layer change occurred at the end of the path."),this.solved=!0;return}const h=this.find45DegreePath(s,n);if(!h&&this.lastHeadMoveDistance>this.minStepSize)this.stepBackAndReduceStepSize();else{if(!h&&!this.lastValidPath){const t=this.getPointAtDistance(this.tailDistanceAlongPath);this.tailDistanceAlongPath+=this.minStepSize,this.moveHead(this.minStepSize);const e=this.getNearestIndexForDistance(this.tailDistanceAlongPath),s=this.inputRoute.route[e],n=this.inputRoute.route[this.inputRoute.route.length-1];return void(this.arePointsEqual(t,s)||this.arePointsEqual(s,n)||this.newRoute.push(s))}if(h)return this.lastValidPath=h,void(this.lastValidPathHeadDistance=this.headDistanceAlongPath);this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null,this.tailDistanceAlongPath=this.lastValidPathHeadDistance,this.moveHead(this.minStepSize))}}visualize(){const t=this.getVisualsForNewRouteAndObstacles(),e=this.getPointAtDistance(this.tailDistanceAlongPath),s=this.getPointAtDistance(this.headDistanceAlongPath);t.points.push({x:e.x,y:e.y,color:"yellow",label:["Tail",`z: ${e.z}`].join("\n")}),t.points.push({x:s.x,y:s.y,color:"orange",label:["Head",`z: ${s.z}`].join("\n")});const n=this.getPointAtDistance(this.headDistanceAlongPath+this.currentStepSize);t.points.push({x:n.x,y:n.y,color:"red",label:["Tentative Head",`z: ${n.z}`].join("\n")});let i=0;for(;i<this.totalPathLength;){const e=this.getPointAtDistance(i);t.circles.push({center:{x:e.x,y:e.y},radius:.05,fill:"rgba(100, 100, 100, 0.5)"}),i+=this.totalPathLength/20}if(this.lastValidPath&&this.lastValidPath.length>1)for(let e=0;e<this.lastValidPath.length-1;e++)t.lines.push({points:[{x:this.lastValidPath[e].x,y:this.lastValidPath[e].y},{x:this.lastValidPath[e+1].x,y:this.lastValidPath[e+1].y}],strokeColor:"rgba(0, 255, 255, 0.9)",strokeDash:"3, 3"});return t}},ci=class extends e{simplifiedHdRoutes;currentUnsimplifiedHdRouteIndex=0;activeSubSolver=null;unsimplifiedHdRoutes;obstacles;connMap;colorMap;outline;defaultViaDiameter;constructor(t){super(),this.MAX_ITERATIONS=1e8,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.obstacles=t.obstacles,this.connMap=t.connMap||new Ne({}),this.colorMap=t.colorMap||{},this.outline=t.outline,this.defaultViaDiameter=t.defaultViaDiameter??.6,this.simplifiedHdRoutes=[]}_step(){const t=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];if(!this.activeSubSolver)return t?(this.activeSubSolver=new hi({inputRoute:t,otherHdRoutes:this.unsimplifiedHdRoutes.slice(this.currentUnsimplifiedHdRouteIndex+1).concat(this.simplifiedHdRoutes),obstacles:this.obstacles,connMap:this.connMap,colorMap:this.colorMap,outline:this.outline}),void this.currentUnsimplifiedHdRouteIndex++):void(this.solved=!0);this.activeSubSolver.step(),this.activeSubSolver.solved&&(this.simplifiedHdRoutes.push(this.activeSubSolver.simplifiedRoute),this.activeSubSolver=null)}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Multi Simplified Path Solver"};for(const e of this.unsimplifiedHdRoutes)if(!this.simplifiedHdRoutes.some(t=>t.connectionName===e.connectionName)){for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeColor:1===e.route[s].z?"rgba(0, 0, 255, 0.4)":"rgba(255, 0, 0, 0.4)",strokeWidth:.15,strokeDash:1===e.route[s].z?[.5,.5]:void 0});for(const s of e.vias||[])t.circles.push({center:s,radius:(e.viaDiameter??this.defaultViaDiameter)/2,fill:"rgba(0, 0, 255, 0.4)"})}for(const e of this.simplifiedHdRoutes){const s=this.colorMap?.[e.connectionName]||"rgba(128, 128, 128, 0.8)";for(let n=0;n<e.route.length-1;n++)t.lines.push({points:[{x:e.route[n].x,y:e.route[n].y},{x:e.route[n+1].x,y:e.route[n+1].y}],strokeWidth:.15,strokeColor:s,strokeDash:1===e.route[n].z?[.5,.5]:void 0,step:1});for(const s of e.vias||[])t.circles.push({center:s,radius:e.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)",step:1})}for(const e of this.unsimplifiedHdRoutes){for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeWidth:.15,strokeColor:"rgba(255, 0, 0, 0.2)",strokeDash:[.5,.5],step:0,layer:`z${e.route[s].z.toString()}`});for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 0, 0.2)",step:0})}for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});if(this.currentUnsimplifiedHdRouteIndex<this.unsimplifiedHdRoutes.length){const e=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];e.route.length>0&&t.circles.push({center:{x:e.route[0].x,y:e.route[0].y},radius:.2,fill:"yellow",label:"Current"})}return t}},di=class extends e{constructor(t){super(),this.input=t,this.MAX_ITERATIONS=1e6,this.inputHdRoutes=t.inputHdRoutes,this.mergedViaHdRoutes=structuredClone(this.inputHdRoutes),this.unprocessedRoutes=[...t.inputHdRoutes],this.colorMap=t.colorMap,this.outline=t.outline,this.obstacles=t.obstacles,this.obstacleSHI=new Bn("flatbush",t.obstacles),this.hdRouteSHI=new Zn(this.inputHdRoutes),this.vias=[],this.offendingVias=[],this.connMap=t.connMap,this.viasByNet=new Map,this.rebuildVias()}inputHdRoutes;mergedViaHdRoutes;unprocessedRoutes;vias;offendingVias;currentViaRoutes=[];connMap;colorMap;outline;obstacles;viasByNet;obstacleSHI=null;hdRouteSHI=null;rebuildVias(){this.vias=[],this.viasByNet=new Map;for(let t=0;t<this.mergedViaHdRoutes.length;t++){const e=this.mergedViaHdRoutes[t];for(let s=0;s<e.vias.length;s++){const n=e.vias[s],i={x:n.x,y:n.y,diameter:e.viaDiameter,net:this.connMap?.idToNetMap[e.connectionName]??"",layers:[...new Set(e.route.map(t=>t.z))],routeIndex:t};this.vias.push(i);const o=this.viasByNet.get(i.net);o?o.push(i):this.viasByNet.set(i.net,[i])}}}findNextOffendingPair(){for(let t=0;t<this.vias.length-1;t++){const e=this.vias[t],s=this.viasByNet.get(e.net);if(!s)continue;const n=s.indexOf(e);for(let t=n>=0?n+1:0;t<s.length;t++){const n=s[t],i=e.x-n.x,o=e.y-n.y,a=i*i+o*o,r=e.diameter/2+n.diameter/2;if(a<=r*r&&0!==a)return[e,n]}}return null}handleOffendingPair(t,e){const s=t.layers.length<e.layers.length?t:e,n=s===t?e:t,i=this.mergedViaHdRoutes[s.routeIndex].route;for(let t=0;t<s.layers.length;t++)for(let t=i.length-1;t>=1;t--){const e=i[t-1],o=i[t];if(o.x===s.x&&o.y===s.y){i.splice(t,0,{x:n.x,y:n.y,z:o.z}),i.splice(t,0,{x:n.x,y:n.y,z:e.z});const a=this.mergedViaHdRoutes[s.routeIndex];return a.vias=a.vias.map(t=>t.x===s.x&&t.y===s.y?{x:n.x,y:n.y}:t),void this.rebuildVias()}}this.rebuildVias()}_step(){const t=this.findNextOffendingPair();t?this.handleOffendingPair(t[0],t[1]):this.solved=!0}getMergedViaHdRoutes(){return this.mergedViaHdRoutes}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Same Net Via Merger Solver"};for(const e of this.input.obstacles){let s="rgba(128, 128, 128, 0.2)";const n=e.zLayers?.includes(0),i=e.zLayers?.includes(1);n&&i?s="rgba(128, 0, 128, 0.2)":n?s="rgba(255, 0, 0, 0.2)":i&&(s="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.mergedViaHdRoutes){if(0===e.route.length)continue;this.input.colorMap[e.connectionName];for(let s=0;s<e.route.length-1;s++){const n=e.route[s],i=e.route[s+1];n.z===i.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:i.x,y:i.y}],strokeColor:0===n.z?"rgba(255, 0, 0, 0.5)":"rgba(0, 0, 255, 0.5)",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${n.z})`})}for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`})}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},li=class extends e{constructor(t){super(),this.simplificationConfig=t,this.hdRoutes=[...t.hdRoutes],this.MAX_ITERATIONS=1e8}hdRoutes=[];simplificationPipelineLoops=0;MAX_SIMPLIFICATION_PIPELINE_LOOPS=2;PHASE_ORDER=["via_removal","via_merging","path_simplification"];currentPhase="via_removal";extractResult=null;get simplifiedHdRoutes(){return this.hdRoutes}_step(){if(this.simplificationPipelineLoops>=this.MAX_SIMPLIFICATION_PIPELINE_LOOPS)this.solved=!0;else{if(this.activeSubSolver){if(this.activeSubSolver.step(),!this.activeSubSolver.failed&&!this.activeSubSolver.solved)return;if(this.activeSubSolver.solved){if(this.extractResult&&(this.hdRoutes=this.extractResult(this.activeSubSolver)),this.activeSubSolver=null,this.extractResult=null,"via_removal"===this.currentPhase?this.currentPhase="via_merging":"via_merging"===this.currentPhase?this.currentPhase="path_simplification":(this.currentPhase="via_removal",this.simplificationPipelineLoops++),this.simplificationPipelineLoops>=this.MAX_SIMPLIFICATION_PIPELINE_LOOPS)return void(this.solved=!0)}else if(this.activeSubSolver.failed)return this.failed=!0,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 Un({unsimplifiedHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,colorMap:this.simplificationConfig.colorMap,layerCount:this.simplificationConfig.layerCount}),this.extractResult=t=>t.getOptimizedHdRoutes()??[];break;case"via_merging":this.activeSubSolver=new di({inputHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,colorMap:this.simplificationConfig.colorMap,layerCount:this.simplificationConfig.layerCount,connMap:this.simplificationConfig.connMap,outline:this.simplificationConfig.outline}),this.extractResult=t=>t.getMergedViaHdRoutes()??[];break;case"path_simplification":this.activeSubSolver=new ci({unsimplifiedHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,connMap:this.simplificationConfig.connMap,colorMap:this.simplificationConfig.colorMap,outline:this.simplificationConfig.outline,defaultViaDiameter:this.simplificationConfig.defaultViaDiameter}),this.extractResult=t=>t.simplifiedHdRoutes;break;default:this.failed=!0,this.error=`Unknown phase: ${this.currentPhase}`}}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Trace Simplification Solver"};for(const e of this.simplificationConfig.obstacles){let s="rgba(128, 128, 128, 0.2)";const n=e.zLayers?.includes(0),i=e.zLayers?.includes(1);n&&i?s="rgba(128, 0, 128, 0.2)":n?s="rgba(255, 0, 0, 0.2)":i&&(s="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.hdRoutes)if(0!==e.route.length){for(let s=0;s<e.route.length-1;s++){const n=e.route[s],i=e.route[s+1];n.z===i.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:i.x,y:i.y}],strokeColor:0===n.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${n.z})`})}for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`})}return t}};function ui(t,e,s,n={}){return{solverName:t,solverClass:e,getConstructorParams:s,onSolved:n.onSolved}}var pi=class extends e{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth,void 0===e.capacityDepth){const s=t.bounds.maxX-t.bounds.minX,n=t.bounds.maxY-t.bounds.minY,i=Math.max(s,n),o=e.targetMinCapacity??.5;e.capacityDepth=Ce(i,o)}this.connMap=Ie(t),this.colorMap=H(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?st():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;initialPathingSolver;pathingOptimizer;edgeToPortSegmentSolver;colorMap;segmentToPointSolver;unravelMultiSectionSolver;segmentToPointOptimizer;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;viaDiameter;minTraceWidth;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[ui("netToPointPairsSolver",As,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=H(t.srjWithPointPairs,this.connMap),t.connMap=Ie(t.srjWithPointPairs)}}),ui("nodeSolver",un,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),ui("strawSolver",vs,t=>[{nodes:t.capacityNodes}],{onSolved:t=>{t.capacityNodes=t.strawSolver?.getResultNodes()}}),ui("edgeSolver",Ns,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),ui("deadEndSolver",Is,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges}],{onSolved:t=>{const e=t.deadEndSolver?.removedNodeIds;t.capacityNodes=t.capacityNodes.filter(t=>!e.has(t.capacityMeshNodeId)),t.capacityEdges=t.capacityEdges.filter(t=>t.nodeIds.every(t=>!e.has(t)))}}),ui("initialPathingSolver",os,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),ui("pathingOptimizer",xs,t=>[{initialPathingSolver:t.initialPathingSolver,simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,cacheProvider:t.cacheProvider,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),ui("edgeToPortSegmentSolver",j,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.pathingOptimizer?.getCapacityPaths()||[],colorMap:t.colorMap}]),ui("segmentToPointSolver",q,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),ui("unravelMultiSectionSolver",es,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),ui("highDensityRouteSolver",be,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),ui("highDensityStitchSolver",De,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),ui("traceSimplificationSolver",li,t=>[{hdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline,defaultViaDiameter:t.viaDiameter,layerCount:t.srj.layerCount,iterations:2}])];currentPipelineStepIndex=0;_step(){const t=this.pipelineDef[this.currentPipelineStepIndex];if(!t)return void(this.solved=!0);if(this.activeSubSolver)return this.activeSubSolver.step(),void(this.activeSubSolver.solved?(this.endTimeOfPhase[t.solverName]=performance.now(),this.timeSpentOnPhase[t.solverName]=this.endTimeOfPhase[t.solverName]-this.startTimeOfPhase[t.solverName],t.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStepIndex++):this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null));const e=t.getConstructorParams(this);this.activeSubSolver=new t.solverClass(...e),this[t.solverName]=this.activeSubSolver,this.timeSpentOnPhase[t.solverName]=0,this.startTimeOfPhase[t.solverName]=performance.now()}solveUntilPhase(t){for(;this.getCurrentPhase()!==t;)this.step()}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();const e=this.netToPointPairsSolver?.visualize(),s=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),i=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),a=this.edgeSolver?.visualize(),r=this.deadEndSolver?.visualize(),h=this.initialPathingSolver?.visualize(),c=this.pathingOptimizer?.visualize(),d=this.edgeToPortSegmentSolver?.visualize(),l=this.segmentToPointSolver?.visualize(),u=this.unravelMultiSectionSolver?.visualize()??this.segmentToPointOptimizer?.visualize(),p=this.highDensityRouteSolver?.visualize(),f=this.highDensityStitchSolver?.visualize(),g=this.traceSimplificationSolver?.visualize(),m=this.srj.outline,y=[];if(y.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),m&&m.length>=2){const t=m.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),y.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const x={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:t.layers?.join(", ")}))],lines:y},v=[x,e,s,n,i,o,a,r,h,c,d,l,u,p?t(x,p):null,f,g,this.solved?t(x,$e(this.getOutputSimpleRouteJson())):null].filter(Boolean);return t(...v)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const s=this.highDensityRouteSolver.routes[e];if(t.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[s.connectionName]}),t.length>200)break}return{lines:t}}if(this.pathingOptimizer){const t=[];for(const e of this.pathingOptimizer.connectionsWithNodes)e.path&&t.push({points:e.path.map(t=>({x:t.center.x,y:t.center.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}getOriginalConnectionName(t){const e=t.match(/^(.+?)_mst\d+$/);return e?e[1]:t}_getOutputHdRoutes(){return this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const s of this.netToPointPairsSolver?.newConnections??[]){const n=s.netConnectionName??this.srj.connections.find(t=>t.name===s.name)?.netConnectionName,i=e.filter(t=>t.connectionName===s.name);for(let e=0;e<i.length;e++){const o=i[e],a={type:"pcb_trace",pcb_trace_id:`${s.name}_${e}`,connection_name:n??this.getOriginalConnectionName(s.name),route:Ee(o,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},fi=pi,gi=class{constructor(t){this.targets=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const s=t[e],n=Math.floor(s.bounds.minX/this.CELL_SIZE)*this.CELL_SIZE,i=Math.floor(s.bounds.minY/this.CELL_SIZE)*this.CELL_SIZE,o=s.bounds.maxX,a=s.bounds.maxY;for(let t=n;t<=o;t+=this.CELL_SIZE)for(let n=i;n<=a;n+=this.CELL_SIZE){const i=this.getBucketKey(t,n),o=this.buckets.get(i);o?o.push([s,e]):this.buckets.set(i,[[s,e]])}}}buckets;CELL_SIZE=5;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getTargetsInArea(t,e,s,n){const i=[],o=new Set,a=Math.floor((t-s/2)/this.CELL_SIZE)*this.CELL_SIZE,r=Math.floor((e-n/2)/this.CELL_SIZE)*this.CELL_SIZE,h=t+s/2,c=e+n/2;for(let t=a;t<=h;t+=this.CELL_SIZE)for(let e=r;e<=c;e+=this.CELL_SIZE){const s=this.getBucketKey(t,e),n=this.buckets.get(s)||[];for(const t of n)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},mi=class extends e{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.MAX_DEPTH=e?.capacityDepth??this.MAX_DEPTH,this.MAX_ITERATIONS=1e5,this.layerCount=t.layerCount??2,this.outlinePolygon=t.outline&&t.outline.length>=3?t.outline:void 0;for(const e of t.obstacles)if(!e.zLayers){const s=[];for(const n of e.layers)s.push(Ae(n,t.layerCount));e.zLayers=s}const s={x:(t.bounds.minX+t.bounds.maxX)/2,y:(t.bounds.minY+t.bounds.maxY)/2},n={width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},i=Math.max(n.width,n.height);this.unfinishedNodes=[{capacityMeshNodeId:this.getNextNodeId(),center:s,width:i,height:i,layer:"top",availableZ:Array.from({length:this.layerCount},(t,e)=>e),_depth:0,_containsTarget:!0,_containsObstacle:!0,_completelyInsideObstacle:!1}],this.finishedNodes=[],this.nodeToXYOverlappingObstaclesMap=new Map,this.obstacleTree=new Bn("flatbush",this.srj.obstacles),this.targets=this.computeTargets(),this.targetTree=new gi(this.targets)}unfinishedNodes;finishedNodes;nodeToXYOverlappingObstaclesMap;layerCount;outlinePolygon;MAX_DEPTH=4;targets;targetTree;obstacleTree;computeTargets(){const t=[];for(const e of this.srj.connections)for(const s of e.pointsToConnect){const n=ze(s),i=this.obstacleTree.searchArea(s.x,s.y,.01,.01).filter(t=>t.zLayers.some(t=>n.some(e=>t===Ae(e,this.layerCount))));let o={minX:s.x-.005,minY:s.y-.005,maxX:s.x+.005,maxY:s.y+.005};i.length>0&&(o={minX:Math.min(...i.map(t=>t.center.x-t.width/2)),minY:Math.min(...i.map(t=>t.center.y-t.height/2)),maxX:Math.max(...i.map(t=>t.center.x+t.width/2)),maxY:Math.max(...i.map(t=>t.center.y+t.height/2))});const a={...s,connectionName:e.name,availableZ:n.map(t=>Ae(t,this.layerCount)),bounds:o};t.push(a)}return t}getNodeBounds(t){const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-s,maxY:t.center.y+s}}getNodeRect(t){return{center:{x:t.center.x,y:t.center.y},width:t.width,height:t.height}}_nextNodeCounter=0;getNextNodeId(){return"cn"+this._nextNodeCounter++}getCapacityFromDepth(t){return(this.MAX_DEPTH-t+1)**2}getTargetIfNodeContainsTarget(t){const e=t.width>4*this.targetTree.CELL_SIZE?this.targets:this.targetTree.getTargetsInArea(t.center.x,t.center.y,t.width,t.height);for(const s of e)if(s.bounds.minX<=t.center.x+t.width/2&&s.bounds.maxX>=t.center.x-t.width/2&&s.bounds.minY<=t.center.y+t.height/2&&s.bounds.maxY>=t.center.y-t.height/2&&s.availableZ.some(e=>t.availableZ.includes(e)))return s;return null}getXYOverlappingObstacles(t){const e=this.nodeToXYOverlappingObstaclesMap.get(t.capacityMeshNodeId);if(e)return e;const s=[],n=this.getNodeBounds(t),i=n.minX,o=n.maxX,a=n.minY,r=n.maxY,h=t._parent?this.getXYOverlappingObstacles(t._parent):this.srj.obstacles;for(const t of h){const e=t.center.x-t.width/2,n=t.center.x+t.width/2,h=t.center.y-t.height/2,c=t.center.y+t.height/2;o>=e&&i<=n&&r>=h&&a<=c?s.push(t):(i>=e&&o<=n&&a>=h&&r<=c||e>=i&&n<=o&&h>=a&&c<=r)&&s.push(t)}return this.nodeToXYOverlappingObstaclesMap.set(t.capacityMeshNodeId,s),s}getXYZOverlappingObstacles(t){const e=this.getXYOverlappingObstacles(t),s=[];for(const n of e)t.availableZ.some(t=>n.zLayers.includes(t))&&s.push(n);return s}doesNodeOverlapObstacle(t){if(this.getXYZOverlappingObstacles(t).length>0)return!0;const e=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!Mt(e,this.outlinePolygon))return!0}return e.minX<this.srj.bounds.minX||e.maxX>this.srj.bounds.maxX||e.minY<this.srj.bounds.minY||e.maxY>this.srj.bounds.maxY}isNodeCompletelyInsideObstacle(t){const e=this.getXYZOverlappingObstacles(t),s=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!vt(e,this.outlinePolygon))return!0}for(const t of e){const e=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2;if(s.minX>=e&&s.maxX<=n&&s.minY>=i&&s.maxY<=o)return!0}return!1}getChildNodes(t){if(t._depth===this.MAX_DEPTH)return[];const e=[],s={width:t.width/2,height:t.height/2},n=[{x:t.center.x-s.width/2,y:t.center.y-s.height/2},{x:t.center.x+s.width/2,y:t.center.y-s.height/2},{x:t.center.x-s.width/2,y:t.center.y+s.height/2},{x:t.center.x+s.width/2,y:t.center.y+s.height/2}];for(const i of n){const n={capacityMeshNodeId:this.getNextNodeId(),center:i,width:s.width,height:s.height,layer:t.layer,availableZ:t.availableZ,_depth:(t._depth??0)+1,_parent:t};n._containsObstacle=this.doesNodeOverlapObstacle(n);const o=this.getTargetIfNodeContainsTarget(n);o&&(n._targetConnectionName=o.connectionName,n.availableZ=o.availableZ,n._containsTarget=!0),n._containsObstacle&&(n._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(n)),n._completelyInsideObstacle&&!n._containsTarget||e.push(n)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||!(!t._containsObstacle||t._completelyInsideObstacle))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),s=[],n=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t);e?n.push(t):e||t._containsObstacle?!e&&t._containsTarget&&s.push(t):s.push(t)}this.unfinishedNodes.push(...n),this.finishedNodes.push(...s)}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Mesh Visualization"};if(this.outlinePolygon&&this.outlinePolygon.length>=2){const e=this.outlinePolygon.map(t=>({x:t.x,y:t.y}));e.push({...e[0]}),t.lines.push({points:e,strokeColor:"rgba(0, 136, 255, 0.95)",label:"outline"});for(const e of this.outlinePolygon)t.points.push({x:e.x,y:e.y,color:"rgba(0, 136, 255, 0.95)"})}for(const e of this.srj.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:1===e.zLayers?.length&&e.zLayers?.includes(1)?"rgba(0,0,255,0.3)":"rgba(255,0,0,0.3)",stroke:"red",label:["obstacle",`z: ${e.zLayers.join(",")}`].join("\n")});const e=[...this.finishedNodes,...this.unfinishedNodes];for(const s of e){const e=Math.min(...s.availableZ),n=this.unfinishedNodes.length>0&&s===this.unfinishedNodes[this.unfinishedNodes.length-1];t.rects.push({center:{x:s.center.x+e*s.width*.05,y:s.center.y-e*s.width*.05},width:Math.max(s.width-2,.8*s.width),height:Math.max(s.height-2,.8*s.height),fill:s._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)"}[s.availableZ.join(",")]??"rgba(0,200,200,0.1)",stroke:n?"rgba(255,165,0,0.5)":void 0,label:[s.capacityMeshNodeId,`availableZ: ${s.availableZ.join(",")}`,`target? ${s._containsTarget??!1}`,`obs? ${s._containsObstacle??!1}`,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`capacity: ${Pe(s).toFixed(2)}`].join("\n")})}return t.rects.sort((t,e)=>t.center.y-e.center.y),this.srj.connections.forEach((e,s)=>{const n=Y[s%Y.length];for(const i of e.pointsToConnect){const e=ze(i);t.points.push({x:i.x,y:i.y,label:`conn-${s} (${e.join(",")})`,color:n})}}),t}},yi=class extends mi{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e,this.VIA_DIAMETER=t.minViaDiameter??this.VIA_DIAMETER}VIA_DIAMETER=.6;OBSTACLE_MARGIN=.1;OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES=.2;isNodeCompletelyOutsideBounds(t){if(this.outlinePolygon){const e=this.getNodeRect(t);if(!vt(e,this.outlinePolygon))return!0}return t.center.x+t.width/2<this.srj.bounds.minX||t.center.x-t.width/2>this.srj.bounds.maxX||t.center.y+t.height/2<this.srj.bounds.minY||t.center.y-t.height/2>this.srj.bounds.maxY}isNodePartiallyOutsideBounds(t){if(this.outlinePolygon){const e=this.getNodeRect(t);return!!vt(e,this.outlinePolygon)&&!Mt(e,this.outlinePolygon)}return t.center.x-t.width/2<this.srj.bounds.minX||t.center.x+t.width/2>this.srj.bounds.maxX||t.center.y-t.height/2<this.srj.bounds.minY||t.center.y+t.height/2>this.srj.bounds.maxY}getObstacleCoveragePercentage(t){const e=this.getXYZOverlappingObstacles(t);if(0===e.length)return 0;const s=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2,a=t.width*t.height;let r=0;for(const t of e){const e=Math.max(s,t.center.x-t.width/2),a=Math.min(n,t.center.x+t.width/2),h=Math.max(i,t.center.y-t.height/2),c=Math.min(o,t.center.y+t.height/2);if(e<a&&h<c){r+=(a-e)*(c-h)}}return r/a}shouldFilterSingleLayerNodeForObstacle(t){if(1!==t.availableZ.length)return!1;if(!t._containsObstacle)return!1;return this.getObstacleCoveragePercentage(t)>this.OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES}shouldFilterNodeForObstacle(t){return!!t._containsObstacle&&(1!==t.availableZ.length||this.shouldFilterSingleLayerNodeForObstacle(t))}createChildNodeAtPosition(t,e){const s={capacityMeshNodeId:this.getNextNodeId(),center:e.center,width:e.width,height:e.height,layer:t.layer,availableZ:e.availableZ,_depth:e._depth??(t._depth??0)+1,_parent:t},n=this.getXYZOverlappingObstacles(s);s._containsObstacle=n.length>0||this.isNodePartiallyOutsideBounds(s);const i=this.getTargetIfNodeContainsTarget(s);return i&&(s._targetConnectionName=i.connectionName,s._containsTarget=!0),s._containsObstacle&&(s._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(s)),s}getZSubdivisionChildNodes(t){if(1===t.availableZ.length)return[];const e=[],s=t.availableZ.map(t=>[t]);for(const n of s){const s=this.createChildNodeAtPosition(t,{center:{...t.center},width:t.width,height:t.height,availableZ:n,_depth:t._depth});this.isNodeCompletelyOutsideBounds(s)||e.push(s)}return e}getChildNodes(t){if(t._depth>=this.MAX_DEPTH)return[];const e=[],s={width:t.width/2,height:t.height/2},n=[{x:t.center.x-s.width/2,y:t.center.y-s.height/2},{x:t.center.x+s.width/2,y:t.center.y-s.height/2},{x:t.center.x-s.width/2,y:t.center.y+s.height/2},{x:t.center.x+s.width/2,y:t.center.y+s.height/2}];for(const i of n){const n=this.createChildNodeAtPosition(t,{center:i,width:s.width,height:s.height,availableZ:t.availableZ});this.isNodeCompletelyOutsideBounds(n)||e.push(n)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||(1===t.availableZ.length&&t._depth<=this.MAX_DEPTH||!(!t._containsObstacle||t._completelyInsideObstacle)))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),s=[],n=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),i=t.availableZ.length>1&&!e&&(t._containsObstacle||t.width<this.VIA_DIAMETER+this.OBSTACLE_MARGIN);if(e)n.push(t);else if(e||this.shouldFilterNodeForObstacle(t)||i)if(!e&&t._containsTarget)if(i){const e=this.getZSubdivisionChildNodes(t);s.push(...e.filter(t=>t._containsTarget||!this.shouldFilterNodeForObstacle(t)))}else s.push(t);else i&&s.push(...this.getZSubdivisionChildNodes(t).filter(t=>!this.shouldFilterNodeForObstacle(t)));else s.push(t)}this.unfinishedNodes.push(...n),this.finishedNodes.push(...s)}},xi=class extends yi{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e}MAX_SIZE_FOR_SINGLE_LAYER_NODES=2;isObstacleAssignable(t){return Boolean(t?.netIsAssignable)}getOverlappingAssignableObstacles(t){return this.getXYZOverlappingObstacles(t).filter(t=>this.isObstacleAssignable(t))}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||(!(!t._containsObstacle||t._completelyInsideObstacle)||1===t.availableZ.length&&(t.width>this.MAX_SIZE_FOR_SINGLE_LAYER_NODES||t.height>this.MAX_SIZE_FOR_SINGLE_LAYER_NODES)))}shouldFilterNodeForObstacle(t){if(!t._containsObstacle)return!1;return!(this.getOverlappingAssignableObstacles(t).length>0)&&(1!==t.availableZ.length||this.shouldFilterSingleLayerNodeForObstacle(t))}insertAssignableObstaclesAsNodes(){const t=this.srj.obstacles.filter(t=>this.isObstacleAssignable(t)),e=new Map;for(const s of t){const t=[];for(const e of this.finishedNodes){this.getXYZOverlappingObstacles(e).some(t=>t===s)&&t.push(e)}e.set(s,t)}const s=new Set;for(const t of e.values())for(const e of t)s.add(e);this.finishedNodes=this.finishedNodes.filter(t=>!s.has(t));for(const s of t){const t=e.get(s)||[],n=Array.from({length:this.srj.layerCount},(t,e)=>this.srj.layerCount-e-1);let i=s.center.x-s.width/2,o=s.center.x+s.width/2,a=s.center.y-s.height/2,r=s.center.y+s.height/2;for(const e of t){const t=e.center.x-e.width/2,s=e.center.x+e.width/2,n=e.center.y-e.height/2,h=e.center.y+e.height/2;i=Math.min(i,t),o=Math.max(o,s),a=Math.min(a,n),r=Math.max(r,h)}const h=o-i,c=r-a,d=(i+o)/2,l=(a+r)/2;let u=!1;for(const t of this.srj.connections){for(const e of t.pointsToConnect)if(e.x>=i&&e.x<=o&&e.y>=a&&e.y<=r){u=!0;break}if(u)break}const p={capacityMeshNodeId:`assignable_via_${s.center.x}_${s.center.y}`,center:{x:d,y:l},width:h,height:c,layer:1===n.length?`z${n[0]}`:`z${n.join(",")}`,availableZ:n,_depth:0,_containsTarget:u,_containsObstacle:!1,_completelyInsideObstacle:!1};p._assignedViaObstacle=s,this.finishedNodes.push(p)}}_step(){const t=this.unfinishedNodes.pop();if(!t)return this.insertAssignableObstaclesAsNodes(),void(this.solved=!0);const e=this.getChildNodes(t),s=[],n=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),i=t.availableZ.length>1&&!e;if(e)n.push(t);else{if(i){const e=this.getZSubdivisionChildNodes(t);for(const t of e)!t._containsTarget&&this.shouldFilterNodeForObstacle(t)||(this.shouldNodeBeXYSubdivided(t)?n.push(t):(t._containsObstacle=!1,s.push(t)));continue}this.shouldFilterNodeForObstacle(t)&&!t._containsTarget||s.push(t)}}this.unfinishedNodes.push(...n),this.finishedNodes.push(...s)}},vi=.005,Mi=class extends e{nodeMap;currentBatchNodeIds;absorbedNodeIds;nextBatchNodeIds;batchHadModifications;hasComputedAdjacentNodeIds=!1;newNodes;constructor(t){super(),this.nodeMap=new Map,this.MAX_ITERATIONS=1e5;for(const e of t)this.nodeMap.set(e.capacityMeshNodeId,e);this.newNodes=[],this.absorbedNodeIds=new Set;const e=[];for(const s of t)s._assignedViaObstacle?(this.newNodes.push(s),this.absorbedNodeIds.add(s.capacityMeshNodeId)):s._containsTarget?s.availableZ.length>1?(this.newNodes.push(s),this.absorbedNodeIds.add(s.capacityMeshNodeId)):e.push([s,s.width*s.height]):(this.newNodes.push(s),this.absorbedNodeIds.add(s.capacityMeshNodeId));e.sort((t,e)=>t[1]-e[1]);for(const[t,s]of e){const e={...t,center:{...t.center}};this.nodeMap.set(t.capacityMeshNodeId,e)}this.currentBatchNodeIds=e.map(([t])=>t.capacityMeshNodeId),this.nextBatchNodeIds=[],this.batchHadModifications=!1}computeAdjacentNodeIdsForFirstBatch(t){const e=Math.max(...t.map(t=>Math.max(...t.availableZ))),s=[];for(let n=0;n<=e;n++)s.push(new bs(t.filter(t=>t.availableZ[0]===n)));for(const e of t){const t=[],n=s[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const s of n)s._containsTarget&&s._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!s._containsTarget||s._targetConnectionName!==e._targetConnectionName)||s.capacityMeshNodeId!==e.capacityMeshNodeId&&Ms(e,s)&&t.push(s);e._adjacentNodeIds=t.map(t=>t.capacityMeshNodeId)}}getAdjacentSameLayerUnprocessedNodes(t){const e=[],s=Array.from(new Set((t._adjacentNodeIds??[]).map(t=>this.nodeMap.get(t)))).filter(e=>e&&e.capacityMeshNodeId!==t.capacityMeshNodeId);s.sort((t,e)=>t.width*t.height-e.width*e.height);for(const t of s)this.absorbedNodeIds.has(t.capacityMeshNodeId)||e.push(t);return e}_step(){this.hasComputedAdjacentNodeIds||(this.computeAdjacentNodeIdsForFirstBatch(this.currentBatchNodeIds.map(t=>this.nodeMap.get(t))),this.hasComputedAdjacentNodeIds=!0);let t=this.currentBatchNodeIds.pop();for(;t&&this.absorbedNodeIds.has(t);)t=this.currentBatchNodeIds.pop();if(!t)return this.batchHadModifications?(this.currentBatchNodeIds=this.nextBatchNodeIds.sort((t,e)=>{const s=this.nodeMap.get(t),n=this.nodeMap.get(e);return s.width*s.height-n.width*n.height}),this.nextBatchNodeIds=[],void(this.batchHadModifications=!1)):(this.solved=!0,void this.newNodes.push(...this.nextBatchNodeIds.map(t=>this.nodeMap.get(t))));const e=this.nodeMap.get(t);let s=!1;const n=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===n.length)return void this.nextBatchNodeIds.push(t);const i=t=>{for(const e of t)this.absorbedNodeIds.add(e.capacityMeshNodeId);e._adjacentNodeIds=Array.from(new Set([...e._adjacentNodeIds??[],...t.flatMap(t=>t._adjacentNodeIds??[])].filter(t=>t!==e.capacityMeshNodeId&&!this.absorbedNodeIds.has(t))))},o=n.filter(t=>t.center.x<e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(o.length>0){const{width:t,height:n}=o[0],a=o.every(e=>e.width===t&&e.height===n);Math.abs(o.reduce((t,e)=>t+e.height,0)-e.height)<vi&&a&&(e.width+=t,e.center.x=e.center.x-t/2,i(o),s=!0)}const a=n.filter(t=>t.center.x>e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(a.length>0&&!s){const{width:t,height:n}=a[0],o=a.every(e=>e.width===t&&e.height===n);Math.abs(a.reduce((t,e)=>t+e.height,0)-e.height)<vi&&o&&(e.width+=t,e.center.x=e.center.x+t/2,i(a),s=!0)}const r=n.filter(t=>t.center.y>e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(r.length>0&&!s){const{width:t,height:n}=r[0],o=r.every(e=>e.width===t&&e.height===n);Math.abs(r.reduce((t,e)=>t+e.width,0)-e.width)<vi&&o&&(e.height+=n,e.center.y=e.center.y+n/2,i(r),s=!0)}const h=n.filter(t=>t.center.y<e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(h.length>0&&!s){const{width:t,height:n}=h[0],o=h.every(e=>e.width===t&&e.height===n);Math.abs(h.reduce((t,e)=>t+e.width,0)-e.width)<vi&&o&&(e.height+=n,e.center.y=e.center.y-n/2,i(h),s=!0)}s?(this.batchHadModifications=!0,this.currentBatchNodeIds.push(t)):this.nextBatchNodeIds.unshift(t)}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Single Layer Node Merger (Only Merge Targets)"};for(const e of this.newNodes)t.rects.push(ss(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let s;e&&(s=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const n of this.currentBatchNodeIds){const i=this.nodeMap.get(n);if(!this.absorbedNodeIds.has(n)&&i){const o=ss(i,{rectMargin:.01});n===e?o.stroke="rgba(0, 255, 0, 0.8)":s?.some(t=>t.capacityMeshNodeId===n)?o.stroke="rgba(128, 0, 128, 0.8)":o.stroke="rgba(255, 165, 0, 0.8)",o.layer=`z${i.availableZ.join(",")}`,o.label=`${o.label}\n(unprocessed)`,t.rects.push(o)}}for(const e of this.nextBatchNodeIds){const s=this.nodeMap.get(e);if(!this.absorbedNodeIds.has(e)&&s){const e=ss(s,{rectMargin:.01});e.layer=`z${s.availableZ.join(",")}`,e.stroke="rgba(0, 217, 255, 0.8)",e.label=`${e.label}\nx: ${s.center.x}, y: ${s.center.y}\n${s.width}x${s.height}\n(next batch)`,t.rects.push(e)}}return t}},Si=class extends e{newNodes;obstacleToNodesMap;obstaclesToProcess;mergedNodeIds;constructor(t){super(),this.MAX_ITERATIONS=1e4,this.newNodes=[],this.obstacleToNodesMap=new Map,this.mergedNodeIds=new Set;for(const e of t){const t=e._assignedViaObstacle;if(t){const s=this.obstacleToNodesMap.get(t)||[];s.push(e),this.obstacleToNodesMap.set(t,s)}else this.newNodes.push(e)}this.obstaclesToProcess=Array.from(this.obstacleToNodesMap.keys())}_step(){const t=this.obstaclesToProcess.pop();if(!t)return void(this.solved=!0);const e=this.obstacleToNodesMap.get(t);if(!e||0===e.length)return;let s=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY,o=Number.NEGATIVE_INFINITY;const a=new Set;let r=!1;for(const t of e){const e=t.center.x-t.width/2,h=t.center.x+t.width/2,c=t.center.y-t.height/2,d=t.center.y+t.height/2;s=Math.min(s,e),n=Math.max(n,h),i=Math.min(i,c),o=Math.max(o,d);for(const e of t.availableZ)a.add(e);t._containsTarget&&(r=!0)}const h=n-s,c=o-i,d=(s+n)/2,l=(i+o)/2,u=Array.from(a).sort((t,e)=>t-e),p={capacityMeshNodeId:`merged_via_${t.center.x}_${t.center.y}`,center:{x:d,y:l},width:h,height:c,layer:1===u.length?`z${u[0]}`:`z${u.join(",")}`,availableZ:u,_containsTarget:r,_containsObstacle:!1,_completelyInsideObstacle:!1};p._assignedViaObstacle=t;for(const t of e)this.mergedNodeIds.add(t.capacityMeshNodeId);this.newNodes.push(p)}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Assignable Via Node Merger"};for(const e of this.newNodes){const s=ss(e);e._assignedViaObstacle&&(s.stroke="rgba(255, 0, 255, 0.8)",s.label=`${s.label||""}\n(merged via)`),t.rects.push(s)}const e=this.obstaclesToProcess[this.obstaclesToProcess.length-1];if(e){const s=this.obstacleToNodesMap.get(e)||[];for(const e of s){const s=ss(e,{rectMargin:.01});s.stroke="rgba(0, 255, 0, 0.8)",s.label=`${s.label||""}\n(to be merged)`,t.rects.push(s)}}return t}},bi=class extends e{constructor(t){const{simpleRouteJson:e,nodes:n,edges:i,colorMap:o,MAX_ITERATIONS:a=1e6,hyperParameters:r={}}=t;super(),this.inputParams=t,this.hyperParameters=r,this.MAX_ITERATIONS=a,this.simpleRouteJson=e,this.nodes=n,this.edges=i,this.colorMap=o??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=s(this.edges);const h=this.nodes.filter(t=>t._containsTarget);this.unprocessedConnectionPairs=zt(this.simpleRouteJson.connections.map(t=>{const[e,s]=t.pointsToConnect;return{start:h.find(t=>dt(t.center,e)<t.width/2),end:h.find(t=>dt(t.center,s)<t.width/2),connection:t}}),this.hyperParameters.SHUFFLE_SEED??0),this.viaNodes=this.nodes.filter(t=>t.availableZ.length>1)}GREEDY_MULTIPLIER=1.5;simpleRouteJson;nodes;edges;colorMap;MAX_ITERATIONS;hyperParameters;usedNodeMap=new Map;nodeMap;nodeEdgeMap;unprocessedConnectionPairs;solvedRoutes=[];activeConnectionPair=null;ogUnprocessedSubpaths=null;unprocessedSubpaths=null;solvedSubpaths=null;activeSubpath=null;viaNodes=[];closestViaForConnectionStartMap=new Map;closestViaForConnectionEndMap=new Map;getConstructorParams(){return this.inputParams}lastStepOperation="none";computeClosestViaForAllConnections(){this.closestViaForConnectionStartMap.clear(),this.closestViaForConnectionEndMap.clear();for(const t of this.unprocessedConnectionPairs){const e=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId));if(e.length>0){const s=e.reduce((e,s)=>{const n=this._dist(e,t.start);return this._dist(s,t.start)<n?s:e});this.closestViaForConnectionStartMap.set(t,s);const n=e.reduce((e,s)=>{const n=this._dist(e,t.end);return this._dist(s,t.end)<n?s:e});this.closestViaForConnectionEndMap.set(t,n)}}}_step(){if(!this.activeConnectionPair)return this.activeConnectionPair=this.unprocessedConnectionPairs.shift(),this.activeConnectionPair?(this.computeClosestViaForAllConnections(),void(this.lastStepOperation="dequeueConnectionPair")):void(this.solved=!0);if(this.activeConnectionPair&&!this.unprocessedSubpaths)return this.unprocessedSubpaths=this.breakConnectionPairIntoSubpaths(this.activeConnectionPair),this.ogUnprocessedSubpaths=this.unprocessedSubpaths.slice(),this.solvedSubpaths=[],void(this.lastStepOperation="breakConnectionPairIntoSubpaths");if(this.activeSubpath){if(this.activeSubpath&&(this.stepSolveSubpath(this.activeSubpath),this.activeSubpath.solved))return this.solvedSubpaths.push(this.activeSubpath),this.activeSubpath=null,this.clearCandidateNodes(),void(this.lastStepOperation="finishedSolvingSubpath");this.lastStepOperation="stepSolveSubpath"}else{if(this.activeSubpath=this.unprocessedSubpaths.shift(),!this.activeSubpath){const t=this.activeConnectionPair;return this.activeConnectionPair=null,this.unprocessedSubpaths=null,this.ogUnprocessedSubpaths=null,this.activeSubpath=null,this.solvedRoutes.push(this.createSolvedRoute(this.solvedSubpaths,t)),void(this.lastStepOperation="finishedSolvingConnectionPair")}this.lastStepOperation="dequeueSubpath"}}queuedCandidateNodes=[];visitedNodes=new Set;_dist(t,e){return Math.hypot(t.center.x-e.center.x,t.center.y-e.center.y)}stepSolveSubpath(t){const{start:e,end:s}=t;if(e.capacityMeshNodeId===s.capacityMeshNodeId)return t.path=[e],t.solved=!0,void this.usedNodeMap.set(e.capacityMeshNodeId,!0);if(0===this.queuedCandidateNodes.length&&0===this.visitedNodes.size){const t=this._dist(e,s),n={prevCandidate:null,node:e,g:0,h:t,f:this.GREEDY_MULTIPLIER*t};this.queuedCandidateNodes.push(n)}let n;for(this.queuedCandidateNodes.sort((t,e)=>t.f-e.f);this.queuedCandidateNodes.length&&!n;){const t=this.queuedCandidateNodes.shift();this.visitedNodes.has(t.node.capacityMeshNodeId)||(n=t)}if(!n)return this.failed=!0,void(this.error="No viable candidates left");if(this.visitedNodes.add(n.node.capacityMeshNodeId),n.node.capacityMeshNodeId===s.capacityMeshNodeId){const e=[];let s=n;for(;s;)e.unshift(s.node),this.usedNodeMap.set(s.node.capacityMeshNodeId,!0),s=s.prevCandidate;return t.path=e,void(t.solved=!0)}const i=this.getNeighbors(n.node);for(const t of i){const e=t.capacityMeshNodeId;if(this.visitedNodes.has(e))continue;const i=this.computeG(n,t,s),o=this.computeH(n,t,s),a=i+this.GREEDY_MULTIPLIER*o,r=this.queuedCandidateNodes.findIndex(t=>t.node.capacityMeshNodeId===e);if(r>=0){if(this.queuedCandidateNodes[r].g<=i)continue;this.queuedCandidateNodes.splice(r,1)}this.queuedCandidateNodes.push({prevCandidate:n,node:t,g:i,h:o,f:a})}}getNeighbors(t){const e=new Set,s=this.nodeEdgeMap.get(t.capacityMeshNodeId)??[];for(const n of s){const[s,i]=n.nodeIds,o=s===t.capacityMeshNodeId?i:s,a=this.nodeMap.get(o);a&&e.add(a)}const n=this.activeSubpath?.layer;return Array.from(e).filter(t=>!(t.capacityMeshNodeId!==this.activeSubpath?.end.capacityMeshNodeId)||!t._containsObstacle&&(!t._containsTarget&&(!this.usedNodeMap.has(t.capacityMeshNodeId)&&!(void 0!==n&&!t.availableZ.includes(n)))))}clearCandidateNodes(){this.queuedCandidateNodes=[],this.visitedNodes=new Set}computeG(t,e,s){const n=this._dist(t.node,e);return t.g+n}computeH(t,e,s){return this._dist(e,s)}createSolvedRoute(t,e){const s=[];for(let e=0;e<t.length;e++){const n=t[e];n.path?0===e?s.push(...n.path):s.push(...n.path.slice(1)):(0===e&&s.push(n.start),e===t.length-1&&s.push(n.end))}return{connection:e.connection,path:s}}breakConnectionPairIntoSubpaths(t){var e,s;if(!(e=[this.hyperParameters.DIRECTIVE_SEED??0,this.solvedRoutes.length],s=this.hyperParameters.FORCE_VIA_TRAVEL_CHANCE??0,Tt(e.reduce((t,e)=>t+16807*e%2147483647,0))()<s))return[{start:t.start,end:t.end,solved:!1,layer:t.start.availableZ[0]??0}];const n=this.getClosestVia(t.start),i=this.getFarVia(n,t.end),o=t.start.availableZ[0]??0,a=t.end.availableZ[0]??0,r=[];return r.push({start:t.start,end:n,solved:!1,layer:o}),o===a?(r.push({start:n,end:i,solved:!1,layer:0===o?1:0}),r.push({start:i,end:t.end,solved:!1,layer:a})):r.push({start:n,end:t.end,solved:!1,layer:a}),r}getClosestVia(t){if(0===this.viaNodes.length)return t;const e=new Set;for(const[t,s]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&e.add(s.capacityMeshNodeId);for(const[t,s]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&e.add(s.capacityMeshNodeId);const s=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId)).filter(t=>!e.has(t.capacityMeshNodeId));if(0===s.length){const e=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId));return 0===e.length?t:(e.sort((e,s)=>this._dist(e,t)-this._dist(s,t)),e[0])}s.sort((e,s)=>this._dist(e,t)-this._dist(s,t));const n=this.hyperParameters.MAX_CLOSEST_VIA_SKIP??0;if(n>0&&s.length>1){const t=Tt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length),e=Math.floor(t()*(n+1));return s[Math.min(e,s.length-1)]}return s[0]}getFarVia(t,e){if(0===this.viaNodes.length)return t;const s=null!=this.hyperParameters.FAR_VIA_MIN_DISTANCE?this.hyperParameters.FAR_VIA_MIN_DISTANCE:50,n=new Set;for(const[t,e]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&n.add(e.capacityMeshNodeId);for(const[t,e]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&n.add(e.capacityMeshNodeId);const i=this.viaNodes.filter(e=>!this.usedNodeMap.has(e.capacityMeshNodeId)&&e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!n.has(e.capacityMeshNodeId)&&this._dist(e,t)>=s);if(0===i.length){const n=this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)&&this._dist(e,t)>=s).sort((t,s)=>this._dist(t,e)-this._dist(s,e));if(n.length>0)return n[0];return this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)).sort((t,s)=>this._dist(t,e)-this._dist(s,e))[0]??t}i.sort((t,s)=>this._dist(t,e)-this._dist(s,e));const o=this.hyperParameters.MAX_FURTHEST_VIA_SKIP??0;if(o>0&&i.length>1){const t=Tt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length+1e3),e=Math.floor(t()*(o+1));return i[Math.min(e,i.length-1)]}return i[0]}getCapacityPaths(){const t=[];for(const e of this.solvedRoutes){const s=e.path;s&&s.length>0&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:s.map(t=>t.capacityMeshNodeId)})}return t}visualize(){const t={lines:[],points:[],rects:[],circles:[]},e=t=>!!t&&"number"==typeof t.x&&"number"==typeof t.y&&!Number.isNaN(t.x)&&!Number.isNaN(t.y)&&Number.isFinite(t.x)&&Number.isFinite(t.y),s=t=>"number"==typeof t&&!Number.isNaN(t)&&Number.isFinite(t);for(const n of this.nodes){const i=this.queuedCandidateNodes.some(t=>t.node.capacityMeshNodeId===n.capacityMeshNodeId),o=this.queuedCandidateNodes.find(t=>t.node.capacityMeshNodeId===n.capacityMeshNodeId);if(e(n.center)&&s(n.width)&&s(n.height)){const e=ss(n,{rectMargin:.025,zOffset:.01});t.rects.push({...e,fill:i?"rgba(255, 128, 255, 0.5)":n._containsTarget?"rgba(0, 150, 255, 0.15)":n._containsObstacle?"rgba(255, 0, 0, 0.1)":"rgba(200, 200, 200, 0.05)",label:[`ID: ${n.capacityMeshNodeId}`,`Size: ${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Z: ${n.availableZ.join(", ")}`,o?`g: ${o.g.toFixed(2)}`:"",o?`h: ${o.h.toFixed(2)}`:"",o?`f: ${o.f.toFixed(2)}`:"",n._containsTarget?"TARGET":"",n._containsObstacle?"OBSTACLE":""].filter(t=>t).join("\n")})}}for(const s of this.edges){const[n,i]=s.nodeIds,o=this.nodeMap.get(n),a=this.nodeMap.get(i);o?.center&&a?.center&&e(o.center)&&e(a.center)&&t.lines.push({points:[o.center,a.center],strokeColor:"rgba(150, 150, 150, 0.2)"})}for(let s=0;s<this.solvedRoutes.length;s++){const n=this.solvedRoutes[s],i=n.path,o="blue";for(let n=0;n<i.length-1;n++){const a=i[n],r=i[n+1];if(a?.center&&r?.center&&e(a.center)&&e(r.center)){const e=a.availableZ.includes(1)&&r.availableZ.includes(1),n=s%5*.02;t.lines.push({points:[{x:a.center.x+n,y:a.center.y+n},{x:r.center.x+n,y:r.center.y+n}],strokeColor:o,strokeDash:e?"5 5":void 0})}}if(i.length>0){const s=i[0],o=i[i.length-1];s?.center&&e(s.center)&&t.points.push({x:s.center.x,y:s.center.y,label:`START: ${n.connection.name}`}),o?.center&&e(o.center)&&t.points.push({x:o.center.x,y:o.center.y,label:`END: ${n.connection.name}`})}}if(this.solvedSubpaths)for(let s=0;s<this.solvedSubpaths.length;s++){const n=this.solvedSubpaths[s];if(n.path&&n.path.length>1)for(let s=0;s<n.path.length-1;s++){const i=n.path[s],o=n.path[s+1];i?.center&&o?.center&&e(i.center)&&e(o.center)&&t.lines.push({points:[i.center,o.center],strokeColor:"green",strokeDash:1===n.layer?"3 3":void 0})}}if(this.activeSubpath){const s=this.activeSubpath.start?.center,n=this.activeSubpath.end?.center;s&&n&&e(s)&&e(n)&&(t.lines.push({points:[s,n],strokeColor:"orange",strokeDash:"5 5"}),t.points.push({x:s.x,y:s.y,label:"ACTIVE START"}),t.points.push({x:n.x,y:n.y,label:"ACTIVE END"}))}const n=this.queuedCandidateNodes.slice(0,10).sort((t,e)=>t.f-e.f);for(let s=0;s<n.length;s++){const i=.6*(1-s/10),o=[];let a=n[s];for(;a;)o.push(a.node),a=a.prevCandidate;if(o.reverse(),o.length>1){const s=o.map(t=>t.center).filter(t=>e(t));s.length>1&&t.lines.push({points:s,strokeColor:V("purple",1-i),strokeDash:1===this.activeSubpath?.layer?"4 2":void 0})}}if(this.activeConnectionPair){const s=this.activeConnectionPair.start?.center,n=this.activeConnectionPair.end?.center;s&&n&&e(s)&&e(n)&&t.lines.push({points:[s,n],strokeColor:"cyan",strokeDash:"20 5"})}if(this.ogUnprocessedSubpaths&&3===this.ogUnprocessedSubpaths.length){const[,n]=this.ogUnprocessedSubpaths;if(n.start?.center&&e(n.start.center)){const e=Math.max(n.start.width||0,n.start.height||0);s(e)&&e>0&&(t.circles.push({center:n.start.center,radius:e,stroke:"blue"}),t.points.push({x:n.start.center.x,y:n.start.center.y,label:"DIRECTIVE VIA 1"}))}if(n.end?.center&&e(n.end.center)){const e=Math.max(n.end.width||0,n.end.height||0);s(e)&&e>0&&(t.circles.push({center:n.end.center,radius:e,stroke:"purple"}),t.points.push({x:n.end.center.x,y:n.end.center.y,label:"DIRECTIVE VIA 2"}))}}if(this.queuedCandidateNodes.length>0)for(const s of this.queuedCandidateNodes){const n=s.node;n?.center&&e(n.center)&&t.circles.push({center:n.center,radius:.05,fill:"rgba(255, 255, 0, 0.6)",stroke:"yellow"})}if(this.visitedNodes.size>0)for(const s of this.visitedNodes){const n=this.nodeMap.get(s);n?.center&&e(n.center)&&t.circles.push({center:n.center,radius:.08,fill:"rgba(128, 128, 128, 0.5)",stroke:"gray"})}return t}},Ni=class extends $t{constructorParams;constructor(t){super(),this.constructorParams=t,this.MAX_ITERATIONS=t.MAX_ITERATIONS??12e4,this.MIN_SUBSTEPS=5,this.GREEDY_MULTIPLIER=1.35}getHyperParameterDefs(){return[{name:"traceOrderingSeed",possibleValues:[{SHUFFLE_SEED:0},{SHUFFLE_SEED:1},{SHUFFLE_SEED:2},{SHUFFLE_SEED:3},{SHUFFLE_SEED:4},{SHUFFLE_SEED:5},{SHUFFLE_SEED:6},{SHUFFLE_SEED:7},{SHUFFLE_SEED:8},{SHUFFLE_SEED:9}]},{name:"forceViaTravelChance",possibleValues:[{FORCE_VIA_TRAVEL_CHANCE:.6},{FORCE_VIA_TRAVEL_CHANCE:.8},{FORCE_VIA_TRAVEL_CHANCE:.9}]}]}computeG(t){const e=t.unprocessedConnectionPairs.length+t.solvedRoutes.length+(t.activeConnectionPair?1:0),s=t.solvedRoutes.length,n=e>0?s/e:0;return t.iterations/t.MAX_ITERATIONS+(1-n)}computeH(t){const e=t.unprocessedConnectionPairs.length+t.solvedRoutes.length+(t.activeConnectionPair?1:0),s=t.solvedRoutes.length;return e>0?1-s/e:0}generateSolver(t){return new bi({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}};function Ii(t){const e=new Map;for(const s of t)e.set(s.capacityMeshNodeId,s);return e}function Pi(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var Ci=class extends e{capacityNodes;capacityEdges;enhancedEdges=[];animationState="showing_nodes";assignableNodes=[];shownNodes=[];pendingEdges=[];createdEdges=[];nextEdgeId=0;nodeMap=new Map;constructor(t){super(),this.capacityNodes=t.capacityNodes,this.capacityEdges=t.capacityEdges,this.nodeMap=Ii(this.capacityNodes),this.enhancedEdges=[...this.capacityEdges],this.initializeAssignableNodes(),this.initializePendingEdges(),this.MAX_ITERATIONS=this.assignableNodes.length+this.pendingEdges.length+10}initializeAssignableNodes(){for(const t of this.capacityNodes){const e=t._assignedViaObstacle;e?.offBoardConnectsTo&&e.offBoardConnectsTo.length>0&&this.assignableNodes.push(t)}}initializePendingEdges(){const t=new Map;for(const e of this.assignableNodes){const s=e._assignedViaObstacle;if(s?.offBoardConnectsTo)for(const n of s.offBoardConnectsTo)t.has(n)||t.set(n,[]),t.get(n).push(e)}this.pendingEdges=[];for(const[e,s]of t)if(s.length>1)for(let t=0;t<s.length;t++)for(let n=t+1;n<s.length;n++)this.pendingEdges.push({node1:s[t],node2:s[n],netName:e})}_step(){switch(this.animationState){case"showing_nodes":if(this.assignableNodes.length>0){const t=this.assignableNodes.shift();this.shownNodes.push(t)}else this.animationState="showing_edges";break;case"showing_edges":if(this.pendingEdges.length>0){const{node1:t,node2:e,netName:s}=this.pendingEdges.shift(),n=this.createOffboardEdge(t,e,s);this.enhancedEdges.push(n),this.createdEdges.push(n)}else this.animationState="done",this.solved=!0;break;case"done":this.solved=!0}}createOffboardEdge(t,e,s){return{capacityMeshEdgeId:"offboard_"+this.nextEdgeId++,nodeIds:[t.capacityMeshNodeId,e.capacityMeshNodeId],isOffboardEdge:!0,offboardNetName:s}}visualize(){const t=[],e=[],s=[],n=new Set(this.shownNodes.map(t=>t.capacityMeshNodeId));for(const e of this.capacityEdges){if(e.isOffboardEdge)continue;if(n.has(e.nodeIds[0])||n.has(e.nodeIds[1])){const s=this.nodeMap.get(e.nodeIds[0]),n=this.nodeMap.get(e.nodeIds[1]);s&&n&&t.push({points:[s.center,n.center],strokeColor:"rgba(0, 200, 0, 0.5)",strokeWidth:.05})}}for(let t=0;t<this.shownNodes.length;t++){const n=this.shownNodes[t],i=n._assignedViaObstacle,o=t===this.shownNodes.length-1&&"showing_nodes"===this.animationState;s.push({center:n.center,width:n.width,height:n.height,fill:o?"rgba(255, 165, 0, 0.5)":"rgba(173, 216, 230, 0.5)",stroke:o?"orange":"blue",strokeWidth:o?.15:.1}),e.push({x:n.center.x,y:n.center.y,color:o?"orange":"blue",label:`${o?"NEW: ":""}${n.capacityMeshNodeId}\n${i?.offBoardConnectsTo?.join(", ")||""}`})}for(let s=0;s<this.createdEdges.length;s++){const n=this.createdEdges[s],i=s===this.createdEdges.length-1&&"showing_edges"===this.animationState,o=this.nodeMap.get(n.nodeIds[0]),a=this.nodeMap.get(n.nodeIds[1]);if(o&&a){t.push({points:[o.center,a.center],strokeColor:i?"red":"orange",strokeWidth:i?.2:.1,strokeDasharray:"0.3,0.15"});const s=Pi(o.center,a.center);e.push({x:s.x,y:s.y,color:i?"red":"orange",label:`${i?"NEW: ":""}⚡ ${n.offboardNetName}`})}}let i="Offboard Capacity Node Solver";switch(this.animationState){case"showing_nodes":i+=` - Showing nodes (${this.shownNodes.length}/${this.shownNodes.length+this.assignableNodes.length})`;break;case"showing_edges":i+=` - Creating edges (${this.createdEdges.length}/${this.createdEdges.length+this.pendingEdges.length})`;break;case"done":i+=` - Done (${this.shownNodes.length} nodes, ${this.createdEdges.length} edges)`}return{lines:t,points:e,rects:s,title:i}}getVirtualOffboardNodes(){return[]}getOffboardEdges(){return this.enhancedEdges.filter(t=>t.isOffboardEdge)}};function _i(t,e){return t.x>=e.center.x-e.width/2&&t.x<=e.center.x+e.width/2&&t.y>=e.center.y-e.height/2&&t.y<=e.center.y+e.height/2}var Ei=class extends e{inputPaths;capacityEdges;originalConnections;fragmentedPaths=[];fragmentedConnections=[];fragmentedOriginalConnectionNames=new Set;nextFragmentId=0;animationState="showing_original_path";currentPath=null;currentFragments=[];currentFragmentIndex=0;nodeMap=new Map;constructor({capacityPaths:t,capacityEdges:e,capacityNodes:s,connections:n}){super(),this.inputPaths=[...t],this.capacityEdges=e,this.originalConnections=n,this.nodeMap=Ii(s)}_step(){switch(this.animationState){case"showing_original_path":if(0===this.inputPaths.length)return this.animationState="done",void(this.solved=!0);this.currentPath=this.inputPaths.shift(),this.currentFragments=this.splitPath(this.currentPath),this.currentFragmentIndex=0;this.currentFragments.some(t=>t.isFragmentedPath)?this.animationState="showing_fragment":this.fragmentedPaths.push(...this.currentFragments);break;case"showing_fragment":if(this.currentFragmentIndex<this.currentFragments.length){const t=this.currentFragments[this.currentFragmentIndex];this.fragmentedPaths.push(t),this.currentFragmentIndex++}else this.currentPath&&(this.fragmentedOriginalConnectionNames.add(this.currentPath.connectionName),this.createFragmentConnections(this.currentPath,this.currentFragments)),this.currentPath=null,this.currentFragments=[],this.currentFragmentIndex=0,this.animationState="showing_original_path";break;case"done":this.solved=!0}}createFragmentConnections(t,e){const s=this.originalConnections.find(e=>e.name===t.connectionName);if(s)for(let t=0;t<e.length;t++){const n=e[t];if(!n.isFragmentedPath)continue;const i=s.pointsToConnect.filter(t=>{for(const e of n.nodeIds){const s=this.nodeMap.get(e);if(s&&_i(t,s))return!0}return!1}),o=0===t,a=o?n.nodeIds[n.nodeIds.length-1]:n.nodeIds[0],r=this.nodeMap.get(a);if(i.length>0&&r){const t=i[0],e={x:r.center.x,y:r.center.y,layer:we(t)},a=o?[...i,e]:[e,...i];this.fragmentedConnections.push({name:n.connectionName,pointsToConnect:a,netConnectionName:s.netConnectionName})}}}splitPath(t){const{nodeIds:e}=t;if(e.length<2)return[t];const s=[];for(let t=0;t<e.length-1;t++){const n=this.capacityEdges.find(s=>s.nodeIds[0]===e[t]&&s.nodeIds[1]===e[t+1]||s.nodeIds[0]===e[t+1]&&s.nodeIds[1]===e[t]);n&&n.isOffboardEdge&&s.push(t)}if(0===s.length)return[t];const n=[];let i=0,o=0;for(const a of s){const s=e.slice(i,a+1);if(s.length>=1){const e=this.nextFragmentId++;n.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${o++}`,nodeIds:s,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}i=a+1}if(i<e.length){const s=e.slice(i);if(s.length>=1){const e=this.nextFragmentId++;n.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${o++}`,nodeIds:s,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}}return n.length>0?n:[t]}getFragmentedPaths(){return this.fragmentedPaths}getFragmentedConnections(){return this.fragmentedConnections}getFragmentedOriginalConnectionNames(){return this.fragmentedOriginalConnectionNames}visualize(){const t=[],e=[],s=[];if("showing_original_path"===this.animationState&&this.currentPath&&this.drawPath({path:this.currentPath,color:"gray",lines:t,points:e,rects:s,labelPrefix:"Original: "}),this.fragmentedPaths.forEach((n,i)=>{if(n.isFragmentedPath){const o=i%2==0?"blue":"red";this.drawPath({path:n,color:o,lines:t,points:e,rects:s,labelPrefix:`Frag ${i}: `})}else this.drawPath({path:n,color:"green",lines:t,points:e,rects:s,labelPrefix:""})}),"showing_fragment"===this.animationState&&this.currentFragmentIndex>0){const n=this.fragmentedPaths.length-1;if(n>=0){const i=this.fragmentedPaths[n];i.isFragmentedPath&&this.drawPath({path:i,color:"orange",lines:t,points:e,rects:s,labelPrefix:"NEW: "})}}for(const e of this.capacityEdges)if(e.isOffboardEdge){const s=this.nodeMap.get(e.nodeIds[0]),n=this.nodeMap.get(e.nodeIds[1]);s&&n&&t.push({points:[s.center,n.center],strokeColor:"orange",strokeWidth:.15,strokeDasharray:"0.3,0.15"})}let n="Offboard Path Fragment Solver";return"showing_original_path"===this.animationState?n+=" - Analyzing path...":"showing_fragment"===this.animationState?n+=` - Fragment ${this.currentFragmentIndex}/${this.currentFragments.length}`:n+=` - Done (${this.fragmentedPaths.filter(t=>t.isFragmentedPath).length} fragments)`,{lines:t,points:e,rects:s,title:n}}drawPath(t){const{path:e,color:s,lines:n,points:i,rects:o,labelPrefix:a}=t,r=[];for(let t=0;t<e.nodeIds.length;t++){const n=e.nodeIds[t],h=this.nodeMap.get(n);h&&(r.push(h.center),o.push({center:h.center,width:.8*h.width,height:.8*h.height,stroke:s,strokeWidth:.05,fill:`${s}33`}),0!==t&&t!==e.nodeIds.length-1||i.push({x:h.center.x,y:h.center.y,color:s,label:`${a}${e.connectionName}\n${n}`}))}r.length>1&&n.push({points:r,strokeColor:s,strokeWidth:.1})}};function Ti(t,e,s,n={}){return{solverName:t,solverClass:e,getConstructorParams:s,onSolved:n.onSolved}}var wi=class extends e{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,void 0===e.capacityDepth){const s=t.bounds.maxX-t.bounds.minX,n=t.bounds.maxY-t.bounds.minY,i=Math.max(s,n),o=e.targetMinCapacity??.5;e.capacityDepth=Ce(i,o)}this.connMap=Ie(t),this.colorMap=H(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?st():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;initialPathingSolver;initialPathingHyperSolver;pathingOptimizer;edgeToPortSegmentSolver;colorMap;segmentToPointSolver;unravelMultiSectionSolver;segmentToPointOptimizer;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;mergeAssignableViaNodes;offboardCapacityNodeSolver;offboardPathFragmentSolver;strawSolver;deadEndSolver;uselessViaRemovalSolver1;uselessViaRemovalSolver2;multiSimplifiedPathSolver1;multiSimplifiedPathSolver2;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[Ti("netToPointPairsSolver",zs,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=H(t.srjWithPointPairs,this.connMap),t.connMap=Ie(t.srjWithPointPairs)}}),Ti("nodeSolver",xi,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),Ti("mergeAssignableViaNodes",Si,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.mergeAssignableViaNodes?.newNodes}}),Ti("singleLayerNodeMerger",Mi,t=>[t.capacityNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),Ti("edgeSolver",Ns,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Ti("offboardCapacityNodeSolver",Ci,t=>[{capacityNodes:t.capacityNodes,capacityEdges:t.capacityEdges||[]}],{onSolved:t=>{t.capacityEdges=t.offboardCapacityNodeSolver?.enhancedEdges||t.capacityEdges}}),Ti("deadEndSolver",Is,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges}],{onSolved:t=>{const e=t.deadEndSolver?.removedNodeIds;t.capacityNodes=t.capacityNodes.filter(t=>!e.has(t.capacityMeshNodeId)),t.capacityEdges=t.capacityEdges.filter(t=>t.nodeIds.every(t=>!e.has(t)))}}),Ti("initialPathingHyperSolver",Ni,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}],{onSolved:t=>{const e=t.initialPathingHyperSolver?.winningSolver;e&&(t.initialPathingSolver=e)}}),Ti("offboardPathFragmentSolver",Ei,t=>[{capacityPaths:t.initialPathingSolver?.getCapacityPaths()||[],capacityEdges:t.capacityEdges||[],capacityNodes:t.capacityNodes||[],connections:t.srjWithPointPairs?.connections||[]}],{onSolved:t=>{const e=t.offboardPathFragmentSolver;if(!e)return;const s=e.getFragmentedPaths();for(const e of s)if(e.isFragmentedPath&&e.mstPairConnectionName){const s=t.colorMap[e.mstPairConnectionName];s&&!t.colorMap[e.connectionName]&&(t.colorMap[e.connectionName]=s)}const n=e.getFragmentedOriginalConnectionNames(),i=e.getFragmentedConnections();n.size>0&&t.srjWithPointPairs&&(t.srjWithPointPairs={...t.srjWithPointPairs,connections:[...t.srjWithPointPairs.connections.filter(t=>!n.has(t.name)),...i]},t.connMap=Ie(t.srjWithPointPairs))}}),Ti("edgeToPortSegmentSolver",j,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.offboardPathFragmentSolver?.getFragmentedPaths()||t.initialPathingSolver?.getCapacityPaths()||[],colorMap:t.colorMap}]),Ti("segmentToPointSolver",q,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),Ti("unravelMultiSectionSolver",es,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),Ti("highDensityRouteSolver",be,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap}]),Ti("highDensityStitchSolver",De,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Ti("uselessViaRemovalSolver1",Un,t=>[{unsimplifiedHdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Ti("multiSimplifiedPathSolver1",ci,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver1?.getOptimizedHdRoutes()||t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}]),Ti("uselessViaRemovalSolver2",Un,t=>[{unsimplifiedHdRoutes:t.multiSimplifiedPathSolver1.simplifiedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Ti("multiSimplifiedPathSolver2",ci,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver2?.getOptimizedHdRoutes(),obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}])];currentPipelineStepIndex=0;_step(){const t=this.pipelineDef[this.currentPipelineStepIndex];if(!t)return void(this.solved=!0);if(this.activeSubSolver)return this.activeSubSolver.step(),void(this.activeSubSolver.solved?(this.endTimeOfPhase[t.solverName]=performance.now(),this.timeSpentOnPhase[t.solverName]=this.endTimeOfPhase[t.solverName]-this.startTimeOfPhase[t.solverName],t.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStepIndex++):this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null));const e=t.getConstructorParams(this);this.activeSubSolver=new t.solverClass(...e),this[t.solverName]=this.activeSubSolver,this.timeSpentOnPhase[t.solverName]=0,this.startTimeOfPhase[t.solverName]=performance.now()}solveUntilPhase(t){for(;this.getCurrentPhase()!==t;)this.step()}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();const e=this.netToPointPairsSolver?.visualize(),s=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),i=this.mergeAssignableViaNodes?.visualize(),o=this.singleLayerNodeMerger?.visualize(),a=this.strawSolver?.visualize(),r=this.edgeSolver?.visualize(),h=this.deadEndSolver?.visualize(),c=this.initialPathingSolver?.visualize(),d=this.offboardPathFragmentSolver?.visualize(),l=this.pathingOptimizer?.visualize(),u=this.edgeToPortSegmentSolver?.visualize(),p=this.segmentToPointSolver?.visualize(),f=this.unravelMultiSectionSolver?.visualize()??this.segmentToPointOptimizer?.visualize(),g=this.highDensityRouteSolver?.visualize(),m=this.highDensityStitchSolver?.visualize(),y=this.uselessViaRemovalSolver1?.visualize(),x=this.uselessViaRemovalSolver2?.visualize(),v=this.multiSimplifiedPathSolver1?.visualize(),M=this.multiSimplifiedPathSolver2?.visualize(),S=this.srj.outline,b=[];if(b.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),S&&S.length>=2){const t=S.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),b.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const N={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:t.layers?.join(", ")}))],lines:b},I=[N,e,s,n,i,o,a,r,h,c,d,l,u,p,f,g?t(N,g):null,m,y,v,x,M,this.solved?t(N,$e(this.getOutputSimpleRouteJson())):null].filter(Boolean);return t(...I)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const s=this.highDensityRouteSolver.routes[e];if(t.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[s.connectionName]}),t.length>200)break}return{lines:t}}if(this.pathingOptimizer){const t=[];for(const e of this.pathingOptimizer.connectionsWithNodes)e.path&&t.push({points:e.path.map(t=>({x:t.center.x,y:t.center.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}getOriginalConnectionName(t){const e=t.match(/^(.+?)_mst\d+$/);return e?e[1]:t}_getOutputHdRoutes(){return this.multiSimplifiedPathSolver2?.simplifiedHdRoutes??this.uselessViaRemovalSolver2?.getOptimizedHdRoutes()??this.multiSimplifiedPathSolver1?.simplifiedHdRoutes??this.uselessViaRemovalSolver1?.getOptimizedHdRoutes()??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes(),s=this.srjWithPointPairs?.connections??[];for(const n of s){const s=n.name.match(/^(.+?)_frag_\d+$/),i=s?s[1]:n.name,o=n.netConnectionName??this.srj.connections.find(t=>t.name===i)?.netConnectionName,a=e.filter(t=>t.connectionName===n.name);for(let e=0;e<a.length;e++){const s=a[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??this.getOriginalConnectionName(i),route:Ee(s,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}};export{wi as AssignableViaAutoroutingPipelineSolver,pi as AutoroutingPipelineSolver,fi as CapacityMeshSolver,J as InMemoryCache,tt as LocalStorageCache,Ce as calculateOptimalCapacityDepth,$e as convertSrjToGraphicsObject,st as getGlobalInMemoryCache,et as getGlobalLocalStorageCache,Pe as getTunedTotalCapacity1,nt as setupGlobalCaches};//# sourceMappingURL=index.js.map
|
|
1
|
+
var t=(...t)=>{const e={points:[],lines:[],circles:[],rects:[]};return t.forEach((t,s)=>{t&&(t.lines&&(e.lines=[...e.lines||[],...t.lines.map(t=>({...t,step:s}))]),t.points&&(e.points=[...e.points||[],...t.points.map(t=>({...t,step:s}))]),t.circles&&(e.circles=[...e.circles||[],...t.circles.map(t=>({...t,step:s}))]),t.rects&&(e.rects=[...e.rects||[],...t.rects.map(t=>({...t,step:s}))]))}),e},e=class{MAX_ITERATIONS=1e3;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};cacheHit;cacheKey;cacheToSolveSpaceTransform;step(){if(!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,console.error(this.error),this.failed=!0,t}!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 (MAX_ITERATIONS=${this.MAX_ITERATIONS})`,console.error(this.error),this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}};function s(t){const e=new Map;for(const s of t)for(const t of s.nodeIds)e.set(t,[...e.get(t)??[],s]);return e}function n(){return n=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var n in s)({}).hasOwnProperty.call(s,n)&&(t[n]=s[n])}return t},n.apply(null,arguments)}function i(t,e){return(i=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t})(t,e)}function o(t){return(o=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function a(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(a=function(){return!!t})()}function r(t){var e="function"==typeof Map?new Map:void 0;return r=function(t){if(null===t||!function(t){try{return-1!==Function.toString.call(t).indexOf("[native code]")}catch(e){return"function"==typeof t}}(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,s)}function s(){return function(t,e,s){if(a())return Reflect.construct.apply(null,arguments);var n=[null];n.push.apply(n,e);var o=new(t.bind.apply(t,n));return s&&i(o,s.prototype),o}(t,arguments,o(this).constructor)}return s.prototype=Object.create(t.prototype,{constructor:{value:s,enumerable:!1,writable:!0,configurable:!0}}),i(s,t)},r(t)}var h={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 }).\n\n",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 }).\n\n",3:"Passed an incorrect argument to a color function, please pass a string representation of a color.\n\n",4:"Couldn't generate valid rgb string from %s, it returned %s.\n\n",5:"Couldn't parse the color string. Please provide the color as a string in hex, rgb, rgba, hsl or hsla notation.\n\n",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 }).\n\n",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 }).\n\n",8:"Passed invalid argument to toColorString, please pass a RgbColor, RgbaColor, HslColor or HslaColor object.\n\n",9:"Please provide a number of steps to the modularScale helper.\n\n",10:"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\n\n",11:'Invalid value passed as base to modularScale, expected number or em string but got "%s"\n\n',12:'Expected a string ending in "px" or a number passed as the first argument to %s(), got "%s" instead.\n\n',13:'Expected a string ending in "px" or a number passed as the second argument to %s(), got "%s" instead.\n\n',14:'Passed invalid pixel value ("%s") to %s(), please pass a value like "12px" or 12.\n\n',15:'Passed invalid base value ("%s") to %s(), please pass a value like "12px" or 12.\n\n',16:"You must provide a template to this method.\n\n",17:"You passed an unsupported selector state to this method.\n\n",18:"minScreen and maxScreen must be provided as stringified numbers with the same units.\n\n",19:"fromSize and toSize must be provided as stringified numbers with the same units.\n\n",20:"expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\n\n",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.\n\n",24:"fontFace expects either the path to the font file(s) or a name of a local copy.\n\n",25:"fontFace expects localFonts to be an array.\n\n",26:"fontFace expects fileFormats to be an array.\n\n",27:"radialGradient requries at least 2 color-stops to properly render.\n\n",28:"Please supply a filename to retinaImage() as the first argument.\n\n",29:"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\n\n",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\n\n",32:"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')\n\n",33:"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation\n\n",34:"borderRadius expects a radius value as a string or number as the second argument.\n\n",35:'borderRadius expects one of "top", "bottom", "left" or "right" as the first argument.\n\n',36:"Property must be a string value.\n\n",37:"Syntax Error at %s.\n\n",38:"Formula contains a function that needs parentheses at %s.\n\n",39:"Formula is missing closing parenthesis at %s.\n\n",40:"Formula has too many closing parentheses at %s.\n\n",41:"All values in a formula must have the same unit or be unitless.\n\n",42:"Please provide a number of steps to the modularScale helper.\n\n",43:"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\n\n",44:"Invalid value passed as base to modularScale, expected number or em/rem string but got %s.\n\n",45:"Passed invalid argument to hslToColorString, please pass a HslColor or HslaColor object.\n\n",46:"Passed invalid argument to rgbToColorString, please pass a RgbColor or RgbaColor object.\n\n",47:"minScreen and maxScreen must be provided as stringified numbers with the same units.\n\n",48:"fromSize and toSize must be provided as stringified numbers with the same units.\n\n",49:"Expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\n\n",50:"Expects the objects in the first argument array to have the properties prop, fromSize, and toSize.\n\n",51:"Expects the first argument object to have the properties prop, fromSize, and toSize.\n\n",52:"fontFace expects either the path to the font file(s) or a name of a local copy.\n\n",53:"fontFace expects localFonts to be an array.\n\n",54:"fontFace expects fileFormats to be an array.\n\n",55:"fontFace expects a name of a font-family.\n\n",56:"linearGradient requries at least 2 color-stops to properly render.\n\n",57:"radialGradient requries at least 2 color-stops to properly render.\n\n",58:"Please supply a filename to retinaImage() as the first argument.\n\n",59:"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\n\n",60:"Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\n\n",61:"Property must be a string value.\n\n",62:"borderRadius expects a radius value as a string or number as the second argument.\n\n",63:'borderRadius expects one of "top", "bottom", "left" or "right" as the first argument.\n\n',64:"The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation.\n\n",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').\n\n",66:"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation.\n\n",67:"You must provide a template to this method.\n\n",68:"You passed an unsupported selector state to this method.\n\n",69:'Expected a string ending in "px" or a number passed as the first argument to %s(), got %s instead.\n\n',70:'Expected a string ending in "px" or a number passed as the second argument to %s(), got %s instead.\n\n',71:'Passed invalid pixel value %s to %s(), please pass a value like "12px" or 12.\n\n',72:'Passed invalid base value %s to %s(), please pass a value like "12px" or 12.\n\n',73:"Please provide a valid CSS variable.\n\n",74:"CSS variable not found and no default was provided.\n\n",75:"important requires a valid style object, got a %s instead.\n\n",76:"fromSize and toSize must be provided as stringified numbers with the same units as minScreen and maxScreen.\n\n",77:'remToPx expects a value in "rem" but you provided it in "%s".\n\n',78:'base must be set in "px" or "%" but you set it in "%s".\n'};function c(){for(var t=arguments.length,e=new Array(t),s=0;s<t;s++)e[s]=arguments[s];var n,i=e[0],o=[];for(n=1;n<e.length;n+=1)o.push(e[n]);return o.forEach(function(t){i=i.replace(/%[a-z]/,t)}),i}var d=function(t){var e,s;function n(e){var s;if("production"===process.env.NODE_ENV)s=t.call(this,"An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#"+e+" for more information.")||this;else{for(var n=arguments.length,i=new Array(n>1?n-1:0),o=1;o<n;o++)i[o-1]=arguments[o];s=t.call(this,c.apply(void 0,[h[e]].concat(i)))||this}return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(s)}return s=t,(e=n).prototype=Object.create(s.prototype),e.prototype.constructor=e,i(e,s),n}(r(Error));function l(t,e){return t.substr(-e.length)===e}var u=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;function p(t){return"string"!=typeof t?t:t.match(u)?parseFloat(t):t}var f=function(t){return function(e,s){void 0===s&&(s="16px");var n=e,i=s;if("string"==typeof e){if(!l(e,"px"))throw new d(69,t,e);n=p(e)}if("string"==typeof s){if(!l(s,"px"))throw new d(70,t,s);i=p(s)}if("string"==typeof n)throw new d(71,e,t);if("string"==typeof i)throw new d(72,s,t);return""+n/i+t}};f("em"),f("rem");function g(t){return Math.round(255*t)}function m(t,e,s){return g(t)+","+g(e)+","+g(s)}function y(t,e,s,n){if(void 0===n&&(n=m),0===e)return n(s,s,s);var i=(t%360+360)%360/60,o=(1-Math.abs(2*s-1))*e,a=o*(1-Math.abs(i%2-1)),r=0,h=0,c=0;i>=0&&i<1?(r=o,h=a):i>=1&&i<2?(r=a,h=o):i>=2&&i<3?(h=o,c=a):i>=3&&i<4?(h=a,c=o):i>=4&&i<5?(r=a,c=o):i>=5&&i<6&&(r=o,c=a);var d=s-o/2;return n(r+d,h+d,c+d)}var x={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 v=/^#[a-fA-F0-9]{6}$/,M=/^#[a-fA-F0-9]{8}$/,S=/^#[a-fA-F0-9]{3}$/,b=/^#[a-fA-F0-9]{4}$/,N=/^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i,I=/^rgb(?:a)?\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i,P=/^hsl\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*\)$/i,C=/^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 _(t){if("string"!=typeof t)throw new d(3);var e=function(t){if("string"!=typeof t)return t;var e=t.toLowerCase();return x[e]?"#"+x[e]:t}(t);if(e.match(v))return{red:parseInt(""+e[1]+e[2],16),green:parseInt(""+e[3]+e[4],16),blue:parseInt(""+e[5]+e[6],16)};if(e.match(M)){var s=parseFloat((parseInt(""+e[7]+e[8],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[2],16),green:parseInt(""+e[3]+e[4],16),blue:parseInt(""+e[5]+e[6],16),alpha:s}}if(e.match(S))return{red:parseInt(""+e[1]+e[1],16),green:parseInt(""+e[2]+e[2],16),blue:parseInt(""+e[3]+e[3],16)};if(e.match(b)){var n=parseFloat((parseInt(""+e[4]+e[4],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[1],16),green:parseInt(""+e[2]+e[2],16),blue:parseInt(""+e[3]+e[3],16),alpha:n}}var i=N.exec(e);if(i)return{red:parseInt(""+i[1],10),green:parseInt(""+i[2],10),blue:parseInt(""+i[3],10)};var o=I.exec(e.substring(0,50));if(o)return{red:parseInt(""+o[1],10),green:parseInt(""+o[2],10),blue:parseInt(""+o[3],10),alpha:parseFloat(""+o[4])>1?parseFloat(""+o[4])/100:parseFloat(""+o[4])};var a=P.exec(e);if(a){var r="rgb("+y(parseInt(""+a[1],10),parseInt(""+a[2],10)/100,parseInt(""+a[3],10)/100)+")",h=N.exec(r);if(!h)throw new d(4,e,r);return{red:parseInt(""+h[1],10),green:parseInt(""+h[2],10),blue:parseInt(""+h[3],10)}}var c=C.exec(e.substring(0,50));if(c){var l="rgb("+y(parseInt(""+c[1],10),parseInt(""+c[2],10)/100,parseInt(""+c[3],10)/100)+")",u=N.exec(l);if(!u)throw new d(4,e,l);return{red:parseInt(""+u[1],10),green:parseInt(""+u[2],10),blue:parseInt(""+u[3],10),alpha:parseFloat(""+c[4])>1?parseFloat(""+c[4])/100:parseFloat(""+c[4])}}throw new d(5)}function E(t){return function(t){var e,s=t.red/255,n=t.green/255,i=t.blue/255,o=Math.max(s,n,i),a=Math.min(s,n,i),r=(o+a)/2;if(o===a)return void 0!==t.alpha?{hue:0,saturation:0,lightness:r,alpha:t.alpha}:{hue:0,saturation:0,lightness:r};var h=o-a,c=r>.5?h/(2-o-a):h/(o+a);switch(o){case s:e=(n-i)/h+(n<i?6:0);break;case n:e=(i-s)/h+2;break;default:e=(s-n)/h+4}return e*=60,void 0!==t.alpha?{hue:e,saturation:c,lightness:r,alpha:t.alpha}:{hue:e,saturation:c,lightness:r}}(_(t))}var T=function(t){return 7===t.length&&t[1]===t[2]&&t[3]===t[4]&&t[5]===t[6]?"#"+t[1]+t[3]+t[5]:t};function w(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function z(t){return w(Math.round(255*t))}function A(t,e,s){return T("#"+z(t)+z(e)+z(s))}function R(t,e,s){return y(t,e,s,A)}function O(t,e,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s)return T("#"+w(t)+w(e)+w(s));if("object"==typeof t&&void 0===e&&void 0===s)return T("#"+w(t.red)+w(t.green)+w(t.blue));throw new d(6)}function L(t,e,s,n){if("string"==typeof t&&"number"==typeof e){var i=_(t);return"rgba("+i.red+","+i.green+","+i.blue+","+e+")"}if("number"==typeof t&&"number"==typeof e&&"number"==typeof s&&"number"==typeof n)return n>=1?O(t,e,s):"rgba("+t+","+e+","+s+","+n+")";if("object"==typeof t&&void 0===e&&void 0===s&&void 0===n)return t.alpha>=1?O(t.red,t.green,t.blue):"rgba("+t.red+","+t.green+","+t.blue+","+t.alpha+")";throw new d(7)}function D(t){if("object"!=typeof t)throw new d(8);if(function(t){return"number"==typeof t.red&&"number"==typeof t.green&&"number"==typeof t.blue&&"number"==typeof t.alpha}(t))return L(t);if(function(t){return"number"==typeof t.red&&"number"==typeof t.green&&"number"==typeof t.blue&&("number"!=typeof t.alpha||void 0===t.alpha)}(t))return O(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&"number"==typeof t.alpha}(t))return function(t,e,s,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s&&"number"==typeof n)return n>=1?R(t,e,s):"rgba("+y(t,e,s)+","+n+")";if("object"==typeof t&&void 0===e&&void 0===s&&void 0===n)return t.alpha>=1?R(t.hue,t.saturation,t.lightness):"rgba("+y(t.hue,t.saturation,t.lightness)+","+t.alpha+")";throw new d(2)}(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&("number"!=typeof t.alpha||void 0===t.alpha)}(t))return function(t,e,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s)return R(t,e,s);if("object"==typeof t&&void 0===e&&void 0===s)return R(t.hue,t.saturation,t.lightness);throw new d(1)}(t);throw new d(8)}function F(t,e,s){return function(){var n=s.concat(Array.prototype.slice.call(arguments));return n.length>=e?t.apply(this,n):F(t,e,n)}}function $(t){return F(t,t.length,[])}$(function(t,e){if("transparent"===e)return e;var s=E(e);return D(n({},s,{hue:s.hue+parseFloat(t)}))});function k(t,e,s){return Math.max(t,Math.min(e,s))}$(function(t,e){if("transparent"===e)return e;var s=E(e);return D(n({},s,{lightness:k(0,1,s.lightness-parseFloat(t))}))});$(function(t,e){if("transparent"===e)return e;var s=E(e);return D(n({},s,{saturation:k(0,1,s.saturation-parseFloat(t))}))});$(function(t,e){if("transparent"===e)return e;var s=E(e);return D(n({},s,{lightness:k(0,1,s.lightness+parseFloat(t))}))});var B=$(function(t,e,s){if("transparent"===e)return s;if("transparent"===s)return e;if(0===t)return s;var i=_(e),o=n({},i,{alpha:"number"==typeof i.alpha?i.alpha:1}),a=_(s),r=n({},a,{alpha:"number"==typeof a.alpha?a.alpha:1}),h=o.alpha-r.alpha,c=2*parseFloat(t)-1,d=((c*h===-1?c:c+h)/(1+c*h)+1)/2,l=1-d;return L({red:Math.floor(o.red*d+r.red*l),green:Math.floor(o.green*d+r.green*l),blue:Math.floor(o.blue*d+r.blue*l),alpha:o.alpha*parseFloat(t)+r.alpha*(1-parseFloat(t))})});$(function(t,e){if("transparent"===e)return e;var s=_(e);return L(n({},s,{alpha:k(0,1,(100*("number"==typeof s.alpha?s.alpha:1)+100*parseFloat(t))/100)}))});$(function(t,e){if("transparent"===e)return e;var s=E(e);return D(n({},s,{saturation:k(0,1,s.saturation+parseFloat(t))}))});$(function(t,e){return"transparent"===e?e:D(n({},E(e),{hue:parseFloat(t)}))});$(function(t,e){return"transparent"===e?e:D(n({},E(e),{lightness:parseFloat(t)}))});$(function(t,e){return"transparent"===e?e:D(n({},E(e),{saturation:parseFloat(t)}))});$(function(t,e){return"transparent"===e?e:B(parseFloat(t),"rgb(0, 0, 0)",e)});$(function(t,e){return"transparent"===e?e:B(parseFloat(t),"rgb(255, 255, 255)",e)});var X=$(function(t,e){if("transparent"===e)return e;var s=_(e);return L(n({},s,{alpha:k(0,1,+(100*("number"==typeof s.alpha?s.alpha:1)-100*parseFloat(t)).toFixed(2)/100)}))}),Y=["blue","orange","purple","cyan","magenta","yellowgreen","darkgoldenrod","deeppink"],H=(t,e)=>{const s={};for(let n=0;n<t.connections.length;n++){const i=t.connections[n],o=e?.getNetConnectedToId(i.name);o&&!s[o]&&(s[o]=`hsl(${300*n/t.connections.length}, 100%, 50%)`),s[i.name]=(o?s[o]:null)??`hsl(${340*n/t.connections.length}, 100%, 50%)`}return s},V=(t,e)=>{try{return X(e,t)}catch(e){return console.error(e),t}},j=class extends e{nodes;edges;capacityPaths;nodeMap;nodeEdgeMap;unprocessedNodeIds;nodePortSegments;colorMap;constructor({nodes:t,edges:e,capacityPaths:n,colorMap:i}){super(),this.nodes=t,this.edges=e,this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=s(e),this.capacityPaths=n,this.colorMap=i??{},this.unprocessedNodeIds=[...new Set(n.flatMap(t=>t.nodeIds))],this.nodePortSegments=new Map}step(){const t=this.unprocessedNodeIds.pop();if(!t)return void(this.solved=!0);const e=[];for(const s of this.capacityPaths){const n=s.nodeIds.indexOf(t);-1!==n&&e.push({path:s,indexOfNodeInPath:n})}const s=this.nodeMap.get(t),n=[];for(const{path:i,indexOfNodeInPath:o}of e){const e=i.nodeIds[o-1],a=i.nodeIds[o+1];for(const o of[e,a]){const e=this.nodeMap.get(o);if(!e)continue;const a=Z(s,e),r=e.availableZ.filter(t=>s.availableZ.includes(t));if(0===r.length)continue;const h={capacityMeshNodeId:t,start:a.start,end:a.end,connectionNames:[i.connectionName],rootConnectionNames:i.rootConnectionName?[i.rootConnectionName]:void 0,availableZ:r};n.push(h)}}const i=function(t){const e=[],s=t.map(t=>({...t,connectionNames:[...t.connectionNames],rootConnectionNames:t.rootConnectionNames?[...t.rootConnectionNames]:[],availableZ:[...t.availableZ].sort((t,e)=>t-e)}));for(;s.length>0;){const t=s.pop();let n=!1;for(let s=0;s<e.length;s++){const i=e[s],o=U(i.start,t.start)&&U(i.end,t.end)||U(i.start,t.end)&&U(i.end,t.start),a=G(i.availableZ,t.availableZ);if(o&&a){const e=new Set(i.connectionNames);t.connectionNames.forEach(t=>e.add(t)),i.connectionNames=Array.from(e);const s=new Set(i.rootConnectionNames||[]);t.rootConnectionNames?.forEach(t=>s.add(t)),i.rootConnectionNames=Array.from(s),n=!0;break}}n||e.push(t)}return e}(n);this.nodePortSegments.set(t,i)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};return this.nodePortSegments.forEach((e,s)=>{this.nodeMap.get(s);e.forEach(e=>{e.start.x,e.end.x;for(let n=0;n<e.connectionNames.length;n++){const i={x:.05*Math.max(...e.availableZ),y:.05*Math.max(...e.availableZ)},o={x:(e.start.x+e.end.x)/2,y:(e.start.y+e.end.y)/2},a={x:o.x+i.x,y:o.y+i.y};i.x>0&&t.lines.push({points:[o,a],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5"}),t.points.push({x:a.x,y:a.y,label:`${s}: ${e.connectionNames.join(", ")}\navailableZ: ${e.availableZ.join(",")}\nnodePortSegmentId: ${e.nodePortSegmentId}`}),t.lines.push({points:[e.start,e.end],strokeColor:V(this.colorMap[e.connectionNames[n]],.6)})}})}),t}};function Z(t,e){const s={start:Math.max(t.center.x-t.width/2,e.center.x-e.width/2),end:Math.min(t.center.x+t.width/2,e.center.x+e.width/2)},n={start:Math.max(t.center.y-t.height/2,e.center.y-e.height/2),end:Math.min(t.center.y+t.height/2,e.center.y+e.height/2)};if(s.end-s.start<n.end-n.start){const t=(s.start+s.end)/2;return{start:{x:t,y:n.start},end:{x:t,y:n.end}}}{const t=(n.start+n.end)/2;return{start:{x:s.start,y:t},end:{x:s.end,y:t}}}}var W=1e-9;function U(t,e){return Math.abs(t.x-e.x)<W&&Math.abs(t.y-e.y)<W}function G(t,e){if(t.length!==e.length)return!1;for(let s=0;s<t.length;s++)if(t[s]!==e[s])return!1;return!0}var q=class extends e{unsolvedSegments;solvedSegments;nodeMap;colorMap;constructor({segments:t,colorMap:e,nodes:s}){super(),this.MAX_ITERATIONS=1e5,this.unsolvedSegments=t,this.solvedSegments=[],this.colorMap=e??{},this.nodeMap=Object.fromEntries(s.map(t=>[t.capacityMeshNodeId,t]))}_step(){let t=!1;const e=[...this.unsolvedSegments];for(const s of e){const e=s.connectionNames.length;if((!("assignedPoints"in s)||s.assignedPoints?.length!==e)&&1===e){const e={x:(s.start.x+s.end.x)/2,y:(s.start.y+s.end.y)/2,z:s.availableZ[0]};s.assignedPoints=[{connectionName:s.connectionNames[0],rootConnectionName:s.rootConnectionNames?.[0],point:e}],this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(s),1),this.solvedSegments.push(s),t=!0}}if(!t&&e.length>0){let s=e[0];for(const t of e)t.connectionNames.length<s.connectionNames.length&&(s=t);const n=[...s.connectionNames].sort(),i=s.end.x-s.start.x,o=s.end.y-s.start.y,a=n.length,r=[];for(let t=1;t<=a;t++){const e=t/(a+1);r.push({x:s.start.x+i*e,y:s.start.y+o*e,z:s.availableZ[0]})}s.assignedPoints=n.map((t,e)=>({connectionName:t,rootConnectionName:s.rootConnectionNames?.[s.connectionNames.indexOf(t)],point:r[e]})),this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(s),1),this.solvedSegments.push(s),t=!0}0===this.unsolvedSegments.length&&(this.solved=!0)}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.solvedSegments){const s=e.capacityMeshNodeId,n=this.nodeMap[s];t.has(s)||t.set(s,{capacityMeshNodeId:s,portPoints:[],center:n.center,width:n.width,height:n.height}),t.get(s).portPoints.push(...e.assignedPoints.map(t=>({...t.point,connectionName:t.connectionName})))}return Array.from(t.values())}visualize(){const t={points:[],lines:this.solvedSegments.map(t=>({points:[t.start,t.end],step:4})),rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Segment to Point Solver"};for(let e=0;e<this.solvedSegments.length;e++){const s=this.solvedSegments[e];for(let e=0;e<s.assignedPoints.length;e++){const n=s.assignedPoints[e],i={x:n.point.x,y:n.point.y},o={x:n.point.x+.05*n.point.z,y:n.point.y+.05*n.point.z};0!==n.point.z&&t.lines.push({points:[i,o],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5",step:4}),t.points.push({x:o.x,y:o.y,label:[`${s.capacityMeshNodeId}-${n.connectionName}`,`z: ${s.availableZ.join(",")}`,`nodePortSegmentId: ${s.nodePortSegmentId}`].join("\n"),color:this.colorMap[n.connectionName],step:4})}}const e=[],s={};for(const t of this.solvedSegments){const e=t.capacityMeshNodeId;s[e]||(s[e]={});for(const n of t.assignedPoints)s[e][n.connectionName]||(s[e][n.connectionName]=[]),s[e][n.connectionName].push({x:n.point.x,y:n.point.y})}for(const t in s)for(const n in s[t]){const i=s[t][n];i.length>1&&e.push({points:i,step:4,strokeDash:"5 5",strokeColor:this.colorMap[n]||"#000"})}return t.lines.push(...e),t}};import K from"object-hash";var J=class{cacheHitsByPrefix={};cacheMissesByPrefix={};isSyncCache=!0;cacheHits=0;cacheMisses=0;cache=new Map;getCachedSolutionSync(t){const e=this.cache.get(t);if(void 0!==e){this.cacheHits++;const s=t.split(":")[0];return this.cacheHitsByPrefix[s]=(this.cacheHitsByPrefix[s]||0)+1,structuredClone(e)}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){this.cache.set(t,structuredClone(e))}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){this.cache.clear(),this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}getAllCacheKeys(){return Array.from(this.cache.keys())}},Q="tscircuit_autorouter_cache_",tt=class{isSyncCache=!0;cacheHits=0;cacheMisses=0;cacheHitsByPrefix={};cacheMissesByPrefix={};constructor(){}getKey(t){return`${Q}${t}`}getCachedSolutionSync(t){if("undefined"==typeof localStorage)return;const e=this.getKey(t);try{const s=localStorage.getItem(e);if(null!==s){const e=JSON.parse(s);this.cacheHits++;const n=t.split(":")[0];return this.cacheHitsByPrefix[n]=(this.cacheHitsByPrefix[n]||0)+1,e}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}catch(s){console.error(`Error getting cached solution sync for ${e}:`,s),this.cacheMisses++;const n=t.split(":")[0];return void(this.cacheMissesByPrefix[n]=(this.cacheMissesByPrefix[n]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){if("undefined"==typeof localStorage)return;const s=this.getKey(t);try{const t=JSON.stringify(e);localStorage.setItem(s,t)}catch(t){console.error(`Error setting cached solution sync for ${s}:`,t),t instanceof DOMException&&("QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&console.warn(`LocalStorage quota exceeded. Failed to cache solution for ${s}. Consider clearing the cache.`)}}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){if("undefined"!=typeof localStorage)try{const t=[];for(let e=0;e<localStorage.length;e++){const s=localStorage.key(e);s?.startsWith(Q)&&t.push(s)}t.forEach(t=>localStorage.removeItem(t)),console.log(`Cleared ${t.length} items from LocalStorage cache.`)}catch(t){console.error("Error clearing LocalStorage cache:",t)}finally{this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}}getAllCacheKeys(){const t=[];for(let e=0;e<1e4;e++){const s=localStorage.key(e);if(!s)break;s.includes(Q)&&t.push(s)}return t}};function et(){return globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE||nt(),globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE}function st(){return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE||nt(),globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE}function nt(){globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE??=new tt,globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE??=new J}function it(t){const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-s,maxY:t.center.y+s}}function ot(t,e,s){return Math.max(e,Math.min(s,t))}function at(t,e,s,n){const i=rt(t,e,s),o=rt(t,e,n),a=rt(s,n,t),r=rt(s,n,e);return i!==o&&a!==r||(!(0!==i||!ht(t,s,e))||(!(0!==o||!ht(t,n,e))||(!(0!==a||!ht(s,t,n))||!(0!==r||!ht(s,e,n)))))}function rt(t,e,s){const n=(e.y-t.y)*(s.x-e.x)-(e.x-t.x)*(s.y-e.y);return 0===n?0:n>0?1:2}function ht(t,e,s){return e.x<=Math.max(t.x,s.x)&&e.x>=Math.min(t.x,s.x)&&e.y<=Math.max(t.y,s.y)&&e.y>=Math.min(t.y,s.y)}function ct(t,e,s){const n=(s.x-e.x)**2+(s.y-e.y)**2;if(0===n)return dt(t,e);let i=((t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y))/n;i=Math.max(0,Math.min(1,i));return dt(t,{x:e.x+i*(s.x-e.x),y:e.y+i*(s.y-e.y)})}function dt(t,e){const s=t.x-e.x,n=t.y-e.y;return Math.sqrt(s*s+n*n)}function lt(t,e,s,n){const i=e.x-t.x,o=e.y-t.y,a=n.x-s.x,r=n.y-s.y,h=t.x-s.x,c=t.y-s.y,d=i*r-o*a;if(Math.abs(d)<1e-10)return null;const l=(c*a-h*r)/d,u=(i*c-o*h)/d,p=1e-9;if(l>=-1e-9&&l<=1+p&&u>=-1e-9&&u<=1+p){return{x:t.x+l*i,y:t.y+l*o}}return null}function ut(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var pt=t=>{if("minX"in t)return t;const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,minY:t.center.y-s,maxX:t.center.x+e,maxY:t.center.y+s}},ft=t=>[{x:t.minX,y:t.minY},{x:t.maxX,y:t.minY},{x:t.maxX,y:t.maxY},{x:t.minX,y:t.maxY}],gt=t=>{const e=[];for(let s=0;s<t.length;s++){const n=t[s],i=t[(s+1)%t.length];e.push([n,i])}return e},mt=(t,e,s)=>{const n=(t.y-e.y)*(s.x-e.x)-(t.x-e.x)*(s.y-e.y);if(Math.abs(n)>1e-9)return!1;const i=(t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y);if(i<0)return!1;return!(i>(s.x-e.x)**2+(s.y-e.y)**2)},yt=(t,e)=>{if(e.length<3)return!1;const s=gt(e);for(const[e,n]of s)if(mt(t,e,n))return!0;let n=!1;for(let s=0,i=e.length-1;s<e.length;i=s++){const o=e[s].x,a=e[s].y,r=e[i].x,h=e[i].y;a>t.y!=h>t.y&&t.x<(r-o)*(t.y-a)/(h-a)+o&&(n=!n)}return n},xt=(t,e)=>{const s=ft(t),n=[[s[0],s[1]],[s[1],s[2]],[s[2],s[3]],[s[3],s[0]]],i=gt(e);for(const[t,e]of i)for(const[s,i]of n)if(at(t,e,s,i))return!0;return!1},vt=(t,e)=>((t,e)=>!(e.length<3)&&(!!e.some(e=>((t,e)=>t.x>=e.minX&&t.x<=e.maxX&&t.y>=e.minY&&t.y<=e.maxY)(e,t))||(!!ft(t).some(t=>yt(t,e))||xt(t,e))))(pt(t),e),Mt=(t,e)=>((t,e)=>!(e.length<3)&&(!!ft(t).every(t=>yt(t,e))&&!xt(t,e)))(pt(t),e);function St(t,e,s,n){if(t.x===e.x&&t.y===e.y)return ct(t,s,n);if(s.x===n.x&&s.y===n.y)return ct(s,t,e);if(at(t,e,s,n))return 0;const i=[ct(t,s,n),ct(e,s,n),ct(s,t,e),ct(n,t,e)];return Math.min(...i)}function bt(t,e,s){const n=s.width/2,i=s.height/2;return function(t,e,s){const n={x:s.minX,y:s.minY},i={x:s.maxX,y:s.minY},o={x:s.minX,y:s.maxY},a={x:s.maxX,y:s.maxY};if(at(t,e,n,i)||at(t,e,i,a)||at(t,e,a,o)||at(t,e,o,n))return 0;if(t.x>=s.minX&&t.x<=s.maxX&&t.y>=s.minY&&t.y<=s.maxY&&e.x>=s.minX&&e.x<=s.maxX&&e.y>=s.minY&&e.y<=s.maxY)return 0;const r=[ct(n,t,e),ct(i,t,e),ct(o,t,e),ct(a,t,e)];if(t.x>=s.minX&&t.x<=s.maxX&&t.y>=s.minY&&t.y<=s.maxY)return 0;if(e.x>=s.minX&&e.x<=s.maxX&&e.y>=s.minY&&e.y<=s.maxY)return 0;if(t.x<s.minX||t.x>s.maxX||t.y<s.minY||t.y>s.maxY){const e=ot(t.x,s.minX,s.maxX),n=ot(t.y,s.minY,s.maxY);r.push(dt(t,{x:e,y:n}))}if(e.x<s.minX||e.x>s.maxX||e.y<s.minY||e.y>s.maxY){const t=ot(e.x,s.minX,s.maxX),n=ot(e.y,s.minY,s.maxY);r.push(dt(e,{x:t,y:n}))}return Math.min(...r)}(t,e,{minX:s.center.x-n,maxX:s.center.x+n,minY:s.center.y-i,maxY:s.center.y+i})}function Nt(t,e,s){const n=s.x-e.x,i=s.y-e.y,o=n*n+i*i;if(0===o)return{x:e.x,y:e.y};let a=((t.x-e.x)*n+(t.y-e.y)*i)/o;a=Math.max(0,Math.min(1,a));return{x:e.x+a*n,y:e.y+a*i}}var It=class{heap=[];constructor(t){this.heap=[];for(const e of t)this.enqueue(e)}getLeftChildIndex(t){return 2*t+1}getRightChildIndex(t){return 2*t+2}getParentIndex(t){return Math.floor((t-1)/2)}hasLeftChild(t){return this.getLeftChildIndex(t)<this.heap.length}hasRightChild(t){return this.getRightChildIndex(t)<this.heap.length}hasParent(t){return this.getParentIndex(t)>=0}leftChild(t){return this.heap[this.getLeftChildIndex(t)]}rightChild(t){return this.heap[this.getRightChildIndex(t)]}parent(t){return this.heap[this.getParentIndex(t)]}swap(t,e){const s=this.heap[t];this.heap[t]=this.heap[e],this.heap[e]=s}dequeue(){if(0===this.heap.length)return null;const t=this.heap[0];return this.heap[0]=this.heap[this.heap.length-1],this.heap.pop(),this.heapifyDown(),t}peek(){return 0===this.heap.length?null:this.heap[0]}enqueue(t){this.heap.push(t),this.heapifyUp()}heapifyUp(){let t=this.heap.length-1;for(;this.hasParent(t)&&this.parent(t).f>this.heap[t].f;)this.swap(this.getParentIndex(t),t),t=this.getParentIndex(t)}heapifyDown(){let t=0;for(;this.hasLeftChild(t);){let e=this.getLeftChildIndex(t);if(this.hasRightChild(t)&&this.rightChild(t).f<this.leftChild(t).f&&(e=this.getRightChildIndex(t)),this.heap[t].f<this.heap[e].f)break;this.swap(t,e),t=e}}},Pt=class extends e{obstacleRoutes;bounds;boundsSize;boundsCenter;A;B;straightLineDistance;viaDiameter;traceThickness;obstacleMargin;layerCount;minCellSize=.05;cellStep=.05;GREEDY_MULTIPLER=1.1;numRoutes;VIA_PENALTY_FACTOR=.3;CELL_SIZE_FACTOR;exploredNodes;candidates;connectionName;solvedPath=null;futureConnections;hyperParameters;connMap;debug_exploredNodesOrdered;debug_nodesTooCloseToObstacle;debug_nodePathToParentIntersectsObstacle;debugEnabled=!0;initialNodeGridOffset;constructor(t){super(),this.bounds=t.bounds,this.connMap=t.connMap,this.hyperParameters=t.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=t.connectionName,this.obstacleRoutes=t.obstacleRoutes,this.A=t.A,this.B=t.B,this.viaDiameter=t.viaDiameter??.6,this.traceThickness=t.traceThickness??.15,this.obstacleMargin=t.obstacleMargin??.2,this.layerCount=t.layerCount??2,this.exploredNodes=new Set,this.straightLineDistance=dt(this.A,this.B),this.futureConnections=t.futureConnections??[],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;const e=Math.ceil(5*(this.numRoutes+1));let s=this.boundsSize.width/this.cellStep,n=this.boundsSize.height/this.cellStep;for(;s*n>e**2&&!(2*this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,s=this.boundsSize.width/this.cellStep,n=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR;const i=Math.abs(this.A.x-this.bounds.minX)<.001&&Math.abs(this.B.x-this.bounds.minX)<.001||Math.abs(this.A.x-this.bounds.maxX)<.001&&Math.abs(this.B.x-this.bounds.maxX)<.001||Math.abs(this.A.y-this.bounds.minY)<.001&&Math.abs(this.B.y-this.bounds.minY)<.001||Math.abs(this.A.y-this.bounds.maxY)<.001&&Math.abs(this.B.y-this.bounds.maxY)<.001;this.futureConnections&&0===this.futureConnections.length&&0===this.obstacleRoutes.length&&!i&&this.handleSimpleCases();const o={x:Math.round(t.A.x/(this.cellStep/2))*(this.cellStep/2),y:Math.round(t.A.y/(this.cellStep/2))*(this.cellStep/2)};this.initialNodeGridOffset={x:o.x-Math.round(t.A.x/this.cellStep)*this.cellStep,y:o.y-Math.round(t.A.y/this.cellStep)*this.cellStep},this.candidates=new It([{...t.A,...o,z:t.A.z??0,g:0,h:0,f:0,parent:{...t.A,z:t.A.z??0,g:0,h:0,f:0,parent:null}}])}handleSimpleCases(){this.solved=!0;const{A:t,B:e}=this,s=t.z===e.z?[t,e]:[t,{...this.boundsCenter,z:this.A.z},{...this.boundsCenter,z:e.z},e];this.solvedPath={connectionName:this.connectionName,route:s,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(t,e,s){if(e??=this.obstacleMargin,s&&t.parent){const s=this.getViasInNodePath(t.parent);for(const n of s)if(dt(t,n)<this.viaDiameter/2+e)return!0}for(const n of this.obstacleRoutes){const i=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!i){const i=Ct(n);for(const n of i)if((s||n.z===t.z)&&ct(t,n.A,n.B)<this.traceThickness+e)return!0}for(const s of n.vias)if(dt(t,s)<this.viaDiameter/2+this.traceThickness/2+e)return!0}return!1}isNodeTooCloseToEdge(t,e){const s=e?this.viaDiameter/2+this.obstacleMargin/2:this.obstacleMargin/2,n=t.x<this.bounds.minX+s||t.x>this.bounds.maxX-s||t.y<this.bounds.minY+s||t.y>this.bounds.maxY-s;return!(n&&!e&&(dt(t,this.B)<2*s||dt(t,this.A)<2*s))&&n}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const s of this.obstacleRoutes){const n=this.connMap?.areIdsConnected?.(this.connectionName,s.connectionName);if(!n)for(const n of Ct(s))if(n.z===t.z&&at(t,e,n.A,n.B))return!0}return!1}computeH(t){return dt(t,this.B)+(t.z!==this.B.z?this.viaPenaltyDistance:0)}computeG(t){return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+dt(t,t.parent)}computeF(t,e){return t+e*this.GREEDY_MULTIPLER}getNodeKey(t){return`${Math.round(t.x/this.cellStep)*this.cellStep},${Math.round(t.y/this.cellStep)*this.cellStep},${t.z}`}getNeighbors(t){const e=[],{maxX:s,minX:n,maxY:i,minY:o}=this.bounds;for(let a=-1;a<=1;a++)for(let r=-1;r<=1;r++){if(0===a&&0===r)continue;const h={...t,parent:t,x:_t(t.x+a*this.cellStep,n,s),y:_t(t.y+r*this.cellStep,o,i)},c=this.getNodeKey(h);this.exploredNodes.has(c)||(this.isNodeTooCloseToObstacle(h)?(this.debug_nodesTooCloseToObstacle.add(c),this.exploredNodes.add(c)):this.isNodeTooCloseToEdge(h,!1)?this.exploredNodes.add(c):this.doesPathToParentIntersectObstacle(h)?(this.debug_nodePathToParentIntersectsObstacle.add(c),this.exploredNodes.add(c)):(h.g=this.computeG(h),h.h=this.computeH(h),h.f=this.computeF(h.g,h.h),e.push(h)))}for(let s=0;s<this.layerCount;s++){if(s===t.z)continue;const n={...t,parent:t,z:s};this.exploredNodes.has(this.getNodeKey(n))||this.isNodeTooCloseToObstacle(n,this.viaDiameter/2+this.obstacleMargin/2,!0)||this.isNodeTooCloseToEdge(n,!0)||(n.g=this.computeG(n),n.h=this.computeH(n),n.f=this.computeF(n.g,n.h),e.push(n))}return e}getNodePath(t){const e=[];for(;t;)e.push(t),t=t.parent;return e}getViasInNodePath(t){const e=this.getNodePath(t),s=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&s.push({x:e[t].x,y:e[t].y});return s}setSolvedPath(t){const e=this.getNodePath(t);e.reverse();const s=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&s.push({x:e[t].x,y:e[t].y});this.solvedPath={connectionName:this.connectionName,traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,route:e.map(t=>({x:t.x,y:t.y,z:t.z})).concat([this.B]),vias:s}}computeProgress(t,e,s){s||(e+=this.viaPenaltyDistance);const n=1-e/this.straightLineDistance;return Math.max(this.progress||0,2/Math.PI*Math.atan(.112*n/(1-n)))}_step(){let t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;for(;t&&e&&this.exploredNodes.has(e);)t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;if(!t||!e)return void(this.failed=!0);this.exploredNodes.add(e),this.debug_exploredNodesOrdered.push(e);const s=dt(t,this.B);this.progress=this.computeProgress(t,s,t.z===this.B.z),s<=this.cellStep*Math.SQRT2&&t.z===this.B.z&&!this.doesPathToParentIntersectObstacle({...t,parent:t,x:this.B.x,y:this.B.y})&&(this.solved=!0,this.setSolvedPath(t));const n=this.getNeighbors(t);for(const t of n)this.candidates.enqueue(t)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.points.push({x:this.A.x,y:this.A.y,label:`Input A\nz: ${this.A.z}`,color:"orange"}),t.points.push({x:this.B.x,y:this.B.y,label:`Input B\nz: ${this.B.z}`,color:"orange"}),t.lines.push({points:[this.A,this.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:"Direct Input Connection"});for(let e=0;e<this.obstacleRoutes.length;e++){const s=this.obstacleRoutes[e];for(let n=0;n<s.route.length-1;n++){const i=s.route[n].z;t.lines.push({points:[s.route[n],s.route[n+1]],strokeColor:0===i?"rgba(255, 0, 0, 0.75)":"rgba(255, 128, 0, 0.25)",strokeWidth:s.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`})}}for(let e=0;e<this.debug_exploredNodesOrdered.length;e++){const s=this.debug_exploredNodesOrdered[e],[n,i,o]=s.split(",").map(Number);this.debug_nodesTooCloseToObstacle.has(s)||(this.debug_nodePathToParentIntersectsObstacle.has(s)||t.rects.push({center:{x:n+this.initialNodeGridOffset.x+o*this.cellStep/20,y:i+this.initialNodeGridOffset.y+o*this.cellStep/20},fill:0===o?`rgba(255,0,255,${.3-e/this.debug_exploredNodesOrdered.length*.2})`:`rgba(0,0,255,${.3-e/this.debug_exploredNodesOrdered.length*.2})`,width:.9*this.cellStep,height:.9*this.cellStep,label:`Explored (z=${o})`}))}if(this.candidates.peek()){const e=this.candidates.peek();t.rects.push({center:{x:e.x+e.z*this.cellStep/20,y:e.y+e.z*this.cellStep/20},fill:"rgba(0, 255, 0, 0.8)",width:.9*this.cellStep,height:.9*this.cellStep,label:`Next (z=${e.z})`})}for(const e of this.obstacleRoutes)for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:this.viaDiameter/2,fill:"rgba(255, 0, 0, 0.5)",label:"Via"});if(this.solvedPath){t.lines.push({points:this.solvedPath.route,strokeColor:"green",label:"Solved Route"});for(const e of this.solvedPath.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"green",label:"Via"})}return t}};function Ct(t){const e=[];for(let s=0;s<t.route.length-1;s++)t.route[s].z===t.route[s+1].z&&e.push({z:t.route[s].z,A:t.route[s],B:t.route[s+1]});return e}function _t(t,e,s){return Math.max(e,Math.min(t,s))}var Et=class extends Pt{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=!1;constructor(t){super(t);for(const e in t.hyperParameters)this[e]=t.hyperParameters[e];const e=this.boundsSize.width/this.viaDiameter,s=Math.max(1,this.numRoutes);this.VIA_PENALTY_FACTOR=e/s*.3*this.VIA_PENALTY_FACTOR_2}getClosestFutureConnectionPoint(t){let e=1/0,s=null;for(const n of this.futureConnections)for(const i of n.points){const n=dt(t,i)+(t.z!==i.z?this.viaPenaltyDistance:0);n<e&&(e=n,s=i)}return s}diminishCloseToGoal(t){const e=dt(t,this.B);return 1-Math.exp(-e/this.straightLineDistance*5)}getFutureConnectionPenalty(t,e){let s=0;const n=this.getClosestFutureConnectionPoint(t),i=dt(t,this.B);if(n){const o=dt(t,n);if(i<=o)return 0;const a=o/(this.viaDiameter*this.FUTURE_CONNECTION_PROXIMITY_VD);s=(e?this.straightLineDistance*this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR:this.straightLineDistance*this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR)*Math.exp(5*-a)}return s}computeH(t){const e=dt(t,this.B)**1.6;this.straightLineDistance;return e+(t.z!==this.B.z?this.viaPenaltyDistance:0)+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}computeG(t){const e=Math.abs(t.x-t.parent.x),s=Math.abs(t.y-t.parent.y),n=Math.sqrt(e**2+s**2),i=t.z%2==0,o=this.FLIP_TRACE_ALIGNMENT_DIRECTION?i?e:s:i?s:e;return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+n+o*this.MISALIGNED_DIST_PENALTY_FACTOR+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}};function Tt(t){let e=t;for(let t=0;t<10;t++)e=16807*e%2147483647;let s=e;e=(69069*t+1)%2147483647;for(let t=0;t<10;t++)e=48271*e%2147483647;let n=e;return()=>{let t=s;s=n,t^=t<<23,t^=t>>>17,t^=n,t^=n>>>26,n=t;const e=(s+n)/4294967296;return e-Math.floor(e)}}var wt={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 zt(t,e){if(0===e)return t;if(t.length<=4){const s=wt[t.length];return s[e%s.length].map(e=>t[e])}const s=Tt(e),n=t.slice();for(let t=0;t<n.length;t++){const e=Math.floor(s()*n.length),i=Math.floor(s()*(t+1));[n[e],n[i]]=[n[i],n[e]]}return n}function At(t){const e={minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2};for(const s of t.portPoints)s.x<e.minX&&(e.minX=s.x),s.x>e.maxX&&(e.maxX=s.x),s.y<e.minY&&(e.minY=s.y),s.y>e.maxY&&(e.maxY=s.y);return e}var Rt=class extends e{nodeWithPortPoints;colorMap;unsolvedConnections;totalConnections;solvedRoutes;failedSubSolvers;hyperParameters;minDistBetweenEnteringPoints;viaDiameter;traceWidth;activeSubSolver=null;connMap;get failedSolvers(){return this.failedSubSolvers}get activeSolver(){return this.activeSubSolver}constructor(t){const{nodeWithPortPoints:e,colorMap:s}=t;super(),this.nodeWithPortPoints=e,this.colorMap=s??{},this.solvedRoutes=[],this.hyperParameters=t.hyperParameters??{},this.failedSubSolvers=[],this.connMap=t.connMap,this.viaDiameter=t.viaDiameter??.6,this.traceWidth=t.traceWidth??.15;const n=new Map;for(const{connectionName:t,x:s,y:i,z:o}of e.portPoints)n.set(t,[...n.get(t)??[],{x:s,y:i,z:o??0}]);this.unsolvedConnections=Array.from(n.entries().map(([t,e])=>({connectionName:t,points:e}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=zt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},s)=>({...e,points:zt(t,7117*s+(this.hyperParameters.SHUFFLE_SEED??0))}))),this.totalConnections=this.unsolvedConnections.length,this.MAX_ITERATIONS=1e3*this.totalConnections**1.5,this.minDistBetweenEnteringPoints=(t=>{let e=1/0;const s=t.portPoints;for(let t=0;t<s.length;t++)for(let n=t+1;n<s.length;n++){if(s[t].z!==s[n].z)continue;const i=s[t],o=s[n],a=Math.sqrt((i.x-o.x)**2+(i.y-o.y)**2);e=Math.min(e,a)}return e===1/0?0:e})(this.nodeWithPortPoints)}computeProgress(){return(this.solvedRoutes.length+(this.activeSubSolver?.progress||0))/this.totalConnections}_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(t=>t.error).join("\n"),this.failed=!0));const t=this.unsolvedConnections.pop();if(this.progress=this.computeProgress(),!t)return void(this.solved=0===this.failedSubSolvers.length);if(1===t.points.length)return;if(2===t.points.length){const[e,s]=t.points;if(e.x===s.x&&e.y===s.y&&e.z===s.z)return}const{connectionName:e,points:s}=t;this.activeSubSolver=new Et({connectionName:e,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:At(this.nodeWithPortPoints),A:{x:s[0].x,y:s[0].y,z:s[0].z},B:{x:s[s.length-1].x,y:s[s.length-1].y,z:s[s.length-1].z},obstacleRoutes:this.connMap?this.solvedRoutes.filter(t=>!this.connMap.areIdsConnected(t.connectionName,e)):this.solvedRoutes,futureConnections:this.unsolvedConnections,layerCount:this.nodeWithPortPoints.portPoints.reduce((t,e)=>Math.max(t,(e.z??0)+1),2),hyperParameters:this.hyperParameters,connMap:this.connMap,viaDiameter:this.viaDiameter,traceThickness:this.traceWidth})}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:[e.connectionName,`layer: ${e.z}`].join("\n"),color:this.colorMap[e.connectionName]??"blue"});for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e];if(s.route.length>0){const n=this.colorMap[s.connectionName]??"blue";for(let i=0;i<s.route.length-1;i++){const o=s.route[i],a=s.route[i+1];t.lines.push({points:[o,a],strokeColor:0===o.z?V(n,.2):V(n,.8),layer:`route-layer-${o.z}`,step:e,strokeWidth:s.traceThickness})}for(const i of s.vias)t.circles.push({center:{x:i.x,y:i.y},radius:s.viaDiameter/2,fill:V(n,.5),layer:"via",step:e})}}const e=At(this.nodeWithPortPoints),{minX:s,minY:n,maxX:i,maxY:o}=e;return t.lines.push({points:[{x:s,y:n},{x:i,y:n},{x:i,y:o},{x:s,y:o},{x:s,y:n}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}},Ot=t=>Math.round(200*t)/200,Lt=t=>"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t));nt();var Dt=class extends Rt{cacheProvider;cacheHit=!1;hasAttemptedToUseCache=!1;initialUnsolvedConnections;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?st():t.cacheProvider,this.initialUnsolvedConnections=Lt(this.unsolvedConnections),(this.solved||this.failed)&&this.cacheProvider&&!this.cacheHit&&this.saveToCacheSync()}_step(){if(!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync())return;const t=this.solved,e=this.failed;super._step(),!this.cacheProvider||this.cacheHit||!this.solved&&!this.failed||t||e||this.saveToCacheSync()}computeCacheKeyAndTransform(){const t=this.nodeWithPortPoints.center,e=this.initialUnsolvedConnections.map(({connectionName:e,points:s})=>({connectionName:e,points:s.map(s=>({connectionName:e,x:Ot(s.x-t.x),y:Ot(s.y-t.y),z:s.z??0}))})),s=Object.fromEntries(Object.entries(this.hyperParameters??{}).filter(([,t])=>void 0!==t).sort(([t],[e])=>t.localeCompare(e))),n=this.connMap?this.initialUnsolvedConnections.map(({connectionName:t})=>({connectionName:t,connectedIds:[...new Set(this.connMap.getIdsConnectedToNet(t)??[])].sort()})):void 0,i={node:{width:Ot(this.nodeWithPortPoints.width),height:Ot(this.nodeWithPortPoints.height),center:{x:Ot(this.nodeWithPortPoints.center.x),y:Ot(this.nodeWithPortPoints.center.y)},availableZ:this.nodeWithPortPoints.availableZ?[...this.nodeWithPortPoints.availableZ].sort():void 0},normalizedConnections:e,normalizedHyperParameters:s,minDistBetweenEnteringPoints:Ot(this.minDistBetweenEnteringPoints),normalizedConnMap:n},o=`intranode-solver:${K(i)}`,a={};return this.cacheKey=o,this.cacheToSolveSpaceTransform=a,{cacheKey:o,cacheToSolveSpaceTransform:a}}applyCachedSolution(t){t.success?(this.solvedRoutes=Lt(t.solvedRoutes),this.solved=!0,this.failed=!1):(this.solvedRoutes=[],this.failedSubSolvers=[],this.solved=!1,this.failed=!0,this.error=t.error??this.error),this.unsolvedConnections=[],this.activeSubSolver=null,this.cacheHit=!0,this.progress=1}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return!1;if(!this.cacheKey)try{this.computeCacheKeyAndTransform()}catch(t){return console.error("Error computing cache key:",t),!1}if(!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(null!=t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(!this.cacheProvider?.isSyncCache)return;if(!this.cacheKey)try{this.computeCacheKeyAndTransform()}catch(t){return void console.error("Error computing cache key during save:",t)}if(!this.cacheKey)return void console.error("Failed to compute cache key before saving.");const t=this.failed?{success:!1,error:this.error??void 0}:{success:!0,solvedRoutes:Lt(this.solvedRoutes)};try{this.cacheProvider.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}},Ft=class extends e{GREEDY_MULTIPLIER=1.2;MIN_SUBSTEPS=1;supervisedSolvers;winningSolver;getHyperParameterDefs(){throw new Error("Not implemented")}getCombinationDefs(){return null}getHyperParameterCombinations(t){t||(t=this.getHyperParameterDefs());const e=[];if(0===t.length)return[{}];const[s,...n]=t,i=this.getHyperParameterCombinations(n);return s.possibleValues.forEach(t=>{i.forEach(s=>{e.push({...s,...t})})}),e}initializeSolvers(){const t=this.getHyperParameterDefs(),e=this.getCombinationDefs()??[t.map(t=>t.name)];this.supervisedSolvers=[];for(const s of e){const e=this.getHyperParameterCombinations(t.filter(t=>s.includes(t.name)));for(const t of e){const e=this.generateSolver(t),s=this.computeG(e);this.supervisedSolvers.push({hyperParameters:t,solver:e,h:0,g:s,f:s})}}}generateSolver(t){throw new Error("Not implemented")}computeG(t){return t.iterations/t.MAX_ITERATIONS}computeH(t){return 1-(t.progress||0)}computeF(t,e){return t+e*this.GREEDY_MULTIPLIER}getSupervisedSolverWithBestFitness(){let t=1/0,e=null;for(const s of this.supervisedSolvers??[]){if(s.solver.solved)return s;if(s.solver.failed)continue;const n=s.f;n<t&&(t=n,e=s)}return e}getFailureMessage(){return"All solvers failed in hyper solver."}_step(){this.supervisedSolvers||this.initializeSolvers();const t=this.getSupervisedSolverWithBestFitness();if(!t)return this.failed=!0,void(this.error=this.getFailureMessage());for(let e=0;e<this.MIN_SUBSTEPS;e++)t.solver.step();t.g=this.computeG(t.solver),t.h=this.computeH(t.solver),t.f=this.computeF(t.g,t.h),t.solver.solved&&(this.solved=!0,this.winningSolver=t.solver,this.onSolve?.(t))}onSolve(t){}visualize(){const t=this.getSupervisedSolverWithBestFitness();let e={lines:[],circles:[],points:[],rects:[]};return t&&(e=t.solver.visualize()),e}};function $t({A:t,B:e,C:s,D:n,E:i,F:o,radius:a,margin:r,subdivisions:h=0}){const c=(t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}),d=(t,e,s)=>{const n=e.x-t.x,i=e.y-t.y,o=Math.sqrt(n*n+i*i),a=n/o,r=i/o,h=-r,c=a;return{midpoint:{x:(t.x+e.x)/2,y:(t.y+e.y)/2},A_Opp:{x:t.x-a*s,y:t.y-r*s},A_Right:{x:t.x+h*s,y:t.y+c*s},A_Left:{x:t.x-h*s,y:t.y-c*s},B_Opp:{x:e.x+a*s,y:e.y+r*s},B_Right:{x:e.x+h*s,y:e.y+c*s},B_Left:{x:e.x-h*s,y:e.y-c*s}}},l=(t,e)=>{const s=dt(t,e.start),n=dt(t,e.end),i=dt(e.start,e.end);return Math.abs(s+n-i)<1e-4},u=(t,e)=>{const{start:s,end:n}=t,{start:i,end:o}=e;if(l(s,e)||l(n,e)||l(i,t)||l(o,t))return!0;const a=n.x-s.x,r=n.y-s.y,h=o.x-i.x,c=o.y-i.y,d=a*c-r*h;if(Math.abs(d)<1e-4)return!1;const u=i.x-s.x,p=i.y-s.y,f=(u*c-p*h)/d,g=(u*r-p*a)/d;return f>0&&f<1&&g>0&&g<1},p=(t,e)=>{const s=[];for(let e=0;e<t.length-1;e++)s.push({start:t[e],end:t[e+1]});const n=[];for(let t=0;t<e.length-1;t++)n.push({start:e[t],end:e[t+1]});for(const t of s)for(const e of n)if(u(t,e))return!0;return!1},f=t=>{let e=0;for(let s=1;s<t.length;s++){const n=t[s].x-t[s-1].x,i=t[s].y-t[s-1].y;e+=Math.sqrt(n*n+i*i)}return e},g=(t,e)=>{const{start:s,end:n}=t,i=n.x-s.x,o=n.y-s.y,a=i*i+o*o;if(0===a)return{...s,t:0};const r=Math.max(0,Math.min(1,((e.x-s.x)*i+(e.y-s.y)*o)/a));return{x:s.x+r*i,y:s.y+r*o,t:r}},m=(e,s,n)=>{const i=g(e,s);if(dt(i,s)>=n)return i;const o=i.x-s.x,a=i.y-s.y,r=Math.sqrt(o*o+a*a);if(0===r){const o=e.end.x-e.start.x,a=e.end.y-e.start.y,r=Math.sqrt(o*o+a*a);return{x:s.x+n*o/r,y:s.y+n*a/r,t:i.t,isSpecial:!0,specialType:s===t?"A":"B"}}return{x:s.x+n*o/r,y:s.y+n*a/r,t:i.t,isSpecial:!0,specialType:s===t?"A":"B"}},y=d(t,e,a),x=d(t,e,a+r),v=(t,e,s,n,i)=>{const o=t.points;if(o.length<2)return o;const r=s+n,h=[o[0]];for(let t=0;t<o.length-1;t++){const s={start:o[t],end:o[t+1]};if(ct(e,s.start,s.end)<r){const t=g(s,e),n=t.x-e.x,i=t.y-e.y,o=Math.sqrt(n*n+i*i);let c=null;if(o>1e-6)c={x:e.x+r*n/o,y:e.y+r*i/o};else{const t=s.end.x-s.start.x,n=s.end.y-s.start.y,i=Math.sqrt(t*t+n*n);i>1e-6&&(c={x:e.x+r*t/i,y:e.y+r*n/i})}c&&dt(s.start,c)>a/10&&h.push(c)}dt(h[h.length-1],s.end)>a/10&&h.push(s.end)}if(h.length>1){const t=[h[0]];for(let e=1;e<h.length;e++)dt(t[t.length-1],h[e])>a/10&&t.push(h[e]);return t}return h},M=(()=>{const t=[[s,y.B_Left,y.B_Opp,y.B_Right,c(y.midpoint,c(y.B_Right,y.A_Right)),c(y.midpoint,c(y.A_Left,y.B_Left)),y.A_Left,y.A_Opp,y.A_Right,n],[s,y.B_Right,y.B_Opp,y.B_Left,c(y.midpoint,c(y.A_Left,y.B_Left)),c(y.midpoint,c(y.A_Right,y.B_Right)),y.A_Right,y.A_Opp,y.A_Left,n],[n,y.B_Left,y.B_Opp,y.B_Right,c(y.midpoint,c(y.A_Right,y.B_Right)),c(y.midpoint,c(y.A_Left,y.B_Left)),y.A_Left,y.A_Opp,y.A_Right,s],[n,y.B_Right,y.B_Opp,y.B_Left,c(y.midpoint,c(y.A_Left,y.B_Left)),c(y.midpoint,c(y.A_Right,y.B_Right)),y.A_Right,y.A_Opp,y.A_Left,s]],e=[];for(let s=0;s<t.length;s++){const n=t[s],i={start:n[0],end:n[1]},o={start:n[n.length-2],end:n[n.length-1]},a={start:n[3],end:n[4]};u(i,o)||u(i,a)||u(o,a)||e.push({index:s+1,path:n,length:f(n)})}if(0===e.length)return{index:0,path:[]};const i=e.sort((t,e)=>t.length-e.length)[0],o=[...i.path],a=o[0],r=dt(a,o[2]),h=dt(a,o[3]),d=r<h?2:3;(r<dt(a,o[1])||h<dt(a,o[1]))&&o.splice(1,d-1);const l=o[o.length-1],p=dt(l,o[o.length-3]),g=dt(l,o[o.length-4]),m=p<g?o.length-3:o.length-4;return(p<dt(l,o[o.length-2])||g<dt(l,o[o.length-2]))&&o.splice(m+1,o.length-m-2),{index:i.index,path:o,startsAt:o[0]===s?"C":"D",goesTo:o[o.length-1]===s?"C":"D"}})(),S=h>0?((s,n)=>{if(s.length<2)return s;const i=[s[0]];for(let o=0;o<s.length-1;o++){const r={start:s[o],end:s[o+1]},h={x:(r.start.x+r.end.x)/2,y:(r.start.y+r.end.y)/2},c=dt(h,t),d=dt(h,e);if((c<=a||d<=a)&&Math.abs(c-d)>1e-4){const s=g(r,t),o=g(r,e),h=dt(s,t),c=dt(o,e)<a,d=h<a?m(r,t,a):null,l=c?m(r,e,a):null;let u=[];if(dt(r.start,r.end)>a/2&&n>0)for(let s=1;s<=n;s++){const i=s/(n+1),o={x:r.start.x+i*(r.end.x-r.start.x),y:r.start.y+i*(r.end.y-r.start.y),t:i,isSpecial:!1},h=dt(o,t),c=dt(o,e);h<a||c<a||(d&&Math.abs(o.t-d.t)<.1||l&&Math.abs(o.t-l.t)<.1||u.push(o))}if(d&&u.push(d),l&&u.push(l),u.sort((t,e)=>t.t-e.t),u.length>1){const t=[u[0]];for(let e=1;e<u.length;e++){const s=t[t.length-1],n=u[e];dt(s,n)>a/10&&t.push(n)}u=t}u.forEach(t=>i.push(t))}i.push(s[o+1])}if(i.length>1){const t=[i[0]];for(let e=1;e<i.length;e++){const s=t[t.length-1],n=i[e];dt(s,n)>a/10&&t.push(n)}return t}return i})(M.path,h):M.path;let b=(()=>{if(0===M.path.length)return null;const s=(()=>{const s=c(y.A_Right,y.B_Right),n=c(y.B_Left,y.A_Left);return[{startsAt:"E",goesTo:"B",points:[i,e]},{startsAt:"E",goesTo:"A",points:[i,t]},{startsAt:"F",goesTo:"B",points:[o,e]},{startsAt:"F",goesTo:"A",points:[o,t]},{startsAt:"E",goesTo:"B",points:[i,s,e]},{startsAt:"E",goesTo:"A",points:[i,s,t]},{startsAt:"F",goesTo:"B",points:[o,s,e]},{startsAt:"F",goesTo:"A",points:[o,s,t]},{startsAt:"E",goesTo:"B",points:[i,n,e]},{startsAt:"E",goesTo:"A",points:[i,n,t]},{startsAt:"F",goesTo:"B",points:[o,n,e]},{startsAt:"F",goesTo:"A",points:[o,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Right,s,e]},{startsAt:"F",goesTo:"B",points:[o,x.B_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Left,n,t]},{startsAt:"F",goesTo:"A",points:[o,x.A_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Right,s,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Opp,x.A_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Opp,x.B_Left,n,t]},{startsAt:"F",goesTo:"B",points:[o,x.A_Opp,x.A_Left,n,e]},{startsAt:"F",goesTo:"A",points:[o,x.B_Opp,x.B_Right,s,t]},{startsAt:"F",goesTo:"A",points:[o,x.B_Opp,x.B_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Opp,x.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Opp,x.B_Right,s,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Left,x.A_Opp,x.A_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Right,x.B_Opp,x.B_Left,n,t]},{startsAt:"F",goesTo:"B",points:[o,x.A_Right,x.A_Opp,x.A_Left,n,e]},{startsAt:"F",goesTo:"A",points:[o,x.B_Left,x.B_Opp,x.B_Right,s,t]},{startsAt:"F",goesTo:"A",points:[o,x.B_Right,x.B_Opp,x.B_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Right,x.A_Opp,x.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Left,x.B_Opp,x.B_Right,s,t]}].map((t,e)=>({...t,index:e}))})(),n=s.filter(t=>"E"===t.startsAt),a=s.filter(t=>"F"===t.startsAt),r=[],h=[];for(const t of n)if(!p(t.points,M.path)){r.push(t);break}for(const t of a)if(!p(t.points,M.path)){h.push(t);break}return 0===r.length||0===h.length?null:{line1:r[0],line2:h[0]}})();if(b){const s="A"===b.line1.goesTo?e:t,n="A"===b.line2.goesTo?e:t,i=v(b.line1,s,a,r),o=v(b.line2,n,a,r);b={line1:{...b.line1,points:i},line2:{...b.line2,points:o}}}return{jPair:b,optimalPath:{startsAt:M.startsAt,goesTo:M.goesTo,points:S}}}var kt=class extends e{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;escapeLayer=1;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return void(this.failed=!0);const[e,s]=this.routes;if(!(e.startPort.z===e.endPort.z))return void(this.failed=!0);if(!(s.startPort.z===s.endPort.z))return void(this.failed=!0);e.startPort.z===s.startPort.z?0===e.startPort.z?this.escapeLayer=1:this.escapeLayer=0:this.failed=!0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,s=new Map;for(const t of e){const{connectionName:e}=t;s.has(e)||s.set(e,[]),s.get(e)?.push(t)}for(const[e,n]of s.entries())2===n.length&&t.push({startPort:{...n[0],z:n[0].z??0},endPort:{...n[1],z:n[1].z??0},connectionName:e});return t}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(t,e){return at(t.startPort,t.endPort,e.startPort,e.endPort)}calculateViaPositions(t,e){const s=this.bounds.maxX-this.bounds.minX,n=this.bounds.maxY-this.bounds.minY,i=this.bounds.minX,o=this.bounds.minY,a={width:s-2*this.obstacleMargin-this.viaDiameter,height:n-2*this.obstacleMargin-this.viaDiameter,x:i+this.obstacleMargin+this.viaDiameter/2,y:o+this.obstacleMargin+this.viaDiameter/2},r=this.viaDiameter+this.obstacleMargin,h=e.startPort,c=e.endPort,d=[{x:a.x,y:a.y},{x:a.x+a.width,y:a.y},{x:a.x+a.width,y:a.y+a.height},{x:a.x,y:a.y+a.height}],l=(t,e)=>dt(t,e),u=[];d.forEach((t,e)=>{l(t,h)>=r&&l(t,c)>=r&&u.push({...t,type:"corner",index:e})});const p=[{p1:d[0],p2:d[1]},{p1:d[1],p2:d[2]},{p1:d[2],p2:d[3]},{p1:d[3],p2:d[0]}];if([h,c].forEach((t,e)=>{p.forEach((s,n)=>{((t,e)=>{const s=t.x,n=t.y,i=t.r,o=e.p1.x,a=e.p1.y,r=e.p2.x,h=e.p2.y;if(Math.abs(r-o)<.001){const t=o,e=i*i-(t-s)**2;if(e<0)return[];if(Math.abs(e)<.001){const e=n;return e>=Math.min(a,h)&&e<=Math.max(a,h)?[{x:t,y:e}]:[]}const r=n+Math.sqrt(e),c=n-Math.sqrt(e),d=[];return r>=Math.min(a,h)&&r<=Math.max(a,h)&&d.push({x:t,y:r}),c>=Math.min(a,h)&&c<=Math.max(a,h)&&d.push({x:t,y:c}),d}const c=(h-a)/(r-o),d=a-c*o,l=1+c*c,u=2*(c*d-c*n-s),p=u*u-4*l*(s*s+(d-n)*(d-n)-i*i);if(p<0)return[];if(Math.abs(p)<.001){const t=-u/(2*l),e=c*t+d;return t>=Math.min(o,r)&&t<=Math.max(o,r)&&e>=Math.min(a,h)&&e<=Math.max(a,h)?[{x:t,y:e}]:[]}const f=(-u+Math.sqrt(p))/(2*l),g=(-u-Math.sqrt(p))/(2*l),m=c*f+d,y=c*g+d,x=[];return f>=Math.min(o,r)&&f<=Math.max(o,r)&&m>=Math.min(a,h)&&m<=Math.max(a,h)&&x.push({x:f,y:m}),g>=Math.min(o,r)&&g<=Math.max(o,r)&&y>=Math.min(a,h)&&y<=Math.max(a,h)&&x.push({x:g,y:y}),x})({...t,r:r},s).forEach(t=>{l(t,0===e?c:h)>=r&&u.push({...t,type:"intersection",circle:e,edge:n})})})}),u.length<2){const t=.8*r;if(d.forEach((e,s)=>{l(e,h)>=t&&l(e,c)>=t&&!u.some(t=>t.x===e.x&&t.y===e.y)&&u.push({...e,type:"relaxed_corner",index:s})}),u.length<2){const t=[...d].sort((t,e)=>{const s=Math.min(l(t,h),l(t,c));return Math.min(l(e,h),l(e,c))-s});for(const e of t)if(!u.some(t=>t.x===e.x&&t.y===e.y)&&(u.push({...e,type:"forced_corner"}),u.length>=2))break}}if(u.length<2)return null;let f=0,g=[u[0],u[u.length>1?1:0]];for(let t=0;t<u.length;t++)for(let e=t+1;e<u.length;e++){const s=l(u[t],u[e]);s>f&&(f=s,g=[u[t],u[e]])}let m={x:g[0].x,y:g[0].y},y={x:g[1].x,y:g[1].y};const x=dt(m,t.startPort);return dt(y,t.startPort)<x&&([m,y]=[y,m]),{via1:m,via2:y}}trySolveAOverB(t,e,s=!1){const n=s?this.calculateViaPositions(t,e):this.calculateViaPositions(e,t);if(!n)return!1;this.debugViaPositions.push(n);const{via1:i,via2:o}=this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(n));this.debugViaPositions.push({via1:i,via2:o});const{jPair:a,optimalPath:r}=$t({A:i,B:o,C:t.startPort,D:t.endPort,E:e.startPort,F:e.endPort,radius:this.viaDiameter/2+this.obstacleMargin+this.traceThickness/2*1.5,margin:2*this.obstacleMargin+this.traceThickness/2*1.5,subdivisions:1});if(!a)return!1;const h={connectionName:t.connectionName,route:r.points.map(e=>({x:e.x,y:e.y,z:t.startPort.z??0})),traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};a.line2.points.reverse();const c={connectionName:e.connectionName,route:[...a.line1.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0})),{...a.line1.points[a.line1.points.length-1],z:this.escapeLayer},{...a.line2.points[0],z:this.escapeLayer},...a.line2.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0}))],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[i,o]};return this.solvedRoutes.push(h,c),!0}pushViasFromEndpoints(t){const e={...t.via1},s={...t.via2},n=[this.routes[0].startPort,this.routes[0].endPort,this.routes[1].startPort,this.routes[1].endPort],i=this.getMinDistanceBetweenViaCenters(),o=this.viaDiameter/2+2*this.traceThickness+2*this.obstacleMargin;for(let t=0;t<10;t++){let a=!1,r=!1;const h=.9**t;for(const t of n){const n=dt(e,t);if(n<o){const s=(o-n)*h,i=e.x-t.x,r=e.y-t.y,c=Math.sqrt(i*i+r*r);c>1e-6&&(e.x+=i/c*s,e.y+=r/c*s,a=!0)}const i=dt(s,t);if(i<o){const e=(o-i)*h,n=s.x-t.x,a=s.y-t.y,c=Math.sqrt(n*n+a*a);c>1e-6&&(s.x+=n/c*e,s.y+=a/c*e,r=!0)}}const c=dt(e,s);if(c<i){const t=(i-c)/2,n=s.x-e.x,o=s.y-e.y,h=Math.sqrt(n*n+o*o);h>1e-6?(e.x-=n/h*t,e.y-=o/h*t,s.x+=n/h*t,s.y+=o/h*t,a=!0,r=!0):(e.x-=t,s.x+=t,a=!0,r=!0)}if(!a&&!r)break}const a=dt(e,s);if(a<i){const t=(i-a)/2,n=s.x-e.x,o=s.y-e.y,r=Math.sqrt(n*n+o*o);r>1e-6?(e.x-=n/r*t,e.y-=o/r*t,s.x+=n/r*t,s.y+=o/r*t):(e.x-=t,s.x+=t)}return{via1:e,via2:s}}getMinDistanceBetweenViaCenters(){return this.viaDiameter+this.traceThickness+2*this.obstacleMargin}moveViasAsCloseAsPossible(t){const{via1:e,via2:s}=t,n=this.getMinDistanceBetweenViaCenters(),i=dt(e,s);if(i<=n)return t;const o=s.x-e.x,a=s.y-e.y,r=Math.sqrt(o*o+a*a),h=o/r,c=a/r,d=(e.x,s.x,e.y,s.y,(i-n)/2);return{via1:{x:e.x+h*d,y:e.y+c*d},via2:{x:s.x-h*d,y:s.y-c*d}}}handleRoutesDontCross(){const[t,e]=this.routes,s={connectionName:t.connectionName,route:[{x:t.startPort.x,y:t.startPort.y,z:t.startPort.z??0},{x:t.endPort.x,y:t.endPort.y,z:t.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]},n={connectionName:e.connectionName,route:[{x:e.startPort.x,y:e.startPort.y,z:e.startPort.z??0},{x:e.endPort.x,y:e.endPort.y,z:e.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};this.solvedRoutes.push(s,n),this.solved=!0}_step(){if(2!==this.routes.length)return void(this.failed=!0);const[t,e]=this.routes;this.doRoutesCross(t,e)?this.trySolveAOverB(t,e)||this.trySolveAOverB(e,t)||this.trySolveAOverB(t,e,!0)||this.trySolveAOverB(e,t,!0)?this.solved=!0:this.failed=!0:this.handleRoutesDontCross()}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.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[e,s]of[["Route A",this.routes[0]],["Route B",this.routes[1]]])t.points.push({x:s.startPort.x,y:s.startPort.y,label:`${e}\n${s.connectionName} start`,color:"orange"}),t.points.push({x:s.endPort.x,y:s.endPort.y,label:`${e}\n${s.connectionName} end`,color:"orange"}),t.lines.push({points:[s.startPort,s.endPort],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e}\n${s.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via1:s,via2:n}=this.debugViaPositions[e],i=["rgba(255, 165, 0, 0.3)","rgba(128, 0, 128, 0.3)"],o=i[e%i.length];t.circles.push({center:s,radius:this.viaDiameter/2,fill:o,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via A (attempt ${e+1})`}),t.circles.push({center:n,radius:this.viaDiameter/2,fill:o,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via B (attempt ${e+1})`});const a=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:s,radius:a,stroke:o,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 1 Safety Margin (attempt ${e+1})`}),t.circles.push({center:n,radius:a,stroke:o,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 2 Safety Margin (attempt ${e+1})`}),t.lines.push({points:[this.routes[e%2].startPort,s,n,this.routes[e%2].endPort],strokeColor:`${o.substring(0,o.lastIndexOf(","))}, 0.3)`,strokeDash:[5,5],label:`Potential Route (attempt ${e+1})`})}for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e],n=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1];t.lines.push({points:[i,o],strokeColor:n,strokeDash:1===i.z?[.2,.2]:void 0,strokeWidth:s.traceThickness,label:`${s.connectionName} z=${i.z}`}),i._label&&t.points.push({x:i.x,y:i.y,label:i._label})}for(const e of s.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Solved Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}};function Bt(t,e,s,n,i){const o={x:(t.x+e.x+s.x)/3,y:(t.y+e.y+s.y)/3},a=(t,e)=>Math.sqrt((e.x-t.x)**2+(e.y-t.y)**2),r=o=>{const r=a(o,t),h=a(o,e),c=a(o,s),d=o.x>=i.minX&&o.x<=i.maxX&&o.y>=i.minY&&o.y<=i.maxY;return r>=n&&h>=n&&c>=n&&d};if(r(o))return o;const h=(t,e,s)=>{const n=t.x-e.x,i=t.y-e.y,o=Math.sqrt(n*n+i*i);return o<1e-10?{x:e.x+s,y:e.y}:{x:e.x+n/o*s,y:e.y+i/o*s}},c=(t,e,s)=>{const n=e.x-t.x,i=e.y-t.y,o=Math.sqrt(n*n+i*i);if(o>2*s-1e-10||o<1e-10)return[];const r=o*o/(2*o),h=Math.sqrt(Math.max(0,s*s-r*r)),c=t.x+n*r/o,d=t.y+i*r/o,l={x:c+h*i/o,y:d-h*n/o},u={x:c-h*i/o,y:d+h*n/o},p=[],f=1e-6;return Math.abs(a(l,t)-s)<f&&Math.abs(a(l,e)-s)<f&&p.push(l),Math.abs(a(u,t)-s)<f&&Math.abs(a(u,e)-s)<f&&p.push(u),p},d=[h(o,t,n),h(o,e,n),h(o,s,n),...c(t,e,n),...c(e,s,n),...c(s,t,n)],l=d.filter(r);if(l.length>0){const t=l.filter(t=>!(t=>{const e=1e-6;return Math.abs(t.x-i.minX)<e||Math.abs(t.x-i.maxX)<e||Math.abs(t.y-i.minY)<e||Math.abs(t.y-i.maxY)<e})(t));if(t.length>0)return t.sort((t,e)=>a(t,o)-a(e,o)),t[0]}let u=null,p=1/0;for(let t=i.minX+1;t<i.maxX;t+=5)for(let e=i.minY+1;e<i.maxY;e+=5){const s={x:t,y:e};if(r(s)){const t=a(s,o);t<p&&(p=t,u=s)}}if(null!==u)return u;const f=[];for(let t=0;t<=100;t++){const e=t/100;f.push({x:i.minX+e*(i.maxX-i.minX),y:i.minY}),f.push({x:i.maxX,y:i.minY+e*(i.maxY-i.minY)}),f.push({x:i.maxX-e*(i.maxX-i.minX),y:i.maxY}),f.push({x:i.minX,y:i.maxY-e*(i.maxY-i.minY)})}const g=f.filter(r);if(g.length>0)return g.sort((t,e)=>a(t,o)-a(e,o)),g[0];let m=1/0,y={x:i.minX,y:i.minY};for(const o of[...d,...f])if(o.x>=i.minX&&o.x<=i.maxX&&o.y>=i.minY&&o.y<=i.maxY){const i=Math.max(0,n-a(o,t))+Math.max(0,n-a(o,e))+Math.max(0,n-a(o,s));i<m&&(m=i,y=o)}return y}function Xt(t,e,s){const n=Yt(e,t,s.center,s.radius),i=Yt(t,e,s.center,s.radius),o=Ht(n,e),a=Ht(t,i),r=1e-6;let h;if(o>r&&a>r){h={x:(n.x+i.x)/2,y:(n.y+i.y)/2};const o=Ht(n,h),a=Ht(i,h);if(Math.abs(o-a)>.5*Math.min(o,a)){const s=Ht(t,n),o=Ht(e,i),a=s+o;if(a>r){const t=o/a,e=s/a;h={x:n.x*t+i.x*e,y:n.y*t+i.y*e}}}const c=Ht(h,s.center);if(c<1.05*s.radius){const t={x:(h.x-s.center.x)/c,y:(h.y-s.center.y)/c};h={x:s.center.x+t.x*s.radius*1.2,y:s.center.y+t.y*s.radius*1.2}}}else{const n={x:(t.x+e.x)/2,y:(t.y+e.y)/2},i=Ht(n,s.center);if(i<1.1*s.radius){const t={x:(n.x-s.center.x)/i,y:(n.y-s.center.y)/i};h={x:s.center.x+t.x*s.radius*1.2,y:s.center.y+t.y*s.radius*1.2}}else h=n}return{B:n,D:i,E:h}}function Yt(t,e,s,n){const i=[s.x-t.x,s.y-t.y],o=Math.sqrt(i[0]*i[0]+i[1]*i[1]);if(o<=n){if(o<1e-8){const i=[e.x-t.x,e.y-t.y],o=Math.sqrt(i[0]*i[0]+i[1]*i[1]);return o<1e-8?{x:s.x+n,y:s.y}:{x:s.x+i[0]/o*n,y:s.y+i[1]/o*n}}const a=[i[0]/o,i[1]/o];return{x:s.x-a[0]*n,y:s.y-a[1]*n}}const a=[e.x-t.x,e.y-t.y],r=Math.sqrt(o*o-n*n),h=[i[0]/o,i[1]/o],c=[-h[1],h[0]],d=[h[1],-h[0]],l=a[0]*c[0]+a[1]*c[1]>a[0]*d[0]+a[1]*d[1]?c:d,u=n/o,p=r/o,f=[h[0]*p+l[0]*u,h[1]*p+l[1]*u];return{x:t.x+r*f[0],y:t.y+r*f[1]}}function Ht(t,e){const s=e.x-t.x,n=e.y-t.y;return Math.sqrt(s*s+n*n)}var Vt=1e-9;function jt(t,e,s,n="cw"){const i=Zt(t,s),o=Zt(e,s);return Math.abs(o-i)<Vt?{left:0,top:0,right:0,bottom:0}:function(t,e,s,n){const i=s.maxX-s.minX,o=s.maxY-s.minY;if(i<Vt&&o<Vt)return{left:0,top:0,right:0,bottom:0};const a=2*(i+o);if(a<Vt)return{left:0,top:0,right:0,bottom:0};const r=i/a*(2*Math.PI),h=(i+o)/a*(2*Math.PI),c=(i+i+o)/a*(2*Math.PI),d=2*Math.PI,l=[{name:"top",start:0,end:r,length:i},{name:"right",start:r,end:h,length:o},{name:"bottom",start:h,end:c,length:i},{name:"left",start:c,end:d,length:o}],u={left:0,top:0,right:0,bottom:0},p=(t,e,s,n,i)=>{const o=e>2*Math.PI-Vt?2*Math.PI:e;if(o<=t+Vt)return 0;if(i){const e=Math.max(t,s),i=Math.min(o,2*Math.PI),a=Math.max(0,i-e),r=Math.max(t,0),h=Math.min(o,n);return a+Math.max(0,h-r)}{const e=Math.max(t,s),i=Math.min(o,n);return Math.max(0,i-e)}};for(const s of l){const i=s.end-s.start;if(i<Vt||s.length<Vt)continue;let o=0;if("cw"===n){const n=t>e+Vt;o=p(s.start,s.end,t,e,n)}else{const n=e>t+Vt;o=p(s.start,s.end,e,t,n)}if(o>Vt){const t=o/i;u[s.name]+=Math.max(0,Number.isFinite(t)?t:0)}}for(const t in u)u[t]=Math.max(0,Math.min(1,u[t]));return u}(i,o,s,n)}function Zt(t,e){const s=e.maxX-e.minX,n=e.maxY-e.minY;if(s<Vt&&n<Vt)return 0;const i=2*(s+n);if(i<Vt)return 0;let o=0;if(Math.abs(t.y-e.maxY)<Vt&&t.x>=e.minX-Vt&&t.x<=e.maxX+Vt)o=Math.max(0,Math.min(s,t.x-e.minX));else if(Math.abs(t.x-e.maxX)<Vt&&t.y>=e.minY-Vt&&t.y<=e.maxY+Vt)o=s+Math.max(0,Math.min(n,e.maxY-t.y));else if(Math.abs(t.y-e.minY)<Vt&&t.x>=e.minX-Vt&&t.x<=e.maxX+Vt)o=s+n+Math.max(0,Math.min(s,e.maxX-t.x));else{if(!(Math.abs(t.x-e.minX)<Vt&&t.y>=e.minY-Vt&&t.y<=e.maxY+Vt))throw new Error(`Point (${t.x}, ${t.y}) does not lie on the boundary defined by ${JSON.stringify(e)}`);o=s+n+s+Math.max(0,Math.min(n,t.y-e.minY))}return o=Math.max(0,Math.min(i,o)),i>Vt?o/i*(2*Math.PI):0}function Wt(t,e,s,n){return function({angleA:t,angleB:e,angleC:s}){const n=Math.cos(t),i=Math.sin(t),o=Math.cos(e),a=Math.sin(e),r=Math.cos(s);return(o-n)*(Math.sin(s)-i)-(a-i)*(r-n)<0?"ccw":"cw"}({angleA:Zt(t,n),angleB:Zt(e,n),angleC:Zt(s,n)})}var Ut=class extends e{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return void(this.failed=!0);const[e,s]=this.routes,n=e.A.z!==e.B.z,i=s.A.z!==s.B.z;(n&&i||!n&&!i)&&(this.failed=!0)}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,s=new Map;for(const t of e){const{connectionName:e}=t;s.has(e)||s.set(e,[]),s.get(e)?.push(t)}for(const[e,n]of s.entries())2===n.length&&t.push({A:{...n[0],z:n[0].z??0},B:{...n[1],z:n[1].z??0},connectionName:e});return t}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(t,e){return at(t.A,t.B,e.A,e.B)}calculateViaPosition(t,e){const s=e.A.z,n=t.A.z!==s?t.A:t.B,i=2*this.obstacleMargin+this.viaDiameter/2+this.traceThickness,o=this.obstacleMargin+this.viaDiameter/2,a=e.A,r=n,h=e.B,c=Wt(a,r,h,this.bounds),d=function(t,e,s,n,i){const o=jt(t,e,n,i),a=jt(e,s,n,i),r={left:Math.min(1,o.left+a.left),top:Math.min(1,o.top+a.top),right:Math.min(1,o.right+a.right),bottom:Math.min(1,o.bottom+a.bottom)};for(const t in r)Math.abs(r[t])<Vt&&(r[t]=0);return r}(a,r,h,this.bounds,c),l={minX:this.bounds.minX+(d.left>.5?i:o),minY:this.bounds.minY+(d.bottom>.5?i:o),maxX:this.bounds.maxX-(d.right>.5?i:o),maxY:this.bounds.maxY-(d.top>.5?i:o)};return l.maxY<l.minY&&(l.minY=(l.minY+l.maxY)/2,l.maxY=l.minY),l.maxX<l.minX&&(l.minX=(l.minX+l.maxX)/2,l.maxX=l.minX),Bt(a,r,h,i,l)}createTransitionRoute(t,e,s,n){return{connectionName:n,route:[{x:t.x,y:t.y,z:t.z??0},{x:s.x,y:s.y,z:t.z??0},{x:s.x,y:s.y,z:e.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[s]}}createFlatRoute(t,e,s,n,i,o){n.z,t.z;const a=this.viaDiameter/2+this.traceThickness/2+this.obstacleMargin,r=((t,e,s,n)=>{const i=s.x-t.x,o=s.y-t.y;return((t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}))({x:t.x+i*e,y:t.y+o*e},{x:s.x-i*n,y:s.y-o*n})})(s,this.viaDiameter,n.z!==t.z?n:i,this.traceThickness),h={center:{x:s.x,y:s.y},radius:a},c=Xt(t,r,h).E,d=Xt(r,e,h).E,l=Xt(t,c,h).E,u=Xt(c,r,h).E,p=Xt(r,d,h).E,f=Xt(d,e,h).E,g=Xt(u,p,h).E;return{connectionName:o,route:[{x:t.x,y:t.y,z:t.z??0},{x:l.x,y:l.y,z:t.z??0},{x:c.x,y:c.y,z:t.z??0},{x:u.x,y:u.y,z:t.z??0},{x:g.x,y:g.y,z:t.z??0},{x:p.x,y:p.y,z:t.z??0},{x:d.x,y:d.y,z:t.z??0},{x:f.x,y:f.y,z:t.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]}}trySolve(){const[t,e]=this.routes,s=t.A.z!==t.B.z,n=s?t:e,i=s?e:t,o=this.calculateViaPosition(n,i);if(!o)return!1;this.debugViaPositions.push({via:o});const a=this.createTransitionRoute(n.A,n.B,o,n.connectionName),r=this.createFlatRoute(i.A,i.B,o,n.A,n.B,i.connectionName);return this.solvedRoutes.push(a,r),!0}_step(){if(!this.doRoutesCross(this.routes[0],this.routes[1]))return this.failed=!0,void(this.error="Can only solve routes that have a single transition crossing");this.trySolve()?this.solved=!0:this.failed=!0}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.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 e of this.routes)t.points.push({x:e.A.x,y:e.A.y,label:`${e.connectionName} start (z=${e.A.z})`,color:"orange"}),t.points.push({x:e.B.x,y:e.B.y,label:`${e.connectionName} end (z=${e.B.z})`,color:"orange"}),t.lines.push({points:[e.A,e.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via:s}=this.debugViaPositions[e];t.circles.push({center:s,radius:this.viaDiameter/2,fill:"rgba(255, 165, 0, 0.7)",stroke:"rgba(0, 0, 0, 0.5)",label:`Computed Via (attempt ${e+1})`});const n=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:s,radius:n,stroke:"rgba(255, 165, 0, 0.7)",fill:"rgba(0, 0, 0, 0)",label:"Safety Margin"})}for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e],n=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1];t.lines.push({points:[i,o],strokeColor:n,strokeDash:i.z!==s.route[0].z?[.2,.2]:void 0,strokeWidth:s.traceThickness,label:`${s.connectionName} z=${i.z}`})}for(const e of s.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}},Gt=(t,e)=>{const s={};return t.portPoints.forEach((e,n)=>{s[e.connectionName]=`hsl(${360*n/t.portPoints.length}, 100%, 50%)`}),s},qt=class extends e{bounds;maxViaCount;portPairMap;colorMap;nodeWidth;availableZ;hyperParameters;VIA_INTERSECTION_BUFFER_DISTANCE=.05;PLACEHOLDER_WALL_BUFFER_DISTANCE=.1;NEW_HEAD_WALL_BUFFER_DISTANCE=.05;viaDiameter;unprocessedConnections;completedPaths=new Map;placeholderPaths=new Map;currentHead;currentConnectionName;currentPath;currentViaCount;constructor({nodeWithPortPoints:t,colorMap:e,hyperParameters:s,viaDiameter:n}){super(),this.MAX_ITERATIONS=1e5,this.colorMap=e??Gt(t),this.maxViaCount=5,this.bounds=At(t),this.nodeWidth=this.bounds.maxX-this.bounds.minX,this.portPairMap=(t=>{const e=new Map;return t.portPoints.forEach(t=>{e.has(t.connectionName)?e.get(t.connectionName).end=t:e.set(t.connectionName,{start:t,end:null,connectionName:t.connectionName})}),e})(t),this.stats.solutionsFound=0,this.availableZ=t.availableZ??[0,1],this.hyperParameters=s??{SHUFFLE_SEED:0},this.viaDiameter=n??.6,this.unprocessedConnections=Array.from(this.portPairMap.keys()).sort(),s?.SHUFFLE_SEED&&(this.unprocessedConnections=zt(this.unprocessedConnections,s.SHUFFLE_SEED));for(const[t,{start:e,end:s}]of this.portPairMap.entries())if(e.z===s.z){const n=Math.abs(e.x-s.x)<1e-9,i=Math.abs(e.y-s.y)<1e-9;n||i?this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),this._padByPlaceholderWallBuffer(s),s]):this.placeholderPaths.set(t,[e,s])}else{const n=(e.x+s.x)/2,i=(e.y+s.y)/2,o=this._padByPlaceholderWallBuffer({x:n,y:i,z:e.z}),a=this._padByPlaceholderWallBuffer({x:n,y:i,z:s.z});this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),o,a,this._padByPlaceholderWallBuffer(s),s])}this.currentConnectionName=this.unprocessedConnections.pop();const i=this.portPairMap.get(this.currentConnectionName).start;this.currentHead=this._padByNewHeadWallBuffer(i),this.currentPath=[i,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}_padByNewHeadWallBuffer(t){return{x:ot(t.x,this.bounds.minX+this.NEW_HEAD_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.NEW_HEAD_WALL_BUFFER_DISTANCE),y:ot(t.y,this.bounds.minY+this.NEW_HEAD_WALL_BUFFER_DISTANCE,this.bounds.maxY-this.NEW_HEAD_WALL_BUFFER_DISTANCE),z:t.z}}_padByPlaceholderWallBuffer(t){return{x:ot(t.x,this.bounds.minX+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),y:ot(t.y,this.bounds.minY+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxY-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),z:t.z}}_step(){if(this.solved)return;const t=this.portPairMap.get(this.currentConnectionName).end,e=[this.currentHead,t];let s=null,n=null;const i=t=>{for(const i of t.values())for(let t=0;t<i.length-1;t++){const o=[i[t],i[t+1]];if(o[0].x===o[1].x&&o[0].y===o[1].y)continue;if(o[0].z!==this.currentHead.z)continue;const a=lt(e[0],e[1],o[0],o[1]);if(a){const t=dt(this.currentHead,a);if(t<1e-6)continue;(!s||t<s.dist)&&(s={point:a,dist:t},n=o[0].z)}}};i(this.completedPaths),i(this.placeholderPaths);const o=this.currentHead.z!==t.z;if((s||o)&&(this.currentViaCount++,this.currentViaCount>=this.maxViaCount))this.failed=!0;else if(s){let t;const e=s.dist;if(e<=this.VIA_INTERSECTION_BUFFER_DISTANCE+1e-6)t=ut(this.currentHead,s.point);else{const n=s.point,i=n.x-this.currentHead.x,o=n.y-this.currentHead.y,a=(e-this.VIA_INTERSECTION_BUFFER_DISTANCE)/e;t={x:this.currentHead.x+i*a,y:this.currentHead.y+o*a}}const i=this.availableZ.find(t=>t!==n);if(void 0===i)return console.error("Could not determine next Z level for via placement!"),void(this.failed=!0);const o={...t,z:this.currentHead.z},a={...t,z:i};this.currentPath.push(o,a),this.currentHead=a}else if(o){let e;const s=dt(this.currentHead,t);if(s<this.VIA_INTERSECTION_BUFFER_DISTANCE)e=ut(this.currentHead,t);else{const n=t.x-this.currentHead.x,i=t.y-this.currentHead.y,o=(s-this.VIA_INTERSECTION_BUFFER_DISTANCE)/s;e={x:this.currentHead.x+n*o,y:this.currentHead.y+i*o}}const n=t.z,i={...e,z:this.currentHead.z},o={...e,z:n};this.currentPath.push(i,o),this.currentHead=o}else if(this.currentPath.push(t),this.completedPaths.set(this.currentConnectionName,this.currentPath),0===this.unprocessedConnections.length)this.solved=!0,this.stats.solutionsFound=1;else{this.currentConnectionName=this.unprocessedConnections.pop();const{start:t}=this.portPairMap.get(this.currentConnectionName);this.currentHead=this._padByNewHeadWallBuffer(t),this.currentPath=[t,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}}visualize(){const t={points:[],lines:[],circles:[],rects:[],title:"Via Possibilities Solver State",coordinateSystem:"cartesian"},e=this.colorMap;t.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:.01});for(const[e,{start:s,end:n}]of this.portPairMap.entries()){const i=this.colorMap[e]??"black";t.points.push({x:s.x,y:s.y,color:i,label:`Port: ${e} Start (z${s.z})`}),t.points.push({x:n.x,y:n.y,color:i,label:`Port: ${e} End (z${n.z})`})}const s=(s,n)=>{for(const[i,o]of s.entries()){const s=e[i]??"black";for(let e=0;e<o.length-1;e++){const a=o[e],r=o[e+1];a.x===r.x&&a.y===r.y&&a.z!==r.z?t.circles.push({center:{x:a.x,y:a.y},radius:this.viaDiameter/2,fill:V(s,.5),label:`${n}: ${i} Via (z${a.z}->z${r.z})`}):t.lines.push({points:[a,r],strokeColor:V(s,.5),strokeDash:0===a.z?void 0:[.1,.1],strokeWidth:.1,label:`${n}: ${i} (z${a.z})`})}}};if(s(this.placeholderPaths,"Placeholder"),s(this.completedPaths,"Completed"),this.currentPath&&this.currentPath.length>0){const s=e[this.currentConnectionName]??"orange";for(let e=0;e<this.currentPath.length-1;e++){const n=this.currentPath[e],i=this.currentPath[e+1];n.x===i.x&&n.y===i.y&&n.z!==i.z?t.circles.push({center:{x:n.x,y:n.y},radius:this.viaDiameter/2,fill:V(s,.5),label:`Current: ${this.currentConnectionName} Via (z${n.z}->z${i.z})`}):t.lines.push({points:[n,i],strokeColor:V(s,.5),strokeWidth:.15,strokeDash:"2,2",label:`Current: ${this.currentConnectionName} (z${n.z})`})}t.points.push({x:this.currentHead.x,y:this.currentHead.y,color:"green",label:`Current Head: ${this.currentConnectionName} (z${this.currentHead.z})`})}return t}},Kt=1e-9;function Jt(t,e,s=Kt){return Math.abs(t-e)<s}function Qt(t,e,s,n){return t*n-e*s}function te(t,e,s,n){const i={x:e.x-t.x,y:e.y-t.y},o={x:n.x-s.x,y:n.y-s.y},a=Qt(i.x,i.y,o.x,o.y);if(Jt(a,0))return null;const r={x:s.x-t.x,y:s.y-t.y},h=Qt(r.x,r.y,o.x,o.y)/a,c=Qt(r.x,r.y,i.x,i.y)/a;return h<-Kt||h>1+Kt||c<-Kt||c>1+Kt?null:{x:t.x+h*i.x,y:t.y+h*i.y}}function ee(t){let e=0;for(let s=0,n=t.length;s<n;++s){const i=(s+1)%n;e+=t[s].x*t[i].y-t[i].x*t[s].y}return.5*e}function se(t){let e=0,s=0,n=0;for(let i=0,o=t.length;i<o;++i){const a=(i+1)%o,r=t[i].x*t[a].y-t[a].x*t[i].y;e+=r,s+=(t[i].x+t[a].x)*r,n+=(t[i].y+t[a].y)*r}return e*=.5,Jt(e,0)?null:(s/=6*e,n/=6*e,{x:s,y:n})}var ne=class{x;y;out;connectionNames;constructor(t,e){this.x=t,this.y=e,this.out=[],this.connectionNames=new Set}},ie=class{orig;dest;twin;next;visited;constructor(t,e){this.orig=t,this.dest=e,this.twin=null,this.next=null,this.visited=!1}};function oe(t,e){const s=[...e,...[{start:{x:t.minX,y:t.minY},end:{x:t.maxX,y:t.minY}},{start:{x:t.maxX,y:t.minY},end:{x:t.maxX,y:t.maxY}},{start:{x:t.maxX,y:t.maxY},end:{x:t.minX,y:t.maxY}},{start:{x:t.minX,y:t.maxY},end:{x:t.minX,y:t.minY}}]],n=s.map(()=>[]);for(let t=0;t<s.length;++t){const e=s[t];n[t].push(e.start,e.end)}for(let t=0;t<s.length;++t)for(let e=t+1;e<s.length;++e){const i=te(s[t].start,s[t].end,s[e].start,s[e].end);i&&(n[t].push(i),n[e].push(i))}const i=new Map,o=[];function a(t){const e=function(t,e=Kt){return`${Math.round(t.x/e)}:${Math.round(t.y/e)}`}(t);if(!i.has(e)){const s=o.length;return i.set(e,s),o.push(new ne(t.x,t.y)),s}return i.get(e)}const r=[];for(let t=0;t<s.length;++t){const e=s[t],i=n[t].slice();i.sort((t,s)=>{const n=e.end.x-e.start.x,i=e.end.y-e.start.y;return(Jt(Math.abs(n),0)?(t.y-e.start.y)/i:(t.x-e.start.x)/n)-(Jt(Math.abs(n),0)?(s.y-e.start.y)/i:(s.x-e.start.x)/n)});for(let t=0;t<i.length-1;++t){const s=i[t],n=i[t+1],h=a(s),c=a(n);h!==c&&(r.push([h,c]),e.connectionName&&(o[h].connectionNames.add(e.connectionName),o[c].connectionNames.add(e.connectionName)))}}const h=[];for(const[t,e]of r){const s=new ie(t,e),n=new ie(e,t);s.twin=h.length+1,n.twin=h.length;const i=h.length;h.push(s,n),o[t].out.push(i),o[e].out.push(i+1)}for(let t=0;t<o.length;++t){const e=o[t];e.out.sort((t,s)=>{const n=h[t],i=h[s],a=o[n.dest],r=o[i.dest];return Math.atan2(a.y-e.y,a.x-e.x)-Math.atan2(r.y-e.y,r.x-e.x)});const s=e.out.length;for(let t=0;t<s;++t){const n=e.out[t],i=e.out[(t-1+s)%s],o=h[n];null!==o.twin&&(h[o.twin].next=i)}}const c=[],d=[];for(let t=0;t<h.length;++t){if(h[t].visited)continue;let e=t;const s=[],n=[];do{if(null===e)break;const t=h[e];t.visited=!0,s.push(o[t.orig]),n.push(e),e=t.next}while(null!==e&&e!==t&&!h[e].visited);if(s.length<3)continue;if(ee(s)>Kt){const t=se(s);t&&(c.push(t),d.push({vertices:s.map(t=>({x:t.x,y:t.y,connectionNames:t.connectionNames.size>0?t.connectionNames:void 0})),centroid:t}))}}return{centroids:c,faces:d,allVertices:o}}function ae(t,e){if(t>e)throw new Error("oneCount cannot be greater than length");if(t<0||e<0)throw new Error("oneCount and length must be non-negative");const s=[];return function t(n,i,o){o!==e?(n[o]=0,t(n,i,o+1),i>0&&(n[o]=1,t(n,i-1,o+1))):0===i&&s.push([...n])}(Array(e).fill(0),t,0),s}var re=t=>{if(0===t.length)return[[]];const e=[];for(let s=0;s<t.length;s++){const n=t[s],i=[...t.slice(0,s),...t.slice(s+1)],o=re(i);for(const t of o)e.push([n,...t])}return e};var he=t=>{const{start:e,end:s,segmentsPerPolyline:n,viaPositions:i,viaCount:o,availableZ:a}=t,r=function(t,e){const s=new Array(t).fill(0);if(0===e)return s;if(e===t)return s.fill(1);if(e<=t/2){const n=Math.floor(t/e),i=Math.floor((t-(n*(e-1)+1))/2);for(let t=0;t<e;t++)s[i+t*n]=1}else{const n=t-e,i=Math.floor(t/n),o=Math.floor((t-(i*(n-1)+1))/2);s.fill(1);for(let t=0;t<n;t++)s[o+t*i]=0}return s}(n,o),h=r.map(()=>null);let c=0,d=e.z1;const l=a.indexOf(e.z1);for(let t=0;t<r.length;t++)if(1===r[t]){const e=a[(l+c+1)%a.length];h[t]={...i[c],z1:d,z2:e},d=e,c++}let u=e;for(let t=0;t<h.length;t++){if(h[t]){u=h[t];continue}let e=s,n=h.length;for(let s=t+1;s<h.length;s++)if(h[s]){e=h[s],n=s;break}const i=n-t,o=e.x-u.x,a=e.y-u.y;for(let e=1/(i+1),s=0;t+s!==n;e+=1/(i+1),s++)h[t+s]={x:u.x+o*e,y:u.y+a*e,z1:u.z2,z2:u.z2}}return h},ce=1e-9;function de(t,e){return Math.abs(t-e)<ce}function le(t){return`${Math.round(t.x/ce)}:${Math.round(t.y/ce)}`}function ue(t,e,s,n){return t*n-e*s}function pe(t,e,s,n){const i={x:e.x-t.x,y:e.y-t.y},o={x:n.x-s.x,y:n.y-s.y},a=ue(i.x,i.y,o.x,o.y),r={x:s.x-t.x,y:s.y-t.y};if(de(a,0))return null;const h=ue(r.x,r.y,o.x,o.y)/a,c=ue(r.x,r.y,i.x,i.y)/a;return h>=-1e-9&&h<=1+ce&&c>=-1e-9&&c<=1+ce?{x:t.x+h*i.x,y:t.y+h*i.y}:null}function fe(t,e,s){return de(Math.hypot(t.x-e.x,t.y-e.y)+Math.hypot(t.x-s.x,t.y-s.y),Math.hypot(e.x-s.x,e.y-s.y))}function ge(t,e){const s=[],n=new Map;for(const e of t){const t=[e.start,...e.mPoints,e.end];for(let i=0;i<t.length-1;i++){const o=t[i],a=t[i+1],r=o.z2;if(s.push({start:{x:o.x,y:o.y},end:{x:a.x,y:a.y},connectionName:e.connectionName,layer:r}),o.z1!==o.z2){const t=le(o);n.has(t)||n.set(t,{point:o,connectionName:e.connectionName})}}const i=t[t.length-1];if(i.z1!==i.z2){const t=le(i);n.has(t)||n.set(t,{point:i,connectionName:e.connectionName})}}const i=[{start:{x:e.minX,y:e.minY},end:{x:e.maxX,y:e.minY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.minY},end:{x:e.maxX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.maxY},end:{x:e.minX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.minX,y:e.maxY},end:{x:e.minX,y:e.minY},connectionName:null,layer:0}];s.push(...i);const o=new Map;let a=0;function r(t,e){const s=le(t);let i=o.get(s);if(!i){const e=n.has(s);i={id:a++,x:t.x,y:t.y,isVia:e,connectionNames:new Set,outgoingEdges:[]},o.set(s,i),e&&n.get(s)&&i.connectionNames.add(n.get(s).connectionName)}return e&&i.connectionNames.add(e),i}for(const t of s)r(t.start,t.connectionName),r(t.end,t.connectionName);const h=new Map;for(const t of s)h.set(t,[]);for(let t=0;t<s.length;t++)for(let e=t+1;e<s.length;e++){if(s[t].layer!==s[e].layer)continue;const n=pe(s[t].start,s[t].end,s[e].start,s[e].end);n&&(r(n),fe(n,s[t].start,s[t].end)&&h.get(s[t]).push(n),fe(n,s[e].start,s[e].end)&&h.get(s[e]).push(n))}const c=[];let d=0;for(const t of s){const e=[t.start,...h.get(t),t.end];e.sort((e,s)=>{const n=t.end.x-t.start.x,i=t.end.y-t.start.y;return Math.abs(n)>Math.abs(i)?(e.x-t.start.x)/n-(s.x-t.start.x)/n:Math.abs(i)<ce?0:(e.y-t.start.y)/i-(s.y-t.start.y)/i});const s=[];if(e.length>0){s.push(e[0]);for(let t=1;t<e.length;t++)de(e[t].x,e[t-1].x)&&de(e[t].y,e[t-1].y)||s.push(e[t])}for(let e=0;e<s.length-1;e++){const n=s[e],i=s[e+1],o=r(n,t.connectionName),a=r(i,t.connectionName);if(o===a)continue;const h={id:d++,origin:o,twin:null,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1},l={id:d++,origin:a,twin:h,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1};h.twin=l,c.push(h,l),o.outgoingEdges.push(h),a.outgoingEdges.push(l)}}for(const t of o.values()){t.outgoingEdges.sort((e,s)=>{const n=e.twin.origin,i=s.twin.origin;return Math.atan2(n.y-t.y,n.x-t.x)-Math.atan2(i.y-t.y,i.x-t.x)});const e=t.outgoingEdges.length;for(let s=0;s<e;s++){const n=t.outgoingEdges[s],i=t.outgoingEdges[(s-1+e)%e];n.twin&&(n.twin.next=i)}}const l=[];let u=0,p=null,f=-1/0;for(const t of c){if(t.visited)continue;const e={id:u++,outerComponent:t,innerComponents:[],isOuterFace:!1};l.push(e);let s=t;const n=[],i=[],o=new Set;let a=0;do{if(!s||s.visited){console.warn("Face traversal encountered visited edge or null, breaking loop.",e.id),n.length=0;break}s.visited=!0,s.face=e,n.push(s),i.push(s.origin),null!==s.connectionName&&o.add(s.connectionName);const t=s.origin,r=s.twin.origin;a+=t.x*r.y-r.x*t.y,s=s.next}while(s!==t&&null!==s);if(s===t){if(a=.5*Math.abs(a),a>f&&(f=a,p&&(p.isOuterFace=!1),p=e,e.isOuterFace=!0),!e.isOuterFace&&n.length>0){if([...o].filter(t=>null!==t).length>1){let t=!1;for(const e of i)if(e.isVia){t=!0;break}if(!t)return!0}}}else console.warn(`Face ${e.id} did not close properly.`),l.pop(),u--}return!1}var me=class extends e{nodeWithPortPoints;colorMap;hyperParameters;connMap;candidates;bounds;solvedRoutes=[];unsolvedConnections=[];SEGMENTS_PER_POLYLINE;cellSize;MAX_CANDIDATES=5e4;viaDiameter=.6;obstacleMargin=.1;traceWidth=.15;availableZ=[];uniqueConnections=0;BOUNDARY_PADDING;lastCandidate=null;maxViaCount;minViaCount;phase="setup";progress=0;constructor(t){super(),this.MAX_ITERATIONS=1e4,this.nodeWithPortPoints=t.nodeWithPortPoints,this.colorMap=t.colorMap??Gt(t.nodeWithPortPoints),this.hyperParameters=t.hyperParameters??{},this.SEGMENTS_PER_POLYLINE=t.hyperParameters?.SEGMENTS_PER_POLYLINE??3,this.BOUNDARY_PADDING=t.hyperParameters?.BOUNDARY_PADDING??.05,this.connMap=t.connMap,this.viaDiameter=t.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 e=this.nodeWithPortPoints.width*this.nodeWithPortPoints.height,s=(this.viaDiameter+2*this.obstacleMargin+this.traceWidth/2)**2,n=new Set(this.nodeWithPortPoints.portPoints.map(t=>t.connectionName)).size;this.uniqueConnections=n;const{numSameLayerCrossings:i,numTransitions:o}=(t=>{let e=0,s=[];const n=[];let i=0;for(const e of t.portPoints){if(s.some(t=>t.connectionName===e.connectionName))continue;if(n.some(t=>t.connectionName===e.connectionName))continue;const o={connectionName:e.connectionName,z:e.z,points:[{x:e.x,y:e.y,z:e.z}]};for(const s of t.portPoints)e.connectionName===s.connectionName&&(e.x===s.x&&e.y===s.y||o.points.push({x:s.x,y:s.y,z:s.z}));o.points.some(t=>t.z!==o.z)?(i++,n.push(o)):s.push(o)}s=s.filter(t=>t.points.length>1);for(let t=0;t<s.length;t++)for(let n=t+1;n<s.length;n++){const i=s[t],o=s[n];i.z===o.z&&at(i.points[0],i.points[1],o.points[0],o.points[1])&&e++}let o=0;for(let t=0;t<n.length;t++)for(let e=t+1;e<n.length;e++){const s=n[t],i=n[e];at(s.points[0],s.points[1],i.points[0],i.points[1])&&o++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:i,numTransitionPairCrossings:o,numTransitions:n.length}})(this.nodeWithPortPoints);if(this.minViaCount=2*i+o,this.maxViaCount=Math.min(Math.floor(e/s),Math.ceil(1.5*n)),this.minViaCount>this.SEGMENTS_PER_POLYLINE*(n/2))return this.failed=!0,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(t){const e=[],s=[],n=[];for(let e=0;e<t.length;e++){const i=t[e],o=[i.start,...i.mPoints,i.end],a=new Map(this.availableZ.map(t=>[t,[]]));for(let t=0;t<o.length-1;t++){const e=[o[t],o[t+1]],s=e[0].z2;a.has(s)||a.set(s,[]),a.get(s).push(e)}s.push(a),n.push(o.filter(t=>t.z1!==t.z2))}for(let i=0;i<t.length;i++){const o=s[i],a=n[i];for(let r=i+1;r<t.length;r++){if(this.connMap?.areIdsConnected(t[i].connectionName,t[r].connectionName))continue;const h=s[r],c=n[r];let d=1;for(const t of this.availableZ){const e=o.get(t)??[],s=h.get(t)??[];for(const t of e)for(const e of s)d=Math.min(d,St(t[0],t[1],e[0],e[1])-this.traceWidth);for(const t of a)for(const e of s)d=Math.min(d,ct(t,e[0],e[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of c)for(const s of e)d=Math.min(d,ct(t,s[0],s[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of a)for(const e of c)d=Math.min(d,dt(t,e)-this.viaDiameter)}e.push(d)}}return e}insertCandidate(t){let e=0,s=this.candidates.length-1;for(;e<=s;){const n=Math.floor((e+s)/2);this.candidates[n].f<t.f?e=n+1:s=n-1}this.candidates.splice(e,0,t)}setupInitialPolyLines(){const t=new Map;this.nodeWithPortPoints.portPoints.forEach(e=>{t.has(e.connectionName)?t.get(e.connectionName).end={...e,z1:e.z??0,z2:e.z??0}:t.set(e.connectionName,{start:{...e,z1:e.z??0,z2:e.z??0},end:null})});for(const[e,s]of t.entries())null===s.end&&t.delete(e);if(0===t.size)return this.failed=!0,void(this.error="No port pairs found, can't solve");const e=Array.from(t.entries()),s=((t,e,s,n)=>{const i=[];for(const[,s]of t){const t=s.start.z1!==s.end.z1,n=[];for(let s=0;s<=e;s++){const e=s%2!=0;t&&e?n.push(s):t||e||n.push(s)}i.push(n)}if(0===i.length)return[[]];let o=(t=>{if(!t||0===t.length)return[[]];let e=[[]];for(const s of t){const t=[];for(const n of e)for(const e of s)t.push([...n,e]);e=t}return e})(i).filter(t=>{for(let e=0;e<t.length;e++)if(t.reduce((t,e)=>t+e,0)<n)return!1;return!0});return o=o.filter(e=>{for(let s=0;s<t.length;s++){const[,n]=t[s];if(n.start.z1!==n.start.z2&&0===e[s])return!1}return!0}),o=o.filter(e=>{for(let s=0;s<t.length;s++){const[,n]=t[s];if(t[s][1].start.z1===t[s][1].start.z2)for(let i=s+1;i<t.length;i++){if(t[i][1].start.z1!==t[i][1].start.z2)continue;const[,o]=t[i];if(n.start.z1===n.end.z1&&o.start.z1===o.end.z1&&n.start.z1===o.start.z1&&at(n.start,n.end,o.start,o.end)&&e[s]+e[i]<2)return!1}}return!0}),o=o.filter(t=>!(t.reduce((t,e)=>t+e,0)>s)),o})(e,this.SEGMENTS_PER_POLYLINE,this.maxViaCount,this.minViaCount),n=(t=>{const{bounds:e,portPairsEntries:s,viaCountVariants:n}=t,{centroids:i}=oe(e,s.map(([t,e])=>e)),o=[];for(const t of n){const s=t.reduce((t,e)=>t+e,0);let n=i;if(i.length<s){n=[];const t=Math.ceil(Math.sqrt(s)),i=t;for(let s=0;s<t;s++)for(let o=0;o<i;o++)n.push({x:e.minX+(o+1)/(i+1)*(e.maxX-e.minX),y:e.minY+(s+1)/(t+1)*(e.maxY-e.minY)})}const a=ae(s,n.length);for(const e of a){const s=[];for(let t=0;t<e.length;t++)1===e[t]&&s.push(n[t]);o.push({viaPositions:s,viaCountVariant:t})}}return o})({portPairsEntries:e,viaCountVariants:s,bounds:this.bounds}),i=[];for(const{viaCountVariant:t,viaPositions:e}of n){const s=re(e);for(const e of s)i.push({viaCountVariant:t,viaPositions:e})}for(const{viaPositions:t,viaCountVariant:s}of i){const n=[];let i=0;for(let o=0;o<e.length;o++){const[a,r]=e[o],h=s[o],c=t.slice(i,i+h),d=he({start:r.start,end:r.end,segmentsPerPolyline:this.SEGMENTS_PER_POLYLINE,viaPositions:c,viaCount:h,availableZ:this.availableZ});i+=h,n.push({connectionName:a,start:r.start,end:r.end,mPoints:d})}if(ge(n,this.bounds))continue;const o=this.computeMinGapBtwPolyLines(n),a=this.computeH({minGaps:o,forces:[]}),r={polyLines:n,g:0,h:a,f:a,viaCount:s.reduce((t,e)=>t+e,0),minGaps:o};if(this.checkIfSolved(r))return void(this.candidates=[r]);if(this.candidates.push(r),this.candidates.length>this.MAX_CANDIDATES)return}this.candidates.sort((t,e)=>t.f-e.f)}computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){let e=0;for(const s of t.forces??[])for(const t of s)for(const s of t.values())e+=s.fx*s.fx+s.fy*s.fy;return e}getNeighbors(t){const{polyLines:e}=t,s=e.length,n=.02,i=.008,o=1e-6,a=Array.from({length:s},(t,s)=>Array.from({length:e[s].mPoints.length},()=>new Map)),r=(t,s,n,i,o)=>{if(s>0&&s<e[t].mPoints.length+1){const e=s-1,r=a[t][e],h=r.get(n)||{fx:0,fy:0};r.set(n,{fx:h.fx+i,fy:h.fy+o})}};for(let t=0;t<s;t++)for(let i=t+1;i<s;i++){const s=e[t],a=e[i],h=[s.start,...s.mPoints,s.end],c=[a.start,...a.mPoints,a.end],d=[],l=[];for(let t=0;t<h.length-1;t++)d.push({p1:h[t],p2:h[t+1],layer:h[t].z2,p1Idx:t,p2Idx:t+1});h.forEach((t,e)=>{t.z1!==t.z2&&l.push({point:t,layers:[t.z1,t.z2],index:e})});const u=[],p=[];for(let t=0;t<c.length-1;t++)u.push({p1:c[t],p2:c[t+1],layer:c[t].z2,p1Idx:t,p2Idx:t+1});c.forEach((t,e)=>{t.z1!==t.z2&&p.push({point:t,layers:[t.z1,t.z2],index:e})});for(const e of d)for(const s of u)if(e.layer===s.layer){if(St(e.p1,e.p2,s.p1,s.p2)<o)continue;const n={x:(e.p1.x+e.p2.x)/2,y:(e.p1.y+e.p2.y)/2},a={x:(s.p1.x+s.p2.x)/2,y:(s.p1.y+s.p2.y)/2},h=n.x-a.x,c=n.y-a.y,d=h*h+c*c;if(d>o){const n=Math.sqrt(d),a=(Math.exp(-6*n),`seg:${i}:${s.p1Idx}:${s.p2Idx}`),h=`seg:${t}:${e.p1Idx}:${e.p2Idx}`,c=(t,e,s,n,i,a,h)=>{const c=Nt(t,s.p1,s.p2),d=t.x-c.x,l=t.y-c.y,u=d*d+l*l;if(u<=o)return;const p=Math.sqrt(u),f=.02*Math.exp(-6*p),g=d/p*f,m=l/p*f;r(n,e,a,g,m),r(i,s.p1Idx,h,-g/2,-m/2),r(i,s.p2Idx,h,-g/2,-m/2)};c(e.p1,e.p1Idx,s,t,i,a,h),c(e.p2,e.p2Idx,s,t,i,a,h),c(s.p1,s.p1Idx,e,i,t,h,a),c(s.p2,s.p2Idx,e,i,t,h,a)}}for(const e of l)for(const s of u)if(e.layers.includes(s.layer)){const a=Nt(e.point,s.p1,s.p2),h=e.point.x-a.x,c=e.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,g=c/a*p,m=`seg:${i}:${s.p1Idx}:${s.p2Idx}`;r(t,e.index,m,f,g);const y=`via:${t}:${e.index}`;r(i,s.p1Idx,y,-f/2,-g/2),r(i,s.p2Idx,y,-f/2,-g/2)}}for(const e of p)for(const s of d)if(e.layers.includes(s.layer)){const a=Nt(e.point,s.p1,s.p2),h=e.point.x-a.x,c=e.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,g=c/a*p,m=`seg:${t}:${s.p1Idx}:${s.p2Idx}`;r(i,e.index,m,f,g);const y=`via:${i}:${e.index}`;r(t,s.p1Idx,y,-f/2,-g/2),r(t,s.p2Idx,y,-f/2,-g/2)}}for(const e of l)for(const s of p){if(e.layers.filter(t=>s.layers.includes(t)).length>0){const a=e.point.x-s.point.x,h=e.point.y-s.point.y,c=a*a+h*h;if(c>o){const d=Math.sqrt(c);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(o,d)):u=Math.max(o,d-this.viaDiameter);const p=l*n*Math.exp(-6*u),f=a/d*p,g=h/d*p,m=`via:${i}:${s.index}`,y=`via:${t}:${e.index}`;r(t,e.index,m,f,g),r(i,s.index,y,-f,-g)}}}}for(let t=0;t<s;t++){const s=e[t],i=[s.start,...s.mPoints,s.end],a=[];if(i.forEach((t,e)=>{t.z1!==t.z2&&a.push({point:t,layers:[t.z1,t.z2],index:e})}),!(a.length<2))for(let e=0;e<a.length;e++)for(let s=e+1;s<a.length;s++){const i=a[e],h=a[s],c=i.point.x-h.point.x,d=i.point.y-h.point.y,l=c*c+d*d;if(l>o){const e=Math.sqrt(l);let s=2,a=e;e<this.viaDiameter?(s*=4,a=Math.max(o,e)):a=Math.max(o,e-this.viaDiameter);const u=s*n*Math.exp(-6*a),p=c/e*u,f=d/e*u,g=`via:${t}:${h.index}`,m=`via:${t}:${i.index}`;r(t,i.index,g,p,f),r(t,h.index,m,-p,-f)}}}const h=e.map(t=>({...t,mPoints:t.mPoints.map(t=>({...t}))}));let c=!1;for(let t=0;t<s;t++)for(let e=0;e<h[t].mPoints.length;e++){const s=h[t].mPoints[e],n=a[t][e],r={fx:0,fy:0};for(const t of n.values())r.fx+=t.fx,r.fy+=t.fy;const d=s.z1!==s.z2;let l=s.x+r.fx,u=s.y+r.fy;if(d){const t=this.viaDiameter/2;let e=0,n=0;const o=this.viaDiameter/2+this.BOUNDARY_PADDING,a=this.bounds.minX+o,h=this.bounds.maxX-o,c=this.bounds.minY+o,d=this.bounds.maxY-o,p=a+t-s.x,f=s.x-(h-t),g=c+t-s.y,m=s.y-(d-t);p>0?e=i*(Math.exp(p/(2*this.obstacleMargin))-1):f>0&&(e=-.008*(Math.exp(f/(2*this.obstacleMargin))-1)),g>0?n=i*(Math.exp(g/(2*this.obstacleMargin))-1):m>0&&(n=-.008*(Math.exp(m/(2*this.obstacleMargin))-1)),r.fx+=e,r.fy+=n,l=s.x+r.fx,u=s.y+r.fy}else{const t=this.traceWidth/2+this.BOUNDARY_PADDING;l=Math.max(this.bounds.minX+t,Math.min(this.bounds.maxX-t,l)),u=Math.max(this.bounds.minY+t,Math.min(this.bounds.maxY-t,u))}Math.abs(r.fx)<o&&Math.abs(r.fy)<o||(Math.abs(s.x-l)>o||Math.abs(s.y-u)>o)&&(s.x=l,s.y=u,c=!0)}if(!c)return[];const d=this.computeMinGapBtwPolyLines(h),l=this.computeG(h,t),u=this.computeH({minGaps:d,forces:a});return[{polyLines:h,g:l,h:u,f:Math.round(5*l)/5+u,minGaps:d,forces:a,viaCount:t.viaCount}]}checkIfSolved(t){const e=t.minGaps.every(t=>t>=this.obstacleMargin),s=t.polyLines.every(t=>t.mPoints.every(t=>{const e=(t.z1!==t.z2?this.viaDiameter/2:this.traceWidth/2)+this.BOUNDARY_PADDING;return((t,e,s=0)=>t.x>=e.minX+s&&t.x<=e.maxX-s&&t.y>=e.minY+s&&t.y<=e.maxY-s)(t,this.bounds,e)}));return e&&s}tryFinalAcceptance(){const t=this.hyperParameters?.MINIMUM_FINAL_ACCEPTANCE_GAP??void 0;if(void 0===t||null===this.lastCandidate||0===this.lastCandidate.minGaps.length)return;return Math.min(...this.lastCandidate.minGaps)>=t?(this.solved=!0,void this._setSolvedRoutes()):void 0}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return this.failed=!0,void(this.error="No candidates left")}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();if(!t)return void(this.failed=!0);const e=this.getNeighbors(t);for(const t of e)this.insertCandidate(t)}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"MultiHeadPolyLineIntraNodeSolver Visualization"};t.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 e=this.lastCandidate??this.candidates[0];if(e?.hasClosedSameLayerFace){const e=.1*(this.bounds.maxX-this.bounds.minX),s=.1*(this.bounds.maxY-this.bounds.minY);t.rects.push({center:{x:this.bounds.maxX+.6*e,y:this.bounds.maxY+.6*s},width:e,height:s,fill:"red",label:"HAS CLOSED FACE"})}for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:`${e.connectionName} (Port z=${e.z??0})`,color:this.colorMap[e.connectionName]??"blue"});return e&&e.polyLines.forEach((s,n)=>{const i=this.colorMap[s.connectionName]??"purple",o=[s.start,...s.mPoints,s.end];for(let e=0;e<o.length-1;e++){const n=o[e],a=o[e+1],r=n.z2,h=0===r,c=h?i:V(i,.5);t.lines.push({points:[n,a],strokeColor:c,strokeWidth:this.traceWidth,strokeDash:h?void 0:[.15,.15],label:`${s.connectionName} segment (z=${r})`})}o.forEach((a,r)=>{const h=a.z1!==a.z2,c=a.z1,d=r>0&&r<o.length-1;let l="",u="";if(d){const i=r-1,o=e.forces?.[n]?.[i];if(o&&o.size>0){const n={fx:0,fy:0};o.forEach((o,r)=>{if(n.fx+=o.fx,n.fy+=o.fy,Math.abs(o.fx)>1e-6||Math.abs(o.fy)>1e-6){const n=r.split(":"),h=n[0],c=parseInt(n[1],10),d=e.polyLines[c],l=this.colorMap[d.connectionName]??"gray",u=20,p={x:a.x+o.fx*u,y:a.y+o.fy*u};let f=d.connectionName;if("via"===h){f+=` Via ${parseInt(n[2],10)}`}else if("seg"===h){f+=` Seg ${parseInt(n[2],10)}-${parseInt(n[3],10)}`}t.lines.push({points:[a,p],strokeColor:l,strokeWidth:.02,strokeDash:"2,2",label:`Force by ${f} on ${s.connectionName} mPoint ${i}`})}}),(Math.abs(n.fx)>1e-6||Math.abs(n.fy)>1e-6)&&(u=`\nNet Force: (${n.fx.toFixed(3)}, ${n.fy.toFixed(3)})`)}}if(h)l=`Via (${s.connectionName} z=${a.z1} -> z=${a.z2})${u}`,t.circles.push({center:a,radius:this.viaDiameter/2,fill:V(i,.5),label:l});else if(d){const e=0===c?i:V(i,.5);l=`mPoint (${s.connectionName} z=${c})${u}`,t.circles.push({center:a,radius:this.cellSize/8,fill:e,label:l})}})}),t}_setSolvedRoutes(){if(!this.solved||!this.lastCandidate)return[];const t=[];for(const e of this.lastCandidate.polyLines){const s=[],n=[],i=[e.start,...e.mPoints,e.end];for(let t=0;t<i.length;t++){const e=i[t];s.push({x:e.x,y:e.y,z:e.z1}),e.z1!==e.z2&&(n.push({x:e.x,y:e.y}),s.push({x:e.x,y:e.y,z:e.z2}))}t.push({connectionName:e.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:s,vias:n})}this.solvedRoutes=t}},ye=class extends me{computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){const{minGaps:e}=t;let s=0;for(const t of e)t<0&&(s+=this.obstacleMargin),t<this.obstacleMargin&&(s+=this.obstacleMargin-t);return.011*s}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return void(this.failed=!0)}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();let e=!1,s=0;const n=void 0===t.magForceApplied?1:10;for(let i=0;i<n;i++){const n=this.applyForcesToPolyLines(t.polyLines);if(s+=n.magForceApplied,e=n.lastStepMoved,!n.lastStepMoved)break}if(t.magForceApplied=s,t.minGaps=this.computeMinGapBtwPolyLines(t.polyLines),this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();t.g=this.computeG(t.polyLines,t),t.h=this.computeH(t),t.f=t.g+t.h,e&&this.insertCandidate(t)}applyForcesToPolyLines(t){let e=0;const s=t.length,n=.02,i=.008,o=1e-6,a=Array.from({length:s},(e,s)=>Array.from({length:t[s].mPoints.length},()=>({fx:0,fy:0}))),r=(e,s,n,i)=>{if(s>0&&s<t[e].mPoints.length+1){const t=s-1;a[e][t].fx+=n,a[e][t].fy+=i}},h=(t,e,s,n,i)=>{const a=Nt(t,s.p1,s.p2),h=t.x-a.x,c=t.y-a.y,d=h*h+c*c;if(d<=o)return;const l=Math.sqrt(d),u=.02*Math.exp(-6*l),p=h/l*u,f=c/l*u;r(n,e,p,f),r(i,s.p1Idx,-p/2,-f/2),r(i,s.p2Idx,-p/2,-f/2)};for(let e=0;e<s;e++)for(let i=e+1;i<s;i++){const s=t[e],a=t[i],c=[s.start,...s.mPoints,s.end],d=[a.start,...a.mPoints,a.end],l=[],u=[];for(let t=0;t<c.length-1;t++)l.push({p1:c[t],p2:c[t+1],layer:c[t].z2,p1Idx:t,p2Idx:t+1});c.forEach((t,e)=>{t.z1!==t.z2&&u.push({point:t,layers:[t.z1,t.z2],index:e})});const p=[],f=[];for(let t=0;t<d.length-1;t++)p.push({p1:d[t],p2:d[t+1],layer:d[t].z2,p1Idx:t,p2Idx:t+1});d.forEach((t,e)=>{t.z1!==t.z2&&f.push({point:t,layers:[t.z1,t.z2],index:e})});for(const t of l)for(const s of p)if(t.layer===s.layer){St(t.p1,t.p2,s.p1,s.p2);h(t.p1,t.p1Idx,s,e,i),h(t.p2,t.p2Idx,s,e,i),h(s.p1,s.p1Idx,t,i,e),h(s.p2,s.p2Idx,t,i,e)}for(const t of u)for(const s of p)if(t.layers.includes(s.layer)){const a=Nt(t.point,s.p1,s.p2),h=t.point.x-a.x,c=t.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,g=c/a*p;r(e,t.index,f,g),r(i,s.p1Idx,-f/2,-g/2),r(i,s.p2Idx,-f/2,-g/2)}}for(const t of f)for(const s of l)if(t.layers.includes(s.layer)){const a=Nt(t.point,s.p1,s.p2),h=t.point.x-a.x,c=t.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,g=c/a*p;r(i,t.index,f,g),r(e,s.p1Idx,-f/2,-g/2),r(e,s.p2Idx,-f/2,-g/2)}}for(const t of u)for(const s of f){if(t.layers.filter(t=>s.layers.includes(t)).length>0){const a=t.point.x-s.point.x,h=t.point.y-s.point.y,c=a*a+h*h;if(c>o){const d=Math.sqrt(c);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(o,d)):u=Math.max(o,d-this.viaDiameter);const p=l*n*Math.exp(-6*u),f=a/d*p,g=h/d*p;r(e,t.index,f,g),r(i,s.index,-f,-g)}}}}for(let e=0;e<s;e++){const s=t[e],i=[s.start,...s.mPoints,s.end],a=[];if(i.forEach((t,e)=>{t.z1!==t.z2&&a.push({point:t,layers:[t.z1,t.z2],index:e})}),!(a.length<2))for(let t=0;t<a.length;t++)for(let s=t+1;s<a.length;s++){const i=a[t],h=a[s],c=i.point.x-h.point.x,d=i.point.y-h.point.y,l=c*c+d*d;if(l>o){const t=Math.sqrt(l);let s=2,a=t;t<this.viaDiameter?(s*=4,a=Math.max(o,t)):a=Math.max(o,t-this.viaDiameter);const u=s*n*Math.exp(-6*a),p=c/t*u,f=d/t*u;r(e,i.index,p,f),r(e,h.index,-p,-f)}}}let c=!1;for(let n=0;n<s;n++)for(let s=0;s<t[n].mPoints.length;s++){const r=t[n].mPoints[s],h=a[n][s],d=r.z1!==r.z2;let l=h.fx,u=h.fy,p=r.x+l,f=r.y+u;if(d){const t=this.viaDiameter/2;let e=0,s=0;const n=this.viaDiameter/2+this.BOUNDARY_PADDING,o=this.bounds.minX+n,a=this.bounds.maxX-n,h=this.bounds.minY+n,c=this.bounds.maxY-n,d=o+t-r.x,g=r.x-(a-t),m=h+t-r.y,y=r.y-(c-t);d>0?e=i*(Math.exp(d/(2*this.obstacleMargin))-1):g>0&&(e=-.008*(Math.exp(g/(2*this.obstacleMargin))-1)),m>0?s=i*(Math.exp(m/(2*this.obstacleMargin))-1):y>0&&(s=-.008*(Math.exp(y/(2*this.obstacleMargin))-1)),l+=e,u+=s,p=r.x+l,f=r.y+u}else{const t=this.traceWidth/2+this.BOUNDARY_PADDING;p=Math.max(this.bounds.minX+t,Math.min(this.bounds.maxX-t,p)),f=Math.max(this.bounds.minY+t,Math.min(this.bounds.maxY-t,f))}if(Math.abs(l)<o&&Math.abs(u)<o)continue;e+=Math.sqrt(l*l+u*u),(Math.abs(r.x-p)>o||Math.abs(r.y-f)>o)&&(r.x=p,r.y=f,c=!0)}return{lastStepMoved:c,magForceApplied:e}}},xe=t=>t.flatMap(t=>`${t.connectionName}-${t.mPoints.map(t=>`${t.x.toFixed(2)},${t.y.toFixed(2)},${t.z1},${t.z2}`)}`).sort().join("|");var ve=class extends ye{constructor(t){super(t),this.MAX_ITERATIONS=1e3}createInitialCandidateFromSeed(t){const e=new qt({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,hyperParameters:{SHUFFLE_SEED:t},viaDiameter:this.viaDiameter});if(e.solve(),e.failed||!e.solved)return null;const s=[];let n=0;for(const[t,i]of e.completedPaths.entries()){if(i.length<2){console.warn(`Skipping connection "${t}" due to insufficient points (${i.length}) in ViaPossibilitiesSolver2 path.`);continue}const e=i[0],o=i[i.length-1],a=i.slice(1,-1),r=[];let h=0,c=e.z;for(let t=0;t<a.length;t++){const e=a[t],s=t+1<a.length?a[t+1]:o,n=c,i=t+1<a.length&&e.x===s.x&&e.y===s.y&&e.z!==s.z?s.z:e.z;r.push({x:e.x,y:e.y,z1:n,z2:i}),n!==i?(h++,t++,c=i):c=e.z}n+=h;const d=this.SEGMENTS_PER_POLYLINE;let l=r.length+1;for(;l<d;){let s=-1,n=-1,i=null,a=null;const h=[{...e,z1:e.z,z2:e.z,connectionName:t},...r,{...o,z1:o.z,z2:o.z,connectionName:t}];for(let t=0;t<h.length-1;t++){const e=h[t],o=h[t+1];if(e.x===o.x&&e.y===o.y)continue;const r=dt(e,o);r>s&&(s=r,n=t,i=e,a=o)}if(-1===n||!i||!a){console.warn(`Could not find longest segment for ${t} while trying to reach ${d} segments.`);break}const c=(i.x+a.x)/2,u=(i.y+a.y)/2,p=i.z2,f={x:c,y:u,z1:p,z2:p};r.splice(n,0,f),l++}s.push({connectionName:t,start:{...e,z1:e.z,z2:e.z},end:{...o,z1:o.z,z2:o.z},mPoints:r})}if(0===s.length)return this.failed=!0,this.error="No valid polylines generated from ViaPossibilitiesSolver2.",console.error(this.error),null;const i=this.computeMinGapBtwPolyLines(s),o=this.computeH({minGaps:i,forces:[]}),a={polyLines:s,g:0,h:o,f:0+o,viaCount:n,minGaps:i};return a.g=this.computeG(s,a),a.f=a.g+a.h,a}setupInitialPolyLines(){this.candidates=[];const t=Math.min(2e3,function(t){if(!Number.isInteger(t)||t<0)throw new RangeError("n must be a non-negative integer");let e=1;for(let s=2;s<=t;s++)e*=s;return e}(this.uniqueConnections)),e=new Set;for(let s=0;s<t;s++){const t=this.createInitialCandidateFromSeed(s);if(!t)continue;const n=xe(t.polyLines);e.has(n)||(e.add(n),this.candidates.push(t))}this.candidates.sort((t,e)=>t.f-e.f)}},Me=class extends Ft{constructorParams;solvedRoutes=[];nodeWithPortPoints;connMap;constructor(t){super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.connMap=t.connMap,this.constructorParams=t,this.MAX_ITERATIONS=25e4,this.GREEDY_MULTIPLIER=5,this.MIN_SUBSTEPS=100}getCombinationDefs(){return[["multiHeadPolyLine"],["majorCombinations","orderings6","cellSizeFactor"],["noVias"],["orderings50"],["flipTraceAlignmentDirection","orderings6"],["closedFormTwoTrace"]]}getHyperParameterDefs(){return[{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:.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:[{SHUFFLE_SEED:0},{SHUFFLE_SEED:1},{SHUFFLE_SEED:2},{SHUFFLE_SEED:3},{SHUFFLE_SEED:4},{SHUFFLE_SEED:5}]},{name:"cellSizeFactor",possibleValues:[{CELL_SIZE_FACTOR:.5},{CELL_SIZE_FACTOR:1}]},{name:"flipTraceAlignmentDirection",possibleValues:[{FLIP_TRACE_ALIGNMENT_DIRECTION:!0}]},{name:"noVias",possibleValues:[{CELL_SIZE_FACTOR:2,VIA_PENALTY_FACTOR_2:10}]},{name:"orderings50",possibleValues:Array.from({length:50},(t,e)=>({SHUFFLE_SEED:100+e}))},{name:"closedFormTwoTrace",possibleValues:[{CLOSED_FORM_TWO_TRACE_SAME_LAYER:!0},{CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING:!0}]},{name:"multiHeadPolyLine",possibleValues:[{MULTI_HEAD_POLYLINE_SOLVER:!0,SEGMENTS_PER_POLYLINE:6,BOUNDARY_PADDING:.05},{MULTI_HEAD_POLYLINE_SOLVER:!0,SEGMENTS_PER_POLYLINE:6,BOUNDARY_PADDING:-.05,ITERATION_PENALTY:1e4,MINIMUM_FINAL_ACCEPTANCE_GAP:.001}]}]}computeG(t){return t?.hyperParameters?.MULTI_HEAD_POLYLINE_SOLVER?1e3+((t.hyperParameters?.ITERATION_PENALTY??0)+t.iterations)/1e4+1e4*(t.hyperParameters.SEGMENTS_PER_POLYLINE-3):t.iterations/1e4}computeH(t){return 1-(t.progress||0)}generateSolver(t){return t.CLOSED_FORM_TWO_TRACE_SAME_LAYER?new kt({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING?new Ut({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.MULTI_HEAD_POLYLINE_SOLVER?new ve({nodeWithPortPoints:this.nodeWithPortPoints,connMap:this.connMap,hyperParameters:t,viaDiameter:this.constructorParams.viaDiameter}):new Dt({...this.constructorParams,hyperParameters:t})}onSolve(t){this.solvedRoutes=t.solver.solvedRoutes.map(t=>{const e=this.nodeWithPortPoints.portPoints.find(e=>e.connectionName===t.connectionName);return e?.rootConnectionName?{...t,rootConnectionName:e.rootConnectionName}:t})}};function Se(t,e,s){const n=[];let i=null;for(let o=0;o<t.length;o++){const a=t[o];i?i.z===a.z?i.points.push({x:a.x,y:a.y}):(n.push(i),i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:s}):i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:s},o===t.length-1&&i&&n.push(i)}return n}var be=class extends e{unsolvedNodePortPoints;routes;colorMap;defaultViaDiameter=.6;defaultTraceThickness=.15;viaDiameter;traceWidth;failedSolvers;activeSubSolver=null;connMap;constructor({nodePortPoints:t,colorMap:e,connMap:s,viaDiameter:n,traceWidth:i}){super(),this.unsolvedNodePortPoints=t,this.colorMap=e??{},this.connMap=s,this.routes=[],this.failedSolvers=[],this.MAX_ITERATIONS=1e6,this.viaDiameter=n??this.defaultViaDiameter,this.traceWidth=i??this.defaultTraceThickness}_step(){if(this.updateCacheStats(),this.activeSubSolver)return this.activeSubSolver.step(),this.activeSubSolver.solved?(this.routes.push(...this.activeSubSolver.solvedRoutes),this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSolvers.push(this.activeSubSolver),this.activeSubSolver=null),void this.updateCacheStats();if(0===this.unsolvedNodePortPoints.length)return this.failedSolvers.length>0?(this.solved=!1,this.failed=!0,this.error=`Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0,5).map(t=>t.nodeWithPortPoints.capacityMeshNodeId)}. err0: ${this.failedSolvers[0].error}.`,void this.updateCacheStats()):(this.solved=!0,void this.updateCacheStats());const t=this.unsolvedNodePortPoints.pop();this.activeSubSolver=new Me({nodeWithPortPoints:t,colorMap:this.colorMap,connMap:this.connMap,viaDiameter:this.viaDiameter,traceWidth:this.traceWidth}),this.updateCacheStats()}updateCacheStats(){const t=st();this.stats.intraNodeCacheHits=t.cacheHits,this.stats.intraNodeCacheMisses=t.cacheMisses}visualize(){let e={lines:[],points:[],rects:[],circles:[]};for(const t of this.routes){const s=Se(t.route,t.connectionName,this.colorMap[t.connectionName]);for(const n of s)e.lines.push({points:n.points,label:n.connectionName,strokeColor:0===n.z?n.color:V(n.color,.75),layer:`z${n.z}`,strokeWidth:t.traceThickness,strokeDash:0!==n.z?"10, 5":void 0});for(const s of t.vias)e.circles.push({center:s,layer:"z0,1",radius:t.viaDiameter/2,fill:this.colorMap[t.connectionName],label:`${t.connectionName} via`})}for(const t of this.failedSolvers){const s=t.nodeWithPortPoints,n=.1*s.width,i=.1*s.height;e.rects.push({center:{x:s.center.x-n/2,y:s.center.y-i/2},layer:"did_not_connect",width:n,height:i,fill:"red",label:`Failed: ${s.capacityMeshNodeId}`});const o={};for(const t of s.portPoints)o[t.connectionName]||(o[t.connectionName]=[]),o[t.connectionName].push({x:t.x,y:t.y,z:t.z});for(const[t,s]of Object.entries(o))for(let t=0;t<s.length-1;t++){const n=s[t],i=s[t+1];e.lines.push({points:[n,i],strokeColor:"red",strokeDash:"10, 5",layer:"did_not_connect"})}}return this.activeSubSolver&&(e=t(e,this.activeSubSolver.visualize())),e}},Ne=class{netMap;idToNetMap;constructor(t){this.netMap=t,this.idToNetMap={};for(const[e,s]of Object.entries(t))for(const t of s)this.idToNetMap[t]=e}addConnections(t){for(const e of t){const t=new Set;for(const s of e){const e=this.idToNetMap[s];e&&t.add(e)}let s;if(0===t.size)s=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[s]=[];else if(1===t.size)s=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{s=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(const e of t)if(e!==s){this.netMap[s].push(...this.netMap[e]),this.netMap[e]=this.netMap[s];for(const t of this.netMap[s])this.idToNetMap[t]=s}}for(const t of e)this.netMap[s].includes(t)||this.netMap[s].push(t),this.idToNetMap[t]=s}}getIdsConnectedToNet(t){return this.netMap[t]||[]}getNetConnectedToId(t){return this.idToNetMap[t]}areIdsConnected(t,e){if(t===e)return!0;const s=this.getNetConnectedToId(t);if(!s)return!1;const n=this.getNetConnectedToId(e);return!!n&&(s===n||n===t||n===t)}areAllIdsConnected(t){const e=this.getNetConnectedToId(t[0]);for(const s of t){const t=this.getNetConnectedToId(s);if(void 0===t)return!1;if(t!==e)return!1}return!0}},Ie=t=>{const e=new Ne({});for(const s of t.connections){if(s.rootConnectionName&&e.addConnections([[s.name,s.rootConnectionName]]),s.netConnectionName&&e.addConnections([[s.name,s.netConnectionName]]),s.mergedConnectionNames)for(const t of s.mergedConnectionNames)e.addConnections([[s.name,t]]);for(const t of s.pointsToConnect)"pcb_port_id"in t&&t.pcb_port_id&&e.addConnections([[s.name,t.pcb_port_id]])}for(const s of t.obstacles){const t=s.offBoardConnectsTo??[],n=Array.from(new Set([...s.connectedTo,...t]));n.length>0&&e.addConnections([n])}return e},Pe=(t,e=1,s={})=>{const n=s.viaDiameter??.6,i=s.obstacleMargin??.2,o=(("width"in t?t.width:t)/(n/2+i)/2)**1.1*e;return 1===t.availableZ?.length&&o>1?1:o},Ce=(t,e=.5,s=16)=>{let n=0,i=t;for(;n<s;){if(Pe({width:i})<=e)break;i/=2,n++}return Math.max(1,n)},_e=(t,e)=>{if(t<0||t>=e)throw new Error(`Invalid z "${t}" for layer count: ${e}`);return 0===t?"top":t===e-1?"bottom":`inner${t}`},Ee=(t,e)=>{const s=[];if(0===t.route.length)return s;let n=[],i=t.route[0].z;for(let o=0;o<t.route.length;o++){const a=t.route[o];if(a.z!==i){const o=_e(i,e);for(const e of n)s.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:o});if(t.vias.some(t=>Math.abs(t.x-a.x)<.001&&Math.abs(t.y-a.y)<.001)){const t=_e(i,e),n=_e(a.z,e);s.push({route_type:"via",x:a.x,y:a.y,from_layer:t,to_layer:n})}n=[a],i=a.z}else n.push(a)}const o=_e(i,e);for(const e of n)s.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:o});return s};function Te(t){return"layers"in t&&Array.isArray(t.layers)}function we(t){return Te(t)?t.layers[0]:t.layer}function ze(t){return Te(t)?t.layers:[t.layer]}var Ae=(t,e)=>"top"===t?0:"bottom"===t?e-1:parseInt(t.slice(5)),Re=1e5,Oe=.001,Le=class extends e{mergedHdRoute;remainingHdRoutes;start;end;colorMap;constructor(t){if(super(),this.remainingHdRoutes=[...t.hdRoutes],this.colorMap=t.colorMap??{},0===t.hdRoutes.length){this.start=t.start,this.end=t.end;const e=[{x:t.start.x,y:t.start.y,z:t.start.z}],s=[];return t.start.z!==t.end.z&&(e.push({x:t.start.x,y:t.start.y,z:t.end.z}),s.push({x:t.start.x,y:t.start.y})),e.push({x:t.end.x,y:t.end.y,z:t.end.z}),this.mergedHdRoute={connectionName:t.connectionName,rootConnectionName:t.hdRoutes[0]?.rootConnectionName,route:e,vias:s,viaDiameter:t.defaultViaDiameter??.6,traceThickness:t.defaultTraceThickness??.15},void(this.solved=!0)}let e=1/0,s=t.hdRoutes[0],n="start-to-end";for(const i of t.hdRoutes){const o=i.route[0],a=i.route[i.route.length-1],r=dt(t.start,o),h=dt(t.start,a),c=dt(t.end,o),d=dt(t.end,a),l=Math.min(r,h,c,d);l<e&&(e=l,s=i,n=Math.min(c,d)<Math.min(r,h)?"end-to-start":"start-to-end")}"start-to-end"===n?(this.start=t.start,this.end=t.end):(this.start=t.end,this.end=t.start);const i=s.route[0],o=s.route[s.route.length-1],a=dt(this.start,i)<=dt(this.start,o)?i:o;this.mergedHdRoute={connectionName:t.connectionName,rootConnectionName:s.rootConnectionName,route:[{x:this.start.x,y:this.start.y,z:a.z}],vias:[],viaDiameter:s.viaDiameter,traceThickness:s.traceThickness}}getDisjointedRoute(){for(const t of this.remainingHdRoutes){if([t.route[0],t.route[t.route.length-1]].some(e=>!this.remainingHdRoutes.some(s=>{if(s===t)return!1;return[s.route[0],s.route[s.route.length-1]].some(t=>t.z===e.z&&dt(e,t)<.001)})))return{firstRoute:t}}return{firstRoute:this.remainingHdRoutes[0]}}_step(){if(0===this.remainingHdRoutes.length){const t=this.mergedHdRoute.route[this.mergedHdRoute.route.length-1];return this.mergedHdRoute.route.push({x:this.end.x,y:this.end.y,z:t.z}),void(this.solved=!0)}const t=this.mergedHdRoute.route[this.mergedHdRoute.route.length-1];let e=-1,s="first",n=1/0;for(let i=0;i<this.remainingHdRoutes.length;i++){const o=this.remainingHdRoutes[i],a=o.route[0],r=o.route[o.route.length-1],h=dt(t,a),c=dt(t,r);let d=1/0;d=t.z===a.z?h<Oe?h:Re+h:h<Oe?1e3+h:Re+h,d<n&&(n=d,e=i,s="first");let l=1/0;l=t.z===r.z?c<Oe?c:Re+c:c<Oe?1e3+c:Re+c,l<n&&(n=l,e=i,s="last")}if(-1===e)return void(this.remainingHdRoutes=[]);const i=this.remainingHdRoutes[e];let o;this.remainingHdRoutes.splice(e,1),o="first"===s?i.route:[...i.route].reverse(),o.length>0&&dt(t,o[0])<Oe&&t.z===o[0].z?this.mergedHdRoute.route.push(...o.slice(1)):this.mergedHdRoute.route.push(...o),this.mergedHdRoute.vias.push(...i.vias)}visualize(){const t={points:[],lines:[],circles:[],title:"Single High Density Route Stitch Solver"};if(t.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){t.lines?.push({points:this.mergedHdRoute.route.map(t=>({x:t.x,y:t.y})),strokeColor:"green"});for(const e of this.mergedHdRoute.route)t.points?.push({x:e.x,y:e.y,color:"green"});for(const e of this.mergedHdRoute.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:this.mergedHdRoute.viaDiameter/2,fill:"green"})}for(const[e,s]of this.remainingHdRoutes.entries()){const n=this.colorMap[s.connectionName]??"gray";s.route.length>1&&t.lines?.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:n});for(let i=0;i<s.route.length;i++){const o=s.route[i];t.points?.push({x:o.x+(e%2-.5)/500+(i%8-4)/1e3,y:o.y+(e%2-.5)/500+(i%8-4)/1e3,color:n,label:`Route ${s.connectionName} ${o===s.route[0]?"First":o===s.route[s.route.length-1]?"Last":""}`})}for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n})}return t}},De=class extends e{unsolvedRoutes;activeSolver=null;mergedHdRoutes=[];colorMap={};defaultTraceThickness;defaultViaDiameter;constructor(t){super(),this.colorMap=t.colorMap??{};const e=t.hdRoutes[0];this.defaultTraceThickness=e?.traceThickness??.15,this.defaultViaDiameter=e?.viaDiameter??t.defaultViaDiameter??.6,this.unsolvedRoutes=t.connections.map(e=>({connectionName:e.name,hdRoutes:t.hdRoutes.filter(t=>t.connectionName===e.name),start:{...e.pointsToConnect[0],z:Ae(we(e.pointsToConnect[0]),t.layerCount)},end:{...e.pointsToConnect[1],z:Ae(we(e.pointsToConnect[1]),t.layerCount)}})),this.MAX_ITERATIONS=1e5}_step(){if(this.activeSolver)return this.activeSolver.step(),void(this.activeSolver.solved?(this.activeSolver instanceof Le&&this.mergedHdRoutes.push(this.activeSolver.mergedHdRoute),this.activeSolver=null):this.activeSolver.failed&&(this.failed=!0,this.error=this.activeSolver.error));const t=this.unsolvedRoutes.pop();t?this.activeSolver=new Le({connectionName:t.connectionName,hdRoutes:t.hdRoutes,start:t.start,end:t.end,colorMap:this.colorMap,defaultTraceThickness:this.defaultTraceThickness,defaultViaDiameter:this.defaultViaDiameter}):this.solved=!0}visualize(){const t={points:[],lines:[],circles:[],title:"Multiple High Density Route Stitch Solver"};if(this.activeSolver){const e=this.activeSolver.visualize();e.points?.length&&t.points?.push(...e.points),e.lines?.length&&t.lines?.push(...e.lines),e.circles?.length&&t.circles?.push(...e.circles),e.rects?.length&&(t.rects||(t.rects=[]),t.rects.push(...e.rects))}for(const[e,s]of this.mergedHdRoutes.entries()){const n=this.colorMap[s.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1],a=0!==i.z?V(n,.5):n;t.lines?.push({points:[{x:i.x,y:i.y},{x:o.x,y:o.y}],strokeColor:a,strokeWidth:s.traceThickness})}for(const e of s.route){const s=0!==e.z?V(n,.5):n;t.points?.push({x:e.x,y:e.y,color:s})}for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n})}for(const e of this.unsolvedRoutes){const s=this.colorMap[e.connectionName]??"gray";t.points?.push({x:e.start.x,y:e.start.y,color:s,label:`${e.connectionName} Start (z=${e.start.z})`},{x:e.end.x,y:e.end.y,color:s,label:`${e.connectionName} End (z=${e.end.z})`}),t.lines?.push({points:[{x:e.start.x,y:e.start.y},{x:e.end.x,y:e.end.y}],strokeColor:s,strokeDash:"2 2"});for(const n of e.hdRoutes){n.route.length>1&&t.lines?.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:V(s,.5),strokeDash:"10 5"});for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s})}}return t}},Fe=t=>{const e=[],s=[],n=[],i=H(t),o=(t.minViaDiameter??.6)/2;if(t.connections)for(const e of t.connections)for(const t of e.pointsToConnect){const s=ze(t);n.push({x:t.x,y:t.y,color:i[e.name],layer:s[0]??("z"in t?_e(t.z,2):"top"),label:`${e.name} (${s.join(",")})`})}if(t.traces)for(const n of t.traces)for(let t=0;t<n.route.length-1;t++){const i=n.route[t],a=n.route[t+1];"via"===i.route_type?s.push({center:{x:i.x,y:i.y},radius:o,fill:"blue",stroke:"none",layer:"z0,1"}):"wire"===i.route_type&&"wire"===a.route_type&&a.layer===i.layer&&e.push({points:[{x:i.x,y:i.y},{x:a.x,y:a.y}],layer:`z${Ae(i.layer,2)}`,strokeWidth:.15,strokeColor:V({top:"red",bottom:"blue",inner1:"green",inner2:"yellow"}[i.layer],.5)})}return{rects:t.obstacles.map(t=>({center:t.center,width:t.width,height:t.height,fill:"rgba(255,0,0,0.5)",layer:`z${t.layers.map(Ae).join(",")}`})),circles:s,lines:e,points:n}};function $e(t){const{nodeId:e,nodeIdToSegmentIds:s,segmentIdToNodeIds:n,hops:i}=t;if(0===i)return[e];const o=new Set([e]),a=[{nodeId:e,remainingHops:i}];for(;a.length>0;){const{nodeId:t,remainingHops:e}=a.shift();if(0===e)continue;const i=s.get(t)||[];for(const t of i){const s=n.get(t)||[];for(const t of s)o.has(t)||(o.add(t),a.push({nodeId:t,remainingHops:e-1}))}}return Array.from(o)}var ke=t=>Array.from(t.entries()).map(([t,{x:e,y:s,z:n}])=>`${t}(${e?.toFixed(3)??""},${s?.toFixed(3)??""},${n??""})`).sort().join("&"),Be=(t,e,s,n)=>{const i=Math.min(t,e),o=Math.max(t,e),a=Math.min(s,n);return i<=Math.max(s,n)&&o>=a},Xe=(t,e,s,n)=>{const i=[],o=new Map(t.originalPointMap);for(const[t,e]of s.entries()){const s=o.get(t);o.set(t,{x:e.x??s.x,y:e.y??s.y,z:e.z??s.z})}for(const s of t.allNodeIds){if(!e.get(s))continue;const a=t.segmentPairsInNode.get(s);for(const t of a){const e=o.get(t[0]),n=o.get(t[1]);e.z!==n.z&&i.push({type:"transition_via",segmentPoints:t,capacityMeshNodeId:s,probabilityOfFailure:0})}for(let t=0;t<a.length;t++)for(let e=t+1;e<a.length;e++){if(n?.areIdsConnected(a[t][0],a[t][1]))continue;const r=a[t],h=a[e],c=o.get(r[0]),d=o.get(r[1]),l=o.get(h[0]),u=o.get(h[1]);if(!Be(c.z,d.z,l.z,u.z))continue;const p=at(c,d,l,u),f=c.z===d.z&&l.z===u.z&&c.z===l.z;p&&(f?i.push({type:"same_layer_crossing",segmentPoints:[r,h],capacityMeshNodeId:s,crossingLine1:r,crossingLine2:h,probabilityOfFailure:0}):c.z===d.z&&l.z!==u.z?i.push({type:"single_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:s,sameLayerCrossingLine:r,transitionCrossingLine:h,probabilityOfFailure:0}):c.z!==d.z&&l.z===u.z?i.push({type:"single_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:s,sameLayerCrossingLine:h,transitionCrossingLine:r,probabilityOfFailure:0}):c.z!==d.z&&l.z!==u.z&&i.push({type:"double_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:s,crossingLine1:r,crossingLine2:h,probabilityOfFailure:0}))}}return i},Ye=(t,e,s)=>{if("change_layer"===e.type)for(const s of e.segmentPointIds){const n=t.get(s)||{};t.set(s,{...n,z:e.newZ})}else if("swap_position_on_segment"===e.type){const[n,i]=e.segmentPointIds,o=s(n),a=s(i),r=t.get(n)||{},h=t.get(i)||{};t.set(n,{...r,x:a.x,y:a.y}),t.set(i,{...h,x:o.x,y:o.y})}else if("combined"===e.type)for(const n of e.operations)Ye(t,n,s)},He=(t,e)=>{const s=new Map,n=new Map,i=new Map,o=[];let a=0;for(const r of t)for(const t of r.assignedPoints){const h={segmentPointId:"SP"+a++,segmentId:r.nodePortSegmentId,capacityMeshNodeIds:e.get(r.nodePortSegmentId),connectionName:t.connectionName,rootConnectionName:t.rootConnectionName,x:t.point.x,y:t.point.y,z:t.point.z,directlyConnectedSegmentPointIds:[]};s.set(h.segmentPointId,h);for(const t of h.capacityMeshNodeIds)n.set(t,[...n.get(t)??[],h.segmentPointId]);i.set(r.nodePortSegmentId,[...i.get(r.nodePortSegmentId)??[],h.segmentPointId]),o.push(h)}return{segmentPointMap:s,nodeToSegmentPointMap:n,segmentToSegmentPointMap:i}},Ve=(t,e,s,n)=>{if(t?._containsTarget)return 0;return((.82*e+.41*s+.2*n)/2)**1.1/Pe(t)},je=class extends e{nodeMap;dedupedSegments;dedupedSegmentMap;MUTABLE_HOPS=1;unravelSection;candidates=[];lastProcessedCandidate=null;bestCandidate=null;originalCandidate;rootNodeId;nodeIdToSegmentIds;segmentIdToNodeIds;colorMap;tunedNodeCapacityMap;MAX_CANDIDATES=500;iterationsSinceImprovement=0;hyperParameters;selectedCandidateIndex=null;queuedOrExploredCandidatePointModificationHashes=new Set;constructorParams;constructor(t){if(super(),this.constructorParams=t,this.MUTABLE_HOPS=t.MUTABLE_HOPS??this.MUTABLE_HOPS,this.MAX_ITERATIONS=5e4,this.hyperParameters={...t.hyperParameters,MAX_ITERATIONS_WITHOUT_IMPROVEMENT:200},this.nodeMap=t.nodeMap,this.dedupedSegments=t.dedupedSegments,t.dedupedSegmentMap)this.dedupedSegmentMap=t.dedupedSegmentMap;else{this.dedupedSegmentMap=new Map;for(const t of this.dedupedSegments)this.dedupedSegmentMap.set(t.nodePortSegmentId,t)}this.nodeIdToSegmentIds=t.nodeIdToSegmentIds,this.segmentIdToNodeIds=t.segmentIdToNodeIds,this.rootNodeId=t.rootNodeId,this.colorMap=t.colorMap??{},this.unravelSection=this.createUnravelSection({segmentPointMap:t.segmentPointMap,nodeToSegmentPointMap:t.nodeToSegmentPointMap,segmentToSegmentPointMap:t.segmentToSegmentPointMap}),this.tunedNodeCapacityMap=new Map;for(const t of this.unravelSection.allNodeIds)this.tunedNodeCapacityMap.set(t,Pe(this.nodeMap.get(t)));this.originalCandidate=this.createInitialCandidate(),this.candidates=[this.originalCandidate]}getConstructorParams(){return{...this.constructorParams,segmentPointMap:this.unravelSection.segmentPointMap,nodeToSegmentPointMap:this.unravelSection.segmentPointsInNode,segmentToSegmentPointMap:this.unravelSection.segmentPointsInSegment}}createUnravelSection(t){const e=$e({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS}),s=$e({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS+1}),n=Array.from(new Set(s).difference(new Set(e)));t?.segmentPointMap||(t=He(this.dedupedSegments,this.segmentIdToNodeIds));const i=new Map;for(const e of s)i.set(e,t.nodeToSegmentPointMap.get(e));const o=new Map;for(const e of s)for(const s of i.get(e)){const e=t.segmentPointMap.get(s);o.set(s,e)}const a=Array.from(o.values()),r=new Map;for(const t of a)r.set(t.segmentId,[...r.get(t.segmentId)??[],t.segmentPointId]);for(const[e,s]of i.entries())for(let e=0;e<s.length;e++){const n=t.segmentPointMap.get(s[e]);for(let i=e+1;i<s.length;i++){const e=t.segmentPointMap.get(s[i]);e.segmentPointId!==n.segmentPointId&&(e.segmentId!==n.segmentId&&e.connectionName===n.connectionName&&(e.directlyConnectedSegmentPointIds.includes(n.segmentPointId)||(n.directlyConnectedSegmentPointIds.push(e.segmentPointId),e.directlyConnectedSegmentPointIds.push(n.segmentPointId))))}}const h=new Map;for(const t of s)h.set(t,[]);for(const e of a)for(const s of e.capacityMeshNodeIds){const n=h.get(s);if(n)for(const i of e.directlyConnectedSegmentPointIds){const o=t.segmentPointMap.get(i);o.segmentPointId!==e.segmentPointId&&(o.capacityMeshNodeIds.some(t=>t===s)&&(n.some(([t,s])=>t===e.segmentPointId&&s===o.segmentPointId||t===o.segmentPointId&&s===e.segmentPointId)||n.push([e.segmentPointId,o.segmentPointId])))}}const c=new Set;for(const t of e)for(const e of this.nodeIdToSegmentIds.get(t)){this.segmentIdToNodeIds.get(e).every(t=>!this.nodeMap.get(t)._containsTarget)&&c.add(e)}const d=new Set;for(const t of a){const s=t.capacityMeshNodeIds.some(t=>e.includes(t)),n=this.dedupedSegmentMap.get(t.segmentId),i=n&&n.availableZ.length>1;(s||i)&&d.add(t.segmentPointId)}const l=new Set;for(const t of a){if(t.capacityMeshNodeIds.some(t=>this.nodeMap.get(t)?._containsTarget)){const e=this.dedupedSegmentMap.get(t.segmentId);e&&1===e.availableZ.length&&l.add(t.segmentPointId)}}return{allNodeIds:s,mutableNodeIds:e,immutableNodeIds:n,mutableSegmentIds:c,segmentPairsInNode:h,segmentPointMap:o,segmentPointsInNode:i,segmentPointsInSegment:r,originalPointMap:o,mutableSegmentPointIds:d,zLockedSegmentPointIds:l}}createInitialCandidate(){const t=new Map,e=Xe(this.unravelSection,this.nodeMap,t),s=this.computeG({issues:e,originalCandidate:{},operationsPerformed:0,operation:{}});return{pointModifications:t,g:s,h:0,f:s,operationsPerformed:0,candidateHash:ke(t),issues:Xe(this.unravelSection,this.nodeMap,t)}}get nextCandidate(){return this.candidates[0]??null}getPointInCandidate(t,e){const s=this.unravelSection.segmentPointMap.get(e),n=t.pointModifications.get(e);return{x:n?.x??s.x,y:n?.y??s.y,z:n?.z??s.z,segmentId:s.segmentId}}getConnectionSegmentPointIds(t){const e=[];for(const[s,n]of this.unravelSection.segmentPointMap.entries())n.connectionName===t&&e.push(s);return e}canConnectionUseLayer(t,e){for(const s of t){const t=this.unravelSection.segmentPointMap.get(s),n=this.dedupedSegmentMap.get(t.segmentId);if(!n||!n.availableZ.includes(e))return!1}return!0}getOperationsForIssue(t,e){const s=[];if("transition_via"===e.type){const[n,i]=e.segmentPoints,o=this.getPointInCandidate(t,n),a=this.getPointInCandidate(t,i),r=this.unravelSection.segmentPointMap.get(n),h=(this.unravelSection.segmentPointMap.get(i),this.dedupedSegmentMap.get(o.segmentId).availableZ),c=this.dedupedSegmentMap.get(a.segmentId).availableZ,d=this.unravelSection.zLockedSegmentPointIds.has(n),l=this.unravelSection.zLockedSegmentPointIds.has(i),u=this.getConnectionSegmentPointIds(r.connectionName);if(this.canConnectionUseLayer(u,a.z)){const t=u.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));t.length>0&&s.push({type:"change_layer",newZ:a.z,segmentPointIds:t})}if(this.canConnectionUseLayer(u,o.z)){const t=u.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));t.length>0&&s.push({type:"change_layer",newZ:o.z,segmentPointIds:t})}this.unravelSection.mutableSegmentPointIds.has(n)&&!d&&h.includes(a.z)&&s.push({type:"change_layer",newZ:a.z,segmentPointIds:[n]}),this.unravelSection.mutableSegmentPointIds.has(i)&&!l&&c.includes(o.z)&&s.push({type:"change_layer",newZ:o.z,segmentPointIds:[i]})}if("same_layer_crossing"===e.type){const[t,n]=e.crossingLine1,[i,o]=e.crossingLine2,a=[],r=this.unravelSection.segmentPointMap.get(t),h=this.unravelSection.segmentPointMap.get(n),c=this.unravelSection.segmentPointMap.get(i),d=this.unravelSection.segmentPointMap.get(o),l=this.unravelSection.mutableSegmentPointIds.has(t),u=this.unravelSection.mutableSegmentPointIds.has(n),p=this.unravelSection.mutableSegmentPointIds.has(i),f=this.unravelSection.mutableSegmentPointIds.has(o),g=this.unravelSection.zLockedSegmentPointIds.has(t),m=this.unravelSection.zLockedSegmentPointIds.has(n),y=this.unravelSection.zLockedSegmentPointIds.has(i),x=this.unravelSection.zLockedSegmentPointIds.has(o);l&&p&&r.segmentId===c.segmentId&&a.push([t,i]),l&&f&&r.segmentId===d.segmentId&&a.push([t,o]),u&&p&&h.segmentId===c.segmentId&&a.push([n,i]),u&&f&&h.segmentId===d.segmentId&&a.push([n,o]);for(const[t,e]of a)s.push({type:"swap_position_on_segment",segmentPointIds:[t,e]});const v=this.getConnectionSegmentPointIds(r.connectionName),M=this.getConnectionSegmentPointIds(c.connectionName),S=new Set;for(const t of this.unravelSection.segmentPointMap.values()){const e=this.dedupedSegmentMap.get(t.segmentId);if(e)for(const t of e.availableZ)S.add(t)}for(const t of S)if(t!==r.z&&this.canConnectionUseLayer(v,t)){const e=v.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));e.length>0&&s.push({type:"change_layer",newZ:t,segmentPointIds:e})}for(const t of S)if(t!==c.z&&this.canConnectionUseLayer(M,t)){const e=M.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));e.length>0&&s.push({type:"change_layer",newZ:t,segmentPointIds:e})}const b=this.dedupedSegmentMap.get(r.segmentId),N=this.dedupedSegmentMap.get(h.segmentId),I=this.dedupedSegmentMap.get(c.segmentId),P=this.dedupedSegmentMap.get(d.segmentId),C=(t,e)=>t.every(t=>t.availableZ.includes(e));if(l&&u&&!g&&!m){const e=0===r.z?1:0;C([b,N],e)&&s.push({type:"change_layer",newZ:e,segmentPointIds:[t,n]})}if(p&&f&&!y&&!x){const t=0===c.z?1:0;C([I,P],t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[i,o]})}if(l&&!g){const e=0===r.z?1:0;b.availableZ.includes(e)&&s.push({type:"change_layer",newZ:e,segmentPointIds:[t]})}if(u&&!m){const t=0===h.z?1:0;N.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[n]})}if(p&&!y){const t=0===c.z?1:0;I.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[i]})}if(f&&!x){const t=0===d.z?1:0;P.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[o]})}}return s}computeG(t){const{issues:e,originalCandidate:s,operationsPerformed:n,operation:i}=t,o=new Map;for(const t of e){o.has(t.capacityMeshNodeId)||o.set(t.capacityMeshNodeId,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0});const e=o.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"===t.type||"single_transition_crossing"===t.type?e.numEntryExitLayerChanges++:t.type}let a=0;for(const[t,{numEntryExitLayerChanges:e,numSameLayerCrossings:s,numTransitionCrossings:n}]of o){const i=this.nodeMap.get(t),o=Math.min(Ve(i,s,e,n),.999999);a+=Math.log(1-o)}var r;return(r=a)<-Math.LN2?Math.log(1-Math.exp(r)):Math.log(-Math.expm1(r))}getUnexploredNeighborByApplyingOperation(t,e){const s=new Map(t.pointModifications);Ye(s,e,e=>this.getPointInCandidate(t,e));const n=ke(s);if(this.queuedOrExploredCandidatePointModificationHashes.has(n))return null;const i=Xe(this.unravelSection,this.nodeMap,s),o=t.operationsPerformed+1,a=this.computeG({issues:i,originalCandidate:t,operationsPerformed:o,operation:e});return{issues:i,g:a,h:0,f:a,pointModifications:s,candidateHash:n,operationsPerformed:o}}getNeighborOperationsForCandidate(t){return t.issues.flatMap(e=>this.getOperationsForIssue(t,e))}getNeighbors(t){const e=[],s=this.getNeighborOperationsForCandidate(t);for(const n of s){const s=this.getUnexploredNeighborByApplyingOperation(t,n);s&&e.push(s)}return e}_step(){const t=this.candidates.shift();this.iterationsSinceImprovement++,this.iterationsSinceImprovement>this.hyperParameters.MAX_ITERATIONS_WITHOUT_IMPROVEMENT?this.solved=!0:t?(this.lastProcessedCandidate=t,t.f<(this.bestCandidate?.f??1/0)&&(this.bestCandidate=t,this.iterationsSinceImprovement=0),this.getNeighbors(t).forEach(t=>{this.queuedOrExploredCandidatePointModificationHashes.has(t.candidateHash)||(this.queuedOrExploredCandidatePointModificationHashes.add(t.candidateHash),this.candidates.push(t))}),this.candidates.sort((t,e)=>t.f-e.f),this.candidates.length=Math.min(this.candidates.length,this.MAX_CANDIDATES)):this.solved=!0}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Section Solver"};let e=null;if(e=null!==this.selectedCandidateIndex?"best"===this.selectedCandidateIndex?this.bestCandidate:"original"===this.selectedCandidateIndex?this.originalCandidate:this.candidates[this.selectedCandidateIndex]:this.solved?this.bestCandidate:this.lastProcessedCandidate||this.candidates[0],!e)return t;const s=new Map;for(const[t,n]of this.unravelSection.segmentPointMap){const i={...n},o=e.pointModifications.get(t);o&&(void 0!==o.x&&(i.x=o.x),void 0!==o.y&&(i.y=o.y),void 0!==o.z&&(i.z=o.z)),s.set(t,i)}for(const[e,n]of s)t.points.push({x:n.x,y:n.y,label:`${e}\nSegment: ${n.segmentId} ${this.unravelSection.mutableSegmentIds.has(n.segmentId)?"MUTABLE":"IMMUTABLE"}\nLayer: ${n.z}`,color:this.colorMap[n.connectionName]||"#000"});const n=new Map;for(const t of this.unravelSection.allNodeIds)n.set(t,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0,estPf:0});for(const t of e.issues){const e=n.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"!==t.type&&"single_transition_crossing"!==t.type||e.numEntryExitLayerChanges++}for(const[t,e]of n.entries()){const s=this.nodeMap.get(t);e.estPf=Ve(s,e.numSameLayerCrossings,e.numEntryExitLayerChanges,e.numTransitionCrossings)}for(const e of this.unravelSection.allNodeIds){const s=this.nodeMap.get(e),i=this.unravelSection.mutableNodeIds.includes(e),o=n.get(e),a=[`${e} (${i?"MUT":"IMM"})`,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Pf: ${o.estPf.toFixed(3)}`,`TC: ${o.numTransitionCrossings}`,`SLC: ${o.numSameLayerCrossings}`,`EELC: ${o.numEntryExitLayerChanges}`].join("\n");t.rects.push({center:s.center,label:a,color:i?"green":"red",width:s.width/8,height:s.height/8})}for(const[e,n]of this.unravelSection.segmentPointsInSegment){if(n.length<=1)continue;const i=n.map(t=>s.get(t));for(let s=0;s<i.length-1;s++)t.lines.push({points:[{x:i[s].x,y:i[s].y},{x:i[s+1].x,y:i[s+1].y}],strokeColor:this.colorMap[e]||"#000"})}for(const[e,n]of s)for(const i of n.directlyConnectedSegmentPointIds)if(e<i){const e=s.get(i);if(!e)continue;const o=n.z===e.z,a=n.z;let r;r=o?0===a?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:n.x,y:n.y},{x:e.x,y:e.y}],strokeDash:r,strokeColor:this.colorMap[n.connectionName]||"#000"})}for(const n of e.issues){const e=this.nodeMap.get(n.capacityMeshNodeId);if("transition_via"===n.type)for(const i of n.segmentPoints){const n=s.get(i);t.circles.push({center:{x:n.x,y:n.y},radius:e.width/16,stroke:"#ff0000",fill:"rgba(255, 0, 0, 0.2)",label:`Via Issue\n${i}\nLayer: ${n.z}`})}else if("same_layer_crossing"===n.type)for(const[i,o]of[n.crossingLine1,n.crossingLine2]){const n=s.get(i),a=s.get(o);t.lines.push({points:[{x:n.x,y:n.y},{x:a.x,y:a.y}],strokeColor:"rgba(255,0,0,0.2)",strokeWidth:e.width/32})}}for(const[n,i]of e.pointModifications){const e=s.get(n),i=this.unravelSection.segmentPointMap.get(n);t.circles.push({center:{x:e.x,y:e.y},radius:.05,stroke:"#0000ff",fill:"rgba(0, 0, 255, 0.2)",label:`${n}\nOriginal: (${i.x.toFixed(2)}, ${i.y.toFixed(2)}, ${i.z})\nNew: (${e.x.toFixed(2)}, ${e.y.toFixed(2)}, ${e.z})`})}return t}};import Ze from"object-hash";function We(t,e){return Array.isArray(e)?[t.a*e[0]+t.c*e[1]+t.e,t.b*e[0]+t.d*e[1]+t.f]:{x:t.a*e.x+t.c*e.y+t.e,y:t.b*e.x+t.d*e.y+t.f}}var{cos:Ue,sin:Ge,PI:qe}=Math,{tan:Ke}=Math,Je=t=>(Math.round(20*t)/20).toFixed(2),Qe=t=>(Math.round(1e3*t)/1e3).toFixed(3);nt();var ts=class extends je{cacheHit=!1;cacheProvider;hasAttemptedToUseCache=!1;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?et():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}computeCacheKeyAndTransform(){const t=this.nodeMap.get(this.rootNodeId),e=function(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}(-t.center.x,-t.center.y),s=new Map,n=new Map,i=new Map,o=new Map,a=new Map,r=new Map;let h=0,c=0,d=0;const l=[...this.unravelSection.allNodeIds].sort((t,e)=>{const s=this.nodeMap.get(t),n=this.nodeMap.get(e);return s.center.x!==n.center.x?s.center.x-n.center.x:s.center.y-n.center.y});for(const t of l){const e="node_"+h++;s.set(t,e),n.set(e,t)}const u=[...Array.from(this.unravelSection.segmentPointMap.entries()).sort(([,t],[,e])=>t.x!==e.x?t.x-e.x:t.y-e.y).map(([t])=>t)].sort();for(const t of u){const e="sp_"+d++;a.set(t,e),r.set(e,t);const s=this.unravelSection.segmentPointMap.get(t).segmentId;if(!i.has(s)){const t="seg_"+c++;i.set(s,t),o.set(t,s)}}const p={};for(const[t,n]of s.entries()){const s=this.nodeMap.get(t),i=We(e,s.center);p[n]={width:s.width,height:s.height,availableZ:s.availableZ,center:{x:Je(i.x),y:Je(i.y)}}}const f={};for(const[t,s]of a.entries()){const n=this.unravelSection.segmentPointMap.get(t),i=We(e,{x:n.x,y:n.y});f[s]={x:Je(i.x),y:Je(i.y),z:n.z}}const g={hyperParameters:this.hyperParameters,normalizedNodes:p,normalizedSegmentPoints:f,mutableHops:this.MUTABLE_HOPS},m=`unravelsec:${Ze(g)}`,y={realToCacheTransform:e,nodeIdMap:s,segmentIdMap:i,segmentPointIdMap:a,reverseNodeIdMap:n,reverseSegmentIdMap:o,reverseSegmentPointIdMap:r};return this.cacheKey=m,this.cacheToSolveSpaceTransform=y,{cacheKey:m,cacheToSolveSpaceTransform:y}}applyCachedSolution(t){if(!1===t.success)return void(this.failed=!0);if(!this.cacheToSolveSpaceTransform)return void console.error("Cache transform not available to apply cached solution.");const{reverseSegmentPointIdMap:e,reverseNodeIdMap:s}=this.cacheToSolveSpaceTransform,n=new Map;for(const[s,i]of t.bestCandidatePointModificationsDelta){const t=e.get(s);if(!t){console.warn(`Could not find original ID for normalized SP ID: ${s} when applying cache.`);continue}const o=this.unravelSection.segmentPointMap.get(t);if(!o){console.warn(`Could not find original segment point for ID: ${t} when applying cache.`);continue}const a={};if(void 0!==i.dx){const t=parseFloat(i.dx);Number.isNaN(t)?console.warn(`Failed to parse cached dx coordinate: ${i.dx}`):a.x=o.x+t}if(void 0!==i.dy){const t=parseFloat(i.dy);Number.isNaN(t)?console.warn(`Failed to parse cached dy coordinate: ${i.dy}`):a.y=o.y+t}void 0!==i.dz&&(a.z=o.z+i.dz),Object.keys(a).length>0&&n.set(t,a)}const i=Xe(this.unravelSection,this.nodeMap,n);this.bestCandidate={pointModifications:n,issues:i,f:t.bestCandidateF,g:t.bestCandidateF,h:0,operationsPerformed:-1,candidateHash:ke(n)},this.cacheHit=!0,this.solved=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(this.failed)return void this.cacheProvider?.setCachedSolutionSync(this.cacheKey,{success:!1});if(!this.bestCandidate)return;const{segmentPointIdMap:t}=this.cacheToSolveSpaceTransform,e=[];for(const[s,n]of this.bestCandidate.pointModifications.entries()){const i=t.get(s);if(!i){console.warn(`Could not find normalized ID for original SP ID: ${s} when saving to cache.`);continue}const o=this.unravelSection.segmentPointMap.get(s);if(!o){console.warn(`Could not find original segment point for ID: ${s} when saving cache.`);continue}const a={};let r=!1;if(void 0!==n.x){const t=n.x-o.x,e=Qe(t);0!==parseFloat(e)&&(a.dx=e,r=!0)}if(void 0!==n.y){const t=n.y-o.y,e=Qe(t);0!==parseFloat(e)&&(a.dy=e,r=!0)}if(void 0!==n.z){const t=n.z-o.z;0!==t&&(a.dz=t,r=!0)}r&&e.push([i,a])}const s={success:!0,bestCandidatePointModificationsDelta:e,bestCandidateF:this.bestCandidate.f};this.cacheProvider?.setCachedSolutionSync(this.cacheKey,s)}},es=class extends e{nodeMap;dedupedSegmentMap;dedupedSegments;nodeIdToSegmentIds;segmentIdToNodeIds;nodeToSegmentPointMap;segmentToSegmentPointMap;colorMap;tunedNodeCapacityMap;MAX_NODE_ATTEMPTS=2;MUTABLE_HOPS=1;ACCEPTABLE_PF=.05;MAX_ITERATIONS_WITHOUT_IMPROVEMENT=200;nodePfMap;attemptsToFixNode;activeSubSolver=null;segmentPointMap;cacheProvider=null;constructor({assignedSegments:t,colorMap:e,nodes:s,cacheProvider:n}){super(),this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.cacheHits=0,this.stats.cacheMisses=0,this.cacheProvider=n??null,this.MAX_ITERATIONS=1e6,this.dedupedSegments=(t=>{const e=[],s=new Map;let n=-1;for(const i of t){const t=`${i.start.x}-${i.start.y}-${i.end.x}-${i.end.y}-${i.availableZ.join(",")}`,o=s.get(t);o?i.nodePortSegmentId=o.nodePortSegmentId:(n++,i.nodePortSegmentId=`SEG${n}`,s.set(t,i),e.push(i))}return e})(t),this.dedupedSegmentMap=new Map;for(const t of this.dedupedSegments)this.dedupedSegmentMap.set(t.nodePortSegmentId,t);this.nodeMap=new Map;for(const t of s)this.nodeMap.set(t.capacityMeshNodeId,t);this.nodeIdToSegmentIds=new Map,this.segmentIdToNodeIds=new Map,this.attemptsToFixNode=new Map;for(const e of t)this.segmentIdToNodeIds.set(e.nodePortSegmentId,[...this.segmentIdToNodeIds.get(e.nodePortSegmentId)??[],e.capacityMeshNodeId]),this.nodeIdToSegmentIds.set(e.capacityMeshNodeId,[...this.nodeIdToSegmentIds.get(e.capacityMeshNodeId)??[],e.nodePortSegmentId]);this.colorMap=e??{},this.tunedNodeCapacityMap=new Map;for(const[t,e]of this.nodeMap)this.tunedNodeCapacityMap.set(t,Pe(e));const{segmentPointMap:i,nodeToSegmentPointMap:o,segmentToSegmentPointMap:a}=He(this.dedupedSegments,this.segmentIdToNodeIds);this.segmentPointMap=i,this.nodeToSegmentPointMap=o,this.segmentToSegmentPointMap=a,this.nodePfMap=this.computeInitialPfMap()}computeInitialPfMap(){const t=new Map;for(const[e,s]of this.nodeMap.entries())t.set(e,this.computeNodePf(s));return t}computeNodePf(t){const{numSameLayerCrossings:e,numEntryExitLayerChanges:s,numTransitionCrossings:n}=(t=>{let e=0,s=0,n=0;const i=new Map;for(const e of t)i.has(e.connectionName)||i.set(e.connectionName,[]),i.get(e.connectionName).push(e);const o=[],a=[];for(const[t,e]of i.entries()){if(e.length<2)continue;const n=e[0];for(let i=1;i<e.length;i++){const r=e[i],h={connectionName:t,z:n.z,points:[n,r]};n.z!==r.z?(s++,a.push({connectionName:t,points:[n,r]})):o.push(h)}}for(let t=0;t<o.length;t++)for(let s=t+1;s<o.length;s++){const n=o[t],i=o[s];n.z===i.z&&at(n.points[0],n.points[1],i.points[0],i.points[1])&&e++}for(let t=0;t<a.length;t++)for(let e=t+1;e<a.length;e++){const s=a[t],i=a[e];at(s.points[0],s.points[1],i.points[0],i.points[1])&&n++}for(let t=0;t<a.length;t++)for(let e=0;e<o.length;e++){const s=a[t],i=o[e];at(s.points[0],s.points[1],i.points[0],i.points[1])&&n++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:s,numTransitionCrossings:n}})((this.nodeToSegmentPointMap.get(t.capacityMeshNodeId)??[]).map(t=>this.segmentPointMap.get(t)));return Ve(t,e,s,n)}_step(){if(this.iterations>=this.MAX_ITERATIONS-1)return void(this.solved=!0);if(!this.activeSubSolver){let t=null,e=0;for(const[s,n]of this.nodePfMap.entries()){n*(1-(this.attemptsToFixNode.get(s)??0)/this.MAX_NODE_ATTEMPTS)>e&&(e=n,t=s)}if(!t||e<this.ACCEPTABLE_PF)return void(this.solved=!0);this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.activeSubSolver=new ts({dedupedSegments:this.dedupedSegments,dedupedSegmentMap:this.dedupedSegmentMap,nodeMap:this.nodeMap,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,colorMap:this.colorMap,rootNodeId:t,MUTABLE_HOPS:this.MUTABLE_HOPS,segmentPointMap:this.segmentPointMap,nodeToSegmentPointMap:this.nodeToSegmentPointMap,segmentToSegmentPointMap:this.segmentToSegmentPointMap,cacheProvider:this.cacheProvider})}this.activeSubSolver.step();const{bestCandidate:t,originalCandidate:e,lastProcessedCandidate:s}=this.activeSubSolver;if(this.activeSubSolver.failed)return this.stats.failedOptimizations+=1,void(this.activeSubSolver=null);if(this.activeSubSolver.solved){this.activeSubSolver.cacheHit?this.stats.cacheHits+=1:this.stats.cacheMisses+=1;if(t&&t.g<e.g){this.stats.successfulOptimizations+=1;for(const[e,s]of t.pointModifications.entries()){const t=this.segmentPointMap.get(e);t.x=s.x??t.x,t.y=s.y??t.y,t.z=s.z??t.z}for(const t of this.activeSubSolver.unravelSection.allNodeIds)this.nodePfMap.set(t,this.computeNodePf(this.nodeMap.get(t)))}else this.stats.failedOptimizations+=1;this.activeSubSolver=null}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Multi Section Solver"};for(const[e,s]of this.nodeMap.entries()){const n=this.nodePfMap.get(e)||0,i=Math.min(n,1),o=`rgb(${Math.floor(255*i)}, ${Math.floor(255*(1-i))}, 0)`;0===(this.attemptsToFixNode.get(e)??0)&&0===i||t.rects.push({center:s.center,label:[e,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Pf: ${n.toFixed(3)}`].join("\n"),color:o,width:s.width/8,height:s.height/8})}for(const e of this.segmentPointMap.values()){const s=this.dedupedSegmentMap.get(e.segmentId);t.points.push({x:e.x,y:e.y,label:[e.segmentPointId,e.segmentId,`z: ${e.z}`,`segment.availableZ: ${s?.availableZ.join(",")}`].join("\n"),color:this.colorMap[e.connectionName]||"#000"})}const e=new Map;for(const t of this.segmentPointMap.values())e.has(t.segmentId)||e.set(t.segmentId,[]),e.get(t.segmentId).push(t);for(const[s,n]of e.entries()){if(n.length<2)continue;const e=[...n].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y);for(let n=0;n<e.length-1;n++)t.lines.push({points:[{x:e[n].x,y:e[n].y},{x:e[n+1].x,y:e[n+1].y}],strokeColor:this.colorMap[s]||"#000"})}const s=new Set,n=Array.from(this.segmentPointMap.values());for(let e=0;e<n.length;e++){const i=n[e];for(let o=e+1;o<n.length;o++){const e=n[o];if(i.connectionName!==e.connectionName||i.segmentId===e.segmentId)continue;if(i.capacityMeshNodeIds.some(t=>e.capacityMeshNodeIds.includes(t))){const n=`${i.segmentPointId}-${e.segmentPointId}`;if(s.has(n))continue;s.add(n);const o=i.z===e.z,a=i.z;let r;r=o?0===a?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:i.x,y:i.y},{x:e.x,y:e.y}],strokeDash:r,strokeColor:this.colorMap[i.connectionName]||"#666"})}}}return t}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.dedupedSegments){const s=e.nodePortSegmentId;for(const e of this.segmentIdToNodeIds.get(s)){const s=this.nodeMap.get(e);t.has(e)||t.set(e,{capacityMeshNodeId:e,portPoints:[],center:s.center,width:s.width,height:s.height})}}for(const e of this.segmentPointMap.values())for(const s of e.capacityMeshNodeIds){const n=t.get(s);n&&n.portPoints.push({x:e.x,y:e.y,z:e.z,connectionName:e.connectionName,rootConnectionName:e.rootConnectionName})}return Array.from(t.values())}},ss=(t,e={})=>{const s=Math.min(...t.availableZ);return{center:!e.rectMargin||e.zOffset?{x:t.center.x+s*t.width*(e.zOffset??.05),y:t.center.y-s*t.width*(e.zOffset??.05)}:t.center,width:e.rectMargin?t.width-2*e.rectMargin:Math.max(t.width-.5,.8*t.width),height:e.rectMargin?t.height-2*e.rectMargin:Math.max(t.height-.5,.8*t.height),fill:t._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)"}[t.availableZ.join(",")]??"rgba(0,200,200,0.1)",layer:`z${t.availableZ.join(",")}`,label:[t.capacityMeshNodeId,`availableZ: ${t.availableZ.join(",")}`,""+(t._containsTarget?"containsTarget":""),""+(t._containsObstacle?"containsObstacle":"")].filter(Boolean).join("\n")}},ns=class extends e{connectionsWithNodes;usedNodeCapacityMap;simpleRouteJson;nodes;edges;GREEDY_MULTIPLIER=1.1;MAX_CANDIDATES_IN_MEMORY=1e5;nodeMap;nodeEdgeMap;connectionNameToGoalNodeIds;colorMap;maxDepthOfNodes;activeCandidateStraightLineDistance;debug_lastNodeCostMap;hyperParameters;constructor({simpleRouteJson:t,nodes:e,edges:n,colorMap:i,MAX_ITERATIONS:o=1e6,hyperParameters:a={}}){super(),this.MAX_ITERATIONS=o,this.simpleRouteJson=t,this.nodes=e,this.edges=n,this.colorMap=i??{};const{connectionsWithNodes:r,connectionNameToGoalNodeIds:h}=this.getConnectionsWithNodes();this.connectionsWithNodes=r,this.connectionNameToGoalNodeIds=h,this.hyperParameters=a,this.usedNodeCapacityMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,0])),this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=s(this.edges),this.maxDepthOfNodes=Math.max(...this.nodes.map(t=>t._depth??0)),this.debug_lastNodeCostMap=new Map}getTotalCapacity(t){const e=t._depth??0;return(this.maxDepthOfNodes-e+1)**2}getConnectionsWithNodes(){const t=[],e=this.nodes.filter(t=>t._containsTarget),s=new Map;for(const n of this.simpleRouteJson.connections){const i=[];for(const t of n.pointsToConnect){let s=this.nodes[0],n=Number.MAX_VALUE;for(const i of e){const e=Math.sqrt((i.center.x-t.x)**2+(i.center.y-t.y)**2);e<n&&(n=e,s=i)}i.push(s)}if(i.length<2)throw new Error(`Not enough nodes for connection "${n.name}", only ${i.length} found`);s.set(n.name,i.map(t=>t.capacityMeshNodeId)),t.push({connection:n,nodes:i,pathFound:!1,straightLineDistance:dt(i[0].center,i[i.length-1].center)})}return t.sort((t,e)=>t.straightLineDistance-e.straightLineDistance),{connectionsWithNodes:t,connectionNameToGoalNodeIds:s}}currentConnectionIndex=0;candidates;visitedNodes;computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)}getBacktrackedPath(t){const e=[];let s=t;for(;s;)e.push(s.node),s=s.prevCandidate;return e}getNeighboringNodes(t){return this.nodeEdgeMap.get(t.capacityMeshNodeId).flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t))}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const s=e.path;s&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,rootConnectionName:e.connection.rootConnectionName,nodeIds:s.map(t=>t.capacityMeshNodeId)})}return t}doesNodeHaveCapacityForTrace(t,e){const s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=this.getTotalCapacity(t);if(1===t.availableZ.length&&!t._containsTarget&&s>0)return!1;let i=0;return t.availableZ.length>1&&1===e.availableZ.length&&(i+=.5),s+i<n}canTravelThroughObstacle(t,e){const s=this.connectionNameToGoalNodeIds.get(e);return s?.includes(t.capacityMeshNodeId)??!1}getDistanceBetweenNodes(t,e){return Math.sqrt((t.center.x-e.center.x)**2+(t.center.y-e.center.y)**2)}reduceCapacityAlongPath(t){for(const e of t.path??[])this.usedNodeCapacityMap.set(e.capacityMeshNodeId,this.usedNodeCapacityMap.get(e.capacityMeshNodeId)+1)}isConnectedToEndGoal(t,e){return this.nodeEdgeMap.get(t.capacityMeshNodeId).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}_step(){const t=this.connectionsWithNodes[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const[e,s]=t.nodes;this.candidates||(this.candidates=[{prevCandidate:null,node:e,f:0,g:0,h:0}],this.debug_lastNodeCostMap=new Map,this.visitedNodes=new Set([e.capacityMeshNodeId]),this.activeCandidateStraightLineDistance=dt(e.center,s.center)),this.candidates.sort((t,e)=>t.f-e.f);const n=this.candidates.shift();if(this.candidates.length>this.MAX_CANDIDATES_IN_MEMORY&&this.candidates.splice(this.MAX_CANDIDATES_IN_MEMORY,this.candidates.length-this.MAX_CANDIDATES_IN_MEMORY),!n)return console.error(`Ran out of candidates on connection ${t.connection.name}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,void(this.failed=!0);if(this.isConnectedToEndGoal(n.node,s))return t.path=this.getBacktrackedPath({prevCandidate:n,node:s,f:0,g:0,h:0}),this.reduceCapacityAlongPath(t),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);const i=this.getNeighboringNodes(n.node);for(const t of i){if(this.visitedNodes?.has(t.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(t,n.node))continue;const e=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;if(t._containsObstacle&&!this.canTravelThroughObstacle(t,e))continue;const i=this.computeG(n,t,s),o=this.computeH(n,t,s),a=i+o*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:a,g:i,h:o});const r={prevCandidate:n,node:t,f:a,g:i,h:o};this.candidates.push(r)}this.visitedNodes.add(n.node.capacityMeshNodeId)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(this.connectionsWithNodes)for(let e=0;e<this.connectionsWithNodes.length;e++){const s=this.connectionsWithNodes[e];if(s.path&&s.path.length>0){const n=s.path.map(({center:{x:t,y:s},width:n,availableZ:i})=>({x:t+.005*n*(e%10+e%19),y:s+.005*n*(e%10+e%19),availableZ:i}));t.lines.push({points:n,strokeColor:this.colorMap[s.connection.name]});for(let e=0;e<n.length;e++){const i=n[e];t.points.push({x:i.x,y:i.y,label:[`conn: ${s.connection.name}`,`node: ${s.path[e].capacityMeshNodeId}`,`z: ${i.availableZ.join(",")}`].join("\n")})}}}for(const e of this.nodes){const s=this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,n=this.getTotalCapacity(e),i=this.debug_lastNodeCostMap.get(e.capacityMeshNodeId);t.rects.push({...ss(e,{rectMargin:.025,zOffset:.01}),label:[`${e.capacityMeshNodeId}`,`${s}/${n}`,`${e.width.toFixed(2)}x${e.height.toFixed(2)}`,`g: ${void 0!==i?.g?i.g.toFixed(2):"?"}`,`h: ${void 0!==i?.h?i.h.toFixed(2):"?"}`,`f: ${void 0!==i?.f?i.f.toFixed(2):"?"}`,`z: ${e.availableZ.join(", ")}`].join("\n"),stroke:s>n+.5?"red":void 0})}if(this.connectionsWithNodes)for(const e of this.connectionsWithNodes)if(e.connection?.pointsToConnect)for(const s of e.connection.pointsToConnect)t.points.push({x:s.x,y:s.y,label:[`pointsToConnect ${e.connection.name}`].join("\n")});let e=this.connectionsWithNodes[this.currentConnectionIndex];if(!this.candidates&&this.currentConnectionIndex>0&&!this.connectionsWithNodes[this.currentConnectionIndex-1].path&&(e=this.connectionsWithNodes[this.currentConnectionIndex-1]),e){const[s,n]=e.connection.pointsToConnect;t.lines.push({points:[{x:s.x,y:s.y},{x:n.x,y:n.y}],strokeColor:"red",strokeDash:"10 5"})}if(this.candidates){const e=this.candidates.slice(0,5),s=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;e.forEach((e,n)=>{const i=.5*(1-n/5),o=this.getBacktrackedPath(e);t.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:V(this.colorMap[s]??"red",1-i)})})}return t}},is=class extends ns{NEGATIVE_CAPACITY_PENALTY_FACTOR=1;REDUCED_CAPACITY_PENALTY_FACTOR=1;constructor(...t){super(...t),this.GREEDY_MULTIPLIER=2.5}get maxCapacityFactor(){return this.hyperParameters.MAX_CAPACITY_FACTOR??1}getTotalCapacity(t){return Pe(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){const e=t.width+t.height,s=.05,n=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0);if(n>2)return s;return(e-s)*Math.max(1,(2-n)/(e-s))+s}getDistanceBetweenNodes(t,e){const s=t.center.x-e.center.x,n=t.center.y-e.center.y;return Math.sqrt(s**2+n**2)}computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)+this.getNodeCapacityPenalty(e)}},os=class extends is{doesNodeHaveCapacityForTrace(t,e){return!0}getNodeCapacityPenalty(t){const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let s=1;return 1===t.availableZ.length&&(s=10),(.05+2*Math.abs(e))*s}};function as(t,e,s){const n=e.x-t.x,i=e.y-t.y;if(Math.abs(n)<1e-9&&Math.abs(i)<1e-9)return t;const o=s.width/2,a=s.height/2,r=s.center.x-o,h=s.center.x+o,c=s.center.y-a,d=s.center.y+a;let l=0,u=1/0;if(Math.abs(n)>1e-9){const e=(r-t.x)/n,s=(h-t.x)/n;l=Math.max(l,Math.min(e,s)),u=Math.min(u,Math.max(e,s))}else if(t.x<r||t.x>h)return t;if(Math.abs(i)>1e-9){const e=(c-t.y)/i,s=(d-t.y)/i;l=Math.max(l,Math.min(e,s)),u=Math.min(u,Math.max(e,s))}else if(t.y<c||t.y>d)return t;if(u<l||l===1/0||l<-1e9)return t;return{x:t.x+n*l,y:t.y+i*l}}function rs(t,e){const s=t.center,n=e.center,i=as(s,n,t),o=as(n,s,e),a=n.x-s.x,r=n.y-s.y,h=Math.sqrt(a*a+r*r);let c=i,d=o;if(h>1e-9){const s={x:a/h,y:r/h},n=.3*t.width,l=.3*e.width;n+l<Math.sqrt((o.x-i.x)**2+(o.y-i.y)**2)?(c={x:i.x+s.x*n,y:i.y+s.y*n},d={x:o.x-s.x*l,y:o.y-s.y*l}):(c=i,d=o)}return{lineStart:c,lineEnd:d}}var hs=(t,e,s)=>{if(t<e)return 0;if(e<1&&t<=1)return 0;if(1===s&&t>1)return 1-.01**t;const n=t/e-1;return 1-Math.exp(-2*n)},cs=(t,e,s)=>{if(s._containsTarget)return 0;if(t<=e)return 0;const n=1-hs(t,e,s.availableZ.length);return n<=0?-1e9:Math.log(n)},ds=({totalNodeCapacityMap:t,usedNodeCapacityMap:e,nodeMap:s,sectionNodeIds:n})=>{let i=0;const o=n??new Set(e.keys());for(const n of o){if(!t.has(n))continue;const o=s.get(n);if(!o)continue;const a=t.get(n),r=e.get(n)??0;i+=cs(r,a,o)}return i};function ls({sectionNodes:t,sectionEdges:e,sectionConnectionTerminals:s,completedPaths:n,nodeMap:i,colorMap:o,centerNodeId:a,title:r,nodeOpacity:h=.1,usedNodeCapacityMap:c,totalCapacityMap:d}){const l={points:[],lines:[],rects:[],circles:[],title:r},u=new Set(t.map(t=>t.capacityMeshNodeId));for(const e of t){let t=`rgba(128, 128, 128, ${h})`,s=`rgba(128, 128, 128, ${h})`;const n=e.availableZ??[],i=n.includes(0),o=n.includes(1);i&&o?(t=`rgba(128, 0, 128, ${h})`,s=`rgba(128, 0, 128, ${h})`):i?(t=`rgba(0, 0, 255, ${h})`,s=`rgba(0, 0, 255, ${h})`):o&&(t=`rgba(255, 0, 0, ${h})`,s=`rgba(255, 0, 0, ${h})`),a&&e.capacityMeshNodeId===a&&(t=`rgba(0, 255, 0, ${h})`,s=`rgba(0, 128, 0, ${h})`),l.rects.push({...ss(e),fill:t,stroke:s,label:`${e.capacityMeshNodeId}\n(Section Node)\nZ: ${n.join(",")}`});const r=l.rects.length-1;if(c&&d){const t=c.get(e.capacityMeshNodeId)??0,s=d.get(e.capacityMeshNodeId)??0,n=s>0?(t/s*100).toFixed(1):"N/A",i=hs(t,s,e.availableZ.length);l.rects[r].label+=`\n${t.toFixed(1)} / ${s.toFixed(1)}\n${n}% (Pf: ${(100*i).toFixed(1)}%)`,i>.2&&(l.rects[r].stroke=V("red",.7*(.8+h)))}}for(const t of e){const[e,s]=t.nodeIds,n=i.get(e),o=i.get(s);if(n&&o){const{lineStart:t,lineEnd:e}=rs(n,o);l.lines.push({points:[t,e],strokeColor:`rgba(0, 0, 0, ${.2*Math.min(1,h/.1)})`})}}return s.forEach((t,e)=>{const s=i.get(t.startNodeId),n=i.get(t.endNodeId),a=o[t.connectionName]??"black",r=s&&u.has(s.capacityMeshNodeId),h=n&&u.has(n.capacityMeshNodeId),c=(e+e/50)%5;let d=0,p=0,f=0,g=0;if(r&&s){const e=.02*Math.min(s.width,s.height);d=e*c,p=e*c,l.points.push({x:s.center.x+d,y:s.center.y+p,color:a,label:`Start: ${t.connectionName}\n(${t.startNodeId})`}),l.lines.push({points:[{x:s.center.x,y:s.center.y},{x:s.center.x+d,y:s.center.y+p}],strokeColor:"gray",strokeDash:"2 2"})}if(h&&n){const e=.02*Math.min(n.width,n.height);f=e*c,g=e*c,l.points.push({x:n.center.x+f,y:n.center.y+g,color:a,label:`End: ${t.connectionName}\n(${t.endNodeId})`}),l.lines.push({points:[{x:n.center.x,y:n.center.y},{x:n.center.x+f,y:n.center.y+g}],strokeColor:"gray",strokeDash:"2 2"})}r&&h&&s&&n&&l.lines.push({points:[{x:s.center.x+d,y:s.center.y+p},{x:n.center.x+f,y:n.center.y+g}],strokeColor:a,strokeDash:"5 5"})}),n&&n.forEach((t,e)=>{if(t.path&&t.path.length>0){const s=o[t.connectionName]??"gray",n={x:(e+e/50)%5*.03,y:(e+e/50)%5*.03};l.lines.push({points:t.path.map(({center:{x:t,y:e}})=>({x:t+n.x,y:e+n.y})),strokeColor:V(s,.2)})}}),l}var us=class extends e{GREEDY_MULTIPLIER=1.5;sectionNodes;sectionEdges;sectionConnectionTerminals;nodeMap;nodeEdgeMap;colorMap;usedNodeCapacityMap;totalNodeCapacityMap;centerNodeId;currentSectionScore=0;MAX_CANDIDATES_IN_MEMORY=1e4;currentConnectionIndex=0;candidates=null;visitedNodes=null;queuedNodes=null;activeCandidateStraightLineDistance;debug_lastNodeCostMap=new Map;maxCapacityFactor=1;constructor(t){super(),this.MAX_ITERATIONS=1e4,this.centerNodeId=t.centerNodeId,this.sectionNodes=t.sectionNodes,this.sectionEdges=t.sectionEdges,this.sectionConnectionTerminals=t.sectionConnectionTerminals.map(t=>({...t,path:void 0})),this.nodeMap=t.nodeMap??new Map(this.sectionNodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=t.nodeEdgeMap??s(this.sectionEdges),this.colorMap=t.colorMap??{},this.usedNodeCapacityMap=new Map(this.sectionNodes.map(t=>[t.capacityMeshNodeId,0])),this.totalNodeCapacityMap=new Map(this.sectionNodes.map(t=>[t.capacityMeshNodeId,this.getTotalCapacity(t)]));const e=new Set(this.sectionNodes.map(t=>t.capacityMeshNodeId));this.currentSectionScore=ds({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:e}),t.hyperParameters?.SHUFFLE_SEED&&(this.sectionConnectionTerminals=zt(this.sectionConnectionTerminals,t.hyperParameters?.SHUFFLE_SEED))}getTotalCapacity(t){return Pe(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){if(!this.nodeMap.has(t.capacityMeshNodeId))return 1/0;const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let s=1;return 1===t.availableZ.length&&(s=10),(.05+e**2*4)*s}getDistanceBetweenNodes(t,e){const s=t.center.x-e.center.x,n=t.center.y-e.center.y;return Math.sqrt(s**2+n**2)}computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)+this.getNodeCapacityPenalty(e)}getBacktrackedPath(t){const e=[];let s=t;for(;s;){if(e.push(s.node),!this.nodeMap.has(s.node.capacityMeshNodeId)){console.warn("Backtracked path went outside section bounds");break}s=s.prevCandidate}return e.reverse()}getNeighboringNodes(t){return this.nodeMap.has(t.capacityMeshNodeId)?this.nodeEdgeMap.get(t.capacityMeshNodeId)?.flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t)).filter(Boolean)??[]:[]}isConnectedToEndGoal(t,e){return!(!this.nodeMap.has(t.capacityMeshNodeId)||!this.nodeMap.has(e.capacityMeshNodeId))&&(this.nodeEdgeMap.get(t.capacityMeshNodeId)??[]).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}doesNodeHaveCapacityForTrace(t,e){return!0}reduceCapacityAlongPath(t){for(const e of t)if(this.usedNodeCapacityMap.has(e.capacityMeshNodeId)){const t=e.capacityMeshNodeId,s=this.nodeMap.get(t);if(!s){console.warn(`Node ${t} from path not found in section's nodeMap during score update.`);continue}const n=this.totalNodeCapacityMap.get(t),i=this.usedNodeCapacityMap.get(t)??0,o=cs(i,n,s);this.currentSectionScore-=o;const a=i+1;this.usedNodeCapacityMap.set(t,a);const r=cs(a,n,s);this.currentSectionScore+=r}}getSolvedSectionScore(){return this.currentSectionScore}_step(){const t=this.sectionConnectionTerminals[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const e=this.nodeMap.get(t.startNodeId),s=this.nodeMap.get(t.endNodeId);if(!e||!s)return console.error(`Start or end node not found in section for connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);this.candidates||this._setupAStar(e,s);const n=this.candidates;if(0===n.length)return void this._handleCandidatesExhausted(t);n.sort((t,e)=>t.f-e.f);const i=n.shift();if(n.length>this.MAX_CANDIDATES_IN_MEMORY&&n.splice(this.MAX_CANDIDATES_IN_MEMORY,n.length-this.MAX_CANDIDATES_IN_MEMORY),this.visitedNodes.add(i.node.capacityMeshNodeId),i.node.capacityMeshNodeId===s.capacityMeshNodeId)return void this._handleGoalReached(i,t,s);const o=this.getNeighboringNodes(i.node);for(const e of o){if(this.queuedNodes?.has(e.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(e,i.node))continue;if(e._containsObstacle){const s=e.capacityMeshNodeId===t.startNodeId,n=e.capacityMeshNodeId===t.endNodeId;if(!s&&!n)continue}const o=this.computeG(i,e,s),a=this.computeH(i,e,s),r=o+a*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(e.capacityMeshNodeId,{f:r,g:o,h:a});const h={prevCandidate:i,node:e,f:r,g:o,h:a};this.queuedNodes?.add(e.capacityMeshNodeId),n.push(h)}}computeProgress(){const t=this.sectionConnectionTerminals.length;if(0===t)return 1;let e=this.currentConnectionIndex/t;if(this.currentConnectionIndex<t&&this.candidates&&this.candidates.length>0&&this.activeCandidateStraightLineDistance&&this.activeCandidateStraightLineDistance>0){const s=this.candidates.reduce((t,e)=>e.f<t.f?e:t);e+=Math.max(0,Math.min(1,1-s.h/this.activeCandidateStraightLineDistance))/t}else this.solved&&(e=1);return Math.min(1,e)}_setupAStar(t,e){this.candidates=[{prevCandidate:null,node:t,f:0,g:0,h:0}],this.visitedNodes=new Set([t.capacityMeshNodeId]),this.debug_lastNodeCostMap=new Map,this.activeCandidateStraightLineDistance=dt(t.center,e.center);const s=this.computeH(null,t,e);this.candidates[0].h=s,this.candidates[0].f=s*this.GREEDY_MULTIPLIER,this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:this.candidates[0].f,g:0,h:s}),this.queuedNodes=new Set([t.capacityMeshNodeId])}_handleCandidatesExhausted(t){console.error(`Ran out of candidates for section connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}_handleGoalReached(t,e,s){const n=this.getBacktrackedPath(t);e.path=n,this.reduceCapacityAlongPath(n),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}visualize(){const t=this.sectionConnectionTerminals.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connectionName,path:t.path})),e=ls({sectionNodes:this.sectionNodes,sectionEdges:this.sectionEdges,sectionConnectionTerminals:this.sectionConnectionTerminals,completedPaths:t,nodeMap:this.nodeMap,colorMap:this.colorMap,centerNodeId:null,title:`Section Pathing: Conn ${this.currentConnectionIndex+1}/${this.sectionConnectionTerminals.length} (${this.sectionNodes.length} nodes)`,nodeOpacity:.1});for(const t of this.sectionNodes){const s=e.rects.findIndex(e=>e.label?.includes(t.capacityMeshNodeId));if(-1!==s){const n=this.debug_lastNodeCostMap.get(t.capacityMeshNodeId),i=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,o=this.getTotalCapacity(t),a=`${i.toFixed(1)}/${o.toFixed(1)}`,r=n?`f:${n.f.toFixed(1)} g:${n.g.toFixed(1)} h:${n.h.toFixed(1)}`:"cost:?";e.rects[s].label=[t.capacityMeshNodeId,`Cap: ${a}`,r,`Z: ${t.availableZ.join(",")}`].join("\n"),i>o&&(e.rects[s].stroke=V("red",.7))}}if(this.candidates&&this.candidates.length>0){const t=this.candidates.slice().sort((t,e)=>t.f-e.f).slice(0,5),s=this.sectionConnectionTerminals[this.currentConnectionIndex],n=s?.connectionName??"unknown",i=this.colorMap[n]??"purple";t.forEach((t,s)=>{const n=.8*(1-s/5),o=this.getBacktrackedPath(t);o.length>0&&e.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:V(i,1-n),strokeWidth:.05})})}return e}},ps=t=>Array.from({length:t},(t,e)=>e),fs=class extends Ft{constructorParams;constructor(t){super(),this.MAX_ITERATIONS=1e5,this.constructorParams=t}computeG(t){return-t.getSolvedSectionScore()}computeH(t){return 0}getCombinationDefs(){const t=this.constructorParams.sectionConnectionTerminals.length;return 2===t?[["orderings2_for2"]]:3===t?[["orderings6_for3"]]:4===t?[["orderings24_for4"]]:[["orderings30"]]}getFailureMessage(){return`All CapacityPathingSingleSection solvers failed for "${this.centerNodeId}"`}getHyperParameterDefs(){return[{name:"orderings2_for2",possibleValues:ps(2).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings6_for3",possibleValues:ps(6).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings24_for4",possibleValues:ps(24).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings30",possibleValues:ps(30).map(t=>({SHUFFLE_SEED:t}))}]}generateSolver(t){return new us({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}onSolve({solver:t}){this.winningSolver=t}get centerNodeId(){return this.constructorParams.centerNodeId}get sectionNodes(){return this.constructorParams.sectionNodes}get sectionConnectionTerminals(){return this.winningSolver?.sectionConnectionTerminals}};import gs from"object-hash";var ms=t=>Math.floor(10*t)/10,ys=class extends fs{cacheHit=!1;cacheProvider;hasAttemptedToUseCache=!1;sectionNodeIdSet;cachedSectionConnectionTerminals=null;sectionScore=0;constructor(t){t.nodeMap=t.nodeMap??new Map(t.sectionNodes.map(t=>[t.capacityMeshNodeId,t])),super(t),this.sectionNodeIdSet=new Set(t.sectionNodes.map(t=>t.capacityMeshNodeId)),this.cacheProvider=void 0===t.cacheProvider?st():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}_computeBfsOrderingOfNodesInSection(){const t=new Set(this.constructorParams.centerNodeId),e=[],s=[{ancestorCapacitySum:0,capacity:0,g:0,capacityMeshNodeId:this.constructorParams.centerNodeId}];for(;s.length>0;){s.sort((t,e)=>e.g-t.g);const n=s.pop();if(!n)break;e.push(n.capacityMeshNodeId);const i=this.constructorParams.nodeEdgeMap.get(n.capacityMeshNodeId).flatMap(t=>t.nodeIds).filter(e=>!t.has(e)).filter(t=>this.sectionNodeIdSet.has(t));for(const e of i){t.add(e);const i=this.constructorParams.nodeMap.get(e),o=Pe(i);s.push({ancestorCapacitySum:n.g,capacity:o,g:n.g+o,capacityMeshNodeId:e})}}return e}computeCacheKeyAndTransform(){const t=this._computeBfsOrderingOfNodesInSection(),e=new Map,s=new Map;t.forEach((t,n)=>{const i=`node${n}`;e.set(t,i),s.set(i,t)});const n={};for(const s of t){const t=e.get(s),i=this.constructorParams.nodeMap.get(s),o=Pe(i);n[t]=ms(o).toFixed(1)}const i=new Set,o=[];for(const s of t){const t=e.get(s),n=this.constructorParams.nodeEdgeMap.get(s)??[];for(const a of n){const n=a.nodeIds.find(t=>t!==s);if(this.sectionNodeIdSet.has(n)){const s=[t,e.get(n)].sort(),a=`${s[0]}-${s[1]}`;i.has(a)||(o.push(s),i.add(a))}}}o.sort((t,e)=>t[0]!==e[0]?t[0].localeCompare(e[0]):t[1].localeCompare(e[1]));const a={},r=new Map,h=new Map;for(const t of this.constructorParams.sectionConnectionTerminals){const s=e.get(t.startNodeId),n=e.get(t.endNodeId),[i,o]=[s,n].sort(),c=`${i}->${o}`,d=h.get(c)??0;h.set(c,d+1);const l=`${i}->${o}::${d}`;a[l]={start:i,end:o},r.set(l,t.connectionName)}const c=`capacitypathing:${gs({node_capacity_map:n,node_edge_map:o,terminals:a})}`,d={cacheSpaceToRealConnectionId:r,cacheSpaceToRealNodeId:s};return this.cacheKey=c,this.cacheToSolveSpaceTransform=d,{cacheKey:c,cacheToSolveSpaceTransform:d}}applyCachedSolution(t){if(!this.cacheToSolveSpaceTransform)return console.error("Cache transform not available, cannot apply cached solution."),void(this.failed=!0);if(!t.success)return this.failed=!0,void(this.cacheHit=!0);this.cachedSectionConnectionTerminals=[];const{cacheSpaceToRealNodeId:e,cacheSpaceToRealConnectionId:s}=this.cacheToSolveSpaceTransform;for(const[n,i]of Object.entries(t.solutionPaths)){const t=s.get(n);if(!t){console.warn(`Could not find real connection name for ${n}`);continue}const o=this.constructorParams.sectionConnectionTerminals.find(e=>e.connectionName===t);if(!o){console.warn(`Could not find original terminal for connection name ${t}`);continue}const a=i.map(s=>{const n=e.get(s);if(!n)throw new Error(`Could not map cache node ID ${s} to real node ID for connection ${t}`);const i=this.constructorParams.nodeMap.get(n);if(!i)throw new Error(`Could not find node with ID ${n} in nodeMap for connection ${t}`);return i});this.cachedSectionConnectionTerminals.push({...o,path:a})}this.sectionScore=t.sectionScore,this.solved=!0,this.cacheHit=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(!this.cacheKey)return void console.error("Cannot save to cache without cache key.");if(!this.cacheToSolveSpaceTransform)return void console.error("Cache transform not available, cannot save solution to cache.");let t;if(this.failed)t={success:!1};else{if(!this.solved)return;{const e={},{cacheSpaceToRealNodeId:s,cacheSpaceToRealConnectionId:n}=this.cacheToSolveSpaceTransform,i=new Map;for(const[t,e]of s)i.set(e,t);const o=new Map;for(const[t,e]of n)o.set(e,t);const a=[];if(super.sectionConnectionTerminals)for(const t of super.sectionConnectionTerminals)if(t.path&&t.path.length>0){const e=t.path.map(t=>t.capacityMeshNodeId);a.push([t.connectionName,e])}for(const[t,s]of a){const n=o.get(t);if(!n){console.warn(`Could not find cache space connection ID for ${t} when saving to cache.`);continue}const a=s.map(e=>{const s=i.get(e);if(!s)throw new Error(`Could not map real node ID ${e} to cache node ID for connection ${t} when saving to cache.`);return s});e[n]=a}t={success:!0,sectionScore:this.sectionScore,solutionPaths:e}}}try{this.cacheProvider?.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}get sectionConnectionTerminals(){return this.cacheHit&&this.solved&&this.cachedSectionConnectionTerminals?(console.log("returning the cached section connection terminals"),this.cachedSectionConnectionTerminals):super.sectionConnectionTerminals}visualize(){if(!this.cacheHit)return super.visualize();return ls({sectionNodes:this.constructorParams.sectionNodes,sectionEdges:this.constructorParams.sectionEdges,sectionConnectionTerminals:this.cachedSectionConnectionTerminals,completedPaths:this.cachedSectionConnectionTerminals.map(t=>({connectionName:t.connectionName,path:t.path})),nodeMap:this.constructorParams.nodeMap,colorMap:this.constructorParams.colorMap,title:"CachedHyperCapacityPathingSingleSectionSolver"})}},xs=class extends e{simpleRouteJson;nodes;edges;nodeEdgeMap;connectionsWithNodes=[];colorMap;initialSolver;cacheProvider;stage="initialization";nodeMap=new Map;allNodeIdsSet;usedNodeCapacityMap=new Map;totalNodeCapacityMap=new Map;nodeCapacityPercentMap=new Map;nodeOptimizationAttemptCountMap=new Map;currentSection=null;sectionSolver=null;currentScheduleIndex=0;stats;OPTIMIZATION_SCHEDULE=[{MAX_ATTEMPTS_PER_NODE:1,MAX_EXPANSION_DEGREES:3,MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE:.05},{MAX_ATTEMPTS_PER_NODE:2,MAX_EXPANSION_DEGREES:5,MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE:.2},{MAX_ATTEMPTS_PER_NODE:3,MAX_EXPANSION_DEGREES:7,MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE:.9}];get currentSchedule(){return this.OPTIMIZATION_SCHEDULE[this.currentScheduleIndex]??null}constructor(t){super(),this.stats={successfulOptimizations:0,failedOptimizations:0,failedSectionSolvers:0,startingScore:0,scheduleScores:this.OPTIMIZATION_SCHEDULE.map(({MAX_EXPANSION_DEGREES:t})=>({maxExpansionDegrees:t,endingScore:0,endingHighestNodePf:0,sectionAttempts:0})),cacheHits:0,cacheMisses:0},this.MAX_ITERATIONS=t.MAX_ITERATIONS??1e7,this.cacheProvider=t.cacheProvider,this.simpleRouteJson=t.simpleRouteJson,this.nodes=t.nodes,this.edges=t.edges,this.nodeEdgeMap=s(this.edges),this.colorMap=t.colorMap??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=s(this.edges),this.initialSolver=t.initialPathingSolver||new os({simpleRouteJson:this.simpleRouteJson,nodes:this.nodes,edges:this.edges,colorMap:this.colorMap}),this.activeSubSolver=this.initialSolver;for(const t of this.nodes){const e=this.initialSolver.getTotalCapacity(t);this.totalNodeCapacityMap.set(t.capacityMeshNodeId,e)}this.allNodeIdsSet=new Set(this.nodes.map(t=>t.capacityMeshNodeId))}_stepInitialization(){if(this.initialSolver?.step(),this.initialSolver?.failed)return this.failed=!0,void(this.error=this.initialSolver.error);if(this.initialSolver?.solved){this.usedNodeCapacityMap=new Map(this.initialSolver.usedNodeCapacityMap);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=e>0?s/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,n),this.nodeOptimizationAttemptCountMap.set(t.capacityMeshNodeId,0)}this.connectionsWithNodes=this.initialSolver.connectionsWithNodes,this.stats.startingScore=ds({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet}),this.stage="section-optimization"}}_getNextNodeToOptimize(){let t=0,e=0,s=null;for(const n of this.nodes){if(n._containsTarget)continue;const i=this.nodeOptimizationAttemptCountMap.get(n.capacityMeshNodeId),o=this.totalNodeCapacityMap.get(n.capacityMeshNodeId),a=hs(this.usedNodeCapacityMap.get(n.capacityMeshNodeId)??0,o,n.availableZ.length),r=a/(i+1);i<this.currentSchedule.MAX_ATTEMPTS_PER_NODE&&r>t&&a>this.currentSchedule.MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE&&(t=r,e=a,s=n.capacityMeshNodeId)}return s}getOverallScore(){let t=0;for(const e of this.nodes){if(e._containsTarget)continue;const s=this.totalNodeCapacityMap.get(e.capacityMeshNodeId),n=hs(this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,s,e.availableZ.length);n>t&&(t=n)}return{highestNodePf:t,score:ds({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet})}}_stepSectionOptimization(){if(!this.sectionSolver){const t=this._getNextNodeToOptimize();if(!t){const{highestNodePf:t,score:e}=this.getOverallScore();return this.stats.scheduleScores[this.currentScheduleIndex].endingHighestNodePf=t,this.stats.scheduleScores[this.currentScheduleIndex].endingScore=e,this.currentScheduleIndex++,void(this.currentSchedule||(this.solved=!0))}const e=(t=>{const{centerNodeId:e,connectionsWithNodes:s,nodeMap:n,edges:i,nodeEdgeMap:o,expansionDegrees:a}=t,r=new Set,h=[{nodeId:e,depth:0}];r.add(e);let c=0;for(;c<h.length;){const{nodeId:t,depth:e}=h[c++];if(e>=a)continue;const s=o.get(t)?.flatMap(e=>e.nodeIds.filter(e=>e!==t))??[];for(const t of s)r.has(t)||(r.add(t),h.push({nodeId:t,depth:e+1}))}const d=Array.from(r).map(t=>n.get(t)),l=i.filter(t=>{const[e,s]=t.nodeIds;return r.has(e)&&r.has(s)}),u=[];for(const t of s){if(!t.path)continue;let e=null,s=null;for(const s of t.path)if(r.has(s.capacityMeshNodeId)){e=s.capacityMeshNodeId;break}for(let e=t.path.length-1;e>=0;e--){const n=t.path[e];if(r.has(n.capacityMeshNodeId)){s=n.capacityMeshNodeId;break}}e&&s&&u.push({connectionName:t.connection.name,startNodeId:e,endNodeId:s})}return{sectionConnectionTerminals:u,sectionNodes:d,sectionEdges:l,centerNodeId:e}})({centerNodeId:t,connectionsWithNodes:this.connectionsWithNodes,nodeMap:this.nodeMap,edges:this.edges,expansionDegrees:this.currentSchedule.MAX_EXPANSION_DEGREES,nodeEdgeMap:this.nodeEdgeMap});this.stats.scheduleScores[this.currentScheduleIndex].sectionAttempts++,this.currentSection=e,this.sectionSolver=new ys({sectionNodes:this.currentSection.sectionNodes,sectionEdges:this.currentSection.sectionEdges,sectionConnectionTerminals:this.currentSection.sectionConnectionTerminals,colorMap:this.colorMap,centerNodeId:this.currentSection.centerNodeId,nodeEdgeMap:this.nodeEdgeMap,hyperParameters:{EXPANSION_DEGREES:this.currentSchedule.MAX_EXPANSION_DEGREES},cacheProvider:this.cacheProvider}),this.activeSubSolver=this.sectionSolver,this.nodeOptimizationAttemptCountMap.set(t,(this.nodeOptimizationAttemptCountMap.get(t)??0)+1)}if(this.sectionSolver.step(),(this.sectionSolver.failed||this.sectionSolver.solved)&&(this.sectionSolver.cacheHit?this.stats.cacheHits++:this.stats.cacheMisses++),this.sectionSolver.failed)return console.warn(`Section solver failed for node ${this.currentSection.centerNodeId}. Error: ${this.sectionSolver.error}`),this.stats.failedSectionSolvers++,this.stats.failedOptimizations++,this.sectionSolver=null,void(this.activeSubSolver=null);if(this.sectionSolver.solved){const t=this.sectionSolver.sectionConnectionTerminals,e=this.sectionSolver.sectionNodes,s=this.sectionSolver.centerNodeId;if(this.sectionSolver=null,this.activeSubSolver=null,!t)return void console.warn(`Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`);const n=new Set(e.map(t=>t.capacityMeshNodeId)),i=ds({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:n}),o=new Map(this.usedNodeCapacityMap),a=t;for(const t of a){const e=this.connectionsWithNodes.find(e=>e.connection.name===t.connectionName);if(e?.path)for(const t of e.path)if(n.has(t.capacityMeshNodeId)){const e=o.get(t.capacityMeshNodeId)??0;o.set(t.capacityMeshNodeId,Math.max(0,e-1))}}for(const t of a)if(t.path)for(const e of t.path)n.has(e.capacityMeshNodeId)&&o.set(e.capacityMeshNodeId,(o.get(e.capacityMeshNodeId)??0)+1);ds({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:o,nodeMap:this.nodeMap,sectionNodeIds:n})>i?(this.stats.successfulOptimizations++,this._mergeSolvedSectionPaths({centerNodeId:s,sectionConnectionTerminals:t}),this._recalculateNodeCapacityUsage()):this.stats.failedOptimizations++}}_mergeSolvedSectionPaths({centerNodeId:t,sectionConnectionTerminals:e}){for(const s of e){if(!s.path){console.warn(`No path found for connection ${s.connectionName} in section ${t}`);continue}const e=this.connectionsWithNodes.find(t=>t.connection.name===s.connectionName);if(!e||!e.path){console.warn(`Original connection or path not found for ${s.connectionName} while merging section ${t}`);continue}const n=e.path,i=s.path,o=n.findIndex(t=>t.capacityMeshNodeId===s.startNodeId),a=n.findIndex(t=>t.capacityMeshNodeId===s.endNodeId);if(-1===o||-1===a){console.warn(`Could not find start/end nodes (${s.startNodeId}/${s.endNodeId}) in original path for ${s.connectionName}`);continue}const[r,h]=o<=a?[o,a]:[a,o],c=n.slice(0,r),d=n.slice(h+1);let l=i;if(i.length>0&&n[r]&&i[0].capacityMeshNodeId!==n[r].capacityMeshNodeId){if(i[i.length-1].capacityMeshNodeId!==n[r].capacityMeshNodeId){console.warn(`New section path for ${s.connectionName} doesn't align with original path boundaries. Skipping merge for this connection.`);continue}l=[...i].reverse()}e.path=[...c,...l,...d]}}_recalculateNodeCapacityUsage(){this.usedNodeCapacityMap.clear();for(const t of this.connectionsWithNodes)if(t.path)for(const e of t.path)this.usedNodeCapacityMap.set(e.capacityMeshNodeId,(this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0)+1);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=e>0?s/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,n)}}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const s=e.path;s&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:s.map(t=>t.capacityMeshNodeId)})}return t}_step(){this.iterations>=this.MAX_ITERATIONS-1?this.solved=!0:"initialization"===this.stage?this._stepInitialization():"section-optimization"===this.stage&&this._stepSectionOptimization()}visualize(){const t=this.connectionsWithNodes.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connection.name,path:t.path}));return ls({nodeMap:this.nodeMap,sectionConnectionTerminals:this.connectionsWithNodes.map(t=>({connectionName:t.connection.name,startNodeId:t.path?.[0]?.capacityMeshNodeId,endNodeId:t.path?.[t.path.length-1]?.capacityMeshNodeId})),completedPaths:t,sectionNodes:this.nodes,sectionEdges:this.edges,colorMap:this.colorMap,totalCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeOpacity:.05,title:"Capacity Pathing Multi-Section Solver (Solved)"})}},vs=class extends e{multiLayerNodes;strawNodes;skippedNodes;unprocessedNodes;strawSize;nodeIdCounter;constructor(t){super(),this.MAX_ITERATIONS=1e5,this.strawSize=t.strawSize??.5,this.multiLayerNodes=[],this.strawNodes=[],this.skippedNodes=[],this.nodeIdCounter=0,this.unprocessedNodes=[];for(const e of t.nodes)1===e.availableZ.length?this.unprocessedNodes.push(e):this.multiLayerNodes.push(e)}getCapacityOfMultiLayerNodesWithinBounds(t){let e=0;for(const s of this.multiLayerNodes){const n=s.center.x-s.width/2,i=s.center.x+s.width/2,o=s.center.y-s.height/2,a=s.center.y+s.height/2,r=Math.max(t.minX,n),h=Math.min(t.maxX,i),c=Math.max(t.minY,o),d=Math.min(t.maxY,a);if(r<h&&c<d){const t=(h-r)*(d-c)/(s.width*s.height);e+=Pe(s)*t}}return e}getSurroundingCapacities(t){const e=Math.min(t.width,t.height);return{leftSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2-e,maxX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),rightSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x+t.width/2,maxX:t.center.x+t.width/2+e,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),topSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2-e,maxY:t.center.y-t.height/2}),bottomSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y+t.height/2,maxY:t.center.y+t.height/2+e})}}createStrawsForNode(t){const e=[],{leftSurroundingCapacity:s,rightSurroundingCapacity:n,topSurroundingCapacity:i,bottomSurroundingCapacity:o}=this.getSurroundingCapacities(t);if(1*(s+n)>i+o){const s=Math.floor(t.height/this.strawSize),n=t.height/s;for(let i=0;i<s;i++){const s=t.center.y-t.height/2+i*n+n/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:t.center.x,y:s},width:t.width,height:n,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}else{const s=Math.floor(t.width/this.strawSize),n=t.width/s;for(let i=0;i<s;i++){const s=t.center.x-t.width/2+i*n+n/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:s,y:t.center.y},width:n,height:t.height,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}return e}getResultNodes(){return[...this.multiLayerNodes,...this.strawNodes,...this.skippedNodes]}_step(){const t=this.unprocessedNodes.pop();if(!t)return void(this.solved=!0);if(t.width<this.strawSize&&t.height<this.strawSize)return void this.skippedNodes.push(t);if(t._containsTarget)return void this.skippedNodes.push(t);const e=this.createStrawsForNode(t);this.strawNodes.push(...e),0===e.length&&this.strawNodes.push(t)}visualize(){const t={rects:[],lines:[],points:[],circles:[],title:"Straw Solver"};for(const e of this.unprocessedNodes)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(200, 200, 200, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nUnprocessed\n${e.width}x${e.height}`});for(const e of this.strawNodes){const s=0===e.availableZ[0]?"rgba(0, 150, 255, 0.5)":"rgba(255, 100, 0, 0.5)";t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nLayer: ${e.availableZ[0]}\n${e.width}x${e.height}`,layer:`z${e.availableZ.join(",")}`})}for(const e of this.multiLayerNodes)t.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,fill:"rgba(100, 255, 100, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",layer:`z${e.availableZ.join(",")}`,label:`${e.capacityMeshNodeId}\nLayers: ${e.availableZ.join(",")}\n${e.width}x${e.height}`});return t}};function Ms(t,e){const s=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2,a=e.center.x-e.width/2,r=e.center.x+e.width/2,h=e.center.y-e.height/2,c=e.center.y+e.height/2,d=.001,l=(Math.abs(n-a)<d||Math.abs(s-r)<d)&&Math.min(o,c)-Math.max(i,h)>=d,u=(Math.abs(o-h)<d||Math.abs(i-c)<d)&&Math.min(n,r)-Math.max(s,a)>=d;return l||u}var Ss=class extends e{constructor(t){super(),this.nodes=t,this.edges=[]}edges;nodeMap;getNextCapacityMeshEdgeId(){return`ce${this.edges.length}`}_step(){this.edges=[];for(let t=0;t<this.nodes.length;t++)for(let e=t+1;e<this.nodes.length;e++){!(this.nodes[t]._strawNode&&this.nodes[e]._strawNode&&this.nodes[t]._strawParentCapacityMeshNodeId===this.nodes[e]._strawParentCapacityMeshNodeId)&&Ms(this.nodes[t],this.nodes[e])&&this.doNodesHaveSharedLayer(this.nodes[t],this.nodes[e])&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[this.nodes[t].capacityMeshNodeId,this.nodes[e].capacityMeshNodeId]})}this.handleTargetNodes(),this.solved=!0}handleTargetNodes(){const t=this.nodes.filter(t=>t._containsTarget);for(const e of t){if(this.edges.some(t=>t.nodeIds.includes(e.capacityMeshNodeId)))continue;let t=null,s=1/0;for(const n of this.nodes){if(n._containsObstacle)continue;if(n._containsTarget)continue;const i=dt(e.center,n.center);i<s&&(s=i,t=n)}t&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[e.capacityMeshNodeId,t.capacityMeshNodeId]})}}doNodesHaveSharedLayer(t,e){return t.availableZ.some(t=>e.availableZ.includes(t))}visualize(){const t=new Map;for(const e of this.edges)for(const s of e.nodeIds)t.set(s,1+(t.get(s)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const s=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+s*e.width*.05,y:e.center.y-s*e.width*.05},fill:e._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)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}for(const t of this.edges){const s=this.nodeMap.get(t.nodeIds[0]),n=this.nodeMap.get(t.nodeIds[1]);if(s?.center&&n?.center){const t=Math.min(...s.availableZ),i=Math.min(...n.availableZ),o={x:s.center.x+t*s.width*.05,y:s.center.y-t*s.width*.05},a={x:n.center.x+i*n.width*.05,y:n.center.y-i*n.width*.05},r=Array.from(new Set([...s.availableZ,...n.availableZ])).sort();e.lines.push({layer:`z${r.join(",")}`,points:[o,a],strokeDash:s.availableZ.join(",")===n.availableZ.join(",")?void 0:"10 5"})}}return e}},bs=class{constructor(t){this.nodes=t,this.buckets=new Map;for(const e of t){const t=e.center.x-e.width/2,s=e.center.y-e.height/2,n=e.center.x+e.width/2,i=e.center.y+e.height/2;for(let o=t;o<=n;o+=this.CELL_SIZE)for(let t=s;t<=i;t+=this.CELL_SIZE){const s=this.getBucketKey(o,t),n=this.buckets.get(s);n?n.push(e):this.buckets.set(s,[e])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,s,n){const i=[],o=new Set,a=e-n/2,r=t+s/2,h=e+n/2;for(let e=t-s/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const s=this.getBucketKey(e,t),n=this.buckets.get(s)||[];for(const t of n)o.has(t.capacityMeshNodeId)||(o.add(t.capacityMeshNodeId),i.push(t))}return i}},Ns=class extends Ss{constructor(t){super(t),this.nodes=t,this.MAX_ITERATIONS=1e7,this.nodeTree=new bs(this.nodes),this.currentNodeIndex=0,this.edgeSet=new Set}nodeTree;currentNodeIndex;edgeSet;_step(){if(this.currentNodeIndex>=this.nodes.length)return this.handleTargetNodes(),void(this.solved=!0);const t=this.nodes[this.currentNodeIndex],e=this.nodeTree.getNodesInArea(t.center.x,t.center.y,2*t.width,2*t.height);for(const s of e){if(!Ms(t,s))continue;const e=t._strawNode&&s._strawNode&&t._strawParentCapacityMeshNodeId===s._strawParentCapacityMeshNodeId;t.capacityMeshNodeId===s.capacityMeshNodeId||e||!this.doNodesHaveSharedLayer(t,s)||this.edgeSet.has(`${t.capacityMeshNodeId}-${s.capacityMeshNodeId}`)||(this.edgeSet.add(`${t.capacityMeshNodeId}-${s.capacityMeshNodeId}`),this.edgeSet.add(`${s.capacityMeshNodeId}-${t.capacityMeshNodeId}`),this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[t.capacityMeshNodeId,s.capacityMeshNodeId]}))}this.currentNodeIndex++}},Is=class extends e{removedNodeIds;targetNodeIds;leaves;leavesIndex;adjacencyList;nodeMap;nodes;edges;constructor({nodes:t,edges:e}){super(),this.MAX_ITERATIONS=t.length,this.nodes=t,this.edges=e,this.removedNodeIds=new Set,this.targetNodeIds=new Set(t.filter(t=>t._containsTarget).map(t=>t.capacityMeshNodeId)),this.adjacencyList=new Map(t.map(({capacityMeshNodeId:t})=>[t,new Set]));for(const{nodeIds:[t,s]}of e)this.adjacencyList.get(t).add(s),this.adjacencyList.get(s).add(t);this.leavesIndex=0,this.leaves=[...this.adjacencyList.entries()].filter(([t,e])=>1===e.size).filter(([t,e])=>!this.targetNodeIds.has(t)).map(([t,e])=>t)}_step(){if(this.leavesIndex===this.leaves.length)return void(this.solved=!0);const t=this.leaves[this.leavesIndex],e=this.adjacencyList.get(t);if(!e||0===e.size)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));const[s]=e,n=s?this.adjacencyList.get(s):void 0;if(!s||!n)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));n.delete(t),this.removedNodeIds.add(t),this.adjacencyList.delete(t),1!==n.size||this.targetNodeIds.has(s)||this.leaves.push(s),this.leavesIndex+=1,this.leavesIndex===this.leaves.length&&(this.solved=!0)}visualize(){if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}const t=new Map;for(const e of this.edges)for(const s of e.nodeIds)t.set(s,1+(t.get(s)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const s=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+s*e.width*.05,y:e.center.y-s*e.width*.05},fill:e._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)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};for(const t of this.edges){const s=this.nodeMap.get(t.nodeIds[0]),n=this.nodeMap.get(t.nodeIds[1]);if(s?.center&&n?.center){const i=Math.min(...s.availableZ),o=Math.min(...n.availableZ),a={x:s.center.x+i*s.width*.05,y:s.center.y-i*s.width*.05},r={x:n.center.x+o*n.width*.05,y:n.center.y-o*n.width*.05},h=Array.from(new Set([...s.availableZ,...n.availableZ])).sort();e.lines.push({layer:`z${h.join(",")}`,points:[a,r],strokeDash:s.availableZ.join(",")===n.availableZ.join(",")?void 0:"10 5",strokeColor:t.nodeIds.some(t=>this.removedNodeIds.has(t))?V("black",.9):void 0})}}return e}},Ps=class{parent={};constructor(t){for(const e of t)this.parent[e]=e}find(t){return this.parent[t]===t?t:this.parent[t]=this.find(this.parent[t])}union(t,e){const s=this.find(t),n=this.find(e);s!==n&&(this.parent[n]=s)}getGroup(t){const e=this.find(t),s=[];for(const t in this.parent)this.find(t)===e&&s.push(t);return s}},Cs=class{point;left=null;right=null;constructor(t){this.point=t}},_s=class{root=null;constructor(t){t.length>0&&(this.root=this.buildTree(t,0))}buildTree(t,e){const s=e%2==0?"x":"y";t.sort((t,e)=>t[s]-e[s]);const n=Math.floor(t.length/2),i=new Cs(t[n]);return n>0&&(i.left=this.buildTree(t.slice(0,n),e+1)),n<t.length-1&&(i.right=this.buildTree(t.slice(n+1),e+1)),i}findNearestNeighbor(t){if(!this.root)throw new Error("Tree is empty");const e=this.root.point,s=this.distance(t,e);return this.nearestNeighborSearch(this.root,t,0,e,s),e}nearestNeighborSearch(t,e,s,n,i){if(!t)return n;const o=s%2?"x":"y",a=this.distance(e,t.point);a<i&&(n=t.point,i=a);const r=e[o]-t.point[o],h=r<=0?t.left:t.right,c=r<=0?t.right:t.left;return n=this.nearestNeighborSearch(h,e,s+1,n,i),i=this.distance(e,n),Math.abs(r)<i&&(n=this.nearestNeighborSearch(c,e,s+1,n,i)),n}findKNearestNeighbors(t,e){if(!this.root)return[];const s=[];return this.kNearestNeighborSearch(this.root,t,0,s,e),s.sort((t,e)=>t.distance-e.distance).slice(0,e).map(t=>t.point)}kNearestNeighborSearch(t,e,s,n,i){if(!t)return;const o=s%2?"x":"y",a=this.distance(e,t.point);n.push({point:t.point,distance:a});const r=e[o]-t.point[o],h=r<=0?t.left:t.right,c=r<=0?t.right:t.left;this.kNearestNeighborSearch(h,e,s+1,n,i);let d=1/0;n.length>=i&&(n.sort((t,e)=>t.distance-e.distance),d=n[i-1]?.distance||1/0),(Math.abs(r)<d||n.length<i)&&this.kNearestNeighborSearch(c,e,s+1,n,i)}distance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}},Es=class{parent=new Map;rank=new Map;constructor(t){for(const e of t){const t=this.pointToKey(e);this.parent.set(t,t),this.rank.set(t,0)}}pointToKey(t){return`${t.x},${t.y}`}find(t){const e=this.pointToKey(t);if(!this.parent.has(e))throw new Error(`Point ${e} not found in DisjointSet`);let s=e;for(;s!==this.parent.get(s);)s=this.parent.get(s);let n=e;for(;n!==s;){const t=this.parent.get(n);this.parent.set(n,s),n=t}return s}union(t,e){const s=this.find(t),n=this.find(e);if(s===n)return!1;const i=this.rank.get(s)||0,o=this.rank.get(n)||0;return i<o?this.parent.set(s,n):i>o?this.parent.set(n,s):(this.parent.set(n,s),this.rank.set(s,i+1)),!0}};function Ts(t){if(t.length<=1)return[];const e=new _s(t),s=[],n=Math.min(10,t.length-1);for(const i of t){const t=e.findKNearestNeighbors(i,n+1);for(const e of t){if(i.x===e.x&&i.y===e.y)continue;const t=Math.sqrt((i.x-e.x)**2+(i.y-e.y)**2);s.push({from:i,to:e,weight:t})}}s.sort((t,e)=>t.weight-e.weight);const i=new Es(t),o=[];for(const e of s)if(i.union(e.from,e.to)&&(o.push(e),o.length===t.length-1))break;return o}function ws(t){if(t.pointId)return t.pointId;let e="";var s;return"layer"in(s=t)&&"string"==typeof s.layer?e=t.layer:Te(t)&&t.layers&&(e=t.layers.sort().join("-")),`${t.x.toFixed(4)},${t.y.toFixed(4)},${e}`}var zs=class extends e{constructor(t,e={}){super(),this.ogSrj=t,this.colorMap=e,this.unprocessedConnections=function(t){if(0===t.length)return[];const e=t.map((t,e)=>`conn_${e}`),s=new Ps(e),n=new Map;t.forEach((t,e)=>{const s=`conn_${e}`;t.pointsToConnect.forEach(t=>{const e=ws(t);n.has(e)||n.set(e,[]),n.get(e).push(s)})});for(const t of n.values())if(t.length>1){const e=t[0];for(let n=1;n<t.length;n++)s.union(e,t[n])}const i=new Map;t.forEach((t,e)=>{const n=`conn_${e}`,o=s.find(n);i.has(o)||i.set(o,[]),i.get(o).push(t)});const o=[];for(const t of i.values()){if(1===t.length){o.push(t[0]);continue}const e=new Map,s=new Set;let n=!1;const i=[],a=new Set;let r;t.forEach(t=>{t.pointsToConnect.forEach(t=>e.set(ws(t),t)),s.add(t.name),t.isOffBoard&&(n=!0),t.externallyConnectedPointIds&&i.push(...t.externallyConnectedPointIds),t.netConnectionName&&a.add(t.netConnectionName),void 0===r&&void 0!==t.nominalTraceWidth&&(r=t.nominalTraceWidth)});const h={name:Array.from(s).join("__"),mergedConnectionNames:Array.from(s),pointsToConnect:Array.from(e.values()),isOffBoard:n,externallyConnectedPointIds:i.length>0?i:void 0,netConnectionName:a.size>0?Array.from(a).join("__"):void 0,nominalTraceWidth:r};o.push(h)}return o}([...t.connections]),this.newConnections=[]}unprocessedConnections;newConnections;_step(){if(0===this.unprocessedConnections.length)return void(this.solved=!0);const t=this.unprocessedConnections.pop(),e=t.externallyConnectedPointIds??[],s=new Map;e.forEach((t,e)=>t.forEach(t=>s.set(t,e)));const n=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const n=s.get(t.pointId),i=s.get(e.pointId);return void 0!==n&&n===i};if(2===t.pointsToConnect.length){if(n(t.pointsToConnect[0],t.pointsToConnect[1]))return;return void this.newConnections.push({...t,rootConnectionName:t.name})}const i=Ts(t.pointsToConnect);let o=0;for(const e of i)n(e.from,e.to)||this.newConnections.push({pointsToConnect:[e.from,e.to],name:`${t.name}_mst${o++}`,rootConnectionName:t.name,mergedConnectionNames:t.mergedConnectionNames,netConnectionName:t.netConnectionName})}getNewSimpleRouteJson(){return{...this.ogSrj,connections:this.newConnections}}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Net To Point Pairs Visualization"};return this.unprocessedConnections.forEach(e=>{e.pointsToConnect.forEach(s=>{t.points.push({x:s.x,y:s.y,color:"red",label:e.name})});const s=e.pointsToConnect.length**2,n=Tt(0),i=new Set;for(let o=0;o<Math.max(s,2*e.pointsToConnect.length);o++){const s=Math.floor(n()*e.pointsToConnect.length),o=Math.floor(n()*e.pointsToConnect.length);i.has(`${s}-${o}`)||(i.add(`${s}-${o}`),t.lines.push({points:[e.pointsToConnect[s],e.pointsToConnect[o]],strokeColor:"rgba(255,0,0,0.25)"}))}}),this.newConnections.forEach(e=>{const s=this.colorMap?.[e.name]||"blue";e.pointsToConnect.forEach(n=>{t.points.push({x:n.x,y:n.y,color:s,label:e.name})});for(let n=0;n<e.pointsToConnect.length-1;n++)for(let i=n+1;i<e.pointsToConnect.length;i++)t.lines.push({points:[e.pointsToConnect[n],e.pointsToConnect[i]],strokeColor:s})}),t}},As=class extends zs{constructor(t,e={}){const s=t.connections.flatMap(t=>t.pointsToConnect),n=new Map;for(const t of s)t.pointId&&n.set(t.pointId,t);const i=s.map(t=>t.pointId).filter(t=>!!t),o=new Ps(i),a=[];for(const e of t.connections)e.isOffBoard?e.pointsToConnect.length>=2&&e.pointsToConnect[0].pointId&&e.pointsToConnect[1].pointId&&o.union(e.pointsToConnect[0].pointId,e.pointsToConnect[1].pointId):a.push(e);super({...t,connections:a},e),this.ogSrj=t,this.colorMap=e,this.connectionPointDsu=o,this.connectionPointMap=n,this.ogSrj=t}connectionPointDsu;connectionPointMap;_findBestConnectionPointsFromDisjointSets(t,e){if(!t.pointId||!e.pointId)return{pointsToConnect:[t,e]};const s=this.connectionPointDsu.getGroup(t.pointId).map(t=>this.connectionPointMap.get(t)),n=this.connectionPointDsu.getGroup(e.pointId).map(t=>this.connectionPointMap.get(t));let i=t,o=e,a=1/0;for(const t of s)for(const e of n){const s=Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));s<a&&(a=s,i=t,o=e)}return{pointsToConnect:[i,o]}}_step(){if(0===this.unprocessedConnections.length)return void(this.solved=!0);const t=this.unprocessedConnections.pop(),e=t.externallyConnectedPointIds??[],s=new Map;e.forEach((t,e)=>t.forEach(t=>s.set(t,e)));const n=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const n=s.get(t.pointId),i=s.get(e.pointId);return void 0!==n&&n===i};if(2===t.pointsToConnect.length){if(n(t.pointsToConnect[0],t.pointsToConnect[1]))return;const e=this._findBestConnectionPointsFromDisjointSets(t.pointsToConnect[0],t.pointsToConnect[1]);return void this.newConnections.push({...t,pointsToConnect:e.pointsToConnect,rootConnectionName:t.name})}const i=Ts(t.pointsToConnect);let o=0;for(const e of i){if(n(e.from,e.to))continue;const s=this._findBestConnectionPointsFromDisjointSets(e.from,e.to);this.newConnections.push({pointsToConnect:s.pointsToConnect,name:`${t.name}_mst${o++}`,rootConnectionName:t.name,mergedConnectionNames:t.mergedConnectionNames,netConnectionName:t.netConnectionName})}}},Rs=class{MAX_ITERATIONS=1e5;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};_setupDone=!1;setup(){this._setupDone||(this._setup(),this._setupDone=!0)}_setup(){}step(){if(this._setupDone||this.setup(),!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,console.error(this.error),this.failed=!0,t}!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`,console.error(this.error),this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}getOutput(){return null}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}},Os=1e-9,Ls=(t,e,s)=>Math.max(e,Math.min(s,t)),Ds=(t,e)=>t>e+Os,Fs=(t,e)=>t>e-Os,$s=(t,e)=>t<e-Os,ks=(t,e)=>t<e+Os;function Bs(t,e){return!(t.x+t.width<=e.x+Os||e.x+e.width<=t.x+Os||t.y+t.height<=e.y+Os||e.y+e.height<=t.y+Os)}function Xs(t,e,s){return e>=t.x-Os&&e<=t.x+t.width+Os&&s>=t.y-Os&&s<=t.y+t.height+Os}function Ys(t,e,s){const n=[[s.x,s.y,s.x+s.width,s.y],[s.x+s.width,s.y,s.x+s.width,s.y+s.height],[s.x+s.width,s.y+s.height,s.x,s.y+s.height],[s.x,s.y+s.height,s.x,s.y]];let i=1/0;for(const[s,o,a,r]of n){const n=a-s,h=r-o,c=n*n+h*h;let d=0!==c?((t-s)*n+(e-o)*h)/c:0;d=Ls(d,0,1);const l=s+d*n,u=o+d*h;i=Math.min(i,Math.hypot(t-l,e-u))}return i}function Hs(t,e,s,n){let i=e.x+e.width-t.x;for(const e of s){if(t.y+t.height>e.y+Os&&e.y+e.height>t.y+Os)if(Fs(e.x,t.x+t.width))i=Math.min(i,e.x-t.x);else if(e.x+e.width>t.x+t.width-Os&&e.x<t.x+t.width+Os)return 0}let o=Math.max(0,i-t.width);if(o<=0)return 0;if(null!=n){const e=t.width,s=t.height;e>=s&&(o=Math.min(o,n*s-e))}return Math.max(0,o)}function Vs(t,e,s,n){let i=e.y+e.height-t.y;for(const e of s){if(t.x+t.width>e.x+Os&&e.x+e.width>t.x+Os)if(Fs(e.y,t.y+t.height))i=Math.min(i,e.y-t.y);else if(e.y+e.height>t.y+t.height-Os&&e.y<t.y+t.height+Os)return 0}let o=Math.max(0,i-t.height);if(o<=0)return 0;if(null!=n){const e=t.width,s=t.height;s>=e&&(o=Math.min(o,n*e-s))}return Math.max(0,o)}function js(t,e,s,n){let i=e.x;for(const e of s){if(t.y+t.height>e.y+Os&&e.y+e.height>t.y+Os)if(ks(e.x+e.width,t.x))i=Math.max(i,e.x+e.width);else if(e.x<t.x+Os&&e.x+e.width>t.x-Os)return 0}let o=Math.max(0,t.x-i);if(o<=0)return 0;if(null!=n){const e=t.width,s=t.height;e>=s&&(o=Math.min(o,n*s-e))}return Math.max(0,o)}function Zs(t,e,s,n){let i=e.y;for(const e of s){if(t.x+t.width>e.x+Os&&e.x+e.width>t.x+Os)if(ks(e.y+e.height,t.y))i=Math.max(i,e.y+e.height);else if(e.y<t.y+Os&&e.y+e.height>t.y-Os)return 0}let o=Math.max(0,t.y-i);if(o<=0)return 0;if(null!=n){const e=t.width,s=t.height;s>=e&&(o=Math.min(o,n*e-s))}return Math.max(0,o)}function Ws(t){const{startX:e,startY:s,gridSize:n,bounds:i,blockers:o,initialCellRatio:a,maxAspectRatio:r,minReq:h}=t,c=Math.max(1e-9,n*a),d=Math.max(c,h.width),l=Math.max(c,h.height),u=[{ox:0,oy:0},{ox:-d,oy:0},{ox:0,oy:-l},{ox:-d,oy:-l},{ox:-d/2,oy:-l/2}];let p=null,f=0;t:for(const t of u){let n={x:e+t.ox,y:s+t.oy,width:d,height:l};if($s(n.x,i.x)||$s(n.y,i.y)||Ds(n.x+n.width,i.x+i.width)||Ds(n.y+n.height,i.y+i.height))continue;for(const t of o)if(Bs(n,t))continue t;let a=!0;for(;a;){a=!1;const t=Hs(n,i,o,r);t>0&&(n={...n,width:n.width+t},a=!0);const e=Vs(n,i,o,r);e>0&&(n={...n,height:n.height+e},a=!0);const s=js(n,i,o,r);s>0&&(n={x:n.x-s,y:n.y,width:n.width+s,height:n.height},a=!0);const h=Zs(n,i,o,r);h>0&&(n={x:n.x,y:n.y-h,width:n.width,height:n.height+h},a=!0)}if(n.width+Os>=h.width&&n.height+Os>=h.height){const t=n.width*n.height;t>f&&(p=n,f=t)}}return p}function Us(t,e,s,n){const i=Math.max(t,s),o=Math.min(e,n);return o>i+Os?[i,o]:null}function Gs(t,e){if(!Bs(t,e))return[t];const s=Us(t.x,t.x+t.width,e.x,e.x+e.width),n=Us(t.y,t.y+t.height,e.y,e.y+e.height);if(!s||!n)return[t];const[i,o]=s,[a,r]=n,h=[];i>t.x+Os&&h.push({x:t.x,y:t.y,width:i-t.x,height:t.height}),t.x+t.width>o+Os&&h.push({x:o,y:t.y,width:t.x+t.width-o,height:t.height});const c=Math.max(0,o-i);return c>Os&&a>t.y+Os&&h.push({x:i,y:t.y,width:c,height:a-t.y}),c>Os&&t.y+t.height>r+Os&&h.push({x:i,y:r,width:c,height:t.y+t.height-r}),h.filter(t=>t.width>Os&&t.height>Os)}function qs(t){const{x:e,y:s,layerCount:n,obstaclesByLayer:i,placedByLayer:o}=t;for(let t=0;t<n;t++){const n=i[t]??[],a=o[t]??[];if(!(n.some(t=>Xs(t,e,s))||a.some(t=>Xs(t,e,s))))return!1}return!0}function Ks(t){const{x:e,y:s,z:n,layerCount:i,minSpan:o,maxSpan:a,obstaclesByLayer:r,placedByLayer:h}=t,c=t=>![...r[t]??[],...h[t]??[]].some(t=>Xs(t,e,s));let d=n,l=n;for(;d-1>=0&&c(d-1);)d--;for(;l+1<i&&c(l+1);)l++;if("number"==typeof a){const t=Ls(a,1,i);for(;l-d+1>t;)n-d>l-n?d++:l--}const u=[];for(let t=d;t<=l;t++)u.push(t);return u.length>=o?u:[]}function Js(t){const e=Math.max(t.width,t.height);return[e/8,e/16,e/32]}function Qs(t){const{lineStart:e,lineEnd:s,coveringIntervals:n,minSegmentLength:i}=t;if(0===n.length){return[{start:e,end:s,center:(e+s)/2}]}const o=[...n].sort((t,e)=>t.start-e.start),a=[];let r={...o[0]};for(let t=1;t<o.length;t++){const e=o[t];e.start<=r.end+Os?r.end=Math.max(r.end,e.end):(a.push(r),r={...e})}a.push(r);const h=[];if(a[0].start>e+Os){const t=e,s=a[0].start;s-t>=i&&h.push({start:t,end:s,center:(t+s)/2})}for(let t=0;t<a.length-1;t++){const e=a[t].end,s=a[t+1].start;s-e>=i&&h.push({start:e,end:s,center:(e+s)/2})}if(a[a.length-1].end<s-Os){const t=a[a.length-1].end,e=s;e-t>=i&&h.push({start:t,end:e,center:(t+e)/2})}return h}function tn(t){const{bounds:e,minSize:s,layerCount:n,obstaclesByLayer:i,placedByLayer:o,hardPlacedByLayer:a}=t,r=[],h=Math.max(.15*s,3*Os),c=new Set;function d(t,s,h){if(t<e.x+Os||s<e.y+Os||t>e.x+e.width-Os||s>e.y+e.height-Os)return;if(function(t,e){return qs({x:t,y:e,layerCount:n,obstaclesByLayer:i,placedByLayer:o})}(t,s))return;const d=[...i[h]??[],...a[h]??[]],l=Math.min(Ys(t,s,e),...d.length?d.map(e=>Ys(t,s,e)):[1/0]),u=((t,e,s)=>`${s}|${t.toFixed(6)}|${e.toFixed(6)}`)(t,s,h);if(c.has(u))return;c.add(u);const p=Ks({x:t,y:s,z:h,layerCount:n,minSpan:1,maxSpan:void 0,obstaclesByLayer:i,placedByLayer:a});r.push({x:t,y:s,z:h,distance:l,zSpanLen:p.length,isEdgeSeed:!0})}for(let t=0;t<n;t++){const n=[...i[t]??[],...a[t]??[]],o=[{x:e.x+h,y:e.y+h},{x:e.x+e.width-h,y:e.y+h},{x:e.x+h,y:e.y+e.height-h},{x:e.x+e.width-h,y:e.y+e.height-h}];for(const e of o)d(e.x,e.y,t);const r=e.y+h,c=n.filter(t=>t.y<=r&&t.y+t.height>=r).map(t=>({start:Math.max(e.x,t.x),end:Math.min(e.x+e.width,t.x+t.width)})),l=Qs({lineStart:e.x+h,lineEnd:e.x+e.width-h,coveringIntervals:c,minSegmentLength:.5*s});for(const e of l){const n=e.end-e.start;n>=s&&(d(e.center,r,t),n>1.5*s&&(d(e.start+.4*s,r,t),d(e.end-.4*s,r,t)))}const u=e.y+e.height-h,p=n.filter(t=>t.y<=u&&t.y+t.height>=u).map(t=>({start:Math.max(e.x,t.x),end:Math.min(e.x+e.width,t.x+t.width)})),f=Qs({lineStart:e.x+h,lineEnd:e.x+e.width-h,coveringIntervals:p,minSegmentLength:.5*s});for(const e of f){const n=e.end-e.start;n>=s&&(d(e.center,u,t),n>1.5*s&&(d(e.start+.4*s,u,t),d(e.end-.4*s,u,t)))}const g=e.x+h,m=n.filter(t=>t.x<=g&&t.x+t.width>=g).map(t=>({start:Math.max(e.y,t.y),end:Math.min(e.y+e.height,t.y+t.height)})),y=Qs({lineStart:e.y+h,lineEnd:e.y+e.height-h,coveringIntervals:m,minSegmentLength:.5*s});for(const e of y){const n=e.end-e.start;n>=s&&(d(g,e.center,t),n>1.5*s&&(d(g,e.start+.4*s,t),d(g,e.end-.4*s,t)))}const x=e.x+e.width-h,v=n.filter(t=>t.x<=x&&t.x+t.width>=x).map(t=>({start:Math.max(e.y,t.y),end:Math.min(e.y+e.height,t.y+t.height)})),M=Qs({lineStart:e.y+h,lineEnd:e.y+e.height-h,coveringIntervals:v,minSegmentLength:.5*s});for(const e of M){const n=e.end-e.start;n>=s&&(d(x,e.center,t),n>1.5*s&&(d(x,e.start+.4*s,t),d(x,e.end-.4*s,t)))}for(const i of n){const o=i.x-h;if(o>e.x+Os&&o<e.x+e.width-Os){const e=n.filter(t=>t!==i&&t.x<=o&&t.x+t.width>=o).map(t=>({start:Math.max(i.y,t.y),end:Math.min(i.y+i.height,t.y+t.height)})),a=Qs({lineStart:i.y,lineEnd:i.y+i.height,coveringIntervals:e,minSegmentLength:.5*s});for(const e of a)d(o,e.center,t)}const a=i.x+i.width+h;if(a>e.x+Os&&a<e.x+e.width-Os){const e=n.filter(t=>t!==i&&t.x<=a&&t.x+t.width>=a).map(t=>({start:Math.max(i.y,t.y),end:Math.min(i.y+i.height,t.y+t.height)})),o=Qs({lineStart:i.y,lineEnd:i.y+i.height,coveringIntervals:e,minSegmentLength:.5*s});for(const e of o)d(a,e.center,t)}const r=i.y-h;if(r>e.y+Os&&r<e.y+e.height-Os){const e=n.filter(t=>t!==i&&t.y<=r&&t.y+t.height>=r).map(t=>({start:Math.max(i.x,t.x),end:Math.min(i.x+i.width,t.x+t.width)})),o=Qs({lineStart:i.x,lineEnd:i.x+i.width,coveringIntervals:e,minSegmentLength:.5*s});for(const e of o)d(e.center,r,t)}const c=i.y+i.height+h;if(c>e.y+Os&&c<e.y+e.height-Os){const e=n.filter(t=>t!==i&&t.y<=c&&t.y+t.height>=c).map(t=>({start:Math.max(i.x,t.x),end:Math.min(i.x+i.width,t.x+t.width)})),o=Qs({lineStart:i.x,lineEnd:i.x+i.width,coveringIntervals:e,minSegmentLength:.5*s});for(const e of o)d(e.center,c,t)}}}return r.sort((t,e)=>e.zSpanLen-t.zSpanLen||e.distance-t.distance),r}function en(t,e){let s=!1;for(let n=0,i=e.length-1;n<e.length;i=n++){const o=e[n].x,a=e[n].y,r=e[i].x,h=e[i].y;a>t.y!=h>t.y&&t.x<(r-o)*(t.y-a)/(h-a)+o&&(s=!s)}return s}function sn(t){const e=t.toLowerCase();if("top"===e)return-1e6;if("bottom"===e)return 1e6;const s=/^inner(\d+)$/i.exec(e);return s?parseInt(s[1],10)||0:100+e.charCodeAt(0)}function nn(t){const e=function(t){return Array.from(new Set(t)).sort((t,e)=>{const s=sn(t),n=sn(e);return s!==n?s-n:t.localeCompare(e)})}((t.obstacles??[]).flatMap(t=>t.layers??[])),s=Math.max(1,t.layerCount||e.length||1),n=Array.from({length:s},(t,e)=>0===e?"top":e===s-1?"bottom":`inner${e}`),i=[],o=new Set,a=t=>{const e=t.toLowerCase();o.has(e)||(o.add(e),i.push(t))};n.forEach(a),e.forEach(a);const r=i.slice(0,s),h=new Map;return r.forEach((t,e)=>h.set(t.toLowerCase(),e)),i.slice(r.length).forEach(t=>{const e=t.toLowerCase();h.set(e,(t=>{if(r.length<=1)return 0;if("top"===t)return 0;if("bottom"===t)return r.length-1;const e=/^inner(\d+)$/i.exec(t);if(e){if(r.length<=2)return r.length-1;const t=parseInt(e[1],10),s=r.length-2;return Math.min(s,Math.max(1,Number.isFinite(t)?t:1))}return 0})(e))}),{layerNames:r,zIndexByName:h}}function on(t,e){if(t.zLayers?.length)return Array.from(new Set(t.zLayers)).sort((t,e)=>t-e);const s=(t.layers??[]).map(t=>e.get(t.toLowerCase())).filter(t=>"number"==typeof t);return Array.from(new Set(s)).sort((t,e)=>t-e)}function an(t){const e=t.width,s=t.height;return"number"!=typeof e||"number"!=typeof s?null:{x:t.center.x-e/2,y:t.center.y-s/2,width:e,height:s}}function rn(t,e){const{layerNames:s,zIndexByName:n}=nn(t),i=Math.max(1,s.length,t.layerCount||1),o={x:t.bounds.minX,y:t.bounds.minY,width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},a=Array.from({length:i},()=>[]);let r=[];if(t.outline&&t.outline.length>2){r=function(t,e){if(!e||e.length<3)return[];const s=new Set([t.x,t.x+t.width]),n=new Set([t.y,t.y+t.height]);for(const t of e)s.add(t.x),n.add(t.y);const i=Array.from(s).sort((t,e)=>t-e),o=Array.from(n).sort((t,e)=>t-e),a=[];for(let s=0;s<i.length-1;s++)for(let n=0;n<o.length-1;n++){const r=i[s],h=i[s+1],c=o[n],d=o[n+1],l=(r+h)/2,u=(c+d)/2;l>=t.x&&l<=t.x+t.width&&u>=t.y&&u<=t.y+t.height&&(en({x:l,y:u},e)||a.push({x:r,y:c,width:h-r,height:d-c}))}const r=[];a.sort((t,e)=>Math.abs(t.y-e.y)>Os?t.y-e.y:t.x-e.x);let h=null;for(const t of a){if(!h){h=t;continue}const e=Math.abs(h.y-t.y)<Os,s=Math.abs(h.height-t.height)<Os,n=Math.abs(h.x+h.width-t.x)<Os;e&&s&&n?h.width+=t.width:(r.push(h),h=t)}h&&r.push(h),r.sort((t,e)=>Math.abs(t.x-e.x)>Os?t.x-e.x:t.y-e.y);const c=[];h=null;for(const t of r){if(!h){h=t;continue}const e=Math.abs(h.x-t.x)<Os,s=Math.abs(h.width-t.width)<Os,n=Math.abs(h.y+h.height-t.y)<Os;e&&s&&n?h.height+=t.height:(c.push(h),h=t)}return h&&c.push(h),c}(o,t.outline);for(const t of r)for(let e=0;e<i;e++)a[e].push(t)}for(const e of t.obstacles??[]){const t=an(e);if(!t)continue;const s=on(e,n),o=s.filter(t=>t<0||t>=i);if(o.length)throw new Error(`RectDiffSolver: obstacle uses z-layer indices ${o.join(",")} outside 0-${i-1}`);e.zLayers&&0!==e.zLayers.length||!s.length||(e.zLayers=s);for(const e of s)a[e].push(t)}const h=Math.max(.01,t.minTraceWidth||.15),c={gridSizes:Js(o),initialCellRatio:.2,maxAspectRatio:3,minSingle:{width:2*h,height:2*h},minMulti:{width:4*h,height:4*h,minLayers:Math.min(2,Math.max(1,t.layerCount||1))},preferMultiLayer:!0,maxMultiLayerSpan:void 0},d={...c,...e,gridSizes:e.gridSizes??c.gridSizes},l=Array.from({length:i},()=>[]);return{srj:t,layerNames:s,layerCount:i,bounds:o,options:d,obstaclesByLayer:a,boardVoidRects:r,phase:"GRID",gridIndex:0,candidates:[],placed:[],placedByLayer:l,expansionIndex:0,edgeAnalysisDone:!1,totalSeedsThisGrid:0,consumedSeedsThisGrid:0}}function hn(t){const e=Array.from({length:t.layerCount},()=>[]);for(const s of t.placed)if(s.zLayers.length>=t.layerCount)for(const t of s.zLayers)e[t].push(s.rect);return e}function cn(t,e){for(let s=0;s<t.layerCount;s++){const n=t.obstaclesByLayer[s]??[],i=t.placedByLayer[s]??[];if(!(n.some(t=>Xs(t,e.x,e.y))||i.some(t=>Xs(t,e.x,e.y))))return!1}return!0}function dn(t,e){const s=t.placed[e],{rect:n,zLayers:i}=s,o=t.layerCount,a=[],r=[];for(let s=0;s<t.placed.length;s++){if(s===e)continue;const h=t.placed[s];if(h.zLayers.length>=o)continue;const c=h.zLayers.filter(t=>i.includes(t));if(0===c.length)continue;if(!Bs(h.rect,n))continue;const d=Gs(h.rect,n);a.push(s);const l=h.zLayers.filter(t=>!i.includes(t));l.length>0&&r.push({rect:h.rect,zLayers:l});const u=Math.min(t.options.minSingle.width,t.options.minMulti.width),p=Math.min(t.options.minSingle.height,t.options.minMulti.height);for(const t of d)t.width+Os>=u&&t.height+Os>=p&&r.push({rect:t,zLayers:c.slice()})}a.sort((t,e)=>e-t).forEach(e=>{const s=t.placed.splice(e,1)[0];for(const e of s.zLayers){const n=t.placedByLayer[e],i=n.findIndex(t=>t===s.rect);i>=0&&n.splice(i,1)}});for(const e of r){t.placed.push(e);for(const s of e.zLayers)t.placedByLayer[s].push(e.rect)}}function ln(t){const{gridSizes:e,initialCellRatio:s,maxAspectRatio:n,minSingle:i,minMulti:o,preferMultiLayer:a,maxMultiLayerSpan:r}=t.options,h=e[t.gridIndex],c=hn(t);if(0===t.candidates.length&&0===t.consumedSeedsThisGrid&&(t.candidates=function(t){const{bounds:e,gridSize:s,layerCount:n,obstaclesByLayer:i,placedByLayer:o,hardPlacedByLayer:a}=t,r=new Map;for(let t=e.x;t<e.x+e.width;t+=s)for(let h=e.y;h<e.y+e.height;h+=s){if(Math.abs(t-e.x)<Os||Math.abs(h-e.y)<Os||t>e.x+e.width-s-Os||h>e.y+e.height-s-Os)continue;if(qs({x:t,y:h,layerCount:n,obstaclesByLayer:i,placedByLayer:o}))continue;let c=[],d=0;for(let e=0;e<n;e++){const s=Ks({x:t,y:h,z:e,layerCount:n,minSpan:1,maxSpan:void 0,obstaclesByLayer:i,placedByLayer:a});s.length>c.length&&(c=s,d=e)}const l=c.length?c[Math.floor(c.length/2)]:d,u=[...i[l]??[],...a[l]??[]],p=Math.min(Ys(t,h,e),...u.length?u.map(e=>Ys(t,h,e)):[1/0]),f=`${t.toFixed(6)}|${h.toFixed(6)}`,g={x:t,y:h,z:l,distance:p,zSpanLen:c.length},m=r.get(f);(!m||g.zSpanLen>(m.zSpanLen??0)||g.zSpanLen===m.zSpanLen&&g.distance>m.distance)&&r.set(f,g)}const h=Array.from(r.values());return h.sort((t,e)=>e.zSpanLen-t.zSpanLen||e.distance-t.distance),h}({bounds:t.bounds,gridSize:h,layerCount:t.layerCount,obstaclesByLayer:t.obstaclesByLayer,placedByLayer:t.placedByLayer,hardPlacedByLayer:c}),t.totalSeedsThisGrid=t.candidates.length,t.consumedSeedsThisGrid=0),0===t.candidates.length){if(t.gridIndex+1<e.length)return t.gridIndex+=1,t.totalSeedsThisGrid=0,void(t.consumedSeedsThisGrid=0);if(!t.edgeAnalysisDone){const e=Math.min(i.width,i.height);return t.candidates=tn({bounds:t.bounds,minSize:e,layerCount:t.layerCount,obstaclesByLayer:t.obstaclesByLayer,placedByLayer:t.placedByLayer,hardPlacedByLayer:c}),t.edgeAnalysisDone=!0,t.totalSeedsThisGrid=t.candidates.length,void(t.consumedSeedsThisGrid=0)}return t.phase="EXPANSION",void(t.expansionIndex=0)}const d=t.candidates.shift();t.consumedSeedsThisGrid+=1;const l=Ks({x:d.x,y:d.y,z:d.z,layerCount:t.layerCount,minSpan:o.minLayers,maxSpan:r,obstaclesByLayer:t.obstaclesByLayer,placedByLayer:c}),u=[];l.length>=o.minLayers&&u.push({kind:"multi",layers:l,minReq:{width:o.width,height:o.height}}),u.push({kind:"single",layers:[d.z],minReq:{width:i.width,height:i.height}});const p=a?u:u.reverse();for(const e of p){const i=[];for(const s of e.layers)t.obstaclesByLayer[s]&&i.push(...t.obstaclesByLayer[s]),c[s]&&i.push(...c[s]);const o=Ws({startX:d.x,startY:d.y,gridSize:h,bounds:t.bounds,blockers:i,initialCellRatio:s,maxAspectRatio:n,minReq:e.minReq});if(!o)continue;const a={rect:o,zLayers:[...e.layers]},r=t.placed.push(a)-1;for(const s of e.layers)t.placedByLayer[s].push(o);return dn(t,r),void(t.candidates=t.candidates.filter(e=>!cn(t,{x:e.x,y:e.y})))}}var un=class extends Rs{srj;gridOptions;state;_meshNodes=[];constructor(t){super(),this.srj=t.simpleRouteJson,this.gridOptions=t.gridOptions??{}}_setup(){this.state=rn(this.srj,this.gridOptions),this.stats={phase:this.state.phase,gridIndex:this.state.gridIndex}}_step(){if("GRID"===this.state.phase)ln(this.state);else if("EXPANSION"===this.state.phase)!function(t){if(t.expansionIndex>=t.placed.length)return void(t.phase="GAP_FILL");const e=t.expansionIndex,s=t.placed[e],n=t.options.gridSizes[t.options.gridSizes.length-1],i=hn(t),o=[];for(const e of s.zLayers)o.push(...t.obstaclesByLayer[e]??[]),o.push(...i[e]??[]);const a=s.rect,r=Ws({startX:s.rect.x+s.rect.width/2,startY:s.rect.y+s.rect.height/2,gridSize:n,bounds:t.bounds,blockers:o,initialCellRatio:0,maxAspectRatio:null,minReq:{width:s.rect.width,height:s.rect.height}});if(r){t.placed[e]={rect:r,zLayers:s.zLayers};for(const e of s.zLayers){const s=t.placedByLayer[e],n=s.findIndex(t=>t===a);n>=0&&(s[n]=r)}dn(t,e)}t.expansionIndex+=1}(this.state);else if("GAP_FILL"===this.state.phase)this.state.phase="DONE";else if("DONE"===this.state.phase){if(!this.solved){const t=function(t){const e=t.placed.map(t=>({minX:t.rect.x,minY:t.rect.y,maxX:t.rect.x+t.rect.width,maxY:t.rect.y+t.rect.height,zLayers:[...t.zLayers].sort((t,e)=>t-e)})),s=new Map;t.obstaclesByLayer.forEach((t,e)=>{for(const n of t){const t=s.get(n)??[];t.push(e),s.set(n,t)}});const n=new Set(t.boardVoidRects||[]);for(const[t,i]of s.entries())n.has(t)||e.push({minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height,zLayers:i.sort((t,e)=>t-e),isObstacle:!0});return e}(this.state);this._meshNodes=function(t){let e=0;const s=[];for(const n of t){const t=Math.max(0,n.maxX-n.minX),i=Math.max(0,n.maxY-n.minY);t<=0||i<=0||0===n.zLayers.length||s.push({capacityMeshNodeId:"cmn_"+e++,center:{x:(n.minX+n.maxX)/2,y:(n.minY+n.maxY)/2},width:t,height:i,layer:"top",availableZ:n.zLayers.slice(),_containsObstacle:n.isObstacle,_containsTarget:n.isObstacle})}return s}(t),this.solved=!0}return}this.stats.phase=this.state.phase,this.stats.gridIndex=this.state.gridIndex,this.stats.placed=this.state.placed.length}computeProgress(){return this.solved||"DONE"===this.state.phase?1:function(t){const e=t.options.gridSizes.length;if("GRID"===t.phase){const s=t.gridIndex/(e+1),n=Math.max(1,t.totalSeedsThisGrid),i=n?t.consumedSeedsThisGrid/n:1;return Math.min(.999,s+i*(1/(e+1)))}if("EXPANSION"===t.phase){const s=e/(e+1),n=Math.max(1,t.placed.length),i=n?t.expansionIndex/n:1;return Math.min(.999,s+i*(1/(e+1)))}return 1}(this.state)}getOutput(){return{meshNodes:this._meshNodes}}getCoverage(t=.05){return function({sampleResolution:t=.1},e){const{bounds:s,layerCount:n,obstaclesByLayer:i,placedByLayer:o}=e;let a=0,r=0;for(let e=0;e<n;e++){const n=[...i[e]??[],...o[e]??[]];for(let e=s.x;e<=s.x+s.width;e+=t)for(let i=s.y;i<=s.y+s.height;i+=t)a++,n.some(t=>e>=t.x&&e<=t.x+t.width&&i>=t.y&&i<=t.y+t.height)&&r++}return a>0?r/a:1}({sampleResolution:t},{bounds:this.state.bounds,layerCount:this.state.layerCount,obstaclesByLayer:this.state.obstaclesByLayer,placedByLayer:this.state.placedByLayer})}getUncoveredPoints(t=.05){return function({sampleResolution:t=.05},e){const{bounds:s,layerCount:n,obstaclesByLayer:i,placedByLayer:o}=e,a=[];for(let e=0;e<n;e++){const n=[...i[e]??[],...o[e]??[]];for(let i=s.x;i<=s.x+s.width;i+=t)for(let o=s.y;o<=s.y+s.height;o+=t)n.some(t=>i>=t.x&&i<=t.x+t.width&&o>=t.y&&o<=t.y+t.height)||a.push({x:i,y:o,z:e})}return a}({sampleResolution:t},{bounds:this.state.bounds,layerCount:this.state.layerCount,obstaclesByLayer:this.state.obstaclesByLayer,placedByLayer:this.state.placedByLayer})}getColorForZLayer(t){const e=[{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 e[Math.min(...t)%e.length]}visualize(){const t=[],e=[],s=[],n=this.srj.bounds.minX,i=this.srj.bounds.maxX,o=this.srj.bounds.minY,a=this.srj.bounds.maxY;this.srj.outline&&this.srj.outline.length>1?s.push({points:[...this.srj.outline,this.srj.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):t.push({center:{x:(n+i)/2,y:(o+a)/2},width:i-n,height:a-o,fill:"none",stroke:"#111827",label:"board"});for(const e of this.srj.obstacles??[])"rect"!==e.type&&"oval"!==e.type||t.push({center:{x:e.center.x,y:e.center.y},width:e.width,height:e.height,fill:"#fee2e2",stroke:"#ef4444",layer:"obstacle",label:"obstacle"});if(this.state?.boardVoidRects){let e=null;if(this.srj.outline&&this.srj.outline.length>0){const t=this.srj.outline.map(t=>t.x),s=this.srj.outline.map(t=>t.y),n=Math.min(...t),i=Math.min(...s);e={x:n,y:i,width:Math.max(...t)-n,height:Math.max(...s)-i}}for(const s of this.state.boardVoidRects)e&&!Bs(s,e)||t.push({center:{x:s.x+s.width/2,y:s.y+s.height/2},width:s.width,height:s.height,fill:"rgba(0, 0, 0, 0.5)",stroke:"none",label:"void"})}if(this.state?.candidates?.length)for(const t of this.state.candidates)e.push({x:t.x,y:t.y,fill:"#9333ea",stroke:"#6b21a8",label:`z:${t.z}`});if(this.state?.placed?.length)for(const e of this.state.placed){const s=this.getColorForZLayer(e.zLayers);t.push({center:{x:e.rect.x+e.rect.width/2,y:e.rect.y+e.rect.height/2},width:e.rect.width,height:e.rect.height,fill:s.fill,stroke:s.stroke,label:`free\nz:${e.zLayers.join(",")}`})}return{title:`RectDiff (${this.state?.phase??"init"})`,coordinateSystem:"cartesian",rects:t,points:e,lines:s}}};function pn(t,e,s=0,n=t.length-1,i=gn){for(;n>s;){if(n-s>600){const o=n-s+1,a=e-s+1,r=Math.log(o),h=.5*Math.exp(2*r/3),c=.5*Math.sqrt(r*h*(o-h)/o)*(a-o/2<0?-1:1);pn(t,e,Math.max(s,Math.floor(e-a*h/o+c)),Math.min(n,Math.floor(e+(o-a)*h/o+c)),i)}const o=t[e];let a=s,r=n;for(fn(t,s,e),i(t[n],o)>0&&fn(t,s,n);a<r;){for(fn(t,a,r),a++,r--;i(t[a],o)<0;)a++;for(;i(t[r],o)>0;)r--}0===i(t[s],o)?fn(t,s,r):(r++,fn(t,r,n)),r<=e&&(s=r+1),e<=r&&(n=r-1)}}function fn(t,e,s){const n=t[e];t[e]=t[s],t[s]=n}function gn(t,e){return t<e?-1:t>e?1:0}var mn=class{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(.4*this._maxEntries)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const s=[];if(!En(t,e))return s;const n=this.toBBox,i=[];for(;e;){for(let o=0;o<e.children.length;o++){const a=e.children[o],r=e.leaf?n(a):a;En(t,r)&&(e.leaf?s.push(a):_n(t,r)?this._all(a,s):i.push(a))}e=i.pop()}return s}collides(t){let e=this.data;if(!En(t,e))return!1;const s=[];for(;e;){for(let n=0;n<e.children.length;n++){const i=e.children[n],o=e.leaf?this.toBBox(i):i;if(En(t,o)){if(e.leaf||_n(t,o))return!0;s.push(i)}}e=s.pop()}return!1}load(t){if(!t||!t.length)return this;if(t.length<this._minEntries){for(let e=0;e<t.length;e++)this.insert(t[e]);return this}let e=this._build(t.slice(),0,t.length-1,0);if(this.data.children.length)if(this.data.height===e.height)this._splitRoot(this.data,e);else{if(this.data.height<e.height){const t=this.data;this.data=e,e=t}this._insert(e,this.data.height-e.height-1,!0)}else this.data=e;return this}insert(t){return t&&this._insert(t,this.data.height-1),this}clear(){return this.data=Tn([]),this}remove(t,e){if(!t)return this;let s=this.data;const n=this.toBBox(t),i=[],o=[];let a,r,h;for(;s||i.length;){if(s||(s=i.pop(),r=i[i.length-1],a=o.pop(),h=!0),s.leaf){const n=yn(t,s.children,e);if(-1!==n)return s.children.splice(n,1),i.push(s),this._condense(i),this}h||s.leaf||!_n(s,n)?r?(a++,s=r.children[a],h=!1):s=null:(i.push(s),o.push(a),a=0,r=s,s=s.children[0])}return this}toBBox(t){return t}compareMinX(t,e){return t.minX-e.minX}compareMinY(t,e){return t.minY-e.minY}toJSON(){return this.data}fromJSON(t){return this.data=t,this}_all(t,e){const s=[];for(;t;)t.leaf?e.push(...t.children):s.push(...t.children),t=s.pop();return e}_build(t,e,s,n){const i=s-e+1;let o,a=this._maxEntries;if(i<=a)return o=Tn(t.slice(e,s+1)),xn(o,this.toBBox),o;n||(n=Math.ceil(Math.log(i)/Math.log(a)),a=Math.ceil(i/Math.pow(a,n-1))),o=Tn([]),o.leaf=!1,o.height=n;const r=Math.ceil(i/a),h=r*Math.ceil(Math.sqrt(a));wn(t,e,s,h,this.compareMinX);for(let i=e;i<=s;i+=h){const e=Math.min(i+h-1,s);wn(t,i,e,r,this.compareMinY);for(let s=i;s<=e;s+=r){const i=Math.min(s+r-1,e);o.children.push(this._build(t,s,i,n-1))}}return xn(o,this.toBBox),o}_chooseSubtree(t,e,s,n){for(;n.push(e),!e.leaf&&n.length-1!==s;){let s,n=1/0,i=1/0;for(let o=0;o<e.children.length;o++){const a=e.children[o],r=Nn(a),h=Pn(t,a)-r;h<i?(i=h,n=r<n?r:n,s=a):h===i&&r<n&&(n=r,s=a)}e=s||e.children[0]}return e}_insert(t,e,s){const n=s?t:this.toBBox(t),i=[],o=this._chooseSubtree(n,this.data,e,i);for(o.children.push(t),Mn(o,n);e>=0&&i[e].children.length>this._maxEntries;)this._split(i,e),e--;this._adjustParentBBoxes(n,i,e)}_split(t,e){const s=t[e],n=s.children.length,i=this._minEntries;this._chooseSplitAxis(s,i,n);const o=this._chooseSplitIndex(s,i,n),a=Tn(s.children.splice(o,s.children.length-o));a.height=s.height,a.leaf=s.leaf,xn(s,this.toBBox),xn(a,this.toBBox),e?t[e-1].children.push(a):this._splitRoot(s,a)}_splitRoot(t,e){this.data=Tn([t,e]),this.data.height=t.height+1,this.data.leaf=!1,xn(this.data,this.toBBox)}_chooseSplitIndex(t,e,s){let n,i=1/0,o=1/0;for(let a=e;a<=s-e;a++){const e=vn(t,0,a,this.toBBox),r=vn(t,a,s,this.toBBox),h=Cn(e,r),c=Nn(e)+Nn(r);h<i?(i=h,n=a,o=c<o?c:o):h===i&&c<o&&(o=c,n=a)}return n||s-e}_chooseSplitAxis(t,e,s){const n=t.leaf?this.compareMinX:Sn,i=t.leaf?this.compareMinY:bn;this._allDistMargin(t,e,s,n)<this._allDistMargin(t,e,s,i)&&t.children.sort(n)}_allDistMargin(t,e,s,n){t.children.sort(n);const i=this.toBBox,o=vn(t,0,e,i),a=vn(t,s-e,s,i);let r=In(o)+In(a);for(let n=e;n<s-e;n++){const e=t.children[n];Mn(o,t.leaf?i(e):e),r+=In(o)}for(let n=s-e-1;n>=e;n--){const e=t.children[n];Mn(a,t.leaf?i(e):e),r+=In(a)}return r}_adjustParentBBoxes(t,e,s){for(let n=s;n>=0;n--)Mn(e[n],t)}_condense(t){for(let e,s=t.length-1;s>=0;s--)0===t[s].children.length?s>0?(e=t[s-1].children,e.splice(e.indexOf(t[s]),1)):this.clear():xn(t[s],this.toBBox)}};function yn(t,e,s){if(!s)return e.indexOf(t);for(let n=0;n<e.length;n++)if(s(t,e[n]))return n;return-1}function xn(t,e){vn(t,0,t.children.length,e,t)}function vn(t,e,s,n,i){i||(i=Tn(null)),i.minX=1/0,i.minY=1/0,i.maxX=-1/0,i.maxY=-1/0;for(let o=e;o<s;o++){const e=t.children[o];Mn(i,t.leaf?n(e):e)}return i}function Mn(t,e){return t.minX=Math.min(t.minX,e.minX),t.minY=Math.min(t.minY,e.minY),t.maxX=Math.max(t.maxX,e.maxX),t.maxY=Math.max(t.maxY,e.maxY),t}function Sn(t,e){return t.minX-e.minX}function bn(t,e){return t.minY-e.minY}function Nn(t){return(t.maxX-t.minX)*(t.maxY-t.minY)}function In(t){return t.maxX-t.minX+(t.maxY-t.minY)}function Pn(t,e){return(Math.max(e.maxX,t.maxX)-Math.min(e.minX,t.minX))*(Math.max(e.maxY,t.maxY)-Math.min(e.minY,t.minY))}function Cn(t,e){const s=Math.max(t.minX,e.minX),n=Math.max(t.minY,e.minY),i=Math.min(t.maxX,e.maxX),o=Math.min(t.maxY,e.maxY);return Math.max(0,i-s)*Math.max(0,o-n)}function _n(t,e){return t.minX<=e.minX&&t.minY<=e.minY&&e.maxX<=t.maxX&&e.maxY<=t.maxY}function En(t,e){return e.minX<=t.maxX&&e.minY<=t.maxY&&e.maxX>=t.minX&&e.maxY>=t.minY}function Tn(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function wn(t,e,s,n,i){const o=[e,s];for(;o.length;){if((s=o.pop())-(e=o.pop())<=n)continue;const a=e+Math.ceil((s-e)/n/2)*n;pn(t,a,e,s,i),o.push(e,a,a,s)}}var zn=class{tree;constructor(t=9){this.tree=new mn(t)}insert(t,e,s,n,i){this.tree.insert({minX:e,minY:s,maxX:n,maxY:i,data:t})}bulkLoad(t){const e=t.map(({item:t,minX:e,minY:s,maxX:n,maxY:i})=>({minX:e,minY:s,maxX:n,maxY:i,data:t}));this.tree.load(e)}search(t,e,s,n){return this.tree.search({minX:t,minY:e,maxX:s,maxY:n}).map(t=>t.data)}clear(){this.tree.clear()}},An=class{constructor(){this.ids=[],this.values=[],this.length=0}clear(){this.length=0}push(t,e){let s=this.length++;for(;s>0;){const t=s-1>>1,n=this.values[t];if(e>=n)break;this.ids[s]=this.ids[t],this.values[s]=n,s=t}this.ids[s]=t,this.values[s]=e}pop(){if(0===this.length)return;const t=this.ids,e=this.values,s=t[0],n=--this.length;if(n>0){const s=t[n],i=e[n];let o=0;const a=n>>1;for(;o<a;){const s=1+(o<<1),a=s+1,r=s+(+(a<n)&+(e[a]<e[s]));if(e[r]>=i)break;t[o]=t[r],e[o]=e[r],o=r}t[o]=s,e[o]=i}return s}peek(){return this.length>0?this.ids[0]:void 0}peekValue(){return this.length>0?this.values[0]:void 0}shrink(){this.ids.length=this.values.length=this.length}},Rn=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],On=class t{static from(e,s=0){if(s%8!=0)throw new Error("byteOffset must be 8-byte aligned.");if(!e||void 0===e.byteLength||e.buffer)throw new Error("Data must be an instance of ArrayBuffer or SharedArrayBuffer.");const[n,i]=new Uint8Array(e,s+0,2);if(251!==n)throw new Error("Data does not appear to be in a Flatbush format.");const o=i>>4;if(3!==o)throw new Error(`Got v${o} data when expected v3.`);const a=Rn[15&i];if(!a)throw new Error("Unrecognized array type.");const[r]=new Uint16Array(e,s+2,1),[h]=new Uint32Array(e,s+4,1);return new t(h,r,a,void 0,e,s)}constructor(t,e=16,s=Float64Array,n=ArrayBuffer,i,o=0){if(void 0===t)throw new Error("Missing required argument: numItems.");if(isNaN(t)||t<=0)throw new Error(`Unexpected numItems value: ${t}.`);this.numItems=+t,this.nodeSize=Math.min(Math.max(+e,2),65535),this.byteOffset=o;let a=t,r=a;this._levelBounds=[4*a];do{a=Math.ceil(a/this.nodeSize),r+=a,this._levelBounds.push(4*r)}while(1!==a);this.ArrayType=s,this.IndexArrayType=r<16384?Uint16Array:Uint32Array;const h=Rn.indexOf(s),c=4*r*s.BYTES_PER_ELEMENT;if(h<0)throw new Error(`Unexpected typed array class: ${s}.`);if(i)this.data=i,this._boxes=new s(i,o+8,4*r),this._indices=new this.IndexArrayType(i,o+8+c,r),this._pos=4*r,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 i=this.data=new n(8+c+r*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new s(i,8,4*r),this._indices=new this.IndexArrayType(i,8+c,r),this._pos=0,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,new Uint8Array(i,0,2).set([251,48+h]),new Uint16Array(i,2,1)[0]=e,new Uint32Array(i,4,1)[0]=t}this._queue=new An}add(t,e,s=t,n=e){const i=this._pos>>2,o=this._boxes;return this._indices[i]=i,o[this._pos++]=t,o[this._pos++]=e,o[this._pos++]=s,o[this._pos++]=n,t<this.minX&&(this.minX=t),e<this.minY&&(this.minY=e),s>this.maxX&&(this.maxX=s),n>this.maxY&&(this.maxY=n),i}finish(){if(this._pos>>2!==this.numItems)throw new Error(`Added ${this._pos>>2} items when expected ${this.numItems}.`);const t=this._boxes;if(this.numItems<=this.nodeSize)return t[this._pos++]=this.minX,t[this._pos++]=this.minY,t[this._pos++]=this.maxX,void(t[this._pos++]=this.maxY);const e=this.maxX-this.minX||1,s=this.maxY-this.minY||1,n=new Uint32Array(this.numItems);for(let i=0,o=0;i<this.numItems;i++){const a=t[o++],r=t[o++],h=t[o++],c=t[o++],d=Math.floor(65535*((a+h)/2-this.minX)/e),l=Math.floor(65535*((r+c)/2-this.minY)/s);n[i]=$n(d,l)}Dn(n,t,this._indices,0,this.numItems-1,this.nodeSize);for(let e=0,s=0;e<this._levelBounds.length-1;e++){const n=this._levelBounds[e];for(;s<n;){const e=s;let i=t[s++],o=t[s++],a=t[s++],r=t[s++];for(let e=1;e<this.nodeSize&&s<n;e++)i=Math.min(i,t[s++]),o=Math.min(o,t[s++]),a=Math.max(a,t[s++]),r=Math.max(r,t[s++]);this._indices[this._pos>>2]=e,t[this._pos++]=i,t[this._pos++]=o,t[this._pos++]=a,t[this._pos++]=r}}}search(t,e,s,n,i){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let o=this._boxes.length-4;const a=[],r=[];for(;void 0!==o;){const h=Math.min(o+4*this.nodeSize,Ln(o,this._levelBounds));for(let c=o;c<h;c+=4){const h=this._boxes[c];if(s<h)continue;const d=this._boxes[c+1];if(n<d)continue;const l=this._boxes[c+2];if(t>l)continue;const u=this._boxes[c+3];if(e>u)continue;const p=0|this._indices[c>>2];o>=4*this.numItems?a.push(p):(void 0===i||i(p,h,d,l,u))&&r.push(p)}o=a.pop()}return r}neighbors(t,e,s=1/0,n=1/0,i){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let o=this._boxes.length-4;const a=this._queue,r=[],h=n*n;t:for(;void 0!==o;){const n=Math.min(o+4*this.nodeSize,Ln(o,this._levelBounds));for(let s=o;s<n;s+=4){const n=0|this._indices[s>>2],r=this._boxes[s],c=this._boxes[s+1],d=this._boxes[s+2],l=this._boxes[s+3],u=t<r?r-t:t>d?t-d:0,p=e<c?c-e:e>l?e-l:0,f=u*u+p*p;f>h||(o>=4*this.numItems?a.push(n<<1,f):(void 0===i||i(n))&&a.push(1+(n<<1),f))}for(;a.length&&1&a.peek();){if(a.peekValue()>h)break t;if(r.push(a.pop()>>1),r.length===s)break t}o=a.length?a.pop()>>1:void 0}return a.clear(),r}};function Ln(t,e){let s=0,n=e.length-1;for(;s<n;){const i=s+n>>1;e[i]>t?n=i:s=i+1}return e[s]}function Dn(t,e,s,n,i,o){if(Math.floor(n/o)>=Math.floor(i/o))return;const a=t[n],r=t[n+i>>1],h=t[i];let c=h;const d=Math.max(a,r);h>d?c=d:d===a?c=Math.max(r,h):d===r&&(c=Math.max(a,h));let l=n-1,u=i+1;for(;;){do{l++}while(t[l]<c);do{u--}while(t[u]>c);if(l>=u)break;Fn(t,e,s,l,u)}Dn(t,e,s,n,u,o),Dn(t,e,s,u+1,i,o)}function Fn(t,e,s,n,i){const o=t[n];t[n]=t[i],t[i]=o;const a=4*n,r=4*i,h=e[a],c=e[a+1],d=e[a+2],l=e[a+3];e[a]=e[r],e[a+1]=e[r+1],e[a+2]=e[r+2],e[a+3]=e[r+3],e[r]=h,e[r+1]=c,e[r+2]=d,e[r+3]=l;const u=s[n];s[n]=s[i],s[i]=u}function $n(t,e){let s=t^e,n=65535^s,i=65535^(t|e),o=t&(65535^e),a=s|n>>1,r=s>>1^s,h=i>>1^n&o>>1^i,c=s&i>>1^o>>1^o;s=a,n=r,i=h,o=c,a=s&s>>2^n&n>>2,r=s&n>>2^n&(s^n)>>2,h^=s&i>>2^n&o>>2,c^=n&i>>2^(s^n)&o>>2,s=a,n=r,i=h,o=c,a=s&s>>4^n&n>>4,r=s&n>>4^n&(s^n)>>4,h^=s&i>>4^n&o>>4,c^=n&i>>4^(s^n)&o>>4,s=a,n=r,i=h,o=c,h^=s&i>>8^n&o>>8,c^=n&i>>8^(s^n)&o>>8,s=h^h>>1,n=c^c>>1;let d=t^e,l=n|65535^(d|s);return d=16711935&(d|d<<8),d=252645135&(d|d<<4),d=858993459&(d|d<<2),d=1431655765&(d|d<<1),l=16711935&(l|l<<8),l=252645135&(l|l<<4),l=858993459&(l|l<<2),l=1431655765&(l|l<<1),(l<<1|d)>>>0}var kn=class{index;items=[];currentIndex=0;capacity;constructor(t){this.capacity=Math.max(1,t),this.index=new On(this.capacity)}insert(t,e,s,n,i){if(this.currentIndex>=this.index.numItems)throw new Error("Exceeded initial capacity");this.items[this.currentIndex]=t,this.index.add(e,s,n,i),this.currentIndex++}finish(){this.index.finish()}search(t,e,s,n){return this.index.search(t,e,s,n).map(t=>this.items[t]||null).filter(Boolean)}clear(){this.items=[],this.currentIndex=0,this.index=new On(this.capacity)}},Bn=class{idx;storage=[];constructor(t="native",e=[]){"flatbush"===t?0===e.length?(this.idx=new zn,t="rbush"):this.idx=new kn(e.length):this.idx="rbush"===t?new zn:new class{shi=new Xn(e);insert(t){}search(t,e,s,n){const i=(t+s)/2,o=(e+n)/2,a=s-t,r=n-e;return this.shi.getNodesInArea(i,o,a,r)}clear(){}},e.forEach(t=>this.insert(t)),"flatbush"===t&&e.length>0&&this.idx.finish?.()}insert(t){this.storage.push(t),this.idx.insert(t,t.center.x-t.width/2,t.center.y-t.height/2,t.center.x+t.width/2,t.center.y+t.height/2)}search(t){return this.idx.search(t.minX,t.minY,t.maxX,t.maxY)}searchArea(t,e,s,n){return this.search({minX:t-s/2,minY:e-n/2,maxX:t+s/2,maxY:e+n/2})}},Xn=class{constructor(t){this.obstacles=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const s=t[e],n=s.center.x-s.width/2,i=s.center.y-s.height/2,o=s.center.x+s.width/2,a=s.center.y+s.height/2;for(let t=n;t<=o;t+=this.CELL_SIZE)for(let n=i;n<=a;n+=this.CELL_SIZE){const i=this.getBucketKey(t,n),o=this.buckets.get(i);o?o.push([s,e]):this.buckets.set(i,[[s,e]])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,s,n){const i=[],o=new Set,a=e-n/2,r=t+s/2,h=e+n/2;for(let e=t-s/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const s=this.getBucketKey(e,t),n=this.buckets.get(s)||[];for(const t of n)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},Yn=t=>({minX:Math.min(t[0].x,t[1].x),maxX:Math.max(t[0].x,t[1].x),minY:Math.min(t[0].y,t[1].y),maxY:Math.max(t[0].y,t[1].y)});function Hn(t,e){const s=t.x-e.x,n=t.y-e.y;return s*s+n*n}function Vn(t,e,s){const n=Hn(e,s);if(0===n)return Hn(t,e);let i=((t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y))/n;i=Math.max(0,Math.min(1,i));return Hn(t,{x:e.x+i*(s.x-e.x),y:e.y+i*(s.y-e.y)})}function jn(t,e,s,n){if(at(t,e,s,n))return 0;const i={x:t.x,y:t.y},o={x:e.x,y:e.y},a={x:s.x,y:s.y},r={x:n.x,y:n.y};return Math.min(Vn(i,a,r),Vn(o,a,r),Vn(a,i,o),Vn(r,i,o))}var Zn=class{segmentBuckets;viaBuckets;routes;CELL_SIZE;constructor(t,e=1){this.segmentBuckets=new Map,this.viaBuckets=new Map,this.routes=new Map,this.CELL_SIZE=e;for(const e of t)if(e&&e.connectionName)if(this.routes.has(e.connectionName))console.warn(`Skipping duplicate route connectionName: ${e.connectionName}`);else{if(this.routes.set(e.connectionName,e),e.route&&e.route.length>=2)for(let t=0;t<e.route.length-1;t++){const s=e.route[t],n=e.route[t+1];if(s.x===n.x&&s.y===n.y)continue;const i=[s,n],o=Yn(i),a={segmentId:`${e.connectionName}-seg-${t}`,segment:i,parentRoute:e},r=Math.floor(o.minX/this.CELL_SIZE),h=Math.floor((o.maxX+1e-9)/this.CELL_SIZE),c=Math.floor(o.minY/this.CELL_SIZE),d=Math.floor((o.maxY+1e-9)/this.CELL_SIZE);for(let t=r;t<=h;t++)for(let e=c;e<=d;e++){const s=`${t}x${e}`;let n=this.segmentBuckets.get(s);n||(n=[],this.segmentBuckets.set(s,n)),n.push(a)}}if(e.vias&&e.vias.length>0)for(let t=0;t<e.vias.length;t++){const s=e.vias[t];if(null==s)continue;const n={viaId:`${e.connectionName}-via-${t}`,x:s.x,y:s.y,parentRoute:e},i=`${Math.floor(s.x/this.CELL_SIZE)}x${Math.floor(s.y/this.CELL_SIZE)}`;let o=this.viaBuckets.get(i);o||(o=[],this.viaBuckets.set(i,o)),o.push(n)}}else console.warn("Skipping route with missing data:",e)}getConflictingRoutesForSegment(t,e,s){const n=Yn([t,e]),i=n.minX-s,o=n.minY-s,a=n.maxX+s,r=n.maxY+s,h=Math.floor(i/this.CELL_SIZE),c=Math.floor((a+1e-9)/this.CELL_SIZE),d=Math.floor(o/this.CELL_SIZE),l=Math.floor((r+1e-9)/this.CELL_SIZE),u=new Map,p=new Set,f=new Set,g={x:t.x,y:t.y},m={x:e.x,y:e.y};for(let n=h;n<=c;n++)for(let i=d;i<=l;i++){const o=`${n}x${i}`,a=this.segmentBuckets.get(o);if(a)for(const n of a){if(p.has(n.segmentId))continue;p.add(n.segmentId);const i=n.parentRoute,[o,a]=n.segment,r=s+i.traceThickness/2,h=r*r,c=jn(t,e,o,a);if(c<h){const t=i.connectionName,e=u.get(t);(!e||c<e.minDistSq)&&u.set(t,{route:i,minDistSq:c})}}const r=this.viaBuckets.get(o);if(r)for(const t of r){if(f.has(t.viaId))continue;f.add(t.viaId);const e=t.parentRoute,n={x:t.x,y:t.y},i=s+e.viaDiameter/2,o=i*i,a=Vn(n,g,m);if(a<o){const t=e.connectionName,s=u.get(t);(!s||a<s.minDistSq)&&u.set(t,{route:e,minDistSq:a})}}}const y=[];for(const t of u.values())y.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return y}getConflictingRoutesNearPoint(t,e){const s=t.x-e,n=t.y-e,i=t.x+e,o=t.y+e,a=Math.floor(s/this.CELL_SIZE),r=Math.floor((i+1e-9)/this.CELL_SIZE),h=Math.floor(n/this.CELL_SIZE),c=Math.floor((o+1e-9)/this.CELL_SIZE),d=new Map,l=new Set,u=new Set;for(let s=a;s<=r;s++)for(let n=h;n<=c;n++){const i=`${s}x${n}`,o=this.segmentBuckets.get(i);if(o)for(const s of o){if(l.has(s.segmentId))continue;l.add(s.segmentId);const n=s.parentRoute,i={x:s.segment[0].x,y:s.segment[0].y},o={x:s.segment[1].x,y:s.segment[1].y},a=e+n.traceThickness/2,r=a*a,h=Vn(t,i,o);if(h<r){const t=n.connectionName,e=d.get(t);(!e||h<e.minDistSq)&&d.set(t,{route:n,minDistSq:h})}}const a=this.viaBuckets.get(i);if(a)for(const s of a){if(u.has(s.viaId))continue;u.add(s.viaId);const n=s.parentRoute,i={x:s.x,y:s.y},o=e+n.viaDiameter/2,a=o*o,r=Hn(t,i);if(r<a){const t=n.connectionName,e=d.get(t);(!e||r<e.minDistSq)&&d.set(t,{route:n,minDistSq:r})}}}const p=[];for(const t of d.values())p.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return p}},Wn=class extends e{obstacleSHI;hdRouteSHI;unsimplifiedRoute;routeSections;currentSectionIndex;TRACE_THICKNESS=.15;OBSTACLE_MARGIN=.1;constructor(t){super(),this.currentSectionIndex=0,this.obstacleSHI=t.obstacleSHI,this.hdRouteSHI=t.hdRouteSHI,this.unsimplifiedRoute=t.unsimplifiedRoute,this.routeSections=this.breakRouteIntoSections(this.unsimplifiedRoute)}breakRouteIntoSections(t){const e=[],s=t.route;if(0===s.length)return[];let n={startIndex:0,endIndex:-1,z:s[0].z,points:[s[0]]};for(let t=1;t<s.length;t++)s[t].z===n.z?n.points.push(s[t]):(n.endIndex=t-1,e.push(n),n={startIndex:t,endIndex:-1,z:s[t].z,points:[s[t]]});return n.endIndex=s.length-1,e.push(n),e}_step(){if(this.currentSectionIndex>=this.routeSections.length)return void(this.solved=!0);if(0===this.currentSectionIndex&&this.routeSections.length>1){const t=this.routeSections[0],e=this.routeSections[1];if(t.z!==e.z){const s=e.z,n=t.points[0];if(this.canEndpointConnectOnLayer(n.x,n.y,s)&&this.canSectionMoveToLayer({currentSection:t,targetZ:s}))return t.z=s,t.points=t.points.map(t=>({...t,z:s})),void(this.currentSectionIndex=2)}return void this.currentSectionIndex++}if(this.currentSectionIndex===this.routeSections.length-1){if(this.routeSections.length>=2){const t=this.routeSections[this.routeSections.length-1],e=this.routeSections[this.routeSections.length-2];if(t.z!==e.z){const s=e.z,n=t.points[t.points.length-1];this.canEndpointConnectOnLayer(n.x,n.y,s)&&this.canSectionMoveToLayer({currentSection:t,targetZ:s})&&(t.z=s,t.points=t.points.map(t=>({...t,z:s})))}}return void(this.solved=!0)}const t=this.routeSections[this.currentSectionIndex-1],e=this.routeSections[this.currentSectionIndex],s=this.routeSections[this.currentSectionIndex+1];if(t.z!==s.z)return void this.currentSectionIndex++;const n=t.z;if(this.canSectionMoveToLayer({currentSection:e,targetZ:n}))return e.z=n,e.points=e.points.map(t=>({...t,z:n})),void(this.currentSectionIndex+=2);this.currentSectionIndex++}canEndpointConnectOnLayer(t,e,s){const n=this.obstacleSHI.searchArea(t,e,2,2).filter(s=>{if(!s.connectedTo?.includes(this.unsimplifiedRoute.connectionName))return!1;const n=s.width/2+.05,i=s.height/2+.05,o=Math.abs(t-s.center.x)<=n,a=Math.abs(e-s.center.y)<=i;return o&&a});return!(n.length>0)||n.some(t=>t.zLayers?.includes(s))}canSectionMoveToLayer({currentSection:t,targetZ:e}){for(let s=0;s<t.points.length-1;s++){const n={...t.points[s],z:e},i={...t.points[s+1],z:e},o=this.hdRouteSHI.getConflictingRoutesForSegment(n,i,this.TRACE_THICKNESS);for(const{conflictingRoute:t,distance:e}of o)if(t.connectionName!==this.unsimplifiedRoute.connectionName&&e<this.TRACE_THICKNESS+t.traceThickness)return!1;const a={centerX:(n.x+i.x)/2,centerY:(n.y+i.y)/2,width:Math.abs(n.x-i.x),height:Math.abs(n.y-i.y)},r=this.obstacleSHI.searchArea(a.centerX,a.centerY,a.width+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN),a.height+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN));for(const t of r){if(t.connectedTo?.includes(this.unsimplifiedRoute.connectionName))continue;if(t.zLayers?.includes(e)){if(Math.abs(n.x-t.center.x)<.01&&Math.abs(n.y-t.center.y)<.01||Math.abs(i.x-t.center.x)<.01&&Math.abs(i.y-t.center.y)<.01)continue}if(bt(n,i,t)<this.TRACE_THICKNESS+this.OBSTACLE_MARGIN)return!1}}return!0}getConstructorParams(){return{obstacleSHI:this.obstacleSHI,hdRouteSHI:this.hdRouteSHI,unsimplifiedRoute:this.unsimplifiedRoute}}getOptimizedHdRoute(){const t=this.routeSections.flatMap(t=>t.points),e=[];for(let s=0;s<t.length-1;s++)t[s].z!==t[s+1].z&&e.push({x:t[s].x,y:t[s].y});return{connectionName:this.unsimplifiedRoute.connectionName,route:t,traceThickness:this.unsimplifiedRoute.traceThickness,vias:e,viaDiameter:this.unsimplifiedRoute.viaDiameter}}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Single Route Useless Via Removal Solver"};for(let e=0;e<this.routeSections.length;e++){const s=this.routeSections[e];t.lines.push({points:s.points,strokeWidth:this.TRACE_THICKNESS,strokeColor:e===this.currentSectionIndex?"orange":0===s.z?"red":"blue"})}return t}},Un=class extends e{constructor(t){super(),this.input=t,this.MAX_ITERATIONS=1e6,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.optimizedHdRoutes=[],this.unprocessedRoutes=[...t.unsimplifiedHdRoutes],this.obstacleSHI=new Bn("flatbush",t.obstacles),this.hdRouteSHI=new Zn(this.unsimplifiedHdRoutes)}unsimplifiedHdRoutes;optimizedHdRoutes;unprocessedRoutes;activeSubSolver=null;obstacleSHI=null;hdRouteSHI=null;_step(){if(this.activeSubSolver)return this.activeSubSolver.step(),void(this.activeSubSolver.solved?(this.optimizedHdRoutes.push(this.activeSubSolver.getOptimizedHdRoute()),this.activeSubSolver=null):(this.activeSubSolver.failed||this.activeSubSolver.error)&&(this.error=this.activeSubSolver.error,this.failed=!0));const t=this.unprocessedRoutes.shift();t?this.activeSubSolver=new Wn({hdRouteSHI:this.hdRouteSHI,obstacleSHI:this.obstacleSHI,unsimplifiedRoute:t}):this.solved=!0}getOptimizedHdRoutes(){return this.optimizedHdRoutes}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Useless Via Removal Solver"};for(const e of this.input.obstacles){let s="rgba(128, 128, 128, 0.2)";const n=e.zLayers?.includes(0),i=e.zLayers?.includes(1);n&&i?s="rgba(128, 0, 128, 0.2)":n?s="rgba(255, 0, 0, 0.2)":i&&(s="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.optimizedHdRoutes){if(0===e.route.length)continue;this.input.colorMap[e.connectionName];for(let s=0;s<e.route.length-1;s++){const n=e.route[s],i=e.route[s+1];n.z===i.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:i.x,y:i.y}],strokeColor:0===n.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${n.z})`})}for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`})}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},Gn=class extends e{newRoute;newVias;headIndex=0;tailIndex=0;inputRoute;otherHdRoutes;obstacles;connMap;colorMap;outline;constructor(t){super(),this.inputRoute=t.inputRoute,this.otherHdRoutes=t.otherHdRoutes,this.obstacles=t.obstacles,this.connMap=t.connMap,this.colorMap=t.colorMap,this.outline=t.outline,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}}get simplifiedRoute(){return{connectionName:this.inputRoute.connectionName,traceThickness:this.inputRoute.traceThickness,viaDiameter:this.inputRoute.viaDiameter,route:this.newRoute,vias:this.newVias}}isValidPath(t){throw new Error("Not implemented")}_step(){throw new Error("Not implemented")}getVisualsForNewRouteAndObstacles(){const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Simplified Path Solver"};for(let e=0;e<this.inputRoute.route.length-1;e++)t.lines.push({points:[{x:this.inputRoute.route[e].x,y:this.inputRoute.route[e].y},{x:this.inputRoute.route[e+1].x,y:this.inputRoute.route[e+1].y}],strokeColor:"rgba(255, 0, 0, 0.8)",strokeDash:1===this.inputRoute.route[e].z?"5, 5":void 0,layer:`z${this.inputRoute.route[e].z.toString()}`});for(let e=0;e<this.newRoute.length;e++)e<this.newRoute.length-1&&t.lines.push({points:[{x:this.newRoute[e].x,y:this.newRoute[e].y},{x:this.newRoute[e+1].x,y:this.newRoute[e+1].y}],strokeWidth:.15,strokeColor:"rgba(0, 255, 0, 0.8)",strokeDash:1===this.newRoute[e].z?[.4,.4]:void 0,layer:`z${this.newRoute[e].z.toString()}`}),t.points.push({x:this.newRoute[e].x,y:this.newRoute[e].y,color:"rgba(0, 255, 0, 0.8)",label:`z: ${this.newRoute[e].z}`,layer:`z${this.newRoute[e].z.toString()}`});for(const e of this.newVias)t.circles.push({center:e,radius:this.inputRoute.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)"});for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});for(const e of this.otherHdRoutes)for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeWidth:.15,strokeColor:0===e.route[s].z?"rgba(255, 0, 255, 0.5)":1===e.route[s].z?"rgba(128, 0, 128, 0.5)":"rgba(0, 0, 255, 0.5)",layer:`z${e.route[s].z.toString()}`});if("filteredObstaclePathSegments"in this){const e=this.filteredObstaclePathSegments;for(const[s,n]of e)t.lines.push({points:[s,n]})}return t}};function qn(t,e,s,n){if(function(t,e,s,n){const i=ti(t,e,s),o=ti(t,e,n),a=ti(s,n,t),r=ti(s,n,e);return i!==o&&a!==r||(!(0!==i||!ei(t,s,e))||(!(0!==o||!ei(t,n,e))||(!(0!==a||!ei(s,t,n))||!(0!==r||!ei(s,e,n)))))}(t,e,s,n))return 0;const i=Kn(t,s,n),o=Kn(e,s,n),a=Kn(s,t,e),r=Kn(n,t,e);return Math.min(i,o,a,r)}function Kn(t,e,s){const n={x:s.x-e.x,y:s.y-e.y},i=Jn({x:t.x-e.x,y:t.y-e.y},n);if(i<=0)return Qn(t,e);const o=Jn(n,n);if(o<=i)return Qn(t,s);const a=i/o;return Qn(t,{x:e.x+a*n.x,y:e.y+a*n.y})}function Jn(t,e){return t.x*e.x+t.y*e.y}function Qn(t,e){const s=e.x-t.x,n=e.y-t.y;return Math.sqrt(s*s+n*n)}function ti(t,e,s){const n=(e.y-t.y)*(s.x-e.x)-(e.x-t.x)*(s.y-e.y);return 0===n?0:n>0?1:2}function ei(t,e,s){return e.x<=Math.max(t.x,s.x)&&e.x>=Math.min(t.x,s.x)&&e.y<=Math.max(t.y,s.y)&&e.y>=Math.min(t.y,s.y)}var si=t=>({minX:Math.min(t[0].x,t[1].x),maxX:Math.max(t[0].x,t[1].x),minY:Math.min(t[0].y,t[1].y),maxY:Math.max(t[0].y,t[1].y)}),ni=class{constructor(t){this.segments=t,this.buckets=new Map;const e=new Map;for(const s of t){const t=this.getSegmentKey(s);if(e.has(t))continue;e.set(t,s);const n=si(s),i=Math.floor(n.minX/this.CELL_SIZE),o=Math.floor(n.maxX/this.CELL_SIZE),a=Math.floor(n.minY/this.CELL_SIZE),r=Math.floor(n.maxY/this.CELL_SIZE);for(let e=i;e<=o;e++)for(let n=a;n<=r;n++){const i=`${e}x${n}`,o=this.buckets.get(i),a=[s[0],s[1],t];o?o.push(a):this.buckets.set(i,[a])}}}buckets;CELL_SIZE=.4;SEGMENT_MARGIN=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getSegmentKey(t){return`${t[0].x}-${t[0].y}-${t[0].z}-${t[1].x}-${t[1].y}-${t[1].z}`}getSegmentsThatCouldIntersect(t,e){const s=[],n=new Set,i=Math.min(t.x,e.x)-this.SEGMENT_MARGIN,o=Math.min(t.y,e.y)-this.SEGMENT_MARGIN,a=Math.max(t.x,e.x)+this.SEGMENT_MARGIN,r=Math.max(t.y,e.y)+this.SEGMENT_MARGIN,h=Math.floor(i/this.CELL_SIZE),c=Math.floor(a/this.CELL_SIZE),d=Math.floor(o/this.CELL_SIZE),l=Math.floor(r/this.CELL_SIZE);for(let t=h;t<=c;t++)for(let e=d;e<=l;e++){const i=`${t}x${e}`,o=this.buckets.get(i);if(o)for(const t of o){const e=t[2];n.has(e)||(n.add(e),s.push(t))}}return s}},ii=1e-6,oi=(t,e,s)=>ct(t,e,s)<=ii,ai=(t,e)=>Math.abs(t.x-e.x)<=ii&&Math.abs(t.y-e.y)<=ii,ri=(t,e)=>{if(!e||e.length<3)return!1;for(let s=0;s<e.length;s++){const n=e[s],i=e[(s+1)%e.length];if(oi(t,n,i))return!0}let s=!1;for(let n=0,i=e.length-1;n<e.length;i=n++){const o=e[n],a=e[i];o.y>t.y!=a.y>t.y&&t.x<(a.x-o.x)*(t.y-o.y)/(a.y-o.y)+o.x&&(s=!s)}return s},hi=class extends Gn{pathSegments=[];totalPathLength=0;headDistanceAlongPath=0;tailDistanceAlongPath=0;minStepSize=.25;lastValidPath=null;lastValidPathHeadDistance=0;STEP_SIZE_REDUCTION_FACTOR=.25;maxStepSize=4;currentStepSize=this.maxStepSize;lastHeadMoveDistance=0;cachedValidPathSegments;filteredObstacles=[];filteredObstaclePathSegments=[];filteredVias=[];segmentTree;OBSTACLE_MARGIN=.1;TRACE_THICKNESS=.15;TAIL_JUMP_RATIO=.8;constructor(t){if(super(t),this.cachedValidPathSegments=new Set,this.inputRoute.route.length<=1)return this.newRoute=[...this.inputRoute.route],void(this.solved=!0);const e=this.inputRoute.route.reduce((t,e)=>(t.minX=Math.min(t.minX,e.x),t.maxX=Math.max(t.maxX,e.x),t.minY=Math.min(t.minY,e.y),t.maxY=Math.max(t.maxY,e.y),t),{minX:1/0,maxX:-1/0,minY:1/0,maxY:-1/0}),s={center:{x:(e.minX+e.maxX)/2,y:(e.minY+e.maxY)/2},width:e.maxX-e.minX,height:e.maxY-e.minY};this.filteredObstacles=this.obstacles.filter(t=>!t.connectedTo.some(t=>this.connMap.areIdsConnected(this.inputRoute.connectionName,t))).filter(t=>{if(t.connectedTo.some(t=>this.connMap.areIdsConnected(this.inputRoute.connectionName,t)))return!1;return function(t,e){const s=it(t),n=it(e),i=Math.max(s.minX-n.maxX,n.minX-s.maxX,0),o=Math.max(s.minY-n.maxY,n.minY-s.maxY,0);return Math.hypot(i,o)}(s,t)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2}),this.filteredObstaclePathSegments=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const s=t.route,n=[];for(let t=0;t<s.length-1;t++){const i=s[t],o=s[t+1],a=Math.min(i.x,o.x),r=Math.max(i.x,o.x),h=Math.min(i.y,o.y),c=Math.max(i.y,o.y);a<=e.maxX&&r>=e.minX&&h<=e.maxY&&c>=e.minY&&n.push([i,o])}return n}),this.segmentTree=new ni(this.filteredObstaclePathSegments),this.filteredVias=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const s=t.vias,n=[];for(const i of s){const s=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2+t.viaDiameter/2,o=i.x-s,a=i.x+s,r=i.y-s,h=i.y+s;o<=e.maxX&&a>=e.minX&&r<=e.maxY&&h>=e.minY&&n.push({...i,diameter:t.viaDiameter})}return n}),this.computePathSegments()}computePathSegments(){let t=0;for(let e=0;e<this.inputRoute.route.length-1;e++){const s=this.inputRoute.route[e],n=this.inputRoute.route[e+1],i=Math.sqrt((n.x-s.x)**2+(n.y-s.y)**2)+e/1e4;this.pathSegments.push({start:s,end:n,length:i,startDistance:t,endDistance:t+i}),t+=i}this.totalPathLength=t}arePointsEqual(t,e){return t.x===e.x&&t.y===e.y&&t.z===e.z}getPointAtDistance(t){t=Math.max(0,Math.min(t,this.totalPathLength));const e=this.pathSegments.find(e=>t>=e.startDistance&&t<=e.endDistance);if(!e)return this.inputRoute.route[this.inputRoute.route.length-1];const s=(t-e.startDistance)/e.length;return{x:e.start.x+s*(e.end.x-e.start.x),y:e.start.y+s*(e.end.y-e.start.y),z:s<.5?e.start.z:e.end.z}}getNearestIndexForDistance(t){if(t<=0)return 0;if(t>=this.totalPathLength)return this.inputRoute.route.length-1;const e=this.pathSegments.findIndex(e=>t>=e.startDistance&&t<=e.endDistance);if(-1===e)return 0;const s=this.pathSegments[e],n=(s.startDistance+s.endDistance)/2;return t>n?e+1:e}isValidPathSegment(t,e){for(const s of this.filteredObstacles){if(!s.zLayers?.includes(t.z))continue;if(bt(t,e,s)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2)return!1}const s=this.segmentTree.getSegmentsThatCouldIntersect(t,e);for(const[n,i,o]of s)if(n.z===t.z&&i.z===t.z){if(qn({x:t.x,y:t.y},{x:e.x,y:e.y},{x:n.x,y:n.y},{x:i.x,y:i.y})<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS)return!1}for(const s of this.filteredVias)if(ct(s,t,e)<this.OBSTACLE_MARGIN+s.diameter/2+this.TRACE_THICKNESS/2)return!1;if(this.outline&&this.outline.length>=3){const s=(({start:t,end:e,polygon:s,margin:n=.2})=>{if(!s||s.length<3)return!1;const i=ri(t,s),o=ri(e,s);if(!i||!o)return!0;for(let i=0;i<s.length;i++){const o=s[i],a=s[(i+1)%s.length],r=oi(t,o,a),h=oi(e,o,a);if(r&&h)continue;if(!at(t,e,o,a)){if(!r&&!h&&qn(t,e,o,a)<n-ii)return!0;continue}const c=lt(t,e,o,a);if(!(c&&(r&&ai(c,t)||h&&ai(c,e))||c&&(ai(c,t)||ai(c,e))))return!0}return!1})({start:{x:t.x,y:t.y},end:{x:e.x,y:e.y},polygon:this.outline});if(s)return!1}return!0}isValidPath(t){if(t.length<2)return!0;for(let e=0;e<t.length-1;e++)if(t[e].z!==t[e+1].z)return!1;for(let e=0;e<t.length-1;e++)if(!this.isValidPathSegment(t[e],t[e+1]))return!1;return!0}find45DegreePath(t,e){if(this.arePointsEqual(t,e))return[t];if(t.z!==e.z)return null;const s=((t,e)=>{const s=[],n=Math.abs(e.x-t.x),i=Math.abs(e.y-t.y),o=e.x>t.x?1:-1,a=e.y>t.y?1:-1,r={x:e.x-o*Math.abs(e.y-t.y),y:t.y};(r.x-t.x)*o>=0&&(r.x-e.x)*o<=0&&s.push([t,r,e]);const h={x:t.x,y:e.y-a*Math.abs(e.x-t.x)};(h.y-t.y)*a>=0&&(h.y-e.y)*a<=0&&s.push([t,h,e]);const c=Math.min(n,i),d={x:t.x+o*c,y:t.y+a*c};return(d.x-t.x)*o>=0&&(d.x-e.x)*o<=0&&(d.y-t.y)*a>=0&&(d.y-e.y)*a<=0&&s.push([t,d,e]),s})({x:t.x,y:t.y},{x:e.x,y:e.y});for(const e of s){const s=e.map(e=>({x:e.x,y:e.y,z:t.z}));if(this.isValidPath(s))return s}return null}addPathToResult(t){if(0!==t.length){for(let e=0;e<t.length;e++)0===e&&this.newRoute.length>0&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t[e])||this.newRoute.push(t[e]);this.currentStepSize=this.maxStepSize}}moveHead(t){this.lastHeadMoveDistance=t,this.headDistanceAlongPath=Math.min(this.headDistanceAlongPath+t,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 t=this.tailDistanceAlongPath>=this.totalPathLength,e=this.headDistanceAlongPath>=this.totalPathLength;if(t){const t=this.inputRoute.route[this.inputRoute.route.length-1];return 0!==this.newRoute.length&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t)||this.newRoute.push(t),void(this.solved=!0)}if(e){const t=this.getPointAtDistance(this.tailDistanceAlongPath),e=this.inputRoute.route[this.inputRoute.route.length-1],s=this.find45DegreePath(t,e);if(s)return this.addPathToResult(s),void(this.solved=!0);this.lastValidPath=null,this.tailDistanceAlongPath=this.totalPathLength,this.headDistanceAlongPath=this.totalPathLength;const n=[];for(const t of this.inputRoute.route)0!==n.length&&this.arePointsEqual(n[n.length-1],t)||n.push(t);return this.newRoute=n,this.newVias=[...this.inputRoute.vias],void(this.solved=!0)}this.moveHead(this.currentStepSize);const s=this.getPointAtDistance(this.tailDistanceAlongPath),n=this.getPointAtDistance(this.headDistanceAlongPath),i=this.getNearestIndexForDistance(this.tailDistanceAlongPath),o=this.getNearestIndexForDistance(this.headDistanceAlongPath);let a=!1,r=-1;for(let t=i;t<o;t++)if(t+1<this.inputRoute.route.length&&this.inputRoute.route[t].z!==this.inputRoute.route[t+1].z){a=!0;const e=t;r=this.pathSegments[e].startDistance;break}if(a&&this.lastHeadMoveDistance>this.minStepSize)return void this.stepBackAndReduceStepSize();if(a&&r>0){const t=this.getNearestIndexForDistance(r)+1,e=this.inputRoute.route[t],s={x:e.x,y:e.y};this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null);const n=this.newRoute[this.newRoute.length-1];n.x===s.x&&n.y===s.y||this.newRoute.push({x:s.x,y:s.y,z:n.z}),this.newVias.push(s),this.newRoute.push({x:s.x,y:s.y,z:e.z}),this.currentStepSize=this.maxStepSize;const i=this.pathSegments.findIndex(t=>t.start===e);if(-1!==i)this.tailDistanceAlongPath=this.pathSegments[i].startDistance,this.headDistanceAlongPath=this.tailDistanceAlongPath,this.lastValidPath=null,this.lastValidPathHeadDistance=this.tailDistanceAlongPath;else if(t<this.inputRoute.route.length){if(t===this.inputRoute.route.length-1)return void(this.solved=!0);console.warn("Fallback used for tailDistanceAlongPath after layer change");const e=this.pathSegments.find(e=>e.start===this.inputRoute.route[t]);e?(this.tailDistanceAlongPath=e.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.\n Index sought: ${t}, Point: (${this.inputRoute.route[t].x.toFixed(3)}, ${this.inputRoute.route[t].y.toFixed(3)}, z=${this.inputRoute.route[t].z})\n Route Length: ${this.inputRoute.route.length}, Path Segments: ${this.pathSegments.length}`),this.solved=!0)}else console.warn("Layer change occurred at the end of the path."),this.solved=!0;return}const h=this.find45DegreePath(s,n);if(!h&&this.lastHeadMoveDistance>this.minStepSize)this.stepBackAndReduceStepSize();else{if(!h&&!this.lastValidPath){const t=this.getPointAtDistance(this.tailDistanceAlongPath);this.tailDistanceAlongPath+=this.minStepSize,this.moveHead(this.minStepSize);const e=this.getNearestIndexForDistance(this.tailDistanceAlongPath),s=this.inputRoute.route[e],n=this.inputRoute.route[this.inputRoute.route.length-1];return void(this.arePointsEqual(t,s)||this.arePointsEqual(s,n)||this.newRoute.push(s))}if(h)return this.lastValidPath=h,void(this.lastValidPathHeadDistance=this.headDistanceAlongPath);this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null,this.tailDistanceAlongPath=this.lastValidPathHeadDistance,this.moveHead(this.minStepSize))}}visualize(){const t=this.getVisualsForNewRouteAndObstacles(),e=this.getPointAtDistance(this.tailDistanceAlongPath),s=this.getPointAtDistance(this.headDistanceAlongPath);t.points.push({x:e.x,y:e.y,color:"yellow",label:["Tail",`z: ${e.z}`].join("\n")}),t.points.push({x:s.x,y:s.y,color:"orange",label:["Head",`z: ${s.z}`].join("\n")});const n=this.getPointAtDistance(this.headDistanceAlongPath+this.currentStepSize);t.points.push({x:n.x,y:n.y,color:"red",label:["Tentative Head",`z: ${n.z}`].join("\n")});let i=0;for(;i<this.totalPathLength;){const e=this.getPointAtDistance(i);t.circles.push({center:{x:e.x,y:e.y},radius:.05,fill:"rgba(100, 100, 100, 0.5)"}),i+=this.totalPathLength/20}if(this.lastValidPath&&this.lastValidPath.length>1)for(let e=0;e<this.lastValidPath.length-1;e++)t.lines.push({points:[{x:this.lastValidPath[e].x,y:this.lastValidPath[e].y},{x:this.lastValidPath[e+1].x,y:this.lastValidPath[e+1].y}],strokeColor:"rgba(0, 255, 255, 0.9)",strokeDash:"3, 3"});return t}},ci=class extends e{simplifiedHdRoutes;currentUnsimplifiedHdRouteIndex=0;activeSubSolver=null;unsimplifiedHdRoutes;obstacles;connMap;colorMap;outline;defaultViaDiameter;constructor(t){super(),this.MAX_ITERATIONS=1e8,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.obstacles=t.obstacles,this.connMap=t.connMap||new Ne({}),this.colorMap=t.colorMap||{},this.outline=t.outline,this.defaultViaDiameter=t.defaultViaDiameter??.6,this.simplifiedHdRoutes=[]}_step(){const t=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];if(!this.activeSubSolver)return t?(this.activeSubSolver=new hi({inputRoute:t,otherHdRoutes:this.unsimplifiedHdRoutes.slice(this.currentUnsimplifiedHdRouteIndex+1).concat(this.simplifiedHdRoutes),obstacles:this.obstacles,connMap:this.connMap,colorMap:this.colorMap,outline:this.outline}),void this.currentUnsimplifiedHdRouteIndex++):void(this.solved=!0);this.activeSubSolver.step(),this.activeSubSolver.solved&&(this.simplifiedHdRoutes.push(this.activeSubSolver.simplifiedRoute),this.activeSubSolver=null)}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Multi Simplified Path Solver"};for(const e of this.unsimplifiedHdRoutes)if(!this.simplifiedHdRoutes.some(t=>t.connectionName===e.connectionName)){for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeColor:1===e.route[s].z?"rgba(0, 0, 255, 0.4)":"rgba(255, 0, 0, 0.4)",strokeWidth:.15,strokeDash:1===e.route[s].z?[.5,.5]:void 0});for(const s of e.vias||[])t.circles.push({center:s,radius:(e.viaDiameter??this.defaultViaDiameter)/2,fill:"rgba(0, 0, 255, 0.4)"})}for(const e of this.simplifiedHdRoutes){const s=this.colorMap?.[e.connectionName]||"rgba(128, 128, 128, 0.8)";for(let n=0;n<e.route.length-1;n++)t.lines.push({points:[{x:e.route[n].x,y:e.route[n].y},{x:e.route[n+1].x,y:e.route[n+1].y}],strokeWidth:.15,strokeColor:s,strokeDash:1===e.route[n].z?[.5,.5]:void 0,step:1});for(const s of e.vias||[])t.circles.push({center:s,radius:e.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)",step:1})}for(const e of this.unsimplifiedHdRoutes){for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeWidth:.15,strokeColor:"rgba(255, 0, 0, 0.2)",strokeDash:[.5,.5],step:0,layer:`z${e.route[s].z.toString()}`});for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 0, 0.2)",step:0})}for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});if(this.currentUnsimplifiedHdRouteIndex<this.unsimplifiedHdRoutes.length){const e=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];e.route.length>0&&t.circles.push({center:{x:e.route[0].x,y:e.route[0].y},radius:.2,fill:"yellow",label:"Current"})}return t}},di=class extends e{constructor(t){super(),this.input=t,this.MAX_ITERATIONS=1e6,this.inputHdRoutes=t.inputHdRoutes,this.mergedViaHdRoutes=structuredClone(this.inputHdRoutes),this.unprocessedRoutes=[...t.inputHdRoutes],this.colorMap=t.colorMap,this.outline=t.outline,this.obstacles=t.obstacles,this.obstacleSHI=new Bn("flatbush",t.obstacles),this.hdRouteSHI=new Zn(this.inputHdRoutes),this.vias=[],this.offendingVias=[],this.connMap=t.connMap,this.viasByNet=new Map,this.rebuildVias()}inputHdRoutes;mergedViaHdRoutes;unprocessedRoutes;vias;offendingVias;currentViaRoutes=[];connMap;colorMap;outline;obstacles;viasByNet;obstacleSHI=null;hdRouteSHI=null;rebuildVias(){this.vias=[],this.viasByNet=new Map;for(let t=0;t<this.mergedViaHdRoutes.length;t++){const e=this.mergedViaHdRoutes[t];for(let s=0;s<e.vias.length;s++){const n=e.vias[s],i={x:n.x,y:n.y,diameter:e.viaDiameter,net:this.connMap?.idToNetMap[e.connectionName]??"",layers:[...new Set(e.route.map(t=>t.z))],routeIndex:t};this.vias.push(i);const o=this.viasByNet.get(i.net);o?o.push(i):this.viasByNet.set(i.net,[i])}}}findNextOffendingPair(){for(let t=0;t<this.vias.length-1;t++){const e=this.vias[t],s=this.viasByNet.get(e.net);if(!s)continue;const n=s.indexOf(e);for(let t=n>=0?n+1:0;t<s.length;t++){const n=s[t],i=e.x-n.x,o=e.y-n.y,a=i*i+o*o,r=e.diameter/2+n.diameter/2;if(a<=r*r&&0!==a)return[e,n]}}return null}handleOffendingPair(t,e){const s=t.layers.length<e.layers.length?t:e,n=s===t?e:t,i=this.mergedViaHdRoutes[s.routeIndex].route;for(let t=0;t<s.layers.length;t++)for(let t=i.length-1;t>=1;t--){const e=i[t-1],o=i[t];if(o.x===s.x&&o.y===s.y){i.splice(t,0,{x:n.x,y:n.y,z:o.z}),i.splice(t,0,{x:n.x,y:n.y,z:e.z});const a=this.mergedViaHdRoutes[s.routeIndex];return a.vias=a.vias.map(t=>t.x===s.x&&t.y===s.y?{x:n.x,y:n.y}:t),void this.rebuildVias()}}this.rebuildVias()}_step(){const t=this.findNextOffendingPair();t?this.handleOffendingPair(t[0],t[1]):this.solved=!0}getMergedViaHdRoutes(){return this.mergedViaHdRoutes}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Same Net Via Merger Solver"};for(const e of this.input.obstacles){let s="rgba(128, 128, 128, 0.2)";const n=e.zLayers?.includes(0),i=e.zLayers?.includes(1);n&&i?s="rgba(128, 0, 128, 0.2)":n?s="rgba(255, 0, 0, 0.2)":i&&(s="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.mergedViaHdRoutes){if(0===e.route.length)continue;this.input.colorMap[e.connectionName];for(let s=0;s<e.route.length-1;s++){const n=e.route[s],i=e.route[s+1];n.z===i.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:i.x,y:i.y}],strokeColor:0===n.z?"rgba(255, 0, 0, 0.5)":"rgba(0, 0, 255, 0.5)",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${n.z})`})}for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`})}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},li=class extends e{constructor(t){super(),this.simplificationConfig=t,this.hdRoutes=[...t.hdRoutes],this.MAX_ITERATIONS=1e8}hdRoutes=[];simplificationPipelineLoops=0;MAX_SIMPLIFICATION_PIPELINE_LOOPS=2;PHASE_ORDER=["via_removal","via_merging","path_simplification"];currentPhase="via_removal";extractResult=null;get simplifiedHdRoutes(){return this.hdRoutes}_step(){if(this.simplificationPipelineLoops>=this.MAX_SIMPLIFICATION_PIPELINE_LOOPS)this.solved=!0;else{if(this.activeSubSolver){if(this.activeSubSolver.step(),!this.activeSubSolver.failed&&!this.activeSubSolver.solved)return;if(this.activeSubSolver.solved){if(this.extractResult&&(this.hdRoutes=this.extractResult(this.activeSubSolver)),this.activeSubSolver=null,this.extractResult=null,"via_removal"===this.currentPhase?this.currentPhase="via_merging":"via_merging"===this.currentPhase?this.currentPhase="path_simplification":(this.currentPhase="via_removal",this.simplificationPipelineLoops++),this.simplificationPipelineLoops>=this.MAX_SIMPLIFICATION_PIPELINE_LOOPS)return void(this.solved=!0)}else if(this.activeSubSolver.failed)return this.failed=!0,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 Un({unsimplifiedHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,colorMap:this.simplificationConfig.colorMap,layerCount:this.simplificationConfig.layerCount}),this.extractResult=t=>t.getOptimizedHdRoutes()??[];break;case"via_merging":this.activeSubSolver=new di({inputHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,colorMap:this.simplificationConfig.colorMap,layerCount:this.simplificationConfig.layerCount,connMap:this.simplificationConfig.connMap,outline:this.simplificationConfig.outline}),this.extractResult=t=>t.getMergedViaHdRoutes()??[];break;case"path_simplification":this.activeSubSolver=new ci({unsimplifiedHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,connMap:this.simplificationConfig.connMap,colorMap:this.simplificationConfig.colorMap,outline:this.simplificationConfig.outline,defaultViaDiameter:this.simplificationConfig.defaultViaDiameter}),this.extractResult=t=>t.simplifiedHdRoutes;break;default:this.failed=!0,this.error=`Unknown phase: ${this.currentPhase}`}}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Trace Simplification Solver"};for(const e of this.simplificationConfig.obstacles){let s="rgba(128, 128, 128, 0.2)";const n=e.zLayers?.includes(0),i=e.zLayers?.includes(1);n&&i?s="rgba(128, 0, 128, 0.2)":n?s="rgba(255, 0, 0, 0.2)":i&&(s="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.hdRoutes)if(0!==e.route.length){for(let s=0;s<e.route.length-1;s++){const n=e.route[s],i=e.route[s+1];n.z===i.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:i.x,y:i.y}],strokeColor:0===n.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${n.z})`})}for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`})}return t}};function ui(t,e,s,n={}){return{solverName:t,solverClass:e,getConstructorParams:s,onSolved:n.onSolved}}var pi=class extends e{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth,void 0===e.capacityDepth){const s=t.bounds.maxX-t.bounds.minX,n=t.bounds.maxY-t.bounds.minY,i=Math.max(s,n),o=e.targetMinCapacity??.5;e.capacityDepth=Ce(i,o)}this.connMap=Ie(t),this.colorMap=H(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?st():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;initialPathingSolver;pathingOptimizer;edgeToPortSegmentSolver;colorMap;segmentToPointSolver;unravelMultiSectionSolver;segmentToPointOptimizer;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;viaDiameter;minTraceWidth;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[ui("netToPointPairsSolver",As,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=H(t.srjWithPointPairs,this.connMap),t.connMap=Ie(t.srjWithPointPairs)}}),ui("nodeSolver",un,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),ui("strawSolver",vs,t=>[{nodes:t.capacityNodes}],{onSolved:t=>{t.capacityNodes=t.strawSolver?.getResultNodes()}}),ui("edgeSolver",Ns,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),ui("deadEndSolver",Is,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges}],{onSolved:t=>{const e=t.deadEndSolver?.removedNodeIds;t.capacityNodes=t.capacityNodes.filter(t=>!e.has(t.capacityMeshNodeId)),t.capacityEdges=t.capacityEdges.filter(t=>t.nodeIds.every(t=>!e.has(t)))}}),ui("initialPathingSolver",os,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),ui("pathingOptimizer",xs,t=>[{initialPathingSolver:t.initialPathingSolver,simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,cacheProvider:t.cacheProvider,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),ui("edgeToPortSegmentSolver",j,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.pathingOptimizer?.getCapacityPaths()||[],colorMap:t.colorMap}]),ui("segmentToPointSolver",q,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),ui("unravelMultiSectionSolver",es,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),ui("highDensityRouteSolver",be,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),ui("highDensityStitchSolver",De,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),ui("traceSimplificationSolver",li,t=>[{hdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline,defaultViaDiameter:t.viaDiameter,layerCount:t.srj.layerCount,iterations:2}])];currentPipelineStepIndex=0;_step(){const t=this.pipelineDef[this.currentPipelineStepIndex];if(!t)return void(this.solved=!0);if(this.activeSubSolver)return this.activeSubSolver.step(),void(this.activeSubSolver.solved?(this.endTimeOfPhase[t.solverName]=performance.now(),this.timeSpentOnPhase[t.solverName]=this.endTimeOfPhase[t.solverName]-this.startTimeOfPhase[t.solverName],t.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStepIndex++):this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null));const e=t.getConstructorParams(this);this.activeSubSolver=new t.solverClass(...e),this[t.solverName]=this.activeSubSolver,this.timeSpentOnPhase[t.solverName]=0,this.startTimeOfPhase[t.solverName]=performance.now()}solveUntilPhase(t){for(;this.getCurrentPhase()!==t;)this.step()}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();const e=this.netToPointPairsSolver?.visualize(),s=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),i=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),a=this.edgeSolver?.visualize(),r=this.deadEndSolver?.visualize(),h=this.initialPathingSolver?.visualize(),c=this.pathingOptimizer?.visualize(),d=this.edgeToPortSegmentSolver?.visualize(),l=this.segmentToPointSolver?.visualize(),u=this.unravelMultiSectionSolver?.visualize()??this.segmentToPointOptimizer?.visualize(),p=this.highDensityRouteSolver?.visualize(),f=this.highDensityStitchSolver?.visualize(),g=this.traceSimplificationSolver?.visualize(),m=this.srj.outline,y=[];if(y.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),m&&m.length>=2){const t=m.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),y.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const x={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:t.layers?.join(", ")}))],lines:y},v=[x,e,s,n,i,o,a,r,h,c,d,l,u,p?t(x,p):null,f,g,this.solved?t(x,Fe(this.getOutputSimpleRouteJson())):null].filter(Boolean);return t(...v)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const s=this.highDensityRouteSolver.routes[e];if(t.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[s.connectionName]}),t.length>200)break}return{lines:t}}if(this.pathingOptimizer){const t=[];for(const e of this.pathingOptimizer.connectionsWithNodes)e.path&&t.push({points:e.path.map(t=>({x:t.center.x,y:t.center.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const s of this.netToPointPairsSolver?.newConnections??[]){const n=s.netConnectionName??this.srj.connections.find(t=>t.name===s.name)?.netConnectionName,i=e.filter(t=>t.connectionName===s.name);for(let e=0;e<i.length;e++){const o=i[e],a={type:"pcb_trace",pcb_trace_id:`${s.name}_${e}`,connection_name:n??s.rootConnectionName??s.name,route:Ee(o,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},fi=pi,gi=class{constructor(t){this.targets=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const s=t[e],n=Math.floor(s.bounds.minX/this.CELL_SIZE)*this.CELL_SIZE,i=Math.floor(s.bounds.minY/this.CELL_SIZE)*this.CELL_SIZE,o=s.bounds.maxX,a=s.bounds.maxY;for(let t=n;t<=o;t+=this.CELL_SIZE)for(let n=i;n<=a;n+=this.CELL_SIZE){const i=this.getBucketKey(t,n),o=this.buckets.get(i);o?o.push([s,e]):this.buckets.set(i,[[s,e]])}}}buckets;CELL_SIZE=5;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getTargetsInArea(t,e,s,n){const i=[],o=new Set,a=Math.floor((t-s/2)/this.CELL_SIZE)*this.CELL_SIZE,r=Math.floor((e-n/2)/this.CELL_SIZE)*this.CELL_SIZE,h=t+s/2,c=e+n/2;for(let t=a;t<=h;t+=this.CELL_SIZE)for(let e=r;e<=c;e+=this.CELL_SIZE){const s=this.getBucketKey(t,e),n=this.buckets.get(s)||[];for(const t of n)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},mi=class extends e{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.MAX_DEPTH=e?.capacityDepth??this.MAX_DEPTH,this.MAX_ITERATIONS=1e5,this.layerCount=t.layerCount??2,this.outlinePolygon=t.outline&&t.outline.length>=3?t.outline:void 0;for(const e of t.obstacles)if(!e.zLayers){const s=[];for(const n of e.layers)s.push(Ae(n,t.layerCount));e.zLayers=s}const s={x:(t.bounds.minX+t.bounds.maxX)/2,y:(t.bounds.minY+t.bounds.maxY)/2},n={width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},i=Math.max(n.width,n.height);this.unfinishedNodes=[{capacityMeshNodeId:this.getNextNodeId(),center:s,width:i,height:i,layer:"top",availableZ:Array.from({length:this.layerCount},(t,e)=>e),_depth:0,_containsTarget:!0,_containsObstacle:!0,_completelyInsideObstacle:!1}],this.finishedNodes=[],this.nodeToXYOverlappingObstaclesMap=new Map,this.obstacleTree=new Bn("flatbush",this.srj.obstacles),this.targets=this.computeTargets(),this.targetTree=new gi(this.targets)}unfinishedNodes;finishedNodes;nodeToXYOverlappingObstaclesMap;layerCount;outlinePolygon;MAX_DEPTH=4;targets;targetTree;obstacleTree;computeTargets(){const t=[];for(const e of this.srj.connections)for(const s of e.pointsToConnect){const n=ze(s),i=this.obstacleTree.searchArea(s.x,s.y,.01,.01).filter(t=>t.zLayers.some(t=>n.some(e=>t===Ae(e,this.layerCount))));let o={minX:s.x-.005,minY:s.y-.005,maxX:s.x+.005,maxY:s.y+.005};i.length>0&&(o={minX:Math.min(...i.map(t=>t.center.x-t.width/2)),minY:Math.min(...i.map(t=>t.center.y-t.height/2)),maxX:Math.max(...i.map(t=>t.center.x+t.width/2)),maxY:Math.max(...i.map(t=>t.center.y+t.height/2))});const a={...s,connectionName:e.name,availableZ:n.map(t=>Ae(t,this.layerCount)),bounds:o};t.push(a)}return t}getNodeBounds(t){const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-s,maxY:t.center.y+s}}getNodeRect(t){return{center:{x:t.center.x,y:t.center.y},width:t.width,height:t.height}}_nextNodeCounter=0;getNextNodeId(){return"cn"+this._nextNodeCounter++}getCapacityFromDepth(t){return(this.MAX_DEPTH-t+1)**2}getTargetIfNodeContainsTarget(t){const e=t.width>4*this.targetTree.CELL_SIZE?this.targets:this.targetTree.getTargetsInArea(t.center.x,t.center.y,t.width,t.height);for(const s of e)if(s.bounds.minX<=t.center.x+t.width/2&&s.bounds.maxX>=t.center.x-t.width/2&&s.bounds.minY<=t.center.y+t.height/2&&s.bounds.maxY>=t.center.y-t.height/2&&s.availableZ.some(e=>t.availableZ.includes(e)))return s;return null}getXYOverlappingObstacles(t){const e=this.nodeToXYOverlappingObstaclesMap.get(t.capacityMeshNodeId);if(e)return e;const s=[],n=this.getNodeBounds(t),i=n.minX,o=n.maxX,a=n.minY,r=n.maxY,h=t._parent?this.getXYOverlappingObstacles(t._parent):this.srj.obstacles;for(const t of h){const e=t.center.x-t.width/2,n=t.center.x+t.width/2,h=t.center.y-t.height/2,c=t.center.y+t.height/2;o>=e&&i<=n&&r>=h&&a<=c?s.push(t):(i>=e&&o<=n&&a>=h&&r<=c||e>=i&&n<=o&&h>=a&&c<=r)&&s.push(t)}return this.nodeToXYOverlappingObstaclesMap.set(t.capacityMeshNodeId,s),s}getXYZOverlappingObstacles(t){const e=this.getXYOverlappingObstacles(t),s=[];for(const n of e)t.availableZ.some(t=>n.zLayers.includes(t))&&s.push(n);return s}doesNodeOverlapObstacle(t){if(this.getXYZOverlappingObstacles(t).length>0)return!0;const e=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!Mt(e,this.outlinePolygon))return!0}return e.minX<this.srj.bounds.minX||e.maxX>this.srj.bounds.maxX||e.minY<this.srj.bounds.minY||e.maxY>this.srj.bounds.maxY}isNodeCompletelyInsideObstacle(t){const e=this.getXYZOverlappingObstacles(t),s=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!vt(e,this.outlinePolygon))return!0}for(const t of e){const e=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2;if(s.minX>=e&&s.maxX<=n&&s.minY>=i&&s.maxY<=o)return!0}return!1}getChildNodes(t){if(t._depth===this.MAX_DEPTH)return[];const e=[],s={width:t.width/2,height:t.height/2},n=[{x:t.center.x-s.width/2,y:t.center.y-s.height/2},{x:t.center.x+s.width/2,y:t.center.y-s.height/2},{x:t.center.x-s.width/2,y:t.center.y+s.height/2},{x:t.center.x+s.width/2,y:t.center.y+s.height/2}];for(const i of n){const n={capacityMeshNodeId:this.getNextNodeId(),center:i,width:s.width,height:s.height,layer:t.layer,availableZ:t.availableZ,_depth:(t._depth??0)+1,_parent:t};n._containsObstacle=this.doesNodeOverlapObstacle(n);const o=this.getTargetIfNodeContainsTarget(n);o&&(n._targetConnectionName=o.connectionName,n.availableZ=o.availableZ,n._containsTarget=!0),n._containsObstacle&&(n._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(n)),n._completelyInsideObstacle&&!n._containsTarget||e.push(n)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||!(!t._containsObstacle||t._completelyInsideObstacle))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),s=[],n=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t);e?n.push(t):e||t._containsObstacle?!e&&t._containsTarget&&s.push(t):s.push(t)}this.unfinishedNodes.push(...n),this.finishedNodes.push(...s)}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Mesh Visualization"};if(this.outlinePolygon&&this.outlinePolygon.length>=2){const e=this.outlinePolygon.map(t=>({x:t.x,y:t.y}));e.push({...e[0]}),t.lines.push({points:e,strokeColor:"rgba(0, 136, 255, 0.95)",label:"outline"});for(const e of this.outlinePolygon)t.points.push({x:e.x,y:e.y,color:"rgba(0, 136, 255, 0.95)"})}for(const e of this.srj.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:1===e.zLayers?.length&&e.zLayers?.includes(1)?"rgba(0,0,255,0.3)":"rgba(255,0,0,0.3)",stroke:"red",label:["obstacle",`z: ${e.zLayers.join(",")}`].join("\n")});const e=[...this.finishedNodes,...this.unfinishedNodes];for(const s of e){const e=Math.min(...s.availableZ),n=this.unfinishedNodes.length>0&&s===this.unfinishedNodes[this.unfinishedNodes.length-1];t.rects.push({center:{x:s.center.x+e*s.width*.05,y:s.center.y-e*s.width*.05},width:Math.max(s.width-2,.8*s.width),height:Math.max(s.height-2,.8*s.height),fill:s._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)"}[s.availableZ.join(",")]??"rgba(0,200,200,0.1)",stroke:n?"rgba(255,165,0,0.5)":void 0,label:[s.capacityMeshNodeId,`availableZ: ${s.availableZ.join(",")}`,`target? ${s._containsTarget??!1}`,`obs? ${s._containsObstacle??!1}`,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`capacity: ${Pe(s).toFixed(2)}`].join("\n")})}return t.rects.sort((t,e)=>t.center.y-e.center.y),this.srj.connections.forEach((e,s)=>{const n=Y[s%Y.length];for(const i of e.pointsToConnect){const e=ze(i);t.points.push({x:i.x,y:i.y,label:`conn-${s} (${e.join(",")})`,color:n})}}),t}},yi=class extends mi{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e,this.VIA_DIAMETER=t.minViaDiameter??this.VIA_DIAMETER}VIA_DIAMETER=.6;OBSTACLE_MARGIN=.1;OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES=.2;isNodeCompletelyOutsideBounds(t){if(this.outlinePolygon){const e=this.getNodeRect(t);if(!vt(e,this.outlinePolygon))return!0}return t.center.x+t.width/2<this.srj.bounds.minX||t.center.x-t.width/2>this.srj.bounds.maxX||t.center.y+t.height/2<this.srj.bounds.minY||t.center.y-t.height/2>this.srj.bounds.maxY}isNodePartiallyOutsideBounds(t){if(this.outlinePolygon){const e=this.getNodeRect(t);return!!vt(e,this.outlinePolygon)&&!Mt(e,this.outlinePolygon)}return t.center.x-t.width/2<this.srj.bounds.minX||t.center.x+t.width/2>this.srj.bounds.maxX||t.center.y-t.height/2<this.srj.bounds.minY||t.center.y+t.height/2>this.srj.bounds.maxY}getObstacleCoveragePercentage(t){const e=this.getXYZOverlappingObstacles(t);if(0===e.length)return 0;const s=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2,a=t.width*t.height;let r=0;for(const t of e){const e=Math.max(s,t.center.x-t.width/2),a=Math.min(n,t.center.x+t.width/2),h=Math.max(i,t.center.y-t.height/2),c=Math.min(o,t.center.y+t.height/2);if(e<a&&h<c){r+=(a-e)*(c-h)}}return r/a}shouldFilterSingleLayerNodeForObstacle(t){if(1!==t.availableZ.length)return!1;if(!t._containsObstacle)return!1;return this.getObstacleCoveragePercentage(t)>this.OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES}shouldFilterNodeForObstacle(t){return!!t._containsObstacle&&(1!==t.availableZ.length||this.shouldFilterSingleLayerNodeForObstacle(t))}createChildNodeAtPosition(t,e){const s={capacityMeshNodeId:this.getNextNodeId(),center:e.center,width:e.width,height:e.height,layer:t.layer,availableZ:e.availableZ,_depth:e._depth??(t._depth??0)+1,_parent:t},n=this.getXYZOverlappingObstacles(s);s._containsObstacle=n.length>0||this.isNodePartiallyOutsideBounds(s);const i=this.getTargetIfNodeContainsTarget(s);return i&&(s._targetConnectionName=i.connectionName,s._containsTarget=!0),s._containsObstacle&&(s._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(s)),s}getZSubdivisionChildNodes(t){if(1===t.availableZ.length)return[];const e=[],s=t.availableZ.map(t=>[t]);for(const n of s){const s=this.createChildNodeAtPosition(t,{center:{...t.center},width:t.width,height:t.height,availableZ:n,_depth:t._depth});this.isNodeCompletelyOutsideBounds(s)||e.push(s)}return e}getChildNodes(t){if(t._depth>=this.MAX_DEPTH)return[];const e=[],s={width:t.width/2,height:t.height/2},n=[{x:t.center.x-s.width/2,y:t.center.y-s.height/2},{x:t.center.x+s.width/2,y:t.center.y-s.height/2},{x:t.center.x-s.width/2,y:t.center.y+s.height/2},{x:t.center.x+s.width/2,y:t.center.y+s.height/2}];for(const i of n){const n=this.createChildNodeAtPosition(t,{center:i,width:s.width,height:s.height,availableZ:t.availableZ});this.isNodeCompletelyOutsideBounds(n)||e.push(n)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||(1===t.availableZ.length&&t._depth<=this.MAX_DEPTH||!(!t._containsObstacle||t._completelyInsideObstacle)))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),s=[],n=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),i=t.availableZ.length>1&&!e&&(t._containsObstacle||t.width<this.VIA_DIAMETER+this.OBSTACLE_MARGIN);if(e)n.push(t);else if(e||this.shouldFilterNodeForObstacle(t)||i)if(!e&&t._containsTarget)if(i){const e=this.getZSubdivisionChildNodes(t);s.push(...e.filter(t=>t._containsTarget||!this.shouldFilterNodeForObstacle(t)))}else s.push(t);else i&&s.push(...this.getZSubdivisionChildNodes(t).filter(t=>!this.shouldFilterNodeForObstacle(t)));else s.push(t)}this.unfinishedNodes.push(...n),this.finishedNodes.push(...s)}},xi=class extends yi{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e}MAX_SIZE_FOR_SINGLE_LAYER_NODES=2;isObstacleAssignable(t){return Boolean(t?.netIsAssignable)}getOverlappingAssignableObstacles(t){return this.getXYZOverlappingObstacles(t).filter(t=>this.isObstacleAssignable(t))}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||(!(!t._containsObstacle||t._completelyInsideObstacle)||1===t.availableZ.length&&(t.width>this.MAX_SIZE_FOR_SINGLE_LAYER_NODES||t.height>this.MAX_SIZE_FOR_SINGLE_LAYER_NODES)))}shouldFilterNodeForObstacle(t){if(!t._containsObstacle)return!1;return!(this.getOverlappingAssignableObstacles(t).length>0)&&(1!==t.availableZ.length||this.shouldFilterSingleLayerNodeForObstacle(t))}insertAssignableObstaclesAsNodes(){const t=this.srj.obstacles.filter(t=>this.isObstacleAssignable(t)),e=new Map;for(const s of t){const t=[];for(const e of this.finishedNodes){this.getXYZOverlappingObstacles(e).some(t=>t===s)&&t.push(e)}e.set(s,t)}const s=new Set;for(const t of e.values())for(const e of t)s.add(e);this.finishedNodes=this.finishedNodes.filter(t=>!s.has(t));for(const s of t){const t=e.get(s)||[],n=Array.from({length:this.srj.layerCount},(t,e)=>this.srj.layerCount-e-1);let i=s.center.x-s.width/2,o=s.center.x+s.width/2,a=s.center.y-s.height/2,r=s.center.y+s.height/2;for(const e of t){const t=e.center.x-e.width/2,s=e.center.x+e.width/2,n=e.center.y-e.height/2,h=e.center.y+e.height/2;i=Math.min(i,t),o=Math.max(o,s),a=Math.min(a,n),r=Math.max(r,h)}const h=o-i,c=r-a,d=(i+o)/2,l=(a+r)/2;let u=!1;for(const t of this.srj.connections){for(const e of t.pointsToConnect)if(e.x>=i&&e.x<=o&&e.y>=a&&e.y<=r){u=!0;break}if(u)break}const p={capacityMeshNodeId:`assignable_via_${s.center.x}_${s.center.y}`,center:{x:d,y:l},width:h,height:c,layer:1===n.length?`z${n[0]}`:`z${n.join(",")}`,availableZ:n,_depth:0,_containsTarget:u,_containsObstacle:!1,_completelyInsideObstacle:!1};p._assignedViaObstacle=s,this.finishedNodes.push(p)}}_step(){const t=this.unfinishedNodes.pop();if(!t)return this.insertAssignableObstaclesAsNodes(),void(this.solved=!0);const e=this.getChildNodes(t),s=[],n=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),i=t.availableZ.length>1&&!e;if(e)n.push(t);else{if(i){const e=this.getZSubdivisionChildNodes(t);for(const t of e)!t._containsTarget&&this.shouldFilterNodeForObstacle(t)||(this.shouldNodeBeXYSubdivided(t)?n.push(t):(t._containsObstacle=!1,s.push(t)));continue}this.shouldFilterNodeForObstacle(t)&&!t._containsTarget||s.push(t)}}this.unfinishedNodes.push(...n),this.finishedNodes.push(...s)}},vi=.005,Mi=class extends e{nodeMap;currentBatchNodeIds;absorbedNodeIds;nextBatchNodeIds;batchHadModifications;hasComputedAdjacentNodeIds=!1;newNodes;constructor(t){super(),this.nodeMap=new Map,this.MAX_ITERATIONS=1e5;for(const e of t)this.nodeMap.set(e.capacityMeshNodeId,e);this.newNodes=[],this.absorbedNodeIds=new Set;const e=[];for(const s of t)s._assignedViaObstacle?(this.newNodes.push(s),this.absorbedNodeIds.add(s.capacityMeshNodeId)):s._containsTarget?s.availableZ.length>1?(this.newNodes.push(s),this.absorbedNodeIds.add(s.capacityMeshNodeId)):e.push([s,s.width*s.height]):(this.newNodes.push(s),this.absorbedNodeIds.add(s.capacityMeshNodeId));e.sort((t,e)=>t[1]-e[1]);for(const[t,s]of e){const e={...t,center:{...t.center}};this.nodeMap.set(t.capacityMeshNodeId,e)}this.currentBatchNodeIds=e.map(([t])=>t.capacityMeshNodeId),this.nextBatchNodeIds=[],this.batchHadModifications=!1}computeAdjacentNodeIdsForFirstBatch(t){const e=Math.max(...t.map(t=>Math.max(...t.availableZ))),s=[];for(let n=0;n<=e;n++)s.push(new bs(t.filter(t=>t.availableZ[0]===n)));for(const e of t){const t=[],n=s[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const s of n)s._containsTarget&&s._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!s._containsTarget||s._targetConnectionName!==e._targetConnectionName)||s.capacityMeshNodeId!==e.capacityMeshNodeId&&Ms(e,s)&&t.push(s);e._adjacentNodeIds=t.map(t=>t.capacityMeshNodeId)}}getAdjacentSameLayerUnprocessedNodes(t){const e=[],s=Array.from(new Set((t._adjacentNodeIds??[]).map(t=>this.nodeMap.get(t)))).filter(e=>e&&e.capacityMeshNodeId!==t.capacityMeshNodeId);s.sort((t,e)=>t.width*t.height-e.width*e.height);for(const t of s)this.absorbedNodeIds.has(t.capacityMeshNodeId)||e.push(t);return e}_step(){this.hasComputedAdjacentNodeIds||(this.computeAdjacentNodeIdsForFirstBatch(this.currentBatchNodeIds.map(t=>this.nodeMap.get(t))),this.hasComputedAdjacentNodeIds=!0);let t=this.currentBatchNodeIds.pop();for(;t&&this.absorbedNodeIds.has(t);)t=this.currentBatchNodeIds.pop();if(!t)return this.batchHadModifications?(this.currentBatchNodeIds=this.nextBatchNodeIds.sort((t,e)=>{const s=this.nodeMap.get(t),n=this.nodeMap.get(e);return s.width*s.height-n.width*n.height}),this.nextBatchNodeIds=[],void(this.batchHadModifications=!1)):(this.solved=!0,void this.newNodes.push(...this.nextBatchNodeIds.map(t=>this.nodeMap.get(t))));const e=this.nodeMap.get(t);let s=!1;const n=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===n.length)return void this.nextBatchNodeIds.push(t);const i=t=>{for(const e of t)this.absorbedNodeIds.add(e.capacityMeshNodeId);e._adjacentNodeIds=Array.from(new Set([...e._adjacentNodeIds??[],...t.flatMap(t=>t._adjacentNodeIds??[])].filter(t=>t!==e.capacityMeshNodeId&&!this.absorbedNodeIds.has(t))))},o=n.filter(t=>t.center.x<e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(o.length>0){const{width:t,height:n}=o[0],a=o.every(e=>e.width===t&&e.height===n);Math.abs(o.reduce((t,e)=>t+e.height,0)-e.height)<vi&&a&&(e.width+=t,e.center.x=e.center.x-t/2,i(o),s=!0)}const a=n.filter(t=>t.center.x>e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(a.length>0&&!s){const{width:t,height:n}=a[0],o=a.every(e=>e.width===t&&e.height===n);Math.abs(a.reduce((t,e)=>t+e.height,0)-e.height)<vi&&o&&(e.width+=t,e.center.x=e.center.x+t/2,i(a),s=!0)}const r=n.filter(t=>t.center.y>e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(r.length>0&&!s){const{width:t,height:n}=r[0],o=r.every(e=>e.width===t&&e.height===n);Math.abs(r.reduce((t,e)=>t+e.width,0)-e.width)<vi&&o&&(e.height+=n,e.center.y=e.center.y+n/2,i(r),s=!0)}const h=n.filter(t=>t.center.y<e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(h.length>0&&!s){const{width:t,height:n}=h[0],o=h.every(e=>e.width===t&&e.height===n);Math.abs(h.reduce((t,e)=>t+e.width,0)-e.width)<vi&&o&&(e.height+=n,e.center.y=e.center.y-n/2,i(h),s=!0)}s?(this.batchHadModifications=!0,this.currentBatchNodeIds.push(t)):this.nextBatchNodeIds.unshift(t)}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Single Layer Node Merger (Only Merge Targets)"};for(const e of this.newNodes)t.rects.push(ss(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let s;e&&(s=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const n of this.currentBatchNodeIds){const i=this.nodeMap.get(n);if(!this.absorbedNodeIds.has(n)&&i){const o=ss(i,{rectMargin:.01});n===e?o.stroke="rgba(0, 255, 0, 0.8)":s?.some(t=>t.capacityMeshNodeId===n)?o.stroke="rgba(128, 0, 128, 0.8)":o.stroke="rgba(255, 165, 0, 0.8)",o.layer=`z${i.availableZ.join(",")}`,o.label=`${o.label}\n(unprocessed)`,t.rects.push(o)}}for(const e of this.nextBatchNodeIds){const s=this.nodeMap.get(e);if(!this.absorbedNodeIds.has(e)&&s){const e=ss(s,{rectMargin:.01});e.layer=`z${s.availableZ.join(",")}`,e.stroke="rgba(0, 217, 255, 0.8)",e.label=`${e.label}\nx: ${s.center.x}, y: ${s.center.y}\n${s.width}x${s.height}\n(next batch)`,t.rects.push(e)}}return t}},Si=class extends e{newNodes;obstacleToNodesMap;obstaclesToProcess;mergedNodeIds;constructor(t){super(),this.MAX_ITERATIONS=1e4,this.newNodes=[],this.obstacleToNodesMap=new Map,this.mergedNodeIds=new Set;for(const e of t){const t=e._assignedViaObstacle;if(t){const s=this.obstacleToNodesMap.get(t)||[];s.push(e),this.obstacleToNodesMap.set(t,s)}else this.newNodes.push(e)}this.obstaclesToProcess=Array.from(this.obstacleToNodesMap.keys())}_step(){const t=this.obstaclesToProcess.pop();if(!t)return void(this.solved=!0);const e=this.obstacleToNodesMap.get(t);if(!e||0===e.length)return;let s=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY,o=Number.NEGATIVE_INFINITY;const a=new Set;let r=!1;for(const t of e){const e=t.center.x-t.width/2,h=t.center.x+t.width/2,c=t.center.y-t.height/2,d=t.center.y+t.height/2;s=Math.min(s,e),n=Math.max(n,h),i=Math.min(i,c),o=Math.max(o,d);for(const e of t.availableZ)a.add(e);t._containsTarget&&(r=!0)}const h=n-s,c=o-i,d=(s+n)/2,l=(i+o)/2,u=Array.from(a).sort((t,e)=>t-e),p={capacityMeshNodeId:`merged_via_${t.center.x}_${t.center.y}`,center:{x:d,y:l},width:h,height:c,layer:1===u.length?`z${u[0]}`:`z${u.join(",")}`,availableZ:u,_containsTarget:r,_containsObstacle:!1,_completelyInsideObstacle:!1};p._assignedViaObstacle=t;for(const t of e)this.mergedNodeIds.add(t.capacityMeshNodeId);this.newNodes.push(p)}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Assignable Via Node Merger"};for(const e of this.newNodes){const s=ss(e);e._assignedViaObstacle&&(s.stroke="rgba(255, 0, 255, 0.8)",s.label=`${s.label||""}\n(merged via)`),t.rects.push(s)}const e=this.obstaclesToProcess[this.obstaclesToProcess.length-1];if(e){const s=this.obstacleToNodesMap.get(e)||[];for(const e of s){const s=ss(e,{rectMargin:.01});s.stroke="rgba(0, 255, 0, 0.8)",s.label=`${s.label||""}\n(to be merged)`,t.rects.push(s)}}return t}},bi=class extends e{constructor(t){const{simpleRouteJson:e,nodes:n,edges:i,colorMap:o,MAX_ITERATIONS:a=1e6,hyperParameters:r={}}=t;super(),this.inputParams=t,this.hyperParameters=r,this.MAX_ITERATIONS=a,this.simpleRouteJson=e,this.nodes=n,this.edges=i,this.colorMap=o??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=s(this.edges);const h=this.nodes.filter(t=>t._containsTarget);this.unprocessedConnectionPairs=zt(this.simpleRouteJson.connections.map(t=>{const[e,s]=t.pointsToConnect;return{start:h.find(t=>dt(t.center,e)<t.width/2),end:h.find(t=>dt(t.center,s)<t.width/2),connection:t}}),this.hyperParameters.SHUFFLE_SEED??0),this.viaNodes=this.nodes.filter(t=>t.availableZ.length>1)}GREEDY_MULTIPLIER=1.5;simpleRouteJson;nodes;edges;colorMap;MAX_ITERATIONS;hyperParameters;usedNodeMap=new Map;nodeMap;nodeEdgeMap;unprocessedConnectionPairs;solvedRoutes=[];activeConnectionPair=null;ogUnprocessedSubpaths=null;unprocessedSubpaths=null;solvedSubpaths=null;activeSubpath=null;viaNodes=[];closestViaForConnectionStartMap=new Map;closestViaForConnectionEndMap=new Map;getConstructorParams(){return this.inputParams}lastStepOperation="none";computeClosestViaForAllConnections(){this.closestViaForConnectionStartMap.clear(),this.closestViaForConnectionEndMap.clear();for(const t of this.unprocessedConnectionPairs){const e=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId));if(e.length>0){const s=e.reduce((e,s)=>{const n=this._dist(e,t.start);return this._dist(s,t.start)<n?s:e});this.closestViaForConnectionStartMap.set(t,s);const n=e.reduce((e,s)=>{const n=this._dist(e,t.end);return this._dist(s,t.end)<n?s:e});this.closestViaForConnectionEndMap.set(t,n)}}}_step(){if(!this.activeConnectionPair)return this.activeConnectionPair=this.unprocessedConnectionPairs.shift(),this.activeConnectionPair?(this.computeClosestViaForAllConnections(),void(this.lastStepOperation="dequeueConnectionPair")):void(this.solved=!0);if(this.activeConnectionPair&&!this.unprocessedSubpaths)return this.unprocessedSubpaths=this.breakConnectionPairIntoSubpaths(this.activeConnectionPair),this.ogUnprocessedSubpaths=this.unprocessedSubpaths.slice(),this.solvedSubpaths=[],void(this.lastStepOperation="breakConnectionPairIntoSubpaths");if(this.activeSubpath){if(this.activeSubpath&&(this.stepSolveSubpath(this.activeSubpath),this.activeSubpath.solved))return this.solvedSubpaths.push(this.activeSubpath),this.activeSubpath=null,this.clearCandidateNodes(),void(this.lastStepOperation="finishedSolvingSubpath");this.lastStepOperation="stepSolveSubpath"}else{if(this.activeSubpath=this.unprocessedSubpaths.shift(),!this.activeSubpath){const t=this.activeConnectionPair;return this.activeConnectionPair=null,this.unprocessedSubpaths=null,this.ogUnprocessedSubpaths=null,this.activeSubpath=null,this.solvedRoutes.push(this.createSolvedRoute(this.solvedSubpaths,t)),void(this.lastStepOperation="finishedSolvingConnectionPair")}this.lastStepOperation="dequeueSubpath"}}queuedCandidateNodes=[];visitedNodes=new Set;_dist(t,e){return Math.hypot(t.center.x-e.center.x,t.center.y-e.center.y)}stepSolveSubpath(t){const{start:e,end:s}=t;if(e.capacityMeshNodeId===s.capacityMeshNodeId)return t.path=[e],t.solved=!0,void this.usedNodeMap.set(e.capacityMeshNodeId,!0);if(0===this.queuedCandidateNodes.length&&0===this.visitedNodes.size){const t=this._dist(e,s),n={prevCandidate:null,node:e,g:0,h:t,f:this.GREEDY_MULTIPLIER*t};this.queuedCandidateNodes.push(n)}let n;for(this.queuedCandidateNodes.sort((t,e)=>t.f-e.f);this.queuedCandidateNodes.length&&!n;){const t=this.queuedCandidateNodes.shift();this.visitedNodes.has(t.node.capacityMeshNodeId)||(n=t)}if(!n)return this.failed=!0,void(this.error="No viable candidates left");if(this.visitedNodes.add(n.node.capacityMeshNodeId),n.node.capacityMeshNodeId===s.capacityMeshNodeId){const e=[];let s=n;for(;s;)e.unshift(s.node),this.usedNodeMap.set(s.node.capacityMeshNodeId,!0),s=s.prevCandidate;return t.path=e,void(t.solved=!0)}const i=this.getNeighbors(n.node);for(const t of i){const e=t.capacityMeshNodeId;if(this.visitedNodes.has(e))continue;const i=this.computeG(n,t,s),o=this.computeH(n,t,s),a=i+this.GREEDY_MULTIPLIER*o,r=this.queuedCandidateNodes.findIndex(t=>t.node.capacityMeshNodeId===e);if(r>=0){if(this.queuedCandidateNodes[r].g<=i)continue;this.queuedCandidateNodes.splice(r,1)}this.queuedCandidateNodes.push({prevCandidate:n,node:t,g:i,h:o,f:a})}}getNeighbors(t){const e=new Set,s=this.nodeEdgeMap.get(t.capacityMeshNodeId)??[];for(const n of s){const[s,i]=n.nodeIds,o=s===t.capacityMeshNodeId?i:s,a=this.nodeMap.get(o);a&&e.add(a)}const n=this.activeSubpath?.layer;return Array.from(e).filter(t=>!(t.capacityMeshNodeId!==this.activeSubpath?.end.capacityMeshNodeId)||!t._containsObstacle&&(!t._containsTarget&&(!this.usedNodeMap.has(t.capacityMeshNodeId)&&!(void 0!==n&&!t.availableZ.includes(n)))))}clearCandidateNodes(){this.queuedCandidateNodes=[],this.visitedNodes=new Set}computeG(t,e,s){const n=this._dist(t.node,e);return t.g+n}computeH(t,e,s){return this._dist(e,s)}createSolvedRoute(t,e){const s=[];for(let e=0;e<t.length;e++){const n=t[e];n.path?0===e?s.push(...n.path):s.push(...n.path.slice(1)):(0===e&&s.push(n.start),e===t.length-1&&s.push(n.end))}return{connection:e.connection,path:s}}breakConnectionPairIntoSubpaths(t){var e,s;if(!(e=[this.hyperParameters.DIRECTIVE_SEED??0,this.solvedRoutes.length],s=this.hyperParameters.FORCE_VIA_TRAVEL_CHANCE??0,Tt(e.reduce((t,e)=>t+16807*e%2147483647,0))()<s))return[{start:t.start,end:t.end,solved:!1,layer:t.start.availableZ[0]??0}];const n=this.getClosestVia(t.start),i=this.getFarVia(n,t.end),o=t.start.availableZ[0]??0,a=t.end.availableZ[0]??0,r=[];return r.push({start:t.start,end:n,solved:!1,layer:o}),o===a?(r.push({start:n,end:i,solved:!1,layer:0===o?1:0}),r.push({start:i,end:t.end,solved:!1,layer:a})):r.push({start:n,end:t.end,solved:!1,layer:a}),r}getClosestVia(t){if(0===this.viaNodes.length)return t;const e=new Set;for(const[t,s]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&e.add(s.capacityMeshNodeId);for(const[t,s]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&e.add(s.capacityMeshNodeId);const s=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId)).filter(t=>!e.has(t.capacityMeshNodeId));if(0===s.length){const e=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId));return 0===e.length?t:(e.sort((e,s)=>this._dist(e,t)-this._dist(s,t)),e[0])}s.sort((e,s)=>this._dist(e,t)-this._dist(s,t));const n=this.hyperParameters.MAX_CLOSEST_VIA_SKIP??0;if(n>0&&s.length>1){const t=Tt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length),e=Math.floor(t()*(n+1));return s[Math.min(e,s.length-1)]}return s[0]}getFarVia(t,e){if(0===this.viaNodes.length)return t;const s=null!=this.hyperParameters.FAR_VIA_MIN_DISTANCE?this.hyperParameters.FAR_VIA_MIN_DISTANCE:50,n=new Set;for(const[t,e]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&n.add(e.capacityMeshNodeId);for(const[t,e]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&n.add(e.capacityMeshNodeId);const i=this.viaNodes.filter(e=>!this.usedNodeMap.has(e.capacityMeshNodeId)&&e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!n.has(e.capacityMeshNodeId)&&this._dist(e,t)>=s);if(0===i.length){const n=this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)&&this._dist(e,t)>=s).sort((t,s)=>this._dist(t,e)-this._dist(s,e));if(n.length>0)return n[0];return this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)).sort((t,s)=>this._dist(t,e)-this._dist(s,e))[0]??t}i.sort((t,s)=>this._dist(t,e)-this._dist(s,e));const o=this.hyperParameters.MAX_FURTHEST_VIA_SKIP??0;if(o>0&&i.length>1){const t=Tt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length+1e3),e=Math.floor(t()*(o+1));return i[Math.min(e,i.length-1)]}return i[0]}getCapacityPaths(){const t=[];for(const e of this.solvedRoutes){const s=e.path;s&&s.length>0&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:s.map(t=>t.capacityMeshNodeId)})}return t}visualize(){const t={lines:[],points:[],rects:[],circles:[]},e=t=>!!t&&"number"==typeof t.x&&"number"==typeof t.y&&!Number.isNaN(t.x)&&!Number.isNaN(t.y)&&Number.isFinite(t.x)&&Number.isFinite(t.y),s=t=>"number"==typeof t&&!Number.isNaN(t)&&Number.isFinite(t);for(const n of this.nodes){const i=this.queuedCandidateNodes.some(t=>t.node.capacityMeshNodeId===n.capacityMeshNodeId),o=this.queuedCandidateNodes.find(t=>t.node.capacityMeshNodeId===n.capacityMeshNodeId);if(e(n.center)&&s(n.width)&&s(n.height)){const e=ss(n,{rectMargin:.025,zOffset:.01});t.rects.push({...e,fill:i?"rgba(255, 128, 255, 0.5)":n._containsTarget?"rgba(0, 150, 255, 0.15)":n._containsObstacle?"rgba(255, 0, 0, 0.1)":"rgba(200, 200, 200, 0.05)",label:[`ID: ${n.capacityMeshNodeId}`,`Size: ${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Z: ${n.availableZ.join(", ")}`,o?`g: ${o.g.toFixed(2)}`:"",o?`h: ${o.h.toFixed(2)}`:"",o?`f: ${o.f.toFixed(2)}`:"",n._containsTarget?"TARGET":"",n._containsObstacle?"OBSTACLE":""].filter(t=>t).join("\n")})}}for(const s of this.edges){const[n,i]=s.nodeIds,o=this.nodeMap.get(n),a=this.nodeMap.get(i);o?.center&&a?.center&&e(o.center)&&e(a.center)&&t.lines.push({points:[o.center,a.center],strokeColor:"rgba(150, 150, 150, 0.2)"})}for(let s=0;s<this.solvedRoutes.length;s++){const n=this.solvedRoutes[s],i=n.path,o="blue";for(let n=0;n<i.length-1;n++){const a=i[n],r=i[n+1];if(a?.center&&r?.center&&e(a.center)&&e(r.center)){const e=a.availableZ.includes(1)&&r.availableZ.includes(1),n=s%5*.02;t.lines.push({points:[{x:a.center.x+n,y:a.center.y+n},{x:r.center.x+n,y:r.center.y+n}],strokeColor:o,strokeDash:e?"5 5":void 0})}}if(i.length>0){const s=i[0],o=i[i.length-1];s?.center&&e(s.center)&&t.points.push({x:s.center.x,y:s.center.y,label:`START: ${n.connection.name}`}),o?.center&&e(o.center)&&t.points.push({x:o.center.x,y:o.center.y,label:`END: ${n.connection.name}`})}}if(this.solvedSubpaths)for(let s=0;s<this.solvedSubpaths.length;s++){const n=this.solvedSubpaths[s];if(n.path&&n.path.length>1)for(let s=0;s<n.path.length-1;s++){const i=n.path[s],o=n.path[s+1];i?.center&&o?.center&&e(i.center)&&e(o.center)&&t.lines.push({points:[i.center,o.center],strokeColor:"green",strokeDash:1===n.layer?"3 3":void 0})}}if(this.activeSubpath){const s=this.activeSubpath.start?.center,n=this.activeSubpath.end?.center;s&&n&&e(s)&&e(n)&&(t.lines.push({points:[s,n],strokeColor:"orange",strokeDash:"5 5"}),t.points.push({x:s.x,y:s.y,label:"ACTIVE START"}),t.points.push({x:n.x,y:n.y,label:"ACTIVE END"}))}const n=this.queuedCandidateNodes.slice(0,10).sort((t,e)=>t.f-e.f);for(let s=0;s<n.length;s++){const i=.6*(1-s/10),o=[];let a=n[s];for(;a;)o.push(a.node),a=a.prevCandidate;if(o.reverse(),o.length>1){const s=o.map(t=>t.center).filter(t=>e(t));s.length>1&&t.lines.push({points:s,strokeColor:V("purple",1-i),strokeDash:1===this.activeSubpath?.layer?"4 2":void 0})}}if(this.activeConnectionPair){const s=this.activeConnectionPair.start?.center,n=this.activeConnectionPair.end?.center;s&&n&&e(s)&&e(n)&&t.lines.push({points:[s,n],strokeColor:"cyan",strokeDash:"20 5"})}if(this.ogUnprocessedSubpaths&&3===this.ogUnprocessedSubpaths.length){const[,n]=this.ogUnprocessedSubpaths;if(n.start?.center&&e(n.start.center)){const e=Math.max(n.start.width||0,n.start.height||0);s(e)&&e>0&&(t.circles.push({center:n.start.center,radius:e,stroke:"blue"}),t.points.push({x:n.start.center.x,y:n.start.center.y,label:"DIRECTIVE VIA 1"}))}if(n.end?.center&&e(n.end.center)){const e=Math.max(n.end.width||0,n.end.height||0);s(e)&&e>0&&(t.circles.push({center:n.end.center,radius:e,stroke:"purple"}),t.points.push({x:n.end.center.x,y:n.end.center.y,label:"DIRECTIVE VIA 2"}))}}if(this.queuedCandidateNodes.length>0)for(const s of this.queuedCandidateNodes){const n=s.node;n?.center&&e(n.center)&&t.circles.push({center:n.center,radius:.05,fill:"rgba(255, 255, 0, 0.6)",stroke:"yellow"})}if(this.visitedNodes.size>0)for(const s of this.visitedNodes){const n=this.nodeMap.get(s);n?.center&&e(n.center)&&t.circles.push({center:n.center,radius:.08,fill:"rgba(128, 128, 128, 0.5)",stroke:"gray"})}return t}},Ni=class extends Ft{constructorParams;constructor(t){super(),this.constructorParams=t,this.MAX_ITERATIONS=t.MAX_ITERATIONS??12e4,this.MIN_SUBSTEPS=5,this.GREEDY_MULTIPLIER=1.35}getHyperParameterDefs(){return[{name:"traceOrderingSeed",possibleValues:[{SHUFFLE_SEED:0},{SHUFFLE_SEED:1},{SHUFFLE_SEED:2},{SHUFFLE_SEED:3},{SHUFFLE_SEED:4},{SHUFFLE_SEED:5},{SHUFFLE_SEED:6},{SHUFFLE_SEED:7},{SHUFFLE_SEED:8},{SHUFFLE_SEED:9}]},{name:"forceViaTravelChance",possibleValues:[{FORCE_VIA_TRAVEL_CHANCE:.6},{FORCE_VIA_TRAVEL_CHANCE:.8},{FORCE_VIA_TRAVEL_CHANCE:.9}]}]}computeG(t){const e=t.unprocessedConnectionPairs.length+t.solvedRoutes.length+(t.activeConnectionPair?1:0),s=t.solvedRoutes.length,n=e>0?s/e:0;return t.iterations/t.MAX_ITERATIONS+(1-n)}computeH(t){const e=t.unprocessedConnectionPairs.length+t.solvedRoutes.length+(t.activeConnectionPair?1:0),s=t.solvedRoutes.length;return e>0?1-s/e:0}generateSolver(t){return new bi({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}};function Ii(t){const e=new Map;for(const s of t)e.set(s.capacityMeshNodeId,s);return e}function Pi(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var Ci=class extends e{capacityNodes;capacityEdges;enhancedEdges=[];animationState="showing_nodes";assignableNodes=[];shownNodes=[];pendingEdges=[];createdEdges=[];nextEdgeId=0;nodeMap=new Map;constructor(t){super(),this.capacityNodes=t.capacityNodes,this.capacityEdges=t.capacityEdges,this.nodeMap=Ii(this.capacityNodes),this.enhancedEdges=[...this.capacityEdges],this.initializeAssignableNodes(),this.initializePendingEdges(),this.MAX_ITERATIONS=this.assignableNodes.length+this.pendingEdges.length+10}initializeAssignableNodes(){for(const t of this.capacityNodes){const e=t._assignedViaObstacle;e?.offBoardConnectsTo&&e.offBoardConnectsTo.length>0&&this.assignableNodes.push(t)}}initializePendingEdges(){const t=new Map;for(const e of this.assignableNodes){const s=e._assignedViaObstacle;if(s?.offBoardConnectsTo)for(const n of s.offBoardConnectsTo)t.has(n)||t.set(n,[]),t.get(n).push(e)}this.pendingEdges=[];for(const[e,s]of t)if(s.length>1)for(let t=0;t<s.length;t++)for(let n=t+1;n<s.length;n++)this.pendingEdges.push({node1:s[t],node2:s[n],netName:e})}_step(){switch(this.animationState){case"showing_nodes":if(this.assignableNodes.length>0){const t=this.assignableNodes.shift();this.shownNodes.push(t)}else this.animationState="showing_edges";break;case"showing_edges":if(this.pendingEdges.length>0){const{node1:t,node2:e,netName:s}=this.pendingEdges.shift(),n=this.createOffboardEdge(t,e,s);this.enhancedEdges.push(n),this.createdEdges.push(n)}else this.animationState="done",this.solved=!0;break;case"done":this.solved=!0}}createOffboardEdge(t,e,s){return{capacityMeshEdgeId:"offboard_"+this.nextEdgeId++,nodeIds:[t.capacityMeshNodeId,e.capacityMeshNodeId],isOffboardEdge:!0,offboardNetName:s}}visualize(){const t=[],e=[],s=[],n=new Set(this.shownNodes.map(t=>t.capacityMeshNodeId));for(const e of this.capacityEdges){if(e.isOffboardEdge)continue;if(n.has(e.nodeIds[0])||n.has(e.nodeIds[1])){const s=this.nodeMap.get(e.nodeIds[0]),n=this.nodeMap.get(e.nodeIds[1]);s&&n&&t.push({points:[s.center,n.center],strokeColor:"rgba(0, 200, 0, 0.5)",strokeWidth:.05})}}for(let t=0;t<this.shownNodes.length;t++){const n=this.shownNodes[t],i=n._assignedViaObstacle,o=t===this.shownNodes.length-1&&"showing_nodes"===this.animationState;s.push({center:n.center,width:n.width,height:n.height,fill:o?"rgba(255, 165, 0, 0.5)":"rgba(173, 216, 230, 0.5)",stroke:o?"orange":"blue",strokeWidth:o?.15:.1}),e.push({x:n.center.x,y:n.center.y,color:o?"orange":"blue",label:`${o?"NEW: ":""}${n.capacityMeshNodeId}\n${i?.offBoardConnectsTo?.join(", ")||""}`})}for(let s=0;s<this.createdEdges.length;s++){const n=this.createdEdges[s],i=s===this.createdEdges.length-1&&"showing_edges"===this.animationState,o=this.nodeMap.get(n.nodeIds[0]),a=this.nodeMap.get(n.nodeIds[1]);if(o&&a){t.push({points:[o.center,a.center],strokeColor:i?"red":"orange",strokeWidth:i?.2:.1,strokeDasharray:"0.3,0.15"});const s=Pi(o.center,a.center);e.push({x:s.x,y:s.y,color:i?"red":"orange",label:`${i?"NEW: ":""}⚡ ${n.offboardNetName}`})}}let i="Offboard Capacity Node Solver";switch(this.animationState){case"showing_nodes":i+=` - Showing nodes (${this.shownNodes.length}/${this.shownNodes.length+this.assignableNodes.length})`;break;case"showing_edges":i+=` - Creating edges (${this.createdEdges.length}/${this.createdEdges.length+this.pendingEdges.length})`;break;case"done":i+=` - Done (${this.shownNodes.length} nodes, ${this.createdEdges.length} edges)`}return{lines:t,points:e,rects:s,title:i}}getVirtualOffboardNodes(){return[]}getOffboardEdges(){return this.enhancedEdges.filter(t=>t.isOffboardEdge)}};function _i(t,e){return t.x>=e.center.x-e.width/2&&t.x<=e.center.x+e.width/2&&t.y>=e.center.y-e.height/2&&t.y<=e.center.y+e.height/2}var Ei=class extends e{inputPaths;capacityEdges;originalConnections;fragmentedPaths=[];fragmentedConnections=[];fragmentedOriginalConnectionNames=new Set;nextFragmentId=0;animationState="showing_original_path";currentPath=null;currentFragments=[];currentFragmentIndex=0;nodeMap=new Map;constructor({capacityPaths:t,capacityEdges:e,capacityNodes:s,connections:n}){super(),this.inputPaths=[...t],this.capacityEdges=e,this.originalConnections=n,this.nodeMap=Ii(s)}_step(){switch(this.animationState){case"showing_original_path":if(0===this.inputPaths.length)return this.animationState="done",void(this.solved=!0);this.currentPath=this.inputPaths.shift(),this.currentFragments=this.splitPath(this.currentPath),this.currentFragmentIndex=0;this.currentFragments.some(t=>t.isFragmentedPath)?this.animationState="showing_fragment":this.fragmentedPaths.push(...this.currentFragments);break;case"showing_fragment":if(this.currentFragmentIndex<this.currentFragments.length){const t=this.currentFragments[this.currentFragmentIndex];this.fragmentedPaths.push(t),this.currentFragmentIndex++}else this.currentPath&&(this.fragmentedOriginalConnectionNames.add(this.currentPath.connectionName),this.createFragmentConnections(this.currentPath,this.currentFragments)),this.currentPath=null,this.currentFragments=[],this.currentFragmentIndex=0,this.animationState="showing_original_path";break;case"done":this.solved=!0}}createFragmentConnections(t,e){const s=this.originalConnections.find(e=>e.name===t.connectionName);if(s)for(let t=0;t<e.length;t++){const n=e[t];if(!n.isFragmentedPath)continue;const i=s.pointsToConnect.filter(t=>{for(const e of n.nodeIds){const s=this.nodeMap.get(e);if(s&&_i(t,s))return!0}return!1}),o=0===t,a=o?n.nodeIds[n.nodeIds.length-1]:n.nodeIds[0],r=this.nodeMap.get(a);if(i.length>0&&r){const t=i[0],e={x:r.center.x,y:r.center.y,layer:we(t)},a=o?[...i,e]:[e,...i];this.fragmentedConnections.push({name:n.connectionName,pointsToConnect:a,netConnectionName:s.netConnectionName,rootConnectionName:s.rootConnectionName})}}}splitPath(t){const{nodeIds:e}=t;if(e.length<2)return[t];const s=[];for(let t=0;t<e.length-1;t++){const n=this.capacityEdges.find(s=>s.nodeIds[0]===e[t]&&s.nodeIds[1]===e[t+1]||s.nodeIds[0]===e[t+1]&&s.nodeIds[1]===e[t]);n&&n.isOffboardEdge&&s.push(t)}if(0===s.length)return[t];const n=[];let i=0,o=0;for(const a of s){const s=e.slice(i,a+1);if(s.length>=1){const e=this.nextFragmentId++;n.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${o++}`,rootConnectionName:t.rootConnectionName,nodeIds:s,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}i=a+1}if(i<e.length){const s=e.slice(i);if(s.length>=1){const e=this.nextFragmentId++;n.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${o++}`,rootConnectionName:t.rootConnectionName,nodeIds:s,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}}return n.length>0?n:[t]}getFragmentedPaths(){return this.fragmentedPaths}getFragmentedConnections(){return this.fragmentedConnections}getFragmentedOriginalConnectionNames(){return this.fragmentedOriginalConnectionNames}visualize(){const t=[],e=[],s=[];if("showing_original_path"===this.animationState&&this.currentPath&&this.drawPath({path:this.currentPath,color:"gray",lines:t,points:e,rects:s,labelPrefix:"Original: "}),this.fragmentedPaths.forEach((n,i)=>{if(n.isFragmentedPath){const o=i%2==0?"blue":"red";this.drawPath({path:n,color:o,lines:t,points:e,rects:s,labelPrefix:`Frag ${i}: `})}else this.drawPath({path:n,color:"green",lines:t,points:e,rects:s,labelPrefix:""})}),"showing_fragment"===this.animationState&&this.currentFragmentIndex>0){const n=this.fragmentedPaths.length-1;if(n>=0){const i=this.fragmentedPaths[n];i.isFragmentedPath&&this.drawPath({path:i,color:"orange",lines:t,points:e,rects:s,labelPrefix:"NEW: "})}}for(const e of this.capacityEdges)if(e.isOffboardEdge){const s=this.nodeMap.get(e.nodeIds[0]),n=this.nodeMap.get(e.nodeIds[1]);s&&n&&t.push({points:[s.center,n.center],strokeColor:"orange",strokeWidth:.15,strokeDasharray:"0.3,0.15"})}let n="Offboard Path Fragment Solver";return"showing_original_path"===this.animationState?n+=" - Analyzing path...":"showing_fragment"===this.animationState?n+=` - Fragment ${this.currentFragmentIndex}/${this.currentFragments.length}`:n+=` - Done (${this.fragmentedPaths.filter(t=>t.isFragmentedPath).length} fragments)`,{lines:t,points:e,rects:s,title:n}}drawPath(t){const{path:e,color:s,lines:n,points:i,rects:o,labelPrefix:a}=t,r=[];for(let t=0;t<e.nodeIds.length;t++){const n=e.nodeIds[t],h=this.nodeMap.get(n);h&&(r.push(h.center),o.push({center:h.center,width:.8*h.width,height:.8*h.height,stroke:s,strokeWidth:.05,fill:`${s}33`}),0!==t&&t!==e.nodeIds.length-1||i.push({x:h.center.x,y:h.center.y,color:s,label:`${a}${e.connectionName}\n${n}`}))}r.length>1&&n.push({points:r,strokeColor:s,strokeWidth:.1})}};function Ti(t,e,s,n={}){return{solverName:t,solverClass:e,getConstructorParams:s,onSolved:n.onSolved}}var wi=class extends e{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,void 0===e.capacityDepth){const s=t.bounds.maxX-t.bounds.minX,n=t.bounds.maxY-t.bounds.minY,i=Math.max(s,n),o=e.targetMinCapacity??.5;e.capacityDepth=Ce(i,o)}this.connMap=Ie(t),this.colorMap=H(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?st():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;initialPathingSolver;initialPathingHyperSolver;pathingOptimizer;edgeToPortSegmentSolver;colorMap;segmentToPointSolver;unravelMultiSectionSolver;segmentToPointOptimizer;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;mergeAssignableViaNodes;offboardCapacityNodeSolver;offboardPathFragmentSolver;strawSolver;deadEndSolver;uselessViaRemovalSolver1;uselessViaRemovalSolver2;multiSimplifiedPathSolver1;multiSimplifiedPathSolver2;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[Ti("netToPointPairsSolver",zs,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=H(t.srjWithPointPairs,this.connMap),t.connMap=Ie(t.srjWithPointPairs)}}),Ti("nodeSolver",xi,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),Ti("mergeAssignableViaNodes",Si,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.mergeAssignableViaNodes?.newNodes}}),Ti("singleLayerNodeMerger",Mi,t=>[t.capacityNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),Ti("edgeSolver",Ns,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Ti("offboardCapacityNodeSolver",Ci,t=>[{capacityNodes:t.capacityNodes,capacityEdges:t.capacityEdges||[]}],{onSolved:t=>{t.capacityEdges=t.offboardCapacityNodeSolver?.enhancedEdges||t.capacityEdges}}),Ti("deadEndSolver",Is,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges}],{onSolved:t=>{const e=t.deadEndSolver?.removedNodeIds;t.capacityNodes=t.capacityNodes.filter(t=>!e.has(t.capacityMeshNodeId)),t.capacityEdges=t.capacityEdges.filter(t=>t.nodeIds.every(t=>!e.has(t)))}}),Ti("initialPathingHyperSolver",Ni,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}],{onSolved:t=>{const e=t.initialPathingHyperSolver?.winningSolver;e&&(t.initialPathingSolver=e)}}),Ti("offboardPathFragmentSolver",Ei,t=>[{capacityPaths:t.initialPathingSolver?.getCapacityPaths()||[],capacityEdges:t.capacityEdges||[],capacityNodes:t.capacityNodes||[],connections:t.srjWithPointPairs?.connections||[]}],{onSolved:t=>{const e=t.offboardPathFragmentSolver;if(!e)return;const s=e.getFragmentedPaths();for(const e of s)if(e.isFragmentedPath&&e.mstPairConnectionName){const s=t.colorMap[e.mstPairConnectionName];s&&!t.colorMap[e.connectionName]&&(t.colorMap[e.connectionName]=s)}const n=e.getFragmentedOriginalConnectionNames(),i=e.getFragmentedConnections();n.size>0&&t.srjWithPointPairs&&(t.srjWithPointPairs={...t.srjWithPointPairs,connections:[...t.srjWithPointPairs.connections.filter(t=>!n.has(t.name)),...i]},t.connMap=Ie(t.srjWithPointPairs))}}),Ti("edgeToPortSegmentSolver",j,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.offboardPathFragmentSolver?.getFragmentedPaths()||t.initialPathingSolver?.getCapacityPaths()||[],colorMap:t.colorMap}]),Ti("segmentToPointSolver",q,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),Ti("unravelMultiSectionSolver",es,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),Ti("highDensityRouteSolver",be,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap}]),Ti("highDensityStitchSolver",De,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Ti("uselessViaRemovalSolver1",Un,t=>[{unsimplifiedHdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Ti("multiSimplifiedPathSolver1",ci,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver1?.getOptimizedHdRoutes()||t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}]),Ti("uselessViaRemovalSolver2",Un,t=>[{unsimplifiedHdRoutes:t.multiSimplifiedPathSolver1.simplifiedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Ti("multiSimplifiedPathSolver2",ci,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver2?.getOptimizedHdRoutes(),obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}])];currentPipelineStepIndex=0;_step(){const t=this.pipelineDef[this.currentPipelineStepIndex];if(!t)return void(this.solved=!0);if(this.activeSubSolver)return this.activeSubSolver.step(),void(this.activeSubSolver.solved?(this.endTimeOfPhase[t.solverName]=performance.now(),this.timeSpentOnPhase[t.solverName]=this.endTimeOfPhase[t.solverName]-this.startTimeOfPhase[t.solverName],t.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStepIndex++):this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null));const e=t.getConstructorParams(this);this.activeSubSolver=new t.solverClass(...e),this[t.solverName]=this.activeSubSolver,this.timeSpentOnPhase[t.solverName]=0,this.startTimeOfPhase[t.solverName]=performance.now()}solveUntilPhase(t){for(;this.getCurrentPhase()!==t;)this.step()}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();const e=this.netToPointPairsSolver?.visualize(),s=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),i=this.mergeAssignableViaNodes?.visualize(),o=this.singleLayerNodeMerger?.visualize(),a=this.strawSolver?.visualize(),r=this.edgeSolver?.visualize(),h=this.deadEndSolver?.visualize(),c=this.initialPathingSolver?.visualize(),d=this.offboardPathFragmentSolver?.visualize(),l=this.pathingOptimizer?.visualize(),u=this.edgeToPortSegmentSolver?.visualize(),p=this.segmentToPointSolver?.visualize(),f=this.unravelMultiSectionSolver?.visualize()??this.segmentToPointOptimizer?.visualize(),g=this.highDensityRouteSolver?.visualize(),m=this.highDensityStitchSolver?.visualize(),y=this.uselessViaRemovalSolver1?.visualize(),x=this.uselessViaRemovalSolver2?.visualize(),v=this.multiSimplifiedPathSolver1?.visualize(),M=this.multiSimplifiedPathSolver2?.visualize(),S=this.srj.outline,b=[];if(b.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),S&&S.length>=2){const t=S.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),b.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const N={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:t.layers?.join(", ")}))],lines:b},I=[N,e,s,n,i,o,a,r,h,c,d,l,u,p,f,g?t(N,g):null,m,y,v,x,M,this.solved?t(N,Fe(this.getOutputSimpleRouteJson())):null].filter(Boolean);return t(...I)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const s=this.highDensityRouteSolver.routes[e];if(t.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[s.connectionName]}),t.length>200)break}return{lines:t}}if(this.pathingOptimizer){const t=[];for(const e of this.pathingOptimizer.connectionsWithNodes)e.path&&t.push({points:e.path.map(t=>({x:t.center.x,y:t.center.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.multiSimplifiedPathSolver2?.simplifiedHdRoutes??this.uselessViaRemovalSolver2?.getOptimizedHdRoutes()??this.multiSimplifiedPathSolver1?.simplifiedHdRoutes??this.uselessViaRemovalSolver1?.getOptimizedHdRoutes()??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes(),s=this.srjWithPointPairs?.connections??[];for(const n of s){const s=n.netConnectionName,i=n.rootConnectionName,o=e.filter(t=>t.connectionName===n.name);for(let e=0;e<o.length;e++){const a=o[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??i??n.name,route:Ee(a,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}};export{wi as AssignableViaAutoroutingPipelineSolver,pi as AutoroutingPipelineSolver,fi as CapacityMeshSolver,J as InMemoryCache,tt as LocalStorageCache,Ce as calculateOptimalCapacityDepth,Fe as convertSrjToGraphicsObject,st as getGlobalInMemoryCache,et as getGlobalLocalStorageCache,Pe as getTunedTotalCapacity1,nt as setupGlobalCaches};//# sourceMappingURL=index.js.map
|