@tscircuit/capacity-autorouter 0.0.188 → 0.0.190

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.js CHANGED
@@ -1 +1 @@
1
- var t=(...t)=>{const e={points:[],lines:[],circles:[],rects:[]};return t.forEach((t,n)=>{t&&(t.lines&&(e.lines=[...e.lines||[],...t.lines.map(t=>({...t,step:n}))]),t.points&&(e.points=[...e.points||[],...t.points.map(t=>({...t,step:n}))]),t.circles&&(e.circles=[...e.circles||[],...t.circles.map(t=>({...t,step:n}))]),t.rects&&(e.rects=[...e.rects||[],...t.rects.map(t=>({...t,step:n}))]))}),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})`,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 n(){return n=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var s in n)({}).hasOwnProperty.call(n,s)&&(t[s]=n[s])}return t},n.apply(null,arguments)}function s(t,e){return(s=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t})(t,e)}function i(t){return(i=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function o(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(o=function(){return!!t})()}function a(t){var e="function"==typeof Map?new Map:void 0;return a=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,n)}function n(){return function(t,e,n){if(o())return Reflect.construct.apply(null,arguments);var i=[null];i.push.apply(i,e);var a=new(t.bind.apply(t,i));return n&&s(a,n.prototype),a}(t,arguments,i(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),s(n,t)},a(t)}var r={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 h(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];var s,i=e[0],o=[];for(s=1;s<e.length;s+=1)o.push(e[s]);return o.forEach(function(t){i=i.replace(/%[a-z]/,t)}),i}var c=function(t){var e,n;function i(e){var n;if("production"===process.env.NODE_ENV)n=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 s=arguments.length,i=new Array(s>1?s-1:0),o=1;o<s;o++)i[o-1]=arguments[o];n=t.call(this,h.apply(void 0,[r[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}(n)}return n=t,(e=i).prototype=Object.create(n.prototype),e.prototype.constructor=e,s(e,n),i}(a(Error));function d(t,e){return t.substr(-e.length)===e}var l=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;function u(t){return"string"!=typeof t?t:t.match(l)?parseFloat(t):t}var p=function(t){return function(e,n){void 0===n&&(n="16px");var s=e,i=n;if("string"==typeof e){if(!d(e,"px"))throw new c(69,t,e);s=u(e)}if("string"==typeof n){if(!d(n,"px"))throw new c(70,t,n);i=u(n)}if("string"==typeof s)throw new c(71,e,t);if("string"==typeof i)throw new c(72,n,t);return""+s/i+t}};p("em"),p("rem");function f(t){return Math.round(255*t)}function g(t,e,n){return f(t)+","+f(e)+","+f(n)}function m(t,e,n,s){if(void 0===s&&(s=g),0===e)return s(n,n,n);var i=(t%360+360)%360/60,o=(1-Math.abs(2*n-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=n-o/2;return s(r+d,h+d,c+d)}var y={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 x=/^#[a-fA-F0-9]{6}$/,v=/^#[a-fA-F0-9]{8}$/,M=/^#[a-fA-F0-9]{3}$/,S=/^#[a-fA-F0-9]{4}$/,N=/^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i,b=/^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,I=/^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 C(t){if("string"!=typeof t)throw new c(3);var e=function(t){if("string"!=typeof t)return t;var e=t.toLowerCase();return y[e]?"#"+y[e]:t}(t);if(e.match(x))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(v)){var n=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:n}}if(e.match(M))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(S)){var s=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:s}}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=b.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("+m(parseInt(""+a[1],10),parseInt(""+a[2],10)/100,parseInt(""+a[3],10)/100)+")",h=N.exec(r);if(!h)throw new c(4,e,r);return{red:parseInt(""+h[1],10),green:parseInt(""+h[2],10),blue:parseInt(""+h[3],10)}}var d=I.exec(e.substring(0,50));if(d){var l="rgb("+m(parseInt(""+d[1],10),parseInt(""+d[2],10)/100,parseInt(""+d[3],10)/100)+")",u=N.exec(l);if(!u)throw new c(4,e,l);return{red:parseInt(""+u[1],10),green:parseInt(""+u[2],10),blue:parseInt(""+u[3],10),alpha:parseFloat(""+d[4])>1?parseFloat(""+d[4])/100:parseFloat(""+d[4])}}throw new c(5)}function _(t){return function(t){var e,n=t.red/255,s=t.green/255,i=t.blue/255,o=Math.max(n,s,i),a=Math.min(n,s,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 n:e=(s-i)/h+(s<i?6:0);break;case s:e=(i-n)/h+2;break;default:e=(n-s)/h+4}return e*=60,void 0!==t.alpha?{hue:e,saturation:c,lightness:r,alpha:t.alpha}:{hue:e,saturation:c,lightness:r}}(C(t))}var E=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 T(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function w(t){return T(Math.round(255*t))}function A(t,e,n){return E("#"+w(t)+w(e)+w(n))}function z(t,e,n){return m(t,e,n,A)}function R(t,e,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n)return E("#"+T(t)+T(e)+T(n));if("object"==typeof t&&void 0===e&&void 0===n)return E("#"+T(t.red)+T(t.green)+T(t.blue));throw new c(6)}function O(t,e,n,s){if("string"==typeof t&&"number"==typeof e){var i=C(t);return"rgba("+i.red+","+i.green+","+i.blue+","+e+")"}if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof s)return s>=1?R(t,e,n):"rgba("+t+","+e+","+n+","+s+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===s)return t.alpha>=1?R(t.red,t.green,t.blue):"rgba("+t.red+","+t.green+","+t.blue+","+t.alpha+")";throw new c(7)}function L(t){if("object"!=typeof t)throw new c(8);if(function(t){return"number"==typeof t.red&&"number"==typeof t.green&&"number"==typeof t.blue&&"number"==typeof t.alpha}(t))return O(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 R(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,n,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof s)return s>=1?z(t,e,n):"rgba("+m(t,e,n)+","+s+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===s)return t.alpha>=1?z(t.hue,t.saturation,t.lightness):"rgba("+m(t.hue,t.saturation,t.lightness)+","+t.alpha+")";throw new c(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,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n)return z(t,e,n);if("object"==typeof t&&void 0===e&&void 0===n)return z(t.hue,t.saturation,t.lightness);throw new c(1)}(t);throw new c(8)}function D(t,e,n){return function(){var s=n.concat(Array.prototype.slice.call(arguments));return s.length>=e?t.apply(this,s):D(t,e,s)}}function F(t){return D(t,t.length,[])}F(function(t,e){if("transparent"===e)return e;var s=_(e);return L(n({},s,{hue:s.hue+parseFloat(t)}))});function $(t,e,n){return Math.max(t,Math.min(e,n))}F(function(t,e){if("transparent"===e)return e;var s=_(e);return L(n({},s,{lightness:$(0,1,s.lightness-parseFloat(t))}))});F(function(t,e){if("transparent"===e)return e;var s=_(e);return L(n({},s,{saturation:$(0,1,s.saturation-parseFloat(t))}))});F(function(t,e){if("transparent"===e)return e;var s=_(e);return L(n({},s,{lightness:$(0,1,s.lightness+parseFloat(t))}))});var k=F(function(t,e,s){if("transparent"===e)return s;if("transparent"===s)return e;if(0===t)return s;var i=C(e),o=n({},i,{alpha:"number"==typeof i.alpha?i.alpha:1}),a=C(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 O({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=C(e);return O(n({},s,{alpha:$(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);return L(n({},s,{saturation:$(0,1,s.saturation+parseFloat(t))}))});F(function(t,e){return"transparent"===e?e:L(n({},_(e),{hue:parseFloat(t)}))});F(function(t,e){return"transparent"===e?e:L(n({},_(e),{lightness:parseFloat(t)}))});F(function(t,e){return"transparent"===e?e:L(n({},_(e),{saturation:parseFloat(t)}))});F(function(t,e){return"transparent"===e?e:k(parseFloat(t),"rgb(0, 0, 0)",e)});F(function(t,e){return"transparent"===e?e:k(parseFloat(t),"rgb(255, 255, 255)",e)});var B=F(function(t,e){if("transparent"===e)return e;var s=C(e);return O(n({},s,{alpha:$(0,1,+(100*("number"==typeof s.alpha?s.alpha:1)-100*parseFloat(t)).toFixed(2)/100)}))}),X=["blue","orange","purple","cyan","magenta","yellowgreen","darkgoldenrod","deeppink"],Y=(t,e)=>{const n={};for(let s=0;s<t.connections.length;s++){const i=t.connections[s],o=e?.getNetConnectedToId(i.name);o&&!n[o]&&(n[o]=`hsl(${300*s/t.connections.length}, 100%, 50%)`),n[i.name]=(o?n[o]:null)??`hsl(${340*s/t.connections.length}, 100%, 50%)`}return n},H=(t,e)=>{try{return B(e,t)}catch(e){return console.error(e),t}};import j from"object-hash";var W=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 n=t.split(":")[0];return this.cacheHitsByPrefix[n]=(this.cacheHitsByPrefix[n]||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())}},V="tscircuit_autorouter_cache_",Z=class{isSyncCache=!0;cacheHits=0;cacheMisses=0;cacheHitsByPrefix={};cacheMissesByPrefix={};constructor(){}getKey(t){return`${V}${t}`}getCachedSolutionSync(t){if("undefined"==typeof localStorage)return;const e=this.getKey(t);try{const n=localStorage.getItem(e);if(null!==n){const e=JSON.parse(n);this.cacheHits++;const s=t.split(":")[0];return this.cacheHitsByPrefix[s]=(this.cacheHitsByPrefix[s]||0)+1,e}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}catch(n){console.error(`Error getting cached solution sync for ${e}:`,n),this.cacheMisses++;const s=t.split(":")[0];return void(this.cacheMissesByPrefix[s]=(this.cacheMissesByPrefix[s]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){if("undefined"==typeof localStorage)return;const n=this.getKey(t);try{const t=JSON.stringify(e);localStorage.setItem(n,t)}catch(t){console.error(`Error setting cached solution sync for ${n}:`,t),t instanceof DOMException&&("QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&console.warn(`LocalStorage quota exceeded. Failed to cache solution for ${n}. 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 n=localStorage.key(e);n?.startsWith(V)&&t.push(n)}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 n=localStorage.key(e);if(!n)break;n.includes(V)&&t.push(n)}return t}};function U(){return globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE||q(),globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE}function G(){return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE||q(),globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE}function q(){globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE??=new Z,globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE??=new W}function K(t){const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-n,maxY:t.center.y+n}}function J(t,e,n){return Math.max(e,Math.min(n,t))}function Q(t,e,n,s){const i=tt(t,e,n),o=tt(t,e,s),a=tt(n,s,t),r=tt(n,s,e);return i!==o&&a!==r||(!(0!==i||!et(t,n,e))||(!(0!==o||!et(t,s,e))||(!(0!==a||!et(n,t,s))||!(0!==r||!et(n,e,s)))))}function tt(t,e,n){const s=(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y);return 0===s?0:s>0?1:2}function et(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function nt(t,e,n){const s=(n.x-e.x)**2+(n.y-e.y)**2;if(0===s)return st(t,e);let i=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/s;i=Math.max(0,Math.min(1,i));return st(t,{x:e.x+i*(n.x-e.x),y:e.y+i*(n.y-e.y)})}function st(t,e){const n=t.x-e.x,s=t.y-e.y;return Math.sqrt(n*n+s*s)}function it(t,e,n,s){const i=e.x-t.x,o=e.y-t.y,a=s.x-n.x,r=s.y-n.y,h=t.x-n.x,c=t.y-n.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 ot(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var at=t=>{if("minX"in t)return t;const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,minY:t.center.y-n,maxX:t.center.x+e,maxY:t.center.y+n}},rt=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}],ht=t=>{const e=[];for(let n=0;n<t.length;n++){const s=t[n],i=t[(n+1)%t.length];e.push([s,i])}return e},ct=(t,e,n)=>{const s=(t.y-e.y)*(n.x-e.x)-(t.x-e.x)*(n.y-e.y);if(Math.abs(s)>1e-9)return!1;const i=(t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y);if(i<0)return!1;return!(i>(n.x-e.x)**2+(n.y-e.y)**2)},dt=(t,e)=>{if(e.length<3)return!1;const n=ht(e);for(const[e,s]of n)if(ct(t,e,s))return!0;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},lt=(t,e)=>{const n=rt(t),s=[[n[0],n[1]],[n[1],n[2]],[n[2],n[3]],[n[3],n[0]]],i=ht(e);for(const[t,e]of i)for(const[n,i]of s)if(Q(t,e,n,i))return!0;return!1},ut=(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))||(!!rt(t).some(t=>dt(t,e))||lt(t,e))))(at(t),e),pt=(t,e)=>((t,e)=>!(e.length<3)&&(!!rt(t).every(t=>dt(t,e))&&!lt(t,e)))(at(t),e);function ft(t,e,n,s){if(t.x===e.x&&t.y===e.y)return nt(t,n,s);if(n.x===s.x&&n.y===s.y)return nt(n,t,e);if(Q(t,e,n,s))return 0;const i=[nt(t,n,s),nt(e,n,s),nt(n,t,e),nt(s,t,e)];return Math.min(...i)}function gt(t,e,n){const s=n.width/2,i=n.height/2;return function(t,e,n){const s={x:n.minX,y:n.minY},i={x:n.maxX,y:n.minY},o={x:n.minX,y:n.maxY},a={x:n.maxX,y:n.maxY};if(Q(t,e,s,i)||Q(t,e,i,a)||Q(t,e,a,o)||Q(t,e,o,s))return 0;if(t.x>=n.minX&&t.x<=n.maxX&&t.y>=n.minY&&t.y<=n.maxY&&e.x>=n.minX&&e.x<=n.maxX&&e.y>=n.minY&&e.y<=n.maxY)return 0;const r=[nt(s,t,e),nt(i,t,e),nt(o,t,e),nt(a,t,e)];if(t.x>=n.minX&&t.x<=n.maxX&&t.y>=n.minY&&t.y<=n.maxY)return 0;if(e.x>=n.minX&&e.x<=n.maxX&&e.y>=n.minY&&e.y<=n.maxY)return 0;if(t.x<n.minX||t.x>n.maxX||t.y<n.minY||t.y>n.maxY){const e=J(t.x,n.minX,n.maxX),s=J(t.y,n.minY,n.maxY);r.push(st(t,{x:e,y:s}))}if(e.x<n.minX||e.x>n.maxX||e.y<n.minY||e.y>n.maxY){const t=J(e.x,n.minX,n.maxX),s=J(e.y,n.minY,n.maxY);r.push(st(e,{x:t,y:s}))}return Math.min(...r)}(t,e,{minX:n.center.x-s,maxX:n.center.x+s,minY:n.center.y-i,maxY:n.center.y+i})}function mt(t,e,n){const s=n.x-e.x,i=n.y-e.y,o=s*s+i*i;if(0===o)return{x:e.x,y:e.y};let a=((t.x-e.x)*s+(t.y-e.y)*i)/o;a=Math.max(0,Math.min(1,a));return{x:e.x+a*s,y:e.y+a*i}}var yt=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 n=this.heap[t];this.heap[t]=this.heap[e],this.heap[e]=n}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}}},xt=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=st(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 n=this.boundsSize.width/this.cellStep,s=this.boundsSize.height/this.cellStep;for(;n*s>e**2&&!(2*this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,n=this.boundsSize.width/this.cellStep,s=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 yt([{...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,n=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:n,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,n){if(e??=this.obstacleMargin,n&&t.parent){const n=this.getViasInNodePath(t.parent);for(const s of n)if(st(t,s)<this.viaDiameter/2+e)return!0}for(const s of this.obstacleRoutes){const i=this.connMap?.areIdsConnected?.(this.connectionName,s.connectionName);if(!i){const i=vt(s);for(const s of i)if((n||s.z===t.z)&&nt(t,s.A,s.B)<this.traceThickness+e)return!0}for(const n of s.vias)if(st(t,n)<this.viaDiameter/2+this.traceThickness/2+e)return!0}return!1}isNodeTooCloseToEdge(t,e){const n=e?this.viaDiameter/2+this.obstacleMargin/2:this.obstacleMargin/2,s=t.x<this.bounds.minX+n||t.x>this.bounds.maxX-n||t.y<this.bounds.minY+n||t.y>this.bounds.maxY-n;return!(s&&!e&&(st(t,this.B)<2*n||st(t,this.A)<2*n))&&s}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!s)for(const s of vt(n))if(s.z===t.z&&Q(t,e,s.A,s.B))return!0}return!1}computeH(t){return st(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)+st(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:n,minX:s,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:Mt(t.x+a*this.cellStep,s,n),y:Mt(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 n=0;n<this.layerCount;n++){if(n===t.z)continue;const s={...t,parent:t,z:n};this.exploredNodes.has(this.getNodeKey(s))||this.isNodeTooCloseToObstacle(s,this.viaDiameter/2+this.obstacleMargin/2,!0)||this.isNodeTooCloseToEdge(s,!0)||(s.g=this.computeG(s),s.h=this.computeH(s),s.f=this.computeF(s.g,s.h),e.push(s))}return e}getNodePath(t){const e=[];for(;t;)e.push(t),t=t.parent;return e}getViasInNodePath(t){const e=this.getNodePath(t),n=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&n.push({x:e[t].x,y:e[t].y});return n}setSolvedPath(t){const e=this.getNodePath(t);e.reverse();const n=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&n.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:n}}computeProgress(t,e,n){n||(e+=this.viaPenaltyDistance);const s=1-e/this.straightLineDistance;return Math.max(this.progress||0,2/Math.PI*Math.atan(.112*s/(1-s)))}_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 this.failed=!0,void(this.error="Ran out of candidate nodes to explore");this.exploredNodes.add(e),this.debug_exploredNodesOrdered.push(e);const n=st(t,this.B);this.progress=this.computeProgress(t,n,t.z===this.B.z),n<=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 s=this.getNeighbors(t);for(const t of s)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 n=this.obstacleRoutes[e];for(let s=0;s<n.route.length-1;s++){const i=n.route[s].z;t.lines.push({points:[n.route[s],n.route[s+1]],strokeColor:0===i?"rgba(255, 0, 0, 0.75)":"rgba(255, 128, 0, 0.25)",strokeWidth:n.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`})}}for(let e=0;e<this.debug_exploredNodesOrdered.length;e++){const n=this.debug_exploredNodesOrdered[e],[s,i,o]=n.split(",").map(Number);this.debug_nodesTooCloseToObstacle.has(n)||(this.debug_nodePathToParentIntersectsObstacle.has(n)||t.rects.push({center:{x:s+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 n of e.vias)t.circles.push({center:{x:n.x,y:n.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 vt(t){const e=[];for(let n=0;n<t.route.length-1;n++)t.route[n].z===t.route[n+1].z&&e.push({z:t.route[n].z,A:t.route[n],B:t.route[n+1]});return e}function Mt(t,e,n){return Math.max(e,Math.min(t,n))}var St=class extends xt{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,n=Math.max(1,this.numRoutes);this.VIA_PENALTY_FACTOR=e/n*.3*this.VIA_PENALTY_FACTOR_2}getClosestFutureConnectionPoint(t){let e=1/0,n=null;for(const s of this.futureConnections)for(const i of s.points){const s=st(t,i)+(t.z!==i.z?this.viaPenaltyDistance:0);s<e&&(e=s,n=i)}return n}diminishCloseToGoal(t){const e=st(t,this.B);return 1-Math.exp(-e/this.straightLineDistance*5)}getFutureConnectionPenalty(t,e){let n=0;const s=this.getClosestFutureConnectionPoint(t),i=st(t,this.B);if(s){const o=st(t,s);if(i<=o)return 0;const a=o/(this.viaDiameter*this.FUTURE_CONNECTION_PROXIMITY_VD);n=(e?this.straightLineDistance*this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR:this.straightLineDistance*this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR)*Math.exp(5*-a)}return n}computeH(t){const e=st(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),n=Math.abs(t.y-t.parent.y),s=Math.sqrt(e**2+n**2),i=t.z%2==0,o=this.FLIP_TRACE_ALIGNMENT_DIRECTION?i?e:n:i?n:e;return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+s+o*this.MISALIGNED_DIST_PENALTY_FACTOR+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}};function Nt(t){let e=t;for(let t=0;t<10;t++)e=16807*e%2147483647;let n=e;e=(69069*t+1)%2147483647;for(let t=0;t<10;t++)e=48271*e%2147483647;let s=e;return()=>{let t=n;n=s,t^=t<<23,t^=t>>>17,t^=s,t^=s>>>26,s=t;const e=(n+s)/4294967296;return e-Math.floor(e)}}var bt={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 Pt(t,e){if(0===e)return t;if(t.length<=4){const n=bt[t.length];return n[e%n.length].map(e=>t[e])}const n=Nt(e),s=t.slice();for(let t=0;t<s.length;t++){const e=Math.floor(n()*s.length),i=Math.floor(n()*(t+1));[s[e],s[i]]=[s[i],s[e]]}return s}function It(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 n of t.portPoints)n.x<e.minX&&(e.minX=n.x),n.x>e.maxX&&(e.maxX=n.x),n.y<e.minY&&(e.minY=n.y),n.y>e.maxY&&(e.maxY=n.y);return e}var Ct=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:n}=t;super(),this.nodeWithPortPoints=e,this.colorMap=n??{},this.solvedRoutes=[],this.hyperParameters=t.hyperParameters??{},this.failedSubSolvers=[],this.connMap=t.connMap,this.viaDiameter=t.viaDiameter??.6,this.traceWidth=t.traceWidth??.15;const s=new Map;for(const{connectionName:t,x:n,y:i,z:o}of e.portPoints)s.set(t,[...s.get(t)??[],{x:n,y:i,z:o??0}]);this.unsolvedConnections=Array.from(s.entries().map(([t,e])=>({connectionName:t,points:e}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=Pt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},n)=>({...e,points:Pt(t,7117*n+(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 n=t.portPoints;for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++){if(n[t].z!==n[s].z)continue;const i=n[t],o=n[s],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,n]=t.points,s=Math.abs(e.x-n.x)<1e-6,i=Math.abs(e.y-n.y)<1e-6;if(s&&i&&e.z===n.z)return;if(s&&i&&e.z!==n.z){const s={x:this.nodeWithPortPoints.center.x,y:this.nodeWithPortPoints.center.y},i=[{x:e.x,y:e.y,z:e.z},{...s,z:e.z},{...s,z:n.z},{x:n.x,y:n.y,z:n.z}].filter((t,e,n)=>0===e||Math.abs(t.x-n[e-1].x)>1e-6||Math.abs(t.y-n[e-1].y)>1e-6||t.z!==n[e-1].z);return void this.solvedRoutes.push({connectionName:t.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:i,vias:[s]})}}const{connectionName:e,points:n}=t;this.activeSubSolver=new St({connectionName:e,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:It(this.nodeWithPortPoints),A:{x:n[0].x,y:n[0].y,z:n[0].z},B:{x:n[n.length-1].x,y:n[n.length-1].y,z:n[n.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 n=this.solvedRoutes[e];if(n.route.length>0){const s=this.colorMap[n.connectionName]??"blue";for(let i=0;i<n.route.length-1;i++){const o=n.route[i],a=n.route[i+1];t.lines.push({points:[o,a],strokeColor:0===o.z?H(s,.2):H(s,.8),layer:`route-layer-${o.z}`,step:e,strokeWidth:n.traceThickness})}for(const i of n.vias)t.circles.push({center:{x:i.x,y:i.y},radius:n.viaDiameter/2,fill:H(s,.5),layer:"via",step:e})}}const e=It(this.nodeWithPortPoints),{minX:n,minY:s,maxX:i,maxY:o}=e;return t.lines.push({points:[{x:n,y:s},{x:i,y:s},{x:i,y:o},{x:n,y:o},{x:n,y:s}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}},_t=t=>Math.round(200*t)/200,Et=t=>"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t));q();var Tt=class extends Ct{cacheProvider;cacheHit=!1;hasAttemptedToUseCache=!1;initialUnsolvedConnections;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?G():t.cacheProvider,this.initialUnsolvedConnections=Et(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:n})=>({connectionName:e,points:n.map(n=>({connectionName:e,x:_t(n.x-t.x),y:_t(n.y-t.y),z:n.z??0}))})),n=Object.fromEntries(Object.entries(this.hyperParameters??{}).filter(([,t])=>void 0!==t).sort(([t],[e])=>t.localeCompare(e))),s=this.connMap?this.initialUnsolvedConnections.map(({connectionName:t})=>({connectionName:t,connectedIds:[...new Set(this.connMap.getIdsConnectedToNet(t)??[])].sort()})):void 0,i={node:{width:_t(this.nodeWithPortPoints.width),height:_t(this.nodeWithPortPoints.height),center:{x:_t(this.nodeWithPortPoints.center.x),y:_t(this.nodeWithPortPoints.center.y)},availableZ:this.nodeWithPortPoints.availableZ?[...this.nodeWithPortPoints.availableZ].sort():void 0},normalizedConnections:e,normalizedHyperParameters:n,minDistBetweenEnteringPoints:_t(this.minDistBetweenEnteringPoints),normalizedConnMap:s},o=`intranode-solver:${j(i)}`,a={};return this.cacheKey=o,this.cacheToSolveSpaceTransform=a,{cacheKey:o,cacheToSolveSpaceTransform:a}}applyCachedSolution(t){t.success?(this.solvedRoutes=Et(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:Et(this.solvedRoutes)};try{this.cacheProvider.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}},wt=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[n,...s]=t,i=this.getHyperParameterCombinations(s);return n.possibleValues.forEach(t=>{i.forEach(n=>{e.push({...n,...t})})}),e}initializeSolvers(){const t=this.getHyperParameterDefs(),e=this.getCombinationDefs()??[t.map(t=>t.name)];this.supervisedSolvers=[];for(const n of e){const e=this.getHyperParameterCombinations(t.filter(t=>n.includes(t.name)));for(const t of e){const e=this.generateSolver(t),n=this.computeG(e);this.supervisedSolvers.push({hyperParameters:t,solver:e,h:0,g:n,f:n})}}}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 n of this.supervisedSolvers??[]){if(n.solver.solved)return n;if(n.solver.failed)continue;const s=n.f;s<t&&(t=s,e=n)}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 At({A:t,B:e,C:n,D:s,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,n)=>{const s=e.x-t.x,i=e.y-t.y,o=Math.sqrt(s*s+i*i),a=s/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*n,y:t.y-r*n},A_Right:{x:t.x+h*n,y:t.y+c*n},A_Left:{x:t.x-h*n,y:t.y-c*n},B_Opp:{x:e.x+a*n,y:e.y+r*n},B_Right:{x:e.x+h*n,y:e.y+c*n},B_Left:{x:e.x-h*n,y:e.y-c*n}}},l=(t,e)=>{const n=st(t,e.start),s=st(t,e.end),i=st(e.start,e.end);return Math.abs(n+s-i)<1e-4},u=(t,e)=>{const{start:n,end:s}=t,{start:i,end:o}=e;if(l(n,e)||l(s,e)||l(i,t)||l(o,t))return!0;const a=s.x-n.x,r=s.y-n.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-n.x,p=i.y-n.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 n=[];for(let e=0;e<t.length-1;e++)n.push({start:t[e],end:t[e+1]});const s=[];for(let t=0;t<e.length-1;t++)s.push({start:e[t],end:e[t+1]});for(const t of n)for(const e of s)if(u(t,e))return!0;return!1},f=t=>{let e=0;for(let n=1;n<t.length;n++){const s=t[n].x-t[n-1].x,i=t[n].y-t[n-1].y;e+=Math.sqrt(s*s+i*i)}return e},g=(t,e)=>{const{start:n,end:s}=t,i=s.x-n.x,o=s.y-n.y,a=i*i+o*o;if(0===a)return{...n,t:0};const r=Math.max(0,Math.min(1,((e.x-n.x)*i+(e.y-n.y)*o)/a));return{x:n.x+r*i,y:n.y+r*o,t:r}},m=(e,n,s)=>{const i=g(e,n);if(st(i,n)>=s)return i;const o=i.x-n.x,a=i.y-n.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:n.x+s*o/r,y:n.y+s*a/r,t:i.t,isSpecial:!0,specialType:n===t?"A":"B"}}return{x:n.x+s*o/r,y:n.y+s*a/r,t:i.t,isSpecial:!0,specialType:n===t?"A":"B"}},y=d(t,e,a),x=d(t,e,a+r),v=(t,e,n,s,i)=>{const o=t.points;if(o.length<2)return o;const r=n+s,h=[o[0]];for(let t=0;t<o.length-1;t++){const n={start:o[t],end:o[t+1]};if(nt(e,n.start,n.end)<r){const t=g(n,e),s=t.x-e.x,i=t.y-e.y,o=Math.sqrt(s*s+i*i);let c=null;if(o>1e-6)c={x:e.x+r*s/o,y:e.y+r*i/o};else{const t=n.end.x-n.start.x,s=n.end.y-n.start.y,i=Math.sqrt(t*t+s*s);i>1e-6&&(c={x:e.x+r*t/i,y:e.y+r*s/i})}c&&st(n.start,c)>a/10&&h.push(c)}st(h[h.length-1],n.end)>a/10&&h.push(n.end)}if(h.length>1){const t=[h[0]];for(let e=1;e<h.length;e++)st(t[t.length-1],h[e])>a/10&&t.push(h[e]);return t}return h},M=(()=>{const t=[[n,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,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],[s,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,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]],e=[];for(let n=0;n<t.length;n++){const s=t[n],i={start:s[0],end:s[1]},o={start:s[s.length-2],end:s[s.length-1]},a={start:s[3],end:s[4]};u(i,o)||u(i,a)||u(o,a)||e.push({index:n+1,path:s,length:f(s)})}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=st(a,o[2]),h=st(a,o[3]),d=r<h?2:3;(r<st(a,o[1])||h<st(a,o[1]))&&o.splice(1,d-1);const l=o[o.length-1],p=st(l,o[o.length-3]),g=st(l,o[o.length-4]),m=p<g?o.length-3:o.length-4;return(p<st(l,o[o.length-2])||g<st(l,o[o.length-2]))&&o.splice(m+1,o.length-m-2),{index:i.index,path:o,startsAt:o[0]===n?"C":"D",goesTo:o[o.length-1]===n?"C":"D"}})(),S=h>0?((n,s)=>{if(n.length<2)return n;const i=[n[0]];for(let o=0;o<n.length-1;o++){const r={start:n[o],end:n[o+1]},h={x:(r.start.x+r.end.x)/2,y:(r.start.y+r.end.y)/2},c=st(h,t),d=st(h,e);if((c<=a||d<=a)&&Math.abs(c-d)>1e-4){const n=g(r,t),o=g(r,e),h=st(n,t),c=st(o,e)<a,d=h<a?m(r,t,a):null,l=c?m(r,e,a):null;let u=[];if(st(r.start,r.end)>a/2&&s>0)for(let n=1;n<=s;n++){const i=n/(s+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=st(o,t),c=st(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 n=t[t.length-1],s=u[e];st(n,s)>a/10&&t.push(s)}u=t}u.forEach(t=>i.push(t))}i.push(n[o+1])}if(i.length>1){const t=[i[0]];for(let e=1;e<i.length;e++){const n=t[t.length-1],s=i[e];st(n,s)>a/10&&t.push(s)}return t}return i})(M.path,h):M.path;let N=(()=>{if(0===M.path.length)return null;const n=(()=>{const n=c(y.A_Right,y.B_Right),s=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,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,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,x.A_Right,n,e]},{startsAt:"F",goesTo:"B",points:[o,x.B_Right,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Left,s,t]},{startsAt:"F",goesTo:"A",points:[o,x.A_Left,s,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Opp,x.B_Left,s,t]},{startsAt:"F",goesTo:"B",points:[o,x.A_Opp,x.A_Left,s,e]},{startsAt:"F",goesTo:"A",points:[o,x.B_Opp,x.B_Right,n,t]},{startsAt:"F",goesTo:"A",points:[o,x.B_Opp,x.B_Left,s,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Opp,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Opp,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Left,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Right,x.B_Opp,x.B_Left,s,t]},{startsAt:"F",goesTo:"B",points:[o,x.A_Right,x.A_Opp,x.A_Left,s,e]},{startsAt:"F",goesTo:"A",points:[o,x.B_Left,x.B_Opp,x.B_Right,n,t]},{startsAt:"F",goesTo:"A",points:[o,x.B_Right,x.B_Opp,x.B_Left,s,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Right,x.A_Opp,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Left,x.B_Opp,x.B_Right,n,t]}].map((t,e)=>({...t,index:e}))})(),s=n.filter(t=>"E"===t.startsAt),a=n.filter(t=>"F"===t.startsAt),r=[],h=[];for(const t of s)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(N){const n="A"===N.line1.goesTo?e:t,s="A"===N.line2.goesTo?e:t,i=v(N.line1,n,a,r),o=v(N.line2,s,a,r);N={line1:{...N.line1,points:i},line2:{...N.line2,points:o}}}return{jPair:N,optimalPath:{startsAt:M.startsAt,goesTo:M.goesTo,points:S}}}var zt=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 this.failed=!0,void(this.error=`Expected 2 routes, but got ${this.routes.length}`);const[e,n]=this.routes;if(!(e.startPort.z===e.endPort.z))return this.failed=!0,void(this.error="Route A must start and end on the same layer");if(!(n.startPort.z===n.endPort.z))return this.failed=!0,void(this.error="Route B must start and end on the same layer");if(!(e.startPort.z===n.startPort.z))return this.failed=!0,void(this.error="Both routes must be on the same layer");0===e.startPort.z?this.escapeLayer=1:this.escapeLayer=0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e)?.push(t)}for(const[e,s]of n.entries())2===s.length&&t.push({startPort:{...s[0],z:s[0].z??0},endPort:{...s[1],z:s[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 Q(t.startPort,t.endPort,e.startPort,e.endPort)}calculateViaPositions(t,e){const n=this.bounds.maxX-this.bounds.minX,s=this.bounds.maxY-this.bounds.minY,i=this.bounds.minX,o=this.bounds.minY,a={width:n-2*this.obstacleMargin-this.viaDiameter,height:s-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)=>st(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((n,s)=>{((t,e)=>{const n=t.x,s=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-n)**2;if(e<0)return[];if(Math.abs(e)<.001){const e=s;return e>=Math.min(a,h)&&e<=Math.max(a,h)?[{x:t,y:e}]:[]}const r=s+Math.sqrt(e),c=s-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*s-n),p=u*u-4*l*(n*n+(d-s)*(d-s)-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},n).forEach(t=>{l(t,0===e?c:h)>=r&&u.push({...t,type:"intersection",circle:e,edge:s})})})}),u.length<2){const t=.8*r;if(d.forEach((e,n)=>{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:n})}),u.length<2){const t=[...d].sort((t,e)=>{const n=Math.min(l(t,h),l(t,c));return Math.min(l(e,h),l(e,c))-n});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 n=l(u[t],u[e]);n>f&&(f=n,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=st(m,t.startPort);return st(y,t.startPort)<x&&([m,y]=[y,m]),{via1:m,via2:y}}trySolveAOverB(t,e,n=!1){const s=n?this.calculateViaPositions(t,e):this.calculateViaPositions(e,t);if(!s)return!1;this.debugViaPositions.push(s);const{via1:i,via2:o}=this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(s));this.debugViaPositions.push({via1:i,via2:o});const{jPair:a,optimalPath:r}=At({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},n={...t.via2},s=[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 s){const s=st(e,t);if(s<o){const n=(o-s)*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*n,e.y+=r/c*n,a=!0)}const i=st(n,t);if(i<o){const e=(o-i)*h,s=n.x-t.x,a=n.y-t.y,c=Math.sqrt(s*s+a*a);c>1e-6&&(n.x+=s/c*e,n.y+=a/c*e,r=!0)}}const c=st(e,n);if(c<i){const t=(i-c)/2,s=n.x-e.x,o=n.y-e.y,h=Math.sqrt(s*s+o*o);h>1e-6?(e.x-=s/h*t,e.y-=o/h*t,n.x+=s/h*t,n.y+=o/h*t,a=!0,r=!0):(e.x-=t,n.x+=t,a=!0,r=!0)}if(!a&&!r)break}const a=st(e,n);if(a<i){const t=(i-a)/2,s=n.x-e.x,o=n.y-e.y,r=Math.sqrt(s*s+o*o);r>1e-6?(e.x-=s/r*t,e.y-=o/r*t,n.x+=s/r*t,n.y+=o/r*t):(e.x-=t,n.x+=t)}return{via1:e,via2:n}}getMinDistanceBetweenViaCenters(){return this.viaDiameter+this.traceThickness+2*this.obstacleMargin}moveViasAsCloseAsPossible(t){const{via1:e,via2:n}=t,s=this.getMinDistanceBetweenViaCenters(),i=st(e,n);if(i<=s)return t;const o=n.x-e.x,a=n.y-e.y,r=Math.sqrt(o*o+a*a),h=o/r,c=a/r,d=(e.x,n.x,e.y,n.y,(i-s)/2);return{via1:{x:e.x+h*d,y:e.y+c*d},via2:{x:n.x-h*d,y:n.y-c*d}}}handleRoutesDontCross(){const[t,e]=this.routes,n={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:[]},s={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(n,s),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.error="All crossover strategies failed"):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,n]of[["Route A",this.routes[0]],["Route B",this.routes[1]]])t.points.push({x:n.startPort.x,y:n.startPort.y,label:`${e}\n${n.connectionName} start`,color:"orange"}),t.points.push({x:n.endPort.x,y:n.endPort.y,label:`${e}\n${n.connectionName} end`,color:"orange"}),t.lines.push({points:[n.startPort,n.endPort],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e}\n${n.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via1:n,via2:s}=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:n,radius:this.viaDiameter/2,fill:o,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via A (attempt ${e+1})`}),t.circles.push({center:s,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:n,radius:a,stroke:o,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 1 Safety Margin (attempt ${e+1})`}),t.circles.push({center:s,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,n,s,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 n=this.solvedRoutes[e],s=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<n.route.length-1;e++){const i=n.route[e],o=n.route[e+1];t.lines.push({points:[i,o],strokeColor:s,strokeDash:1===i.z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${i.z}`}),i._label&&t.points.push({x:i.x,y:i.y,label:i._label})}for(const e of n.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 Rt(t,e,n,s,i){const o={x:(t.x+e.x+n.x)/3,y:(t.y+e.y+n.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,n),d=o.x>=i.minX&&o.x<=i.maxX&&o.y>=i.minY&&o.y<=i.maxY;return r>=s&&h>=s&&c>=s&&d};if(r(o))return o;const h=(t,e,n)=>{const s=t.x-e.x,i=t.y-e.y,o=Math.sqrt(s*s+i*i);return o<1e-10?{x:e.x+n,y:e.y}:{x:e.x+s/o*n,y:e.y+i/o*n}},c=(t,e,n)=>{const s=e.x-t.x,i=e.y-t.y,o=Math.sqrt(s*s+i*i);if(o>2*n-1e-10||o<1e-10)return[];const r=o*o/(2*o),h=Math.sqrt(Math.max(0,n*n-r*r)),c=t.x+s*r/o,d=t.y+i*r/o,l={x:c+h*i/o,y:d-h*s/o},u={x:c-h*i/o,y:d+h*s/o},p=[],f=1e-6;return Math.abs(a(l,t)-n)<f&&Math.abs(a(l,e)-n)<f&&p.push(l),Math.abs(a(u,t)-n)<f&&Math.abs(a(u,e)-n)<f&&p.push(u),p},d=[h(o,t,s),h(o,e,s),h(o,n,s),...c(t,e,s),...c(e,n,s),...c(n,t,s)],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 n={x:t,y:e};if(r(n)){const t=a(n,o);t<p&&(p=t,u=n)}}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,s-a(o,t))+Math.max(0,s-a(o,e))+Math.max(0,s-a(o,n));i<m&&(m=i,y=o)}return y}function Ot(t,e,n){const s=Lt(e,t,n.center,n.radius),i=Lt(t,e,n.center,n.radius),o=Dt(s,e),a=Dt(t,i),r=1e-6;let h;if(o>r&&a>r){h={x:(s.x+i.x)/2,y:(s.y+i.y)/2};const o=Dt(s,h),a=Dt(i,h);if(Math.abs(o-a)>.5*Math.min(o,a)){const n=Dt(t,s),o=Dt(e,i),a=n+o;if(a>r){const t=o/a,e=n/a;h={x:s.x*t+i.x*e,y:s.y*t+i.y*e}}}const c=Dt(h,n.center);if(c<1.05*n.radius){const t={x:(h.x-n.center.x)/c,y:(h.y-n.center.y)/c};h={x:n.center.x+t.x*n.radius*1.2,y:n.center.y+t.y*n.radius*1.2}}}else{const s={x:(t.x+e.x)/2,y:(t.y+e.y)/2},i=Dt(s,n.center);if(i<1.1*n.radius){const t={x:(s.x-n.center.x)/i,y:(s.y-n.center.y)/i};h={x:n.center.x+t.x*n.radius*1.2,y:n.center.y+t.y*n.radius*1.2}}else h=s}return{B:s,D:i,E:h}}function Lt(t,e,n,s){const i=[n.x-t.x,n.y-t.y],o=Math.sqrt(i[0]*i[0]+i[1]*i[1]);if(o<=s){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:n.x+s,y:n.y}:{x:n.x+i[0]/o*s,y:n.y+i[1]/o*s}}const a=[i[0]/o,i[1]/o];return{x:n.x-a[0]*s,y:n.y-a[1]*s}}const a=[e.x-t.x,e.y-t.y],r=Math.sqrt(o*o-s*s),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=s/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 Dt(t,e){const n=e.x-t.x,s=e.y-t.y;return Math.sqrt(n*n+s*s)}var Ft=1e-9;function $t(t,e,n,s="cw"){const i=kt(t,n),o=kt(e,n);return Math.abs(o-i)<Ft?{left:0,top:0,right:0,bottom:0}:function(t,e,n,s){const i=n.maxX-n.minX,o=n.maxY-n.minY;if(i<Ft&&o<Ft)return{left:0,top:0,right:0,bottom:0};const a=2*(i+o);if(a<Ft)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,n,s,i)=>{const o=e>2*Math.PI-Ft?2*Math.PI:e;if(o<=t+Ft)return 0;if(i){const e=Math.max(t,n),i=Math.min(o,2*Math.PI),a=Math.max(0,i-e),r=Math.max(t,0),h=Math.min(o,s);return a+Math.max(0,h-r)}{const e=Math.max(t,n),i=Math.min(o,s);return Math.max(0,i-e)}};for(const n of l){const i=n.end-n.start;if(i<Ft||n.length<Ft)continue;let o=0;if("cw"===s){const s=t>e+Ft;o=p(n.start,n.end,t,e,s)}else{const s=e>t+Ft;o=p(n.start,n.end,e,t,s)}if(o>Ft){const t=o/i;u[n.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,n,s)}function kt(t,e){const n=e.maxX-e.minX,s=e.maxY-e.minY;if(n<Ft&&s<Ft)return 0;const i=2*(n+s);if(i<Ft)return 0;let o=0;if(Math.abs(t.y-e.maxY)<Ft&&t.x>=e.minX-Ft&&t.x<=e.maxX+Ft)o=Math.max(0,Math.min(n,t.x-e.minX));else if(Math.abs(t.x-e.maxX)<Ft&&t.y>=e.minY-Ft&&t.y<=e.maxY+Ft)o=n+Math.max(0,Math.min(s,e.maxY-t.y));else if(Math.abs(t.y-e.minY)<Ft&&t.x>=e.minX-Ft&&t.x<=e.maxX+Ft)o=n+s+Math.max(0,Math.min(n,e.maxX-t.x));else{if(!(Math.abs(t.x-e.minX)<Ft&&t.y>=e.minY-Ft&&t.y<=e.maxY+Ft))throw new Error(`Point (${t.x}, ${t.y}) does not lie on the boundary defined by ${JSON.stringify(e)}`);o=n+s+n+Math.max(0,Math.min(s,t.y-e.minY))}return o=Math.max(0,Math.min(i,o)),i>Ft?o/i*(2*Math.PI):0}function Bt(t,e,n,s){return function({angleA:t,angleB:e,angleC:n}){const s=Math.cos(t),i=Math.sin(t),o=Math.cos(e),a=Math.sin(e),r=Math.cos(n);return(o-s)*(Math.sin(n)-i)-(a-i)*(r-s)<0?"ccw":"cw"}({angleA:kt(t,s),angleB:kt(e,s),angleC:kt(n,s)})}var Xt=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 this.failed=!0,void(this.error=`Expected 2 routes, but got ${this.routes.length}`);const[e,n]=this.routes,s=e.A.z!==e.B.z,i=n.A.z!==n.B.z;return s&&i||!s&&!i?(this.failed=!0,void(this.error="Exactly one route must have a layer transition")):void 0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e)?.push(t)}for(const[e,s]of n.entries())2===s.length&&t.push({A:{...s[0],z:s[0].z??0},B:{...s[1],z:s[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 Q(t.A,t.B,e.A,e.B)}calculateViaPosition(t,e){const n=e.A.z,s=t.A.z!==n?t.A:t.B,i=2*this.obstacleMargin+this.viaDiameter/2+this.traceThickness,o=this.obstacleMargin+this.viaDiameter/2,a=e.A,r=s,h=e.B,c=Bt(a,r,h,this.bounds),d=function(t,e,n,s,i){const o=$t(t,e,s,i),a=$t(e,n,s,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])<Ft&&(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),Rt(a,r,h,i,l)}createTransitionRoute(t,e,n,s){return{connectionName:s,route:[{x:t.x,y:t.y,z:t.z??0},{x:n.x,y:n.y,z:t.z??0},{x:n.x,y:n.y,z:e.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[n]}}createFlatRoute(t,e,n,s,i,o){s.z,t.z;const a=this.viaDiameter/2+this.traceThickness/2+this.obstacleMargin,r=((t,e,n,s)=>{const i=n.x-t.x,o=n.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:n.x-i*s,y:n.y-o*s})})(n,this.viaDiameter,s.z!==t.z?s:i,this.traceThickness),h={center:{x:n.x,y:n.y},radius:a},c=Ot(t,r,h).E,d=Ot(r,e,h).E,l=Ot(t,c,h).E,u=Ot(c,r,h).E,p=Ot(r,d,h).E,f=Ot(d,e,h).E,g=Ot(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,n=t.A.z!==t.B.z,s=n?t:e,i=n?e:t,o=this.calculateViaPosition(s,i);if(!o)return!1;this.debugViaPositions.push({via:o});const a=this.createTransitionRoute(s.A,s.B,o,s.connectionName),r=this.createFlatRoute(i.A,i.B,o,s.A,s.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,this.error="Failed to find a valid via position and route path")}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:n}=this.debugViaPositions[e];t.circles.push({center:n,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 s=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:n,radius:s,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 n=this.solvedRoutes[e],s=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<n.route.length-1;e++){const i=n.route[e],o=n.route[e+1];t.lines.push({points:[i,o],strokeColor:s,strokeDash:i.z!==n.route[0].z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${i.z}`})}for(const e of n.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}},Yt=(t,e)=>{const n={};return t.portPoints.forEach((e,s)=>{n[e.connectionName]=`hsl(${360*s/t.portPoints.length}, 100%, 50%)`}),n},Ht=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:n,viaDiameter:s}){super(),this.MAX_ITERATIONS=1e5,this.colorMap=e??Yt(t),this.maxViaCount=5,this.bounds=It(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=n??{SHUFFLE_SEED:0},this.viaDiameter=s??.6,this.unprocessedConnections=Array.from(this.portPairMap.keys()).sort(),n?.SHUFFLE_SEED&&(this.unprocessedConnections=Pt(this.unprocessedConnections,n.SHUFFLE_SEED));for(const[t,{start:e,end:n}]of this.portPairMap.entries())if(e.z===n.z){const s=Math.abs(e.x-n.x)<1e-9,i=Math.abs(e.y-n.y)<1e-9;s||i?this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),this._padByPlaceholderWallBuffer(n),n]):this.placeholderPaths.set(t,[e,n])}else{const s=(e.x+n.x)/2,i=(e.y+n.y)/2,o=this._padByPlaceholderWallBuffer({x:s,y:i,z:e.z}),a=this._padByPlaceholderWallBuffer({x:s,y:i,z:n.z});this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),o,a,this._padByPlaceholderWallBuffer(n),n])}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:J(t.x,this.bounds.minX+this.NEW_HEAD_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.NEW_HEAD_WALL_BUFFER_DISTANCE),y:J(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:J(t.x,this.bounds.minX+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),y:J(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 n=null,s=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=it(e[0],e[1],o[0],o[1]);if(a){const t=st(this.currentHead,a);if(t<1e-6)continue;(!n||t<n.dist)&&(n={point:a,dist:t},s=o[0].z)}}};i(this.completedPaths),i(this.placeholderPaths);const o=this.currentHead.z!==t.z;if((n||o)&&(this.currentViaCount++,this.currentViaCount>=this.maxViaCount))return this.failed=!0,void(this.error=`Exceeded max via count of ${this.maxViaCount}`);if(n){let t;const e=n.dist;if(e<=this.VIA_INTERSECTION_BUFFER_DISTANCE+1e-6)t=ot(this.currentHead,n.point);else{const s=n.point,i=s.x-this.currentHead.x,o=s.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!==s);if(void 0===i)return this.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 n=st(this.currentHead,t);if(n<this.VIA_INTERSECTION_BUFFER_DISTANCE)e=ot(this.currentHead,t);else{const s=t.x-this.currentHead.x,i=t.y-this.currentHead.y,o=(n-this.VIA_INTERSECTION_BUFFER_DISTANCE)/n;e={x:this.currentHead.x+s*o,y:this.currentHead.y+i*o}}const s=t.z,i={...e,z:this.currentHead.z},o={...e,z:s};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:n,end:s}]of this.portPairMap.entries()){const i=this.colorMap[e]??"black";t.points.push({x:n.x,y:n.y,color:i,label:`Port: ${e} Start (z${n.z})`}),t.points.push({x:s.x,y:s.y,color:i,label:`Port: ${e} End (z${s.z})`})}const n=(n,s)=>{for(const[i,o]of n.entries()){const n=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:H(n,.5),label:`${s}: ${i} Via (z${a.z}->z${r.z})`}):t.lines.push({points:[a,r],strokeColor:H(n,.5),strokeDash:0===a.z?void 0:[.1,.1],strokeWidth:.1,label:`${s}: ${i} (z${a.z})`})}}};if(n(this.placeholderPaths,"Placeholder"),n(this.completedPaths,"Completed"),this.currentPath&&this.currentPath.length>0){const n=e[this.currentConnectionName]??"orange";for(let e=0;e<this.currentPath.length-1;e++){const s=this.currentPath[e],i=this.currentPath[e+1];s.x===i.x&&s.y===i.y&&s.z!==i.z?t.circles.push({center:{x:s.x,y:s.y},radius:this.viaDiameter/2,fill:H(n,.5),label:`Current: ${this.currentConnectionName} Via (z${s.z}->z${i.z})`}):t.lines.push({points:[s,i],strokeColor:H(n,.5),strokeWidth:.15,strokeDash:"2,2",label:`Current: ${this.currentConnectionName} (z${s.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}},jt=t=>{let e=0,n=[];const s=[];let i=0;for(const e of t.portPoints){if(n.some(t=>t.connectionName===e.connectionName))continue;if(s.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 n of t.portPoints)e.connectionName===n.connectionName&&(e.x===n.x&&e.y===n.y||o.points.push({x:n.x,y:n.y,z:n.z}));o.points.some(t=>t.z!==o.z)?(i++,s.push(o)):n.push(o)}n=n.filter(t=>t.points.length>1);for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++){const i=n[t],o=n[s];i.z===o.z&&Q(i.points[0],i.points[1],o.points[0],o.points[1])&&e++}let o=0;for(let t=0;t<s.length;t++)for(let e=t+1;e<s.length;e++){const n=s[t],i=s[e];Q(n.points[0],n.points[1],i.points[0],i.points[1])&&o++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:i,numTransitionPairCrossings:o,numTransitions:s.length}},Wt=1e-9;function Vt(t,e,n=Wt){return Math.abs(t-e)<n}function Zt(t,e,n,s){return t*s-e*n}function Ut(t,e,n,s){const i={x:e.x-t.x,y:e.y-t.y},o={x:s.x-n.x,y:s.y-n.y},a=Zt(i.x,i.y,o.x,o.y);if(Vt(a,0))return null;const r={x:n.x-t.x,y:n.y-t.y},h=Zt(r.x,r.y,o.x,o.y)/a,c=Zt(r.x,r.y,i.x,i.y)/a;return h<-Wt||h>1+Wt||c<-Wt||c>1+Wt?null:{x:t.x+h*i.x,y:t.y+h*i.y}}function Gt(t){let e=0;for(let n=0,s=t.length;n<s;++n){const i=(n+1)%s;e+=t[n].x*t[i].y-t[i].x*t[n].y}return.5*e}function qt(t){let e=0,n=0,s=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,n+=(t[i].x+t[a].x)*r,s+=(t[i].y+t[a].y)*r}return e*=.5,Vt(e,0)?null:(n/=6*e,s/=6*e,{x:n,y:s})}var Kt=class{x;y;out;connectionNames;constructor(t,e){this.x=t,this.y=e,this.out=[],this.connectionNames=new Set}},Jt=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 Qt(t,e){const n=[...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}}]],s=n.map(()=>[]);for(let t=0;t<n.length;++t){const e=n[t];s[t].push(e.start,e.end)}for(let t=0;t<n.length;++t)for(let e=t+1;e<n.length;++e){const i=Ut(n[t].start,n[t].end,n[e].start,n[e].end);i&&(s[t].push(i),s[e].push(i))}const i=new Map,o=[];function a(t){const e=function(t,e=Wt){return`${Math.round(t.x/e)}:${Math.round(t.y/e)}`}(t);if(!i.has(e)){const n=o.length;return i.set(e,n),o.push(new Kt(t.x,t.y)),n}return i.get(e)}const r=[];for(let t=0;t<n.length;++t){const e=n[t],i=s[t].slice();i.sort((t,n)=>{const s=e.end.x-e.start.x,i=e.end.y-e.start.y;return(Vt(Math.abs(s),0)?(t.y-e.start.y)/i:(t.x-e.start.x)/s)-(Vt(Math.abs(s),0)?(n.y-e.start.y)/i:(n.x-e.start.x)/s)});for(let t=0;t<i.length-1;++t){const n=i[t],s=i[t+1],h=a(n),c=a(s);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 n=new Jt(t,e),s=new Jt(e,t);n.twin=h.length+1,s.twin=h.length;const i=h.length;h.push(n,s),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,n)=>{const s=h[t],i=h[n],a=o[s.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 n=e.out.length;for(let t=0;t<n;++t){const s=e.out[t],i=e.out[(t-1+n)%n],o=h[s];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 n=[],s=[];do{if(null===e)break;const t=h[e];t.visited=!0,n.push(o[t.orig]),s.push(e),e=t.next}while(null!==e&&e!==t&&!h[e].visited);if(n.length<3)continue;if(Gt(n)>Wt){const t=qt(n);t&&(c.push(t),d.push({vertices:n.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 te(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 n=[];return function t(s,i,o){o!==e?(s[o]=0,t(s,i,o+1),i>0&&(s[o]=1,t(s,i-1,o+1))):0===i&&n.push([...s])}(Array(e).fill(0),t,0),n}var ee=t=>{if(0===t.length)return[[]];const e=[];for(let n=0;n<t.length;n++){const s=t[n],i=[...t.slice(0,n),...t.slice(n+1)],o=ee(i);for(const t of o)e.push([s,...t])}return e};var ne=t=>{const{start:e,end:n,segmentsPerPolyline:s,viaPositions:i,viaCount:o,availableZ:a}=t,r=function(t,e){const n=new Array(t).fill(0);if(0===e)return n;if(e===t)return n.fill(1);if(e<=t/2){const s=Math.floor(t/e),i=Math.floor((t-(s*(e-1)+1))/2);for(let t=0;t<e;t++)n[i+t*s]=1}else{const s=t-e,i=Math.floor(t/s),o=Math.floor((t-(i*(s-1)+1))/2);n.fill(1);for(let t=0;t<s;t++)n[o+t*i]=0}return n}(s,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=n,s=h.length;for(let n=t+1;n<h.length;n++)if(h[n]){e=h[n],s=n;break}const i=s-t,o=e.x-u.x,a=e.y-u.y;for(let e=1/(i+1),n=0;t+n!==s;e+=1/(i+1),n++)h[t+n]={x:u.x+o*e,y:u.y+a*e,z1:u.z2,z2:u.z2}}return h},se=1e-9;function ie(t,e){return Math.abs(t-e)<se}function oe(t){return`${Math.round(t.x/se)}:${Math.round(t.y/se)}`}function ae(t,e,n,s){return t*s-e*n}function re(t,e,n,s){const i={x:e.x-t.x,y:e.y-t.y},o={x:s.x-n.x,y:s.y-n.y},a=ae(i.x,i.y,o.x,o.y),r={x:n.x-t.x,y:n.y-t.y};if(ie(a,0))return null;const h=ae(r.x,r.y,o.x,o.y)/a,c=ae(r.x,r.y,i.x,i.y)/a;return h>=-1e-9&&h<=1+se&&c>=-1e-9&&c<=1+se?{x:t.x+h*i.x,y:t.y+h*i.y}:null}function he(t,e,n){return ie(Math.hypot(t.x-e.x,t.y-e.y)+Math.hypot(t.x-n.x,t.y-n.y),Math.hypot(e.x-n.x,e.y-n.y))}function ce(t,e){const n=[],s=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(n.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=oe(o);s.has(t)||s.set(t,{point:o,connectionName:e.connectionName})}}const i=t[t.length-1];if(i.z1!==i.z2){const t=oe(i);s.has(t)||s.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}];n.push(...i);const o=new Map;let a=0;function r(t,e){const n=oe(t);let i=o.get(n);if(!i){const e=s.has(n);i={id:a++,x:t.x,y:t.y,isVia:e,connectionNames:new Set,outgoingEdges:[]},o.set(n,i),e&&s.get(n)&&i.connectionNames.add(s.get(n).connectionName)}return e&&i.connectionNames.add(e),i}for(const t of n)r(t.start,t.connectionName),r(t.end,t.connectionName);const h=new Map;for(const t of n)h.set(t,[]);for(let t=0;t<n.length;t++)for(let e=t+1;e<n.length;e++){if(n[t].layer!==n[e].layer)continue;const s=re(n[t].start,n[t].end,n[e].start,n[e].end);s&&(r(s),he(s,n[t].start,n[t].end)&&h.get(n[t]).push(s),he(s,n[e].start,n[e].end)&&h.get(n[e]).push(s))}const c=[];let d=0;for(const t of n){const e=[t.start,...h.get(t),t.end];e.sort((e,n)=>{const s=t.end.x-t.start.x,i=t.end.y-t.start.y;return Math.abs(s)>Math.abs(i)?(e.x-t.start.x)/s-(n.x-t.start.x)/s:Math.abs(i)<se?0:(e.y-t.start.y)/i-(n.y-t.start.y)/i});const n=[];if(e.length>0){n.push(e[0]);for(let t=1;t<e.length;t++)ie(e[t].x,e[t-1].x)&&ie(e[t].y,e[t-1].y)||n.push(e[t])}for(let e=0;e<n.length-1;e++){const s=n[e],i=n[e+1],o=r(s,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,n)=>{const s=e.twin.origin,i=n.twin.origin;return Math.atan2(s.y-t.y,s.x-t.x)-Math.atan2(i.y-t.y,i.x-t.x)});const e=t.outgoingEdges.length;for(let n=0;n<e;n++){const s=t.outgoingEdges[n],i=t.outgoingEdges[(n-1+e)%e];s.twin&&(s.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 n=t;const s=[],i=[],o=new Set;let a=0;do{if(!n||n.visited){console.warn("Face traversal encountered visited edge or null, breaking loop.",e.id),s.length=0;break}n.visited=!0,n.face=e,s.push(n),i.push(n.origin),null!==n.connectionName&&o.add(n.connectionName);const t=n.origin,r=n.twin.origin;a+=t.x*r.y-r.x*t.y,n=n.next}while(n!==t&&null!==n);if(n===t){if(a=.5*Math.abs(a),a>f&&(f=a,p&&(p.isOuterFace=!1),p=e,e.isOuterFace=!0),!e.isOuterFace&&s.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 de=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??Yt(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,n=(this.viaDiameter+2*this.obstacleMargin+this.traceWidth/2)**2,s=new Set(this.nodeWithPortPoints.portPoints.map(t=>t.connectionName)).size;this.uniqueConnections=s;const{numSameLayerCrossings:i,numTransitions:o}=jt(this.nodeWithPortPoints);if(this.minViaCount=2*i+o,this.maxViaCount=Math.min(Math.floor(e/n),Math.ceil(1.5*s)),this.minViaCount>this.SEGMENTS_PER_POLYLINE*(s/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=[],n=[],s=[];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]],n=e[0].z2;a.has(n)||a.set(n,[]),a.get(n).push(e)}n.push(a),s.push(o.filter(t=>t.z1!==t.z2))}for(let i=0;i<t.length;i++){const o=n[i],a=s[i];for(let r=i+1;r<t.length;r++){if(this.connMap?.areIdsConnected(t[i].connectionName,t[r].connectionName))continue;const h=n[r],c=s[r];let d=1;for(const t of this.availableZ){const e=o.get(t)??[],n=h.get(t)??[];for(const t of e)for(const e of n)d=Math.min(d,ft(t[0],t[1],e[0],e[1])-this.traceWidth);for(const t of a)for(const e of n)d=Math.min(d,nt(t,e[0],e[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of c)for(const n of e)d=Math.min(d,nt(t,n[0],n[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of a)for(const e of c)d=Math.min(d,st(t,e)-this.viaDiameter)}e.push(d)}}return e}insertCandidate(t){let e=0,n=this.candidates.length-1;for(;e<=n;){const s=Math.floor((e+n)/2);this.candidates[s].f<t.f?e=s+1:n=s-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,n]of t.entries())null===n.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()),n=((t,e,n,s)=>{const i=[];for(const[,n]of t){const t=n.start.z1!==n.end.z1,s=[];for(let n=0;n<=e;n++){const e=n%2!=0;t&&e?s.push(n):t||e||s.push(n)}i.push(s)}if(0===i.length)return[[]];let o=(t=>{if(!t||0===t.length)return[[]];let e=[[]];for(const n of t){const t=[];for(const s of e)for(const e of n)t.push([...s,e]);e=t}return e})(i).filter(t=>{for(let e=0;e<t.length;e++)if(t.reduce((t,e)=>t+e,0)<s)return!1;return!0});return o=o.filter(e=>{for(let n=0;n<t.length;n++){const[,s]=t[n];if(s.start.z1!==s.start.z2&&0===e[n])return!1}return!0}),o=o.filter(e=>{for(let n=0;n<t.length;n++){const[,s]=t[n];if(t[n][1].start.z1===t[n][1].start.z2)for(let i=n+1;i<t.length;i++){if(t[i][1].start.z1!==t[i][1].start.z2)continue;const[,o]=t[i];if(s.start.z1===s.end.z1&&o.start.z1===o.end.z1&&s.start.z1===o.start.z1&&Q(s.start,s.end,o.start,o.end)&&e[n]+e[i]<2)return!1}}return!0}),o=o.filter(t=>!(t.reduce((t,e)=>t+e,0)>n)),o})(e,this.SEGMENTS_PER_POLYLINE,this.maxViaCount,this.minViaCount),s=(t=>{const{bounds:e,portPairsEntries:n,viaCountVariants:s}=t,{centroids:i}=Qt(e,n.map(([t,e])=>e)),o=[];for(const t of s){const n=t.reduce((t,e)=>t+e,0);let s=i;if(i.length<n){s=[];const t=Math.ceil(Math.sqrt(n)),i=t;for(let n=0;n<t;n++)for(let o=0;o<i;o++)s.push({x:e.minX+(o+1)/(i+1)*(e.maxX-e.minX),y:e.minY+(n+1)/(t+1)*(e.maxY-e.minY)})}const a=te(n,s.length);for(const e of a){const n=[];for(let t=0;t<e.length;t++)1===e[t]&&n.push(s[t]);o.push({viaPositions:n,viaCountVariant:t})}}return o})({portPairsEntries:e,viaCountVariants:n,bounds:this.bounds}),i=[];for(const{viaCountVariant:t,viaPositions:e}of s){const n=ee(e);for(const e of n)i.push({viaCountVariant:t,viaPositions:e})}for(const{viaPositions:t,viaCountVariant:n}of i){const s=[];let i=0;for(let o=0;o<e.length;o++){const[a,r]=e[o],h=n[o],c=t.slice(i,i+h),d=ne({start:r.start,end:r.end,segmentsPerPolyline:this.SEGMENTS_PER_POLYLINE,viaPositions:c,viaCount:h,availableZ:this.availableZ});i+=h,s.push({connectionName:a,start:r.start,end:r.end,mPoints:d})}if(ce(s,this.bounds))continue;const o=this.computeMinGapBtwPolyLines(s),a=this.computeH({minGaps:o,forces:[]}),r={polyLines:s,g:0,h:a,f:a,viaCount:n.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 n of t.forces??[])for(const t of n)for(const n of t.values())e+=n.fx*n.fx+n.fy*n.fy;return e}getNeighbors(t){const{polyLines:e}=t,n=e.length,s=.02,i=.008,o=1e-6,a=Array.from({length:n},(t,n)=>Array.from({length:e[n].mPoints.length},()=>new Map)),r=(t,n,s,i,o)=>{if(n>0&&n<e[t].mPoints.length+1){const e=n-1,r=a[t][e],h=r.get(s)||{fx:0,fy:0};r.set(s,{fx:h.fx+i,fy:h.fy+o})}};for(let t=0;t<n;t++)for(let i=t+1;i<n;i++){const n=e[t],a=e[i],h=[n.start,...n.mPoints,n.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 n of u)if(e.layer===n.layer){if(ft(e.p1,e.p2,n.p1,n.p2)<o)continue;const s={x:(e.p1.x+e.p2.x)/2,y:(e.p1.y+e.p2.y)/2},a={x:(n.p1.x+n.p2.x)/2,y:(n.p1.y+n.p2.y)/2},h=s.x-a.x,c=s.y-a.y,d=h*h+c*c;if(d>o){const s=Math.sqrt(d),a=(Math.exp(-6*s),`seg:${i}:${n.p1Idx}:${n.p2Idx}`),h=`seg:${t}:${e.p1Idx}:${e.p2Idx}`,c=(t,e,n,s,i,a,h)=>{const c=mt(t,n.p1,n.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(s,e,a,g,m),r(i,n.p1Idx,h,-g/2,-m/2),r(i,n.p2Idx,h,-g/2,-m/2)};c(e.p1,e.p1Idx,n,t,i,a,h),c(e.p2,e.p2Idx,n,t,i,a,h),c(n.p1,n.p1Idx,e,i,t,h,a),c(n.p2,n.p2Idx,e,i,t,h,a)}}for(const e of l)for(const n of u)if(e.layers.includes(n.layer)){const a=mt(e.point,n.p1,n.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*s*Math.exp(-6*u),f=h/a*p,g=c/a*p,m=`seg:${i}:${n.p1Idx}:${n.p2Idx}`;r(t,e.index,m,f,g);const y=`via:${t}:${e.index}`;r(i,n.p1Idx,y,-f/2,-g/2),r(i,n.p2Idx,y,-f/2,-g/2)}}for(const e of p)for(const n of d)if(e.layers.includes(n.layer)){const a=mt(e.point,n.p1,n.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*s*Math.exp(-6*u),f=h/a*p,g=c/a*p,m=`seg:${t}:${n.p1Idx}:${n.p2Idx}`;r(i,e.index,m,f,g);const y=`via:${i}:${e.index}`;r(t,n.p1Idx,y,-f/2,-g/2),r(t,n.p2Idx,y,-f/2,-g/2)}}for(const e of l)for(const n of p){if(e.layers.filter(t=>n.layers.includes(t)).length>0){const a=e.point.x-n.point.x,h=e.point.y-n.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*s*Math.exp(-6*u),f=a/d*p,g=h/d*p,m=`via:${i}:${n.index}`,y=`via:${t}:${e.index}`;r(t,e.index,m,f,g),r(i,n.index,y,-f,-g)}}}}for(let t=0;t<n;t++){const n=e[t],i=[n.start,...n.mPoints,n.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 n=e+1;n<a.length;n++){const i=a[e],h=a[n],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 n=2,a=e;e<this.viaDiameter?(n*=4,a=Math.max(o,e)):a=Math.max(o,e-this.viaDiameter);const u=n*s*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<n;t++)for(let e=0;e<h[t].mPoints.length;e++){const n=h[t].mPoints[e],s=a[t][e],r={fx:0,fy:0};for(const t of s.values())r.fx+=t.fx,r.fy+=t.fy;const d=n.z1!==n.z2;let l=n.x+r.fx,u=n.y+r.fy;if(d){const t=this.viaDiameter/2;let e=0,s=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-n.x,f=n.x-(h-t),g=c+t-n.y,m=n.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?s=i*(Math.exp(g/(2*this.obstacleMargin))-1):m>0&&(s=-.008*(Math.exp(m/(2*this.obstacleMargin))-1)),r.fx+=e,r.fy+=s,l=n.x+r.fx,u=n.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(n.x-l)>o||Math.abs(n.y-u)>o)&&(n.x=l,n.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),n=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,n=0)=>t.x>=e.minX+n&&t.x<=e.maxX-n&&t.y>=e.minY+n&&t.y<=e.maxY-n)(t,this.bounds,e)}));return e&&n}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),n=.1*(this.bounds.maxY-this.bounds.minY);t.rects.push({center:{x:this.bounds.maxX+.6*e,y:this.bounds.maxY+.6*n},width:e,height:n,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((n,s)=>{const i=this.colorMap[n.connectionName]??"purple",o=[n.start,...n.mPoints,n.end];for(let e=0;e<o.length-1;e++){const s=o[e],a=o[e+1],r=s.z2,h=0===r,c=h?i:H(i,.5);t.lines.push({points:[s,a],strokeColor:c,strokeWidth:this.traceWidth,strokeDash:h?void 0:[.15,.15],label:`${n.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?.[s]?.[i];if(o&&o.size>0){const s={fx:0,fy:0};o.forEach((o,r)=>{if(s.fx+=o.fx,s.fy+=o.fy,Math.abs(o.fx)>1e-6||Math.abs(o.fy)>1e-6){const s=r.split(":"),h=s[0],c=parseInt(s[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(s[2],10)}`}else if("seg"===h){f+=` Seg ${parseInt(s[2],10)}-${parseInt(s[3],10)}`}t.lines.push({points:[a,p],strokeColor:l,strokeWidth:.02,strokeDash:"2,2",label:`Force by ${f} on ${n.connectionName} mPoint ${i}`})}}),(Math.abs(s.fx)>1e-6||Math.abs(s.fy)>1e-6)&&(u=`\nNet Force: (${s.fx.toFixed(3)}, ${s.fy.toFixed(3)})`)}}if(h)l=`Via (${n.connectionName} z=${a.z1} -> z=${a.z2})${u}`,t.circles.push({center:a,radius:this.viaDiameter/2,fill:H(i,.5),label:l});else if(d){const e=0===c?i:H(i,.5);l=`mPoint (${n.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 n=[],s=[],i=[e.start,...e.mPoints,e.end];for(let t=0;t<i.length;t++){const e=i[t];n.push({x:e.x,y:e.y,z:e.z1}),e.z1!==e.z2&&(s.push({x:e.x,y:e.y}),n.push({x:e.x,y:e.y,z:e.z2}))}t.push({connectionName:e.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:n,vias:s})}this.solvedRoutes=t}},le=class extends de{computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){const{minGaps:e}=t;let n=0;for(const t of e)t<0&&(n+=this.obstacleMargin),t<this.obstacleMargin&&(n+=this.obstacleMargin-t);return.011*n}_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,n=0;const s=void 0===t.magForceApplied?1:10;for(let i=0;i<s;i++){const s=this.applyForcesToPolyLines(t.polyLines);if(n+=s.magForceApplied,e=s.lastStepMoved,!s.lastStepMoved)break}if(t.magForceApplied=n,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 n=t.length,s=.02,i=.008,o=1e-6,a=Array.from({length:n},(e,n)=>Array.from({length:t[n].mPoints.length},()=>({fx:0,fy:0}))),r=(e,n,s,i)=>{if(n>0&&n<t[e].mPoints.length+1){const t=n-1;a[e][t].fx+=s,a[e][t].fy+=i}},h=(t,e,n,s,i)=>{const a=mt(t,n.p1,n.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(s,e,p,f),r(i,n.p1Idx,-p/2,-f/2),r(i,n.p2Idx,-p/2,-f/2)};for(let e=0;e<n;e++)for(let i=e+1;i<n;i++){const n=t[e],a=t[i],c=[n.start,...n.mPoints,n.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 n of p)if(t.layer===n.layer){ft(t.p1,t.p2,n.p1,n.p2);h(t.p1,t.p1Idx,n,e,i),h(t.p2,t.p2Idx,n,e,i),h(n.p1,n.p1Idx,t,i,e),h(n.p2,n.p2Idx,t,i,e)}for(const t of u)for(const n of p)if(t.layers.includes(n.layer)){const a=mt(t.point,n.p1,n.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*s*Math.exp(-6*u),f=h/a*p,g=c/a*p;r(e,t.index,f,g),r(i,n.p1Idx,-f/2,-g/2),r(i,n.p2Idx,-f/2,-g/2)}}for(const t of f)for(const n of l)if(t.layers.includes(n.layer)){const a=mt(t.point,n.p1,n.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*s*Math.exp(-6*u),f=h/a*p,g=c/a*p;r(i,t.index,f,g),r(e,n.p1Idx,-f/2,-g/2),r(e,n.p2Idx,-f/2,-g/2)}}for(const t of u)for(const n of f){if(t.layers.filter(t=>n.layers.includes(t)).length>0){const a=t.point.x-n.point.x,h=t.point.y-n.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*s*Math.exp(-6*u),f=a/d*p,g=h/d*p;r(e,t.index,f,g),r(i,n.index,-f,-g)}}}}for(let e=0;e<n;e++){const n=t[e],i=[n.start,...n.mPoints,n.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 n=t+1;n<a.length;n++){const i=a[t],h=a[n],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 n=2,a=t;t<this.viaDiameter?(n*=4,a=Math.max(o,t)):a=Math.max(o,t-this.viaDiameter);const u=n*s*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 s=0;s<n;s++)for(let n=0;n<t[s].mPoints.length;n++){const r=t[s].mPoints[n],h=a[s][n],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,n=0;const s=this.viaDiameter/2+this.BOUNDARY_PADDING,o=this.bounds.minX+s,a=this.bounds.maxX-s,h=this.bounds.minY+s,c=this.bounds.maxY-s,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?n=i*(Math.exp(m/(2*this.obstacleMargin))-1):y>0&&(n=-.008*(Math.exp(y/(2*this.obstacleMargin))-1)),l+=e,u+=n,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}}},ue=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 pe=class extends le{constructor(t){super(t),this.MAX_ITERATIONS=1e3}createInitialCandidateFromSeed(t){const e=new Ht({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,hyperParameters:{SHUFFLE_SEED:t},viaDiameter:this.viaDiameter});if(e.solve(),e.failed||!e.solved)return this.failed=!0,this.error=`ViaPossibilitiesSolver2 failed with: ${e.error}`,null;const n=[];let s=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],n=t+1<a.length?a[t+1]:o,s=c,i=t+1<a.length&&e.x===n.x&&e.y===n.y&&e.z!==n.z?n.z:e.z;r.push({x:e.x,y:e.y,z1:s,z2:i}),s!==i?(h++,t++,c=i):c=e.z}s+=h;const d=this.SEGMENTS_PER_POLYLINE;let l=r.length+1;for(;l<d;){let n=-1,s=-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=st(e,o);r>n&&(n=r,s=t,i=e,a=o)}if(-1===s||!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(s,0,f),l++}n.push({connectionName:t,start:{...e,z1:e.z,z2:e.z},end:{...o,z1:o.z,z2:o.z},mPoints:r})}if(0===n.length)return this.failed=!0,this.error="No valid polylines generated from ViaPossibilitiesSolver2.",console.error(this.error),null;const i=this.computeMinGapBtwPolyLines(n),o=this.computeH({minGaps:i,forces:[]}),a={polyLines:n,g:0,h:o,f:0+o,viaCount:s,minGaps:i};return a.g=this.computeG(n,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 n=2;n<=t;n++)e*=n;return e}(this.uniqueConnections)),e=new Set;for(let n=0;n<t;n++){const t=this.createInitialCandidateFromSeed(n);if(!t)continue;const s=ue(t.polyLines);e.has(s)||(e.add(s),this.candidates.push(t))}this.candidates.sort((t,e)=>t.f-e.f)}},fe=class extends wt{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 zt({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING?new Xt({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.MULTI_HEAD_POLYLINE_SOLVER?new pe({nodeWithPortPoints:this.nodeWithPortPoints,connMap:this.connMap,hyperParameters:t,viaDiameter:this.constructorParams.viaDiameter}):new Tt({...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 ge(t,e,n){const s=[];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}):(s.push(i),i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:n}):i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:n},o===t.length-1&&i&&s.push(i)}return s}var me=class extends e{unsolvedNodePortPoints;routes;colorMap;defaultViaDiameter=.6;defaultTraceThickness=.15;viaDiameter;traceWidth;failedSolvers;activeSubSolver=null;connMap;constructor({nodePortPoints:t,colorMap:e,connMap:n,viaDiameter:s,traceWidth:i}){super(),this.unsolvedNodePortPoints=t,this.colorMap=e??{},this.connMap=n,this.routes=[],this.failedSolvers=[],this.MAX_ITERATIONS=1e6,this.viaDiameter=s??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();!function(t){const{node:e,viaDiameter:n=.6,traceWidth:s,obstacleMargin:i=.1}=t,{portPoints:o,width:a}=e,r=null!=s?1.1*s:n/2+i;let h=0;for(let t=0;t<o.length;t++)for(let e=t+1;e<o.length;e++){const n=o[t],s=o[e];if(n.connectionName===s.connectionName)continue;if(n.z!==s.z)continue;const i=n.x-s.x,a=n.y-s.y;Math.sqrt(i*i+a*a)<r&&h++}const c=new Map;for(const t of o)c.has(t.connectionName)||c.set(t.connectionName,[]),c.get(t.connectionName).push(t);const d=c.size,l=[];for(const[t,e]of c.entries()){if(e.length<2)continue;const n=e[0],s=e[e.length-1];l.push({connectionName:t,entry:n,exit:s})}const u=new Set;let p=0;for(let t=0;t<l.length;t++)for(let e=t+1;e<l.length;e++){const n=l[t],s=l[e];n.entry.z===n.exit.z&&s.entry.z===s.exit.z&&n.entry.z===s.entry.z&&Q(n.entry,n.exit,s.entry,s.exit)&&(u.add(n.connectionName),u.add(s.connectionName),p++)}let f=0;for(const t of c.values()){const e=new Map;for(const n of t){const t=`${n.x.toFixed(6)},${n.y.toFixed(6)}`;e.has(t)||e.set(t,new Set),e.get(t).add(n.z)}const n=Array.from(e.values()),s=new Set;if(n.forEach(t=>{t.forEach(t=>s.add(t))}),s.size>1&&n.length>1){let t=!1;if(2===s.size){for(const n of e.values())if(n.size>1){t=!0;break}}else if(s.size>2)for(const n of e.values())if(n.size===s.size){t=!0;break}t||f++}}const g=2*p+f,m=n+2*i,y=Math.min(g,3),x=y*m,v=a>=x,M=e.height>=x;u.size,e.height}({node:t,viaDiameter:this.viaDiameter,traceWidth:this.traceWidth});this.activeSubSolver=new fe({nodeWithPortPoints:t,colorMap:this.colorMap,connMap:this.connMap,viaDiameter:this.viaDiameter,traceWidth:this.traceWidth}),this.updateCacheStats()}updateCacheStats(){const t=G();this.stats.intraNodeCacheHits=t.cacheHits,this.stats.intraNodeCacheMisses=t.cacheMisses}visualize(){let e={lines:[],points:[],rects:[],circles:[]};for(const t of this.routes){const n=ge(t.route,t.connectionName,this.colorMap[t.connectionName]);for(const s of n)e.lines.push({points:s.points,label:s.connectionName,strokeColor:0===s.z?s.color:H(s.color,.75),layer:`z${s.z}`,strokeWidth:t.traceThickness,strokeDash:0!==s.z?"10, 5":void 0});for(const n of t.vias)e.circles.push({center:n,layer:"z0,1",radius:t.viaDiameter/2,fill:this.colorMap[t.connectionName],label:`${t.connectionName} via`})}for(const t of this.failedSolvers){const n=t.nodeWithPortPoints,s=.1*n.width,i=.1*n.height;e.rects.push({center:{x:n.center.x-s/2,y:n.center.y-i/2},layer:"did_not_connect",width:s,height:i,fill:"red",label:`Failed: ${n.capacityMeshNodeId}`});const o={};for(const t of n.portPoints)o[t.connectionName]||(o[t.connectionName]=[]),o[t.connectionName].push({x:t.x,y:t.y,z:t.z});for(const[t,n]of Object.entries(o))for(let t=0;t<n.length-1;t++){const s=n[t],i=n[t+1];e.lines.push({points:[s,i],strokeColor:"red",strokeDash:"10, 5",layer:"did_not_connect"})}}return this.activeSubSolver&&(e=t(e,this.activeSubSolver.visualize())),e}},ye=class{netMap;idToNetMap;constructor(t){this.netMap=t,this.idToNetMap={};for(const[e,n]of Object.entries(t))for(const t of n)this.idToNetMap[t]=e}addConnections(t){for(const e of t){const t=new Set;for(const n of e){const e=this.idToNetMap[n];e&&t.add(e)}let n;if(0===t.size)n=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[n]=[];else if(1===t.size)n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(const e of t)if(e!==n){this.netMap[n].push(...this.netMap[e]),this.netMap[e]=this.netMap[n];for(const t of this.netMap[n])this.idToNetMap[t]=n}}for(const t of e)this.netMap[n].includes(t)||this.netMap[n].push(t),this.idToNetMap[t]=n}}getIdsConnectedToNet(t){return this.netMap[t]||[]}getNetConnectedToId(t){return this.idToNetMap[t]}areIdsConnected(t,e){if(t===e)return!0;const n=this.getNetConnectedToId(t);if(!n)return!1;const s=this.getNetConnectedToId(e);return!!s&&(n===s||s===t||s===t)}areAllIdsConnected(t){const e=this.getNetConnectedToId(t[0]);for(const n of t){const t=this.getNetConnectedToId(n);if(void 0===t)return!1;if(t!==e)return!1}return!0}},xe=t=>{const e=new ye({});for(const n of t.connections){if(n.rootConnectionName&&e.addConnections([[n.name,n.rootConnectionName]]),n.netConnectionName&&e.addConnections([[n.name,n.netConnectionName]]),n.mergedConnectionNames)for(const t of n.mergedConnectionNames)e.addConnections([[n.name,t]]);for(const t of n.pointsToConnect)"pcb_port_id"in t&&t.pcb_port_id&&e.addConnections([[n.name,t.pcb_port_id]])}for(const n of t.obstacles){const t=n.offBoardConnectsTo??[],s=Array.from(new Set([...n.connectedTo,...t]));s.length>0&&e.addConnections([s])}return e},ve=(t,e=1,n={})=>{const s=n.viaDiameter??.6,i=n.obstacleMargin??.2,o=(("width"in t?t.width:t)/(s/2+i)/2)**1.1*e;return 1===t.availableZ?.length&&o>1?1:o},Me=(t,e=.5,n=16)=>{let s=0,i=t;for(;s<n;){if(ve({width:i})<=e)break;i/=2,s++}return Math.max(1,s)},Se=(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}`},Ne=(t,e)=>{const n=[];if(0===t.route.length)return n;let s=[],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=Se(i,e);for(const e of s)n.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=Se(i,e),s=Se(a.z,e);n.push({route_type:"via",x:a.x,y:a.y,from_layer:t,to_layer:s})}s=[a],i=a.z}else s.push(a)}const o=Se(i,e);for(const e of s)n.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:o});return n};function be(t){return"layers"in t&&Array.isArray(t.layers)}function Pe(t){return be(t)?t.layers[0]:t.layer}function Ie(t){return be(t)?t.layers:[t.layer]}var Ce=(t,e)=>"top"===t?0:"bottom"===t?e-1:parseInt(t.slice(5)),_e=1e5,Ee=.001,Te=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}],n=[];return t.start.z!==t.end.z&&(e.push({x:t.start.x,y:t.start.y,z:t.end.z}),n.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:n,viaDiameter:t.defaultViaDiameter??.6,traceThickness:t.defaultTraceThickness??.15},void(this.solved=!0)}let e=1/0,n=t.hdRoutes[0],s="start-to-end";for(const i of t.hdRoutes){const o=i.route[0],a=i.route[i.route.length-1],r=st(t.start,o),h=st(t.start,a),c=st(t.end,o),d=st(t.end,a),l=Math.min(r,h,c,d);l<e&&(e=l,n=i,s=Math.min(c,d)<Math.min(r,h)?"end-to-start":"start-to-end")}"start-to-end"===s?(this.start=t.start,this.end=t.end):(this.start=t.end,this.end=t.start);const i=n.route[0],o=n.route[n.route.length-1],a=st(this.start,i)<=st(this.start,o)?i:o;this.mergedHdRoute={connectionName:t.connectionName,rootConnectionName:n.rootConnectionName,route:[{x:this.start.x,y:this.start.y,z:a.z}],vias:[],viaDiameter:n.viaDiameter,traceThickness:n.traceThickness}}getDisjointedRoute(){for(const t of this.remainingHdRoutes){if([t.route[0],t.route[t.route.length-1]].some(e=>!this.remainingHdRoutes.some(n=>{if(n===t)return!1;return[n.route[0],n.route[n.route.length-1]].some(t=>t.z===e.z&&st(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,n="first",s=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=st(t,a),c=st(t,r);let d=1/0;d=t.z===a.z?h<Ee?h:_e+h:h<Ee?1e3+h:_e+h,d<s&&(s=d,e=i,n="first");let l=1/0;l=t.z===r.z?c<Ee?c:_e+c:c<Ee?1e3+c:_e+c,l<s&&(s=l,e=i,n="last")}if(-1===e)return void(this.remainingHdRoutes=[]);const i=this.remainingHdRoutes[e];let o;this.remainingHdRoutes.splice(e,1),o="first"===n?i.route:[...i.route].reverse(),o.length>0&&st(t,o[0])<Ee&&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,n]of this.remainingHdRoutes.entries()){const s=this.colorMap[n.connectionName]??"gray";n.route.length>1&&t.lines?.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:s});for(let i=0;i<n.route.length;i++){const o=n.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:s,label:`Route ${n.connectionName} ${o===n.route[0]?"First":o===n.route[n.route.length-1]?"Last":""}`})}for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s})}return t}},we=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:Ce(Pe(e.pointsToConnect[0]),t.layerCount)},end:{...e.pointsToConnect[1],z:Ce(Pe(e.pointsToConnect[1]),t.layerCount)}})),this.MAX_ITERATIONS=1e5}_step(){if(this.activeSolver)return this.activeSolver.step(),void(this.activeSolver.solved?(this.activeSolver instanceof Te&&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 Te({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,n]of this.mergedHdRoutes.entries()){const s=this.colorMap[n.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<n.route.length-1;e++){const i=n.route[e],o=n.route[e+1],a=0!==i.z?H(s,.5):s;t.lines?.push({points:[{x:i.x,y:i.y},{x:o.x,y:o.y}],strokeColor:a,strokeWidth:n.traceThickness})}for(const e of n.route){const n=0!==e.z?H(s,.5):s;t.points?.push({x:e.x,y:e.y,color:n})}for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s})}for(const e of this.unsolvedRoutes){const n=this.colorMap[e.connectionName]??"gray";t.points?.push({x:e.start.x,y:e.start.y,color:n,label:`${e.connectionName} Start (z=${e.start.z})`},{x:e.end.x,y:e.end.y,color:n,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:n,strokeDash:"2 2"});for(const s of e.hdRoutes){s.route.length>1&&t.lines?.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:H(n,.5),strokeDash:"10 5"});for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n})}}return t}},Ae=t=>{const e=[],n=[],s=[],i=Y(t),o=(t.minViaDiameter??.6)/2;if(t.connections)for(const e of t.connections)for(const t of e.pointsToConnect){const n=Ie(t);s.push({x:t.x,y:t.y,color:i[e.name],layer:n[0]??("z"in t?Se(t.z,2):"top"),label:`${e.name} (${n.join(",")})`})}if(t.traces)for(const s of t.traces)for(let t=0;t<s.route.length-1;t++){const i=s.route[t],a=s.route[t+1];"via"===i.route_type?n.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${Ce(i.layer,2)}`,strokeWidth:.15,strokeColor:H({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(Ce).join(",")}`})),circles:n,lines:e,points:s}};function ze(t,e){const n=t.center.x-t.width/2,s=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(s-a)<d||Math.abs(n-r)<d)&&Math.min(o,c)-Math.max(i,h)>=d,u=(Math.abs(o-h)<d||Math.abs(i-c)<d)&&Math.min(s,r)-Math.max(n,a)>=d;return l||u}var Re=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)&&ze(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,n=1/0;for(const s of this.nodes){if(s._containsObstacle)continue;if(s._containsTarget)continue;const i=st(e.center,s.center);i<n&&(n=i,t=s)}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 n of e.nodeIds)t.set(n,1+(t.get(n)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const n=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+n*e.width*.05,y:e.center.y-n*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 n=this.nodeMap.get(t.nodeIds[0]),s=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&s?.center){const t=Math.min(...n.availableZ),i=Math.min(...s.availableZ),o={x:n.center.x+t*n.width*.05,y:n.center.y-t*n.width*.05},a={x:s.center.x+i*s.width*.05,y:s.center.y-i*s.width*.05},r=Array.from(new Set([...n.availableZ,...s.availableZ])).sort();e.lines.push({layer:`z${r.join(",")}`,points:[o,a],strokeDash:n.availableZ.join(",")===s.availableZ.join(",")?void 0:"10 5"})}}return e}},Oe=class{constructor(t){this.nodes=t,this.buckets=new Map;for(const e of t){const t=e.center.x-e.width/2,n=e.center.y-e.height/2,s=e.center.x+e.width/2,i=e.center.y+e.height/2;for(let o=t;o<=s;o+=this.CELL_SIZE)for(let t=n;t<=i;t+=this.CELL_SIZE){const n=this.getBucketKey(o,t),s=this.buckets.get(n);s?s.push(e):this.buckets.set(n,[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,n,s){const i=[],o=new Set,a=e-s/2,r=t+n/2,h=e+s/2;for(let e=t-n/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const n=this.getBucketKey(e,t),s=this.buckets.get(n)||[];for(const t of s)o.has(t.capacityMeshNodeId)||(o.add(t.capacityMeshNodeId),i.push(t))}return i}},Le=class extends Re{constructor(t){super(t),this.nodes=t,this.MAX_ITERATIONS=1e7,this.nodeTree=new Oe(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 n of e){if(!ze(t,n))continue;const e=t._strawNode&&n._strawNode&&t._strawParentCapacityMeshNodeId===n._strawParentCapacityMeshNodeId;t.capacityMeshNodeId===n.capacityMeshNodeId||e||!this.doNodesHaveSharedLayer(t,n)||this.edgeSet.has(`${t.capacityMeshNodeId}-${n.capacityMeshNodeId}`)||(this.edgeSet.add(`${t.capacityMeshNodeId}-${n.capacityMeshNodeId}`),this.edgeSet.add(`${n.capacityMeshNodeId}-${t.capacityMeshNodeId}`),this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[t.capacityMeshNodeId,n.capacityMeshNodeId]}))}this.currentNodeIndex++}},De=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 n=this.find(t),s=this.find(e);n!==s&&(this.parent[s]=n)}getGroup(t){const e=this.find(t),n=[];for(const t in this.parent)this.find(t)===e&&n.push(t);return n}},Fe=class{point;left=null;right=null;constructor(t){this.point=t}},$e=class{root=null;constructor(t){t.length>0&&(this.root=this.buildTree(t,0))}buildTree(t,e){const n=e%2==0?"x":"y";t.sort((t,e)=>t[n]-e[n]);const s=Math.floor(t.length/2),i=new Fe(t[s]);return s>0&&(i.left=this.buildTree(t.slice(0,s),e+1)),s<t.length-1&&(i.right=this.buildTree(t.slice(s+1),e+1)),i}findNearestNeighbor(t){if(!this.root)throw new Error("Tree is empty");const e=this.root.point,n=this.distance(t,e);return this.nearestNeighborSearch(this.root,t,0,e,n),e}nearestNeighborSearch(t,e,n,s,i){if(!t)return s;const o=n%2?"x":"y",a=this.distance(e,t.point);a<i&&(s=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 s=this.nearestNeighborSearch(h,e,n+1,s,i),i=this.distance(e,s),Math.abs(r)<i&&(s=this.nearestNeighborSearch(c,e,n+1,s,i)),s}findKNearestNeighbors(t,e){if(!this.root)return[];const n=[];return this.kNearestNeighborSearch(this.root,t,0,n,e),n.sort((t,e)=>t.distance-e.distance).slice(0,e).map(t=>t.point)}kNearestNeighborSearch(t,e,n,s,i){if(!t)return;const o=n%2?"x":"y",a=this.distance(e,t.point);s.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,n+1,s,i);let d=1/0;s.length>=i&&(s.sort((t,e)=>t.distance-e.distance),d=s[i-1]?.distance||1/0),(Math.abs(r)<d||s.length<i)&&this.kNearestNeighborSearch(c,e,n+1,s,i)}distance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}},ke=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 n=e;for(;n!==this.parent.get(n);)n=this.parent.get(n);let s=e;for(;s!==n;){const t=this.parent.get(s);this.parent.set(s,n),s=t}return n}union(t,e){const n=this.find(t),s=this.find(e);if(n===s)return!1;const i=this.rank.get(n)||0,o=this.rank.get(s)||0;return i<o?this.parent.set(n,s):i>o?this.parent.set(s,n):(this.parent.set(s,n),this.rank.set(n,i+1)),!0}};function Be(t){if(t.length<=1)return[];const e=new $e(t),n=[],s=Math.min(10,t.length-1);for(const i of t){const t=e.findKNearestNeighbors(i,s+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);n.push({from:i,to:e,weight:t})}}n.sort((t,e)=>t.weight-e.weight);const i=new ke(t),o=[];for(const e of n)if(i.union(e.from,e.to)&&(o.push(e),o.length===t.length-1))break;return o}function Xe(t){if(t.pointId)return t.pointId;let e="";var n;return"layer"in(n=t)&&"string"==typeof n.layer?e=t.layer:be(t)&&t.layers&&(e=t.layers.sort().join("-")),`${t.x.toFixed(4)},${t.y.toFixed(4)},${e}`}var Ye=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}`),n=new De(e),s=new Map;t.forEach((t,e)=>{const n=`conn_${e}`;t.pointsToConnect.forEach(t=>{const e=Xe(t);s.has(e)||s.set(e,[]),s.get(e).push(n)})});for(const t of s.values())if(t.length>1){const e=t[0];for(let s=1;s<t.length;s++)n.union(e,t[s])}const i=new Map;t.forEach((t,e)=>{const s=`conn_${e}`,o=n.find(s);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,n=new Set;let s=!1;const i=[],a=new Set;let r;t.forEach(t=>{t.pointsToConnect.forEach(t=>e.set(Xe(t),t)),n.add(t.name),t.isOffBoard&&(s=!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(n).join("__"),mergedConnectionNames:Array.from(n),pointsToConnect:Array.from(e.values()),isOffBoard:s,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??[],n=new Map;e.forEach((t,e)=>t.forEach(t=>n.set(t,e)));const s=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const s=n.get(t.pointId),i=n.get(e.pointId);return void 0!==s&&s===i};if(2===t.pointsToConnect.length){if(s(t.pointsToConnect[0],t.pointsToConnect[1]))return;return void this.newConnections.push({...t,rootConnectionName:t.name})}const i=Be(t.pointsToConnect);let o=0;for(const e of i)s(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(n=>{t.points.push({x:n.x,y:n.y,color:"red",label:e.name})});const n=e.pointsToConnect.length**2,s=Nt(0),i=new Set;for(let o=0;o<Math.max(n,2*e.pointsToConnect.length);o++){const n=Math.floor(s()*e.pointsToConnect.length),o=Math.floor(s()*e.pointsToConnect.length);i.has(`${n}-${o}`)||(i.add(`${n}-${o}`),t.lines.push({points:[e.pointsToConnect[n],e.pointsToConnect[o]],strokeColor:"rgba(255,0,0,0.25)"}))}}),this.newConnections.forEach(e=>{const n=this.colorMap?.[e.name]||"blue";e.pointsToConnect.forEach(s=>{t.points.push({x:s.x,y:s.y,color:n,label:e.name})});for(let s=0;s<e.pointsToConnect.length-1;s++)for(let i=s+1;i<e.pointsToConnect.length;i++)t.lines.push({points:[e.pointsToConnect[s],e.pointsToConnect[i]],strokeColor:n})}),t}},He=class extends Ye{constructor(t,e={}){const n=t.connections.flatMap(t=>t.pointsToConnect),s=new Map;for(const t of n)t.pointId&&s.set(t.pointId,t);const i=n.map(t=>t.pointId).filter(t=>!!t),o=new De(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=s,this.ogSrj=t}connectionPointDsu;connectionPointMap;_findBestConnectionPointsFromDisjointSets(t,e){if(!t.pointId||!e.pointId)return{pointsToConnect:[t,e]};const n=this.connectionPointDsu.getGroup(t.pointId).map(t=>this.connectionPointMap.get(t)),s=this.connectionPointDsu.getGroup(e.pointId).map(t=>this.connectionPointMap.get(t));let i=t,o=e,a=1/0;for(const t of n)for(const e of s){const n=Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));n<a&&(a=n,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??[],n=new Map;e.forEach((t,e)=>t.forEach(t=>n.set(t,e)));const s=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const s=n.get(t.pointId),i=n.get(e.pointId);return void 0!==s&&s===i};if(2===t.pointsToConnect.length){if(s(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=Be(t.pointsToConnect);let o=0;for(const e of i){if(s(e.from,e.to))continue;const n=this._findBestConnectionPointsFromDisjointSets(e.from,e.to);this.newConnections.push({pointsToConnect:n.pointsToConnect,name:`${t.name}_mst${o++}`,rootConnectionName:t.name,mergedConnectionNames:t.mergedConnectionNames,netConnectionName:t.netConnectionName})}}},je=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:[]}}},We=1e-9,Ve=(t,e,n)=>Math.max(e,Math.min(n,t)),Ze=(t,e)=>t>e+We,Ue=(t,e)=>t>e-We,Ge=(t,e)=>t<e-We,qe=(t,e)=>t<e+We;function Ke(t,e){return!(t.x+t.width<=e.x+We||e.x+e.width<=t.x+We||t.y+t.height<=e.y+We||e.y+e.height<=t.y+We)}function Je(t,e,n){return e>=t.x-We&&e<=t.x+t.width+We&&n>=t.y-We&&n<=t.y+t.height+We}function Qe(t,e,n){const s=[[n.x,n.y,n.x+n.width,n.y],[n.x+n.width,n.y,n.x+n.width,n.y+n.height],[n.x+n.width,n.y+n.height,n.x,n.y+n.height],[n.x,n.y+n.height,n.x,n.y]];let i=1/0;for(const[n,o,a,r]of s){const s=a-n,h=r-o,c=s*s+h*h;let d=0!==c?((t-n)*s+(e-o)*h)/c:0;d=Ve(d,0,1);const l=n+d*s,u=o+d*h;i=Math.min(i,Math.hypot(t-l,e-u))}return i}function tn(t,e,n,s){let i=e.x+e.width-t.x;for(const e of n){if(t.y+t.height>e.y+We&&e.y+e.height>t.y+We)if(Ue(e.x,t.x+t.width))i=Math.min(i,e.x-t.x);else if(e.x+e.width>t.x+t.width-We&&e.x<t.x+t.width+We)return 0}let o=Math.max(0,i-t.width);if(o<=0)return 0;if(null!=s){const e=t.width,n=t.height;e>=n&&(o=Math.min(o,s*n-e))}return Math.max(0,o)}function en(t,e,n,s){let i=e.y+e.height-t.y;for(const e of n){if(t.x+t.width>e.x+We&&e.x+e.width>t.x+We)if(Ue(e.y,t.y+t.height))i=Math.min(i,e.y-t.y);else if(e.y+e.height>t.y+t.height-We&&e.y<t.y+t.height+We)return 0}let o=Math.max(0,i-t.height);if(o<=0)return 0;if(null!=s){const e=t.width,n=t.height;n>=e&&(o=Math.min(o,s*e-n))}return Math.max(0,o)}function nn(t,e,n,s){let i=e.x;for(const e of n){if(t.y+t.height>e.y+We&&e.y+e.height>t.y+We)if(qe(e.x+e.width,t.x))i=Math.max(i,e.x+e.width);else if(e.x<t.x+We&&e.x+e.width>t.x-We)return 0}let o=Math.max(0,t.x-i);if(o<=0)return 0;if(null!=s){const e=t.width,n=t.height;e>=n&&(o=Math.min(o,s*n-e))}return Math.max(0,o)}function sn(t,e,n,s){let i=e.y;for(const e of n){if(t.x+t.width>e.x+We&&e.x+e.width>t.x+We)if(qe(e.y+e.height,t.y))i=Math.max(i,e.y+e.height);else if(e.y<t.y+We&&e.y+e.height>t.y-We)return 0}let o=Math.max(0,t.y-i);if(o<=0)return 0;if(null!=s){const e=t.width,n=t.height;n>=e&&(o=Math.min(o,s*e-n))}return Math.max(0,o)}function on(t){const{startX:e,startY:n,gridSize:s,bounds:i,blockers:o,initialCellRatio:a,maxAspectRatio:r,minReq:h}=t,c=Math.max(1e-9,s*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 s={x:e+t.ox,y:n+t.oy,width:d,height:l};if(Ge(s.x,i.x)||Ge(s.y,i.y)||Ze(s.x+s.width,i.x+i.width)||Ze(s.y+s.height,i.y+i.height))continue;for(const t of o)if(Ke(s,t))continue t;let a=!0;for(;a;){a=!1;const t=tn(s,i,o,r);t>0&&(s={...s,width:s.width+t},a=!0);const e=en(s,i,o,r);e>0&&(s={...s,height:s.height+e},a=!0);const n=nn(s,i,o,r);n>0&&(s={x:s.x-n,y:s.y,width:s.width+n,height:s.height},a=!0);const h=sn(s,i,o,r);h>0&&(s={x:s.x,y:s.y-h,width:s.width,height:s.height+h},a=!0)}if(s.width+We>=h.width&&s.height+We>=h.height){const t=s.width*s.height;t>f&&(p=s,f=t)}}return p}function an(t,e,n,s){const i=Math.max(t,n),o=Math.min(e,s);return o>i+We?[i,o]:null}function rn(t,e){if(!Ke(t,e))return[t];const n=an(t.x,t.x+t.width,e.x,e.x+e.width),s=an(t.y,t.y+t.height,e.y,e.y+e.height);if(!n||!s)return[t];const[i,o]=n,[a,r]=s,h=[];i>t.x+We&&h.push({x:t.x,y:t.y,width:i-t.x,height:t.height}),t.x+t.width>o+We&&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>We&&a>t.y+We&&h.push({x:i,y:t.y,width:c,height:a-t.y}),c>We&&t.y+t.height>r+We&&h.push({x:i,y:r,width:c,height:t.y+t.height-r}),h.filter(t=>t.width>We&&t.height>We)}function hn(t){const{x:e,y:n,layerCount:s,obstaclesByLayer:i,placedByLayer:o}=t;for(let t=0;t<s;t++){const s=i[t]??[],a=o[t]??[];if(!(s.some(t=>Je(t,e,n))||a.some(t=>Je(t,e,n))))return!1}return!0}function cn(t){const{x:e,y:n,z:s,layerCount:i,minSpan:o,maxSpan:a,obstaclesByLayer:r,placedByLayer:h}=t,c=t=>![...r[t]??[],...h[t]??[]].some(t=>Je(t,e,n));let d=s,l=s;for(;d-1>=0&&c(d-1);)d--;for(;l+1<i&&c(l+1);)l++;if("number"==typeof a){const t=Ve(a,1,i);for(;l-d+1>t;)s-d>l-s?d++:l--}const u=[];for(let t=d;t<=l;t++)u.push(t);return u.length>=o?u:[]}function dn(t){const e=Math.max(t.width,t.height);return[e/8,e/16,e/32]}function ln(t){const{lineStart:e,lineEnd:n,coveringIntervals:s,minSegmentLength:i}=t;if(0===s.length){return[{start:e,end:n,center:(e+n)/2}]}const o=[...s].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+We?r.end=Math.max(r.end,e.end):(a.push(r),r={...e})}a.push(r);const h=[];if(a[0].start>e+We){const t=e,n=a[0].start;n-t>=i&&h.push({start:t,end:n,center:(t+n)/2})}for(let t=0;t<a.length-1;t++){const e=a[t].end,n=a[t+1].start;n-e>=i&&h.push({start:e,end:n,center:(e+n)/2})}if(a[a.length-1].end<n-We){const t=a[a.length-1].end,e=n;e-t>=i&&h.push({start:t,end:e,center:(t+e)/2})}return h}function un(t){const{bounds:e,minSize:n,layerCount:s,obstaclesByLayer:i,placedByLayer:o,hardPlacedByLayer:a}=t,r=[],h=Math.max(.15*n,3*We),c=new Set;function d(t,n,h){if(t<e.x+We||n<e.y+We||t>e.x+e.width-We||n>e.y+e.height-We)return;if(function(t,e){return hn({x:t,y:e,layerCount:s,obstaclesByLayer:i,placedByLayer:o})}(t,n))return;const d=[...i[h]??[],...a[h]??[]],l=Math.min(Qe(t,n,e),...d.length?d.map(e=>Qe(t,n,e)):[1/0]),u=((t,e,n)=>`${n}|${t.toFixed(6)}|${e.toFixed(6)}`)(t,n,h);if(c.has(u))return;c.add(u);const p=cn({x:t,y:n,z:h,layerCount:s,minSpan:1,maxSpan:void 0,obstaclesByLayer:i,placedByLayer:a});r.push({x:t,y:n,z:h,distance:l,zSpanLen:p.length,isEdgeSeed:!0})}for(let t=0;t<s;t++){const s=[...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=s.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=ln({lineStart:e.x+h,lineEnd:e.x+e.width-h,coveringIntervals:c,minSegmentLength:.5*n});for(const e of l){const s=e.end-e.start;s>=n&&(d(e.center,r,t),s>1.5*n&&(d(e.start+.4*n,r,t),d(e.end-.4*n,r,t)))}const u=e.y+e.height-h,p=s.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=ln({lineStart:e.x+h,lineEnd:e.x+e.width-h,coveringIntervals:p,minSegmentLength:.5*n});for(const e of f){const s=e.end-e.start;s>=n&&(d(e.center,u,t),s>1.5*n&&(d(e.start+.4*n,u,t),d(e.end-.4*n,u,t)))}const g=e.x+h,m=s.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=ln({lineStart:e.y+h,lineEnd:e.y+e.height-h,coveringIntervals:m,minSegmentLength:.5*n});for(const e of y){const s=e.end-e.start;s>=n&&(d(g,e.center,t),s>1.5*n&&(d(g,e.start+.4*n,t),d(g,e.end-.4*n,t)))}const x=e.x+e.width-h,v=s.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=ln({lineStart:e.y+h,lineEnd:e.y+e.height-h,coveringIntervals:v,minSegmentLength:.5*n});for(const e of M){const s=e.end-e.start;s>=n&&(d(x,e.center,t),s>1.5*n&&(d(x,e.start+.4*n,t),d(x,e.end-.4*n,t)))}for(const i of s){const o=i.x-h;if(o>e.x+We&&o<e.x+e.width-We){const e=s.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=ln({lineStart:i.y,lineEnd:i.y+i.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of a)d(o,e.center,t)}const a=i.x+i.width+h;if(a>e.x+We&&a<e.x+e.width-We){const e=s.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=ln({lineStart:i.y,lineEnd:i.y+i.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of o)d(a,e.center,t)}const r=i.y-h;if(r>e.y+We&&r<e.y+e.height-We){const e=s.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=ln({lineStart:i.x,lineEnd:i.x+i.width,coveringIntervals:e,minSegmentLength:.5*n});for(const e of o)d(e.center,r,t)}const c=i.y+i.height+h;if(c>e.y+We&&c<e.y+e.height-We){const e=s.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=ln({lineStart:i.x,lineEnd:i.x+i.width,coveringIntervals:e,minSegmentLength:.5*n});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 pn(t,e){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}function fn(t){const e=t.toLowerCase();if("top"===e)return-1e6;if("bottom"===e)return 1e6;const n=/^inner(\d+)$/i.exec(e);return n?parseInt(n[1],10)||0:100+e.charCodeAt(0)}function gn(t){const e=function(t){return Array.from(new Set(t)).sort((t,e)=>{const n=fn(t),s=fn(e);return n!==s?n-s:t.localeCompare(e)})}((t.obstacles??[]).flatMap(t=>t.layers??[])),n=Math.max(1,t.layerCount||e.length||1),s=Array.from({length:n},(t,e)=>0===e?"top":e===n-1?"bottom":`inner${e}`),i=[],o=new Set,a=t=>{const e=t.toLowerCase();o.has(e)||(o.add(e),i.push(t))};s.forEach(a),e.forEach(a);const r=i.slice(0,n),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),n=r.length-2;return Math.min(n,Math.max(1,Number.isFinite(t)?t:1))}return 0})(e))}),{layerNames:r,zIndexByName:h}}function mn(t,e){if(t.zLayers?.length)return Array.from(new Set(t.zLayers)).sort((t,e)=>t-e);const n=(t.layers??[]).map(t=>e.get(t.toLowerCase())).filter(t=>"number"==typeof t);return Array.from(new Set(n)).sort((t,e)=>t-e)}function yn(t){const e=t.width,n=t.height;return"number"!=typeof e||"number"!=typeof n?null:{x:t.center.x-e/2,y:t.center.y-n/2,width:e,height:n}}function xn(t,e){const{layerNames:n,zIndexByName:s}=gn(t),i=Math.max(1,n.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 n=new Set([t.x,t.x+t.width]),s=new Set([t.y,t.y+t.height]);for(const t of e)n.add(t.x),s.add(t.y);const i=Array.from(n).sort((t,e)=>t-e),o=Array.from(s).sort((t,e)=>t-e),a=[];for(let n=0;n<i.length-1;n++)for(let s=0;s<o.length-1;s++){const r=i[n],h=i[n+1],c=o[s],d=o[s+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&&(pn({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)>We?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)<We,n=Math.abs(h.height-t.height)<We,s=Math.abs(h.x+h.width-t.x)<We;e&&n&&s?h.width+=t.width:(r.push(h),h=t)}h&&r.push(h),r.sort((t,e)=>Math.abs(t.x-e.x)>We?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)<We,n=Math.abs(h.width-t.width)<We,s=Math.abs(h.y+h.height-t.y)<We;e&&n&&s?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=yn(e);if(!t)continue;const n=mn(e,s),o=n.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||!n.length||(e.zLayers=n);for(const e of n)a[e].push(t)}const h=Math.max(.01,t.minTraceWidth||.15),c={gridSizes:dn(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:n,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 vn(t){const e=Array.from({length:t.layerCount},()=>[]);for(const n of t.placed)if(n.zLayers.length>=t.layerCount)for(const t of n.zLayers)e[t].push(n.rect);return e}function Mn(t,e){for(let n=0;n<t.layerCount;n++){const s=t.obstaclesByLayer[n]??[],i=t.placedByLayer[n]??[];if(!(s.some(t=>Je(t,e.x,e.y))||i.some(t=>Je(t,e.x,e.y))))return!1}return!0}function Sn(t,e){const n=t.placed[e],{rect:s,zLayers:i}=n,o=t.layerCount,a=[],r=[];for(let n=0;n<t.placed.length;n++){if(n===e)continue;const h=t.placed[n];if(h.zLayers.length>=o)continue;const c=h.zLayers.filter(t=>i.includes(t));if(0===c.length)continue;if(!Ke(h.rect,s))continue;const d=rn(h.rect,s);a.push(n);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+We>=u&&t.height+We>=p&&r.push({rect:t,zLayers:c.slice()})}a.sort((t,e)=>e-t).forEach(e=>{const n=t.placed.splice(e,1)[0];for(const e of n.zLayers){const s=t.placedByLayer[e],i=s.findIndex(t=>t===n.rect);i>=0&&s.splice(i,1)}});for(const e of r){t.placed.push(e);for(const n of e.zLayers)t.placedByLayer[n].push(e.rect)}}function Nn(t){const{gridSizes:e,initialCellRatio:n,maxAspectRatio:s,minSingle:i,minMulti:o,preferMultiLayer:a,maxMultiLayerSpan:r}=t.options,h=e[t.gridIndex],c=vn(t);if(0===t.candidates.length&&0===t.consumedSeedsThisGrid&&(t.candidates=function(t){const{bounds:e,gridSize:n,layerCount:s,obstaclesByLayer:i,placedByLayer:o,hardPlacedByLayer:a}=t,r=new Map;for(let t=e.x;t<e.x+e.width;t+=n)for(let h=e.y;h<e.y+e.height;h+=n){if(Math.abs(t-e.x)<We||Math.abs(h-e.y)<We||t>e.x+e.width-n-We||h>e.y+e.height-n-We)continue;if(hn({x:t,y:h,layerCount:s,obstaclesByLayer:i,placedByLayer:o}))continue;let c=[],d=0;for(let e=0;e<s;e++){const n=cn({x:t,y:h,z:e,layerCount:s,minSpan:1,maxSpan:void 0,obstaclesByLayer:i,placedByLayer:a});n.length>c.length&&(c=n,d=e)}const l=c.length?c[Math.floor(c.length/2)]:d,u=[...i[l]??[],...a[l]??[]],p=Math.min(Qe(t,h,e),...u.length?u.map(e=>Qe(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=un({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=cn({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 n of e.layers)t.obstaclesByLayer[n]&&i.push(...t.obstaclesByLayer[n]),c[n]&&i.push(...c[n]);const o=on({startX:d.x,startY:d.y,gridSize:h,bounds:t.bounds,blockers:i,initialCellRatio:n,maxAspectRatio:s,minReq:e.minReq});if(!o)continue;const a={rect:o,zLayers:[...e.layers]},r=t.placed.push(a)-1;for(const n of e.layers)t.placedByLayer[n].push(o);return Sn(t,r),void(t.candidates=t.candidates.filter(e=>!Mn(t,{x:e.x,y:e.y})))}}var bn=class extends je{srj;gridOptions;state;_meshNodes=[];constructor(t){super(),this.srj=t.simpleRouteJson,this.gridOptions=t.gridOptions??{}}_setup(){this.state=xn(this.srj,this.gridOptions),this.stats={phase:this.state.phase,gridIndex:this.state.gridIndex}}_step(){if("GRID"===this.state.phase)Nn(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,n=t.placed[e],s=t.options.gridSizes[t.options.gridSizes.length-1],i=vn(t),o=[];for(const e of n.zLayers)o.push(...t.obstaclesByLayer[e]??[]),o.push(...i[e]??[]);const a=n.rect,r=on({startX:n.rect.x+n.rect.width/2,startY:n.rect.y+n.rect.height/2,gridSize:s,bounds:t.bounds,blockers:o,initialCellRatio:0,maxAspectRatio:null,minReq:{width:n.rect.width,height:n.rect.height}});if(r){t.placed[e]={rect:r,zLayers:n.zLayers};for(const e of n.zLayers){const n=t.placedByLayer[e],s=n.findIndex(t=>t===a);s>=0&&(n[s]=r)}Sn(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)})),n=new Map;t.obstaclesByLayer.forEach((t,e)=>{for(const s of t){const t=n.get(s)??[];t.push(e),n.set(s,t)}});const s=new Set(t.boardVoidRects||[]);for(const[t,i]of n.entries())s.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 n=[];for(const s of t){const t=Math.max(0,s.maxX-s.minX),i=Math.max(0,s.maxY-s.minY);t<=0||i<=0||0===s.zLayers.length||n.push({capacityMeshNodeId:"cmn_"+e++,center:{x:(s.minX+s.maxX)/2,y:(s.minY+s.maxY)/2},width:t,height:i,layer:"top",availableZ:s.zLayers.slice(),_containsObstacle:s.isObstacle,_containsTarget:s.isObstacle})}return n}(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 n=t.gridIndex/(e+1),s=Math.max(1,t.totalSeedsThisGrid),i=s?t.consumedSeedsThisGrid/s:1;return Math.min(.999,n+i*(1/(e+1)))}if("EXPANSION"===t.phase){const n=e/(e+1),s=Math.max(1,t.placed.length),i=s?t.expansionIndex/s:1;return Math.min(.999,n+i*(1/(e+1)))}return 1}(this.state)}getOutput(){return{meshNodes:this._meshNodes}}getCoverage(t=.05){return function({sampleResolution:t=.1},e){const{bounds:n,layerCount:s,obstaclesByLayer:i,placedByLayer:o}=e;let a=0,r=0;for(let e=0;e<s;e++){const s=[...i[e]??[],...o[e]??[]];for(let e=n.x;e<=n.x+n.width;e+=t)for(let i=n.y;i<=n.y+n.height;i+=t)a++,s.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:n,layerCount:s,obstaclesByLayer:i,placedByLayer:o}=e,a=[];for(let e=0;e<s;e++){const s=[...i[e]??[],...o[e]??[]];for(let i=n.x;i<=n.x+n.width;i+=t)for(let o=n.y;o<=n.y+n.height;o+=t)s.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=[],n=[],s=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?n.push({points:[...this.srj.outline,this.srj.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):t.push({center:{x:(s+i)/2,y:(o+a)/2},width:i-s,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),n=this.srj.outline.map(t=>t.y),s=Math.min(...t),i=Math.min(...n);e={x:s,y:i,width:Math.max(...t)-s,height:Math.max(...n)-i}}for(const n of this.state.boardVoidRects)e&&!Ke(n,e)||t.push({center:{x:n.x+n.width/2,y:n.y+n.height/2},width:n.width,height:n.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 n=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:n.fill,stroke:n.stroke,label:`free\nz:${e.zLayers.join(",")}`})}return{title:`RectDiff (${this.state?.phase??"init"})`,coordinateSystem:"cartesian",rects:t,points:e,lines:n}}};function Pn(t,e,n=0,s=t.length-1,i=Cn){for(;s>n;){if(s-n>600){const o=s-n+1,a=e-n+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(n,Math.floor(e-a*h/o+c)),Math.min(s,Math.floor(e+(o-a)*h/o+c)),i)}const o=t[e];let a=n,r=s;for(In(t,n,e),i(t[s],o)>0&&In(t,n,s);a<r;){for(In(t,a,r),a++,r--;i(t[a],o)<0;)a++;for(;i(t[r],o)>0;)r--}0===i(t[n],o)?In(t,n,r):(r++,In(t,r,s)),r<=e&&(n=r+1),e<=r&&(s=r-1)}}function In(t,e,n){const s=t[e];t[e]=t[n],t[n]=s}function Cn(t,e){return t<e?-1:t>e?1:0}var _n=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 n=[];if(!kn(t,e))return n;const s=this.toBBox,i=[];for(;e;){for(let o=0;o<e.children.length;o++){const a=e.children[o],r=e.leaf?s(a):a;kn(t,r)&&(e.leaf?n.push(a):$n(t,r)?this._all(a,n):i.push(a))}e=i.pop()}return n}collides(t){let e=this.data;if(!kn(t,e))return!1;const n=[];for(;e;){for(let s=0;s<e.children.length;s++){const i=e.children[s],o=e.leaf?this.toBBox(i):i;if(kn(t,o)){if(e.leaf||$n(t,o))return!0;n.push(i)}}e=n.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=Bn([]),this}remove(t,e){if(!t)return this;let n=this.data;const s=this.toBBox(t),i=[],o=[];let a,r,h;for(;n||i.length;){if(n||(n=i.pop(),r=i[i.length-1],a=o.pop(),h=!0),n.leaf){const s=En(t,n.children,e);if(-1!==s)return n.children.splice(s,1),i.push(n),this._condense(i),this}h||n.leaf||!$n(n,s)?r?(a++,n=r.children[a],h=!1):n=null:(i.push(n),o.push(a),a=0,r=n,n=n.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 n=[];for(;t;)t.leaf?e.push(...t.children):n.push(...t.children),t=n.pop();return e}_build(t,e,n,s){const i=n-e+1;let o,a=this._maxEntries;if(i<=a)return o=Bn(t.slice(e,n+1)),Tn(o,this.toBBox),o;s||(s=Math.ceil(Math.log(i)/Math.log(a)),a=Math.ceil(i/Math.pow(a,s-1))),o=Bn([]),o.leaf=!1,o.height=s;const r=Math.ceil(i/a),h=r*Math.ceil(Math.sqrt(a));Xn(t,e,n,h,this.compareMinX);for(let i=e;i<=n;i+=h){const e=Math.min(i+h-1,n);Xn(t,i,e,r,this.compareMinY);for(let n=i;n<=e;n+=r){const i=Math.min(n+r-1,e);o.children.push(this._build(t,n,i,s-1))}}return Tn(o,this.toBBox),o}_chooseSubtree(t,e,n,s){for(;s.push(e),!e.leaf&&s.length-1!==n;){let n,s=1/0,i=1/0;for(let o=0;o<e.children.length;o++){const a=e.children[o],r=On(a),h=Dn(t,a)-r;h<i?(i=h,s=r<s?r:s,n=a):h===i&&r<s&&(s=r,n=a)}e=n||e.children[0]}return e}_insert(t,e,n){const s=n?t:this.toBBox(t),i=[],o=this._chooseSubtree(s,this.data,e,i);for(o.children.push(t),An(o,s);e>=0&&i[e].children.length>this._maxEntries;)this._split(i,e),e--;this._adjustParentBBoxes(s,i,e)}_split(t,e){const n=t[e],s=n.children.length,i=this._minEntries;this._chooseSplitAxis(n,i,s);const o=this._chooseSplitIndex(n,i,s),a=Bn(n.children.splice(o,n.children.length-o));a.height=n.height,a.leaf=n.leaf,Tn(n,this.toBBox),Tn(a,this.toBBox),e?t[e-1].children.push(a):this._splitRoot(n,a)}_splitRoot(t,e){this.data=Bn([t,e]),this.data.height=t.height+1,this.data.leaf=!1,Tn(this.data,this.toBBox)}_chooseSplitIndex(t,e,n){let s,i=1/0,o=1/0;for(let a=e;a<=n-e;a++){const e=wn(t,0,a,this.toBBox),r=wn(t,a,n,this.toBBox),h=Fn(e,r),c=On(e)+On(r);h<i?(i=h,s=a,o=c<o?c:o):h===i&&c<o&&(o=c,s=a)}return s||n-e}_chooseSplitAxis(t,e,n){const s=t.leaf?this.compareMinX:zn,i=t.leaf?this.compareMinY:Rn;this._allDistMargin(t,e,n,s)<this._allDistMargin(t,e,n,i)&&t.children.sort(s)}_allDistMargin(t,e,n,s){t.children.sort(s);const i=this.toBBox,o=wn(t,0,e,i),a=wn(t,n-e,n,i);let r=Ln(o)+Ln(a);for(let s=e;s<n-e;s++){const e=t.children[s];An(o,t.leaf?i(e):e),r+=Ln(o)}for(let s=n-e-1;s>=e;s--){const e=t.children[s];An(a,t.leaf?i(e):e),r+=Ln(a)}return r}_adjustParentBBoxes(t,e,n){for(let s=n;s>=0;s--)An(e[s],t)}_condense(t){for(let e,n=t.length-1;n>=0;n--)0===t[n].children.length?n>0?(e=t[n-1].children,e.splice(e.indexOf(t[n]),1)):this.clear():Tn(t[n],this.toBBox)}};function En(t,e,n){if(!n)return e.indexOf(t);for(let s=0;s<e.length;s++)if(n(t,e[s]))return s;return-1}function Tn(t,e){wn(t,0,t.children.length,e,t)}function wn(t,e,n,s,i){i||(i=Bn(null)),i.minX=1/0,i.minY=1/0,i.maxX=-1/0,i.maxY=-1/0;for(let o=e;o<n;o++){const e=t.children[o];An(i,t.leaf?s(e):e)}return i}function An(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 zn(t,e){return t.minX-e.minX}function Rn(t,e){return t.minY-e.minY}function On(t){return(t.maxX-t.minX)*(t.maxY-t.minY)}function Ln(t){return t.maxX-t.minX+(t.maxY-t.minY)}function Dn(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 Fn(t,e){const n=Math.max(t.minX,e.minX),s=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-n)*Math.max(0,o-s)}function $n(t,e){return t.minX<=e.minX&&t.minY<=e.minY&&e.maxX<=t.maxX&&e.maxY<=t.maxY}function kn(t,e){return e.minX<=t.maxX&&e.minY<=t.maxY&&e.maxX>=t.minX&&e.maxY>=t.minY}function Bn(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function Xn(t,e,n,s,i){const o=[e,n];for(;o.length;){if((n=o.pop())-(e=o.pop())<=s)continue;const a=e+Math.ceil((n-e)/s/2)*s;Pn(t,a,e,n,i),o.push(e,a,a,n)}}var Yn=class{tree;constructor(t=9){this.tree=new _n(t)}insert(t,e,n,s,i){this.tree.insert({minX:e,minY:n,maxX:s,maxY:i,data:t})}bulkLoad(t){const e=t.map(({item:t,minX:e,minY:n,maxX:s,maxY:i})=>({minX:e,minY:n,maxX:s,maxY:i,data:t}));this.tree.load(e)}search(t,e,n,s){return this.tree.search({minX:t,minY:e,maxX:n,maxY:s}).map(t=>t.data)}clear(){this.tree.clear()}},Hn=class{constructor(){this.ids=[],this.values=[],this.length=0}clear(){this.length=0}push(t,e){let n=this.length++;for(;n>0;){const t=n-1>>1,s=this.values[t];if(e>=s)break;this.ids[n]=this.ids[t],this.values[n]=s,n=t}this.ids[n]=t,this.values[n]=e}pop(){if(0===this.length)return;const t=this.ids,e=this.values,n=t[0],s=--this.length;if(s>0){const n=t[s],i=e[s];let o=0;const a=s>>1;for(;o<a;){const n=1+(o<<1),a=n+1,r=n+(+(a<s)&+(e[a]<e[n]));if(e[r]>=i)break;t[o]=t[r],e[o]=e[r],o=r}t[o]=n,e[o]=i}return n}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}},jn=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],Wn=class t{static from(e,n=0){if(n%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[s,i]=new Uint8Array(e,n+0,2);if(251!==s)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=jn[15&i];if(!a)throw new Error("Unrecognized array type.");const[r]=new Uint16Array(e,n+2,1),[h]=new Uint32Array(e,n+4,1);return new t(h,r,a,void 0,e,n)}constructor(t,e=16,n=Float64Array,s=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=n,this.IndexArrayType=r<16384?Uint16Array:Uint32Array;const h=jn.indexOf(n),c=4*r*n.BYTES_PER_ELEMENT;if(h<0)throw new Error(`Unexpected typed array class: ${n}.`);if(i)this.data=i,this._boxes=new n(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 s(8+c+r*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new n(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 Hn}add(t,e,n=t,s=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++]=n,o[this._pos++]=s,t<this.minX&&(this.minX=t),e<this.minY&&(this.minY=e),n>this.maxX&&(this.maxX=n),s>this.maxY&&(this.maxY=s),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,n=this.maxY-this.minY||1,s=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)/n);s[i]=Gn(d,l)}Zn(s,t,this._indices,0,this.numItems-1,this.nodeSize);for(let e=0,n=0;e<this._levelBounds.length-1;e++){const s=this._levelBounds[e];for(;n<s;){const e=n;let i=t[n++],o=t[n++],a=t[n++],r=t[n++];for(let e=1;e<this.nodeSize&&n<s;e++)i=Math.min(i,t[n++]),o=Math.min(o,t[n++]),a=Math.max(a,t[n++]),r=Math.max(r,t[n++]);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,n,s,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,Vn(o,this._levelBounds));for(let c=o;c<h;c+=4){const h=this._boxes[c];if(n<h)continue;const d=this._boxes[c+1];if(s<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,n=1/0,s=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=s*s;t:for(;void 0!==o;){const s=Math.min(o+4*this.nodeSize,Vn(o,this._levelBounds));for(let n=o;n<s;n+=4){const s=0|this._indices[n>>2],r=this._boxes[n],c=this._boxes[n+1],d=this._boxes[n+2],l=this._boxes[n+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(s<<1,f):(void 0===i||i(s))&&a.push(1+(s<<1),f))}for(;a.length&&1&a.peek();){if(a.peekValue()>h)break t;if(r.push(a.pop()>>1),r.length===n)break t}o=a.length?a.pop()>>1:void 0}return a.clear(),r}};function Vn(t,e){let n=0,s=e.length-1;for(;n<s;){const i=n+s>>1;e[i]>t?s=i:n=i+1}return e[n]}function Zn(t,e,n,s,i,o){if(Math.floor(s/o)>=Math.floor(i/o))return;const a=t[s],r=t[s+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=s-1,u=i+1;for(;;){do{l++}while(t[l]<c);do{u--}while(t[u]>c);if(l>=u)break;Un(t,e,n,l,u)}Zn(t,e,n,s,u,o),Zn(t,e,n,u+1,i,o)}function Un(t,e,n,s,i){const o=t[s];t[s]=t[i],t[i]=o;const a=4*s,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=n[s];n[s]=n[i],n[i]=u}function Gn(t,e){let n=t^e,s=65535^n,i=65535^(t|e),o=t&(65535^e),a=n|s>>1,r=n>>1^n,h=i>>1^s&o>>1^i,c=n&i>>1^o>>1^o;n=a,s=r,i=h,o=c,a=n&n>>2^s&s>>2,r=n&s>>2^s&(n^s)>>2,h^=n&i>>2^s&o>>2,c^=s&i>>2^(n^s)&o>>2,n=a,s=r,i=h,o=c,a=n&n>>4^s&s>>4,r=n&s>>4^s&(n^s)>>4,h^=n&i>>4^s&o>>4,c^=s&i>>4^(n^s)&o>>4,n=a,s=r,i=h,o=c,h^=n&i>>8^s&o>>8,c^=s&i>>8^(n^s)&o>>8,n=h^h>>1,s=c^c>>1;let d=t^e,l=s|65535^(d|n);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 qn=class{index;items=[];currentIndex=0;capacity;constructor(t){this.capacity=Math.max(1,t),this.index=new Wn(this.capacity)}insert(t,e,n,s,i){if(this.currentIndex>=this.index.numItems)throw new Error("Exceeded initial capacity");this.items[this.currentIndex]=t,this.index.add(e,n,s,i),this.currentIndex++}finish(){this.index.finish()}search(t,e,n,s){return this.index.search(t,e,n,s).map(t=>this.items[t]||null).filter(Boolean)}clear(){this.items=[],this.currentIndex=0,this.index=new Wn(this.capacity)}},Kn=class{idx;storage=[];constructor(t="native",e=[]){"flatbush"===t?0===e.length?(this.idx=new Yn,t="rbush"):this.idx=new qn(e.length):this.idx="rbush"===t?new Yn:new class{shi=new Jn(e);insert(t){}search(t,e,n,s){const i=(t+n)/2,o=(e+s)/2,a=n-t,r=s-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,n,s){return this.search({minX:t-n/2,minY:e-s/2,maxX:t+n/2,maxY:e+s/2})}},Jn=class{constructor(t){this.obstacles=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],s=n.center.x-n.width/2,i=n.center.y-n.height/2,o=n.center.x+n.width/2,a=n.center.y+n.height/2;for(let t=s;t<=o;t+=this.CELL_SIZE)for(let s=i;s<=a;s+=this.CELL_SIZE){const i=this.getBucketKey(t,s),o=this.buckets.get(i);o?o.push([n,e]):this.buckets.set(i,[[n,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,n,s){const i=[],o=new Set,a=e-s/2,r=t+n/2,h=e+s/2;for(let e=t-n/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const n=this.getBucketKey(e,t),s=this.buckets.get(n)||[];for(const t of s)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},Qn=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 ts(t,e){const n=t.x-e.x,s=t.y-e.y;return n*n+s*s}function es(t,e,n){const s=ts(e,n);if(0===s)return ts(t,e);let i=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/s;i=Math.max(0,Math.min(1,i));return ts(t,{x:e.x+i*(n.x-e.x),y:e.y+i*(n.y-e.y)})}function ns(t,e,n,s){if(Q(t,e,n,s))return 0;const i={x:t.x,y:t.y},o={x:e.x,y:e.y},a={x:n.x,y:n.y},r={x:s.x,y:s.y};return Math.min(es(i,a,r),es(o,a,r),es(a,i,o),es(r,i,o))}var ss=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 n=e.route[t],s=e.route[t+1];if(n.x===s.x&&n.y===s.y)continue;const i=[n,s],o=Qn(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 n=`${t}x${e}`;let s=this.segmentBuckets.get(n);s||(s=[],this.segmentBuckets.set(n,s)),s.push(a)}}if(e.vias&&e.vias.length>0)for(let t=0;t<e.vias.length;t++){const n=e.vias[t];if(null==n)continue;const s={viaId:`${e.connectionName}-via-${t}`,x:n.x,y:n.y,parentRoute:e},i=`${Math.floor(n.x/this.CELL_SIZE)}x${Math.floor(n.y/this.CELL_SIZE)}`;let o=this.viaBuckets.get(i);o||(o=[],this.viaBuckets.set(i,o)),o.push(s)}}else console.warn("Skipping route with missing data:",e)}getConflictingRoutesForSegment(t,e,n){const s=Qn([t,e]),i=s.minX-n,o=s.minY-n,a=s.maxX+n,r=s.maxY+n,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 s=h;s<=c;s++)for(let i=d;i<=l;i++){const o=`${s}x${i}`,a=this.segmentBuckets.get(o);if(a)for(const s of a){if(p.has(s.segmentId))continue;p.add(s.segmentId);const i=s.parentRoute,[o,a]=s.segment,r=n+i.traceThickness/2,h=r*r,c=ns(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,s={x:t.x,y:t.y},i=n+e.viaDiameter/2,o=i*i,a=es(s,g,m);if(a<o){const t=e.connectionName,n=u.get(t);(!n||a<n.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 n=t.x-e,s=t.y-e,i=t.x+e,o=t.y+e,a=Math.floor(n/this.CELL_SIZE),r=Math.floor((i+1e-9)/this.CELL_SIZE),h=Math.floor(s/this.CELL_SIZE),c=Math.floor((o+1e-9)/this.CELL_SIZE),d=new Map,l=new Set,u=new Set;for(let n=a;n<=r;n++)for(let s=h;s<=c;s++){const i=`${n}x${s}`,o=this.segmentBuckets.get(i);if(o)for(const n of o){if(l.has(n.segmentId))continue;l.add(n.segmentId);const s=n.parentRoute,i={x:n.segment[0].x,y:n.segment[0].y},o={x:n.segment[1].x,y:n.segment[1].y},a=e+s.traceThickness/2,r=a*a,h=es(t,i,o);if(h<r){const t=s.connectionName,e=d.get(t);(!e||h<e.minDistSq)&&d.set(t,{route:s,minDistSq:h})}}const a=this.viaBuckets.get(i);if(a)for(const n of a){if(u.has(n.viaId))continue;u.add(n.viaId);const s=n.parentRoute,i={x:n.x,y:n.y},o=e+s.viaDiameter/2,a=o*o,r=ts(t,i);if(r<a){const t=s.connectionName,e=d.get(t);(!e||r<e.minDistSq)&&d.set(t,{route:s,minDistSq:r})}}}const p=[];for(const t of d.values())p.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return p}},is=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=[],n=t.route;if(0===n.length)return[];let s={startIndex:0,endIndex:-1,z:n[0].z,points:[n[0]]};for(let t=1;t<n.length;t++)n[t].z===s.z?s.points.push(n[t]):(s.endIndex=t-1,e.push(s),s={startIndex:t,endIndex:-1,z:n[t].z,points:[n[t]]});return s.endIndex=n.length-1,e.push(s),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 n=e.z,s=t.points[0];if(this.canEndpointConnectOnLayer(s.x,s.y,n)&&this.canSectionMoveToLayer({currentSection:t,targetZ:n}))return t.z=n,t.points=t.points.map(t=>({...t,z:n})),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 n=e.z,s=t.points[t.points.length-1];this.canEndpointConnectOnLayer(s.x,s.y,n)&&this.canSectionMoveToLayer({currentSection:t,targetZ:n})&&(t.z=n,t.points=t.points.map(t=>({...t,z:n})))}}return void(this.solved=!0)}const t=this.routeSections[this.currentSectionIndex-1],e=this.routeSections[this.currentSectionIndex],n=this.routeSections[this.currentSectionIndex+1];if(t.z!==n.z)return void this.currentSectionIndex++;const s=t.z;if(this.canSectionMoveToLayer({currentSection:e,targetZ:s}))return e.z=s,e.points=e.points.map(t=>({...t,z:s})),void(this.currentSectionIndex+=2);this.currentSectionIndex++}canEndpointConnectOnLayer(t,e,n){const s=this.obstacleSHI.searchArea(t,e,2,2).filter(n=>{if(!n.connectedTo?.includes(this.unsimplifiedRoute.connectionName))return!1;const s=n.width/2+.05,i=n.height/2+.05,o=Math.abs(t-n.center.x)<=s,a=Math.abs(e-n.center.y)<=i;return o&&a});return!(s.length>0)||s.some(t=>t.zLayers?.includes(n))}canSectionMoveToLayer({currentSection:t,targetZ:e}){for(let n=0;n<t.points.length-1;n++){const s={...t.points[n],z:e},i={...t.points[n+1],z:e},o=this.hdRouteSHI.getConflictingRoutesForSegment(s,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:(s.x+i.x)/2,centerY:(s.y+i.y)/2,width:Math.abs(s.x-i.x),height:Math.abs(s.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(s.x-t.center.x)<.01&&Math.abs(s.y-t.center.y)<.01||Math.abs(i.x-t.center.x)<.01&&Math.abs(i.y-t.center.y)<.01)continue}if(gt(s,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 n=0;n<t.length-1;n++)t[n].z!==t[n+1].z&&e.push({x:t[n].x,y:t[n].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 n=this.routeSections[e];t.lines.push({points:n.points,strokeWidth:this.TRACE_THICKNESS,strokeColor:e===this.currentSectionIndex?"orange":0===n.z?"red":"blue"})}return t}},os=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 Kn("flatbush",t.obstacles),this.hdRouteSHI=new ss(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 is({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 n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),i=e.zLayers?.includes(1);s&&i?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":i&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,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 n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:0===s.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.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}},as=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 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:0===e.route[n].z?"rgba(255, 0, 255, 0.5)":1===e.route[n].z?"rgba(128, 0, 128, 0.5)":"rgba(0, 0, 255, 0.5)",layer:`z${e.route[n].z.toString()}`});if("filteredObstaclePathSegments"in this){const e=this.filteredObstaclePathSegments;for(const[n,s]of e)t.lines.push({points:[n,s]})}return t}};function rs(t,e,n,s){if(Q(t,e,n,s))return 0;const i=hs(t,n,s),o=hs(e,n,s),a=hs(n,t,e),r=hs(s,t,e);return Math.min(i,o,a,r)}function hs(t,e,n){const s={x:n.x-e.x,y:n.y-e.y},i=cs({x:t.x-e.x,y:t.y-e.y},s);if(i<=0)return ds(t,e);const o=cs(s,s);if(o<=i)return ds(t,n);const a=i/o;return ds(t,{x:e.x+a*s.x,y:e.y+a*s.y})}function cs(t,e){return t.x*e.x+t.y*e.y}function ds(t,e){const n=e.x-t.x,s=e.y-t.y;return Math.sqrt(n*n+s*s)}var ls=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)}),us=class{constructor(t){this.segments=t,this.buckets=new Map;const e=new Map;for(const n of t){const t=this.getSegmentKey(n);if(e.has(t))continue;e.set(t,n);const s=ls(n),i=Math.floor(s.minX/this.CELL_SIZE),o=Math.floor(s.maxX/this.CELL_SIZE),a=Math.floor(s.minY/this.CELL_SIZE),r=Math.floor(s.maxY/this.CELL_SIZE);for(let e=i;e<=o;e++)for(let s=a;s<=r;s++){const i=`${e}x${s}`,o=this.buckets.get(i),a=[n[0],n[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 n=[],s=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];s.has(e)||(s.add(e),n.push(t))}}return n}},ps=1e-6,fs=(t,e,n)=>nt(t,e,n)<=ps,gs=(t,e)=>Math.abs(t.x-e.x)<=ps&&Math.abs(t.y-e.y)<=ps,ms=(t,e)=>{if(!e||e.length<3)return!1;for(let n=0;n<e.length;n++){const s=e[n],i=e[(n+1)%e.length];if(fs(t,s,i))return!0}let n=!1;for(let s=0,i=e.length-1;s<e.length;i=s++){const o=e[s],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&&(n=!n)}return n},ys=class extends as{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}),n={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 n=K(t),s=K(e),i=Math.max(n.minX-s.maxX,s.minX-n.maxX,0),o=Math.max(n.minY-s.maxY,s.minY-n.maxY,0);return Math.hypot(i,o)}(n,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 n=t.route,s=[];for(let t=0;t<n.length-1;t++){const i=n[t],o=n[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&&s.push([i,o])}return s}),this.segmentTree=new us(this.filteredObstaclePathSegments),this.filteredVias=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const n=t.vias,s=[];for(const i of n){const n=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2+t.viaDiameter/2,o=i.x-n,a=i.x+n,r=i.y-n,h=i.y+n;o<=e.maxX&&a>=e.minX&&r<=e.maxY&&h>=e.minY&&s.push({...i,diameter:t.viaDiameter})}return s}),this.computePathSegments()}computePathSegments(){let t=0;for(let e=0;e<this.inputRoute.route.length-1;e++){const n=this.inputRoute.route[e],s=this.inputRoute.route[e+1],i=Math.sqrt((s.x-n.x)**2+(s.y-n.y)**2)+e/1e4;this.pathSegments.push({start:n,end:s,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 n=(t-e.startDistance)/e.length;return{x:e.start.x+n*(e.end.x-e.start.x),y:e.start.y+n*(e.end.y-e.start.y),z:n<.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 n=this.pathSegments[e],s=(n.startDistance+n.endDistance)/2;return t>s?e+1:e}isValidPathSegment(t,e){for(const n of this.filteredObstacles){if(!n.zLayers?.includes(t.z))continue;if(gt(t,e,n)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2)return!1}const n=this.segmentTree.getSegmentsThatCouldIntersect(t,e);for(const[s,i,o]of n)if(s.z===t.z&&i.z===t.z){if(rs({x:t.x,y:t.y},{x:e.x,y:e.y},{x:s.x,y:s.y},{x:i.x,y:i.y})<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS)return!1}for(const n of this.filteredVias)if(nt(n,t,e)<this.OBSTACLE_MARGIN+n.diameter/2+this.TRACE_THICKNESS/2)return!1;if(this.outline&&this.outline.length>=3){const n=(({start:t,end:e,polygon:n,margin:s=.2})=>{if(!n||n.length<3)return!1;const i=ms(t,n),o=ms(e,n);if(!i||!o)return!0;for(let i=0;i<n.length;i++){const o=n[i],a=n[(i+1)%n.length],r=fs(t,o,a),h=fs(e,o,a);if(r&&h)continue;if(!Q(t,e,o,a)){if(!r&&!h&&rs(t,e,o,a)<s-ps)return!0;continue}const c=it(t,e,o,a);if(!(c&&(r&&gs(c,t)||h&&gs(c,e))||c&&(gs(c,t)||gs(c,e))))return!0}return!1})({start:{x:t.x,y:t.y},end:{x:e.x,y:e.y},polygon:this.outline});if(n)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 n=((t,e)=>{const n=[],s=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&&n.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&&n.push([t,h,e]);const c=Math.min(s,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&&n.push([t,d,e]),n})({x:t.x,y:t.y},{x:e.x,y:e.y});for(const e of n){const n=e.map(e=>({x:e.x,y:e.y,z:t.z}));if(this.isValidPath(n))return n}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],n=this.find45DegreePath(t,e);if(n)return this.addPathToResult(n),void(this.solved=!0);this.lastValidPath=null,this.tailDistanceAlongPath=this.totalPathLength,this.headDistanceAlongPath=this.totalPathLength;const s=[];for(const t of this.inputRoute.route)0!==s.length&&this.arePointsEqual(s[s.length-1],t)||s.push(t);return this.newRoute=s,this.newVias=[...this.inputRoute.vias],void(this.solved=!0)}this.moveHead(this.currentStepSize);const n=this.getPointAtDistance(this.tailDistanceAlongPath),s=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],n={x:e.x,y:e.y};this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null);const s=this.newRoute[this.newRoute.length-1];s.x===n.x&&s.y===n.y||this.newRoute.push({x:n.x,y:n.y,z:s.z}),this.newVias.push(n),this.newRoute.push({x:n.x,y:n.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(n,s);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),n=this.inputRoute.route[e],s=this.inputRoute.route[this.inputRoute.route.length-1];return void(this.arePointsEqual(t,n)||this.arePointsEqual(n,s)||this.newRoute.push(n))}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),n=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:n.x,y:n.y,color:"orange",label:["Head",`z: ${n.z}`].join("\n")});const s=this.getPointAtDistance(this.headDistanceAlongPath+this.currentStepSize);t.points.push({x:s.x,y:s.y,color:"red",label:["Tentative Head",`z: ${s.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}},xs=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 ye({}),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 ys({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 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}],strokeColor:1===e.route[n].z?"rgba(0, 0, 255, 0.4)":"rgba(255, 0, 0, 0.4)",strokeWidth:.15,strokeDash:1===e.route[n].z?[.5,.5]:void 0});for(const n of e.vias||[])t.circles.push({center:n,radius:(e.viaDiameter??this.defaultViaDiameter)/2,fill:"rgba(0, 0, 255, 0.4)"})}for(const e of this.simplifiedHdRoutes){const n=this.colorMap?.[e.connectionName]||"rgba(128, 128, 128, 0.8)";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:n,strokeDash:1===e.route[s].z?[.5,.5]:void 0,step:1});for(const n of e.vias||[])t.circles.push({center:n,radius:e.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)",step:1})}for(const e of this.unsimplifiedHdRoutes){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:"rgba(255, 0, 0, 0.2)",strokeDash:[.5,.5],step:0,layer:`z${e.route[n].z.toString()}`});for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.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}},vs=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 Kn("flatbush",t.obstacles),this.hdRouteSHI=new ss(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 n=0;n<e.vias.length;n++){const s=e.vias[n],i={x:s.x,y:s.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],n=this.viasByNet.get(e.net);if(!n)continue;const s=n.indexOf(e);for(let t=s>=0?s+1:0;t<n.length;t++){const s=n[t],i=e.x-s.x,o=e.y-s.y,a=i*i+o*o,r=e.diameter/2+s.diameter/2;if(a<=r*r&&0!==a)return[e,s]}}return null}handleOffendingPair(t,e){const n=t.layers.length<e.layers.length?t:e,s=n===t?e:t,i=this.mergedViaHdRoutes[n.routeIndex].route;for(let t=0;t<n.layers.length;t++)for(let t=i.length-1;t>=1;t--){const e=i[t-1],o=i[t];if(o.x===n.x&&o.y===n.y){i.splice(t,0,{x:s.x,y:s.y,z:o.z}),i.splice(t,0,{x:s.x,y:s.y,z:e.z});const a=this.mergedViaHdRoutes[n.routeIndex];return a.vias=a.vias.map(t=>t.x===n.x&&t.y===n.y?{x:s.x,y:s.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 n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),i=e.zLayers?.includes(1);s&&i?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":i&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,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 n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:0===s.z?"rgba(255, 0, 0, 0.5)":"rgba(0, 0, 255, 0.5)",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.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}},Ms=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 os({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 vs({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 xs({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 n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),i=e.zLayers?.includes(1);s&&i?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":i&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.hdRoutes)if(0!==e.route.length){for(let n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:0===s.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`})}return t}};function Ss(t){const e=new Map;for(const n of t)for(const t of n.nodeIds)e.set(t,[...e.get(t)??[],n]);return e}var Ns=class extends e{nodes;edges;traceWidth;obstacleMargin;minPortSpacing;nodeMap;nodeEdgeMap;sharedEdgeSegments=[];edgeSegmentMap=new Map;portPointMap=new Map;colorMap;constructor({nodes:t,edges:e,traceWidth:n,obstacleMargin:s,colorMap:i}){super(),this.nodes=t,this.edges=e,this.traceWidth=n,this.obstacleMargin=s??.15,this.minPortSpacing=this.traceWidth+this.obstacleMargin,this.colorMap=i??{},this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ss(e),this.MAX_ITERATIONS=1}_step(){this.computeAllSharedEdgeSegments(),this.solved=!0}computeAllSharedEdgeSegments(){for(const t of this.edges){const[e,n]=t.nodeIds,s=this.nodeMap.get(e),i=this.nodeMap.get(n);if(!s||!i)continue;const o=this.computeSharedEdgeSegment(t,s,i);if(o){this.sharedEdgeSegments.push(o),this.edgeSegmentMap.set(t.capacityMeshEdgeId,o);for(const t of o.portPoints)this.portPointMap.set(t.segmentPortPointId,t)}}}computeSharedEdgeSegment(t,e,n){const s=this.findOverlappingSegment(e,n);if(!s)return null;const i=e.availableZ.filter(t=>n.availableZ.includes(t));if(0===i.length)return null;const o=Math.sqrt((s.end.x-s.start.x)**2+(s.end.y-s.start.y)**2),a=this.minPortSpacing/2,r=Math.max(0,o-2*a),h=Math.max(1,Math.floor(r/this.minPortSpacing)+1),c=[],d=s.end.x-s.start.x,l=s.end.y-s.start.y,u=(s.start.x+s.end.x)/2,p=(s.start.y+s.end.y)/2,f=[];for(let t=0;t<h;t++){let e;e=0===o||1===h?.5:(a+r*t/(h-1))/o;const n=s.start.x+d*e,i=s.start.y+l*e,c=Math.sqrt((n-u)**2+(i-p)**2);f.push({x:n,y:i,distToCenter:c})}const g=f.reduce((t,e)=>e.distToCenter<t.distToCenter?e:t);for(let s=0;s<h;s++){const{x:o,y:a}=f[s],r=Math.sqrt((o-g.x)**2+(a-g.y)**2);for(const h of i){const i={segmentPortPointId:`${t.capacityMeshEdgeId}_pp${s}_z${h}`,x:o,y:a,availableZ:[h],nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],edgeId:t.capacityMeshEdgeId,connectionName:null,distToCentermostPortOnZ:r};c.push(i)}}return{edgeId:t.capacityMeshEdgeId,nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],start:s.start,end:s.end,availableZ:i,portPoints:c}}findOverlappingSegment(t,e){const n={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)},s={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)},i=n.end-n.start,o=s.end-s.start;if(i<-1e-4||o<-1e-4)return null;if(i<o){const t=(n.start+n.end)/2;return{start:{x:t,y:s.start},end:{x:t,y:s.end}}}{const t=(s.start+s.end)/2;return{start:{x:n.start,y:t},end:{x:n.end,y:t}}}}getAvailablePortPointsBetweenNodes(t,e){const n=this.edges.find(n=>n.nodeIds[0]===t&&n.nodeIds[1]===e||n.nodeIds[0]===e&&n.nodeIds[1]===t);if(!n)return[];const s=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return s?s.portPoints.filter(t=>null===t.connectionName):[]}getPortPointsForEdge(t,e){const n=this.edges.find(n=>n.nodeIds[0]===t&&n.nodeIds[1]===e||n.nodeIds[0]===e&&n.nodeIds[1]===t);if(!n)return[];const s=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return s?.portPoints??[]}assignPortPoint(t,e,n){const s=this.portPointMap.get(t);return!!s&&(null===s.connectionName&&(s.connectionName=e,s.rootConnectionName=n,!0))}releasePortPoint(t){const e=this.portPointMap.get(t);return!!e&&(e.connectionName=null,e.rootConnectionName=void 0,!0)}getAvailablePortCountForEdge(t,e){return this.getAvailablePortPointsBetweenNodes(t,e).length}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.sharedEdgeSegments){t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.5)"});for(const n of e.portPoints){const e=n.connectionName?this.colorMap[n.connectionName]??"blue":"rgba(0, 200, 0, 0.7)";t.circles.push({center:{x:n.x,y:n.y},radius:this.traceWidth/2,fill:e,layer:`z${n.availableZ.join(",")}`,label:[n.segmentPortPointId,n.connectionName,n.availableZ.join(","),`cd: ${n.distToCentermostPortOnZ}`,`connects: ${n.nodeIds.join(",")}`].filter(Boolean).join("\n")})}}return t}},bs=(t,e,n,s)=>{if(t?._containsTarget)return 0;return((.82*e+.41*n+.2*s)/2)**1.1/ve(t)};var Ps=class extends e{hyperParameters;simpleRouteJson;inputNodes;nodeMap;nodePortPointsMap;portPointMap;connectionsWithResults=[];assignedPortPoints=new Map;nodeAssignedPortPoints=new Map;PORT_POINT_REUSE_FACTOR=1e3;get NODE_PF_FACTOR(){return this.hyperParameters.NODE_PF_FACTOR??50}get MEMORY_PF_FACTOR(){return this.hyperParameters.MEMORY_PF_FACTOR??0}get CENTER_OFFSET_FOCUS_SHIFT(){return this.hyperParameters.CENTER_OFFSET_FOCUS_SHIFT??0}get RANDOM_COST_MAGNITUDE(){return this.hyperParameters.RANDOM_COST_MAGNITUDE??0}get REWARD_LOW_TRAVEL_PF_MAGNITUDE(){return this.hyperParameters.REWARD_LOW_TRAVEL_PF_MAGNITUDE??0}get BASE_CANDIDATE_COST(){return this.hyperParameters.BASE_CANDIDATE_COST??0}Z_DIST_COST=0;get CENTER_OFFSET_DIST_PENALTY_FACTOR(){return this.hyperParameters.CENTER_OFFSET_DIST_PENALTY_FACTOR??0}colorMap;get GREEDY_MULTIPLIER(){return this.hyperParameters.GREEDY_MULTIPLIER??1.3}MAX_CANDIDATES_IN_MEMORY=5e4;get MAX_ITERATIONS_PER_PATH(){return this.hyperParameters.MAX_ITERATIONS_PER_PATH??4e3}nodeMemoryPfMap;currentConnectionIndex=0;currentPathIterations=0;candidates;visitedPortPoints;connectionNameToGoalNodeIds;capacityMeshNodeMap;avgNodePitch=1;baseNodeCostCache=new Map;segmentDeltaCostCache=new Map;constructor({simpleRouteJson:t,inputNodes:e,capacityMeshNodes:n,colorMap:s,nodeMemoryPfMap:i,hyperParameters:o}){super(),this.MAX_ITERATIONS=5e4,this.simpleRouteJson=t,this.inputNodes=e,this.colorMap=s??{},this.capacityMeshNodeMap=new Map(n.map(t=>[t.capacityMeshNodeId,t])),this.nodeMemoryPfMap=i??new Map,this.hyperParameters=o??{SHUFFLE_SEED:0},this.nodeMap=new Map(e.map(t=>[t.capacityMeshNodeId,t]));const a=e.map(t=>(t.width+t.height)/2).filter(t=>Number.isFinite(t)&&t>0);this.avgNodePitch=a.length>0?a.reduce((t,e)=>t+e,0)/a.length:1,this.portPointMap=new Map,this.nodePortPointsMap=new Map;for(const t of e)this.nodePortPointsMap.set(t.capacityMeshNodeId,[]),this.nodeAssignedPortPoints.set(t.capacityMeshNodeId,[]);for(const t of e)for(const e of t.portPoints){this.portPointMap.set(e.portPointId,e);for(const t of e.connectionNodeIds){const n=this.nodePortPointsMap.get(t);n&&!n.some(t=>t.portPointId===e.portPointId)&&n.push(e)}}const{connectionsWithResults:r,connectionNameToGoalNodeIds:h}=this.getConnectionsWithNodes();this.connectionsWithResults=r,this.connectionNameToGoalNodeIds=h}clearCostCaches(){this.baseNodeCostCache.clear(),this.segmentDeltaCostCache.clear()}clampPf(t){return Number.isFinite(t)?Math.min(Math.max(t,0),.999999):.999999}pfToFailureCost(t){const e=this.clampPf(t);return-Math.log(1-e)}round3(t){return Math.round(1e3*t)/1e3}pointKey(t,e){return`${this.round3(t.x)},${this.round3(t.y)},${e}`}getBaseNodeFailureCost(t){const e=this.baseNodeCostCache.get(t);if(null!=e)return e;const n=this.nodeMap.get(t);if(!n)return 0;const s=this.computeNodePf(n),i=this.pfToFailureCost(s);return this.baseNodeCostCache.set(t,i),i}getNodeDeltaFailureCostForSegment(t,e,n){const s=`${t}|${this.pointKey({x:e.x,y:e.y},e.z)}|${this.pointKey({x:n.x,y:n.y},n.z)}|${e.connectionName}|${e.rootConnectionName??""}`,i=this.segmentDeltaCostCache.get(s);if(null!=i)return i;const o=this.nodeMap.get(t);if(!o)return 0;const a=this.getBaseNodeFailureCost(t),r=this.computeNodePf(o,[e,n]),h=this.pfToFailureCost(r),c=Math.max(0,h-a)*this.NODE_PF_FACTOR;return this.segmentDeltaCostCache.set(s,c),c}getConnectionsWithNodes(){let t=[];const e=this.inputNodes.filter(t=>t._containsTarget),n=new Map;for(const s of this.simpleRouteJson.connections){const i=[];for(const t of s.pointsToConnect){let n=this.inputNodes[0],s=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<s&&(s=e,n=i)}i.push(n)}if(i.length<2)throw new Error(`Not enough nodes for connection "${s.name}", only ${i.length} found`);n.set(s.name,i.map(t=>t.capacityMeshNodeId)),t.push({connection:s,nodeIds:[i[0].capacityMeshNodeId,i[i.length-1].capacityMeshNodeId],straightLineDistance:st(i[0].center,i[i.length-1].center)})}return t=Pt(t,this.hyperParameters.SHUFFLE_SEED??0),{connectionsWithResults:t,connectionNameToGoalNodeIds:n}}buildNodeWithPortPointsForCrossing(t,e){const n=this.nodeAssignedPortPoints.get(t.capacityMeshNodeId)??[],s=e?[...n,...e]:n;return{capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:s,availableZ:t.availableZ}}computeNodePf(t,e){if(t._containsTarget)return 0;const n=this.buildNodeWithPortPointsForCrossing(t,e),s=jt(n);return bs(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),s.numSameLayerCrossings,s.numEntryExitLayerChanges,s.numTransitionPairCrossings)}getPortPointReusePenalty(t,e){const n=this.assignedPortPoints.get(t);return n?e===n.rootConnectionName?0:this.PORT_POINT_REUSE_FACTOR:0}getOtherNodeId(t,e){const[n,s]=t.connectionNodeIds;return n===e?s:s===e?n:null}computeG(t,e,n,s,i){const o=t.currentNodeId,a=t.point,r=st(a,{x:e.x,y:e.y}),h={x:a.x,y:a.y,z:t.z,connectionName:s,rootConnectionName:i},c={x:e.x,y:e.y,z:e.z,connectionName:s,rootConnectionName:i},d=this.getNodeDeltaFailureCostForSegment(o,h,c),l=this.getPortPointReusePenalty(e.portPointId,i),u=(e.distToCentermostPortOnZ-this.CENTER_OFFSET_FOCUS_SHIFT)**2*this.CENTER_OFFSET_DIST_PENALTY_FACTOR;return t.g+this.BASE_CANDIDATE_COST+r+d+l+u}computeGToEndTarget(t,e,n,s){const i=t.currentNodeId,o=st(t.point,e),a={x:t.point.x,y:t.point.y,z:t.z,connectionName:n,rootConnectionName:s},r={x:e.x,y:e.y,z:t.z,connectionName:n,rootConnectionName:s},h=this.getNodeDeltaFailureCostForSegment(i,a,r);return t.g+this.BASE_CANDIDATE_COST+o+h}computeH(t,e,n,s){const i=this.nodeMap.get(n);if(!i)return 0;const o=st(t,i.center),a=this.avgNodePitch>0?o/this.avgNodePitch:0,r=this.clampPf(this.nodeMemoryPfMap.get(e)??0),h=(r+this.clampPf(this.nodeMemoryPfMap.get(n)??0))/2,c=a*(this.pfToFailureCost(h)*this.MEMORY_PF_FACTOR);return o+a*this.BASE_CANDIDATE_COST+c+(!i.availableZ.includes(s)?this.Z_DIST_COST:0)+(r<.15?-this.REWARD_LOW_TRAVEL_PF_MAGNITUDE:0)}getAvailableExitPortPointsWithOmissions(t,e){const n=this.nodePortPointsMap.get(t)??[],s=new Map;for(const e of n){if(this.visitedPortPoints?.has(e.portPointId))continue;const n=this.getOtherNodeId(e,t);if(!n)continue;const i=`${n}|${e.z}`,o=s.get(i)??[];o.push(e),s.set(i,o)}const i=[];for(const[,t]of s){t.sort((t,e)=>t.distToCentermostPortOnZ-e.distToCentermostPortOnZ);const e=t[0];if(!e)continue;if(!this.assignedPortPoints.has(e.portPointId)){i.push(e);continue}const n=[];for(let e=1;e<t.length;e++)this.assignedPortPoints.has(t[e].portPointId)||n.push(t[e]);i.push(...n)}return i}canTravelThroughObstacle(t,e){const n=this.connectionNameToGoalNodeIds.get(e);return n?.includes(t.capacityMeshNodeId)??!1}isAtEndGoal(t,e){return t===e}getBacktrackedPath(t){const e=[];let n=t;for(;n;)e.push(n),n=n.prevCandidate;return e.reverse()}assignPortPointsForPath(t,e,n){const s=[];for(const i of t){if(!i.portPoint)continue;const t=i.portPoint;this.assignedPortPoints.set(t.portPointId,{connectionName:e,rootConnectionName:n});const o={x:t.x,y:t.y,z:t.z,connectionName:e,rootConnectionName:n};s.push(o);for(const e of t.connectionNodeIds){const t=this.nodeAssignedPortPoints.get(e)??[];t.push(o),this.nodeAssignedPortPoints.set(e,t)}}return s}addTargetPointsToNodes(t,e){const n=t[0],s=t[t.length-1],i=e.pointsToConnect[0],o=e.pointsToConnect[e.pointsToConnect.length-1];if(n&&i){const t=this.nodeAssignedPortPoints.get(n.currentNodeId)??[];t.push({x:i.x,y:i.y,z:n.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(n.currentNodeId,t)}if(s&&o){const t=this.nodeAssignedPortPoints.get(s.currentNodeId)??[];t.push({x:o.x,y:o.y,z:s.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(s.currentNodeId,t)}}isPortPointInPathChain(t,e){let n=t;for(;n;){if(n.portPoint?.portPointId===e)return!0;n=n.prevCandidate}return!1}isNodeInPathChain(t,e){let n=t;for(;n;){if(n.currentNodeId===e)return!0;n=n.prevCandidate}return!1}_step(){const t=this.connectionsWithResults[this.currentConnectionIndex];if(!t)return void(this.solved=!0);if(this.currentPathIterations++,this.currentPathIterations>this.MAX_ITERATIONS_PER_PATH)return this.currentConnectionIndex++,this.candidates=null,this.visitedPortPoints=null,this.currentPathIterations=0,this.failed=!0,void(this.error=`Exceeded MAX_ITERATIONS_PER_PATH (${this.MAX_ITERATIONS_PER_PATH}) on connection ${t.connection.name}`);const[e,n]=t.nodeIds,s=this.nodeMap.get(e),i=this.nodeMap.get(n);if(!s||!i)return this.currentConnectionIndex++,void(this.currentPathIterations=0);const o=t.connection.name,a=t.connection.rootConnectionName,r=t.connection.pointsToConnect[0];if(!this.candidates){this.clearCostCaches(),this.candidates=[],this.visitedPortPoints=new Set;for(const t of s.availableZ){const i=r?{x:r.x,y:r.y}:s.center,o=this.computeH(i,e,n,t),a=0+o*this.GREEDY_MULTIPLIER;this.candidates.push({prevCandidate:null,portPoint:null,currentNodeId:e,point:i,z:t,f:a,g:0,h:o})}}this.candidates.sort((t,e)=>t.f-e.f);const h=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),!h)return this.error=`Ran out of candidates on connection ${o}`,this.currentConnectionIndex++,this.candidates=null,this.visitedPortPoints=null,this.currentPathIterations=0,void(this.failed=!0);if(this.isAtEndGoal(h.currentNodeId,n)){const e=t.connection.pointsToConnect[t.connection.pointsToConnect.length-1],s=e?{x:e.x,y:e.y}:i.center,r=this.computeGToEndTarget(h,s,o,a),c={prevCandidate:h,portPoint:null,currentNodeId:n,point:s,z:h.z,g:r,h:0,f:r},d=this.getBacktrackedPath(c);return t.path=d,t.portPoints=this.assignPortPointsForPath(d,o,a),this.addTargetPointsToNodes(d,t.connection),this.clearCostCaches(),this.currentConnectionIndex++,this.candidates=null,this.visitedPortPoints=null,void(this.currentPathIterations=0)}const c=this.getAvailableExitPortPointsWithOmissions(h.currentNodeId,n);for(const t of c){if(this.isPortPointInPathChain(h,t.portPointId))continue;const e=this.getOtherNodeId(t,h.currentNodeId);if(!e)continue;if(this.isNodeInPathChain(h,e))continue;const s=this.nodeMap.get(e);if(!s)continue;if(s._containsObstacle&&!this.canTravelThroughObstacle(s,o))continue;const i=this.computeG(h,t,e,o,a),r=this.computeH({x:t.x,y:t.y},e,n,t.z),c=this.RANDOM_COST_MAGNITUDE*Nt(this.iterations)(),d=i+r*this.GREEDY_MULTIPLIER+c;this.candidates.push({prevCandidate:h,portPoint:t,currentNodeId:e,point:{x:t.x,y:t.y},z:t.z,f:d,g:i,h:r})}h.portPoint&&this.visitedPortPoints&&this.visitedPortPoints.add(h.portPoint.portPointId)}getNodesWithPortPoints(){const t=[];for(const e of this.inputNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];n.length>0&&t.push({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ})}return t}visualize(){return function(t){const e={lines:[],points:[],rects:[],circles:[]};for(const n of t.inputNodes){const s=t.computeNodePf(n),i=t.nodeMemoryPfMap.get(n.capacityMeshNodeId)??0,o=Math.min(255,Math.floor(512*s)),a=Math.max(0,255-Math.floor(512*s)),r=`rgba(${o}, ${a}, ${a}, 0.3)`,h=t.buildNodeWithPortPointsForCrossing(n),c=jt(h);e.rects.push({center:n.center,width:.9*n.width,height:.9*n.height,layer:`z${n.availableZ.join(",")}`,fill:r,label:`${n.capacityMeshNodeId}\npf: ${s.toFixed(3)}, memPf: ${i.toFixed(3)}\nxSame: ${c.numSameLayerCrossings}, xLC: ${c.numEntryExitLayerChanges}, xTransition: ${c.numTransitionPairCrossings}`})}for(const[n,s]of t.portPointMap){const i=t.assignedPortPoints.get(n),o=i?t.colorMap[i.connectionName]??"blue":"rgba(150, 150, 150, 0.5)";e.circles.push({center:{x:s.x,y:s.y},radius:.05,fill:o,layer:`z${s.z}`,label:[n,`conn: ${i?.connectionName}`,`cd: ${s.distToCentermostPortOnZ}`,`connects: ${s.connectionNodeIds.join(",")}`,`rootConn: ${i?.rootConnectionName}`].filter(Boolean).join("\n")})}for(const n of t.connectionsWithResults){if(!n.path)continue;const s=n.connection,i=t.colorMap[s.name]??"blue",o=[];for(const t of n.path)o.push({x:t.point.x,y:t.point.y,z:t.z});for(let t=0;t<o.length-1;t++){const n=o[t],s=o[t+1],a=n.z===s.z,r=n.z;let h;h=a?0===r?void 0:"10 5":"3 3 10",e.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.y}],strokeColor:i,strokeDash:h})}}if(!t.solved&&t.candidates&&t.candidates.length>0){const n=t.connectionsWithResults[t.currentConnectionIndex],s=n?t.colorMap[n.connection.name]??"blue":"blue";if(n){const[i,o]=n.nodeIds,a=t.nodeMap.get(i),r=t.nodeMap.get(o),h=n.connection.pointsToConnect[0],c=n.connection.pointsToConnect[n.connection.pointsToConnect.length-1];if(a&&r){const t=h?{x:h.x,y:h.y}:a.center,i=c?{x:c.x,y:c.y}:r.center;e.lines.push({points:[t,i],strokeColor:H(s,.5),strokeDash:"5 5"}),e.points.push({x:t.x,y:t.y,color:s,label:[`Start: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.points.push({x:i.x,y:i.y,color:s,label:[`End: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.circles.push({center:i,radius:.08,stroke:s,label:`Goal: ${n.connection.name}`})}}const i=[...t.candidates].sort((t,e)=>t.f-e.f).slice(0,20);for(const o of i){const i=[];let a=o;for(;a;)i.unshift({x:a.point.x,y:a.point.y,z:a.z}),a=a.prevCandidate;for(let t=0;t<i.length-1;t++){const n=i[t],o=i[t+1],a=n.z===o.z,r=n.z;let h;h=a?0===r?void 0:"10 5":"3 3 10",e.lines.push({points:[{x:n.x+.02*n.z,y:n.y+.02*n.z},{x:o.x+.02*o.z,y:o.y+.02*o.z}],strokeColor:H(s,.25),strokeDash:h})}if(i.length>=1){const a=i[i.length-1];let r=0,h=0,c=0,d=0,l=0;const u=t.nodeMap.get(o.prevCandidate?.currentNodeId);if(u&&o.prevCandidate&&o.portPoint){const e=n.connection.name,s={x:o.prevCandidate.point.x,y:o.prevCandidate.point.y,z:o.prevCandidate.z,connectionName:e},i={x:o.portPoint.x,y:o.portPoint.y,z:o.portPoint.z,connectionName:e},a=t.buildNodeWithPortPointsForCrossing(u,[s,i]),p=jt(a);c=p.numSameLayerCrossings,d=p.numTransitionPairCrossings,l=p.numEntryExitLayerChanges;const f=t.capacityMeshNodeMap.get(u.capacityMeshNodeId);f&&(h=bs(f,c,l,d),r=h**2*t.NODE_PF_FACTOR)}e.circles.push({center:a,radius:.03,fill:H(s,.25),layer:`z${o.z}`,label:[`f: ${o.f.toFixed(2)}`,`g: ${o.g.toFixed(2)}`,`h: ${o.h.toFixed(2)}`,`z: ${o.z}`,`node: ${o.currentNodeId}`,`Cost(Pf): ${r.toFixed(3)}`,`Pf: ${h.toFixed(3)}`,`xSame: ${c}, xTrans: ${d}, xLC: ${l}`].join("\n")})}}}return e}(this)}};function Is(t,e){let n=0;for(const s of t){const t=e.get(s.capacityMeshNodeId);if(!t)continue;if(t._containsTarget)continue;const i=jt(s),o=Math.min(bs(t,i.numSameLayerCrossings,i.numEntryExitLayerChanges,i.numTransitionPairCrossings),.999999);n+=Math.log(1-o)}return n}function Cs(t,e){if(e._containsTarget)return 0;const n=jt(t);return bs(e,n.numSameLayerCrossings,n.numEntryExitLayerChanges,n.numTransitionPairCrossings)}var _s=[{SHUFFLE_SEED:3,EXPANSION_DEGREES:8,CENTER_OFFSET_DIST_PENALTY_FACTOR:0}],Es=class extends e{simpleRouteJson;inputNodes;capacityMeshNodes;capacityMeshEdges;colorMap;nodeMap;capacityMeshNodeMap;connectionResults;assignedPortPoints;nodeAssignedPortPoints;sections=[];activeSubSolver=null;currentSection=null;sectionScoreBeforeOptimization=0;currentSectionCenterNodeId=null;currentScheduleIndex=0;nodePfMap=new Map;attemptsToFixNode=new Map;sectionAttempts=0;MAX_ATTEMPTS_PER_NODE=25;MAX_SECTION_ATTEMPTS=500;ACCEPTABLE_PF=.1;constructor(t){super(),this.MAX_ITERATIONS=1e6,this.simpleRouteJson=t.simpleRouteJson,this.inputNodes=t.inputNodes,this.capacityMeshNodes=t.capacityMeshNodes,this.capacityMeshEdges=t.capacityMeshEdges,this.colorMap=t.colorMap??{},this.nodeMap=new Map(t.inputNodes.map(t=>[t.capacityMeshNodeId,t])),this.capacityMeshNodeMap=new Map(t.capacityMeshNodes.map(t=>[t.capacityMeshNodeId,t])),this.connectionResults=[...t.initialConnectionResults],this.assignedPortPoints=new Map(t.initialAssignedPortPoints),this.nodeAssignedPortPoints=new Map(t.initialNodeAssignedPortPoints),this.nodePfMap=this.computeInitialPfMap();const e=this.computeBoardScore();this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.nodesExamined=0,this.stats.sectionAttempts=0,this.stats.sectionScores={},this.stats.initialBoardScore=e,this.stats.currentBoardScore=e,this.stats.errors=0}computeInitialPfMap(){const t=new Map;for(const e of this.capacityMeshNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];if(0===n.length)continue;const s=Cs({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ},e);t.set(e.capacityMeshNodeId,s)}return t}computeBoardScore(){return Is(this.getNodesWithPortPoints(),this.capacityMeshNodeMap)}recomputePfForNodes(t){for(const e of t){const t=this.capacityMeshNodeMap.get(e);if(!t)continue;const n=this.nodeAssignedPortPoints.get(e)??[];if(0===n.length){this.nodePfMap.set(e,0);continue}const s=Cs({capacityMeshNodeId:e,center:t.center,width:t.width,height:t.height,portPoints:n,availableZ:t.availableZ},t);this.nodePfMap.set(e,s)}}getCreatePortPointSectionInput(){return{inputNodes:this.inputNodes,capacityMeshNodes:this.capacityMeshNodes,capacityMeshEdges:this.capacityMeshEdges,nodeMap:this.nodeMap,connectionResults:this.connectionResults}}createSection(t){return function(t,e){const{inputNodes:n,capacityMeshNodes:s,capacityMeshEdges:i,connectionResults:o}=t,{centerOfSectionCapacityNodeId:a,expansionDegrees:r}=e,h=new Map;for(const t of i){const[e,n]=t.nodeIds;h.has(e)||h.set(e,new Set),h.has(n)||h.set(n,new Set),h.get(e).add(n),h.get(n).add(e)}const c=new Set,d=new Set,l=[];for(l.push({nodeId:a,depth:0}),d.add(a);l.length>0;){const{nodeId:t,depth:e}=l.shift();if(c.add(t),e<r){const n=h.get(t)??new Set;for(const t of n)d.has(t)||(d.add(t),l.push({nodeId:t,depth:e+1}))}}const u=n.filter(t=>c.has(t.capacityMeshNodeId)),p=(new Map(s.map(t=>[t.capacityMeshNodeId,t])),s.filter(t=>c.has(t.capacityMeshNodeId))),f=[],g=[];for(const t of i){const[e,n]=t.nodeIds,s=c.has(e),i=c.has(n);s&&i?f.push(t):(s||i)&&g.push(t)}const m=u.map(t=>{const e=t.portPoints.filter(t=>{const[e,n]=t.connectionNodeIds,s=c.has(e),i=c.has(n);return s||i});return{...t,portPoints:e}}),y=function(t,e){const n=[];for(const s of t){if(!s.path||0===s.path.length)continue;const t=s.connection.name,i=s.connection.rootConnectionName;let o=null;for(let a=0;a<s.path.length;a++){const r=s.path[a];if(e.has(r.currentNodeId))null===o&&(o=a);else if(null!==o){const e=s.path.slice(o,a);n.push({connectionName:t,rootConnectionName:i,points:e.map(t=>({x:t.point.x,y:t.point.y,z:t.z,nodeId:t.currentNodeId})),originalStartIndex:o,originalEndIndex:a-1,hasEntryFromOutside:o>0,hasExitToOutside:!0}),o=null}}if(null!==o){const e=s.path.slice(o);n.push({connectionName:t,rootConnectionName:i,points:e.map(t=>({x:t.point.x,y:t.point.y,z:t.z,nodeId:t.currentNodeId})),originalStartIndex:o,originalEndIndex:s.path.length-1,hasEntryFromOutside:o>0,hasExitToOutside:!1})}}return n}(o??[],c);return{centerNodeId:a,expansionDegrees:r,nodeIds:c,inputNodes:m,capacityMeshNodes:p,internalEdges:f,boundaryEdges:g,sectionPaths:y}}(this.getCreatePortPointSectionInput(),t)}getSectionNodesWithPortPoints(t){const e=[];for(const n of t.nodeIds){const t=this.nodeMap.get(n),s=this.capacityMeshNodeMap.get(n);if(!t||!s)continue;const i=this.nodeAssignedPortPoints.get(n)??[];i.length>0&&e.push({capacityMeshNodeId:n,center:t.center,width:t.width,height:t.height,portPoints:i,availableZ:t.availableZ})}return e}getNodesWithPortPoints(){const t=[];for(const e of this.inputNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];n.length>0&&t.push({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ})}return t}findHighestPfNode(){let t=null,e=0;for(const[n,s]of this.nodePfMap.entries()){s*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_ATTEMPTS_PER_NODE)**2>e&&(e=s,t=n)}return!t||e<this.ACCEPTABLE_PF?null:t}currentSectionCutPathInfo=new Map;createSectionSimpleRouteJson(t){const e=[];this.currentSectionCutPathInfo.clear();for(const n of this.connectionResults){if(!n.path||0===n.path.length)continue;const[s,i]=n.nodeIds,o=t.nodeIds.has(s),a=t.nodeIds.has(i);o&&a&&e.push(n.connection)}for(const n of t.sectionPaths){if(!n.hasEntryFromOutside&&!n.hasExitToOutside)continue;if(n.points.length<2)continue;const t=this.connectionResults.find(t=>t.connection.name===n.connectionName);if(!t)continue;const s=`__cut__${n.connectionName}__${n.originalStartIndex}`;this.colorMap[s]=this.colorMap[n.connectionName];const i=n.points[0],o=n.points[n.points.length-1],a={name:s,rootConnectionName:n.rootConnectionName??n.connectionName,pointsToConnect:[{x:i.x,y:i.y,layers:[`layer${i.z+1}`]},{x:o.x,y:o.y,layers:[`layer${o.z+1}`]}]};e.push(a),this.currentSectionCutPathInfo.set(s,{sectionPath:n,originalConnectionResult:t})}return{...this.simpleRouteJson,connections:e}}prepareSectionInputNodesForCutPaths(t){const e=new Set;for(const[,t]of this.currentSectionCutPathInfo.entries()){const{sectionPath:n}=t;if(0===n.points.length)continue;const s=n.points[0].nodeId;e.add(s);const i=n.points[n.points.length-1].nodeId;e.add(i)}return t.inputNodes.map(t=>e.has(t.capacityMeshNodeId)?{...t,_containsTarget:!0}:t)}getHyperParametersForAttempt(t){return{..._s[t%_s.length],SHUFFLE_SEED:(_s[t%_s.length].SHUFFLE_SEED??0)+1700*t}}reattachSection(t,e,n,s){const i=[],o=[];for(const t of e)t.connection.name.startsWith("__cut__")?o.push(t):i.push(t);const a=new Set(i.map(t=>t.connection.name));this.connectionResults=this.connectionResults.filter(t=>!a.has(t.connection.name)),this.connectionResults.push(...i);for(const[t,e]of this.nodeAssignedPortPoints.entries()){const n=e.filter(t=>!a.has(t.connectionName));this.nodeAssignedPortPoints.set(t,n)}for(const[t,e]of this.assignedPortPoints.entries())a.has(e.connectionName)&&this.assignedPortPoints.delete(t);for(const e of o){const n=this.currentSectionCutPathInfo.get(e.connection.name);if(!n||!e.path)continue;const{sectionPath:s,originalConnectionResult:i}=n,o=i.path;if(!o)continue;const a=s.connectionName;for(const[e,n]of this.nodeAssignedPortPoints.entries()){const s=n.filter(n=>n.connectionName!==a||!t.nodeIds.has(e));this.nodeAssignedPortPoints.set(e,s)}const r=o.slice(0,s.originalStartIndex),h=o.slice(s.originalEndIndex+1),c=[];let d=r.length>0?r[r.length-1]:null;for(const t of e.path){const e={...t,prevCandidate:d};c.push(e),d=e}if(h.length>0&&c.length>0&&(h[0]={...h[0],prevCandidate:c[c.length-1]}),i.path=[...r,...c,...h],e.portPoints)for(const n of e.portPoints){const e={...n,connectionName:a,rootConnectionName:s.rootConnectionName??a};for(const s of t.inputNodes)for(const t of s.portPoints)if(Math.abs(t.x-n.x)<.001&&Math.abs(t.y-n.y)<.001&&t.z===n.z){for(const n of t.connectionNodeIds){const t=this.nodeAssignedPortPoints.get(n)??[];t.push(e),this.nodeAssignedPortPoints.set(n,t)}break}}}for(const[t,e]of n.entries())e.connectionName.startsWith("__cut__")||this.assignedPortPoints.set(t,e);for(const[t,e]of s.entries()){const n=e.filter(t=>!t.connectionName.startsWith("__cut__"));if(n.length>0){const e=this.nodeAssignedPortPoints.get(t)??[];this.nodeAssignedPortPoints.set(t,[...e,...n])}}}_step(){if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved||this.activeSubSolver.failed){if(this.activeSubSolver.failed){if(this.currentScheduleIndex++,this.activeSubSolver.error&&this.stats.errors++,this.currentScheduleIndex<_s.length&&this.currentSectionCenterNodeId){const t=_s[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:this.currentSectionCenterNodeId,expansionDegrees:t.EXPANSION_DEGREES});const e=this.createSectionSimpleRouteJson(this.currentSection),n=this.prepareSectionInputNodesForCutPaths(this.currentSection);this.activeSubSolver=new Ps({simpleRouteJson:e,inputNodes:n,capacityMeshNodes:this.currentSection.capacityMeshNodes,colorMap:this.colorMap,nodeMemoryPfMap:this.nodePfMap,hyperParameters:this.getHyperParametersForAttempt(this.sectionAttempts)})}else this.stats.failedOptimizations++,this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0;return}const t=Is(this.activeSubSolver.getNodesWithPortPoints(),this.capacityMeshNodeMap),e=`attempt${this.sectionAttempts}`;if(t>this.sectionScoreBeforeOptimization){const t=this.stats.currentBoardScore,n=[...this.connectionResults],s=new Map(this.assignedPortPoints),i=new Map(Array.from(this.nodeAssignedPortPoints.entries()).map(([t,e])=>[t,[...e]]));this.reattachSection(this.currentSection,this.activeSubSolver.connectionsWithResults,this.activeSubSolver.assignedPortPoints,this.activeSubSolver.nodeAssignedPortPoints),this.recomputePfForNodes(this.currentSection.nodeIds);const o=this.computeBoardScore();this.stats.sectionScores[e]=o,o>t?(this.stats.successfulOptimizations++,this.stats.currentBoardScore=o):(this.connectionResults=n,this.assignedPortPoints=s,this.nodeAssignedPortPoints=i,this.recomputePfForNodes(this.currentSection.nodeIds),this.stats.failedOptimizations++),this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0}else if(this.currentScheduleIndex++,this.currentScheduleIndex<_s.length&&this.currentSectionCenterNodeId){const t=_s[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:this.currentSectionCenterNodeId,expansionDegrees:t.EXPANSION_DEGREES});const e=this.createSectionSimpleRouteJson(this.currentSection),n=this.prepareSectionInputNodesForCutPaths(this.currentSection);this.activeSubSolver=new Ps({simpleRouteJson:e,inputNodes:n,capacityMeshNodes:this.currentSection.capacityMeshNodes,colorMap:this.colorMap,nodeMemoryPfMap:this.nodePfMap,hyperParameters:this.getHyperParametersForAttempt(this.sectionAttempts)})}else this.stats.failedOptimizations++,this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0}return}if(this.sectionAttempts>=this.MAX_SECTION_ATTEMPTS)return void(this.solved=!0);const t=this.findHighestPfNode();if(!t)return void(this.solved=!0);this.sectionAttempts++,this.stats.sectionAttempts=this.sectionAttempts,this.stats.nodesExamined++,this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.currentSectionCenterNodeId=t,this.currentScheduleIndex=0;const e=_s[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:t,expansionDegrees:e.EXPANSION_DEGREES});const n=this.getSectionNodesWithPortPoints(this.currentSection);this.sectionScoreBeforeOptimization=Is(n,this.capacityMeshNodeMap);const s=this.createSectionSimpleRouteJson(this.currentSection);if(0===s.connections.length)return this.currentSection=null,void(this.currentSectionCenterNodeId=null);const i=this.prepareSectionInputNodesForCutPaths(this.currentSection);this.activeSubSolver=new Ps({simpleRouteJson:s,inputNodes:i,capacityMeshNodes:this.currentSection.capacityMeshNodes,colorMap:this.colorMap,nodeMemoryPfMap:this.nodePfMap,hyperParameters:this.getHyperParametersForAttempt(this.sectionAttempts)})}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();if(this.currentSection)return function(t,e){const n={lines:[],points:[],rects:[],circles:[]};for(const e of t.inputNodes){const s=e.capacityMeshNodeId===t.centerNodeId,i=s?"rgba(0, 200, 0, 0.3)":"rgba(200, 200, 200, 0.3)";n.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,layer:`z${e.availableZ.join(",")}`,fill:i,label:`${e.capacityMeshNodeId}${s?" (CENTER)":""}`})}for(const e of t.inputNodes)for(const t of e.portPoints){const e="rgba(150, 150, 150, 0.5)";n.circles.push({center:{x:t.x,y:t.y},radius:.05,fill:e,layer:`z${t.z}`,label:[t.portPointId,`cd: ${t.distToCentermostPortOnZ}`,`connects: ${t.connectionNodeIds.join(",")}`].filter(Boolean).join("\n")})}for(const s of t.sectionPaths){const t=e?.[s.connectionName]??"blue";for(let e=0;e<s.points.length-1;e++){const i=s.points[e],o=s.points[e+1],a=i.z===o.z,r=i.z;let h;h=a?0===r?"5 5":"10 5":"3 3 10",n.lines.push({points:[{x:i.x,y:i.y},{x:o.x,y:o.y}],strokeColor:t,strokeDash:h})}}return n}(this.currentSection,this.colorMap);const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.inputNodes){const n=this.nodePfMap.get(e.capacityMeshNodeId)??0,s=`rgba(${Math.floor(255*Math.min(n,1))}, ${Math.floor(255*(1-Math.min(n,1)))}, 0, 0.3)`;t.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,fill:s,label:`${e.capacityMeshNodeId}\nPf: ${n.toFixed(3)}`})}for(const e of this.connectionResults){if(!e.path)continue;const n=e.connection,s=this.colorMap[n.name]??"blue",i=[];for(const t of e.path)i.push({x:t.point.x,y:t.point.y,z:t.z});for(let e=0;e<i.length-1;e++){const n=i[e],o=i[e+1],a=n.z===o.z,r=n.z;let h;h=a?0===r?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:n.x,y:n.y},{x:o.x,y:o.y}],strokeColor:s,strokeDash:h})}}return t}};function Ts(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var ws=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 n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,i=Math.max(n,s),o=e.targetMinCapacity??.5;e.capacityDepth=Me(i,o)}this.connMap=xe(t),this.colorMap=Y(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?G():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;colorMap;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;viaDiameter;minTraceWidth;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[Ts("netToPointPairsSolver",He,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=Y(t.srjWithPointPairs,this.connMap),t.connMap=xe(t.srjWithPointPairs)}}),Ts("nodeSolver",bn,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Ts("edgeSolver",Le,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Ts("availableSegmentPointSolver",Ns,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),Ts("portPointPathingSolver",Ps,t=>{const e=t.capacityNodes.map(t=>({capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:[],availableZ:t.availableZ,_containsTarget:t._containsTarget,_containsObstacle:t._containsObstacle})),n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),s=t.availableSegmentPointSolver;for(const t of s.sharedEdgeSegments)for(const e of t.portPoints){const[t,s]=e.nodeIds,i={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[t,s],distToCentermostPortOnZ:e.distToCentermostPortOnZ},o=n.get(t);o&&o.portPoints.push(i)}return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e,capacityMeshNodes:t.capacityNodes,colorMap:t.colorMap}]}),Ts("multiSectionPortPointOptimizer",Es,t=>{const e=t.portPointPathingSolver;return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e.inputNodes,capacityMeshNodes:t.capacityNodes,capacityMeshEdges:t.capacityEdges,colorMap:t.colorMap,initialConnectionResults:e.connectionsWithResults,initialAssignedPortPoints:e.assignedPortPoints,initialNodeAssignedPortPoints:e.nodeAssignedPortPoints}]}),Ts("highDensityRouteSolver",me,t=>[{nodePortPoints:t.portPointPathingSolver?.getNodesWithPortPoints()??t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),Ts("highDensityStitchSolver",we,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),Ts("traceSimplificationSolver",Ms,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(),n=this.nodeSolver?.visualize(),s=this.nodeTargetMerger?.visualize(),i=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),a=this.edgeSolver?.visualize(),r=this.deadEndSolver?.visualize(),h=this.availableSegmentPointSolver?.visualize(),c=this.portPointPathingSolver?.visualize(),d=this.multiSectionPortPointOptimizer?.visualize(),l=this.highDensityRouteSolver?.visualize(),u=this.highDensityStitchSolver?.visualize(),p=this.traceSimplificationSolver?.visualize(),f=this.srj.outline,g=[];if(g.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)"}),f&&f.length>=2){const t=f.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),g.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const m={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:g},y=[m,e,n,s,i,o,a,r,h,c,d,l?t(m,l):null,u,p,this.solved?t(m,Ae(this.getOutputSimpleRouteJson())):null].filter(Boolean);return t(...y)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.connectionName]}),t.length>200)break}return{lines:t}}if(this.portPointPathingSolver){const t=[];for(const e of this.portPointPathingSolver.connectionsWithResults)e.path&&t.push({points:e.path.map(t=>({x:t.point.x,y:t.point.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 n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,i=e.filter(t=>t.connectionName===n.name);for(let e=0;e<i.length;e++){const o=i[e],a={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:Ne(o,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},As=ws,zs=class extends e{nodes;edges;capacityPaths;nodeMap;nodeEdgeMap;unprocessedNodeIds;nodePortSegments;colorMap;constructor({nodes:t,edges:e,capacityPaths:n,colorMap:s}){super(),this.nodes=t,this.edges=e,this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ss(e),this.capacityPaths=n,this.colorMap=s??{},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 n of this.capacityPaths){const s=n.nodeIds.indexOf(t);-1!==s&&e.push({path:n,indexOfNodeInPath:s})}const n=this.nodeMap.get(t),s=[];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=Rs(n,e),r=e.availableZ.filter(t=>n.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};s.push(h)}}const i=function(t){const e=[],n=t.map(t=>({...t,connectionNames:[...t.connectionNames],rootConnectionNames:t.rootConnectionNames?[...t.rootConnectionNames]:[],availableZ:[...t.availableZ].sort((t,e)=>t-e)}));for(;n.length>0;){const t=n.pop();let s=!1;for(let n=0;n<e.length;n++){const i=e[n],o=Ls(i.start,t.start)&&Ls(i.end,t.end)||Ls(i.start,t.end)&&Ls(i.end,t.start),a=Ds(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 n=new Set(i.rootConnectionNames||[]);t.rootConnectionNames?.forEach(t=>n.add(t)),i.rootConnectionNames=Array.from(n),s=!0;break}}s||e.push(t)}return e}(s);this.nodePortSegments.set(t,i)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};return this.nodePortSegments.forEach((e,n)=>{this.nodeMap.get(n);e.forEach(e=>{e.start.x,e.end.x;for(let s=0;s<e.connectionNames.length;s++){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:`${n}: ${e.connectionNames.join(", ")}\navailableZ: ${e.availableZ.join(",")}\nnodePortSegmentId: ${e.nodePortSegmentId}`}),t.lines.push({points:[e.start,e.end],strokeColor:H(this.colorMap[e.connectionNames[s]],.6)})}})}),t}};function Rs(t,e){const n={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)},s={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(n.end-n.start<s.end-s.start){const t=(n.start+n.end)/2;return{start:{x:t,y:s.start},end:{x:t,y:s.end}}}{const t=(s.start+s.end)/2;return{start:{x:n.start,y:t},end:{x:n.end,y:t}}}}var Os=1e-9;function Ls(t,e){return Math.abs(t.x-e.x)<Os&&Math.abs(t.y-e.y)<Os}function Ds(t,e){if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++)if(t[n]!==e[n])return!1;return!0}var Fs=class extends e{unsolvedSegments;solvedSegments;nodeMap;colorMap;constructor({segments:t,colorMap:e,nodes:n}){super(),this.MAX_ITERATIONS=1e5,this.unsolvedSegments=t,this.solvedSegments=[],this.colorMap=e??{},this.nodeMap=Object.fromEntries(n.map(t=>[t.capacityMeshNodeId,t]))}_step(){let t=!1;const e=[...this.unsolvedSegments];for(const n of e){const e=n.connectionNames.length;if((!("assignedPoints"in n)||n.assignedPoints?.length!==e)&&1===e){const e={x:(n.start.x+n.end.x)/2,y:(n.start.y+n.end.y)/2,z:n.availableZ[0]};n.assignedPoints=[{connectionName:n.connectionNames[0],rootConnectionName:n.rootConnectionNames?.[0],point:e}],this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(n),1),this.solvedSegments.push(n),t=!0}}if(!t&&e.length>0){let n=e[0];for(const t of e)t.connectionNames.length<n.connectionNames.length&&(n=t);const s=[...n.connectionNames].sort(),i=n.end.x-n.start.x,o=n.end.y-n.start.y,a=s.length,r=[];for(let t=1;t<=a;t++){const e=t/(a+1);r.push({x:n.start.x+i*e,y:n.start.y+o*e,z:n.availableZ[0]})}n.assignedPoints=s.map((t,e)=>({connectionName:t,rootConnectionName:n.rootConnectionNames?.[n.connectionNames.indexOf(t)],point:r[e]})),this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(n),1),this.solvedSegments.push(n),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 n=e.capacityMeshNodeId,s=this.nodeMap[n];t.has(n)||t.set(n,{capacityMeshNodeId:n,portPoints:[],center:s.center,width:s.width,height:s.height}),t.get(n).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 n=this.solvedSegments[e];for(let e=0;e<n.assignedPoints.length;e++){const s=n.assignedPoints[e],i={x:s.point.x,y:s.point.y},o={x:s.point.x+.05*s.point.z,y:s.point.y+.05*s.point.z};0!==s.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:[`${n.capacityMeshNodeId}-${s.connectionName}`,`z: ${n.availableZ.join(",")}`,`nodePortSegmentId: ${n.nodePortSegmentId}`].join("\n"),color:this.colorMap[s.connectionName],step:4})}}const e=[],n={};for(const t of this.solvedSegments){const e=t.capacityMeshNodeId;n[e]||(n[e]={});for(const s of t.assignedPoints)n[e][s.connectionName]||(n[e][s.connectionName]=[]),n[e][s.connectionName].push({x:s.point.x,y:s.point.y})}for(const t in n)for(const s in n[t]){const i=n[t][s];i.length>1&&e.push({points:i,step:4,strokeDash:"5 5",strokeColor:this.colorMap[s]||"#000"})}return t.lines.push(...e),t}};function $s(t){const{nodeId:e,nodeIdToSegmentIds:n,segmentIdToNodeIds:s,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=n.get(t)||[];for(const t of i){const n=s.get(t)||[];for(const t of n)o.has(t)||(o.add(t),a.push({nodeId:t,remainingHops:e-1}))}}return Array.from(o)}var ks=t=>Array.from(t.entries()).map(([t,{x:e,y:n,z:s}])=>`${t}(${e?.toFixed(3)??""},${n?.toFixed(3)??""},${s??""})`).sort().join("&"),Bs=(t,e,n,s)=>{const i=Math.min(t,e),o=Math.max(t,e),a=Math.min(n,s);return i<=Math.max(n,s)&&o>=a},Xs=(t,e,n,s)=>{const i=[],o=new Map(t.originalPointMap);for(const[t,e]of n.entries()){const n=o.get(t);o.set(t,{x:e.x??n.x,y:e.y??n.y,z:e.z??n.z})}for(const n of t.allNodeIds){if(!e.get(n))continue;const a=t.segmentPairsInNode.get(n);for(const t of a){const e=o.get(t[0]),s=o.get(t[1]);e.z!==s.z&&i.push({type:"transition_via",segmentPoints:t,capacityMeshNodeId:n,probabilityOfFailure:0})}for(let t=0;t<a.length;t++)for(let e=t+1;e<a.length;e++){if(s?.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(!Bs(c.z,d.z,l.z,u.z))continue;const p=Q(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:n,crossingLine1:r,crossingLine2:h,probabilityOfFailure:0}):c.z===d.z&&l.z!==u.z?i.push({type:"single_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:n,sameLayerCrossingLine:r,transitionCrossingLine:h,probabilityOfFailure:0}):c.z!==d.z&&l.z===u.z?i.push({type:"single_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:n,sameLayerCrossingLine:h,transitionCrossingLine:r,probabilityOfFailure:0}):c.z!==d.z&&l.z!==u.z&&i.push({type:"double_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:n,crossingLine1:r,crossingLine2:h,probabilityOfFailure:0}))}}return i},Ys=(t,e,n)=>{if("change_layer"===e.type)for(const n of e.segmentPointIds){const s=t.get(n)||{};t.set(n,{...s,z:e.newZ})}else if("swap_position_on_segment"===e.type){const[s,i]=e.segmentPointIds,o=n(s),a=n(i),r=t.get(s)||{},h=t.get(i)||{};t.set(s,{...r,x:a.x,y:a.y}),t.set(i,{...h,x:o.x,y:o.y})}else if("combined"===e.type)for(const s of e.operations)Ys(t,s,n)},Hs=(t,e)=>{const n=new Map,s=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:[]};n.set(h.segmentPointId,h);for(const t of h.capacityMeshNodeIds)s.set(t,[...s.get(t)??[],h.segmentPointId]);i.set(r.nodePortSegmentId,[...i.get(r.nodePortSegmentId)??[],h.segmentPointId]),o.push(h)}return{segmentPointMap:n,nodeToSegmentPointMap:s,segmentToSegmentPointMap:i}},js=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,ve(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=$s({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS}),n=$s({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS+1}),s=Array.from(new Set(n).difference(new Set(e)));t?.segmentPointMap||(t=Hs(this.dedupedSegments,this.segmentIdToNodeIds));const i=new Map;for(const e of n)i.set(e,t.nodeToSegmentPointMap.get(e));const o=new Map;for(const e of n)for(const n of i.get(e)){const e=t.segmentPointMap.get(n);o.set(n,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,n]of i.entries())for(let e=0;e<n.length;e++){const s=t.segmentPointMap.get(n[e]);for(let i=e+1;i<n.length;i++){const e=t.segmentPointMap.get(n[i]);e.segmentPointId!==s.segmentPointId&&(e.segmentId!==s.segmentId&&e.connectionName===s.connectionName&&(e.directlyConnectedSegmentPointIds.includes(s.segmentPointId)||(s.directlyConnectedSegmentPointIds.push(e.segmentPointId),e.directlyConnectedSegmentPointIds.push(s.segmentPointId))))}}const h=new Map;for(const t of n)h.set(t,[]);for(const e of a)for(const n of e.capacityMeshNodeIds){const s=h.get(n);if(s)for(const i of e.directlyConnectedSegmentPointIds){const o=t.segmentPointMap.get(i);o.segmentPointId!==e.segmentPointId&&(o.capacityMeshNodeIds.some(t=>t===n)&&(s.some(([t,n])=>t===e.segmentPointId&&n===o.segmentPointId||t===o.segmentPointId&&n===e.segmentPointId)||s.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 n=t.capacityMeshNodeIds.some(t=>e.includes(t)),s=this.dedupedSegmentMap.get(t.segmentId),i=s&&s.availableZ.length>1;(n||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:n,mutableNodeIds:e,immutableNodeIds:s,mutableSegmentIds:c,segmentPairsInNode:h,segmentPointMap:o,segmentPointsInNode:i,segmentPointsInSegment:r,originalPointMap:o,mutableSegmentPointIds:d,zLockedSegmentPointIds:l}}createInitialCandidate(){const t=new Map,e=Xs(this.unravelSection,this.nodeMap,t),n=this.computeG({issues:e,originalCandidate:{},operationsPerformed:0,operation:{}});return{pointModifications:t,g:n,h:0,f:n,operationsPerformed:0,candidateHash:ks(t),issues:Xs(this.unravelSection,this.nodeMap,t)}}get nextCandidate(){return this.candidates[0]??null}getPointInCandidate(t,e){const n=this.unravelSection.segmentPointMap.get(e),s=t.pointModifications.get(e);return{x:s?.x??n.x,y:s?.y??n.y,z:s?.z??n.z,segmentId:n.segmentId}}getConnectionSegmentPointIds(t){const e=[];for(const[n,s]of this.unravelSection.segmentPointMap.entries())s.connectionName===t&&e.push(n);return e}canConnectionUseLayer(t,e){for(const n of t){const t=this.unravelSection.segmentPointMap.get(n),s=this.dedupedSegmentMap.get(t.segmentId);if(!s||!s.availableZ.includes(e))return!1}return!0}getOperationsForIssue(t,e){const n=[];if("transition_via"===e.type){const[s,i]=e.segmentPoints,o=this.getPointInCandidate(t,s),a=this.getPointInCandidate(t,i),r=this.unravelSection.segmentPointMap.get(s),h=(this.unravelSection.segmentPointMap.get(i),this.dedupedSegmentMap.get(o.segmentId).availableZ),c=this.dedupedSegmentMap.get(a.segmentId).availableZ,d=this.unravelSection.zLockedSegmentPointIds.has(s),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&&n.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&&n.push({type:"change_layer",newZ:o.z,segmentPointIds:t})}this.unravelSection.mutableSegmentPointIds.has(s)&&!d&&h.includes(a.z)&&n.push({type:"change_layer",newZ:a.z,segmentPointIds:[s]}),this.unravelSection.mutableSegmentPointIds.has(i)&&!l&&c.includes(o.z)&&n.push({type:"change_layer",newZ:o.z,segmentPointIds:[i]})}if("same_layer_crossing"===e.type){const[t,s]=e.crossingLine1,[i,o]=e.crossingLine2,a=[],r=this.unravelSection.segmentPointMap.get(t),h=this.unravelSection.segmentPointMap.get(s),c=this.unravelSection.segmentPointMap.get(i),d=this.unravelSection.segmentPointMap.get(o),l=this.unravelSection.mutableSegmentPointIds.has(t),u=this.unravelSection.mutableSegmentPointIds.has(s),p=this.unravelSection.mutableSegmentPointIds.has(i),f=this.unravelSection.mutableSegmentPointIds.has(o),g=this.unravelSection.zLockedSegmentPointIds.has(t),m=this.unravelSection.zLockedSegmentPointIds.has(s),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([s,i]),u&&f&&h.segmentId===d.segmentId&&a.push([s,o]);for(const[t,e]of a)n.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&&n.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&&n.push({type:"change_layer",newZ:t,segmentPointIds:e})}const N=this.dedupedSegmentMap.get(r.segmentId),b=this.dedupedSegmentMap.get(h.segmentId),P=this.dedupedSegmentMap.get(c.segmentId),I=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([N,b],e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t,s]})}if(p&&f&&!y&&!x){const t=0===c.z?1:0;C([P,I],t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[i,o]})}if(l&&!g){const e=0===r.z?1:0;N.availableZ.includes(e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t]})}if(u&&!m){const t=0===h.z?1:0;b.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[s]})}if(p&&!y){const t=0===c.z?1:0;P.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[i]})}if(f&&!x){const t=0===d.z?1:0;I.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[o]})}}return n}computeG(t){const{issues:e,originalCandidate:n,operationsPerformed:s,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:n,numTransitionCrossings:s}]of o){const i=this.nodeMap.get(t),o=Math.min(bs(i,n,e,s),.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 n=new Map(t.pointModifications);Ys(n,e,e=>this.getPointInCandidate(t,e));const s=ks(n);if(this.queuedOrExploredCandidatePointModificationHashes.has(s))return null;const i=Xs(this.unravelSection,this.nodeMap,n),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:n,candidateHash:s,operationsPerformed:o}}getNeighborOperationsForCandidate(t){return t.issues.flatMap(e=>this.getOperationsForIssue(t,e))}getNeighbors(t){const e=[],n=this.getNeighborOperationsForCandidate(t);for(const s of n){const n=this.getUnexploredNeighborByApplyingOperation(t,s);n&&e.push(n)}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 n=new Map;for(const[t,s]of this.unravelSection.segmentPointMap){const i={...s},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)),n.set(t,i)}for(const[e,s]of n)t.points.push({x:s.x,y:s.y,label:`${e}\nSegment: ${s.segmentId} ${this.unravelSection.mutableSegmentIds.has(s.segmentId)?"MUTABLE":"IMMUTABLE"}\nLayer: ${s.z}`,color:this.colorMap[s.connectionName]||"#000"});const s=new Map;for(const t of this.unravelSection.allNodeIds)s.set(t,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0,estPf:0});for(const t of e.issues){const e=s.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 s.entries()){const n=this.nodeMap.get(t);e.estPf=bs(n,e.numSameLayerCrossings,e.numEntryExitLayerChanges,e.numTransitionCrossings)}for(const e of this.unravelSection.allNodeIds){const n=this.nodeMap.get(e),i=this.unravelSection.mutableNodeIds.includes(e),o=s.get(e),a=[`${e} (${i?"MUT":"IMM"})`,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Pf: ${o.estPf.toFixed(3)}`,`TC: ${o.numTransitionCrossings}`,`SLC: ${o.numSameLayerCrossings}`,`EELC: ${o.numEntryExitLayerChanges}`].join("\n");t.rects.push({center:n.center,label:a,color:i?"green":"red",width:n.width/8,height:n.height/8})}for(const[e,s]of this.unravelSection.segmentPointsInSegment){if(s.length<=1)continue;const i=s.map(t=>n.get(t));for(let n=0;n<i.length-1;n++)t.lines.push({points:[{x:i[n].x,y:i[n].y},{x:i[n+1].x,y:i[n+1].y}],strokeColor:this.colorMap[e]||"#000"})}for(const[e,s]of n)for(const i of s.directlyConnectedSegmentPointIds)if(e<i){const e=n.get(i);if(!e)continue;const o=s.z===e.z,a=s.z;let r;r=o?0===a?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:s.x,y:s.y},{x:e.x,y:e.y}],strokeDash:r,strokeColor:this.colorMap[s.connectionName]||"#000"})}for(const s of e.issues){const e=this.nodeMap.get(s.capacityMeshNodeId);if("transition_via"===s.type)for(const i of s.segmentPoints){const s=n.get(i);t.circles.push({center:{x:s.x,y:s.y},radius:e.width/16,stroke:"#ff0000",fill:"rgba(255, 0, 0, 0.2)",label:`Via Issue\n${i}\nLayer: ${s.z}`})}else if("same_layer_crossing"===s.type)for(const[i,o]of[s.crossingLine1,s.crossingLine2]){const s=n.get(i),a=n.get(o);t.lines.push({points:[{x:s.x,y:s.y},{x:a.x,y:a.y}],strokeColor:"rgba(255,0,0,0.2)",strokeWidth:e.width/32})}}for(const[s,i]of e.pointModifications){const e=n.get(s),i=this.unravelSection.segmentPointMap.get(s);t.circles.push({center:{x:e.x,y:e.y},radius:.05,stroke:"#0000ff",fill:"rgba(0, 0, 255, 0.2)",label:`${s}\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 Ws from"object-hash";function Vs(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:Zs,sin:Us,PI:Gs}=Math,{tan:qs}=Math,Ks=t=>(Math.round(20*t)/20).toFixed(2),Js=t=>(Math.round(1e3*t)/1e3).toFixed(3);q();var Qs=class extends js{cacheHit=!1;cacheProvider;hasAttemptedToUseCache=!1;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?U():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),n=new Map,s=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 n=this.nodeMap.get(t),s=this.nodeMap.get(e);return n.center.x!==s.center.x?n.center.x-s.center.x:n.center.y-s.center.y});for(const t of l){const e="node_"+h++;n.set(t,e),s.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 n=this.unravelSection.segmentPointMap.get(t).segmentId;if(!i.has(n)){const t="seg_"+c++;i.set(n,t),o.set(t,n)}}const p={};for(const[t,s]of n.entries()){const n=this.nodeMap.get(t),i=Vs(e,n.center);p[s]={width:n.width,height:n.height,availableZ:n.availableZ,center:{x:Ks(i.x),y:Ks(i.y)}}}const f={};for(const[t,n]of a.entries()){const s=this.unravelSection.segmentPointMap.get(t),i=Vs(e,{x:s.x,y:s.y});f[n]={x:Ks(i.x),y:Ks(i.y),z:s.z}}const g={hyperParameters:this.hyperParameters,normalizedNodes:p,normalizedSegmentPoints:f,mutableHops:this.MUTABLE_HOPS},m=`unravelsec:${Ws(g)}`,y={realToCacheTransform:e,nodeIdMap:n,segmentIdMap:i,segmentPointIdMap:a,reverseNodeIdMap:s,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:n}=this.cacheToSolveSpaceTransform,s=new Map;for(const[n,i]of t.bestCandidatePointModificationsDelta){const t=e.get(n);if(!t){console.warn(`Could not find original ID for normalized SP ID: ${n} 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&&s.set(t,a)}const i=Xs(this.unravelSection,this.nodeMap,s);this.bestCandidate={pointModifications:s,issues:i,f:t.bestCandidateF,g:t.bestCandidateF,h:0,operationsPerformed:-1,candidateHash:ks(s)},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[n,s]of this.bestCandidate.pointModifications.entries()){const i=t.get(n);if(!i){console.warn(`Could not find normalized ID for original SP ID: ${n} when saving to cache.`);continue}const o=this.unravelSection.segmentPointMap.get(n);if(!o){console.warn(`Could not find original segment point for ID: ${n} when saving cache.`);continue}const a={};let r=!1;if(void 0!==s.x){const t=s.x-o.x,e=Js(t);0!==parseFloat(e)&&(a.dx=e,r=!0)}if(void 0!==s.y){const t=s.y-o.y,e=Js(t);0!==parseFloat(e)&&(a.dy=e,r=!0)}if(void 0!==s.z){const t=s.z-o.z;0!==t&&(a.dz=t,r=!0)}r&&e.push([i,a])}const n={success:!0,bestCandidatePointModificationsDelta:e,bestCandidateF:this.bestCandidate.f};this.cacheProvider?.setCachedSolutionSync(this.cacheKey,n)}},ti=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:n,cacheProvider:s}){super(),this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.cacheHits=0,this.stats.cacheMisses=0,this.cacheProvider=s??null,this.MAX_ITERATIONS=1e6,this.dedupedSegments=(t=>{const e=[],n=new Map;let s=-1;for(const i of t){const t=`${i.start.x}-${i.start.y}-${i.end.x}-${i.end.y}-${i.availableZ.join(",")}`,o=n.get(t);o?i.nodePortSegmentId=o.nodePortSegmentId:(s++,i.nodePortSegmentId=`SEG${s}`,n.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 n)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,ve(e));const{segmentPointMap:i,nodeToSegmentPointMap:o,segmentToSegmentPointMap:a}=Hs(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,n]of this.nodeMap.entries())t.set(e,this.computeNodePf(n));return t}computeNodePf(t){const{numSameLayerCrossings:e,numEntryExitLayerChanges:n,numTransitionCrossings:s}=(t=>{let e=0,n=0,s=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 s=e[0];for(let i=1;i<e.length;i++){const r=e[i],h={connectionName:t,z:s.z,points:[s,r]};s.z!==r.z?(n++,a.push({connectionName:t,points:[s,r]})):o.push(h)}}for(let t=0;t<o.length;t++)for(let n=t+1;n<o.length;n++){const s=o[t],i=o[n];s.z===i.z&&Q(s.points[0],s.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 n=a[t],i=a[e];Q(n.points[0],n.points[1],i.points[0],i.points[1])&&s++}for(let t=0;t<a.length;t++)for(let e=0;e<o.length;e++){const n=a[t],i=o[e];Q(n.points[0],n.points[1],i.points[0],i.points[1])&&s++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:n,numTransitionCrossings:s}})((this.nodeToSegmentPointMap.get(t.capacityMeshNodeId)??[]).map(t=>this.segmentPointMap.get(t)));return bs(t,e,n,s)}_step(){if(this.iterations>=this.MAX_ITERATIONS-1)return void(this.solved=!0);if(!this.activeSubSolver){let t=null,e=0;for(const[n,s]of this.nodePfMap.entries()){s*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_NODE_ATTEMPTS)>e&&(e=s,t=n)}if(!t||e<this.ACCEPTABLE_PF)return void(this.solved=!0);this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.activeSubSolver=new Qs({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:n}=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,n]of t.pointModifications.entries()){const t=this.segmentPointMap.get(e);t.x=n.x??t.x,t.y=n.y??t.y,t.z=n.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,n]of this.nodeMap.entries()){const s=this.nodePfMap.get(e)||0,i=Math.min(s,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:n.center,label:[e,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Pf: ${s.toFixed(3)}`].join("\n"),color:o,width:n.width/8,height:n.height/8})}for(const e of this.segmentPointMap.values()){const n=this.dedupedSegmentMap.get(e.segmentId);t.points.push({x:e.x,y:e.y,label:[e.segmentPointId,e.segmentId,`z: ${e.z}`,`segment.availableZ: ${n?.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[n,s]of e.entries()){if(s.length<2)continue;const e=[...s].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y);for(let s=0;s<e.length-1;s++)t.lines.push({points:[{x:e[s].x,y:e[s].y},{x:e[s+1].x,y:e[s+1].y}],strokeColor:this.colorMap[n]||"#000"})}const n=new Set,s=Array.from(this.segmentPointMap.values());for(let e=0;e<s.length;e++){const i=s[e];for(let o=e+1;o<s.length;o++){const e=s[o];if(i.connectionName!==e.connectionName||i.segmentId===e.segmentId)continue;if(i.capacityMeshNodeIds.some(t=>e.capacityMeshNodeIds.includes(t))){const s=`${i.segmentPointId}-${e.segmentPointId}`;if(n.has(s))continue;n.add(s);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 n=e.nodePortSegmentId;for(const e of this.segmentIdToNodeIds.get(n)){const n=this.nodeMap.get(e);t.has(e)||t.set(e,{capacityMeshNodeId:e,portPoints:[],center:n.center,width:n.width,height:n.height})}}for(const e of this.segmentPointMap.values())for(const n of e.capacityMeshNodeIds){const s=t.get(n);s&&s.portPoints.push({x:e.x,y:e.y,z:e.z,connectionName:e.connectionName,rootConnectionName:e.rootConnectionName})}return Array.from(t.values())}},ei=(t,e={})=>{const n=Math.min(...t.availableZ);return{center:!e.rectMargin||e.zOffset?{x:t.center.x+n*t.width*(e.zOffset??.05),y:t.center.y-n*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")}},ni=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:s,MAX_ITERATIONS:i=1e6,hyperParameters:o={}}){super(),this.MAX_ITERATIONS=i,this.simpleRouteJson=t,this.nodes=e,this.edges=n,this.colorMap=s??{};const{connectionsWithNodes:a,connectionNameToGoalNodeIds:r}=this.getConnectionsWithNodes();this.connectionsWithNodes=a,this.connectionNameToGoalNodeIds=r,this.hyperParameters=o,this.usedNodeCapacityMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,0])),this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ss(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),n=new Map;for(const s of this.simpleRouteJson.connections){const i=[];for(const t of s.pointsToConnect){let n=this.nodes[0],s=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<s&&(s=e,n=i)}i.push(n)}if(i.length<2)throw new Error(`Not enough nodes for connection "${s.name}", only ${i.length} found`);n.set(s.name,i.map(t=>t.capacityMeshNodeId)),t.push({connection:s,nodes:i,pathFound:!1,straightLineDistance:st(i[0].center,i[i.length-1].center)})}return t.sort((t,e)=>t.straightLineDistance-e.straightLineDistance),{connectionsWithNodes:t,connectionNameToGoalNodeIds:n}}currentConnectionIndex=0;candidates;visitedNodes;computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)}getBacktrackedPath(t){const e=[];let n=t;for(;n;)e.push(n.node),n=n.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 n=e.path;n&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,rootConnectionName:e.connection.rootConnectionName,nodeIds:n.map(t=>t.capacityMeshNodeId)})}return t}doesNodeHaveCapacityForTrace(t,e){const n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.getTotalCapacity(t);if(1===t.availableZ.length&&!t._containsTarget&&n>0)return!1;let i=0;return t.availableZ.length>1&&1===e.availableZ.length&&(i+=.5),n+i<s}canTravelThroughObstacle(t,e){const n=this.connectionNameToGoalNodeIds.get(e);return n?.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,n]=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=st(e.center,n.center)),this.candidates.sort((t,e)=>t.f-e.f);const s=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),!s)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(s.node,n))return t.path=this.getBacktrackedPath({prevCandidate:s,node:n,f:0,g:0,h:0}),this.reduceCapacityAlongPath(t),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);const i=this.getNeighboringNodes(s.node);for(const t of i){if(this.visitedNodes?.has(t.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(t,s.node))continue;const e=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;if(t._containsObstacle&&!this.canTravelThroughObstacle(t,e))continue;const i=this.computeG(s,t,n),o=this.computeH(s,t,n),a=i+o*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:a,g:i,h:o});const r={prevCandidate:s,node:t,f:a,g:i,h:o};this.candidates.push(r)}this.visitedNodes.add(s.node.capacityMeshNodeId)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(this.connectionsWithNodes)for(let e=0;e<this.connectionsWithNodes.length;e++){const n=this.connectionsWithNodes[e];if(n.path&&n.path.length>0){const s=n.path.map(({center:{x:t,y:n},width:s,availableZ:i})=>({x:t+.005*s*(e%10+e%19),y:n+.005*s*(e%10+e%19),availableZ:i}));t.lines.push({points:s,strokeColor:this.colorMap[n.connection.name]});for(let e=0;e<s.length;e++){const i=s[e];t.points.push({x:i.x,y:i.y,label:[`conn: ${n.connection.name}`,`node: ${n.path[e].capacityMeshNodeId}`,`z: ${i.availableZ.join(",")}`].join("\n")})}}}for(const e of this.nodes){const n=this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,s=this.getTotalCapacity(e),i=this.debug_lastNodeCostMap.get(e.capacityMeshNodeId);t.rects.push({...ei(e,{rectMargin:.025,zOffset:.01}),label:[`${e.capacityMeshNodeId}`,`${n}/${s}`,`${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:n>s+.5?"red":void 0})}if(this.connectionsWithNodes)for(const e of this.connectionsWithNodes)if(e.connection?.pointsToConnect)for(const n of e.connection.pointsToConnect)t.points.push({x:n.x,y:n.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[n,s]=e.connection.pointsToConnect;t.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.y}],strokeColor:"red",strokeDash:"10 5"})}if(this.candidates){const e=this.candidates.slice(0,5),n=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;e.forEach((e,s)=>{const i=.5*(1-s/5),o=this.getBacktrackedPath(e);t.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:H(this.colorMap[n]??"red",1-i)})})}return t}},si=class extends ni{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 ve(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){const e=t.width+t.height,n=.05,s=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0);if(s>2)return n;return(e-n)*Math.max(1,(2-s)/(e-n))+n}getDistanceBetweenNodes(t,e){const n=t.center.x-e.center.x,s=t.center.y-e.center.y;return Math.sqrt(n**2+s**2)}computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)+this.getNodeCapacityPenalty(e)}},ii=class extends si{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 n=1;return 1===t.availableZ.length&&(n=10),(.05+2*Math.abs(e))*n}};function oi(t,e,n){const s=e.x-t.x,i=e.y-t.y;if(Math.abs(s)<1e-9&&Math.abs(i)<1e-9)return t;const o=n.width/2,a=n.height/2,r=n.center.x-o,h=n.center.x+o,c=n.center.y-a,d=n.center.y+a;let l=0,u=1/0;if(Math.abs(s)>1e-9){const e=(r-t.x)/s,n=(h-t.x)/s;l=Math.max(l,Math.min(e,n)),u=Math.min(u,Math.max(e,n))}else if(t.x<r||t.x>h)return t;if(Math.abs(i)>1e-9){const e=(c-t.y)/i,n=(d-t.y)/i;l=Math.max(l,Math.min(e,n)),u=Math.min(u,Math.max(e,n))}else if(t.y<c||t.y>d)return t;if(u<l||l===1/0||l<-1e9)return t;return{x:t.x+s*l,y:t.y+i*l}}function ai(t,e){const n=t.center,s=e.center,i=oi(n,s,t),o=oi(s,n,e),a=s.x-n.x,r=s.y-n.y,h=Math.sqrt(a*a+r*r);let c=i,d=o;if(h>1e-9){const n={x:a/h,y:r/h},s=.3*t.width,l=.3*e.width;s+l<Math.sqrt((o.x-i.x)**2+(o.y-i.y)**2)?(c={x:i.x+n.x*s,y:i.y+n.y*s},d={x:o.x-n.x*l,y:o.y-n.y*l}):(c=i,d=o)}return{lineStart:c,lineEnd:d}}var ri=t=>{const{usedCapacity:e,totalCapacity:n,layerCount:s}=t;if(e<n)return 0;if(n<1&&e<=1)return 0;if(1===s&&e>1)return 1-.01**e;const i=e/n-1;return 1-Math.exp(-2*i)},hi=(t,e,n)=>{if(n._containsTarget)return 0;if(t<=e)return 0;const s=1-ri({usedCapacity:t,totalCapacity:e,layerCount:n.availableZ.length});return s<=0?-1e9:Math.log(s)},ci=({totalNodeCapacityMap:t,usedNodeCapacityMap:e,nodeMap:n,sectionNodeIds:s})=>{let i=0;const o=s??new Set(e.keys());for(const s of o){if(!t.has(s))continue;const o=n.get(s);if(!o)continue;const a=t.get(s),r=e.get(s)??0;i+=hi(r,a,o)}return i};function di({sectionNodes:t,sectionEdges:e,sectionConnectionTerminals:n,completedPaths:s,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})`,n=`rgba(128, 128, 128, ${h})`;const s=e.availableZ??[],i=s.includes(0),o=s.includes(1);i&&o?(t=`rgba(128, 0, 128, ${h})`,n=`rgba(128, 0, 128, ${h})`):i?(t=`rgba(0, 0, 255, ${h})`,n=`rgba(0, 0, 255, ${h})`):o&&(t=`rgba(255, 0, 0, ${h})`,n=`rgba(255, 0, 0, ${h})`),a&&e.capacityMeshNodeId===a&&(t=`rgba(0, 255, 0, ${h})`,n=`rgba(0, 128, 0, ${h})`),l.rects.push({...ei(e),fill:t,stroke:n,label:`${e.capacityMeshNodeId}\n(Section Node)\nZ: ${s.join(",")}`});const r=l.rects.length-1;if(c&&d){const t=c.get(e.capacityMeshNodeId)??0,n=d.get(e.capacityMeshNodeId)??0,s=n>0?(t/n*100).toFixed(1):"N/A",i=ri({usedCapacity:t,totalCapacity:n,layerCount:e.availableZ.length});l.rects[r].label+=`\n${t.toFixed(1)} / ${n.toFixed(1)}\n${s}% (Pf: ${(100*i).toFixed(1)}%)`,i>.2&&(l.rects[r].stroke=H("red",.7*(.8+h)))}}for(const t of e){const[e,n]=t.nodeIds,s=i.get(e),o=i.get(n);if(s&&o){const{lineStart:t,lineEnd:e}=ai(s,o);l.lines.push({points:[t,e],strokeColor:`rgba(0, 0, 0, ${.2*Math.min(1,h/.1)})`})}}return n.forEach((t,e)=>{const n=i.get(t.startNodeId),s=i.get(t.endNodeId),a=o[t.connectionName]??"black",r=n&&u.has(n.capacityMeshNodeId),h=s&&u.has(s.capacityMeshNodeId),c=(e+e/50)%5;let d=0,p=0,f=0,g=0;if(r&&n){const e=.02*Math.min(n.width,n.height);d=e*c,p=e*c,l.points.push({x:n.center.x+d,y:n.center.y+p,color:a,label:`Start: ${t.connectionName}\n(${t.startNodeId})`}),l.lines.push({points:[{x:n.center.x,y:n.center.y},{x:n.center.x+d,y:n.center.y+p}],strokeColor:"gray",strokeDash:"2 2"})}if(h&&s){const e=.02*Math.min(s.width,s.height);f=e*c,g=e*c,l.points.push({x:s.center.x+f,y:s.center.y+g,color:a,label:`End: ${t.connectionName}\n(${t.endNodeId})`}),l.lines.push({points:[{x:s.center.x,y:s.center.y},{x:s.center.x+f,y:s.center.y+g}],strokeColor:"gray",strokeDash:"2 2"})}r&&h&&n&&s&&l.lines.push({points:[{x:n.center.x+d,y:n.center.y+p},{x:s.center.x+f,y:s.center.y+g}],strokeColor:a,strokeDash:"5 5"})}),s&&s.forEach((t,e)=>{if(t.path&&t.path.length>0){const n=o[t.connectionName]??"gray",s={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+s.x,y:e+s.y})),strokeColor:H(n,.2)})}}),l}var li=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??Ss(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=ci({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:e}),t.hyperParameters?.SHUFFLE_SEED&&(this.sectionConnectionTerminals=Pt(this.sectionConnectionTerminals,t.hyperParameters?.SHUFFLE_SEED))}getTotalCapacity(t){return ve(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 n=1;return 1===t.availableZ.length&&(n=10),(.05+e**2*4)*n}getDistanceBetweenNodes(t,e){const n=t.center.x-e.center.x,s=t.center.y-e.center.y;return Math.sqrt(n**2+s**2)}computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)+this.getNodeCapacityPenalty(e)}getBacktrackedPath(t){const e=[];let n=t;for(;n;){if(e.push(n.node),!this.nodeMap.has(n.node.capacityMeshNodeId)){console.warn("Backtracked path went outside section bounds");break}n=n.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,n=this.nodeMap.get(t);if(!n){console.warn(`Node ${t} from path not found in section's nodeMap during score update.`);continue}const s=this.totalNodeCapacityMap.get(t),i=this.usedNodeCapacityMap.get(t)??0,o=hi(i,s,n);this.currentSectionScore-=o;const a=i+1;this.usedNodeCapacityMap.set(t,a);const r=hi(a,s,n);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),n=this.nodeMap.get(t.endNodeId);if(!e||!n)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,n);const s=this.candidates;if(0===s.length)return void this._handleCandidatesExhausted(t);s.sort((t,e)=>t.f-e.f);const i=s.shift();if(s.length>this.MAX_CANDIDATES_IN_MEMORY&&s.splice(this.MAX_CANDIDATES_IN_MEMORY,s.length-this.MAX_CANDIDATES_IN_MEMORY),this.visitedNodes.add(i.node.capacityMeshNodeId),i.node.capacityMeshNodeId===n.capacityMeshNodeId)return void this._handleGoalReached(i,t,n);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 n=e.capacityMeshNodeId===t.startNodeId,s=e.capacityMeshNodeId===t.endNodeId;if(!n&&!s)continue}const o=this.computeG(i,e,n),a=this.computeH(i,e,n),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),s.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 n=this.candidates.reduce((t,e)=>e.f<t.f?e:t);e+=Math.max(0,Math.min(1,1-n.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=st(t.center,e.center);const n=this.computeH(null,t,e);this.candidates[0].h=n,this.candidates[0].f=n*this.GREEDY_MULTIPLIER,this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:this.candidates[0].f,g:0,h:n}),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,n){const s=this.getBacktrackedPath(t);e.path=s,this.reduceCapacityAlongPath(s),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=di({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 n=e.rects.findIndex(e=>e.label?.includes(t.capacityMeshNodeId));if(-1!==n){const s=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=s?`f:${s.f.toFixed(1)} g:${s.g.toFixed(1)} h:${s.h.toFixed(1)}`:"cost:?";e.rects[n].label=[t.capacityMeshNodeId,`Cap: ${a}`,r,`Z: ${t.availableZ.join(",")}`].join("\n"),i>o&&(e.rects[n].stroke=H("red",.7))}}if(this.candidates&&this.candidates.length>0){const t=this.candidates.slice().sort((t,e)=>t.f-e.f).slice(0,5),n=this.sectionConnectionTerminals[this.currentConnectionIndex],s=n?.connectionName??"unknown",i=this.colorMap[s]??"purple";t.forEach((t,n)=>{const s=.8*(1-n/5),o=this.getBacktrackedPath(t);o.length>0&&e.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:H(i,1-s),strokeWidth:.05})})}return e}},ui=t=>Array.from({length:t},(t,e)=>e),pi=class extends wt{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:ui(2).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings6_for3",possibleValues:ui(6).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings24_for4",possibleValues:ui(24).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings30",possibleValues:ui(30).map(t=>({SHUFFLE_SEED:t}))}]}generateSolver(t){return new li({...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 fi from"object-hash";var gi=t=>Math.floor(10*t)/10,mi=class extends pi{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?G():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=[],n=[{ancestorCapacitySum:0,capacity:0,g:0,capacityMeshNodeId:this.constructorParams.centerNodeId}];for(;n.length>0;){n.sort((t,e)=>e.g-t.g);const s=n.pop();if(!s)break;e.push(s.capacityMeshNodeId);const i=this.constructorParams.nodeEdgeMap.get(s.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=ve(i);n.push({ancestorCapacitySum:s.g,capacity:o,g:s.g+o,capacityMeshNodeId:e})}}return e}computeCacheKeyAndTransform(){const t=this._computeBfsOrderingOfNodesInSection(),e=new Map,n=new Map;t.forEach((t,s)=>{const i=`node${s}`;e.set(t,i),n.set(i,t)});const s={};for(const n of t){const t=e.get(n),i=this.constructorParams.nodeMap.get(n),o=ve(i);s[t]=gi(o).toFixed(1)}const i=new Set,o=[];for(const n of t){const t=e.get(n),s=this.constructorParams.nodeEdgeMap.get(n)??[];for(const a of s){const s=a.nodeIds.find(t=>t!==n);if(this.sectionNodeIdSet.has(s)){const n=[t,e.get(s)].sort(),a=`${n[0]}-${n[1]}`;i.has(a)||(o.push(n),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 n=e.get(t.startNodeId),s=e.get(t.endNodeId),[i,o]=[n,s].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:${fi({node_capacity_map:s,node_edge_map:o,terminals:a})}`,d={cacheSpaceToRealConnectionId:r,cacheSpaceToRealNodeId:n};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:n}=this.cacheToSolveSpaceTransform;for(const[s,i]of Object.entries(t.solutionPaths)){const t=n.get(s);if(!t){console.warn(`Could not find real connection name for ${s}`);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(n=>{const s=e.get(n);if(!s)throw new Error(`Could not map cache node ID ${n} to real node ID for connection ${t}`);const i=this.constructorParams.nodeMap.get(s);if(!i)throw new Error(`Could not find node with ID ${s} 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:n,cacheSpaceToRealConnectionId:s}=this.cacheToSolveSpaceTransform,i=new Map;for(const[t,e]of n)i.set(e,t);const o=new Map;for(const[t,e]of s)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,n]of a){const s=o.get(t);if(!s){console.warn(`Could not find cache space connection ID for ${t} when saving to cache.`);continue}const a=n.map(e=>{const n=i.get(e);if(!n)throw new Error(`Could not map real node ID ${e} to cache node ID for connection ${t} when saving to cache.`);return n});e[s]=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 di({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"})}},yi=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=Ss(this.edges),this.colorMap=t.colorMap??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ss(this.edges),this.initialSolver=t.initialPathingSolver||new ii({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,n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,s),this.nodeOptimizationAttemptCountMap.set(t.capacityMeshNodeId,0)}this.connectionsWithNodes=this.initialSolver.connectionsWithNodes,this.stats.startingScore=ci({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet}),this.stage="section-optimization"}}_getNextNodeToOptimize(){let t=0,e=0,n=null;for(const s of this.nodes){if(s._containsTarget)continue;const i=this.nodeOptimizationAttemptCountMap.get(s.capacityMeshNodeId),o=this.totalNodeCapacityMap.get(s.capacityMeshNodeId),a=ri({usedCapacity:this.usedNodeCapacityMap.get(s.capacityMeshNodeId)??0,totalCapacity:o,layerCount:s.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,n=s.capacityMeshNodeId)}return n}getOverallScore(){let t=0;for(const e of this.nodes){if(e._containsTarget)continue;const n=this.totalNodeCapacityMap.get(e.capacityMeshNodeId),s=ri({usedCapacity:this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,totalCapacity:n,layerCount:e.availableZ.length});s>t&&(t=s)}return{highestNodePf:t,score:ci({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:n,nodeMap:s,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 n=o.get(t)?.flatMap(e=>e.nodeIds.filter(e=>e!==t))??[];for(const t of n)r.has(t)||(r.add(t),h.push({nodeId:t,depth:e+1}))}const d=Array.from(r).map(t=>s.get(t)),l=i.filter(t=>{const[e,n]=t.nodeIds;return r.has(e)&&r.has(n)}),u=[];for(const t of n){if(!t.path)continue;let e=null,n=null;for(const n of t.path)if(r.has(n.capacityMeshNodeId)){e=n.capacityMeshNodeId;break}for(let e=t.path.length-1;e>=0;e--){const s=t.path[e];if(r.has(s.capacityMeshNodeId)){n=s.capacityMeshNodeId;break}}e&&n&&u.push({connectionName:t.connection.name,startNodeId:e,endNodeId:n})}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 mi({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,n=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 s=new Set(e.map(t=>t.capacityMeshNodeId)),i=ci({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:s}),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(s.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)s.has(e.capacityMeshNodeId)&&o.set(e.capacityMeshNodeId,(o.get(e.capacityMeshNodeId)??0)+1);ci({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:o,nodeMap:this.nodeMap,sectionNodeIds:s})>i?(this.stats.successfulOptimizations++,this._mergeSolvedSectionPaths({centerNodeId:n,sectionConnectionTerminals:t}),this._recalculateNodeCapacityUsage()):this.stats.failedOptimizations++}}_mergeSolvedSectionPaths({centerNodeId:t,sectionConnectionTerminals:e}){for(const n of e){if(!n.path){console.warn(`No path found for connection ${n.connectionName} in section ${t}`);continue}const e=this.connectionsWithNodes.find(t=>t.connection.name===n.connectionName);if(!e||!e.path){console.warn(`Original connection or path not found for ${n.connectionName} while merging section ${t}`);continue}const s=e.path,i=n.path,o=s.findIndex(t=>t.capacityMeshNodeId===n.startNodeId),a=s.findIndex(t=>t.capacityMeshNodeId===n.endNodeId);if(-1===o||-1===a){console.warn(`Could not find start/end nodes (${n.startNodeId}/${n.endNodeId}) in original path for ${n.connectionName}`);continue}const[r,h]=o<=a?[o,a]:[a,o],c=s.slice(0,r),d=s.slice(h+1);let l=i;if(i.length>0&&s[r]&&i[0].capacityMeshNodeId!==s[r].capacityMeshNodeId){if(i[i.length-1].capacityMeshNodeId!==s[r].capacityMeshNodeId){console.warn(`New section path for ${n.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,n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,s)}}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const n=e.path;n&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:n.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 di({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)"})}},xi=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 n of this.multiLayerNodes){const s=n.center.x-n.width/2,i=n.center.x+n.width/2,o=n.center.y-n.height/2,a=n.center.y+n.height/2,r=Math.max(t.minX,s),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)/(n.width*n.height);e+=ve(n)*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:n,rightSurroundingCapacity:s,topSurroundingCapacity:i,bottomSurroundingCapacity:o}=this.getSurroundingCapacities(t);if(1*(n+s)>i+o){const n=Math.floor(t.height/this.strawSize),s=t.height/n;for(let i=0;i<n;i++){const n=t.center.y-t.height/2+i*s+s/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:t.center.x,y:n},width:t.width,height:s,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}else{const n=Math.floor(t.width/this.strawSize),s=t.width/n;for(let i=0;i<n;i++){const n=t.center.x-t.width/2+i*s+s/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:n,y:t.center.y},width:s,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 n=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:n,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}},vi=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,n]}of e)this.adjacencyList.get(t).add(n),this.adjacencyList.get(n).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[n]=e,s=n?this.adjacencyList.get(n):void 0;if(!n||!s)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));s.delete(t),this.removedNodeIds.add(t),this.adjacencyList.delete(t),1!==s.size||this.targetNodeIds.has(n)||this.leaves.push(n),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 n of e.nodeIds)t.set(n,1+(t.get(n)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const n=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+n*e.width*.05,y:e.center.y-n*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 n=this.nodeMap.get(t.nodeIds[0]),s=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&s?.center){const i=Math.min(...n.availableZ),o=Math.min(...s.availableZ),a={x:n.center.x+i*n.width*.05,y:n.center.y-i*n.width*.05},r={x:s.center.x+o*s.width*.05,y:s.center.y-o*s.width*.05},h=Array.from(new Set([...n.availableZ,...s.availableZ])).sort();e.lines.push({layer:`z${h.join(",")}`,points:[a,r],strokeDash:n.availableZ.join(",")===s.availableZ.join(",")?void 0:"10 5",strokeColor:t.nodeIds.some(t=>this.removedNodeIds.has(t))?H("black",.9):void 0})}}return e}};function Mi(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Si=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 n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,i=Math.max(n,s),o=e.targetMinCapacity??.5;e.capacityDepth=Me(i,o)}this.connMap=xe(t),this.colorMap=Y(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?G():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=[Mi("netToPointPairsSolver",He,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=Y(t.srjWithPointPairs,this.connMap),t.connMap=xe(t.srjWithPointPairs)}}),Mi("nodeSolver",bn,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Mi("strawSolver",xi,t=>[{nodes:t.capacityNodes}],{onSolved:t=>{t.capacityNodes=t.strawSolver?.getResultNodes()}}),Mi("edgeSolver",Le,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Mi("deadEndSolver",vi,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)))}}),Mi("initialPathingSolver",ii,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),Mi("pathingOptimizer",yi,t=>[{initialPathingSolver:t.initialPathingSolver,simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,cacheProvider:t.cacheProvider,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),Mi("edgeToPortSegmentSolver",zs,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.pathingOptimizer?.getCapacityPaths()||[],colorMap:t.colorMap}]),Mi("segmentToPointSolver",Fs,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),Mi("unravelMultiSectionSolver",ti,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),Mi("highDensityRouteSolver",me,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),Mi("highDensityStitchSolver",we,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),Mi("traceSimplificationSolver",Ms,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(),n=this.nodeSolver?.visualize(),s=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,n,s,i,o,a,r,h,c,d,l,u,p?t(x,p):null,f,g,this.solved?t(x,Ae(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 n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.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 n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,i=e.filter(t=>t.connectionName===n.name);for(let e=0;e<i.length;e++){const o=i[e],a={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:Ne(o,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Ni=class{constructor(t){this.targets=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],s=Math.floor(n.bounds.minX/this.CELL_SIZE)*this.CELL_SIZE,i=Math.floor(n.bounds.minY/this.CELL_SIZE)*this.CELL_SIZE,o=n.bounds.maxX,a=n.bounds.maxY;for(let t=s;t<=o;t+=this.CELL_SIZE)for(let s=i;s<=a;s+=this.CELL_SIZE){const i=this.getBucketKey(t,s),o=this.buckets.get(i);o?o.push([n,e]):this.buckets.set(i,[[n,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,n,s){const i=[],o=new Set,a=Math.floor((t-n/2)/this.CELL_SIZE)*this.CELL_SIZE,r=Math.floor((e-s/2)/this.CELL_SIZE)*this.CELL_SIZE,h=t+n/2,c=e+s/2;for(let t=a;t<=h;t+=this.CELL_SIZE)for(let e=r;e<=c;e+=this.CELL_SIZE){const n=this.getBucketKey(t,e),s=this.buckets.get(n)||[];for(const t of s)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},bi=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 n=[];for(const s of e.layers)n.push(Ce(s,t.layerCount));e.zLayers=n}const n={x:(t.bounds.minX+t.bounds.maxX)/2,y:(t.bounds.minY+t.bounds.maxY)/2},s={width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},i=Math.max(s.width,s.height);this.unfinishedNodes=[{capacityMeshNodeId:this.getNextNodeId(),center:n,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 Kn("flatbush",this.srj.obstacles),this.targets=this.computeTargets(),this.targetTree=new Ni(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 n of e.pointsToConnect){const s=Ie(n),i=this.obstacleTree.searchArea(n.x,n.y,.01,.01).filter(t=>t.zLayers.some(t=>s.some(e=>t===Ce(e,this.layerCount))));let o={minX:n.x-.005,minY:n.y-.005,maxX:n.x+.005,maxY:n.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={...n,connectionName:e.name,availableZ:s.map(t=>Ce(t,this.layerCount)),bounds:o};t.push(a)}return t}getNodeBounds(t){const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-n,maxY:t.center.y+n}}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 n of e)if(n.bounds.minX<=t.center.x+t.width/2&&n.bounds.maxX>=t.center.x-t.width/2&&n.bounds.minY<=t.center.y+t.height/2&&n.bounds.maxY>=t.center.y-t.height/2&&n.availableZ.some(e=>t.availableZ.includes(e)))return n;return null}getXYOverlappingObstacles(t){const e=this.nodeToXYOverlappingObstaclesMap.get(t.capacityMeshNodeId);if(e)return e;const n=[],s=this.getNodeBounds(t),i=s.minX,o=s.maxX,a=s.minY,r=s.maxY,h=t._parent?this.getXYOverlappingObstacles(t._parent):this.srj.obstacles;for(const t of h){const e=t.center.x-t.width/2,s=t.center.x+t.width/2,h=t.center.y-t.height/2,c=t.center.y+t.height/2;o>=e&&i<=s&&r>=h&&a<=c?n.push(t):(i>=e&&o<=s&&a>=h&&r<=c||e>=i&&s<=o&&h>=a&&c<=r)&&n.push(t)}return this.nodeToXYOverlappingObstaclesMap.set(t.capacityMeshNodeId,n),n}getXYZOverlappingObstacles(t){const e=this.getXYOverlappingObstacles(t),n=[];for(const s of e)t.availableZ.some(t=>s.zLayers.includes(t))&&n.push(s);return n}doesNodeOverlapObstacle(t){if(this.getXYZOverlappingObstacles(t).length>0)return!0;const e=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!pt(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),n=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!ut(e,this.outlinePolygon))return!0}for(const t of e){const e=t.center.x-t.width/2,s=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2;if(n.minX>=e&&n.maxX<=s&&n.minY>=i&&n.maxY<=o)return!0}return!1}getChildNodes(t){if(t._depth===this.MAX_DEPTH)return[];const e=[],n={width:t.width/2,height:t.height/2},s=[{x:t.center.x-n.width/2,y:t.center.y-n.height/2},{x:t.center.x+n.width/2,y:t.center.y-n.height/2},{x:t.center.x-n.width/2,y:t.center.y+n.height/2},{x:t.center.x+n.width/2,y:t.center.y+n.height/2}];for(const i of s){const s={capacityMeshNodeId:this.getNextNodeId(),center:i,width:n.width,height:n.height,layer:t.layer,availableZ:t.availableZ,_depth:(t._depth??0)+1,_parent:t};s._containsObstacle=this.doesNodeOverlapObstacle(s);const o=this.getTargetIfNodeContainsTarget(s);o&&(s._targetConnectionName=o.connectionName,s.availableZ=o.availableZ,s._containsTarget=!0),s._containsObstacle&&(s._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(s)),s._completelyInsideObstacle&&!s._containsTarget||e.push(s)}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),n=[],s=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t);e?s.push(t):e||t._containsObstacle?!e&&t._containsTarget&&n.push(t):n.push(t)}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}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 n of e){const e=Math.min(...n.availableZ),s=this.unfinishedNodes.length>0&&n===this.unfinishedNodes[this.unfinishedNodes.length-1];t.rects.push({center:{x:n.center.x+e*n.width*.05,y:n.center.y-e*n.width*.05},width:Math.max(n.width-2,.8*n.width),height:Math.max(n.height-2,.8*n.height),fill:n._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)"}[n.availableZ.join(",")]??"rgba(0,200,200,0.1)",stroke:s?"rgba(255,165,0,0.5)":void 0,label:[n.capacityMeshNodeId,`availableZ: ${n.availableZ.join(",")}`,`target? ${n._containsTarget??!1}`,`obs? ${n._containsObstacle??!1}`,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`capacity: ${ve(n).toFixed(2)}`].join("\n")})}return t.rects.sort((t,e)=>t.center.y-e.center.y),this.srj.connections.forEach((e,n)=>{const s=X[n%X.length];for(const i of e.pointsToConnect){const e=Ie(i);t.points.push({x:i.x,y:i.y,label:`conn-${n} (${e.join(",")})`,color:s})}}),t}},Pi=class extends bi{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(!ut(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!!ut(e,this.outlinePolygon)&&!pt(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 n=t.center.x-t.width/2,s=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(n,t.center.x-t.width/2),a=Math.min(s,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 n={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},s=this.getXYZOverlappingObstacles(n);n._containsObstacle=s.length>0||this.isNodePartiallyOutsideBounds(n);const i=this.getTargetIfNodeContainsTarget(n);return i&&(n._targetConnectionName=i.connectionName,n._containsTarget=!0),n._containsObstacle&&(n._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(n)),n}getZSubdivisionChildNodes(t){if(1===t.availableZ.length)return[];const e=[],n=t.availableZ.map(t=>[t]);for(const s of n){const n=this.createChildNodeAtPosition(t,{center:{...t.center},width:t.width,height:t.height,availableZ:s,_depth:t._depth});this.isNodeCompletelyOutsideBounds(n)||e.push(n)}return e}getChildNodes(t){if(t._depth>=this.MAX_DEPTH)return[];const e=[],n={width:t.width/2,height:t.height/2},s=[{x:t.center.x-n.width/2,y:t.center.y-n.height/2},{x:t.center.x+n.width/2,y:t.center.y-n.height/2},{x:t.center.x-n.width/2,y:t.center.y+n.height/2},{x:t.center.x+n.width/2,y:t.center.y+n.height/2}];for(const i of s){const s=this.createChildNodeAtPosition(t,{center:i,width:n.width,height:n.height,availableZ:t.availableZ});this.isNodeCompletelyOutsideBounds(s)||e.push(s)}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),n=[],s=[];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)s.push(t);else if(e||this.shouldFilterNodeForObstacle(t)||i)if(!e&&t._containsTarget)if(i){const e=this.getZSubdivisionChildNodes(t);n.push(...e.filter(t=>t._containsTarget||!this.shouldFilterNodeForObstacle(t)))}else n.push(t);else i&&n.push(...this.getZSubdivisionChildNodes(t).filter(t=>!this.shouldFilterNodeForObstacle(t)));else n.push(t)}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}},Ii=class extends Pi{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 n of t){const t=[];for(const e of this.finishedNodes){this.getXYZOverlappingObstacles(e).some(t=>t===n)&&t.push(e)}e.set(n,t)}const n=new Set;for(const t of e.values())for(const e of t)n.add(e);this.finishedNodes=this.finishedNodes.filter(t=>!n.has(t));for(const n of t){const t=e.get(n)||[],s=n.layers&&n.layers.length>0?Array.from(new Set(n.layers.map(t=>Ce(t,this.srj.layerCount)))).sort((t,e)=>t-e):Array.from({length:this.srj.layerCount},(t,e)=>this.srj.layerCount-e-1);let i=n.center.x-n.width/2,o=n.center.x+n.width/2,a=n.center.y-n.height/2,r=n.center.y+n.height/2;for(const e of t){const t=e.center.x-e.width/2,n=e.center.x+e.width/2,s=e.center.y-e.height/2,h=e.center.y+e.height/2;i=Math.min(i,t),o=Math.max(o,n),a=Math.min(a,s),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_${n.center.x}_${n.center.y}`,center:{x:d,y:l},width:h,height:c,layer:1===s.length?`z${s[0]}`:`z${s.join(",")}`,availableZ:s,_depth:0,_containsTarget:u,_containsObstacle:!1,_completelyInsideObstacle:!1};p._assignedViaObstacle=n,this.finishedNodes.push(p)}}_step(){const t=this.unfinishedNodes.pop();if(!t)return this.insertAssignableObstaclesAsNodes(),void(this.solved=!0);const e=this.getChildNodes(t),n=[],s=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),i=t.availableZ.length>1&&!e;if(e)s.push(t);else{if(i){const e=this.getZSubdivisionChildNodes(t);for(const t of e)!t._containsTarget&&this.shouldFilterNodeForObstacle(t)||(this.shouldNodeBeXYSubdivided(t)?s.push(t):(t._containsObstacle=!1,n.push(t)));continue}this.shouldFilterNodeForObstacle(t)&&!t._containsTarget||n.push(t)}}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}},Ci=.005,_i=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 n of t)n._assignedViaObstacle?(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId)):n._containsTarget?n.availableZ.length>1?(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId)):e.push([n,n.width*n.height]):(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId));e.sort((t,e)=>t[1]-e[1]);for(const[t,n]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))),n=[];for(let s=0;s<=e;s++)n.push(new Oe(t.filter(t=>t.availableZ[0]===s)));for(const e of t){const t=[],s=n[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const n of s)n._containsTarget&&n._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!n._containsTarget||n._targetConnectionName!==e._targetConnectionName)||n.capacityMeshNodeId!==e.capacityMeshNodeId&&ze(e,n)&&t.push(n);e._adjacentNodeIds=t.map(t=>t.capacityMeshNodeId)}}getAdjacentSameLayerUnprocessedNodes(t){const e=[],n=Array.from(new Set((t._adjacentNodeIds??[]).map(t=>this.nodeMap.get(t)))).filter(e=>e&&e.capacityMeshNodeId!==t.capacityMeshNodeId);n.sort((t,e)=>t.width*t.height-e.width*e.height);for(const t of n)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 n=this.nodeMap.get(t),s=this.nodeMap.get(e);return n.width*n.height-s.width*s.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 n=!1;const s=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===s.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=s.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:s}=o[0],a=o.every(e=>e.width===t&&e.height===s);Math.abs(o.reduce((t,e)=>t+e.height,0)-e.height)<Ci&&a&&(e.width+=t,e.center.x=e.center.x-t/2,i(o),n=!0)}const a=s.filter(t=>t.center.x>e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(a.length>0&&!n){const{width:t,height:s}=a[0],o=a.every(e=>e.width===t&&e.height===s);Math.abs(a.reduce((t,e)=>t+e.height,0)-e.height)<Ci&&o&&(e.width+=t,e.center.x=e.center.x+t/2,i(a),n=!0)}const r=s.filter(t=>t.center.y>e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(r.length>0&&!n){const{width:t,height:s}=r[0],o=r.every(e=>e.width===t&&e.height===s);Math.abs(r.reduce((t,e)=>t+e.width,0)-e.width)<Ci&&o&&(e.height+=s,e.center.y=e.center.y+s/2,i(r),n=!0)}const h=s.filter(t=>t.center.y<e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(h.length>0&&!n){const{width:t,height:s}=h[0],o=h.every(e=>e.width===t&&e.height===s);Math.abs(h.reduce((t,e)=>t+e.width,0)-e.width)<Ci&&o&&(e.height+=s,e.center.y=e.center.y-s/2,i(h),n=!0)}n?(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(ei(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let n;e&&(n=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const s of this.currentBatchNodeIds){const i=this.nodeMap.get(s);if(!this.absorbedNodeIds.has(s)&&i){const o=ei(i,{rectMargin:.01});s===e?o.stroke="rgba(0, 255, 0, 0.8)":n?.some(t=>t.capacityMeshNodeId===s)?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 n=this.nodeMap.get(e);if(!this.absorbedNodeIds.has(e)&&n){const e=ei(n,{rectMargin:.01});e.layer=`z${n.availableZ.join(",")}`,e.stroke="rgba(0, 217, 255, 0.8)",e.label=`${e.label}\nx: ${n.center.x}, y: ${n.center.y}\n${n.width}x${n.height}\n(next batch)`,t.rects.push(e)}}return t}},Ei=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 n=this.obstacleToNodesMap.get(t)||[];n.push(e),this.obstacleToNodesMap.set(t,n)}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 n=Number.POSITIVE_INFINITY,s=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;n=Math.min(n,e),s=Math.max(s,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=s-n,c=o-i,d=(n+s)/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 n=ei(e);e._assignedViaObstacle&&(n.stroke="rgba(255, 0, 255, 0.8)",n.label=`${n.label||""}\n(merged via)`),t.rects.push(n)}const e=this.obstaclesToProcess[this.obstaclesToProcess.length-1];if(e){const n=this.obstacleToNodesMap.get(e)||[];for(const e of n){const n=ei(e,{rectMargin:.01});n.stroke="rgba(0, 255, 0, 0.8)",n.label=`${n.label||""}\n(to be merged)`,t.rects.push(n)}}return t}},Ti=class extends e{constructor(t){const{simpleRouteJson:e,nodes:n,edges:s,colorMap:i,MAX_ITERATIONS:o=1e6,hyperParameters:a={}}=t;super(),this.inputParams=t,this.hyperParameters=a,this.MAX_ITERATIONS=o,this.simpleRouteJson=e,this.nodes=n,this.edges=s,this.colorMap=i??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ss(this.edges);const r=this.nodes.filter(t=>t._containsTarget);this.unprocessedConnectionPairs=Pt(this.simpleRouteJson.connections.map(t=>{const[e,n]=t.pointsToConnect;return{start:r.find(t=>st(t.center,e)<t.width/2),end:r.find(t=>st(t.center,n)<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 n=e.reduce((e,n)=>{const s=this._dist(e,t.start);return this._dist(n,t.start)<s?n:e});this.closestViaForConnectionStartMap.set(t,n);const s=e.reduce((e,n)=>{const s=this._dist(e,t.end);return this._dist(n,t.end)<s?n:e});this.closestViaForConnectionEndMap.set(t,s)}}}_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:n}=t;if(e.capacityMeshNodeId===n.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,n),s={prevCandidate:null,node:e,g:0,h:t,f:this.GREEDY_MULTIPLIER*t};this.queuedCandidateNodes.push(s)}let s;for(this.queuedCandidateNodes.sort((t,e)=>t.f-e.f);this.queuedCandidateNodes.length&&!s;){const t=this.queuedCandidateNodes.shift();this.visitedNodes.has(t.node.capacityMeshNodeId)||(s=t)}if(!s)return this.failed=!0,void(this.error="No viable candidates left");if(this.visitedNodes.add(s.node.capacityMeshNodeId),s.node.capacityMeshNodeId===n.capacityMeshNodeId){const e=[];let n=s;for(;n;)e.unshift(n.node),this.usedNodeMap.set(n.node.capacityMeshNodeId,!0),n=n.prevCandidate;return t.path=e,void(t.solved=!0)}const i=this.getNeighbors(s.node);for(const t of i){const e=t.capacityMeshNodeId;if(this.visitedNodes.has(e))continue;const i=this.computeG(s,t,n),o=this.computeH(s,t,n),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:s,node:t,g:i,h:o,f:a})}}getNeighbors(t){const e=new Set,n=this.nodeEdgeMap.get(t.capacityMeshNodeId)??[];for(const s of n){const[n,i]=s.nodeIds,o=n===t.capacityMeshNodeId?i:n,a=this.nodeMap.get(o);a&&e.add(a)}const s=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!==s&&!t.availableZ.includes(s)))))}clearCandidateNodes(){this.queuedCandidateNodes=[],this.visitedNodes=new Set}computeG(t,e,n){const s=this._dist(t.node,e);return t.g+s}computeH(t,e,n){return this._dist(e,n)}createSolvedRoute(t,e){const n=[];for(let e=0;e<t.length;e++){const s=t[e];s.path?0===e?n.push(...s.path):n.push(...s.path.slice(1)):(0===e&&n.push(s.start),e===t.length-1&&n.push(s.end))}return{connection:e.connection,path:n}}breakConnectionPairIntoSubpaths(t){var e,n;if(!(e=[this.hyperParameters.DIRECTIVE_SEED??0,this.solvedRoutes.length],n=this.hyperParameters.FORCE_VIA_TRAVEL_CHANCE??0,Nt(e.reduce((t,e)=>t+16807*e%2147483647,0))()<n))return[{start:t.start,end:t.end,solved:!1,layer:t.start.availableZ[0]??0}];const s=this.getClosestVia(t.start),i=this.getFarVia(s,t.end),o=t.start.availableZ[0]??0,a=t.end.availableZ[0]??0,r=[];return r.push({start:t.start,end:s,solved:!1,layer:o}),o===a?(r.push({start:s,end:i,solved:!1,layer:0===o?1:0}),r.push({start:i,end:t.end,solved:!1,layer:a})):r.push({start:s,end:t.end,solved:!1,layer:a}),r}getClosestVia(t){if(0===this.viaNodes.length)return t;const e=new Set;for(const[t,n]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&e.add(n.capacityMeshNodeId);for(const[t,n]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&e.add(n.capacityMeshNodeId);const n=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId)).filter(t=>!e.has(t.capacityMeshNodeId));if(0===n.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,n)=>this._dist(e,t)-this._dist(n,t)),e[0])}n.sort((e,n)=>this._dist(e,t)-this._dist(n,t));const s=this.hyperParameters.MAX_CLOSEST_VIA_SKIP??0;if(s>0&&n.length>1){const t=Nt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length),e=Math.floor(t()*(s+1));return n[Math.min(e,n.length-1)]}return n[0]}getFarVia(t,e){if(0===this.viaNodes.length)return t;const n=null!=this.hyperParameters.FAR_VIA_MIN_DISTANCE?this.hyperParameters.FAR_VIA_MIN_DISTANCE:50,s=new Set;for(const[t,e]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&s.add(e.capacityMeshNodeId);for(const[t,e]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&s.add(e.capacityMeshNodeId);const i=this.viaNodes.filter(e=>!this.usedNodeMap.has(e.capacityMeshNodeId)&&e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!s.has(e.capacityMeshNodeId)&&this._dist(e,t)>=n);if(0===i.length){const s=this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)&&this._dist(e,t)>=n).sort((t,n)=>this._dist(t,e)-this._dist(n,e));if(s.length>0)return s[0];return this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)).sort((t,n)=>this._dist(t,e)-this._dist(n,e))[0]??t}i.sort((t,n)=>this._dist(t,e)-this._dist(n,e));const o=this.hyperParameters.MAX_FURTHEST_VIA_SKIP??0;if(o>0&&i.length>1){const t=Nt((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 n=e.path;n&&n.length>0&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:n.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),n=t=>"number"==typeof t&&!Number.isNaN(t)&&Number.isFinite(t);for(const s of this.nodes){const i=this.queuedCandidateNodes.some(t=>t.node.capacityMeshNodeId===s.capacityMeshNodeId),o=this.queuedCandidateNodes.find(t=>t.node.capacityMeshNodeId===s.capacityMeshNodeId);if(e(s.center)&&n(s.width)&&n(s.height)){const e=ei(s,{rectMargin:.025,zOffset:.01});t.rects.push({...e,fill:i?"rgba(255, 128, 255, 0.5)":s._containsTarget?"rgba(0, 150, 255, 0.15)":s._containsObstacle?"rgba(255, 0, 0, 0.1)":"rgba(200, 200, 200, 0.05)",label:[`ID: ${s.capacityMeshNodeId}`,`Size: ${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Z: ${s.availableZ.join(", ")}`,o?`g: ${o.g.toFixed(2)}`:"",o?`h: ${o.h.toFixed(2)}`:"",o?`f: ${o.f.toFixed(2)}`:"",s._containsTarget?"TARGET":"",s._containsObstacle?"OBSTACLE":""].filter(t=>t).join("\n")})}}for(const n of this.edges){const[s,i]=n.nodeIds,o=this.nodeMap.get(s),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 n=0;n<this.solvedRoutes.length;n++){const s=this.solvedRoutes[n],i=s.path,o="blue";for(let s=0;s<i.length-1;s++){const a=i[s],r=i[s+1];if(a?.center&&r?.center&&e(a.center)&&e(r.center)){const e=a.availableZ.includes(1)&&r.availableZ.includes(1),s=n%5*.02;t.lines.push({points:[{x:a.center.x+s,y:a.center.y+s},{x:r.center.x+s,y:r.center.y+s}],strokeColor:o,strokeDash:e?"5 5":void 0})}}if(i.length>0){const n=i[0],o=i[i.length-1];n?.center&&e(n.center)&&t.points.push({x:n.center.x,y:n.center.y,label:`START: ${s.connection.name}`}),o?.center&&e(o.center)&&t.points.push({x:o.center.x,y:o.center.y,label:`END: ${s.connection.name}`})}}if(this.solvedSubpaths)for(let n=0;n<this.solvedSubpaths.length;n++){const s=this.solvedSubpaths[n];if(s.path&&s.path.length>1)for(let n=0;n<s.path.length-1;n++){const i=s.path[n],o=s.path[n+1];i?.center&&o?.center&&e(i.center)&&e(o.center)&&t.lines.push({points:[i.center,o.center],strokeColor:"green",strokeDash:1===s.layer?"3 3":void 0})}}if(this.activeSubpath){const n=this.activeSubpath.start?.center,s=this.activeSubpath.end?.center;n&&s&&e(n)&&e(s)&&(t.lines.push({points:[n,s],strokeColor:"orange",strokeDash:"5 5"}),t.points.push({x:n.x,y:n.y,label:"ACTIVE START"}),t.points.push({x:s.x,y:s.y,label:"ACTIVE END"}))}const s=this.queuedCandidateNodes.slice(0,10).sort((t,e)=>t.f-e.f);for(let n=0;n<s.length;n++){const i=.6*(1-n/10),o=[];let a=s[n];for(;a;)o.push(a.node),a=a.prevCandidate;if(o.reverse(),o.length>1){const n=o.map(t=>t.center).filter(t=>e(t));n.length>1&&t.lines.push({points:n,strokeColor:H("purple",1-i),strokeDash:1===this.activeSubpath?.layer?"4 2":void 0})}}if(this.activeConnectionPair){const n=this.activeConnectionPair.start?.center,s=this.activeConnectionPair.end?.center;n&&s&&e(n)&&e(s)&&t.lines.push({points:[n,s],strokeColor:"cyan",strokeDash:"20 5"})}if(this.ogUnprocessedSubpaths&&3===this.ogUnprocessedSubpaths.length){const[,s]=this.ogUnprocessedSubpaths;if(s.start?.center&&e(s.start.center)){const e=Math.max(s.start.width||0,s.start.height||0);n(e)&&e>0&&(t.circles.push({center:s.start.center,radius:e,stroke:"blue"}),t.points.push({x:s.start.center.x,y:s.start.center.y,label:"DIRECTIVE VIA 1"}))}if(s.end?.center&&e(s.end.center)){const e=Math.max(s.end.width||0,s.end.height||0);n(e)&&e>0&&(t.circles.push({center:s.end.center,radius:e,stroke:"purple"}),t.points.push({x:s.end.center.x,y:s.end.center.y,label:"DIRECTIVE VIA 2"}))}}if(this.queuedCandidateNodes.length>0)for(const n of this.queuedCandidateNodes){const s=n.node;s?.center&&e(s.center)&&t.circles.push({center:s.center,radius:.05,fill:"rgba(255, 255, 0, 0.6)",stroke:"yellow"})}if(this.visitedNodes.size>0)for(const n of this.visitedNodes){const s=this.nodeMap.get(n);s?.center&&e(s.center)&&t.circles.push({center:s.center,radius:.08,fill:"rgba(128, 128, 128, 0.5)",stroke:"gray"})}return t}},wi=class extends wt{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),n=t.solvedRoutes.length,s=e>0?n/e:0;return t.iterations/t.MAX_ITERATIONS+(1-s)}computeH(t){const e=t.unprocessedConnectionPairs.length+t.solvedRoutes.length+(t.activeConnectionPair?1:0),n=t.solvedRoutes.length;return e>0?1-n/e:0}generateSolver(t){return new Ti({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}};function Ai(t){const e=new Map;for(const n of t)e.set(n.capacityMeshNodeId,n);return e}function zi(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var Ri=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=Ai(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 n=e._assignedViaObstacle;if(n?.offBoardConnectsTo)for(const s of n.offBoardConnectsTo)t.has(s)||t.set(s,[]),t.get(s).push(e)}this.pendingEdges=[];for(const[e,n]of t)if(n.length>1)for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++)this.pendingEdges.push({node1:n[t],node2:n[s],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:n}=this.pendingEdges.shift(),s=this.createOffboardEdge(t,e,n);this.enhancedEdges.push(s),this.createdEdges.push(s)}else this.animationState="done",this.solved=!0;break;case"done":this.solved=!0}}createOffboardEdge(t,e,n){return{capacityMeshEdgeId:"offboard_"+this.nextEdgeId++,nodeIds:[t.capacityMeshNodeId,e.capacityMeshNodeId],isOffboardEdge:!0,offboardNetName:n}}visualize(){const t=[],e=[],n=[],s=new Set(this.shownNodes.map(t=>t.capacityMeshNodeId));for(const e of this.capacityEdges){if(e.isOffboardEdge)continue;if(s.has(e.nodeIds[0])||s.has(e.nodeIds[1])){const n=this.nodeMap.get(e.nodeIds[0]),s=this.nodeMap.get(e.nodeIds[1]);n&&s&&t.push({points:[n.center,s.center],strokeColor:"rgba(0, 200, 0, 0.5)",strokeWidth:.05})}}for(let t=0;t<this.shownNodes.length;t++){const s=this.shownNodes[t],i=s._assignedViaObstacle,o=t===this.shownNodes.length-1&&"showing_nodes"===this.animationState;n.push({center:s.center,width:s.width,height:s.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:s.center.x,y:s.center.y,color:o?"orange":"blue",label:`${o?"NEW: ":""}${s.capacityMeshNodeId}\n${i?.offBoardConnectsTo?.join(", ")||""}`})}for(let n=0;n<this.createdEdges.length;n++){const s=this.createdEdges[n],i=n===this.createdEdges.length-1&&"showing_edges"===this.animationState,o=this.nodeMap.get(s.nodeIds[0]),a=this.nodeMap.get(s.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 n=zi(o.center,a.center);e.push({x:n.x,y:n.y,color:i?"red":"orange",label:`${i?"NEW: ":""}⚡ ${s.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:n,title:i}}getVirtualOffboardNodes(){return[]}getOffboardEdges(){return this.enhancedEdges.filter(t=>t.isOffboardEdge)}};function Oi(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 Li=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:n,connections:s}){super(),this.inputPaths=[...t],this.capacityEdges=e,this.originalConnections=s,this.nodeMap=Ai(n)}_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 n=this.originalConnections.find(e=>e.name===t.connectionName);if(n)for(let t=0;t<e.length;t++){const s=e[t];if(!s.isFragmentedPath)continue;const i=n.pointsToConnect.filter(t=>{for(const e of s.nodeIds){const n=this.nodeMap.get(e);if(n&&Oi(t,n))return!0}return!1}),o=0===t,a=o?s.nodeIds[s.nodeIds.length-1]:s.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:Pe(t)},a=o?[...i,e]:[e,...i];this.fragmentedConnections.push({name:s.connectionName,pointsToConnect:a,netConnectionName:n.netConnectionName,rootConnectionName:n.rootConnectionName})}}}splitPath(t){const{nodeIds:e}=t;if(e.length<2)return[t];const n=[];for(let t=0;t<e.length-1;t++){const s=this.capacityEdges.find(n=>n.nodeIds[0]===e[t]&&n.nodeIds[1]===e[t+1]||n.nodeIds[0]===e[t+1]&&n.nodeIds[1]===e[t]);s&&s.isOffboardEdge&&n.push(t)}if(0===n.length)return[t];const s=[];let i=0,o=0;for(const a of n){const n=e.slice(i,a+1);if(n.length>=1){const e=this.nextFragmentId++;s.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${o++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}i=a+1}if(i<e.length){const n=e.slice(i);if(n.length>=1){const e=this.nextFragmentId++;s.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${o++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}}return s.length>0?s:[t]}getFragmentedPaths(){return this.fragmentedPaths}getFragmentedConnections(){return this.fragmentedConnections}getFragmentedOriginalConnectionNames(){return this.fragmentedOriginalConnectionNames}visualize(){const t=[],e=[],n=[];if("showing_original_path"===this.animationState&&this.currentPath&&this.drawPath({path:this.currentPath,color:"gray",lines:t,points:e,rects:n,labelPrefix:"Original: "}),this.fragmentedPaths.forEach((s,i)=>{if(s.isFragmentedPath){const o=i%2==0?"blue":"red";this.drawPath({path:s,color:o,lines:t,points:e,rects:n,labelPrefix:`Frag ${i}: `})}else this.drawPath({path:s,color:"green",lines:t,points:e,rects:n,labelPrefix:""})}),"showing_fragment"===this.animationState&&this.currentFragmentIndex>0){const s=this.fragmentedPaths.length-1;if(s>=0){const i=this.fragmentedPaths[s];i.isFragmentedPath&&this.drawPath({path:i,color:"orange",lines:t,points:e,rects:n,labelPrefix:"NEW: "})}}for(const e of this.capacityEdges)if(e.isOffboardEdge){const n=this.nodeMap.get(e.nodeIds[0]),s=this.nodeMap.get(e.nodeIds[1]);n&&s&&t.push({points:[n.center,s.center],strokeColor:"orange",strokeWidth:.15,strokeDasharray:"0.3,0.15"})}let s="Offboard Path Fragment Solver";return"showing_original_path"===this.animationState?s+=" - Analyzing path...":"showing_fragment"===this.animationState?s+=` - Fragment ${this.currentFragmentIndex}/${this.currentFragments.length}`:s+=` - Done (${this.fragmentedPaths.filter(t=>t.isFragmentedPath).length} fragments)`,{lines:t,points:e,rects:n,title:s}}drawPath(t){const{path:e,color:n,lines:s,points:i,rects:o,labelPrefix:a}=t,r=[];for(let t=0;t<e.nodeIds.length;t++){const s=e.nodeIds[t],h=this.nodeMap.get(s);h&&(r.push(h.center),o.push({center:h.center,width:.8*h.width,height:.8*h.height,stroke:n,strokeWidth:.05,fill:`${n}33`}),0!==t&&t!==e.nodeIds.length-1||i.push({x:h.center.x,y:h.center.y,color:n,label:`${a}${e.connectionName}\n${s}`}))}r.length>1&&s.push({points:r,strokeColor:n,strokeWidth:.1})}};function Di(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Fi=class extends e{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,i=Math.max(n,s),o=e.targetMinCapacity??.5;e.capacityDepth=Me(i,o)}this.connMap=xe(t),this.colorMap=Y(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?G():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=[Di("netToPointPairsSolver",Ye,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=Y(t.srjWithPointPairs,this.connMap),t.connMap=xe(t.srjWithPointPairs)}}),Di("nodeSolver",Ii,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),Di("mergeAssignableViaNodes",Ei,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.mergeAssignableViaNodes?.newNodes}}),Di("singleLayerNodeMerger",_i,t=>[t.capacityNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),Di("edgeSolver",Le,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Di("offboardCapacityNodeSolver",Ri,t=>[{capacityNodes:t.capacityNodes,capacityEdges:t.capacityEdges||[]}],{onSolved:t=>{t.capacityEdges=t.offboardCapacityNodeSolver?.enhancedEdges||t.capacityEdges}}),Di("deadEndSolver",vi,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)))}}),Di("initialPathingHyperSolver",wi,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)}}),Di("offboardPathFragmentSolver",Li,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 n=e.getFragmentedPaths();for(const e of n)if(e.isFragmentedPath&&e.mstPairConnectionName){const n=t.colorMap[e.mstPairConnectionName];n&&!t.colorMap[e.connectionName]&&(t.colorMap[e.connectionName]=n)}const s=e.getFragmentedOriginalConnectionNames(),i=e.getFragmentedConnections();s.size>0&&t.srjWithPointPairs&&(t.srjWithPointPairs={...t.srjWithPointPairs,connections:[...t.srjWithPointPairs.connections.filter(t=>!s.has(t.name)),...i]},t.connMap=xe(t.srjWithPointPairs))}}),Di("edgeToPortSegmentSolver",zs,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.offboardPathFragmentSolver?.getFragmentedPaths()||t.initialPathingSolver?.getCapacityPaths()||[],colorMap:t.colorMap}]),Di("segmentToPointSolver",Fs,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),Di("unravelMultiSectionSolver",ti,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),Di("highDensityRouteSolver",me,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap}]),Di("highDensityStitchSolver",we,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Di("uselessViaRemovalSolver1",os,t=>[{unsimplifiedHdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Di("multiSimplifiedPathSolver1",xs,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver1?.getOptimizedHdRoutes()||t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}]),Di("uselessViaRemovalSolver2",os,t=>[{unsimplifiedHdRoutes:t.multiSimplifiedPathSolver1.simplifiedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Di("multiSimplifiedPathSolver2",xs,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(),n=this.nodeSolver?.visualize(),s=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,N=[];if(N.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]}),N.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const b={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:N},P=[b,e,n,s,i,o,a,r,h,c,d,l,u,p,f,g?t(b,g):null,m,y,v,x,M,this.solved?t(b,Ae(this.getOutputSimpleRouteJson())):null].filter(Boolean);return t(...P)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.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(),n=this.srjWithPointPairs?.connections??[];for(const s of n){const n=s.netConnectionName,i=s.rootConnectionName,o=e.filter(t=>t.connectionName===s.name);for(let e=0;e<o.length;e++){const a=o[e],r={type:"pcb_trace",pcb_trace_id:`${s.name}_${e}`,connection_name:n??i??s.name,route:Ne(a,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}};export{Fi as AssignableViaAutoroutingPipelineSolver,Si as AutoroutingPipeline1_OriginalUnravel,ws as AutoroutingPipelineSolver,As as CapacityMeshSolver,W as InMemoryCache,Z as LocalStorageCache,Me as calculateOptimalCapacityDepth,Ae as convertSrjToGraphicsObject,G as getGlobalInMemoryCache,U as getGlobalLocalStorageCache,ve as getTunedTotalCapacity1,q as setupGlobalCaches};//# sourceMappingURL=index.js.map
1
+ var t=(...t)=>{const e={points:[],lines:[],circles:[],rects:[]};return t.forEach((t,n)=>{t&&(t.lines&&(e.lines=[...e.lines||[],...t.lines.map(t=>({...t,step:n}))]),t.points&&(e.points=[...e.points||[],...t.points.map(t=>({...t,step:n}))]),t.circles&&(e.circles=[...e.circles||[],...t.circles.map(t=>({...t,step:n}))]),t.rects&&(e.rects=[...e.rects||[],...t.rects.map(t=>({...t,step:n}))]))}),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})`,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 n(){return n=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var s in n)({}).hasOwnProperty.call(n,s)&&(t[s]=n[s])}return t},n.apply(null,arguments)}function s(t,e){return(s=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t})(t,e)}function i(t){return(i=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function o(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(o=function(){return!!t})()}function a(t){var e="function"==typeof Map?new Map:void 0;return a=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,n)}function n(){return function(t,e,n){if(o())return Reflect.construct.apply(null,arguments);var i=[null];i.push.apply(i,e);var a=new(t.bind.apply(t,i));return n&&s(a,n.prototype),a}(t,arguments,i(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),s(n,t)},a(t)}var r={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 h(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];var s,i=e[0],o=[];for(s=1;s<e.length;s+=1)o.push(e[s]);return o.forEach(function(t){i=i.replace(/%[a-z]/,t)}),i}var c=function(t){var e,n;function i(e){var n;if("production"===process.env.NODE_ENV)n=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 s=arguments.length,i=new Array(s>1?s-1:0),o=1;o<s;o++)i[o-1]=arguments[o];n=t.call(this,h.apply(void 0,[r[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}(n)}return n=t,(e=i).prototype=Object.create(n.prototype),e.prototype.constructor=e,s(e,n),i}(a(Error));function d(t,e){return t.substr(-e.length)===e}var l=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;function u(t){return"string"!=typeof t?t:t.match(l)?parseFloat(t):t}var p=function(t){return function(e,n){void 0===n&&(n="16px");var s=e,i=n;if("string"==typeof e){if(!d(e,"px"))throw new c(69,t,e);s=u(e)}if("string"==typeof n){if(!d(n,"px"))throw new c(70,t,n);i=u(n)}if("string"==typeof s)throw new c(71,e,t);if("string"==typeof i)throw new c(72,n,t);return""+s/i+t}};p("em"),p("rem");function f(t){return Math.round(255*t)}function g(t,e,n){return f(t)+","+f(e)+","+f(n)}function m(t,e,n,s){if(void 0===s&&(s=g),0===e)return s(n,n,n);var i=(t%360+360)%360/60,o=(1-Math.abs(2*n-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=n-o/2;return s(r+d,h+d,c+d)}var y={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 x=/^#[a-fA-F0-9]{6}$/,v=/^#[a-fA-F0-9]{8}$/,S=/^#[a-fA-F0-9]{3}$/,M=/^#[a-fA-F0-9]{4}$/,N=/^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i,b=/^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,I=/^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 C(t){if("string"!=typeof t)throw new c(3);var e=function(t){if("string"!=typeof t)return t;var e=t.toLowerCase();return y[e]?"#"+y[e]:t}(t);if(e.match(x))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(v)){var n=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:n}}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(M)){var s=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:s}}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=b.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("+m(parseInt(""+a[1],10),parseInt(""+a[2],10)/100,parseInt(""+a[3],10)/100)+")",h=N.exec(r);if(!h)throw new c(4,e,r);return{red:parseInt(""+h[1],10),green:parseInt(""+h[2],10),blue:parseInt(""+h[3],10)}}var d=I.exec(e.substring(0,50));if(d){var l="rgb("+m(parseInt(""+d[1],10),parseInt(""+d[2],10)/100,parseInt(""+d[3],10)/100)+")",u=N.exec(l);if(!u)throw new c(4,e,l);return{red:parseInt(""+u[1],10),green:parseInt(""+u[2],10),blue:parseInt(""+u[3],10),alpha:parseFloat(""+d[4])>1?parseFloat(""+d[4])/100:parseFloat(""+d[4])}}throw new c(5)}function _(t){return function(t){var e,n=t.red/255,s=t.green/255,i=t.blue/255,o=Math.max(n,s,i),a=Math.min(n,s,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 n:e=(s-i)/h+(s<i?6:0);break;case s:e=(i-n)/h+2;break;default:e=(n-s)/h+4}return e*=60,void 0!==t.alpha?{hue:e,saturation:c,lightness:r,alpha:t.alpha}:{hue:e,saturation:c,lightness:r}}(C(t))}var E=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 T(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function w(t){return T(Math.round(255*t))}function z(t,e,n){return E("#"+w(t)+w(e)+w(n))}function A(t,e,n){return m(t,e,n,z)}function R(t,e,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n)return E("#"+T(t)+T(e)+T(n));if("object"==typeof t&&void 0===e&&void 0===n)return E("#"+T(t.red)+T(t.green)+T(t.blue));throw new c(6)}function O(t,e,n,s){if("string"==typeof t&&"number"==typeof e){var i=C(t);return"rgba("+i.red+","+i.green+","+i.blue+","+e+")"}if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof s)return s>=1?R(t,e,n):"rgba("+t+","+e+","+n+","+s+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===s)return t.alpha>=1?R(t.red,t.green,t.blue):"rgba("+t.red+","+t.green+","+t.blue+","+t.alpha+")";throw new c(7)}function D(t){if("object"!=typeof t)throw new c(8);if(function(t){return"number"==typeof t.red&&"number"==typeof t.green&&"number"==typeof t.blue&&"number"==typeof t.alpha}(t))return O(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 R(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,n,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof s)return s>=1?A(t,e,n):"rgba("+m(t,e,n)+","+s+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===s)return t.alpha>=1?A(t.hue,t.saturation,t.lightness):"rgba("+m(t.hue,t.saturation,t.lightness)+","+t.alpha+")";throw new c(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,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n)return A(t,e,n);if("object"==typeof t&&void 0===e&&void 0===n)return A(t.hue,t.saturation,t.lightness);throw new c(1)}(t);throw new c(8)}function L(t,e,n){return function(){var s=n.concat(Array.prototype.slice.call(arguments));return s.length>=e?t.apply(this,s):L(t,e,s)}}function F(t){return L(t,t.length,[])}F(function(t,e){if("transparent"===e)return e;var s=_(e);return D(n({},s,{hue:s.hue+parseFloat(t)}))});function $(t,e,n){return Math.max(t,Math.min(e,n))}F(function(t,e){if("transparent"===e)return e;var s=_(e);return D(n({},s,{lightness:$(0,1,s.lightness-parseFloat(t))}))});F(function(t,e){if("transparent"===e)return e;var s=_(e);return D(n({},s,{saturation:$(0,1,s.saturation-parseFloat(t))}))});F(function(t,e){if("transparent"===e)return e;var s=_(e);return D(n({},s,{lightness:$(0,1,s.lightness+parseFloat(t))}))});var k=F(function(t,e,s){if("transparent"===e)return s;if("transparent"===s)return e;if(0===t)return s;var i=C(e),o=n({},i,{alpha:"number"==typeof i.alpha?i.alpha:1}),a=C(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 O({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=C(e);return O(n({},s,{alpha:$(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);return D(n({},s,{saturation:$(0,1,s.saturation+parseFloat(t))}))});F(function(t,e){return"transparent"===e?e:D(n({},_(e),{hue:parseFloat(t)}))});F(function(t,e){return"transparent"===e?e:D(n({},_(e),{lightness:parseFloat(t)}))});F(function(t,e){return"transparent"===e?e:D(n({},_(e),{saturation:parseFloat(t)}))});F(function(t,e){return"transparent"===e?e:k(parseFloat(t),"rgb(0, 0, 0)",e)});F(function(t,e){return"transparent"===e?e:k(parseFloat(t),"rgb(255, 255, 255)",e)});var X=F(function(t,e){if("transparent"===e)return e;var s=C(e);return O(n({},s,{alpha:$(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"],B=(t,e)=>{const n={};for(let s=0;s<t.connections.length;s++){const i=t.connections[s],o=e?.getNetConnectedToId(i.name);o&&!n[o]&&(n[o]=`hsl(${300*s/t.connections.length}, 100%, 50%)`),n[i.name]=(o?n[o]:null)??`hsl(${340*s/t.connections.length}, 100%, 50%)`}return n},H=(t,e)=>{try{return X(e,t)}catch(e){return console.error(e),t}};import j from"object-hash";var Z=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 n=t.split(":")[0];return this.cacheHitsByPrefix[n]=(this.cacheHitsByPrefix[n]||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())}},W="tscircuit_autorouter_cache_",V=class{isSyncCache=!0;cacheHits=0;cacheMisses=0;cacheHitsByPrefix={};cacheMissesByPrefix={};constructor(){}getKey(t){return`${W}${t}`}getCachedSolutionSync(t){if("undefined"==typeof localStorage)return;const e=this.getKey(t);try{const n=localStorage.getItem(e);if(null!==n){const e=JSON.parse(n);this.cacheHits++;const s=t.split(":")[0];return this.cacheHitsByPrefix[s]=(this.cacheHitsByPrefix[s]||0)+1,e}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}catch(n){console.error(`Error getting cached solution sync for ${e}:`,n),this.cacheMisses++;const s=t.split(":")[0];return void(this.cacheMissesByPrefix[s]=(this.cacheMissesByPrefix[s]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){if("undefined"==typeof localStorage)return;const n=this.getKey(t);try{const t=JSON.stringify(e);localStorage.setItem(n,t)}catch(t){console.error(`Error setting cached solution sync for ${n}:`,t),t instanceof DOMException&&("QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&console.warn(`LocalStorage quota exceeded. Failed to cache solution for ${n}. 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 n=localStorage.key(e);n?.startsWith(W)&&t.push(n)}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 n=localStorage.key(e);if(!n)break;n.includes(W)&&t.push(n)}return t}};function U(){return globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE||q(),globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE}function G(){return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE||q(),globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE}function q(){globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE??=new V,globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE??=new Z}function K(t){const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-n,maxY:t.center.y+n}}function J(t,e,n){return Math.max(e,Math.min(n,t))}function Q(t,e,n,s){const i=tt(t,e,n),o=tt(t,e,s),a=tt(n,s,t),r=tt(n,s,e);return i!==o&&a!==r||(!(0!==i||!et(t,n,e))||(!(0!==o||!et(t,s,e))||(!(0!==a||!et(n,t,s))||!(0!==r||!et(n,e,s)))))}function tt(t,e,n){const s=(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y);return 0===s?0:s>0?1:2}function et(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function nt(t,e,n){const s=(n.x-e.x)**2+(n.y-e.y)**2;if(0===s)return st(t,e);let i=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/s;i=Math.max(0,Math.min(1,i));return st(t,{x:e.x+i*(n.x-e.x),y:e.y+i*(n.y-e.y)})}function st(t,e){const n=t.x-e.x,s=t.y-e.y;return Math.sqrt(n*n+s*s)}function it(t,e,n,s){const i=e.x-t.x,o=e.y-t.y,a=s.x-n.x,r=s.y-n.y,h=t.x-n.x,c=t.y-n.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 ot(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var at=t=>{if("minX"in t)return t;const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,minY:t.center.y-n,maxX:t.center.x+e,maxY:t.center.y+n}},rt=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}],ht=t=>{const e=[];for(let n=0;n<t.length;n++){const s=t[n],i=t[(n+1)%t.length];e.push([s,i])}return e},ct=(t,e,n)=>{const s=(t.y-e.y)*(n.x-e.x)-(t.x-e.x)*(n.y-e.y);if(Math.abs(s)>1e-9)return!1;const i=(t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y);if(i<0)return!1;return!(i>(n.x-e.x)**2+(n.y-e.y)**2)},dt=(t,e)=>{if(e.length<3)return!1;const n=ht(e);for(const[e,s]of n)if(ct(t,e,s))return!0;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},lt=(t,e)=>{const n=rt(t),s=[[n[0],n[1]],[n[1],n[2]],[n[2],n[3]],[n[3],n[0]]],i=ht(e);for(const[t,e]of i)for(const[n,i]of s)if(Q(t,e,n,i))return!0;return!1},ut=(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))||(!!rt(t).some(t=>dt(t,e))||lt(t,e))))(at(t),e),pt=(t,e)=>((t,e)=>!(e.length<3)&&(!!rt(t).every(t=>dt(t,e))&&!lt(t,e)))(at(t),e);function ft(t,e,n,s){if(t.x===e.x&&t.y===e.y)return nt(t,n,s);if(n.x===s.x&&n.y===s.y)return nt(n,t,e);if(Q(t,e,n,s))return 0;const i=[nt(t,n,s),nt(e,n,s),nt(n,t,e),nt(s,t,e)];return Math.min(...i)}function gt(t,e,n){const s=n.width/2,i=n.height/2;return function(t,e,n){const s={x:n.minX,y:n.minY},i={x:n.maxX,y:n.minY},o={x:n.minX,y:n.maxY},a={x:n.maxX,y:n.maxY};if(Q(t,e,s,i)||Q(t,e,i,a)||Q(t,e,a,o)||Q(t,e,o,s))return 0;if(t.x>=n.minX&&t.x<=n.maxX&&t.y>=n.minY&&t.y<=n.maxY&&e.x>=n.minX&&e.x<=n.maxX&&e.y>=n.minY&&e.y<=n.maxY)return 0;const r=[nt(s,t,e),nt(i,t,e),nt(o,t,e),nt(a,t,e)];if(t.x>=n.minX&&t.x<=n.maxX&&t.y>=n.minY&&t.y<=n.maxY)return 0;if(e.x>=n.minX&&e.x<=n.maxX&&e.y>=n.minY&&e.y<=n.maxY)return 0;if(t.x<n.minX||t.x>n.maxX||t.y<n.minY||t.y>n.maxY){const e=J(t.x,n.minX,n.maxX),s=J(t.y,n.minY,n.maxY);r.push(st(t,{x:e,y:s}))}if(e.x<n.minX||e.x>n.maxX||e.y<n.minY||e.y>n.maxY){const t=J(e.x,n.minX,n.maxX),s=J(e.y,n.minY,n.maxY);r.push(st(e,{x:t,y:s}))}return Math.min(...r)}(t,e,{minX:n.center.x-s,maxX:n.center.x+s,minY:n.center.y-i,maxY:n.center.y+i})}function mt(t,e,n){const s=n.x-e.x,i=n.y-e.y,o=s*s+i*i;if(0===o)return{x:e.x,y:e.y};let a=((t.x-e.x)*s+(t.y-e.y)*i)/o;a=Math.max(0,Math.min(1,a));return{x:e.x+a*s,y:e.y+a*i}}var yt=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 n=this.heap[t];this.heap[t]=this.heap[e],this.heap[e]=n}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}}},xt=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=st(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 n=this.boundsSize.width/this.cellStep,s=this.boundsSize.height/this.cellStep;for(;n*s>e**2&&!(2*this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,n=this.boundsSize.width/this.cellStep,s=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 yt([{...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,n=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:n,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,n){if(e??=this.obstacleMargin,n&&t.parent){const n=this.getViasInNodePath(t.parent);for(const s of n)if(st(t,s)<this.viaDiameter/2+e)return!0}for(const s of this.obstacleRoutes){const i=this.connMap?.areIdsConnected?.(this.connectionName,s.connectionName);if(!i){const i=vt(s);for(const s of i)if((n||s.z===t.z)&&nt(t,s.A,s.B)<this.traceThickness+e)return!0}for(const n of s.vias)if(st(t,n)<this.viaDiameter/2+this.traceThickness/2+e)return!0}return!1}isNodeTooCloseToEdge(t,e){const n=e?this.viaDiameter/2+this.obstacleMargin/2:this.obstacleMargin/2,s=t.x<this.bounds.minX+n||t.x>this.bounds.maxX-n||t.y<this.bounds.minY+n||t.y>this.bounds.maxY-n;return!(s&&!e&&(st(t,this.B)<2*n||st(t,this.A)<2*n))&&s}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!s)for(const s of vt(n))if(s.z===t.z&&Q(t,e,s.A,s.B))return!0}return!1}computeH(t){return st(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)+st(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:n,minX:s,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:St(t.x+a*this.cellStep,s,n),y:St(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 n=0;n<this.layerCount;n++){if(n===t.z)continue;const s={...t,parent:t,z:n};this.exploredNodes.has(this.getNodeKey(s))||this.isNodeTooCloseToObstacle(s,this.viaDiameter/2+this.obstacleMargin/2,!0)||this.isNodeTooCloseToEdge(s,!0)||(s.g=this.computeG(s),s.h=this.computeH(s),s.f=this.computeF(s.g,s.h),e.push(s))}return e}getNodePath(t){const e=[];for(;t;)e.push(t),t=t.parent;return e}getViasInNodePath(t){const e=this.getNodePath(t),n=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&n.push({x:e[t].x,y:e[t].y});return n}setSolvedPath(t){const e=this.getNodePath(t);e.reverse();const n=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&n.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:n}}computeProgress(t,e,n){n||(e+=this.viaPenaltyDistance);const s=1-e/this.straightLineDistance;return Math.max(this.progress||0,2/Math.PI*Math.atan(.112*s/(1-s)))}_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 this.failed=!0,void(this.error="Ran out of candidate nodes to explore");this.exploredNodes.add(e),this.debug_exploredNodesOrdered.push(e);const n=st(t,this.B);this.progress=this.computeProgress(t,n,t.z===this.B.z),n<=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 s=this.getNeighbors(t);for(const t of s)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 n=this.obstacleRoutes[e];for(let s=0;s<n.route.length-1;s++){const i=n.route[s].z;t.lines.push({points:[n.route[s],n.route[s+1]],strokeColor:0===i?"rgba(255, 0, 0, 0.75)":"rgba(255, 128, 0, 0.25)",strokeWidth:n.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`})}}for(let e=0;e<this.debug_exploredNodesOrdered.length;e++){const n=this.debug_exploredNodesOrdered[e],[s,i,o]=n.split(",").map(Number);this.debug_nodesTooCloseToObstacle.has(n)||(this.debug_nodePathToParentIntersectsObstacle.has(n)||t.rects.push({center:{x:s+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 n of e.vias)t.circles.push({center:{x:n.x,y:n.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 vt(t){const e=[];for(let n=0;n<t.route.length-1;n++)t.route[n].z===t.route[n+1].z&&e.push({z:t.route[n].z,A:t.route[n],B:t.route[n+1]});return e}function St(t,e,n){return Math.max(e,Math.min(t,n))}var Mt=class extends xt{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,n=Math.max(1,this.numRoutes);this.VIA_PENALTY_FACTOR=e/n*.3*this.VIA_PENALTY_FACTOR_2}getClosestFutureConnectionPoint(t){let e=1/0,n=null;for(const s of this.futureConnections)for(const i of s.points){const s=st(t,i)+(t.z!==i.z?this.viaPenaltyDistance:0);s<e&&(e=s,n=i)}return n}diminishCloseToGoal(t){const e=st(t,this.B);return 1-Math.exp(-e/this.straightLineDistance*5)}getFutureConnectionPenalty(t,e){let n=0;const s=this.getClosestFutureConnectionPoint(t),i=st(t,this.B);if(s){const o=st(t,s);if(i<=o)return 0;const a=o/(this.viaDiameter*this.FUTURE_CONNECTION_PROXIMITY_VD);n=(e?this.straightLineDistance*this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR:this.straightLineDistance*this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR)*Math.exp(5*-a)}return n}computeH(t){const e=st(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),n=Math.abs(t.y-t.parent.y),s=Math.sqrt(e**2+n**2),i=t.z%2==0,o=this.FLIP_TRACE_ALIGNMENT_DIRECTION?i?e:n:i?n:e;return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+s+o*this.MISALIGNED_DIST_PENALTY_FACTOR+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}};function Nt(t){let e=t;for(let t=0;t<10;t++)e=16807*e%2147483647;let n=e;e=(69069*t+1)%2147483647;for(let t=0;t<10;t++)e=48271*e%2147483647;let s=e;return()=>{let t=n;n=s,t^=t<<23,t^=t>>>17,t^=s,t^=s>>>26,s=t;const e=(n+s)/4294967296;return e-Math.floor(e)}}var bt={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 Pt(t,e){if(0===e)return t;if(t.length<=4){const n=bt[t.length];return n[e%n.length].map(e=>t[e])}const n=Nt(e),s=t.slice();for(let t=0;t<s.length;t++){const e=Math.floor(n()*s.length),i=Math.floor(n()*(t+1));[s[e],s[i]]=[s[i],s[e]]}return s}function It(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 n of t.portPoints)n.x<e.minX&&(e.minX=n.x),n.x>e.maxX&&(e.maxX=n.x),n.y<e.minY&&(e.minY=n.y),n.y>e.maxY&&(e.maxY=n.y);return e}var Ct=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:n}=t;super(),this.nodeWithPortPoints=e,this.colorMap=n??{},this.solvedRoutes=[],this.hyperParameters=t.hyperParameters??{},this.failedSubSolvers=[],this.connMap=t.connMap,this.viaDiameter=t.viaDiameter??.6,this.traceWidth=t.traceWidth??.15;const s=new Map;for(const{connectionName:t,x:n,y:i,z:o}of e.portPoints)s.set(t,[...s.get(t)??[],{x:n,y:i,z:o??0}]);this.unsolvedConnections=Array.from(s.entries().map(([t,e])=>({connectionName:t,points:e}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=Pt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},n)=>({...e,points:Pt(t,7117*n+(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 n=t.portPoints;for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++){if(n[t].z!==n[s].z)continue;const i=n[t],o=n[s],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,n]=t.points,s=Math.abs(e.x-n.x)<1e-6,i=Math.abs(e.y-n.y)<1e-6;if(s&&i&&e.z===n.z)return;if(s&&i&&e.z!==n.z){const s={x:this.nodeWithPortPoints.center.x,y:this.nodeWithPortPoints.center.y},i=[{x:e.x,y:e.y,z:e.z},{...s,z:e.z},{...s,z:n.z},{x:n.x,y:n.y,z:n.z}].filter((t,e,n)=>0===e||Math.abs(t.x-n[e-1].x)>1e-6||Math.abs(t.y-n[e-1].y)>1e-6||t.z!==n[e-1].z);return void this.solvedRoutes.push({connectionName:t.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:i,vias:[s]})}}const{connectionName:e,points:n}=t;this.activeSubSolver=new Mt({connectionName:e,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:It(this.nodeWithPortPoints),A:{x:n[0].x,y:n[0].y,z:n[0].z},B:{x:n[n.length-1].x,y:n[n.length-1].y,z:n[n.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 n=this.solvedRoutes[e];if(n.route.length>0){const s=this.colorMap[n.connectionName]??"blue";for(let i=0;i<n.route.length-1;i++){const o=n.route[i],a=n.route[i+1];t.lines.push({points:[o,a],strokeColor:0===o.z?H(s,.2):H(s,.8),layer:`route-layer-${o.z}`,step:e,strokeWidth:n.traceThickness})}for(const i of n.vias)t.circles.push({center:{x:i.x,y:i.y},radius:n.viaDiameter/2,fill:H(s,.5),layer:"via",step:e})}}const e=It(this.nodeWithPortPoints),{minX:n,minY:s,maxX:i,maxY:o}=e;return t.lines.push({points:[{x:n,y:s},{x:i,y:s},{x:i,y:o},{x:n,y:o},{x:n,y:s}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}},_t=t=>Math.round(200*t)/200,Et=t=>"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t));q();var Tt=class extends Ct{cacheProvider;cacheHit=!1;hasAttemptedToUseCache=!1;initialUnsolvedConnections;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?G():t.cacheProvider,this.initialUnsolvedConnections=Et(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:n})=>({connectionName:e,points:n.map(n=>({connectionName:e,x:_t(n.x-t.x),y:_t(n.y-t.y),z:n.z??0}))})),n=Object.fromEntries(Object.entries(this.hyperParameters??{}).filter(([,t])=>void 0!==t).sort(([t],[e])=>t.localeCompare(e))),s=this.connMap?this.initialUnsolvedConnections.map(({connectionName:t})=>({connectionName:t,connectedIds:[...new Set(this.connMap.getIdsConnectedToNet(t)??[])].sort()})):void 0,i={node:{width:_t(this.nodeWithPortPoints.width),height:_t(this.nodeWithPortPoints.height),center:{x:_t(this.nodeWithPortPoints.center.x),y:_t(this.nodeWithPortPoints.center.y)},availableZ:this.nodeWithPortPoints.availableZ?[...this.nodeWithPortPoints.availableZ].sort():void 0},normalizedConnections:e,normalizedHyperParameters:n,minDistBetweenEnteringPoints:_t(this.minDistBetweenEnteringPoints),normalizedConnMap:s},o=`intranode-solver:${j(i)}`,a={};return this.cacheKey=o,this.cacheToSolveSpaceTransform=a,{cacheKey:o,cacheToSolveSpaceTransform:a}}applyCachedSolution(t){t.success?(this.solvedRoutes=Et(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:Et(this.solvedRoutes)};try{this.cacheProvider.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}},wt=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[n,...s]=t,i=this.getHyperParameterCombinations(s);return n.possibleValues.forEach(t=>{i.forEach(n=>{e.push({...n,...t})})}),e}initializeSolvers(){const t=this.getHyperParameterDefs(),e=this.getCombinationDefs()??[t.map(t=>t.name)];this.supervisedSolvers=[];for(const n of e){const e=this.getHyperParameterCombinations(t.filter(t=>n.includes(t.name)));for(const t of e){const e=this.generateSolver(t),n=this.computeG(e);this.supervisedSolvers.push({hyperParameters:t,solver:e,h:0,g:n,f:n})}}}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 n of this.supervisedSolvers??[]){if(n.solver.solved)return n;if(n.solver.failed)continue;const s=n.f;s<t&&(t=s,e=n)}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 zt({A:t,B:e,C:n,D:s,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,n)=>{const s=e.x-t.x,i=e.y-t.y,o=Math.sqrt(s*s+i*i),a=s/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*n,y:t.y-r*n},A_Right:{x:t.x+h*n,y:t.y+c*n},A_Left:{x:t.x-h*n,y:t.y-c*n},B_Opp:{x:e.x+a*n,y:e.y+r*n},B_Right:{x:e.x+h*n,y:e.y+c*n},B_Left:{x:e.x-h*n,y:e.y-c*n}}},l=(t,e)=>{const n=st(t,e.start),s=st(t,e.end),i=st(e.start,e.end);return Math.abs(n+s-i)<1e-4},u=(t,e)=>{const{start:n,end:s}=t,{start:i,end:o}=e;if(l(n,e)||l(s,e)||l(i,t)||l(o,t))return!0;const a=s.x-n.x,r=s.y-n.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-n.x,p=i.y-n.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 n=[];for(let e=0;e<t.length-1;e++)n.push({start:t[e],end:t[e+1]});const s=[];for(let t=0;t<e.length-1;t++)s.push({start:e[t],end:e[t+1]});for(const t of n)for(const e of s)if(u(t,e))return!0;return!1},f=t=>{let e=0;for(let n=1;n<t.length;n++){const s=t[n].x-t[n-1].x,i=t[n].y-t[n-1].y;e+=Math.sqrt(s*s+i*i)}return e},g=(t,e)=>{const{start:n,end:s}=t,i=s.x-n.x,o=s.y-n.y,a=i*i+o*o;if(0===a)return{...n,t:0};const r=Math.max(0,Math.min(1,((e.x-n.x)*i+(e.y-n.y)*o)/a));return{x:n.x+r*i,y:n.y+r*o,t:r}},m=(e,n,s)=>{const i=g(e,n);if(st(i,n)>=s)return i;const o=i.x-n.x,a=i.y-n.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:n.x+s*o/r,y:n.y+s*a/r,t:i.t,isSpecial:!0,specialType:n===t?"A":"B"}}return{x:n.x+s*o/r,y:n.y+s*a/r,t:i.t,isSpecial:!0,specialType:n===t?"A":"B"}},y=d(t,e,a),x=d(t,e,a+r),v=(t,e,n,s,i)=>{const o=t.points;if(o.length<2)return o;const r=n+s,h=[o[0]];for(let t=0;t<o.length-1;t++){const n={start:o[t],end:o[t+1]};if(nt(e,n.start,n.end)<r){const t=g(n,e),s=t.x-e.x,i=t.y-e.y,o=Math.sqrt(s*s+i*i);let c=null;if(o>1e-6)c={x:e.x+r*s/o,y:e.y+r*i/o};else{const t=n.end.x-n.start.x,s=n.end.y-n.start.y,i=Math.sqrt(t*t+s*s);i>1e-6&&(c={x:e.x+r*t/i,y:e.y+r*s/i})}c&&st(n.start,c)>a/10&&h.push(c)}st(h[h.length-1],n.end)>a/10&&h.push(n.end)}if(h.length>1){const t=[h[0]];for(let e=1;e<h.length;e++)st(t[t.length-1],h[e])>a/10&&t.push(h[e]);return t}return h},S=(()=>{const t=[[n,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,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],[s,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,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]],e=[];for(let n=0;n<t.length;n++){const s=t[n],i={start:s[0],end:s[1]},o={start:s[s.length-2],end:s[s.length-1]},a={start:s[3],end:s[4]};u(i,o)||u(i,a)||u(o,a)||e.push({index:n+1,path:s,length:f(s)})}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=st(a,o[2]),h=st(a,o[3]),d=r<h?2:3;(r<st(a,o[1])||h<st(a,o[1]))&&o.splice(1,d-1);const l=o[o.length-1],p=st(l,o[o.length-3]),g=st(l,o[o.length-4]),m=p<g?o.length-3:o.length-4;return(p<st(l,o[o.length-2])||g<st(l,o[o.length-2]))&&o.splice(m+1,o.length-m-2),{index:i.index,path:o,startsAt:o[0]===n?"C":"D",goesTo:o[o.length-1]===n?"C":"D"}})(),M=h>0?((n,s)=>{if(n.length<2)return n;const i=[n[0]];for(let o=0;o<n.length-1;o++){const r={start:n[o],end:n[o+1]},h={x:(r.start.x+r.end.x)/2,y:(r.start.y+r.end.y)/2},c=st(h,t),d=st(h,e);if((c<=a||d<=a)&&Math.abs(c-d)>1e-4){const n=g(r,t),o=g(r,e),h=st(n,t),c=st(o,e)<a,d=h<a?m(r,t,a):null,l=c?m(r,e,a):null;let u=[];if(st(r.start,r.end)>a/2&&s>0)for(let n=1;n<=s;n++){const i=n/(s+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=st(o,t),c=st(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 n=t[t.length-1],s=u[e];st(n,s)>a/10&&t.push(s)}u=t}u.forEach(t=>i.push(t))}i.push(n[o+1])}if(i.length>1){const t=[i[0]];for(let e=1;e<i.length;e++){const n=t[t.length-1],s=i[e];st(n,s)>a/10&&t.push(s)}return t}return i})(S.path,h):S.path;let N=(()=>{if(0===S.path.length)return null;const n=(()=>{const n=c(y.A_Right,y.B_Right),s=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,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,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,x.A_Right,n,e]},{startsAt:"F",goesTo:"B",points:[o,x.B_Right,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Left,s,t]},{startsAt:"F",goesTo:"A",points:[o,x.A_Left,s,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Opp,x.B_Left,s,t]},{startsAt:"F",goesTo:"B",points:[o,x.A_Opp,x.A_Left,s,e]},{startsAt:"F",goesTo:"A",points:[o,x.B_Opp,x.B_Right,n,t]},{startsAt:"F",goesTo:"A",points:[o,x.B_Opp,x.B_Left,s,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Opp,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Opp,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Left,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Right,x.B_Opp,x.B_Left,s,t]},{startsAt:"F",goesTo:"B",points:[o,x.A_Right,x.A_Opp,x.A_Left,s,e]},{startsAt:"F",goesTo:"A",points:[o,x.B_Left,x.B_Opp,x.B_Right,n,t]},{startsAt:"F",goesTo:"A",points:[o,x.B_Right,x.B_Opp,x.B_Left,s,t]},{startsAt:"E",goesTo:"B",points:[i,x.A_Right,x.A_Opp,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[i,x.B_Left,x.B_Opp,x.B_Right,n,t]}].map((t,e)=>({...t,index:e}))})(),s=n.filter(t=>"E"===t.startsAt),a=n.filter(t=>"F"===t.startsAt),r=[],h=[];for(const t of s)if(!p(t.points,S.path)){r.push(t);break}for(const t of a)if(!p(t.points,S.path)){h.push(t);break}return 0===r.length||0===h.length?null:{line1:r[0],line2:h[0]}})();if(N){const n="A"===N.line1.goesTo?e:t,s="A"===N.line2.goesTo?e:t,i=v(N.line1,n,a,r),o=v(N.line2,s,a,r);N={line1:{...N.line1,points:i},line2:{...N.line2,points:o}}}return{jPair:N,optimalPath:{startsAt:S.startsAt,goesTo:S.goesTo,points:M}}}var At=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 this.failed=!0,void(this.error=`Expected 2 routes, but got ${this.routes.length}`);const[e,n]=this.routes;if(!(e.startPort.z===e.endPort.z))return this.failed=!0,void(this.error="Route A must start and end on the same layer");if(!(n.startPort.z===n.endPort.z))return this.failed=!0,void(this.error="Route B must start and end on the same layer");if(!(e.startPort.z===n.startPort.z))return this.failed=!0,void(this.error="Both routes must be on the same layer");0===e.startPort.z?this.escapeLayer=1:this.escapeLayer=0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e)?.push(t)}for(const[e,s]of n.entries())2===s.length&&t.push({startPort:{...s[0],z:s[0].z??0},endPort:{...s[1],z:s[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 Q(t.startPort,t.endPort,e.startPort,e.endPort)}calculateViaPositions(t,e){const n=this.bounds.maxX-this.bounds.minX,s=this.bounds.maxY-this.bounds.minY,i=this.bounds.minX,o=this.bounds.minY,a={width:n-2*this.obstacleMargin-this.viaDiameter,height:s-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)=>st(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((n,s)=>{((t,e)=>{const n=t.x,s=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-n)**2;if(e<0)return[];if(Math.abs(e)<.001){const e=s;return e>=Math.min(a,h)&&e<=Math.max(a,h)?[{x:t,y:e}]:[]}const r=s+Math.sqrt(e),c=s-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*s-n),p=u*u-4*l*(n*n+(d-s)*(d-s)-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},n).forEach(t=>{l(t,0===e?c:h)>=r&&u.push({...t,type:"intersection",circle:e,edge:s})})})}),u.length<2){const t=.8*r;if(d.forEach((e,n)=>{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:n})}),u.length<2){const t=[...d].sort((t,e)=>{const n=Math.min(l(t,h),l(t,c));return Math.min(l(e,h),l(e,c))-n});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 n=l(u[t],u[e]);n>f&&(f=n,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=st(m,t.startPort);return st(y,t.startPort)<x&&([m,y]=[y,m]),{via1:m,via2:y}}trySolveAOverB(t,e,n=!1){const s=n?this.calculateViaPositions(t,e):this.calculateViaPositions(e,t);if(!s)return!1;this.debugViaPositions.push(s);const{via1:i,via2:o}=this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(s));this.debugViaPositions.push({via1:i,via2:o});const{jPair:a,optimalPath:r}=zt({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},n={...t.via2},s=[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 s){const s=st(e,t);if(s<o){const n=(o-s)*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*n,e.y+=r/c*n,a=!0)}const i=st(n,t);if(i<o){const e=(o-i)*h,s=n.x-t.x,a=n.y-t.y,c=Math.sqrt(s*s+a*a);c>1e-6&&(n.x+=s/c*e,n.y+=a/c*e,r=!0)}}const c=st(e,n);if(c<i){const t=(i-c)/2,s=n.x-e.x,o=n.y-e.y,h=Math.sqrt(s*s+o*o);h>1e-6?(e.x-=s/h*t,e.y-=o/h*t,n.x+=s/h*t,n.y+=o/h*t,a=!0,r=!0):(e.x-=t,n.x+=t,a=!0,r=!0)}if(!a&&!r)break}const a=st(e,n);if(a<i){const t=(i-a)/2,s=n.x-e.x,o=n.y-e.y,r=Math.sqrt(s*s+o*o);r>1e-6?(e.x-=s/r*t,e.y-=o/r*t,n.x+=s/r*t,n.y+=o/r*t):(e.x-=t,n.x+=t)}return{via1:e,via2:n}}getMinDistanceBetweenViaCenters(){return this.viaDiameter+this.traceThickness+2*this.obstacleMargin}moveViasAsCloseAsPossible(t){const{via1:e,via2:n}=t,s=this.getMinDistanceBetweenViaCenters(),i=st(e,n);if(i<=s)return t;const o=n.x-e.x,a=n.y-e.y,r=Math.sqrt(o*o+a*a),h=o/r,c=a/r,d=(e.x,n.x,e.y,n.y,(i-s)/2);return{via1:{x:e.x+h*d,y:e.y+c*d},via2:{x:n.x-h*d,y:n.y-c*d}}}handleRoutesDontCross(){const[t,e]=this.routes,n={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:[]},s={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(n,s),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.error="All crossover strategies failed"):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,n]of[["Route A",this.routes[0]],["Route B",this.routes[1]]])t.points.push({x:n.startPort.x,y:n.startPort.y,label:`${e}\n${n.connectionName} start`,color:"orange"}),t.points.push({x:n.endPort.x,y:n.endPort.y,label:`${e}\n${n.connectionName} end`,color:"orange"}),t.lines.push({points:[n.startPort,n.endPort],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e}\n${n.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via1:n,via2:s}=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:n,radius:this.viaDiameter/2,fill:o,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via A (attempt ${e+1})`}),t.circles.push({center:s,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:n,radius:a,stroke:o,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 1 Safety Margin (attempt ${e+1})`}),t.circles.push({center:s,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,n,s,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 n=this.solvedRoutes[e],s=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<n.route.length-1;e++){const i=n.route[e],o=n.route[e+1];t.lines.push({points:[i,o],strokeColor:s,strokeDash:1===i.z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${i.z}`}),i._label&&t.points.push({x:i.x,y:i.y,label:i._label})}for(const e of n.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 Rt(t,e,n,s,i){const o={x:(t.x+e.x+n.x)/3,y:(t.y+e.y+n.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,n),d=o.x>=i.minX&&o.x<=i.maxX&&o.y>=i.minY&&o.y<=i.maxY;return r>=s&&h>=s&&c>=s&&d};if(r(o))return o;const h=(t,e,n)=>{const s=t.x-e.x,i=t.y-e.y,o=Math.sqrt(s*s+i*i);return o<1e-10?{x:e.x+n,y:e.y}:{x:e.x+s/o*n,y:e.y+i/o*n}},c=(t,e,n)=>{const s=e.x-t.x,i=e.y-t.y,o=Math.sqrt(s*s+i*i);if(o>2*n-1e-10||o<1e-10)return[];const r=o*o/(2*o),h=Math.sqrt(Math.max(0,n*n-r*r)),c=t.x+s*r/o,d=t.y+i*r/o,l={x:c+h*i/o,y:d-h*s/o},u={x:c-h*i/o,y:d+h*s/o},p=[],f=1e-6;return Math.abs(a(l,t)-n)<f&&Math.abs(a(l,e)-n)<f&&p.push(l),Math.abs(a(u,t)-n)<f&&Math.abs(a(u,e)-n)<f&&p.push(u),p},d=[h(o,t,s),h(o,e,s),h(o,n,s),...c(t,e,s),...c(e,n,s),...c(n,t,s)],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 n={x:t,y:e};if(r(n)){const t=a(n,o);t<p&&(p=t,u=n)}}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,s-a(o,t))+Math.max(0,s-a(o,e))+Math.max(0,s-a(o,n));i<m&&(m=i,y=o)}return y}function Ot(t,e,n){const s=Dt(e,t,n.center,n.radius),i=Dt(t,e,n.center,n.radius),o=Lt(s,e),a=Lt(t,i),r=1e-6;let h;if(o>r&&a>r){h={x:(s.x+i.x)/2,y:(s.y+i.y)/2};const o=Lt(s,h),a=Lt(i,h);if(Math.abs(o-a)>.5*Math.min(o,a)){const n=Lt(t,s),o=Lt(e,i),a=n+o;if(a>r){const t=o/a,e=n/a;h={x:s.x*t+i.x*e,y:s.y*t+i.y*e}}}const c=Lt(h,n.center);if(c<1.05*n.radius){const t={x:(h.x-n.center.x)/c,y:(h.y-n.center.y)/c};h={x:n.center.x+t.x*n.radius*1.2,y:n.center.y+t.y*n.radius*1.2}}}else{const s={x:(t.x+e.x)/2,y:(t.y+e.y)/2},i=Lt(s,n.center);if(i<1.1*n.radius){const t={x:(s.x-n.center.x)/i,y:(s.y-n.center.y)/i};h={x:n.center.x+t.x*n.radius*1.2,y:n.center.y+t.y*n.radius*1.2}}else h=s}return{B:s,D:i,E:h}}function Dt(t,e,n,s){const i=[n.x-t.x,n.y-t.y],o=Math.sqrt(i[0]*i[0]+i[1]*i[1]);if(o<=s){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:n.x+s,y:n.y}:{x:n.x+i[0]/o*s,y:n.y+i[1]/o*s}}const a=[i[0]/o,i[1]/o];return{x:n.x-a[0]*s,y:n.y-a[1]*s}}const a=[e.x-t.x,e.y-t.y],r=Math.sqrt(o*o-s*s),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=s/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 Lt(t,e){const n=e.x-t.x,s=e.y-t.y;return Math.sqrt(n*n+s*s)}var Ft=1e-9;function $t(t,e,n,s="cw"){const i=kt(t,n),o=kt(e,n);return Math.abs(o-i)<Ft?{left:0,top:0,right:0,bottom:0}:function(t,e,n,s){const i=n.maxX-n.minX,o=n.maxY-n.minY;if(i<Ft&&o<Ft)return{left:0,top:0,right:0,bottom:0};const a=2*(i+o);if(a<Ft)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,n,s,i)=>{const o=e>2*Math.PI-Ft?2*Math.PI:e;if(o<=t+Ft)return 0;if(i){const e=Math.max(t,n),i=Math.min(o,2*Math.PI),a=Math.max(0,i-e),r=Math.max(t,0),h=Math.min(o,s);return a+Math.max(0,h-r)}{const e=Math.max(t,n),i=Math.min(o,s);return Math.max(0,i-e)}};for(const n of l){const i=n.end-n.start;if(i<Ft||n.length<Ft)continue;let o=0;if("cw"===s){const s=t>e+Ft;o=p(n.start,n.end,t,e,s)}else{const s=e>t+Ft;o=p(n.start,n.end,e,t,s)}if(o>Ft){const t=o/i;u[n.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,n,s)}function kt(t,e){const n=e.maxX-e.minX,s=e.maxY-e.minY;if(n<Ft&&s<Ft)return 0;const i=2*(n+s);if(i<Ft)return 0;let o=0;if(Math.abs(t.y-e.maxY)<Ft&&t.x>=e.minX-Ft&&t.x<=e.maxX+Ft)o=Math.max(0,Math.min(n,t.x-e.minX));else if(Math.abs(t.x-e.maxX)<Ft&&t.y>=e.minY-Ft&&t.y<=e.maxY+Ft)o=n+Math.max(0,Math.min(s,e.maxY-t.y));else if(Math.abs(t.y-e.minY)<Ft&&t.x>=e.minX-Ft&&t.x<=e.maxX+Ft)o=n+s+Math.max(0,Math.min(n,e.maxX-t.x));else{if(!(Math.abs(t.x-e.minX)<Ft&&t.y>=e.minY-Ft&&t.y<=e.maxY+Ft))throw new Error(`Point (${t.x}, ${t.y}) does not lie on the boundary defined by ${JSON.stringify(e)}`);o=n+s+n+Math.max(0,Math.min(s,t.y-e.minY))}return o=Math.max(0,Math.min(i,o)),i>Ft?o/i*(2*Math.PI):0}function Xt(t,e,n,s){return function({angleA:t,angleB:e,angleC:n}){const s=Math.cos(t),i=Math.sin(t),o=Math.cos(e),a=Math.sin(e),r=Math.cos(n);return(o-s)*(Math.sin(n)-i)-(a-i)*(r-s)<0?"ccw":"cw"}({angleA:kt(t,s),angleB:kt(e,s),angleC:kt(n,s)})}var Yt=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 this.failed=!0,void(this.error=`Expected 2 routes, but got ${this.routes.length}`);const[e,n]=this.routes,s=e.A.z!==e.B.z,i=n.A.z!==n.B.z;return s&&i||!s&&!i?(this.failed=!0,void(this.error="Exactly one route must have a layer transition")):void 0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e)?.push(t)}for(const[e,s]of n.entries())2===s.length&&t.push({A:{...s[0],z:s[0].z??0},B:{...s[1],z:s[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 Q(t.A,t.B,e.A,e.B)}calculateViaPosition(t,e){const n=e.A.z,s=t.A.z!==n?t.A:t.B,i=2*this.obstacleMargin+this.viaDiameter/2+this.traceThickness,o=this.obstacleMargin+this.viaDiameter/2,a=e.A,r=s,h=e.B,c=Xt(a,r,h,this.bounds),d=function(t,e,n,s,i){const o=$t(t,e,s,i),a=$t(e,n,s,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])<Ft&&(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),Rt(a,r,h,i,l)}createTransitionRoute(t,e,n,s){return{connectionName:s,route:[{x:t.x,y:t.y,z:t.z??0},{x:n.x,y:n.y,z:t.z??0},{x:n.x,y:n.y,z:e.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[n]}}createFlatRoute(t,e,n,s,i,o){s.z,t.z;const a=this.viaDiameter/2+this.traceThickness/2+this.obstacleMargin,r=((t,e,n,s)=>{const i=n.x-t.x,o=n.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:n.x-i*s,y:n.y-o*s})})(n,this.viaDiameter,s.z!==t.z?s:i,this.traceThickness),h={center:{x:n.x,y:n.y},radius:a},c=Ot(t,r,h).E,d=Ot(r,e,h).E,l=Ot(t,c,h).E,u=Ot(c,r,h).E,p=Ot(r,d,h).E,f=Ot(d,e,h).E,g=Ot(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,n=t.A.z!==t.B.z,s=n?t:e,i=n?e:t,o=this.calculateViaPosition(s,i);if(!o)return!1;this.debugViaPositions.push({via:o});const a=this.createTransitionRoute(s.A,s.B,o,s.connectionName),r=this.createFlatRoute(i.A,i.B,o,s.A,s.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,this.error="Failed to find a valid via position and route path")}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:n}=this.debugViaPositions[e];t.circles.push({center:n,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 s=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:n,radius:s,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 n=this.solvedRoutes[e],s=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<n.route.length-1;e++){const i=n.route[e],o=n.route[e+1];t.lines.push({points:[i,o],strokeColor:s,strokeDash:i.z!==n.route[0].z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${i.z}`})}for(const e of n.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}},Bt=(t,e)=>{const n={};return t.portPoints.forEach((e,s)=>{n[e.connectionName]=`hsl(${360*s/t.portPoints.length}, 100%, 50%)`}),n},Ht=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:n,viaDiameter:s}){super(),this.MAX_ITERATIONS=1e5,this.colorMap=e??Bt(t),this.maxViaCount=5,this.bounds=It(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=n??{SHUFFLE_SEED:0},this.viaDiameter=s??.6,this.unprocessedConnections=Array.from(this.portPairMap.keys()).sort(),n?.SHUFFLE_SEED&&(this.unprocessedConnections=Pt(this.unprocessedConnections,n.SHUFFLE_SEED));for(const[t,{start:e,end:n}]of this.portPairMap.entries())if(e.z===n.z){const s=Math.abs(e.x-n.x)<1e-9,i=Math.abs(e.y-n.y)<1e-9;s||i?this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),this._padByPlaceholderWallBuffer(n),n]):this.placeholderPaths.set(t,[e,n])}else{const s=(e.x+n.x)/2,i=(e.y+n.y)/2,o=this._padByPlaceholderWallBuffer({x:s,y:i,z:e.z}),a=this._padByPlaceholderWallBuffer({x:s,y:i,z:n.z});this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),o,a,this._padByPlaceholderWallBuffer(n),n])}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:J(t.x,this.bounds.minX+this.NEW_HEAD_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.NEW_HEAD_WALL_BUFFER_DISTANCE),y:J(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:J(t.x,this.bounds.minX+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),y:J(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 n=null,s=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=it(e[0],e[1],o[0],o[1]);if(a){const t=st(this.currentHead,a);if(t<1e-6)continue;(!n||t<n.dist)&&(n={point:a,dist:t},s=o[0].z)}}};i(this.completedPaths),i(this.placeholderPaths);const o=this.currentHead.z!==t.z;if((n||o)&&(this.currentViaCount++,this.currentViaCount>=this.maxViaCount))return this.failed=!0,void(this.error=`Exceeded max via count of ${this.maxViaCount}`);if(n){let t;const e=n.dist;if(e<=this.VIA_INTERSECTION_BUFFER_DISTANCE+1e-6)t=ot(this.currentHead,n.point);else{const s=n.point,i=s.x-this.currentHead.x,o=s.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!==s);if(void 0===i)return this.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 n=st(this.currentHead,t);if(n<this.VIA_INTERSECTION_BUFFER_DISTANCE)e=ot(this.currentHead,t);else{const s=t.x-this.currentHead.x,i=t.y-this.currentHead.y,o=(n-this.VIA_INTERSECTION_BUFFER_DISTANCE)/n;e={x:this.currentHead.x+s*o,y:this.currentHead.y+i*o}}const s=t.z,i={...e,z:this.currentHead.z},o={...e,z:s};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:n,end:s}]of this.portPairMap.entries()){const i=this.colorMap[e]??"black";t.points.push({x:n.x,y:n.y,color:i,label:`Port: ${e} Start (z${n.z})`}),t.points.push({x:s.x,y:s.y,color:i,label:`Port: ${e} End (z${s.z})`})}const n=(n,s)=>{for(const[i,o]of n.entries()){const n=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:H(n,.5),label:`${s}: ${i} Via (z${a.z}->z${r.z})`}):t.lines.push({points:[a,r],strokeColor:H(n,.5),strokeDash:0===a.z?void 0:[.1,.1],strokeWidth:.1,label:`${s}: ${i} (z${a.z})`})}}};if(n(this.placeholderPaths,"Placeholder"),n(this.completedPaths,"Completed"),this.currentPath&&this.currentPath.length>0){const n=e[this.currentConnectionName]??"orange";for(let e=0;e<this.currentPath.length-1;e++){const s=this.currentPath[e],i=this.currentPath[e+1];s.x===i.x&&s.y===i.y&&s.z!==i.z?t.circles.push({center:{x:s.x,y:s.y},radius:this.viaDiameter/2,fill:H(n,.5),label:`Current: ${this.currentConnectionName} Via (z${s.z}->z${i.z})`}):t.lines.push({points:[s,i],strokeColor:H(n,.5),strokeWidth:.15,strokeDash:"2,2",label:`Current: ${this.currentConnectionName} (z${s.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}},jt=t=>{let e=0,n=[];const s=[];let i=0;for(const e of t.portPoints){if(n.some(t=>t.connectionName===e.connectionName))continue;if(s.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 n of t.portPoints)e.connectionName===n.connectionName&&(e.x===n.x&&e.y===n.y||o.points.push({x:n.x,y:n.y,z:n.z}));o.points.some(t=>t.z!==o.z)?(i++,s.push(o)):n.push(o)}n=n.filter(t=>t.points.length>1);for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++){const i=n[t],o=n[s];i.z===o.z&&Q(i.points[0],i.points[1],o.points[0],o.points[1])&&e++}let o=0;for(let t=0;t<s.length;t++)for(let e=t+1;e<s.length;e++){const n=s[t],i=s[e];Q(n.points[0],n.points[1],i.points[0],i.points[1])&&o++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:i,numTransitionPairCrossings:o,numTransitions:s.length}},Zt=1e-9;function Wt(t,e,n=Zt){return Math.abs(t-e)<n}function Vt(t,e,n,s){return t*s-e*n}function Ut(t,e,n,s){const i={x:e.x-t.x,y:e.y-t.y},o={x:s.x-n.x,y:s.y-n.y},a=Vt(i.x,i.y,o.x,o.y);if(Wt(a,0))return null;const r={x:n.x-t.x,y:n.y-t.y},h=Vt(r.x,r.y,o.x,o.y)/a,c=Vt(r.x,r.y,i.x,i.y)/a;return h<-Zt||h>1+Zt||c<-Zt||c>1+Zt?null:{x:t.x+h*i.x,y:t.y+h*i.y}}function Gt(t){let e=0;for(let n=0,s=t.length;n<s;++n){const i=(n+1)%s;e+=t[n].x*t[i].y-t[i].x*t[n].y}return.5*e}function qt(t){let e=0,n=0,s=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,n+=(t[i].x+t[a].x)*r,s+=(t[i].y+t[a].y)*r}return e*=.5,Wt(e,0)?null:(n/=6*e,s/=6*e,{x:n,y:s})}var Kt=class{x;y;out;connectionNames;constructor(t,e){this.x=t,this.y=e,this.out=[],this.connectionNames=new Set}},Jt=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 Qt(t,e){const n=[...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}}]],s=n.map(()=>[]);for(let t=0;t<n.length;++t){const e=n[t];s[t].push(e.start,e.end)}for(let t=0;t<n.length;++t)for(let e=t+1;e<n.length;++e){const i=Ut(n[t].start,n[t].end,n[e].start,n[e].end);i&&(s[t].push(i),s[e].push(i))}const i=new Map,o=[];function a(t){const e=function(t,e=Zt){return`${Math.round(t.x/e)}:${Math.round(t.y/e)}`}(t);if(!i.has(e)){const n=o.length;return i.set(e,n),o.push(new Kt(t.x,t.y)),n}return i.get(e)}const r=[];for(let t=0;t<n.length;++t){const e=n[t],i=s[t].slice();i.sort((t,n)=>{const s=e.end.x-e.start.x,i=e.end.y-e.start.y;return(Wt(Math.abs(s),0)?(t.y-e.start.y)/i:(t.x-e.start.x)/s)-(Wt(Math.abs(s),0)?(n.y-e.start.y)/i:(n.x-e.start.x)/s)});for(let t=0;t<i.length-1;++t){const n=i[t],s=i[t+1],h=a(n),c=a(s);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 n=new Jt(t,e),s=new Jt(e,t);n.twin=h.length+1,s.twin=h.length;const i=h.length;h.push(n,s),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,n)=>{const s=h[t],i=h[n],a=o[s.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 n=e.out.length;for(let t=0;t<n;++t){const s=e.out[t],i=e.out[(t-1+n)%n],o=h[s];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 n=[],s=[];do{if(null===e)break;const t=h[e];t.visited=!0,n.push(o[t.orig]),s.push(e),e=t.next}while(null!==e&&e!==t&&!h[e].visited);if(n.length<3)continue;if(Gt(n)>Zt){const t=qt(n);t&&(c.push(t),d.push({vertices:n.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 te(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 n=[];return function t(s,i,o){o!==e?(s[o]=0,t(s,i,o+1),i>0&&(s[o]=1,t(s,i-1,o+1))):0===i&&n.push([...s])}(Array(e).fill(0),t,0),n}var ee=t=>{if(0===t.length)return[[]];const e=[];for(let n=0;n<t.length;n++){const s=t[n],i=[...t.slice(0,n),...t.slice(n+1)],o=ee(i);for(const t of o)e.push([s,...t])}return e};var ne=t=>{const{start:e,end:n,segmentsPerPolyline:s,viaPositions:i,viaCount:o,availableZ:a}=t,r=function(t,e){const n=new Array(t).fill(0);if(0===e)return n;if(e===t)return n.fill(1);if(e<=t/2){const s=Math.floor(t/e),i=Math.floor((t-(s*(e-1)+1))/2);for(let t=0;t<e;t++)n[i+t*s]=1}else{const s=t-e,i=Math.floor(t/s),o=Math.floor((t-(i*(s-1)+1))/2);n.fill(1);for(let t=0;t<s;t++)n[o+t*i]=0}return n}(s,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=n,s=h.length;for(let n=t+1;n<h.length;n++)if(h[n]){e=h[n],s=n;break}const i=s-t,o=e.x-u.x,a=e.y-u.y;for(let e=1/(i+1),n=0;t+n!==s;e+=1/(i+1),n++)h[t+n]={x:u.x+o*e,y:u.y+a*e,z1:u.z2,z2:u.z2}}return h},se=1e-9;function ie(t,e){return Math.abs(t-e)<se}function oe(t){return`${Math.round(t.x/se)}:${Math.round(t.y/se)}`}function ae(t,e,n,s){return t*s-e*n}function re(t,e,n,s){const i={x:e.x-t.x,y:e.y-t.y},o={x:s.x-n.x,y:s.y-n.y},a=ae(i.x,i.y,o.x,o.y),r={x:n.x-t.x,y:n.y-t.y};if(ie(a,0))return null;const h=ae(r.x,r.y,o.x,o.y)/a,c=ae(r.x,r.y,i.x,i.y)/a;return h>=-1e-9&&h<=1+se&&c>=-1e-9&&c<=1+se?{x:t.x+h*i.x,y:t.y+h*i.y}:null}function he(t,e,n){return ie(Math.hypot(t.x-e.x,t.y-e.y)+Math.hypot(t.x-n.x,t.y-n.y),Math.hypot(e.x-n.x,e.y-n.y))}function ce(t,e){const n=[],s=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(n.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=oe(o);s.has(t)||s.set(t,{point:o,connectionName:e.connectionName})}}const i=t[t.length-1];if(i.z1!==i.z2){const t=oe(i);s.has(t)||s.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}];n.push(...i);const o=new Map;let a=0;function r(t,e){const n=oe(t);let i=o.get(n);if(!i){const e=s.has(n);i={id:a++,x:t.x,y:t.y,isVia:e,connectionNames:new Set,outgoingEdges:[]},o.set(n,i),e&&s.get(n)&&i.connectionNames.add(s.get(n).connectionName)}return e&&i.connectionNames.add(e),i}for(const t of n)r(t.start,t.connectionName),r(t.end,t.connectionName);const h=new Map;for(const t of n)h.set(t,[]);for(let t=0;t<n.length;t++)for(let e=t+1;e<n.length;e++){if(n[t].layer!==n[e].layer)continue;const s=re(n[t].start,n[t].end,n[e].start,n[e].end);s&&(r(s),he(s,n[t].start,n[t].end)&&h.get(n[t]).push(s),he(s,n[e].start,n[e].end)&&h.get(n[e]).push(s))}const c=[];let d=0;for(const t of n){const e=[t.start,...h.get(t),t.end];e.sort((e,n)=>{const s=t.end.x-t.start.x,i=t.end.y-t.start.y;return Math.abs(s)>Math.abs(i)?(e.x-t.start.x)/s-(n.x-t.start.x)/s:Math.abs(i)<se?0:(e.y-t.start.y)/i-(n.y-t.start.y)/i});const n=[];if(e.length>0){n.push(e[0]);for(let t=1;t<e.length;t++)ie(e[t].x,e[t-1].x)&&ie(e[t].y,e[t-1].y)||n.push(e[t])}for(let e=0;e<n.length-1;e++){const s=n[e],i=n[e+1],o=r(s,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,n)=>{const s=e.twin.origin,i=n.twin.origin;return Math.atan2(s.y-t.y,s.x-t.x)-Math.atan2(i.y-t.y,i.x-t.x)});const e=t.outgoingEdges.length;for(let n=0;n<e;n++){const s=t.outgoingEdges[n],i=t.outgoingEdges[(n-1+e)%e];s.twin&&(s.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 n=t;const s=[],i=[],o=new Set;let a=0;do{if(!n||n.visited){console.warn("Face traversal encountered visited edge or null, breaking loop.",e.id),s.length=0;break}n.visited=!0,n.face=e,s.push(n),i.push(n.origin),null!==n.connectionName&&o.add(n.connectionName);const t=n.origin,r=n.twin.origin;a+=t.x*r.y-r.x*t.y,n=n.next}while(n!==t&&null!==n);if(n===t){if(a=.5*Math.abs(a),a>f&&(f=a,p&&(p.isOuterFace=!1),p=e,e.isOuterFace=!0),!e.isOuterFace&&s.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 de=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??Bt(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,n=(this.viaDiameter+2*this.obstacleMargin+this.traceWidth/2)**2,s=new Set(this.nodeWithPortPoints.portPoints.map(t=>t.connectionName)).size;this.uniqueConnections=s;const{numSameLayerCrossings:i,numTransitions:o}=jt(this.nodeWithPortPoints);if(this.minViaCount=2*i+o,this.maxViaCount=Math.min(Math.floor(e/n),Math.ceil(1.5*s)),this.minViaCount>this.SEGMENTS_PER_POLYLINE*(s/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=[],n=[],s=[];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]],n=e[0].z2;a.has(n)||a.set(n,[]),a.get(n).push(e)}n.push(a),s.push(o.filter(t=>t.z1!==t.z2))}for(let i=0;i<t.length;i++){const o=n[i],a=s[i];for(let r=i+1;r<t.length;r++){if(this.connMap?.areIdsConnected(t[i].connectionName,t[r].connectionName))continue;const h=n[r],c=s[r];let d=1;for(const t of this.availableZ){const e=o.get(t)??[],n=h.get(t)??[];for(const t of e)for(const e of n)d=Math.min(d,ft(t[0],t[1],e[0],e[1])-this.traceWidth);for(const t of a)for(const e of n)d=Math.min(d,nt(t,e[0],e[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of c)for(const n of e)d=Math.min(d,nt(t,n[0],n[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of a)for(const e of c)d=Math.min(d,st(t,e)-this.viaDiameter)}e.push(d)}}return e}insertCandidate(t){let e=0,n=this.candidates.length-1;for(;e<=n;){const s=Math.floor((e+n)/2);this.candidates[s].f<t.f?e=s+1:n=s-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,n]of t.entries())null===n.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()),n=((t,e,n,s)=>{const i=[];for(const[,n]of t){const t=n.start.z1!==n.end.z1,s=[];for(let n=0;n<=e;n++){const e=n%2!=0;t&&e?s.push(n):t||e||s.push(n)}i.push(s)}if(0===i.length)return[[]];let o=(t=>{if(!t||0===t.length)return[[]];let e=[[]];for(const n of t){const t=[];for(const s of e)for(const e of n)t.push([...s,e]);e=t}return e})(i).filter(t=>{for(let e=0;e<t.length;e++)if(t.reduce((t,e)=>t+e,0)<s)return!1;return!0});return o=o.filter(e=>{for(let n=0;n<t.length;n++){const[,s]=t[n];if(s.start.z1!==s.start.z2&&0===e[n])return!1}return!0}),o=o.filter(e=>{for(let n=0;n<t.length;n++){const[,s]=t[n];if(t[n][1].start.z1===t[n][1].start.z2)for(let i=n+1;i<t.length;i++){if(t[i][1].start.z1!==t[i][1].start.z2)continue;const[,o]=t[i];if(s.start.z1===s.end.z1&&o.start.z1===o.end.z1&&s.start.z1===o.start.z1&&Q(s.start,s.end,o.start,o.end)&&e[n]+e[i]<2)return!1}}return!0}),o=o.filter(t=>!(t.reduce((t,e)=>t+e,0)>n)),o})(e,this.SEGMENTS_PER_POLYLINE,this.maxViaCount,this.minViaCount),s=(t=>{const{bounds:e,portPairsEntries:n,viaCountVariants:s}=t,{centroids:i}=Qt(e,n.map(([t,e])=>e)),o=[];for(const t of s){const n=t.reduce((t,e)=>t+e,0);let s=i;if(i.length<n){s=[];const t=Math.ceil(Math.sqrt(n)),i=t;for(let n=0;n<t;n++)for(let o=0;o<i;o++)s.push({x:e.minX+(o+1)/(i+1)*(e.maxX-e.minX),y:e.minY+(n+1)/(t+1)*(e.maxY-e.minY)})}const a=te(n,s.length);for(const e of a){const n=[];for(let t=0;t<e.length;t++)1===e[t]&&n.push(s[t]);o.push({viaPositions:n,viaCountVariant:t})}}return o})({portPairsEntries:e,viaCountVariants:n,bounds:this.bounds}),i=[];for(const{viaCountVariant:t,viaPositions:e}of s){const n=ee(e);for(const e of n)i.push({viaCountVariant:t,viaPositions:e})}for(const{viaPositions:t,viaCountVariant:n}of i){const s=[];let i=0;for(let o=0;o<e.length;o++){const[a,r]=e[o],h=n[o],c=t.slice(i,i+h),d=ne({start:r.start,end:r.end,segmentsPerPolyline:this.SEGMENTS_PER_POLYLINE,viaPositions:c,viaCount:h,availableZ:this.availableZ});i+=h,s.push({connectionName:a,start:r.start,end:r.end,mPoints:d})}if(ce(s,this.bounds))continue;const o=this.computeMinGapBtwPolyLines(s),a=this.computeH({minGaps:o,forces:[]}),r={polyLines:s,g:0,h:a,f:a,viaCount:n.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 n of t.forces??[])for(const t of n)for(const n of t.values())e+=n.fx*n.fx+n.fy*n.fy;return e}getNeighbors(t){const{polyLines:e}=t,n=e.length,s=.02,i=.008,o=1e-6,a=Array.from({length:n},(t,n)=>Array.from({length:e[n].mPoints.length},()=>new Map)),r=(t,n,s,i,o)=>{if(n>0&&n<e[t].mPoints.length+1){const e=n-1,r=a[t][e],h=r.get(s)||{fx:0,fy:0};r.set(s,{fx:h.fx+i,fy:h.fy+o})}};for(let t=0;t<n;t++)for(let i=t+1;i<n;i++){const n=e[t],a=e[i],h=[n.start,...n.mPoints,n.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 n of u)if(e.layer===n.layer){if(ft(e.p1,e.p2,n.p1,n.p2)<o)continue;const s={x:(e.p1.x+e.p2.x)/2,y:(e.p1.y+e.p2.y)/2},a={x:(n.p1.x+n.p2.x)/2,y:(n.p1.y+n.p2.y)/2},h=s.x-a.x,c=s.y-a.y,d=h*h+c*c;if(d>o){const s=Math.sqrt(d),a=(Math.exp(-6*s),`seg:${i}:${n.p1Idx}:${n.p2Idx}`),h=`seg:${t}:${e.p1Idx}:${e.p2Idx}`,c=(t,e,n,s,i,a,h)=>{const c=mt(t,n.p1,n.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(s,e,a,g,m),r(i,n.p1Idx,h,-g/2,-m/2),r(i,n.p2Idx,h,-g/2,-m/2)};c(e.p1,e.p1Idx,n,t,i,a,h),c(e.p2,e.p2Idx,n,t,i,a,h),c(n.p1,n.p1Idx,e,i,t,h,a),c(n.p2,n.p2Idx,e,i,t,h,a)}}for(const e of l)for(const n of u)if(e.layers.includes(n.layer)){const a=mt(e.point,n.p1,n.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*s*Math.exp(-6*u),f=h/a*p,g=c/a*p,m=`seg:${i}:${n.p1Idx}:${n.p2Idx}`;r(t,e.index,m,f,g);const y=`via:${t}:${e.index}`;r(i,n.p1Idx,y,-f/2,-g/2),r(i,n.p2Idx,y,-f/2,-g/2)}}for(const e of p)for(const n of d)if(e.layers.includes(n.layer)){const a=mt(e.point,n.p1,n.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*s*Math.exp(-6*u),f=h/a*p,g=c/a*p,m=`seg:${t}:${n.p1Idx}:${n.p2Idx}`;r(i,e.index,m,f,g);const y=`via:${i}:${e.index}`;r(t,n.p1Idx,y,-f/2,-g/2),r(t,n.p2Idx,y,-f/2,-g/2)}}for(const e of l)for(const n of p){if(e.layers.filter(t=>n.layers.includes(t)).length>0){const a=e.point.x-n.point.x,h=e.point.y-n.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*s*Math.exp(-6*u),f=a/d*p,g=h/d*p,m=`via:${i}:${n.index}`,y=`via:${t}:${e.index}`;r(t,e.index,m,f,g),r(i,n.index,y,-f,-g)}}}}for(let t=0;t<n;t++){const n=e[t],i=[n.start,...n.mPoints,n.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 n=e+1;n<a.length;n++){const i=a[e],h=a[n],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 n=2,a=e;e<this.viaDiameter?(n*=4,a=Math.max(o,e)):a=Math.max(o,e-this.viaDiameter);const u=n*s*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<n;t++)for(let e=0;e<h[t].mPoints.length;e++){const n=h[t].mPoints[e],s=a[t][e],r={fx:0,fy:0};for(const t of s.values())r.fx+=t.fx,r.fy+=t.fy;const d=n.z1!==n.z2;let l=n.x+r.fx,u=n.y+r.fy;if(d){const t=this.viaDiameter/2;let e=0,s=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-n.x,f=n.x-(h-t),g=c+t-n.y,m=n.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?s=i*(Math.exp(g/(2*this.obstacleMargin))-1):m>0&&(s=-.008*(Math.exp(m/(2*this.obstacleMargin))-1)),r.fx+=e,r.fy+=s,l=n.x+r.fx,u=n.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(n.x-l)>o||Math.abs(n.y-u)>o)&&(n.x=l,n.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),n=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,n=0)=>t.x>=e.minX+n&&t.x<=e.maxX-n&&t.y>=e.minY+n&&t.y<=e.maxY-n)(t,this.bounds,e)}));return e&&n}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),n=.1*(this.bounds.maxY-this.bounds.minY);t.rects.push({center:{x:this.bounds.maxX+.6*e,y:this.bounds.maxY+.6*n},width:e,height:n,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((n,s)=>{const i=this.colorMap[n.connectionName]??"purple",o=[n.start,...n.mPoints,n.end];for(let e=0;e<o.length-1;e++){const s=o[e],a=o[e+1],r=s.z2,h=0===r,c=h?i:H(i,.5);t.lines.push({points:[s,a],strokeColor:c,strokeWidth:this.traceWidth,strokeDash:h?void 0:[.15,.15],label:`${n.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?.[s]?.[i];if(o&&o.size>0){const s={fx:0,fy:0};o.forEach((o,r)=>{if(s.fx+=o.fx,s.fy+=o.fy,Math.abs(o.fx)>1e-6||Math.abs(o.fy)>1e-6){const s=r.split(":"),h=s[0],c=parseInt(s[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(s[2],10)}`}else if("seg"===h){f+=` Seg ${parseInt(s[2],10)}-${parseInt(s[3],10)}`}t.lines.push({points:[a,p],strokeColor:l,strokeWidth:.02,strokeDash:"2,2",label:`Force by ${f} on ${n.connectionName} mPoint ${i}`})}}),(Math.abs(s.fx)>1e-6||Math.abs(s.fy)>1e-6)&&(u=`\nNet Force: (${s.fx.toFixed(3)}, ${s.fy.toFixed(3)})`)}}if(h)l=`Via (${n.connectionName} z=${a.z1} -> z=${a.z2})${u}`,t.circles.push({center:a,radius:this.viaDiameter/2,fill:H(i,.5),label:l});else if(d){const e=0===c?i:H(i,.5);l=`mPoint (${n.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 n=[],s=[],i=[e.start,...e.mPoints,e.end];for(let t=0;t<i.length;t++){const e=i[t];n.push({x:e.x,y:e.y,z:e.z1}),e.z1!==e.z2&&(s.push({x:e.x,y:e.y}),n.push({x:e.x,y:e.y,z:e.z2}))}t.push({connectionName:e.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:n,vias:s})}this.solvedRoutes=t}},le=class extends de{computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){const{minGaps:e}=t;let n=0;for(const t of e)t<0&&(n+=this.obstacleMargin),t<this.obstacleMargin&&(n+=this.obstacleMargin-t);return.011*n}_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,n=0;const s=void 0===t.magForceApplied?1:10;for(let i=0;i<s;i++){const s=this.applyForcesToPolyLines(t.polyLines);if(n+=s.magForceApplied,e=s.lastStepMoved,!s.lastStepMoved)break}if(t.magForceApplied=n,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 n=t.length,s=.02,i=.008,o=1e-6,a=Array.from({length:n},(e,n)=>Array.from({length:t[n].mPoints.length},()=>({fx:0,fy:0}))),r=(e,n,s,i)=>{if(n>0&&n<t[e].mPoints.length+1){const t=n-1;a[e][t].fx+=s,a[e][t].fy+=i}},h=(t,e,n,s,i)=>{const a=mt(t,n.p1,n.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(s,e,p,f),r(i,n.p1Idx,-p/2,-f/2),r(i,n.p2Idx,-p/2,-f/2)};for(let e=0;e<n;e++)for(let i=e+1;i<n;i++){const n=t[e],a=t[i],c=[n.start,...n.mPoints,n.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 n of p)if(t.layer===n.layer){ft(t.p1,t.p2,n.p1,n.p2);h(t.p1,t.p1Idx,n,e,i),h(t.p2,t.p2Idx,n,e,i),h(n.p1,n.p1Idx,t,i,e),h(n.p2,n.p2Idx,t,i,e)}for(const t of u)for(const n of p)if(t.layers.includes(n.layer)){const a=mt(t.point,n.p1,n.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*s*Math.exp(-6*u),f=h/a*p,g=c/a*p;r(e,t.index,f,g),r(i,n.p1Idx,-f/2,-g/2),r(i,n.p2Idx,-f/2,-g/2)}}for(const t of f)for(const n of l)if(t.layers.includes(n.layer)){const a=mt(t.point,n.p1,n.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*s*Math.exp(-6*u),f=h/a*p,g=c/a*p;r(i,t.index,f,g),r(e,n.p1Idx,-f/2,-g/2),r(e,n.p2Idx,-f/2,-g/2)}}for(const t of u)for(const n of f){if(t.layers.filter(t=>n.layers.includes(t)).length>0){const a=t.point.x-n.point.x,h=t.point.y-n.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*s*Math.exp(-6*u),f=a/d*p,g=h/d*p;r(e,t.index,f,g),r(i,n.index,-f,-g)}}}}for(let e=0;e<n;e++){const n=t[e],i=[n.start,...n.mPoints,n.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 n=t+1;n<a.length;n++){const i=a[t],h=a[n],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 n=2,a=t;t<this.viaDiameter?(n*=4,a=Math.max(o,t)):a=Math.max(o,t-this.viaDiameter);const u=n*s*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 s=0;s<n;s++)for(let n=0;n<t[s].mPoints.length;n++){const r=t[s].mPoints[n],h=a[s][n],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,n=0;const s=this.viaDiameter/2+this.BOUNDARY_PADDING,o=this.bounds.minX+s,a=this.bounds.maxX-s,h=this.bounds.minY+s,c=this.bounds.maxY-s,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?n=i*(Math.exp(m/(2*this.obstacleMargin))-1):y>0&&(n=-.008*(Math.exp(y/(2*this.obstacleMargin))-1)),l+=e,u+=n,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}}},ue=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 pe=class extends le{constructor(t){super(t),this.MAX_ITERATIONS=1e3}createInitialCandidateFromSeed(t){const e=new Ht({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,hyperParameters:{SHUFFLE_SEED:t},viaDiameter:this.viaDiameter});if(e.solve(),e.failed||!e.solved)return this.failed=!0,this.error=`ViaPossibilitiesSolver2 failed with: ${e.error}`,null;const n=[];let s=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],n=t+1<a.length?a[t+1]:o,s=c,i=t+1<a.length&&e.x===n.x&&e.y===n.y&&e.z!==n.z?n.z:e.z;r.push({x:e.x,y:e.y,z1:s,z2:i}),s!==i?(h++,t++,c=i):c=e.z}s+=h;const d=this.SEGMENTS_PER_POLYLINE;let l=r.length+1;for(;l<d;){let n=-1,s=-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=st(e,o);r>n&&(n=r,s=t,i=e,a=o)}if(-1===s||!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(s,0,f),l++}n.push({connectionName:t,start:{...e,z1:e.z,z2:e.z},end:{...o,z1:o.z,z2:o.z},mPoints:r})}if(0===n.length)return this.failed=!0,this.error="No valid polylines generated from ViaPossibilitiesSolver2.",console.error(this.error),null;const i=this.computeMinGapBtwPolyLines(n),o=this.computeH({minGaps:i,forces:[]}),a={polyLines:n,g:0,h:o,f:0+o,viaCount:s,minGaps:i};return a.g=this.computeG(n,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 n=2;n<=t;n++)e*=n;return e}(this.uniqueConnections)),e=new Set;for(let n=0;n<t;n++){const t=this.createInitialCandidateFromSeed(n);if(!t)continue;const s=ue(t.polyLines);e.has(s)||(e.add(s),this.candidates.push(t))}this.candidates.sort((t,e)=>t.f-e.f)}},fe=class extends wt{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 At({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING?new Yt({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.MULTI_HEAD_POLYLINE_SOLVER?new pe({nodeWithPortPoints:this.nodeWithPortPoints,connMap:this.connMap,hyperParameters:t,viaDiameter:this.constructorParams.viaDiameter}):new Tt({...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 ge(t,e,n){const s=[];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}):(s.push(i),i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:n}):i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:n},o===t.length-1&&i&&s.push(i)}return s}var me=class extends e{unsolvedNodePortPoints;routes;colorMap;defaultViaDiameter=.6;defaultTraceThickness=.15;viaDiameter;traceWidth;failedSolvers;activeSubSolver=null;connMap;constructor({nodePortPoints:t,colorMap:e,connMap:n,viaDiameter:s,traceWidth:i}){super(),this.unsolvedNodePortPoints=t,this.colorMap=e??{},this.connMap=n,this.routes=[],this.failedSolvers=[],this.MAX_ITERATIONS=1e6,this.viaDiameter=s??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();!function(t){const{node:e,viaDiameter:n=.6,traceWidth:s,obstacleMargin:i=.1}=t,{portPoints:o,width:a}=e,r=null!=s?1.1*s:n/2+i;let h=0;for(let t=0;t<o.length;t++)for(let e=t+1;e<o.length;e++){const n=o[t],s=o[e];if(n.connectionName===s.connectionName)continue;if(n.z!==s.z)continue;const i=n.x-s.x,a=n.y-s.y;Math.sqrt(i*i+a*a)<r&&h++}const c=new Map;for(const t of o)c.has(t.connectionName)||c.set(t.connectionName,[]),c.get(t.connectionName).push(t);const d=c.size,l=[];for(const[t,e]of c.entries()){if(e.length<2)continue;const n=e[0],s=e[e.length-1];l.push({connectionName:t,entry:n,exit:s})}const u=new Set;let p=0;for(let t=0;t<l.length;t++)for(let e=t+1;e<l.length;e++){const n=l[t],s=l[e];n.entry.z===n.exit.z&&s.entry.z===s.exit.z&&n.entry.z===s.entry.z&&Q(n.entry,n.exit,s.entry,s.exit)&&(u.add(n.connectionName),u.add(s.connectionName),p++)}let f=0;for(const t of c.values()){const e=new Map;for(const n of t){const t=`${n.x.toFixed(6)},${n.y.toFixed(6)}`;e.has(t)||e.set(t,new Set),e.get(t).add(n.z)}const n=Array.from(e.values()),s=new Set;if(n.forEach(t=>{t.forEach(t=>s.add(t))}),s.size>1&&n.length>1){let t=!1;if(2===s.size){for(const n of e.values())if(n.size>1){t=!0;break}}else if(s.size>2)for(const n of e.values())if(n.size===s.size){t=!0;break}t||f++}}const g=2*p+f,m=n+2*i,y=Math.min(g,3),x=y*m,v=a>=x,S=e.height>=x;u.size,e.height}({node:t,viaDiameter:this.viaDiameter,traceWidth:this.traceWidth});this.activeSubSolver=new fe({nodeWithPortPoints:t,colorMap:this.colorMap,connMap:this.connMap,viaDiameter:this.viaDiameter,traceWidth:this.traceWidth}),this.updateCacheStats()}updateCacheStats(){const t=G();this.stats.intraNodeCacheHits=t.cacheHits,this.stats.intraNodeCacheMisses=t.cacheMisses}visualize(){let e={lines:[],points:[],rects:[],circles:[]};for(const t of this.routes){const n=ge(t.route,t.connectionName,this.colorMap[t.connectionName]);for(const s of n)e.lines.push({points:s.points,label:s.connectionName,strokeColor:0===s.z?s.color:H(s.color,.75),layer:`z${s.z}`,strokeWidth:t.traceThickness,strokeDash:0!==s.z?"10, 5":void 0});for(const n of t.vias)e.circles.push({center:n,layer:"z0,1",radius:t.viaDiameter/2,fill:this.colorMap[t.connectionName],label:`${t.connectionName} via`})}for(const t of this.failedSolvers){const n=t.nodeWithPortPoints,s=.1*n.width,i=.1*n.height;e.rects.push({center:{x:n.center.x-s/2,y:n.center.y-i/2},layer:"did_not_connect",width:s,height:i,fill:"red",label:`Failed: ${n.capacityMeshNodeId}`});const o={};for(const t of n.portPoints)o[t.connectionName]||(o[t.connectionName]=[]),o[t.connectionName].push({x:t.x,y:t.y,z:t.z});for(const[t,n]of Object.entries(o))for(let t=0;t<n.length-1;t++){const s=n[t],i=n[t+1];e.lines.push({points:[s,i],strokeColor:"red",strokeDash:"10, 5",layer:"did_not_connect"})}}return this.activeSubSolver&&(e=t(e,this.activeSubSolver.visualize())),e}},ye=class{netMap;idToNetMap;constructor(t){this.netMap=t,this.idToNetMap={};for(const[e,n]of Object.entries(t))for(const t of n)this.idToNetMap[t]=e}addConnections(t){for(const e of t){const t=new Set;for(const n of e){const e=this.idToNetMap[n];e&&t.add(e)}let n;if(0===t.size)n=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[n]=[];else if(1===t.size)n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(const e of t)if(e!==n){this.netMap[n].push(...this.netMap[e]),this.netMap[e]=this.netMap[n];for(const t of this.netMap[n])this.idToNetMap[t]=n}}for(const t of e)this.netMap[n].includes(t)||this.netMap[n].push(t),this.idToNetMap[t]=n}}getIdsConnectedToNet(t){return this.netMap[t]||[]}getNetConnectedToId(t){return this.idToNetMap[t]}areIdsConnected(t,e){if(t===e)return!0;const n=this.getNetConnectedToId(t);if(!n)return!1;const s=this.getNetConnectedToId(e);return!!s&&(n===s||s===t||s===t)}areAllIdsConnected(t){const e=this.getNetConnectedToId(t[0]);for(const n of t){const t=this.getNetConnectedToId(n);if(void 0===t)return!1;if(t!==e)return!1}return!0}},xe=t=>{const e=new ye({});for(const n of t.connections){if(n.rootConnectionName&&e.addConnections([[n.name,n.rootConnectionName]]),n.netConnectionName&&e.addConnections([[n.name,n.netConnectionName]]),n.mergedConnectionNames)for(const t of n.mergedConnectionNames)e.addConnections([[n.name,t]]);for(const t of n.pointsToConnect)"pcb_port_id"in t&&t.pcb_port_id&&e.addConnections([[n.name,t.pcb_port_id]])}for(const n of t.obstacles){const t=n.offBoardConnectsTo??[],s=Array.from(new Set([...n.connectedTo,...t]));s.length>0&&e.addConnections([s])}return e},ve=(t,e=1,n={})=>{const s=n.viaDiameter??.6,i=n.obstacleMargin??.2,o=(("width"in t?t.width:t)/(s/2+i)/2)**1.1*e;return 1===t.availableZ?.length&&o>1?1:o},Se=(t,e=.5,n=16)=>{let s=0,i=t;for(;s<n;){if(ve({width:i})<=e)break;i/=2,s++}return Math.max(1,s)},Me=(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}`},Ne=(t,e)=>{const n=[];if(0===t.route.length)return n;let s=[],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=Me(i,e);for(const e of s)n.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=Me(i,e),s=Me(a.z,e);n.push({route_type:"via",x:a.x,y:a.y,from_layer:t,to_layer:s})}s=[a],i=a.z}else s.push(a)}const o=Me(i,e);for(const e of s)n.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:o});return n};function be(t){return"layers"in t&&Array.isArray(t.layers)}function Pe(t){return be(t)?t.layers[0]:t.layer}function Ie(t){return be(t)?t.layers:[t.layer]}var Ce=(t,e)=>"top"===t?0:"bottom"===t?e-1:parseInt(t.slice(5)),_e=1e5,Ee=.001,Te=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}],n=[];return t.start.z!==t.end.z&&(e.push({x:t.start.x,y:t.start.y,z:t.end.z}),n.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:n,viaDiameter:t.defaultViaDiameter??.6,traceThickness:t.defaultTraceThickness??.15},void(this.solved=!0)}let e=1/0,n=t.hdRoutes[0],s="start-to-end";for(const i of t.hdRoutes){const o=i.route[0],a=i.route[i.route.length-1],r=st(t.start,o),h=st(t.start,a),c=st(t.end,o),d=st(t.end,a),l=Math.min(r,h,c,d);l<e&&(e=l,n=i,s=Math.min(c,d)<Math.min(r,h)?"end-to-start":"start-to-end")}"start-to-end"===s?(this.start=t.start,this.end=t.end):(this.start=t.end,this.end=t.start);const i=n.route[0],o=n.route[n.route.length-1],a=st(this.start,i)<=st(this.start,o)?i:o;this.mergedHdRoute={connectionName:t.connectionName,rootConnectionName:n.rootConnectionName,route:[{x:this.start.x,y:this.start.y,z:a.z}],vias:[],viaDiameter:n.viaDiameter,traceThickness:n.traceThickness}}getDisjointedRoute(){for(const t of this.remainingHdRoutes){if([t.route[0],t.route[t.route.length-1]].some(e=>!this.remainingHdRoutes.some(n=>{if(n===t)return!1;return[n.route[0],n.route[n.route.length-1]].some(t=>t.z===e.z&&st(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,n="first",s=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=st(t,a),c=st(t,r);let d=1/0;d=t.z===a.z?h<Ee?h:_e+h:h<Ee?1e3+h:_e+h,d<s&&(s=d,e=i,n="first");let l=1/0;l=t.z===r.z?c<Ee?c:_e+c:c<Ee?1e3+c:_e+c,l<s&&(s=l,e=i,n="last")}if(-1===e)return void(this.remainingHdRoutes=[]);const i=this.remainingHdRoutes[e];let o;this.remainingHdRoutes.splice(e,1),o="first"===n?i.route:[...i.route].reverse(),o.length>0&&st(t,o[0])<Ee&&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,n]of this.remainingHdRoutes.entries()){const s=this.colorMap[n.connectionName]??"gray";n.route.length>1&&t.lines?.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:s});for(let i=0;i<n.route.length;i++){const o=n.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:s,label:`Route ${n.connectionName} ${o===n.route[0]?"First":o===n.route[n.route.length-1]?"Last":""}`})}for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s})}return t}},we=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:Ce(Pe(e.pointsToConnect[0]),t.layerCount)},end:{...e.pointsToConnect[1],z:Ce(Pe(e.pointsToConnect[1]),t.layerCount)}})),this.MAX_ITERATIONS=1e5}_step(){if(this.activeSolver)return this.activeSolver.step(),void(this.activeSolver.solved?(this.activeSolver instanceof Te&&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 Te({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,n]of this.mergedHdRoutes.entries()){const s=this.colorMap[n.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<n.route.length-1;e++){const i=n.route[e],o=n.route[e+1],a=0!==i.z?H(s,.5):s;t.lines?.push({points:[{x:i.x,y:i.y},{x:o.x,y:o.y}],strokeColor:a,strokeWidth:n.traceThickness})}for(const e of n.route){const n=0!==e.z?H(s,.5):s;t.points?.push({x:e.x,y:e.y,color:n})}for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s})}for(const e of this.unsolvedRoutes){const n=this.colorMap[e.connectionName]??"gray";t.points?.push({x:e.start.x,y:e.start.y,color:n,label:`${e.connectionName} Start (z=${e.start.z})`},{x:e.end.x,y:e.end.y,color:n,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:n,strokeDash:"2 2"});for(const s of e.hdRoutes){s.route.length>1&&t.lines?.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:H(n,.5),strokeDash:"10 5"});for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n})}}return t}},ze=t=>{const e=[],n=[],s=[],i=B(t),o=(t.minViaDiameter??.6)/2;if(t.connections)for(const e of t.connections)for(const t of e.pointsToConnect){const n=Ie(t);s.push({x:t.x,y:t.y,color:i[e.name],layer:n[0]??("z"in t?Me(t.z,2):"top"),label:`${e.name} (${n.join(",")})`})}if(t.traces)for(const s of t.traces)for(let t=0;t<s.route.length-1;t++){const i=s.route[t],a=s.route[t+1];"via"===i.route_type?n.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${Ce(i.layer,2)}`,strokeWidth:.15,strokeColor:H({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(Ce).join(",")}`})),circles:n,lines:e,points:s}};function Ae(t,e){const n=t.center.x-t.width/2,s=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(s-a)<d||Math.abs(n-r)<d)&&Math.min(o,c)-Math.max(i,h)>=d,u=(Math.abs(o-h)<d||Math.abs(i-c)<d)&&Math.min(s,r)-Math.max(n,a)>=d;return l||u}var Re=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)&&Ae(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,n=1/0;for(const s of this.nodes){if(s._containsObstacle)continue;if(s._containsTarget)continue;const i=st(e.center,s.center);i<n&&(n=i,t=s)}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 n of e.nodeIds)t.set(n,1+(t.get(n)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const n=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+n*e.width*.05,y:e.center.y-n*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 n=this.nodeMap.get(t.nodeIds[0]),s=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&s?.center){const t=Math.min(...n.availableZ),i=Math.min(...s.availableZ),o={x:n.center.x+t*n.width*.05,y:n.center.y-t*n.width*.05},a={x:s.center.x+i*s.width*.05,y:s.center.y-i*s.width*.05},r=Array.from(new Set([...n.availableZ,...s.availableZ])).sort();e.lines.push({layer:`z${r.join(",")}`,points:[o,a],strokeDash:n.availableZ.join(",")===s.availableZ.join(",")?void 0:"10 5"})}}return e}},Oe=class{constructor(t){this.nodes=t,this.buckets=new Map;for(const e of t){const t=e.center.x-e.width/2,n=e.center.y-e.height/2,s=e.center.x+e.width/2,i=e.center.y+e.height/2;for(let o=t;o<=s;o+=this.CELL_SIZE)for(let t=n;t<=i;t+=this.CELL_SIZE){const n=this.getBucketKey(o,t),s=this.buckets.get(n);s?s.push(e):this.buckets.set(n,[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,n,s){const i=[],o=new Set,a=e-s/2,r=t+n/2,h=e+s/2;for(let e=t-n/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const n=this.getBucketKey(e,t),s=this.buckets.get(n)||[];for(const t of s)o.has(t.capacityMeshNodeId)||(o.add(t.capacityMeshNodeId),i.push(t))}return i}},De=class extends Re{constructor(t){super(t),this.nodes=t,this.MAX_ITERATIONS=1e7,this.nodeTree=new Oe(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 n of e){if(!Ae(t,n))continue;const e=t._strawNode&&n._strawNode&&t._strawParentCapacityMeshNodeId===n._strawParentCapacityMeshNodeId;t.capacityMeshNodeId===n.capacityMeshNodeId||e||!this.doNodesHaveSharedLayer(t,n)||this.edgeSet.has(`${t.capacityMeshNodeId}-${n.capacityMeshNodeId}`)||(this.edgeSet.add(`${t.capacityMeshNodeId}-${n.capacityMeshNodeId}`),this.edgeSet.add(`${n.capacityMeshNodeId}-${t.capacityMeshNodeId}`),this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[t.capacityMeshNodeId,n.capacityMeshNodeId]}))}this.currentNodeIndex++}},Le=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 n=this.find(t),s=this.find(e);n!==s&&(this.parent[s]=n)}getGroup(t){const e=this.find(t),n=[];for(const t in this.parent)this.find(t)===e&&n.push(t);return n}},Fe=class{point;left=null;right=null;constructor(t){this.point=t}},$e=class{root=null;constructor(t){t.length>0&&(this.root=this.buildTree(t,0))}buildTree(t,e){const n=e%2==0?"x":"y";t.sort((t,e)=>t[n]-e[n]);const s=Math.floor(t.length/2),i=new Fe(t[s]);return s>0&&(i.left=this.buildTree(t.slice(0,s),e+1)),s<t.length-1&&(i.right=this.buildTree(t.slice(s+1),e+1)),i}findNearestNeighbor(t){if(!this.root)throw new Error("Tree is empty");const e=this.root.point,n=this.distance(t,e);return this.nearestNeighborSearch(this.root,t,0,e,n),e}nearestNeighborSearch(t,e,n,s,i){if(!t)return s;const o=n%2?"x":"y",a=this.distance(e,t.point);a<i&&(s=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 s=this.nearestNeighborSearch(h,e,n+1,s,i),i=this.distance(e,s),Math.abs(r)<i&&(s=this.nearestNeighborSearch(c,e,n+1,s,i)),s}findKNearestNeighbors(t,e){if(!this.root)return[];const n=[];return this.kNearestNeighborSearch(this.root,t,0,n,e),n.sort((t,e)=>t.distance-e.distance).slice(0,e).map(t=>t.point)}kNearestNeighborSearch(t,e,n,s,i){if(!t)return;const o=n%2?"x":"y",a=this.distance(e,t.point);s.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,n+1,s,i);let d=1/0;s.length>=i&&(s.sort((t,e)=>t.distance-e.distance),d=s[i-1]?.distance||1/0),(Math.abs(r)<d||s.length<i)&&this.kNearestNeighborSearch(c,e,n+1,s,i)}distance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}},ke=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 n=e;for(;n!==this.parent.get(n);)n=this.parent.get(n);let s=e;for(;s!==n;){const t=this.parent.get(s);this.parent.set(s,n),s=t}return n}union(t,e){const n=this.find(t),s=this.find(e);if(n===s)return!1;const i=this.rank.get(n)||0,o=this.rank.get(s)||0;return i<o?this.parent.set(n,s):i>o?this.parent.set(s,n):(this.parent.set(s,n),this.rank.set(n,i+1)),!0}};function Xe(t){if(t.length<=1)return[];const e=new $e(t),n=[],s=Math.min(10,t.length-1);for(const i of t){const t=e.findKNearestNeighbors(i,s+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);n.push({from:i,to:e,weight:t})}}n.sort((t,e)=>t.weight-e.weight);const i=new ke(t),o=[];for(const e of n)if(i.union(e.from,e.to)&&(o.push(e),o.length===t.length-1))break;return o}function Ye(t){if(t.pointId)return t.pointId;let e="";var n;return"layer"in(n=t)&&"string"==typeof n.layer?e=t.layer:be(t)&&t.layers&&(e=t.layers.sort().join("-")),`${t.x.toFixed(4)},${t.y.toFixed(4)},${e}`}var Be=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}`),n=new Le(e),s=new Map;t.forEach((t,e)=>{const n=`conn_${e}`;t.pointsToConnect.forEach(t=>{const e=Ye(t);s.has(e)||s.set(e,[]),s.get(e).push(n)})});for(const t of s.values())if(t.length>1){const e=t[0];for(let s=1;s<t.length;s++)n.union(e,t[s])}const i=new Map;t.forEach((t,e)=>{const s=`conn_${e}`,o=n.find(s);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,n=new Set;let s=!1;const i=[],a=new Set;let r;t.forEach(t=>{t.pointsToConnect.forEach(t=>e.set(Ye(t),t)),n.add(t.name),t.isOffBoard&&(s=!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(n).join("__"),mergedConnectionNames:Array.from(n),pointsToConnect:Array.from(e.values()),isOffBoard:s,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??[],n=new Map;e.forEach((t,e)=>t.forEach(t=>n.set(t,e)));const s=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const s=n.get(t.pointId),i=n.get(e.pointId);return void 0!==s&&s===i};if(2===t.pointsToConnect.length){if(s(t.pointsToConnect[0],t.pointsToConnect[1]))return;return void this.newConnections.push({...t,rootConnectionName:t.name})}const i=Xe(t.pointsToConnect);let o=0;for(const e of i)s(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(n=>{t.points.push({x:n.x,y:n.y,color:"red",label:e.name})});const n=e.pointsToConnect.length**2,s=Nt(0),i=new Set;for(let o=0;o<Math.max(n,2*e.pointsToConnect.length);o++){const n=Math.floor(s()*e.pointsToConnect.length),o=Math.floor(s()*e.pointsToConnect.length);i.has(`${n}-${o}`)||(i.add(`${n}-${o}`),t.lines.push({points:[e.pointsToConnect[n],e.pointsToConnect[o]],strokeColor:"rgba(255,0,0,0.25)"}))}}),this.newConnections.forEach(e=>{const n=this.colorMap?.[e.name]||"blue";e.pointsToConnect.forEach(s=>{t.points.push({x:s.x,y:s.y,color:n,label:e.name})});for(let s=0;s<e.pointsToConnect.length-1;s++)for(let i=s+1;i<e.pointsToConnect.length;i++)t.lines.push({points:[e.pointsToConnect[s],e.pointsToConnect[i]],strokeColor:n})}),t}},He=class extends Be{constructor(t,e={}){const n=t.connections.flatMap(t=>t.pointsToConnect),s=new Map;for(const t of n)t.pointId&&s.set(t.pointId,t);const i=n.map(t=>t.pointId).filter(t=>!!t),o=new Le(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=s,this.ogSrj=t}connectionPointDsu;connectionPointMap;_findBestConnectionPointsFromDisjointSets(t,e){if(!t.pointId||!e.pointId)return{pointsToConnect:[t,e]};const n=this.connectionPointDsu.getGroup(t.pointId).map(t=>this.connectionPointMap.get(t)),s=this.connectionPointDsu.getGroup(e.pointId).map(t=>this.connectionPointMap.get(t));let i=t,o=e,a=1/0;for(const t of n)for(const e of s){const n=Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));n<a&&(a=n,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??[],n=new Map;e.forEach((t,e)=>t.forEach(t=>n.set(t,e)));const s=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const s=n.get(t.pointId),i=n.get(e.pointId);return void 0!==s&&s===i};if(2===t.pointsToConnect.length){if(s(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=Xe(t.pointsToConnect);let o=0;for(const e of i){if(s(e.from,e.to))continue;const n=this._findBestConnectionPointsFromDisjointSets(e.from,e.to);this.newConnections.push({pointsToConnect:n.pointsToConnect,name:`${t.name}_mst${o++}`,rootConnectionName:t.name,mergedConnectionNames:t.mergedConnectionNames,netConnectionName:t.netConnectionName})}}},je=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:[]}}};function Ze(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var We=class extends je{startTimeOfPhase={};endTimeOfPhase={};timeSpentOnPhase={};firstIterationOfPhase={};currentPipelineStepIndex=0;inputProblem;pipelineOutputs={};constructor(t){super(),this.inputProblem=t,this.MAX_ITERATIONS=1e6}_step(){const t=this.pipelineDef[this.currentPipelineStepIndex];if(!t)return void(this.solved=!0);if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved){this.endTimeOfPhase[t.solverName]=performance.now(),this.timeSpentOnPhase[t.solverName]=this.endTimeOfPhase[t.solverName]-this.startTimeOfPhase[t.solverName];const e=this.activeSubSolver.getOutput();null!==e&&(this.pipelineOutputs[t.solverName]=e),t.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStepIndex++}else this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null);return}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(),this.firstIterationOfPhase[t.solverName]=this.iterations}solveUntilPhase(t){for(;this.getCurrentPhase().toLowerCase()!==t.toLowerCase()&&(this.step(),!this.failed&&!this.solved););}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}getPhaseProgress(){const t=this.pipelineDef.length;if(0===t)return 1;const e=this.activeSubSolver?.progress??0;return(this.currentPipelineStepIndex+e)/t}getPhaseStats(){const t={};for(const e of this.pipelineDef){const n=this.timeSpentOnPhase[e.solverName]||0,s=this.firstIterationOfPhase[e.solverName]||0,i=this.iterations,o=e.solverName===this.getCurrentPhase()?i-s:0,a=this.currentPipelineStepIndex>this.pipelineDef.findIndex(t=>t.solverName===e.solverName);t[e.solverName]={timeSpent:n,iterations:o,completed:a}}return t}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();const t=this.pipelineDef.map((t,e)=>{const n=this[t.solverName],s=n?.visualize();if(!s)return null;for(const t of s.rects??[])t.step=e;for(const t of s.points??[])t.step=e;for(const t of s.circles??[])t.step=e;for(const t of s.texts??[])t.step=e;for(const t of s.lines??[])t.step=e;return s}).filter(Boolean);return 0===t.length?{points:[],rects:[],lines:[],circles:[],texts:[]}:1===t.length?t[0]:{points:t.flatMap(t=>t.points||[]),rects:t.flatMap(t=>t.rects||[]),lines:t.flatMap(t=>t.lines||[]),circles:t.flatMap(t=>t.circles||[]),texts:t.flatMap(t=>t.texts||[])}}preview(){return this.activeSubSolver?this.activeSubSolver.preview():super.preview()}computeProgress(){return this.getPhaseProgress()}getStepOutput(t){return this.pipelineOutputs[t]}getAllOutputs(){return{...this.pipelineOutputs}}hasStepOutput(t){return t in this.pipelineOutputs}getSolver(t){return this[t]}},Ve=class{constructor(){this.ids=[],this.values=[],this.length=0}clear(){this.length=0}push(t,e){let n=this.length++;for(;n>0;){const t=n-1>>1,s=this.values[t];if(e>=s)break;this.ids[n]=this.ids[t],this.values[n]=s,n=t}this.ids[n]=t,this.values[n]=e}pop(){if(0===this.length)return;const t=this.ids,e=this.values,n=t[0],s=--this.length;if(s>0){const n=t[s],i=e[s];let o=0;const a=s>>1;for(;o<a;){const n=1+(o<<1),a=n+1,r=n+(+(a<s)&+(e[a]<e[n]));if(e[r]>=i)break;t[o]=t[r],e[o]=e[r],o=r}t[o]=n,e[o]=i}return n}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}},Ue=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],Ge=class t{static from(e,n=0){if(n%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[s,i]=new Uint8Array(e,n+0,2);if(251!==s)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=Ue[15&i];if(!a)throw new Error("Unrecognized array type.");const[r]=new Uint16Array(e,n+2,1),[h]=new Uint32Array(e,n+4,1);return new t(h,r,a,void 0,e,n)}constructor(t,e=16,n=Float64Array,s=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=n,this.IndexArrayType=r<16384?Uint16Array:Uint32Array;const h=Ue.indexOf(n),c=4*r*n.BYTES_PER_ELEMENT;if(h<0)throw new Error(`Unexpected typed array class: ${n}.`);if(i)this.data=i,this._boxes=new n(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 s(8+c+r*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new n(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 Ve}add(t,e,n=t,s=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++]=n,o[this._pos++]=s,t<this.minX&&(this.minX=t),e<this.minY&&(this.minY=e),n>this.maxX&&(this.maxX=n),s>this.maxY&&(this.maxY=s),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,n=this.maxY-this.minY||1,s=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)/n);s[i]=Qe(d,l)}Ke(s,t,this._indices,0,this.numItems-1,this.nodeSize);for(let e=0,n=0;e<this._levelBounds.length-1;e++){const s=this._levelBounds[e];for(;n<s;){const e=n;let i=t[n++],o=t[n++],a=t[n++],r=t[n++];for(let e=1;e<this.nodeSize&&n<s;e++)i=Math.min(i,t[n++]),o=Math.min(o,t[n++]),a=Math.max(a,t[n++]),r=Math.max(r,t[n++]);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,n,s,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,qe(o,this._levelBounds));for(let c=o;c<h;c+=4){const h=this._boxes[c];if(n<h)continue;const d=this._boxes[c+1];if(s<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,n=1/0,s=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=s*s;t:for(;void 0!==o;){const s=Math.min(o+4*this.nodeSize,qe(o,this._levelBounds));for(let n=o;n<s;n+=4){const s=0|this._indices[n>>2],r=this._boxes[n],c=this._boxes[n+1],d=this._boxes[n+2],l=this._boxes[n+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(s<<1,f):(void 0===i||i(s))&&a.push(1+(s<<1),f))}for(;a.length&&1&a.peek();){if(a.peekValue()>h)break t;if(r.push(a.pop()>>1),r.length===n)break t}o=a.length?a.pop()>>1:void 0}return a.clear(),r}};function qe(t,e){let n=0,s=e.length-1;for(;n<s;){const i=n+s>>1;e[i]>t?s=i:n=i+1}return e[n]}function Ke(t,e,n,s,i,o){if(Math.floor(s/o)>=Math.floor(i/o))return;const a=t[s],r=t[s+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=s-1,u=i+1;for(;;){do{l++}while(t[l]<c);do{u--}while(t[u]>c);if(l>=u)break;Je(t,e,n,l,u)}Ke(t,e,n,s,u,o),Ke(t,e,n,u+1,i,o)}function Je(t,e,n,s,i){const o=t[s];t[s]=t[i],t[i]=o;const a=4*s,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=n[s];n[s]=n[i],n[i]=u}function Qe(t,e){let n=t^e,s=65535^n,i=65535^(t|e),o=t&(65535^e),a=n|s>>1,r=n>>1^n,h=i>>1^s&o>>1^i,c=n&i>>1^o>>1^o;n=a,s=r,i=h,o=c,a=n&n>>2^s&s>>2,r=n&s>>2^s&(n^s)>>2,h^=n&i>>2^s&o>>2,c^=s&i>>2^(n^s)&o>>2,n=a,s=r,i=h,o=c,a=n&n>>4^s&s>>4,r=n&s>>4^s&(n^s)>>4,h^=n&i>>4^s&o>>4,c^=s&i>>4^(n^s)&o>>4,n=a,s=r,i=h,o=c,h^=n&i>>8^s&o>>8,c^=s&i>>8^(n^s)&o>>8,n=h^h>>1,s=c^c>>1;let d=t^e,l=s|65535^(d|n);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}function tn(t,e,n=0,s=t.length-1,i=nn){for(;s>n;){if(s-n>600){const o=s-n+1,a=e-n+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);tn(t,e,Math.max(n,Math.floor(e-a*h/o+c)),Math.min(s,Math.floor(e+(o-a)*h/o+c)),i)}const o=t[e];let a=n,r=s;for(en(t,n,e),i(t[s],o)>0&&en(t,n,s);a<r;){for(en(t,a,r),a++,r--;i(t[a],o)<0;)a++;for(;i(t[r],o)>0;)r--}0===i(t[n],o)?en(t,n,r):(r++,en(t,r,s)),r<=e&&(n=r+1),e<=r&&(s=r-1)}}function en(t,e,n){const s=t[e];t[e]=t[n],t[n]=s}function nn(t,e){return t<e?-1:t>e?1:0}var sn=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 n=[];if(!mn(t,e))return n;const s=this.toBBox,i=[];for(;e;){for(let o=0;o<e.children.length;o++){const a=e.children[o],r=e.leaf?s(a):a;mn(t,r)&&(e.leaf?n.push(a):gn(t,r)?this._all(a,n):i.push(a))}e=i.pop()}return n}collides(t){let e=this.data;if(!mn(t,e))return!1;const n=[];for(;e;){for(let s=0;s<e.children.length;s++){const i=e.children[s],o=e.leaf?this.toBBox(i):i;if(mn(t,o)){if(e.leaf||gn(t,o))return!0;n.push(i)}}e=n.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=yn([]),this}remove(t,e){if(!t)return this;let n=this.data;const s=this.toBBox(t),i=[],o=[];let a,r,h;for(;n||i.length;){if(n||(n=i.pop(),r=i[i.length-1],a=o.pop(),h=!0),n.leaf){const s=on(t,n.children,e);if(-1!==s)return n.children.splice(s,1),i.push(n),this._condense(i),this}h||n.leaf||!gn(n,s)?r?(a++,n=r.children[a],h=!1):n=null:(i.push(n),o.push(a),a=0,r=n,n=n.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 n=[];for(;t;)t.leaf?e.push(...t.children):n.push(...t.children),t=n.pop();return e}_build(t,e,n,s){const i=n-e+1;let o,a=this._maxEntries;if(i<=a)return o=yn(t.slice(e,n+1)),an(o,this.toBBox),o;s||(s=Math.ceil(Math.log(i)/Math.log(a)),a=Math.ceil(i/Math.pow(a,s-1))),o=yn([]),o.leaf=!1,o.height=s;const r=Math.ceil(i/a),h=r*Math.ceil(Math.sqrt(a));xn(t,e,n,h,this.compareMinX);for(let i=e;i<=n;i+=h){const e=Math.min(i+h-1,n);xn(t,i,e,r,this.compareMinY);for(let n=i;n<=e;n+=r){const i=Math.min(n+r-1,e);o.children.push(this._build(t,n,i,s-1))}}return an(o,this.toBBox),o}_chooseSubtree(t,e,n,s){for(;s.push(e),!e.leaf&&s.length-1!==n;){let n,s=1/0,i=1/0;for(let o=0;o<e.children.length;o++){const a=e.children[o],r=ln(a),h=pn(t,a)-r;h<i?(i=h,s=r<s?r:s,n=a):h===i&&r<s&&(s=r,n=a)}e=n||e.children[0]}return e}_insert(t,e,n){const s=n?t:this.toBBox(t),i=[],o=this._chooseSubtree(s,this.data,e,i);for(o.children.push(t),hn(o,s);e>=0&&i[e].children.length>this._maxEntries;)this._split(i,e),e--;this._adjustParentBBoxes(s,i,e)}_split(t,e){const n=t[e],s=n.children.length,i=this._minEntries;this._chooseSplitAxis(n,i,s);const o=this._chooseSplitIndex(n,i,s),a=yn(n.children.splice(o,n.children.length-o));a.height=n.height,a.leaf=n.leaf,an(n,this.toBBox),an(a,this.toBBox),e?t[e-1].children.push(a):this._splitRoot(n,a)}_splitRoot(t,e){this.data=yn([t,e]),this.data.height=t.height+1,this.data.leaf=!1,an(this.data,this.toBBox)}_chooseSplitIndex(t,e,n){let s,i=1/0,o=1/0;for(let a=e;a<=n-e;a++){const e=rn(t,0,a,this.toBBox),r=rn(t,a,n,this.toBBox),h=fn(e,r),c=ln(e)+ln(r);h<i?(i=h,s=a,o=c<o?c:o):h===i&&c<o&&(o=c,s=a)}return s||n-e}_chooseSplitAxis(t,e,n){const s=t.leaf?this.compareMinX:cn,i=t.leaf?this.compareMinY:dn;this._allDistMargin(t,e,n,s)<this._allDistMargin(t,e,n,i)&&t.children.sort(s)}_allDistMargin(t,e,n,s){t.children.sort(s);const i=this.toBBox,o=rn(t,0,e,i),a=rn(t,n-e,n,i);let r=un(o)+un(a);for(let s=e;s<n-e;s++){const e=t.children[s];hn(o,t.leaf?i(e):e),r+=un(o)}for(let s=n-e-1;s>=e;s--){const e=t.children[s];hn(a,t.leaf?i(e):e),r+=un(a)}return r}_adjustParentBBoxes(t,e,n){for(let s=n;s>=0;s--)hn(e[s],t)}_condense(t){for(let e,n=t.length-1;n>=0;n--)0===t[n].children.length?n>0?(e=t[n-1].children,e.splice(e.indexOf(t[n]),1)):this.clear():an(t[n],this.toBBox)}};function on(t,e,n){if(!n)return e.indexOf(t);for(let s=0;s<e.length;s++)if(n(t,e[s]))return s;return-1}function an(t,e){rn(t,0,t.children.length,e,t)}function rn(t,e,n,s,i){i||(i=yn(null)),i.minX=1/0,i.minY=1/0,i.maxX=-1/0,i.maxY=-1/0;for(let o=e;o<n;o++){const e=t.children[o];hn(i,t.leaf?s(e):e)}return i}function hn(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 cn(t,e){return t.minX-e.minX}function dn(t,e){return t.minY-e.minY}function ln(t){return(t.maxX-t.minX)*(t.maxY-t.minY)}function un(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 fn(t,e){const n=Math.max(t.minX,e.minX),s=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-n)*Math.max(0,o-s)}function gn(t,e){return t.minX<=e.minX&&t.minY<=e.minY&&e.maxX<=t.maxX&&e.maxY<=t.maxY}function mn(t,e){return e.minX<=t.maxX&&e.minY<=t.maxY&&e.maxX>=t.minX&&e.maxY>=t.minY}function yn(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function xn(t,e,n,s,i){const o=[e,n];for(;o.length;){if((n=o.pop())-(e=o.pop())<=s)continue;const a=e+Math.ceil((n-e)/s/2)*s;tn(t,a,e,n,i),o.push(e,a,a,n)}}var vn=1e-9,Sn=(t,e,n)=>Math.max(e,Math.min(n,t)),Mn=(t,e)=>t>e+vn,Nn=(t,e)=>t>e-vn,bn=(t,e)=>t<e-vn,Pn=(t,e)=>t<e+vn;function In(t,e){return!(t.x+t.width<=e.x+vn||e.x+e.width<=t.x+vn||t.y+t.height<=e.y+vn||e.y+e.height<=t.y+vn)}function Cn(t,e,n){return e>=t.x-vn&&e<=t.x+t.width+vn&&n>=t.y-vn&&n<=t.y+t.height+vn}function _n(t,e,n){const s=[[n.x,n.y,n.x+n.width,n.y],[n.x+n.width,n.y,n.x+n.width,n.y+n.height],[n.x+n.width,n.y+n.height,n.x,n.y+n.height],[n.x,n.y+n.height,n.x,n.y]];let i=1/0;for(const[n,o,a,r]of s){const s=a-n,h=r-o,c=s*s+h*h;let d=0!==c?((t-n)*s+(e-o)*h)/c:0;d=Sn(d,0,1);const l=n+d*s,u=o+d*h;i=Math.min(i,Math.hypot(t-l,e-u))}return i}function En(t,e,n,s){let i=e.x+e.width-t.x;for(const e of n){if(t.y+t.height>e.y+vn&&e.y+e.height>t.y+vn)if(Nn(e.x,t.x+t.width))i=Math.min(i,e.x-t.x);else if(e.x+e.width>t.x+t.width-vn&&e.x<t.x+t.width+vn)return 0}let o=Math.max(0,i-t.width);if(o<=0)return 0;if(null!=s){const e=t.width,n=t.height;e>=n&&(o=Math.min(o,s*n-e))}return Math.max(0,o)}function Tn(t,e,n,s){let i=e.y+e.height-t.y;for(const e of n){if(t.x+t.width>e.x+vn&&e.x+e.width>t.x+vn)if(Nn(e.y,t.y+t.height))i=Math.min(i,e.y-t.y);else if(e.y+e.height>t.y+t.height-vn&&e.y<t.y+t.height+vn)return 0}let o=Math.max(0,i-t.height);if(o<=0)return 0;if(null!=s){const e=t.width,n=t.height;n>=e&&(o=Math.min(o,s*e-n))}return Math.max(0,o)}function wn(t,e,n,s){let i=e.x;for(const e of n){if(t.y+t.height>e.y+vn&&e.y+e.height>t.y+vn)if(Pn(e.x+e.width,t.x))i=Math.max(i,e.x+e.width);else if(e.x<t.x+vn&&e.x+e.width>t.x-vn)return 0}let o=Math.max(0,t.x-i);if(o<=0)return 0;if(null!=s){const e=t.width,n=t.height;e>=n&&(o=Math.min(o,s*n-e))}return Math.max(0,o)}function zn(t,e,n,s){let i=e.y;for(const e of n){if(t.x+t.width>e.x+vn&&e.x+e.width>t.x+vn)if(Pn(e.y+e.height,t.y))i=Math.max(i,e.y+e.height);else if(e.y<t.y+vn&&e.y+e.height>t.y-vn)return 0}let o=Math.max(0,t.y-i);if(o<=0)return 0;if(null!=s){const e=t.width,n=t.height;n>=e&&(o=Math.min(o,s*e-n))}return Math.max(0,o)}function An(t){const{startX:e,startY:n,gridSize:s,bounds:i,blockers:o,initialCellRatio:a,maxAspectRatio:r,minReq:h}=t,c=Math.max(1e-9,s*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 s={x:e+t.ox,y:n+t.oy,width:d,height:l};if(bn(s.x,i.x)||bn(s.y,i.y)||Mn(s.x+s.width,i.x+i.width)||Mn(s.y+s.height,i.y+i.height))continue;for(const t of o)if(In(s,t))continue t;let a=!0;for(;a;){a=!1;const t=En(s,i,o,r);t>0&&(s={...s,width:s.width+t},a=!0);const e=Tn(s,i,o,r);e>0&&(s={...s,height:s.height+e},a=!0);const n=wn(s,i,o,r);n>0&&(s={x:s.x-n,y:s.y,width:s.width+n,height:s.height},a=!0);const h=zn(s,i,o,r);h>0&&(s={x:s.x,y:s.y-h,width:s.width,height:s.height+h},a=!0)}if(s.width+vn>=h.width&&s.height+vn>=h.height){const t=s.width*s.height;t>f&&(p=s,f=t)}}return p}function Rn(t,e,n,s){const i=Math.max(t,n),o=Math.min(e,s);return o>i+vn?[i,o]:null}function On(t,e){if(!In(t,e))return[t];const n=Rn(t.x,t.x+t.width,e.x,e.x+e.width),s=Rn(t.y,t.y+t.height,e.y,e.y+e.height);if(!n||!s)return[t];const[i,o]=n,[a,r]=s,h=[];i>t.x+vn&&h.push({x:t.x,y:t.y,width:i-t.x,height:t.height}),t.x+t.width>o+vn&&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>vn&&a>t.y+vn&&h.push({x:i,y:t.y,width:c,height:a-t.y}),c>vn&&t.y+t.height>r+vn&&h.push({x:i,y:r,width:c,height:t.y+t.height-r}),h.filter(t=>t.width>vn&&t.height>vn)}function Dn(t){const{x:e,y:n,layerCount:s,obstaclesByLayer:i,placedByLayer:o}=t;for(let t=0;t<s;t++){const s=i[t]??[],a=o[t]??[];if(!(s.some(t=>Cn(t,e,n))||a.some(t=>Cn(t,e,n))))return!1}return!0}function Ln(t){const{x:e,y:n,z:s,layerCount:i,minSpan:o,maxSpan:a,obstaclesByLayer:r,placedByLayer:h}=t,c=t=>![...r[t]??[],...h[t]??[]].some(t=>Cn(t,e,n));let d=s,l=s;for(;d-1>=0&&c(d-1);)d--;for(;l+1<i&&c(l+1);)l++;if("number"==typeof a){const t=Sn(a,1,i);for(;l-d+1>t;)s-d>l-s?d++:l--}const u=[];for(let t=d;t<=l;t++)u.push(t);return u.length>=o?u:[]}function Fn(t){const e=Math.max(t.width,t.height);return[e/8,e/16,e/32]}function $n(t){const{lineStart:e,lineEnd:n,coveringIntervals:s,minSegmentLength:i}=t;if(0===s.length){return[{start:e,end:n,center:(e+n)/2}]}const o=[...s].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+vn?r.end=Math.max(r.end,e.end):(a.push(r),r={...e})}a.push(r);const h=[];if(a[0].start>e+vn){const t=e,n=a[0].start;n-t>=i&&h.push({start:t,end:n,center:(t+n)/2})}for(let t=0;t<a.length-1;t++){const e=a[t].end,n=a[t+1].start;n-e>=i&&h.push({start:e,end:n,center:(e+n)/2})}if(a[a.length-1].end<n-vn){const t=a[a.length-1].end,e=n;e-t>=i&&h.push({start:t,end:e,center:(t+e)/2})}return h}function kn(t){const{bounds:e,minSize:n,layerCount:s,obstaclesByLayer:i,placedByLayer:o,hardPlacedByLayer:a}=t,r=[],h=Math.max(.15*n,3*vn),c=new Set;function d(t,n,h){if(t<e.x+vn||n<e.y+vn||t>e.x+e.width-vn||n>e.y+e.height-vn)return;if(function(t,e){return Dn({x:t,y:e,layerCount:s,obstaclesByLayer:i,placedByLayer:o})}(t,n))return;const d=[...i[h]??[],...a[h]??[]],l=Math.min(_n(t,n,e),...d.length?d.map(e=>_n(t,n,e)):[1/0]),u=((t,e,n)=>`${n}|${t.toFixed(6)}|${e.toFixed(6)}`)(t,n,h);if(c.has(u))return;c.add(u);const p=Ln({x:t,y:n,z:h,layerCount:s,minSpan:1,maxSpan:void 0,obstaclesByLayer:i,placedByLayer:a});r.push({x:t,y:n,z:h,distance:l,zSpanLen:p.length,isEdgeSeed:!0})}for(let t=0;t<s;t++){const s=[...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=s.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=$n({lineStart:e.x+h,lineEnd:e.x+e.width-h,coveringIntervals:c,minSegmentLength:.5*n});for(const e of l){const s=e.end-e.start;s>=n&&(d(e.center,r,t),s>1.5*n&&(d(e.start+.4*n,r,t),d(e.end-.4*n,r,t)))}const u=e.y+e.height-h,p=s.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=$n({lineStart:e.x+h,lineEnd:e.x+e.width-h,coveringIntervals:p,minSegmentLength:.5*n});for(const e of f){const s=e.end-e.start;s>=n&&(d(e.center,u,t),s>1.5*n&&(d(e.start+.4*n,u,t),d(e.end-.4*n,u,t)))}const g=e.x+h,m=s.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=$n({lineStart:e.y+h,lineEnd:e.y+e.height-h,coveringIntervals:m,minSegmentLength:.5*n});for(const e of y){const s=e.end-e.start;s>=n&&(d(g,e.center,t),s>1.5*n&&(d(g,e.start+.4*n,t),d(g,e.end-.4*n,t)))}const x=e.x+e.width-h,v=s.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)})),S=$n({lineStart:e.y+h,lineEnd:e.y+e.height-h,coveringIntervals:v,minSegmentLength:.5*n});for(const e of S){const s=e.end-e.start;s>=n&&(d(x,e.center,t),s>1.5*n&&(d(x,e.start+.4*n,t),d(x,e.end-.4*n,t)))}for(const i of s){const o=i.x-h;if(o>e.x+vn&&o<e.x+e.width-vn){const e=s.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=$n({lineStart:i.y,lineEnd:i.y+i.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of a)d(o,e.center,t)}const a=i.x+i.width+h;if(a>e.x+vn&&a<e.x+e.width-vn){const e=s.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=$n({lineStart:i.y,lineEnd:i.y+i.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of o)d(a,e.center,t)}const r=i.y-h;if(r>e.y+vn&&r<e.y+e.height-vn){const e=s.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=$n({lineStart:i.x,lineEnd:i.x+i.width,coveringIntervals:e,minSegmentLength:.5*n});for(const e of o)d(e.center,r,t)}const c=i.y+i.height+h;if(c>e.y+vn&&c<e.y+e.height-vn){const e=s.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=$n({lineStart:i.x,lineEnd:i.x+i.width,coveringIntervals:e,minSegmentLength:.5*n});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 Xn(t,e){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}function Yn(t){const e=t.toLowerCase();if("top"===e)return-1e6;if("bottom"===e)return 1e6;const n=/^inner(\d+)$/i.exec(e);return n?parseInt(n[1],10)||0:100+e.charCodeAt(0)}function Bn(t){const e=function(t){return Array.from(new Set(t)).sort((t,e)=>{const n=Yn(t),s=Yn(e);return n!==s?n-s:t.localeCompare(e)})}((t.obstacles??[]).flatMap(t=>t.layers??[])),n=Math.max(1,t.layerCount||e.length||1),s=Array.from({length:n},(t,e)=>0===e?"top":e===n-1?"bottom":`inner${e}`),i=[],o=new Set,a=t=>{const e=t.toLowerCase();o.has(e)||(o.add(e),i.push(t))};s.forEach(a),e.forEach(a);const r=i.slice(0,n),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),n=r.length-2;return Math.min(n,Math.max(1,Number.isFinite(t)?t:1))}return 0})(e))}),{layerNames:r,zIndexByName:h}}function Hn(t,e){if(t.zLayers?.length)return Array.from(new Set(t.zLayers)).sort((t,e)=>t-e);const n=(t.layers??[]).map(t=>e.get(t.toLowerCase())).filter(t=>"number"==typeof t);return Array.from(new Set(n)).sort((t,e)=>t-e)}function jn(t){const e=t.width,n=t.height;return"number"!=typeof e||"number"!=typeof n?null:{x:t.center.x-e/2,y:t.center.y-n/2,width:e,height:n}}function Zn(t,e){const{layerNames:n,zIndexByName:s}=Bn(t),i=Math.max(1,n.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 n=new Set([t.x,t.x+t.width]),s=new Set([t.y,t.y+t.height]);for(const t of e)n.add(t.x),s.add(t.y);const i=Array.from(n).sort((t,e)=>t-e),o=Array.from(s).sort((t,e)=>t-e),a=[];for(let n=0;n<i.length-1;n++)for(let s=0;s<o.length-1;s++){const r=i[n],h=i[n+1],c=o[s],d=o[s+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&&(Xn({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)>vn?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)<vn,n=Math.abs(h.height-t.height)<vn,s=Math.abs(h.x+h.width-t.x)<vn;e&&n&&s?h.width+=t.width:(r.push(h),h=t)}h&&r.push(h),r.sort((t,e)=>Math.abs(t.x-e.x)>vn?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)<vn,n=Math.abs(h.width-t.width)<vn,s=Math.abs(h.y+h.height-t.y)<vn;e&&n&&s?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=jn(e);if(!t)continue;const n=Hn(e,s),o=n.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||!n.length||(e.zLayers=n);for(const e of n)a[e].push(t)}const h=Math.max(.01,t.minTraceWidth||.15),c={gridSizes:Fn(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:n,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 Wn(t){const e=Array.from({length:t.layerCount},()=>[]);for(const n of t.placed)if(n.zLayers.length>=t.layerCount)for(const t of n.zLayers)e[t].push(n.rect);return e}function Vn(t,e){for(let n=0;n<t.layerCount;n++){const s=t.obstaclesByLayer[n]??[],i=t.placedByLayer[n]??[];if(!(s.some(t=>Cn(t,e.x,e.y))||i.some(t=>Cn(t,e.x,e.y))))return!1}return!0}function Un(t,e){const n=t.placed[e],{rect:s,zLayers:i}=n,o=t.layerCount,a=[],r=[];for(let n=0;n<t.placed.length;n++){if(n===e)continue;const h=t.placed[n];if(h.zLayers.length>=o)continue;const c=h.zLayers.filter(t=>i.includes(t));if(0===c.length)continue;if(!In(h.rect,s))continue;const d=On(h.rect,s);a.push(n);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+vn>=u&&t.height+vn>=p&&r.push({rect:t,zLayers:c.slice()})}a.sort((t,e)=>e-t).forEach(e=>{const n=t.placed.splice(e,1)[0];for(const e of n.zLayers){const s=t.placedByLayer[e],i=s.findIndex(t=>t===n.rect);i>=0&&s.splice(i,1)}});for(const e of r){t.placed.push(e);for(const n of e.zLayers)t.placedByLayer[n].push(e.rect)}}function Gn(t){const{gridSizes:e,initialCellRatio:n,maxAspectRatio:s,minSingle:i,minMulti:o,preferMultiLayer:a,maxMultiLayerSpan:r}=t.options,h=e[t.gridIndex],c=Wn(t);if(0===t.candidates.length&&0===t.consumedSeedsThisGrid&&(t.candidates=function(t){const{bounds:e,gridSize:n,layerCount:s,obstaclesByLayer:i,placedByLayer:o,hardPlacedByLayer:a}=t,r=new Map;for(let t=e.x;t<e.x+e.width;t+=n)for(let h=e.y;h<e.y+e.height;h+=n){if(Math.abs(t-e.x)<vn||Math.abs(h-e.y)<vn||t>e.x+e.width-n-vn||h>e.y+e.height-n-vn)continue;if(Dn({x:t,y:h,layerCount:s,obstaclesByLayer:i,placedByLayer:o}))continue;let c=[],d=0;for(let e=0;e<s;e++){const n=Ln({x:t,y:h,z:e,layerCount:s,minSpan:1,maxSpan:void 0,obstaclesByLayer:i,placedByLayer:a});n.length>c.length&&(c=n,d=e)}const l=c.length?c[Math.floor(c.length/2)]:d,u=[...i[l]??[],...a[l]??[]],p=Math.min(_n(t,h,e),...u.length?u.map(e=>_n(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=kn({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=Ln({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 n of e.layers)t.obstaclesByLayer[n]&&i.push(...t.obstaclesByLayer[n]),c[n]&&i.push(...c[n]);const o=An({startX:d.x,startY:d.y,gridSize:h,bounds:t.bounds,blockers:i,initialCellRatio:n,maxAspectRatio:s,minReq:e.minReq});if(!o)continue;const a={rect:o,zLayers:[...e.layers]},r=t.placed.push(a)-1;for(const n of e.layers)t.placedByLayer[n].push(o);return Un(t,r),void(t.candidates=t.candidates.filter(e=>!Vn(t,{x:e.x,y:e.y})))}}var qn=class extends je{srj;gridOptions;state;_meshNodes=[];constructor(t){super(),this.srj=t.simpleRouteJson,this.gridOptions=t.gridOptions??{}}_setup(){this.state=Zn(this.srj,this.gridOptions),this.stats={phase:this.state.phase,gridIndex:this.state.gridIndex}}_step(){if("GRID"===this.state.phase)Gn(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,n=t.placed[e],s=t.options.gridSizes[t.options.gridSizes.length-1],i=Wn(t),o=[];for(const e of n.zLayers)o.push(...t.obstaclesByLayer[e]??[]),o.push(...i[e]??[]);const a=n.rect,r=An({startX:n.rect.x+n.rect.width/2,startY:n.rect.y+n.rect.height/2,gridSize:s,bounds:t.bounds,blockers:o,initialCellRatio:0,maxAspectRatio:null,minReq:{width:n.rect.width,height:n.rect.height}});if(r){t.placed[e]={rect:r,zLayers:n.zLayers};for(const e of n.zLayers){const n=t.placedByLayer[e],s=n.findIndex(t=>t===a);s>=0&&(n[s]=r)}Un(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)})),n=new Map;t.obstaclesByLayer.forEach((t,e)=>{for(const s of t){const t=n.get(s)??[];t.push(e),n.set(s,t)}});const s=new Set(t.boardVoidRects||[]);for(const[t,i]of n.entries())s.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 n=[];for(const s of t){const t=Math.max(0,s.maxX-s.minX),i=Math.max(0,s.maxY-s.minY);t<=0||i<=0||0===s.zLayers.length||n.push({capacityMeshNodeId:"cmn_"+e++,center:{x:(s.minX+s.maxX)/2,y:(s.minY+s.maxY)/2},width:t,height:i,layer:"top",availableZ:s.zLayers.slice(),_containsObstacle:s.isObstacle,_containsTarget:s.isObstacle})}return n}(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 n=t.gridIndex/(e+1),s=Math.max(1,t.totalSeedsThisGrid),i=s?t.consumedSeedsThisGrid/s:1;return Math.min(.999,n+i*(1/(e+1)))}if("EXPANSION"===t.phase){const n=e/(e+1),s=Math.max(1,t.placed.length),i=s?t.expansionIndex/s:1;return Math.min(.999,n+i*(1/(e+1)))}return 1}(this.state)}getOutput(){return{meshNodes:this._meshNodes}}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=[],n=[],s=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?n.push({points:[...this.srj.outline,this.srj.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):t.push({center:{x:(s+i)/2,y:(o+a)/2},width:i-s,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),n=this.srj.outline.map(t=>t.y),s=Math.min(...t),i=Math.min(...n);e={x:s,y:i,width:Math.max(...t)-s,height:Math.max(...n)-i}}for(const n of this.state.boardVoidRects)e&&!In(n,e)||t.push({center:{x:n.x+n.width/2,y:n.y+n.height/2},width:n.width,height:n.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 n=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:n.fill,stroke:n.stroke,layer:`z${e.zLayers.join(",")}`,label:`free\nz:${e.zLayers.join(",")}`})}return{title:`RectDiff (${this.state?.phase??"init"})`,coordinateSystem:"cartesian",rects:t,points:e,lines:n}}};function Kn(t,e="RectDiff"){const n=[],s=[],i=t.bounds.minX,o=t.bounds.maxX,a=t.bounds.minY,r=t.bounds.maxY;t.outline&&t.outline.length>1?s.push({points:[...t.outline,t.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):n.push({center:{x:(i+o)/2,y:(a+r)/2},width:o-i,height:r-a,fill:"none",stroke:"#111827",label:"board"});for(const e of t.obstacles??[])"rect"!==e.type&&"oval"!==e.type||n.push({center:{x:e.center.x,y:e.center.y},width:e.width,height:e.height,fill:"#fee2e2",stroke:"#ef4444",layer:"obstacle",label:"obstacle"});return{title:e,coordinateSystem:"cartesian",rects:n,points:[],lines:s}}var Jn=1e-4;var Qn=[{facingDirection:"x-",dx:-1,dy:0,startX:-.5,startY:.5,endX:-.5,endY:-.5},{facingDirection:"x+",dx:1,dy:0,startX:.5,startY:.5,endX:.5,endY:-.5},{facingDirection:"y-",dx:0,dy:-1,startX:-.5,startY:-.5,endX:.5,endY:-.5},{facingDirection:"y+",dx:0,dy:1,startX:.5,startY:.5,endX:-.5,endY:.5}],ts={"x-":Qn.find(t=>"x-"===t.facingDirection),"x+":Qn.find(t=>"x+"===t.facingDirection),"y-":Qn.find(t=>"y-"===t.facingDirection),"y+":Qn.find(t=>"y+"===t.facingDirection)},es={"x-":{x:-1,y:0},"x+":{x:1,y:0},"y-":{x:0,y:-1},"y+":{x:0,y:1}},ns=(t,e,n)=>{const s=es[e];return t.map(t=>({x:t.x+s.x*n,y:t.y+s.y*n}))},ss=1e-4,is=class extends je{constructor(t){super(),this.input=t;for(const t of this.input.meshNodes)for(const e of Qn){let n={x:t.center.x+t.width*e.startX,y:t.center.y+t.height*e.startY},s={x:t.center.x+t.width*e.endX,y:t.center.y+t.height*e.endY};n.x>s.x&&([n,s]=[s,n]),Math.abs(n.x-s.x)<ss&&n.y>s.y&&([n,s]=[s,n]);for(const i of t.availableZ)this.unprocessedEdges.push({parent:t,start:n,end:s,facingDirection:e.facingDirection,z:i})}this.allEdges=[...this.unprocessedEdges],this.edgeSpatialIndex=new Ge(this.allEdges.length);for(const t of this.allEdges)this.edgeSpatialIndex.add(t.start.x,t.start.y,t.end.x,t.end.y);this.edgeSpatialIndex.finish()}allEdges;unprocessedEdges=[];segmentsWithAdjacentEmptySpace=[];edgeSpatialIndex;lastCandidateEdge=null;lastOverlappingEdges=null;lastUncoveredSegments=null;_step(){if(0===this.unprocessedEdges.length)return this.solved=!0,this.lastCandidateEdge=null,this.lastOverlappingEdges=null,void(this.lastUncoveredSegments=null);const t=this.unprocessedEdges.shift();this.lastCandidateEdge=t;const e=this.edgeSpatialIndex.search(t.start.x-ss,t.start.y-ss,t.end.x+ss,t.end.y+ss).map(t=>this.allEdges[t]).filter(e=>e.z===t.z);this.lastOverlappingEdges=e;const n=function(t,e){const n=Math.abs(t.start.y-t.end.y)<Jn,s=Math.abs(t.start.x-t.end.x)<Jn;if(!n&&!s)return[];const i=n?"x":"y",o=n?"y":"x",a=t.start[o],r=t.start[i],h=t.end[i],c=Math.min(r,h),d=Math.max(r,h),l=t=>Math.max(c,Math.min(d,t)),u=[];for(const n of e){if(n===t)continue;const e=Math.abs(n.start.y-n.end.y)<Jn,s=Math.abs(n.start.x-n.end.x)<Jn;if("x"===i&&!e)continue;if("y"===i&&!s)continue;if(Math.abs(n.start[o]-a)>Jn)continue;const r=Math.min(n.start[i],n.end[i]),h=Math.max(n.start[i],n.end[i]),c=l(r),d=l(h);d-c>Jn&&u.push({s:c,e:d})}if(0===u.length)return[{...t,start:{...t.start},end:{...t.end}}];u.sort((t,e)=>t.s-e.s);const p=[];for(const t of u){const e=p[p.length-1];!e||t.s>e.e+Jn?p.push({...t}):e.e=Math.max(e.e,t.e)}const f=[];let g=c;for(const t of p)if(t.s>g+Jn&&f.push({s:g,e:t.s}),g=Math.max(g,t.e),g>=d-Jn)break;return d>g+Jn&&f.push({s:g,e:d}),0===f.length?[]:f.filter(t=>t.e-t.s>Jn).map(e=>{const n="x"===i?{x:e.s,y:a}:{x:a,y:e.s},s="x"===i?{x:e.e,y:a}:{x:a,y:e.e};return{parent:t.parent,facingDirection:t.facingDirection,start:n,end:s,z:t.z}})}(t,e);this.lastUncoveredSegments=n,this.segmentsWithAdjacentEmptySpace.push(...n)}getOutput(){return{segmentsWithAdjacentEmptySpace:this.segmentsWithAdjacentEmptySpace}}visualize(){const t={title:"FindSegmentsWithAdjacentEmptySpace",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]};for(const e of this.input.meshNodes)t.rects.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(0, 0, 0, 0.1)"});for(const e of this.unprocessedEdges)t.lines.push({points:ns([e.start,e.end],e.facingDirection,-.1),strokeColor:"rgba(0, 0, 255, 0.5)",strokeDash:"5 5"});for(const e of this.segmentsWithAdjacentEmptySpace)t.lines.push({points:[e.start,e.end],strokeColor:"rgba(0,255,0, 0.5)"});if(this.lastCandidateEdge&&t.lines.push({points:[this.lastCandidateEdge.start,this.lastCandidateEdge.end],strokeColor:"blue"}),this.lastOverlappingEdges)for(const e of this.lastOverlappingEdges)t.lines.push({points:ns([e.start,e.end],e.facingDirection,.05),strokeColor:"red",strokeDash:"2 2"});if(this.lastUncoveredSegments)for(const e of this.lastUncoveredSegments)t.lines.push({points:ns([e.start,e.end],e.facingDirection,-.05),strokeColor:"green",strokeDash:"2 2"});return t}},os=t=>({minX:Math.min(...t.map(t=>t.x)),minY:Math.min(...t.map(t=>t.y)),maxX:Math.max(...t.map(t=>t.x)),maxY:Math.max(...t.map(t=>t.y))}),as=1e-4,rs=class extends je{constructor(t){super(),this.input=t,this.unprocessedSegments=[...this.input.segmentsWithAdjacentEmptySpace],this.rectSpatialIndex=new sn,this.rectSpatialIndex.load(this.input.inputMeshNodes.map(t=>({...t,minX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxX:t.center.x+t.width/2,maxY:t.center.y+t.height/2})))}unprocessedSegments=[];expandedSegments=[];lastSegment=null;lastSearchBounds=null;lastCollidingNodes=null;lastSearchCorner1=null;lastSearchCorner2=null;lastExpandedSegment=null;rectSpatialIndex;_step(){if(0===this.unprocessedSegments.length)return void(this.solved=!0);const t=this.unprocessedSegments.shift();this.lastSegment=t;const{dx:e,dy:n}=ts[t.facingDirection],s=t.end.x-t.start.x,i=t.end.y-t.start.y,o=Math.sqrt(s**2+i**2),a=s/o,r=i/o;let h=null,c=1;const d={x:t.start.x+e*as+a*as*10,y:t.start.y+n*as+r*as*10},l={x:t.end.x+e*as-a*as*10,y:t.end.y+n*as-r*as*10};for(this.lastSearchCorner1=d,this.lastSearchCorner2=l;(!h||0===h.length)&&c<1e3;){const s=os([d,l,{x:d.x+e*c,y:d.y+n*c},{x:l.x+e*c,y:l.y+n*c}]);this.lastSearchBounds=s,h=this.rectSpatialIndex.search(s).filter(e=>e.availableZ.includes(t.z)).filter(e=>e.capacityMeshNodeId!==t.parent.capacityMeshNodeId),c*=4}if(!h||0===h.length)return;this.lastCollidingNodes=h;let u=1/0;for(const e of h){const n=gt(t.start,t.end,e);n<u&&(u=n)}const p=u,f=os([t.start,t.end,{x:t.start.x+e*p,y:t.start.y+n*p},{x:t.end.x+e*p,y:t.end.y+n*p}]),g={x:(f.minX+f.maxX)/2,y:(f.minY+f.maxY)/2},m=f.maxX-f.minX,y=f.maxY-f.minY,x={segment:t,newNode:{capacityMeshNodeId:`new-${t.parent.capacityMeshNodeId}-${this.expandedSegments.length}`,center:g,width:m,height:y,availableZ:[t.z],layer:t.parent.layer}};this.lastExpandedSegment=x,m<as||y<as||(this.expandedSegments.push(x),this.rectSpatialIndex.insert({...x.newNode,...f}))}getOutput(){return{expandedSegments:this.expandedSegments}}visualize(){const t={title:"ExpandEdgesToEmptySpace",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]};for(const e of this.input.inputMeshNodes)t.rects.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(0, 0, 0, 0.1)",layer:`z${e.availableZ.join(",")}`,label:[`node ${e.capacityMeshNodeId}`,`z:${e.availableZ.join(",")}`].join("\n")});for(const{newNode:e}of this.expandedSegments)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"green",label:`expandedSegment (z=${e.availableZ.join(",")})`,layer:`z${e.availableZ.join(",")}`});if(this.lastSegment&&t.lines.push({points:[this.lastSegment.start,this.lastSegment.end],strokeColor:"rgba(0, 0, 255, 0.5)"}),this.lastSearchBounds&&t.rects.push({center:{x:(this.lastSearchBounds.minX+this.lastSearchBounds.maxX)/2,y:(this.lastSearchBounds.minY+this.lastSearchBounds.maxY)/2},width:this.lastSearchBounds.maxX-this.lastSearchBounds.minX,height:this.lastSearchBounds.maxY-this.lastSearchBounds.minY,fill:"rgba(0, 0, 255, 0.25)"}),this.lastSearchCorner1&&this.lastSearchCorner2&&(t.points.push({x:this.lastSearchCorner1.x,y:this.lastSearchCorner1.y,color:"rgba(0, 0, 255, 0.5)",label:["searchCorner1",`z=${this.lastSegment?.z}`].join("\n")}),t.points.push({x:this.lastSearchCorner2.x,y:this.lastSearchCorner2.y,color:"rgba(0, 0, 255, 0.5)",label:["searchCorner2",`z=${this.lastSegment?.z}`].join("\n")})),this.lastExpandedSegment&&t.rects.push({center:this.lastExpandedSegment.newNode.center,width:this.lastExpandedSegment.newNode.width,height:this.lastExpandedSegment.newNode.height,fill:"purple",label:`expandedSegment (z=${this.lastExpandedSegment.segment.z})`}),this.lastCollidingNodes)for(const e of this.lastCollidingNodes)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(255, 0, 0, 0.5)"});return t}},hs=class extends We{findSegmentsWithAdjacentEmptySpaceSolver;expandEdgesToEmptySpaceSolver;pipelineDef=[Ze("findSegmentsWithAdjacentEmptySpaceSolver",is,t=>[{meshNodes:t.inputProblem.meshNodes}],{onSolved:()=>{}}),Ze("expandEdgesToEmptySpace",rs,t=>[{inputMeshNodes:t.inputProblem.meshNodes,segmentsWithAdjacentEmptySpace:t.findSegmentsWithAdjacentEmptySpaceSolver.getOutput().segmentsWithAdjacentEmptySpace}],{onSolved:()=>{}})];getOutput(){const t=(this.expandEdgesToEmptySpaceSolver?.getOutput().expandedSegments??[]).map(t=>t.newNode);return{outputNodes:[...this.inputProblem.meshNodes,...t]}}initialVisualize(){const t={title:"GapFillSolverPipeline - Initial",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]};for(const e of this.inputProblem.meshNodes)t.rects.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(0, 0, 0, 0.3)",fill:"rgba(100, 100, 100, 0.1)",layer:`z${e.availableZ.join(",")}`,label:[`node ${e.capacityMeshNodeId}`,`z:${e.availableZ.join(",")}`].join("\n")});return t}finalVisualize(){const t={title:"GapFillSolverPipeline - Final",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]},{outputNodes:e}=this.getOutput(),n=this.expandEdgesToEmptySpaceSolver?.getOutput().expandedSegments??[],s=new Set(n.map(t=>t.newNode.capacityMeshNodeId));for(const n of e){const e=s.has(n.capacityMeshNodeId);t.rects.push({center:n.center,width:n.width,height:n.height,stroke:e?"rgba(0, 128, 0, 0.8)":"rgba(0, 0, 0, 0.3)",fill:e?"rgba(0, 200, 0, 0.3)":"rgba(100, 100, 100, 0.1)",layer:`z${n.availableZ.join(",")}`,label:[`${e?"[expanded] ":""}node ${n.capacityMeshNodeId}`,`z:${n.availableZ.join(",")}`].join("\n")})}return t}},cs=class extends We{rectDiffSolver;gapFillSolver;pipelineDef=[Ze("rectDiffSolver",qn,t=>[{simpleRouteJson:t.inputProblem.simpleRouteJson,gridOptions:t.inputProblem.gridOptions}],{onSolved:()=>{}}),Ze("gapFillSolver",hs,t=>[{meshNodes:t.rectDiffSolver?.getOutput().meshNodes??[]}])];getConstructorParams(){return[this.inputProblem]}getOutput(){const t=this.gapFillSolver?.getOutput();return t?{meshNodes:t.outputNodes}:this.rectDiffSolver.getOutput()}initialVisualize(){console.log("RectDiffPipeline - initialVisualize");const t=Kn(this.inputProblem.simpleRouteJson,"RectDiffPipeline - Initial"),e=this.rectDiffSolver?.getOutput().meshNodes??[];for(const n of e)t.rects.push({center:n.center,width:n.width,height:n.height,stroke:"rgba(0, 0, 0, 0.3)",fill:"rgba(100, 100, 100, 0.1)",layer:`z${n.availableZ.join(",")}`,label:[`node ${n.capacityMeshNodeId}`,`z:${n.availableZ.join(",")}`].join("\n")});return t}finalVisualize(){const t=Kn(this.inputProblem.simpleRouteJson,"RectDiffPipeline - Final"),{meshNodes:e}=this.getOutput(),n=new Set((this.rectDiffSolver?.getOutput().meshNodes??[]).map(t=>t.capacityMeshNodeId));for(const s of e){const e=!n.has(s.capacityMeshNodeId);t.rects.push({center:s.center,width:s.width,height:s.height,stroke:e?"rgba(0, 128, 0, 0.8)":"rgba(0, 0, 0, 0.3)",fill:e?"rgba(0, 200, 0, 0.3)":"rgba(100, 100, 100, 0.1)",layer:`z${s.availableZ.join(",")}`,label:[`${e?"[expanded] ":""}node ${s.capacityMeshNodeId}`,`z:${s.availableZ.join(",")}`].join("\n")})}return t}},ds=class{tree;constructor(t=9){this.tree=new sn(t)}insert(t,e,n,s,i){this.tree.insert({minX:e,minY:n,maxX:s,maxY:i,data:t})}bulkLoad(t){const e=t.map(({item:t,minX:e,minY:n,maxX:s,maxY:i})=>({minX:e,minY:n,maxX:s,maxY:i,data:t}));this.tree.load(e)}search(t,e,n,s){return this.tree.search({minX:t,minY:e,maxX:n,maxY:s}).map(t=>t.data)}clear(){this.tree.clear()}},ls=class{index;items=[];currentIndex=0;capacity;constructor(t){this.capacity=Math.max(1,t),this.index=new Ge(this.capacity)}insert(t,e,n,s,i){if(this.currentIndex>=this.index.numItems)throw new Error("Exceeded initial capacity");this.items[this.currentIndex]=t,this.index.add(e,n,s,i),this.currentIndex++}finish(){this.index.finish()}search(t,e,n,s){return this.index.search(t,e,n,s).map(t=>this.items[t]||null).filter(Boolean)}clear(){this.items=[],this.currentIndex=0,this.index=new Ge(this.capacity)}},us=class{idx;storage=[];constructor(t="native",e=[]){"flatbush"===t?0===e.length?(this.idx=new ds,t="rbush"):this.idx=new ls(e.length):this.idx="rbush"===t?new ds:new class{shi=new ps(e);insert(t){}search(t,e,n,s){const i=(t+n)/2,o=(e+s)/2,a=n-t,r=s-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,n,s){return this.search({minX:t-n/2,minY:e-s/2,maxX:t+n/2,maxY:e+s/2})}},ps=class{constructor(t){this.obstacles=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],s=n.center.x-n.width/2,i=n.center.y-n.height/2,o=n.center.x+n.width/2,a=n.center.y+n.height/2;for(let t=s;t<=o;t+=this.CELL_SIZE)for(let s=i;s<=a;s+=this.CELL_SIZE){const i=this.getBucketKey(t,s),o=this.buckets.get(i);o?o.push([n,e]):this.buckets.set(i,[[n,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,n,s){const i=[],o=new Set,a=e-s/2,r=t+n/2,h=e+s/2;for(let e=t-n/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const n=this.getBucketKey(e,t),s=this.buckets.get(n)||[];for(const t of s)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},fs=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 gs(t,e){const n=t.x-e.x,s=t.y-e.y;return n*n+s*s}function ms(t,e,n){const s=gs(e,n);if(0===s)return gs(t,e);let i=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/s;i=Math.max(0,Math.min(1,i));return gs(t,{x:e.x+i*(n.x-e.x),y:e.y+i*(n.y-e.y)})}function ys(t,e,n,s){if(Q(t,e,n,s))return 0;const i={x:t.x,y:t.y},o={x:e.x,y:e.y},a={x:n.x,y:n.y},r={x:s.x,y:s.y};return Math.min(ms(i,a,r),ms(o,a,r),ms(a,i,o),ms(r,i,o))}var xs=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 n=e.route[t],s=e.route[t+1];if(n.x===s.x&&n.y===s.y)continue;const i=[n,s],o=fs(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 n=`${t}x${e}`;let s=this.segmentBuckets.get(n);s||(s=[],this.segmentBuckets.set(n,s)),s.push(a)}}if(e.vias&&e.vias.length>0)for(let t=0;t<e.vias.length;t++){const n=e.vias[t];if(null==n)continue;const s={viaId:`${e.connectionName}-via-${t}`,x:n.x,y:n.y,parentRoute:e},i=`${Math.floor(n.x/this.CELL_SIZE)}x${Math.floor(n.y/this.CELL_SIZE)}`;let o=this.viaBuckets.get(i);o||(o=[],this.viaBuckets.set(i,o)),o.push(s)}}else console.warn("Skipping route with missing data:",e)}getConflictingRoutesForSegment(t,e,n){const s=fs([t,e]),i=s.minX-n,o=s.minY-n,a=s.maxX+n,r=s.maxY+n,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 s=h;s<=c;s++)for(let i=d;i<=l;i++){const o=`${s}x${i}`,a=this.segmentBuckets.get(o);if(a)for(const s of a){if(p.has(s.segmentId))continue;p.add(s.segmentId);const i=s.parentRoute,[o,a]=s.segment,r=n+i.traceThickness/2,h=r*r,c=ys(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,s={x:t.x,y:t.y},i=n+e.viaDiameter/2,o=i*i,a=ms(s,g,m);if(a<o){const t=e.connectionName,n=u.get(t);(!n||a<n.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 n=t.x-e,s=t.y-e,i=t.x+e,o=t.y+e,a=Math.floor(n/this.CELL_SIZE),r=Math.floor((i+1e-9)/this.CELL_SIZE),h=Math.floor(s/this.CELL_SIZE),c=Math.floor((o+1e-9)/this.CELL_SIZE),d=new Map,l=new Set,u=new Set;for(let n=a;n<=r;n++)for(let s=h;s<=c;s++){const i=`${n}x${s}`,o=this.segmentBuckets.get(i);if(o)for(const n of o){if(l.has(n.segmentId))continue;l.add(n.segmentId);const s=n.parentRoute,i={x:n.segment[0].x,y:n.segment[0].y},o={x:n.segment[1].x,y:n.segment[1].y},a=e+s.traceThickness/2,r=a*a,h=ms(t,i,o);if(h<r){const t=s.connectionName,e=d.get(t);(!e||h<e.minDistSq)&&d.set(t,{route:s,minDistSq:h})}}const a=this.viaBuckets.get(i);if(a)for(const n of a){if(u.has(n.viaId))continue;u.add(n.viaId);const s=n.parentRoute,i={x:n.x,y:n.y},o=e+s.viaDiameter/2,a=o*o,r=gs(t,i);if(r<a){const t=s.connectionName,e=d.get(t);(!e||r<e.minDistSq)&&d.set(t,{route:s,minDistSq:r})}}}const p=[];for(const t of d.values())p.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return p}},vs=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=[],n=t.route;if(0===n.length)return[];let s={startIndex:0,endIndex:-1,z:n[0].z,points:[n[0]]};for(let t=1;t<n.length;t++)n[t].z===s.z?s.points.push(n[t]):(s.endIndex=t-1,e.push(s),s={startIndex:t,endIndex:-1,z:n[t].z,points:[n[t]]});return s.endIndex=n.length-1,e.push(s),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 n=e.z,s=t.points[0];if(this.canEndpointConnectOnLayer(s.x,s.y,n)&&this.canSectionMoveToLayer({currentSection:t,targetZ:n}))return t.z=n,t.points=t.points.map(t=>({...t,z:n})),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 n=e.z,s=t.points[t.points.length-1];this.canEndpointConnectOnLayer(s.x,s.y,n)&&this.canSectionMoveToLayer({currentSection:t,targetZ:n})&&(t.z=n,t.points=t.points.map(t=>({...t,z:n})))}}return void(this.solved=!0)}const t=this.routeSections[this.currentSectionIndex-1],e=this.routeSections[this.currentSectionIndex],n=this.routeSections[this.currentSectionIndex+1];if(t.z!==n.z)return void this.currentSectionIndex++;const s=t.z;if(this.canSectionMoveToLayer({currentSection:e,targetZ:s}))return e.z=s,e.points=e.points.map(t=>({...t,z:s})),void(this.currentSectionIndex+=2);this.currentSectionIndex++}canEndpointConnectOnLayer(t,e,n){const s=this.obstacleSHI.searchArea(t,e,2,2).filter(n=>{if(!n.connectedTo?.includes(this.unsimplifiedRoute.connectionName))return!1;const s=n.width/2+.05,i=n.height/2+.05,o=Math.abs(t-n.center.x)<=s,a=Math.abs(e-n.center.y)<=i;return o&&a});return!(s.length>0)||s.some(t=>t.zLayers?.includes(n))}canSectionMoveToLayer({currentSection:t,targetZ:e}){for(let n=0;n<t.points.length-1;n++){const s={...t.points[n],z:e},i={...t.points[n+1],z:e},o=this.hdRouteSHI.getConflictingRoutesForSegment(s,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:(s.x+i.x)/2,centerY:(s.y+i.y)/2,width:Math.abs(s.x-i.x),height:Math.abs(s.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(s.x-t.center.x)<.01&&Math.abs(s.y-t.center.y)<.01||Math.abs(i.x-t.center.x)<.01&&Math.abs(i.y-t.center.y)<.01)continue}if(gt(s,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 n=0;n<t.length-1;n++)t[n].z!==t[n+1].z&&e.push({x:t[n].x,y:t[n].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 n=this.routeSections[e];t.lines.push({points:n.points,strokeWidth:this.TRACE_THICKNESS,strokeColor:e===this.currentSectionIndex?"orange":0===n.z?"red":"blue"})}return t}},Ss=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 us("flatbush",t.obstacles),this.hdRouteSHI=new xs(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 vs({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 n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),i=e.zLayers?.includes(1);s&&i?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":i&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,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 n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:0===s.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.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}},Ms=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 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:0===e.route[n].z?"rgba(255, 0, 255, 0.5)":1===e.route[n].z?"rgba(128, 0, 128, 0.5)":"rgba(0, 0, 255, 0.5)",layer:`z${e.route[n].z.toString()}`});if("filteredObstaclePathSegments"in this){const e=this.filteredObstaclePathSegments;for(const[n,s]of e)t.lines.push({points:[n,s]})}return t}};function Ns(t,e,n,s){if(Q(t,e,n,s))return 0;const i=bs(t,n,s),o=bs(e,n,s),a=bs(n,t,e),r=bs(s,t,e);return Math.min(i,o,a,r)}function bs(t,e,n){const s={x:n.x-e.x,y:n.y-e.y},i=Ps({x:t.x-e.x,y:t.y-e.y},s);if(i<=0)return Is(t,e);const o=Ps(s,s);if(o<=i)return Is(t,n);const a=i/o;return Is(t,{x:e.x+a*s.x,y:e.y+a*s.y})}function Ps(t,e){return t.x*e.x+t.y*e.y}function Is(t,e){const n=e.x-t.x,s=e.y-t.y;return Math.sqrt(n*n+s*s)}var Cs=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)}),_s=class{constructor(t){this.segments=t,this.buckets=new Map;const e=new Map;for(const n of t){const t=this.getSegmentKey(n);if(e.has(t))continue;e.set(t,n);const s=Cs(n),i=Math.floor(s.minX/this.CELL_SIZE),o=Math.floor(s.maxX/this.CELL_SIZE),a=Math.floor(s.minY/this.CELL_SIZE),r=Math.floor(s.maxY/this.CELL_SIZE);for(let e=i;e<=o;e++)for(let s=a;s<=r;s++){const i=`${e}x${s}`,o=this.buckets.get(i),a=[n[0],n[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 n=[],s=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];s.has(e)||(s.add(e),n.push(t))}}return n}},Es=1e-6,Ts=(t,e,n)=>nt(t,e,n)<=Es,ws=(t,e)=>Math.abs(t.x-e.x)<=Es&&Math.abs(t.y-e.y)<=Es,zs=(t,e)=>{if(!e||e.length<3)return!1;for(let n=0;n<e.length;n++){const s=e[n],i=e[(n+1)%e.length];if(Ts(t,s,i))return!0}let n=!1;for(let s=0,i=e.length-1;s<e.length;i=s++){const o=e[s],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&&(n=!n)}return n},As=class extends Ms{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}),n={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 n=K(t),s=K(e),i=Math.max(n.minX-s.maxX,s.minX-n.maxX,0),o=Math.max(n.minY-s.maxY,s.minY-n.maxY,0);return Math.hypot(i,o)}(n,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 n=t.route,s=[];for(let t=0;t<n.length-1;t++){const i=n[t],o=n[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&&s.push([i,o])}return s}),this.segmentTree=new _s(this.filteredObstaclePathSegments),this.filteredVias=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const n=t.vias,s=[];for(const i of n){const n=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2+t.viaDiameter/2,o=i.x-n,a=i.x+n,r=i.y-n,h=i.y+n;o<=e.maxX&&a>=e.minX&&r<=e.maxY&&h>=e.minY&&s.push({...i,diameter:t.viaDiameter})}return s}),this.computePathSegments()}computePathSegments(){let t=0;for(let e=0;e<this.inputRoute.route.length-1;e++){const n=this.inputRoute.route[e],s=this.inputRoute.route[e+1],i=Math.sqrt((s.x-n.x)**2+(s.y-n.y)**2)+e/1e4;this.pathSegments.push({start:n,end:s,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 n=(t-e.startDistance)/e.length;return{x:e.start.x+n*(e.end.x-e.start.x),y:e.start.y+n*(e.end.y-e.start.y),z:n<.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 n=this.pathSegments[e],s=(n.startDistance+n.endDistance)/2;return t>s?e+1:e}isValidPathSegment(t,e){for(const n of this.filteredObstacles){if(!n.zLayers?.includes(t.z))continue;if(gt(t,e,n)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2)return!1}const n=this.segmentTree.getSegmentsThatCouldIntersect(t,e);for(const[s,i,o]of n)if(s.z===t.z&&i.z===t.z){if(Ns({x:t.x,y:t.y},{x:e.x,y:e.y},{x:s.x,y:s.y},{x:i.x,y:i.y})<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS)return!1}for(const n of this.filteredVias)if(nt(n,t,e)<this.OBSTACLE_MARGIN+n.diameter/2+this.TRACE_THICKNESS/2)return!1;if(this.outline&&this.outline.length>=3){const n=(({start:t,end:e,polygon:n,margin:s=.2})=>{if(!n||n.length<3)return!1;const i=zs(t,n),o=zs(e,n);if(!i||!o)return!0;for(let i=0;i<n.length;i++){const o=n[i],a=n[(i+1)%n.length],r=Ts(t,o,a),h=Ts(e,o,a);if(r&&h)continue;if(!Q(t,e,o,a)){if(!r&&!h&&Ns(t,e,o,a)<s-Es)return!0;continue}const c=it(t,e,o,a);if(!(c&&(r&&ws(c,t)||h&&ws(c,e))||c&&(ws(c,t)||ws(c,e))))return!0}return!1})({start:{x:t.x,y:t.y},end:{x:e.x,y:e.y},polygon:this.outline});if(n)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 n=((t,e)=>{const n=[],s=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&&n.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&&n.push([t,h,e]);const c=Math.min(s,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&&n.push([t,d,e]),n})({x:t.x,y:t.y},{x:e.x,y:e.y});for(const e of n){const n=e.map(e=>({x:e.x,y:e.y,z:t.z}));if(this.isValidPath(n))return n}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],n=this.find45DegreePath(t,e);if(n)return this.addPathToResult(n),void(this.solved=!0);this.lastValidPath=null,this.tailDistanceAlongPath=this.totalPathLength,this.headDistanceAlongPath=this.totalPathLength;const s=[];for(const t of this.inputRoute.route)0!==s.length&&this.arePointsEqual(s[s.length-1],t)||s.push(t);return this.newRoute=s,this.newVias=[...this.inputRoute.vias],void(this.solved=!0)}this.moveHead(this.currentStepSize);const n=this.getPointAtDistance(this.tailDistanceAlongPath),s=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],n={x:e.x,y:e.y};this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null);const s=this.newRoute[this.newRoute.length-1];s.x===n.x&&s.y===n.y||this.newRoute.push({x:n.x,y:n.y,z:s.z}),this.newVias.push(n),this.newRoute.push({x:n.x,y:n.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(n,s);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),n=this.inputRoute.route[e],s=this.inputRoute.route[this.inputRoute.route.length-1];return void(this.arePointsEqual(t,n)||this.arePointsEqual(n,s)||this.newRoute.push(n))}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),n=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:n.x,y:n.y,color:"orange",label:["Head",`z: ${n.z}`].join("\n")});const s=this.getPointAtDistance(this.headDistanceAlongPath+this.currentStepSize);t.points.push({x:s.x,y:s.y,color:"red",label:["Tentative Head",`z: ${s.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}},Rs=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 ye({}),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 As({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 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}],strokeColor:1===e.route[n].z?"rgba(0, 0, 255, 0.4)":"rgba(255, 0, 0, 0.4)",strokeWidth:.15,strokeDash:1===e.route[n].z?[.5,.5]:void 0});for(const n of e.vias||[])t.circles.push({center:n,radius:(e.viaDiameter??this.defaultViaDiameter)/2,fill:"rgba(0, 0, 255, 0.4)"})}for(const e of this.simplifiedHdRoutes){const n=this.colorMap?.[e.connectionName]||"rgba(128, 128, 128, 0.8)";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:n,strokeDash:1===e.route[s].z?[.5,.5]:void 0,step:1});for(const n of e.vias||[])t.circles.push({center:n,radius:e.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)",step:1})}for(const e of this.unsimplifiedHdRoutes){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:"rgba(255, 0, 0, 0.2)",strokeDash:[.5,.5],step:0,layer:`z${e.route[n].z.toString()}`});for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.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}},Os=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 us("flatbush",t.obstacles),this.hdRouteSHI=new xs(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 n=0;n<e.vias.length;n++){const s=e.vias[n],i={x:s.x,y:s.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],n=this.viasByNet.get(e.net);if(!n)continue;const s=n.indexOf(e);for(let t=s>=0?s+1:0;t<n.length;t++){const s=n[t],i=e.x-s.x,o=e.y-s.y,a=i*i+o*o,r=e.diameter/2+s.diameter/2;if(a<=r*r&&0!==a)return[e,s]}}return null}handleOffendingPair(t,e){const n=t.layers.length<e.layers.length?t:e,s=n===t?e:t,i=this.mergedViaHdRoutes[n.routeIndex].route;for(let t=0;t<n.layers.length;t++)for(let t=i.length-1;t>=1;t--){const e=i[t-1],o=i[t];if(o.x===n.x&&o.y===n.y){i.splice(t,0,{x:s.x,y:s.y,z:o.z}),i.splice(t,0,{x:s.x,y:s.y,z:e.z});const a=this.mergedViaHdRoutes[n.routeIndex];return a.vias=a.vias.map(t=>t.x===n.x&&t.y===n.y?{x:s.x,y:s.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 n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),i=e.zLayers?.includes(1);s&&i?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":i&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,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 n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:0===s.z?"rgba(255, 0, 0, 0.5)":"rgba(0, 0, 255, 0.5)",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.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}},Ds=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 Ss({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 Os({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 Rs({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 n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),i=e.zLayers?.includes(1);s&&i?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":i&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.hdRoutes)if(0!==e.route.length){for(let n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:0===s.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`})}return t}};function Ls(t){const e=new Map;for(const n of t)for(const t of n.nodeIds)e.set(t,[...e.get(t)??[],n]);return e}var Fs=class extends e{nodes;edges;traceWidth;obstacleMargin;minPortSpacing;nodeMap;nodeEdgeMap;sharedEdgeSegments=[];edgeSegmentMap=new Map;portPointMap=new Map;colorMap;constructor({nodes:t,edges:e,traceWidth:n,obstacleMargin:s,colorMap:i}){super(),this.nodes=t,this.edges=e,this.traceWidth=n,this.obstacleMargin=s??.15,this.minPortSpacing=this.traceWidth+this.obstacleMargin,this.colorMap=i??{},this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ls(e),this.MAX_ITERATIONS=1}_step(){this.computeAllSharedEdgeSegments(),this.solved=!0}computeAllSharedEdgeSegments(){for(const t of this.edges){const[e,n]=t.nodeIds,s=this.nodeMap.get(e),i=this.nodeMap.get(n);if(!s||!i)continue;const o=this.computeSharedEdgeSegment(t,s,i);if(o){this.sharedEdgeSegments.push(o),this.edgeSegmentMap.set(t.capacityMeshEdgeId,o);for(const t of o.portPoints)this.portPointMap.set(t.segmentPortPointId,t)}}}computeSharedEdgeSegment(t,e,n){const s=this.findOverlappingSegment(e,n);if(!s)return null;const i=e.availableZ.filter(t=>n.availableZ.includes(t));if(0===i.length)return null;const o=Math.sqrt((s.end.x-s.start.x)**2+(s.end.y-s.start.y)**2),a=this.minPortSpacing/2,r=Math.max(0,o-2*a),h=Math.max(1,Math.floor(r/this.minPortSpacing)+1),c=[],d=s.end.x-s.start.x,l=s.end.y-s.start.y,u=(s.start.x+s.end.x)/2,p=(s.start.y+s.end.y)/2,f=[];for(let t=0;t<h;t++){let e;e=0===o||1===h?.5:(a+r*t/(h-1))/o;const n=s.start.x+d*e,i=s.start.y+l*e,c=Math.sqrt((n-u)**2+(i-p)**2);f.push({x:n,y:i,distToCenter:c})}const g=f.reduce((t,e)=>e.distToCenter<t.distToCenter?e:t);for(let s=0;s<h;s++){const{x:o,y:a}=f[s],r=Math.sqrt((o-g.x)**2+(a-g.y)**2);for(const h of i){const i={segmentPortPointId:`${t.capacityMeshEdgeId}_pp${s}_z${h}`,x:o,y:a,availableZ:[h],nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],edgeId:t.capacityMeshEdgeId,connectionName:null,distToCentermostPortOnZ:r};c.push(i)}}return{edgeId:t.capacityMeshEdgeId,nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],start:s.start,end:s.end,availableZ:i,portPoints:c}}findOverlappingSegment(t,e){const n={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)},s={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)},i=n.end-n.start,o=s.end-s.start;if(i<-1e-4||o<-1e-4)return null;if(i<o){const t=(n.start+n.end)/2;return{start:{x:t,y:s.start},end:{x:t,y:s.end}}}{const t=(s.start+s.end)/2;return{start:{x:n.start,y:t},end:{x:n.end,y:t}}}}getAvailablePortPointsBetweenNodes(t,e){const n=this.edges.find(n=>n.nodeIds[0]===t&&n.nodeIds[1]===e||n.nodeIds[0]===e&&n.nodeIds[1]===t);if(!n)return[];const s=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return s?s.portPoints.filter(t=>null===t.connectionName):[]}getPortPointsForEdge(t,e){const n=this.edges.find(n=>n.nodeIds[0]===t&&n.nodeIds[1]===e||n.nodeIds[0]===e&&n.nodeIds[1]===t);if(!n)return[];const s=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return s?.portPoints??[]}assignPortPoint(t,e,n){const s=this.portPointMap.get(t);return!!s&&(null===s.connectionName&&(s.connectionName=e,s.rootConnectionName=n,!0))}releasePortPoint(t){const e=this.portPointMap.get(t);return!!e&&(e.connectionName=null,e.rootConnectionName=void 0,!0)}getAvailablePortCountForEdge(t,e){return this.getAvailablePortPointsBetweenNodes(t,e).length}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.sharedEdgeSegments){t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.5)"});for(const n of e.portPoints){const e=n.connectionName?this.colorMap[n.connectionName]??"blue":"rgba(0, 200, 0, 0.7)";t.circles.push({center:{x:n.x,y:n.y},radius:this.traceWidth/2,fill:e,layer:`z${n.availableZ.join(",")}`,label:[n.segmentPortPointId,n.connectionName,n.availableZ.join(","),`cd: ${n.distToCentermostPortOnZ}`,`connects: ${n.nodeIds.join(",")}`].filter(Boolean).join("\n")})}}return t}},$s=(t,e,n,s)=>{if(t?._containsTarget)return 0;return((.82*e+.41*n+.2*s)/2)**1.1/ve(t)};var ks=class extends e{hyperParameters;simpleRouteJson;inputNodes;nodeMap;nodePortPointsMap;portPointMap;connectionsWithResults=[];assignedPortPoints=new Map;nodeAssignedPortPoints=new Map;PORT_POINT_REUSE_FACTOR=1e3;get NODE_PF_FACTOR(){return this.hyperParameters.NODE_PF_FACTOR??50}get MEMORY_PF_FACTOR(){return this.hyperParameters.MEMORY_PF_FACTOR??0}get CENTER_OFFSET_FOCUS_SHIFT(){return this.hyperParameters.CENTER_OFFSET_FOCUS_SHIFT??0}get RANDOM_COST_MAGNITUDE(){return this.hyperParameters.RANDOM_COST_MAGNITUDE??0}get BASE_CANDIDATE_COST(){return this.hyperParameters.BASE_CANDIDATE_COST??0}Z_DIST_COST=0;get CENTER_OFFSET_DIST_PENALTY_FACTOR(){return this.hyperParameters.CENTER_OFFSET_DIST_PENALTY_FACTOR??0}colorMap;get GREEDY_MULTIPLIER(){return this.hyperParameters.GREEDY_MULTIPLIER??1.3}MAX_CANDIDATES_IN_MEMORY=5e4;get MAX_ITERATIONS_PER_PATH(){return this.hyperParameters.MAX_ITERATIONS_PER_PATH??4e3}nodeMemoryPfMap;currentConnectionIndex=0;currentPathIterations=0;candidates;visitedPortPoints;connectionNameToGoalNodeIds;capacityMeshNodeMap;avgNodePitch=1;baseNodeCostCache=new Map;segmentDeltaCostCache=new Map;constructor({simpleRouteJson:t,inputNodes:e,capacityMeshNodes:n,colorMap:s,nodeMemoryPfMap:i,hyperParameters:o}){super(),this.MAX_ITERATIONS=5e4,this.simpleRouteJson=t,this.inputNodes=e,this.colorMap=s??{},this.capacityMeshNodeMap=new Map(n.map(t=>[t.capacityMeshNodeId,t])),this.nodeMemoryPfMap=i??new Map,this.hyperParameters=o??{SHUFFLE_SEED:0},this.nodeMap=new Map(e.map(t=>[t.capacityMeshNodeId,t]));const a=e.map(t=>(t.width+t.height)/2).filter(t=>Number.isFinite(t)&&t>0);this.avgNodePitch=a.length>0?a.reduce((t,e)=>t+e,0)/a.length:1,this.portPointMap=new Map,this.nodePortPointsMap=new Map;for(const t of e)this.nodePortPointsMap.set(t.capacityMeshNodeId,[]),this.nodeAssignedPortPoints.set(t.capacityMeshNodeId,[]);for(const t of e)for(const e of t.portPoints){this.portPointMap.set(e.portPointId,e);for(const t of e.connectionNodeIds){const n=this.nodePortPointsMap.get(t);n&&!n.some(t=>t.portPointId===e.portPointId)&&n.push(e)}}const{connectionsWithResults:r,connectionNameToGoalNodeIds:h}=this.getConnectionsWithNodes();this.connectionsWithResults=r,this.connectionNameToGoalNodeIds=h}clearCostCaches(){this.baseNodeCostCache.clear(),this.segmentDeltaCostCache.clear()}clampPf(t){return Number.isFinite(t)?Math.min(Math.max(t,0),.999999):.999999}pfToFailureCost(t){const e=this.clampPf(t);return-Math.log(1-e)}round3(t){return Math.round(1e3*t)/1e3}pointKey(t,e){return`${this.round3(t.x)},${this.round3(t.y)},${e}`}getBaseNodeFailureCost(t){const e=this.baseNodeCostCache.get(t);if(null!=e)return e;const n=this.nodeMap.get(t);if(!n)return 0;const s=this.computeNodePf(n),i=this.pfToFailureCost(s);return this.baseNodeCostCache.set(t,i),i}getNodeDeltaFailureCostForSegment(t,e,n){const s=`${t}|${this.pointKey({x:e.x,y:e.y},e.z)}|${this.pointKey({x:n.x,y:n.y},n.z)}|${e.connectionName}|${e.rootConnectionName??""}`,i=this.segmentDeltaCostCache.get(s);if(null!=i)return i;const o=this.nodeMap.get(t);if(!o)return 0;const a=this.getBaseNodeFailureCost(t),r=this.computeNodePf(o,[e,n]),h=this.pfToFailureCost(r),c=Math.max(0,h-a)*this.NODE_PF_FACTOR;return this.segmentDeltaCostCache.set(s,c),c}getConnectionsWithNodes(){let t=[];const e=this.inputNodes.filter(t=>t._containsTarget),n=new Map;for(const s of this.simpleRouteJson.connections){const i=[];for(const t of s.pointsToConnect){let n=this.inputNodes[0],s=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<s&&(s=e,n=i)}i.push(n)}if(i.length<2)throw new Error(`Not enough nodes for connection "${s.name}", only ${i.length} found`);n.set(s.name,i.map(t=>t.capacityMeshNodeId)),t.push({connection:s,nodeIds:[i[0].capacityMeshNodeId,i[i.length-1].capacityMeshNodeId],straightLineDistance:st(i[0].center,i[i.length-1].center)})}return t=Pt(t,this.hyperParameters.SHUFFLE_SEED??0),{connectionsWithResults:t,connectionNameToGoalNodeIds:n}}buildNodeWithPortPointsForCrossing(t,e){const n=this.nodeAssignedPortPoints.get(t.capacityMeshNodeId)??[],s=e?[...n,...e]:n;return{capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:s,availableZ:t.availableZ}}computeNodePf(t,e){if(t._containsTarget)return 0;const n=this.buildNodeWithPortPointsForCrossing(t,e),s=jt(n);return $s(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),s.numSameLayerCrossings,s.numEntryExitLayerChanges,s.numTransitionPairCrossings)}getPortPointReusePenalty(t,e){const n=this.assignedPortPoints.get(t);return n?e===n.rootConnectionName?0:this.PORT_POINT_REUSE_FACTOR:0}getOtherNodeId(t,e){const[n,s]=t.connectionNodeIds;return n===e?s:s===e?n:null}computeG(t,e,n,s,i){const o=t.currentNodeId,a=t.point,r=st(a,{x:e.x,y:e.y}),h={x:a.x,y:a.y,z:t.z,connectionName:s,rootConnectionName:i},c={x:e.x,y:e.y,z:e.z,connectionName:s,rootConnectionName:i},d=this.getNodeDeltaFailureCostForSegment(o,h,c),l=this.getPortPointReusePenalty(e.portPointId,i),u=(e.distToCentermostPortOnZ-this.CENTER_OFFSET_FOCUS_SHIFT)**2*this.CENTER_OFFSET_DIST_PENALTY_FACTOR;return t.g+this.BASE_CANDIDATE_COST+r+d+l+u}computeGToEndTarget(t,e,n,s){const i=t.currentNodeId,o=st(t.point,e),a={x:t.point.x,y:t.point.y,z:t.z,connectionName:n,rootConnectionName:s},r={x:e.x,y:e.y,z:t.z,connectionName:n,rootConnectionName:s},h=this.getNodeDeltaFailureCostForSegment(i,a,r);return t.g+this.BASE_CANDIDATE_COST+o+h}computeH(t,e,n,s){const i=this.nodeMap.get(n);if(!i)return 0;const o=st(t,i.center),a=this.avgNodePitch>0?o/this.avgNodePitch:0,r=(this.clampPf(this.nodeMemoryPfMap.get(e)??0)+this.clampPf(this.nodeMemoryPfMap.get(n)??0))/2,h=a*(this.pfToFailureCost(r)*this.MEMORY_PF_FACTOR);return o+a*this.BASE_CANDIDATE_COST+h+(!i.availableZ.includes(s)?this.Z_DIST_COST:0)}getAvailableExitPortPoints(t){const e=this.connectionsWithResults[this.currentConnectionIndex],n=e?.connection.rootConnectionName,s=this.nodePortPointsMap.get(t)??[],i=[];for(const t of s){if(this.visitedPortPoints?.has(t.portPointId))continue;const e=this.assignedPortPoints.get(t.portPointId);e&&e?.rootConnectionName!==n||i.push(t)}return i}getAvailableExitPortPointsWithOmissions(t,e){const n=this.nodePortPointsMap.get(t)??[],s=this.connectionsWithResults[this.currentConnectionIndex],i=s?.connection.rootConnectionName,o=new Map;for(const e of n){if(this.visitedPortPoints?.has(e.portPointId))continue;const n=this.getOtherNodeId(e,t);if(!n)continue;const s=`${n}|${e.z}`,i=o.get(s)??[];i.push(e),o.set(s,i)}const a=[];for(const[,t]of o){t.sort((t,e)=>t.distToCentermostPortOnZ-e.distToCentermostPortOnZ);const e=t[0];if(!e)continue;const n=this.assignedPortPoints.get(e.portPointId),s=n&&n.rootConnectionName===i;if(!n||s){a.push(e);continue}const o=[];for(let e=1;e<t.length;e++)this.assignedPortPoints.has(t[e].portPointId)||o.push(t[e]);a.push(...o)}return a}canTravelThroughObstacle(t,e){const n=this.connectionNameToGoalNodeIds.get(e);return n?.includes(t.capacityMeshNodeId)??!1}isAtEndGoal(t,e){return t===e}getBacktrackedPath(t){const e=[];let n=t;for(;n;)e.push(n),n=n.prevCandidate;return e.reverse()}assignPortPointsForPath(t,e,n){const s=[];for(const i of t){if(!i.portPoint)continue;const t=i.portPoint;this.assignedPortPoints.set(t.portPointId,{connectionName:e,rootConnectionName:n});const o={x:t.x,y:t.y,z:t.z,connectionName:e,rootConnectionName:n};s.push(o);for(const e of t.connectionNodeIds){const t=this.nodeAssignedPortPoints.get(e)??[];t.push(o),this.nodeAssignedPortPoints.set(e,t)}}return s}addTargetPointsToNodes(t,e){const n=t[0],s=t[t.length-1],i=e.pointsToConnect[0],o=e.pointsToConnect[e.pointsToConnect.length-1];if(n&&i){const t=this.nodeAssignedPortPoints.get(n.currentNodeId)??[];t.push({x:i.x,y:i.y,z:n.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(n.currentNodeId,t)}if(s&&o){const t=this.nodeAssignedPortPoints.get(s.currentNodeId)??[];t.push({x:o.x,y:o.y,z:s.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(s.currentNodeId,t)}}isPortPointInPathChain(t,e){let n=t;for(;n;){if(n.portPoint?.portPointId===e)return!0;n=n.prevCandidate}return!1}isNodeInPathChain(t,e){let n=t;for(;n;){if(n.currentNodeId===e)return!0;n=n.prevCandidate}return!1}_step(){const t=this.connectionsWithResults[this.currentConnectionIndex];if(!t)return void(this.solved=!0);if(this.currentPathIterations++,this.currentPathIterations>this.MAX_ITERATIONS_PER_PATH)return this.currentConnectionIndex++,this.candidates=null,this.visitedPortPoints=null,this.currentPathIterations=0,this.failed=!0,void(this.error=`Exceeded MAX_ITERATIONS_PER_PATH (${this.MAX_ITERATIONS_PER_PATH}) on connection ${t.connection.name}`);const[e,n]=t.nodeIds,s=this.nodeMap.get(e),i=this.nodeMap.get(n);if(!s||!i)return this.currentConnectionIndex++,void(this.currentPathIterations=0);const o=t.connection.name,a=t.connection.rootConnectionName,r=t.connection.pointsToConnect[0];if(!this.candidates){this.clearCostCaches(),this.candidates=[],this.visitedPortPoints=new Set;for(const t of s.availableZ){const i=r?{x:r.x,y:r.y}:s.center,o=this.computeH(i,e,n,t),a=0+o*this.GREEDY_MULTIPLIER;this.candidates.push({prevCandidate:null,portPoint:null,currentNodeId:e,point:i,z:t,f:a,g:0,h:o})}}this.candidates.sort((t,e)=>t.f-e.f);const h=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),!h)return this.error=`Ran out of candidates on connection ${o}`,this.currentConnectionIndex++,this.candidates=null,this.visitedPortPoints=null,this.currentPathIterations=0,void(this.failed=!0);if(this.isAtEndGoal(h.currentNodeId,n)){const e=t.connection.pointsToConnect[t.connection.pointsToConnect.length-1],s=e?{x:e.x,y:e.y}:i.center,r=this.computeGToEndTarget(h,s,o,a),c={prevCandidate:h,portPoint:null,currentNodeId:n,point:s,z:h.z,g:r,h:0,f:r},d=this.getBacktrackedPath(c);return t.path=d,t.portPoints=this.assignPortPointsForPath(d,o,a),this.addTargetPointsToNodes(d,t.connection),this.clearCostCaches(),this.currentConnectionIndex++,this.candidates=null,this.visitedPortPoints=null,void(this.currentPathIterations=0)}const c=this.getAvailableExitPortPointsWithOmissions(h.currentNodeId,n);for(const t of c){if(this.isPortPointInPathChain(h,t.portPointId))continue;const e=this.getOtherNodeId(t,h.currentNodeId);if(!e)continue;if(this.isNodeInPathChain(h,e))continue;const s=this.nodeMap.get(e);if(!s)continue;if(s._containsObstacle&&!this.canTravelThroughObstacle(s,o))continue;const i=this.computeG(h,t,e,o,a),r=this.computeH({x:t.x,y:t.y},e,n,t.z),c=this.RANDOM_COST_MAGNITUDE*Nt(this.iterations)(),d=i+r*this.GREEDY_MULTIPLIER+c;this.candidates.push({prevCandidate:h,portPoint:t,currentNodeId:e,point:{x:t.x,y:t.y},z:t.z,f:d,g:i,h:r})}h.portPoint&&this.visitedPortPoints&&this.visitedPortPoints.add(h.portPoint.portPointId)}getNodesWithPortPoints(){const t=[];for(const e of this.inputNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];n.length>0&&t.push({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ})}return t}visualize(){return function(t){const e={lines:[],points:[],rects:[],circles:[]};for(const n of t.inputNodes){const s=t.computeNodePf(n),i=t.nodeMemoryPfMap.get(n.capacityMeshNodeId)??0,o=Math.min(255,Math.floor(512*s)),a=Math.max(0,255-Math.floor(512*s)),r=`rgba(${o}, ${a}, ${a}, 0.3)`,h=t.buildNodeWithPortPointsForCrossing(n),c=jt(h);e.rects.push({center:n.center,width:.9*n.width,height:.9*n.height,layer:`z${n.availableZ.join(",")}`,fill:r,label:`${n.capacityMeshNodeId}\npf: ${s.toFixed(3)}, memPf: ${i.toFixed(3)}\nxSame: ${c.numSameLayerCrossings}, xLC: ${c.numEntryExitLayerChanges}, xTransition: ${c.numTransitionPairCrossings}`})}for(const[n,s]of t.portPointMap){const i=t.assignedPortPoints.get(n),o=i?t.colorMap[i.connectionName]??"blue":"rgba(150, 150, 150, 0.5)";e.circles.push({center:{x:s.x,y:s.y},radius:.05,fill:o,layer:`z${s.z}`,label:[n,`conn: ${i?.connectionName}`,`cd: ${s.distToCentermostPortOnZ}`,`connects: ${s.connectionNodeIds.join(",")}`,`rootConn: ${i?.rootConnectionName}`].filter(Boolean).join("\n")})}for(const n of t.connectionsWithResults){if(!n.path)continue;const s=n.connection,i=t.colorMap[s.name]??"blue",o=[];for(const t of n.path)o.push({x:t.point.x,y:t.point.y,z:t.z});for(let t=0;t<o.length-1;t++){const n=o[t],s=o[t+1],a=n.z===s.z,r=n.z;let h;h=a?0===r?void 0:"10 5":"3 3 10",e.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.y}],strokeColor:i,strokeDash:h})}}if(!t.solved&&t.candidates&&t.candidates.length>0){const n=t.connectionsWithResults[t.currentConnectionIndex],s=n?t.colorMap[n.connection.name]??"blue":"blue";if(n){const[i,o]=n.nodeIds,a=t.nodeMap.get(i),r=t.nodeMap.get(o),h=n.connection.pointsToConnect[0],c=n.connection.pointsToConnect[n.connection.pointsToConnect.length-1];if(a&&r){const t=h?{x:h.x,y:h.y}:a.center,i=c?{x:c.x,y:c.y}:r.center;e.lines.push({points:[t,i],strokeColor:H(s,.5),strokeDash:"5 5"}),e.points.push({x:t.x,y:t.y,color:s,label:[`Start: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.points.push({x:i.x,y:i.y,color:s,label:[`End: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.circles.push({center:i,radius:.08,stroke:s,label:`Goal: ${n.connection.name}`})}}const i=[...t.candidates].sort((t,e)=>t.f-e.f).slice(0,20);for(const o of i){const i=[];let a=o;for(;a;)i.unshift({x:a.point.x,y:a.point.y,z:a.z}),a=a.prevCandidate;for(let t=0;t<i.length-1;t++){const n=i[t],o=i[t+1],a=n.z===o.z,r=n.z;let h;h=a?0===r?void 0:"10 5":"3 3 10",e.lines.push({points:[{x:n.x+.02*n.z,y:n.y+.02*n.z},{x:o.x+.02*o.z,y:o.y+.02*o.z}],strokeColor:H(s,.25),strokeDash:h})}if(i.length>=1){const a=i[i.length-1];let r=0,h=0,c=0,d=0,l=0;const u=t.nodeMap.get(o.prevCandidate?.currentNodeId);if(u&&o.prevCandidate&&o.portPoint){const e=n.connection.name,s={x:o.prevCandidate.point.x,y:o.prevCandidate.point.y,z:o.prevCandidate.z,connectionName:e},i={x:o.portPoint.x,y:o.portPoint.y,z:o.portPoint.z,connectionName:e},a=t.buildNodeWithPortPointsForCrossing(u,[s,i]),p=jt(a);c=p.numSameLayerCrossings,d=p.numTransitionPairCrossings,l=p.numEntryExitLayerChanges;const f=t.capacityMeshNodeMap.get(u.capacityMeshNodeId);f&&(h=$s(f,c,l,d),r=h**2*t.NODE_PF_FACTOR)}e.circles.push({center:a,radius:.03,fill:H(s,.25),layer:`z${o.z}`,label:[`f: ${o.f.toFixed(2)}`,`g: ${o.g.toFixed(2)}`,`h: ${o.h.toFixed(2)}`,`z: ${o.z}`,`node: ${o.currentNodeId}`,`Cost(Pf): ${r.toFixed(3)}`,`Pf: ${h.toFixed(3)}`,`xSame: ${c}, xTrans: ${d}, xLC: ${l}`].join("\n")})}}}return e}(this)}};function Xs(t,e){let n=0;for(const s of t){const t=e.get(s.capacityMeshNodeId);if(!t)continue;if(t._containsTarget)continue;const i=jt(s),o=Math.min($s(t,i.numSameLayerCrossings,i.numEntryExitLayerChanges,i.numTransitionPairCrossings),.999999);n+=Math.log(1-o)}return n}function Ys(t,e){if(e._containsTarget)return 0;const n=jt(t);return $s(e,n.numSameLayerCrossings,n.numEntryExitLayerChanges,n.numTransitionPairCrossings)}var Bs=[{SHUFFLE_SEED:3,EXPANSION_DEGREES:8,CENTER_OFFSET_DIST_PENALTY_FACTOR:0}],Hs=class extends e{simpleRouteJson;inputNodes;capacityMeshNodes;capacityMeshEdges;colorMap;nodeMap;capacityMeshNodeMap;connectionResults;assignedPortPoints;nodeAssignedPortPoints;sections=[];activeSubSolver=null;currentSection=null;sectionScoreBeforeOptimization=0;currentSectionCenterNodeId=null;currentScheduleIndex=0;nodePfMap=new Map;attemptsToFixNode=new Map;sectionAttempts=0;MAX_ATTEMPTS_PER_NODE=25;MAX_SECTION_ATTEMPTS=500;ACCEPTABLE_PF=.1;constructor(t){super(),this.MAX_ITERATIONS=1e6,this.simpleRouteJson=t.simpleRouteJson,this.inputNodes=t.inputNodes,this.capacityMeshNodes=t.capacityMeshNodes,this.capacityMeshEdges=t.capacityMeshEdges,this.colorMap=t.colorMap??{},this.nodeMap=new Map(t.inputNodes.map(t=>[t.capacityMeshNodeId,t])),this.capacityMeshNodeMap=new Map(t.capacityMeshNodes.map(t=>[t.capacityMeshNodeId,t])),this.connectionResults=[...t.initialConnectionResults],this.assignedPortPoints=new Map(t.initialAssignedPortPoints),this.nodeAssignedPortPoints=new Map(t.initialNodeAssignedPortPoints),this.nodePfMap=this.computeInitialPfMap();const e=this.computeBoardScore();this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.nodesExamined=0,this.stats.sectionAttempts=0,this.stats.sectionScores={},this.stats.initialBoardScore=e,this.stats.currentBoardScore=e,this.stats.errors=0}computeInitialPfMap(){const t=new Map;for(const e of this.capacityMeshNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];if(0===n.length)continue;const s=Ys({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ},e);t.set(e.capacityMeshNodeId,s)}return t}computeBoardScore(){return Xs(this.getNodesWithPortPoints(),this.capacityMeshNodeMap)}recomputePfForNodes(t){for(const e of t){const t=this.capacityMeshNodeMap.get(e);if(!t)continue;const n=this.nodeAssignedPortPoints.get(e)??[];if(0===n.length){this.nodePfMap.set(e,0);continue}const s=Ys({capacityMeshNodeId:e,center:t.center,width:t.width,height:t.height,portPoints:n,availableZ:t.availableZ},t);this.nodePfMap.set(e,s)}}getCreatePortPointSectionInput(){return{inputNodes:this.inputNodes,capacityMeshNodes:this.capacityMeshNodes,capacityMeshEdges:this.capacityMeshEdges,nodeMap:this.nodeMap,connectionResults:this.connectionResults}}createSection(t){return function(t,e){const{inputNodes:n,capacityMeshNodes:s,capacityMeshEdges:i,connectionResults:o}=t,{centerOfSectionCapacityNodeId:a,expansionDegrees:r}=e,h=new Map;for(const t of i){const[e,n]=t.nodeIds;h.has(e)||h.set(e,new Set),h.has(n)||h.set(n,new Set),h.get(e).add(n),h.get(n).add(e)}const c=new Set,d=new Set,l=[];for(l.push({nodeId:a,depth:0}),d.add(a);l.length>0;){const{nodeId:t,depth:e}=l.shift();if(c.add(t),e<r){const n=h.get(t)??new Set;for(const t of n)d.has(t)||(d.add(t),l.push({nodeId:t,depth:e+1}))}}const u=n.filter(t=>c.has(t.capacityMeshNodeId)),p=(new Map(s.map(t=>[t.capacityMeshNodeId,t])),s.filter(t=>c.has(t.capacityMeshNodeId))),f=[],g=[];for(const t of i){const[e,n]=t.nodeIds,s=c.has(e),i=c.has(n);s&&i?f.push(t):(s||i)&&g.push(t)}const m=u.map(t=>{const e=t.portPoints.filter(t=>{const[e,n]=t.connectionNodeIds,s=c.has(e),i=c.has(n);return s||i});return{...t,portPoints:e}}),y=function(t,e){const n=[];for(const s of t){if(!s.path||0===s.path.length)continue;const t=s.connection.name,i=s.connection.rootConnectionName;let o=null;for(let a=0;a<s.path.length;a++){const r=s.path[a];if(e.has(r.currentNodeId))null===o&&(o=a);else if(null!==o){const e=s.path.slice(o,a);n.push({connectionName:t,rootConnectionName:i,points:e.map(t=>({x:t.point.x,y:t.point.y,z:t.z,nodeId:t.currentNodeId})),originalStartIndex:o,originalEndIndex:a-1,hasEntryFromOutside:o>0,hasExitToOutside:!0}),o=null}}if(null!==o){const e=s.path.slice(o);n.push({connectionName:t,rootConnectionName:i,points:e.map(t=>({x:t.point.x,y:t.point.y,z:t.z,nodeId:t.currentNodeId})),originalStartIndex:o,originalEndIndex:s.path.length-1,hasEntryFromOutside:o>0,hasExitToOutside:!1})}}return n}(o??[],c);return{centerNodeId:a,expansionDegrees:r,nodeIds:c,inputNodes:m,capacityMeshNodes:p,internalEdges:f,boundaryEdges:g,sectionPaths:y}}(this.getCreatePortPointSectionInput(),t)}getSectionNodesWithPortPoints(t){const e=[];for(const n of t.nodeIds){const t=this.nodeMap.get(n),s=this.capacityMeshNodeMap.get(n);if(!t||!s)continue;const i=this.nodeAssignedPortPoints.get(n)??[];i.length>0&&e.push({capacityMeshNodeId:n,center:t.center,width:t.width,height:t.height,portPoints:i,availableZ:t.availableZ})}return e}getNodesWithPortPoints(){const t=[];for(const e of this.inputNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];n.length>0&&t.push({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ})}return t}findHighestPfNode(){let t=null,e=0;for(const[n,s]of this.nodePfMap.entries()){s*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_ATTEMPTS_PER_NODE)**2>e&&(e=s,t=n)}return!t||e<this.ACCEPTABLE_PF?null:t}currentSectionCutPathInfo=new Map;createSectionSimpleRouteJson(t){const e=[];this.currentSectionCutPathInfo.clear();for(const n of this.connectionResults){if(!n.path||0===n.path.length)continue;const[s,i]=n.nodeIds,o=t.nodeIds.has(s),a=t.nodeIds.has(i);o&&a&&e.push(n.connection)}for(const n of t.sectionPaths){if(!n.hasEntryFromOutside&&!n.hasExitToOutside)continue;if(n.points.length<2)continue;const t=this.connectionResults.find(t=>t.connection.name===n.connectionName);if(!t)continue;const s=`__cut__${n.connectionName}__${n.originalStartIndex}`;this.colorMap[s]=this.colorMap[n.connectionName];const i=n.points[0],o=n.points[n.points.length-1],a={name:s,rootConnectionName:n.rootConnectionName??n.connectionName,pointsToConnect:[{x:i.x,y:i.y,layers:[`layer${i.z+1}`]},{x:o.x,y:o.y,layers:[`layer${o.z+1}`]}]};e.push(a),this.currentSectionCutPathInfo.set(s,{sectionPath:n,originalConnectionResult:t})}return{...this.simpleRouteJson,connections:e}}prepareSectionInputNodesForCutPaths(t){const e=new Set;for(const[,t]of this.currentSectionCutPathInfo.entries()){const{sectionPath:n}=t;if(0===n.points.length)continue;const s=n.points[0].nodeId;e.add(s);const i=n.points[n.points.length-1].nodeId;e.add(i)}return t.inputNodes.map(t=>e.has(t.capacityMeshNodeId)?{...t,_containsTarget:!0}:t)}getHyperParametersForAttempt(t){return{...Bs[t%Bs.length],SHUFFLE_SEED:(Bs[t%Bs.length].SHUFFLE_SEED??0)+1700*t}}reattachSection(t,e,n,s){const i=[],o=[];for(const t of e)t.connection.name.startsWith("__cut__")?o.push(t):i.push(t);const a=new Set(i.map(t=>t.connection.name));this.connectionResults=this.connectionResults.filter(t=>!a.has(t.connection.name)),this.connectionResults.push(...i);for(const[t,e]of this.nodeAssignedPortPoints.entries()){const n=e.filter(t=>!a.has(t.connectionName));this.nodeAssignedPortPoints.set(t,n)}for(const[t,e]of this.assignedPortPoints.entries())a.has(e.connectionName)&&this.assignedPortPoints.delete(t);for(const e of o){const n=this.currentSectionCutPathInfo.get(e.connection.name);if(!n||!e.path)continue;const{sectionPath:s,originalConnectionResult:i}=n,o=i.path;if(!o)continue;const a=s.connectionName;for(const[e,n]of this.nodeAssignedPortPoints.entries()){const s=n.filter(n=>n.connectionName!==a||!t.nodeIds.has(e));this.nodeAssignedPortPoints.set(e,s)}const r=o.slice(0,s.originalStartIndex),h=o.slice(s.originalEndIndex+1),c=[];let d=r.length>0?r[r.length-1]:null;for(const t of e.path){const e={...t,prevCandidate:d};c.push(e),d=e}if(h.length>0&&c.length>0&&(h[0]={...h[0],prevCandidate:c[c.length-1]}),i.path=[...r,...c,...h],e.portPoints)for(const n of e.portPoints){const e={...n,connectionName:a,rootConnectionName:s.rootConnectionName??a};for(const s of t.inputNodes)for(const t of s.portPoints)if(Math.abs(t.x-n.x)<.001&&Math.abs(t.y-n.y)<.001&&t.z===n.z){for(const n of t.connectionNodeIds){const t=this.nodeAssignedPortPoints.get(n)??[];t.push(e),this.nodeAssignedPortPoints.set(n,t)}break}}}for(const[t,e]of n.entries())e.connectionName.startsWith("__cut__")||this.assignedPortPoints.set(t,e);for(const[t,e]of s.entries()){const n=e.filter(t=>!t.connectionName.startsWith("__cut__"));if(n.length>0){const e=this.nodeAssignedPortPoints.get(t)??[];this.nodeAssignedPortPoints.set(t,[...e,...n])}}}_step(){if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved||this.activeSubSolver.failed){if(this.activeSubSolver.failed){if(this.currentScheduleIndex++,this.activeSubSolver.error&&this.stats.errors++,this.currentScheduleIndex<Bs.length&&this.currentSectionCenterNodeId){const t=Bs[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:this.currentSectionCenterNodeId,expansionDegrees:t.EXPANSION_DEGREES});const e=this.createSectionSimpleRouteJson(this.currentSection),n=this.prepareSectionInputNodesForCutPaths(this.currentSection);this.activeSubSolver=new ks({simpleRouteJson:e,inputNodes:n,capacityMeshNodes:this.currentSection.capacityMeshNodes,colorMap:this.colorMap,nodeMemoryPfMap:this.nodePfMap,hyperParameters:this.getHyperParametersForAttempt(this.sectionAttempts)})}else this.stats.failedOptimizations++,this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0;return}const t=Xs(this.activeSubSolver.getNodesWithPortPoints(),this.capacityMeshNodeMap),e=`attempt${this.sectionAttempts}`;if(t>this.sectionScoreBeforeOptimization){const t=this.stats.currentBoardScore,n=[...this.connectionResults],s=new Map(this.assignedPortPoints),i=new Map(Array.from(this.nodeAssignedPortPoints.entries()).map(([t,e])=>[t,[...e]]));this.reattachSection(this.currentSection,this.activeSubSolver.connectionsWithResults,this.activeSubSolver.assignedPortPoints,this.activeSubSolver.nodeAssignedPortPoints),this.recomputePfForNodes(this.currentSection.nodeIds);const o=this.computeBoardScore();this.stats.sectionScores[e]=o,o>t?(this.stats.successfulOptimizations++,this.stats.currentBoardScore=o):(this.connectionResults=n,this.assignedPortPoints=s,this.nodeAssignedPortPoints=i,this.recomputePfForNodes(this.currentSection.nodeIds),this.stats.failedOptimizations++),this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0}else if(this.currentScheduleIndex++,this.currentScheduleIndex<Bs.length&&this.currentSectionCenterNodeId){const t=Bs[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:this.currentSectionCenterNodeId,expansionDegrees:t.EXPANSION_DEGREES});const e=this.createSectionSimpleRouteJson(this.currentSection),n=this.prepareSectionInputNodesForCutPaths(this.currentSection);this.activeSubSolver=new ks({simpleRouteJson:e,inputNodes:n,capacityMeshNodes:this.currentSection.capacityMeshNodes,colorMap:this.colorMap,nodeMemoryPfMap:this.nodePfMap,hyperParameters:this.getHyperParametersForAttempt(this.sectionAttempts)})}else this.stats.failedOptimizations++,this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0}return}if(this.sectionAttempts>=this.MAX_SECTION_ATTEMPTS)return void(this.solved=!0);const t=this.findHighestPfNode();if(!t)return void(this.solved=!0);this.sectionAttempts++,this.stats.sectionAttempts=this.sectionAttempts,this.stats.nodesExamined++,this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.currentSectionCenterNodeId=t,this.currentScheduleIndex=0;const e=Bs[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:t,expansionDegrees:e.EXPANSION_DEGREES});const n=this.getSectionNodesWithPortPoints(this.currentSection);this.sectionScoreBeforeOptimization=Xs(n,this.capacityMeshNodeMap);const s=this.createSectionSimpleRouteJson(this.currentSection);if(0===s.connections.length)return this.currentSection=null,void(this.currentSectionCenterNodeId=null);const i=this.prepareSectionInputNodesForCutPaths(this.currentSection);this.activeSubSolver=new ks({simpleRouteJson:s,inputNodes:i,capacityMeshNodes:this.currentSection.capacityMeshNodes,colorMap:this.colorMap,nodeMemoryPfMap:this.nodePfMap,hyperParameters:this.getHyperParametersForAttempt(this.sectionAttempts)})}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();if(this.currentSection)return function(t,e){const n={lines:[],points:[],rects:[],circles:[]};for(const e of t.inputNodes){const s=e.capacityMeshNodeId===t.centerNodeId,i=s?"rgba(0, 200, 0, 0.3)":"rgba(200, 200, 200, 0.3)";n.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,layer:`z${e.availableZ.join(",")}`,fill:i,label:`${e.capacityMeshNodeId}${s?" (CENTER)":""}`})}for(const e of t.inputNodes)for(const t of e.portPoints){const e="rgba(150, 150, 150, 0.5)";n.circles.push({center:{x:t.x,y:t.y},radius:.05,fill:e,layer:`z${t.z}`,label:[t.portPointId,`cd: ${t.distToCentermostPortOnZ}`,`connects: ${t.connectionNodeIds.join(",")}`].filter(Boolean).join("\n")})}for(const s of t.sectionPaths){const t=e?.[s.connectionName]??"blue";for(let e=0;e<s.points.length-1;e++){const i=s.points[e],o=s.points[e+1],a=i.z===o.z,r=i.z;let h;h=a?0===r?"5 5":"10 5":"3 3 10",n.lines.push({points:[{x:i.x,y:i.y},{x:o.x,y:o.y}],strokeColor:t,strokeDash:h})}}return n}(this.currentSection,this.colorMap);const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.inputNodes){const n=this.nodePfMap.get(e.capacityMeshNodeId)??0,s=`rgba(${Math.floor(255*Math.min(n,1))}, ${Math.floor(255*(1-Math.min(n,1)))}, 0, 0.3)`;t.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,fill:s,label:`${e.capacityMeshNodeId}\nPf: ${n.toFixed(3)}`})}for(const e of this.connectionResults){if(!e.path)continue;const n=e.connection,s=this.colorMap[n.name]??"blue",i=[];for(const t of e.path)i.push({x:t.point.x,y:t.point.y,z:t.z});for(let e=0;e<i.length-1;e++){const n=i[e],o=i[e+1],a=n.z===o.z,r=n.z;let h;h=a?0===r?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:n.x,y:n.y},{x:o.x,y:o.y}],strokeColor:s,strokeDash:h})}}return t}};function js(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Zs=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 n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,i=Math.max(n,s),o=e.targetMinCapacity??.5;e.capacityDepth=Se(i,o)}this.connMap=xe(t),this.colorMap=B(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?G():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;colorMap;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;viaDiameter;minTraceWidth;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[js("netToPointPairsSolver",He,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=B(t.srjWithPointPairs,this.connMap),t.connMap=xe(t.srjWithPointPairs)}}),js("nodeSolver",cs,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),js("edgeSolver",De,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),js("availableSegmentPointSolver",Fs,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),js("portPointPathingSolver",ks,t=>{const e=t.capacityNodes.map(t=>({capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:[],availableZ:t.availableZ,_containsTarget:t._containsTarget,_containsObstacle:t._containsObstacle})),n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),s=t.availableSegmentPointSolver;for(const t of s.sharedEdgeSegments)for(const e of t.portPoints){const[t,s]=e.nodeIds,i={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[t,s],distToCentermostPortOnZ:e.distToCentermostPortOnZ},o=n.get(t);o&&o.portPoints.push(i)}return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e,capacityMeshNodes:t.capacityNodes,colorMap:t.colorMap}]}),js("multiSectionPortPointOptimizer",Hs,t=>{const e=t.portPointPathingSolver;return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e.inputNodes,capacityMeshNodes:t.capacityNodes,capacityMeshEdges:t.capacityEdges,colorMap:t.colorMap,initialConnectionResults:e.connectionsWithResults,initialAssignedPortPoints:e.assignedPortPoints,initialNodeAssignedPortPoints:e.nodeAssignedPortPoints}]}),js("highDensityRouteSolver",me,t=>[{nodePortPoints:t.portPointPathingSolver?.getNodesWithPortPoints()??t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),js("highDensityStitchSolver",we,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),js("traceSimplificationSolver",Ds,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(),n=this.nodeSolver?.visualize(),s=this.nodeTargetMerger?.visualize(),i=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),a=this.edgeSolver?.visualize(),r=this.deadEndSolver?.visualize(),h=this.availableSegmentPointSolver?.visualize(),c=this.portPointPathingSolver?.visualize(),d=this.multiSectionPortPointOptimizer?.visualize(),l=this.highDensityRouteSolver?.visualize(),u=this.highDensityStitchSolver?.visualize(),p=this.traceSimplificationSolver?.visualize(),f=this.srj.outline,g=[];if(g.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)"}),f&&f.length>=2){const t=f.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),g.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const m={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:g},y=[m,e,n,s,i,o,a,r,h,c,d,l?t(m,l):null,u,p,this.solved?t(m,ze(this.getOutputSimpleRouteJson())):null].filter(Boolean);return t(...y)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.connectionName]}),t.length>200)break}return{lines:t}}if(this.portPointPathingSolver){const t=[];for(const e of this.portPointPathingSolver.connectionsWithResults)e.path&&t.push({points:e.path.map(t=>({x:t.point.x,y:t.point.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 n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,i=e.filter(t=>t.connectionName===n.name);for(let e=0;e<i.length;e++){const o=i[e],a={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:Ne(o,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Ws=Zs,Vs=class extends e{nodes;edges;capacityPaths;nodeMap;nodeEdgeMap;unprocessedNodeIds;nodePortSegments;colorMap;constructor({nodes:t,edges:e,capacityPaths:n,colorMap:s}){super(),this.nodes=t,this.edges=e,this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ls(e),this.capacityPaths=n,this.colorMap=s??{},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 n of this.capacityPaths){const s=n.nodeIds.indexOf(t);-1!==s&&e.push({path:n,indexOfNodeInPath:s})}const n=this.nodeMap.get(t),s=[];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=Us(n,e),r=e.availableZ.filter(t=>n.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};s.push(h)}}const i=function(t){const e=[],n=t.map(t=>({...t,connectionNames:[...t.connectionNames],rootConnectionNames:t.rootConnectionNames?[...t.rootConnectionNames]:[],availableZ:[...t.availableZ].sort((t,e)=>t-e)}));for(;n.length>0;){const t=n.pop();let s=!1;for(let n=0;n<e.length;n++){const i=e[n],o=qs(i.start,t.start)&&qs(i.end,t.end)||qs(i.start,t.end)&&qs(i.end,t.start),a=Ks(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 n=new Set(i.rootConnectionNames||[]);t.rootConnectionNames?.forEach(t=>n.add(t)),i.rootConnectionNames=Array.from(n),s=!0;break}}s||e.push(t)}return e}(s);this.nodePortSegments.set(t,i)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};return this.nodePortSegments.forEach((e,n)=>{this.nodeMap.get(n);e.forEach(e=>{e.start.x,e.end.x;for(let s=0;s<e.connectionNames.length;s++){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:`${n}: ${e.connectionNames.join(", ")}\navailableZ: ${e.availableZ.join(",")}\nnodePortSegmentId: ${e.nodePortSegmentId}`}),t.lines.push({points:[e.start,e.end],strokeColor:H(this.colorMap[e.connectionNames[s]],.6)})}})}),t}};function Us(t,e){const n={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)},s={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(n.end-n.start<s.end-s.start){const t=(n.start+n.end)/2;return{start:{x:t,y:s.start},end:{x:t,y:s.end}}}{const t=(s.start+s.end)/2;return{start:{x:n.start,y:t},end:{x:n.end,y:t}}}}var Gs=1e-9;function qs(t,e){return Math.abs(t.x-e.x)<Gs&&Math.abs(t.y-e.y)<Gs}function Ks(t,e){if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++)if(t[n]!==e[n])return!1;return!0}var Js=class extends e{unsolvedSegments;solvedSegments;nodeMap;colorMap;constructor({segments:t,colorMap:e,nodes:n}){super(),this.MAX_ITERATIONS=1e5,this.unsolvedSegments=t,this.solvedSegments=[],this.colorMap=e??{},this.nodeMap=Object.fromEntries(n.map(t=>[t.capacityMeshNodeId,t]))}_step(){let t=!1;const e=[...this.unsolvedSegments];for(const n of e){const e=n.connectionNames.length;if((!("assignedPoints"in n)||n.assignedPoints?.length!==e)&&1===e){const e={x:(n.start.x+n.end.x)/2,y:(n.start.y+n.end.y)/2,z:n.availableZ[0]};n.assignedPoints=[{connectionName:n.connectionNames[0],rootConnectionName:n.rootConnectionNames?.[0],point:e}],this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(n),1),this.solvedSegments.push(n),t=!0}}if(!t&&e.length>0){let n=e[0];for(const t of e)t.connectionNames.length<n.connectionNames.length&&(n=t);const s=[...n.connectionNames].sort(),i=n.end.x-n.start.x,o=n.end.y-n.start.y,a=s.length,r=[];for(let t=1;t<=a;t++){const e=t/(a+1);r.push({x:n.start.x+i*e,y:n.start.y+o*e,z:n.availableZ[0]})}n.assignedPoints=s.map((t,e)=>({connectionName:t,rootConnectionName:n.rootConnectionNames?.[n.connectionNames.indexOf(t)],point:r[e]})),this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(n),1),this.solvedSegments.push(n),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 n=e.capacityMeshNodeId,s=this.nodeMap[n];t.has(n)||t.set(n,{capacityMeshNodeId:n,portPoints:[],center:s.center,width:s.width,height:s.height}),t.get(n).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 n=this.solvedSegments[e];for(let e=0;e<n.assignedPoints.length;e++){const s=n.assignedPoints[e],i={x:s.point.x,y:s.point.y},o={x:s.point.x+.05*s.point.z,y:s.point.y+.05*s.point.z};0!==s.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:[`${n.capacityMeshNodeId}-${s.connectionName}`,`z: ${n.availableZ.join(",")}`,`nodePortSegmentId: ${n.nodePortSegmentId}`].join("\n"),color:this.colorMap[s.connectionName],step:4})}}const e=[],n={};for(const t of this.solvedSegments){const e=t.capacityMeshNodeId;n[e]||(n[e]={});for(const s of t.assignedPoints)n[e][s.connectionName]||(n[e][s.connectionName]=[]),n[e][s.connectionName].push({x:s.point.x,y:s.point.y})}for(const t in n)for(const s in n[t]){const i=n[t][s];i.length>1&&e.push({points:i,step:4,strokeDash:"5 5",strokeColor:this.colorMap[s]||"#000"})}return t.lines.push(...e),t}};function Qs(t){const{nodeId:e,nodeIdToSegmentIds:n,segmentIdToNodeIds:s,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=n.get(t)||[];for(const t of i){const n=s.get(t)||[];for(const t of n)o.has(t)||(o.add(t),a.push({nodeId:t,remainingHops:e-1}))}}return Array.from(o)}var ti=t=>Array.from(t.entries()).map(([t,{x:e,y:n,z:s}])=>`${t}(${e?.toFixed(3)??""},${n?.toFixed(3)??""},${s??""})`).sort().join("&"),ei=(t,e,n,s)=>{const i=Math.min(t,e),o=Math.max(t,e),a=Math.min(n,s);return i<=Math.max(n,s)&&o>=a},ni=(t,e,n,s)=>{const i=[],o=new Map(t.originalPointMap);for(const[t,e]of n.entries()){const n=o.get(t);o.set(t,{x:e.x??n.x,y:e.y??n.y,z:e.z??n.z})}for(const n of t.allNodeIds){if(!e.get(n))continue;const a=t.segmentPairsInNode.get(n);for(const t of a){const e=o.get(t[0]),s=o.get(t[1]);e.z!==s.z&&i.push({type:"transition_via",segmentPoints:t,capacityMeshNodeId:n,probabilityOfFailure:0})}for(let t=0;t<a.length;t++)for(let e=t+1;e<a.length;e++){if(s?.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(!ei(c.z,d.z,l.z,u.z))continue;const p=Q(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:n,crossingLine1:r,crossingLine2:h,probabilityOfFailure:0}):c.z===d.z&&l.z!==u.z?i.push({type:"single_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:n,sameLayerCrossingLine:r,transitionCrossingLine:h,probabilityOfFailure:0}):c.z!==d.z&&l.z===u.z?i.push({type:"single_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:n,sameLayerCrossingLine:h,transitionCrossingLine:r,probabilityOfFailure:0}):c.z!==d.z&&l.z!==u.z&&i.push({type:"double_transition_crossing",segmentPoints:[r,h],capacityMeshNodeId:n,crossingLine1:r,crossingLine2:h,probabilityOfFailure:0}))}}return i},si=(t,e,n)=>{if("change_layer"===e.type)for(const n of e.segmentPointIds){const s=t.get(n)||{};t.set(n,{...s,z:e.newZ})}else if("swap_position_on_segment"===e.type){const[s,i]=e.segmentPointIds,o=n(s),a=n(i),r=t.get(s)||{},h=t.get(i)||{};t.set(s,{...r,x:a.x,y:a.y}),t.set(i,{...h,x:o.x,y:o.y})}else if("combined"===e.type)for(const s of e.operations)si(t,s,n)},ii=(t,e)=>{const n=new Map,s=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:[]};n.set(h.segmentPointId,h);for(const t of h.capacityMeshNodeIds)s.set(t,[...s.get(t)??[],h.segmentPointId]);i.set(r.nodePortSegmentId,[...i.get(r.nodePortSegmentId)??[],h.segmentPointId]),o.push(h)}return{segmentPointMap:n,nodeToSegmentPointMap:s,segmentToSegmentPointMap:i}},oi=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,ve(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=Qs({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS}),n=Qs({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS+1}),s=Array.from(new Set(n).difference(new Set(e)));t?.segmentPointMap||(t=ii(this.dedupedSegments,this.segmentIdToNodeIds));const i=new Map;for(const e of n)i.set(e,t.nodeToSegmentPointMap.get(e));const o=new Map;for(const e of n)for(const n of i.get(e)){const e=t.segmentPointMap.get(n);o.set(n,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,n]of i.entries())for(let e=0;e<n.length;e++){const s=t.segmentPointMap.get(n[e]);for(let i=e+1;i<n.length;i++){const e=t.segmentPointMap.get(n[i]);e.segmentPointId!==s.segmentPointId&&(e.segmentId!==s.segmentId&&e.connectionName===s.connectionName&&(e.directlyConnectedSegmentPointIds.includes(s.segmentPointId)||(s.directlyConnectedSegmentPointIds.push(e.segmentPointId),e.directlyConnectedSegmentPointIds.push(s.segmentPointId))))}}const h=new Map;for(const t of n)h.set(t,[]);for(const e of a)for(const n of e.capacityMeshNodeIds){const s=h.get(n);if(s)for(const i of e.directlyConnectedSegmentPointIds){const o=t.segmentPointMap.get(i);o.segmentPointId!==e.segmentPointId&&(o.capacityMeshNodeIds.some(t=>t===n)&&(s.some(([t,n])=>t===e.segmentPointId&&n===o.segmentPointId||t===o.segmentPointId&&n===e.segmentPointId)||s.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 n=t.capacityMeshNodeIds.some(t=>e.includes(t)),s=this.dedupedSegmentMap.get(t.segmentId),i=s&&s.availableZ.length>1;(n||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:n,mutableNodeIds:e,immutableNodeIds:s,mutableSegmentIds:c,segmentPairsInNode:h,segmentPointMap:o,segmentPointsInNode:i,segmentPointsInSegment:r,originalPointMap:o,mutableSegmentPointIds:d,zLockedSegmentPointIds:l}}createInitialCandidate(){const t=new Map,e=ni(this.unravelSection,this.nodeMap,t),n=this.computeG({issues:e,originalCandidate:{},operationsPerformed:0,operation:{}});return{pointModifications:t,g:n,h:0,f:n,operationsPerformed:0,candidateHash:ti(t),issues:ni(this.unravelSection,this.nodeMap,t)}}get nextCandidate(){return this.candidates[0]??null}getPointInCandidate(t,e){const n=this.unravelSection.segmentPointMap.get(e),s=t.pointModifications.get(e);return{x:s?.x??n.x,y:s?.y??n.y,z:s?.z??n.z,segmentId:n.segmentId}}getConnectionSegmentPointIds(t){const e=[];for(const[n,s]of this.unravelSection.segmentPointMap.entries())s.connectionName===t&&e.push(n);return e}canConnectionUseLayer(t,e){for(const n of t){const t=this.unravelSection.segmentPointMap.get(n),s=this.dedupedSegmentMap.get(t.segmentId);if(!s||!s.availableZ.includes(e))return!1}return!0}getOperationsForIssue(t,e){const n=[];if("transition_via"===e.type){const[s,i]=e.segmentPoints,o=this.getPointInCandidate(t,s),a=this.getPointInCandidate(t,i),r=this.unravelSection.segmentPointMap.get(s),h=(this.unravelSection.segmentPointMap.get(i),this.dedupedSegmentMap.get(o.segmentId).availableZ),c=this.dedupedSegmentMap.get(a.segmentId).availableZ,d=this.unravelSection.zLockedSegmentPointIds.has(s),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&&n.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&&n.push({type:"change_layer",newZ:o.z,segmentPointIds:t})}this.unravelSection.mutableSegmentPointIds.has(s)&&!d&&h.includes(a.z)&&n.push({type:"change_layer",newZ:a.z,segmentPointIds:[s]}),this.unravelSection.mutableSegmentPointIds.has(i)&&!l&&c.includes(o.z)&&n.push({type:"change_layer",newZ:o.z,segmentPointIds:[i]})}if("same_layer_crossing"===e.type){const[t,s]=e.crossingLine1,[i,o]=e.crossingLine2,a=[],r=this.unravelSection.segmentPointMap.get(t),h=this.unravelSection.segmentPointMap.get(s),c=this.unravelSection.segmentPointMap.get(i),d=this.unravelSection.segmentPointMap.get(o),l=this.unravelSection.mutableSegmentPointIds.has(t),u=this.unravelSection.mutableSegmentPointIds.has(s),p=this.unravelSection.mutableSegmentPointIds.has(i),f=this.unravelSection.mutableSegmentPointIds.has(o),g=this.unravelSection.zLockedSegmentPointIds.has(t),m=this.unravelSection.zLockedSegmentPointIds.has(s),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([s,i]),u&&f&&h.segmentId===d.segmentId&&a.push([s,o]);for(const[t,e]of a)n.push({type:"swap_position_on_segment",segmentPointIds:[t,e]});const v=this.getConnectionSegmentPointIds(r.connectionName),S=this.getConnectionSegmentPointIds(c.connectionName),M=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)M.add(t)}for(const t of M)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&&n.push({type:"change_layer",newZ:t,segmentPointIds:e})}for(const t of M)if(t!==c.z&&this.canConnectionUseLayer(S,t)){const e=S.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));e.length>0&&n.push({type:"change_layer",newZ:t,segmentPointIds:e})}const N=this.dedupedSegmentMap.get(r.segmentId),b=this.dedupedSegmentMap.get(h.segmentId),P=this.dedupedSegmentMap.get(c.segmentId),I=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([N,b],e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t,s]})}if(p&&f&&!y&&!x){const t=0===c.z?1:0;C([P,I],t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[i,o]})}if(l&&!g){const e=0===r.z?1:0;N.availableZ.includes(e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t]})}if(u&&!m){const t=0===h.z?1:0;b.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[s]})}if(p&&!y){const t=0===c.z?1:0;P.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[i]})}if(f&&!x){const t=0===d.z?1:0;I.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[o]})}}return n}computeG(t){const{issues:e,originalCandidate:n,operationsPerformed:s,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:n,numTransitionCrossings:s}]of o){const i=this.nodeMap.get(t),o=Math.min($s(i,n,e,s),.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 n=new Map(t.pointModifications);si(n,e,e=>this.getPointInCandidate(t,e));const s=ti(n);if(this.queuedOrExploredCandidatePointModificationHashes.has(s))return null;const i=ni(this.unravelSection,this.nodeMap,n),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:n,candidateHash:s,operationsPerformed:o}}getNeighborOperationsForCandidate(t){return t.issues.flatMap(e=>this.getOperationsForIssue(t,e))}getNeighbors(t){const e=[],n=this.getNeighborOperationsForCandidate(t);for(const s of n){const n=this.getUnexploredNeighborByApplyingOperation(t,s);n&&e.push(n)}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 n=new Map;for(const[t,s]of this.unravelSection.segmentPointMap){const i={...s},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)),n.set(t,i)}for(const[e,s]of n)t.points.push({x:s.x,y:s.y,label:`${e}\nSegment: ${s.segmentId} ${this.unravelSection.mutableSegmentIds.has(s.segmentId)?"MUTABLE":"IMMUTABLE"}\nLayer: ${s.z}`,color:this.colorMap[s.connectionName]||"#000"});const s=new Map;for(const t of this.unravelSection.allNodeIds)s.set(t,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0,estPf:0});for(const t of e.issues){const e=s.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 s.entries()){const n=this.nodeMap.get(t);e.estPf=$s(n,e.numSameLayerCrossings,e.numEntryExitLayerChanges,e.numTransitionCrossings)}for(const e of this.unravelSection.allNodeIds){const n=this.nodeMap.get(e),i=this.unravelSection.mutableNodeIds.includes(e),o=s.get(e),a=[`${e} (${i?"MUT":"IMM"})`,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Pf: ${o.estPf.toFixed(3)}`,`TC: ${o.numTransitionCrossings}`,`SLC: ${o.numSameLayerCrossings}`,`EELC: ${o.numEntryExitLayerChanges}`].join("\n");t.rects.push({center:n.center,label:a,color:i?"green":"red",width:n.width/8,height:n.height/8})}for(const[e,s]of this.unravelSection.segmentPointsInSegment){if(s.length<=1)continue;const i=s.map(t=>n.get(t));for(let n=0;n<i.length-1;n++)t.lines.push({points:[{x:i[n].x,y:i[n].y},{x:i[n+1].x,y:i[n+1].y}],strokeColor:this.colorMap[e]||"#000"})}for(const[e,s]of n)for(const i of s.directlyConnectedSegmentPointIds)if(e<i){const e=n.get(i);if(!e)continue;const o=s.z===e.z,a=s.z;let r;r=o?0===a?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:s.x,y:s.y},{x:e.x,y:e.y}],strokeDash:r,strokeColor:this.colorMap[s.connectionName]||"#000"})}for(const s of e.issues){const e=this.nodeMap.get(s.capacityMeshNodeId);if("transition_via"===s.type)for(const i of s.segmentPoints){const s=n.get(i);t.circles.push({center:{x:s.x,y:s.y},radius:e.width/16,stroke:"#ff0000",fill:"rgba(255, 0, 0, 0.2)",label:`Via Issue\n${i}\nLayer: ${s.z}`})}else if("same_layer_crossing"===s.type)for(const[i,o]of[s.crossingLine1,s.crossingLine2]){const s=n.get(i),a=n.get(o);t.lines.push({points:[{x:s.x,y:s.y},{x:a.x,y:a.y}],strokeColor:"rgba(255,0,0,0.2)",strokeWidth:e.width/32})}}for(const[s,i]of e.pointModifications){const e=n.get(s),i=this.unravelSection.segmentPointMap.get(s);t.circles.push({center:{x:e.x,y:e.y},radius:.05,stroke:"#0000ff",fill:"rgba(0, 0, 255, 0.2)",label:`${s}\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 ai from"object-hash";function ri(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:hi,sin:ci,PI:di}=Math,{tan:li}=Math,ui=t=>(Math.round(20*t)/20).toFixed(2),pi=t=>(Math.round(1e3*t)/1e3).toFixed(3);q();var fi=class extends oi{cacheHit=!1;cacheProvider;hasAttemptedToUseCache=!1;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?U():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),n=new Map,s=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 n=this.nodeMap.get(t),s=this.nodeMap.get(e);return n.center.x!==s.center.x?n.center.x-s.center.x:n.center.y-s.center.y});for(const t of l){const e="node_"+h++;n.set(t,e),s.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 n=this.unravelSection.segmentPointMap.get(t).segmentId;if(!i.has(n)){const t="seg_"+c++;i.set(n,t),o.set(t,n)}}const p={};for(const[t,s]of n.entries()){const n=this.nodeMap.get(t),i=ri(e,n.center);p[s]={width:n.width,height:n.height,availableZ:n.availableZ,center:{x:ui(i.x),y:ui(i.y)}}}const f={};for(const[t,n]of a.entries()){const s=this.unravelSection.segmentPointMap.get(t),i=ri(e,{x:s.x,y:s.y});f[n]={x:ui(i.x),y:ui(i.y),z:s.z}}const g={hyperParameters:this.hyperParameters,normalizedNodes:p,normalizedSegmentPoints:f,mutableHops:this.MUTABLE_HOPS},m=`unravelsec:${ai(g)}`,y={realToCacheTransform:e,nodeIdMap:n,segmentIdMap:i,segmentPointIdMap:a,reverseNodeIdMap:s,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:n}=this.cacheToSolveSpaceTransform,s=new Map;for(const[n,i]of t.bestCandidatePointModificationsDelta){const t=e.get(n);if(!t){console.warn(`Could not find original ID for normalized SP ID: ${n} 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&&s.set(t,a)}const i=ni(this.unravelSection,this.nodeMap,s);this.bestCandidate={pointModifications:s,issues:i,f:t.bestCandidateF,g:t.bestCandidateF,h:0,operationsPerformed:-1,candidateHash:ti(s)},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[n,s]of this.bestCandidate.pointModifications.entries()){const i=t.get(n);if(!i){console.warn(`Could not find normalized ID for original SP ID: ${n} when saving to cache.`);continue}const o=this.unravelSection.segmentPointMap.get(n);if(!o){console.warn(`Could not find original segment point for ID: ${n} when saving cache.`);continue}const a={};let r=!1;if(void 0!==s.x){const t=s.x-o.x,e=pi(t);0!==parseFloat(e)&&(a.dx=e,r=!0)}if(void 0!==s.y){const t=s.y-o.y,e=pi(t);0!==parseFloat(e)&&(a.dy=e,r=!0)}if(void 0!==s.z){const t=s.z-o.z;0!==t&&(a.dz=t,r=!0)}r&&e.push([i,a])}const n={success:!0,bestCandidatePointModificationsDelta:e,bestCandidateF:this.bestCandidate.f};this.cacheProvider?.setCachedSolutionSync(this.cacheKey,n)}},gi=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:n,cacheProvider:s}){super(),this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.cacheHits=0,this.stats.cacheMisses=0,this.cacheProvider=s??null,this.MAX_ITERATIONS=1e6,this.dedupedSegments=(t=>{const e=[],n=new Map;let s=-1;for(const i of t){const t=`${i.start.x}-${i.start.y}-${i.end.x}-${i.end.y}-${i.availableZ.join(",")}`,o=n.get(t);o?i.nodePortSegmentId=o.nodePortSegmentId:(s++,i.nodePortSegmentId=`SEG${s}`,n.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 n)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,ve(e));const{segmentPointMap:i,nodeToSegmentPointMap:o,segmentToSegmentPointMap:a}=ii(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,n]of this.nodeMap.entries())t.set(e,this.computeNodePf(n));return t}computeNodePf(t){const{numSameLayerCrossings:e,numEntryExitLayerChanges:n,numTransitionCrossings:s}=(t=>{let e=0,n=0,s=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 s=e[0];for(let i=1;i<e.length;i++){const r=e[i],h={connectionName:t,z:s.z,points:[s,r]};s.z!==r.z?(n++,a.push({connectionName:t,points:[s,r]})):o.push(h)}}for(let t=0;t<o.length;t++)for(let n=t+1;n<o.length;n++){const s=o[t],i=o[n];s.z===i.z&&Q(s.points[0],s.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 n=a[t],i=a[e];Q(n.points[0],n.points[1],i.points[0],i.points[1])&&s++}for(let t=0;t<a.length;t++)for(let e=0;e<o.length;e++){const n=a[t],i=o[e];Q(n.points[0],n.points[1],i.points[0],i.points[1])&&s++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:n,numTransitionCrossings:s}})((this.nodeToSegmentPointMap.get(t.capacityMeshNodeId)??[]).map(t=>this.segmentPointMap.get(t)));return $s(t,e,n,s)}_step(){if(this.iterations>=this.MAX_ITERATIONS-1)return void(this.solved=!0);if(!this.activeSubSolver){let t=null,e=0;for(const[n,s]of this.nodePfMap.entries()){s*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_NODE_ATTEMPTS)>e&&(e=s,t=n)}if(!t||e<this.ACCEPTABLE_PF)return void(this.solved=!0);this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.activeSubSolver=new fi({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:n}=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,n]of t.pointModifications.entries()){const t=this.segmentPointMap.get(e);t.x=n.x??t.x,t.y=n.y??t.y,t.z=n.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,n]of this.nodeMap.entries()){const s=this.nodePfMap.get(e)||0,i=Math.min(s,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:n.center,label:[e,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Pf: ${s.toFixed(3)}`].join("\n"),color:o,width:n.width/8,height:n.height/8})}for(const e of this.segmentPointMap.values()){const n=this.dedupedSegmentMap.get(e.segmentId);t.points.push({x:e.x,y:e.y,label:[e.segmentPointId,e.segmentId,`z: ${e.z}`,`segment.availableZ: ${n?.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[n,s]of e.entries()){if(s.length<2)continue;const e=[...s].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y);for(let s=0;s<e.length-1;s++)t.lines.push({points:[{x:e[s].x,y:e[s].y},{x:e[s+1].x,y:e[s+1].y}],strokeColor:this.colorMap[n]||"#000"})}const n=new Set,s=Array.from(this.segmentPointMap.values());for(let e=0;e<s.length;e++){const i=s[e];for(let o=e+1;o<s.length;o++){const e=s[o];if(i.connectionName!==e.connectionName||i.segmentId===e.segmentId)continue;if(i.capacityMeshNodeIds.some(t=>e.capacityMeshNodeIds.includes(t))){const s=`${i.segmentPointId}-${e.segmentPointId}`;if(n.has(s))continue;n.add(s);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 n=e.nodePortSegmentId;for(const e of this.segmentIdToNodeIds.get(n)){const n=this.nodeMap.get(e);t.has(e)||t.set(e,{capacityMeshNodeId:e,portPoints:[],center:n.center,width:n.width,height:n.height})}}for(const e of this.segmentPointMap.values())for(const n of e.capacityMeshNodeIds){const s=t.get(n);s&&s.portPoints.push({x:e.x,y:e.y,z:e.z,connectionName:e.connectionName,rootConnectionName:e.rootConnectionName})}return Array.from(t.values())}},mi=(t,e={})=>{const n=Math.min(...t.availableZ);return{center:!e.rectMargin||e.zOffset?{x:t.center.x+n*t.width*(e.zOffset??.05),y:t.center.y-n*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")}},yi=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:s,MAX_ITERATIONS:i=1e6,hyperParameters:o={}}){super(),this.MAX_ITERATIONS=i,this.simpleRouteJson=t,this.nodes=e,this.edges=n,this.colorMap=s??{};const{connectionsWithNodes:a,connectionNameToGoalNodeIds:r}=this.getConnectionsWithNodes();this.connectionsWithNodes=a,this.connectionNameToGoalNodeIds=r,this.hyperParameters=o,this.usedNodeCapacityMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,0])),this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ls(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),n=new Map;for(const s of this.simpleRouteJson.connections){const i=[];for(const t of s.pointsToConnect){let n=this.nodes[0],s=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<s&&(s=e,n=i)}i.push(n)}if(i.length<2)throw new Error(`Not enough nodes for connection "${s.name}", only ${i.length} found`);n.set(s.name,i.map(t=>t.capacityMeshNodeId)),t.push({connection:s,nodes:i,pathFound:!1,straightLineDistance:st(i[0].center,i[i.length-1].center)})}return t.sort((t,e)=>t.straightLineDistance-e.straightLineDistance),{connectionsWithNodes:t,connectionNameToGoalNodeIds:n}}currentConnectionIndex=0;candidates;visitedNodes;computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)}getBacktrackedPath(t){const e=[];let n=t;for(;n;)e.push(n.node),n=n.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 n=e.path;n&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,rootConnectionName:e.connection.rootConnectionName,nodeIds:n.map(t=>t.capacityMeshNodeId)})}return t}doesNodeHaveCapacityForTrace(t,e){const n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.getTotalCapacity(t);if(1===t.availableZ.length&&!t._containsTarget&&n>0)return!1;let i=0;return t.availableZ.length>1&&1===e.availableZ.length&&(i+=.5),n+i<s}canTravelThroughObstacle(t,e){const n=this.connectionNameToGoalNodeIds.get(e);return n?.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,n]=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=st(e.center,n.center)),this.candidates.sort((t,e)=>t.f-e.f);const s=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),!s)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(s.node,n))return t.path=this.getBacktrackedPath({prevCandidate:s,node:n,f:0,g:0,h:0}),this.reduceCapacityAlongPath(t),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);const i=this.getNeighboringNodes(s.node);for(const t of i){if(this.visitedNodes?.has(t.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(t,s.node))continue;const e=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;if(t._containsObstacle&&!this.canTravelThroughObstacle(t,e))continue;const i=this.computeG(s,t,n),o=this.computeH(s,t,n),a=i+o*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:a,g:i,h:o});const r={prevCandidate:s,node:t,f:a,g:i,h:o};this.candidates.push(r)}this.visitedNodes.add(s.node.capacityMeshNodeId)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(this.connectionsWithNodes)for(let e=0;e<this.connectionsWithNodes.length;e++){const n=this.connectionsWithNodes[e];if(n.path&&n.path.length>0){const s=n.path.map(({center:{x:t,y:n},width:s,availableZ:i})=>({x:t+.005*s*(e%10+e%19),y:n+.005*s*(e%10+e%19),availableZ:i}));t.lines.push({points:s,strokeColor:this.colorMap[n.connection.name]});for(let e=0;e<s.length;e++){const i=s[e];t.points.push({x:i.x,y:i.y,label:[`conn: ${n.connection.name}`,`node: ${n.path[e].capacityMeshNodeId}`,`z: ${i.availableZ.join(",")}`].join("\n")})}}}for(const e of this.nodes){const n=this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,s=this.getTotalCapacity(e),i=this.debug_lastNodeCostMap.get(e.capacityMeshNodeId);t.rects.push({...mi(e,{rectMargin:.025,zOffset:.01}),label:[`${e.capacityMeshNodeId}`,`${n}/${s}`,`${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:n>s+.5?"red":void 0})}if(this.connectionsWithNodes)for(const e of this.connectionsWithNodes)if(e.connection?.pointsToConnect)for(const n of e.connection.pointsToConnect)t.points.push({x:n.x,y:n.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[n,s]=e.connection.pointsToConnect;t.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.y}],strokeColor:"red",strokeDash:"10 5"})}if(this.candidates){const e=this.candidates.slice(0,5),n=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;e.forEach((e,s)=>{const i=.5*(1-s/5),o=this.getBacktrackedPath(e);t.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:H(this.colorMap[n]??"red",1-i)})})}return t}},xi=class extends yi{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 ve(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){const e=t.width+t.height,n=.05,s=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0);if(s>2)return n;return(e-n)*Math.max(1,(2-s)/(e-n))+n}getDistanceBetweenNodes(t,e){const n=t.center.x-e.center.x,s=t.center.y-e.center.y;return Math.sqrt(n**2+s**2)}computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)+this.getNodeCapacityPenalty(e)}},vi=class extends xi{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 n=1;return 1===t.availableZ.length&&(n=10),(.05+2*Math.abs(e))*n}};function Si(t,e,n){const s=e.x-t.x,i=e.y-t.y;if(Math.abs(s)<1e-9&&Math.abs(i)<1e-9)return t;const o=n.width/2,a=n.height/2,r=n.center.x-o,h=n.center.x+o,c=n.center.y-a,d=n.center.y+a;let l=0,u=1/0;if(Math.abs(s)>1e-9){const e=(r-t.x)/s,n=(h-t.x)/s;l=Math.max(l,Math.min(e,n)),u=Math.min(u,Math.max(e,n))}else if(t.x<r||t.x>h)return t;if(Math.abs(i)>1e-9){const e=(c-t.y)/i,n=(d-t.y)/i;l=Math.max(l,Math.min(e,n)),u=Math.min(u,Math.max(e,n))}else if(t.y<c||t.y>d)return t;if(u<l||l===1/0||l<-1e9)return t;return{x:t.x+s*l,y:t.y+i*l}}function Mi(t,e){const n=t.center,s=e.center,i=Si(n,s,t),o=Si(s,n,e),a=s.x-n.x,r=s.y-n.y,h=Math.sqrt(a*a+r*r);let c=i,d=o;if(h>1e-9){const n={x:a/h,y:r/h},s=.3*t.width,l=.3*e.width;s+l<Math.sqrt((o.x-i.x)**2+(o.y-i.y)**2)?(c={x:i.x+n.x*s,y:i.y+n.y*s},d={x:o.x-n.x*l,y:o.y-n.y*l}):(c=i,d=o)}return{lineStart:c,lineEnd:d}}var Ni=t=>{const{usedCapacity:e,totalCapacity:n,layerCount:s}=t;if(e<n)return 0;if(n<1&&e<=1)return 0;if(1===s&&e>1)return 1-.01**e;const i=e/n-1;return 1-Math.exp(-2*i)},bi=(t,e,n)=>{if(n._containsTarget)return 0;if(t<=e)return 0;const s=1-Ni({usedCapacity:t,totalCapacity:e,layerCount:n.availableZ.length});return s<=0?-1e9:Math.log(s)},Pi=({totalNodeCapacityMap:t,usedNodeCapacityMap:e,nodeMap:n,sectionNodeIds:s})=>{let i=0;const o=s??new Set(e.keys());for(const s of o){if(!t.has(s))continue;const o=n.get(s);if(!o)continue;const a=t.get(s),r=e.get(s)??0;i+=bi(r,a,o)}return i};function Ii({sectionNodes:t,sectionEdges:e,sectionConnectionTerminals:n,completedPaths:s,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})`,n=`rgba(128, 128, 128, ${h})`;const s=e.availableZ??[],i=s.includes(0),o=s.includes(1);i&&o?(t=`rgba(128, 0, 128, ${h})`,n=`rgba(128, 0, 128, ${h})`):i?(t=`rgba(0, 0, 255, ${h})`,n=`rgba(0, 0, 255, ${h})`):o&&(t=`rgba(255, 0, 0, ${h})`,n=`rgba(255, 0, 0, ${h})`),a&&e.capacityMeshNodeId===a&&(t=`rgba(0, 255, 0, ${h})`,n=`rgba(0, 128, 0, ${h})`),l.rects.push({...mi(e),fill:t,stroke:n,label:`${e.capacityMeshNodeId}\n(Section Node)\nZ: ${s.join(",")}`});const r=l.rects.length-1;if(c&&d){const t=c.get(e.capacityMeshNodeId)??0,n=d.get(e.capacityMeshNodeId)??0,s=n>0?(t/n*100).toFixed(1):"N/A",i=Ni({usedCapacity:t,totalCapacity:n,layerCount:e.availableZ.length});l.rects[r].label+=`\n${t.toFixed(1)} / ${n.toFixed(1)}\n${s}% (Pf: ${(100*i).toFixed(1)}%)`,i>.2&&(l.rects[r].stroke=H("red",.7*(.8+h)))}}for(const t of e){const[e,n]=t.nodeIds,s=i.get(e),o=i.get(n);if(s&&o){const{lineStart:t,lineEnd:e}=Mi(s,o);l.lines.push({points:[t,e],strokeColor:`rgba(0, 0, 0, ${.2*Math.min(1,h/.1)})`})}}return n.forEach((t,e)=>{const n=i.get(t.startNodeId),s=i.get(t.endNodeId),a=o[t.connectionName]??"black",r=n&&u.has(n.capacityMeshNodeId),h=s&&u.has(s.capacityMeshNodeId),c=(e+e/50)%5;let d=0,p=0,f=0,g=0;if(r&&n){const e=.02*Math.min(n.width,n.height);d=e*c,p=e*c,l.points.push({x:n.center.x+d,y:n.center.y+p,color:a,label:`Start: ${t.connectionName}\n(${t.startNodeId})`}),l.lines.push({points:[{x:n.center.x,y:n.center.y},{x:n.center.x+d,y:n.center.y+p}],strokeColor:"gray",strokeDash:"2 2"})}if(h&&s){const e=.02*Math.min(s.width,s.height);f=e*c,g=e*c,l.points.push({x:s.center.x+f,y:s.center.y+g,color:a,label:`End: ${t.connectionName}\n(${t.endNodeId})`}),l.lines.push({points:[{x:s.center.x,y:s.center.y},{x:s.center.x+f,y:s.center.y+g}],strokeColor:"gray",strokeDash:"2 2"})}r&&h&&n&&s&&l.lines.push({points:[{x:n.center.x+d,y:n.center.y+p},{x:s.center.x+f,y:s.center.y+g}],strokeColor:a,strokeDash:"5 5"})}),s&&s.forEach((t,e)=>{if(t.path&&t.path.length>0){const n=o[t.connectionName]??"gray",s={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+s.x,y:e+s.y})),strokeColor:H(n,.2)})}}),l}var Ci=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??Ls(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=Pi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:e}),t.hyperParameters?.SHUFFLE_SEED&&(this.sectionConnectionTerminals=Pt(this.sectionConnectionTerminals,t.hyperParameters?.SHUFFLE_SEED))}getTotalCapacity(t){return ve(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 n=1;return 1===t.availableZ.length&&(n=10),(.05+e**2*4)*n}getDistanceBetweenNodes(t,e){const n=t.center.x-e.center.x,s=t.center.y-e.center.y;return Math.sqrt(n**2+s**2)}computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)+this.getNodeCapacityPenalty(e)}getBacktrackedPath(t){const e=[];let n=t;for(;n;){if(e.push(n.node),!this.nodeMap.has(n.node.capacityMeshNodeId)){console.warn("Backtracked path went outside section bounds");break}n=n.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,n=this.nodeMap.get(t);if(!n){console.warn(`Node ${t} from path not found in section's nodeMap during score update.`);continue}const s=this.totalNodeCapacityMap.get(t),i=this.usedNodeCapacityMap.get(t)??0,o=bi(i,s,n);this.currentSectionScore-=o;const a=i+1;this.usedNodeCapacityMap.set(t,a);const r=bi(a,s,n);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),n=this.nodeMap.get(t.endNodeId);if(!e||!n)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,n);const s=this.candidates;if(0===s.length)return void this._handleCandidatesExhausted(t);s.sort((t,e)=>t.f-e.f);const i=s.shift();if(s.length>this.MAX_CANDIDATES_IN_MEMORY&&s.splice(this.MAX_CANDIDATES_IN_MEMORY,s.length-this.MAX_CANDIDATES_IN_MEMORY),this.visitedNodes.add(i.node.capacityMeshNodeId),i.node.capacityMeshNodeId===n.capacityMeshNodeId)return void this._handleGoalReached(i,t,n);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 n=e.capacityMeshNodeId===t.startNodeId,s=e.capacityMeshNodeId===t.endNodeId;if(!n&&!s)continue}const o=this.computeG(i,e,n),a=this.computeH(i,e,n),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),s.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 n=this.candidates.reduce((t,e)=>e.f<t.f?e:t);e+=Math.max(0,Math.min(1,1-n.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=st(t.center,e.center);const n=this.computeH(null,t,e);this.candidates[0].h=n,this.candidates[0].f=n*this.GREEDY_MULTIPLIER,this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:this.candidates[0].f,g:0,h:n}),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,n){const s=this.getBacktrackedPath(t);e.path=s,this.reduceCapacityAlongPath(s),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=Ii({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 n=e.rects.findIndex(e=>e.label?.includes(t.capacityMeshNodeId));if(-1!==n){const s=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=s?`f:${s.f.toFixed(1)} g:${s.g.toFixed(1)} h:${s.h.toFixed(1)}`:"cost:?";e.rects[n].label=[t.capacityMeshNodeId,`Cap: ${a}`,r,`Z: ${t.availableZ.join(",")}`].join("\n"),i>o&&(e.rects[n].stroke=H("red",.7))}}if(this.candidates&&this.candidates.length>0){const t=this.candidates.slice().sort((t,e)=>t.f-e.f).slice(0,5),n=this.sectionConnectionTerminals[this.currentConnectionIndex],s=n?.connectionName??"unknown",i=this.colorMap[s]??"purple";t.forEach((t,n)=>{const s=.8*(1-n/5),o=this.getBacktrackedPath(t);o.length>0&&e.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:H(i,1-s),strokeWidth:.05})})}return e}},_i=t=>Array.from({length:t},(t,e)=>e),Ei=class extends wt{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:_i(2).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings6_for3",possibleValues:_i(6).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings24_for4",possibleValues:_i(24).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings30",possibleValues:_i(30).map(t=>({SHUFFLE_SEED:t}))}]}generateSolver(t){return new Ci({...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 Ti from"object-hash";var wi=t=>Math.floor(10*t)/10,zi=class extends Ei{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?G():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=[],n=[{ancestorCapacitySum:0,capacity:0,g:0,capacityMeshNodeId:this.constructorParams.centerNodeId}];for(;n.length>0;){n.sort((t,e)=>e.g-t.g);const s=n.pop();if(!s)break;e.push(s.capacityMeshNodeId);const i=this.constructorParams.nodeEdgeMap.get(s.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=ve(i);n.push({ancestorCapacitySum:s.g,capacity:o,g:s.g+o,capacityMeshNodeId:e})}}return e}computeCacheKeyAndTransform(){const t=this._computeBfsOrderingOfNodesInSection(),e=new Map,n=new Map;t.forEach((t,s)=>{const i=`node${s}`;e.set(t,i),n.set(i,t)});const s={};for(const n of t){const t=e.get(n),i=this.constructorParams.nodeMap.get(n),o=ve(i);s[t]=wi(o).toFixed(1)}const i=new Set,o=[];for(const n of t){const t=e.get(n),s=this.constructorParams.nodeEdgeMap.get(n)??[];for(const a of s){const s=a.nodeIds.find(t=>t!==n);if(this.sectionNodeIdSet.has(s)){const n=[t,e.get(s)].sort(),a=`${n[0]}-${n[1]}`;i.has(a)||(o.push(n),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 n=e.get(t.startNodeId),s=e.get(t.endNodeId),[i,o]=[n,s].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:${Ti({node_capacity_map:s,node_edge_map:o,terminals:a})}`,d={cacheSpaceToRealConnectionId:r,cacheSpaceToRealNodeId:n};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:n}=this.cacheToSolveSpaceTransform;for(const[s,i]of Object.entries(t.solutionPaths)){const t=n.get(s);if(!t){console.warn(`Could not find real connection name for ${s}`);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(n=>{const s=e.get(n);if(!s)throw new Error(`Could not map cache node ID ${n} to real node ID for connection ${t}`);const i=this.constructorParams.nodeMap.get(s);if(!i)throw new Error(`Could not find node with ID ${s} 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:n,cacheSpaceToRealConnectionId:s}=this.cacheToSolveSpaceTransform,i=new Map;for(const[t,e]of n)i.set(e,t);const o=new Map;for(const[t,e]of s)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,n]of a){const s=o.get(t);if(!s){console.warn(`Could not find cache space connection ID for ${t} when saving to cache.`);continue}const a=n.map(e=>{const n=i.get(e);if(!n)throw new Error(`Could not map real node ID ${e} to cache node ID for connection ${t} when saving to cache.`);return n});e[s]=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 Ii({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"})}},Ai=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=Ls(this.edges),this.colorMap=t.colorMap??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ls(this.edges),this.initialSolver=t.initialPathingSolver||new vi({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,n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,s),this.nodeOptimizationAttemptCountMap.set(t.capacityMeshNodeId,0)}this.connectionsWithNodes=this.initialSolver.connectionsWithNodes,this.stats.startingScore=Pi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet}),this.stage="section-optimization"}}_getNextNodeToOptimize(){let t=0,e=0,n=null;for(const s of this.nodes){if(s._containsTarget)continue;const i=this.nodeOptimizationAttemptCountMap.get(s.capacityMeshNodeId),o=this.totalNodeCapacityMap.get(s.capacityMeshNodeId),a=Ni({usedCapacity:this.usedNodeCapacityMap.get(s.capacityMeshNodeId)??0,totalCapacity:o,layerCount:s.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,n=s.capacityMeshNodeId)}return n}getOverallScore(){let t=0;for(const e of this.nodes){if(e._containsTarget)continue;const n=this.totalNodeCapacityMap.get(e.capacityMeshNodeId),s=Ni({usedCapacity:this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,totalCapacity:n,layerCount:e.availableZ.length});s>t&&(t=s)}return{highestNodePf:t,score:Pi({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:n,nodeMap:s,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 n=o.get(t)?.flatMap(e=>e.nodeIds.filter(e=>e!==t))??[];for(const t of n)r.has(t)||(r.add(t),h.push({nodeId:t,depth:e+1}))}const d=Array.from(r).map(t=>s.get(t)),l=i.filter(t=>{const[e,n]=t.nodeIds;return r.has(e)&&r.has(n)}),u=[];for(const t of n){if(!t.path)continue;let e=null,n=null;for(const n of t.path)if(r.has(n.capacityMeshNodeId)){e=n.capacityMeshNodeId;break}for(let e=t.path.length-1;e>=0;e--){const s=t.path[e];if(r.has(s.capacityMeshNodeId)){n=s.capacityMeshNodeId;break}}e&&n&&u.push({connectionName:t.connection.name,startNodeId:e,endNodeId:n})}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 zi({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,n=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 s=new Set(e.map(t=>t.capacityMeshNodeId)),i=Pi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:s}),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(s.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)s.has(e.capacityMeshNodeId)&&o.set(e.capacityMeshNodeId,(o.get(e.capacityMeshNodeId)??0)+1);Pi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:o,nodeMap:this.nodeMap,sectionNodeIds:s})>i?(this.stats.successfulOptimizations++,this._mergeSolvedSectionPaths({centerNodeId:n,sectionConnectionTerminals:t}),this._recalculateNodeCapacityUsage()):this.stats.failedOptimizations++}}_mergeSolvedSectionPaths({centerNodeId:t,sectionConnectionTerminals:e}){for(const n of e){if(!n.path){console.warn(`No path found for connection ${n.connectionName} in section ${t}`);continue}const e=this.connectionsWithNodes.find(t=>t.connection.name===n.connectionName);if(!e||!e.path){console.warn(`Original connection or path not found for ${n.connectionName} while merging section ${t}`);continue}const s=e.path,i=n.path,o=s.findIndex(t=>t.capacityMeshNodeId===n.startNodeId),a=s.findIndex(t=>t.capacityMeshNodeId===n.endNodeId);if(-1===o||-1===a){console.warn(`Could not find start/end nodes (${n.startNodeId}/${n.endNodeId}) in original path for ${n.connectionName}`);continue}const[r,h]=o<=a?[o,a]:[a,o],c=s.slice(0,r),d=s.slice(h+1);let l=i;if(i.length>0&&s[r]&&i[0].capacityMeshNodeId!==s[r].capacityMeshNodeId){if(i[i.length-1].capacityMeshNodeId!==s[r].capacityMeshNodeId){console.warn(`New section path for ${n.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,n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,s)}}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const n=e.path;n&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:n.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 Ii({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)"})}},Ri=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 n of this.multiLayerNodes){const s=n.center.x-n.width/2,i=n.center.x+n.width/2,o=n.center.y-n.height/2,a=n.center.y+n.height/2,r=Math.max(t.minX,s),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)/(n.width*n.height);e+=ve(n)*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:n,rightSurroundingCapacity:s,topSurroundingCapacity:i,bottomSurroundingCapacity:o}=this.getSurroundingCapacities(t);if(1*(n+s)>i+o){const n=Math.floor(t.height/this.strawSize),s=t.height/n;for(let i=0;i<n;i++){const n=t.center.y-t.height/2+i*s+s/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:t.center.x,y:n},width:t.width,height:s,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}else{const n=Math.floor(t.width/this.strawSize),s=t.width/n;for(let i=0;i<n;i++){const n=t.center.x-t.width/2+i*s+s/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:n,y:t.center.y},width:s,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 n=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:n,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}},Oi=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,n]}of e)this.adjacencyList.get(t).add(n),this.adjacencyList.get(n).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[n]=e,s=n?this.adjacencyList.get(n):void 0;if(!n||!s)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));s.delete(t),this.removedNodeIds.add(t),this.adjacencyList.delete(t),1!==s.size||this.targetNodeIds.has(n)||this.leaves.push(n),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 n of e.nodeIds)t.set(n,1+(t.get(n)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const n=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+n*e.width*.05,y:e.center.y-n*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 n=this.nodeMap.get(t.nodeIds[0]),s=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&s?.center){const i=Math.min(...n.availableZ),o=Math.min(...s.availableZ),a={x:n.center.x+i*n.width*.05,y:n.center.y-i*n.width*.05},r={x:s.center.x+o*s.width*.05,y:s.center.y-o*s.width*.05},h=Array.from(new Set([...n.availableZ,...s.availableZ])).sort();e.lines.push({layer:`z${h.join(",")}`,points:[a,r],strokeDash:n.availableZ.join(",")===s.availableZ.join(",")?void 0:"10 5",strokeColor:t.nodeIds.some(t=>this.removedNodeIds.has(t))?H("black",.9):void 0})}}return e}};function Di(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Li=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 n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,i=Math.max(n,s),o=e.targetMinCapacity??.5;e.capacityDepth=Se(i,o)}this.connMap=xe(t),this.colorMap=B(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?G():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=[Di("netToPointPairsSolver",He,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=B(t.srjWithPointPairs,this.connMap),t.connMap=xe(t.srjWithPointPairs)}}),Di("nodeSolver",cs,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Di("strawSolver",Ri,t=>[{nodes:t.capacityNodes}],{onSolved:t=>{t.capacityNodes=t.strawSolver?.getResultNodes()}}),Di("edgeSolver",De,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Di("deadEndSolver",Oi,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)))}}),Di("initialPathingSolver",vi,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),Di("pathingOptimizer",Ai,t=>[{initialPathingSolver:t.initialPathingSolver,simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,cacheProvider:t.cacheProvider,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),Di("edgeToPortSegmentSolver",Vs,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.pathingOptimizer?.getCapacityPaths()||[],colorMap:t.colorMap}]),Di("segmentToPointSolver",Js,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),Di("unravelMultiSectionSolver",gi,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),Di("highDensityRouteSolver",me,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),Di("highDensityStitchSolver",we,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),Di("traceSimplificationSolver",Ds,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(),n=this.nodeSolver?.visualize(),s=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,n,s,i,o,a,r,h,c,d,l,u,p?t(x,p):null,f,g,this.solved?t(x,ze(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 n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.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 n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,i=e.filter(t=>t.connectionName===n.name);for(let e=0;e<i.length;e++){const o=i[e],a={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:Ne(o,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Fi=class{constructor(t){this.targets=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],s=Math.floor(n.bounds.minX/this.CELL_SIZE)*this.CELL_SIZE,i=Math.floor(n.bounds.minY/this.CELL_SIZE)*this.CELL_SIZE,o=n.bounds.maxX,a=n.bounds.maxY;for(let t=s;t<=o;t+=this.CELL_SIZE)for(let s=i;s<=a;s+=this.CELL_SIZE){const i=this.getBucketKey(t,s),o=this.buckets.get(i);o?o.push([n,e]):this.buckets.set(i,[[n,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,n,s){const i=[],o=new Set,a=Math.floor((t-n/2)/this.CELL_SIZE)*this.CELL_SIZE,r=Math.floor((e-s/2)/this.CELL_SIZE)*this.CELL_SIZE,h=t+n/2,c=e+s/2;for(let t=a;t<=h;t+=this.CELL_SIZE)for(let e=r;e<=c;e+=this.CELL_SIZE){const n=this.getBucketKey(t,e),s=this.buckets.get(n)||[];for(const t of s)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},$i=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 n=[];for(const s of e.layers)n.push(Ce(s,t.layerCount));e.zLayers=n}const n={x:(t.bounds.minX+t.bounds.maxX)/2,y:(t.bounds.minY+t.bounds.maxY)/2},s={width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},i=Math.max(s.width,s.height);this.unfinishedNodes=[{capacityMeshNodeId:this.getNextNodeId(),center:n,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 us("flatbush",this.srj.obstacles),this.targets=this.computeTargets(),this.targetTree=new Fi(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 n of e.pointsToConnect){const s=Ie(n),i=this.obstacleTree.searchArea(n.x,n.y,.01,.01).filter(t=>t.zLayers.some(t=>s.some(e=>t===Ce(e,this.layerCount))));let o={minX:n.x-.005,minY:n.y-.005,maxX:n.x+.005,maxY:n.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={...n,connectionName:e.name,availableZ:s.map(t=>Ce(t,this.layerCount)),bounds:o};t.push(a)}return t}getNodeBounds(t){const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-n,maxY:t.center.y+n}}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 n of e)if(n.bounds.minX<=t.center.x+t.width/2&&n.bounds.maxX>=t.center.x-t.width/2&&n.bounds.minY<=t.center.y+t.height/2&&n.bounds.maxY>=t.center.y-t.height/2&&n.availableZ.some(e=>t.availableZ.includes(e)))return n;return null}getXYOverlappingObstacles(t){const e=this.nodeToXYOverlappingObstaclesMap.get(t.capacityMeshNodeId);if(e)return e;const n=[],s=this.getNodeBounds(t),i=s.minX,o=s.maxX,a=s.minY,r=s.maxY,h=t._parent?this.getXYOverlappingObstacles(t._parent):this.srj.obstacles;for(const t of h){const e=t.center.x-t.width/2,s=t.center.x+t.width/2,h=t.center.y-t.height/2,c=t.center.y+t.height/2;o>=e&&i<=s&&r>=h&&a<=c?n.push(t):(i>=e&&o<=s&&a>=h&&r<=c||e>=i&&s<=o&&h>=a&&c<=r)&&n.push(t)}return this.nodeToXYOverlappingObstaclesMap.set(t.capacityMeshNodeId,n),n}getXYZOverlappingObstacles(t){const e=this.getXYOverlappingObstacles(t),n=[];for(const s of e)t.availableZ.some(t=>s.zLayers.includes(t))&&n.push(s);return n}doesNodeOverlapObstacle(t){if(this.getXYZOverlappingObstacles(t).length>0)return!0;const e=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!pt(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),n=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!ut(e,this.outlinePolygon))return!0}for(const t of e){const e=t.center.x-t.width/2,s=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2;if(n.minX>=e&&n.maxX<=s&&n.minY>=i&&n.maxY<=o)return!0}return!1}getChildNodes(t){if(t._depth===this.MAX_DEPTH)return[];const e=[],n={width:t.width/2,height:t.height/2},s=[{x:t.center.x-n.width/2,y:t.center.y-n.height/2},{x:t.center.x+n.width/2,y:t.center.y-n.height/2},{x:t.center.x-n.width/2,y:t.center.y+n.height/2},{x:t.center.x+n.width/2,y:t.center.y+n.height/2}];for(const i of s){const s={capacityMeshNodeId:this.getNextNodeId(),center:i,width:n.width,height:n.height,layer:t.layer,availableZ:t.availableZ,_depth:(t._depth??0)+1,_parent:t};s._containsObstacle=this.doesNodeOverlapObstacle(s);const o=this.getTargetIfNodeContainsTarget(s);o&&(s._targetConnectionName=o.connectionName,s.availableZ=o.availableZ,s._containsTarget=!0),s._containsObstacle&&(s._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(s)),s._completelyInsideObstacle&&!s._containsTarget||e.push(s)}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),n=[],s=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t);e?s.push(t):e||t._containsObstacle?!e&&t._containsTarget&&n.push(t):n.push(t)}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}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 n of e){const e=Math.min(...n.availableZ),s=this.unfinishedNodes.length>0&&n===this.unfinishedNodes[this.unfinishedNodes.length-1];t.rects.push({center:{x:n.center.x+e*n.width*.05,y:n.center.y-e*n.width*.05},width:Math.max(n.width-2,.8*n.width),height:Math.max(n.height-2,.8*n.height),fill:n._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)"}[n.availableZ.join(",")]??"rgba(0,200,200,0.1)",stroke:s?"rgba(255,165,0,0.5)":void 0,label:[n.capacityMeshNodeId,`availableZ: ${n.availableZ.join(",")}`,`target? ${n._containsTarget??!1}`,`obs? ${n._containsObstacle??!1}`,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`capacity: ${ve(n).toFixed(2)}`].join("\n")})}return t.rects.sort((t,e)=>t.center.y-e.center.y),this.srj.connections.forEach((e,n)=>{const s=Y[n%Y.length];for(const i of e.pointsToConnect){const e=Ie(i);t.points.push({x:i.x,y:i.y,label:`conn-${n} (${e.join(",")})`,color:s})}}),t}},ki=class extends $i{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(!ut(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!!ut(e,this.outlinePolygon)&&!pt(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 n=t.center.x-t.width/2,s=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(n,t.center.x-t.width/2),a=Math.min(s,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 n={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},s=this.getXYZOverlappingObstacles(n);n._containsObstacle=s.length>0||this.isNodePartiallyOutsideBounds(n);const i=this.getTargetIfNodeContainsTarget(n);return i&&(n._targetConnectionName=i.connectionName,n._containsTarget=!0),n._containsObstacle&&(n._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(n)),n}getZSubdivisionChildNodes(t){if(1===t.availableZ.length)return[];const e=[],n=t.availableZ.map(t=>[t]);for(const s of n){const n=this.createChildNodeAtPosition(t,{center:{...t.center},width:t.width,height:t.height,availableZ:s,_depth:t._depth});this.isNodeCompletelyOutsideBounds(n)||e.push(n)}return e}getChildNodes(t){if(t._depth>=this.MAX_DEPTH)return[];const e=[],n={width:t.width/2,height:t.height/2},s=[{x:t.center.x-n.width/2,y:t.center.y-n.height/2},{x:t.center.x+n.width/2,y:t.center.y-n.height/2},{x:t.center.x-n.width/2,y:t.center.y+n.height/2},{x:t.center.x+n.width/2,y:t.center.y+n.height/2}];for(const i of s){const s=this.createChildNodeAtPosition(t,{center:i,width:n.width,height:n.height,availableZ:t.availableZ});this.isNodeCompletelyOutsideBounds(s)||e.push(s)}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),n=[],s=[];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)s.push(t);else if(e||this.shouldFilterNodeForObstacle(t)||i)if(!e&&t._containsTarget)if(i){const e=this.getZSubdivisionChildNodes(t);n.push(...e.filter(t=>t._containsTarget||!this.shouldFilterNodeForObstacle(t)))}else n.push(t);else i&&n.push(...this.getZSubdivisionChildNodes(t).filter(t=>!this.shouldFilterNodeForObstacle(t)));else n.push(t)}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}},Xi=class extends ki{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 n of t){const t=[];for(const e of this.finishedNodes){this.getXYZOverlappingObstacles(e).some(t=>t===n)&&t.push(e)}e.set(n,t)}const n=new Set;for(const t of e.values())for(const e of t)n.add(e);this.finishedNodes=this.finishedNodes.filter(t=>!n.has(t));for(const n of t){const t=e.get(n)||[],s=n.layers&&n.layers.length>0?Array.from(new Set(n.layers.map(t=>Ce(t,this.srj.layerCount)))).sort((t,e)=>t-e):Array.from({length:this.srj.layerCount},(t,e)=>this.srj.layerCount-e-1);let i=n.center.x-n.width/2,o=n.center.x+n.width/2,a=n.center.y-n.height/2,r=n.center.y+n.height/2;for(const e of t){const t=e.center.x-e.width/2,n=e.center.x+e.width/2,s=e.center.y-e.height/2,h=e.center.y+e.height/2;i=Math.min(i,t),o=Math.max(o,n),a=Math.min(a,s),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_${n.center.x}_${n.center.y}`,center:{x:d,y:l},width:h,height:c,layer:1===s.length?`z${s[0]}`:`z${s.join(",")}`,availableZ:s,_depth:0,_containsTarget:u,_containsObstacle:!1,_completelyInsideObstacle:!1};p._assignedViaObstacle=n,this.finishedNodes.push(p)}}_step(){const t=this.unfinishedNodes.pop();if(!t)return this.insertAssignableObstaclesAsNodes(),void(this.solved=!0);const e=this.getChildNodes(t),n=[],s=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),i=t.availableZ.length>1&&!e;if(e)s.push(t);else{if(i){const e=this.getZSubdivisionChildNodes(t);for(const t of e)!t._containsTarget&&this.shouldFilterNodeForObstacle(t)||(this.shouldNodeBeXYSubdivided(t)?s.push(t):(t._containsObstacle=!1,n.push(t)));continue}this.shouldFilterNodeForObstacle(t)&&!t._containsTarget||n.push(t)}}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}},Yi=.005,Bi=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 n of t)n._assignedViaObstacle?(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId)):n._containsTarget?n.availableZ.length>1?(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId)):e.push([n,n.width*n.height]):(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId));e.sort((t,e)=>t[1]-e[1]);for(const[t,n]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))),n=[];for(let s=0;s<=e;s++)n.push(new Oe(t.filter(t=>t.availableZ[0]===s)));for(const e of t){const t=[],s=n[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const n of s)n._containsTarget&&n._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!n._containsTarget||n._targetConnectionName!==e._targetConnectionName)||n.capacityMeshNodeId!==e.capacityMeshNodeId&&Ae(e,n)&&t.push(n);e._adjacentNodeIds=t.map(t=>t.capacityMeshNodeId)}}getAdjacentSameLayerUnprocessedNodes(t){const e=[],n=Array.from(new Set((t._adjacentNodeIds??[]).map(t=>this.nodeMap.get(t)))).filter(e=>e&&e.capacityMeshNodeId!==t.capacityMeshNodeId);n.sort((t,e)=>t.width*t.height-e.width*e.height);for(const t of n)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 n=this.nodeMap.get(t),s=this.nodeMap.get(e);return n.width*n.height-s.width*s.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 n=!1;const s=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===s.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=s.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:s}=o[0],a=o.every(e=>e.width===t&&e.height===s);Math.abs(o.reduce((t,e)=>t+e.height,0)-e.height)<Yi&&a&&(e.width+=t,e.center.x=e.center.x-t/2,i(o),n=!0)}const a=s.filter(t=>t.center.x>e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(a.length>0&&!n){const{width:t,height:s}=a[0],o=a.every(e=>e.width===t&&e.height===s);Math.abs(a.reduce((t,e)=>t+e.height,0)-e.height)<Yi&&o&&(e.width+=t,e.center.x=e.center.x+t/2,i(a),n=!0)}const r=s.filter(t=>t.center.y>e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(r.length>0&&!n){const{width:t,height:s}=r[0],o=r.every(e=>e.width===t&&e.height===s);Math.abs(r.reduce((t,e)=>t+e.width,0)-e.width)<Yi&&o&&(e.height+=s,e.center.y=e.center.y+s/2,i(r),n=!0)}const h=s.filter(t=>t.center.y<e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(h.length>0&&!n){const{width:t,height:s}=h[0],o=h.every(e=>e.width===t&&e.height===s);Math.abs(h.reduce((t,e)=>t+e.width,0)-e.width)<Yi&&o&&(e.height+=s,e.center.y=e.center.y-s/2,i(h),n=!0)}n?(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(mi(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let n;e&&(n=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const s of this.currentBatchNodeIds){const i=this.nodeMap.get(s);if(!this.absorbedNodeIds.has(s)&&i){const o=mi(i,{rectMargin:.01});s===e?o.stroke="rgba(0, 255, 0, 0.8)":n?.some(t=>t.capacityMeshNodeId===s)?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 n=this.nodeMap.get(e);if(!this.absorbedNodeIds.has(e)&&n){const e=mi(n,{rectMargin:.01});e.layer=`z${n.availableZ.join(",")}`,e.stroke="rgba(0, 217, 255, 0.8)",e.label=`${e.label}\nx: ${n.center.x}, y: ${n.center.y}\n${n.width}x${n.height}\n(next batch)`,t.rects.push(e)}}return t}},Hi=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 n=this.obstacleToNodesMap.get(t)||[];n.push(e),this.obstacleToNodesMap.set(t,n)}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 n=Number.POSITIVE_INFINITY,s=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;n=Math.min(n,e),s=Math.max(s,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=s-n,c=o-i,d=(n+s)/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 n=mi(e);e._assignedViaObstacle&&(n.stroke="rgba(255, 0, 255, 0.8)",n.label=`${n.label||""}\n(merged via)`),t.rects.push(n)}const e=this.obstaclesToProcess[this.obstaclesToProcess.length-1];if(e){const n=this.obstacleToNodesMap.get(e)||[];for(const e of n){const n=mi(e,{rectMargin:.01});n.stroke="rgba(0, 255, 0, 0.8)",n.label=`${n.label||""}\n(to be merged)`,t.rects.push(n)}}return t}},ji=class extends e{constructor(t){const{simpleRouteJson:e,nodes:n,edges:s,colorMap:i,MAX_ITERATIONS:o=1e6,hyperParameters:a={}}=t;super(),this.inputParams=t,this.hyperParameters=a,this.MAX_ITERATIONS=o,this.simpleRouteJson=e,this.nodes=n,this.edges=s,this.colorMap=i??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ls(this.edges);const r=this.nodes.filter(t=>t._containsTarget);this.unprocessedConnectionPairs=Pt(this.simpleRouteJson.connections.map(t=>{const[e,n]=t.pointsToConnect;return{start:r.find(t=>st(t.center,e)<t.width/2),end:r.find(t=>st(t.center,n)<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 n=e.reduce((e,n)=>{const s=this._dist(e,t.start);return this._dist(n,t.start)<s?n:e});this.closestViaForConnectionStartMap.set(t,n);const s=e.reduce((e,n)=>{const s=this._dist(e,t.end);return this._dist(n,t.end)<s?n:e});this.closestViaForConnectionEndMap.set(t,s)}}}_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:n}=t;if(e.capacityMeshNodeId===n.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,n),s={prevCandidate:null,node:e,g:0,h:t,f:this.GREEDY_MULTIPLIER*t};this.queuedCandidateNodes.push(s)}let s;for(this.queuedCandidateNodes.sort((t,e)=>t.f-e.f);this.queuedCandidateNodes.length&&!s;){const t=this.queuedCandidateNodes.shift();this.visitedNodes.has(t.node.capacityMeshNodeId)||(s=t)}if(!s)return this.failed=!0,void(this.error="No viable candidates left");if(this.visitedNodes.add(s.node.capacityMeshNodeId),s.node.capacityMeshNodeId===n.capacityMeshNodeId){const e=[];let n=s;for(;n;)e.unshift(n.node),this.usedNodeMap.set(n.node.capacityMeshNodeId,!0),n=n.prevCandidate;return t.path=e,void(t.solved=!0)}const i=this.getNeighbors(s.node);for(const t of i){const e=t.capacityMeshNodeId;if(this.visitedNodes.has(e))continue;const i=this.computeG(s,t,n),o=this.computeH(s,t,n),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:s,node:t,g:i,h:o,f:a})}}getNeighbors(t){const e=new Set,n=this.nodeEdgeMap.get(t.capacityMeshNodeId)??[];for(const s of n){const[n,i]=s.nodeIds,o=n===t.capacityMeshNodeId?i:n,a=this.nodeMap.get(o);a&&e.add(a)}const s=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!==s&&!t.availableZ.includes(s)))))}clearCandidateNodes(){this.queuedCandidateNodes=[],this.visitedNodes=new Set}computeG(t,e,n){const s=this._dist(t.node,e);return t.g+s}computeH(t,e,n){return this._dist(e,n)}createSolvedRoute(t,e){const n=[];for(let e=0;e<t.length;e++){const s=t[e];s.path?0===e?n.push(...s.path):n.push(...s.path.slice(1)):(0===e&&n.push(s.start),e===t.length-1&&n.push(s.end))}return{connection:e.connection,path:n}}breakConnectionPairIntoSubpaths(t){var e,n;if(!(e=[this.hyperParameters.DIRECTIVE_SEED??0,this.solvedRoutes.length],n=this.hyperParameters.FORCE_VIA_TRAVEL_CHANCE??0,Nt(e.reduce((t,e)=>t+16807*e%2147483647,0))()<n))return[{start:t.start,end:t.end,solved:!1,layer:t.start.availableZ[0]??0}];const s=this.getClosestVia(t.start),i=this.getFarVia(s,t.end),o=t.start.availableZ[0]??0,a=t.end.availableZ[0]??0,r=[];return r.push({start:t.start,end:s,solved:!1,layer:o}),o===a?(r.push({start:s,end:i,solved:!1,layer:0===o?1:0}),r.push({start:i,end:t.end,solved:!1,layer:a})):r.push({start:s,end:t.end,solved:!1,layer:a}),r}getClosestVia(t){if(0===this.viaNodes.length)return t;const e=new Set;for(const[t,n]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&e.add(n.capacityMeshNodeId);for(const[t,n]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&e.add(n.capacityMeshNodeId);const n=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId)).filter(t=>!e.has(t.capacityMeshNodeId));if(0===n.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,n)=>this._dist(e,t)-this._dist(n,t)),e[0])}n.sort((e,n)=>this._dist(e,t)-this._dist(n,t));const s=this.hyperParameters.MAX_CLOSEST_VIA_SKIP??0;if(s>0&&n.length>1){const t=Nt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length),e=Math.floor(t()*(s+1));return n[Math.min(e,n.length-1)]}return n[0]}getFarVia(t,e){if(0===this.viaNodes.length)return t;const n=null!=this.hyperParameters.FAR_VIA_MIN_DISTANCE?this.hyperParameters.FAR_VIA_MIN_DISTANCE:50,s=new Set;for(const[t,e]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&s.add(e.capacityMeshNodeId);for(const[t,e]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&s.add(e.capacityMeshNodeId);const i=this.viaNodes.filter(e=>!this.usedNodeMap.has(e.capacityMeshNodeId)&&e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!s.has(e.capacityMeshNodeId)&&this._dist(e,t)>=n);if(0===i.length){const s=this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)&&this._dist(e,t)>=n).sort((t,n)=>this._dist(t,e)-this._dist(n,e));if(s.length>0)return s[0];return this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)).sort((t,n)=>this._dist(t,e)-this._dist(n,e))[0]??t}i.sort((t,n)=>this._dist(t,e)-this._dist(n,e));const o=this.hyperParameters.MAX_FURTHEST_VIA_SKIP??0;if(o>0&&i.length>1){const t=Nt((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 n=e.path;n&&n.length>0&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:n.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),n=t=>"number"==typeof t&&!Number.isNaN(t)&&Number.isFinite(t);for(const s of this.nodes){const i=this.queuedCandidateNodes.some(t=>t.node.capacityMeshNodeId===s.capacityMeshNodeId),o=this.queuedCandidateNodes.find(t=>t.node.capacityMeshNodeId===s.capacityMeshNodeId);if(e(s.center)&&n(s.width)&&n(s.height)){const e=mi(s,{rectMargin:.025,zOffset:.01});t.rects.push({...e,fill:i?"rgba(255, 128, 255, 0.5)":s._containsTarget?"rgba(0, 150, 255, 0.15)":s._containsObstacle?"rgba(255, 0, 0, 0.1)":"rgba(200, 200, 200, 0.05)",label:[`ID: ${s.capacityMeshNodeId}`,`Size: ${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Z: ${s.availableZ.join(", ")}`,o?`g: ${o.g.toFixed(2)}`:"",o?`h: ${o.h.toFixed(2)}`:"",o?`f: ${o.f.toFixed(2)}`:"",s._containsTarget?"TARGET":"",s._containsObstacle?"OBSTACLE":""].filter(t=>t).join("\n")})}}for(const n of this.edges){const[s,i]=n.nodeIds,o=this.nodeMap.get(s),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 n=0;n<this.solvedRoutes.length;n++){const s=this.solvedRoutes[n],i=s.path,o="blue";for(let s=0;s<i.length-1;s++){const a=i[s],r=i[s+1];if(a?.center&&r?.center&&e(a.center)&&e(r.center)){const e=a.availableZ.includes(1)&&r.availableZ.includes(1),s=n%5*.02;t.lines.push({points:[{x:a.center.x+s,y:a.center.y+s},{x:r.center.x+s,y:r.center.y+s}],strokeColor:o,strokeDash:e?"5 5":void 0})}}if(i.length>0){const n=i[0],o=i[i.length-1];n?.center&&e(n.center)&&t.points.push({x:n.center.x,y:n.center.y,label:`START: ${s.connection.name}`}),o?.center&&e(o.center)&&t.points.push({x:o.center.x,y:o.center.y,label:`END: ${s.connection.name}`})}}if(this.solvedSubpaths)for(let n=0;n<this.solvedSubpaths.length;n++){const s=this.solvedSubpaths[n];if(s.path&&s.path.length>1)for(let n=0;n<s.path.length-1;n++){const i=s.path[n],o=s.path[n+1];i?.center&&o?.center&&e(i.center)&&e(o.center)&&t.lines.push({points:[i.center,o.center],strokeColor:"green",strokeDash:1===s.layer?"3 3":void 0})}}if(this.activeSubpath){const n=this.activeSubpath.start?.center,s=this.activeSubpath.end?.center;n&&s&&e(n)&&e(s)&&(t.lines.push({points:[n,s],strokeColor:"orange",strokeDash:"5 5"}),t.points.push({x:n.x,y:n.y,label:"ACTIVE START"}),t.points.push({x:s.x,y:s.y,label:"ACTIVE END"}))}const s=this.queuedCandidateNodes.slice(0,10).sort((t,e)=>t.f-e.f);for(let n=0;n<s.length;n++){const i=.6*(1-n/10),o=[];let a=s[n];for(;a;)o.push(a.node),a=a.prevCandidate;if(o.reverse(),o.length>1){const n=o.map(t=>t.center).filter(t=>e(t));n.length>1&&t.lines.push({points:n,strokeColor:H("purple",1-i),strokeDash:1===this.activeSubpath?.layer?"4 2":void 0})}}if(this.activeConnectionPair){const n=this.activeConnectionPair.start?.center,s=this.activeConnectionPair.end?.center;n&&s&&e(n)&&e(s)&&t.lines.push({points:[n,s],strokeColor:"cyan",strokeDash:"20 5"})}if(this.ogUnprocessedSubpaths&&3===this.ogUnprocessedSubpaths.length){const[,s]=this.ogUnprocessedSubpaths;if(s.start?.center&&e(s.start.center)){const e=Math.max(s.start.width||0,s.start.height||0);n(e)&&e>0&&(t.circles.push({center:s.start.center,radius:e,stroke:"blue"}),t.points.push({x:s.start.center.x,y:s.start.center.y,label:"DIRECTIVE VIA 1"}))}if(s.end?.center&&e(s.end.center)){const e=Math.max(s.end.width||0,s.end.height||0);n(e)&&e>0&&(t.circles.push({center:s.end.center,radius:e,stroke:"purple"}),t.points.push({x:s.end.center.x,y:s.end.center.y,label:"DIRECTIVE VIA 2"}))}}if(this.queuedCandidateNodes.length>0)for(const n of this.queuedCandidateNodes){const s=n.node;s?.center&&e(s.center)&&t.circles.push({center:s.center,radius:.05,fill:"rgba(255, 255, 0, 0.6)",stroke:"yellow"})}if(this.visitedNodes.size>0)for(const n of this.visitedNodes){const s=this.nodeMap.get(n);s?.center&&e(s.center)&&t.circles.push({center:s.center,radius:.08,fill:"rgba(128, 128, 128, 0.5)",stroke:"gray"})}return t}},Zi=class extends wt{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),n=t.solvedRoutes.length,s=e>0?n/e:0;return t.iterations/t.MAX_ITERATIONS+(1-s)}computeH(t){const e=t.unprocessedConnectionPairs.length+t.solvedRoutes.length+(t.activeConnectionPair?1:0),n=t.solvedRoutes.length;return e>0?1-n/e:0}generateSolver(t){return new ji({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}};function Wi(t){const e=new Map;for(const n of t)e.set(n.capacityMeshNodeId,n);return e}function Vi(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var Ui=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=Wi(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 n=e._assignedViaObstacle;if(n?.offBoardConnectsTo)for(const s of n.offBoardConnectsTo)t.has(s)||t.set(s,[]),t.get(s).push(e)}this.pendingEdges=[];for(const[e,n]of t)if(n.length>1)for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++)this.pendingEdges.push({node1:n[t],node2:n[s],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:n}=this.pendingEdges.shift(),s=this.createOffboardEdge(t,e,n);this.enhancedEdges.push(s),this.createdEdges.push(s)}else this.animationState="done",this.solved=!0;break;case"done":this.solved=!0}}createOffboardEdge(t,e,n){return{capacityMeshEdgeId:"offboard_"+this.nextEdgeId++,nodeIds:[t.capacityMeshNodeId,e.capacityMeshNodeId],isOffboardEdge:!0,offboardNetName:n}}visualize(){const t=[],e=[],n=[],s=new Set(this.shownNodes.map(t=>t.capacityMeshNodeId));for(const e of this.capacityEdges){if(e.isOffboardEdge)continue;if(s.has(e.nodeIds[0])||s.has(e.nodeIds[1])){const n=this.nodeMap.get(e.nodeIds[0]),s=this.nodeMap.get(e.nodeIds[1]);n&&s&&t.push({points:[n.center,s.center],strokeColor:"rgba(0, 200, 0, 0.5)",strokeWidth:.05})}}for(let t=0;t<this.shownNodes.length;t++){const s=this.shownNodes[t],i=s._assignedViaObstacle,o=t===this.shownNodes.length-1&&"showing_nodes"===this.animationState;n.push({center:s.center,width:s.width,height:s.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:s.center.x,y:s.center.y,color:o?"orange":"blue",label:`${o?"NEW: ":""}${s.capacityMeshNodeId}\n${i?.offBoardConnectsTo?.join(", ")||""}`})}for(let n=0;n<this.createdEdges.length;n++){const s=this.createdEdges[n],i=n===this.createdEdges.length-1&&"showing_edges"===this.animationState,o=this.nodeMap.get(s.nodeIds[0]),a=this.nodeMap.get(s.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 n=Vi(o.center,a.center);e.push({x:n.x,y:n.y,color:i?"red":"orange",label:`${i?"NEW: ":""}⚡ ${s.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:n,title:i}}getVirtualOffboardNodes(){return[]}getOffboardEdges(){return this.enhancedEdges.filter(t=>t.isOffboardEdge)}};function Gi(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 qi=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:n,connections:s}){super(),this.inputPaths=[...t],this.capacityEdges=e,this.originalConnections=s,this.nodeMap=Wi(n)}_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 n=this.originalConnections.find(e=>e.name===t.connectionName);if(n)for(let t=0;t<e.length;t++){const s=e[t];if(!s.isFragmentedPath)continue;const i=n.pointsToConnect.filter(t=>{for(const e of s.nodeIds){const n=this.nodeMap.get(e);if(n&&Gi(t,n))return!0}return!1}),o=0===t,a=o?s.nodeIds[s.nodeIds.length-1]:s.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:Pe(t)},a=o?[...i,e]:[e,...i];this.fragmentedConnections.push({name:s.connectionName,pointsToConnect:a,netConnectionName:n.netConnectionName,rootConnectionName:n.rootConnectionName})}}}splitPath(t){const{nodeIds:e}=t;if(e.length<2)return[t];const n=[];for(let t=0;t<e.length-1;t++){const s=this.capacityEdges.find(n=>n.nodeIds[0]===e[t]&&n.nodeIds[1]===e[t+1]||n.nodeIds[0]===e[t+1]&&n.nodeIds[1]===e[t]);s&&s.isOffboardEdge&&n.push(t)}if(0===n.length)return[t];const s=[];let i=0,o=0;for(const a of n){const n=e.slice(i,a+1);if(n.length>=1){const e=this.nextFragmentId++;s.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${o++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}i=a+1}if(i<e.length){const n=e.slice(i);if(n.length>=1){const e=this.nextFragmentId++;s.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${o++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}}return s.length>0?s:[t]}getFragmentedPaths(){return this.fragmentedPaths}getFragmentedConnections(){return this.fragmentedConnections}getFragmentedOriginalConnectionNames(){return this.fragmentedOriginalConnectionNames}visualize(){const t=[],e=[],n=[];if("showing_original_path"===this.animationState&&this.currentPath&&this.drawPath({path:this.currentPath,color:"gray",lines:t,points:e,rects:n,labelPrefix:"Original: "}),this.fragmentedPaths.forEach((s,i)=>{if(s.isFragmentedPath){const o=i%2==0?"blue":"red";this.drawPath({path:s,color:o,lines:t,points:e,rects:n,labelPrefix:`Frag ${i}: `})}else this.drawPath({path:s,color:"green",lines:t,points:e,rects:n,labelPrefix:""})}),"showing_fragment"===this.animationState&&this.currentFragmentIndex>0){const s=this.fragmentedPaths.length-1;if(s>=0){const i=this.fragmentedPaths[s];i.isFragmentedPath&&this.drawPath({path:i,color:"orange",lines:t,points:e,rects:n,labelPrefix:"NEW: "})}}for(const e of this.capacityEdges)if(e.isOffboardEdge){const n=this.nodeMap.get(e.nodeIds[0]),s=this.nodeMap.get(e.nodeIds[1]);n&&s&&t.push({points:[n.center,s.center],strokeColor:"orange",strokeWidth:.15,strokeDasharray:"0.3,0.15"})}let s="Offboard Path Fragment Solver";return"showing_original_path"===this.animationState?s+=" - Analyzing path...":"showing_fragment"===this.animationState?s+=` - Fragment ${this.currentFragmentIndex}/${this.currentFragments.length}`:s+=` - Done (${this.fragmentedPaths.filter(t=>t.isFragmentedPath).length} fragments)`,{lines:t,points:e,rects:n,title:s}}drawPath(t){const{path:e,color:n,lines:s,points:i,rects:o,labelPrefix:a}=t,r=[];for(let t=0;t<e.nodeIds.length;t++){const s=e.nodeIds[t],h=this.nodeMap.get(s);h&&(r.push(h.center),o.push({center:h.center,width:.8*h.width,height:.8*h.height,stroke:n,strokeWidth:.05,fill:`${n}33`}),0!==t&&t!==e.nodeIds.length-1||i.push({x:h.center.x,y:h.center.y,color:n,label:`${a}${e.connectionName}\n${s}`}))}r.length>1&&s.push({points:r,strokeColor:n,strokeWidth:.1})}};function Ki(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Ji=class extends e{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,i=Math.max(n,s),o=e.targetMinCapacity??.5;e.capacityDepth=Se(i,o)}this.connMap=xe(t),this.colorMap=B(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?G():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=[Ki("netToPointPairsSolver",Be,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=B(t.srjWithPointPairs,this.connMap),t.connMap=xe(t.srjWithPointPairs)}}),Ki("nodeSolver",Xi,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),Ki("mergeAssignableViaNodes",Hi,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.mergeAssignableViaNodes?.newNodes}}),Ki("singleLayerNodeMerger",Bi,t=>[t.capacityNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),Ki("edgeSolver",De,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Ki("offboardCapacityNodeSolver",Ui,t=>[{capacityNodes:t.capacityNodes,capacityEdges:t.capacityEdges||[]}],{onSolved:t=>{t.capacityEdges=t.offboardCapacityNodeSolver?.enhancedEdges||t.capacityEdges}}),Ki("deadEndSolver",Oi,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)))}}),Ki("initialPathingHyperSolver",Zi,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)}}),Ki("offboardPathFragmentSolver",qi,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 n=e.getFragmentedPaths();for(const e of n)if(e.isFragmentedPath&&e.mstPairConnectionName){const n=t.colorMap[e.mstPairConnectionName];n&&!t.colorMap[e.connectionName]&&(t.colorMap[e.connectionName]=n)}const s=e.getFragmentedOriginalConnectionNames(),i=e.getFragmentedConnections();s.size>0&&t.srjWithPointPairs&&(t.srjWithPointPairs={...t.srjWithPointPairs,connections:[...t.srjWithPointPairs.connections.filter(t=>!s.has(t.name)),...i]},t.connMap=xe(t.srjWithPointPairs))}}),Ki("edgeToPortSegmentSolver",Vs,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.offboardPathFragmentSolver?.getFragmentedPaths()||t.initialPathingSolver?.getCapacityPaths()||[],colorMap:t.colorMap}]),Ki("segmentToPointSolver",Js,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),Ki("unravelMultiSectionSolver",gi,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),Ki("highDensityRouteSolver",me,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap}]),Ki("highDensityStitchSolver",we,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Ki("uselessViaRemovalSolver1",Ss,t=>[{unsimplifiedHdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Ki("multiSimplifiedPathSolver1",Rs,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver1?.getOptimizedHdRoutes()||t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}]),Ki("uselessViaRemovalSolver2",Ss,t=>[{unsimplifiedHdRoutes:t.multiSimplifiedPathSolver1.simplifiedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Ki("multiSimplifiedPathSolver2",Rs,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(),n=this.nodeSolver?.visualize(),s=this.nodeTargetMerger?.visualize(),i=this.mergeAssignableViaNodes?.visualize(),o=this.singleLayerNodeMerger?.visualize(),a=this.strawSolver?.visualize(),r=this.edgeSolver?.visualize(),h=(this.offboardCapacityNodeSolver?.visualize(),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(),S=this.multiSimplifiedPathSolver2?.visualize(),M=this.srj.outline,N=[];if(N.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]}),N.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const b={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:N},P=[b,e,n,s,i,o,a,r,h,c,d,l,u,p,f,g?t(b,g):null,m,y,v,x,S,this.solved?t(b,ze(this.getOutputSimpleRouteJson())):null].filter(Boolean);return t(...P)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.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(),n=this.srjWithPointPairs?.connections??[];for(const s of n){const n=s.netConnectionName,i=s.rootConnectionName,o=e.filter(t=>t.connectionName===s.name);for(let e=0;e<o.length;e++){const a=o[e],r={type:"pcb_trace",pcb_trace_id:`${s.name}_${e}`,connection_name:n??i??s.name,route:Ne(a,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}};export{Ji as AssignableViaAutoroutingPipelineSolver,Li as AutoroutingPipeline1_OriginalUnravel,Zs as AutoroutingPipelineSolver,Ws as CapacityMeshSolver,Z as InMemoryCache,V as LocalStorageCache,Se as calculateOptimalCapacityDepth,ze as convertSrjToGraphicsObject,G as getGlobalInMemoryCache,U as getGlobalLocalStorageCache,ve as getTunedTotalCapacity1,q as setupGlobalCaches};//# sourceMappingURL=index.js.map