@tscircuit/capacity-autorouter 0.0.131 → 0.0.132

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,s)=>{t&&(t.lines&&(e.lines=[...e.lines||[],...t.lines.map(t=>({...t,step:s}))]),t.points&&(e.points=[...e.points||[],...t.points.map(t=>({...t,step:s}))]),t.circles&&(e.circles=[...e.circles||[],...t.circles.map(t=>({...t,step:s}))]),t.rects&&(e.rects=[...e.rects||[],...t.rects.map(t=>({...t,step:s}))]))}),e},e=class{MAX_ITERATIONS=1e3;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};cacheHit;cacheKey;cacheToSolveSpaceTransform;step(){if(!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,console.error(this.error),this.failed=!0,t}!this.solved&&this.iterations>this.MAX_ITERATIONS&&this.tryFinalAcceptance(),!this.solved&&this.iterations>this.MAX_ITERATIONS&&(this.error=`${this.constructor.name} ran out of iterations`,console.error(this.error),this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}};function s(t){const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-s,maxY:t.center.y+s}}function n(t,e,s){return Math.max(e,Math.min(s,t))}function i(t,e,s,n){const i=o(t,e,s),r=o(t,e,n),h=o(s,n,t),c=o(s,n,e);return i!==r&&h!==c||(!(0!==i||!a(t,s,e))||(!(0!==r||!a(t,n,e))||(!(0!==h||!a(s,t,n))||!(0!==c||!a(s,e,n)))))}function o(t,e,s){const n=(e.y-t.y)*(s.x-e.x)-(e.x-t.x)*(s.y-e.y);return 0===n?0:n>0?1:2}function a(t,e,s){return e.x<=Math.max(t.x,s.x)&&e.x>=Math.min(t.x,s.x)&&e.y<=Math.max(t.y,s.y)&&e.y>=Math.min(t.y,s.y)}function r(t,e,s){const n=(s.x-e.x)**2+(s.y-e.y)**2;if(0===n)return h(t,e);let i=((t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y))/n;i=Math.max(0,Math.min(1,i));return h(t,{x:e.x+i*(s.x-e.x),y:e.y+i*(s.y-e.y)})}function h(t,e){const s=t.x-e.x,n=t.y-e.y;return Math.sqrt(s*s+n*n)}function c(t,e,s,n){const i=e.x-t.x,o=e.y-t.y,a=n.x-s.x,r=n.y-s.y,h=t.x-s.x,c=t.y-s.y,d=i*r-o*a;if(Math.abs(d)<1e-10)return null;const l=(c*a-h*r)/d,u=(i*c-o*h)/d,p=1e-9;if(l>=-1e-9&&l<=1+p&&u>=-1e-9&&u<=1+p){return{x:t.x+l*i,y:t.y+l*o}}return null}function d(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var l=t=>{if("minX"in t)return t;const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,minY:t.center.y-s,maxX:t.center.x+e,maxY:t.center.y+s}},u=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}],p=t=>{const e=[];for(let s=0;s<t.length;s++){const n=t[s],i=t[(s+1)%t.length];e.push([n,i])}return e},f=(t,e,s)=>{const n=(t.y-e.y)*(s.x-e.x)-(t.x-e.x)*(s.y-e.y);if(Math.abs(n)>1e-9)return!1;const i=(t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y);if(i<0)return!1;return!(i>(s.x-e.x)**2+(s.y-e.y)**2)},m=(t,e)=>{if(e.length<3)return!1;const s=p(e);for(const[e,n]of s)if(f(t,e,n))return!0;let n=!1;for(let s=0,i=e.length-1;s<e.length;i=s++){const o=e[s].x,a=e[s].y,r=e[i].x,h=e[i].y;a>t.y!=h>t.y&&t.x<(r-o)*(t.y-a)/(h-a)+o&&(n=!n)}return n},g=(t,e)=>{const s=u(t),n=[[s[0],s[1]],[s[1],s[2]],[s[2],s[3]],[s[3],s[0]]],o=p(e);for(const[t,e]of o)for(const[s,o]of n)if(i(t,e,s,o))return!0;return!1},y=(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))||(!!u(t).some(t=>m(t,e))||g(t,e))))(l(t),e),x=(t,e)=>((t,e)=>!(e.length<3)&&(!!u(t).every(t=>m(t,e))&&!g(t,e)))(l(t),e);function M(t,e,s,n){if(t.x===e.x&&t.y===e.y)return r(t,s,n);if(s.x===n.x&&s.y===n.y)return r(s,t,e);if(i(t,e,s,n))return 0;const o=[r(t,s,n),r(e,s,n),r(s,t,e),r(n,t,e)];return Math.min(...o)}function v(t,e,s){const o=s.width/2,a=s.height/2;return function(t,e,s){const o={x:s.minX,y:s.minY},a={x:s.maxX,y:s.minY},c={x:s.minX,y:s.maxY},d={x:s.maxX,y:s.maxY};if(i(t,e,o,a)||i(t,e,a,d)||i(t,e,d,c)||i(t,e,c,o))return 0;if(t.x>=s.minX&&t.x<=s.maxX&&t.y>=s.minY&&t.y<=s.maxY&&e.x>=s.minX&&e.x<=s.maxX&&e.y>=s.minY&&e.y<=s.maxY)return 0;const l=[r(o,t,e),r(a,t,e),r(c,t,e),r(d,t,e)];if(t.x>=s.minX&&t.x<=s.maxX&&t.y>=s.minY&&t.y<=s.maxY)return 0;if(e.x>=s.minX&&e.x<=s.maxX&&e.y>=s.minY&&e.y<=s.maxY)return 0;if(t.x<s.minX||t.x>s.maxX||t.y<s.minY||t.y>s.maxY){const e=n(t.x,s.minX,s.maxX),i=n(t.y,s.minY,s.maxY);l.push(h(t,{x:e,y:i}))}if(e.x<s.minX||e.x>s.maxX||e.y<s.minY||e.y>s.maxY){const t=n(e.x,s.minX,s.maxX),i=n(e.y,s.minY,s.maxY);l.push(h(e,{x:t,y:i}))}return Math.min(...l)}(t,e,{minX:s.center.x-o,maxX:s.center.x+o,minY:s.center.y-a,maxY:s.center.y+a})}function S(t,e,s){const n=s.x-e.x,i=s.y-e.y,o=n*n+i*i;if(0===o)return{x:e.x,y:e.y};let a=((t.x-e.x)*n+(t.y-e.y)*i)/o;a=Math.max(0,Math.min(1,a));return{x:e.x+a*n,y:e.y+a*i}}function b(){return b=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var n in s)({}).hasOwnProperty.call(s,n)&&(t[n]=s[n])}return t},b.apply(null,arguments)}function N(t,e){return(N=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 P(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(P=function(){return!!t})()}function C(t){var e="function"==typeof Map?new Map:void 0;return C=function(t){if(null===t||!function(t){try{return-1!==Function.toString.call(t).indexOf("[native code]")}catch(e){return"function"==typeof t}}(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,s)}function s(){return function(t,e,s){if(P())return Reflect.construct.apply(null,arguments);var n=[null];n.push.apply(n,e);var i=new(t.bind.apply(t,n));return s&&N(i,s.prototype),i}(t,arguments,I(this).constructor)}return s.prototype=Object.create(t.prototype,{constructor:{value:s,enumerable:!1,writable:!0,configurable:!0}}),N(s,t)},C(t)}var _={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 T(){for(var t=arguments.length,e=new Array(t),s=0;s<t;s++)e[s]=arguments[s];var n,i=e[0],o=[];for(n=1;n<e.length;n+=1)o.push(e[n]);return o.forEach(function(t){i=i.replace(/%[a-z]/,t)}),i}var E=function(t){var e,s;function n(e){var s;if("production"===process.env.NODE_ENV)s=t.call(this,"An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#"+e+" for more information.")||this;else{for(var n=arguments.length,i=new Array(n>1?n-1:0),o=1;o<n;o++)i[o-1]=arguments[o];s=t.call(this,T.apply(void 0,[_[e]].concat(i)))||this}return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(s)}return s=t,(e=n).prototype=Object.create(s.prototype),e.prototype.constructor=e,N(e,s),n}(C(Error));function A(t,e){return t.substr(-e.length)===e}var w=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;function z(t){return"string"!=typeof t?t:t.match(w)?parseFloat(t):t}var R=function(t){return function(e,s){void 0===s&&(s="16px");var n=e,i=s;if("string"==typeof e){if(!A(e,"px"))throw new E(69,t,e);n=z(e)}if("string"==typeof s){if(!A(s,"px"))throw new E(70,t,s);i=z(s)}if("string"==typeof n)throw new E(71,e,t);if("string"==typeof i)throw new E(72,s,t);return""+n/i+t}};R("em"),R("rem");function O(t){return Math.round(255*t)}function L(t,e,s){return O(t)+","+O(e)+","+O(s)}function D(t,e,s,n){if(void 0===n&&(n=L),0===e)return n(s,s,s);var i=(t%360+360)%360/60,o=(1-Math.abs(2*s-1))*e,a=o*(1-Math.abs(i%2-1)),r=0,h=0,c=0;i>=0&&i<1?(r=o,h=a):i>=1&&i<2?(r=a,h=o):i>=2&&i<3?(h=o,c=a):i>=3&&i<4?(h=a,c=o):i>=4&&i<5?(r=a,c=o):i>=5&&i<6&&(r=o,c=a);var d=s-o/2;return n(r+d,h+d,c+d)}var $={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 Y=/^#[a-fA-F0-9]{6}$/,X=/^#[a-fA-F0-9]{8}$/,k=/^#[a-fA-F0-9]{3}$/,B=/^#[a-fA-F0-9]{4}$/,F=/^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i,H=/^rgb(?:a)?\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i,Z=/^hsl\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*\)$/i,U=/^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 V(t){if("string"!=typeof t)throw new E(3);var e=function(t){if("string"!=typeof t)return t;var e=t.toLowerCase();return $[e]?"#"+$[e]:t}(t);if(e.match(Y))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(X)){var s=parseFloat((parseInt(""+e[7]+e[8],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[2],16),green:parseInt(""+e[3]+e[4],16),blue:parseInt(""+e[5]+e[6],16),alpha:s}}if(e.match(k))return{red:parseInt(""+e[1]+e[1],16),green:parseInt(""+e[2]+e[2],16),blue:parseInt(""+e[3]+e[3],16)};if(e.match(B)){var n=parseFloat((parseInt(""+e[4]+e[4],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[1],16),green:parseInt(""+e[2]+e[2],16),blue:parseInt(""+e[3]+e[3],16),alpha:n}}var i=F.exec(e);if(i)return{red:parseInt(""+i[1],10),green:parseInt(""+i[2],10),blue:parseInt(""+i[3],10)};var o=H.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=Z.exec(e);if(a){var r="rgb("+D(parseInt(""+a[1],10),parseInt(""+a[2],10)/100,parseInt(""+a[3],10)/100)+")",h=F.exec(r);if(!h)throw new E(4,e,r);return{red:parseInt(""+h[1],10),green:parseInt(""+h[2],10),blue:parseInt(""+h[3],10)}}var c=U.exec(e.substring(0,50));if(c){var d="rgb("+D(parseInt(""+c[1],10),parseInt(""+c[2],10)/100,parseInt(""+c[3],10)/100)+")",l=F.exec(d);if(!l)throw new E(4,e,d);return{red:parseInt(""+l[1],10),green:parseInt(""+l[2],10),blue:parseInt(""+l[3],10),alpha:parseFloat(""+c[4])>1?parseFloat(""+c[4])/100:parseFloat(""+c[4])}}throw new E(5)}function j(t){return function(t){var e,s=t.red/255,n=t.green/255,i=t.blue/255,o=Math.max(s,n,i),a=Math.min(s,n,i),r=(o+a)/2;if(o===a)return void 0!==t.alpha?{hue:0,saturation:0,lightness:r,alpha:t.alpha}:{hue:0,saturation:0,lightness:r};var h=o-a,c=r>.5?h/(2-o-a):h/(o+a);switch(o){case s:e=(n-i)/h+(n<i?6:0);break;case n:e=(i-s)/h+2;break;default:e=(s-n)/h+4}return e*=60,void 0!==t.alpha?{hue:e,saturation:c,lightness:r,alpha:t.alpha}:{hue:e,saturation:c,lightness:r}}(V(t))}var W=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 G(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function q(t){return G(Math.round(255*t))}function K(t,e,s){return W("#"+q(t)+q(e)+q(s))}function J(t,e,s){return D(t,e,s,K)}function Q(t,e,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s)return W("#"+G(t)+G(e)+G(s));if("object"==typeof t&&void 0===e&&void 0===s)return W("#"+G(t.red)+G(t.green)+G(t.blue));throw new E(6)}function tt(t,e,s,n){if("string"==typeof t&&"number"==typeof e){var i=V(t);return"rgba("+i.red+","+i.green+","+i.blue+","+e+")"}if("number"==typeof t&&"number"==typeof e&&"number"==typeof s&&"number"==typeof n)return n>=1?Q(t,e,s):"rgba("+t+","+e+","+s+","+n+")";if("object"==typeof t&&void 0===e&&void 0===s&&void 0===n)return t.alpha>=1?Q(t.red,t.green,t.blue):"rgba("+t.red+","+t.green+","+t.blue+","+t.alpha+")";throw new E(7)}function et(t){if("object"!=typeof t)throw new E(8);if(function(t){return"number"==typeof t.red&&"number"==typeof t.green&&"number"==typeof t.blue&&"number"==typeof t.alpha}(t))return tt(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 Q(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&"number"==typeof t.alpha}(t))return function(t,e,s,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s&&"number"==typeof n)return n>=1?J(t,e,s):"rgba("+D(t,e,s)+","+n+")";if("object"==typeof t&&void 0===e&&void 0===s&&void 0===n)return t.alpha>=1?J(t.hue,t.saturation,t.lightness):"rgba("+D(t.hue,t.saturation,t.lightness)+","+t.alpha+")";throw new E(2)}(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&("number"!=typeof t.alpha||void 0===t.alpha)}(t))return function(t,e,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s)return J(t,e,s);if("object"==typeof t&&void 0===e&&void 0===s)return J(t.hue,t.saturation,t.lightness);throw new E(1)}(t);throw new E(8)}function st(t,e,s){return function(){var n=s.concat(Array.prototype.slice.call(arguments));return n.length>=e?t.apply(this,n):st(t,e,n)}}function nt(t){return st(t,t.length,[])}nt(function(t,e){if("transparent"===e)return e;var s=j(e);return et(b({},s,{hue:s.hue+parseFloat(t)}))});function it(t,e,s){return Math.max(t,Math.min(e,s))}nt(function(t,e){if("transparent"===e)return e;var s=j(e);return et(b({},s,{lightness:it(0,1,s.lightness-parseFloat(t))}))});nt(function(t,e){if("transparent"===e)return e;var s=j(e);return et(b({},s,{saturation:it(0,1,s.saturation-parseFloat(t))}))});nt(function(t,e){if("transparent"===e)return e;var s=j(e);return et(b({},s,{lightness:it(0,1,s.lightness+parseFloat(t))}))});var ot=nt(function(t,e,s){if("transparent"===e)return s;if("transparent"===s)return e;if(0===t)return s;var n=V(e),i=b({},n,{alpha:"number"==typeof n.alpha?n.alpha:1}),o=V(s),a=b({},o,{alpha:"number"==typeof o.alpha?o.alpha:1}),r=i.alpha-a.alpha,h=2*parseFloat(t)-1,c=((h*r===-1?h:h+r)/(1+h*r)+1)/2,d=1-c;return tt({red:Math.floor(i.red*c+a.red*d),green:Math.floor(i.green*c+a.green*d),blue:Math.floor(i.blue*c+a.blue*d),alpha:i.alpha*parseFloat(t)+a.alpha*(1-parseFloat(t))})});nt(function(t,e){if("transparent"===e)return e;var s=V(e);return tt(b({},s,{alpha:it(0,1,(100*("number"==typeof s.alpha?s.alpha:1)+100*parseFloat(t))/100)}))});nt(function(t,e){if("transparent"===e)return e;var s=j(e);return et(b({},s,{saturation:it(0,1,s.saturation+parseFloat(t))}))});nt(function(t,e){return"transparent"===e?e:et(b({},j(e),{hue:parseFloat(t)}))});nt(function(t,e){return"transparent"===e?e:et(b({},j(e),{lightness:parseFloat(t)}))});nt(function(t,e){return"transparent"===e?e:et(b({},j(e),{saturation:parseFloat(t)}))});nt(function(t,e){return"transparent"===e?e:ot(parseFloat(t),"rgb(0, 0, 0)",e)});nt(function(t,e){return"transparent"===e?e:ot(parseFloat(t),"rgb(255, 255, 255)",e)});var at=nt(function(t,e){if("transparent"===e)return e;var s=V(e);return tt(b({},s,{alpha:it(0,1,+(100*("number"==typeof s.alpha?s.alpha:1)-100*parseFloat(t)).toFixed(2)/100)}))}),rt=["blue","orange","purple","cyan","magenta","yellowgreen","darkgoldenrod","deeppink"],ht=(t,e)=>{const s={};for(let n=0;n<t.connections.length;n++){const i=t.connections[n],o=e?.getNetConnectedToId(i.name);o&&!s[o]&&(s[o]=`hsl(${300*n/t.connections.length}, 100%, 50%)`),s[i.name]=(o?s[o]:null)??`hsl(${340*n/t.connections.length}, 100%, 50%)`}return s},ct=(t,e)=>{try{return at(e,t)}catch(e){return console.error(e),t}},dt=(t,e)=>"top"===t?0:"bottom"===t?e-1:parseInt(t.slice(5)),lt=(t,e=1)=>{const s=(("width"in t?t.width:t)/.5/2)**1.1*e;return 1===t.availableZ?.length&&s>1?1:s},ut=(t,e=.5,s=16)=>{let n=0,i=t;for(;n<s;){if(lt({width:i})<=e)break;i/=2,n++}return Math.max(1,n)};function pt(t,e,s=0,n=t.length-1,i=mt){for(;n>s;){if(n-s>600){const o=n-s+1,a=e-s+1,r=Math.log(o),h=.5*Math.exp(2*r/3),c=.5*Math.sqrt(r*h*(o-h)/o)*(a-o/2<0?-1:1);pt(t,e,Math.max(s,Math.floor(e-a*h/o+c)),Math.min(n,Math.floor(e+(o-a)*h/o+c)),i)}const o=t[e];let a=s,r=n;for(ft(t,s,e),i(t[n],o)>0&&ft(t,s,n);a<r;){for(ft(t,a,r),a++,r--;i(t[a],o)<0;)a++;for(;i(t[r],o)>0;)r--}0===i(t[s],o)?ft(t,s,r):(r++,ft(t,r,n)),r<=e&&(s=r+1),e<=r&&(n=r-1)}}function ft(t,e,s){const n=t[e];t[e]=t[s],t[s]=n}function mt(t,e){return t<e?-1:t>e?1:0}var gt=class{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(.4*this._maxEntries)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const s=[];if(!Tt(t,e))return s;const n=this.toBBox,i=[];for(;e;){for(let o=0;o<e.children.length;o++){const a=e.children[o],r=e.leaf?n(a):a;Tt(t,r)&&(e.leaf?s.push(a):_t(t,r)?this._all(a,s):i.push(a))}e=i.pop()}return s}collides(t){let e=this.data;if(!Tt(t,e))return!1;const s=[];for(;e;){for(let n=0;n<e.children.length;n++){const i=e.children[n],o=e.leaf?this.toBBox(i):i;if(Tt(t,o)){if(e.leaf||_t(t,o))return!0;s.push(i)}}e=s.pop()}return!1}load(t){if(!t||!t.length)return this;if(t.length<this._minEntries){for(let e=0;e<t.length;e++)this.insert(t[e]);return this}let e=this._build(t.slice(),0,t.length-1,0);if(this.data.children.length)if(this.data.height===e.height)this._splitRoot(this.data,e);else{if(this.data.height<e.height){const t=this.data;this.data=e,e=t}this._insert(e,this.data.height-e.height-1,!0)}else this.data=e;return this}insert(t){return t&&this._insert(t,this.data.height-1),this}clear(){return this.data=Et([]),this}remove(t,e){if(!t)return this;let s=this.data;const n=this.toBBox(t),i=[],o=[];let a,r,h;for(;s||i.length;){if(s||(s=i.pop(),r=i[i.length-1],a=o.pop(),h=!0),s.leaf){const n=yt(t,s.children,e);if(-1!==n)return s.children.splice(n,1),i.push(s),this._condense(i),this}h||s.leaf||!_t(s,n)?r?(a++,s=r.children[a],h=!1):s=null:(i.push(s),o.push(a),a=0,r=s,s=s.children[0])}return this}toBBox(t){return t}compareMinX(t,e){return t.minX-e.minX}compareMinY(t,e){return t.minY-e.minY}toJSON(){return this.data}fromJSON(t){return this.data=t,this}_all(t,e){const s=[];for(;t;)t.leaf?e.push(...t.children):s.push(...t.children),t=s.pop();return e}_build(t,e,s,n){const i=s-e+1;let o,a=this._maxEntries;if(i<=a)return o=Et(t.slice(e,s+1)),xt(o,this.toBBox),o;n||(n=Math.ceil(Math.log(i)/Math.log(a)),a=Math.ceil(i/Math.pow(a,n-1))),o=Et([]),o.leaf=!1,o.height=n;const r=Math.ceil(i/a),h=r*Math.ceil(Math.sqrt(a));At(t,e,s,h,this.compareMinX);for(let i=e;i<=s;i+=h){const e=Math.min(i+h-1,s);At(t,i,e,r,this.compareMinY);for(let s=i;s<=e;s+=r){const i=Math.min(s+r-1,e);o.children.push(this._build(t,s,i,n-1))}}return xt(o,this.toBBox),o}_chooseSubtree(t,e,s,n){for(;n.push(e),!e.leaf&&n.length-1!==s;){let s,n=1/0,i=1/0;for(let o=0;o<e.children.length;o++){const a=e.children[o],r=Nt(a),h=Pt(t,a)-r;h<i?(i=h,n=r<n?r:n,s=a):h===i&&r<n&&(n=r,s=a)}e=s||e.children[0]}return e}_insert(t,e,s){const n=s?t:this.toBBox(t),i=[],o=this._chooseSubtree(n,this.data,e,i);for(o.children.push(t),vt(o,n);e>=0&&i[e].children.length>this._maxEntries;)this._split(i,e),e--;this._adjustParentBBoxes(n,i,e)}_split(t,e){const s=t[e],n=s.children.length,i=this._minEntries;this._chooseSplitAxis(s,i,n);const o=this._chooseSplitIndex(s,i,n),a=Et(s.children.splice(o,s.children.length-o));a.height=s.height,a.leaf=s.leaf,xt(s,this.toBBox),xt(a,this.toBBox),e?t[e-1].children.push(a):this._splitRoot(s,a)}_splitRoot(t,e){this.data=Et([t,e]),this.data.height=t.height+1,this.data.leaf=!1,xt(this.data,this.toBBox)}_chooseSplitIndex(t,e,s){let n,i=1/0,o=1/0;for(let a=e;a<=s-e;a++){const e=Mt(t,0,a,this.toBBox),r=Mt(t,a,s,this.toBBox),h=Ct(e,r),c=Nt(e)+Nt(r);h<i?(i=h,n=a,o=c<o?c:o):h===i&&c<o&&(o=c,n=a)}return n||s-e}_chooseSplitAxis(t,e,s){const n=t.leaf?this.compareMinX:St,i=t.leaf?this.compareMinY:bt;this._allDistMargin(t,e,s,n)<this._allDistMargin(t,e,s,i)&&t.children.sort(n)}_allDistMargin(t,e,s,n){t.children.sort(n);const i=this.toBBox,o=Mt(t,0,e,i),a=Mt(t,s-e,s,i);let r=It(o)+It(a);for(let n=e;n<s-e;n++){const e=t.children[n];vt(o,t.leaf?i(e):e),r+=It(o)}for(let n=s-e-1;n>=e;n--){const e=t.children[n];vt(a,t.leaf?i(e):e),r+=It(a)}return r}_adjustParentBBoxes(t,e,s){for(let n=s;n>=0;n--)vt(e[n],t)}_condense(t){for(let e,s=t.length-1;s>=0;s--)0===t[s].children.length?s>0?(e=t[s-1].children,e.splice(e.indexOf(t[s]),1)):this.clear():xt(t[s],this.toBBox)}};function yt(t,e,s){if(!s)return e.indexOf(t);for(let n=0;n<e.length;n++)if(s(t,e[n]))return n;return-1}function xt(t,e){Mt(t,0,t.children.length,e,t)}function Mt(t,e,s,n,i){i||(i=Et(null)),i.minX=1/0,i.minY=1/0,i.maxX=-1/0,i.maxY=-1/0;for(let o=e;o<s;o++){const e=t.children[o];vt(i,t.leaf?n(e):e)}return i}function vt(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 St(t,e){return t.minX-e.minX}function bt(t,e){return t.minY-e.minY}function Nt(t){return(t.maxX-t.minX)*(t.maxY-t.minY)}function It(t){return t.maxX-t.minX+(t.maxY-t.minY)}function Pt(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 Ct(t,e){const s=Math.max(t.minX,e.minX),n=Math.max(t.minY,e.minY),i=Math.min(t.maxX,e.maxX),o=Math.min(t.maxY,e.maxY);return Math.max(0,i-s)*Math.max(0,o-n)}function _t(t,e){return t.minX<=e.minX&&t.minY<=e.minY&&e.maxX<=t.maxX&&e.maxY<=t.maxY}function Tt(t,e){return e.minX<=t.maxX&&e.minY<=t.maxY&&e.maxX>=t.minX&&e.maxY>=t.minY}function Et(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function At(t,e,s,n,i){const o=[e,s];for(;o.length;){if((s=o.pop())-(e=o.pop())<=n)continue;const a=e+Math.ceil((s-e)/n/2)*n;pt(t,a,e,s,i),o.push(e,a,a,s)}}var wt=class{tree;constructor(t=9){this.tree=new gt(t)}insert(t,e,s,n,i){this.tree.insert({minX:e,minY:s,maxX:n,maxY:i,data:t})}bulkLoad(t){const e=t.map(({item:t,minX:e,minY:s,maxX:n,maxY:i})=>({minX:e,minY:s,maxX:n,maxY:i,data:t}));this.tree.load(e)}search(t,e,s,n){return this.tree.search({minX:t,minY:e,maxX:s,maxY:n}).map(t=>t.data)}clear(){this.tree.clear()}},zt=class{constructor(){this.ids=[],this.values=[],this.length=0}clear(){this.length=0}push(t,e){let s=this.length++;for(;s>0;){const t=s-1>>1,n=this.values[t];if(e>=n)break;this.ids[s]=this.ids[t],this.values[s]=n,s=t}this.ids[s]=t,this.values[s]=e}pop(){if(0===this.length)return;const t=this.ids,e=this.values,s=t[0],n=--this.length;if(n>0){const s=t[n],i=e[n];let o=0;const a=n>>1;for(;o<a;){const s=1+(o<<1),a=s+1,r=s+(+(a<n)&+(e[a]<e[s]));if(e[r]>=i)break;t[o]=t[r],e[o]=e[r],o=r}t[o]=s,e[o]=i}return s}peek(){return this.length>0?this.ids[0]:void 0}peekValue(){return this.length>0?this.values[0]:void 0}shrink(){this.ids.length=this.values.length=this.length}},Rt=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],Ot=class t{static from(e,s=0){if(s%8!=0)throw new Error("byteOffset must be 8-byte aligned.");if(!e||void 0===e.byteLength||e.buffer)throw new Error("Data must be an instance of ArrayBuffer or SharedArrayBuffer.");const[n,i]=new Uint8Array(e,s+0,2);if(251!==n)throw new Error("Data does not appear to be in a Flatbush format.");const o=i>>4;if(3!==o)throw new Error(`Got v${o} data when expected v3.`);const a=Rt[15&i];if(!a)throw new Error("Unrecognized array type.");const[r]=new Uint16Array(e,s+2,1),[h]=new Uint32Array(e,s+4,1);return new t(h,r,a,void 0,e,s)}constructor(t,e=16,s=Float64Array,n=ArrayBuffer,i,o=0){if(void 0===t)throw new Error("Missing required argument: numItems.");if(isNaN(t)||t<=0)throw new Error(`Unexpected numItems value: ${t}.`);this.numItems=+t,this.nodeSize=Math.min(Math.max(+e,2),65535),this.byteOffset=o;let a=t,r=a;this._levelBounds=[4*a];do{a=Math.ceil(a/this.nodeSize),r+=a,this._levelBounds.push(4*r)}while(1!==a);this.ArrayType=s,this.IndexArrayType=r<16384?Uint16Array:Uint32Array;const h=Rt.indexOf(s),c=4*r*s.BYTES_PER_ELEMENT;if(h<0)throw new Error(`Unexpected typed array class: ${s}.`);if(i)this.data=i,this._boxes=new s(i,o+8,4*r),this._indices=new this.IndexArrayType(i,o+8+c,r),this._pos=4*r,this.minX=this._boxes[this._pos-4],this.minY=this._boxes[this._pos-3],this.maxX=this._boxes[this._pos-2],this.maxY=this._boxes[this._pos-1];else{const i=this.data=new n(8+c+r*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new s(i,8,4*r),this._indices=new this.IndexArrayType(i,8+c,r),this._pos=0,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,new Uint8Array(i,0,2).set([251,48+h]),new Uint16Array(i,2,1)[0]=e,new Uint32Array(i,4,1)[0]=t}this._queue=new zt}add(t,e,s=t,n=e){const i=this._pos>>2,o=this._boxes;return this._indices[i]=i,o[this._pos++]=t,o[this._pos++]=e,o[this._pos++]=s,o[this._pos++]=n,t<this.minX&&(this.minX=t),e<this.minY&&(this.minY=e),s>this.maxX&&(this.maxX=s),n>this.maxY&&(this.maxY=n),i}finish(){if(this._pos>>2!==this.numItems)throw new Error(`Added ${this._pos>>2} items when expected ${this.numItems}.`);const t=this._boxes;if(this.numItems<=this.nodeSize)return t[this._pos++]=this.minX,t[this._pos++]=this.minY,t[this._pos++]=this.maxX,void(t[this._pos++]=this.maxY);const e=this.maxX-this.minX||1,s=this.maxY-this.minY||1,n=new Uint32Array(this.numItems);for(let i=0,o=0;i<this.numItems;i++){const a=t[o++],r=t[o++],h=t[o++],c=t[o++],d=Math.floor(65535*((a+h)/2-this.minX)/e),l=Math.floor(65535*((r+c)/2-this.minY)/s);n[i]=Yt(d,l)}Dt(n,t,this._indices,0,this.numItems-1,this.nodeSize);for(let e=0,s=0;e<this._levelBounds.length-1;e++){const n=this._levelBounds[e];for(;s<n;){const e=s;let i=t[s++],o=t[s++],a=t[s++],r=t[s++];for(let e=1;e<this.nodeSize&&s<n;e++)i=Math.min(i,t[s++]),o=Math.min(o,t[s++]),a=Math.max(a,t[s++]),r=Math.max(r,t[s++]);this._indices[this._pos>>2]=e,t[this._pos++]=i,t[this._pos++]=o,t[this._pos++]=a,t[this._pos++]=r}}}search(t,e,s,n,i){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let o=this._boxes.length-4;const a=[],r=[];for(;void 0!==o;){const h=Math.min(o+4*this.nodeSize,Lt(o,this._levelBounds));for(let c=o;c<h;c+=4){const h=this._boxes[c];if(s<h)continue;const d=this._boxes[c+1];if(n<d)continue;const l=this._boxes[c+2];if(t>l)continue;const u=this._boxes[c+3];if(e>u)continue;const p=0|this._indices[c>>2];o>=4*this.numItems?a.push(p):(void 0===i||i(p,h,d,l,u))&&r.push(p)}o=a.pop()}return r}neighbors(t,e,s=1/0,n=1/0,i){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let o=this._boxes.length-4;const a=this._queue,r=[],h=n*n;t:for(;void 0!==o;){const n=Math.min(o+4*this.nodeSize,Lt(o,this._levelBounds));for(let s=o;s<n;s+=4){const n=0|this._indices[s>>2],r=this._boxes[s],c=this._boxes[s+1],d=this._boxes[s+2],l=this._boxes[s+3],u=t<r?r-t:t>d?t-d:0,p=e<c?c-e:e>l?e-l:0,f=u*u+p*p;f>h||(o>=4*this.numItems?a.push(n<<1,f):(void 0===i||i(n))&&a.push(1+(n<<1),f))}for(;a.length&&1&a.peek();){if(a.peekValue()>h)break t;if(r.push(a.pop()>>1),r.length===s)break t}o=a.length?a.pop()>>1:void 0}return a.clear(),r}};function Lt(t,e){let s=0,n=e.length-1;for(;s<n;){const i=s+n>>1;e[i]>t?n=i:s=i+1}return e[s]}function Dt(t,e,s,n,i,o){if(Math.floor(n/o)>=Math.floor(i/o))return;const a=t[n],r=t[n+i>>1],h=t[i];let c=h;const d=Math.max(a,r);h>d?c=d:d===a?c=Math.max(r,h):d===r&&(c=Math.max(a,h));let l=n-1,u=i+1;for(;;){do{l++}while(t[l]<c);do{u--}while(t[u]>c);if(l>=u)break;$t(t,e,s,l,u)}Dt(t,e,s,n,u,o),Dt(t,e,s,u+1,i,o)}function $t(t,e,s,n,i){const o=t[n];t[n]=t[i],t[i]=o;const a=4*n,r=4*i,h=e[a],c=e[a+1],d=e[a+2],l=e[a+3];e[a]=e[r],e[a+1]=e[r+1],e[a+2]=e[r+2],e[a+3]=e[r+3],e[r]=h,e[r+1]=c,e[r+2]=d,e[r+3]=l;const u=s[n];s[n]=s[i],s[i]=u}function Yt(t,e){let s=t^e,n=65535^s,i=65535^(t|e),o=t&(65535^e),a=s|n>>1,r=s>>1^s,h=i>>1^n&o>>1^i,c=s&i>>1^o>>1^o;s=a,n=r,i=h,o=c,a=s&s>>2^n&n>>2,r=s&n>>2^n&(s^n)>>2,h^=s&i>>2^n&o>>2,c^=n&i>>2^(s^n)&o>>2,s=a,n=r,i=h,o=c,a=s&s>>4^n&n>>4,r=s&n>>4^n&(s^n)>>4,h^=s&i>>4^n&o>>4,c^=n&i>>4^(s^n)&o>>4,s=a,n=r,i=h,o=c,h^=s&i>>8^n&o>>8,c^=n&i>>8^(s^n)&o>>8,s=h^h>>1,n=c^c>>1;let d=t^e,l=n|65535^(d|s);return d=16711935&(d|d<<8),d=252645135&(d|d<<4),d=858993459&(d|d<<2),d=1431655765&(d|d<<1),l=16711935&(l|l<<8),l=252645135&(l|l<<4),l=858993459&(l|l<<2),l=1431655765&(l|l<<1),(l<<1|d)>>>0}var Xt=class{index;items=[];currentIndex=0;capacity;constructor(t){this.capacity=Math.max(1,t),this.index=new Ot(this.capacity)}insert(t,e,s,n,i){if(this.currentIndex>=this.index.numItems)throw new Error("Exceeded initial capacity");this.items[this.currentIndex]=t,this.index.add(e,s,n,i),this.currentIndex++}finish(){this.index.finish()}search(t,e,s,n){return this.index.search(t,e,s,n).map(t=>this.items[t]||null).filter(Boolean)}clear(){this.items=[],this.currentIndex=0,this.index=new Ot(this.capacity)}},kt=class{idx;storage=[];constructor(t="native",e=[]){"flatbush"===t?0===e.length?(this.idx=new wt,t="rbush"):this.idx=new Xt(e.length):this.idx="rbush"===t?new wt:new class{shi=new Bt(e);insert(t){}search(t,e,s,n){const i=(t+s)/2,o=(e+n)/2,a=s-t,r=n-e;return this.shi.getNodesInArea(i,o,a,r)}clear(){}},e.forEach(t=>this.insert(t)),"flatbush"===t&&e.length>0&&this.idx.finish?.()}insert(t){this.storage.push(t),this.idx.insert(t,t.center.x-t.width/2,t.center.y-t.height/2,t.center.x+t.width/2,t.center.y+t.height/2)}search(t){return this.idx.search(t.minX,t.minY,t.maxX,t.maxY)}searchArea(t,e,s,n){return this.search({minX:t-s/2,minY:e-n/2,maxX:t+s/2,maxY:e+n/2})}},Bt=class{constructor(t){this.obstacles=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const s=t[e],n=s.center.x-s.width/2,i=s.center.y-s.height/2,o=s.center.x+s.width/2,a=s.center.y+s.height/2;for(let t=n;t<=o;t+=this.CELL_SIZE)for(let n=i;n<=a;n+=this.CELL_SIZE){const i=this.getBucketKey(t,n),o=this.buckets.get(i);o?o.push([s,e]):this.buckets.set(i,[[s,e]])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,s,n){const i=[],o=new Set,a=e-n/2,r=t+s/2,h=e+n/2;for(let e=t-s/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const s=this.getBucketKey(e,t),n=this.buckets.get(s)||[];for(const t of n)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},Ft=class{constructor(t){this.targets=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const s=t[e],n=Math.floor(s.bounds.minX/this.CELL_SIZE)*this.CELL_SIZE,i=Math.floor(s.bounds.minY/this.CELL_SIZE)*this.CELL_SIZE,o=s.bounds.maxX,a=s.bounds.maxY;for(let t=n;t<=o;t+=this.CELL_SIZE)for(let n=i;n<=a;n+=this.CELL_SIZE){const i=this.getBucketKey(t,n),o=this.buckets.get(i);o?o.push([s,e]):this.buckets.set(i,[[s,e]])}}}buckets;CELL_SIZE=5;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getTargetsInArea(t,e,s,n){const i=[],o=new Set,a=Math.floor((t-s/2)/this.CELL_SIZE)*this.CELL_SIZE,r=Math.floor((e-n/2)/this.CELL_SIZE)*this.CELL_SIZE,h=t+s/2,c=e+n/2;for(let t=a;t<=h;t+=this.CELL_SIZE)for(let e=r;e<=c;e+=this.CELL_SIZE){const s=this.getBucketKey(t,e),n=this.buckets.get(s)||[];for(const t of n)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},Ht=class extends e{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.MAX_DEPTH=e?.capacityDepth??this.MAX_DEPTH,this.MAX_ITERATIONS=1e5,this.layerCount=t.layerCount??2,this.outlinePolygon=t.outline&&t.outline.length>=3?t.outline:void 0;for(const e of t.obstacles)if(!e.zLayers){const s=[];for(const n of e.layers)s.push(dt(n,t.layerCount));e.zLayers=s}const s={x:(t.bounds.minX+t.bounds.maxX)/2,y:(t.bounds.minY+t.bounds.maxY)/2},n={width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},i=Math.max(n.width,n.height);this.unfinishedNodes=[{capacityMeshNodeId:this.getNextNodeId(),center:s,width:i,height:i,layer:"top",availableZ:Array.from({length:this.layerCount},(t,e)=>e),_depth:0,_containsTarget:!0,_containsObstacle:!0,_completelyInsideObstacle:!1}],this.finishedNodes=[],this.nodeToXYOverlappingObstaclesMap=new Map,this.obstacleTree=new kt("flatbush",this.srj.obstacles),this.targets=this.computeTargets(),this.targetTree=new Ft(this.targets)}unfinishedNodes;finishedNodes;nodeToXYOverlappingObstaclesMap;layerCount;outlinePolygon;MAX_DEPTH=4;targets;targetTree;obstacleTree;computeTargets(){const t=[];for(const e of this.srj.connections)for(const s of e.pointsToConnect){const n=this.obstacleTree.searchArea(s.x,s.y,.01,.01).filter(t=>t.zLayers.some(t=>t===dt(s.layer,this.layerCount)));let i={minX:s.x-.005,minY:s.y-.005,maxX:s.x+.005,maxY:s.y+.005};n.length>0&&(i={minX:Math.min(...n.map(t=>t.center.x-t.width/2)),minY:Math.min(...n.map(t=>t.center.y-t.height/2)),maxX:Math.max(...n.map(t=>t.center.x+t.width/2)),maxY:Math.max(...n.map(t=>t.center.y+t.height/2))});const o={...s,connectionName:e.name,availableZ:[dt(s.layer,this.layerCount)],bounds:i};t.push(o)}return t}getNodeBounds(t){const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-s,maxY:t.center.y+s}}getNodeRect(t){return{center:{x:t.center.x,y:t.center.y},width:t.width,height:t.height}}_nextNodeCounter=0;getNextNodeId(){return"cn"+this._nextNodeCounter++}getCapacityFromDepth(t){return(this.MAX_DEPTH-t+1)**2}getTargetIfNodeContainsTarget(t){const e=t.width>4*this.targetTree.CELL_SIZE?this.targets:this.targetTree.getTargetsInArea(t.center.x,t.center.y,t.width,t.height);for(const s of e)if(s.bounds.minX<=t.center.x+t.width/2&&s.bounds.maxX>=t.center.x-t.width/2&&s.bounds.minY<=t.center.y+t.height/2&&s.bounds.maxY>=t.center.y-t.height/2&&s.availableZ.some(e=>t.availableZ.includes(e)))return s;return null}getXYOverlappingObstacles(t){const e=this.nodeToXYOverlappingObstaclesMap.get(t.capacityMeshNodeId);if(e)return e;const s=[],n=this.getNodeBounds(t),i=n.minX,o=n.maxX,a=n.minY,r=n.maxY,h=t._parent?this.getXYOverlappingObstacles(t._parent):this.srj.obstacles;for(const t of h){const e=t.center.x-t.width/2,n=t.center.x+t.width/2,h=t.center.y-t.height/2,c=t.center.y+t.height/2;o>=e&&i<=n&&r>=h&&a<=c?s.push(t):(i>=e&&o<=n&&a>=h&&r<=c||e>=i&&n<=o&&h>=a&&c<=r)&&s.push(t)}return this.nodeToXYOverlappingObstaclesMap.set(t.capacityMeshNodeId,s),s}getXYZOverlappingObstacles(t){const e=this.getXYOverlappingObstacles(t),s=[];for(const n of e)t.availableZ.some(t=>n.zLayers.includes(t))&&s.push(n);return s}doesNodeOverlapObstacle(t){if(this.getXYZOverlappingObstacles(t).length>0)return!0;const e=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!x(e,this.outlinePolygon))return!0}return e.minX<this.srj.bounds.minX||e.maxX>this.srj.bounds.maxX||e.minY<this.srj.bounds.minY||e.maxY>this.srj.bounds.maxY}isNodeCompletelyInsideObstacle(t){const e=this.getXYZOverlappingObstacles(t),s=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!y(e,this.outlinePolygon))return!0}for(const t of e){const e=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2;if(s.minX>=e&&s.maxX<=n&&s.minY>=i&&s.maxY<=o)return!0}return!1}getChildNodes(t){if(t._depth===this.MAX_DEPTH)return[];const e=[],s={width:t.width/2,height:t.height/2},n=[{x:t.center.x-s.width/2,y:t.center.y-s.height/2},{x:t.center.x+s.width/2,y:t.center.y-s.height/2},{x:t.center.x-s.width/2,y:t.center.y+s.height/2},{x:t.center.x+s.width/2,y:t.center.y+s.height/2}];for(const i of n){const n={capacityMeshNodeId:this.getNextNodeId(),center:i,width:s.width,height:s.height,layer:t.layer,availableZ:t.availableZ,_depth:(t._depth??0)+1,_parent:t};n._containsObstacle=this.doesNodeOverlapObstacle(n);const o=this.getTargetIfNodeContainsTarget(n);o&&(n._targetConnectionName=o.connectionName,n.availableZ=o.availableZ,n._containsTarget=!0),n._containsObstacle&&(n._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(n)),n._completelyInsideObstacle&&!n._containsTarget||e.push(n)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||!(!t._containsObstacle||t._completelyInsideObstacle))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),s=[],n=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t);e?n.push(t):e||t._containsObstacle?!e&&t._containsTarget&&s.push(t):s.push(t)}this.unfinishedNodes.push(...n),this.finishedNodes.push(...s)}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Mesh Visualization"};if(this.outlinePolygon&&this.outlinePolygon.length>=2){const e=this.outlinePolygon.map(t=>({x:t.x,y:t.y}));e.push({...e[0]}),t.lines.push({points:e,strokeColor:"rgba(0, 136, 255, 0.95)",label:"outline"});for(const e of this.outlinePolygon)t.points.push({x:e.x,y:e.y,color:"rgba(0, 136, 255, 0.95)"})}for(const e of this.srj.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:1===e.zLayers?.length&&e.zLayers?.includes(1)?"rgba(0,0,255,0.3)":"rgba(255,0,0,0.3)",stroke:"red",label:["obstacle",`z: ${e.zLayers.join(",")}`].join("\n")});const e=[...this.finishedNodes,...this.unfinishedNodes];for(const s of e){const e=Math.min(...s.availableZ),n=this.unfinishedNodes.length>0&&s===this.unfinishedNodes[this.unfinishedNodes.length-1];t.rects.push({center:{x:s.center.x+e*s.width*.05,y:s.center.y-e*s.width*.05},width:Math.max(s.width-2,.8*s.width),height:Math.max(s.height-2,.8*s.height),fill:s._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[s.availableZ.join(",")]??"rgba(0,200,200,0.1)",stroke:n?"rgba(255,165,0,0.5)":void 0,label:[s.capacityMeshNodeId,`availableZ: ${s.availableZ.join(",")}`,`target? ${s._containsTarget??!1}`,`obs? ${s._containsObstacle??!1}`,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`capacity: ${lt(s).toFixed(2)}`].join("\n")})}return t.rects.sort((t,e)=>t.center.y-e.center.y),this.srj.connections.forEach((e,s)=>{const n=rt[s%rt.length];for(const i of e.pointsToConnect)t.points.push({x:i.x,y:i.y,label:`conn-${s} (${i.layer})`,color:n})}),t}},Zt=class extends Ht{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e}VIA_DIAMETER=.6;OBSTACLE_MARGIN=.1;OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES=.2;isNodeCompletelyOutsideBounds(t){if(this.outlinePolygon){const e=this.getNodeRect(t);if(!y(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!!y(e,this.outlinePolygon)&&!x(e,this.outlinePolygon)}return t.center.x-t.width/2<this.srj.bounds.minX||t.center.x+t.width/2>this.srj.bounds.maxX||t.center.y-t.height/2<this.srj.bounds.minY||t.center.y+t.height/2>this.srj.bounds.maxY}getObstacleCoveragePercentage(t){const e=this.getXYZOverlappingObstacles(t);if(0===e.length)return 0;const s=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2,a=t.width*t.height;let r=0;for(const t of e){const e=Math.max(s,t.center.x-t.width/2),a=Math.min(n,t.center.x+t.width/2),h=Math.max(i,t.center.y-t.height/2),c=Math.min(o,t.center.y+t.height/2);if(e<a&&h<c){r+=(a-e)*(c-h)}}return r/a}shouldFilterSingleLayerNodeForObstacle(t){if(1!==t.availableZ.length)return!1;if(!t._containsObstacle)return!1;return this.getObstacleCoveragePercentage(t)>this.OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES}shouldFilterNodeForObstacle(t){return!!t._containsObstacle&&(1!==t.availableZ.length||this.shouldFilterSingleLayerNodeForObstacle(t))}createChildNodeAtPosition(t,e){const s={capacityMeshNodeId:this.getNextNodeId(),center:e.center,width:e.width,height:e.height,layer:t.layer,availableZ:e.availableZ,_depth:e._depth??(t._depth??0)+1,_parent:t},n=this.getXYZOverlappingObstacles(s);s._containsObstacle=n.length>0||this.isNodePartiallyOutsideBounds(s);const i=this.getTargetIfNodeContainsTarget(s);return i&&(s._targetConnectionName=i.connectionName,s._containsTarget=!0),s._containsObstacle&&(s._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(s)),s}getZSubdivisionChildNodes(t){if(1===t.availableZ.length)return[];const e=[],s=t.availableZ.map(t=>[t]);for(const n of s){const s=this.createChildNodeAtPosition(t,{center:{...t.center},width:t.width,height:t.height,availableZ:n,_depth:t._depth});this.isNodeCompletelyOutsideBounds(s)||e.push(s)}return e}getChildNodes(t){if(t._depth>=this.MAX_DEPTH)return[];const e=[],s={width:t.width/2,height:t.height/2},n=[{x:t.center.x-s.width/2,y:t.center.y-s.height/2},{x:t.center.x+s.width/2,y:t.center.y-s.height/2},{x:t.center.x-s.width/2,y:t.center.y+s.height/2},{x:t.center.x+s.width/2,y:t.center.y+s.height/2}];for(const i of n){const n=this.createChildNodeAtPosition(t,{center:i,width:s.width,height:s.height,availableZ:t.availableZ});this.isNodeCompletelyOutsideBounds(n)||e.push(n)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||(1===t.availableZ.length&&t._depth<=this.MAX_DEPTH||!(!t._containsObstacle||t._completelyInsideObstacle)))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),s=[],n=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),i=t.availableZ.length>1&&!e&&(t._containsObstacle||t.width<this.VIA_DIAMETER+this.OBSTACLE_MARGIN);if(e)n.push(t);else if(e||this.shouldFilterNodeForObstacle(t)||i)if(!e&&t._containsTarget)if(i){const e=this.getZSubdivisionChildNodes(t);s.push(...e.filter(t=>t._containsTarget||!this.shouldFilterNodeForObstacle(t)))}else s.push(t);else i&&s.push(...this.getZSubdivisionChildNodes(t).filter(t=>!this.shouldFilterNodeForObstacle(t)));else s.push(t)}this.unfinishedNodes.push(...n),this.finishedNodes.push(...s)}};function Ut(t){const e=new Map;for(const s of t)for(const t of s.nodeIds)e.set(t,[...e.get(t)??[],s]);return e}var Vt=class extends e{nodes;edges;capacityPaths;nodeMap;nodeEdgeMap;unprocessedNodeIds;nodePortSegments;colorMap;constructor({nodes:t,edges:e,capacityPaths:s,colorMap:n}){super(),this.nodes=t,this.edges=e,this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ut(e),this.capacityPaths=s,this.colorMap=n??{},this.unprocessedNodeIds=[...new Set(s.flatMap(t=>t.nodeIds))],this.nodePortSegments=new Map}step(){const t=this.unprocessedNodeIds.pop();if(!t)return void(this.solved=!0);const e=[];for(const s of this.capacityPaths){const n=s.nodeIds.indexOf(t);-1!==n&&e.push({path:s,indexOfNodeInPath:n})}const s=this.nodeMap.get(t),n=[];for(const{path:i,indexOfNodeInPath:o}of e){const e=i.nodeIds[o-1],a=i.nodeIds[o+1];for(const o of[e,a]){const e=this.nodeMap.get(o);if(!e)continue;const a=jt(s,e),r=e.availableZ.filter(t=>s.availableZ.includes(t));if(0===r.length)continue;const h={capacityMeshNodeId:t,start:a.start,end:a.end,connectionNames:[i.connectionName],availableZ:r};n.push(h)}}const i=function(t){const e=[],s=t.map(t=>({...t,connectionNames:[...t.connectionNames],availableZ:[...t.availableZ].sort((t,e)=>t-e)}));for(;s.length>0;){const t=s.pop();let n=!1;for(let s=0;s<e.length;s++){const i=e[s],o=Gt(i.start,t.start)&&Gt(i.end,t.end)||Gt(i.start,t.end)&&Gt(i.end,t.start),a=qt(i.availableZ,t.availableZ);if(o&&a){const e=new Set(i.connectionNames);t.connectionNames.forEach(t=>e.add(t)),i.connectionNames=Array.from(e),n=!0;break}}n||e.push(t)}return e}(n);this.nodePortSegments.set(t,i)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};return this.nodePortSegments.forEach((e,s)=>{this.nodeMap.get(s);e.forEach(e=>{e.start.x,e.end.x;for(let n=0;n<e.connectionNames.length;n++){const i={x:.05*Math.max(...e.availableZ),y:.05*Math.max(...e.availableZ)},o={x:(e.start.x+e.end.x)/2,y:(e.start.y+e.end.y)/2},a={x:o.x+i.x,y:o.y+i.y};i.x>0&&t.lines.push({points:[o,a],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5"}),t.points.push({x:a.x,y:a.y,label:`${s}: ${e.connectionNames.join(", ")}\navailableZ: ${e.availableZ.join(",")}\nnodePortSegmentId: ${e.nodePortSegmentId}`}),t.lines.push({points:[e.start,e.end],strokeColor:ct(this.colorMap[e.connectionNames[n]],.6)})}})}),t}};function jt(t,e){const s={start:Math.max(t.center.x-t.width/2,e.center.x-e.width/2),end:Math.min(t.center.x+t.width/2,e.center.x+e.width/2)},n={start:Math.max(t.center.y-t.height/2,e.center.y-e.height/2),end:Math.min(t.center.y+t.height/2,e.center.y+e.height/2)};if(s.end-s.start<n.end-n.start){const t=(s.start+s.end)/2;return{start:{x:t,y:n.start},end:{x:t,y:n.end}}}{const t=(n.start+n.end)/2;return{start:{x:s.start,y:t},end:{x:s.end,y:t}}}}var Wt=1e-9;function Gt(t,e){return Math.abs(t.x-e.x)<Wt&&Math.abs(t.y-e.y)<Wt}function qt(t,e){if(t.length!==e.length)return!1;for(let s=0;s<t.length;s++)if(t[s]!==e[s])return!1;return!0}var Kt=class extends e{unsolvedSegments;solvedSegments;nodeMap;colorMap;constructor({segments:t,colorMap:e,nodes:s}){super(),this.MAX_ITERATIONS=1e5,this.unsolvedSegments=t,this.solvedSegments=[],this.colorMap=e??{},this.nodeMap=Object.fromEntries(s.map(t=>[t.capacityMeshNodeId,t]))}_step(){let t=!1;const e=[...this.unsolvedSegments];for(const s of e){const e=s.connectionNames.length;if((!("assignedPoints"in s)||s.assignedPoints?.length!==e)&&1===e){const e={x:(s.start.x+s.end.x)/2,y:(s.start.y+s.end.y)/2,z:s.availableZ[0]};s.assignedPoints=[{connectionName:s.connectionNames[0],point:e}],this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(s),1),this.solvedSegments.push(s),t=!0}}if(!t&&e.length>0){let s=e[0];for(const t of e)t.connectionNames.length<s.connectionNames.length&&(s=t);const n=[...s.connectionNames].sort(),i=s.end.x-s.start.x,o=s.end.y-s.start.y,a=n.length,r=[];for(let t=1;t<=a;t++){const e=t/(a+1);r.push({x:s.start.x+i*e,y:s.start.y+o*e,z:s.availableZ[0]})}s.assignedPoints=n.map((t,e)=>({connectionName:t,point:r[e]})),this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(s),1),this.solvedSegments.push(s),t=!0}0===this.unsolvedSegments.length&&(this.solved=!0)}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.solvedSegments){const s=e.capacityMeshNodeId,n=this.nodeMap[s];t.has(s)||t.set(s,{capacityMeshNodeId:s,portPoints:[],center:n.center,width:n.width,height:n.height}),t.get(s).portPoints.push(...e.assignedPoints.map(t=>({...t.point,connectionName:t.connectionName})))}return Array.from(t.values())}visualize(){const t={points:[],lines:this.solvedSegments.map(t=>({points:[t.start,t.end],step:4})),rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Segment to Point Solver"};for(let e=0;e<this.solvedSegments.length;e++){const s=this.solvedSegments[e];for(let e=0;e<s.assignedPoints.length;e++){const n=s.assignedPoints[e],i={x:n.point.x,y:n.point.y},o={x:n.point.x+.05*n.point.z,y:n.point.y+.05*n.point.z};0!==n.point.z&&t.lines.push({points:[i,o],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5",step:4}),t.points.push({x:o.x,y:o.y,label:[`${s.capacityMeshNodeId}-${n.connectionName}`,`z: ${s.availableZ.join(",")}`,`nodePortSegmentId: ${s.nodePortSegmentId}`].join("\n"),color:this.colorMap[n.connectionName],step:4})}}const e=[],s={};for(const t of this.solvedSegments){const e=t.capacityMeshNodeId;s[e]||(s[e]={});for(const n of t.assignedPoints)s[e][n.connectionName]||(s[e][n.connectionName]=[]),s[e][n.connectionName].push({x:n.point.x,y:n.point.y})}for(const t in s)for(const n in s[t]){const i=s[t][n];i.length>1&&e.push({points:i,step:4,strokeDash:"5 5",strokeColor:this.colorMap[n]||"#000"})}return t.lines.push(...e),t}};import Jt from"object-hash";var Qt=class{cacheHitsByPrefix={};cacheMissesByPrefix={};isSyncCache=!0;cacheHits=0;cacheMisses=0;cache=new Map;getCachedSolutionSync(t){const e=this.cache.get(t);if(void 0!==e){this.cacheHits++;const s=t.split(":")[0];return this.cacheHitsByPrefix[s]=(this.cacheHitsByPrefix[s]||0)+1,structuredClone(e)}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){this.cache.set(t,structuredClone(e))}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){this.cache.clear(),this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}getAllCacheKeys(){return Array.from(this.cache.keys())}},te="tscircuit_autorouter_cache_",ee=class{isSyncCache=!0;cacheHits=0;cacheMisses=0;cacheHitsByPrefix={};cacheMissesByPrefix={};constructor(){}getKey(t){return`${te}${t}`}getCachedSolutionSync(t){if("undefined"==typeof localStorage)return;const e=this.getKey(t);try{const s=localStorage.getItem(e);if(null!==s){const e=JSON.parse(s);this.cacheHits++;const n=t.split(":")[0];return this.cacheHitsByPrefix[n]=(this.cacheHitsByPrefix[n]||0)+1,e}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}catch(s){console.error(`Error getting cached solution sync for ${e}:`,s),this.cacheMisses++;const n=t.split(":")[0];return void(this.cacheMissesByPrefix[n]=(this.cacheMissesByPrefix[n]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){if("undefined"==typeof localStorage)return;const s=this.getKey(t);try{const t=JSON.stringify(e);localStorage.setItem(s,t)}catch(t){console.error(`Error setting cached solution sync for ${s}:`,t),t instanceof DOMException&&("QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&console.warn(`LocalStorage quota exceeded. Failed to cache solution for ${s}. Consider clearing the cache.`)}}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){if("undefined"!=typeof localStorage)try{const t=[];for(let e=0;e<localStorage.length;e++){const s=localStorage.key(e);s?.startsWith(te)&&t.push(s)}t.forEach(t=>localStorage.removeItem(t)),console.log(`Cleared ${t.length} items from LocalStorage cache.`)}catch(t){console.error("Error clearing LocalStorage cache:",t)}finally{this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}}getAllCacheKeys(){const t=[];for(let e=0;e<1e4;e++){const s=localStorage.key(e);if(!s)break;s.includes(te)&&t.push(s)}return t}};function se(){return globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE||ie(),globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE}function ne(){return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE||ie(),globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE}function ie(){globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE??=new ee,globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE??=new Qt}var oe=class{heap=[];constructor(t){this.heap=[];for(const e of t)this.enqueue(e)}getLeftChildIndex(t){return 2*t+1}getRightChildIndex(t){return 2*t+2}getParentIndex(t){return Math.floor((t-1)/2)}hasLeftChild(t){return this.getLeftChildIndex(t)<this.heap.length}hasRightChild(t){return this.getRightChildIndex(t)<this.heap.length}hasParent(t){return this.getParentIndex(t)>=0}leftChild(t){return this.heap[this.getLeftChildIndex(t)]}rightChild(t){return this.heap[this.getRightChildIndex(t)]}parent(t){return this.heap[this.getParentIndex(t)]}swap(t,e){const s=this.heap[t];this.heap[t]=this.heap[e],this.heap[e]=s}dequeue(){if(0===this.heap.length)return null;const t=this.heap[0];return this.heap[0]=this.heap[this.heap.length-1],this.heap.pop(),this.heapifyDown(),t}peek(){return 0===this.heap.length?null:this.heap[0]}enqueue(t){this.heap.push(t),this.heapifyUp()}heapifyUp(){let t=this.heap.length-1;for(;this.hasParent(t)&&this.parent(t).f>this.heap[t].f;)this.swap(this.getParentIndex(t),t),t=this.getParentIndex(t)}heapifyDown(){let t=0;for(;this.hasLeftChild(t);){let e=this.getLeftChildIndex(t);if(this.hasRightChild(t)&&this.rightChild(t).f<this.leftChild(t).f&&(e=this.getRightChildIndex(t)),this.heap[t].f<this.heap[e].f)break;this.swap(t,e),t=e}}},ae=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=h(this.A,this.B),this.futureConnections=t.futureConnections??[],this.MAX_ITERATIONS=5e3,this.debug_exploredNodesOrdered=[],this.debug_nodesTooCloseToObstacle=new Set,this.debug_nodePathToParentIntersectsObstacle=new Set,this.numRoutes=this.obstacleRoutes.length+this.futureConnections.length;const e=Math.ceil(5*(this.numRoutes+1));let s=this.boundsSize.width/this.cellStep,n=this.boundsSize.height/this.cellStep;for(;s*n>e**2&&!(2*this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,s=this.boundsSize.width/this.cellStep,n=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR,this.futureConnections&&0===this.futureConnections.length&&0===this.obstacleRoutes.length&&this.handleSimpleCases();const i={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:i.x-Math.round(t.A.x/this.cellStep)*this.cellStep,y:i.y-Math.round(t.A.y/this.cellStep)*this.cellStep},this.candidates=new oe([{...t.A,...i,z:t.A.z??0,g:0,h:0,f:0,parent:{...t.A,z:t.A.z??0,g:0,h:0,f:0,parent:null}}])}handleSimpleCases(){this.solved=!0;const{A:t,B:e}=this,s=t.z===e.z?[t,e]:[t,{...this.boundsCenter,z:this.A.z},{...this.boundsCenter,z:e.z},e];this.solvedPath={connectionName:this.connectionName,route:s,traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:this.A.z===this.B.z?[]:[this.boundsCenter]}}get viaPenaltyDistance(){return this.cellStep+this.straightLineDistance*this.VIA_PENALTY_FACTOR}isNodeTooCloseToObstacle(t,e,s){if(e??=this.obstacleMargin,s&&t.parent){const s=this.getViasInNodePath(t.parent);for(const n of s)if(h(t,n)<this.viaDiameter/2+e)return!0}for(const n of this.obstacleRoutes){const i=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!i){const i=re(n);for(const n of i)if((s||n.z===t.z)&&r(t,n.A,n.B)<this.traceThickness+e)return!0}for(const s of n.vias)if(h(t,s)<this.viaDiameter/2+this.traceThickness/2+e)return!0}return!1}isNodeTooCloseToEdge(t,e){const s=e?this.viaDiameter/2+this.obstacleMargin/2:this.obstacleMargin/2,n=t.x<this.bounds.minX+s||t.x>this.bounds.maxX-s||t.y<this.bounds.minY+s||t.y>this.bounds.maxY-s;return!(n&&!e&&(h(t,this.B)<2*s||h(t,this.A)<2*s))&&n}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const s of this.obstacleRoutes){const n=this.connMap?.areIdsConnected?.(this.connectionName,s.connectionName);if(!n)for(const n of re(s))if(n.z===t.z&&i(t,e,n.A,n.B))return!0}return!1}computeH(t){return h(t,this.B)+Math.abs(t.z-this.B.z)*this.viaPenaltyDistance}computeG(t){return(t.parent?.g??0)+(0===t.z?0:this.viaPenaltyDistance)+h(t,t.parent)}computeF(t,e){return t+e*this.GREEDY_MULTIPLER}getNodeKey(t){return`${Math.round(t.x/this.cellStep)*this.cellStep},${Math.round(t.y/this.cellStep)*this.cellStep},${t.z}`}getNeighbors(t){const e=[],{maxX:s,minX:n,maxY:i,minY:o}=this.bounds;for(let a=-1;a<=1;a++)for(let r=-1;r<=1;r++){if(0===a&&0===r)continue;const h={...t,parent:t,x:he(t.x+a*this.cellStep,n,s),y:he(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)))}const a={...t,parent:t,z:0===t.z?this.layerCount-1:0};return this.exploredNodes.has(this.getNodeKey(a))||this.isNodeTooCloseToObstacle(a,this.viaDiameter/2+this.obstacleMargin/2,!0)||this.isNodeTooCloseToEdge(a,!0)||(a.g=this.computeG(a),a.h=this.computeH(a),a.f=this.computeF(a.g,a.h),e.push(a)),e}getNodePath(t){const e=[];for(;t;)e.push(t),t=t.parent;return e}getViasInNodePath(t){const e=this.getNodePath(t),s=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&s.push({x:e[t].x,y:e[t].y});return s}setSolvedPath(t){const e=this.getNodePath(t);e.reverse();const s=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&s.push({x:e[t].x,y:e[t].y});this.solvedPath={connectionName:this.connectionName,traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,route:e.map(t=>({x:t.x,y:t.y,z:t.z})).concat([this.B]),vias:s}}computeProgress(t,e,s){s||(e+=this.viaPenaltyDistance);const n=1-e/this.straightLineDistance;return Math.max(this.progress||0,2/Math.PI*Math.atan(.112*n/(1-n)))}_step(){let t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;for(;t&&e&&this.exploredNodes.has(e);)t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;if(!t||!e)return void(this.failed=!0);this.exploredNodes.add(e),this.debug_exploredNodesOrdered.push(e);const s=h(t,this.B);this.progress=this.computeProgress(t,s,t.z===this.B.z),s<=this.cellStep*Math.SQRT2&&t.z===this.B.z&&!this.doesPathToParentIntersectObstacle({...t,parent:t,x:this.B.x,y:this.B.y})&&(this.solved=!0,this.setSolvedPath(t));const n=this.getNeighbors(t);for(const t of n)this.candidates.enqueue(t)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.points.push({x:this.A.x,y:this.A.y,label:`Input A\nz: ${this.A.z}`,color:"orange"}),t.points.push({x:this.B.x,y:this.B.y,label:`Input B\nz: ${this.B.z}`,color:"orange"}),t.lines.push({points:[this.A,this.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:"Direct Input Connection"});for(let e=0;e<this.obstacleRoutes.length;e++){const s=this.obstacleRoutes[e];for(let n=0;n<s.route.length-1;n++){const i=s.route[n].z;t.lines.push({points:[s.route[n],s.route[n+1]],strokeColor:0===i?"rgba(255, 0, 0, 0.75)":"rgba(255, 128, 0, 0.25)",strokeWidth:s.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`})}}for(let e=0;e<this.debug_exploredNodesOrdered.length;e++){const s=this.debug_exploredNodesOrdered[e],[n,i,o]=s.split(",").map(Number);this.debug_nodesTooCloseToObstacle.has(s)||(this.debug_nodePathToParentIntersectsObstacle.has(s)||t.rects.push({center:{x:n+this.initialNodeGridOffset.x+o*this.cellStep/20,y:i+this.initialNodeGridOffset.y+o*this.cellStep/20},fill:0===o?`rgba(255,0,255,${.3-e/this.debug_exploredNodesOrdered.length*.2})`:`rgba(0,0,255,${.3-e/this.debug_exploredNodesOrdered.length*.2})`,width:.9*this.cellStep,height:.9*this.cellStep,label:`Explored (z=${o})`}))}if(this.candidates.peek()){const e=this.candidates.peek();t.rects.push({center:{x:e.x+e.z*this.cellStep/20,y:e.y+e.z*this.cellStep/20},fill:"rgba(0, 255, 0, 0.8)",width:.9*this.cellStep,height:.9*this.cellStep,label:`Next (z=${e.z})`})}for(const e of this.obstacleRoutes)for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:this.viaDiameter/2,fill:"rgba(255, 0, 0, 0.5)",label:"Via"});if(this.solvedPath){t.lines.push({points:this.solvedPath.route,strokeColor:"green",label:"Solved Route"});for(const e of this.solvedPath.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"green",label:"Via"})}return t}};function re(t){const e=[];for(let s=0;s<t.route.length-1;s++)t.route[s].z===t.route[s+1].z&&e.push({z:t.route[s].z,A:t.route[s],B:t.route[s+1]});return e}function he(t,e,s){return Math.max(e,Math.min(t,s))}var ce=class extends ae{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;this.VIA_PENALTY_FACTOR=e/this.numRoutes*.3*this.VIA_PENALTY_FACTOR_2}getClosestFutureConnectionPoint(t){let e=1/0,s=null;for(const n of this.futureConnections)for(const i of n.points){const n=h(t,i)+(t.z!==i.z?this.viaPenaltyDistance:0);n<e&&(e=n,s=i)}return s}diminishCloseToGoal(t){const e=h(t,this.B);return 1-Math.exp(-e/this.straightLineDistance*5)}getFutureConnectionPenalty(t,e){let s=0;const n=this.getClosestFutureConnectionPoint(t),i=h(t,this.B);if(n){const o=h(t,n);if(i<=o)return 0;const a=o/(this.viaDiameter*this.FUTURE_CONNECTION_PROXIMITY_VD);s=(e?this.straightLineDistance*this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR:this.straightLineDistance*this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR)*Math.exp(5*-a)}return s}computeH(t){const e=h(t,this.B)**1.6;this.straightLineDistance;return e+(t.z!==this.B.z?this.viaPenaltyDistance:0)+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}computeG(t){const e=Math.abs(t.x-t.parent.x),s=Math.abs(t.y-t.parent.y),n=Math.sqrt(e**2+s**2),i=this.FLIP_TRACE_ALIGNMENT_DIRECTION?0===t.z?e:s:0===t.z?s:e;return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+n+i*this.MISALIGNED_DIST_PENALTY_FACTOR+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}};function de(t){let e=t;for(let t=0;t<10;t++)e=16807*e%2147483647;let s=e;e=(69069*t+1)%2147483647;for(let t=0;t<10;t++)e=48271*e%2147483647;let n=e;return()=>{let t=s;s=n,t^=t<<23,t^=t>>>17,t^=n,t^=n>>>26,n=t;const e=(s+n)/4294967296;return e-Math.floor(e)}}var le={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 ue(t,e){if(0===e)return t;if(t.length<=4){const s=le[t.length];return s[e%s.length].map(e=>t[e])}const s=de(e),n=t.slice();for(let t=0;t<n.length;t++){const e=Math.floor(s()*n.length),i=Math.floor(s()*(t+1));[n[e],n[i]]=[n[i],n[e]]}return n}function pe(t){const e={minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2};for(const s of t.portPoints)s.x<e.minX&&(e.minX=s.x),s.x>e.maxX&&(e.maxX=s.x),s.y<e.minY&&(e.minY=s.y),s.y>e.maxY&&(e.maxY=s.y);return e}var fe=class extends e{nodeWithPortPoints;colorMap;unsolvedConnections;totalConnections;solvedRoutes;failedSubSolvers;hyperParameters;minDistBetweenEnteringPoints;activeSubSolver=null;connMap;get failedSolvers(){return this.failedSubSolvers}get activeSolver(){return this.activeSubSolver}constructor(t){const{nodeWithPortPoints:e,colorMap:s}=t;super(),this.nodeWithPortPoints=e,this.colorMap=s??{},this.solvedRoutes=[],this.hyperParameters=t.hyperParameters??{},this.failedSubSolvers=[],this.connMap=t.connMap;const n=new Map;for(const{connectionName:t,x:s,y:i,z:o}of e.portPoints)n.set(t,[...n.get(t)??[],{x:s,y:i,z:o??0}]);this.unsolvedConnections=Array.from(n.entries().map(([t,e])=>({connectionName:t,points:e}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=ue(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},s)=>({...e,points:ue(t,7117*s+(this.hyperParameters.SHUFFLE_SEED??0))}))),this.totalConnections=this.unsolvedConnections.length,this.MAX_ITERATIONS=1e3*this.totalConnections**1.5,this.minDistBetweenEnteringPoints=(t=>{let e=1/0;const s=t.portPoints;for(let t=0;t<s.length;t++)for(let n=t+1;n<s.length;n++){if(s[t].z!==s[n].z)continue;const i=s[t],o=s[n],a=Math.sqrt((i.x-o.x)**2+(i.y-o.y)**2);e=Math.min(e,a)}return e===1/0?0:e})(this.nodeWithPortPoints)}computeProgress(){return(this.solvedRoutes.length+(this.activeSubSolver?.progress||0))/this.totalConnections}_step(){if(this.activeSubSolver)return this.activeSubSolver.step(),this.progress=this.computeProgress(),void(this.activeSubSolver.solved?(this.solvedRoutes.push(this.activeSubSolver.solvedPath),this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSubSolvers.push(this.activeSubSolver),this.activeSubSolver=null,this.error=this.failedSubSolvers.map(t=>t.error).join("\n"),this.failed=!0));const t=this.unsolvedConnections.pop();if(this.progress=this.computeProgress(),!t)return void(this.solved=0===this.failedSubSolvers.length);if(1===t.points.length)return;if(2===t.points.length){const[e,s]=t.points;if(e.x===s.x&&e.y===s.y&&e.z===s.z)return}const{connectionName:e,points:s}=t;this.activeSubSolver=new ce({connectionName:e,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:pe(this.nodeWithPortPoints),A:{x:s[0].x,y:s[0].y,z:s[0].z},B:{x:s[s.length-1].x,y:s[s.length-1].y,z:s[s.length-1].z},obstacleRoutes:this.connMap?this.solvedRoutes.filter(t=>!this.connMap.areIdsConnected(t.connectionName,e)):this.solvedRoutes,futureConnections:this.unsolvedConnections,layerCount:2,hyperParameters:this.hyperParameters,connMap:this.connMap})}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:[e.connectionName,`layer: ${e.z}`].join("\n"),color:this.colorMap[e.connectionName]??"blue"});for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e];if(s.route.length>0){const n=this.colorMap[s.connectionName]??"blue";for(let i=0;i<s.route.length-1;i++){const o=s.route[i],a=s.route[i+1];t.lines.push({points:[o,a],strokeColor:0===o.z?ct(n,.2):ct(n,.8),layer:`route-layer-${o.z}`,step:e,strokeWidth:s.traceThickness})}for(const i of s.vias)t.circles.push({center:{x:i.x,y:i.y},radius:s.viaDiameter/2,fill:ct(n,.5),layer:"via",step:e})}}const e=pe(this.nodeWithPortPoints),{minX:s,minY:n,maxX:i,maxY:o}=e;return t.lines.push({points:[{x:s,y:n},{x:i,y:n},{x:i,y:o},{x:s,y:o},{x:s,y:n}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}},me=t=>Math.round(200*t)/200,ge=t=>"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t));ie();var ye=class extends fe{cacheProvider;cacheHit=!1;hasAttemptedToUseCache=!1;initialUnsolvedConnections;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?ne():t.cacheProvider,this.initialUnsolvedConnections=ge(this.unsolvedConnections),(this.solved||this.failed)&&this.cacheProvider&&!this.cacheHit&&this.saveToCacheSync()}_step(){if(!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync())return;const t=this.solved,e=this.failed;super._step(),!this.cacheProvider||this.cacheHit||!this.solved&&!this.failed||t||e||this.saveToCacheSync()}computeCacheKeyAndTransform(){const t=this.nodeWithPortPoints.center,e=this.initialUnsolvedConnections.map(({connectionName:e,points:s})=>({connectionName:e,points:s.map(s=>({connectionName:e,x:me(s.x-t.x),y:me(s.y-t.y),z:s.z??0}))})),s=Object.fromEntries(Object.entries(this.hyperParameters??{}).filter(([,t])=>void 0!==t).sort(([t],[e])=>t.localeCompare(e))),n=this.connMap?this.initialUnsolvedConnections.map(({connectionName:t})=>({connectionName:t,connectedIds:[...new Set(this.connMap.getIdsConnectedToNet(t)??[])].sort()})):void 0,i={node:{width:me(this.nodeWithPortPoints.width),height:me(this.nodeWithPortPoints.height),center:{x:me(this.nodeWithPortPoints.center.x),y:me(this.nodeWithPortPoints.center.y)},availableZ:this.nodeWithPortPoints.availableZ?[...this.nodeWithPortPoints.availableZ].sort():void 0},normalizedConnections:e,normalizedHyperParameters:s,minDistBetweenEnteringPoints:me(this.minDistBetweenEnteringPoints),normalizedConnMap:n},o=`intranode-solver:${Jt(i)}`,a={};return this.cacheKey=o,this.cacheToSolveSpaceTransform=a,{cacheKey:o,cacheToSolveSpaceTransform:a}}applyCachedSolution(t){t.success?(this.solvedRoutes=ge(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:ge(this.solvedRoutes)};try{this.cacheProvider.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}},xe=class extends e{GREEDY_MULTIPLIER=1.2;MIN_SUBSTEPS=1;supervisedSolvers;winningSolver;getHyperParameterDefs(){throw new Error("Not implemented")}getCombinationDefs(){return null}getHyperParameterCombinations(t){t||(t=this.getHyperParameterDefs());const e=[];if(0===t.length)return[{}];const[s,...n]=t,i=this.getHyperParameterCombinations(n);return s.possibleValues.forEach(t=>{i.forEach(s=>{e.push({...s,...t})})}),e}initializeSolvers(){const t=this.getHyperParameterDefs(),e=this.getCombinationDefs()??[t.map(t=>t.name)];this.supervisedSolvers=[];for(const s of e){const e=this.getHyperParameterCombinations(t.filter(t=>s.includes(t.name)));for(const t of e){const e=this.generateSolver(t),s=this.computeG(e);this.supervisedSolvers.push({hyperParameters:t,solver:e,h:0,g:s,f:s})}}}generateSolver(t){throw new Error("Not implemented")}computeG(t){return t.iterations/t.MAX_ITERATIONS}computeH(t){return 1-(t.progress||0)}computeF(t,e){return t+e*this.GREEDY_MULTIPLIER}getSupervisedSolverWithBestFitness(){let t=1/0,e=null;for(const s of this.supervisedSolvers??[]){if(s.solver.solved)return s;if(s.solver.failed)continue;const n=s.f;n<t&&(t=n,e=s)}return e}getFailureMessage(){return"All solvers failed in hyper solver."}_step(){this.supervisedSolvers||this.initializeSolvers();const t=this.getSupervisedSolverWithBestFitness();if(!t)return this.failed=!0,void(this.error=this.getFailureMessage());for(let e=0;e<this.MIN_SUBSTEPS;e++)t.solver.step();t.g=this.computeG(t.solver),t.h=this.computeH(t.solver),t.f=this.computeF(t.g,t.h),t.solver.solved&&(this.solved=!0,this.winningSolver=t.solver,this.onSolve?.(t))}onSolve(t){}visualize(){const t=this.getSupervisedSolverWithBestFitness();let e={lines:[],circles:[],points:[],rects:[]};return t&&(e=t.solver.visualize()),e}};function Me({A:t,B:e,C:s,D:n,E:i,F:o,radius:a,margin:c,subdivisions:d=0}){const l=(t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}),u=(t,e,s)=>{const n=e.x-t.x,i=e.y-t.y,o=Math.sqrt(n*n+i*i),a=n/o,r=i/o,h=-r,c=a;return{midpoint:{x:(t.x+e.x)/2,y:(t.y+e.y)/2},A_Opp:{x:t.x-a*s,y:t.y-r*s},A_Right:{x:t.x+h*s,y:t.y+c*s},A_Left:{x:t.x-h*s,y:t.y-c*s},B_Opp:{x:e.x+a*s,y:e.y+r*s},B_Right:{x:e.x+h*s,y:e.y+c*s},B_Left:{x:e.x-h*s,y:e.y-c*s}}},p=(t,e)=>{const s=h(t,e.start),n=h(t,e.end),i=h(e.start,e.end);return Math.abs(s+n-i)<1e-4},f=(t,e)=>{const{start:s,end:n}=t,{start:i,end:o}=e;if(p(s,e)||p(n,e)||p(i,t)||p(o,t))return!0;const a=n.x-s.x,r=n.y-s.y,h=o.x-i.x,c=o.y-i.y,d=a*c-r*h;if(Math.abs(d)<1e-4)return!1;const l=i.x-s.x,u=i.y-s.y,f=(l*c-u*h)/d,m=(l*r-u*a)/d;return f>0&&f<1&&m>0&&m<1},m=(t,e)=>{const s=[];for(let e=0;e<t.length-1;e++)s.push({start:t[e],end:t[e+1]});const n=[];for(let t=0;t<e.length-1;t++)n.push({start:e[t],end:e[t+1]});for(const t of s)for(const e of n)if(f(t,e))return!0;return!1},g=t=>{let e=0;for(let s=1;s<t.length;s++){const n=t[s].x-t[s-1].x,i=t[s].y-t[s-1].y;e+=Math.sqrt(n*n+i*i)}return e},y=(t,e)=>{const{start:s,end:n}=t,i=n.x-s.x,o=n.y-s.y,a=i*i+o*o;if(0===a)return{...s,t:0};const r=Math.max(0,Math.min(1,((e.x-s.x)*i+(e.y-s.y)*o)/a));return{x:s.x+r*i,y:s.y+r*o,t:r}},x=(e,s,n)=>{const i=y(e,s);if(h(i,s)>=n)return i;const o=i.x-s.x,a=i.y-s.y,r=Math.sqrt(o*o+a*a);if(0===r){const o=e.end.x-e.start.x,a=e.end.y-e.start.y,r=Math.sqrt(o*o+a*a);return{x:s.x+n*o/r,y:s.y+n*a/r,t:i.t,isSpecial:!0,specialType:s===t?"A":"B"}}return{x:s.x+n*o/r,y:s.y+n*a/r,t:i.t,isSpecial:!0,specialType:s===t?"A":"B"}},M=u(t,e,a),v=u(t,e,a+c),S=(t,e,s,n,i)=>{const o=t.points;if(o.length<2)return o;const c=s+n,d=[o[0]];for(let t=0;t<o.length-1;t++){const s={start:o[t],end:o[t+1]};if(r(e,s.start,s.end)<c){const t=y(s,e),n=t.x-e.x,i=t.y-e.y,o=Math.sqrt(n*n+i*i);let r=null;if(o>1e-6)r={x:e.x+c*n/o,y:e.y+c*i/o};else{const t=s.end.x-s.start.x,n=s.end.y-s.start.y,i=Math.sqrt(t*t+n*n);i>1e-6&&(r={x:e.x+c*t/i,y:e.y+c*n/i})}r&&h(s.start,r)>a/10&&d.push(r)}h(d[d.length-1],s.end)>a/10&&d.push(s.end)}if(d.length>1){const t=[d[0]];for(let e=1;e<d.length;e++)h(t[t.length-1],d[e])>a/10&&t.push(d[e]);return t}return d},b=(()=>{const t=[[s,M.B_Left,M.B_Opp,M.B_Right,l(M.midpoint,l(M.B_Right,M.A_Right)),l(M.midpoint,l(M.A_Left,M.B_Left)),M.A_Left,M.A_Opp,M.A_Right,n],[s,M.B_Right,M.B_Opp,M.B_Left,l(M.midpoint,l(M.A_Left,M.B_Left)),l(M.midpoint,l(M.A_Right,M.B_Right)),M.A_Right,M.A_Opp,M.A_Left,n],[n,M.B_Left,M.B_Opp,M.B_Right,l(M.midpoint,l(M.A_Right,M.B_Right)),l(M.midpoint,l(M.A_Left,M.B_Left)),M.A_Left,M.A_Opp,M.A_Right,s],[n,M.B_Right,M.B_Opp,M.B_Left,l(M.midpoint,l(M.A_Left,M.B_Left)),l(M.midpoint,l(M.A_Right,M.B_Right)),M.A_Right,M.A_Opp,M.A_Left,s]],e=[];for(let s=0;s<t.length;s++){const n=t[s],i={start:n[0],end:n[1]},o={start:n[n.length-2],end:n[n.length-1]},a={start:n[3],end:n[4]};f(i,o)||f(i,a)||f(o,a)||e.push({index:s+1,path:n,length:g(n)})}if(0===e.length)return{index:0,path:[]};const i=e.sort((t,e)=>t.length-e.length)[0],o=[...i.path],a=o[0],r=h(a,o[2]),c=h(a,o[3]),d=r<c?2:3;(r<h(a,o[1])||c<h(a,o[1]))&&o.splice(1,d-1);const u=o[o.length-1],p=h(u,o[o.length-3]),m=h(u,o[o.length-4]),y=p<m?o.length-3:o.length-4;return(p<h(u,o[o.length-2])||m<h(u,o[o.length-2]))&&o.splice(y+1,o.length-y-2),{index:i.index,path:o,startsAt:o[0]===s?"C":"D",goesTo:o[o.length-1]===s?"C":"D"}})(),N=d>0?((s,n)=>{if(s.length<2)return s;const i=[s[0]];for(let o=0;o<s.length-1;o++){const r={start:s[o],end:s[o+1]},c={x:(r.start.x+r.end.x)/2,y:(r.start.y+r.end.y)/2},d=h(c,t),l=h(c,e);if((d<=a||l<=a)&&Math.abs(d-l)>1e-4){const s=y(r,t),o=y(r,e),c=h(s,t),d=h(o,e)<a,l=c<a?x(r,t,a):null,u=d?x(r,e,a):null;let p=[];if(h(r.start,r.end)>a/2&&n>0)for(let s=1;s<=n;s++){const i=s/(n+1),o={x:r.start.x+i*(r.end.x-r.start.x),y:r.start.y+i*(r.end.y-r.start.y),t:i,isSpecial:!1},c=h(o,t),d=h(o,e);c<a||d<a||(l&&Math.abs(o.t-l.t)<.1||u&&Math.abs(o.t-u.t)<.1||p.push(o))}if(l&&p.push(l),u&&p.push(u),p.sort((t,e)=>t.t-e.t),p.length>1){const t=[p[0]];for(let e=1;e<p.length;e++){const s=t[t.length-1],n=p[e];h(s,n)>a/10&&t.push(n)}p=t}p.forEach(t=>i.push(t))}i.push(s[o+1])}if(i.length>1){const t=[i[0]];for(let e=1;e<i.length;e++){const s=t[t.length-1],n=i[e];h(s,n)>a/10&&t.push(n)}return t}return i})(b.path,d):b.path;let I=(()=>{if(0===b.path.length)return null;const s=(()=>{const s=l(M.A_Right,M.B_Right),n=l(M.B_Left,M.A_Left);return[{startsAt:"E",goesTo:"B",points:[i,e]},{startsAt:"E",goesTo:"A",points:[i,t]},{startsAt:"F",goesTo:"B",points:[o,e]},{startsAt:"F",goesTo:"A",points:[o,t]},{startsAt:"E",goesTo:"B",points:[i,s,e]},{startsAt:"E",goesTo:"A",points:[i,s,t]},{startsAt:"F",goesTo:"B",points:[o,s,e]},{startsAt:"F",goesTo:"A",points:[o,s,t]},{startsAt:"E",goesTo:"B",points:[i,n,e]},{startsAt:"E",goesTo:"A",points:[i,n,t]},{startsAt:"F",goesTo:"B",points:[o,n,e]},{startsAt:"F",goesTo:"A",points:[o,n,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Right,s,e]},{startsAt:"F",goesTo:"B",points:[o,v.B_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Left,n,t]},{startsAt:"F",goesTo:"A",points:[o,v.A_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Right,s,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Opp,v.A_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Opp,v.B_Left,n,t]},{startsAt:"F",goesTo:"B",points:[o,v.A_Opp,v.A_Left,n,e]},{startsAt:"F",goesTo:"A",points:[o,v.B_Opp,v.B_Right,s,t]},{startsAt:"F",goesTo:"A",points:[o,v.B_Opp,v.B_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Opp,v.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Opp,v.B_Right,s,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Left,v.A_Opp,v.A_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Right,v.B_Opp,v.B_Left,n,t]},{startsAt:"F",goesTo:"B",points:[o,v.A_Right,v.A_Opp,v.A_Left,n,e]},{startsAt:"F",goesTo:"A",points:[o,v.B_Left,v.B_Opp,v.B_Right,s,t]},{startsAt:"F",goesTo:"A",points:[o,v.B_Right,v.B_Opp,v.B_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Right,v.A_Opp,v.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Left,v.B_Opp,v.B_Right,s,t]}].map((t,e)=>({...t,index:e}))})(),n=s.filter(t=>"E"===t.startsAt),a=s.filter(t=>"F"===t.startsAt),r=[],h=[];for(const t of n)if(!m(t.points,b.path)){r.push(t);break}for(const t of a)if(!m(t.points,b.path)){h.push(t);break}return 0===r.length||0===h.length?null:{line1:r[0],line2:h[0]}})();if(I){const s="A"===I.line1.goesTo?e:t,n="A"===I.line2.goesTo?e:t,i=S(I.line1,s,a,c),o=S(I.line2,n,a,c);I={line1:{...I.line1,points:i},line2:{...I.line2,points:o}}}return{jPair:I,optimalPath:{startsAt:b.startsAt,goesTo:b.goesTo,points:N}}}var ve=class extends e{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;escapeLayer=1;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return void(this.failed=!0);const[e,s]=this.routes;if(!(e.startPort.z===e.endPort.z))return void(this.failed=!0);if(!(s.startPort.z===s.endPort.z))return void(this.failed=!0);e.startPort.z===s.startPort.z?0===e.startPort.z?this.escapeLayer=1:this.escapeLayer=0:this.failed=!0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,s=new Map;for(const t of e){const{connectionName:e}=t;s.has(e)||s.set(e,[]),s.get(e)?.push(t)}for(const[e,n]of s.entries())2===n.length&&t.push({startPort:{...n[0],z:n[0].z??0},endPort:{...n[1],z:n[1].z??0},connectionName:e});return t}calculateBounds(){return{minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2}}doRoutesCross(t,e){return i(t.startPort,t.endPort,e.startPort,e.endPort)}calculateViaPositions(t,e){const s=this.bounds.maxX-this.bounds.minX,n=this.bounds.maxY-this.bounds.minY,i=this.bounds.minX,o=this.bounds.minY,a={width:s-2*this.obstacleMargin-this.viaDiameter,height:n-2*this.obstacleMargin-this.viaDiameter,x:i+this.obstacleMargin+this.viaDiameter/2,y:o+this.obstacleMargin+this.viaDiameter/2},r=this.viaDiameter+this.obstacleMargin,c=e.startPort,d=e.endPort,l=[{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}],u=(t,e)=>h(t,e),p=[];l.forEach((t,e)=>{u(t,c)>=r&&u(t,d)>=r&&p.push({...t,type:"corner",index:e})});const f=[{p1:l[0],p2:l[1]},{p1:l[1],p2:l[2]},{p1:l[2],p2:l[3]},{p1:l[3],p2:l[0]}];if([c,d].forEach((t,e)=>{f.forEach((s,n)=>{((t,e)=>{const s=t.x,n=t.y,i=t.r,o=e.p1.x,a=e.p1.y,r=e.p2.x,h=e.p2.y;if(Math.abs(r-o)<.001){const t=o,e=i*i-(t-s)**2;if(e<0)return[];if(Math.abs(e)<.001){const e=n;return e>=Math.min(a,h)&&e<=Math.max(a,h)?[{x:t,y:e}]:[]}const r=n+Math.sqrt(e),c=n-Math.sqrt(e),d=[];return r>=Math.min(a,h)&&r<=Math.max(a,h)&&d.push({x:t,y:r}),c>=Math.min(a,h)&&c<=Math.max(a,h)&&d.push({x:t,y:c}),d}const c=(h-a)/(r-o),d=a-c*o,l=1+c*c,u=2*(c*d-c*n-s),p=u*u-4*l*(s*s+(d-n)*(d-n)-i*i);if(p<0)return[];if(Math.abs(p)<.001){const t=-u/(2*l),e=c*t+d;return t>=Math.min(o,r)&&t<=Math.max(o,r)&&e>=Math.min(a,h)&&e<=Math.max(a,h)?[{x:t,y:e}]:[]}const f=(-u+Math.sqrt(p))/(2*l),m=(-u-Math.sqrt(p))/(2*l),g=c*f+d,y=c*m+d,x=[];return f>=Math.min(o,r)&&f<=Math.max(o,r)&&g>=Math.min(a,h)&&g<=Math.max(a,h)&&x.push({x:f,y:g}),m>=Math.min(o,r)&&m<=Math.max(o,r)&&y>=Math.min(a,h)&&y<=Math.max(a,h)&&x.push({x:m,y:y}),x})({...t,r:r},s).forEach(t=>{u(t,0===e?d:c)>=r&&p.push({...t,type:"intersection",circle:e,edge:n})})})}),p.length<2){const t=.8*r;if(l.forEach((e,s)=>{u(e,c)>=t&&u(e,d)>=t&&!p.some(t=>t.x===e.x&&t.y===e.y)&&p.push({...e,type:"relaxed_corner",index:s})}),p.length<2){const t=[...l].sort((t,e)=>{const s=Math.min(u(t,c),u(t,d));return Math.min(u(e,c),u(e,d))-s});for(const e of t)if(!p.some(t=>t.x===e.x&&t.y===e.y)&&(p.push({...e,type:"forced_corner"}),p.length>=2))break}}if(p.length<2)return null;let m=0,g=[p[0],p[p.length>1?1:0]];for(let t=0;t<p.length;t++)for(let e=t+1;e<p.length;e++){const s=u(p[t],p[e]);s>m&&(m=s,g=[p[t],p[e]])}let y={x:g[0].x,y:g[0].y},x={x:g[1].x,y:g[1].y};const M=h(y,t.startPort);return h(x,t.startPort)<M&&([y,x]=[x,y]),{via1:y,via2:x}}trySolveAOverB(t,e,s=!1){const n=s?this.calculateViaPositions(t,e):this.calculateViaPositions(e,t);if(!n)return!1;this.debugViaPositions.push(n);const{via1:i,via2:o}=this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(n));this.debugViaPositions.push({via1:i,via2:o});const{jPair:a,optimalPath:r}=Me({A:i,B:o,C:t.startPort,D:t.endPort,E:e.startPort,F:e.endPort,radius:this.viaDiameter/2+this.obstacleMargin+this.traceThickness/2*1.5,margin:2*this.obstacleMargin+this.traceThickness/2*1.5,subdivisions:1});if(!a)return!1;const h={connectionName:t.connectionName,route:r.points.map(e=>({x:e.x,y:e.y,z:t.startPort.z??0})),traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};a.line2.points.reverse();const c={connectionName:e.connectionName,route:[...a.line1.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0})),{...a.line1.points[a.line1.points.length-1],z:this.escapeLayer},{...a.line2.points[0],z:this.escapeLayer},...a.line2.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0}))],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[i,o]};return this.solvedRoutes.push(h,c),!0}pushViasFromEndpoints(t){const e={...t.via1},s={...t.via2},n=[this.routes[0].startPort,this.routes[0].endPort,this.routes[1].startPort,this.routes[1].endPort],i=this.getMinDistanceBetweenViaCenters(),o=this.viaDiameter/2+2*this.traceThickness+2*this.obstacleMargin;for(let t=0;t<10;t++){let a=!1,r=!1;const c=.9**t;for(const t of n){const n=h(e,t);if(n<o){const s=(o-n)*c,i=e.x-t.x,r=e.y-t.y,h=Math.sqrt(i*i+r*r);h>1e-6&&(e.x+=i/h*s,e.y+=r/h*s,a=!0)}const i=h(s,t);if(i<o){const e=(o-i)*c,n=s.x-t.x,a=s.y-t.y,h=Math.sqrt(n*n+a*a);h>1e-6&&(s.x+=n/h*e,s.y+=a/h*e,r=!0)}}const d=h(e,s);if(d<i){const t=(i-d)/2,n=s.x-e.x,o=s.y-e.y,h=Math.sqrt(n*n+o*o);h>1e-6?(e.x-=n/h*t,e.y-=o/h*t,s.x+=n/h*t,s.y+=o/h*t,a=!0,r=!0):(e.x-=t,s.x+=t,a=!0,r=!0)}if(!a&&!r)break}const a=h(e,s);if(a<i){const t=(i-a)/2,n=s.x-e.x,o=s.y-e.y,r=Math.sqrt(n*n+o*o);r>1e-6?(e.x-=n/r*t,e.y-=o/r*t,s.x+=n/r*t,s.y+=o/r*t):(e.x-=t,s.x+=t)}return{via1:e,via2:s}}getMinDistanceBetweenViaCenters(){return this.viaDiameter+this.traceThickness+2*this.obstacleMargin}moveViasAsCloseAsPossible(t){const{via1:e,via2:s}=t,n=this.getMinDistanceBetweenViaCenters(),i=h(e,s);if(i<=n)return t;const o=s.x-e.x,a=s.y-e.y,r=Math.sqrt(o*o+a*a),c=o/r,d=a/r,l=(e.x,s.x,e.y,s.y,(i-n)/2);return{via1:{x:e.x+c*l,y:e.y+d*l},via2:{x:s.x-c*l,y:s.y-d*l}}}handleRoutesDontCross(){const[t,e]=this.routes,s={connectionName:t.connectionName,route:[{x:t.startPort.x,y:t.startPort.y,z:t.startPort.z??0},{x:t.endPort.x,y:t.endPort.y,z:t.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]},n={connectionName:e.connectionName,route:[{x:e.startPort.x,y:e.startPort.y,z:e.startPort.z??0},{x:e.endPort.x,y:e.endPort.y,z:e.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};this.solvedRoutes.push(s,n),this.solved=!0}_step(){if(2!==this.routes.length)return void(this.failed=!0);const[t,e]=this.routes;this.doRoutesCross(t,e)?this.trySolveAOverB(t,e)||this.trySolveAOverB(e,t)||this.trySolveAOverB(t,e,!0)||this.trySolveAOverB(e,t,!0)?this.solved=!0:this.failed=!0:this.handleRoutesDontCross()}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.rects.push({center:{x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2},width:this.bounds.maxX-this.bounds.minX,height:this.bounds.maxY-this.bounds.minY,stroke:"rgba(0, 0, 0, 0.5)",fill:"rgba(240, 240, 240, 0.1)"});for(const[e,s]of[["Route A",this.routes[0]],["Route B",this.routes[1]]])t.points.push({x:s.startPort.x,y:s.startPort.y,label:`${e}\n${s.connectionName} start`,color:"orange"}),t.points.push({x:s.endPort.x,y:s.endPort.y,label:`${e}\n${s.connectionName} end`,color:"orange"}),t.lines.push({points:[s.startPort,s.endPort],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e}\n${s.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via1:s,via2:n}=this.debugViaPositions[e],i=["rgba(255, 165, 0, 0.3)","rgba(128, 0, 128, 0.3)"],o=i[e%i.length];t.circles.push({center:s,radius:this.viaDiameter/2,fill:o,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via A (attempt ${e+1})`}),t.circles.push({center:n,radius:this.viaDiameter/2,fill:o,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via B (attempt ${e+1})`});const a=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:s,radius:a,stroke:o,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 1 Safety Margin (attempt ${e+1})`}),t.circles.push({center:n,radius:a,stroke:o,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 2 Safety Margin (attempt ${e+1})`}),t.lines.push({points:[this.routes[e%2].startPort,s,n,this.routes[e%2].endPort],strokeColor:`${o.substring(0,o.lastIndexOf(","))}, 0.3)`,strokeDash:[5,5],label:`Potential Route (attempt ${e+1})`})}for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e],n=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1];t.lines.push({points:[i,o],strokeColor:n,strokeDash:1===i.z?[.2,.2]:void 0,strokeWidth:s.traceThickness,label:`${s.connectionName} z=${i.z}`}),i._label&&t.points.push({x:i.x,y:i.y,label:i._label})}for(const e of s.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Solved Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}};function Se(t,e,s,n,i){const o={x:(t.x+e.x+s.x)/3,y:(t.y+e.y+s.y)/3},a=(t,e)=>Math.sqrt((e.x-t.x)**2+(e.y-t.y)**2),r=o=>{const r=a(o,t),h=a(o,e),c=a(o,s),d=o.x>=i.minX&&o.x<=i.maxX&&o.y>=i.minY&&o.y<=i.maxY;return r>=n&&h>=n&&c>=n&&d};if(r(o))return o;const h=(t,e,s)=>{const n=t.x-e.x,i=t.y-e.y,o=Math.sqrt(n*n+i*i);return o<1e-10?{x:e.x+s,y:e.y}:{x:e.x+n/o*s,y:e.y+i/o*s}},c=(t,e,s)=>{const n=e.x-t.x,i=e.y-t.y,o=Math.sqrt(n*n+i*i);if(o>2*s-1e-10||o<1e-10)return[];const r=o*o/(2*o),h=Math.sqrt(Math.max(0,s*s-r*r)),c=t.x+n*r/o,d=t.y+i*r/o,l={x:c+h*i/o,y:d-h*n/o},u={x:c-h*i/o,y:d+h*n/o},p=[],f=1e-6;return Math.abs(a(l,t)-s)<f&&Math.abs(a(l,e)-s)<f&&p.push(l),Math.abs(a(u,t)-s)<f&&Math.abs(a(u,e)-s)<f&&p.push(u),p},d=[h(o,t,n),h(o,e,n),h(o,s,n),...c(t,e,n),...c(e,s,n),...c(s,t,n)],l=d.filter(r);if(l.length>0){const t=l.filter(t=>!(t=>{const e=1e-6;return Math.abs(t.x-i.minX)<e||Math.abs(t.x-i.maxX)<e||Math.abs(t.y-i.minY)<e||Math.abs(t.y-i.maxY)<e})(t));if(t.length>0)return t.sort((t,e)=>a(t,o)-a(e,o)),t[0]}let u=null,p=1/0;for(let t=i.minX+1;t<i.maxX;t+=5)for(let e=i.minY+1;e<i.maxY;e+=5){const s={x:t,y:e};if(r(s)){const t=a(s,o);t<p&&(p=t,u=s)}}if(null!==u)return u;const f=[];for(let t=0;t<=100;t++){const e=t/100;f.push({x:i.minX+e*(i.maxX-i.minX),y:i.minY}),f.push({x:i.maxX,y:i.minY+e*(i.maxY-i.minY)}),f.push({x:i.maxX-e*(i.maxX-i.minX),y:i.maxY}),f.push({x:i.minX,y:i.maxY-e*(i.maxY-i.minY)})}const m=f.filter(r);if(m.length>0)return m.sort((t,e)=>a(t,o)-a(e,o)),m[0];let g=1/0,y={x:i.minX,y:i.minY};for(const o of[...d,...f])if(o.x>=i.minX&&o.x<=i.maxX&&o.y>=i.minY&&o.y<=i.maxY){const i=Math.max(0,n-a(o,t))+Math.max(0,n-a(o,e))+Math.max(0,n-a(o,s));i<g&&(g=i,y=o)}return y}function be(t,e,s){const n=Ne(e,t,s.center,s.radius),i=Ne(t,e,s.center,s.radius),o=Ie(n,e),a=Ie(t,i),r=1e-6;let h;if(o>r&&a>r){h={x:(n.x+i.x)/2,y:(n.y+i.y)/2};const o=Ie(n,h),a=Ie(i,h);if(Math.abs(o-a)>.5*Math.min(o,a)){const s=Ie(t,n),o=Ie(e,i),a=s+o;if(a>r){const t=o/a,e=s/a;h={x:n.x*t+i.x*e,y:n.y*t+i.y*e}}}const c=Ie(h,s.center);if(c<1.05*s.radius){const t={x:(h.x-s.center.x)/c,y:(h.y-s.center.y)/c};h={x:s.center.x+t.x*s.radius*1.2,y:s.center.y+t.y*s.radius*1.2}}}else{const n={x:(t.x+e.x)/2,y:(t.y+e.y)/2},i=Ie(n,s.center);if(i<1.1*s.radius){const t={x:(n.x-s.center.x)/i,y:(n.y-s.center.y)/i};h={x:s.center.x+t.x*s.radius*1.2,y:s.center.y+t.y*s.radius*1.2}}else h=n}return{B:n,D:i,E:h}}function Ne(t,e,s,n){const i=[s.x-t.x,s.y-t.y],o=Math.sqrt(i[0]*i[0]+i[1]*i[1]);if(o<=n){if(o<1e-8){const i=[e.x-t.x,e.y-t.y],o=Math.sqrt(i[0]*i[0]+i[1]*i[1]);return o<1e-8?{x:s.x+n,y:s.y}:{x:s.x+i[0]/o*n,y:s.y+i[1]/o*n}}const a=[i[0]/o,i[1]/o];return{x:s.x-a[0]*n,y:s.y-a[1]*n}}const a=[e.x-t.x,e.y-t.y],r=Math.sqrt(o*o-n*n),h=[i[0]/o,i[1]/o],c=[-h[1],h[0]],d=[h[1],-h[0]],l=a[0]*c[0]+a[1]*c[1]>a[0]*d[0]+a[1]*d[1]?c:d,u=n/o,p=r/o,f=[h[0]*p+l[0]*u,h[1]*p+l[1]*u];return{x:t.x+r*f[0],y:t.y+r*f[1]}}function Ie(t,e){const s=e.x-t.x,n=e.y-t.y;return Math.sqrt(s*s+n*n)}var Pe=1e-9;function Ce(t,e,s,n="cw"){const i=_e(t,s),o=_e(e,s);return Math.abs(o-i)<Pe?{left:0,top:0,right:0,bottom:0}:function(t,e,s,n){const i=s.maxX-s.minX,o=s.maxY-s.minY;if(i<Pe&&o<Pe)return{left:0,top:0,right:0,bottom:0};const a=2*(i+o);if(a<Pe)return{left:0,top:0,right:0,bottom:0};const r=i/a*(2*Math.PI),h=(i+o)/a*(2*Math.PI),c=(i+i+o)/a*(2*Math.PI),d=2*Math.PI,l=[{name:"top",start:0,end:r,length:i},{name:"right",start:r,end:h,length:o},{name:"bottom",start:h,end:c,length:i},{name:"left",start:c,end:d,length:o}],u={left:0,top:0,right:0,bottom:0},p=(t,e,s,n,i)=>{const o=e>2*Math.PI-Pe?2*Math.PI:e;if(o<=t+Pe)return 0;if(i){const e=Math.max(t,s),i=Math.min(o,2*Math.PI),a=Math.max(0,i-e),r=Math.max(t,0),h=Math.min(o,n);return a+Math.max(0,h-r)}{const e=Math.max(t,s),i=Math.min(o,n);return Math.max(0,i-e)}};for(const s of l){const i=s.end-s.start;if(i<Pe||s.length<Pe)continue;let o=0;if("cw"===n){const n=t>e+Pe;o=p(s.start,s.end,t,e,n)}else{const n=e>t+Pe;o=p(s.start,s.end,e,t,n)}if(o>Pe){const t=o/i;u[s.name]+=Math.max(0,Number.isFinite(t)?t:0)}}for(const t in u)u[t]=Math.max(0,Math.min(1,u[t]));return u}(i,o,s,n)}function _e(t,e){const s=e.maxX-e.minX,n=e.maxY-e.minY;if(s<Pe&&n<Pe)return 0;const i=2*(s+n);if(i<Pe)return 0;let o=0;if(Math.abs(t.y-e.maxY)<Pe&&t.x>=e.minX-Pe&&t.x<=e.maxX+Pe)o=Math.max(0,Math.min(s,t.x-e.minX));else if(Math.abs(t.x-e.maxX)<Pe&&t.y>=e.minY-Pe&&t.y<=e.maxY+Pe)o=s+Math.max(0,Math.min(n,e.maxY-t.y));else if(Math.abs(t.y-e.minY)<Pe&&t.x>=e.minX-Pe&&t.x<=e.maxX+Pe)o=s+n+Math.max(0,Math.min(s,e.maxX-t.x));else{if(!(Math.abs(t.x-e.minX)<Pe&&t.y>=e.minY-Pe&&t.y<=e.maxY+Pe))throw new Error(`Point (${t.x}, ${t.y}) does not lie on the boundary defined by ${JSON.stringify(e)}`);o=s+n+s+Math.max(0,Math.min(n,t.y-e.minY))}return o=Math.max(0,Math.min(i,o)),i>Pe?o/i*(2*Math.PI):0}function Te(t,e,s,n){return function({angleA:t,angleB:e,angleC:s}){const n=Math.cos(t),i=Math.sin(t),o=Math.cos(e),a=Math.sin(e),r=Math.cos(s);return(o-n)*(Math.sin(s)-i)-(a-i)*(r-n)<0?"ccw":"cw"}({angleA:_e(t,n),angleB:_e(e,n),angleC:_e(s,n)})}var Ee=class extends e{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return void(this.failed=!0);const[e,s]=this.routes,n=e.A.z!==e.B.z,i=s.A.z!==s.B.z;(n&&i||!n&&!i)&&(this.failed=!0)}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,s=new Map;for(const t of e){const{connectionName:e}=t;s.has(e)||s.set(e,[]),s.get(e)?.push(t)}for(const[e,n]of s.entries())2===n.length&&t.push({A:{...n[0],z:n[0].z??0},B:{...n[1],z:n[1].z??0},connectionName:e});return t}calculateBounds(){return{minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2}}doRoutesCross(t,e){return i(t.A,t.B,e.A,e.B)}calculateViaPosition(t,e){const s=e.A.z,n=t.A.z!==s?t.A:t.B,i=2*this.obstacleMargin+this.viaDiameter/2+this.traceThickness,o=this.obstacleMargin+this.viaDiameter/2,a=e.A,r=n,h=e.B,c=Te(a,r,h,this.bounds),d=function(t,e,s,n,i){const o=Ce(t,e,n,i),a=Ce(e,s,n,i),r={left:Math.min(1,o.left+a.left),top:Math.min(1,o.top+a.top),right:Math.min(1,o.right+a.right),bottom:Math.min(1,o.bottom+a.bottom)};for(const t in r)Math.abs(r[t])<Pe&&(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),Se(a,r,h,i,l)}createTransitionRoute(t,e,s,n){return{connectionName:n,route:[{x:t.x,y:t.y,z:t.z??0},{x:s.x,y:s.y,z:t.z??0},{x:s.x,y:s.y,z:e.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[s]}}createFlatRoute(t,e,s,n,i,o){n.z,t.z;const a=this.viaDiameter/2+this.traceThickness/2+this.obstacleMargin,r=((t,e,s,n)=>{const i=s.x-t.x,o=s.y-t.y;return((t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}))({x:t.x+i*e,y:t.y+o*e},{x:s.x-i*n,y:s.y-o*n})})(s,this.viaDiameter,n.z!==t.z?n:i,this.traceThickness),h={center:{x:s.x,y:s.y},radius:a},c=be(t,r,h).E,d=be(r,e,h).E,l=be(t,c,h).E,u=be(c,r,h).E,p=be(r,d,h).E,f=be(d,e,h).E,m=be(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:m.x,y:m.y,z:t.z??0},{x:p.x,y:p.y,z:t.z??0},{x:d.x,y:d.y,z:t.z??0},{x:f.x,y:f.y,z:t.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]}}trySolve(){const[t,e]=this.routes,s=t.A.z!==t.B.z,n=s?t:e,i=s?e:t,o=this.calculateViaPosition(n,i);if(!o)return!1;this.debugViaPositions.push({via:o});const a=this.createTransitionRoute(n.A,n.B,o,n.connectionName),r=this.createFlatRoute(i.A,i.B,o,n.A,n.B,i.connectionName);return this.solvedRoutes.push(a,r),!0}_step(){if(!this.doRoutesCross(this.routes[0],this.routes[1]))return this.failed=!0,void(this.error="Can only solve routes that have a single transition crossing");this.trySolve()?this.solved=!0:this.failed=!0}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.rects.push({center:{x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2},width:this.bounds.maxX-this.bounds.minX,height:this.bounds.maxY-this.bounds.minY,stroke:"rgba(0, 0, 0, 0.5)",fill:"rgba(240, 240, 240, 0.1)",label:"PCB Bounds"});for(const e of this.routes)t.points.push({x:e.A.x,y:e.A.y,label:`${e.connectionName} start (z=${e.A.z})`,color:"orange"}),t.points.push({x:e.B.x,y:e.B.y,label:`${e.connectionName} end (z=${e.B.z})`,color:"orange"}),t.lines.push({points:[e.A,e.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via:s}=this.debugViaPositions[e];t.circles.push({center:s,radius:this.viaDiameter/2,fill:"rgba(255, 165, 0, 0.7)",stroke:"rgba(0, 0, 0, 0.5)",label:`Computed Via (attempt ${e+1})`});const n=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:s,radius:n,stroke:"rgba(255, 165, 0, 0.7)",fill:"rgba(0, 0, 0, 0)",label:"Safety Margin"})}for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e],n=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1];t.lines.push({points:[i,o],strokeColor:n,strokeDash:i.z!==s.route[0].z?[.2,.2]:void 0,strokeWidth:s.traceThickness,label:`${s.connectionName} z=${i.z}`})}for(const e of s.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}},Ae=(t,e)=>{const s={};return t.portPoints.forEach((e,n)=>{s[e.connectionName]=`hsl(${360*n/t.portPoints.length}, 100%, 50%)`}),s},we=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;unprocessedConnections;completedPaths=new Map;placeholderPaths=new Map;currentHead;currentConnectionName;currentPath;currentViaCount;constructor({nodeWithPortPoints:t,colorMap:e,hyperParameters:s}){super(),this.MAX_ITERATIONS=1e5,this.colorMap=e??Ae(t),this.maxViaCount=5,this.bounds=pe(t),this.nodeWidth=this.bounds.maxX-this.bounds.minX,this.portPairMap=(t=>{const e=new Map;return t.portPoints.forEach(t=>{e.has(t.connectionName)?e.get(t.connectionName).end=t:e.set(t.connectionName,{start:t,end:null,connectionName:t.connectionName})}),e})(t),this.stats.solutionsFound=0,this.availableZ=t.availableZ??[0,1],this.hyperParameters=s??{SHUFFLE_SEED:0},this.unprocessedConnections=Array.from(this.portPairMap.keys()).sort(),s?.SHUFFLE_SEED&&(this.unprocessedConnections=ue(this.unprocessedConnections,s.SHUFFLE_SEED));for(const[t,{start:e,end:s}]of this.portPairMap.entries())if(e.z===s.z){const n=Math.abs(e.x-s.x)<1e-9,i=Math.abs(e.y-s.y)<1e-9;n||i?this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),this._padByPlaceholderWallBuffer(s),s]):this.placeholderPaths.set(t,[e,s])}else{const n=(e.x+s.x)/2,i=(e.y+s.y)/2,o=this._padByPlaceholderWallBuffer({x:n,y:i,z:e.z}),a=this._padByPlaceholderWallBuffer({x:n,y:i,z:s.z});this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),o,a,this._padByPlaceholderWallBuffer(s),s])}this.currentConnectionName=this.unprocessedConnections.pop();const n=this.portPairMap.get(this.currentConnectionName).start;this.currentHead=this._padByNewHeadWallBuffer(n),this.currentPath=[n,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}_padByNewHeadWallBuffer(t){return{x:n(t.x,this.bounds.minX+this.NEW_HEAD_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.NEW_HEAD_WALL_BUFFER_DISTANCE),y:n(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:n(t.x,this.bounds.minX+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),y:n(t.y,this.bounds.minY+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxY-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),z:t.z}}_step(){if(this.solved)return;const t=this.portPairMap.get(this.currentConnectionName).end,e=[this.currentHead,t];let s=null,n=null;const i=t=>{for(const i of t.values())for(let t=0;t<i.length-1;t++){const o=[i[t],i[t+1]];if(o[0].x===o[1].x&&o[0].y===o[1].y)continue;if(o[0].z!==this.currentHead.z)continue;const a=c(e[0],e[1],o[0],o[1]);if(a){const t=h(this.currentHead,a);if(t<1e-6)continue;(!s||t<s.dist)&&(s={point:a,dist:t},n=o[0].z)}}};i(this.completedPaths),i(this.placeholderPaths);const o=this.currentHead.z!==t.z;if((s||o)&&(this.currentViaCount++,this.currentViaCount>=this.maxViaCount))this.failed=!0;else if(s){let t;const e=s.dist;if(e<=this.VIA_INTERSECTION_BUFFER_DISTANCE+1e-6)t=d(this.currentHead,s.point);else{const n=s.point,i=n.x-this.currentHead.x,o=n.y-this.currentHead.y,a=(e-this.VIA_INTERSECTION_BUFFER_DISTANCE)/e;t={x:this.currentHead.x+i*a,y:this.currentHead.y+o*a}}const i=this.availableZ.find(t=>t!==n);if(void 0===i)return console.error("Could not determine next Z level for via placement!"),void(this.failed=!0);const o={...t,z:this.currentHead.z},a={...t,z:i};this.currentPath.push(o,a),this.currentHead=a}else if(o){let e;const s=h(this.currentHead,t);if(s<this.VIA_INTERSECTION_BUFFER_DISTANCE)e=d(this.currentHead,t);else{const n=t.x-this.currentHead.x,i=t.y-this.currentHead.y,o=(s-this.VIA_INTERSECTION_BUFFER_DISTANCE)/s;e={x:this.currentHead.x+n*o,y:this.currentHead.y+i*o}}const n=t.z,i={...e,z:this.currentHead.z},o={...e,z:n};this.currentPath.push(i,o),this.currentHead=o}else if(this.currentPath.push(t),this.completedPaths.set(this.currentConnectionName,this.currentPath),0===this.unprocessedConnections.length)this.solved=!0,this.stats.solutionsFound=1;else{this.currentConnectionName=this.unprocessedConnections.pop();const{start:t}=this.portPairMap.get(this.currentConnectionName);this.currentHead=this._padByNewHeadWallBuffer(t),this.currentPath=[t,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}}visualize(){const t={points:[],lines:[],circles:[],rects:[],title:"Via Possibilities Solver State",coordinateSystem:"cartesian"},e=this.colorMap;t.lines.push({points:[{x:this.bounds.minX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.minY}],strokeColor:"gray",strokeWidth:.01});for(const[e,{start:s,end:n}]of this.portPairMap.entries()){const i=this.colorMap[e]??"black";t.points.push({x:s.x,y:s.y,color:i,label:`Port: ${e} Start (z${s.z})`}),t.points.push({x:n.x,y:n.y,color:i,label:`Port: ${e} End (z${n.z})`})}const s=(s,n)=>{for(const[i,o]of s.entries()){const s=e[i]??"black";for(let e=0;e<o.length-1;e++){const a=o[e],r=o[e+1];a.x===r.x&&a.y===r.y&&a.z!==r.z?t.circles.push({center:{x:a.x,y:a.y},radius:.3,fill:ct(s,.5),label:`${n}: ${i} Via (z${a.z}->z${r.z})`}):t.lines.push({points:[a,r],strokeColor:ct(s,.5),strokeDash:0===a.z?void 0:[.1,.1],strokeWidth:.1,label:`${n}: ${i} (z${a.z})`})}}};if(s(this.placeholderPaths,"Placeholder"),s(this.completedPaths,"Completed"),this.currentPath&&this.currentPath.length>0){const s=e[this.currentConnectionName]??"orange";for(let e=0;e<this.currentPath.length-1;e++){const n=this.currentPath[e],i=this.currentPath[e+1];n.x===i.x&&n.y===i.y&&n.z!==i.z?t.circles.push({center:{x:n.x,y:n.y},radius:.3,fill:ct(s,.5),label:`Current: ${this.currentConnectionName} Via (z${n.z}->z${i.z})`}):t.lines.push({points:[n,i],strokeColor:ct(s,.5),strokeWidth:.15,strokeDash:"2,2",label:`Current: ${this.currentConnectionName} (z${n.z})`})}t.points.push({x:this.currentHead.x,y:this.currentHead.y,color:"green",label:`Current Head: ${this.currentConnectionName} (z${this.currentHead.z})`})}return t}},ze=1e-9;function Re(t,e,s=ze){return Math.abs(t-e)<s}function Oe(t,e,s,n){return t*n-e*s}function Le(t,e,s,n){const i={x:e.x-t.x,y:e.y-t.y},o={x:n.x-s.x,y:n.y-s.y},a=Oe(i.x,i.y,o.x,o.y);if(Re(a,0))return null;const r={x:s.x-t.x,y:s.y-t.y},h=Oe(r.x,r.y,o.x,o.y)/a,c=Oe(r.x,r.y,i.x,i.y)/a;return h<-ze||h>1+ze||c<-ze||c>1+ze?null:{x:t.x+h*i.x,y:t.y+h*i.y}}function De(t){let e=0;for(let s=0,n=t.length;s<n;++s){const i=(s+1)%n;e+=t[s].x*t[i].y-t[i].x*t[s].y}return.5*e}function $e(t){let e=0,s=0,n=0;for(let i=0,o=t.length;i<o;++i){const a=(i+1)%o,r=t[i].x*t[a].y-t[a].x*t[i].y;e+=r,s+=(t[i].x+t[a].x)*r,n+=(t[i].y+t[a].y)*r}return e*=.5,Re(e,0)?null:(s/=6*e,n/=6*e,{x:s,y:n})}var Ye=class{x;y;out;connectionNames;constructor(t,e){this.x=t,this.y=e,this.out=[],this.connectionNames=new Set}},Xe=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 ke(t,e){const s=[...e,...[{start:{x:t.minX,y:t.minY},end:{x:t.maxX,y:t.minY}},{start:{x:t.maxX,y:t.minY},end:{x:t.maxX,y:t.maxY}},{start:{x:t.maxX,y:t.maxY},end:{x:t.minX,y:t.maxY}},{start:{x:t.minX,y:t.maxY},end:{x:t.minX,y:t.minY}}]],n=s.map(()=>[]);for(let t=0;t<s.length;++t){const e=s[t];n[t].push(e.start,e.end)}for(let t=0;t<s.length;++t)for(let e=t+1;e<s.length;++e){const i=Le(s[t].start,s[t].end,s[e].start,s[e].end);i&&(n[t].push(i),n[e].push(i))}const i=new Map,o=[];function a(t){const e=function(t,e=ze){return`${Math.round(t.x/e)}:${Math.round(t.y/e)}`}(t);if(!i.has(e)){const s=o.length;return i.set(e,s),o.push(new Ye(t.x,t.y)),s}return i.get(e)}const r=[];for(let t=0;t<s.length;++t){const e=s[t],i=n[t].slice();i.sort((t,s)=>{const n=e.end.x-e.start.x,i=e.end.y-e.start.y;return(Re(Math.abs(n),0)?(t.y-e.start.y)/i:(t.x-e.start.x)/n)-(Re(Math.abs(n),0)?(s.y-e.start.y)/i:(s.x-e.start.x)/n)});for(let t=0;t<i.length-1;++t){const s=i[t],n=i[t+1],h=a(s),c=a(n);h!==c&&(r.push([h,c]),e.connectionName&&(o[h].connectionNames.add(e.connectionName),o[c].connectionNames.add(e.connectionName)))}}const h=[];for(const[t,e]of r){const s=new Xe(t,e),n=new Xe(e,t);s.twin=h.length+1,n.twin=h.length;const i=h.length;h.push(s,n),o[t].out.push(i),o[e].out.push(i+1)}for(let t=0;t<o.length;++t){const e=o[t];e.out.sort((t,s)=>{const n=h[t],i=h[s],a=o[n.dest],r=o[i.dest];return Math.atan2(a.y-e.y,a.x-e.x)-Math.atan2(r.y-e.y,r.x-e.x)});const s=e.out.length;for(let t=0;t<s;++t){const n=e.out[t],i=e.out[(t-1+s)%s],o=h[n];null!==o.twin&&(h[o.twin].next=i)}}const c=[],d=[];for(let t=0;t<h.length;++t){if(h[t].visited)continue;let e=t;const s=[],n=[];do{if(null===e)break;const t=h[e];t.visited=!0,s.push(o[t.orig]),n.push(e),e=t.next}while(null!==e&&e!==t&&!h[e].visited);if(s.length<3)continue;if(De(s)>ze){const t=$e(s);t&&(c.push(t),d.push({vertices:s.map(t=>({x:t.x,y:t.y,connectionNames:t.connectionNames.size>0?t.connectionNames:void 0})),centroid:t}))}}return{centroids:c,faces:d,allVertices:o}}function Be(t,e){if(t>e)throw new Error("oneCount cannot be greater than length");if(t<0||e<0)throw new Error("oneCount and length must be non-negative");const s=[];return function t(n,i,o){o!==e?(n[o]=0,t(n,i,o+1),i>0&&(n[o]=1,t(n,i-1,o+1))):0===i&&s.push([...n])}(Array(e).fill(0),t,0),s}var Fe=t=>{if(0===t.length)return[[]];const e=[];for(let s=0;s<t.length;s++){const n=t[s],i=[...t.slice(0,s),...t.slice(s+1)],o=Fe(i);for(const t of o)e.push([n,...t])}return e};var He=t=>{const{start:e,end:s,segmentsPerPolyline:n,viaPositions:i,viaCount:o,availableZ:a}=t,r=function(t,e){const s=new Array(t).fill(0);if(0===e)return s;if(e===t)return s.fill(1);if(e<=t/2){const n=Math.floor(t/e),i=Math.floor((t-(n*(e-1)+1))/2);for(let t=0;t<e;t++)s[i+t*n]=1}else{const n=t-e,i=Math.floor(t/n),o=Math.floor((t-(i*(n-1)+1))/2);s.fill(1);for(let t=0;t<n;t++)s[o+t*i]=0}return s}(n,o),h=r.map(()=>null);let c=0,d=e.z1;const l=a.indexOf(e.z1);for(let t=0;t<r.length;t++)if(1===r[t]){const e=a[(l+c+1)%a.length];h[t]={...i[c],z1:d,z2:e},d=e,c++}let u=e;for(let t=0;t<h.length;t++){if(h[t]){u=h[t];continue}let e=s,n=h.length;for(let s=t+1;s<h.length;s++)if(h[s]){e=h[s],n=s;break}const i=n-t,o=e.x-u.x,a=e.y-u.y;for(let e=1/(i+1),s=0;t+s!==n;e+=1/(i+1),s++)h[t+s]={x:u.x+o*e,y:u.y+a*e,z1:u.z2,z2:u.z2}}return h},Ze=1e-9;function Ue(t,e){return Math.abs(t-e)<Ze}function Ve(t){return`${Math.round(t.x/Ze)}:${Math.round(t.y/Ze)}`}function je(t,e,s,n){return t*n-e*s}function We(t,e,s,n){const i={x:e.x-t.x,y:e.y-t.y},o={x:n.x-s.x,y:n.y-s.y},a=je(i.x,i.y,o.x,o.y),r={x:s.x-t.x,y:s.y-t.y};if(Ue(a,0))return null;const h=je(r.x,r.y,o.x,o.y)/a,c=je(r.x,r.y,i.x,i.y)/a;return h>=-1e-9&&h<=1+Ze&&c>=-1e-9&&c<=1+Ze?{x:t.x+h*i.x,y:t.y+h*i.y}:null}function Ge(t,e,s){return Ue(Math.hypot(t.x-e.x,t.y-e.y)+Math.hypot(t.x-s.x,t.y-s.y),Math.hypot(e.x-s.x,e.y-s.y))}function qe(t,e){const s=[],n=new Map;for(const e of t){const t=[e.start,...e.mPoints,e.end];for(let i=0;i<t.length-1;i++){const o=t[i],a=t[i+1],r=o.z2;if(s.push({start:{x:o.x,y:o.y},end:{x:a.x,y:a.y},connectionName:e.connectionName,layer:r}),o.z1!==o.z2){const t=Ve(o);n.has(t)||n.set(t,{point:o,connectionName:e.connectionName})}}const i=t[t.length-1];if(i.z1!==i.z2){const t=Ve(i);n.has(t)||n.set(t,{point:i,connectionName:e.connectionName})}}const i=[{start:{x:e.minX,y:e.minY},end:{x:e.maxX,y:e.minY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.minY},end:{x:e.maxX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.maxY},end:{x:e.minX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.minX,y:e.maxY},end:{x:e.minX,y:e.minY},connectionName:null,layer:0}];s.push(...i);const o=new Map;let a=0;function r(t,e){const s=Ve(t);let i=o.get(s);if(!i){const e=n.has(s);i={id:a++,x:t.x,y:t.y,isVia:e,connectionNames:new Set,outgoingEdges:[]},o.set(s,i),e&&n.get(s)&&i.connectionNames.add(n.get(s).connectionName)}return e&&i.connectionNames.add(e),i}for(const t of s)r(t.start,t.connectionName),r(t.end,t.connectionName);const h=new Map;for(const t of s)h.set(t,[]);for(let t=0;t<s.length;t++)for(let e=t+1;e<s.length;e++){if(s[t].layer!==s[e].layer)continue;const n=We(s[t].start,s[t].end,s[e].start,s[e].end);n&&(r(n),Ge(n,s[t].start,s[t].end)&&h.get(s[t]).push(n),Ge(n,s[e].start,s[e].end)&&h.get(s[e]).push(n))}const c=[];let d=0;for(const t of s){const e=[t.start,...h.get(t),t.end];e.sort((e,s)=>{const n=t.end.x-t.start.x,i=t.end.y-t.start.y;return Math.abs(n)>Math.abs(i)?(e.x-t.start.x)/n-(s.x-t.start.x)/n:Math.abs(i)<Ze?0:(e.y-t.start.y)/i-(s.y-t.start.y)/i});const s=[];if(e.length>0){s.push(e[0]);for(let t=1;t<e.length;t++)Ue(e[t].x,e[t-1].x)&&Ue(e[t].y,e[t-1].y)||s.push(e[t])}for(let e=0;e<s.length-1;e++){const n=s[e],i=s[e+1],o=r(n,t.connectionName),a=r(i,t.connectionName);if(o===a)continue;const h={id:d++,origin:o,twin:null,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1},l={id:d++,origin:a,twin:h,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1};h.twin=l,c.push(h,l),o.outgoingEdges.push(h),a.outgoingEdges.push(l)}}for(const t of o.values()){t.outgoingEdges.sort((e,s)=>{const n=e.twin.origin,i=s.twin.origin;return Math.atan2(n.y-t.y,n.x-t.x)-Math.atan2(i.y-t.y,i.x-t.x)});const e=t.outgoingEdges.length;for(let s=0;s<e;s++){const n=t.outgoingEdges[s],i=t.outgoingEdges[(s-1+e)%e];n.twin&&(n.twin.next=i)}}const l=[];let u=0,p=null,f=-1/0;for(const t of c){if(t.visited)continue;const e={id:u++,outerComponent:t,innerComponents:[],isOuterFace:!1};l.push(e);let s=t;const n=[],i=[],o=new Set;let a=0;do{if(!s||s.visited){console.warn("Face traversal encountered visited edge or null, breaking loop.",e.id),n.length=0;break}s.visited=!0,s.face=e,n.push(s),i.push(s.origin),null!==s.connectionName&&o.add(s.connectionName);const t=s.origin,r=s.twin.origin;a+=t.x*r.y-r.x*t.y,s=s.next}while(s!==t&&null!==s);if(s===t){if(a=.5*Math.abs(a),a>f&&(f=a,p&&(p.isOuterFace=!1),p=e,e.isOuterFace=!0),!e.isOuterFace&&n.length>0){if([...o].filter(t=>null!==t).length>1){let t=!1;for(const e of i)if(e.isVia){t=!0;break}if(!t)return!0}}}else console.warn(`Face ${e.id} did not close properly.`),l.pop(),u--}return!1}var Ke=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??Ae(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.cellSize=this.nodeWithPortPoints.width/1024,this.candidates=[],this.availableZ=this.nodeWithPortPoints.availableZ??[0,1],this.bounds={minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2};const e=this.nodeWithPortPoints.width*this.nodeWithPortPoints.height,s=(this.viaDiameter+2*this.obstacleMargin+this.traceWidth/2)**2,n=new Set(this.nodeWithPortPoints.portPoints.map(t=>t.connectionName)).size;this.uniqueConnections=n;const{numSameLayerCrossings:o,numTransitions:a}=(t=>{let e=0,s=[];const n=[];let o=0;for(const e of t.portPoints){if(s.some(t=>t.connectionName===e.connectionName))continue;if(n.some(t=>t.connectionName===e.connectionName))continue;const i={connectionName:e.connectionName,z:e.z,points:[{x:e.x,y:e.y,z:e.z}]};for(const s of t.portPoints)e.connectionName===s.connectionName&&(e.x===s.x&&e.y===s.y||i.points.push({x:s.x,y:s.y,z:s.z}));i.points.some(t=>t.z!==i.z)?(o++,n.push(i)):s.push(i)}s=s.filter(t=>t.points.length>1);for(let t=0;t<s.length;t++)for(let n=t+1;n<s.length;n++){const o=s[t],a=s[n];o.z===a.z&&i(o.points[0],o.points[1],a.points[0],a.points[1])&&e++}let a=0;for(let t=0;t<n.length;t++)for(let e=t+1;e<n.length;e++){const s=n[t],o=n[e];i(s.points[0],s.points[1],o.points[0],o.points[1])&&a++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:o,numTransitionPairCrossings:a,numTransitions:n.length}})(this.nodeWithPortPoints);if(this.minViaCount=2*o+a,this.maxViaCount=Math.min(Math.floor(e/s),Math.ceil(1.5*n)),this.minViaCount>this.SEGMENTS_PER_POLYLINE*(n/2))return this.failed=!0,void(this.error=`Not possible to solve problem with given SEGMENTS_PER_POLYLINE (${this.SEGMENTS_PER_POLYLINE}), atleast ${this.minViaCount} vias are required`);this.maxViaCount>this.SEGMENTS_PER_POLYLINE&&(this.maxViaCount=this.SEGMENTS_PER_POLYLINE),this.maxViaCount<this.minViaCount&&(this.maxViaCount=this.minViaCount)}computeMinGapBtwPolyLines(t){const e=[],s=[],n=[];for(let e=0;e<t.length;e++){const i=t[e],o=[i.start,...i.mPoints,i.end],a=new Map(this.availableZ.map(t=>[t,[]]));for(let t=0;t<o.length-1;t++){const e=[o[t],o[t+1]],s=e[0].z2;a.has(s)||a.set(s,[]),a.get(s).push(e)}s.push(a),n.push(o.filter(t=>t.z1!==t.z2))}for(let i=0;i<t.length;i++){const o=s[i],a=n[i];for(let c=i+1;c<t.length;c++){if(this.connMap?.areIdsConnected(t[i].connectionName,t[c].connectionName))continue;const d=s[c],l=n[c];let u=1;for(const t of this.availableZ){const e=o.get(t)??[],s=d.get(t)??[];for(const t of e)for(const e of s)u=Math.min(u,M(t[0],t[1],e[0],e[1])-this.traceWidth);for(const t of a)for(const e of s)u=Math.min(u,r(t,e[0],e[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of l)for(const s of e)u=Math.min(u,r(t,s[0],s[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of a)for(const e of l)u=Math.min(u,h(t,e)-this.viaDiameter)}e.push(u)}}return e}insertCandidate(t){let e=0,s=this.candidates.length-1;for(;e<=s;){const n=Math.floor((e+s)/2);this.candidates[n].f<t.f?e=n+1:s=n-1}this.candidates.splice(e,0,t)}setupInitialPolyLines(){const t=new Map;this.nodeWithPortPoints.portPoints.forEach(e=>{t.has(e.connectionName)?t.get(e.connectionName).end={...e,z1:e.z??0,z2:e.z??0}:t.set(e.connectionName,{start:{...e,z1:e.z??0,z2:e.z??0},end:null})});for(const[e,s]of t.entries())null===s.end&&t.delete(e);if(0===t.size)return this.failed=!0,void(this.error="No port pairs found, can't solve");const e=Array.from(t.entries()),s=((t,e,s,n)=>{const o=[];for(const[,s]of t){const t=s.start.z1!==s.end.z1,n=[];for(let s=0;s<=e;s++){const e=s%2!=0;t&&e?n.push(s):t||e||n.push(s)}o.push(n)}if(0===o.length)return[[]];let a=(t=>{if(!t||0===t.length)return[[]];let e=[[]];for(const s of t){const t=[];for(const n of e)for(const e of s)t.push([...n,e]);e=t}return e})(o).filter(t=>{for(let e=0;e<t.length;e++)if(t.reduce((t,e)=>t+e,0)<n)return!1;return!0});return a=a.filter(e=>{for(let s=0;s<t.length;s++){const[,n]=t[s];if(n.start.z1!==n.start.z2&&0===e[s])return!1}return!0}),a=a.filter(e=>{for(let s=0;s<t.length;s++){const[,n]=t[s];if(t[s][1].start.z1===t[s][1].start.z2)for(let o=s+1;o<t.length;o++){if(t[o][1].start.z1!==t[o][1].start.z2)continue;const[,a]=t[o];if(n.start.z1===n.end.z1&&a.start.z1===a.end.z1&&n.start.z1===a.start.z1&&i(n.start,n.end,a.start,a.end)&&e[s]+e[o]<2)return!1}}return!0}),a=a.filter(t=>!(t.reduce((t,e)=>t+e,0)>s)),a})(e,this.SEGMENTS_PER_POLYLINE,this.maxViaCount,this.minViaCount),n=(t=>{const{bounds:e,portPairsEntries:s,viaCountVariants:n}=t,{centroids:i}=ke(e,s.map(([t,e])=>e)),o=[];for(const t of n){const s=t.reduce((t,e)=>t+e,0);let n=i;if(i.length<s){n=[];const t=Math.ceil(Math.sqrt(s)),i=t;for(let s=0;s<t;s++)for(let o=0;o<i;o++)n.push({x:e.minX+(o+1)/(i+1)*(e.maxX-e.minX),y:e.minY+(s+1)/(t+1)*(e.maxY-e.minY)})}const a=Be(s,n.length);for(const e of a){const s=[];for(let t=0;t<e.length;t++)1===e[t]&&s.push(n[t]);o.push({viaPositions:s,viaCountVariant:t})}}return o})({portPairsEntries:e,viaCountVariants:s,bounds:this.bounds}),o=[];for(const{viaCountVariant:t,viaPositions:e}of n){const s=Fe(e);for(const e of s)o.push({viaCountVariant:t,viaPositions:e})}for(const{viaPositions:t,viaCountVariant:s}of o){const n=[];let i=0;for(let o=0;o<e.length;o++){const[a,r]=e[o],h=s[o],c=t.slice(i,i+h),d=He({start:r.start,end:r.end,segmentsPerPolyline:this.SEGMENTS_PER_POLYLINE,viaPositions:c,viaCount:h,availableZ:this.availableZ});i+=h,n.push({connectionName:a,start:r.start,end:r.end,mPoints:d})}if(qe(n,this.bounds))continue;const o=this.computeMinGapBtwPolyLines(n),a=this.computeH({minGaps:o,forces:[]}),r={polyLines:n,g:0,h:a,f:a,viaCount:s.reduce((t,e)=>t+e,0),minGaps:o};if(this.checkIfSolved(r))return void(this.candidates=[r]);if(this.candidates.push(r),this.candidates.length>this.MAX_CANDIDATES)return}this.candidates.sort((t,e)=>t.f-e.f)}computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){let e=0;for(const s of t.forces??[])for(const t of s)for(const s of t.values())e+=s.fx*s.fx+s.fy*s.fy;return e}getNeighbors(t){const{polyLines:e}=t,s=e.length,n=.02,i=.008,o=1e-6,a=Array.from({length:s},(t,s)=>Array.from({length:e[s].mPoints.length},()=>new Map)),r=(t,s,n,i,o)=>{if(s>0&&s<e[t].mPoints.length+1){const e=s-1,r=a[t][e],h=r.get(n)||{fx:0,fy:0};r.set(n,{fx:h.fx+i,fy:h.fy+o})}};for(let t=0;t<s;t++)for(let i=t+1;i<s;i++){const s=e[t],a=e[i],h=[s.start,...s.mPoints,s.end],c=[a.start,...a.mPoints,a.end],d=[],l=[];for(let t=0;t<h.length-1;t++)d.push({p1:h[t],p2:h[t+1],layer:h[t].z2,p1Idx:t,p2Idx:t+1});h.forEach((t,e)=>{t.z1!==t.z2&&l.push({point:t,layers:[t.z1,t.z2],index:e})});const u=[],p=[];for(let t=0;t<c.length-1;t++)u.push({p1:c[t],p2:c[t+1],layer:c[t].z2,p1Idx:t,p2Idx:t+1});c.forEach((t,e)=>{t.z1!==t.z2&&p.push({point:t,layers:[t.z1,t.z2],index:e})});for(const e of d)for(const s of u)if(e.layer===s.layer){if(M(e.p1,e.p2,s.p1,s.p2)<o)continue;const n={x:(e.p1.x+e.p2.x)/2,y:(e.p1.y+e.p2.y)/2},a={x:(s.p1.x+s.p2.x)/2,y:(s.p1.y+s.p2.y)/2},h=n.x-a.x,c=n.y-a.y,d=h*h+c*c;if(d>o){const n=Math.sqrt(d),a=(Math.exp(-6*n),`seg:${i}:${s.p1Idx}:${s.p2Idx}`),h=`seg:${t}:${e.p1Idx}:${e.p2Idx}`,c=(t,e,s,n,i,a,h)=>{const c=S(t,s.p1,s.p2),d=t.x-c.x,l=t.y-c.y,u=d*d+l*l;if(u<=o)return;const p=Math.sqrt(u),f=.02*Math.exp(-6*p),m=d/p*f,g=l/p*f;r(n,e,a,m,g),r(i,s.p1Idx,h,-m/2,-g/2),r(i,s.p2Idx,h,-m/2,-g/2)};c(e.p1,e.p1Idx,s,t,i,a,h),c(e.p2,e.p2Idx,s,t,i,a,h),c(s.p1,s.p1Idx,e,i,t,h,a),c(s.p2,s.p2Idx,e,i,t,h,a)}}for(const e of l)for(const s of u)if(e.layers.includes(s.layer)){const a=S(e.point,s.p1,s.p2),h=e.point.x-a.x,c=e.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,m=c/a*p,g=`seg:${i}:${s.p1Idx}:${s.p2Idx}`;r(t,e.index,g,f,m);const y=`via:${t}:${e.index}`;r(i,s.p1Idx,y,-f/2,-m/2),r(i,s.p2Idx,y,-f/2,-m/2)}}for(const e of p)for(const s of d)if(e.layers.includes(s.layer)){const a=S(e.point,s.p1,s.p2),h=e.point.x-a.x,c=e.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,m=c/a*p,g=`seg:${t}:${s.p1Idx}:${s.p2Idx}`;r(i,e.index,g,f,m);const y=`via:${i}:${e.index}`;r(t,s.p1Idx,y,-f/2,-m/2),r(t,s.p2Idx,y,-f/2,-m/2)}}for(const e of l)for(const s of p){if(e.layers.filter(t=>s.layers.includes(t)).length>0){const a=e.point.x-s.point.x,h=e.point.y-s.point.y,c=a*a+h*h;if(c>o){const d=Math.sqrt(c);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(o,d)):u=Math.max(o,d-this.viaDiameter);const p=l*n*Math.exp(-6*u),f=a/d*p,m=h/d*p,g=`via:${i}:${s.index}`,y=`via:${t}:${e.index}`;r(t,e.index,g,f,m),r(i,s.index,y,-f,-m)}}}}for(let t=0;t<s;t++){const s=e[t],i=[s.start,...s.mPoints,s.end],a=[];if(i.forEach((t,e)=>{t.z1!==t.z2&&a.push({point:t,layers:[t.z1,t.z2],index:e})}),!(a.length<2))for(let e=0;e<a.length;e++)for(let s=e+1;s<a.length;s++){const i=a[e],h=a[s],c=i.point.x-h.point.x,d=i.point.y-h.point.y,l=c*c+d*d;if(l>o){const e=Math.sqrt(l);let s=2,a=e;e<this.viaDiameter?(s*=4,a=Math.max(o,e)):a=Math.max(o,e-this.viaDiameter);const u=s*n*Math.exp(-6*a),p=c/e*u,f=d/e*u,m=`via:${t}:${h.index}`,g=`via:${t}:${i.index}`;r(t,i.index,m,p,f),r(t,h.index,g,-p,-f)}}}const h=e.map(t=>({...t,mPoints:t.mPoints.map(t=>({...t}))}));let c=!1;for(let t=0;t<s;t++)for(let e=0;e<h[t].mPoints.length;e++){const s=h[t].mPoints[e],n=a[t][e],r={fx:0,fy:0};for(const t of n.values())r.fx+=t.fx,r.fy+=t.fy;const d=s.z1!==s.z2;let l=s.x+r.fx,u=s.y+r.fy;if(d){const t=this.viaDiameter/2;let e=0,n=0;const o=this.viaDiameter/2+this.BOUNDARY_PADDING,a=this.bounds.minX+o,h=this.bounds.maxX-o,c=this.bounds.minY+o,d=this.bounds.maxY-o,p=a+t-s.x,f=s.x-(h-t),m=c+t-s.y,g=s.y-(d-t);p>0?e=i*(Math.exp(p/(2*this.obstacleMargin))-1):f>0&&(e=-.008*(Math.exp(f/(2*this.obstacleMargin))-1)),m>0?n=i*(Math.exp(m/(2*this.obstacleMargin))-1):g>0&&(n=-.008*(Math.exp(g/(2*this.obstacleMargin))-1)),r.fx+=e,r.fy+=n,l=s.x+r.fx,u=s.y+r.fy}else{const t=this.traceWidth/2+this.BOUNDARY_PADDING;l=Math.max(this.bounds.minX+t,Math.min(this.bounds.maxX-t,l)),u=Math.max(this.bounds.minY+t,Math.min(this.bounds.maxY-t,u))}Math.abs(r.fx)<o&&Math.abs(r.fy)<o||(Math.abs(s.x-l)>o||Math.abs(s.y-u)>o)&&(s.x=l,s.y=u,c=!0)}if(!c)return[];const d=this.computeMinGapBtwPolyLines(h),l=this.computeG(h,t),u=this.computeH({minGaps:d,forces:a});return[{polyLines:h,g:l,h:u,f:Math.round(5*l)/5+u,minGaps:d,forces:a,viaCount:t.viaCount}]}checkIfSolved(t){const e=t.minGaps.every(t=>t>=this.obstacleMargin),s=t.polyLines.every(t=>t.mPoints.every(t=>{const e=(t.z1!==t.z2?this.viaDiameter/2:this.traceWidth/2)+this.BOUNDARY_PADDING;return((t,e,s=0)=>t.x>=e.minX+s&&t.x<=e.maxX-s&&t.y>=e.minY+s&&t.y<=e.maxY-s)(t,this.bounds,e)}));return e&&s}tryFinalAcceptance(){const t=this.hyperParameters?.MINIMUM_FINAL_ACCEPTANCE_GAP??void 0;if(void 0===t||null===this.lastCandidate||0===this.lastCandidate.minGaps.length)return;return Math.min(...this.lastCandidate.minGaps)>=t?(this.solved=!0,void this._setSolvedRoutes()):void 0}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return this.failed=!0,void(this.error="No candidates left")}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();if(!t)return void(this.failed=!0);const e=this.getNeighbors(t);for(const t of e)this.insertCandidate(t)}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"MultiHeadPolyLineIntraNodeSolver Visualization"};t.lines.push({points:[{x:this.bounds.minX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.minY}],strokeColor:"gray"});const e=this.lastCandidate??this.candidates[0];if(e?.hasClosedSameLayerFace){const e=.1*(this.bounds.maxX-this.bounds.minX),s=.1*(this.bounds.maxY-this.bounds.minY);t.rects.push({center:{x:this.bounds.maxX+.6*e,y:this.bounds.maxY+.6*s},width:e,height:s,fill:"red",label:"HAS CLOSED FACE"})}for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:`${e.connectionName} (Port z=${e.z??0})`,color:this.colorMap[e.connectionName]??"blue"});return e&&e.polyLines.forEach((s,n)=>{const i=this.colorMap[s.connectionName]??"purple",o=[s.start,...s.mPoints,s.end];for(let e=0;e<o.length-1;e++){const n=o[e],a=o[e+1],r=n.z2,h=0===r,c=h?i:ct(i,.5);t.lines.push({points:[n,a],strokeColor:c,strokeWidth:this.traceWidth,strokeDash:h?void 0:[.15,.15],label:`${s.connectionName} segment (z=${r})`})}o.forEach((a,r)=>{const h=a.z1!==a.z2,c=a.z1,d=r>0&&r<o.length-1;let l="",u="";if(d){const i=r-1,o=e.forces?.[n]?.[i];if(o&&o.size>0){const n={fx:0,fy:0};o.forEach((o,r)=>{if(n.fx+=o.fx,n.fy+=o.fy,Math.abs(o.fx)>1e-6||Math.abs(o.fy)>1e-6){const n=r.split(":"),h=n[0],c=parseInt(n[1],10),d=e.polyLines[c],l=this.colorMap[d.connectionName]??"gray",u=20,p={x:a.x+o.fx*u,y:a.y+o.fy*u};let f=d.connectionName;if("via"===h){f+=` Via ${parseInt(n[2],10)}`}else if("seg"===h){f+=` Seg ${parseInt(n[2],10)}-${parseInt(n[3],10)}`}t.lines.push({points:[a,p],strokeColor:l,strokeWidth:.02,strokeDash:"2,2",label:`Force by ${f} on ${s.connectionName} mPoint ${i}`})}}),(Math.abs(n.fx)>1e-6||Math.abs(n.fy)>1e-6)&&(u=`\nNet Force: (${n.fx.toFixed(3)}, ${n.fy.toFixed(3)})`)}}if(h)l=`Via (${s.connectionName} z=${a.z1} -> z=${a.z2})${u}`,t.circles.push({center:a,radius:this.viaDiameter/2,fill:ct(i,.5),label:l});else if(d){const e=0===c?i:ct(i,.5);l=`mPoint (${s.connectionName} z=${c})${u}`,t.circles.push({center:a,radius:this.cellSize/8,fill:e,label:l})}})}),t}_setSolvedRoutes(){if(!this.solved||!this.lastCandidate)return[];const t=[];for(const e of this.lastCandidate.polyLines){const s=[],n=[],i=[e.start,...e.mPoints,e.end];for(let t=0;t<i.length;t++){const e=i[t];s.push({x:e.x,y:e.y,z:e.z1}),e.z1!==e.z2&&(n.push({x:e.x,y:e.y}),s.push({x:e.x,y:e.y,z:e.z2}))}t.push({connectionName:e.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:s,vias:n})}this.solvedRoutes=t}},Je=class extends Ke{computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){const{minGaps:e}=t;let s=0;for(const t of e)t<0&&(s+=this.obstacleMargin),t<this.obstacleMargin&&(s+=this.obstacleMargin-t);return.011*s}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return void(this.failed=!0)}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();let e=!1,s=0;const n=void 0===t.magForceApplied?1:10;for(let i=0;i<n;i++){const n=this.applyForcesToPolyLines(t.polyLines);if(s+=n.magForceApplied,e=n.lastStepMoved,!n.lastStepMoved)break}if(t.magForceApplied=s,t.minGaps=this.computeMinGapBtwPolyLines(t.polyLines),this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();t.g=this.computeG(t.polyLines,t),t.h=this.computeH(t),t.f=t.g+t.h,e&&this.insertCandidate(t)}applyForcesToPolyLines(t){let e=0;const s=t.length,n=.02,i=.008,o=1e-6,a=Array.from({length:s},(e,s)=>Array.from({length:t[s].mPoints.length},()=>({fx:0,fy:0}))),r=(e,s,n,i)=>{if(s>0&&s<t[e].mPoints.length+1){const t=s-1;a[e][t].fx+=n,a[e][t].fy+=i}},h=(t,e,s,n,i)=>{const a=S(t,s.p1,s.p2),h=t.x-a.x,c=t.y-a.y,d=h*h+c*c;if(d<=o)return;const l=Math.sqrt(d),u=.02*Math.exp(-6*l),p=h/l*u,f=c/l*u;r(n,e,p,f),r(i,s.p1Idx,-p/2,-f/2),r(i,s.p2Idx,-p/2,-f/2)};for(let e=0;e<s;e++)for(let i=e+1;i<s;i++){const s=t[e],a=t[i],c=[s.start,...s.mPoints,s.end],d=[a.start,...a.mPoints,a.end],l=[],u=[];for(let t=0;t<c.length-1;t++)l.push({p1:c[t],p2:c[t+1],layer:c[t].z2,p1Idx:t,p2Idx:t+1});c.forEach((t,e)=>{t.z1!==t.z2&&u.push({point:t,layers:[t.z1,t.z2],index:e})});const p=[],f=[];for(let t=0;t<d.length-1;t++)p.push({p1:d[t],p2:d[t+1],layer:d[t].z2,p1Idx:t,p2Idx:t+1});d.forEach((t,e)=>{t.z1!==t.z2&&f.push({point:t,layers:[t.z1,t.z2],index:e})});for(const t of l)for(const s of p)if(t.layer===s.layer){M(t.p1,t.p2,s.p1,s.p2);h(t.p1,t.p1Idx,s,e,i),h(t.p2,t.p2Idx,s,e,i),h(s.p1,s.p1Idx,t,i,e),h(s.p2,s.p2Idx,t,i,e)}for(const t of u)for(const s of p)if(t.layers.includes(s.layer)){const a=S(t.point,s.p1,s.p2),h=t.point.x-a.x,c=t.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,m=c/a*p;r(e,t.index,f,m),r(i,s.p1Idx,-f/2,-m/2),r(i,s.p2Idx,-f/2,-m/2)}}for(const t of f)for(const s of l)if(t.layers.includes(s.layer)){const a=S(t.point,s.p1,s.p2),h=t.point.x-a.x,c=t.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,m=c/a*p;r(i,t.index,f,m),r(e,s.p1Idx,-f/2,-m/2),r(e,s.p2Idx,-f/2,-m/2)}}for(const t of u)for(const s of f){if(t.layers.filter(t=>s.layers.includes(t)).length>0){const a=t.point.x-s.point.x,h=t.point.y-s.point.y,c=a*a+h*h;if(c>o){const d=Math.sqrt(c);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(o,d)):u=Math.max(o,d-this.viaDiameter);const p=l*n*Math.exp(-6*u),f=a/d*p,m=h/d*p;r(e,t.index,f,m),r(i,s.index,-f,-m)}}}}for(let e=0;e<s;e++){const s=t[e],i=[s.start,...s.mPoints,s.end],a=[];if(i.forEach((t,e)=>{t.z1!==t.z2&&a.push({point:t,layers:[t.z1,t.z2],index:e})}),!(a.length<2))for(let t=0;t<a.length;t++)for(let s=t+1;s<a.length;s++){const i=a[t],h=a[s],c=i.point.x-h.point.x,d=i.point.y-h.point.y,l=c*c+d*d;if(l>o){const t=Math.sqrt(l);let s=2,a=t;t<this.viaDiameter?(s*=4,a=Math.max(o,t)):a=Math.max(o,t-this.viaDiameter);const u=s*n*Math.exp(-6*a),p=c/t*u,f=d/t*u;r(e,i.index,p,f),r(e,h.index,-p,-f)}}}let c=!1;for(let n=0;n<s;n++)for(let s=0;s<t[n].mPoints.length;s++){const r=t[n].mPoints[s],h=a[n][s],d=r.z1!==r.z2;let l=h.fx,u=h.fy,p=r.x+l,f=r.y+u;if(d){const t=this.viaDiameter/2;let e=0,s=0;const n=this.viaDiameter/2+this.BOUNDARY_PADDING,o=this.bounds.minX+n,a=this.bounds.maxX-n,h=this.bounds.minY+n,c=this.bounds.maxY-n,d=o+t-r.x,m=r.x-(a-t),g=h+t-r.y,y=r.y-(c-t);d>0?e=i*(Math.exp(d/(2*this.obstacleMargin))-1):m>0&&(e=-.008*(Math.exp(m/(2*this.obstacleMargin))-1)),g>0?s=i*(Math.exp(g/(2*this.obstacleMargin))-1):y>0&&(s=-.008*(Math.exp(y/(2*this.obstacleMargin))-1)),l+=e,u+=s,p=r.x+l,f=r.y+u}else{const t=this.traceWidth/2+this.BOUNDARY_PADDING;p=Math.max(this.bounds.minX+t,Math.min(this.bounds.maxX-t,p)),f=Math.max(this.bounds.minY+t,Math.min(this.bounds.maxY-t,f))}if(Math.abs(l)<o&&Math.abs(u)<o)continue;e+=Math.sqrt(l*l+u*u),(Math.abs(r.x-p)>o||Math.abs(r.y-f)>o)&&(r.x=p,r.y=f,c=!0)}return{lastStepMoved:c,magForceApplied:e}}},Qe=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 ts=class extends Je{constructor(t){super(t),this.MAX_ITERATIONS=1e3}createInitialCandidateFromSeed(t){const e=new we({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,hyperParameters:{SHUFFLE_SEED:t}});if(e.solve(),e.failed||!e.solved)return null;const s=[];let n=0;for(const[t,i]of e.completedPaths.entries()){if(i.length<2){console.warn(`Skipping connection "${t}" due to insufficient points (${i.length}) in ViaPossibilitiesSolver2 path.`);continue}const e=i[0],o=i[i.length-1],a=i.slice(1,-1),r=[];let c=0,d=e.z;for(let t=0;t<a.length;t++){const e=a[t],s=t+1<a.length?a[t+1]:o,n=d,i=t+1<a.length&&e.x===s.x&&e.y===s.y&&e.z!==s.z?s.z:e.z;r.push({x:e.x,y:e.y,z1:n,z2:i}),n!==i?(c++,t++,d=i):d=e.z}n+=c;const l=this.SEGMENTS_PER_POLYLINE;let u=r.length+1;for(;u<l;){let s=-1,n=-1,i=null,a=null;const c=[{...e,z1:e.z,z2:e.z,connectionName:t},...r,{...o,z1:o.z,z2:o.z,connectionName:t}];for(let t=0;t<c.length-1;t++){const e=c[t],o=c[t+1];if(e.x===o.x&&e.y===o.y)continue;const r=h(e,o);r>s&&(s=r,n=t,i=e,a=o)}if(-1===n||!i||!a){console.warn(`Could not find longest segment for ${t} while trying to reach ${l} segments.`);break}const d=(i.x+a.x)/2,p=(i.y+a.y)/2,f=i.z2,m={x:d,y:p,z1:f,z2:f};r.splice(n,0,m),u++}s.push({connectionName:t,start:{...e,z1:e.z,z2:e.z},end:{...o,z1:o.z,z2:o.z},mPoints:r})}if(0===s.length)return this.failed=!0,this.error="No valid polylines generated from ViaPossibilitiesSolver2.",console.error(this.error),null;const i=this.computeMinGapBtwPolyLines(s),o=this.computeH({minGaps:i,forces:[]}),a={polyLines:s,g:0,h:o,f:0+o,viaCount:n,minGaps:i};return a.g=this.computeG(s,a),a.f=a.g+a.h,a}setupInitialPolyLines(){this.candidates=[];const t=Math.min(2e3,function(t){if(!Number.isInteger(t)||t<0)throw new RangeError("n must be a non-negative integer");let e=1;for(let s=2;s<=t;s++)e*=s;return e}(this.uniqueConnections)),e=new Set;for(let s=0;s<t;s++){const t=this.createInitialCandidateFromSeed(s);if(!t)continue;const n=Qe(t.polyLines);e.has(n)||(e.add(n),this.candidates.push(t))}this.candidates.sort((t,e)=>t.f-e.f)}},es=class extends xe{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 ve({nodeWithPortPoints:this.nodeWithPortPoints}):t.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING?new Ee({nodeWithPortPoints:this.nodeWithPortPoints}):t.MULTI_HEAD_POLYLINE_SOLVER?new ts({nodeWithPortPoints:this.nodeWithPortPoints,connMap:this.connMap,hyperParameters:t}):new ye({...this.constructorParams,hyperParameters:t})}onSolve(t){this.solvedRoutes=t.solver.solvedRoutes}};function ss(t,e,s){const n=[];let i=null;for(let o=0;o<t.length;o++){const a=t[o];i?i.z===a.z?i.points.push({x:a.x,y:a.y}):(n.push(i),i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:s}):i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:s},o===t.length-1&&i&&n.push(i)}return n}var ns=class extends e{unsolvedNodePortPoints;routes;colorMap;defaultViaDiameter=.6;defaultTraceThickness=.15;failedSolvers;activeSubSolver=null;connMap;constructor({nodePortPoints:t,colorMap:e,connMap:s}){super(),this.unsolvedNodePortPoints=t,this.colorMap=e??{},this.connMap=s,this.routes=[],this.failedSolvers=[],this.MAX_ITERATIONS=1e6}_step(){if(this.updateCacheStats(),this.activeSubSolver)return this.activeSubSolver.step(),this.activeSubSolver.solved?(this.routes.push(...this.activeSubSolver.solvedRoutes),this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSolvers.push(this.activeSubSolver),this.activeSubSolver=null),void this.updateCacheStats();if(0===this.unsolvedNodePortPoints.length)return this.failedSolvers.length>0?(this.solved=!1,this.failed=!0,this.error=`Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0,5).map(t=>t.nodeWithPortPoints.capacityMeshNodeId)}. err0: ${this.failedSolvers[0].error}.`,void this.updateCacheStats()):(this.solved=!0,void this.updateCacheStats());const t=this.unsolvedNodePortPoints.pop();this.activeSubSolver=new es({nodeWithPortPoints:t,colorMap:this.colorMap,connMap:this.connMap}),this.updateCacheStats()}updateCacheStats(){const t=ne();this.stats.intraNodeCacheHits=t.cacheHits,this.stats.intraNodeCacheMisses=t.cacheMisses}visualize(){let e={lines:[],points:[],rects:[],circles:[]};for(const t of this.routes){const s=ss(t.route,t.connectionName,this.colorMap[t.connectionName]);for(const n of s)e.lines.push({points:n.points,label:n.connectionName,strokeColor:0===n.z?n.color:ct(n.color,.75),layer:`z${n.z}`,strokeWidth:t.traceThickness,strokeDash:0!==n.z?"10, 5":void 0});for(const s of t.vias)e.circles.push({center:s,layer:"z0,1",radius:t.viaDiameter/2,fill:this.colorMap[t.connectionName],label:`${t.connectionName} via`})}for(const t of this.failedSolvers){const s=t.nodeWithPortPoints,n=.1*s.width,i=.1*s.height;e.rects.push({center:{x:s.center.x-n/2,y:s.center.y-i/2},layer:"did_not_connect",width:n,height:i,fill:"red",label:`Failed: ${s.capacityMeshNodeId}`});const o={};for(const t of s.portPoints)o[t.connectionName]||(o[t.connectionName]=[]),o[t.connectionName].push({x:t.x,y:t.y,z:t.z});for(const[t,s]of Object.entries(o))for(let t=0;t<s.length-1;t++){const n=s[t],i=s[t+1];e.lines.push({points:[n,i],strokeColor:"red",strokeDash:"10, 5",layer:"did_not_connect"})}}return this.activeSubSolver&&(e=t(e,this.activeSubSolver.visualize())),e}},is=class{netMap;idToNetMap;constructor(t){this.netMap=t,this.idToNetMap={};for(const[e,s]of Object.entries(t))for(const t of s)this.idToNetMap[t]=e}addConnections(t){for(const e of t){const t=new Set;for(const s of e){const e=this.idToNetMap[s];e&&t.add(e)}let s;if(0===t.size)s=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[s]=[];else if(1===t.size)s=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{s=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(const e of t)if(e!==s){this.netMap[s].push(...this.netMap[e]),this.netMap[e]=this.netMap[s];for(const t of this.netMap[s])this.idToNetMap[t]=s}}for(const t of e)this.netMap[s].includes(t)||this.netMap[s].push(t),this.idToNetMap[t]=s}}getIdsConnectedToNet(t){return this.netMap[t]||[]}getNetConnectedToId(t){return this.idToNetMap[t]}areIdsConnected(t,e){if(t===e)return!0;const s=this.getNetConnectedToId(t);if(!s)return!1;const n=this.getNetConnectedToId(e);return!!n&&(s===n||n===t||n===t)}areAllIdsConnected(t){const e=this.getNetConnectedToId(t[0]);for(const s of t){const t=this.getNetConnectedToId(s);if(void 0===t)return!1;if(t!==e)return!1}return!0}},os=t=>{const e=new is({});for(const s of t.connections)for(const t of s.pointsToConnect)"pcb_port_id"in t&&t.pcb_port_id&&e.addConnections([[s.name,t.pcb_port_id]]);for(const s of t.obstacles)e.addConnections([s.connectedTo]);return e},as=class{point;left=null;right=null;constructor(t){this.point=t}},rs=class{root=null;constructor(t){t.length>0&&(this.root=this.buildTree(t,0))}buildTree(t,e){const s=e%2==0?"x":"y";t.sort((t,e)=>t[s]-e[s]);const n=Math.floor(t.length/2),i=new as(t[n]);return n>0&&(i.left=this.buildTree(t.slice(0,n),e+1)),n<t.length-1&&(i.right=this.buildTree(t.slice(n+1),e+1)),i}findNearestNeighbor(t){if(!this.root)throw new Error("Tree is empty");const e=this.root.point,s=this.distance(t,e);return this.nearestNeighborSearch(this.root,t,0,e,s),e}nearestNeighborSearch(t,e,s,n,i){if(!t)return n;const o=s%2?"x":"y",a=this.distance(e,t.point);a<i&&(n=t.point,i=a);const r=e[o]-t.point[o],h=r<=0?t.left:t.right,c=r<=0?t.right:t.left;return n=this.nearestNeighborSearch(h,e,s+1,n,i),i=this.distance(e,n),Math.abs(r)<i&&(n=this.nearestNeighborSearch(c,e,s+1,n,i)),n}findKNearestNeighbors(t,e){if(!this.root)return[];const s=[];return this.kNearestNeighborSearch(this.root,t,0,s,e),s.sort((t,e)=>t.distance-e.distance).slice(0,e).map(t=>t.point)}kNearestNeighborSearch(t,e,s,n,i){if(!t)return;const o=s%2?"x":"y",a=this.distance(e,t.point);n.push({point:t.point,distance:a});const r=e[o]-t.point[o],h=r<=0?t.left:t.right,c=r<=0?t.right:t.left;this.kNearestNeighborSearch(h,e,s+1,n,i);let d=1/0;n.length>=i&&(n.sort((t,e)=>t.distance-e.distance),d=n[i-1]?.distance||1/0),(Math.abs(r)<d||n.length<i)&&this.kNearestNeighborSearch(c,e,s+1,n,i)}distance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}},hs=class{parent=new Map;rank=new Map;constructor(t){for(const e of t){const t=this.pointToKey(e);this.parent.set(t,t),this.rank.set(t,0)}}pointToKey(t){return`${t.x},${t.y}`}find(t){const e=this.pointToKey(t);if(!this.parent.has(e))throw new Error(`Point ${e} not found in DisjointSet`);let s=e;for(;s!==this.parent.get(s);)s=this.parent.get(s);let n=e;for(;n!==s;){const t=this.parent.get(n);this.parent.set(n,s),n=t}return s}union(t,e){const s=this.find(t),n=this.find(e);if(s===n)return!1;const i=this.rank.get(s)||0,o=this.rank.get(n)||0;return i<o?this.parent.set(s,n):i>o?this.parent.set(n,s):(this.parent.set(n,s),this.rank.set(s,i+1)),!0}};var cs=class extends e{constructor(t,e={}){super(),this.ogSrj=t,this.colorMap=e,this.unprocessedConnections=[...t.connections],this.newConnections=[]}unprocessedConnections;newConnections;_step(){if(0===this.unprocessedConnections.length)return void(this.solved=!0);const t=this.unprocessedConnections.pop(),e=t.externallyConnectedPointIds??[],s=new Map;e.forEach((t,e)=>t.forEach(t=>s.set(t,e)));const n=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const n=s.get(t.pointId),i=s.get(e.pointId);return void 0!==n&&n===i};if(2===t.pointsToConnect.length){if(n(t.pointsToConnect[0],t.pointsToConnect[1]))return;return void this.newConnections.push(t)}const i=function(t){if(t.length<=1)return[];const e=new rs(t),s=[],n=Math.min(10,t.length-1);for(const i of t){const t=e.findKNearestNeighbors(i,n+1);for(const e of t){if(i.x===e.x&&i.y===e.y)continue;const t=Math.sqrt((i.x-e.x)**2+(i.y-e.y)**2);s.push({from:i,to:e,weight:t})}}s.sort((t,e)=>t.weight-e.weight);const i=new hs(t),o=[];for(const e of s)if(i.union(e.from,e.to)&&(o.push(e),o.length===t.length-1))break;return o}(t.pointsToConnect);let o=0;for(const e of i)n(e.from,e.to)||this.newConnections.push({pointsToConnect:[e.from,e.to],name:`${t.name}_mst${o++}`})}getNewSimpleRouteJson(){return{...this.ogSrj,connections:this.newConnections}}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Net To Point Pairs Visualization"};return this.unprocessedConnections.forEach(e=>{e.pointsToConnect.forEach(s=>{t.points.push({x:s.x,y:s.y,color:"red",label:e.name})});const s=e.pointsToConnect.length**2,n=de(0),i=new Set;for(let o=0;o<Math.max(s,2*e.pointsToConnect.length);o++){const s=Math.floor(n()*e.pointsToConnect.length),o=Math.floor(n()*e.pointsToConnect.length);i.has(`${s}-${o}`)||(i.add(`${s}-${o}`),t.lines.push({points:[e.pointsToConnect[s],e.pointsToConnect[o]],strokeColor:"rgba(255,0,0,0.25)"}))}}),this.newConnections.forEach(e=>{const s=this.colorMap?.[e.name]||"blue";e.pointsToConnect.forEach(n=>{t.points.push({x:n.x,y:n.y,color:s,label:e.name})});for(let n=0;n<e.pointsToConnect.length-1;n++)for(let i=n+1;i<e.pointsToConnect.length;i++)t.lines.push({points:[e.pointsToConnect[n],e.pointsToConnect[i]],strokeColor:s})}),t}},ds=(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}`},ls=(t,e)=>{const s=[];if(0===t.route.length)return s;let n=[],i=t.route[0].z;for(let o=0;o<t.route.length;o++){const a=t.route[o];if(a.z!==i){const o=ds(i,e);for(const e of n)s.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:o});if(t.vias.some(t=>Math.abs(t.x-a.x)<.001&&Math.abs(t.y-a.y)<.001)){const t=ds(i,e),n=ds(a.z,e);s.push({route_type:"via",x:a.x,y:a.y,from_layer:t,to_layer:n})}n=[a],i=a.z}else n.push(a)}const o=ds(i,e);for(const e of n)s.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:o});return s},us=class extends e{mergedHdRoute;remainingHdRoutes;start;end;colorMap;constructor(t){if(super(),this.remainingHdRoutes=[...t.hdRoutes],this.colorMap=t.colorMap??{},0===t.hdRoutes.length){this.start=t.start,this.end=t.end;const e=[{x:t.start.x,y:t.start.y,z:t.start.z}],s=[];return t.start.z!==t.end.z&&(e.push({x:t.start.x,y:t.start.y,z:t.end.z}),s.push({x:t.start.x,y:t.start.y})),e.push({x:t.end.x,y:t.end.y,z:t.end.z}),this.mergedHdRoute={connectionName:t.connectionName,route:e,vias:s,viaDiameter:t.defaultViaDiameter??.6,traceThickness:t.defaultTraceThickness??.15},void(this.solved=!0)}const{firstRoute:e}=this.getDisjointedRoute();Math.min(h(e.route[0],t.start),h(e.route[e.route.length-1],t.start))<Math.min(h(e.route[0],t.end),h(e.route[e.route.length-1],t.end))?(this.start=t.start,this.end=t.end):(this.start=t.end,this.end=t.start),this.mergedHdRoute={connectionName:t.connectionName,route:[{x:this.start.x,y:this.start.y,z:this.start.z}],vias:[],viaDiameter:e.viaDiameter,traceThickness:e.traceThickness}}getDisjointedRoute(){for(const t of this.remainingHdRoutes){if([t.route[0],t.route[t.route.length-1]].some(e=>!this.remainingHdRoutes.some(s=>{if(s===t)return!1;return[s.route[0],s.route[s.route.length-1]].some(t=>t.z===e.z&&h(e,t)<5e-6)})))return{firstRoute:t}}return{firstRoute:this.remainingHdRoutes[0]}}_step(){if(0===this.remainingHdRoutes.length)return this.mergedHdRoute.route.push({x:this.end.x,y:this.end.y,z:this.end.z}),void(this.solved=!0);const t=this.mergedHdRoute.route[this.mergedHdRoute.route.length-1];let e=0,s="first",n=1/0;for(let i=0;i<this.remainingHdRoutes.length;i++){const o=this.remainingHdRoutes[i],a=o.route[o.route.length-1],r=o.route[0],c=h(t,r),d=h(t,a);c<n&&t.z===r.z&&(n=c,e=i,s="first"),d<n&&t.z===a.z&&(n=d,e=i,s="last")}const i=this.remainingHdRoutes[e];this.remainingHdRoutes.splice(e,1),"first"===s?this.mergedHdRoute.route.push(...i.route):this.mergedHdRoute.route.push(...[...i.route].reverse()),this.mergedHdRoute.vias.push(...i.vias)}visualize(){const t={points:[],lines:[],circles:[],title:"Single High Density Route Stitch Solver"};if(t.points?.push({x:this.start.x,y:this.start.y,color:"green",label:"Start"},{x:this.end.x,y:this.end.y,color:"red",label:"End"}),this.mergedHdRoute&&this.mergedHdRoute.route.length>1){t.lines?.push({points:this.mergedHdRoute.route.map(t=>({x:t.x,y:t.y})),strokeColor:"green"});for(const e of this.mergedHdRoute.route)t.points?.push({x:e.x,y:e.y,color:"green"});for(const e of this.mergedHdRoute.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:this.mergedHdRoute.viaDiameter/2,fill:"green"})}for(const[e,s]of this.remainingHdRoutes.entries()){const n=this.colorMap[s.connectionName]??"gray";s.route.length>1&&t.lines?.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:n});for(let i=0;i<s.route.length;i++){const o=s.route[i];t.points?.push({x:o.x+(e%2-.5)/500+(i%8-4)/1e3,y:o.y+(e%2-.5)/500+(i%8-4)/1e3,color:n,label:`Route ${s.connectionName} ${o===s.route[0]?"First":o===s.route[s.route.length-1]?"Last":""}`})}for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n})}return t}},ps=class extends e{unsolvedRoutes;activeSolver=null;mergedHdRoutes=[];colorMap={};defaultTraceThickness;defaultViaDiameter;constructor(t){super(),this.colorMap=t.colorMap??{},t.hdRoutes.length>0?(this.defaultTraceThickness=t.hdRoutes[0].traceThickness,this.defaultViaDiameter=t.hdRoutes[0].viaDiameter):(this.defaultTraceThickness=.15,this.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:dt(e.pointsToConnect[0].layer,t.layerCount)},end:{...e.pointsToConnect[1],z:dt(e.pointsToConnect[1].layer,t.layerCount)}})),this.MAX_ITERATIONS=1e5}_step(){if(this.activeSolver)return this.activeSolver.step(),void(this.activeSolver.solved?(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 us({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=e.rects)}for(const[e,s]of this.mergedHdRoutes.entries()){const n=this.colorMap[s.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1],a=0!==i.z?ct(n,.5):n;t.lines?.push({points:[{x:i.x,y:i.y},{x:o.x,y:o.y}],strokeColor:a,strokeWidth:s.traceThickness})}for(const e of s.route){const s=0!==e.z?ct(n,.5):n;t.points?.push({x:e.x,y:e.y,color:s})}for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n})}for(const e of this.unsolvedRoutes){const s=this.colorMap[e.connectionName]??"gray";t.points?.push({x:e.start.x,y:e.start.y,color:s,label:`${e.connectionName} Start (z=${e.start.z})`},{x:e.end.x,y:e.end.y,color:s,label:`${e.connectionName} End (z=${e.end.z})`}),t.lines?.push({points:[{x:e.start.x,y:e.start.y},{x:e.end.x,y:e.end.y}],strokeColor:s,strokeDash:"2 2"});for(const n of e.hdRoutes){n.route.length>1&&t.lines?.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:ct(s,.5),strokeDash:"10 5"});for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s})}}return t}},fs=t=>{const e=[],s=[],n=[],i=ht(t);if(t.connections)for(const e of t.connections)for(const t of e.pointsToConnect)n.push({x:t.x,y:t.y,color:i[e.name],layer:t.layer??("z"in t?ds(t.z,2):"top"),label:`${e.name} (${t.layer})`});if(t.traces)for(const n of t.traces)for(let t=0;t<n.route.length-1;t++){const i=n.route[t],o=n.route[t+1];"via"===i.route_type?s.push({center:{x:i.x,y:i.y},radius:.3,fill:"blue",stroke:"none",layer:"z0,1"}):"wire"===i.route_type&&"wire"===o.route_type&&o.layer===i.layer&&e.push({points:[{x:i.x,y:i.y},{x:o.x,y:o.y}],layer:`z${dt(i.layer,2)}`,strokeWidth:.15,strokeColor:ct({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(dt).join(",")}`})),circles:s,lines:e,points:n}};function ms(t){const{nodeId:e,nodeIdToSegmentIds:s,segmentIdToNodeIds:n,hops:i}=t;if(0===i)return[e];const o=new Set([e]),a=[{nodeId:e,remainingHops:i}];for(;a.length>0;){const{nodeId:t,remainingHops:e}=a.shift();if(0===e)continue;const i=s.get(t)||[];for(const t of i){const s=n.get(t)||[];for(const t of s)o.has(t)||(o.add(t),a.push({nodeId:t,remainingHops:e-1}))}}return Array.from(o)}var gs=t=>Array.from(t.entries()).map(([t,{x:e,y:s,z:n}])=>`${t}(${e?.toFixed(3)??""},${s?.toFixed(3)??""},${n??""})`).sort().join("&"),ys=(t,e,s,n)=>{const i=Math.min(t,e),o=Math.max(t,e),a=Math.min(s,n);return i<=Math.max(s,n)&&o>=a},xs=(t,e,s,n)=>{const o=[],a=new Map(t.originalPointMap);for(const[t,e]of s.entries()){const s=a.get(t);a.set(t,{x:e.x??s.x,y:e.y??s.y,z:e.z??s.z})}for(const s of t.allNodeIds){if(!e.get(s))continue;const r=t.segmentPairsInNode.get(s);for(const t of r){const e=a.get(t[0]),n=a.get(t[1]);e.z!==n.z&&o.push({type:"transition_via",segmentPoints:t,capacityMeshNodeId:s,probabilityOfFailure:0})}for(let t=0;t<r.length;t++)for(let e=t+1;e<r.length;e++){if(n?.areIdsConnected(r[t][0],r[t][1]))continue;const h=r[t],c=r[e],d=a.get(h[0]),l=a.get(h[1]),u=a.get(c[0]),p=a.get(c[1]);if(!ys(d.z,l.z,u.z,p.z))continue;const f=i(d,l,u,p),m=d.z===l.z&&u.z===p.z&&d.z===u.z;f&&(m?o.push({type:"same_layer_crossing",segmentPoints:[h,c],capacityMeshNodeId:s,crossingLine1:h,crossingLine2:c,probabilityOfFailure:0}):d.z===l.z&&u.z!==p.z?o.push({type:"single_transition_crossing",segmentPoints:[h,c],capacityMeshNodeId:s,sameLayerCrossingLine:h,transitionCrossingLine:c,probabilityOfFailure:0}):d.z!==l.z&&u.z===p.z?o.push({type:"single_transition_crossing",segmentPoints:[h,c],capacityMeshNodeId:s,sameLayerCrossingLine:c,transitionCrossingLine:h,probabilityOfFailure:0}):d.z!==l.z&&u.z!==p.z&&o.push({type:"double_transition_crossing",segmentPoints:[h,c],capacityMeshNodeId:s,crossingLine1:h,crossingLine2:c,probabilityOfFailure:0}))}}return o},Ms=(t,e,s)=>{if("change_layer"===e.type)for(const s of e.segmentPointIds){const n=t.get(s)||{};t.set(s,{...n,z:e.newZ})}else if("swap_position_on_segment"===e.type){const[n,i]=e.segmentPointIds,o=s(n),a=s(i),r=t.get(n)||{},h=t.get(i)||{};t.set(n,{...r,x:a.x,y:a.y}),t.set(i,{...h,x:o.x,y:o.y})}else if("combined"===e.type)for(const n of e.operations)Ms(t,n,s)},vs=(t,e)=>{const s=new Map,n=new Map,i=new Map,o=[];let a=0;for(const r of t)for(const t of r.assignedPoints){const h={segmentPointId:"SP"+a++,segmentId:r.nodePortSegmentId,capacityMeshNodeIds:e.get(r.nodePortSegmentId),connectionName:t.connectionName,x:t.point.x,y:t.point.y,z:t.point.z,directlyConnectedSegmentPointIds:[]};s.set(h.segmentPointId,h);for(const t of h.capacityMeshNodeIds)n.set(t,[...n.get(t)??[],h.segmentPointId]);i.set(r.nodePortSegmentId,[...i.get(r.nodePortSegmentId)??[],h.segmentPointId]),o.push(h)}return{segmentPointMap:s,nodeToSegmentPointMap:n,segmentToSegmentPointMap:i}},Ss=(t,e,s,n)=>{if(t?._containsTarget)return 0;return((.82*e+.41*s+.2*n)/2)**1.1/lt(t)},bs=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,lt(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=ms({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS}),s=ms({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS+1}),n=Array.from(new Set(s).difference(new Set(e)));t?.segmentPointMap||(t=vs(this.dedupedSegments,this.segmentIdToNodeIds));const i=new Map;for(const e of s)i.set(e,t.nodeToSegmentPointMap.get(e));const o=new Map;for(const e of s)for(const s of i.get(e)){const e=t.segmentPointMap.get(s);o.set(s,e)}const a=Array.from(o.values()),r=new Map;for(const t of a)r.set(t.segmentId,[...r.get(t.segmentId)??[],t.segmentPointId]);for(const[e,s]of i.entries())for(let e=0;e<s.length;e++){const n=t.segmentPointMap.get(s[e]);for(let i=e+1;i<s.length;i++){const e=t.segmentPointMap.get(s[i]);e.segmentPointId!==n.segmentPointId&&(e.segmentId!==n.segmentId&&e.connectionName===n.connectionName&&(e.directlyConnectedSegmentPointIds.includes(n.segmentPointId)||(n.directlyConnectedSegmentPointIds.push(e.segmentPointId),e.directlyConnectedSegmentPointIds.push(n.segmentPointId))))}}const h=new Map;for(const t of s)h.set(t,[]);for(const e of a)for(const s of e.capacityMeshNodeIds){const n=h.get(s);if(n)for(const i of e.directlyConnectedSegmentPointIds){const o=t.segmentPointMap.get(i);o.segmentPointId!==e.segmentPointId&&(o.capacityMeshNodeIds.some(t=>t===s)&&(n.some(([t,s])=>t===e.segmentPointId&&s===o.segmentPointId||t===o.segmentPointId&&s===e.segmentPointId)||n.push([e.segmentPointId,o.segmentPointId])))}}const c=new Set;for(const t of e)for(const e of this.nodeIdToSegmentIds.get(t)){this.segmentIdToNodeIds.get(e).every(t=>!this.nodeMap.get(t)._containsTarget)&&c.add(e)}const d=new Set;for(const t of a)t.capacityMeshNodeIds.some(t=>e.includes(t))&&d.add(t.segmentPointId);return{allNodeIds:s,mutableNodeIds:e,immutableNodeIds:n,mutableSegmentIds:c,segmentPairsInNode:h,segmentPointMap:o,segmentPointsInNode:i,segmentPointsInSegment:r,originalPointMap:o,mutableSegmentPointIds:d}}createInitialCandidate(){const t=new Map,e=xs(this.unravelSection,this.nodeMap,t),s=this.computeG({issues:e,originalCandidate:{},operationsPerformed:0,operation:{}});return{pointModifications:t,g:s,h:0,f:s,operationsPerformed:0,candidateHash:gs(t),issues:xs(this.unravelSection,this.nodeMap,t)}}get nextCandidate(){return this.candidates[0]??null}getPointInCandidate(t,e){const s=this.unravelSection.segmentPointMap.get(e),n=t.pointModifications.get(e);return{x:n?.x??s.x,y:n?.y??s.y,z:n?.z??s.z,segmentId:s.segmentId}}getOperationsForIssue(t,e){const s=[];if("transition_via"===e.type){const[n,i]=e.segmentPoints,o=this.getPointInCandidate(t,n),a=this.getPointInCandidate(t,i),r=this.dedupedSegmentMap.get(o.segmentId).availableZ,h=this.dedupedSegmentMap.get(a.segmentId).availableZ;this.unravelSection.mutableSegmentPointIds.has(n)&&r.includes(a.z)&&s.push({type:"change_layer",newZ:a.z,segmentPointIds:[n]}),this.unravelSection.mutableSegmentPointIds.has(i)&&h.includes(o.z)&&s.push({type:"change_layer",newZ:o.z,segmentPointIds:[i]})}if("same_layer_crossing"===e.type){const[t,n]=e.crossingLine1,[i,o]=e.crossingLine2,a=[],r=this.unravelSection.segmentPointMap.get(t),h=this.unravelSection.segmentPointMap.get(n),c=this.unravelSection.segmentPointMap.get(i),d=this.unravelSection.segmentPointMap.get(o),l=this.unravelSection.mutableSegmentPointIds.has(t),u=this.unravelSection.mutableSegmentPointIds.has(n),p=this.unravelSection.mutableSegmentPointIds.has(i),f=this.unravelSection.mutableSegmentPointIds.has(o);l&&p&&r.segmentId===c.segmentId&&a.push([t,i]),l&&f&&r.segmentId===d.segmentId&&a.push([t,o]),u&&p&&h.segmentId===c.segmentId&&a.push([n,i]),u&&f&&h.segmentId===d.segmentId&&a.push([n,o]);for(const[t,e]of a)s.push({type:"swap_position_on_segment",segmentPointIds:[t,e]});const m=this.dedupedSegmentMap.get(r.segmentId),g=this.dedupedSegmentMap.get(h.segmentId),y=this.dedupedSegmentMap.get(c.segmentId),x=this.dedupedSegmentMap.get(d.segmentId),M=(t,e)=>t.every(t=>t.availableZ.includes(e));if(l&&u){const e=0===r.z?1:0;M([m,g],e)&&s.push({type:"change_layer",newZ:e,segmentPointIds:[t,n]})}if(p&&f){const t=0===c.z?1:0;M([y,x],t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[i,o]})}if(l){const e=0===r.z?1:0;m.availableZ.includes(e)&&s.push({type:"change_layer",newZ:e,segmentPointIds:[t]})}if(u){const t=0===h.z?1:0;g.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[n]})}if(p){const t=0===c.z?1:0;y.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[i]})}if(f){const t=0===d.z?1:0;x.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[o]})}}return s}computeG(t){const{issues:e,originalCandidate:s,operationsPerformed:n,operation:i}=t,o=new Map;for(const t of e){o.has(t.capacityMeshNodeId)||o.set(t.capacityMeshNodeId,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0});const e=o.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"===t.type||"single_transition_crossing"===t.type?e.numEntryExitLayerChanges++:t.type}let a=0;for(const[t,{numEntryExitLayerChanges:e,numSameLayerCrossings:s,numTransitionCrossings:n}]of o){const i=this.nodeMap.get(t),o=Math.min(Ss(i,s,e,n),.999999);a+=Math.log(1-o)}var r;return(r=a)<-Math.LN2?Math.log(1-Math.exp(r)):Math.log(-Math.expm1(r))}getUnexploredNeighborByApplyingOperation(t,e){const s=new Map(t.pointModifications);Ms(s,e,e=>this.getPointInCandidate(t,e));const n=gs(s);if(this.queuedOrExploredCandidatePointModificationHashes.has(n))return null;const i=xs(this.unravelSection,this.nodeMap,s),o=t.operationsPerformed+1,a=this.computeG({issues:i,originalCandidate:t,operationsPerformed:o,operation:e});return{issues:i,g:a,h:0,f:a,pointModifications:s,candidateHash:n,operationsPerformed:o}}getNeighborOperationsForCandidate(t){return t.issues.flatMap(e=>this.getOperationsForIssue(t,e))}getNeighbors(t){const e=[],s=this.getNeighborOperationsForCandidate(t);for(const n of s){const s=this.getUnexploredNeighborByApplyingOperation(t,n);s&&e.push(s)}return e}_step(){const t=this.candidates.shift();this.iterationsSinceImprovement++,this.iterationsSinceImprovement>this.hyperParameters.MAX_ITERATIONS_WITHOUT_IMPROVEMENT?this.solved=!0:t?(this.lastProcessedCandidate=t,t.f<(this.bestCandidate?.f??1/0)&&(this.bestCandidate=t,this.iterationsSinceImprovement=0),this.getNeighbors(t).forEach(t=>{this.queuedOrExploredCandidatePointModificationHashes.has(t.candidateHash)||(this.queuedOrExploredCandidatePointModificationHashes.add(t.candidateHash),this.candidates.push(t))}),this.candidates.sort((t,e)=>t.f-e.f),this.candidates.length=Math.min(this.candidates.length,this.MAX_CANDIDATES)):this.solved=!0}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Section Solver"};let e=null;if(e=null!==this.selectedCandidateIndex?"best"===this.selectedCandidateIndex?this.bestCandidate:"original"===this.selectedCandidateIndex?this.originalCandidate:this.candidates[this.selectedCandidateIndex]:this.solved?this.bestCandidate:this.lastProcessedCandidate||this.candidates[0],!e)return t;const s=new Map;for(const[t,n]of this.unravelSection.segmentPointMap){const i={...n},o=e.pointModifications.get(t);o&&(void 0!==o.x&&(i.x=o.x),void 0!==o.y&&(i.y=o.y),void 0!==o.z&&(i.z=o.z)),s.set(t,i)}for(const[e,n]of s)t.points.push({x:n.x,y:n.y,label:`${e}\nSegment: ${n.segmentId} ${this.unravelSection.mutableSegmentIds.has(n.segmentId)?"MUTABLE":"IMMUTABLE"}\nLayer: ${n.z}`,color:this.colorMap[n.connectionName]||"#000"});const n=new Map;for(const t of this.unravelSection.allNodeIds)n.set(t,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0,estPf:0});for(const t of e.issues){const e=n.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"!==t.type&&"single_transition_crossing"!==t.type||e.numEntryExitLayerChanges++}for(const[t,e]of n.entries()){const s=this.nodeMap.get(t);e.estPf=Ss(s,e.numSameLayerCrossings,e.numEntryExitLayerChanges,e.numTransitionCrossings)}for(const e of this.unravelSection.allNodeIds){const s=this.nodeMap.get(e),i=this.unravelSection.mutableNodeIds.includes(e),o=n.get(e),a=[`${e} (${i?"MUT":"IMM"})`,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Pf: ${o.estPf.toFixed(3)}`,`TC: ${o.numTransitionCrossings}`,`SLC: ${o.numSameLayerCrossings}`,`EELC: ${o.numEntryExitLayerChanges}`].join("\n");t.rects.push({center:s.center,label:a,color:i?"green":"red",width:s.width/8,height:s.height/8})}for(const[e,n]of this.unravelSection.segmentPointsInSegment){if(n.length<=1)continue;const i=n.map(t=>s.get(t));for(let s=0;s<i.length-1;s++)t.lines.push({points:[{x:i[s].x,y:i[s].y},{x:i[s+1].x,y:i[s+1].y}],strokeColor:this.colorMap[e]||"#000"})}for(const[e,n]of s)for(const i of n.directlyConnectedSegmentPointIds)if(e<i){const e=s.get(i);if(!e)continue;const o=n.z===e.z,a=n.z;let r;r=o?0===a?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:n.x,y:n.y},{x:e.x,y:e.y}],strokeDash:r,strokeColor:this.colorMap[n.connectionName]||"#000"})}for(const n of e.issues){const e=this.nodeMap.get(n.capacityMeshNodeId);if("transition_via"===n.type)for(const i of n.segmentPoints){const n=s.get(i);t.circles.push({center:{x:n.x,y:n.y},radius:e.width/16,stroke:"#ff0000",fill:"rgba(255, 0, 0, 0.2)",label:`Via Issue\n${i}\nLayer: ${n.z}`})}else if("same_layer_crossing"===n.type)for(const[i,o]of[n.crossingLine1,n.crossingLine2]){const n=s.get(i),a=s.get(o);t.lines.push({points:[{x:n.x,y:n.y},{x:a.x,y:a.y}],strokeColor:"rgba(255,0,0,0.2)",strokeWidth:e.width/32})}}for(const[n,i]of e.pointModifications){const e=s.get(n),i=this.unravelSection.segmentPointMap.get(n);t.circles.push({center:{x:e.x,y:e.y},radius:.05,stroke:"#0000ff",fill:"rgba(0, 0, 255, 0.2)",label:`${n}\nOriginal: (${i.x.toFixed(2)}, ${i.y.toFixed(2)}, ${i.z})\nNew: (${e.x.toFixed(2)}, ${e.y.toFixed(2)}, ${e.z})`})}return t}};import Ns from"object-hash";function Is(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:Ps,sin:Cs,PI:_s}=Math,{tan:Ts}=Math,Es=t=>(Math.round(20*t)/20).toFixed(2),As=t=>(Math.round(1e3*t)/1e3).toFixed(3);ie();var ws=class extends bs{cacheHit=!1;cacheProvider;hasAttemptedToUseCache=!1;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?se():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}computeCacheKeyAndTransform(){const t=this.nodeMap.get(this.rootNodeId),e=function(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}(-t.center.x,-t.center.y),s=new Map,n=new Map,i=new Map,o=new Map,a=new Map,r=new Map;let h=0,c=0,d=0;const l=[...this.unravelSection.allNodeIds].sort((t,e)=>{const s=this.nodeMap.get(t),n=this.nodeMap.get(e);return s.center.x!==n.center.x?s.center.x-n.center.x:s.center.y-n.center.y});for(const t of l){const e="node_"+h++;s.set(t,e),n.set(e,t)}const u=[...Array.from(this.unravelSection.segmentPointMap.entries()).sort(([,t],[,e])=>t.x!==e.x?t.x-e.x:t.y-e.y).map(([t])=>t)].sort();for(const t of u){const e="sp_"+d++;a.set(t,e),r.set(e,t);const s=this.unravelSection.segmentPointMap.get(t).segmentId;if(!i.has(s)){const t="seg_"+c++;i.set(s,t),o.set(t,s)}}const p={};for(const[t,n]of s.entries()){const s=this.nodeMap.get(t),i=Is(e,s.center);p[n]={width:s.width,height:s.height,availableZ:s.availableZ,center:{x:Es(i.x),y:Es(i.y)}}}const f={};for(const[t,s]of a.entries()){const n=this.unravelSection.segmentPointMap.get(t),i=Is(e,{x:n.x,y:n.y});f[s]={x:Es(i.x),y:Es(i.y),z:n.z}}const m={hyperParameters:this.hyperParameters,normalizedNodes:p,normalizedSegmentPoints:f,mutableHops:this.MUTABLE_HOPS},g=`unravelsec:${Ns(m)}`,y={realToCacheTransform:e,nodeIdMap:s,segmentIdMap:i,segmentPointIdMap:a,reverseNodeIdMap:n,reverseSegmentIdMap:o,reverseSegmentPointIdMap:r};return this.cacheKey=g,this.cacheToSolveSpaceTransform=y,{cacheKey:g,cacheToSolveSpaceTransform:y}}applyCachedSolution(t){if(!1===t.success)return void(this.failed=!0);if(!this.cacheToSolveSpaceTransform)return void console.error("Cache transform not available to apply cached solution.");const{reverseSegmentPointIdMap:e,reverseNodeIdMap:s}=this.cacheToSolveSpaceTransform,n=new Map;for(const[s,i]of t.bestCandidatePointModificationsDelta){const t=e.get(s);if(!t){console.warn(`Could not find original ID for normalized SP ID: ${s} when applying cache.`);continue}const o=this.unravelSection.segmentPointMap.get(t);if(!o){console.warn(`Could not find original segment point for ID: ${t} when applying cache.`);continue}const a={};if(void 0!==i.dx){const t=parseFloat(i.dx);Number.isNaN(t)?console.warn(`Failed to parse cached dx coordinate: ${i.dx}`):a.x=o.x+t}if(void 0!==i.dy){const t=parseFloat(i.dy);Number.isNaN(t)?console.warn(`Failed to parse cached dy coordinate: ${i.dy}`):a.y=o.y+t}void 0!==i.dz&&(a.z=o.z+i.dz),Object.keys(a).length>0&&n.set(t,a)}const i=xs(this.unravelSection,this.nodeMap,n);this.bestCandidate={pointModifications:n,issues:i,f:t.bestCandidateF,g:t.bestCandidateF,h:0,operationsPerformed:-1,candidateHash:gs(n)},this.cacheHit=!0,this.solved=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(this.failed)return void this.cacheProvider?.setCachedSolutionSync(this.cacheKey,{success:!1});if(!this.bestCandidate)return;const{segmentPointIdMap:t}=this.cacheToSolveSpaceTransform,e=[];for(const[s,n]of this.bestCandidate.pointModifications.entries()){const i=t.get(s);if(!i){console.warn(`Could not find normalized ID for original SP ID: ${s} when saving to cache.`);continue}const o=this.unravelSection.segmentPointMap.get(s);if(!o){console.warn(`Could not find original segment point for ID: ${s} when saving cache.`);continue}const a={};let r=!1;if(void 0!==n.x){const t=n.x-o.x,e=As(t);0!==parseFloat(e)&&(a.dx=e,r=!0)}if(void 0!==n.y){const t=n.y-o.y,e=As(t);0!==parseFloat(e)&&(a.dy=e,r=!0)}if(void 0!==n.z){const t=n.z-o.z;0!==t&&(a.dz=t,r=!0)}r&&e.push([i,a])}const s={success:!0,bestCandidatePointModificationsDelta:e,bestCandidateF:this.bestCandidate.f};this.cacheProvider?.setCachedSolutionSync(this.cacheKey,s)}},zs=class extends e{nodeMap;dedupedSegmentMap;dedupedSegments;nodeIdToSegmentIds;segmentIdToNodeIds;nodeToSegmentPointMap;segmentToSegmentPointMap;colorMap;tunedNodeCapacityMap;MAX_NODE_ATTEMPTS=2;MUTABLE_HOPS=1;ACCEPTABLE_PF=.05;MAX_ITERATIONS_WITHOUT_IMPROVEMENT=200;nodePfMap;attemptsToFixNode;activeSubSolver=null;segmentPointMap;cacheProvider=null;constructor({assignedSegments:t,colorMap:e,nodes:s,cacheProvider:n}){super(),this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.cacheHits=0,this.stats.cacheMisses=0,this.cacheProvider=n??null,this.MAX_ITERATIONS=1e6,this.dedupedSegments=(t=>{const e=[],s=new Map;let n=-1;for(const i of t){const t=`${i.start.x}-${i.start.y}-${i.end.x}-${i.end.y}-${i.availableZ.join(",")}`,o=s.get(t);o?i.nodePortSegmentId=o.nodePortSegmentId:(n++,i.nodePortSegmentId=`SEG${n}`,s.set(t,i),e.push(i))}return e})(t),this.dedupedSegmentMap=new Map;for(const t of this.dedupedSegments)this.dedupedSegmentMap.set(t.nodePortSegmentId,t);this.nodeMap=new Map;for(const t of s)this.nodeMap.set(t.capacityMeshNodeId,t);this.nodeIdToSegmentIds=new Map,this.segmentIdToNodeIds=new Map,this.attemptsToFixNode=new Map;for(const e of t)this.segmentIdToNodeIds.set(e.nodePortSegmentId,[...this.segmentIdToNodeIds.get(e.nodePortSegmentId)??[],e.capacityMeshNodeId]),this.nodeIdToSegmentIds.set(e.capacityMeshNodeId,[...this.nodeIdToSegmentIds.get(e.capacityMeshNodeId)??[],e.nodePortSegmentId]);this.colorMap=e??{},this.tunedNodeCapacityMap=new Map;for(const[t,e]of this.nodeMap)this.tunedNodeCapacityMap.set(t,lt(e));const{segmentPointMap:i,nodeToSegmentPointMap:o,segmentToSegmentPointMap:a}=vs(this.dedupedSegments,this.segmentIdToNodeIds);this.segmentPointMap=i,this.nodeToSegmentPointMap=o,this.segmentToSegmentPointMap=a,this.nodePfMap=this.computeInitialPfMap()}computeInitialPfMap(){const t=new Map;for(const[e,s]of this.nodeMap.entries())t.set(e,this.computeNodePf(s));return t}computeNodePf(t){const{numSameLayerCrossings:e,numEntryExitLayerChanges:s,numTransitionCrossings:n}=(t=>{let e=0,s=0,n=0;const o=new Map;for(const e of t)o.has(e.connectionName)||o.set(e.connectionName,[]),o.get(e.connectionName).push(e);const a=[],r=[];for(const[t,e]of o.entries()){if(e.length<2)continue;const n=e[0];for(let i=1;i<e.length;i++){const o=e[i],h={connectionName:t,z:n.z,points:[n,o]};n.z!==o.z?(s++,r.push({connectionName:t,points:[n,o]})):a.push(h)}}for(let t=0;t<a.length;t++)for(let s=t+1;s<a.length;s++){const n=a[t],o=a[s];n.z===o.z&&i(n.points[0],n.points[1],o.points[0],o.points[1])&&e++}for(let t=0;t<r.length;t++)for(let e=t+1;e<r.length;e++){const s=r[t],o=r[e];i(s.points[0],s.points[1],o.points[0],o.points[1])&&n++}for(let t=0;t<r.length;t++)for(let e=0;e<a.length;e++){const s=r[t],o=a[e];i(s.points[0],s.points[1],o.points[0],o.points[1])&&n++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:s,numTransitionCrossings:n}})((this.nodeToSegmentPointMap.get(t.capacityMeshNodeId)??[]).map(t=>this.segmentPointMap.get(t)));return Ss(t,e,s,n)}_step(){if(this.iterations>=this.MAX_ITERATIONS-1)return void(this.solved=!0);if(!this.activeSubSolver){let t=null,e=0;for(const[s,n]of this.nodePfMap.entries()){n*(1-(this.attemptsToFixNode.get(s)??0)/this.MAX_NODE_ATTEMPTS)>e&&(e=n,t=s)}if(!t||e<this.ACCEPTABLE_PF)return void(this.solved=!0);this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.activeSubSolver=new ws({dedupedSegments:this.dedupedSegments,dedupedSegmentMap:this.dedupedSegmentMap,nodeMap:this.nodeMap,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,colorMap:this.colorMap,rootNodeId:t,MUTABLE_HOPS:this.MUTABLE_HOPS,segmentPointMap:this.segmentPointMap,nodeToSegmentPointMap:this.nodeToSegmentPointMap,segmentToSegmentPointMap:this.segmentToSegmentPointMap,cacheProvider:this.cacheProvider})}this.activeSubSolver.step();const{bestCandidate:t,originalCandidate:e,lastProcessedCandidate:s}=this.activeSubSolver;if(this.activeSubSolver.failed)return this.stats.failedOptimizations+=1,void(this.activeSubSolver=null);if(this.activeSubSolver.solved){this.activeSubSolver.cacheHit?this.stats.cacheHits+=1:this.stats.cacheMisses+=1;if(t&&t.g<e.g){this.stats.successfulOptimizations+=1;for(const[e,s]of t.pointModifications.entries()){const t=this.segmentPointMap.get(e);t.x=s.x??t.x,t.y=s.y??t.y,t.z=s.z??t.z}for(const t of this.activeSubSolver.unravelSection.allNodeIds)this.nodePfMap.set(t,this.computeNodePf(this.nodeMap.get(t)))}else this.stats.failedOptimizations+=1;this.activeSubSolver=null}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Multi Section Solver"};for(const[e,s]of this.nodeMap.entries()){const n=this.nodePfMap.get(e)||0,i=Math.min(n,1),o=`rgb(${Math.floor(255*i)}, ${Math.floor(255*(1-i))}, 0)`;0===(this.attemptsToFixNode.get(e)??0)&&0===i||t.rects.push({center:s.center,label:[e,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Pf: ${n.toFixed(3)}`].join("\n"),color:o,width:s.width/8,height:s.height/8})}for(const e of this.segmentPointMap.values()){const s=this.dedupedSegmentMap.get(e.segmentId);t.points.push({x:e.x,y:e.y,label:[e.segmentPointId,e.segmentId,`z: ${e.z}`,`segment.availableZ: ${s?.availableZ.join(",")}`].join("\n"),color:this.colorMap[e.connectionName]||"#000"})}const e=new Map;for(const t of this.segmentPointMap.values())e.has(t.segmentId)||e.set(t.segmentId,[]),e.get(t.segmentId).push(t);for(const[s,n]of e.entries()){if(n.length<2)continue;const e=[...n].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y);for(let n=0;n<e.length-1;n++)t.lines.push({points:[{x:e[n].x,y:e[n].y},{x:e[n+1].x,y:e[n+1].y}],strokeColor:this.colorMap[s]||"#000"})}const s=new Set,n=Array.from(this.segmentPointMap.values());for(let e=0;e<n.length;e++){const i=n[e];for(let o=e+1;o<n.length;o++){const e=n[o];if(i.connectionName!==e.connectionName||i.segmentId===e.segmentId)continue;if(i.capacityMeshNodeIds.some(t=>e.capacityMeshNodeIds.includes(t))){const n=`${i.segmentPointId}-${e.segmentPointId}`;if(s.has(n))continue;s.add(n);const o=i.z===e.z,a=i.z;let r;r=o?0===a?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:i.x,y:i.y},{x:e.x,y:e.y}],strokeDash:r,strokeColor:this.colorMap[i.connectionName]||"#666"})}}}return t}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.dedupedSegments){const s=e.nodePortSegmentId;for(const e of this.segmentIdToNodeIds.get(s)){const s=this.nodeMap.get(e);t.has(e)||t.set(e,{capacityMeshNodeId:e,portPoints:[],center:s.center,width:s.width,height:s.height})}}for(const e of this.segmentPointMap.values())for(const s of e.capacityMeshNodeIds){const n=t.get(s);n&&n.portPoints.push({x:e.x,y:e.y,z:e.z,connectionName:e.connectionName})}return Array.from(t.values())}},Rs=(t,e={})=>{const s=Math.min(...t.availableZ);return{center:!e.rectMargin||e.zOffset?{x:t.center.x+s*t.width*(e.zOffset??.05),y:t.center.y-s*t.width*(e.zOffset??.05)}:t.center,width:e.rectMargin?t.width-2*e.rectMargin:Math.max(t.width-.5,.8*t.width),height:e.rectMargin?t.height-2*e.rectMargin:Math.max(t.height-.5,.8*t.height),fill:t._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[t.availableZ.join(",")]??"rgba(0,200,200,0.1)",layer:`z${t.availableZ.join(",")}`,label:[t.capacityMeshNodeId,`availableZ: ${t.availableZ.join(",")}`,""+(t._containsTarget?"containsTarget":""),""+(t._containsObstacle?"containsObstacle":"")].filter(Boolean).join("\n")}},Os=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:s,colorMap:n,MAX_ITERATIONS:i=1e6,hyperParameters:o={}}){super(),this.MAX_ITERATIONS=i,this.simpleRouteJson=t,this.nodes=e,this.edges=s,this.colorMap=n??{};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=Ut(this.edges),this.maxDepthOfNodes=Math.max(...this.nodes.map(t=>t._depth??0)),this.debug_lastNodeCostMap=new Map}getTotalCapacity(t){const e=t._depth??0;return(this.maxDepthOfNodes-e+1)**2}getConnectionsWithNodes(){const t=[],e=this.nodes.filter(t=>t._containsTarget),s=new Map;for(const n of this.simpleRouteJson.connections){const i=[];for(const t of n.pointsToConnect){let s=this.nodes[0],n=Number.MAX_VALUE;for(const i of e){const e=Math.sqrt((i.center.x-t.x)**2+(i.center.y-t.y)**2);e<n&&(n=e,s=i)}i.push(s)}if(i.length<2)throw new Error(`Not enough nodes for connection "${n.name}", only ${i.length} found`);s.set(n.name,i.map(t=>t.capacityMeshNodeId)),t.push({connection:n,nodes:i,pathFound:!1,straightLineDistance:h(i[0].center,i[i.length-1].center)})}return t.sort((t,e)=>t.straightLineDistance-e.straightLineDistance),{connectionsWithNodes:t,connectionNameToGoalNodeIds:s}}currentConnectionIndex=0;candidates;visitedNodes;computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)}getBacktrackedPath(t){const e=[];let s=t;for(;s;)e.push(s.node),s=s.prevCandidate;return e}getNeighboringNodes(t){return this.nodeEdgeMap.get(t.capacityMeshNodeId).flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t))}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const s=e.path;s&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:s.map(t=>t.capacityMeshNodeId)})}return t}doesNodeHaveCapacityForTrace(t,e){const s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=this.getTotalCapacity(t);if(1===t.availableZ.length&&!t._containsTarget&&s>0)return!1;let i=0;return t.availableZ.length>1&&1===e.availableZ.length&&(i+=.5),s+i<n}canTravelThroughObstacle(t,e){const s=this.connectionNameToGoalNodeIds.get(e);return s?.includes(t.capacityMeshNodeId)??!1}getDistanceBetweenNodes(t,e){return Math.sqrt((t.center.x-e.center.x)**2+(t.center.y-e.center.y)**2)}reduceCapacityAlongPath(t){for(const e of t.path??[])this.usedNodeCapacityMap.set(e.capacityMeshNodeId,this.usedNodeCapacityMap.get(e.capacityMeshNodeId)+1)}isConnectedToEndGoal(t,e){return this.nodeEdgeMap.get(t.capacityMeshNodeId).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}_step(){const t=this.connectionsWithNodes[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const[e,s]=t.nodes;this.candidates||(this.candidates=[{prevCandidate:null,node:e,f:0,g:0,h:0}],this.debug_lastNodeCostMap=new Map,this.visitedNodes=new Set([e.capacityMeshNodeId]),this.activeCandidateStraightLineDistance=h(e.center,s.center)),this.candidates.sort((t,e)=>t.f-e.f);const n=this.candidates.shift();if(this.candidates.length>this.MAX_CANDIDATES_IN_MEMORY&&this.candidates.splice(this.MAX_CANDIDATES_IN_MEMORY,this.candidates.length-this.MAX_CANDIDATES_IN_MEMORY),!n)return console.error(`Ran out of candidates on connection ${t.connection.name}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,void(this.failed=!0);if(this.isConnectedToEndGoal(n.node,s))return t.path=this.getBacktrackedPath({prevCandidate:n,node:s,f:0,g:0,h:0}),this.reduceCapacityAlongPath(t),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);const i=this.getNeighboringNodes(n.node);for(const t of i){if(this.visitedNodes?.has(t.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(t,n.node))continue;const e=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;if(t._containsObstacle&&!this.canTravelThroughObstacle(t,e))continue;const i=this.computeG(n,t,s),o=this.computeH(n,t,s),a=i+o*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:a,g:i,h:o});const r={prevCandidate:n,node:t,f:a,g:i,h:o};this.candidates.push(r)}this.visitedNodes.add(n.node.capacityMeshNodeId)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(this.connectionsWithNodes)for(let e=0;e<this.connectionsWithNodes.length;e++){const s=this.connectionsWithNodes[e];if(s.path&&s.path.length>0){const n=s.path.map(({center:{x:t,y:s},width:n,availableZ:i})=>({x:t+.005*n*(e%10+e%19),y:s+.005*n*(e%10+e%19),availableZ:i}));t.lines.push({points:n,strokeColor:this.colorMap[s.connection.name]});for(let e=0;e<n.length;e++){const i=n[e];t.points.push({x:i.x,y:i.y,label:[`conn: ${s.connection.name}`,`node: ${s.path[e].capacityMeshNodeId}`,`z: ${i.availableZ.join(",")}`].join("\n")})}}}for(const e of this.nodes){const s=this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,n=this.getTotalCapacity(e),i=this.debug_lastNodeCostMap.get(e.capacityMeshNodeId);t.rects.push({...Rs(e,{rectMargin:.025,zOffset:.01}),label:[`${e.capacityMeshNodeId}`,`${s}/${n}`,`${e.width.toFixed(2)}x${e.height.toFixed(2)}`,`g: ${void 0!==i?.g?i.g.toFixed(2):"?"}`,`h: ${void 0!==i?.h?i.h.toFixed(2):"?"}`,`f: ${void 0!==i?.f?i.f.toFixed(2):"?"}`,`z: ${e.availableZ.join(", ")}`].join("\n"),stroke:s>n+.5?"red":void 0})}if(this.connectionsWithNodes)for(const e of this.connectionsWithNodes)if(e.connection?.pointsToConnect)for(const s of e.connection.pointsToConnect)t.points.push({x:s.x,y:s.y,label:[`pointsToConnect ${e.connection.name}`].join("\n")});let e=this.connectionsWithNodes[this.currentConnectionIndex];if(!this.candidates&&this.currentConnectionIndex>0&&!this.connectionsWithNodes[this.currentConnectionIndex-1].path&&(e=this.connectionsWithNodes[this.currentConnectionIndex-1]),e){const[s,n]=e.connection.pointsToConnect;t.lines.push({points:[{x:s.x,y:s.y},{x:n.x,y:n.y}],strokeColor:"red",strokeDash:"10 5"})}if(this.candidates){const e=this.candidates.slice(0,5),s=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;e.forEach((e,n)=>{const i=.5*(1-n/5),o=this.getBacktrackedPath(e);t.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:ct(this.colorMap[s]??"red",1-i)})})}return t}},Ls=class extends Os{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 lt(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){const e=t.width+t.height,s=.05,n=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0);if(n>2)return s;return(e-s)*Math.max(1,(2-n)/(e-s))+s}getDistanceBetweenNodes(t,e){const s=t.center.x-e.center.x,n=t.center.y-e.center.y;return Math.sqrt(s**2+n**2)}computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)+this.getNodeCapacityPenalty(e)}},Ds=class extends Ls{doesNodeHaveCapacityForTrace(t,e){return!0}getNodeCapacityPenalty(t){const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let s=1;return 1===t.availableZ.length&&(s=10),(.05+2*Math.abs(e))*s}};function $s(t,e,s){const n=e.x-t.x,i=e.y-t.y;if(Math.abs(n)<1e-9&&Math.abs(i)<1e-9)return t;const o=s.width/2,a=s.height/2,r=s.center.x-o,h=s.center.x+o,c=s.center.y-a,d=s.center.y+a;let l=0,u=1/0;if(Math.abs(n)>1e-9){const e=(r-t.x)/n,s=(h-t.x)/n;l=Math.max(l,Math.min(e,s)),u=Math.min(u,Math.max(e,s))}else if(t.x<r||t.x>h)return t;if(Math.abs(i)>1e-9){const e=(c-t.y)/i,s=(d-t.y)/i;l=Math.max(l,Math.min(e,s)),u=Math.min(u,Math.max(e,s))}else if(t.y<c||t.y>d)return t;if(u<l||l===1/0||l<-1e9)return t;return{x:t.x+n*l,y:t.y+i*l}}function Ys(t,e){const s=t.center,n=e.center,i=$s(s,n,t),o=$s(n,s,e),a=n.x-s.x,r=n.y-s.y,h=Math.sqrt(a*a+r*r);let c=i,d=o;if(h>1e-9){const s={x:a/h,y:r/h},n=.3*t.width,l=.3*e.width;n+l<Math.sqrt((o.x-i.x)**2+(o.y-i.y)**2)?(c={x:i.x+s.x*n,y:i.y+s.y*n},d={x:o.x-s.x*l,y:o.y-s.y*l}):(c=i,d=o)}return{lineStart:c,lineEnd:d}}var Xs=(t,e,s)=>{if(t<e)return 0;if(e<1&&t<=1)return 0;if(1===s&&t>1)return 1-.01**t;const n=t/e-1;return 1-Math.exp(-2*n)},ks=(t,e,s)=>{if(s._containsTarget)return 0;if(t<=e)return 0;const n=1-Xs(t,e,s.availableZ.length);return n<=0?-1e9:Math.log(n)},Bs=({totalNodeCapacityMap:t,usedNodeCapacityMap:e,nodeMap:s,sectionNodeIds:n})=>{let i=0;const o=n??new Set(e.keys());for(const n of o){if(!t.has(n))continue;const o=s.get(n);if(!o)continue;const a=t.get(n),r=e.get(n)??0;i+=ks(r,a,o)}return i};function Fs({sectionNodes:t,sectionEdges:e,sectionConnectionTerminals:s,completedPaths:n,nodeMap:i,colorMap:o,centerNodeId:a,title:r,nodeOpacity:h=.1,usedNodeCapacityMap:c,totalCapacityMap:d}){const l={points:[],lines:[],rects:[],circles:[],title:r},u=new Set(t.map(t=>t.capacityMeshNodeId));for(const e of t){let t=`rgba(128, 128, 128, ${h})`,s=`rgba(128, 128, 128, ${h})`;const n=e.availableZ??[],i=n.includes(0),o=n.includes(1);i&&o?(t=`rgba(128, 0, 128, ${h})`,s=`rgba(128, 0, 128, ${h})`):i?(t=`rgba(0, 0, 255, ${h})`,s=`rgba(0, 0, 255, ${h})`):o&&(t=`rgba(255, 0, 0, ${h})`,s=`rgba(255, 0, 0, ${h})`),a&&e.capacityMeshNodeId===a&&(t=`rgba(0, 255, 0, ${h})`,s=`rgba(0, 128, 0, ${h})`),l.rects.push({...Rs(e),fill:t,stroke:s,label:`${e.capacityMeshNodeId}\n(Section Node)\nZ: ${n.join(",")}`});const r=l.rects.length-1;if(c&&d){const t=c.get(e.capacityMeshNodeId)??0,s=d.get(e.capacityMeshNodeId)??0,n=s>0?(t/s*100).toFixed(1):"N/A",i=Xs(t,s,e.availableZ.length);l.rects[r].label+=`\n${t.toFixed(1)} / ${s.toFixed(1)}\n${n}% (Pf: ${(100*i).toFixed(1)}%)`,i>.2&&(l.rects[r].stroke=ct("red",.7*(.8+h)))}}for(const t of e){const[e,s]=t.nodeIds,n=i.get(e),o=i.get(s);if(n&&o){const{lineStart:t,lineEnd:e}=Ys(n,o);l.lines.push({points:[t,e],strokeColor:`rgba(0, 0, 0, ${.2*Math.min(1,h/.1)})`})}}return s.forEach((t,e)=>{const s=i.get(t.startNodeId),n=i.get(t.endNodeId),a=o[t.connectionName]??"black",r=s&&u.has(s.capacityMeshNodeId),h=n&&u.has(n.capacityMeshNodeId),c=(e+e/50)%5;let d=0,p=0,f=0,m=0;if(r&&s){const e=.02*Math.min(s.width,s.height);d=e*c,p=e*c,l.points.push({x:s.center.x+d,y:s.center.y+p,color:a,label:`Start: ${t.connectionName}\n(${t.startNodeId})`}),l.lines.push({points:[{x:s.center.x,y:s.center.y},{x:s.center.x+d,y:s.center.y+p}],strokeColor:"gray",strokeDash:"2 2"})}if(h&&n){const e=.02*Math.min(n.width,n.height);f=e*c,m=e*c,l.points.push({x:n.center.x+f,y:n.center.y+m,color:a,label:`End: ${t.connectionName}\n(${t.endNodeId})`}),l.lines.push({points:[{x:n.center.x,y:n.center.y},{x:n.center.x+f,y:n.center.y+m}],strokeColor:"gray",strokeDash:"2 2"})}r&&h&&s&&n&&l.lines.push({points:[{x:s.center.x+d,y:s.center.y+p},{x:n.center.x+f,y:n.center.y+m}],strokeColor:a,strokeDash:"5 5"})}),n&&n.forEach((t,e)=>{if(t.path&&t.path.length>0){const s=o[t.connectionName]??"gray",n={x:(e+e/50)%5*.03,y:(e+e/50)%5*.03};l.lines.push({points:t.path.map(({center:{x:t,y:e}})=>({x:t+n.x,y:e+n.y})),strokeColor:ct(s,.2)})}}),l}var Hs=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??Ut(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=Bs({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:e}),t.hyperParameters?.SHUFFLE_SEED&&(this.sectionConnectionTerminals=ue(this.sectionConnectionTerminals,t.hyperParameters?.SHUFFLE_SEED))}getTotalCapacity(t){return lt(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){if(!this.nodeMap.has(t.capacityMeshNodeId))return 1/0;const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let s=1;return 1===t.availableZ.length&&(s=10),(.05+e**2*4)*s}getDistanceBetweenNodes(t,e){const s=t.center.x-e.center.x,n=t.center.y-e.center.y;return Math.sqrt(s**2+n**2)}computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)+this.getNodeCapacityPenalty(e)}getBacktrackedPath(t){const e=[];let s=t;for(;s;){if(e.push(s.node),!this.nodeMap.has(s.node.capacityMeshNodeId)){console.warn("Backtracked path went outside section bounds");break}s=s.prevCandidate}return e.reverse()}getNeighboringNodes(t){return this.nodeMap.has(t.capacityMeshNodeId)?this.nodeEdgeMap.get(t.capacityMeshNodeId)?.flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t)).filter(Boolean)??[]:[]}isConnectedToEndGoal(t,e){return!(!this.nodeMap.has(t.capacityMeshNodeId)||!this.nodeMap.has(e.capacityMeshNodeId))&&(this.nodeEdgeMap.get(t.capacityMeshNodeId)??[]).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}doesNodeHaveCapacityForTrace(t,e){return!0}reduceCapacityAlongPath(t){for(const e of t)if(this.usedNodeCapacityMap.has(e.capacityMeshNodeId)){const t=e.capacityMeshNodeId,s=this.nodeMap.get(t);if(!s){console.warn(`Node ${t} from path not found in section's nodeMap during score update.`);continue}const n=this.totalNodeCapacityMap.get(t),i=this.usedNodeCapacityMap.get(t)??0,o=ks(i,n,s);this.currentSectionScore-=o;const a=i+1;this.usedNodeCapacityMap.set(t,a);const r=ks(a,n,s);this.currentSectionScore+=r}}getSolvedSectionScore(){return this.currentSectionScore}_step(){const t=this.sectionConnectionTerminals[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const e=this.nodeMap.get(t.startNodeId),s=this.nodeMap.get(t.endNodeId);if(!e||!s)return console.error(`Start or end node not found in section for connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);this.candidates||this._setupAStar(e,s);const n=this.candidates;if(0===n.length)return void this._handleCandidatesExhausted(t);n.sort((t,e)=>t.f-e.f);const i=n.shift();if(n.length>this.MAX_CANDIDATES_IN_MEMORY&&n.splice(this.MAX_CANDIDATES_IN_MEMORY,n.length-this.MAX_CANDIDATES_IN_MEMORY),this.visitedNodes.add(i.node.capacityMeshNodeId),i.node.capacityMeshNodeId===s.capacityMeshNodeId)return void this._handleGoalReached(i,t,s);const o=this.getNeighboringNodes(i.node);for(const e of o){if(this.queuedNodes?.has(e.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(e,i.node))continue;if(e._containsObstacle){const s=e.capacityMeshNodeId===t.startNodeId,n=e.capacityMeshNodeId===t.endNodeId;if(!s&&!n)continue}const o=this.computeG(i,e,s),a=this.computeH(i,e,s),r=o+a*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(e.capacityMeshNodeId,{f:r,g:o,h:a});const h={prevCandidate:i,node:e,f:r,g:o,h:a};this.queuedNodes?.add(e.capacityMeshNodeId),n.push(h)}}computeProgress(){const t=this.sectionConnectionTerminals.length;if(0===t)return 1;let e=this.currentConnectionIndex/t;if(this.currentConnectionIndex<t&&this.candidates&&this.candidates.length>0&&this.activeCandidateStraightLineDistance&&this.activeCandidateStraightLineDistance>0){const s=this.candidates.reduce((t,e)=>e.f<t.f?e:t);e+=Math.max(0,Math.min(1,1-s.h/this.activeCandidateStraightLineDistance))/t}else this.solved&&(e=1);return Math.min(1,e)}_setupAStar(t,e){this.candidates=[{prevCandidate:null,node:t,f:0,g:0,h:0}],this.visitedNodes=new Set([t.capacityMeshNodeId]),this.debug_lastNodeCostMap=new Map,this.activeCandidateStraightLineDistance=h(t.center,e.center);const s=this.computeH(null,t,e);this.candidates[0].h=s,this.candidates[0].f=s*this.GREEDY_MULTIPLIER,this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:this.candidates[0].f,g:0,h:s}),this.queuedNodes=new Set([t.capacityMeshNodeId])}_handleCandidatesExhausted(t){console.error(`Ran out of candidates for section connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}_handleGoalReached(t,e,s){const n=this.getBacktrackedPath(t);e.path=n,this.reduceCapacityAlongPath(n),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}visualize(){const t=this.sectionConnectionTerminals.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connectionName,path:t.path})),e=Fs({sectionNodes:this.sectionNodes,sectionEdges:this.sectionEdges,sectionConnectionTerminals:this.sectionConnectionTerminals,completedPaths:t,nodeMap:this.nodeMap,colorMap:this.colorMap,centerNodeId:null,title:`Section Pathing: Conn ${this.currentConnectionIndex+1}/${this.sectionConnectionTerminals.length} (${this.sectionNodes.length} nodes)`,nodeOpacity:.1});for(const t of this.sectionNodes){const s=e.rects.findIndex(e=>e.label?.includes(t.capacityMeshNodeId));if(-1!==s){const n=this.debug_lastNodeCostMap.get(t.capacityMeshNodeId),i=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,o=this.getTotalCapacity(t),a=`${i.toFixed(1)}/${o.toFixed(1)}`,r=n?`f:${n.f.toFixed(1)} g:${n.g.toFixed(1)} h:${n.h.toFixed(1)}`:"cost:?";e.rects[s].label=[t.capacityMeshNodeId,`Cap: ${a}`,r,`Z: ${t.availableZ.join(",")}`].join("\n"),i>o&&(e.rects[s].stroke=ct("red",.7))}}if(this.candidates&&this.candidates.length>0){const t=this.candidates.slice().sort((t,e)=>t.f-e.f).slice(0,5),s=this.sectionConnectionTerminals[this.currentConnectionIndex],n=s?.connectionName??"unknown",i=this.colorMap[n]??"purple";t.forEach((t,s)=>{const n=.8*(1-s/5),o=this.getBacktrackedPath(t);o.length>0&&e.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:ct(i,1-n),strokeWidth:.05})})}return e}},Zs=t=>Array.from({length:t},(t,e)=>e),Us=class extends xe{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:Zs(2).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings6_for3",possibleValues:Zs(6).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings24_for4",possibleValues:Zs(24).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings30",possibleValues:Zs(30).map(t=>({SHUFFLE_SEED:t}))}]}generateSolver(t){return new Hs({...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 Vs from"object-hash";var js=t=>Math.floor(10*t)/10,Ws=class extends Us{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?ne():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}_computeBfsOrderingOfNodesInSection(){const t=new Set(this.constructorParams.centerNodeId),e=[],s=[{ancestorCapacitySum:0,capacity:0,g:0,capacityMeshNodeId:this.constructorParams.centerNodeId}];for(;s.length>0;){s.sort((t,e)=>e.g-t.g);const n=s.pop();if(!n)break;e.push(n.capacityMeshNodeId);const i=this.constructorParams.nodeEdgeMap.get(n.capacityMeshNodeId).flatMap(t=>t.nodeIds).filter(e=>!t.has(e)).filter(t=>this.sectionNodeIdSet.has(t));for(const e of i){t.add(e);const i=this.constructorParams.nodeMap.get(e),o=lt(i);s.push({ancestorCapacitySum:n.g,capacity:o,g:n.g+o,capacityMeshNodeId:e})}}return e}computeCacheKeyAndTransform(){const t=this._computeBfsOrderingOfNodesInSection(),e=new Map,s=new Map;t.forEach((t,n)=>{const i=`node${n}`;e.set(t,i),s.set(i,t)});const n={};for(const s of t){const t=e.get(s),i=this.constructorParams.nodeMap.get(s),o=lt(i);n[t]=js(o).toFixed(1)}const i=new Set,o=[];for(const s of t){const t=e.get(s),n=this.constructorParams.nodeEdgeMap.get(s)??[];for(const a of n){const n=a.nodeIds.find(t=>t!==s);if(this.sectionNodeIdSet.has(n)){const s=[t,e.get(n)].sort(),a=`${s[0]}-${s[1]}`;i.has(a)||(o.push(s),i.add(a))}}}o.sort((t,e)=>t[0]!==e[0]?t[0].localeCompare(e[0]):t[1].localeCompare(e[1]));const a={},r=new Map,h=new Map;for(const t of this.constructorParams.sectionConnectionTerminals){const s=e.get(t.startNodeId),n=e.get(t.endNodeId),[i,o]=[s,n].sort(),c=`${i}->${o}`,d=h.get(c)??0;h.set(c,d+1);const l=`${i}->${o}::${d}`;a[l]={start:i,end:o},r.set(l,t.connectionName)}const c=`capacitypathing:${Vs({node_capacity_map:n,node_edge_map:o,terminals:a})}`,d={cacheSpaceToRealConnectionId:r,cacheSpaceToRealNodeId:s};return this.cacheKey=c,this.cacheToSolveSpaceTransform=d,{cacheKey:c,cacheToSolveSpaceTransform:d}}applyCachedSolution(t){if(!this.cacheToSolveSpaceTransform)return console.error("Cache transform not available, cannot apply cached solution."),void(this.failed=!0);if(!t.success)return this.failed=!0,void(this.cacheHit=!0);this.cachedSectionConnectionTerminals=[];const{cacheSpaceToRealNodeId:e,cacheSpaceToRealConnectionId:s}=this.cacheToSolveSpaceTransform;for(const[n,i]of Object.entries(t.solutionPaths)){const t=s.get(n);if(!t){console.warn(`Could not find real connection name for ${n}`);continue}const o=this.constructorParams.sectionConnectionTerminals.find(e=>e.connectionName===t);if(!o){console.warn(`Could not find original terminal for connection name ${t}`);continue}const a=i.map(s=>{const n=e.get(s);if(!n)throw new Error(`Could not map cache node ID ${s} to real node ID for connection ${t}`);const i=this.constructorParams.nodeMap.get(n);if(!i)throw new Error(`Could not find node with ID ${n} in nodeMap for connection ${t}`);return i});this.cachedSectionConnectionTerminals.push({...o,path:a})}this.sectionScore=t.sectionScore,this.solved=!0,this.cacheHit=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(!this.cacheKey)return void console.error("Cannot save to cache without cache key.");if(!this.cacheToSolveSpaceTransform)return void console.error("Cache transform not available, cannot save solution to cache.");let t;if(this.failed)t={success:!1};else{if(!this.solved)return;{const e={},{cacheSpaceToRealNodeId:s,cacheSpaceToRealConnectionId:n}=this.cacheToSolveSpaceTransform,i=new Map;for(const[t,e]of s)i.set(e,t);const o=new Map;for(const[t,e]of n)o.set(e,t);const a=[];if(super.sectionConnectionTerminals)for(const t of super.sectionConnectionTerminals)if(t.path&&t.path.length>0){const e=t.path.map(t=>t.capacityMeshNodeId);a.push([t.connectionName,e])}for(const[t,s]of a){const n=o.get(t);if(!n){console.warn(`Could not find cache space connection ID for ${t} when saving to cache.`);continue}const a=s.map(e=>{const s=i.get(e);if(!s)throw new Error(`Could not map real node ID ${e} to cache node ID for connection ${t} when saving to cache.`);return s});e[n]=a}t={success:!0,sectionScore:this.sectionScore,solutionPaths:e}}}try{this.cacheProvider?.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}get sectionConnectionTerminals(){return this.cacheHit&&this.solved&&this.cachedSectionConnectionTerminals?(console.log("returning the cached section connection terminals"),this.cachedSectionConnectionTerminals):super.sectionConnectionTerminals}visualize(){if(!this.cacheHit)return super.visualize();return Fs({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"})}},Gs=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=Ut(this.edges),this.colorMap=t.colorMap??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ut(this.edges),this.initialSolver=t.initialPathingSolver||new Ds({simpleRouteJson:this.simpleRouteJson,nodes:this.nodes,edges:this.edges,colorMap:this.colorMap}),this.activeSubSolver=this.initialSolver;for(const t of this.nodes){const e=this.initialSolver.getTotalCapacity(t);this.totalNodeCapacityMap.set(t.capacityMeshNodeId,e)}this.allNodeIdsSet=new Set(this.nodes.map(t=>t.capacityMeshNodeId))}_stepInitialization(){if(this.initialSolver?.step(),this.initialSolver?.failed)return this.failed=!0,void(this.error=this.initialSolver.error);if(this.initialSolver?.solved){this.usedNodeCapacityMap=new Map(this.initialSolver.usedNodeCapacityMap);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=e>0?s/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,n),this.nodeOptimizationAttemptCountMap.set(t.capacityMeshNodeId,0)}this.connectionsWithNodes=this.initialSolver.connectionsWithNodes,this.stats.startingScore=Bs({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet}),this.stage="section-optimization"}}_getNextNodeToOptimize(){let t=0,e=0,s=null;for(const n of this.nodes){if(n._containsTarget)continue;const i=this.nodeOptimizationAttemptCountMap.get(n.capacityMeshNodeId),o=this.totalNodeCapacityMap.get(n.capacityMeshNodeId),a=Xs(this.usedNodeCapacityMap.get(n.capacityMeshNodeId)??0,o,n.availableZ.length),r=a/(i+1);i<this.currentSchedule.MAX_ATTEMPTS_PER_NODE&&r>t&&a>this.currentSchedule.MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE&&(t=r,e=a,s=n.capacityMeshNodeId)}return s}getOverallScore(){let t=0;for(const e of this.nodes){if(e._containsTarget)continue;const s=this.totalNodeCapacityMap.get(e.capacityMeshNodeId),n=Xs(this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,s,e.availableZ.length);n>t&&(t=n)}return{highestNodePf:t,score:Bs({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet})}}_stepSectionOptimization(){if(!this.sectionSolver){const t=this._getNextNodeToOptimize();if(!t){const{highestNodePf:t,score:e}=this.getOverallScore();return this.stats.scheduleScores[this.currentScheduleIndex].endingHighestNodePf=t,this.stats.scheduleScores[this.currentScheduleIndex].endingScore=e,this.currentScheduleIndex++,void(this.currentSchedule||(this.solved=!0))}const e=(t=>{const{centerNodeId:e,connectionsWithNodes:s,nodeMap:n,edges:i,nodeEdgeMap:o,expansionDegrees:a}=t,r=new Set,h=[{nodeId:e,depth:0}];r.add(e);let c=0;for(;c<h.length;){const{nodeId:t,depth:e}=h[c++];if(e>=a)continue;const s=o.get(t)?.flatMap(e=>e.nodeIds.filter(e=>e!==t))??[];for(const t of s)r.has(t)||(r.add(t),h.push({nodeId:t,depth:e+1}))}const d=Array.from(r).map(t=>n.get(t)),l=i.filter(t=>{const[e,s]=t.nodeIds;return r.has(e)&&r.has(s)}),u=[];for(const t of s){if(!t.path)continue;let e=null,s=null;for(const s of t.path)if(r.has(s.capacityMeshNodeId)){e=s.capacityMeshNodeId;break}for(let e=t.path.length-1;e>=0;e--){const n=t.path[e];if(r.has(n.capacityMeshNodeId)){s=n.capacityMeshNodeId;break}}e&&s&&u.push({connectionName:t.connection.name,startNodeId:e,endNodeId:s})}return{sectionConnectionTerminals:u,sectionNodes:d,sectionEdges:l,centerNodeId:e}})({centerNodeId:t,connectionsWithNodes:this.connectionsWithNodes,nodeMap:this.nodeMap,edges:this.edges,expansionDegrees:this.currentSchedule.MAX_EXPANSION_DEGREES,nodeEdgeMap:this.nodeEdgeMap});this.stats.scheduleScores[this.currentScheduleIndex].sectionAttempts++,this.currentSection=e,this.sectionSolver=new Ws({sectionNodes:this.currentSection.sectionNodes,sectionEdges:this.currentSection.sectionEdges,sectionConnectionTerminals:this.currentSection.sectionConnectionTerminals,colorMap:this.colorMap,centerNodeId:this.currentSection.centerNodeId,nodeEdgeMap:this.nodeEdgeMap,hyperParameters:{EXPANSION_DEGREES:this.currentSchedule.MAX_EXPANSION_DEGREES},cacheProvider:this.cacheProvider}),this.activeSubSolver=this.sectionSolver,this.nodeOptimizationAttemptCountMap.set(t,(this.nodeOptimizationAttemptCountMap.get(t)??0)+1)}if(this.sectionSolver.step(),(this.sectionSolver.failed||this.sectionSolver.solved)&&(this.sectionSolver.cacheHit?this.stats.cacheHits++:this.stats.cacheMisses++),this.sectionSolver.failed)return console.warn(`Section solver failed for node ${this.currentSection.centerNodeId}. Error: ${this.sectionSolver.error}`),this.stats.failedSectionSolvers++,this.stats.failedOptimizations++,this.sectionSolver=null,void(this.activeSubSolver=null);if(this.sectionSolver.solved){const t=this.sectionSolver.sectionConnectionTerminals,e=this.sectionSolver.sectionNodes,s=this.sectionSolver.centerNodeId;if(this.sectionSolver=null,this.activeSubSolver=null,!t)return void console.warn(`Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`);const n=new Set(e.map(t=>t.capacityMeshNodeId)),i=Bs({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:n}),o=new Map(this.usedNodeCapacityMap),a=t;for(const t of a){const e=this.connectionsWithNodes.find(e=>e.connection.name===t.connectionName);if(e?.path)for(const t of e.path)if(n.has(t.capacityMeshNodeId)){const e=o.get(t.capacityMeshNodeId)??0;o.set(t.capacityMeshNodeId,Math.max(0,e-1))}}for(const t of a)if(t.path)for(const e of t.path)n.has(e.capacityMeshNodeId)&&o.set(e.capacityMeshNodeId,(o.get(e.capacityMeshNodeId)??0)+1);Bs({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:o,nodeMap:this.nodeMap,sectionNodeIds:n})>i?(this.stats.successfulOptimizations++,this._mergeSolvedSectionPaths({centerNodeId:s,sectionConnectionTerminals:t}),this._recalculateNodeCapacityUsage()):this.stats.failedOptimizations++}}_mergeSolvedSectionPaths({centerNodeId:t,sectionConnectionTerminals:e}){for(const s of e){if(!s.path){console.warn(`No path found for connection ${s.connectionName} in section ${t}`);continue}const e=this.connectionsWithNodes.find(t=>t.connection.name===s.connectionName);if(!e||!e.path){console.warn(`Original connection or path not found for ${s.connectionName} while merging section ${t}`);continue}const n=e.path,i=s.path,o=n.findIndex(t=>t.capacityMeshNodeId===s.startNodeId),a=n.findIndex(t=>t.capacityMeshNodeId===s.endNodeId);if(-1===o||-1===a){console.warn(`Could not find start/end nodes (${s.startNodeId}/${s.endNodeId}) in original path for ${s.connectionName}`);continue}const[r,h]=o<=a?[o,a]:[a,o],c=n.slice(0,r),d=n.slice(h+1);let l=i;if(i.length>0&&n[r]&&i[0].capacityMeshNodeId!==n[r].capacityMeshNodeId){if(i[i.length-1].capacityMeshNodeId!==n[r].capacityMeshNodeId){console.warn(`New section path for ${s.connectionName} doesn't align with original path boundaries. Skipping merge for this connection.`);continue}l=[...i].reverse()}e.path=[...c,...l,...d]}}_recalculateNodeCapacityUsage(){this.usedNodeCapacityMap.clear();for(const t of this.connectionsWithNodes)if(t.path)for(const e of t.path)this.usedNodeCapacityMap.set(e.capacityMeshNodeId,(this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0)+1);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=e>0?s/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,n)}}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const s=e.path;s&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:s.map(t=>t.capacityMeshNodeId)})}return t}_step(){this.iterations>=this.MAX_ITERATIONS-1?this.solved=!0:"initialization"===this.stage?this._stepInitialization():"section-optimization"===this.stage&&this._stepSectionOptimization()}visualize(){const t=this.connectionsWithNodes.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connection.name,path:t.path}));return Fs({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)"})}},qs=class extends e{multiLayerNodes;strawNodes;skippedNodes;unprocessedNodes;strawSize;nodeIdCounter;constructor(t){super(),this.MAX_ITERATIONS=1e5,this.strawSize=t.strawSize??.5,this.multiLayerNodes=[],this.strawNodes=[],this.skippedNodes=[],this.nodeIdCounter=0,this.unprocessedNodes=[];for(const e of t.nodes)1===e.availableZ.length?this.unprocessedNodes.push(e):this.multiLayerNodes.push(e)}getCapacityOfMultiLayerNodesWithinBounds(t){let e=0;for(const s of this.multiLayerNodes){const n=s.center.x-s.width/2,i=s.center.x+s.width/2,o=s.center.y-s.height/2,a=s.center.y+s.height/2,r=Math.max(t.minX,n),h=Math.min(t.maxX,i),c=Math.max(t.minY,o),d=Math.min(t.maxY,a);if(r<h&&c<d){const t=(h-r)*(d-c)/(s.width*s.height);e+=lt(s)*t}}return e}getSurroundingCapacities(t){const e=Math.min(t.width,t.height);return{leftSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2-e,maxX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),rightSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x+t.width/2,maxX:t.center.x+t.width/2+e,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),topSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2-e,maxY:t.center.y-t.height/2}),bottomSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y+t.height/2,maxY:t.center.y+t.height/2+e})}}createStrawsForNode(t){const e=[],{leftSurroundingCapacity:s,rightSurroundingCapacity:n,topSurroundingCapacity:i,bottomSurroundingCapacity:o}=this.getSurroundingCapacities(t);if(1*(s+n)>i+o){const s=Math.floor(t.height/this.strawSize),n=t.height/s;for(let i=0;i<s;i++){const s=t.center.y-t.height/2+i*n+n/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:t.center.x,y:s},width:t.width,height:n,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}else{const s=Math.floor(t.width/this.strawSize),n=t.width/s;for(let i=0;i<s;i++){const s=t.center.x-t.width/2+i*n+n/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:s,y:t.center.y},width:n,height:t.height,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}return e}getResultNodes(){return[...this.multiLayerNodes,...this.strawNodes,...this.skippedNodes]}_step(){const t=this.unprocessedNodes.pop();if(!t)return void(this.solved=!0);if(t.width<this.strawSize&&t.height<this.strawSize)return void this.skippedNodes.push(t);if(t._containsTarget)return void this.skippedNodes.push(t);const e=this.createStrawsForNode(t);this.strawNodes.push(...e)}visualize(){const t={rects:[],lines:[],points:[],circles:[],title:"Straw Solver"};for(const e of this.unprocessedNodes)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(200, 200, 200, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nUnprocessed\n${e.width}x${e.height}`});for(const e of this.strawNodes){const s=0===e.availableZ[0]?"rgba(0, 150, 255, 0.5)":"rgba(255, 100, 0, 0.5)";t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nLayer: ${e.availableZ[0]}\n${e.width}x${e.height}`,layer:`z${e.availableZ.join(",")}`})}for(const e of this.multiLayerNodes)t.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,fill:"rgba(100, 255, 100, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",layer:`z${e.availableZ.join(",")}`,label:`${e.capacityMeshNodeId}\nLayers: ${e.availableZ.join(",")}\n${e.width}x${e.height}`});return t}};function Ks(t,e){const s=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2,a=e.center.x-e.width/2,r=e.center.x+e.width/2,h=e.center.y-e.height/2,c=e.center.y+e.height/2,d=.001,l=(Math.abs(n-a)<d||Math.abs(s-r)<d)&&Math.min(o,c)-Math.max(i,h)>=d,u=(Math.abs(o-h)<d||Math.abs(i-c)<d)&&Math.min(n,r)-Math.max(s,a)>=d;return l||u}var Js=class{constructor(t){this.nodes=t,this.buckets=new Map;for(const e of t){const t=e.center.x-e.width/2,s=e.center.y-e.height/2,n=e.center.x+e.width/2,i=e.center.y+e.height/2;for(let o=t;o<=n;o+=this.CELL_SIZE)for(let t=s;t<=i;t+=this.CELL_SIZE){const s=this.getBucketKey(o,t),n=this.buckets.get(s);n?n.push(e):this.buckets.set(s,[e])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,s,n){const i=[],o=new Set,a=e-n/2,r=t+s/2,h=e+n/2;for(let e=t-s/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const s=this.getBucketKey(e,t),n=this.buckets.get(s)||[];for(const t of n)o.has(t.capacityMeshNodeId)||(o.add(t.capacityMeshNodeId),i.push(t))}return i}},Qs=.005,tn=class extends e{nodeMap;currentBatchNodeIds;absorbedNodeIds;nextBatchNodeIds;batchHadModifications;hasComputedAdjacentNodeIds=!1;newNodes;constructor(t){super(),this.nodeMap=new Map,this.MAX_ITERATIONS=1e5;for(const e of t)this.nodeMap.set(e.capacityMeshNodeId,e);this.newNodes=[],this.absorbedNodeIds=new Set;const e=[];for(const s of t)s.availableZ.length>1?(this.newNodes.push(s),this.absorbedNodeIds.add(s.capacityMeshNodeId)):e.push([s,s.width*s.height]);e.sort((t,e)=>t[1]-e[1]);for(const[t,s]of e){const e={...t,center:{...t.center}};this.nodeMap.set(t.capacityMeshNodeId,e)}this.currentBatchNodeIds=e.map(([t])=>t.capacityMeshNodeId),this.nextBatchNodeIds=[],this.batchHadModifications=!1}computeAdjacentNodeIdsForFirstBatch(t){const e=Math.max(...t.map(t=>Math.max(...t.availableZ))),s=[];for(let n=0;n<=e;n++)s.push(new Js(t.filter(t=>t.availableZ[0]===n)));for(const e of t){const t=[],n=s[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const s of n)s._containsTarget&&s._targetConnectionName!==e._targetConnectionName||s.capacityMeshNodeId!==e.capacityMeshNodeId&&Ks(e,s)&&t.push(s);e._adjacentNodeIds=t.map(t=>t.capacityMeshNodeId)}}getAdjacentSameLayerUnprocessedNodes(t){return this.getAdjacentSameLayerUnprocessedNodes2(t)}getAdjacentSameLayerUnprocessedNodes2(t){const e=[],s=Array.from(new Set((t._adjacentNodeIds??[]).map(t=>this.nodeMap.get(t))));s.sort((t,e)=>t.width*t.height-e.width*e.height);for(const t of s)this.absorbedNodeIds.has(t.capacityMeshNodeId)||e.push(t);return e}_step(){this.hasComputedAdjacentNodeIds||(this.computeAdjacentNodeIdsForFirstBatch(this.currentBatchNodeIds.map(t=>this.nodeMap.get(t))),this.hasComputedAdjacentNodeIds=!0);let t=this.currentBatchNodeIds.pop();for(;t&&this.absorbedNodeIds.has(t);)t=this.currentBatchNodeIds.pop();if(!t)return this.batchHadModifications?(this.currentBatchNodeIds=this.nextBatchNodeIds.sort((t,e)=>{const s=this.nodeMap.get(t),n=this.nodeMap.get(e);return s.width*s.height-n.width*n.height}),this.nextBatchNodeIds=[],void(this.batchHadModifications=!1)):(this.solved=!0,void this.newNodes.push(...this.nextBatchNodeIds.map(t=>this.nodeMap.get(t))));const e=this.nodeMap.get(t);let s=!1;const n=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===n.length)return void this.nextBatchNodeIds.push(t);const i=t=>{for(const e of t)this.absorbedNodeIds.add(e.capacityMeshNodeId);e._adjacentNodeIds=Array.from(new Set([...e._adjacentNodeIds??[],...t.flatMap(t=>t._adjacentNodeIds??[])].filter(t=>!this.absorbedNodeIds.has(t))))},o=n.filter(t=>t.center.x<e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(o.length>0){const{width:t,height:n}=o[0],a=o.every(e=>e.width===t&&e.height===n);Math.abs(o.reduce((t,e)=>t+e.height,0)-e.height)<Qs&&a&&(e.width+=t,e.center.x=e.center.x-t/2,i(o),s=!0)}const a=n.filter(t=>t.center.x>e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(a.length>0&&!s){const{width:t,height:n}=a[0],o=a.every(e=>e.width===t&&e.height===n);Math.abs(a.reduce((t,e)=>t+e.height,0)-e.height)<Qs&&o&&(e.width+=t,e.center.x=e.center.x+t/2,i(a),s=!0)}const r=n.filter(t=>t.center.y>e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(r.length>0&&!s){const{width:t,height:n}=r[0],o=r.every(e=>e.width===t&&e.height===n);Math.abs(r.reduce((t,e)=>t+e.width,0)-e.width)<Qs&&o&&(e.height+=n,e.center.y=e.center.y+n/2,i(r),s=!0)}const h=n.filter(t=>t.center.y<e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(h.length>0&&!s){const{width:t,height:n}=h[0],o=h.every(e=>e.width===t&&e.height===n);Math.abs(h.reduce((t,e)=>t+e.width,0)-e.width)<Qs&&o&&(e.height+=n,e.center.y=e.center.y-n/2,i(h),s=!0)}s?(this.batchHadModifications=!0,this.currentBatchNodeIds.push(t)):this.nextBatchNodeIds.unshift(t)}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Same Layer Node Merger"};for(const e of this.newNodes)t.rects.push(Rs(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let s;e&&(s=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const n of this.currentBatchNodeIds){const i=this.nodeMap.get(n);if(!this.absorbedNodeIds.has(n)&&i){const o=Rs(i,{rectMargin:.01});n===e?o.stroke="rgba(0, 255, 0, 0.8)":s?.some(t=>t.capacityMeshNodeId===n)?o.stroke="rgba(128, 0, 128, 0.8)":o.stroke="rgba(255, 165, 0, 0.8)",o.layer=`z${i.availableZ.join(",")}`,o.label=`${o.label}\n(unprocessed)`,t.rects.push(o)}}for(const e of this.nextBatchNodeIds){const s=this.nodeMap.get(e);if(!this.absorbedNodeIds.has(e)&&s){const e=Rs(s,{rectMargin:.01});e.layer=`z${s.availableZ.join(",")}`,e.stroke="rgba(0, 217, 255, 0.8)",e.label=`${e.label}\nx: ${s.center.x}, y: ${s.center.y}\n${s.width}x${s.height}\n(next batch)`,t.rects.push(e)}}return t}},en=class extends e{newRoute;newVias;headIndex=0;tailIndex=0;inputRoute;otherHdRoutes;obstacles;connMap;colorMap;outline;constructor(t){super(),this.inputRoute=t.inputRoute,this.otherHdRoutes=t.otherHdRoutes,this.obstacles=t.obstacles,this.connMap=t.connMap,this.colorMap=t.colorMap,this.outline=t.outline,this.newRoute=[this.inputRoute.route[0]],this.newVias=[]}getConstructorParams(){return{inputRoute:this.inputRoute,otherHdRoutes:this.otherHdRoutes,obstacles:this.obstacles,connMap:this.connMap.netMap,colorMap:this.colorMap,outline:this.outline}}get simplifiedRoute(){return{connectionName:this.inputRoute.connectionName,traceThickness:this.inputRoute.traceThickness,viaDiameter:this.inputRoute.viaDiameter,route:this.newRoute,vias:this.newVias}}isValidPath(t){throw new Error("Not implemented")}_step(){throw new Error("Not implemented")}getVisualsForNewRouteAndObstacles(){const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Simplified Path Solver"};for(let e=0;e<this.inputRoute.route.length-1;e++)t.lines.push({points:[{x:this.inputRoute.route[e].x,y:this.inputRoute.route[e].y},{x:this.inputRoute.route[e+1].x,y:this.inputRoute.route[e+1].y}],strokeColor:"rgba(255, 0, 0, 0.8)",strokeDash:1===this.inputRoute.route[e].z?"5, 5":void 0,layer:`z${this.inputRoute.route[e].z.toString()}`});for(let e=0;e<this.newRoute.length;e++)e<this.newRoute.length-1&&t.lines.push({points:[{x:this.newRoute[e].x,y:this.newRoute[e].y},{x:this.newRoute[e+1].x,y:this.newRoute[e+1].y}],strokeWidth:.15,strokeColor:"rgba(0, 255, 0, 0.8)",strokeDash:1===this.newRoute[e].z?[.4,.4]:void 0,layer:`z${this.newRoute[e].z.toString()}`}),t.points.push({x:this.newRoute[e].x,y:this.newRoute[e].y,color:"rgba(0, 255, 0, 0.8)",label:`z: ${this.newRoute[e].z}`,layer:`z${this.newRoute[e].z.toString()}`});for(const e of this.newVias)t.circles.push({center:e,radius:this.inputRoute.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)"});for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});for(const e of this.otherHdRoutes)for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeWidth:.15,strokeColor:0===e.route[s].z?"rgba(255, 0, 255, 0.5)":1===e.route[s].z?"rgba(128, 0, 128, 0.5)":"rgba(0, 0, 255, 0.5)",layer:`z${e.route[s].z.toString()}`});if("filteredObstaclePathSegments"in this){const e=this.filteredObstaclePathSegments;for(const[s,n]of e)t.lines.push({points:[s,n]})}return t}};function sn(t,e,s,n){if(function(t,e,s,n){const i=rn(t,e,s),o=rn(t,e,n),a=rn(s,n,t),r=rn(s,n,e);return i!==o&&a!==r||(!(0!==i||!hn(t,s,e))||(!(0!==o||!hn(t,n,e))||(!(0!==a||!hn(s,t,n))||!(0!==r||!hn(s,e,n)))))}(t,e,s,n))return 0;const i=nn(t,s,n),o=nn(e,s,n),a=nn(s,t,e),r=nn(n,t,e);return Math.min(i,o,a,r)}function nn(t,e,s){const n={x:s.x-e.x,y:s.y-e.y},i=on({x:t.x-e.x,y:t.y-e.y},n);if(i<=0)return an(t,e);const o=on(n,n);if(o<=i)return an(t,s);const a=i/o;return an(t,{x:e.x+a*n.x,y:e.y+a*n.y})}function on(t,e){return t.x*e.x+t.y*e.y}function an(t,e){const s=e.x-t.x,n=e.y-t.y;return Math.sqrt(s*s+n*n)}function rn(t,e,s){const n=(e.y-t.y)*(s.x-e.x)-(e.x-t.x)*(s.y-e.y);return 0===n?0:n>0?1:2}function hn(t,e,s){return e.x<=Math.max(t.x,s.x)&&e.x>=Math.min(t.x,s.x)&&e.y<=Math.max(t.y,s.y)&&e.y>=Math.min(t.y,s.y)}var cn=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)}),dn=class{constructor(t){this.segments=t,this.buckets=new Map;const e=new Map;for(const s of t){const t=this.getSegmentKey(s);if(e.has(t))continue;e.set(t,s);const n=cn(s),i=Math.floor(n.minX/this.CELL_SIZE),o=Math.floor(n.maxX/this.CELL_SIZE),a=Math.floor(n.minY/this.CELL_SIZE),r=Math.floor(n.maxY/this.CELL_SIZE);for(let e=i;e<=o;e++)for(let n=a;n<=r;n++){const i=`${e}x${n}`,o=this.buckets.get(i),a=[s[0],s[1],t];o?o.push(a):this.buckets.set(i,[a])}}}buckets;CELL_SIZE=.4;SEGMENT_MARGIN=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getSegmentKey(t){return`${t[0].x}-${t[0].y}-${t[0].z}-${t[1].x}-${t[1].y}-${t[1].z}`}getSegmentsThatCouldIntersect(t,e){const s=[],n=new Set,i=Math.min(t.x,e.x)-this.SEGMENT_MARGIN,o=Math.min(t.y,e.y)-this.SEGMENT_MARGIN,a=Math.max(t.x,e.x)+this.SEGMENT_MARGIN,r=Math.max(t.y,e.y)+this.SEGMENT_MARGIN,h=Math.floor(i/this.CELL_SIZE),c=Math.floor(a/this.CELL_SIZE),d=Math.floor(o/this.CELL_SIZE),l=Math.floor(r/this.CELL_SIZE);for(let t=h;t<=c;t++)for(let e=d;e<=l;e++){const i=`${t}x${e}`,o=this.buckets.get(i);if(o)for(const t of o){const e=t[2];n.has(e)||(n.add(e),s.push(t))}}return s}},ln=1e-6,un=(t,e,s)=>r(t,e,s)<=ln,pn=(t,e)=>Math.abs(t.x-e.x)<=ln&&Math.abs(t.y-e.y)<=ln,fn=(t,e)=>{if(!e||e.length<3)return!1;for(let s=0;s<e.length;s++){const n=e[s],i=e[(s+1)%e.length];if(un(t,n,i))return!0}let s=!1;for(let n=0,i=e.length-1;n<e.length;i=n++){const o=e[n],a=e[i];o.y>t.y!=a.y>t.y&&t.x<(a.x-o.x)*(t.y-o.y)/(a.y-o.y)+o.x&&(s=!s)}return s},mn=class extends en{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=s(t),i=s(e),o=Math.max(n.minX-i.maxX,i.minX-n.maxX,0),a=Math.max(n.minY-i.maxY,i.minY-n.maxY,0);return Math.hypot(o,a)}(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 s=t.route,n=[];for(let t=0;t<s.length-1;t++){const i=s[t],o=s[t+1],a=Math.min(i.x,o.x),r=Math.max(i.x,o.x),h=Math.min(i.y,o.y),c=Math.max(i.y,o.y);a<=e.maxX&&r>=e.minX&&h<=e.maxY&&c>=e.minY&&n.push([i,o])}return n}),this.segmentTree=new dn(this.filteredObstaclePathSegments),this.filteredVias=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const s=t.vias,n=[];for(const i of s){const s=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2+t.viaDiameter/2,o=i.x-s,a=i.x+s,r=i.y-s,h=i.y+s;o<=e.maxX&&a>=e.minX&&r<=e.maxY&&h>=e.minY&&n.push({...i,diameter:t.viaDiameter})}return n}),this.computePathSegments()}computePathSegments(){let t=0;for(let e=0;e<this.inputRoute.route.length-1;e++){const s=this.inputRoute.route[e],n=this.inputRoute.route[e+1],i=Math.sqrt((n.x-s.x)**2+(n.y-s.y)**2)+e/1e4;this.pathSegments.push({start:s,end:n,length:i,startDistance:t,endDistance:t+i}),t+=i}this.totalPathLength=t}arePointsEqual(t,e){return t.x===e.x&&t.y===e.y&&t.z===e.z}getPointAtDistance(t){t=Math.max(0,Math.min(t,this.totalPathLength));const e=this.pathSegments.find(e=>t>=e.startDistance&&t<=e.endDistance);if(!e)return this.inputRoute.route[this.inputRoute.route.length-1];const s=(t-e.startDistance)/e.length;return{x:e.start.x+s*(e.end.x-e.start.x),y:e.start.y+s*(e.end.y-e.start.y),z:s<.5?e.start.z:e.end.z}}getNearestIndexForDistance(t){if(t<=0)return 0;if(t>=this.totalPathLength)return this.inputRoute.route.length-1;const e=this.pathSegments.findIndex(e=>t>=e.startDistance&&t<=e.endDistance);if(-1===e)return 0;const s=this.pathSegments[e],n=(s.startDistance+s.endDistance)/2;return t>n?e+1:e}isValidPathSegment(t,e){for(const s of this.filteredObstacles){if(!s.zLayers?.includes(t.z))continue;if(v(t,e,s)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2)return!1}const s=this.segmentTree.getSegmentsThatCouldIntersect(t,e);for(const[n,i,o]of s)if(n.z===t.z&&i.z===t.z){if(sn({x:t.x,y:t.y},{x:e.x,y:e.y},{x:n.x,y:n.y},{x:i.x,y:i.y})<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS)return!1}for(const s of this.filteredVias)if(r(s,t,e)<this.OBSTACLE_MARGIN+s.diameter/2+this.TRACE_THICKNESS/2)return!1;if(this.outline&&this.outline.length>=3){const s=(({start:t,end:e,polygon:s,margin:n=.2})=>{if(!s||s.length<3)return!1;const o=fn(t,s),a=fn(e,s);if(!o||!a)return!0;for(let o=0;o<s.length;o++){const a=s[o],r=s[(o+1)%s.length],h=un(t,a,r),d=un(e,a,r);if(h&&d)continue;if(!i(t,e,a,r)){if(!h&&!d&&sn(t,e,a,r)<n-ln)return!0;continue}const l=c(t,e,a,r);if(!(l&&(h&&pn(l,t)||d&&pn(l,e))||l&&(pn(l,t)||pn(l,e))))return!0}return!1})({start:{x:t.x,y:t.y},end:{x:e.x,y:e.y},polygon:this.outline});if(s)return!1}return!0}isValidPath(t){if(t.length<2)return!0;for(let e=0;e<t.length-1;e++)if(t[e].z!==t[e+1].z)return!1;for(let e=0;e<t.length-1;e++)if(!this.isValidPathSegment(t[e],t[e+1]))return!1;return!0}find45DegreePath(t,e){if(this.arePointsEqual(t,e))return[t];if(t.z!==e.z)return null;const s=((t,e)=>{const s=[],n=Math.abs(e.x-t.x),i=Math.abs(e.y-t.y),o=e.x>t.x?1:-1,a=e.y>t.y?1:-1,r={x:e.x-o*Math.abs(e.y-t.y),y:t.y};(r.x-t.x)*o>=0&&(r.x-e.x)*o<=0&&s.push([t,r,e]);const h={x:t.x,y:e.y-a*Math.abs(e.x-t.x)};(h.y-t.y)*a>=0&&(h.y-e.y)*a<=0&&s.push([t,h,e]);const c=Math.min(n,i),d={x:t.x+o*c,y:t.y+a*c};return(d.x-t.x)*o>=0&&(d.x-e.x)*o<=0&&(d.y-t.y)*a>=0&&(d.y-e.y)*a<=0&&s.push([t,d,e]),s})({x:t.x,y:t.y},{x:e.x,y:e.y});for(const e of s){const s=e.map(e=>({x:e.x,y:e.y,z:t.z}));if(this.isValidPath(s))return s}return null}addPathToResult(t){if(0!==t.length){for(let e=0;e<t.length;e++)0===e&&this.newRoute.length>0&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t[e])||this.newRoute.push(t[e]);this.currentStepSize=this.maxStepSize}}moveHead(t){this.lastHeadMoveDistance=t,this.headDistanceAlongPath=Math.min(this.headDistanceAlongPath+t,this.totalPathLength)}stepBackAndReduceStepSize(){this.headDistanceAlongPath=Math.max(this.tailDistanceAlongPath,this.headDistanceAlongPath-this.lastHeadMoveDistance),this.currentStepSize=Math.max(this.minStepSize,this.currentStepSize*this.STEP_SIZE_REDUCTION_FACTOR)}_step(){const t=this.tailDistanceAlongPath>=this.totalPathLength,e=this.headDistanceAlongPath>=this.totalPathLength;if(t){const t=this.inputRoute.route[this.inputRoute.route.length-1];return 0!==this.newRoute.length&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t)||this.newRoute.push(t),void(this.solved=!0)}if(e){const t=this.getPointAtDistance(this.tailDistanceAlongPath),e=this.inputRoute.route[this.inputRoute.route.length-1],s=this.find45DegreePath(t,e);if(s)return this.addPathToResult(s),void(this.solved=!0);this.lastValidPath=null,this.tailDistanceAlongPath=this.totalPathLength,this.headDistanceAlongPath=this.totalPathLength;const n=[];for(const t of this.inputRoute.route)0!==n.length&&this.arePointsEqual(n[n.length-1],t)||n.push(t);return this.newRoute=n,this.newVias=[...this.inputRoute.vias],void(this.solved=!0)}this.moveHead(this.currentStepSize);const s=this.getPointAtDistance(this.tailDistanceAlongPath),n=this.getPointAtDistance(this.headDistanceAlongPath),i=this.getNearestIndexForDistance(this.tailDistanceAlongPath),o=this.getNearestIndexForDistance(this.headDistanceAlongPath);let a=!1,r=-1;for(let t=i;t<o;t++)if(t+1<this.inputRoute.route.length&&this.inputRoute.route[t].z!==this.inputRoute.route[t+1].z){a=!0;const e=t;r=this.pathSegments[e].startDistance;break}if(a&&this.lastHeadMoveDistance>this.minStepSize)return void this.stepBackAndReduceStepSize();if(a&&r>0){const t=this.getNearestIndexForDistance(r)+1,e=this.inputRoute.route[t],s={x:e.x,y:e.y};this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null);const n=this.newRoute[this.newRoute.length-1];n.x===s.x&&n.y===s.y||this.newRoute.push({x:s.x,y:s.y,z:n.z}),this.newVias.push(s),this.newRoute.push({x:s.x,y:s.y,z:e.z}),this.currentStepSize=this.maxStepSize;const i=this.pathSegments.findIndex(t=>t.start===e);if(-1!==i)this.tailDistanceAlongPath=this.pathSegments[i].startDistance,this.headDistanceAlongPath=this.tailDistanceAlongPath,this.lastValidPath=null,this.lastValidPathHeadDistance=this.tailDistanceAlongPath;else if(t<this.inputRoute.route.length){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("Could not find segment start after layer change, path might be incomplete."),this.solved=!0)}else console.warn("Layer change occurred at the end of the path."),this.solved=!0;return}const h=this.find45DegreePath(s,n);if(!h&&this.lastHeadMoveDistance>this.minStepSize)this.stepBackAndReduceStepSize();else{if(!h&&!this.lastValidPath){const t=this.getPointAtDistance(this.tailDistanceAlongPath);this.tailDistanceAlongPath+=this.minStepSize,this.moveHead(this.minStepSize);const e=this.getNearestIndexForDistance(this.tailDistanceAlongPath),s=this.inputRoute.route[e],n=this.inputRoute.route[this.inputRoute.route.length-1];return void(this.arePointsEqual(t,s)||this.arePointsEqual(s,n)||this.newRoute.push(s))}if(h)return this.lastValidPath=h,void(this.lastValidPathHeadDistance=this.headDistanceAlongPath);this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null,this.tailDistanceAlongPath=this.lastValidPathHeadDistance,this.moveHead(this.minStepSize))}}visualize(){const t=this.getVisualsForNewRouteAndObstacles(),e=this.getPointAtDistance(this.tailDistanceAlongPath),s=this.getPointAtDistance(this.headDistanceAlongPath);t.points.push({x:e.x,y:e.y,color:"yellow",label:["Tail",`z: ${e.z}`].join("\n")}),t.points.push({x:s.x,y:s.y,color:"orange",label:["Head",`z: ${s.z}`].join("\n")});const n=this.getPointAtDistance(this.headDistanceAlongPath+this.currentStepSize);t.points.push({x:n.x,y:n.y,color:"red",label:["Tentative Head",`z: ${n.z}`].join("\n")});let i=0;for(;i<this.totalPathLength;){const e=this.getPointAtDistance(i);t.circles.push({center:{x:e.x,y:e.y},radius:.05,fill:"rgba(100, 100, 100, 0.5)"}),i+=this.totalPathLength/20}if(this.lastValidPath&&this.lastValidPath.length>1)for(let e=0;e<this.lastValidPath.length-1;e++)t.lines.push({points:[{x:this.lastValidPath[e].x,y:this.lastValidPath[e].y},{x:this.lastValidPath[e+1].x,y:this.lastValidPath[e+1].y}],strokeColor:"rgba(0, 255, 255, 0.9)",strokeDash:"3, 3"});return t}},gn=class extends e{simplifiedHdRoutes;currentUnsimplifiedHdRouteIndex=0;activeSubSolver=null;unsimplifiedHdRoutes;obstacles;connMap;colorMap;outline;constructor(t){super(),this.MAX_ITERATIONS=1e8,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.obstacles=t.obstacles,this.connMap=t.connMap||new is({}),this.colorMap=t.colorMap||{},this.outline=t.outline,this.simplifiedHdRoutes=[]}_step(){const t=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];if(!this.activeSubSolver)return t?(this.activeSubSolver=new mn({inputRoute:t,otherHdRoutes:this.unsimplifiedHdRoutes.slice(this.currentUnsimplifiedHdRouteIndex+1).concat(this.simplifiedHdRoutes),obstacles:this.obstacles,connMap:this.connMap,colorMap:this.colorMap,outline:this.outline}),void this.currentUnsimplifiedHdRouteIndex++):void(this.solved=!0);this.activeSubSolver.step(),this.activeSubSolver.solved&&(this.simplifiedHdRoutes.push(this.activeSubSolver.simplifiedRoute),this.activeSubSolver=null)}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Multi Simplified Path Solver"};for(const e of this.unsimplifiedHdRoutes)if(!this.simplifiedHdRoutes.some(t=>t.connectionName===e.connectionName)){for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeColor:1===e.route[s].z?"rgba(0, 0, 255, 0.4)":"rgba(255, 0, 0, 0.4)",strokeWidth:.15,strokeDash:1===e.route[s].z?[.5,.5]:void 0});for(const s of e.vias||[])t.circles.push({center:s,radius:e.viaDiameter/2||.3,fill:"rgba(0, 0, 255, 0.4)"})}for(const e of this.simplifiedHdRoutes){const s=this.colorMap?.[e.connectionName]||"rgba(128, 128, 128, 0.8)";for(let n=0;n<e.route.length-1;n++)t.lines.push({points:[{x:e.route[n].x,y:e.route[n].y},{x:e.route[n+1].x,y:e.route[n+1].y}],strokeWidth:.15,strokeColor:s,strokeDash:1===e.route[n].z?[.5,.5]:void 0,step:1});for(const s of e.vias||[])t.circles.push({center:s,radius:e.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)",step:1})}for(const e of this.unsimplifiedHdRoutes){for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeWidth:.15,strokeColor:"rgba(255, 0, 0, 0.2)",strokeDash:[.5,.5],step:0,layer:`z${e.route[s].z.toString()}`});for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 0, 0.2)",step:0})}for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});if(this.currentUnsimplifiedHdRouteIndex<this.unsimplifiedHdRoutes.length){const e=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];e.route.length>0&&t.circles.push({center:{x:e.route[0].x,y:e.route[0].y},radius:.2,fill:"yellow",label:"Current"})}return t}},yn=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)&&Ks(this.nodes[t],this.nodes[e])&&this.doNodesHaveSharedLayer(this.nodes[t],this.nodes[e])&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[this.nodes[t].capacityMeshNodeId,this.nodes[e].capacityMeshNodeId]})}this.handleTargetNodes(),this.solved=!0}handleTargetNodes(){const t=this.nodes.filter(t=>t._containsTarget);for(const e of t){if(this.edges.some(t=>t.nodeIds.includes(e.capacityMeshNodeId)))continue;let t=null,s=1/0;for(const n of this.nodes){if(n._containsObstacle)continue;if(n._containsTarget)continue;const i=h(e.center,n.center);i<s&&(s=i,t=n)}t&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[e.capacityMeshNodeId,t.capacityMeshNodeId]})}}doNodesHaveSharedLayer(t,e){return t.availableZ.some(t=>e.availableZ.includes(t))}visualize(){const t=new Map;for(const e of this.edges)for(const s of e.nodeIds)t.set(s,1+(t.get(s)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const s=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+s*e.width*.05,y:e.center.y-s*e.width*.05},fill:e._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}for(const t of this.edges){const s=this.nodeMap.get(t.nodeIds[0]),n=this.nodeMap.get(t.nodeIds[1]);if(s?.center&&n?.center){const t=Math.min(...s.availableZ),i=Math.min(...n.availableZ),o={x:s.center.x+t*s.width*.05,y:s.center.y-t*s.width*.05},a={x:n.center.x+i*n.width*.05,y:n.center.y-i*n.width*.05},r=Array.from(new Set([...s.availableZ,...n.availableZ])).sort();e.lines.push({layer:`z${r.join(",")}`,points:[o,a],strokeDash:s.availableZ.join(",")===n.availableZ.join(",")?void 0:"10 5"})}}return e}},xn=class extends yn{constructor(t){super(t),this.nodes=t,this.MAX_ITERATIONS=1e7,this.nodeTree=new Js(this.nodes),this.currentNodeIndex=0,this.edgeSet=new Set}nodeTree;currentNodeIndex;edgeSet;_step(){if(this.currentNodeIndex>=this.nodes.length)return this.handleTargetNodes(),void(this.solved=!0);const t=this.nodes[this.currentNodeIndex],e=this.nodeTree.getNodesInArea(t.center.x,t.center.y,2*t.width,2*t.height);for(const s of e){if(!Ks(t,s))continue;const e=t._strawNode&&s._strawNode&&t._strawParentCapacityMeshNodeId===s._strawParentCapacityMeshNodeId;t.capacityMeshNodeId===s.capacityMeshNodeId||e||!this.doNodesHaveSharedLayer(t,s)||this.edgeSet.has(`${t.capacityMeshNodeId}-${s.capacityMeshNodeId}`)||(this.edgeSet.add(`${t.capacityMeshNodeId}-${s.capacityMeshNodeId}`),this.edgeSet.add(`${s.capacityMeshNodeId}-${t.capacityMeshNodeId}`),this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[t.capacityMeshNodeId,s.capacityMeshNodeId]}))}this.currentNodeIndex++}},Mn=class extends e{removedNodeIds;targetNodeIds;leaves;leavesIndex;adjacencyList;nodeMap;nodes;edges;constructor({nodes:t,edges:e}){super(),this.MAX_ITERATIONS=t.length,this.nodes=t,this.edges=e,this.removedNodeIds=new Set,this.targetNodeIds=new Set(t.filter(t=>t._containsTarget).map(t=>t.capacityMeshNodeId)),this.adjacencyList=new Map(t.map(({capacityMeshNodeId:t})=>[t,new Set]));for(const{nodeIds:[t,s]}of e)this.adjacencyList.get(t).add(s),this.adjacencyList.get(s).add(t);this.leavesIndex=0,this.leaves=[...this.adjacencyList.entries()].filter(([t,e])=>1===e.size).filter(([t,e])=>!this.targetNodeIds.has(t)).map(([t,e])=>t)}_step(){if(this.leavesIndex===this.leaves.length)return void(this.solved=!0);const t=this.leaves[this.leavesIndex],e=this.adjacencyList.get(t);if(!e||0===e.size)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));const[s]=e,n=s?this.adjacencyList.get(s):void 0;if(!s||!n)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));n.delete(t),this.removedNodeIds.add(t),this.adjacencyList.delete(t),1!==n.size||this.targetNodeIds.has(s)||this.leaves.push(s),this.leavesIndex+=1,this.leavesIndex===this.leaves.length&&(this.solved=!0)}visualize(){if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}const t=new Map;for(const e of this.edges)for(const s of e.nodeIds)t.set(s,1+(t.get(s)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const s=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+s*e.width*.05,y:e.center.y-s*e.width*.05},fill:e._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};for(const t of this.edges){const s=this.nodeMap.get(t.nodeIds[0]),n=this.nodeMap.get(t.nodeIds[1]);if(s?.center&&n?.center){const i=Math.min(...s.availableZ),o=Math.min(...n.availableZ),a={x:s.center.x+i*s.width*.05,y:s.center.y-i*s.width*.05},r={x:n.center.x+o*n.width*.05,y:n.center.y-o*n.width*.05},h=Array.from(new Set([...s.availableZ,...n.availableZ])).sort();e.lines.push({layer:`z${h.join(",")}`,points:[a,r],strokeDash:s.availableZ.join(",")===n.availableZ.join(",")?void 0:"10 5",strokeColor:t.nodeIds.some(t=>this.removedNodeIds.has(t))?ct("black",.9):void 0})}}return e}},vn=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 Sn(t,e){const s=t.x-e.x,n=t.y-e.y;return s*s+n*n}function bn(t,e,s){const n=Sn(e,s);if(0===n)return Sn(t,e);let i=((t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y))/n;i=Math.max(0,Math.min(1,i));return Sn(t,{x:e.x+i*(s.x-e.x),y:e.y+i*(s.y-e.y)})}function Nn(t,e,s,n){if(i(t,e,s,n))return 0;const o={x:t.x,y:t.y},a={x:e.x,y:e.y},r={x:s.x,y:s.y},h={x:n.x,y:n.y};return Math.min(bn(o,r,h),bn(a,r,h),bn(r,o,a),bn(h,o,a))}var In=class{segmentBuckets;viaBuckets;routes;CELL_SIZE;constructor(t,e=1){this.segmentBuckets=new Map,this.viaBuckets=new Map,this.routes=new Map,this.CELL_SIZE=e;for(const e of t)if(e&&e.connectionName)if(this.routes.has(e.connectionName))console.warn(`Skipping duplicate route connectionName: ${e.connectionName}`);else{if(this.routes.set(e.connectionName,e),e.route&&e.route.length>=2)for(let t=0;t<e.route.length-1;t++){const s=e.route[t],n=e.route[t+1];if(s.x===n.x&&s.y===n.y)continue;const i=[s,n],o=vn(i),a={segmentId:`${e.connectionName}-seg-${t}`,segment:i,parentRoute:e},r=Math.floor(o.minX/this.CELL_SIZE),h=Math.floor((o.maxX+1e-9)/this.CELL_SIZE),c=Math.floor(o.minY/this.CELL_SIZE),d=Math.floor((o.maxY+1e-9)/this.CELL_SIZE);for(let t=r;t<=h;t++)for(let e=c;e<=d;e++){const s=`${t}x${e}`;let n=this.segmentBuckets.get(s);n||(n=[],this.segmentBuckets.set(s,n)),n.push(a)}}if(e.vias&&e.vias.length>0)for(let t=0;t<e.vias.length;t++){const s=e.vias[t];if(null==s)continue;const n={viaId:`${e.connectionName}-via-${t}`,x:s.x,y:s.y,parentRoute:e},i=`${Math.floor(s.x/this.CELL_SIZE)}x${Math.floor(s.y/this.CELL_SIZE)}`;let o=this.viaBuckets.get(i);o||(o=[],this.viaBuckets.set(i,o)),o.push(n)}}else console.warn("Skipping route with missing data:",e)}getConflictingRoutesForSegment(t,e,s){const n=vn([t,e]),i=n.minX-s,o=n.minY-s,a=n.maxX+s,r=n.maxY+s,h=Math.floor(i/this.CELL_SIZE),c=Math.floor((a+1e-9)/this.CELL_SIZE),d=Math.floor(o/this.CELL_SIZE),l=Math.floor((r+1e-9)/this.CELL_SIZE),u=new Map,p=new Set,f=new Set,m={x:t.x,y:t.y},g={x:e.x,y:e.y};for(let n=h;n<=c;n++)for(let i=d;i<=l;i++){const o=`${n}x${i}`,a=this.segmentBuckets.get(o);if(a)for(const n of a){if(p.has(n.segmentId))continue;p.add(n.segmentId);const i=n.parentRoute,[o,a]=n.segment,r=s+i.traceThickness/2,h=r*r,c=Nn(t,e,o,a);if(c<h){const t=i.connectionName,e=u.get(t);(!e||c<e.minDistSq)&&u.set(t,{route:i,minDistSq:c})}}const r=this.viaBuckets.get(o);if(r)for(const t of r){if(f.has(t.viaId))continue;f.add(t.viaId);const e=t.parentRoute,n={x:t.x,y:t.y},i=s+e.viaDiameter/2,o=i*i,a=bn(n,m,g);if(a<o){const t=e.connectionName,s=u.get(t);(!s||a<s.minDistSq)&&u.set(t,{route:e,minDistSq:a})}}}const y=[];for(const t of u.values())y.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return y}getConflictingRoutesNearPoint(t,e){const s=t.x-e,n=t.y-e,i=t.x+e,o=t.y+e,a=Math.floor(s/this.CELL_SIZE),r=Math.floor((i+1e-9)/this.CELL_SIZE),h=Math.floor(n/this.CELL_SIZE),c=Math.floor((o+1e-9)/this.CELL_SIZE),d=new Map,l=new Set,u=new Set;for(let s=a;s<=r;s++)for(let n=h;n<=c;n++){const i=`${s}x${n}`,o=this.segmentBuckets.get(i);if(o)for(const s of o){if(l.has(s.segmentId))continue;l.add(s.segmentId);const n=s.parentRoute,i={x:s.segment[0].x,y:s.segment[0].y},o={x:s.segment[1].x,y:s.segment[1].y},a=e+n.traceThickness/2,r=a*a,h=bn(t,i,o);if(h<r){const t=n.connectionName,e=d.get(t);(!e||h<e.minDistSq)&&d.set(t,{route:n,minDistSq:h})}}const a=this.viaBuckets.get(i);if(a)for(const s of a){if(u.has(s.viaId))continue;u.add(s.viaId);const n=s.parentRoute,i={x:s.x,y:s.y},o=e+n.viaDiameter/2,a=o*o,r=Sn(t,i);if(r<a){const t=n.connectionName,e=d.get(t);(!e||r<e.minDistSq)&&d.set(t,{route:n,minDistSq:r})}}}const p=[];for(const t of d.values())p.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return p}},Pn=class extends e{obstacleSHI;hdRouteSHI;unsimplifiedRoute;routeSections;currentSectionIndex;TRACE_THICKNESS=.15;OBSTACLE_MARGIN=.1;constructor(t){super(),this.currentSectionIndex=1,this.obstacleSHI=t.obstacleSHI,this.hdRouteSHI=t.hdRouteSHI,this.unsimplifiedRoute=t.unsimplifiedRoute,this.routeSections=this.breakRouteIntoSections(this.unsimplifiedRoute)}breakRouteIntoSections(t){const e=[],s=t.route;if(0===s.length)return[];let n={startIndex:0,endIndex:-1,z:s[0].z,points:[s[0]]};for(let t=1;t<s.length;t++)s[t].z===n.z?n.points.push(s[t]):(n.endIndex=t-1,e.push(n),n={startIndex:t,endIndex:-1,z:s[t].z,points:[s[t]]});return n.endIndex=s.length-1,e.push(n),e}_step(){if(this.currentSectionIndex>=this.routeSections.length-1)return void(this.solved=!0);const t=this.routeSections[this.currentSectionIndex-1],e=this.routeSections[this.currentSectionIndex],s=this.routeSections[this.currentSectionIndex+1];if(t.z!==s.z)return void this.currentSectionIndex++;const n=t.z;if(this.canSectionMoveToLayer({currentSection:e,targetZ:n}))return e.z=n,e.points=e.points.map(t=>({...t,z:n})),void(this.currentSectionIndex+=2);this.currentSectionIndex++}canSectionMoveToLayer({currentSection:t,targetZ:e}){for(let s=0;s<t.points.length-1;s++){const n={...t.points[s],z:e},i={...t.points[s+1],z:e},o=this.hdRouteSHI.getConflictingRoutesForSegment(n,i,this.TRACE_THICKNESS);for(const{conflictingRoute:t,distance:e}of o)if(t.connectionName!==this.unsimplifiedRoute.connectionName&&e<this.TRACE_THICKNESS+t.traceThickness)return!1;const a={centerX:(n.x+i.x)/2,centerY:(n.y+i.y)/2,width:Math.abs(n.x-i.x),height:Math.abs(n.y-i.y)},r=this.obstacleSHI.searchArea(a.centerX,a.centerY,a.width+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN),a.height+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN));for(const t of r){if(v(n,i,t)<this.TRACE_THICKNESS+this.OBSTACLE_MARGIN)return!1}}return!0}getConstructorParams(){return{obstacleSHI:this.obstacleSHI,hdRouteSHI:this.hdRouteSHI,unsimplifiedRoute:this.unsimplifiedRoute}}getOptimizedHdRoute(){const t=this.routeSections.flatMap(t=>t.points),e=[];for(let s=0;s<t.length-1;s++)t[s].z!==t[s+1].z&&e.push({x:t[s].x,y:t[s].y});return{connectionName:this.unsimplifiedRoute.connectionName,route:t,traceThickness:this.unsimplifiedRoute.traceThickness,vias:e,viaDiameter:this.unsimplifiedRoute.viaDiameter}}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Single Route Useless Via Removal Solver"};for(let e=0;e<this.routeSections.length;e++){const s=this.routeSections[e];t.lines.push({points:s.points,strokeWidth:this.TRACE_THICKNESS,strokeColor:e===this.currentSectionIndex?"orange":0===s.z?"red":"blue"})}return t}},Cn=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 kt("flatbush",t.obstacles),this.hdRouteSHI=new In(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 Pn({hdRouteSHI:this.hdRouteSHI,obstacleSHI:this.obstacleSHI,unsimplifiedRoute:t}):this.solved=!0}getOptimizedHdRoutes(){return this.optimizedHdRoutes}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Useless Via Removal Solver"};for(const e of this.input.obstacles){let s="rgba(128, 128, 128, 0.2)";const n=e.zLayers?.includes(0),i=e.zLayers?.includes(1);n&&i?s="rgba(128, 0, 128, 0.2)":n?s="rgba(255, 0, 0, 0.2)":i&&(s="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.optimizedHdRoutes){if(0===e.route.length)continue;this.input.colorMap[e.connectionName];for(let s=0;s<e.route.length-1;s++){const n=e.route[s],i=e.route[s+1];n.z===i.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:i.x,y:i.y}],strokeColor:0===n.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${n.z})`})}for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`})}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}};function _n(t,e,s,n={}){return{solverName:t,solverClass:e,getConstructorParams:s,onSolved:n.onSolved}}var Tn=class extends e{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,void 0===e.capacityDepth){const s=t.bounds.maxX-t.bounds.minX,n=t.bounds.maxY-t.bounds.minY,i=Math.max(s,n),o=e.targetMinCapacity??.5;e.capacityDepth=ut(i,o)}this.connMap=os(t),this.colorMap=ht(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ne():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;uselessViaRemovalSolver1;uselessViaRemovalSolver2;multiSimplifiedPathSolver1;multiSimplifiedPathSolver2;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[_n("netToPointPairsSolver",cs,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ht(t.srjWithPointPairs,this.connMap),t.connMap=os(t.srjWithPointPairs)}}),_n("nodeSolver",Zt,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),_n("singleLayerNodeMerger",tn,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),_n("strawSolver",qs,t=>[{nodes:t.singleLayerNodeMerger?.newNodes}],{onSolved:t=>{t.capacityNodes=t.strawSolver?.getResultNodes()}}),_n("edgeSolver",xn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),_n("deadEndSolver",Mn,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)))}}),_n("initialPathingSolver",Ds,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),_n("pathingOptimizer",Gs,t=>[{initialPathingSolver:t.initialPathingSolver,simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,cacheProvider:t.cacheProvider,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),_n("edgeToPortSegmentSolver",Vt,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.pathingOptimizer?.getCapacityPaths()||[],colorMap:t.colorMap}]),_n("segmentToPointSolver",Kt,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),_n("unravelMultiSectionSolver",zs,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),_n("highDensityRouteSolver",ns,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap}]),_n("highDensityStitchSolver",ps,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),_n("uselessViaRemovalSolver1",Cn,t=>[{unsimplifiedHdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),_n("multiSimplifiedPathSolver1",gn,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver1?.getOptimizedHdRoutes()||t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}]),_n("uselessViaRemovalSolver2",Cn,t=>[{unsimplifiedHdRoutes:t.multiSimplifiedPathSolver1.simplifiedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),_n("multiSimplifiedPathSolver2",gn,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver2?.getOptimizedHdRoutes(),obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}])];currentPipelineStepIndex=0;_step(){const t=this.pipelineDef[this.currentPipelineStepIndex];if(!t)return void(this.solved=!0);if(this.activeSubSolver)return this.activeSubSolver.step(),void(this.activeSubSolver.solved?(this.endTimeOfPhase[t.solverName]=performance.now(),this.timeSpentOnPhase[t.solverName]=this.endTimeOfPhase[t.solverName]-this.startTimeOfPhase[t.solverName],t.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStepIndex++):this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null));const e=t.getConstructorParams(this);this.activeSubSolver=new t.solverClass(...e),this[t.solverName]=this.activeSubSolver,this.timeSpentOnPhase[t.solverName]=0,this.startTimeOfPhase[t.solverName]=performance.now()}solveUntilPhase(t){for(;this.getCurrentPhase()!==t;)this.step()}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();const e=this.netToPointPairsSolver?.visualize(),s=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),i=this.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(),m=this.uselessViaRemovalSolver1?.visualize(),g=this.uselessViaRemovalSolver2?.visualize(),y=this.multiSimplifiedPathSolver1?.visualize(),x=this.multiSimplifiedPathSolver2?.visualize(),M=this.srj.outline,v=[];if(v.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]}),v.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const S={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:v},b=[S,e,s,n,i,o,a,r,h,c,d,l,u,p?t(S,p):null,f,m,y,g,x,this.solved?t(S,fs(this.getOutputSimpleRouteJson())):null].filter(Boolean);return t(...b)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const s=this.highDensityRouteSolver.routes[e];if(t.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[s.connectionName]}),t.length>200)break}return{lines:t}}if(this.pathingOptimizer){const t=[];for(const e of this.pathingOptimizer.connectionsWithNodes)e.path&&t.push({points:e.path.map(t=>({x:t.center.x,y:t.center.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}getOriginalConnectionName(t){const e=t.match(/^(.+?)_mst\d+$/);return e?e[1]:t}_getOutputHdRoutes(){return this.multiSimplifiedPathSolver2?.simplifiedHdRoutes??this.uselessViaRemovalSolver2?.getOptimizedHdRoutes()??this.multiSimplifiedPathSolver1?.simplifiedHdRoutes??this.uselessViaRemovalSolver1?.getOptimizedHdRoutes()??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const s of this.netToPointPairsSolver?.newConnections??[]){const n=this.srj.connections.find(t=>t.name===s.name)?.netConnectionName,i=e.filter(t=>t.connectionName===s.name);for(let e=0;e<i.length;e++){const o=i[e],a={type:"pcb_trace",pcb_trace_id:`${s.name}_${e}`,connection_name:n??this.getOriginalConnectionName(s.name),route:ls(o,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},En=Tn;export{Tn as AutoroutingPipelineSolver,En as CapacityMeshSolver,Qt as InMemoryCache,ee as LocalStorageCache,ut as calculateOptimalCapacityDepth,fs as convertSrjToGraphicsObject,ne as getGlobalInMemoryCache,se as getGlobalLocalStorageCache,lt as getTunedTotalCapacity1,ie as setupGlobalCaches};//# sourceMappingURL=index.js.map
1
+ var t=(...t)=>{const e={points:[],lines:[],circles:[],rects:[]};return t.forEach((t,s)=>{t&&(t.lines&&(e.lines=[...e.lines||[],...t.lines.map(t=>({...t,step:s}))]),t.points&&(e.points=[...e.points||[],...t.points.map(t=>({...t,step:s}))]),t.circles&&(e.circles=[...e.circles||[],...t.circles.map(t=>({...t,step:s}))]),t.rects&&(e.rects=[...e.rects||[],...t.rects.map(t=>({...t,step:s}))]))}),e},e=class{MAX_ITERATIONS=1e3;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};cacheHit;cacheKey;cacheToSolveSpaceTransform;step(){if(!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,console.error(this.error),this.failed=!0,t}!this.solved&&this.iterations>this.MAX_ITERATIONS&&this.tryFinalAcceptance(),!this.solved&&this.iterations>this.MAX_ITERATIONS&&(this.error=`${this.constructor.name} ran out of iterations`,console.error(this.error),this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}};function s(t){const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-s,maxY:t.center.y+s}}function n(t,e,s){return Math.max(e,Math.min(s,t))}function i(t,e,s,n){const i=o(t,e,s),r=o(t,e,n),h=o(s,n,t),c=o(s,n,e);return i!==r&&h!==c||(!(0!==i||!a(t,s,e))||(!(0!==r||!a(t,n,e))||(!(0!==h||!a(s,t,n))||!(0!==c||!a(s,e,n)))))}function o(t,e,s){const n=(e.y-t.y)*(s.x-e.x)-(e.x-t.x)*(s.y-e.y);return 0===n?0:n>0?1:2}function a(t,e,s){return e.x<=Math.max(t.x,s.x)&&e.x>=Math.min(t.x,s.x)&&e.y<=Math.max(t.y,s.y)&&e.y>=Math.min(t.y,s.y)}function r(t,e,s){const n=(s.x-e.x)**2+(s.y-e.y)**2;if(0===n)return h(t,e);let i=((t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y))/n;i=Math.max(0,Math.min(1,i));return h(t,{x:e.x+i*(s.x-e.x),y:e.y+i*(s.y-e.y)})}function h(t,e){const s=t.x-e.x,n=t.y-e.y;return Math.sqrt(s*s+n*n)}function c(t,e,s,n){const i=e.x-t.x,o=e.y-t.y,a=n.x-s.x,r=n.y-s.y,h=t.x-s.x,c=t.y-s.y,d=i*r-o*a;if(Math.abs(d)<1e-10)return null;const l=(c*a-h*r)/d,u=(i*c-o*h)/d,p=1e-9;if(l>=-1e-9&&l<=1+p&&u>=-1e-9&&u<=1+p){return{x:t.x+l*i,y:t.y+l*o}}return null}function d(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var l=t=>{if("minX"in t)return t;const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,minY:t.center.y-s,maxX:t.center.x+e,maxY:t.center.y+s}},u=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}],p=t=>{const e=[];for(let s=0;s<t.length;s++){const n=t[s],i=t[(s+1)%t.length];e.push([n,i])}return e},f=(t,e,s)=>{const n=(t.y-e.y)*(s.x-e.x)-(t.x-e.x)*(s.y-e.y);if(Math.abs(n)>1e-9)return!1;const i=(t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y);if(i<0)return!1;return!(i>(s.x-e.x)**2+(s.y-e.y)**2)},m=(t,e)=>{if(e.length<3)return!1;const s=p(e);for(const[e,n]of s)if(f(t,e,n))return!0;let n=!1;for(let s=0,i=e.length-1;s<e.length;i=s++){const o=e[s].x,a=e[s].y,r=e[i].x,h=e[i].y;a>t.y!=h>t.y&&t.x<(r-o)*(t.y-a)/(h-a)+o&&(n=!n)}return n},g=(t,e)=>{const s=u(t),n=[[s[0],s[1]],[s[1],s[2]],[s[2],s[3]],[s[3],s[0]]],o=p(e);for(const[t,e]of o)for(const[s,o]of n)if(i(t,e,s,o))return!0;return!1},y=(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))||(!!u(t).some(t=>m(t,e))||g(t,e))))(l(t),e),x=(t,e)=>((t,e)=>!(e.length<3)&&(!!u(t).every(t=>m(t,e))&&!g(t,e)))(l(t),e);function M(t,e,s,n){if(t.x===e.x&&t.y===e.y)return r(t,s,n);if(s.x===n.x&&s.y===n.y)return r(s,t,e);if(i(t,e,s,n))return 0;const o=[r(t,s,n),r(e,s,n),r(s,t,e),r(n,t,e)];return Math.min(...o)}function v(t,e,s){const o=s.width/2,a=s.height/2;return function(t,e,s){const o={x:s.minX,y:s.minY},a={x:s.maxX,y:s.minY},c={x:s.minX,y:s.maxY},d={x:s.maxX,y:s.maxY};if(i(t,e,o,a)||i(t,e,a,d)||i(t,e,d,c)||i(t,e,c,o))return 0;if(t.x>=s.minX&&t.x<=s.maxX&&t.y>=s.minY&&t.y<=s.maxY&&e.x>=s.minX&&e.x<=s.maxX&&e.y>=s.minY&&e.y<=s.maxY)return 0;const l=[r(o,t,e),r(a,t,e),r(c,t,e),r(d,t,e)];if(t.x>=s.minX&&t.x<=s.maxX&&t.y>=s.minY&&t.y<=s.maxY)return 0;if(e.x>=s.minX&&e.x<=s.maxX&&e.y>=s.minY&&e.y<=s.maxY)return 0;if(t.x<s.minX||t.x>s.maxX||t.y<s.minY||t.y>s.maxY){const e=n(t.x,s.minX,s.maxX),i=n(t.y,s.minY,s.maxY);l.push(h(t,{x:e,y:i}))}if(e.x<s.minX||e.x>s.maxX||e.y<s.minY||e.y>s.maxY){const t=n(e.x,s.minX,s.maxX),i=n(e.y,s.minY,s.maxY);l.push(h(e,{x:t,y:i}))}return Math.min(...l)}(t,e,{minX:s.center.x-o,maxX:s.center.x+o,minY:s.center.y-a,maxY:s.center.y+a})}function S(t,e,s){const n=s.x-e.x,i=s.y-e.y,o=n*n+i*i;if(0===o)return{x:e.x,y:e.y};let a=((t.x-e.x)*n+(t.y-e.y)*i)/o;a=Math.max(0,Math.min(1,a));return{x:e.x+a*n,y:e.y+a*i}}function b(){return b=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var n in s)({}).hasOwnProperty.call(s,n)&&(t[n]=s[n])}return t},b.apply(null,arguments)}function N(t,e){return(N=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 P(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(P=function(){return!!t})()}function C(t){var e="function"==typeof Map?new Map:void 0;return C=function(t){if(null===t||!function(t){try{return-1!==Function.toString.call(t).indexOf("[native code]")}catch(e){return"function"==typeof t}}(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,s)}function s(){return function(t,e,s){if(P())return Reflect.construct.apply(null,arguments);var n=[null];n.push.apply(n,e);var i=new(t.bind.apply(t,n));return s&&N(i,s.prototype),i}(t,arguments,I(this).constructor)}return s.prototype=Object.create(t.prototype,{constructor:{value:s,enumerable:!1,writable:!0,configurable:!0}}),N(s,t)},C(t)}var _={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 T(){for(var t=arguments.length,e=new Array(t),s=0;s<t;s++)e[s]=arguments[s];var n,i=e[0],o=[];for(n=1;n<e.length;n+=1)o.push(e[n]);return o.forEach(function(t){i=i.replace(/%[a-z]/,t)}),i}var E=function(t){var e,s;function n(e){var s;if("production"===process.env.NODE_ENV)s=t.call(this,"An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#"+e+" for more information.")||this;else{for(var n=arguments.length,i=new Array(n>1?n-1:0),o=1;o<n;o++)i[o-1]=arguments[o];s=t.call(this,T.apply(void 0,[_[e]].concat(i)))||this}return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(s)}return s=t,(e=n).prototype=Object.create(s.prototype),e.prototype.constructor=e,N(e,s),n}(C(Error));function A(t,e){return t.substr(-e.length)===e}var w=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;function z(t){return"string"!=typeof t?t:t.match(w)?parseFloat(t):t}var R=function(t){return function(e,s){void 0===s&&(s="16px");var n=e,i=s;if("string"==typeof e){if(!A(e,"px"))throw new E(69,t,e);n=z(e)}if("string"==typeof s){if(!A(s,"px"))throw new E(70,t,s);i=z(s)}if("string"==typeof n)throw new E(71,e,t);if("string"==typeof i)throw new E(72,s,t);return""+n/i+t}};R("em"),R("rem");function O(t){return Math.round(255*t)}function L(t,e,s){return O(t)+","+O(e)+","+O(s)}function D(t,e,s,n){if(void 0===n&&(n=L),0===e)return n(s,s,s);var i=(t%360+360)%360/60,o=(1-Math.abs(2*s-1))*e,a=o*(1-Math.abs(i%2-1)),r=0,h=0,c=0;i>=0&&i<1?(r=o,h=a):i>=1&&i<2?(r=a,h=o):i>=2&&i<3?(h=o,c=a):i>=3&&i<4?(h=a,c=o):i>=4&&i<5?(r=a,c=o):i>=5&&i<6&&(r=o,c=a);var d=s-o/2;return n(r+d,h+d,c+d)}var $={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 Y=/^#[a-fA-F0-9]{6}$/,X=/^#[a-fA-F0-9]{8}$/,k=/^#[a-fA-F0-9]{3}$/,B=/^#[a-fA-F0-9]{4}$/,F=/^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i,H=/^rgb(?:a)?\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i,Z=/^hsl\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*\)$/i,U=/^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 V(t){if("string"!=typeof t)throw new E(3);var e=function(t){if("string"!=typeof t)return t;var e=t.toLowerCase();return $[e]?"#"+$[e]:t}(t);if(e.match(Y))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(X)){var s=parseFloat((parseInt(""+e[7]+e[8],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[2],16),green:parseInt(""+e[3]+e[4],16),blue:parseInt(""+e[5]+e[6],16),alpha:s}}if(e.match(k))return{red:parseInt(""+e[1]+e[1],16),green:parseInt(""+e[2]+e[2],16),blue:parseInt(""+e[3]+e[3],16)};if(e.match(B)){var n=parseFloat((parseInt(""+e[4]+e[4],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[1],16),green:parseInt(""+e[2]+e[2],16),blue:parseInt(""+e[3]+e[3],16),alpha:n}}var i=F.exec(e);if(i)return{red:parseInt(""+i[1],10),green:parseInt(""+i[2],10),blue:parseInt(""+i[3],10)};var o=H.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=Z.exec(e);if(a){var r="rgb("+D(parseInt(""+a[1],10),parseInt(""+a[2],10)/100,parseInt(""+a[3],10)/100)+")",h=F.exec(r);if(!h)throw new E(4,e,r);return{red:parseInt(""+h[1],10),green:parseInt(""+h[2],10),blue:parseInt(""+h[3],10)}}var c=U.exec(e.substring(0,50));if(c){var d="rgb("+D(parseInt(""+c[1],10),parseInt(""+c[2],10)/100,parseInt(""+c[3],10)/100)+")",l=F.exec(d);if(!l)throw new E(4,e,d);return{red:parseInt(""+l[1],10),green:parseInt(""+l[2],10),blue:parseInt(""+l[3],10),alpha:parseFloat(""+c[4])>1?parseFloat(""+c[4])/100:parseFloat(""+c[4])}}throw new E(5)}function j(t){return function(t){var e,s=t.red/255,n=t.green/255,i=t.blue/255,o=Math.max(s,n,i),a=Math.min(s,n,i),r=(o+a)/2;if(o===a)return void 0!==t.alpha?{hue:0,saturation:0,lightness:r,alpha:t.alpha}:{hue:0,saturation:0,lightness:r};var h=o-a,c=r>.5?h/(2-o-a):h/(o+a);switch(o){case s:e=(n-i)/h+(n<i?6:0);break;case n:e=(i-s)/h+2;break;default:e=(s-n)/h+4}return e*=60,void 0!==t.alpha?{hue:e,saturation:c,lightness:r,alpha:t.alpha}:{hue:e,saturation:c,lightness:r}}(V(t))}var W=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 G(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function q(t){return G(Math.round(255*t))}function K(t,e,s){return W("#"+q(t)+q(e)+q(s))}function J(t,e,s){return D(t,e,s,K)}function Q(t,e,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s)return W("#"+G(t)+G(e)+G(s));if("object"==typeof t&&void 0===e&&void 0===s)return W("#"+G(t.red)+G(t.green)+G(t.blue));throw new E(6)}function tt(t,e,s,n){if("string"==typeof t&&"number"==typeof e){var i=V(t);return"rgba("+i.red+","+i.green+","+i.blue+","+e+")"}if("number"==typeof t&&"number"==typeof e&&"number"==typeof s&&"number"==typeof n)return n>=1?Q(t,e,s):"rgba("+t+","+e+","+s+","+n+")";if("object"==typeof t&&void 0===e&&void 0===s&&void 0===n)return t.alpha>=1?Q(t.red,t.green,t.blue):"rgba("+t.red+","+t.green+","+t.blue+","+t.alpha+")";throw new E(7)}function et(t){if("object"!=typeof t)throw new E(8);if(function(t){return"number"==typeof t.red&&"number"==typeof t.green&&"number"==typeof t.blue&&"number"==typeof t.alpha}(t))return tt(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 Q(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&"number"==typeof t.alpha}(t))return function(t,e,s,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s&&"number"==typeof n)return n>=1?J(t,e,s):"rgba("+D(t,e,s)+","+n+")";if("object"==typeof t&&void 0===e&&void 0===s&&void 0===n)return t.alpha>=1?J(t.hue,t.saturation,t.lightness):"rgba("+D(t.hue,t.saturation,t.lightness)+","+t.alpha+")";throw new E(2)}(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&("number"!=typeof t.alpha||void 0===t.alpha)}(t))return function(t,e,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof s)return J(t,e,s);if("object"==typeof t&&void 0===e&&void 0===s)return J(t.hue,t.saturation,t.lightness);throw new E(1)}(t);throw new E(8)}function st(t,e,s){return function(){var n=s.concat(Array.prototype.slice.call(arguments));return n.length>=e?t.apply(this,n):st(t,e,n)}}function nt(t){return st(t,t.length,[])}nt(function(t,e){if("transparent"===e)return e;var s=j(e);return et(b({},s,{hue:s.hue+parseFloat(t)}))});function it(t,e,s){return Math.max(t,Math.min(e,s))}nt(function(t,e){if("transparent"===e)return e;var s=j(e);return et(b({},s,{lightness:it(0,1,s.lightness-parseFloat(t))}))});nt(function(t,e){if("transparent"===e)return e;var s=j(e);return et(b({},s,{saturation:it(0,1,s.saturation-parseFloat(t))}))});nt(function(t,e){if("transparent"===e)return e;var s=j(e);return et(b({},s,{lightness:it(0,1,s.lightness+parseFloat(t))}))});var ot=nt(function(t,e,s){if("transparent"===e)return s;if("transparent"===s)return e;if(0===t)return s;var n=V(e),i=b({},n,{alpha:"number"==typeof n.alpha?n.alpha:1}),o=V(s),a=b({},o,{alpha:"number"==typeof o.alpha?o.alpha:1}),r=i.alpha-a.alpha,h=2*parseFloat(t)-1,c=((h*r===-1?h:h+r)/(1+h*r)+1)/2,d=1-c;return tt({red:Math.floor(i.red*c+a.red*d),green:Math.floor(i.green*c+a.green*d),blue:Math.floor(i.blue*c+a.blue*d),alpha:i.alpha*parseFloat(t)+a.alpha*(1-parseFloat(t))})});nt(function(t,e){if("transparent"===e)return e;var s=V(e);return tt(b({},s,{alpha:it(0,1,(100*("number"==typeof s.alpha?s.alpha:1)+100*parseFloat(t))/100)}))});nt(function(t,e){if("transparent"===e)return e;var s=j(e);return et(b({},s,{saturation:it(0,1,s.saturation+parseFloat(t))}))});nt(function(t,e){return"transparent"===e?e:et(b({},j(e),{hue:parseFloat(t)}))});nt(function(t,e){return"transparent"===e?e:et(b({},j(e),{lightness:parseFloat(t)}))});nt(function(t,e){return"transparent"===e?e:et(b({},j(e),{saturation:parseFloat(t)}))});nt(function(t,e){return"transparent"===e?e:ot(parseFloat(t),"rgb(0, 0, 0)",e)});nt(function(t,e){return"transparent"===e?e:ot(parseFloat(t),"rgb(255, 255, 255)",e)});var at=nt(function(t,e){if("transparent"===e)return e;var s=V(e);return tt(b({},s,{alpha:it(0,1,+(100*("number"==typeof s.alpha?s.alpha:1)-100*parseFloat(t)).toFixed(2)/100)}))}),rt=["blue","orange","purple","cyan","magenta","yellowgreen","darkgoldenrod","deeppink"],ht=(t,e)=>{const s={};for(let n=0;n<t.connections.length;n++){const i=t.connections[n],o=e?.getNetConnectedToId(i.name);o&&!s[o]&&(s[o]=`hsl(${300*n/t.connections.length}, 100%, 50%)`),s[i.name]=(o?s[o]:null)??`hsl(${340*n/t.connections.length}, 100%, 50%)`}return s},ct=(t,e)=>{try{return at(e,t)}catch(e){return console.error(e),t}},dt=(t,e)=>"top"===t?0:"bottom"===t?e-1:parseInt(t.slice(5)),lt=(t,e=1)=>{const s=(("width"in t?t.width:t)/.5/2)**1.1*e;return 1===t.availableZ?.length&&s>1?1:s},ut=(t,e=.5,s=16)=>{let n=0,i=t;for(;n<s;){if(lt({width:i})<=e)break;i/=2,n++}return Math.max(1,n)};function pt(t,e,s=0,n=t.length-1,i=mt){for(;n>s;){if(n-s>600){const o=n-s+1,a=e-s+1,r=Math.log(o),h=.5*Math.exp(2*r/3),c=.5*Math.sqrt(r*h*(o-h)/o)*(a-o/2<0?-1:1);pt(t,e,Math.max(s,Math.floor(e-a*h/o+c)),Math.min(n,Math.floor(e+(o-a)*h/o+c)),i)}const o=t[e];let a=s,r=n;for(ft(t,s,e),i(t[n],o)>0&&ft(t,s,n);a<r;){for(ft(t,a,r),a++,r--;i(t[a],o)<0;)a++;for(;i(t[r],o)>0;)r--}0===i(t[s],o)?ft(t,s,r):(r++,ft(t,r,n)),r<=e&&(s=r+1),e<=r&&(n=r-1)}}function ft(t,e,s){const n=t[e];t[e]=t[s],t[s]=n}function mt(t,e){return t<e?-1:t>e?1:0}var gt=class{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(.4*this._maxEntries)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const s=[];if(!Tt(t,e))return s;const n=this.toBBox,i=[];for(;e;){for(let o=0;o<e.children.length;o++){const a=e.children[o],r=e.leaf?n(a):a;Tt(t,r)&&(e.leaf?s.push(a):_t(t,r)?this._all(a,s):i.push(a))}e=i.pop()}return s}collides(t){let e=this.data;if(!Tt(t,e))return!1;const s=[];for(;e;){for(let n=0;n<e.children.length;n++){const i=e.children[n],o=e.leaf?this.toBBox(i):i;if(Tt(t,o)){if(e.leaf||_t(t,o))return!0;s.push(i)}}e=s.pop()}return!1}load(t){if(!t||!t.length)return this;if(t.length<this._minEntries){for(let e=0;e<t.length;e++)this.insert(t[e]);return this}let e=this._build(t.slice(),0,t.length-1,0);if(this.data.children.length)if(this.data.height===e.height)this._splitRoot(this.data,e);else{if(this.data.height<e.height){const t=this.data;this.data=e,e=t}this._insert(e,this.data.height-e.height-1,!0)}else this.data=e;return this}insert(t){return t&&this._insert(t,this.data.height-1),this}clear(){return this.data=Et([]),this}remove(t,e){if(!t)return this;let s=this.data;const n=this.toBBox(t),i=[],o=[];let a,r,h;for(;s||i.length;){if(s||(s=i.pop(),r=i[i.length-1],a=o.pop(),h=!0),s.leaf){const n=yt(t,s.children,e);if(-1!==n)return s.children.splice(n,1),i.push(s),this._condense(i),this}h||s.leaf||!_t(s,n)?r?(a++,s=r.children[a],h=!1):s=null:(i.push(s),o.push(a),a=0,r=s,s=s.children[0])}return this}toBBox(t){return t}compareMinX(t,e){return t.minX-e.minX}compareMinY(t,e){return t.minY-e.minY}toJSON(){return this.data}fromJSON(t){return this.data=t,this}_all(t,e){const s=[];for(;t;)t.leaf?e.push(...t.children):s.push(...t.children),t=s.pop();return e}_build(t,e,s,n){const i=s-e+1;let o,a=this._maxEntries;if(i<=a)return o=Et(t.slice(e,s+1)),xt(o,this.toBBox),o;n||(n=Math.ceil(Math.log(i)/Math.log(a)),a=Math.ceil(i/Math.pow(a,n-1))),o=Et([]),o.leaf=!1,o.height=n;const r=Math.ceil(i/a),h=r*Math.ceil(Math.sqrt(a));At(t,e,s,h,this.compareMinX);for(let i=e;i<=s;i+=h){const e=Math.min(i+h-1,s);At(t,i,e,r,this.compareMinY);for(let s=i;s<=e;s+=r){const i=Math.min(s+r-1,e);o.children.push(this._build(t,s,i,n-1))}}return xt(o,this.toBBox),o}_chooseSubtree(t,e,s,n){for(;n.push(e),!e.leaf&&n.length-1!==s;){let s,n=1/0,i=1/0;for(let o=0;o<e.children.length;o++){const a=e.children[o],r=Nt(a),h=Pt(t,a)-r;h<i?(i=h,n=r<n?r:n,s=a):h===i&&r<n&&(n=r,s=a)}e=s||e.children[0]}return e}_insert(t,e,s){const n=s?t:this.toBBox(t),i=[],o=this._chooseSubtree(n,this.data,e,i);for(o.children.push(t),vt(o,n);e>=0&&i[e].children.length>this._maxEntries;)this._split(i,e),e--;this._adjustParentBBoxes(n,i,e)}_split(t,e){const s=t[e],n=s.children.length,i=this._minEntries;this._chooseSplitAxis(s,i,n);const o=this._chooseSplitIndex(s,i,n),a=Et(s.children.splice(o,s.children.length-o));a.height=s.height,a.leaf=s.leaf,xt(s,this.toBBox),xt(a,this.toBBox),e?t[e-1].children.push(a):this._splitRoot(s,a)}_splitRoot(t,e){this.data=Et([t,e]),this.data.height=t.height+1,this.data.leaf=!1,xt(this.data,this.toBBox)}_chooseSplitIndex(t,e,s){let n,i=1/0,o=1/0;for(let a=e;a<=s-e;a++){const e=Mt(t,0,a,this.toBBox),r=Mt(t,a,s,this.toBBox),h=Ct(e,r),c=Nt(e)+Nt(r);h<i?(i=h,n=a,o=c<o?c:o):h===i&&c<o&&(o=c,n=a)}return n||s-e}_chooseSplitAxis(t,e,s){const n=t.leaf?this.compareMinX:St,i=t.leaf?this.compareMinY:bt;this._allDistMargin(t,e,s,n)<this._allDistMargin(t,e,s,i)&&t.children.sort(n)}_allDistMargin(t,e,s,n){t.children.sort(n);const i=this.toBBox,o=Mt(t,0,e,i),a=Mt(t,s-e,s,i);let r=It(o)+It(a);for(let n=e;n<s-e;n++){const e=t.children[n];vt(o,t.leaf?i(e):e),r+=It(o)}for(let n=s-e-1;n>=e;n--){const e=t.children[n];vt(a,t.leaf?i(e):e),r+=It(a)}return r}_adjustParentBBoxes(t,e,s){for(let n=s;n>=0;n--)vt(e[n],t)}_condense(t){for(let e,s=t.length-1;s>=0;s--)0===t[s].children.length?s>0?(e=t[s-1].children,e.splice(e.indexOf(t[s]),1)):this.clear():xt(t[s],this.toBBox)}};function yt(t,e,s){if(!s)return e.indexOf(t);for(let n=0;n<e.length;n++)if(s(t,e[n]))return n;return-1}function xt(t,e){Mt(t,0,t.children.length,e,t)}function Mt(t,e,s,n,i){i||(i=Et(null)),i.minX=1/0,i.minY=1/0,i.maxX=-1/0,i.maxY=-1/0;for(let o=e;o<s;o++){const e=t.children[o];vt(i,t.leaf?n(e):e)}return i}function vt(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 St(t,e){return t.minX-e.minX}function bt(t,e){return t.minY-e.minY}function Nt(t){return(t.maxX-t.minX)*(t.maxY-t.minY)}function It(t){return t.maxX-t.minX+(t.maxY-t.minY)}function Pt(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 Ct(t,e){const s=Math.max(t.minX,e.minX),n=Math.max(t.minY,e.minY),i=Math.min(t.maxX,e.maxX),o=Math.min(t.maxY,e.maxY);return Math.max(0,i-s)*Math.max(0,o-n)}function _t(t,e){return t.minX<=e.minX&&t.minY<=e.minY&&e.maxX<=t.maxX&&e.maxY<=t.maxY}function Tt(t,e){return e.minX<=t.maxX&&e.minY<=t.maxY&&e.maxX>=t.minX&&e.maxY>=t.minY}function Et(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function At(t,e,s,n,i){const o=[e,s];for(;o.length;){if((s=o.pop())-(e=o.pop())<=n)continue;const a=e+Math.ceil((s-e)/n/2)*n;pt(t,a,e,s,i),o.push(e,a,a,s)}}var wt=class{tree;constructor(t=9){this.tree=new gt(t)}insert(t,e,s,n,i){this.tree.insert({minX:e,minY:s,maxX:n,maxY:i,data:t})}bulkLoad(t){const e=t.map(({item:t,minX:e,minY:s,maxX:n,maxY:i})=>({minX:e,minY:s,maxX:n,maxY:i,data:t}));this.tree.load(e)}search(t,e,s,n){return this.tree.search({minX:t,minY:e,maxX:s,maxY:n}).map(t=>t.data)}clear(){this.tree.clear()}},zt=class{constructor(){this.ids=[],this.values=[],this.length=0}clear(){this.length=0}push(t,e){let s=this.length++;for(;s>0;){const t=s-1>>1,n=this.values[t];if(e>=n)break;this.ids[s]=this.ids[t],this.values[s]=n,s=t}this.ids[s]=t,this.values[s]=e}pop(){if(0===this.length)return;const t=this.ids,e=this.values,s=t[0],n=--this.length;if(n>0){const s=t[n],i=e[n];let o=0;const a=n>>1;for(;o<a;){const s=1+(o<<1),a=s+1,r=s+(+(a<n)&+(e[a]<e[s]));if(e[r]>=i)break;t[o]=t[r],e[o]=e[r],o=r}t[o]=s,e[o]=i}return s}peek(){return this.length>0?this.ids[0]:void 0}peekValue(){return this.length>0?this.values[0]:void 0}shrink(){this.ids.length=this.values.length=this.length}},Rt=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],Ot=class t{static from(e,s=0){if(s%8!=0)throw new Error("byteOffset must be 8-byte aligned.");if(!e||void 0===e.byteLength||e.buffer)throw new Error("Data must be an instance of ArrayBuffer or SharedArrayBuffer.");const[n,i]=new Uint8Array(e,s+0,2);if(251!==n)throw new Error("Data does not appear to be in a Flatbush format.");const o=i>>4;if(3!==o)throw new Error(`Got v${o} data when expected v3.`);const a=Rt[15&i];if(!a)throw new Error("Unrecognized array type.");const[r]=new Uint16Array(e,s+2,1),[h]=new Uint32Array(e,s+4,1);return new t(h,r,a,void 0,e,s)}constructor(t,e=16,s=Float64Array,n=ArrayBuffer,i,o=0){if(void 0===t)throw new Error("Missing required argument: numItems.");if(isNaN(t)||t<=0)throw new Error(`Unexpected numItems value: ${t}.`);this.numItems=+t,this.nodeSize=Math.min(Math.max(+e,2),65535),this.byteOffset=o;let a=t,r=a;this._levelBounds=[4*a];do{a=Math.ceil(a/this.nodeSize),r+=a,this._levelBounds.push(4*r)}while(1!==a);this.ArrayType=s,this.IndexArrayType=r<16384?Uint16Array:Uint32Array;const h=Rt.indexOf(s),c=4*r*s.BYTES_PER_ELEMENT;if(h<0)throw new Error(`Unexpected typed array class: ${s}.`);if(i)this.data=i,this._boxes=new s(i,o+8,4*r),this._indices=new this.IndexArrayType(i,o+8+c,r),this._pos=4*r,this.minX=this._boxes[this._pos-4],this.minY=this._boxes[this._pos-3],this.maxX=this._boxes[this._pos-2],this.maxY=this._boxes[this._pos-1];else{const i=this.data=new n(8+c+r*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new s(i,8,4*r),this._indices=new this.IndexArrayType(i,8+c,r),this._pos=0,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,new Uint8Array(i,0,2).set([251,48+h]),new Uint16Array(i,2,1)[0]=e,new Uint32Array(i,4,1)[0]=t}this._queue=new zt}add(t,e,s=t,n=e){const i=this._pos>>2,o=this._boxes;return this._indices[i]=i,o[this._pos++]=t,o[this._pos++]=e,o[this._pos++]=s,o[this._pos++]=n,t<this.minX&&(this.minX=t),e<this.minY&&(this.minY=e),s>this.maxX&&(this.maxX=s),n>this.maxY&&(this.maxY=n),i}finish(){if(this._pos>>2!==this.numItems)throw new Error(`Added ${this._pos>>2} items when expected ${this.numItems}.`);const t=this._boxes;if(this.numItems<=this.nodeSize)return t[this._pos++]=this.minX,t[this._pos++]=this.minY,t[this._pos++]=this.maxX,void(t[this._pos++]=this.maxY);const e=this.maxX-this.minX||1,s=this.maxY-this.minY||1,n=new Uint32Array(this.numItems);for(let i=0,o=0;i<this.numItems;i++){const a=t[o++],r=t[o++],h=t[o++],c=t[o++],d=Math.floor(65535*((a+h)/2-this.minX)/e),l=Math.floor(65535*((r+c)/2-this.minY)/s);n[i]=Yt(d,l)}Dt(n,t,this._indices,0,this.numItems-1,this.nodeSize);for(let e=0,s=0;e<this._levelBounds.length-1;e++){const n=this._levelBounds[e];for(;s<n;){const e=s;let i=t[s++],o=t[s++],a=t[s++],r=t[s++];for(let e=1;e<this.nodeSize&&s<n;e++)i=Math.min(i,t[s++]),o=Math.min(o,t[s++]),a=Math.max(a,t[s++]),r=Math.max(r,t[s++]);this._indices[this._pos>>2]=e,t[this._pos++]=i,t[this._pos++]=o,t[this._pos++]=a,t[this._pos++]=r}}}search(t,e,s,n,i){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let o=this._boxes.length-4;const a=[],r=[];for(;void 0!==o;){const h=Math.min(o+4*this.nodeSize,Lt(o,this._levelBounds));for(let c=o;c<h;c+=4){const h=this._boxes[c];if(s<h)continue;const d=this._boxes[c+1];if(n<d)continue;const l=this._boxes[c+2];if(t>l)continue;const u=this._boxes[c+3];if(e>u)continue;const p=0|this._indices[c>>2];o>=4*this.numItems?a.push(p):(void 0===i||i(p,h,d,l,u))&&r.push(p)}o=a.pop()}return r}neighbors(t,e,s=1/0,n=1/0,i){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let o=this._boxes.length-4;const a=this._queue,r=[],h=n*n;t:for(;void 0!==o;){const n=Math.min(o+4*this.nodeSize,Lt(o,this._levelBounds));for(let s=o;s<n;s+=4){const n=0|this._indices[s>>2],r=this._boxes[s],c=this._boxes[s+1],d=this._boxes[s+2],l=this._boxes[s+3],u=t<r?r-t:t>d?t-d:0,p=e<c?c-e:e>l?e-l:0,f=u*u+p*p;f>h||(o>=4*this.numItems?a.push(n<<1,f):(void 0===i||i(n))&&a.push(1+(n<<1),f))}for(;a.length&&1&a.peek();){if(a.peekValue()>h)break t;if(r.push(a.pop()>>1),r.length===s)break t}o=a.length?a.pop()>>1:void 0}return a.clear(),r}};function Lt(t,e){let s=0,n=e.length-1;for(;s<n;){const i=s+n>>1;e[i]>t?n=i:s=i+1}return e[s]}function Dt(t,e,s,n,i,o){if(Math.floor(n/o)>=Math.floor(i/o))return;const a=t[n],r=t[n+i>>1],h=t[i];let c=h;const d=Math.max(a,r);h>d?c=d:d===a?c=Math.max(r,h):d===r&&(c=Math.max(a,h));let l=n-1,u=i+1;for(;;){do{l++}while(t[l]<c);do{u--}while(t[u]>c);if(l>=u)break;$t(t,e,s,l,u)}Dt(t,e,s,n,u,o),Dt(t,e,s,u+1,i,o)}function $t(t,e,s,n,i){const o=t[n];t[n]=t[i],t[i]=o;const a=4*n,r=4*i,h=e[a],c=e[a+1],d=e[a+2],l=e[a+3];e[a]=e[r],e[a+1]=e[r+1],e[a+2]=e[r+2],e[a+3]=e[r+3],e[r]=h,e[r+1]=c,e[r+2]=d,e[r+3]=l;const u=s[n];s[n]=s[i],s[i]=u}function Yt(t,e){let s=t^e,n=65535^s,i=65535^(t|e),o=t&(65535^e),a=s|n>>1,r=s>>1^s,h=i>>1^n&o>>1^i,c=s&i>>1^o>>1^o;s=a,n=r,i=h,o=c,a=s&s>>2^n&n>>2,r=s&n>>2^n&(s^n)>>2,h^=s&i>>2^n&o>>2,c^=n&i>>2^(s^n)&o>>2,s=a,n=r,i=h,o=c,a=s&s>>4^n&n>>4,r=s&n>>4^n&(s^n)>>4,h^=s&i>>4^n&o>>4,c^=n&i>>4^(s^n)&o>>4,s=a,n=r,i=h,o=c,h^=s&i>>8^n&o>>8,c^=n&i>>8^(s^n)&o>>8,s=h^h>>1,n=c^c>>1;let d=t^e,l=n|65535^(d|s);return d=16711935&(d|d<<8),d=252645135&(d|d<<4),d=858993459&(d|d<<2),d=1431655765&(d|d<<1),l=16711935&(l|l<<8),l=252645135&(l|l<<4),l=858993459&(l|l<<2),l=1431655765&(l|l<<1),(l<<1|d)>>>0}var Xt=class{index;items=[];currentIndex=0;capacity;constructor(t){this.capacity=Math.max(1,t),this.index=new Ot(this.capacity)}insert(t,e,s,n,i){if(this.currentIndex>=this.index.numItems)throw new Error("Exceeded initial capacity");this.items[this.currentIndex]=t,this.index.add(e,s,n,i),this.currentIndex++}finish(){this.index.finish()}search(t,e,s,n){return this.index.search(t,e,s,n).map(t=>this.items[t]||null).filter(Boolean)}clear(){this.items=[],this.currentIndex=0,this.index=new Ot(this.capacity)}},kt=class{idx;storage=[];constructor(t="native",e=[]){"flatbush"===t?0===e.length?(this.idx=new wt,t="rbush"):this.idx=new Xt(e.length):this.idx="rbush"===t?new wt:new class{shi=new Bt(e);insert(t){}search(t,e,s,n){const i=(t+s)/2,o=(e+n)/2,a=s-t,r=n-e;return this.shi.getNodesInArea(i,o,a,r)}clear(){}},e.forEach(t=>this.insert(t)),"flatbush"===t&&e.length>0&&this.idx.finish?.()}insert(t){this.storage.push(t),this.idx.insert(t,t.center.x-t.width/2,t.center.y-t.height/2,t.center.x+t.width/2,t.center.y+t.height/2)}search(t){return this.idx.search(t.minX,t.minY,t.maxX,t.maxY)}searchArea(t,e,s,n){return this.search({minX:t-s/2,minY:e-n/2,maxX:t+s/2,maxY:e+n/2})}},Bt=class{constructor(t){this.obstacles=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const s=t[e],n=s.center.x-s.width/2,i=s.center.y-s.height/2,o=s.center.x+s.width/2,a=s.center.y+s.height/2;for(let t=n;t<=o;t+=this.CELL_SIZE)for(let n=i;n<=a;n+=this.CELL_SIZE){const i=this.getBucketKey(t,n),o=this.buckets.get(i);o?o.push([s,e]):this.buckets.set(i,[[s,e]])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,s,n){const i=[],o=new Set,a=e-n/2,r=t+s/2,h=e+n/2;for(let e=t-s/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const s=this.getBucketKey(e,t),n=this.buckets.get(s)||[];for(const t of n)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},Ft=class{constructor(t){this.targets=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const s=t[e],n=Math.floor(s.bounds.minX/this.CELL_SIZE)*this.CELL_SIZE,i=Math.floor(s.bounds.minY/this.CELL_SIZE)*this.CELL_SIZE,o=s.bounds.maxX,a=s.bounds.maxY;for(let t=n;t<=o;t+=this.CELL_SIZE)for(let n=i;n<=a;n+=this.CELL_SIZE){const i=this.getBucketKey(t,n),o=this.buckets.get(i);o?o.push([s,e]):this.buckets.set(i,[[s,e]])}}}buckets;CELL_SIZE=5;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getTargetsInArea(t,e,s,n){const i=[],o=new Set,a=Math.floor((t-s/2)/this.CELL_SIZE)*this.CELL_SIZE,r=Math.floor((e-n/2)/this.CELL_SIZE)*this.CELL_SIZE,h=t+s/2,c=e+n/2;for(let t=a;t<=h;t+=this.CELL_SIZE)for(let e=r;e<=c;e+=this.CELL_SIZE){const s=this.getBucketKey(t,e),n=this.buckets.get(s)||[];for(const t of n)o.has(t[1])||(o.add(t[1]),i.push(t[0]))}return i}},Ht=class extends e{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.MAX_DEPTH=e?.capacityDepth??this.MAX_DEPTH,this.MAX_ITERATIONS=1e5,this.layerCount=t.layerCount??2,this.outlinePolygon=t.outline&&t.outline.length>=3?t.outline:void 0;for(const e of t.obstacles)if(!e.zLayers){const s=[];for(const n of e.layers)s.push(dt(n,t.layerCount));e.zLayers=s}const s={x:(t.bounds.minX+t.bounds.maxX)/2,y:(t.bounds.minY+t.bounds.maxY)/2},n={width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},i=Math.max(n.width,n.height);this.unfinishedNodes=[{capacityMeshNodeId:this.getNextNodeId(),center:s,width:i,height:i,layer:"top",availableZ:Array.from({length:this.layerCount},(t,e)=>e),_depth:0,_containsTarget:!0,_containsObstacle:!0,_completelyInsideObstacle:!1}],this.finishedNodes=[],this.nodeToXYOverlappingObstaclesMap=new Map,this.obstacleTree=new kt("flatbush",this.srj.obstacles),this.targets=this.computeTargets(),this.targetTree=new Ft(this.targets)}unfinishedNodes;finishedNodes;nodeToXYOverlappingObstaclesMap;layerCount;outlinePolygon;MAX_DEPTH=4;targets;targetTree;obstacleTree;computeTargets(){const t=[];for(const e of this.srj.connections)for(const s of e.pointsToConnect){const n=this.obstacleTree.searchArea(s.x,s.y,.01,.01).filter(t=>t.zLayers.some(t=>t===dt(s.layer,this.layerCount)));let i={minX:s.x-.005,minY:s.y-.005,maxX:s.x+.005,maxY:s.y+.005};n.length>0&&(i={minX:Math.min(...n.map(t=>t.center.x-t.width/2)),minY:Math.min(...n.map(t=>t.center.y-t.height/2)),maxX:Math.max(...n.map(t=>t.center.x+t.width/2)),maxY:Math.max(...n.map(t=>t.center.y+t.height/2))});const o={...s,connectionName:e.name,availableZ:[dt(s.layer,this.layerCount)],bounds:i};t.push(o)}return t}getNodeBounds(t){const e=t.width/2,s=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-s,maxY:t.center.y+s}}getNodeRect(t){return{center:{x:t.center.x,y:t.center.y},width:t.width,height:t.height}}_nextNodeCounter=0;getNextNodeId(){return"cn"+this._nextNodeCounter++}getCapacityFromDepth(t){return(this.MAX_DEPTH-t+1)**2}getTargetIfNodeContainsTarget(t){const e=t.width>4*this.targetTree.CELL_SIZE?this.targets:this.targetTree.getTargetsInArea(t.center.x,t.center.y,t.width,t.height);for(const s of e)if(s.bounds.minX<=t.center.x+t.width/2&&s.bounds.maxX>=t.center.x-t.width/2&&s.bounds.minY<=t.center.y+t.height/2&&s.bounds.maxY>=t.center.y-t.height/2&&s.availableZ.some(e=>t.availableZ.includes(e)))return s;return null}getXYOverlappingObstacles(t){const e=this.nodeToXYOverlappingObstaclesMap.get(t.capacityMeshNodeId);if(e)return e;const s=[],n=this.getNodeBounds(t),i=n.minX,o=n.maxX,a=n.minY,r=n.maxY,h=t._parent?this.getXYOverlappingObstacles(t._parent):this.srj.obstacles;for(const t of h){const e=t.center.x-t.width/2,n=t.center.x+t.width/2,h=t.center.y-t.height/2,c=t.center.y+t.height/2;o>=e&&i<=n&&r>=h&&a<=c?s.push(t):(i>=e&&o<=n&&a>=h&&r<=c||e>=i&&n<=o&&h>=a&&c<=r)&&s.push(t)}return this.nodeToXYOverlappingObstaclesMap.set(t.capacityMeshNodeId,s),s}getXYZOverlappingObstacles(t){const e=this.getXYOverlappingObstacles(t),s=[];for(const n of e)t.availableZ.some(t=>n.zLayers.includes(t))&&s.push(n);return s}doesNodeOverlapObstacle(t){if(this.getXYZOverlappingObstacles(t).length>0)return!0;const e=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!x(e,this.outlinePolygon))return!0}return e.minX<this.srj.bounds.minX||e.maxX>this.srj.bounds.maxX||e.minY<this.srj.bounds.minY||e.maxY>this.srj.bounds.maxY}isNodeCompletelyInsideObstacle(t){const e=this.getXYZOverlappingObstacles(t),s=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!y(e,this.outlinePolygon))return!0}for(const t of e){const e=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2;if(s.minX>=e&&s.maxX<=n&&s.minY>=i&&s.maxY<=o)return!0}return!1}getChildNodes(t){if(t._depth===this.MAX_DEPTH)return[];const e=[],s={width:t.width/2,height:t.height/2},n=[{x:t.center.x-s.width/2,y:t.center.y-s.height/2},{x:t.center.x+s.width/2,y:t.center.y-s.height/2},{x:t.center.x-s.width/2,y:t.center.y+s.height/2},{x:t.center.x+s.width/2,y:t.center.y+s.height/2}];for(const i of n){const n={capacityMeshNodeId:this.getNextNodeId(),center:i,width:s.width,height:s.height,layer:t.layer,availableZ:t.availableZ,_depth:(t._depth??0)+1,_parent:t};n._containsObstacle=this.doesNodeOverlapObstacle(n);const o=this.getTargetIfNodeContainsTarget(n);o&&(n._targetConnectionName=o.connectionName,n.availableZ=o.availableZ,n._containsTarget=!0),n._containsObstacle&&(n._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(n)),n._completelyInsideObstacle&&!n._containsTarget||e.push(n)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||!(!t._containsObstacle||t._completelyInsideObstacle))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),s=[],n=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t);e?n.push(t):e||t._containsObstacle?!e&&t._containsTarget&&s.push(t):s.push(t)}this.unfinishedNodes.push(...n),this.finishedNodes.push(...s)}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Mesh Visualization"};if(this.outlinePolygon&&this.outlinePolygon.length>=2){const e=this.outlinePolygon.map(t=>({x:t.x,y:t.y}));e.push({...e[0]}),t.lines.push({points:e,strokeColor:"rgba(0, 136, 255, 0.95)",label:"outline"});for(const e of this.outlinePolygon)t.points.push({x:e.x,y:e.y,color:"rgba(0, 136, 255, 0.95)"})}for(const e of this.srj.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:1===e.zLayers?.length&&e.zLayers?.includes(1)?"rgba(0,0,255,0.3)":"rgba(255,0,0,0.3)",stroke:"red",label:["obstacle",`z: ${e.zLayers.join(",")}`].join("\n")});const e=[...this.finishedNodes,...this.unfinishedNodes];for(const s of e){const e=Math.min(...s.availableZ),n=this.unfinishedNodes.length>0&&s===this.unfinishedNodes[this.unfinishedNodes.length-1];t.rects.push({center:{x:s.center.x+e*s.width*.05,y:s.center.y-e*s.width*.05},width:Math.max(s.width-2,.8*s.width),height:Math.max(s.height-2,.8*s.height),fill:s._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[s.availableZ.join(",")]??"rgba(0,200,200,0.1)",stroke:n?"rgba(255,165,0,0.5)":void 0,label:[s.capacityMeshNodeId,`availableZ: ${s.availableZ.join(",")}`,`target? ${s._containsTarget??!1}`,`obs? ${s._containsObstacle??!1}`,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`capacity: ${lt(s).toFixed(2)}`].join("\n")})}return t.rects.sort((t,e)=>t.center.y-e.center.y),this.srj.connections.forEach((e,s)=>{const n=rt[s%rt.length];for(const i of e.pointsToConnect)t.points.push({x:i.x,y:i.y,label:`conn-${s} (${i.layer})`,color:n})}),t}},Zt=class extends Ht{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e}VIA_DIAMETER=.6;OBSTACLE_MARGIN=.1;OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES=.2;isNodeCompletelyOutsideBounds(t){if(this.outlinePolygon){const e=this.getNodeRect(t);if(!y(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!!y(e,this.outlinePolygon)&&!x(e,this.outlinePolygon)}return t.center.x-t.width/2<this.srj.bounds.minX||t.center.x+t.width/2>this.srj.bounds.maxX||t.center.y-t.height/2<this.srj.bounds.minY||t.center.y+t.height/2>this.srj.bounds.maxY}getObstacleCoveragePercentage(t){const e=this.getXYZOverlappingObstacles(t);if(0===e.length)return 0;const s=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2,a=t.width*t.height;let r=0;for(const t of e){const e=Math.max(s,t.center.x-t.width/2),a=Math.min(n,t.center.x+t.width/2),h=Math.max(i,t.center.y-t.height/2),c=Math.min(o,t.center.y+t.height/2);if(e<a&&h<c){r+=(a-e)*(c-h)}}return r/a}shouldFilterSingleLayerNodeForObstacle(t){if(1!==t.availableZ.length)return!1;if(!t._containsObstacle)return!1;return this.getObstacleCoveragePercentage(t)>this.OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES}shouldFilterNodeForObstacle(t){return!!t._containsObstacle&&(1!==t.availableZ.length||this.shouldFilterSingleLayerNodeForObstacle(t))}createChildNodeAtPosition(t,e){const s={capacityMeshNodeId:this.getNextNodeId(),center:e.center,width:e.width,height:e.height,layer:t.layer,availableZ:e.availableZ,_depth:e._depth??(t._depth??0)+1,_parent:t},n=this.getXYZOverlappingObstacles(s);s._containsObstacle=n.length>0||this.isNodePartiallyOutsideBounds(s);const i=this.getTargetIfNodeContainsTarget(s);return i&&(s._targetConnectionName=i.connectionName,s._containsTarget=!0),s._containsObstacle&&(s._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(s)),s}getZSubdivisionChildNodes(t){if(1===t.availableZ.length)return[];const e=[],s=t.availableZ.map(t=>[t]);for(const n of s){const s=this.createChildNodeAtPosition(t,{center:{...t.center},width:t.width,height:t.height,availableZ:n,_depth:t._depth});this.isNodeCompletelyOutsideBounds(s)||e.push(s)}return e}getChildNodes(t){if(t._depth>=this.MAX_DEPTH)return[];const e=[],s={width:t.width/2,height:t.height/2},n=[{x:t.center.x-s.width/2,y:t.center.y-s.height/2},{x:t.center.x+s.width/2,y:t.center.y-s.height/2},{x:t.center.x-s.width/2,y:t.center.y+s.height/2},{x:t.center.x+s.width/2,y:t.center.y+s.height/2}];for(const i of n){const n=this.createChildNodeAtPosition(t,{center:i,width:s.width,height:s.height,availableZ:t.availableZ});this.isNodeCompletelyOutsideBounds(n)||e.push(n)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||(1===t.availableZ.length&&t._depth<=this.MAX_DEPTH||!(!t._containsObstacle||t._completelyInsideObstacle)))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),s=[],n=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),i=t.availableZ.length>1&&!e&&(t._containsObstacle||t.width<this.VIA_DIAMETER+this.OBSTACLE_MARGIN);if(e)n.push(t);else if(e||this.shouldFilterNodeForObstacle(t)||i)if(!e&&t._containsTarget)if(i){const e=this.getZSubdivisionChildNodes(t);s.push(...e.filter(t=>t._containsTarget||!this.shouldFilterNodeForObstacle(t)))}else s.push(t);else i&&s.push(...this.getZSubdivisionChildNodes(t).filter(t=>!this.shouldFilterNodeForObstacle(t)));else s.push(t)}this.unfinishedNodes.push(...n),this.finishedNodes.push(...s)}};function Ut(t){const e=new Map;for(const s of t)for(const t of s.nodeIds)e.set(t,[...e.get(t)??[],s]);return e}var Vt=class extends e{nodes;edges;capacityPaths;nodeMap;nodeEdgeMap;unprocessedNodeIds;nodePortSegments;colorMap;constructor({nodes:t,edges:e,capacityPaths:s,colorMap:n}){super(),this.nodes=t,this.edges=e,this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ut(e),this.capacityPaths=s,this.colorMap=n??{},this.unprocessedNodeIds=[...new Set(s.flatMap(t=>t.nodeIds))],this.nodePortSegments=new Map}step(){const t=this.unprocessedNodeIds.pop();if(!t)return void(this.solved=!0);const e=[];for(const s of this.capacityPaths){const n=s.nodeIds.indexOf(t);-1!==n&&e.push({path:s,indexOfNodeInPath:n})}const s=this.nodeMap.get(t),n=[];for(const{path:i,indexOfNodeInPath:o}of e){const e=i.nodeIds[o-1],a=i.nodeIds[o+1];for(const o of[e,a]){const e=this.nodeMap.get(o);if(!e)continue;const a=jt(s,e),r=e.availableZ.filter(t=>s.availableZ.includes(t));if(0===r.length)continue;const h={capacityMeshNodeId:t,start:a.start,end:a.end,connectionNames:[i.connectionName],availableZ:r};n.push(h)}}const i=function(t){const e=[],s=t.map(t=>({...t,connectionNames:[...t.connectionNames],availableZ:[...t.availableZ].sort((t,e)=>t-e)}));for(;s.length>0;){const t=s.pop();let n=!1;for(let s=0;s<e.length;s++){const i=e[s],o=Gt(i.start,t.start)&&Gt(i.end,t.end)||Gt(i.start,t.end)&&Gt(i.end,t.start),a=qt(i.availableZ,t.availableZ);if(o&&a){const e=new Set(i.connectionNames);t.connectionNames.forEach(t=>e.add(t)),i.connectionNames=Array.from(e),n=!0;break}}n||e.push(t)}return e}(n);this.nodePortSegments.set(t,i)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};return this.nodePortSegments.forEach((e,s)=>{this.nodeMap.get(s);e.forEach(e=>{e.start.x,e.end.x;for(let n=0;n<e.connectionNames.length;n++){const i={x:.05*Math.max(...e.availableZ),y:.05*Math.max(...e.availableZ)},o={x:(e.start.x+e.end.x)/2,y:(e.start.y+e.end.y)/2},a={x:o.x+i.x,y:o.y+i.y};i.x>0&&t.lines.push({points:[o,a],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5"}),t.points.push({x:a.x,y:a.y,label:`${s}: ${e.connectionNames.join(", ")}\navailableZ: ${e.availableZ.join(",")}\nnodePortSegmentId: ${e.nodePortSegmentId}`}),t.lines.push({points:[e.start,e.end],strokeColor:ct(this.colorMap[e.connectionNames[n]],.6)})}})}),t}};function jt(t,e){const s={start:Math.max(t.center.x-t.width/2,e.center.x-e.width/2),end:Math.min(t.center.x+t.width/2,e.center.x+e.width/2)},n={start:Math.max(t.center.y-t.height/2,e.center.y-e.height/2),end:Math.min(t.center.y+t.height/2,e.center.y+e.height/2)};if(s.end-s.start<n.end-n.start){const t=(s.start+s.end)/2;return{start:{x:t,y:n.start},end:{x:t,y:n.end}}}{const t=(n.start+n.end)/2;return{start:{x:s.start,y:t},end:{x:s.end,y:t}}}}var Wt=1e-9;function Gt(t,e){return Math.abs(t.x-e.x)<Wt&&Math.abs(t.y-e.y)<Wt}function qt(t,e){if(t.length!==e.length)return!1;for(let s=0;s<t.length;s++)if(t[s]!==e[s])return!1;return!0}var Kt=class extends e{unsolvedSegments;solvedSegments;nodeMap;colorMap;constructor({segments:t,colorMap:e,nodes:s}){super(),this.MAX_ITERATIONS=1e5,this.unsolvedSegments=t,this.solvedSegments=[],this.colorMap=e??{},this.nodeMap=Object.fromEntries(s.map(t=>[t.capacityMeshNodeId,t]))}_step(){let t=!1;const e=[...this.unsolvedSegments];for(const s of e){const e=s.connectionNames.length;if((!("assignedPoints"in s)||s.assignedPoints?.length!==e)&&1===e){const e={x:(s.start.x+s.end.x)/2,y:(s.start.y+s.end.y)/2,z:s.availableZ[0]};s.assignedPoints=[{connectionName:s.connectionNames[0],point:e}],this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(s),1),this.solvedSegments.push(s),t=!0}}if(!t&&e.length>0){let s=e[0];for(const t of e)t.connectionNames.length<s.connectionNames.length&&(s=t);const n=[...s.connectionNames].sort(),i=s.end.x-s.start.x,o=s.end.y-s.start.y,a=n.length,r=[];for(let t=1;t<=a;t++){const e=t/(a+1);r.push({x:s.start.x+i*e,y:s.start.y+o*e,z:s.availableZ[0]})}s.assignedPoints=n.map((t,e)=>({connectionName:t,point:r[e]})),this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(s),1),this.solvedSegments.push(s),t=!0}0===this.unsolvedSegments.length&&(this.solved=!0)}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.solvedSegments){const s=e.capacityMeshNodeId,n=this.nodeMap[s];t.has(s)||t.set(s,{capacityMeshNodeId:s,portPoints:[],center:n.center,width:n.width,height:n.height}),t.get(s).portPoints.push(...e.assignedPoints.map(t=>({...t.point,connectionName:t.connectionName})))}return Array.from(t.values())}visualize(){const t={points:[],lines:this.solvedSegments.map(t=>({points:[t.start,t.end],step:4})),rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Segment to Point Solver"};for(let e=0;e<this.solvedSegments.length;e++){const s=this.solvedSegments[e];for(let e=0;e<s.assignedPoints.length;e++){const n=s.assignedPoints[e],i={x:n.point.x,y:n.point.y},o={x:n.point.x+.05*n.point.z,y:n.point.y+.05*n.point.z};0!==n.point.z&&t.lines.push({points:[i,o],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5",step:4}),t.points.push({x:o.x,y:o.y,label:[`${s.capacityMeshNodeId}-${n.connectionName}`,`z: ${s.availableZ.join(",")}`,`nodePortSegmentId: ${s.nodePortSegmentId}`].join("\n"),color:this.colorMap[n.connectionName],step:4})}}const e=[],s={};for(const t of this.solvedSegments){const e=t.capacityMeshNodeId;s[e]||(s[e]={});for(const n of t.assignedPoints)s[e][n.connectionName]||(s[e][n.connectionName]=[]),s[e][n.connectionName].push({x:n.point.x,y:n.point.y})}for(const t in s)for(const n in s[t]){const i=s[t][n];i.length>1&&e.push({points:i,step:4,strokeDash:"5 5",strokeColor:this.colorMap[n]||"#000"})}return t.lines.push(...e),t}};import Jt from"object-hash";var Qt=class{cacheHitsByPrefix={};cacheMissesByPrefix={};isSyncCache=!0;cacheHits=0;cacheMisses=0;cache=new Map;getCachedSolutionSync(t){const e=this.cache.get(t);if(void 0!==e){this.cacheHits++;const s=t.split(":")[0];return this.cacheHitsByPrefix[s]=(this.cacheHitsByPrefix[s]||0)+1,structuredClone(e)}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){this.cache.set(t,structuredClone(e))}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){this.cache.clear(),this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}getAllCacheKeys(){return Array.from(this.cache.keys())}},te="tscircuit_autorouter_cache_",ee=class{isSyncCache=!0;cacheHits=0;cacheMisses=0;cacheHitsByPrefix={};cacheMissesByPrefix={};constructor(){}getKey(t){return`${te}${t}`}getCachedSolutionSync(t){if("undefined"==typeof localStorage)return;const e=this.getKey(t);try{const s=localStorage.getItem(e);if(null!==s){const e=JSON.parse(s);this.cacheHits++;const n=t.split(":")[0];return this.cacheHitsByPrefix[n]=(this.cacheHitsByPrefix[n]||0)+1,e}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}catch(s){console.error(`Error getting cached solution sync for ${e}:`,s),this.cacheMisses++;const n=t.split(":")[0];return void(this.cacheMissesByPrefix[n]=(this.cacheMissesByPrefix[n]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){if("undefined"==typeof localStorage)return;const s=this.getKey(t);try{const t=JSON.stringify(e);localStorage.setItem(s,t)}catch(t){console.error(`Error setting cached solution sync for ${s}:`,t),t instanceof DOMException&&("QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&console.warn(`LocalStorage quota exceeded. Failed to cache solution for ${s}. Consider clearing the cache.`)}}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){if("undefined"!=typeof localStorage)try{const t=[];for(let e=0;e<localStorage.length;e++){const s=localStorage.key(e);s?.startsWith(te)&&t.push(s)}t.forEach(t=>localStorage.removeItem(t)),console.log(`Cleared ${t.length} items from LocalStorage cache.`)}catch(t){console.error("Error clearing LocalStorage cache:",t)}finally{this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}}getAllCacheKeys(){const t=[];for(let e=0;e<1e4;e++){const s=localStorage.key(e);if(!s)break;s.includes(te)&&t.push(s)}return t}};function se(){return globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE||ie(),globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE}function ne(){return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE||ie(),globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE}function ie(){globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE??=new ee,globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE??=new Qt}var oe=class{heap=[];constructor(t){this.heap=[];for(const e of t)this.enqueue(e)}getLeftChildIndex(t){return 2*t+1}getRightChildIndex(t){return 2*t+2}getParentIndex(t){return Math.floor((t-1)/2)}hasLeftChild(t){return this.getLeftChildIndex(t)<this.heap.length}hasRightChild(t){return this.getRightChildIndex(t)<this.heap.length}hasParent(t){return this.getParentIndex(t)>=0}leftChild(t){return this.heap[this.getLeftChildIndex(t)]}rightChild(t){return this.heap[this.getRightChildIndex(t)]}parent(t){return this.heap[this.getParentIndex(t)]}swap(t,e){const s=this.heap[t];this.heap[t]=this.heap[e],this.heap[e]=s}dequeue(){if(0===this.heap.length)return null;const t=this.heap[0];return this.heap[0]=this.heap[this.heap.length-1],this.heap.pop(),this.heapifyDown(),t}peek(){return 0===this.heap.length?null:this.heap[0]}enqueue(t){this.heap.push(t),this.heapifyUp()}heapifyUp(){let t=this.heap.length-1;for(;this.hasParent(t)&&this.parent(t).f>this.heap[t].f;)this.swap(this.getParentIndex(t),t),t=this.getParentIndex(t)}heapifyDown(){let t=0;for(;this.hasLeftChild(t);){let e=this.getLeftChildIndex(t);if(this.hasRightChild(t)&&this.rightChild(t).f<this.leftChild(t).f&&(e=this.getRightChildIndex(t)),this.heap[t].f<this.heap[e].f)break;this.swap(t,e),t=e}}},ae=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=h(this.A,this.B),this.futureConnections=t.futureConnections??[],this.MAX_ITERATIONS=5e3,this.debug_exploredNodesOrdered=[],this.debug_nodesTooCloseToObstacle=new Set,this.debug_nodePathToParentIntersectsObstacle=new Set,this.numRoutes=this.obstacleRoutes.length+this.futureConnections.length;const e=Math.ceil(5*(this.numRoutes+1));let s=this.boundsSize.width/this.cellStep,n=this.boundsSize.height/this.cellStep;for(;s*n>e**2&&!(2*this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,s=this.boundsSize.width/this.cellStep,n=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR,this.futureConnections&&0===this.futureConnections.length&&0===this.obstacleRoutes.length&&this.handleSimpleCases();const i={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:i.x-Math.round(t.A.x/this.cellStep)*this.cellStep,y:i.y-Math.round(t.A.y/this.cellStep)*this.cellStep},this.candidates=new oe([{...t.A,...i,z:t.A.z??0,g:0,h:0,f:0,parent:{...t.A,z:t.A.z??0,g:0,h:0,f:0,parent:null}}])}handleSimpleCases(){this.solved=!0;const{A:t,B:e}=this,s=t.z===e.z?[t,e]:[t,{...this.boundsCenter,z:this.A.z},{...this.boundsCenter,z:e.z},e];this.solvedPath={connectionName:this.connectionName,route:s,traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:this.A.z===this.B.z?[]:[this.boundsCenter]}}get viaPenaltyDistance(){return this.cellStep+this.straightLineDistance*this.VIA_PENALTY_FACTOR}isNodeTooCloseToObstacle(t,e,s){if(e??=this.obstacleMargin,s&&t.parent){const s=this.getViasInNodePath(t.parent);for(const n of s)if(h(t,n)<this.viaDiameter/2+e)return!0}for(const n of this.obstacleRoutes){const i=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!i){const i=re(n);for(const n of i)if((s||n.z===t.z)&&r(t,n.A,n.B)<this.traceThickness+e)return!0}for(const s of n.vias)if(h(t,s)<this.viaDiameter/2+this.traceThickness/2+e)return!0}return!1}isNodeTooCloseToEdge(t,e){const s=e?this.viaDiameter/2+this.obstacleMargin/2:this.obstacleMargin/2,n=t.x<this.bounds.minX+s||t.x>this.bounds.maxX-s||t.y<this.bounds.minY+s||t.y>this.bounds.maxY-s;return!(n&&!e&&(h(t,this.B)<2*s||h(t,this.A)<2*s))&&n}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const s of this.obstacleRoutes){const n=this.connMap?.areIdsConnected?.(this.connectionName,s.connectionName);if(!n)for(const n of re(s))if(n.z===t.z&&i(t,e,n.A,n.B))return!0}return!1}computeH(t){return h(t,this.B)+Math.abs(t.z-this.B.z)*this.viaPenaltyDistance}computeG(t){return(t.parent?.g??0)+(0===t.z?0:this.viaPenaltyDistance)+h(t,t.parent)}computeF(t,e){return t+e*this.GREEDY_MULTIPLER}getNodeKey(t){return`${Math.round(t.x/this.cellStep)*this.cellStep},${Math.round(t.y/this.cellStep)*this.cellStep},${t.z}`}getNeighbors(t){const e=[],{maxX:s,minX:n,maxY:i,minY:o}=this.bounds;for(let a=-1;a<=1;a++)for(let r=-1;r<=1;r++){if(0===a&&0===r)continue;const h={...t,parent:t,x:he(t.x+a*this.cellStep,n,s),y:he(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)))}const a={...t,parent:t,z:0===t.z?this.layerCount-1:0};return this.exploredNodes.has(this.getNodeKey(a))||this.isNodeTooCloseToObstacle(a,this.viaDiameter/2+this.obstacleMargin/2,!0)||this.isNodeTooCloseToEdge(a,!0)||(a.g=this.computeG(a),a.h=this.computeH(a),a.f=this.computeF(a.g,a.h),e.push(a)),e}getNodePath(t){const e=[];for(;t;)e.push(t),t=t.parent;return e}getViasInNodePath(t){const e=this.getNodePath(t),s=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&s.push({x:e[t].x,y:e[t].y});return s}setSolvedPath(t){const e=this.getNodePath(t);e.reverse();const s=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&s.push({x:e[t].x,y:e[t].y});this.solvedPath={connectionName:this.connectionName,traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,route:e.map(t=>({x:t.x,y:t.y,z:t.z})).concat([this.B]),vias:s}}computeProgress(t,e,s){s||(e+=this.viaPenaltyDistance);const n=1-e/this.straightLineDistance;return Math.max(this.progress||0,2/Math.PI*Math.atan(.112*n/(1-n)))}_step(){let t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;for(;t&&e&&this.exploredNodes.has(e);)t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;if(!t||!e)return void(this.failed=!0);this.exploredNodes.add(e),this.debug_exploredNodesOrdered.push(e);const s=h(t,this.B);this.progress=this.computeProgress(t,s,t.z===this.B.z),s<=this.cellStep*Math.SQRT2&&t.z===this.B.z&&!this.doesPathToParentIntersectObstacle({...t,parent:t,x:this.B.x,y:this.B.y})&&(this.solved=!0,this.setSolvedPath(t));const n=this.getNeighbors(t);for(const t of n)this.candidates.enqueue(t)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.points.push({x:this.A.x,y:this.A.y,label:`Input A\nz: ${this.A.z}`,color:"orange"}),t.points.push({x:this.B.x,y:this.B.y,label:`Input B\nz: ${this.B.z}`,color:"orange"}),t.lines.push({points:[this.A,this.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:"Direct Input Connection"});for(let e=0;e<this.obstacleRoutes.length;e++){const s=this.obstacleRoutes[e];for(let n=0;n<s.route.length-1;n++){const i=s.route[n].z;t.lines.push({points:[s.route[n],s.route[n+1]],strokeColor:0===i?"rgba(255, 0, 0, 0.75)":"rgba(255, 128, 0, 0.25)",strokeWidth:s.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`})}}for(let e=0;e<this.debug_exploredNodesOrdered.length;e++){const s=this.debug_exploredNodesOrdered[e],[n,i,o]=s.split(",").map(Number);this.debug_nodesTooCloseToObstacle.has(s)||(this.debug_nodePathToParentIntersectsObstacle.has(s)||t.rects.push({center:{x:n+this.initialNodeGridOffset.x+o*this.cellStep/20,y:i+this.initialNodeGridOffset.y+o*this.cellStep/20},fill:0===o?`rgba(255,0,255,${.3-e/this.debug_exploredNodesOrdered.length*.2})`:`rgba(0,0,255,${.3-e/this.debug_exploredNodesOrdered.length*.2})`,width:.9*this.cellStep,height:.9*this.cellStep,label:`Explored (z=${o})`}))}if(this.candidates.peek()){const e=this.candidates.peek();t.rects.push({center:{x:e.x+e.z*this.cellStep/20,y:e.y+e.z*this.cellStep/20},fill:"rgba(0, 255, 0, 0.8)",width:.9*this.cellStep,height:.9*this.cellStep,label:`Next (z=${e.z})`})}for(const e of this.obstacleRoutes)for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:this.viaDiameter/2,fill:"rgba(255, 0, 0, 0.5)",label:"Via"});if(this.solvedPath){t.lines.push({points:this.solvedPath.route,strokeColor:"green",label:"Solved Route"});for(const e of this.solvedPath.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"green",label:"Via"})}return t}};function re(t){const e=[];for(let s=0;s<t.route.length-1;s++)t.route[s].z===t.route[s+1].z&&e.push({z:t.route[s].z,A:t.route[s],B:t.route[s+1]});return e}function he(t,e,s){return Math.max(e,Math.min(t,s))}var ce=class extends ae{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;this.VIA_PENALTY_FACTOR=e/this.numRoutes*.3*this.VIA_PENALTY_FACTOR_2}getClosestFutureConnectionPoint(t){let e=1/0,s=null;for(const n of this.futureConnections)for(const i of n.points){const n=h(t,i)+(t.z!==i.z?this.viaPenaltyDistance:0);n<e&&(e=n,s=i)}return s}diminishCloseToGoal(t){const e=h(t,this.B);return 1-Math.exp(-e/this.straightLineDistance*5)}getFutureConnectionPenalty(t,e){let s=0;const n=this.getClosestFutureConnectionPoint(t),i=h(t,this.B);if(n){const o=h(t,n);if(i<=o)return 0;const a=o/(this.viaDiameter*this.FUTURE_CONNECTION_PROXIMITY_VD);s=(e?this.straightLineDistance*this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR:this.straightLineDistance*this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR)*Math.exp(5*-a)}return s}computeH(t){const e=h(t,this.B)**1.6;this.straightLineDistance;return e+(t.z!==this.B.z?this.viaPenaltyDistance:0)+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}computeG(t){const e=Math.abs(t.x-t.parent.x),s=Math.abs(t.y-t.parent.y),n=Math.sqrt(e**2+s**2),i=this.FLIP_TRACE_ALIGNMENT_DIRECTION?0===t.z?e:s:0===t.z?s:e;return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+n+i*this.MISALIGNED_DIST_PENALTY_FACTOR+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}};function de(t){let e=t;for(let t=0;t<10;t++)e=16807*e%2147483647;let s=e;e=(69069*t+1)%2147483647;for(let t=0;t<10;t++)e=48271*e%2147483647;let n=e;return()=>{let t=s;s=n,t^=t<<23,t^=t>>>17,t^=n,t^=n>>>26,n=t;const e=(s+n)/4294967296;return e-Math.floor(e)}}var le={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 ue(t,e){if(0===e)return t;if(t.length<=4){const s=le[t.length];return s[e%s.length].map(e=>t[e])}const s=de(e),n=t.slice();for(let t=0;t<n.length;t++){const e=Math.floor(s()*n.length),i=Math.floor(s()*(t+1));[n[e],n[i]]=[n[i],n[e]]}return n}function pe(t){const e={minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2};for(const s of t.portPoints)s.x<e.minX&&(e.minX=s.x),s.x>e.maxX&&(e.maxX=s.x),s.y<e.minY&&(e.minY=s.y),s.y>e.maxY&&(e.maxY=s.y);return e}var fe=class extends e{nodeWithPortPoints;colorMap;unsolvedConnections;totalConnections;solvedRoutes;failedSubSolvers;hyperParameters;minDistBetweenEnteringPoints;activeSubSolver=null;connMap;get failedSolvers(){return this.failedSubSolvers}get activeSolver(){return this.activeSubSolver}constructor(t){const{nodeWithPortPoints:e,colorMap:s}=t;super(),this.nodeWithPortPoints=e,this.colorMap=s??{},this.solvedRoutes=[],this.hyperParameters=t.hyperParameters??{},this.failedSubSolvers=[],this.connMap=t.connMap;const n=new Map;for(const{connectionName:t,x:s,y:i,z:o}of e.portPoints)n.set(t,[...n.get(t)??[],{x:s,y:i,z:o??0}]);this.unsolvedConnections=Array.from(n.entries().map(([t,e])=>({connectionName:t,points:e}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=ue(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},s)=>({...e,points:ue(t,7117*s+(this.hyperParameters.SHUFFLE_SEED??0))}))),this.totalConnections=this.unsolvedConnections.length,this.MAX_ITERATIONS=1e3*this.totalConnections**1.5,this.minDistBetweenEnteringPoints=(t=>{let e=1/0;const s=t.portPoints;for(let t=0;t<s.length;t++)for(let n=t+1;n<s.length;n++){if(s[t].z!==s[n].z)continue;const i=s[t],o=s[n],a=Math.sqrt((i.x-o.x)**2+(i.y-o.y)**2);e=Math.min(e,a)}return e===1/0?0:e})(this.nodeWithPortPoints)}computeProgress(){return(this.solvedRoutes.length+(this.activeSubSolver?.progress||0))/this.totalConnections}_step(){if(this.activeSubSolver)return this.activeSubSolver.step(),this.progress=this.computeProgress(),void(this.activeSubSolver.solved?(this.solvedRoutes.push(this.activeSubSolver.solvedPath),this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSubSolvers.push(this.activeSubSolver),this.activeSubSolver=null,this.error=this.failedSubSolvers.map(t=>t.error).join("\n"),this.failed=!0));const t=this.unsolvedConnections.pop();if(this.progress=this.computeProgress(),!t)return void(this.solved=0===this.failedSubSolvers.length);if(1===t.points.length)return;if(2===t.points.length){const[e,s]=t.points;if(e.x===s.x&&e.y===s.y&&e.z===s.z)return}const{connectionName:e,points:s}=t;this.activeSubSolver=new ce({connectionName:e,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:pe(this.nodeWithPortPoints),A:{x:s[0].x,y:s[0].y,z:s[0].z},B:{x:s[s.length-1].x,y:s[s.length-1].y,z:s[s.length-1].z},obstacleRoutes:this.connMap?this.solvedRoutes.filter(t=>!this.connMap.areIdsConnected(t.connectionName,e)):this.solvedRoutes,futureConnections:this.unsolvedConnections,layerCount:2,hyperParameters:this.hyperParameters,connMap:this.connMap})}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:[e.connectionName,`layer: ${e.z}`].join("\n"),color:this.colorMap[e.connectionName]??"blue"});for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e];if(s.route.length>0){const n=this.colorMap[s.connectionName]??"blue";for(let i=0;i<s.route.length-1;i++){const o=s.route[i],a=s.route[i+1];t.lines.push({points:[o,a],strokeColor:0===o.z?ct(n,.2):ct(n,.8),layer:`route-layer-${o.z}`,step:e,strokeWidth:s.traceThickness})}for(const i of s.vias)t.circles.push({center:{x:i.x,y:i.y},radius:s.viaDiameter/2,fill:ct(n,.5),layer:"via",step:e})}}const e=pe(this.nodeWithPortPoints),{minX:s,minY:n,maxX:i,maxY:o}=e;return t.lines.push({points:[{x:s,y:n},{x:i,y:n},{x:i,y:o},{x:s,y:o},{x:s,y:n}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}},me=t=>Math.round(200*t)/200,ge=t=>"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t));ie();var ye=class extends fe{cacheProvider;cacheHit=!1;hasAttemptedToUseCache=!1;initialUnsolvedConnections;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?ne():t.cacheProvider,this.initialUnsolvedConnections=ge(this.unsolvedConnections),(this.solved||this.failed)&&this.cacheProvider&&!this.cacheHit&&this.saveToCacheSync()}_step(){if(!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync())return;const t=this.solved,e=this.failed;super._step(),!this.cacheProvider||this.cacheHit||!this.solved&&!this.failed||t||e||this.saveToCacheSync()}computeCacheKeyAndTransform(){const t=this.nodeWithPortPoints.center,e=this.initialUnsolvedConnections.map(({connectionName:e,points:s})=>({connectionName:e,points:s.map(s=>({connectionName:e,x:me(s.x-t.x),y:me(s.y-t.y),z:s.z??0}))})),s=Object.fromEntries(Object.entries(this.hyperParameters??{}).filter(([,t])=>void 0!==t).sort(([t],[e])=>t.localeCompare(e))),n=this.connMap?this.initialUnsolvedConnections.map(({connectionName:t})=>({connectionName:t,connectedIds:[...new Set(this.connMap.getIdsConnectedToNet(t)??[])].sort()})):void 0,i={node:{width:me(this.nodeWithPortPoints.width),height:me(this.nodeWithPortPoints.height),center:{x:me(this.nodeWithPortPoints.center.x),y:me(this.nodeWithPortPoints.center.y)},availableZ:this.nodeWithPortPoints.availableZ?[...this.nodeWithPortPoints.availableZ].sort():void 0},normalizedConnections:e,normalizedHyperParameters:s,minDistBetweenEnteringPoints:me(this.minDistBetweenEnteringPoints),normalizedConnMap:n},o=`intranode-solver:${Jt(i)}`,a={};return this.cacheKey=o,this.cacheToSolveSpaceTransform=a,{cacheKey:o,cacheToSolveSpaceTransform:a}}applyCachedSolution(t){t.success?(this.solvedRoutes=ge(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:ge(this.solvedRoutes)};try{this.cacheProvider.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}},xe=class extends e{GREEDY_MULTIPLIER=1.2;MIN_SUBSTEPS=1;supervisedSolvers;winningSolver;getHyperParameterDefs(){throw new Error("Not implemented")}getCombinationDefs(){return null}getHyperParameterCombinations(t){t||(t=this.getHyperParameterDefs());const e=[];if(0===t.length)return[{}];const[s,...n]=t,i=this.getHyperParameterCombinations(n);return s.possibleValues.forEach(t=>{i.forEach(s=>{e.push({...s,...t})})}),e}initializeSolvers(){const t=this.getHyperParameterDefs(),e=this.getCombinationDefs()??[t.map(t=>t.name)];this.supervisedSolvers=[];for(const s of e){const e=this.getHyperParameterCombinations(t.filter(t=>s.includes(t.name)));for(const t of e){const e=this.generateSolver(t),s=this.computeG(e);this.supervisedSolvers.push({hyperParameters:t,solver:e,h:0,g:s,f:s})}}}generateSolver(t){throw new Error("Not implemented")}computeG(t){return t.iterations/t.MAX_ITERATIONS}computeH(t){return 1-(t.progress||0)}computeF(t,e){return t+e*this.GREEDY_MULTIPLIER}getSupervisedSolverWithBestFitness(){let t=1/0,e=null;for(const s of this.supervisedSolvers??[]){if(s.solver.solved)return s;if(s.solver.failed)continue;const n=s.f;n<t&&(t=n,e=s)}return e}getFailureMessage(){return"All solvers failed in hyper solver."}_step(){this.supervisedSolvers||this.initializeSolvers();const t=this.getSupervisedSolverWithBestFitness();if(!t)return this.failed=!0,void(this.error=this.getFailureMessage());for(let e=0;e<this.MIN_SUBSTEPS;e++)t.solver.step();t.g=this.computeG(t.solver),t.h=this.computeH(t.solver),t.f=this.computeF(t.g,t.h),t.solver.solved&&(this.solved=!0,this.winningSolver=t.solver,this.onSolve?.(t))}onSolve(t){}visualize(){const t=this.getSupervisedSolverWithBestFitness();let e={lines:[],circles:[],points:[],rects:[]};return t&&(e=t.solver.visualize()),e}};function Me({A:t,B:e,C:s,D:n,E:i,F:o,radius:a,margin:c,subdivisions:d=0}){const l=(t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}),u=(t,e,s)=>{const n=e.x-t.x,i=e.y-t.y,o=Math.sqrt(n*n+i*i),a=n/o,r=i/o,h=-r,c=a;return{midpoint:{x:(t.x+e.x)/2,y:(t.y+e.y)/2},A_Opp:{x:t.x-a*s,y:t.y-r*s},A_Right:{x:t.x+h*s,y:t.y+c*s},A_Left:{x:t.x-h*s,y:t.y-c*s},B_Opp:{x:e.x+a*s,y:e.y+r*s},B_Right:{x:e.x+h*s,y:e.y+c*s},B_Left:{x:e.x-h*s,y:e.y-c*s}}},p=(t,e)=>{const s=h(t,e.start),n=h(t,e.end),i=h(e.start,e.end);return Math.abs(s+n-i)<1e-4},f=(t,e)=>{const{start:s,end:n}=t,{start:i,end:o}=e;if(p(s,e)||p(n,e)||p(i,t)||p(o,t))return!0;const a=n.x-s.x,r=n.y-s.y,h=o.x-i.x,c=o.y-i.y,d=a*c-r*h;if(Math.abs(d)<1e-4)return!1;const l=i.x-s.x,u=i.y-s.y,f=(l*c-u*h)/d,m=(l*r-u*a)/d;return f>0&&f<1&&m>0&&m<1},m=(t,e)=>{const s=[];for(let e=0;e<t.length-1;e++)s.push({start:t[e],end:t[e+1]});const n=[];for(let t=0;t<e.length-1;t++)n.push({start:e[t],end:e[t+1]});for(const t of s)for(const e of n)if(f(t,e))return!0;return!1},g=t=>{let e=0;for(let s=1;s<t.length;s++){const n=t[s].x-t[s-1].x,i=t[s].y-t[s-1].y;e+=Math.sqrt(n*n+i*i)}return e},y=(t,e)=>{const{start:s,end:n}=t,i=n.x-s.x,o=n.y-s.y,a=i*i+o*o;if(0===a)return{...s,t:0};const r=Math.max(0,Math.min(1,((e.x-s.x)*i+(e.y-s.y)*o)/a));return{x:s.x+r*i,y:s.y+r*o,t:r}},x=(e,s,n)=>{const i=y(e,s);if(h(i,s)>=n)return i;const o=i.x-s.x,a=i.y-s.y,r=Math.sqrt(o*o+a*a);if(0===r){const o=e.end.x-e.start.x,a=e.end.y-e.start.y,r=Math.sqrt(o*o+a*a);return{x:s.x+n*o/r,y:s.y+n*a/r,t:i.t,isSpecial:!0,specialType:s===t?"A":"B"}}return{x:s.x+n*o/r,y:s.y+n*a/r,t:i.t,isSpecial:!0,specialType:s===t?"A":"B"}},M=u(t,e,a),v=u(t,e,a+c),S=(t,e,s,n,i)=>{const o=t.points;if(o.length<2)return o;const c=s+n,d=[o[0]];for(let t=0;t<o.length-1;t++){const s={start:o[t],end:o[t+1]};if(r(e,s.start,s.end)<c){const t=y(s,e),n=t.x-e.x,i=t.y-e.y,o=Math.sqrt(n*n+i*i);let r=null;if(o>1e-6)r={x:e.x+c*n/o,y:e.y+c*i/o};else{const t=s.end.x-s.start.x,n=s.end.y-s.start.y,i=Math.sqrt(t*t+n*n);i>1e-6&&(r={x:e.x+c*t/i,y:e.y+c*n/i})}r&&h(s.start,r)>a/10&&d.push(r)}h(d[d.length-1],s.end)>a/10&&d.push(s.end)}if(d.length>1){const t=[d[0]];for(let e=1;e<d.length;e++)h(t[t.length-1],d[e])>a/10&&t.push(d[e]);return t}return d},b=(()=>{const t=[[s,M.B_Left,M.B_Opp,M.B_Right,l(M.midpoint,l(M.B_Right,M.A_Right)),l(M.midpoint,l(M.A_Left,M.B_Left)),M.A_Left,M.A_Opp,M.A_Right,n],[s,M.B_Right,M.B_Opp,M.B_Left,l(M.midpoint,l(M.A_Left,M.B_Left)),l(M.midpoint,l(M.A_Right,M.B_Right)),M.A_Right,M.A_Opp,M.A_Left,n],[n,M.B_Left,M.B_Opp,M.B_Right,l(M.midpoint,l(M.A_Right,M.B_Right)),l(M.midpoint,l(M.A_Left,M.B_Left)),M.A_Left,M.A_Opp,M.A_Right,s],[n,M.B_Right,M.B_Opp,M.B_Left,l(M.midpoint,l(M.A_Left,M.B_Left)),l(M.midpoint,l(M.A_Right,M.B_Right)),M.A_Right,M.A_Opp,M.A_Left,s]],e=[];for(let s=0;s<t.length;s++){const n=t[s],i={start:n[0],end:n[1]},o={start:n[n.length-2],end:n[n.length-1]},a={start:n[3],end:n[4]};f(i,o)||f(i,a)||f(o,a)||e.push({index:s+1,path:n,length:g(n)})}if(0===e.length)return{index:0,path:[]};const i=e.sort((t,e)=>t.length-e.length)[0],o=[...i.path],a=o[0],r=h(a,o[2]),c=h(a,o[3]),d=r<c?2:3;(r<h(a,o[1])||c<h(a,o[1]))&&o.splice(1,d-1);const u=o[o.length-1],p=h(u,o[o.length-3]),m=h(u,o[o.length-4]),y=p<m?o.length-3:o.length-4;return(p<h(u,o[o.length-2])||m<h(u,o[o.length-2]))&&o.splice(y+1,o.length-y-2),{index:i.index,path:o,startsAt:o[0]===s?"C":"D",goesTo:o[o.length-1]===s?"C":"D"}})(),N=d>0?((s,n)=>{if(s.length<2)return s;const i=[s[0]];for(let o=0;o<s.length-1;o++){const r={start:s[o],end:s[o+1]},c={x:(r.start.x+r.end.x)/2,y:(r.start.y+r.end.y)/2},d=h(c,t),l=h(c,e);if((d<=a||l<=a)&&Math.abs(d-l)>1e-4){const s=y(r,t),o=y(r,e),c=h(s,t),d=h(o,e)<a,l=c<a?x(r,t,a):null,u=d?x(r,e,a):null;let p=[];if(h(r.start,r.end)>a/2&&n>0)for(let s=1;s<=n;s++){const i=s/(n+1),o={x:r.start.x+i*(r.end.x-r.start.x),y:r.start.y+i*(r.end.y-r.start.y),t:i,isSpecial:!1},c=h(o,t),d=h(o,e);c<a||d<a||(l&&Math.abs(o.t-l.t)<.1||u&&Math.abs(o.t-u.t)<.1||p.push(o))}if(l&&p.push(l),u&&p.push(u),p.sort((t,e)=>t.t-e.t),p.length>1){const t=[p[0]];for(let e=1;e<p.length;e++){const s=t[t.length-1],n=p[e];h(s,n)>a/10&&t.push(n)}p=t}p.forEach(t=>i.push(t))}i.push(s[o+1])}if(i.length>1){const t=[i[0]];for(let e=1;e<i.length;e++){const s=t[t.length-1],n=i[e];h(s,n)>a/10&&t.push(n)}return t}return i})(b.path,d):b.path;let I=(()=>{if(0===b.path.length)return null;const s=(()=>{const s=l(M.A_Right,M.B_Right),n=l(M.B_Left,M.A_Left);return[{startsAt:"E",goesTo:"B",points:[i,e]},{startsAt:"E",goesTo:"A",points:[i,t]},{startsAt:"F",goesTo:"B",points:[o,e]},{startsAt:"F",goesTo:"A",points:[o,t]},{startsAt:"E",goesTo:"B",points:[i,s,e]},{startsAt:"E",goesTo:"A",points:[i,s,t]},{startsAt:"F",goesTo:"B",points:[o,s,e]},{startsAt:"F",goesTo:"A",points:[o,s,t]},{startsAt:"E",goesTo:"B",points:[i,n,e]},{startsAt:"E",goesTo:"A",points:[i,n,t]},{startsAt:"F",goesTo:"B",points:[o,n,e]},{startsAt:"F",goesTo:"A",points:[o,n,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Right,s,e]},{startsAt:"F",goesTo:"B",points:[o,v.B_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Left,n,t]},{startsAt:"F",goesTo:"A",points:[o,v.A_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Right,s,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Opp,v.A_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Opp,v.B_Left,n,t]},{startsAt:"F",goesTo:"B",points:[o,v.A_Opp,v.A_Left,n,e]},{startsAt:"F",goesTo:"A",points:[o,v.B_Opp,v.B_Right,s,t]},{startsAt:"F",goesTo:"A",points:[o,v.B_Opp,v.B_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Opp,v.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Opp,v.B_Right,s,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Left,v.A_Opp,v.A_Right,s,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Right,v.B_Opp,v.B_Left,n,t]},{startsAt:"F",goesTo:"B",points:[o,v.A_Right,v.A_Opp,v.A_Left,n,e]},{startsAt:"F",goesTo:"A",points:[o,v.B_Left,v.B_Opp,v.B_Right,s,t]},{startsAt:"F",goesTo:"A",points:[o,v.B_Right,v.B_Opp,v.B_Left,n,t]},{startsAt:"E",goesTo:"B",points:[i,v.A_Right,v.A_Opp,v.A_Left,n,e]},{startsAt:"E",goesTo:"A",points:[i,v.B_Left,v.B_Opp,v.B_Right,s,t]}].map((t,e)=>({...t,index:e}))})(),n=s.filter(t=>"E"===t.startsAt),a=s.filter(t=>"F"===t.startsAt),r=[],h=[];for(const t of n)if(!m(t.points,b.path)){r.push(t);break}for(const t of a)if(!m(t.points,b.path)){h.push(t);break}return 0===r.length||0===h.length?null:{line1:r[0],line2:h[0]}})();if(I){const s="A"===I.line1.goesTo?e:t,n="A"===I.line2.goesTo?e:t,i=S(I.line1,s,a,c),o=S(I.line2,n,a,c);I={line1:{...I.line1,points:i},line2:{...I.line2,points:o}}}return{jPair:I,optimalPath:{startsAt:b.startsAt,goesTo:b.goesTo,points:N}}}var ve=class extends e{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;escapeLayer=1;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return void(this.failed=!0);const[e,s]=this.routes;if(!(e.startPort.z===e.endPort.z))return void(this.failed=!0);if(!(s.startPort.z===s.endPort.z))return void(this.failed=!0);e.startPort.z===s.startPort.z?0===e.startPort.z?this.escapeLayer=1:this.escapeLayer=0:this.failed=!0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,s=new Map;for(const t of e){const{connectionName:e}=t;s.has(e)||s.set(e,[]),s.get(e)?.push(t)}for(const[e,n]of s.entries())2===n.length&&t.push({startPort:{...n[0],z:n[0].z??0},endPort:{...n[1],z:n[1].z??0},connectionName:e});return t}calculateBounds(){return{minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2}}doRoutesCross(t,e){return i(t.startPort,t.endPort,e.startPort,e.endPort)}calculateViaPositions(t,e){const s=this.bounds.maxX-this.bounds.minX,n=this.bounds.maxY-this.bounds.minY,i=this.bounds.minX,o=this.bounds.minY,a={width:s-2*this.obstacleMargin-this.viaDiameter,height:n-2*this.obstacleMargin-this.viaDiameter,x:i+this.obstacleMargin+this.viaDiameter/2,y:o+this.obstacleMargin+this.viaDiameter/2},r=this.viaDiameter+this.obstacleMargin,c=e.startPort,d=e.endPort,l=[{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}],u=(t,e)=>h(t,e),p=[];l.forEach((t,e)=>{u(t,c)>=r&&u(t,d)>=r&&p.push({...t,type:"corner",index:e})});const f=[{p1:l[0],p2:l[1]},{p1:l[1],p2:l[2]},{p1:l[2],p2:l[3]},{p1:l[3],p2:l[0]}];if([c,d].forEach((t,e)=>{f.forEach((s,n)=>{((t,e)=>{const s=t.x,n=t.y,i=t.r,o=e.p1.x,a=e.p1.y,r=e.p2.x,h=e.p2.y;if(Math.abs(r-o)<.001){const t=o,e=i*i-(t-s)**2;if(e<0)return[];if(Math.abs(e)<.001){const e=n;return e>=Math.min(a,h)&&e<=Math.max(a,h)?[{x:t,y:e}]:[]}const r=n+Math.sqrt(e),c=n-Math.sqrt(e),d=[];return r>=Math.min(a,h)&&r<=Math.max(a,h)&&d.push({x:t,y:r}),c>=Math.min(a,h)&&c<=Math.max(a,h)&&d.push({x:t,y:c}),d}const c=(h-a)/(r-o),d=a-c*o,l=1+c*c,u=2*(c*d-c*n-s),p=u*u-4*l*(s*s+(d-n)*(d-n)-i*i);if(p<0)return[];if(Math.abs(p)<.001){const t=-u/(2*l),e=c*t+d;return t>=Math.min(o,r)&&t<=Math.max(o,r)&&e>=Math.min(a,h)&&e<=Math.max(a,h)?[{x:t,y:e}]:[]}const f=(-u+Math.sqrt(p))/(2*l),m=(-u-Math.sqrt(p))/(2*l),g=c*f+d,y=c*m+d,x=[];return f>=Math.min(o,r)&&f<=Math.max(o,r)&&g>=Math.min(a,h)&&g<=Math.max(a,h)&&x.push({x:f,y:g}),m>=Math.min(o,r)&&m<=Math.max(o,r)&&y>=Math.min(a,h)&&y<=Math.max(a,h)&&x.push({x:m,y:y}),x})({...t,r:r},s).forEach(t=>{u(t,0===e?d:c)>=r&&p.push({...t,type:"intersection",circle:e,edge:n})})})}),p.length<2){const t=.8*r;if(l.forEach((e,s)=>{u(e,c)>=t&&u(e,d)>=t&&!p.some(t=>t.x===e.x&&t.y===e.y)&&p.push({...e,type:"relaxed_corner",index:s})}),p.length<2){const t=[...l].sort((t,e)=>{const s=Math.min(u(t,c),u(t,d));return Math.min(u(e,c),u(e,d))-s});for(const e of t)if(!p.some(t=>t.x===e.x&&t.y===e.y)&&(p.push({...e,type:"forced_corner"}),p.length>=2))break}}if(p.length<2)return null;let m=0,g=[p[0],p[p.length>1?1:0]];for(let t=0;t<p.length;t++)for(let e=t+1;e<p.length;e++){const s=u(p[t],p[e]);s>m&&(m=s,g=[p[t],p[e]])}let y={x:g[0].x,y:g[0].y},x={x:g[1].x,y:g[1].y};const M=h(y,t.startPort);return h(x,t.startPort)<M&&([y,x]=[x,y]),{via1:y,via2:x}}trySolveAOverB(t,e,s=!1){const n=s?this.calculateViaPositions(t,e):this.calculateViaPositions(e,t);if(!n)return!1;this.debugViaPositions.push(n);const{via1:i,via2:o}=this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(n));this.debugViaPositions.push({via1:i,via2:o});const{jPair:a,optimalPath:r}=Me({A:i,B:o,C:t.startPort,D:t.endPort,E:e.startPort,F:e.endPort,radius:this.viaDiameter/2+this.obstacleMargin+this.traceThickness/2*1.5,margin:2*this.obstacleMargin+this.traceThickness/2*1.5,subdivisions:1});if(!a)return!1;const h={connectionName:t.connectionName,route:r.points.map(e=>({x:e.x,y:e.y,z:t.startPort.z??0})),traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};a.line2.points.reverse();const c={connectionName:e.connectionName,route:[...a.line1.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0})),{...a.line1.points[a.line1.points.length-1],z:this.escapeLayer},{...a.line2.points[0],z:this.escapeLayer},...a.line2.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0}))],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[i,o]};return this.solvedRoutes.push(h,c),!0}pushViasFromEndpoints(t){const e={...t.via1},s={...t.via2},n=[this.routes[0].startPort,this.routes[0].endPort,this.routes[1].startPort,this.routes[1].endPort],i=this.getMinDistanceBetweenViaCenters(),o=this.viaDiameter/2+2*this.traceThickness+2*this.obstacleMargin;for(let t=0;t<10;t++){let a=!1,r=!1;const c=.9**t;for(const t of n){const n=h(e,t);if(n<o){const s=(o-n)*c,i=e.x-t.x,r=e.y-t.y,h=Math.sqrt(i*i+r*r);h>1e-6&&(e.x+=i/h*s,e.y+=r/h*s,a=!0)}const i=h(s,t);if(i<o){const e=(o-i)*c,n=s.x-t.x,a=s.y-t.y,h=Math.sqrt(n*n+a*a);h>1e-6&&(s.x+=n/h*e,s.y+=a/h*e,r=!0)}}const d=h(e,s);if(d<i){const t=(i-d)/2,n=s.x-e.x,o=s.y-e.y,h=Math.sqrt(n*n+o*o);h>1e-6?(e.x-=n/h*t,e.y-=o/h*t,s.x+=n/h*t,s.y+=o/h*t,a=!0,r=!0):(e.x-=t,s.x+=t,a=!0,r=!0)}if(!a&&!r)break}const a=h(e,s);if(a<i){const t=(i-a)/2,n=s.x-e.x,o=s.y-e.y,r=Math.sqrt(n*n+o*o);r>1e-6?(e.x-=n/r*t,e.y-=o/r*t,s.x+=n/r*t,s.y+=o/r*t):(e.x-=t,s.x+=t)}return{via1:e,via2:s}}getMinDistanceBetweenViaCenters(){return this.viaDiameter+this.traceThickness+2*this.obstacleMargin}moveViasAsCloseAsPossible(t){const{via1:e,via2:s}=t,n=this.getMinDistanceBetweenViaCenters(),i=h(e,s);if(i<=n)return t;const o=s.x-e.x,a=s.y-e.y,r=Math.sqrt(o*o+a*a),c=o/r,d=a/r,l=(e.x,s.x,e.y,s.y,(i-n)/2);return{via1:{x:e.x+c*l,y:e.y+d*l},via2:{x:s.x-c*l,y:s.y-d*l}}}handleRoutesDontCross(){const[t,e]=this.routes,s={connectionName:t.connectionName,route:[{x:t.startPort.x,y:t.startPort.y,z:t.startPort.z??0},{x:t.endPort.x,y:t.endPort.y,z:t.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]},n={connectionName:e.connectionName,route:[{x:e.startPort.x,y:e.startPort.y,z:e.startPort.z??0},{x:e.endPort.x,y:e.endPort.y,z:e.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};this.solvedRoutes.push(s,n),this.solved=!0}_step(){if(2!==this.routes.length)return void(this.failed=!0);const[t,e]=this.routes;this.doRoutesCross(t,e)?this.trySolveAOverB(t,e)||this.trySolveAOverB(e,t)||this.trySolveAOverB(t,e,!0)||this.trySolveAOverB(e,t,!0)?this.solved=!0:this.failed=!0:this.handleRoutesDontCross()}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.rects.push({center:{x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2},width:this.bounds.maxX-this.bounds.minX,height:this.bounds.maxY-this.bounds.minY,stroke:"rgba(0, 0, 0, 0.5)",fill:"rgba(240, 240, 240, 0.1)"});for(const[e,s]of[["Route A",this.routes[0]],["Route B",this.routes[1]]])t.points.push({x:s.startPort.x,y:s.startPort.y,label:`${e}\n${s.connectionName} start`,color:"orange"}),t.points.push({x:s.endPort.x,y:s.endPort.y,label:`${e}\n${s.connectionName} end`,color:"orange"}),t.lines.push({points:[s.startPort,s.endPort],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e}\n${s.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via1:s,via2:n}=this.debugViaPositions[e],i=["rgba(255, 165, 0, 0.3)","rgba(128, 0, 128, 0.3)"],o=i[e%i.length];t.circles.push({center:s,radius:this.viaDiameter/2,fill:o,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via A (attempt ${e+1})`}),t.circles.push({center:n,radius:this.viaDiameter/2,fill:o,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via B (attempt ${e+1})`});const a=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:s,radius:a,stroke:o,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 1 Safety Margin (attempt ${e+1})`}),t.circles.push({center:n,radius:a,stroke:o,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 2 Safety Margin (attempt ${e+1})`}),t.lines.push({points:[this.routes[e%2].startPort,s,n,this.routes[e%2].endPort],strokeColor:`${o.substring(0,o.lastIndexOf(","))}, 0.3)`,strokeDash:[5,5],label:`Potential Route (attempt ${e+1})`})}for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e],n=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1];t.lines.push({points:[i,o],strokeColor:n,strokeDash:1===i.z?[.2,.2]:void 0,strokeWidth:s.traceThickness,label:`${s.connectionName} z=${i.z}`}),i._label&&t.points.push({x:i.x,y:i.y,label:i._label})}for(const e of s.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Solved Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}};function Se(t,e,s,n,i){const o={x:(t.x+e.x+s.x)/3,y:(t.y+e.y+s.y)/3},a=(t,e)=>Math.sqrt((e.x-t.x)**2+(e.y-t.y)**2),r=o=>{const r=a(o,t),h=a(o,e),c=a(o,s),d=o.x>=i.minX&&o.x<=i.maxX&&o.y>=i.minY&&o.y<=i.maxY;return r>=n&&h>=n&&c>=n&&d};if(r(o))return o;const h=(t,e,s)=>{const n=t.x-e.x,i=t.y-e.y,o=Math.sqrt(n*n+i*i);return o<1e-10?{x:e.x+s,y:e.y}:{x:e.x+n/o*s,y:e.y+i/o*s}},c=(t,e,s)=>{const n=e.x-t.x,i=e.y-t.y,o=Math.sqrt(n*n+i*i);if(o>2*s-1e-10||o<1e-10)return[];const r=o*o/(2*o),h=Math.sqrt(Math.max(0,s*s-r*r)),c=t.x+n*r/o,d=t.y+i*r/o,l={x:c+h*i/o,y:d-h*n/o},u={x:c-h*i/o,y:d+h*n/o},p=[],f=1e-6;return Math.abs(a(l,t)-s)<f&&Math.abs(a(l,e)-s)<f&&p.push(l),Math.abs(a(u,t)-s)<f&&Math.abs(a(u,e)-s)<f&&p.push(u),p},d=[h(o,t,n),h(o,e,n),h(o,s,n),...c(t,e,n),...c(e,s,n),...c(s,t,n)],l=d.filter(r);if(l.length>0){const t=l.filter(t=>!(t=>{const e=1e-6;return Math.abs(t.x-i.minX)<e||Math.abs(t.x-i.maxX)<e||Math.abs(t.y-i.minY)<e||Math.abs(t.y-i.maxY)<e})(t));if(t.length>0)return t.sort((t,e)=>a(t,o)-a(e,o)),t[0]}let u=null,p=1/0;for(let t=i.minX+1;t<i.maxX;t+=5)for(let e=i.minY+1;e<i.maxY;e+=5){const s={x:t,y:e};if(r(s)){const t=a(s,o);t<p&&(p=t,u=s)}}if(null!==u)return u;const f=[];for(let t=0;t<=100;t++){const e=t/100;f.push({x:i.minX+e*(i.maxX-i.minX),y:i.minY}),f.push({x:i.maxX,y:i.minY+e*(i.maxY-i.minY)}),f.push({x:i.maxX-e*(i.maxX-i.minX),y:i.maxY}),f.push({x:i.minX,y:i.maxY-e*(i.maxY-i.minY)})}const m=f.filter(r);if(m.length>0)return m.sort((t,e)=>a(t,o)-a(e,o)),m[0];let g=1/0,y={x:i.minX,y:i.minY};for(const o of[...d,...f])if(o.x>=i.minX&&o.x<=i.maxX&&o.y>=i.minY&&o.y<=i.maxY){const i=Math.max(0,n-a(o,t))+Math.max(0,n-a(o,e))+Math.max(0,n-a(o,s));i<g&&(g=i,y=o)}return y}function be(t,e,s){const n=Ne(e,t,s.center,s.radius),i=Ne(t,e,s.center,s.radius),o=Ie(n,e),a=Ie(t,i),r=1e-6;let h;if(o>r&&a>r){h={x:(n.x+i.x)/2,y:(n.y+i.y)/2};const o=Ie(n,h),a=Ie(i,h);if(Math.abs(o-a)>.5*Math.min(o,a)){const s=Ie(t,n),o=Ie(e,i),a=s+o;if(a>r){const t=o/a,e=s/a;h={x:n.x*t+i.x*e,y:n.y*t+i.y*e}}}const c=Ie(h,s.center);if(c<1.05*s.radius){const t={x:(h.x-s.center.x)/c,y:(h.y-s.center.y)/c};h={x:s.center.x+t.x*s.radius*1.2,y:s.center.y+t.y*s.radius*1.2}}}else{const n={x:(t.x+e.x)/2,y:(t.y+e.y)/2},i=Ie(n,s.center);if(i<1.1*s.radius){const t={x:(n.x-s.center.x)/i,y:(n.y-s.center.y)/i};h={x:s.center.x+t.x*s.radius*1.2,y:s.center.y+t.y*s.radius*1.2}}else h=n}return{B:n,D:i,E:h}}function Ne(t,e,s,n){const i=[s.x-t.x,s.y-t.y],o=Math.sqrt(i[0]*i[0]+i[1]*i[1]);if(o<=n){if(o<1e-8){const i=[e.x-t.x,e.y-t.y],o=Math.sqrt(i[0]*i[0]+i[1]*i[1]);return o<1e-8?{x:s.x+n,y:s.y}:{x:s.x+i[0]/o*n,y:s.y+i[1]/o*n}}const a=[i[0]/o,i[1]/o];return{x:s.x-a[0]*n,y:s.y-a[1]*n}}const a=[e.x-t.x,e.y-t.y],r=Math.sqrt(o*o-n*n),h=[i[0]/o,i[1]/o],c=[-h[1],h[0]],d=[h[1],-h[0]],l=a[0]*c[0]+a[1]*c[1]>a[0]*d[0]+a[1]*d[1]?c:d,u=n/o,p=r/o,f=[h[0]*p+l[0]*u,h[1]*p+l[1]*u];return{x:t.x+r*f[0],y:t.y+r*f[1]}}function Ie(t,e){const s=e.x-t.x,n=e.y-t.y;return Math.sqrt(s*s+n*n)}var Pe=1e-9;function Ce(t,e,s,n="cw"){const i=_e(t,s),o=_e(e,s);return Math.abs(o-i)<Pe?{left:0,top:0,right:0,bottom:0}:function(t,e,s,n){const i=s.maxX-s.minX,o=s.maxY-s.minY;if(i<Pe&&o<Pe)return{left:0,top:0,right:0,bottom:0};const a=2*(i+o);if(a<Pe)return{left:0,top:0,right:0,bottom:0};const r=i/a*(2*Math.PI),h=(i+o)/a*(2*Math.PI),c=(i+i+o)/a*(2*Math.PI),d=2*Math.PI,l=[{name:"top",start:0,end:r,length:i},{name:"right",start:r,end:h,length:o},{name:"bottom",start:h,end:c,length:i},{name:"left",start:c,end:d,length:o}],u={left:0,top:0,right:0,bottom:0},p=(t,e,s,n,i)=>{const o=e>2*Math.PI-Pe?2*Math.PI:e;if(o<=t+Pe)return 0;if(i){const e=Math.max(t,s),i=Math.min(o,2*Math.PI),a=Math.max(0,i-e),r=Math.max(t,0),h=Math.min(o,n);return a+Math.max(0,h-r)}{const e=Math.max(t,s),i=Math.min(o,n);return Math.max(0,i-e)}};for(const s of l){const i=s.end-s.start;if(i<Pe||s.length<Pe)continue;let o=0;if("cw"===n){const n=t>e+Pe;o=p(s.start,s.end,t,e,n)}else{const n=e>t+Pe;o=p(s.start,s.end,e,t,n)}if(o>Pe){const t=o/i;u[s.name]+=Math.max(0,Number.isFinite(t)?t:0)}}for(const t in u)u[t]=Math.max(0,Math.min(1,u[t]));return u}(i,o,s,n)}function _e(t,e){const s=e.maxX-e.minX,n=e.maxY-e.minY;if(s<Pe&&n<Pe)return 0;const i=2*(s+n);if(i<Pe)return 0;let o=0;if(Math.abs(t.y-e.maxY)<Pe&&t.x>=e.minX-Pe&&t.x<=e.maxX+Pe)o=Math.max(0,Math.min(s,t.x-e.minX));else if(Math.abs(t.x-e.maxX)<Pe&&t.y>=e.minY-Pe&&t.y<=e.maxY+Pe)o=s+Math.max(0,Math.min(n,e.maxY-t.y));else if(Math.abs(t.y-e.minY)<Pe&&t.x>=e.minX-Pe&&t.x<=e.maxX+Pe)o=s+n+Math.max(0,Math.min(s,e.maxX-t.x));else{if(!(Math.abs(t.x-e.minX)<Pe&&t.y>=e.minY-Pe&&t.y<=e.maxY+Pe))throw new Error(`Point (${t.x}, ${t.y}) does not lie on the boundary defined by ${JSON.stringify(e)}`);o=s+n+s+Math.max(0,Math.min(n,t.y-e.minY))}return o=Math.max(0,Math.min(i,o)),i>Pe?o/i*(2*Math.PI):0}function Te(t,e,s,n){return function({angleA:t,angleB:e,angleC:s}){const n=Math.cos(t),i=Math.sin(t),o=Math.cos(e),a=Math.sin(e),r=Math.cos(s);return(o-n)*(Math.sin(s)-i)-(a-i)*(r-n)<0?"ccw":"cw"}({angleA:_e(t,n),angleB:_e(e,n),angleC:_e(s,n)})}var Ee=class extends e{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return void(this.failed=!0);const[e,s]=this.routes,n=e.A.z!==e.B.z,i=s.A.z!==s.B.z;(n&&i||!n&&!i)&&(this.failed=!0)}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,s=new Map;for(const t of e){const{connectionName:e}=t;s.has(e)||s.set(e,[]),s.get(e)?.push(t)}for(const[e,n]of s.entries())2===n.length&&t.push({A:{...n[0],z:n[0].z??0},B:{...n[1],z:n[1].z??0},connectionName:e});return t}calculateBounds(){return{minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2}}doRoutesCross(t,e){return i(t.A,t.B,e.A,e.B)}calculateViaPosition(t,e){const s=e.A.z,n=t.A.z!==s?t.A:t.B,i=2*this.obstacleMargin+this.viaDiameter/2+this.traceThickness,o=this.obstacleMargin+this.viaDiameter/2,a=e.A,r=n,h=e.B,c=Te(a,r,h,this.bounds),d=function(t,e,s,n,i){const o=Ce(t,e,n,i),a=Ce(e,s,n,i),r={left:Math.min(1,o.left+a.left),top:Math.min(1,o.top+a.top),right:Math.min(1,o.right+a.right),bottom:Math.min(1,o.bottom+a.bottom)};for(const t in r)Math.abs(r[t])<Pe&&(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),Se(a,r,h,i,l)}createTransitionRoute(t,e,s,n){return{connectionName:n,route:[{x:t.x,y:t.y,z:t.z??0},{x:s.x,y:s.y,z:t.z??0},{x:s.x,y:s.y,z:e.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[s]}}createFlatRoute(t,e,s,n,i,o){n.z,t.z;const a=this.viaDiameter/2+this.traceThickness/2+this.obstacleMargin,r=((t,e,s,n)=>{const i=s.x-t.x,o=s.y-t.y;return((t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}))({x:t.x+i*e,y:t.y+o*e},{x:s.x-i*n,y:s.y-o*n})})(s,this.viaDiameter,n.z!==t.z?n:i,this.traceThickness),h={center:{x:s.x,y:s.y},radius:a},c=be(t,r,h).E,d=be(r,e,h).E,l=be(t,c,h).E,u=be(c,r,h).E,p=be(r,d,h).E,f=be(d,e,h).E,m=be(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:m.x,y:m.y,z:t.z??0},{x:p.x,y:p.y,z:t.z??0},{x:d.x,y:d.y,z:t.z??0},{x:f.x,y:f.y,z:t.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]}}trySolve(){const[t,e]=this.routes,s=t.A.z!==t.B.z,n=s?t:e,i=s?e:t,o=this.calculateViaPosition(n,i);if(!o)return!1;this.debugViaPositions.push({via:o});const a=this.createTransitionRoute(n.A,n.B,o,n.connectionName),r=this.createFlatRoute(i.A,i.B,o,n.A,n.B,i.connectionName);return this.solvedRoutes.push(a,r),!0}_step(){if(!this.doRoutesCross(this.routes[0],this.routes[1]))return this.failed=!0,void(this.error="Can only solve routes that have a single transition crossing");this.trySolve()?this.solved=!0:this.failed=!0}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.rects.push({center:{x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2},width:this.bounds.maxX-this.bounds.minX,height:this.bounds.maxY-this.bounds.minY,stroke:"rgba(0, 0, 0, 0.5)",fill:"rgba(240, 240, 240, 0.1)",label:"PCB Bounds"});for(const e of this.routes)t.points.push({x:e.A.x,y:e.A.y,label:`${e.connectionName} start (z=${e.A.z})`,color:"orange"}),t.points.push({x:e.B.x,y:e.B.y,label:`${e.connectionName} end (z=${e.B.z})`,color:"orange"}),t.lines.push({points:[e.A,e.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via:s}=this.debugViaPositions[e];t.circles.push({center:s,radius:this.viaDiameter/2,fill:"rgba(255, 165, 0, 0.7)",stroke:"rgba(0, 0, 0, 0.5)",label:`Computed Via (attempt ${e+1})`});const n=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:s,radius:n,stroke:"rgba(255, 165, 0, 0.7)",fill:"rgba(0, 0, 0, 0)",label:"Safety Margin"})}for(let e=0;e<this.solvedRoutes.length;e++){const s=this.solvedRoutes[e],n=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1];t.lines.push({points:[i,o],strokeColor:n,strokeDash:i.z!==s.route[0].z?[.2,.2]:void 0,strokeWidth:s.traceThickness,label:`${s.connectionName} z=${i.z}`})}for(const e of s.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}},Ae=(t,e)=>{const s={};return t.portPoints.forEach((e,n)=>{s[e.connectionName]=`hsl(${360*n/t.portPoints.length}, 100%, 50%)`}),s},we=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;unprocessedConnections;completedPaths=new Map;placeholderPaths=new Map;currentHead;currentConnectionName;currentPath;currentViaCount;constructor({nodeWithPortPoints:t,colorMap:e,hyperParameters:s}){super(),this.MAX_ITERATIONS=1e5,this.colorMap=e??Ae(t),this.maxViaCount=5,this.bounds=pe(t),this.nodeWidth=this.bounds.maxX-this.bounds.minX,this.portPairMap=(t=>{const e=new Map;return t.portPoints.forEach(t=>{e.has(t.connectionName)?e.get(t.connectionName).end=t:e.set(t.connectionName,{start:t,end:null,connectionName:t.connectionName})}),e})(t),this.stats.solutionsFound=0,this.availableZ=t.availableZ??[0,1],this.hyperParameters=s??{SHUFFLE_SEED:0},this.unprocessedConnections=Array.from(this.portPairMap.keys()).sort(),s?.SHUFFLE_SEED&&(this.unprocessedConnections=ue(this.unprocessedConnections,s.SHUFFLE_SEED));for(const[t,{start:e,end:s}]of this.portPairMap.entries())if(e.z===s.z){const n=Math.abs(e.x-s.x)<1e-9,i=Math.abs(e.y-s.y)<1e-9;n||i?this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),this._padByPlaceholderWallBuffer(s),s]):this.placeholderPaths.set(t,[e,s])}else{const n=(e.x+s.x)/2,i=(e.y+s.y)/2,o=this._padByPlaceholderWallBuffer({x:n,y:i,z:e.z}),a=this._padByPlaceholderWallBuffer({x:n,y:i,z:s.z});this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),o,a,this._padByPlaceholderWallBuffer(s),s])}this.currentConnectionName=this.unprocessedConnections.pop();const n=this.portPairMap.get(this.currentConnectionName).start;this.currentHead=this._padByNewHeadWallBuffer(n),this.currentPath=[n,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}_padByNewHeadWallBuffer(t){return{x:n(t.x,this.bounds.minX+this.NEW_HEAD_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.NEW_HEAD_WALL_BUFFER_DISTANCE),y:n(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:n(t.x,this.bounds.minX+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),y:n(t.y,this.bounds.minY+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxY-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),z:t.z}}_step(){if(this.solved)return;const t=this.portPairMap.get(this.currentConnectionName).end,e=[this.currentHead,t];let s=null,n=null;const i=t=>{for(const i of t.values())for(let t=0;t<i.length-1;t++){const o=[i[t],i[t+1]];if(o[0].x===o[1].x&&o[0].y===o[1].y)continue;if(o[0].z!==this.currentHead.z)continue;const a=c(e[0],e[1],o[0],o[1]);if(a){const t=h(this.currentHead,a);if(t<1e-6)continue;(!s||t<s.dist)&&(s={point:a,dist:t},n=o[0].z)}}};i(this.completedPaths),i(this.placeholderPaths);const o=this.currentHead.z!==t.z;if((s||o)&&(this.currentViaCount++,this.currentViaCount>=this.maxViaCount))this.failed=!0;else if(s){let t;const e=s.dist;if(e<=this.VIA_INTERSECTION_BUFFER_DISTANCE+1e-6)t=d(this.currentHead,s.point);else{const n=s.point,i=n.x-this.currentHead.x,o=n.y-this.currentHead.y,a=(e-this.VIA_INTERSECTION_BUFFER_DISTANCE)/e;t={x:this.currentHead.x+i*a,y:this.currentHead.y+o*a}}const i=this.availableZ.find(t=>t!==n);if(void 0===i)return console.error("Could not determine next Z level for via placement!"),void(this.failed=!0);const o={...t,z:this.currentHead.z},a={...t,z:i};this.currentPath.push(o,a),this.currentHead=a}else if(o){let e;const s=h(this.currentHead,t);if(s<this.VIA_INTERSECTION_BUFFER_DISTANCE)e=d(this.currentHead,t);else{const n=t.x-this.currentHead.x,i=t.y-this.currentHead.y,o=(s-this.VIA_INTERSECTION_BUFFER_DISTANCE)/s;e={x:this.currentHead.x+n*o,y:this.currentHead.y+i*o}}const n=t.z,i={...e,z:this.currentHead.z},o={...e,z:n};this.currentPath.push(i,o),this.currentHead=o}else if(this.currentPath.push(t),this.completedPaths.set(this.currentConnectionName,this.currentPath),0===this.unprocessedConnections.length)this.solved=!0,this.stats.solutionsFound=1;else{this.currentConnectionName=this.unprocessedConnections.pop();const{start:t}=this.portPairMap.get(this.currentConnectionName);this.currentHead=this._padByNewHeadWallBuffer(t),this.currentPath=[t,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}}visualize(){const t={points:[],lines:[],circles:[],rects:[],title:"Via Possibilities Solver State",coordinateSystem:"cartesian"},e=this.colorMap;t.lines.push({points:[{x:this.bounds.minX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.minY}],strokeColor:"gray",strokeWidth:.01});for(const[e,{start:s,end:n}]of this.portPairMap.entries()){const i=this.colorMap[e]??"black";t.points.push({x:s.x,y:s.y,color:i,label:`Port: ${e} Start (z${s.z})`}),t.points.push({x:n.x,y:n.y,color:i,label:`Port: ${e} End (z${n.z})`})}const s=(s,n)=>{for(const[i,o]of s.entries()){const s=e[i]??"black";for(let e=0;e<o.length-1;e++){const a=o[e],r=o[e+1];a.x===r.x&&a.y===r.y&&a.z!==r.z?t.circles.push({center:{x:a.x,y:a.y},radius:.3,fill:ct(s,.5),label:`${n}: ${i} Via (z${a.z}->z${r.z})`}):t.lines.push({points:[a,r],strokeColor:ct(s,.5),strokeDash:0===a.z?void 0:[.1,.1],strokeWidth:.1,label:`${n}: ${i} (z${a.z})`})}}};if(s(this.placeholderPaths,"Placeholder"),s(this.completedPaths,"Completed"),this.currentPath&&this.currentPath.length>0){const s=e[this.currentConnectionName]??"orange";for(let e=0;e<this.currentPath.length-1;e++){const n=this.currentPath[e],i=this.currentPath[e+1];n.x===i.x&&n.y===i.y&&n.z!==i.z?t.circles.push({center:{x:n.x,y:n.y},radius:.3,fill:ct(s,.5),label:`Current: ${this.currentConnectionName} Via (z${n.z}->z${i.z})`}):t.lines.push({points:[n,i],strokeColor:ct(s,.5),strokeWidth:.15,strokeDash:"2,2",label:`Current: ${this.currentConnectionName} (z${n.z})`})}t.points.push({x:this.currentHead.x,y:this.currentHead.y,color:"green",label:`Current Head: ${this.currentConnectionName} (z${this.currentHead.z})`})}return t}},ze=1e-9;function Re(t,e,s=ze){return Math.abs(t-e)<s}function Oe(t,e,s,n){return t*n-e*s}function Le(t,e,s,n){const i={x:e.x-t.x,y:e.y-t.y},o={x:n.x-s.x,y:n.y-s.y},a=Oe(i.x,i.y,o.x,o.y);if(Re(a,0))return null;const r={x:s.x-t.x,y:s.y-t.y},h=Oe(r.x,r.y,o.x,o.y)/a,c=Oe(r.x,r.y,i.x,i.y)/a;return h<-ze||h>1+ze||c<-ze||c>1+ze?null:{x:t.x+h*i.x,y:t.y+h*i.y}}function De(t){let e=0;for(let s=0,n=t.length;s<n;++s){const i=(s+1)%n;e+=t[s].x*t[i].y-t[i].x*t[s].y}return.5*e}function $e(t){let e=0,s=0,n=0;for(let i=0,o=t.length;i<o;++i){const a=(i+1)%o,r=t[i].x*t[a].y-t[a].x*t[i].y;e+=r,s+=(t[i].x+t[a].x)*r,n+=(t[i].y+t[a].y)*r}return e*=.5,Re(e,0)?null:(s/=6*e,n/=6*e,{x:s,y:n})}var Ye=class{x;y;out;connectionNames;constructor(t,e){this.x=t,this.y=e,this.out=[],this.connectionNames=new Set}},Xe=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 ke(t,e){const s=[...e,...[{start:{x:t.minX,y:t.minY},end:{x:t.maxX,y:t.minY}},{start:{x:t.maxX,y:t.minY},end:{x:t.maxX,y:t.maxY}},{start:{x:t.maxX,y:t.maxY},end:{x:t.minX,y:t.maxY}},{start:{x:t.minX,y:t.maxY},end:{x:t.minX,y:t.minY}}]],n=s.map(()=>[]);for(let t=0;t<s.length;++t){const e=s[t];n[t].push(e.start,e.end)}for(let t=0;t<s.length;++t)for(let e=t+1;e<s.length;++e){const i=Le(s[t].start,s[t].end,s[e].start,s[e].end);i&&(n[t].push(i),n[e].push(i))}const i=new Map,o=[];function a(t){const e=function(t,e=ze){return`${Math.round(t.x/e)}:${Math.round(t.y/e)}`}(t);if(!i.has(e)){const s=o.length;return i.set(e,s),o.push(new Ye(t.x,t.y)),s}return i.get(e)}const r=[];for(let t=0;t<s.length;++t){const e=s[t],i=n[t].slice();i.sort((t,s)=>{const n=e.end.x-e.start.x,i=e.end.y-e.start.y;return(Re(Math.abs(n),0)?(t.y-e.start.y)/i:(t.x-e.start.x)/n)-(Re(Math.abs(n),0)?(s.y-e.start.y)/i:(s.x-e.start.x)/n)});for(let t=0;t<i.length-1;++t){const s=i[t],n=i[t+1],h=a(s),c=a(n);h!==c&&(r.push([h,c]),e.connectionName&&(o[h].connectionNames.add(e.connectionName),o[c].connectionNames.add(e.connectionName)))}}const h=[];for(const[t,e]of r){const s=new Xe(t,e),n=new Xe(e,t);s.twin=h.length+1,n.twin=h.length;const i=h.length;h.push(s,n),o[t].out.push(i),o[e].out.push(i+1)}for(let t=0;t<o.length;++t){const e=o[t];e.out.sort((t,s)=>{const n=h[t],i=h[s],a=o[n.dest],r=o[i.dest];return Math.atan2(a.y-e.y,a.x-e.x)-Math.atan2(r.y-e.y,r.x-e.x)});const s=e.out.length;for(let t=0;t<s;++t){const n=e.out[t],i=e.out[(t-1+s)%s],o=h[n];null!==o.twin&&(h[o.twin].next=i)}}const c=[],d=[];for(let t=0;t<h.length;++t){if(h[t].visited)continue;let e=t;const s=[],n=[];do{if(null===e)break;const t=h[e];t.visited=!0,s.push(o[t.orig]),n.push(e),e=t.next}while(null!==e&&e!==t&&!h[e].visited);if(s.length<3)continue;if(De(s)>ze){const t=$e(s);t&&(c.push(t),d.push({vertices:s.map(t=>({x:t.x,y:t.y,connectionNames:t.connectionNames.size>0?t.connectionNames:void 0})),centroid:t}))}}return{centroids:c,faces:d,allVertices:o}}function Be(t,e){if(t>e)throw new Error("oneCount cannot be greater than length");if(t<0||e<0)throw new Error("oneCount and length must be non-negative");const s=[];return function t(n,i,o){o!==e?(n[o]=0,t(n,i,o+1),i>0&&(n[o]=1,t(n,i-1,o+1))):0===i&&s.push([...n])}(Array(e).fill(0),t,0),s}var Fe=t=>{if(0===t.length)return[[]];const e=[];for(let s=0;s<t.length;s++){const n=t[s],i=[...t.slice(0,s),...t.slice(s+1)],o=Fe(i);for(const t of o)e.push([n,...t])}return e};var He=t=>{const{start:e,end:s,segmentsPerPolyline:n,viaPositions:i,viaCount:o,availableZ:a}=t,r=function(t,e){const s=new Array(t).fill(0);if(0===e)return s;if(e===t)return s.fill(1);if(e<=t/2){const n=Math.floor(t/e),i=Math.floor((t-(n*(e-1)+1))/2);for(let t=0;t<e;t++)s[i+t*n]=1}else{const n=t-e,i=Math.floor(t/n),o=Math.floor((t-(i*(n-1)+1))/2);s.fill(1);for(let t=0;t<n;t++)s[o+t*i]=0}return s}(n,o),h=r.map(()=>null);let c=0,d=e.z1;const l=a.indexOf(e.z1);for(let t=0;t<r.length;t++)if(1===r[t]){const e=a[(l+c+1)%a.length];h[t]={...i[c],z1:d,z2:e},d=e,c++}let u=e;for(let t=0;t<h.length;t++){if(h[t]){u=h[t];continue}let e=s,n=h.length;for(let s=t+1;s<h.length;s++)if(h[s]){e=h[s],n=s;break}const i=n-t,o=e.x-u.x,a=e.y-u.y;for(let e=1/(i+1),s=0;t+s!==n;e+=1/(i+1),s++)h[t+s]={x:u.x+o*e,y:u.y+a*e,z1:u.z2,z2:u.z2}}return h},Ze=1e-9;function Ue(t,e){return Math.abs(t-e)<Ze}function Ve(t){return`${Math.round(t.x/Ze)}:${Math.round(t.y/Ze)}`}function je(t,e,s,n){return t*n-e*s}function We(t,e,s,n){const i={x:e.x-t.x,y:e.y-t.y},o={x:n.x-s.x,y:n.y-s.y},a=je(i.x,i.y,o.x,o.y),r={x:s.x-t.x,y:s.y-t.y};if(Ue(a,0))return null;const h=je(r.x,r.y,o.x,o.y)/a,c=je(r.x,r.y,i.x,i.y)/a;return h>=-1e-9&&h<=1+Ze&&c>=-1e-9&&c<=1+Ze?{x:t.x+h*i.x,y:t.y+h*i.y}:null}function Ge(t,e,s){return Ue(Math.hypot(t.x-e.x,t.y-e.y)+Math.hypot(t.x-s.x,t.y-s.y),Math.hypot(e.x-s.x,e.y-s.y))}function qe(t,e){const s=[],n=new Map;for(const e of t){const t=[e.start,...e.mPoints,e.end];for(let i=0;i<t.length-1;i++){const o=t[i],a=t[i+1],r=o.z2;if(s.push({start:{x:o.x,y:o.y},end:{x:a.x,y:a.y},connectionName:e.connectionName,layer:r}),o.z1!==o.z2){const t=Ve(o);n.has(t)||n.set(t,{point:o,connectionName:e.connectionName})}}const i=t[t.length-1];if(i.z1!==i.z2){const t=Ve(i);n.has(t)||n.set(t,{point:i,connectionName:e.connectionName})}}const i=[{start:{x:e.minX,y:e.minY},end:{x:e.maxX,y:e.minY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.minY},end:{x:e.maxX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.maxY},end:{x:e.minX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.minX,y:e.maxY},end:{x:e.minX,y:e.minY},connectionName:null,layer:0}];s.push(...i);const o=new Map;let a=0;function r(t,e){const s=Ve(t);let i=o.get(s);if(!i){const e=n.has(s);i={id:a++,x:t.x,y:t.y,isVia:e,connectionNames:new Set,outgoingEdges:[]},o.set(s,i),e&&n.get(s)&&i.connectionNames.add(n.get(s).connectionName)}return e&&i.connectionNames.add(e),i}for(const t of s)r(t.start,t.connectionName),r(t.end,t.connectionName);const h=new Map;for(const t of s)h.set(t,[]);for(let t=0;t<s.length;t++)for(let e=t+1;e<s.length;e++){if(s[t].layer!==s[e].layer)continue;const n=We(s[t].start,s[t].end,s[e].start,s[e].end);n&&(r(n),Ge(n,s[t].start,s[t].end)&&h.get(s[t]).push(n),Ge(n,s[e].start,s[e].end)&&h.get(s[e]).push(n))}const c=[];let d=0;for(const t of s){const e=[t.start,...h.get(t),t.end];e.sort((e,s)=>{const n=t.end.x-t.start.x,i=t.end.y-t.start.y;return Math.abs(n)>Math.abs(i)?(e.x-t.start.x)/n-(s.x-t.start.x)/n:Math.abs(i)<Ze?0:(e.y-t.start.y)/i-(s.y-t.start.y)/i});const s=[];if(e.length>0){s.push(e[0]);for(let t=1;t<e.length;t++)Ue(e[t].x,e[t-1].x)&&Ue(e[t].y,e[t-1].y)||s.push(e[t])}for(let e=0;e<s.length-1;e++){const n=s[e],i=s[e+1],o=r(n,t.connectionName),a=r(i,t.connectionName);if(o===a)continue;const h={id:d++,origin:o,twin:null,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1},l={id:d++,origin:a,twin:h,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1};h.twin=l,c.push(h,l),o.outgoingEdges.push(h),a.outgoingEdges.push(l)}}for(const t of o.values()){t.outgoingEdges.sort((e,s)=>{const n=e.twin.origin,i=s.twin.origin;return Math.atan2(n.y-t.y,n.x-t.x)-Math.atan2(i.y-t.y,i.x-t.x)});const e=t.outgoingEdges.length;for(let s=0;s<e;s++){const n=t.outgoingEdges[s],i=t.outgoingEdges[(s-1+e)%e];n.twin&&(n.twin.next=i)}}const l=[];let u=0,p=null,f=-1/0;for(const t of c){if(t.visited)continue;const e={id:u++,outerComponent:t,innerComponents:[],isOuterFace:!1};l.push(e);let s=t;const n=[],i=[],o=new Set;let a=0;do{if(!s||s.visited){console.warn("Face traversal encountered visited edge or null, breaking loop.",e.id),n.length=0;break}s.visited=!0,s.face=e,n.push(s),i.push(s.origin),null!==s.connectionName&&o.add(s.connectionName);const t=s.origin,r=s.twin.origin;a+=t.x*r.y-r.x*t.y,s=s.next}while(s!==t&&null!==s);if(s===t){if(a=.5*Math.abs(a),a>f&&(f=a,p&&(p.isOuterFace=!1),p=e,e.isOuterFace=!0),!e.isOuterFace&&n.length>0){if([...o].filter(t=>null!==t).length>1){let t=!1;for(const e of i)if(e.isVia){t=!0;break}if(!t)return!0}}}else console.warn(`Face ${e.id} did not close properly.`),l.pop(),u--}return!1}var Ke=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??Ae(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.cellSize=this.nodeWithPortPoints.width/1024,this.candidates=[],this.availableZ=this.nodeWithPortPoints.availableZ??[0,1],this.bounds={minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2};const e=this.nodeWithPortPoints.width*this.nodeWithPortPoints.height,s=(this.viaDiameter+2*this.obstacleMargin+this.traceWidth/2)**2,n=new Set(this.nodeWithPortPoints.portPoints.map(t=>t.connectionName)).size;this.uniqueConnections=n;const{numSameLayerCrossings:o,numTransitions:a}=(t=>{let e=0,s=[];const n=[];let o=0;for(const e of t.portPoints){if(s.some(t=>t.connectionName===e.connectionName))continue;if(n.some(t=>t.connectionName===e.connectionName))continue;const i={connectionName:e.connectionName,z:e.z,points:[{x:e.x,y:e.y,z:e.z}]};for(const s of t.portPoints)e.connectionName===s.connectionName&&(e.x===s.x&&e.y===s.y||i.points.push({x:s.x,y:s.y,z:s.z}));i.points.some(t=>t.z!==i.z)?(o++,n.push(i)):s.push(i)}s=s.filter(t=>t.points.length>1);for(let t=0;t<s.length;t++)for(let n=t+1;n<s.length;n++){const o=s[t],a=s[n];o.z===a.z&&i(o.points[0],o.points[1],a.points[0],a.points[1])&&e++}let a=0;for(let t=0;t<n.length;t++)for(let e=t+1;e<n.length;e++){const s=n[t],o=n[e];i(s.points[0],s.points[1],o.points[0],o.points[1])&&a++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:o,numTransitionPairCrossings:a,numTransitions:n.length}})(this.nodeWithPortPoints);if(this.minViaCount=2*o+a,this.maxViaCount=Math.min(Math.floor(e/s),Math.ceil(1.5*n)),this.minViaCount>this.SEGMENTS_PER_POLYLINE*(n/2))return this.failed=!0,void(this.error=`Not possible to solve problem with given SEGMENTS_PER_POLYLINE (${this.SEGMENTS_PER_POLYLINE}), atleast ${this.minViaCount} vias are required`);this.maxViaCount>this.SEGMENTS_PER_POLYLINE&&(this.maxViaCount=this.SEGMENTS_PER_POLYLINE),this.maxViaCount<this.minViaCount&&(this.maxViaCount=this.minViaCount)}computeMinGapBtwPolyLines(t){const e=[],s=[],n=[];for(let e=0;e<t.length;e++){const i=t[e],o=[i.start,...i.mPoints,i.end],a=new Map(this.availableZ.map(t=>[t,[]]));for(let t=0;t<o.length-1;t++){const e=[o[t],o[t+1]],s=e[0].z2;a.has(s)||a.set(s,[]),a.get(s).push(e)}s.push(a),n.push(o.filter(t=>t.z1!==t.z2))}for(let i=0;i<t.length;i++){const o=s[i],a=n[i];for(let c=i+1;c<t.length;c++){if(this.connMap?.areIdsConnected(t[i].connectionName,t[c].connectionName))continue;const d=s[c],l=n[c];let u=1;for(const t of this.availableZ){const e=o.get(t)??[],s=d.get(t)??[];for(const t of e)for(const e of s)u=Math.min(u,M(t[0],t[1],e[0],e[1])-this.traceWidth);for(const t of a)for(const e of s)u=Math.min(u,r(t,e[0],e[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of l)for(const s of e)u=Math.min(u,r(t,s[0],s[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of a)for(const e of l)u=Math.min(u,h(t,e)-this.viaDiameter)}e.push(u)}}return e}insertCandidate(t){let e=0,s=this.candidates.length-1;for(;e<=s;){const n=Math.floor((e+s)/2);this.candidates[n].f<t.f?e=n+1:s=n-1}this.candidates.splice(e,0,t)}setupInitialPolyLines(){const t=new Map;this.nodeWithPortPoints.portPoints.forEach(e=>{t.has(e.connectionName)?t.get(e.connectionName).end={...e,z1:e.z??0,z2:e.z??0}:t.set(e.connectionName,{start:{...e,z1:e.z??0,z2:e.z??0},end:null})});for(const[e,s]of t.entries())null===s.end&&t.delete(e);if(0===t.size)return this.failed=!0,void(this.error="No port pairs found, can't solve");const e=Array.from(t.entries()),s=((t,e,s,n)=>{const o=[];for(const[,s]of t){const t=s.start.z1!==s.end.z1,n=[];for(let s=0;s<=e;s++){const e=s%2!=0;t&&e?n.push(s):t||e||n.push(s)}o.push(n)}if(0===o.length)return[[]];let a=(t=>{if(!t||0===t.length)return[[]];let e=[[]];for(const s of t){const t=[];for(const n of e)for(const e of s)t.push([...n,e]);e=t}return e})(o).filter(t=>{for(let e=0;e<t.length;e++)if(t.reduce((t,e)=>t+e,0)<n)return!1;return!0});return a=a.filter(e=>{for(let s=0;s<t.length;s++){const[,n]=t[s];if(n.start.z1!==n.start.z2&&0===e[s])return!1}return!0}),a=a.filter(e=>{for(let s=0;s<t.length;s++){const[,n]=t[s];if(t[s][1].start.z1===t[s][1].start.z2)for(let o=s+1;o<t.length;o++){if(t[o][1].start.z1!==t[o][1].start.z2)continue;const[,a]=t[o];if(n.start.z1===n.end.z1&&a.start.z1===a.end.z1&&n.start.z1===a.start.z1&&i(n.start,n.end,a.start,a.end)&&e[s]+e[o]<2)return!1}}return!0}),a=a.filter(t=>!(t.reduce((t,e)=>t+e,0)>s)),a})(e,this.SEGMENTS_PER_POLYLINE,this.maxViaCount,this.minViaCount),n=(t=>{const{bounds:e,portPairsEntries:s,viaCountVariants:n}=t,{centroids:i}=ke(e,s.map(([t,e])=>e)),o=[];for(const t of n){const s=t.reduce((t,e)=>t+e,0);let n=i;if(i.length<s){n=[];const t=Math.ceil(Math.sqrt(s)),i=t;for(let s=0;s<t;s++)for(let o=0;o<i;o++)n.push({x:e.minX+(o+1)/(i+1)*(e.maxX-e.minX),y:e.minY+(s+1)/(t+1)*(e.maxY-e.minY)})}const a=Be(s,n.length);for(const e of a){const s=[];for(let t=0;t<e.length;t++)1===e[t]&&s.push(n[t]);o.push({viaPositions:s,viaCountVariant:t})}}return o})({portPairsEntries:e,viaCountVariants:s,bounds:this.bounds}),o=[];for(const{viaCountVariant:t,viaPositions:e}of n){const s=Fe(e);for(const e of s)o.push({viaCountVariant:t,viaPositions:e})}for(const{viaPositions:t,viaCountVariant:s}of o){const n=[];let i=0;for(let o=0;o<e.length;o++){const[a,r]=e[o],h=s[o],c=t.slice(i,i+h),d=He({start:r.start,end:r.end,segmentsPerPolyline:this.SEGMENTS_PER_POLYLINE,viaPositions:c,viaCount:h,availableZ:this.availableZ});i+=h,n.push({connectionName:a,start:r.start,end:r.end,mPoints:d})}if(qe(n,this.bounds))continue;const o=this.computeMinGapBtwPolyLines(n),a=this.computeH({minGaps:o,forces:[]}),r={polyLines:n,g:0,h:a,f:a,viaCount:s.reduce((t,e)=>t+e,0),minGaps:o};if(this.checkIfSolved(r))return void(this.candidates=[r]);if(this.candidates.push(r),this.candidates.length>this.MAX_CANDIDATES)return}this.candidates.sort((t,e)=>t.f-e.f)}computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){let e=0;for(const s of t.forces??[])for(const t of s)for(const s of t.values())e+=s.fx*s.fx+s.fy*s.fy;return e}getNeighbors(t){const{polyLines:e}=t,s=e.length,n=.02,i=.008,o=1e-6,a=Array.from({length:s},(t,s)=>Array.from({length:e[s].mPoints.length},()=>new Map)),r=(t,s,n,i,o)=>{if(s>0&&s<e[t].mPoints.length+1){const e=s-1,r=a[t][e],h=r.get(n)||{fx:0,fy:0};r.set(n,{fx:h.fx+i,fy:h.fy+o})}};for(let t=0;t<s;t++)for(let i=t+1;i<s;i++){const s=e[t],a=e[i],h=[s.start,...s.mPoints,s.end],c=[a.start,...a.mPoints,a.end],d=[],l=[];for(let t=0;t<h.length-1;t++)d.push({p1:h[t],p2:h[t+1],layer:h[t].z2,p1Idx:t,p2Idx:t+1});h.forEach((t,e)=>{t.z1!==t.z2&&l.push({point:t,layers:[t.z1,t.z2],index:e})});const u=[],p=[];for(let t=0;t<c.length-1;t++)u.push({p1:c[t],p2:c[t+1],layer:c[t].z2,p1Idx:t,p2Idx:t+1});c.forEach((t,e)=>{t.z1!==t.z2&&p.push({point:t,layers:[t.z1,t.z2],index:e})});for(const e of d)for(const s of u)if(e.layer===s.layer){if(M(e.p1,e.p2,s.p1,s.p2)<o)continue;const n={x:(e.p1.x+e.p2.x)/2,y:(e.p1.y+e.p2.y)/2},a={x:(s.p1.x+s.p2.x)/2,y:(s.p1.y+s.p2.y)/2},h=n.x-a.x,c=n.y-a.y,d=h*h+c*c;if(d>o){const n=Math.sqrt(d),a=(Math.exp(-6*n),`seg:${i}:${s.p1Idx}:${s.p2Idx}`),h=`seg:${t}:${e.p1Idx}:${e.p2Idx}`,c=(t,e,s,n,i,a,h)=>{const c=S(t,s.p1,s.p2),d=t.x-c.x,l=t.y-c.y,u=d*d+l*l;if(u<=o)return;const p=Math.sqrt(u),f=.02*Math.exp(-6*p),m=d/p*f,g=l/p*f;r(n,e,a,m,g),r(i,s.p1Idx,h,-m/2,-g/2),r(i,s.p2Idx,h,-m/2,-g/2)};c(e.p1,e.p1Idx,s,t,i,a,h),c(e.p2,e.p2Idx,s,t,i,a,h),c(s.p1,s.p1Idx,e,i,t,h,a),c(s.p2,s.p2Idx,e,i,t,h,a)}}for(const e of l)for(const s of u)if(e.layers.includes(s.layer)){const a=S(e.point,s.p1,s.p2),h=e.point.x-a.x,c=e.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,m=c/a*p,g=`seg:${i}:${s.p1Idx}:${s.p2Idx}`;r(t,e.index,g,f,m);const y=`via:${t}:${e.index}`;r(i,s.p1Idx,y,-f/2,-m/2),r(i,s.p2Idx,y,-f/2,-m/2)}}for(const e of p)for(const s of d)if(e.layers.includes(s.layer)){const a=S(e.point,s.p1,s.p2),h=e.point.x-a.x,c=e.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,m=c/a*p,g=`seg:${t}:${s.p1Idx}:${s.p2Idx}`;r(i,e.index,g,f,m);const y=`via:${i}:${e.index}`;r(t,s.p1Idx,y,-f/2,-m/2),r(t,s.p2Idx,y,-f/2,-m/2)}}for(const e of l)for(const s of p){if(e.layers.filter(t=>s.layers.includes(t)).length>0){const a=e.point.x-s.point.x,h=e.point.y-s.point.y,c=a*a+h*h;if(c>o){const d=Math.sqrt(c);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(o,d)):u=Math.max(o,d-this.viaDiameter);const p=l*n*Math.exp(-6*u),f=a/d*p,m=h/d*p,g=`via:${i}:${s.index}`,y=`via:${t}:${e.index}`;r(t,e.index,g,f,m),r(i,s.index,y,-f,-m)}}}}for(let t=0;t<s;t++){const s=e[t],i=[s.start,...s.mPoints,s.end],a=[];if(i.forEach((t,e)=>{t.z1!==t.z2&&a.push({point:t,layers:[t.z1,t.z2],index:e})}),!(a.length<2))for(let e=0;e<a.length;e++)for(let s=e+1;s<a.length;s++){const i=a[e],h=a[s],c=i.point.x-h.point.x,d=i.point.y-h.point.y,l=c*c+d*d;if(l>o){const e=Math.sqrt(l);let s=2,a=e;e<this.viaDiameter?(s*=4,a=Math.max(o,e)):a=Math.max(o,e-this.viaDiameter);const u=s*n*Math.exp(-6*a),p=c/e*u,f=d/e*u,m=`via:${t}:${h.index}`,g=`via:${t}:${i.index}`;r(t,i.index,m,p,f),r(t,h.index,g,-p,-f)}}}const h=e.map(t=>({...t,mPoints:t.mPoints.map(t=>({...t}))}));let c=!1;for(let t=0;t<s;t++)for(let e=0;e<h[t].mPoints.length;e++){const s=h[t].mPoints[e],n=a[t][e],r={fx:0,fy:0};for(const t of n.values())r.fx+=t.fx,r.fy+=t.fy;const d=s.z1!==s.z2;let l=s.x+r.fx,u=s.y+r.fy;if(d){const t=this.viaDiameter/2;let e=0,n=0;const o=this.viaDiameter/2+this.BOUNDARY_PADDING,a=this.bounds.minX+o,h=this.bounds.maxX-o,c=this.bounds.minY+o,d=this.bounds.maxY-o,p=a+t-s.x,f=s.x-(h-t),m=c+t-s.y,g=s.y-(d-t);p>0?e=i*(Math.exp(p/(2*this.obstacleMargin))-1):f>0&&(e=-.008*(Math.exp(f/(2*this.obstacleMargin))-1)),m>0?n=i*(Math.exp(m/(2*this.obstacleMargin))-1):g>0&&(n=-.008*(Math.exp(g/(2*this.obstacleMargin))-1)),r.fx+=e,r.fy+=n,l=s.x+r.fx,u=s.y+r.fy}else{const t=this.traceWidth/2+this.BOUNDARY_PADDING;l=Math.max(this.bounds.minX+t,Math.min(this.bounds.maxX-t,l)),u=Math.max(this.bounds.minY+t,Math.min(this.bounds.maxY-t,u))}Math.abs(r.fx)<o&&Math.abs(r.fy)<o||(Math.abs(s.x-l)>o||Math.abs(s.y-u)>o)&&(s.x=l,s.y=u,c=!0)}if(!c)return[];const d=this.computeMinGapBtwPolyLines(h),l=this.computeG(h,t),u=this.computeH({minGaps:d,forces:a});return[{polyLines:h,g:l,h:u,f:Math.round(5*l)/5+u,minGaps:d,forces:a,viaCount:t.viaCount}]}checkIfSolved(t){const e=t.minGaps.every(t=>t>=this.obstacleMargin),s=t.polyLines.every(t=>t.mPoints.every(t=>{const e=(t.z1!==t.z2?this.viaDiameter/2:this.traceWidth/2)+this.BOUNDARY_PADDING;return((t,e,s=0)=>t.x>=e.minX+s&&t.x<=e.maxX-s&&t.y>=e.minY+s&&t.y<=e.maxY-s)(t,this.bounds,e)}));return e&&s}tryFinalAcceptance(){const t=this.hyperParameters?.MINIMUM_FINAL_ACCEPTANCE_GAP??void 0;if(void 0===t||null===this.lastCandidate||0===this.lastCandidate.minGaps.length)return;return Math.min(...this.lastCandidate.minGaps)>=t?(this.solved=!0,void this._setSolvedRoutes()):void 0}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return this.failed=!0,void(this.error="No candidates left")}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();if(!t)return void(this.failed=!0);const e=this.getNeighbors(t);for(const t of e)this.insertCandidate(t)}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"MultiHeadPolyLineIntraNodeSolver Visualization"};t.lines.push({points:[{x:this.bounds.minX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.minY}],strokeColor:"gray"});const e=this.lastCandidate??this.candidates[0];if(e?.hasClosedSameLayerFace){const e=.1*(this.bounds.maxX-this.bounds.minX),s=.1*(this.bounds.maxY-this.bounds.minY);t.rects.push({center:{x:this.bounds.maxX+.6*e,y:this.bounds.maxY+.6*s},width:e,height:s,fill:"red",label:"HAS CLOSED FACE"})}for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:`${e.connectionName} (Port z=${e.z??0})`,color:this.colorMap[e.connectionName]??"blue"});return e&&e.polyLines.forEach((s,n)=>{const i=this.colorMap[s.connectionName]??"purple",o=[s.start,...s.mPoints,s.end];for(let e=0;e<o.length-1;e++){const n=o[e],a=o[e+1],r=n.z2,h=0===r,c=h?i:ct(i,.5);t.lines.push({points:[n,a],strokeColor:c,strokeWidth:this.traceWidth,strokeDash:h?void 0:[.15,.15],label:`${s.connectionName} segment (z=${r})`})}o.forEach((a,r)=>{const h=a.z1!==a.z2,c=a.z1,d=r>0&&r<o.length-1;let l="",u="";if(d){const i=r-1,o=e.forces?.[n]?.[i];if(o&&o.size>0){const n={fx:0,fy:0};o.forEach((o,r)=>{if(n.fx+=o.fx,n.fy+=o.fy,Math.abs(o.fx)>1e-6||Math.abs(o.fy)>1e-6){const n=r.split(":"),h=n[0],c=parseInt(n[1],10),d=e.polyLines[c],l=this.colorMap[d.connectionName]??"gray",u=20,p={x:a.x+o.fx*u,y:a.y+o.fy*u};let f=d.connectionName;if("via"===h){f+=` Via ${parseInt(n[2],10)}`}else if("seg"===h){f+=` Seg ${parseInt(n[2],10)}-${parseInt(n[3],10)}`}t.lines.push({points:[a,p],strokeColor:l,strokeWidth:.02,strokeDash:"2,2",label:`Force by ${f} on ${s.connectionName} mPoint ${i}`})}}),(Math.abs(n.fx)>1e-6||Math.abs(n.fy)>1e-6)&&(u=`\nNet Force: (${n.fx.toFixed(3)}, ${n.fy.toFixed(3)})`)}}if(h)l=`Via (${s.connectionName} z=${a.z1} -> z=${a.z2})${u}`,t.circles.push({center:a,radius:this.viaDiameter/2,fill:ct(i,.5),label:l});else if(d){const e=0===c?i:ct(i,.5);l=`mPoint (${s.connectionName} z=${c})${u}`,t.circles.push({center:a,radius:this.cellSize/8,fill:e,label:l})}})}),t}_setSolvedRoutes(){if(!this.solved||!this.lastCandidate)return[];const t=[];for(const e of this.lastCandidate.polyLines){const s=[],n=[],i=[e.start,...e.mPoints,e.end];for(let t=0;t<i.length;t++){const e=i[t];s.push({x:e.x,y:e.y,z:e.z1}),e.z1!==e.z2&&(n.push({x:e.x,y:e.y}),s.push({x:e.x,y:e.y,z:e.z2}))}t.push({connectionName:e.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:s,vias:n})}this.solvedRoutes=t}},Je=class extends Ke{computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){const{minGaps:e}=t;let s=0;for(const t of e)t<0&&(s+=this.obstacleMargin),t<this.obstacleMargin&&(s+=this.obstacleMargin-t);return.011*s}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return void(this.failed=!0)}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();let e=!1,s=0;const n=void 0===t.magForceApplied?1:10;for(let i=0;i<n;i++){const n=this.applyForcesToPolyLines(t.polyLines);if(s+=n.magForceApplied,e=n.lastStepMoved,!n.lastStepMoved)break}if(t.magForceApplied=s,t.minGaps=this.computeMinGapBtwPolyLines(t.polyLines),this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();t.g=this.computeG(t.polyLines,t),t.h=this.computeH(t),t.f=t.g+t.h,e&&this.insertCandidate(t)}applyForcesToPolyLines(t){let e=0;const s=t.length,n=.02,i=.008,o=1e-6,a=Array.from({length:s},(e,s)=>Array.from({length:t[s].mPoints.length},()=>({fx:0,fy:0}))),r=(e,s,n,i)=>{if(s>0&&s<t[e].mPoints.length+1){const t=s-1;a[e][t].fx+=n,a[e][t].fy+=i}},h=(t,e,s,n,i)=>{const a=S(t,s.p1,s.p2),h=t.x-a.x,c=t.y-a.y,d=h*h+c*c;if(d<=o)return;const l=Math.sqrt(d),u=.02*Math.exp(-6*l),p=h/l*u,f=c/l*u;r(n,e,p,f),r(i,s.p1Idx,-p/2,-f/2),r(i,s.p2Idx,-p/2,-f/2)};for(let e=0;e<s;e++)for(let i=e+1;i<s;i++){const s=t[e],a=t[i],c=[s.start,...s.mPoints,s.end],d=[a.start,...a.mPoints,a.end],l=[],u=[];for(let t=0;t<c.length-1;t++)l.push({p1:c[t],p2:c[t+1],layer:c[t].z2,p1Idx:t,p2Idx:t+1});c.forEach((t,e)=>{t.z1!==t.z2&&u.push({point:t,layers:[t.z1,t.z2],index:e})});const p=[],f=[];for(let t=0;t<d.length-1;t++)p.push({p1:d[t],p2:d[t+1],layer:d[t].z2,p1Idx:t,p2Idx:t+1});d.forEach((t,e)=>{t.z1!==t.z2&&f.push({point:t,layers:[t.z1,t.z2],index:e})});for(const t of l)for(const s of p)if(t.layer===s.layer){M(t.p1,t.p2,s.p1,s.p2);h(t.p1,t.p1Idx,s,e,i),h(t.p2,t.p2Idx,s,e,i),h(s.p1,s.p1Idx,t,i,e),h(s.p2,s.p2Idx,t,i,e)}for(const t of u)for(const s of p)if(t.layers.includes(s.layer)){const a=S(t.point,s.p1,s.p2),h=t.point.x-a.x,c=t.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,m=c/a*p;r(e,t.index,f,m),r(i,s.p1Idx,-f/2,-m/2),r(i,s.p2Idx,-f/2,-m/2)}}for(const t of f)for(const s of l)if(t.layers.includes(s.layer)){const a=S(t.point,s.p1,s.p2),h=t.point.x-a.x,c=t.point.y-a.y,d=h*h+c*c;if(d>o){const a=Math.sqrt(d);let l=2,u=a;a<this.viaDiameter/2?(l*=4,u=Math.max(o,a)):u=Math.max(o,a-this.viaDiameter/2);const p=l*n*Math.exp(-6*u),f=h/a*p,m=c/a*p;r(i,t.index,f,m),r(e,s.p1Idx,-f/2,-m/2),r(e,s.p2Idx,-f/2,-m/2)}}for(const t of u)for(const s of f){if(t.layers.filter(t=>s.layers.includes(t)).length>0){const a=t.point.x-s.point.x,h=t.point.y-s.point.y,c=a*a+h*h;if(c>o){const d=Math.sqrt(c);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(o,d)):u=Math.max(o,d-this.viaDiameter);const p=l*n*Math.exp(-6*u),f=a/d*p,m=h/d*p;r(e,t.index,f,m),r(i,s.index,-f,-m)}}}}for(let e=0;e<s;e++){const s=t[e],i=[s.start,...s.mPoints,s.end],a=[];if(i.forEach((t,e)=>{t.z1!==t.z2&&a.push({point:t,layers:[t.z1,t.z2],index:e})}),!(a.length<2))for(let t=0;t<a.length;t++)for(let s=t+1;s<a.length;s++){const i=a[t],h=a[s],c=i.point.x-h.point.x,d=i.point.y-h.point.y,l=c*c+d*d;if(l>o){const t=Math.sqrt(l);let s=2,a=t;t<this.viaDiameter?(s*=4,a=Math.max(o,t)):a=Math.max(o,t-this.viaDiameter);const u=s*n*Math.exp(-6*a),p=c/t*u,f=d/t*u;r(e,i.index,p,f),r(e,h.index,-p,-f)}}}let c=!1;for(let n=0;n<s;n++)for(let s=0;s<t[n].mPoints.length;s++){const r=t[n].mPoints[s],h=a[n][s],d=r.z1!==r.z2;let l=h.fx,u=h.fy,p=r.x+l,f=r.y+u;if(d){const t=this.viaDiameter/2;let e=0,s=0;const n=this.viaDiameter/2+this.BOUNDARY_PADDING,o=this.bounds.minX+n,a=this.bounds.maxX-n,h=this.bounds.minY+n,c=this.bounds.maxY-n,d=o+t-r.x,m=r.x-(a-t),g=h+t-r.y,y=r.y-(c-t);d>0?e=i*(Math.exp(d/(2*this.obstacleMargin))-1):m>0&&(e=-.008*(Math.exp(m/(2*this.obstacleMargin))-1)),g>0?s=i*(Math.exp(g/(2*this.obstacleMargin))-1):y>0&&(s=-.008*(Math.exp(y/(2*this.obstacleMargin))-1)),l+=e,u+=s,p=r.x+l,f=r.y+u}else{const t=this.traceWidth/2+this.BOUNDARY_PADDING;p=Math.max(this.bounds.minX+t,Math.min(this.bounds.maxX-t,p)),f=Math.max(this.bounds.minY+t,Math.min(this.bounds.maxY-t,f))}if(Math.abs(l)<o&&Math.abs(u)<o)continue;e+=Math.sqrt(l*l+u*u),(Math.abs(r.x-p)>o||Math.abs(r.y-f)>o)&&(r.x=p,r.y=f,c=!0)}return{lastStepMoved:c,magForceApplied:e}}},Qe=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 ts=class extends Je{constructor(t){super(t),this.MAX_ITERATIONS=1e3}createInitialCandidateFromSeed(t){const e=new we({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,hyperParameters:{SHUFFLE_SEED:t}});if(e.solve(),e.failed||!e.solved)return null;const s=[];let n=0;for(const[t,i]of e.completedPaths.entries()){if(i.length<2){console.warn(`Skipping connection "${t}" due to insufficient points (${i.length}) in ViaPossibilitiesSolver2 path.`);continue}const e=i[0],o=i[i.length-1],a=i.slice(1,-1),r=[];let c=0,d=e.z;for(let t=0;t<a.length;t++){const e=a[t],s=t+1<a.length?a[t+1]:o,n=d,i=t+1<a.length&&e.x===s.x&&e.y===s.y&&e.z!==s.z?s.z:e.z;r.push({x:e.x,y:e.y,z1:n,z2:i}),n!==i?(c++,t++,d=i):d=e.z}n+=c;const l=this.SEGMENTS_PER_POLYLINE;let u=r.length+1;for(;u<l;){let s=-1,n=-1,i=null,a=null;const c=[{...e,z1:e.z,z2:e.z,connectionName:t},...r,{...o,z1:o.z,z2:o.z,connectionName:t}];for(let t=0;t<c.length-1;t++){const e=c[t],o=c[t+1];if(e.x===o.x&&e.y===o.y)continue;const r=h(e,o);r>s&&(s=r,n=t,i=e,a=o)}if(-1===n||!i||!a){console.warn(`Could not find longest segment for ${t} while trying to reach ${l} segments.`);break}const d=(i.x+a.x)/2,p=(i.y+a.y)/2,f=i.z2,m={x:d,y:p,z1:f,z2:f};r.splice(n,0,m),u++}s.push({connectionName:t,start:{...e,z1:e.z,z2:e.z},end:{...o,z1:o.z,z2:o.z},mPoints:r})}if(0===s.length)return this.failed=!0,this.error="No valid polylines generated from ViaPossibilitiesSolver2.",console.error(this.error),null;const i=this.computeMinGapBtwPolyLines(s),o=this.computeH({minGaps:i,forces:[]}),a={polyLines:s,g:0,h:o,f:0+o,viaCount:n,minGaps:i};return a.g=this.computeG(s,a),a.f=a.g+a.h,a}setupInitialPolyLines(){this.candidates=[];const t=Math.min(2e3,function(t){if(!Number.isInteger(t)||t<0)throw new RangeError("n must be a non-negative integer");let e=1;for(let s=2;s<=t;s++)e*=s;return e}(this.uniqueConnections)),e=new Set;for(let s=0;s<t;s++){const t=this.createInitialCandidateFromSeed(s);if(!t)continue;const n=Qe(t.polyLines);e.has(n)||(e.add(n),this.candidates.push(t))}this.candidates.sort((t,e)=>t.f-e.f)}},es=class extends xe{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 ve({nodeWithPortPoints:this.nodeWithPortPoints}):t.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING?new Ee({nodeWithPortPoints:this.nodeWithPortPoints}):t.MULTI_HEAD_POLYLINE_SOLVER?new ts({nodeWithPortPoints:this.nodeWithPortPoints,connMap:this.connMap,hyperParameters:t}):new ye({...this.constructorParams,hyperParameters:t})}onSolve(t){this.solvedRoutes=t.solver.solvedRoutes}};function ss(t,e,s){const n=[];let i=null;for(let o=0;o<t.length;o++){const a=t[o];i?i.z===a.z?i.points.push({x:a.x,y:a.y}):(n.push(i),i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:s}):i={points:[{x:a.x,y:a.y}],z:a.z,connectionName:e,color:s},o===t.length-1&&i&&n.push(i)}return n}var ns=class extends e{unsolvedNodePortPoints;routes;colorMap;defaultViaDiameter=.6;defaultTraceThickness=.15;failedSolvers;activeSubSolver=null;connMap;constructor({nodePortPoints:t,colorMap:e,connMap:s}){super(),this.unsolvedNodePortPoints=t,this.colorMap=e??{},this.connMap=s,this.routes=[],this.failedSolvers=[],this.MAX_ITERATIONS=1e6}_step(){if(this.updateCacheStats(),this.activeSubSolver)return this.activeSubSolver.step(),this.activeSubSolver.solved?(this.routes.push(...this.activeSubSolver.solvedRoutes),this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSolvers.push(this.activeSubSolver),this.activeSubSolver=null),void this.updateCacheStats();if(0===this.unsolvedNodePortPoints.length)return this.failedSolvers.length>0?(this.solved=!1,this.failed=!0,this.error=`Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0,5).map(t=>t.nodeWithPortPoints.capacityMeshNodeId)}. err0: ${this.failedSolvers[0].error}.`,void this.updateCacheStats()):(this.solved=!0,void this.updateCacheStats());const t=this.unsolvedNodePortPoints.pop();this.activeSubSolver=new es({nodeWithPortPoints:t,colorMap:this.colorMap,connMap:this.connMap}),this.updateCacheStats()}updateCacheStats(){const t=ne();this.stats.intraNodeCacheHits=t.cacheHits,this.stats.intraNodeCacheMisses=t.cacheMisses}visualize(){let e={lines:[],points:[],rects:[],circles:[]};for(const t of this.routes){const s=ss(t.route,t.connectionName,this.colorMap[t.connectionName]);for(const n of s)e.lines.push({points:n.points,label:n.connectionName,strokeColor:0===n.z?n.color:ct(n.color,.75),layer:`z${n.z}`,strokeWidth:t.traceThickness,strokeDash:0!==n.z?"10, 5":void 0});for(const s of t.vias)e.circles.push({center:s,layer:"z0,1",radius:t.viaDiameter/2,fill:this.colorMap[t.connectionName],label:`${t.connectionName} via`})}for(const t of this.failedSolvers){const s=t.nodeWithPortPoints,n=.1*s.width,i=.1*s.height;e.rects.push({center:{x:s.center.x-n/2,y:s.center.y-i/2},layer:"did_not_connect",width:n,height:i,fill:"red",label:`Failed: ${s.capacityMeshNodeId}`});const o={};for(const t of s.portPoints)o[t.connectionName]||(o[t.connectionName]=[]),o[t.connectionName].push({x:t.x,y:t.y,z:t.z});for(const[t,s]of Object.entries(o))for(let t=0;t<s.length-1;t++){const n=s[t],i=s[t+1];e.lines.push({points:[n,i],strokeColor:"red",strokeDash:"10, 5",layer:"did_not_connect"})}}return this.activeSubSolver&&(e=t(e,this.activeSubSolver.visualize())),e}},is=class{netMap;idToNetMap;constructor(t){this.netMap=t,this.idToNetMap={};for(const[e,s]of Object.entries(t))for(const t of s)this.idToNetMap[t]=e}addConnections(t){for(const e of t){const t=new Set;for(const s of e){const e=this.idToNetMap[s];e&&t.add(e)}let s;if(0===t.size)s=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[s]=[];else if(1===t.size)s=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{s=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(const e of t)if(e!==s){this.netMap[s].push(...this.netMap[e]),this.netMap[e]=this.netMap[s];for(const t of this.netMap[s])this.idToNetMap[t]=s}}for(const t of e)this.netMap[s].includes(t)||this.netMap[s].push(t),this.idToNetMap[t]=s}}getIdsConnectedToNet(t){return this.netMap[t]||[]}getNetConnectedToId(t){return this.idToNetMap[t]}areIdsConnected(t,e){if(t===e)return!0;const s=this.getNetConnectedToId(t);if(!s)return!1;const n=this.getNetConnectedToId(e);return!!n&&(s===n||n===t||n===t)}areAllIdsConnected(t){const e=this.getNetConnectedToId(t[0]);for(const s of t){const t=this.getNetConnectedToId(s);if(void 0===t)return!1;if(t!==e)return!1}return!0}},os=t=>{const e=new is({});for(const s of t.connections)for(const t of s.pointsToConnect)"pcb_port_id"in t&&t.pcb_port_id&&e.addConnections([[s.name,t.pcb_port_id]]);for(const s of t.obstacles)e.addConnections([s.connectedTo]);return e},as=class{point;left=null;right=null;constructor(t){this.point=t}},rs=class{root=null;constructor(t){t.length>0&&(this.root=this.buildTree(t,0))}buildTree(t,e){const s=e%2==0?"x":"y";t.sort((t,e)=>t[s]-e[s]);const n=Math.floor(t.length/2),i=new as(t[n]);return n>0&&(i.left=this.buildTree(t.slice(0,n),e+1)),n<t.length-1&&(i.right=this.buildTree(t.slice(n+1),e+1)),i}findNearestNeighbor(t){if(!this.root)throw new Error("Tree is empty");const e=this.root.point,s=this.distance(t,e);return this.nearestNeighborSearch(this.root,t,0,e,s),e}nearestNeighborSearch(t,e,s,n,i){if(!t)return n;const o=s%2?"x":"y",a=this.distance(e,t.point);a<i&&(n=t.point,i=a);const r=e[o]-t.point[o],h=r<=0?t.left:t.right,c=r<=0?t.right:t.left;return n=this.nearestNeighborSearch(h,e,s+1,n,i),i=this.distance(e,n),Math.abs(r)<i&&(n=this.nearestNeighborSearch(c,e,s+1,n,i)),n}findKNearestNeighbors(t,e){if(!this.root)return[];const s=[];return this.kNearestNeighborSearch(this.root,t,0,s,e),s.sort((t,e)=>t.distance-e.distance).slice(0,e).map(t=>t.point)}kNearestNeighborSearch(t,e,s,n,i){if(!t)return;const o=s%2?"x":"y",a=this.distance(e,t.point);n.push({point:t.point,distance:a});const r=e[o]-t.point[o],h=r<=0?t.left:t.right,c=r<=0?t.right:t.left;this.kNearestNeighborSearch(h,e,s+1,n,i);let d=1/0;n.length>=i&&(n.sort((t,e)=>t.distance-e.distance),d=n[i-1]?.distance||1/0),(Math.abs(r)<d||n.length<i)&&this.kNearestNeighborSearch(c,e,s+1,n,i)}distance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}},hs=class{parent=new Map;rank=new Map;constructor(t){for(const e of t){const t=this.pointToKey(e);this.parent.set(t,t),this.rank.set(t,0)}}pointToKey(t){return`${t.x},${t.y}`}find(t){const e=this.pointToKey(t);if(!this.parent.has(e))throw new Error(`Point ${e} not found in DisjointSet`);let s=e;for(;s!==this.parent.get(s);)s=this.parent.get(s);let n=e;for(;n!==s;){const t=this.parent.get(n);this.parent.set(n,s),n=t}return s}union(t,e){const s=this.find(t),n=this.find(e);if(s===n)return!1;const i=this.rank.get(s)||0,o=this.rank.get(n)||0;return i<o?this.parent.set(s,n):i>o?this.parent.set(n,s):(this.parent.set(n,s),this.rank.set(s,i+1)),!0}};var cs=class extends e{constructor(t,e={}){super(),this.ogSrj=t,this.colorMap=e,this.unprocessedConnections=[...t.connections],this.newConnections=[]}unprocessedConnections;newConnections;_step(){if(0===this.unprocessedConnections.length)return void(this.solved=!0);const t=this.unprocessedConnections.pop(),e=t.externallyConnectedPointIds??[],s=new Map;e.forEach((t,e)=>t.forEach(t=>s.set(t,e)));const n=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const n=s.get(t.pointId),i=s.get(e.pointId);return void 0!==n&&n===i};if(2===t.pointsToConnect.length){if(n(t.pointsToConnect[0],t.pointsToConnect[1]))return;return void this.newConnections.push(t)}const i=function(t){if(t.length<=1)return[];const e=new rs(t),s=[],n=Math.min(10,t.length-1);for(const i of t){const t=e.findKNearestNeighbors(i,n+1);for(const e of t){if(i.x===e.x&&i.y===e.y)continue;const t=Math.sqrt((i.x-e.x)**2+(i.y-e.y)**2);s.push({from:i,to:e,weight:t})}}s.sort((t,e)=>t.weight-e.weight);const i=new hs(t),o=[];for(const e of s)if(i.union(e.from,e.to)&&(o.push(e),o.length===t.length-1))break;return o}(t.pointsToConnect);let o=0;for(const e of i)n(e.from,e.to)||this.newConnections.push({pointsToConnect:[e.from,e.to],name:`${t.name}_mst${o++}`})}getNewSimpleRouteJson(){return{...this.ogSrj,connections:this.newConnections}}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Net To Point Pairs Visualization"};return this.unprocessedConnections.forEach(e=>{e.pointsToConnect.forEach(s=>{t.points.push({x:s.x,y:s.y,color:"red",label:e.name})});const s=e.pointsToConnect.length**2,n=de(0),i=new Set;for(let o=0;o<Math.max(s,2*e.pointsToConnect.length);o++){const s=Math.floor(n()*e.pointsToConnect.length),o=Math.floor(n()*e.pointsToConnect.length);i.has(`${s}-${o}`)||(i.add(`${s}-${o}`),t.lines.push({points:[e.pointsToConnect[s],e.pointsToConnect[o]],strokeColor:"rgba(255,0,0,0.25)"}))}}),this.newConnections.forEach(e=>{const s=this.colorMap?.[e.name]||"blue";e.pointsToConnect.forEach(n=>{t.points.push({x:n.x,y:n.y,color:s,label:e.name})});for(let n=0;n<e.pointsToConnect.length-1;n++)for(let i=n+1;i<e.pointsToConnect.length;i++)t.lines.push({points:[e.pointsToConnect[n],e.pointsToConnect[i]],strokeColor:s})}),t}},ds=(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}`},ls=(t,e)=>{const s=[];if(0===t.route.length)return s;let n=[],i=t.route[0].z;for(let o=0;o<t.route.length;o++){const a=t.route[o];if(a.z!==i){const o=ds(i,e);for(const e of n)s.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:o});if(t.vias.some(t=>Math.abs(t.x-a.x)<.001&&Math.abs(t.y-a.y)<.001)){const t=ds(i,e),n=ds(a.z,e);s.push({route_type:"via",x:a.x,y:a.y,from_layer:t,to_layer:n})}n=[a],i=a.z}else n.push(a)}const o=ds(i,e);for(const e of n)s.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:o});return s},us=class extends e{mergedHdRoute;remainingHdRoutes;start;end;colorMap;constructor(t){if(super(),this.remainingHdRoutes=[...t.hdRoutes],this.colorMap=t.colorMap??{},0===t.hdRoutes.length){this.start=t.start,this.end=t.end;const e=[{x:t.start.x,y:t.start.y,z:t.start.z}],s=[];return t.start.z!==t.end.z&&(e.push({x:t.start.x,y:t.start.y,z:t.end.z}),s.push({x:t.start.x,y:t.start.y})),e.push({x:t.end.x,y:t.end.y,z:t.end.z}),this.mergedHdRoute={connectionName:t.connectionName,route:e,vias:s,viaDiameter:t.defaultViaDiameter??.6,traceThickness:t.defaultTraceThickness??.15},void(this.solved=!0)}const{firstRoute:e}=this.getDisjointedRoute();Math.min(h(e.route[0],t.start),h(e.route[e.route.length-1],t.start))<Math.min(h(e.route[0],t.end),h(e.route[e.route.length-1],t.end))?(this.start=t.start,this.end=t.end):(this.start=t.end,this.end=t.start),this.mergedHdRoute={connectionName:t.connectionName,route:[{x:this.start.x,y:this.start.y,z:this.start.z}],vias:[],viaDiameter:e.viaDiameter,traceThickness:e.traceThickness}}getDisjointedRoute(){for(const t of this.remainingHdRoutes){if([t.route[0],t.route[t.route.length-1]].some(e=>!this.remainingHdRoutes.some(s=>{if(s===t)return!1;return[s.route[0],s.route[s.route.length-1]].some(t=>t.z===e.z&&h(e,t)<5e-6)})))return{firstRoute:t}}return{firstRoute:this.remainingHdRoutes[0]}}_step(){if(0===this.remainingHdRoutes.length)return this.mergedHdRoute.route.push({x:this.end.x,y:this.end.y,z:this.end.z}),void(this.solved=!0);const t=this.mergedHdRoute.route[this.mergedHdRoute.route.length-1];let e=0,s="first",n=1/0;for(let i=0;i<this.remainingHdRoutes.length;i++){const o=this.remainingHdRoutes[i],a=o.route[o.route.length-1],r=o.route[0],c=h(t,r),d=h(t,a);c<n&&t.z===r.z&&(n=c,e=i,s="first"),d<n&&t.z===a.z&&(n=d,e=i,s="last")}const i=this.remainingHdRoutes[e];this.remainingHdRoutes.splice(e,1),"first"===s?this.mergedHdRoute.route.push(...i.route):this.mergedHdRoute.route.push(...[...i.route].reverse()),this.mergedHdRoute.vias.push(...i.vias)}visualize(){const t={points:[],lines:[],circles:[],title:"Single High Density Route Stitch Solver"};if(t.points?.push({x:this.start.x,y:this.start.y,color:"green",label:"Start"},{x:this.end.x,y:this.end.y,color:"red",label:"End"}),this.mergedHdRoute&&this.mergedHdRoute.route.length>1){t.lines?.push({points:this.mergedHdRoute.route.map(t=>({x:t.x,y:t.y})),strokeColor:"green"});for(const e of this.mergedHdRoute.route)t.points?.push({x:e.x,y:e.y,color:"green"});for(const e of this.mergedHdRoute.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:this.mergedHdRoute.viaDiameter/2,fill:"green"})}for(const[e,s]of this.remainingHdRoutes.entries()){const n=this.colorMap[s.connectionName]??"gray";s.route.length>1&&t.lines?.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:n});for(let i=0;i<s.route.length;i++){const o=s.route[i];t.points?.push({x:o.x+(e%2-.5)/500+(i%8-4)/1e3,y:o.y+(e%2-.5)/500+(i%8-4)/1e3,color:n,label:`Route ${s.connectionName} ${o===s.route[0]?"First":o===s.route[s.route.length-1]?"Last":""}`})}for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n})}return t}},ps=class extends e{unsolvedRoutes;activeSolver=null;mergedHdRoutes=[];colorMap={};defaultTraceThickness;defaultViaDiameter;constructor(t){super(),this.colorMap=t.colorMap??{},t.hdRoutes.length>0?(this.defaultTraceThickness=t.hdRoutes[0].traceThickness,this.defaultViaDiameter=t.hdRoutes[0].viaDiameter):(this.defaultTraceThickness=.15,this.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:dt(e.pointsToConnect[0].layer,t.layerCount)},end:{...e.pointsToConnect[1],z:dt(e.pointsToConnect[1].layer,t.layerCount)}})),this.MAX_ITERATIONS=1e5}_step(){if(this.activeSolver)return this.activeSolver.step(),void(this.activeSolver.solved?(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 us({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=e.rects)}for(const[e,s]of this.mergedHdRoutes.entries()){const n=this.colorMap[s.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<s.route.length-1;e++){const i=s.route[e],o=s.route[e+1],a=0!==i.z?ct(n,.5):n;t.lines?.push({points:[{x:i.x,y:i.y},{x:o.x,y:o.y}],strokeColor:a,strokeWidth:s.traceThickness})}for(const e of s.route){const s=0!==e.z?ct(n,.5):n;t.points?.push({x:e.x,y:e.y,color:s})}for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n})}for(const e of this.unsolvedRoutes){const s=this.colorMap[e.connectionName]??"gray";t.points?.push({x:e.start.x,y:e.start.y,color:s,label:`${e.connectionName} Start (z=${e.start.z})`},{x:e.end.x,y:e.end.y,color:s,label:`${e.connectionName} End (z=${e.end.z})`}),t.lines?.push({points:[{x:e.start.x,y:e.start.y},{x:e.end.x,y:e.end.y}],strokeColor:s,strokeDash:"2 2"});for(const n of e.hdRoutes){n.route.length>1&&t.lines?.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:ct(s,.5),strokeDash:"10 5"});for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s})}}return t}},fs=t=>{const e=[],s=[],n=[],i=ht(t);if(t.connections)for(const e of t.connections)for(const t of e.pointsToConnect)n.push({x:t.x,y:t.y,color:i[e.name],layer:t.layer??("z"in t?ds(t.z,2):"top"),label:`${e.name} (${t.layer})`});if(t.traces)for(const n of t.traces)for(let t=0;t<n.route.length-1;t++){const i=n.route[t],o=n.route[t+1];"via"===i.route_type?s.push({center:{x:i.x,y:i.y},radius:.3,fill:"blue",stroke:"none",layer:"z0,1"}):"wire"===i.route_type&&"wire"===o.route_type&&o.layer===i.layer&&e.push({points:[{x:i.x,y:i.y},{x:o.x,y:o.y}],layer:`z${dt(i.layer,2)}`,strokeWidth:.15,strokeColor:ct({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(dt).join(",")}`})),circles:s,lines:e,points:n}};function ms(t){const{nodeId:e,nodeIdToSegmentIds:s,segmentIdToNodeIds:n,hops:i}=t;if(0===i)return[e];const o=new Set([e]),a=[{nodeId:e,remainingHops:i}];for(;a.length>0;){const{nodeId:t,remainingHops:e}=a.shift();if(0===e)continue;const i=s.get(t)||[];for(const t of i){const s=n.get(t)||[];for(const t of s)o.has(t)||(o.add(t),a.push({nodeId:t,remainingHops:e-1}))}}return Array.from(o)}var gs=t=>Array.from(t.entries()).map(([t,{x:e,y:s,z:n}])=>`${t}(${e?.toFixed(3)??""},${s?.toFixed(3)??""},${n??""})`).sort().join("&"),ys=(t,e,s,n)=>{const i=Math.min(t,e),o=Math.max(t,e),a=Math.min(s,n);return i<=Math.max(s,n)&&o>=a},xs=(t,e,s,n)=>{const o=[],a=new Map(t.originalPointMap);for(const[t,e]of s.entries()){const s=a.get(t);a.set(t,{x:e.x??s.x,y:e.y??s.y,z:e.z??s.z})}for(const s of t.allNodeIds){if(!e.get(s))continue;const r=t.segmentPairsInNode.get(s);for(const t of r){const e=a.get(t[0]),n=a.get(t[1]);e.z!==n.z&&o.push({type:"transition_via",segmentPoints:t,capacityMeshNodeId:s,probabilityOfFailure:0})}for(let t=0;t<r.length;t++)for(let e=t+1;e<r.length;e++){if(n?.areIdsConnected(r[t][0],r[t][1]))continue;const h=r[t],c=r[e],d=a.get(h[0]),l=a.get(h[1]),u=a.get(c[0]),p=a.get(c[1]);if(!ys(d.z,l.z,u.z,p.z))continue;const f=i(d,l,u,p),m=d.z===l.z&&u.z===p.z&&d.z===u.z;f&&(m?o.push({type:"same_layer_crossing",segmentPoints:[h,c],capacityMeshNodeId:s,crossingLine1:h,crossingLine2:c,probabilityOfFailure:0}):d.z===l.z&&u.z!==p.z?o.push({type:"single_transition_crossing",segmentPoints:[h,c],capacityMeshNodeId:s,sameLayerCrossingLine:h,transitionCrossingLine:c,probabilityOfFailure:0}):d.z!==l.z&&u.z===p.z?o.push({type:"single_transition_crossing",segmentPoints:[h,c],capacityMeshNodeId:s,sameLayerCrossingLine:c,transitionCrossingLine:h,probabilityOfFailure:0}):d.z!==l.z&&u.z!==p.z&&o.push({type:"double_transition_crossing",segmentPoints:[h,c],capacityMeshNodeId:s,crossingLine1:h,crossingLine2:c,probabilityOfFailure:0}))}}return o},Ms=(t,e,s)=>{if("change_layer"===e.type)for(const s of e.segmentPointIds){const n=t.get(s)||{};t.set(s,{...n,z:e.newZ})}else if("swap_position_on_segment"===e.type){const[n,i]=e.segmentPointIds,o=s(n),a=s(i),r=t.get(n)||{},h=t.get(i)||{};t.set(n,{...r,x:a.x,y:a.y}),t.set(i,{...h,x:o.x,y:o.y})}else if("combined"===e.type)for(const n of e.operations)Ms(t,n,s)},vs=(t,e)=>{const s=new Map,n=new Map,i=new Map,o=[];let a=0;for(const r of t)for(const t of r.assignedPoints){const h={segmentPointId:"SP"+a++,segmentId:r.nodePortSegmentId,capacityMeshNodeIds:e.get(r.nodePortSegmentId),connectionName:t.connectionName,x:t.point.x,y:t.point.y,z:t.point.z,directlyConnectedSegmentPointIds:[]};s.set(h.segmentPointId,h);for(const t of h.capacityMeshNodeIds)n.set(t,[...n.get(t)??[],h.segmentPointId]);i.set(r.nodePortSegmentId,[...i.get(r.nodePortSegmentId)??[],h.segmentPointId]),o.push(h)}return{segmentPointMap:s,nodeToSegmentPointMap:n,segmentToSegmentPointMap:i}},Ss=(t,e,s,n)=>{if(t?._containsTarget)return 0;return((.82*e+.41*s+.2*n)/2)**1.1/lt(t)},bs=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,lt(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=ms({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS}),s=ms({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS+1}),n=Array.from(new Set(s).difference(new Set(e)));t?.segmentPointMap||(t=vs(this.dedupedSegments,this.segmentIdToNodeIds));const i=new Map;for(const e of s)i.set(e,t.nodeToSegmentPointMap.get(e));const o=new Map;for(const e of s)for(const s of i.get(e)){const e=t.segmentPointMap.get(s);o.set(s,e)}const a=Array.from(o.values()),r=new Map;for(const t of a)r.set(t.segmentId,[...r.get(t.segmentId)??[],t.segmentPointId]);for(const[e,s]of i.entries())for(let e=0;e<s.length;e++){const n=t.segmentPointMap.get(s[e]);for(let i=e+1;i<s.length;i++){const e=t.segmentPointMap.get(s[i]);e.segmentPointId!==n.segmentPointId&&(e.segmentId!==n.segmentId&&e.connectionName===n.connectionName&&(e.directlyConnectedSegmentPointIds.includes(n.segmentPointId)||(n.directlyConnectedSegmentPointIds.push(e.segmentPointId),e.directlyConnectedSegmentPointIds.push(n.segmentPointId))))}}const h=new Map;for(const t of s)h.set(t,[]);for(const e of a)for(const s of e.capacityMeshNodeIds){const n=h.get(s);if(n)for(const i of e.directlyConnectedSegmentPointIds){const o=t.segmentPointMap.get(i);o.segmentPointId!==e.segmentPointId&&(o.capacityMeshNodeIds.some(t=>t===s)&&(n.some(([t,s])=>t===e.segmentPointId&&s===o.segmentPointId||t===o.segmentPointId&&s===e.segmentPointId)||n.push([e.segmentPointId,o.segmentPointId])))}}const c=new Set;for(const t of e)for(const e of this.nodeIdToSegmentIds.get(t)){this.segmentIdToNodeIds.get(e).every(t=>!this.nodeMap.get(t)._containsTarget)&&c.add(e)}const d=new Set;for(const t of a)t.capacityMeshNodeIds.some(t=>e.includes(t))&&d.add(t.segmentPointId);return{allNodeIds:s,mutableNodeIds:e,immutableNodeIds:n,mutableSegmentIds:c,segmentPairsInNode:h,segmentPointMap:o,segmentPointsInNode:i,segmentPointsInSegment:r,originalPointMap:o,mutableSegmentPointIds:d}}createInitialCandidate(){const t=new Map,e=xs(this.unravelSection,this.nodeMap,t),s=this.computeG({issues:e,originalCandidate:{},operationsPerformed:0,operation:{}});return{pointModifications:t,g:s,h:0,f:s,operationsPerformed:0,candidateHash:gs(t),issues:xs(this.unravelSection,this.nodeMap,t)}}get nextCandidate(){return this.candidates[0]??null}getPointInCandidate(t,e){const s=this.unravelSection.segmentPointMap.get(e),n=t.pointModifications.get(e);return{x:n?.x??s.x,y:n?.y??s.y,z:n?.z??s.z,segmentId:s.segmentId}}getOperationsForIssue(t,e){const s=[];if("transition_via"===e.type){const[n,i]=e.segmentPoints,o=this.getPointInCandidate(t,n),a=this.getPointInCandidate(t,i),r=this.dedupedSegmentMap.get(o.segmentId).availableZ,h=this.dedupedSegmentMap.get(a.segmentId).availableZ;this.unravelSection.mutableSegmentPointIds.has(n)&&r.includes(a.z)&&s.push({type:"change_layer",newZ:a.z,segmentPointIds:[n]}),this.unravelSection.mutableSegmentPointIds.has(i)&&h.includes(o.z)&&s.push({type:"change_layer",newZ:o.z,segmentPointIds:[i]})}if("same_layer_crossing"===e.type){const[t,n]=e.crossingLine1,[i,o]=e.crossingLine2,a=[],r=this.unravelSection.segmentPointMap.get(t),h=this.unravelSection.segmentPointMap.get(n),c=this.unravelSection.segmentPointMap.get(i),d=this.unravelSection.segmentPointMap.get(o),l=this.unravelSection.mutableSegmentPointIds.has(t),u=this.unravelSection.mutableSegmentPointIds.has(n),p=this.unravelSection.mutableSegmentPointIds.has(i),f=this.unravelSection.mutableSegmentPointIds.has(o);l&&p&&r.segmentId===c.segmentId&&a.push([t,i]),l&&f&&r.segmentId===d.segmentId&&a.push([t,o]),u&&p&&h.segmentId===c.segmentId&&a.push([n,i]),u&&f&&h.segmentId===d.segmentId&&a.push([n,o]);for(const[t,e]of a)s.push({type:"swap_position_on_segment",segmentPointIds:[t,e]});const m=this.dedupedSegmentMap.get(r.segmentId),g=this.dedupedSegmentMap.get(h.segmentId),y=this.dedupedSegmentMap.get(c.segmentId),x=this.dedupedSegmentMap.get(d.segmentId),M=(t,e)=>t.every(t=>t.availableZ.includes(e));if(l&&u){const e=0===r.z?1:0;M([m,g],e)&&s.push({type:"change_layer",newZ:e,segmentPointIds:[t,n]})}if(p&&f){const t=0===c.z?1:0;M([y,x],t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[i,o]})}if(l){const e=0===r.z?1:0;m.availableZ.includes(e)&&s.push({type:"change_layer",newZ:e,segmentPointIds:[t]})}if(u){const t=0===h.z?1:0;g.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[n]})}if(p){const t=0===c.z?1:0;y.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[i]})}if(f){const t=0===d.z?1:0;x.availableZ.includes(t)&&s.push({type:"change_layer",newZ:t,segmentPointIds:[o]})}}return s}computeG(t){const{issues:e,originalCandidate:s,operationsPerformed:n,operation:i}=t,o=new Map;for(const t of e){o.has(t.capacityMeshNodeId)||o.set(t.capacityMeshNodeId,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0});const e=o.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"===t.type||"single_transition_crossing"===t.type?e.numEntryExitLayerChanges++:t.type}let a=0;for(const[t,{numEntryExitLayerChanges:e,numSameLayerCrossings:s,numTransitionCrossings:n}]of o){const i=this.nodeMap.get(t),o=Math.min(Ss(i,s,e,n),.999999);a+=Math.log(1-o)}var r;return(r=a)<-Math.LN2?Math.log(1-Math.exp(r)):Math.log(-Math.expm1(r))}getUnexploredNeighborByApplyingOperation(t,e){const s=new Map(t.pointModifications);Ms(s,e,e=>this.getPointInCandidate(t,e));const n=gs(s);if(this.queuedOrExploredCandidatePointModificationHashes.has(n))return null;const i=xs(this.unravelSection,this.nodeMap,s),o=t.operationsPerformed+1,a=this.computeG({issues:i,originalCandidate:t,operationsPerformed:o,operation:e});return{issues:i,g:a,h:0,f:a,pointModifications:s,candidateHash:n,operationsPerformed:o}}getNeighborOperationsForCandidate(t){return t.issues.flatMap(e=>this.getOperationsForIssue(t,e))}getNeighbors(t){const e=[],s=this.getNeighborOperationsForCandidate(t);for(const n of s){const s=this.getUnexploredNeighborByApplyingOperation(t,n);s&&e.push(s)}return e}_step(){const t=this.candidates.shift();this.iterationsSinceImprovement++,this.iterationsSinceImprovement>this.hyperParameters.MAX_ITERATIONS_WITHOUT_IMPROVEMENT?this.solved=!0:t?(this.lastProcessedCandidate=t,t.f<(this.bestCandidate?.f??1/0)&&(this.bestCandidate=t,this.iterationsSinceImprovement=0),this.getNeighbors(t).forEach(t=>{this.queuedOrExploredCandidatePointModificationHashes.has(t.candidateHash)||(this.queuedOrExploredCandidatePointModificationHashes.add(t.candidateHash),this.candidates.push(t))}),this.candidates.sort((t,e)=>t.f-e.f),this.candidates.length=Math.min(this.candidates.length,this.MAX_CANDIDATES)):this.solved=!0}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Section Solver"};let e=null;if(e=null!==this.selectedCandidateIndex?"best"===this.selectedCandidateIndex?this.bestCandidate:"original"===this.selectedCandidateIndex?this.originalCandidate:this.candidates[this.selectedCandidateIndex]:this.solved?this.bestCandidate:this.lastProcessedCandidate||this.candidates[0],!e)return t;const s=new Map;for(const[t,n]of this.unravelSection.segmentPointMap){const i={...n},o=e.pointModifications.get(t);o&&(void 0!==o.x&&(i.x=o.x),void 0!==o.y&&(i.y=o.y),void 0!==o.z&&(i.z=o.z)),s.set(t,i)}for(const[e,n]of s)t.points.push({x:n.x,y:n.y,label:`${e}\nSegment: ${n.segmentId} ${this.unravelSection.mutableSegmentIds.has(n.segmentId)?"MUTABLE":"IMMUTABLE"}\nLayer: ${n.z}`,color:this.colorMap[n.connectionName]||"#000"});const n=new Map;for(const t of this.unravelSection.allNodeIds)n.set(t,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0,estPf:0});for(const t of e.issues){const e=n.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"!==t.type&&"single_transition_crossing"!==t.type||e.numEntryExitLayerChanges++}for(const[t,e]of n.entries()){const s=this.nodeMap.get(t);e.estPf=Ss(s,e.numSameLayerCrossings,e.numEntryExitLayerChanges,e.numTransitionCrossings)}for(const e of this.unravelSection.allNodeIds){const s=this.nodeMap.get(e),i=this.unravelSection.mutableNodeIds.includes(e),o=n.get(e),a=[`${e} (${i?"MUT":"IMM"})`,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Pf: ${o.estPf.toFixed(3)}`,`TC: ${o.numTransitionCrossings}`,`SLC: ${o.numSameLayerCrossings}`,`EELC: ${o.numEntryExitLayerChanges}`].join("\n");t.rects.push({center:s.center,label:a,color:i?"green":"red",width:s.width/8,height:s.height/8})}for(const[e,n]of this.unravelSection.segmentPointsInSegment){if(n.length<=1)continue;const i=n.map(t=>s.get(t));for(let s=0;s<i.length-1;s++)t.lines.push({points:[{x:i[s].x,y:i[s].y},{x:i[s+1].x,y:i[s+1].y}],strokeColor:this.colorMap[e]||"#000"})}for(const[e,n]of s)for(const i of n.directlyConnectedSegmentPointIds)if(e<i){const e=s.get(i);if(!e)continue;const o=n.z===e.z,a=n.z;let r;r=o?0===a?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:n.x,y:n.y},{x:e.x,y:e.y}],strokeDash:r,strokeColor:this.colorMap[n.connectionName]||"#000"})}for(const n of e.issues){const e=this.nodeMap.get(n.capacityMeshNodeId);if("transition_via"===n.type)for(const i of n.segmentPoints){const n=s.get(i);t.circles.push({center:{x:n.x,y:n.y},radius:e.width/16,stroke:"#ff0000",fill:"rgba(255, 0, 0, 0.2)",label:`Via Issue\n${i}\nLayer: ${n.z}`})}else if("same_layer_crossing"===n.type)for(const[i,o]of[n.crossingLine1,n.crossingLine2]){const n=s.get(i),a=s.get(o);t.lines.push({points:[{x:n.x,y:n.y},{x:a.x,y:a.y}],strokeColor:"rgba(255,0,0,0.2)",strokeWidth:e.width/32})}}for(const[n,i]of e.pointModifications){const e=s.get(n),i=this.unravelSection.segmentPointMap.get(n);t.circles.push({center:{x:e.x,y:e.y},radius:.05,stroke:"#0000ff",fill:"rgba(0, 0, 255, 0.2)",label:`${n}\nOriginal: (${i.x.toFixed(2)}, ${i.y.toFixed(2)}, ${i.z})\nNew: (${e.x.toFixed(2)}, ${e.y.toFixed(2)}, ${e.z})`})}return t}};import Ns from"object-hash";function Is(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:Ps,sin:Cs,PI:_s}=Math,{tan:Ts}=Math,Es=t=>(Math.round(20*t)/20).toFixed(2),As=t=>(Math.round(1e3*t)/1e3).toFixed(3);ie();var ws=class extends bs{cacheHit=!1;cacheProvider;hasAttemptedToUseCache=!1;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?se():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}computeCacheKeyAndTransform(){const t=this.nodeMap.get(this.rootNodeId),e=function(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}(-t.center.x,-t.center.y),s=new Map,n=new Map,i=new Map,o=new Map,a=new Map,r=new Map;let h=0,c=0,d=0;const l=[...this.unravelSection.allNodeIds].sort((t,e)=>{const s=this.nodeMap.get(t),n=this.nodeMap.get(e);return s.center.x!==n.center.x?s.center.x-n.center.x:s.center.y-n.center.y});for(const t of l){const e="node_"+h++;s.set(t,e),n.set(e,t)}const u=[...Array.from(this.unravelSection.segmentPointMap.entries()).sort(([,t],[,e])=>t.x!==e.x?t.x-e.x:t.y-e.y).map(([t])=>t)].sort();for(const t of u){const e="sp_"+d++;a.set(t,e),r.set(e,t);const s=this.unravelSection.segmentPointMap.get(t).segmentId;if(!i.has(s)){const t="seg_"+c++;i.set(s,t),o.set(t,s)}}const p={};for(const[t,n]of s.entries()){const s=this.nodeMap.get(t),i=Is(e,s.center);p[n]={width:s.width,height:s.height,availableZ:s.availableZ,center:{x:Es(i.x),y:Es(i.y)}}}const f={};for(const[t,s]of a.entries()){const n=this.unravelSection.segmentPointMap.get(t),i=Is(e,{x:n.x,y:n.y});f[s]={x:Es(i.x),y:Es(i.y),z:n.z}}const m={hyperParameters:this.hyperParameters,normalizedNodes:p,normalizedSegmentPoints:f,mutableHops:this.MUTABLE_HOPS},g=`unravelsec:${Ns(m)}`,y={realToCacheTransform:e,nodeIdMap:s,segmentIdMap:i,segmentPointIdMap:a,reverseNodeIdMap:n,reverseSegmentIdMap:o,reverseSegmentPointIdMap:r};return this.cacheKey=g,this.cacheToSolveSpaceTransform=y,{cacheKey:g,cacheToSolveSpaceTransform:y}}applyCachedSolution(t){if(!1===t.success)return void(this.failed=!0);if(!this.cacheToSolveSpaceTransform)return void console.error("Cache transform not available to apply cached solution.");const{reverseSegmentPointIdMap:e,reverseNodeIdMap:s}=this.cacheToSolveSpaceTransform,n=new Map;for(const[s,i]of t.bestCandidatePointModificationsDelta){const t=e.get(s);if(!t){console.warn(`Could not find original ID for normalized SP ID: ${s} when applying cache.`);continue}const o=this.unravelSection.segmentPointMap.get(t);if(!o){console.warn(`Could not find original segment point for ID: ${t} when applying cache.`);continue}const a={};if(void 0!==i.dx){const t=parseFloat(i.dx);Number.isNaN(t)?console.warn(`Failed to parse cached dx coordinate: ${i.dx}`):a.x=o.x+t}if(void 0!==i.dy){const t=parseFloat(i.dy);Number.isNaN(t)?console.warn(`Failed to parse cached dy coordinate: ${i.dy}`):a.y=o.y+t}void 0!==i.dz&&(a.z=o.z+i.dz),Object.keys(a).length>0&&n.set(t,a)}const i=xs(this.unravelSection,this.nodeMap,n);this.bestCandidate={pointModifications:n,issues:i,f:t.bestCandidateF,g:t.bestCandidateF,h:0,operationsPerformed:-1,candidateHash:gs(n)},this.cacheHit=!0,this.solved=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(this.failed)return void this.cacheProvider?.setCachedSolutionSync(this.cacheKey,{success:!1});if(!this.bestCandidate)return;const{segmentPointIdMap:t}=this.cacheToSolveSpaceTransform,e=[];for(const[s,n]of this.bestCandidate.pointModifications.entries()){const i=t.get(s);if(!i){console.warn(`Could not find normalized ID for original SP ID: ${s} when saving to cache.`);continue}const o=this.unravelSection.segmentPointMap.get(s);if(!o){console.warn(`Could not find original segment point for ID: ${s} when saving cache.`);continue}const a={};let r=!1;if(void 0!==n.x){const t=n.x-o.x,e=As(t);0!==parseFloat(e)&&(a.dx=e,r=!0)}if(void 0!==n.y){const t=n.y-o.y,e=As(t);0!==parseFloat(e)&&(a.dy=e,r=!0)}if(void 0!==n.z){const t=n.z-o.z;0!==t&&(a.dz=t,r=!0)}r&&e.push([i,a])}const s={success:!0,bestCandidatePointModificationsDelta:e,bestCandidateF:this.bestCandidate.f};this.cacheProvider?.setCachedSolutionSync(this.cacheKey,s)}},zs=class extends e{nodeMap;dedupedSegmentMap;dedupedSegments;nodeIdToSegmentIds;segmentIdToNodeIds;nodeToSegmentPointMap;segmentToSegmentPointMap;colorMap;tunedNodeCapacityMap;MAX_NODE_ATTEMPTS=2;MUTABLE_HOPS=1;ACCEPTABLE_PF=.05;MAX_ITERATIONS_WITHOUT_IMPROVEMENT=200;nodePfMap;attemptsToFixNode;activeSubSolver=null;segmentPointMap;cacheProvider=null;constructor({assignedSegments:t,colorMap:e,nodes:s,cacheProvider:n}){super(),this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.cacheHits=0,this.stats.cacheMisses=0,this.cacheProvider=n??null,this.MAX_ITERATIONS=1e6,this.dedupedSegments=(t=>{const e=[],s=new Map;let n=-1;for(const i of t){const t=`${i.start.x}-${i.start.y}-${i.end.x}-${i.end.y}-${i.availableZ.join(",")}`,o=s.get(t);o?i.nodePortSegmentId=o.nodePortSegmentId:(n++,i.nodePortSegmentId=`SEG${n}`,s.set(t,i),e.push(i))}return e})(t),this.dedupedSegmentMap=new Map;for(const t of this.dedupedSegments)this.dedupedSegmentMap.set(t.nodePortSegmentId,t);this.nodeMap=new Map;for(const t of s)this.nodeMap.set(t.capacityMeshNodeId,t);this.nodeIdToSegmentIds=new Map,this.segmentIdToNodeIds=new Map,this.attemptsToFixNode=new Map;for(const e of t)this.segmentIdToNodeIds.set(e.nodePortSegmentId,[...this.segmentIdToNodeIds.get(e.nodePortSegmentId)??[],e.capacityMeshNodeId]),this.nodeIdToSegmentIds.set(e.capacityMeshNodeId,[...this.nodeIdToSegmentIds.get(e.capacityMeshNodeId)??[],e.nodePortSegmentId]);this.colorMap=e??{},this.tunedNodeCapacityMap=new Map;for(const[t,e]of this.nodeMap)this.tunedNodeCapacityMap.set(t,lt(e));const{segmentPointMap:i,nodeToSegmentPointMap:o,segmentToSegmentPointMap:a}=vs(this.dedupedSegments,this.segmentIdToNodeIds);this.segmentPointMap=i,this.nodeToSegmentPointMap=o,this.segmentToSegmentPointMap=a,this.nodePfMap=this.computeInitialPfMap()}computeInitialPfMap(){const t=new Map;for(const[e,s]of this.nodeMap.entries())t.set(e,this.computeNodePf(s));return t}computeNodePf(t){const{numSameLayerCrossings:e,numEntryExitLayerChanges:s,numTransitionCrossings:n}=(t=>{let e=0,s=0,n=0;const o=new Map;for(const e of t)o.has(e.connectionName)||o.set(e.connectionName,[]),o.get(e.connectionName).push(e);const a=[],r=[];for(const[t,e]of o.entries()){if(e.length<2)continue;const n=e[0];for(let i=1;i<e.length;i++){const o=e[i],h={connectionName:t,z:n.z,points:[n,o]};n.z!==o.z?(s++,r.push({connectionName:t,points:[n,o]})):a.push(h)}}for(let t=0;t<a.length;t++)for(let s=t+1;s<a.length;s++){const n=a[t],o=a[s];n.z===o.z&&i(n.points[0],n.points[1],o.points[0],o.points[1])&&e++}for(let t=0;t<r.length;t++)for(let e=t+1;e<r.length;e++){const s=r[t],o=r[e];i(s.points[0],s.points[1],o.points[0],o.points[1])&&n++}for(let t=0;t<r.length;t++)for(let e=0;e<a.length;e++){const s=r[t],o=a[e];i(s.points[0],s.points[1],o.points[0],o.points[1])&&n++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:s,numTransitionCrossings:n}})((this.nodeToSegmentPointMap.get(t.capacityMeshNodeId)??[]).map(t=>this.segmentPointMap.get(t)));return Ss(t,e,s,n)}_step(){if(this.iterations>=this.MAX_ITERATIONS-1)return void(this.solved=!0);if(!this.activeSubSolver){let t=null,e=0;for(const[s,n]of this.nodePfMap.entries()){n*(1-(this.attemptsToFixNode.get(s)??0)/this.MAX_NODE_ATTEMPTS)>e&&(e=n,t=s)}if(!t||e<this.ACCEPTABLE_PF)return void(this.solved=!0);this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.activeSubSolver=new ws({dedupedSegments:this.dedupedSegments,dedupedSegmentMap:this.dedupedSegmentMap,nodeMap:this.nodeMap,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,colorMap:this.colorMap,rootNodeId:t,MUTABLE_HOPS:this.MUTABLE_HOPS,segmentPointMap:this.segmentPointMap,nodeToSegmentPointMap:this.nodeToSegmentPointMap,segmentToSegmentPointMap:this.segmentToSegmentPointMap,cacheProvider:this.cacheProvider})}this.activeSubSolver.step();const{bestCandidate:t,originalCandidate:e,lastProcessedCandidate:s}=this.activeSubSolver;if(this.activeSubSolver.failed)return this.stats.failedOptimizations+=1,void(this.activeSubSolver=null);if(this.activeSubSolver.solved){this.activeSubSolver.cacheHit?this.stats.cacheHits+=1:this.stats.cacheMisses+=1;if(t&&t.g<e.g){this.stats.successfulOptimizations+=1;for(const[e,s]of t.pointModifications.entries()){const t=this.segmentPointMap.get(e);t.x=s.x??t.x,t.y=s.y??t.y,t.z=s.z??t.z}for(const t of this.activeSubSolver.unravelSection.allNodeIds)this.nodePfMap.set(t,this.computeNodePf(this.nodeMap.get(t)))}else this.stats.failedOptimizations+=1;this.activeSubSolver=null}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Multi Section Solver"};for(const[e,s]of this.nodeMap.entries()){const n=this.nodePfMap.get(e)||0,i=Math.min(n,1),o=`rgb(${Math.floor(255*i)}, ${Math.floor(255*(1-i))}, 0)`;0===(this.attemptsToFixNode.get(e)??0)&&0===i||t.rects.push({center:s.center,label:[e,`${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Pf: ${n.toFixed(3)}`].join("\n"),color:o,width:s.width/8,height:s.height/8})}for(const e of this.segmentPointMap.values()){const s=this.dedupedSegmentMap.get(e.segmentId);t.points.push({x:e.x,y:e.y,label:[e.segmentPointId,e.segmentId,`z: ${e.z}`,`segment.availableZ: ${s?.availableZ.join(",")}`].join("\n"),color:this.colorMap[e.connectionName]||"#000"})}const e=new Map;for(const t of this.segmentPointMap.values())e.has(t.segmentId)||e.set(t.segmentId,[]),e.get(t.segmentId).push(t);for(const[s,n]of e.entries()){if(n.length<2)continue;const e=[...n].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y);for(let n=0;n<e.length-1;n++)t.lines.push({points:[{x:e[n].x,y:e[n].y},{x:e[n+1].x,y:e[n+1].y}],strokeColor:this.colorMap[s]||"#000"})}const s=new Set,n=Array.from(this.segmentPointMap.values());for(let e=0;e<n.length;e++){const i=n[e];for(let o=e+1;o<n.length;o++){const e=n[o];if(i.connectionName!==e.connectionName||i.segmentId===e.segmentId)continue;if(i.capacityMeshNodeIds.some(t=>e.capacityMeshNodeIds.includes(t))){const n=`${i.segmentPointId}-${e.segmentPointId}`;if(s.has(n))continue;s.add(n);const o=i.z===e.z,a=i.z;let r;r=o?0===a?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:i.x,y:i.y},{x:e.x,y:e.y}],strokeDash:r,strokeColor:this.colorMap[i.connectionName]||"#666"})}}}return t}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.dedupedSegments){const s=e.nodePortSegmentId;for(const e of this.segmentIdToNodeIds.get(s)){const s=this.nodeMap.get(e);t.has(e)||t.set(e,{capacityMeshNodeId:e,portPoints:[],center:s.center,width:s.width,height:s.height})}}for(const e of this.segmentPointMap.values())for(const s of e.capacityMeshNodeIds){const n=t.get(s);n&&n.portPoints.push({x:e.x,y:e.y,z:e.z,connectionName:e.connectionName})}return Array.from(t.values())}},Rs=(t,e={})=>{const s=Math.min(...t.availableZ);return{center:!e.rectMargin||e.zOffset?{x:t.center.x+s*t.width*(e.zOffset??.05),y:t.center.y-s*t.width*(e.zOffset??.05)}:t.center,width:e.rectMargin?t.width-2*e.rectMargin:Math.max(t.width-.5,.8*t.width),height:e.rectMargin?t.height-2*e.rectMargin:Math.max(t.height-.5,.8*t.height),fill:t._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[t.availableZ.join(",")]??"rgba(0,200,200,0.1)",layer:`z${t.availableZ.join(",")}`,label:[t.capacityMeshNodeId,`availableZ: ${t.availableZ.join(",")}`,""+(t._containsTarget?"containsTarget":""),""+(t._containsObstacle?"containsObstacle":"")].filter(Boolean).join("\n")}},Os=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:s,colorMap:n,MAX_ITERATIONS:i=1e6,hyperParameters:o={}}){super(),this.MAX_ITERATIONS=i,this.simpleRouteJson=t,this.nodes=e,this.edges=s,this.colorMap=n??{};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=Ut(this.edges),this.maxDepthOfNodes=Math.max(...this.nodes.map(t=>t._depth??0)),this.debug_lastNodeCostMap=new Map}getTotalCapacity(t){const e=t._depth??0;return(this.maxDepthOfNodes-e+1)**2}getConnectionsWithNodes(){const t=[],e=this.nodes.filter(t=>t._containsTarget),s=new Map;for(const n of this.simpleRouteJson.connections){const i=[];for(const t of n.pointsToConnect){let s=this.nodes[0],n=Number.MAX_VALUE;for(const i of e){const e=Math.sqrt((i.center.x-t.x)**2+(i.center.y-t.y)**2);e<n&&(n=e,s=i)}i.push(s)}if(i.length<2)throw new Error(`Not enough nodes for connection "${n.name}", only ${i.length} found`);s.set(n.name,i.map(t=>t.capacityMeshNodeId)),t.push({connection:n,nodes:i,pathFound:!1,straightLineDistance:h(i[0].center,i[i.length-1].center)})}return t.sort((t,e)=>t.straightLineDistance-e.straightLineDistance),{connectionsWithNodes:t,connectionNameToGoalNodeIds:s}}currentConnectionIndex=0;candidates;visitedNodes;computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)}getBacktrackedPath(t){const e=[];let s=t;for(;s;)e.push(s.node),s=s.prevCandidate;return e}getNeighboringNodes(t){return this.nodeEdgeMap.get(t.capacityMeshNodeId).flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t))}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const s=e.path;s&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:s.map(t=>t.capacityMeshNodeId)})}return t}doesNodeHaveCapacityForTrace(t,e){const s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=this.getTotalCapacity(t);if(1===t.availableZ.length&&!t._containsTarget&&s>0)return!1;let i=0;return t.availableZ.length>1&&1===e.availableZ.length&&(i+=.5),s+i<n}canTravelThroughObstacle(t,e){const s=this.connectionNameToGoalNodeIds.get(e);return s?.includes(t.capacityMeshNodeId)??!1}getDistanceBetweenNodes(t,e){return Math.sqrt((t.center.x-e.center.x)**2+(t.center.y-e.center.y)**2)}reduceCapacityAlongPath(t){for(const e of t.path??[])this.usedNodeCapacityMap.set(e.capacityMeshNodeId,this.usedNodeCapacityMap.get(e.capacityMeshNodeId)+1)}isConnectedToEndGoal(t,e){return this.nodeEdgeMap.get(t.capacityMeshNodeId).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}_step(){const t=this.connectionsWithNodes[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const[e,s]=t.nodes;this.candidates||(this.candidates=[{prevCandidate:null,node:e,f:0,g:0,h:0}],this.debug_lastNodeCostMap=new Map,this.visitedNodes=new Set([e.capacityMeshNodeId]),this.activeCandidateStraightLineDistance=h(e.center,s.center)),this.candidates.sort((t,e)=>t.f-e.f);const n=this.candidates.shift();if(this.candidates.length>this.MAX_CANDIDATES_IN_MEMORY&&this.candidates.splice(this.MAX_CANDIDATES_IN_MEMORY,this.candidates.length-this.MAX_CANDIDATES_IN_MEMORY),!n)return console.error(`Ran out of candidates on connection ${t.connection.name}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,void(this.failed=!0);if(this.isConnectedToEndGoal(n.node,s))return t.path=this.getBacktrackedPath({prevCandidate:n,node:s,f:0,g:0,h:0}),this.reduceCapacityAlongPath(t),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);const i=this.getNeighboringNodes(n.node);for(const t of i){if(this.visitedNodes?.has(t.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(t,n.node))continue;const e=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;if(t._containsObstacle&&!this.canTravelThroughObstacle(t,e))continue;const i=this.computeG(n,t,s),o=this.computeH(n,t,s),a=i+o*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:a,g:i,h:o});const r={prevCandidate:n,node:t,f:a,g:i,h:o};this.candidates.push(r)}this.visitedNodes.add(n.node.capacityMeshNodeId)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(this.connectionsWithNodes)for(let e=0;e<this.connectionsWithNodes.length;e++){const s=this.connectionsWithNodes[e];if(s.path&&s.path.length>0){const n=s.path.map(({center:{x:t,y:s},width:n,availableZ:i})=>({x:t+.005*n*(e%10+e%19),y:s+.005*n*(e%10+e%19),availableZ:i}));t.lines.push({points:n,strokeColor:this.colorMap[s.connection.name]});for(let e=0;e<n.length;e++){const i=n[e];t.points.push({x:i.x,y:i.y,label:[`conn: ${s.connection.name}`,`node: ${s.path[e].capacityMeshNodeId}`,`z: ${i.availableZ.join(",")}`].join("\n")})}}}for(const e of this.nodes){const s=this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,n=this.getTotalCapacity(e),i=this.debug_lastNodeCostMap.get(e.capacityMeshNodeId);t.rects.push({...Rs(e,{rectMargin:.025,zOffset:.01}),label:[`${e.capacityMeshNodeId}`,`${s}/${n}`,`${e.width.toFixed(2)}x${e.height.toFixed(2)}`,`g: ${void 0!==i?.g?i.g.toFixed(2):"?"}`,`h: ${void 0!==i?.h?i.h.toFixed(2):"?"}`,`f: ${void 0!==i?.f?i.f.toFixed(2):"?"}`,`z: ${e.availableZ.join(", ")}`].join("\n"),stroke:s>n+.5?"red":void 0})}if(this.connectionsWithNodes)for(const e of this.connectionsWithNodes)if(e.connection?.pointsToConnect)for(const s of e.connection.pointsToConnect)t.points.push({x:s.x,y:s.y,label:[`pointsToConnect ${e.connection.name}`].join("\n")});let e=this.connectionsWithNodes[this.currentConnectionIndex];if(!this.candidates&&this.currentConnectionIndex>0&&!this.connectionsWithNodes[this.currentConnectionIndex-1].path&&(e=this.connectionsWithNodes[this.currentConnectionIndex-1]),e){const[s,n]=e.connection.pointsToConnect;t.lines.push({points:[{x:s.x,y:s.y},{x:n.x,y:n.y}],strokeColor:"red",strokeDash:"10 5"})}if(this.candidates){const e=this.candidates.slice(0,5),s=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;e.forEach((e,n)=>{const i=.5*(1-n/5),o=this.getBacktrackedPath(e);t.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:ct(this.colorMap[s]??"red",1-i)})})}return t}},Ls=class extends Os{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 lt(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){const e=t.width+t.height,s=.05,n=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0);if(n>2)return s;return(e-s)*Math.max(1,(2-n)/(e-s))+s}getDistanceBetweenNodes(t,e){const s=t.center.x-e.center.x,n=t.center.y-e.center.y;return Math.sqrt(s**2+n**2)}computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)+this.getNodeCapacityPenalty(e)}},Ds=class extends Ls{doesNodeHaveCapacityForTrace(t,e){return!0}getNodeCapacityPenalty(t){const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let s=1;return 1===t.availableZ.length&&(s=10),(.05+2*Math.abs(e))*s}};function $s(t,e,s){const n=e.x-t.x,i=e.y-t.y;if(Math.abs(n)<1e-9&&Math.abs(i)<1e-9)return t;const o=s.width/2,a=s.height/2,r=s.center.x-o,h=s.center.x+o,c=s.center.y-a,d=s.center.y+a;let l=0,u=1/0;if(Math.abs(n)>1e-9){const e=(r-t.x)/n,s=(h-t.x)/n;l=Math.max(l,Math.min(e,s)),u=Math.min(u,Math.max(e,s))}else if(t.x<r||t.x>h)return t;if(Math.abs(i)>1e-9){const e=(c-t.y)/i,s=(d-t.y)/i;l=Math.max(l,Math.min(e,s)),u=Math.min(u,Math.max(e,s))}else if(t.y<c||t.y>d)return t;if(u<l||l===1/0||l<-1e9)return t;return{x:t.x+n*l,y:t.y+i*l}}function Ys(t,e){const s=t.center,n=e.center,i=$s(s,n,t),o=$s(n,s,e),a=n.x-s.x,r=n.y-s.y,h=Math.sqrt(a*a+r*r);let c=i,d=o;if(h>1e-9){const s={x:a/h,y:r/h},n=.3*t.width,l=.3*e.width;n+l<Math.sqrt((o.x-i.x)**2+(o.y-i.y)**2)?(c={x:i.x+s.x*n,y:i.y+s.y*n},d={x:o.x-s.x*l,y:o.y-s.y*l}):(c=i,d=o)}return{lineStart:c,lineEnd:d}}var Xs=(t,e,s)=>{if(t<e)return 0;if(e<1&&t<=1)return 0;if(1===s&&t>1)return 1-.01**t;const n=t/e-1;return 1-Math.exp(-2*n)},ks=(t,e,s)=>{if(s._containsTarget)return 0;if(t<=e)return 0;const n=1-Xs(t,e,s.availableZ.length);return n<=0?-1e9:Math.log(n)},Bs=({totalNodeCapacityMap:t,usedNodeCapacityMap:e,nodeMap:s,sectionNodeIds:n})=>{let i=0;const o=n??new Set(e.keys());for(const n of o){if(!t.has(n))continue;const o=s.get(n);if(!o)continue;const a=t.get(n),r=e.get(n)??0;i+=ks(r,a,o)}return i};function Fs({sectionNodes:t,sectionEdges:e,sectionConnectionTerminals:s,completedPaths:n,nodeMap:i,colorMap:o,centerNodeId:a,title:r,nodeOpacity:h=.1,usedNodeCapacityMap:c,totalCapacityMap:d}){const l={points:[],lines:[],rects:[],circles:[],title:r},u=new Set(t.map(t=>t.capacityMeshNodeId));for(const e of t){let t=`rgba(128, 128, 128, ${h})`,s=`rgba(128, 128, 128, ${h})`;const n=e.availableZ??[],i=n.includes(0),o=n.includes(1);i&&o?(t=`rgba(128, 0, 128, ${h})`,s=`rgba(128, 0, 128, ${h})`):i?(t=`rgba(0, 0, 255, ${h})`,s=`rgba(0, 0, 255, ${h})`):o&&(t=`rgba(255, 0, 0, ${h})`,s=`rgba(255, 0, 0, ${h})`),a&&e.capacityMeshNodeId===a&&(t=`rgba(0, 255, 0, ${h})`,s=`rgba(0, 128, 0, ${h})`),l.rects.push({...Rs(e),fill:t,stroke:s,label:`${e.capacityMeshNodeId}\n(Section Node)\nZ: ${n.join(",")}`});const r=l.rects.length-1;if(c&&d){const t=c.get(e.capacityMeshNodeId)??0,s=d.get(e.capacityMeshNodeId)??0,n=s>0?(t/s*100).toFixed(1):"N/A",i=Xs(t,s,e.availableZ.length);l.rects[r].label+=`\n${t.toFixed(1)} / ${s.toFixed(1)}\n${n}% (Pf: ${(100*i).toFixed(1)}%)`,i>.2&&(l.rects[r].stroke=ct("red",.7*(.8+h)))}}for(const t of e){const[e,s]=t.nodeIds,n=i.get(e),o=i.get(s);if(n&&o){const{lineStart:t,lineEnd:e}=Ys(n,o);l.lines.push({points:[t,e],strokeColor:`rgba(0, 0, 0, ${.2*Math.min(1,h/.1)})`})}}return s.forEach((t,e)=>{const s=i.get(t.startNodeId),n=i.get(t.endNodeId),a=o[t.connectionName]??"black",r=s&&u.has(s.capacityMeshNodeId),h=n&&u.has(n.capacityMeshNodeId),c=(e+e/50)%5;let d=0,p=0,f=0,m=0;if(r&&s){const e=.02*Math.min(s.width,s.height);d=e*c,p=e*c,l.points.push({x:s.center.x+d,y:s.center.y+p,color:a,label:`Start: ${t.connectionName}\n(${t.startNodeId})`}),l.lines.push({points:[{x:s.center.x,y:s.center.y},{x:s.center.x+d,y:s.center.y+p}],strokeColor:"gray",strokeDash:"2 2"})}if(h&&n){const e=.02*Math.min(n.width,n.height);f=e*c,m=e*c,l.points.push({x:n.center.x+f,y:n.center.y+m,color:a,label:`End: ${t.connectionName}\n(${t.endNodeId})`}),l.lines.push({points:[{x:n.center.x,y:n.center.y},{x:n.center.x+f,y:n.center.y+m}],strokeColor:"gray",strokeDash:"2 2"})}r&&h&&s&&n&&l.lines.push({points:[{x:s.center.x+d,y:s.center.y+p},{x:n.center.x+f,y:n.center.y+m}],strokeColor:a,strokeDash:"5 5"})}),n&&n.forEach((t,e)=>{if(t.path&&t.path.length>0){const s=o[t.connectionName]??"gray",n={x:(e+e/50)%5*.03,y:(e+e/50)%5*.03};l.lines.push({points:t.path.map(({center:{x:t,y:e}})=>({x:t+n.x,y:e+n.y})),strokeColor:ct(s,.2)})}}),l}var Hs=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??Ut(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=Bs({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:e}),t.hyperParameters?.SHUFFLE_SEED&&(this.sectionConnectionTerminals=ue(this.sectionConnectionTerminals,t.hyperParameters?.SHUFFLE_SEED))}getTotalCapacity(t){return lt(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){if(!this.nodeMap.has(t.capacityMeshNodeId))return 1/0;const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let s=1;return 1===t.availableZ.length&&(s=10),(.05+e**2*4)*s}getDistanceBetweenNodes(t,e){const s=t.center.x-e.center.x,n=t.center.y-e.center.y;return Math.sqrt(s**2+n**2)}computeG(t,e,s){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,s){return this.getDistanceBetweenNodes(e,s)+this.getNodeCapacityPenalty(e)}getBacktrackedPath(t){const e=[];let s=t;for(;s;){if(e.push(s.node),!this.nodeMap.has(s.node.capacityMeshNodeId)){console.warn("Backtracked path went outside section bounds");break}s=s.prevCandidate}return e.reverse()}getNeighboringNodes(t){return this.nodeMap.has(t.capacityMeshNodeId)?this.nodeEdgeMap.get(t.capacityMeshNodeId)?.flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t)).filter(Boolean)??[]:[]}isConnectedToEndGoal(t,e){return!(!this.nodeMap.has(t.capacityMeshNodeId)||!this.nodeMap.has(e.capacityMeshNodeId))&&(this.nodeEdgeMap.get(t.capacityMeshNodeId)??[]).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}doesNodeHaveCapacityForTrace(t,e){return!0}reduceCapacityAlongPath(t){for(const e of t)if(this.usedNodeCapacityMap.has(e.capacityMeshNodeId)){const t=e.capacityMeshNodeId,s=this.nodeMap.get(t);if(!s){console.warn(`Node ${t} from path not found in section's nodeMap during score update.`);continue}const n=this.totalNodeCapacityMap.get(t),i=this.usedNodeCapacityMap.get(t)??0,o=ks(i,n,s);this.currentSectionScore-=o;const a=i+1;this.usedNodeCapacityMap.set(t,a);const r=ks(a,n,s);this.currentSectionScore+=r}}getSolvedSectionScore(){return this.currentSectionScore}_step(){const t=this.sectionConnectionTerminals[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const e=this.nodeMap.get(t.startNodeId),s=this.nodeMap.get(t.endNodeId);if(!e||!s)return console.error(`Start or end node not found in section for connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);this.candidates||this._setupAStar(e,s);const n=this.candidates;if(0===n.length)return void this._handleCandidatesExhausted(t);n.sort((t,e)=>t.f-e.f);const i=n.shift();if(n.length>this.MAX_CANDIDATES_IN_MEMORY&&n.splice(this.MAX_CANDIDATES_IN_MEMORY,n.length-this.MAX_CANDIDATES_IN_MEMORY),this.visitedNodes.add(i.node.capacityMeshNodeId),i.node.capacityMeshNodeId===s.capacityMeshNodeId)return void this._handleGoalReached(i,t,s);const o=this.getNeighboringNodes(i.node);for(const e of o){if(this.queuedNodes?.has(e.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(e,i.node))continue;if(e._containsObstacle){const s=e.capacityMeshNodeId===t.startNodeId,n=e.capacityMeshNodeId===t.endNodeId;if(!s&&!n)continue}const o=this.computeG(i,e,s),a=this.computeH(i,e,s),r=o+a*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(e.capacityMeshNodeId,{f:r,g:o,h:a});const h={prevCandidate:i,node:e,f:r,g:o,h:a};this.queuedNodes?.add(e.capacityMeshNodeId),n.push(h)}}computeProgress(){const t=this.sectionConnectionTerminals.length;if(0===t)return 1;let e=this.currentConnectionIndex/t;if(this.currentConnectionIndex<t&&this.candidates&&this.candidates.length>0&&this.activeCandidateStraightLineDistance&&this.activeCandidateStraightLineDistance>0){const s=this.candidates.reduce((t,e)=>e.f<t.f?e:t);e+=Math.max(0,Math.min(1,1-s.h/this.activeCandidateStraightLineDistance))/t}else this.solved&&(e=1);return Math.min(1,e)}_setupAStar(t,e){this.candidates=[{prevCandidate:null,node:t,f:0,g:0,h:0}],this.visitedNodes=new Set([t.capacityMeshNodeId]),this.debug_lastNodeCostMap=new Map,this.activeCandidateStraightLineDistance=h(t.center,e.center);const s=this.computeH(null,t,e);this.candidates[0].h=s,this.candidates[0].f=s*this.GREEDY_MULTIPLIER,this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:this.candidates[0].f,g:0,h:s}),this.queuedNodes=new Set([t.capacityMeshNodeId])}_handleCandidatesExhausted(t){console.error(`Ran out of candidates for section connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}_handleGoalReached(t,e,s){const n=this.getBacktrackedPath(t);e.path=n,this.reduceCapacityAlongPath(n),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}visualize(){const t=this.sectionConnectionTerminals.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connectionName,path:t.path})),e=Fs({sectionNodes:this.sectionNodes,sectionEdges:this.sectionEdges,sectionConnectionTerminals:this.sectionConnectionTerminals,completedPaths:t,nodeMap:this.nodeMap,colorMap:this.colorMap,centerNodeId:null,title:`Section Pathing: Conn ${this.currentConnectionIndex+1}/${this.sectionConnectionTerminals.length} (${this.sectionNodes.length} nodes)`,nodeOpacity:.1});for(const t of this.sectionNodes){const s=e.rects.findIndex(e=>e.label?.includes(t.capacityMeshNodeId));if(-1!==s){const n=this.debug_lastNodeCostMap.get(t.capacityMeshNodeId),i=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,o=this.getTotalCapacity(t),a=`${i.toFixed(1)}/${o.toFixed(1)}`,r=n?`f:${n.f.toFixed(1)} g:${n.g.toFixed(1)} h:${n.h.toFixed(1)}`:"cost:?";e.rects[s].label=[t.capacityMeshNodeId,`Cap: ${a}`,r,`Z: ${t.availableZ.join(",")}`].join("\n"),i>o&&(e.rects[s].stroke=ct("red",.7))}}if(this.candidates&&this.candidates.length>0){const t=this.candidates.slice().sort((t,e)=>t.f-e.f).slice(0,5),s=this.sectionConnectionTerminals[this.currentConnectionIndex],n=s?.connectionName??"unknown",i=this.colorMap[n]??"purple";t.forEach((t,s)=>{const n=.8*(1-s/5),o=this.getBacktrackedPath(t);o.length>0&&e.lines.push({points:o.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:ct(i,1-n),strokeWidth:.05})})}return e}},Zs=t=>Array.from({length:t},(t,e)=>e),Us=class extends xe{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:Zs(2).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings6_for3",possibleValues:Zs(6).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings24_for4",possibleValues:Zs(24).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings30",possibleValues:Zs(30).map(t=>({SHUFFLE_SEED:t}))}]}generateSolver(t){return new Hs({...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 Vs from"object-hash";var js=t=>Math.floor(10*t)/10,Ws=class extends Us{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?ne():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}_computeBfsOrderingOfNodesInSection(){const t=new Set(this.constructorParams.centerNodeId),e=[],s=[{ancestorCapacitySum:0,capacity:0,g:0,capacityMeshNodeId:this.constructorParams.centerNodeId}];for(;s.length>0;){s.sort((t,e)=>e.g-t.g);const n=s.pop();if(!n)break;e.push(n.capacityMeshNodeId);const i=this.constructorParams.nodeEdgeMap.get(n.capacityMeshNodeId).flatMap(t=>t.nodeIds).filter(e=>!t.has(e)).filter(t=>this.sectionNodeIdSet.has(t));for(const e of i){t.add(e);const i=this.constructorParams.nodeMap.get(e),o=lt(i);s.push({ancestorCapacitySum:n.g,capacity:o,g:n.g+o,capacityMeshNodeId:e})}}return e}computeCacheKeyAndTransform(){const t=this._computeBfsOrderingOfNodesInSection(),e=new Map,s=new Map;t.forEach((t,n)=>{const i=`node${n}`;e.set(t,i),s.set(i,t)});const n={};for(const s of t){const t=e.get(s),i=this.constructorParams.nodeMap.get(s),o=lt(i);n[t]=js(o).toFixed(1)}const i=new Set,o=[];for(const s of t){const t=e.get(s),n=this.constructorParams.nodeEdgeMap.get(s)??[];for(const a of n){const n=a.nodeIds.find(t=>t!==s);if(this.sectionNodeIdSet.has(n)){const s=[t,e.get(n)].sort(),a=`${s[0]}-${s[1]}`;i.has(a)||(o.push(s),i.add(a))}}}o.sort((t,e)=>t[0]!==e[0]?t[0].localeCompare(e[0]):t[1].localeCompare(e[1]));const a={},r=new Map,h=new Map;for(const t of this.constructorParams.sectionConnectionTerminals){const s=e.get(t.startNodeId),n=e.get(t.endNodeId),[i,o]=[s,n].sort(),c=`${i}->${o}`,d=h.get(c)??0;h.set(c,d+1);const l=`${i}->${o}::${d}`;a[l]={start:i,end:o},r.set(l,t.connectionName)}const c=`capacitypathing:${Vs({node_capacity_map:n,node_edge_map:o,terminals:a})}`,d={cacheSpaceToRealConnectionId:r,cacheSpaceToRealNodeId:s};return this.cacheKey=c,this.cacheToSolveSpaceTransform=d,{cacheKey:c,cacheToSolveSpaceTransform:d}}applyCachedSolution(t){if(!this.cacheToSolveSpaceTransform)return console.error("Cache transform not available, cannot apply cached solution."),void(this.failed=!0);if(!t.success)return this.failed=!0,void(this.cacheHit=!0);this.cachedSectionConnectionTerminals=[];const{cacheSpaceToRealNodeId:e,cacheSpaceToRealConnectionId:s}=this.cacheToSolveSpaceTransform;for(const[n,i]of Object.entries(t.solutionPaths)){const t=s.get(n);if(!t){console.warn(`Could not find real connection name for ${n}`);continue}const o=this.constructorParams.sectionConnectionTerminals.find(e=>e.connectionName===t);if(!o){console.warn(`Could not find original terminal for connection name ${t}`);continue}const a=i.map(s=>{const n=e.get(s);if(!n)throw new Error(`Could not map cache node ID ${s} to real node ID for connection ${t}`);const i=this.constructorParams.nodeMap.get(n);if(!i)throw new Error(`Could not find node with ID ${n} in nodeMap for connection ${t}`);return i});this.cachedSectionConnectionTerminals.push({...o,path:a})}this.sectionScore=t.sectionScore,this.solved=!0,this.cacheHit=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(!this.cacheKey)return void console.error("Cannot save to cache without cache key.");if(!this.cacheToSolveSpaceTransform)return void console.error("Cache transform not available, cannot save solution to cache.");let t;if(this.failed)t={success:!1};else{if(!this.solved)return;{const e={},{cacheSpaceToRealNodeId:s,cacheSpaceToRealConnectionId:n}=this.cacheToSolveSpaceTransform,i=new Map;for(const[t,e]of s)i.set(e,t);const o=new Map;for(const[t,e]of n)o.set(e,t);const a=[];if(super.sectionConnectionTerminals)for(const t of super.sectionConnectionTerminals)if(t.path&&t.path.length>0){const e=t.path.map(t=>t.capacityMeshNodeId);a.push([t.connectionName,e])}for(const[t,s]of a){const n=o.get(t);if(!n){console.warn(`Could not find cache space connection ID for ${t} when saving to cache.`);continue}const a=s.map(e=>{const s=i.get(e);if(!s)throw new Error(`Could not map real node ID ${e} to cache node ID for connection ${t} when saving to cache.`);return s});e[n]=a}t={success:!0,sectionScore:this.sectionScore,solutionPaths:e}}}try{this.cacheProvider?.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}get sectionConnectionTerminals(){return this.cacheHit&&this.solved&&this.cachedSectionConnectionTerminals?(console.log("returning the cached section connection terminals"),this.cachedSectionConnectionTerminals):super.sectionConnectionTerminals}visualize(){if(!this.cacheHit)return super.visualize();return Fs({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"})}},Gs=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=Ut(this.edges),this.colorMap=t.colorMap??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ut(this.edges),this.initialSolver=t.initialPathingSolver||new Ds({simpleRouteJson:this.simpleRouteJson,nodes:this.nodes,edges:this.edges,colorMap:this.colorMap}),this.activeSubSolver=this.initialSolver;for(const t of this.nodes){const e=this.initialSolver.getTotalCapacity(t);this.totalNodeCapacityMap.set(t.capacityMeshNodeId,e)}this.allNodeIdsSet=new Set(this.nodes.map(t=>t.capacityMeshNodeId))}_stepInitialization(){if(this.initialSolver?.step(),this.initialSolver?.failed)return this.failed=!0,void(this.error=this.initialSolver.error);if(this.initialSolver?.solved){this.usedNodeCapacityMap=new Map(this.initialSolver.usedNodeCapacityMap);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=e>0?s/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,n),this.nodeOptimizationAttemptCountMap.set(t.capacityMeshNodeId,0)}this.connectionsWithNodes=this.initialSolver.connectionsWithNodes,this.stats.startingScore=Bs({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet}),this.stage="section-optimization"}}_getNextNodeToOptimize(){let t=0,e=0,s=null;for(const n of this.nodes){if(n._containsTarget)continue;const i=this.nodeOptimizationAttemptCountMap.get(n.capacityMeshNodeId),o=this.totalNodeCapacityMap.get(n.capacityMeshNodeId),a=Xs(this.usedNodeCapacityMap.get(n.capacityMeshNodeId)??0,o,n.availableZ.length),r=a/(i+1);i<this.currentSchedule.MAX_ATTEMPTS_PER_NODE&&r>t&&a>this.currentSchedule.MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE&&(t=r,e=a,s=n.capacityMeshNodeId)}return s}getOverallScore(){let t=0;for(const e of this.nodes){if(e._containsTarget)continue;const s=this.totalNodeCapacityMap.get(e.capacityMeshNodeId),n=Xs(this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,s,e.availableZ.length);n>t&&(t=n)}return{highestNodePf:t,score:Bs({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet})}}_stepSectionOptimization(){if(!this.sectionSolver){const t=this._getNextNodeToOptimize();if(!t){const{highestNodePf:t,score:e}=this.getOverallScore();return this.stats.scheduleScores[this.currentScheduleIndex].endingHighestNodePf=t,this.stats.scheduleScores[this.currentScheduleIndex].endingScore=e,this.currentScheduleIndex++,void(this.currentSchedule||(this.solved=!0))}const e=(t=>{const{centerNodeId:e,connectionsWithNodes:s,nodeMap:n,edges:i,nodeEdgeMap:o,expansionDegrees:a}=t,r=new Set,h=[{nodeId:e,depth:0}];r.add(e);let c=0;for(;c<h.length;){const{nodeId:t,depth:e}=h[c++];if(e>=a)continue;const s=o.get(t)?.flatMap(e=>e.nodeIds.filter(e=>e!==t))??[];for(const t of s)r.has(t)||(r.add(t),h.push({nodeId:t,depth:e+1}))}const d=Array.from(r).map(t=>n.get(t)),l=i.filter(t=>{const[e,s]=t.nodeIds;return r.has(e)&&r.has(s)}),u=[];for(const t of s){if(!t.path)continue;let e=null,s=null;for(const s of t.path)if(r.has(s.capacityMeshNodeId)){e=s.capacityMeshNodeId;break}for(let e=t.path.length-1;e>=0;e--){const n=t.path[e];if(r.has(n.capacityMeshNodeId)){s=n.capacityMeshNodeId;break}}e&&s&&u.push({connectionName:t.connection.name,startNodeId:e,endNodeId:s})}return{sectionConnectionTerminals:u,sectionNodes:d,sectionEdges:l,centerNodeId:e}})({centerNodeId:t,connectionsWithNodes:this.connectionsWithNodes,nodeMap:this.nodeMap,edges:this.edges,expansionDegrees:this.currentSchedule.MAX_EXPANSION_DEGREES,nodeEdgeMap:this.nodeEdgeMap});this.stats.scheduleScores[this.currentScheduleIndex].sectionAttempts++,this.currentSection=e,this.sectionSolver=new Ws({sectionNodes:this.currentSection.sectionNodes,sectionEdges:this.currentSection.sectionEdges,sectionConnectionTerminals:this.currentSection.sectionConnectionTerminals,colorMap:this.colorMap,centerNodeId:this.currentSection.centerNodeId,nodeEdgeMap:this.nodeEdgeMap,hyperParameters:{EXPANSION_DEGREES:this.currentSchedule.MAX_EXPANSION_DEGREES},cacheProvider:this.cacheProvider}),this.activeSubSolver=this.sectionSolver,this.nodeOptimizationAttemptCountMap.set(t,(this.nodeOptimizationAttemptCountMap.get(t)??0)+1)}if(this.sectionSolver.step(),(this.sectionSolver.failed||this.sectionSolver.solved)&&(this.sectionSolver.cacheHit?this.stats.cacheHits++:this.stats.cacheMisses++),this.sectionSolver.failed)return console.warn(`Section solver failed for node ${this.currentSection.centerNodeId}. Error: ${this.sectionSolver.error}`),this.stats.failedSectionSolvers++,this.stats.failedOptimizations++,this.sectionSolver=null,void(this.activeSubSolver=null);if(this.sectionSolver.solved){const t=this.sectionSolver.sectionConnectionTerminals,e=this.sectionSolver.sectionNodes,s=this.sectionSolver.centerNodeId;if(this.sectionSolver=null,this.activeSubSolver=null,!t)return void console.warn(`Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`);const n=new Set(e.map(t=>t.capacityMeshNodeId)),i=Bs({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:n}),o=new Map(this.usedNodeCapacityMap),a=t;for(const t of a){const e=this.connectionsWithNodes.find(e=>e.connection.name===t.connectionName);if(e?.path)for(const t of e.path)if(n.has(t.capacityMeshNodeId)){const e=o.get(t.capacityMeshNodeId)??0;o.set(t.capacityMeshNodeId,Math.max(0,e-1))}}for(const t of a)if(t.path)for(const e of t.path)n.has(e.capacityMeshNodeId)&&o.set(e.capacityMeshNodeId,(o.get(e.capacityMeshNodeId)??0)+1);Bs({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:o,nodeMap:this.nodeMap,sectionNodeIds:n})>i?(this.stats.successfulOptimizations++,this._mergeSolvedSectionPaths({centerNodeId:s,sectionConnectionTerminals:t}),this._recalculateNodeCapacityUsage()):this.stats.failedOptimizations++}}_mergeSolvedSectionPaths({centerNodeId:t,sectionConnectionTerminals:e}){for(const s of e){if(!s.path){console.warn(`No path found for connection ${s.connectionName} in section ${t}`);continue}const e=this.connectionsWithNodes.find(t=>t.connection.name===s.connectionName);if(!e||!e.path){console.warn(`Original connection or path not found for ${s.connectionName} while merging section ${t}`);continue}const n=e.path,i=s.path,o=n.findIndex(t=>t.capacityMeshNodeId===s.startNodeId),a=n.findIndex(t=>t.capacityMeshNodeId===s.endNodeId);if(-1===o||-1===a){console.warn(`Could not find start/end nodes (${s.startNodeId}/${s.endNodeId}) in original path for ${s.connectionName}`);continue}const[r,h]=o<=a?[o,a]:[a,o],c=n.slice(0,r),d=n.slice(h+1);let l=i;if(i.length>0&&n[r]&&i[0].capacityMeshNodeId!==n[r].capacityMeshNodeId){if(i[i.length-1].capacityMeshNodeId!==n[r].capacityMeshNodeId){console.warn(`New section path for ${s.connectionName} doesn't align with original path boundaries. Skipping merge for this connection.`);continue}l=[...i].reverse()}e.path=[...c,...l,...d]}}_recalculateNodeCapacityUsage(){this.usedNodeCapacityMap.clear();for(const t of this.connectionsWithNodes)if(t.path)for(const e of t.path)this.usedNodeCapacityMap.set(e.capacityMeshNodeId,(this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0)+1);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=e>0?s/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,n)}}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const s=e.path;s&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:s.map(t=>t.capacityMeshNodeId)})}return t}_step(){this.iterations>=this.MAX_ITERATIONS-1?this.solved=!0:"initialization"===this.stage?this._stepInitialization():"section-optimization"===this.stage&&this._stepSectionOptimization()}visualize(){const t=this.connectionsWithNodes.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connection.name,path:t.path}));return Fs({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)"})}},qs=class extends e{multiLayerNodes;strawNodes;skippedNodes;unprocessedNodes;strawSize;nodeIdCounter;constructor(t){super(),this.MAX_ITERATIONS=1e5,this.strawSize=t.strawSize??.5,this.multiLayerNodes=[],this.strawNodes=[],this.skippedNodes=[],this.nodeIdCounter=0,this.unprocessedNodes=[];for(const e of t.nodes)1===e.availableZ.length?this.unprocessedNodes.push(e):this.multiLayerNodes.push(e)}getCapacityOfMultiLayerNodesWithinBounds(t){let e=0;for(const s of this.multiLayerNodes){const n=s.center.x-s.width/2,i=s.center.x+s.width/2,o=s.center.y-s.height/2,a=s.center.y+s.height/2,r=Math.max(t.minX,n),h=Math.min(t.maxX,i),c=Math.max(t.minY,o),d=Math.min(t.maxY,a);if(r<h&&c<d){const t=(h-r)*(d-c)/(s.width*s.height);e+=lt(s)*t}}return e}getSurroundingCapacities(t){const e=Math.min(t.width,t.height);return{leftSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2-e,maxX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),rightSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x+t.width/2,maxX:t.center.x+t.width/2+e,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),topSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2-e,maxY:t.center.y-t.height/2}),bottomSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y+t.height/2,maxY:t.center.y+t.height/2+e})}}createStrawsForNode(t){const e=[],{leftSurroundingCapacity:s,rightSurroundingCapacity:n,topSurroundingCapacity:i,bottomSurroundingCapacity:o}=this.getSurroundingCapacities(t);if(1*(s+n)>i+o){const s=Math.floor(t.height/this.strawSize),n=t.height/s;for(let i=0;i<s;i++){const s=t.center.y-t.height/2+i*n+n/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:t.center.x,y:s},width:t.width,height:n,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}else{const s=Math.floor(t.width/this.strawSize),n=t.width/s;for(let i=0;i<s;i++){const s=t.center.x-t.width/2+i*n+n/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${i}`,center:{x:s,y:t.center.y},width:n,height:t.height,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}return e}getResultNodes(){return[...this.multiLayerNodes,...this.strawNodes,...this.skippedNodes]}_step(){const t=this.unprocessedNodes.pop();if(!t)return void(this.solved=!0);if(t.width<this.strawSize&&t.height<this.strawSize)return void this.skippedNodes.push(t);if(t._containsTarget)return void this.skippedNodes.push(t);const e=this.createStrawsForNode(t);this.strawNodes.push(...e)}visualize(){const t={rects:[],lines:[],points:[],circles:[],title:"Straw Solver"};for(const e of this.unprocessedNodes)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(200, 200, 200, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nUnprocessed\n${e.width}x${e.height}`});for(const e of this.strawNodes){const s=0===e.availableZ[0]?"rgba(0, 150, 255, 0.5)":"rgba(255, 100, 0, 0.5)";t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nLayer: ${e.availableZ[0]}\n${e.width}x${e.height}`,layer:`z${e.availableZ.join(",")}`})}for(const e of this.multiLayerNodes)t.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,fill:"rgba(100, 255, 100, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",layer:`z${e.availableZ.join(",")}`,label:`${e.capacityMeshNodeId}\nLayers: ${e.availableZ.join(",")}\n${e.width}x${e.height}`});return t}};function Ks(t,e){const s=t.center.x-t.width/2,n=t.center.x+t.width/2,i=t.center.y-t.height/2,o=t.center.y+t.height/2,a=e.center.x-e.width/2,r=e.center.x+e.width/2,h=e.center.y-e.height/2,c=e.center.y+e.height/2,d=.001,l=(Math.abs(n-a)<d||Math.abs(s-r)<d)&&Math.min(o,c)-Math.max(i,h)>=d,u=(Math.abs(o-h)<d||Math.abs(i-c)<d)&&Math.min(n,r)-Math.max(s,a)>=d;return l||u}var Js=class{constructor(t){this.nodes=t,this.buckets=new Map;for(const e of t){const t=e.center.x-e.width/2,s=e.center.y-e.height/2,n=e.center.x+e.width/2,i=e.center.y+e.height/2;for(let o=t;o<=n;o+=this.CELL_SIZE)for(let t=s;t<=i;t+=this.CELL_SIZE){const s=this.getBucketKey(o,t),n=this.buckets.get(s);n?n.push(e):this.buckets.set(s,[e])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,s,n){const i=[],o=new Set,a=e-n/2,r=t+s/2,h=e+n/2;for(let e=t-s/2;e<=r;e+=this.CELL_SIZE)for(let t=a;t<=h;t+=this.CELL_SIZE){const s=this.getBucketKey(e,t),n=this.buckets.get(s)||[];for(const t of n)o.has(t.capacityMeshNodeId)||(o.add(t.capacityMeshNodeId),i.push(t))}return i}},Qs=.005,tn=class extends e{nodeMap;currentBatchNodeIds;absorbedNodeIds;nextBatchNodeIds;batchHadModifications;hasComputedAdjacentNodeIds=!1;newNodes;constructor(t){super(),this.nodeMap=new Map,this.MAX_ITERATIONS=1e5;for(const e of t)this.nodeMap.set(e.capacityMeshNodeId,e);this.newNodes=[],this.absorbedNodeIds=new Set;const e=[];for(const s of t)s.availableZ.length>1?(this.newNodes.push(s),this.absorbedNodeIds.add(s.capacityMeshNodeId)):e.push([s,s.width*s.height]);e.sort((t,e)=>t[1]-e[1]);for(const[t,s]of e){const e={...t,center:{...t.center}};this.nodeMap.set(t.capacityMeshNodeId,e)}this.currentBatchNodeIds=e.map(([t])=>t.capacityMeshNodeId),this.nextBatchNodeIds=[],this.batchHadModifications=!1}computeAdjacentNodeIdsForFirstBatch(t){const e=Math.max(...t.map(t=>Math.max(...t.availableZ))),s=[];for(let n=0;n<=e;n++)s.push(new Js(t.filter(t=>t.availableZ[0]===n)));for(const e of t){const t=[],n=s[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const s of n)s._containsTarget&&s._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!s._containsTarget||s._targetConnectionName!==e._targetConnectionName)||s.capacityMeshNodeId!==e.capacityMeshNodeId&&Ks(e,s)&&t.push(s);e._adjacentNodeIds=t.map(t=>t.capacityMeshNodeId)}}getAdjacentSameLayerUnprocessedNodes(t){return this.getAdjacentSameLayerUnprocessedNodes2(t)}getAdjacentSameLayerUnprocessedNodes2(t){const e=[],s=Array.from(new Set((t._adjacentNodeIds??[]).map(t=>this.nodeMap.get(t)))).filter(e=>e&&e.capacityMeshNodeId!==t.capacityMeshNodeId);s.sort((t,e)=>t.width*t.height-e.width*e.height);for(const t of s)this.absorbedNodeIds.has(t.capacityMeshNodeId)||e.push(t);return e}_step(){this.hasComputedAdjacentNodeIds||(this.computeAdjacentNodeIdsForFirstBatch(this.currentBatchNodeIds.map(t=>this.nodeMap.get(t))),this.hasComputedAdjacentNodeIds=!0);let t=this.currentBatchNodeIds.pop();for(;t&&this.absorbedNodeIds.has(t);)t=this.currentBatchNodeIds.pop();if(!t)return this.batchHadModifications?(this.currentBatchNodeIds=this.nextBatchNodeIds.sort((t,e)=>{const s=this.nodeMap.get(t),n=this.nodeMap.get(e);return s.width*s.height-n.width*n.height}),this.nextBatchNodeIds=[],void(this.batchHadModifications=!1)):(this.solved=!0,void this.newNodes.push(...this.nextBatchNodeIds.map(t=>this.nodeMap.get(t))));const e=this.nodeMap.get(t);let s=!1;const n=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===n.length)return void this.nextBatchNodeIds.push(t);const i=t=>{for(const e of t)this.absorbedNodeIds.add(e.capacityMeshNodeId);e._adjacentNodeIds=Array.from(new Set([...e._adjacentNodeIds??[],...t.flatMap(t=>t._adjacentNodeIds??[])].filter(t=>t!==e.capacityMeshNodeId&&!this.absorbedNodeIds.has(t))))},o=n.filter(t=>t.center.x<e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(o.length>0){const{width:t,height:n}=o[0],a=o.every(e=>e.width===t&&e.height===n);Math.abs(o.reduce((t,e)=>t+e.height,0)-e.height)<Qs&&a&&(e.width+=t,e.center.x=e.center.x-t/2,i(o),s=!0)}const a=n.filter(t=>t.center.x>e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(a.length>0&&!s){const{width:t,height:n}=a[0],o=a.every(e=>e.width===t&&e.height===n);Math.abs(a.reduce((t,e)=>t+e.height,0)-e.height)<Qs&&o&&(e.width+=t,e.center.x=e.center.x+t/2,i(a),s=!0)}const r=n.filter(t=>t.center.y>e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(r.length>0&&!s){const{width:t,height:n}=r[0],o=r.every(e=>e.width===t&&e.height===n);Math.abs(r.reduce((t,e)=>t+e.width,0)-e.width)<Qs&&o&&(e.height+=n,e.center.y=e.center.y+n/2,i(r),s=!0)}const h=n.filter(t=>t.center.y<e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(h.length>0&&!s){const{width:t,height:n}=h[0],o=h.every(e=>e.width===t&&e.height===n);Math.abs(h.reduce((t,e)=>t+e.width,0)-e.width)<Qs&&o&&(e.height+=n,e.center.y=e.center.y-n/2,i(h),s=!0)}s?(this.batchHadModifications=!0,this.currentBatchNodeIds.push(t)):this.nextBatchNodeIds.unshift(t)}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Same Layer Node Merger"};for(const e of this.newNodes)t.rects.push(Rs(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let s;e&&(s=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const n of this.currentBatchNodeIds){const i=this.nodeMap.get(n);if(!this.absorbedNodeIds.has(n)&&i){const o=Rs(i,{rectMargin:.01});n===e?o.stroke="rgba(0, 255, 0, 0.8)":s?.some(t=>t.capacityMeshNodeId===n)?o.stroke="rgba(128, 0, 128, 0.8)":o.stroke="rgba(255, 165, 0, 0.8)",o.layer=`z${i.availableZ.join(",")}`,o.label=`${o.label}\n(unprocessed)`,t.rects.push(o)}}for(const e of this.nextBatchNodeIds){const s=this.nodeMap.get(e);if(!this.absorbedNodeIds.has(e)&&s){const e=Rs(s,{rectMargin:.01});e.layer=`z${s.availableZ.join(",")}`,e.stroke="rgba(0, 217, 255, 0.8)",e.label=`${e.label}\nx: ${s.center.x}, y: ${s.center.y}\n${s.width}x${s.height}\n(next batch)`,t.rects.push(e)}}return t}},en=class extends e{newRoute;newVias;headIndex=0;tailIndex=0;inputRoute;otherHdRoutes;obstacles;connMap;colorMap;outline;constructor(t){super(),this.inputRoute=t.inputRoute,this.otherHdRoutes=t.otherHdRoutes,this.obstacles=t.obstacles,this.connMap=t.connMap,this.colorMap=t.colorMap,this.outline=t.outline,this.newRoute=[this.inputRoute.route[0]],this.newVias=[]}getConstructorParams(){return{inputRoute:this.inputRoute,otherHdRoutes:this.otherHdRoutes,obstacles:this.obstacles,connMap:this.connMap.netMap,colorMap:this.colorMap,outline:this.outline}}get simplifiedRoute(){return{connectionName:this.inputRoute.connectionName,traceThickness:this.inputRoute.traceThickness,viaDiameter:this.inputRoute.viaDiameter,route:this.newRoute,vias:this.newVias}}isValidPath(t){throw new Error("Not implemented")}_step(){throw new Error("Not implemented")}getVisualsForNewRouteAndObstacles(){const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Simplified Path Solver"};for(let e=0;e<this.inputRoute.route.length-1;e++)t.lines.push({points:[{x:this.inputRoute.route[e].x,y:this.inputRoute.route[e].y},{x:this.inputRoute.route[e+1].x,y:this.inputRoute.route[e+1].y}],strokeColor:"rgba(255, 0, 0, 0.8)",strokeDash:1===this.inputRoute.route[e].z?"5, 5":void 0,layer:`z${this.inputRoute.route[e].z.toString()}`});for(let e=0;e<this.newRoute.length;e++)e<this.newRoute.length-1&&t.lines.push({points:[{x:this.newRoute[e].x,y:this.newRoute[e].y},{x:this.newRoute[e+1].x,y:this.newRoute[e+1].y}],strokeWidth:.15,strokeColor:"rgba(0, 255, 0, 0.8)",strokeDash:1===this.newRoute[e].z?[.4,.4]:void 0,layer:`z${this.newRoute[e].z.toString()}`}),t.points.push({x:this.newRoute[e].x,y:this.newRoute[e].y,color:"rgba(0, 255, 0, 0.8)",label:`z: ${this.newRoute[e].z}`,layer:`z${this.newRoute[e].z.toString()}`});for(const e of this.newVias)t.circles.push({center:e,radius:this.inputRoute.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)"});for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});for(const e of this.otherHdRoutes)for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeWidth:.15,strokeColor:0===e.route[s].z?"rgba(255, 0, 255, 0.5)":1===e.route[s].z?"rgba(128, 0, 128, 0.5)":"rgba(0, 0, 255, 0.5)",layer:`z${e.route[s].z.toString()}`});if("filteredObstaclePathSegments"in this){const e=this.filteredObstaclePathSegments;for(const[s,n]of e)t.lines.push({points:[s,n]})}return t}};function sn(t,e,s,n){if(function(t,e,s,n){const i=rn(t,e,s),o=rn(t,e,n),a=rn(s,n,t),r=rn(s,n,e);return i!==o&&a!==r||(!(0!==i||!hn(t,s,e))||(!(0!==o||!hn(t,n,e))||(!(0!==a||!hn(s,t,n))||!(0!==r||!hn(s,e,n)))))}(t,e,s,n))return 0;const i=nn(t,s,n),o=nn(e,s,n),a=nn(s,t,e),r=nn(n,t,e);return Math.min(i,o,a,r)}function nn(t,e,s){const n={x:s.x-e.x,y:s.y-e.y},i=on({x:t.x-e.x,y:t.y-e.y},n);if(i<=0)return an(t,e);const o=on(n,n);if(o<=i)return an(t,s);const a=i/o;return an(t,{x:e.x+a*n.x,y:e.y+a*n.y})}function on(t,e){return t.x*e.x+t.y*e.y}function an(t,e){const s=e.x-t.x,n=e.y-t.y;return Math.sqrt(s*s+n*n)}function rn(t,e,s){const n=(e.y-t.y)*(s.x-e.x)-(e.x-t.x)*(s.y-e.y);return 0===n?0:n>0?1:2}function hn(t,e,s){return e.x<=Math.max(t.x,s.x)&&e.x>=Math.min(t.x,s.x)&&e.y<=Math.max(t.y,s.y)&&e.y>=Math.min(t.y,s.y)}var cn=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)}),dn=class{constructor(t){this.segments=t,this.buckets=new Map;const e=new Map;for(const s of t){const t=this.getSegmentKey(s);if(e.has(t))continue;e.set(t,s);const n=cn(s),i=Math.floor(n.minX/this.CELL_SIZE),o=Math.floor(n.maxX/this.CELL_SIZE),a=Math.floor(n.minY/this.CELL_SIZE),r=Math.floor(n.maxY/this.CELL_SIZE);for(let e=i;e<=o;e++)for(let n=a;n<=r;n++){const i=`${e}x${n}`,o=this.buckets.get(i),a=[s[0],s[1],t];o?o.push(a):this.buckets.set(i,[a])}}}buckets;CELL_SIZE=.4;SEGMENT_MARGIN=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getSegmentKey(t){return`${t[0].x}-${t[0].y}-${t[0].z}-${t[1].x}-${t[1].y}-${t[1].z}`}getSegmentsThatCouldIntersect(t,e){const s=[],n=new Set,i=Math.min(t.x,e.x)-this.SEGMENT_MARGIN,o=Math.min(t.y,e.y)-this.SEGMENT_MARGIN,a=Math.max(t.x,e.x)+this.SEGMENT_MARGIN,r=Math.max(t.y,e.y)+this.SEGMENT_MARGIN,h=Math.floor(i/this.CELL_SIZE),c=Math.floor(a/this.CELL_SIZE),d=Math.floor(o/this.CELL_SIZE),l=Math.floor(r/this.CELL_SIZE);for(let t=h;t<=c;t++)for(let e=d;e<=l;e++){const i=`${t}x${e}`,o=this.buckets.get(i);if(o)for(const t of o){const e=t[2];n.has(e)||(n.add(e),s.push(t))}}return s}},ln=1e-6,un=(t,e,s)=>r(t,e,s)<=ln,pn=(t,e)=>Math.abs(t.x-e.x)<=ln&&Math.abs(t.y-e.y)<=ln,fn=(t,e)=>{if(!e||e.length<3)return!1;for(let s=0;s<e.length;s++){const n=e[s],i=e[(s+1)%e.length];if(un(t,n,i))return!0}let s=!1;for(let n=0,i=e.length-1;n<e.length;i=n++){const o=e[n],a=e[i];o.y>t.y!=a.y>t.y&&t.x<(a.x-o.x)*(t.y-o.y)/(a.y-o.y)+o.x&&(s=!s)}return s},mn=class extends en{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=s(t),i=s(e),o=Math.max(n.minX-i.maxX,i.minX-n.maxX,0),a=Math.max(n.minY-i.maxY,i.minY-n.maxY,0);return Math.hypot(o,a)}(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 s=t.route,n=[];for(let t=0;t<s.length-1;t++){const i=s[t],o=s[t+1],a=Math.min(i.x,o.x),r=Math.max(i.x,o.x),h=Math.min(i.y,o.y),c=Math.max(i.y,o.y);a<=e.maxX&&r>=e.minX&&h<=e.maxY&&c>=e.minY&&n.push([i,o])}return n}),this.segmentTree=new dn(this.filteredObstaclePathSegments),this.filteredVias=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const s=t.vias,n=[];for(const i of s){const s=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2+t.viaDiameter/2,o=i.x-s,a=i.x+s,r=i.y-s,h=i.y+s;o<=e.maxX&&a>=e.minX&&r<=e.maxY&&h>=e.minY&&n.push({...i,diameter:t.viaDiameter})}return n}),this.computePathSegments()}computePathSegments(){let t=0;for(let e=0;e<this.inputRoute.route.length-1;e++){const s=this.inputRoute.route[e],n=this.inputRoute.route[e+1],i=Math.sqrt((n.x-s.x)**2+(n.y-s.y)**2)+e/1e4;this.pathSegments.push({start:s,end:n,length:i,startDistance:t,endDistance:t+i}),t+=i}this.totalPathLength=t}arePointsEqual(t,e){return t.x===e.x&&t.y===e.y&&t.z===e.z}getPointAtDistance(t){t=Math.max(0,Math.min(t,this.totalPathLength));const e=this.pathSegments.find(e=>t>=e.startDistance&&t<=e.endDistance);if(!e)return this.inputRoute.route[this.inputRoute.route.length-1];const s=(t-e.startDistance)/e.length;return{x:e.start.x+s*(e.end.x-e.start.x),y:e.start.y+s*(e.end.y-e.start.y),z:s<.5?e.start.z:e.end.z}}getNearestIndexForDistance(t){if(t<=0)return 0;if(t>=this.totalPathLength)return this.inputRoute.route.length-1;const e=this.pathSegments.findIndex(e=>t>=e.startDistance&&t<=e.endDistance);if(-1===e)return 0;const s=this.pathSegments[e],n=(s.startDistance+s.endDistance)/2;return t>n?e+1:e}isValidPathSegment(t,e){for(const s of this.filteredObstacles){if(!s.zLayers?.includes(t.z))continue;if(v(t,e,s)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2)return!1}const s=this.segmentTree.getSegmentsThatCouldIntersect(t,e);for(const[n,i,o]of s)if(n.z===t.z&&i.z===t.z){if(sn({x:t.x,y:t.y},{x:e.x,y:e.y},{x:n.x,y:n.y},{x:i.x,y:i.y})<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS)return!1}for(const s of this.filteredVias)if(r(s,t,e)<this.OBSTACLE_MARGIN+s.diameter/2+this.TRACE_THICKNESS/2)return!1;if(this.outline&&this.outline.length>=3){const s=(({start:t,end:e,polygon:s,margin:n=.2})=>{if(!s||s.length<3)return!1;const o=fn(t,s),a=fn(e,s);if(!o||!a)return!0;for(let o=0;o<s.length;o++){const a=s[o],r=s[(o+1)%s.length],h=un(t,a,r),d=un(e,a,r);if(h&&d)continue;if(!i(t,e,a,r)){if(!h&&!d&&sn(t,e,a,r)<n-ln)return!0;continue}const l=c(t,e,a,r);if(!(l&&(h&&pn(l,t)||d&&pn(l,e))||l&&(pn(l,t)||pn(l,e))))return!0}return!1})({start:{x:t.x,y:t.y},end:{x:e.x,y:e.y},polygon:this.outline});if(s)return!1}return!0}isValidPath(t){if(t.length<2)return!0;for(let e=0;e<t.length-1;e++)if(t[e].z!==t[e+1].z)return!1;for(let e=0;e<t.length-1;e++)if(!this.isValidPathSegment(t[e],t[e+1]))return!1;return!0}find45DegreePath(t,e){if(this.arePointsEqual(t,e))return[t];if(t.z!==e.z)return null;const s=((t,e)=>{const s=[],n=Math.abs(e.x-t.x),i=Math.abs(e.y-t.y),o=e.x>t.x?1:-1,a=e.y>t.y?1:-1,r={x:e.x-o*Math.abs(e.y-t.y),y:t.y};(r.x-t.x)*o>=0&&(r.x-e.x)*o<=0&&s.push([t,r,e]);const h={x:t.x,y:e.y-a*Math.abs(e.x-t.x)};(h.y-t.y)*a>=0&&(h.y-e.y)*a<=0&&s.push([t,h,e]);const c=Math.min(n,i),d={x:t.x+o*c,y:t.y+a*c};return(d.x-t.x)*o>=0&&(d.x-e.x)*o<=0&&(d.y-t.y)*a>=0&&(d.y-e.y)*a<=0&&s.push([t,d,e]),s})({x:t.x,y:t.y},{x:e.x,y:e.y});for(const e of s){const s=e.map(e=>({x:e.x,y:e.y,z:t.z}));if(this.isValidPath(s))return s}return null}addPathToResult(t){if(0!==t.length){for(let e=0;e<t.length;e++)0===e&&this.newRoute.length>0&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t[e])||this.newRoute.push(t[e]);this.currentStepSize=this.maxStepSize}}moveHead(t){this.lastHeadMoveDistance=t,this.headDistanceAlongPath=Math.min(this.headDistanceAlongPath+t,this.totalPathLength)}stepBackAndReduceStepSize(){this.headDistanceAlongPath=Math.max(this.tailDistanceAlongPath,this.headDistanceAlongPath-this.lastHeadMoveDistance),this.currentStepSize=Math.max(this.minStepSize,this.currentStepSize*this.STEP_SIZE_REDUCTION_FACTOR)}_step(){const t=this.tailDistanceAlongPath>=this.totalPathLength,e=this.headDistanceAlongPath>=this.totalPathLength;if(t){const t=this.inputRoute.route[this.inputRoute.route.length-1];return 0!==this.newRoute.length&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t)||this.newRoute.push(t),void(this.solved=!0)}if(e){const t=this.getPointAtDistance(this.tailDistanceAlongPath),e=this.inputRoute.route[this.inputRoute.route.length-1],s=this.find45DegreePath(t,e);if(s)return this.addPathToResult(s),void(this.solved=!0);this.lastValidPath=null,this.tailDistanceAlongPath=this.totalPathLength,this.headDistanceAlongPath=this.totalPathLength;const n=[];for(const t of this.inputRoute.route)0!==n.length&&this.arePointsEqual(n[n.length-1],t)||n.push(t);return this.newRoute=n,this.newVias=[...this.inputRoute.vias],void(this.solved=!0)}this.moveHead(this.currentStepSize);const s=this.getPointAtDistance(this.tailDistanceAlongPath),n=this.getPointAtDistance(this.headDistanceAlongPath),i=this.getNearestIndexForDistance(this.tailDistanceAlongPath),o=this.getNearestIndexForDistance(this.headDistanceAlongPath);let a=!1,r=-1;for(let t=i;t<o;t++)if(t+1<this.inputRoute.route.length&&this.inputRoute.route[t].z!==this.inputRoute.route[t+1].z){a=!0;const e=t;r=this.pathSegments[e].startDistance;break}if(a&&this.lastHeadMoveDistance>this.minStepSize)return void this.stepBackAndReduceStepSize();if(a&&r>0){const t=this.getNearestIndexForDistance(r)+1,e=this.inputRoute.route[t],s={x:e.x,y:e.y};this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null);const n=this.newRoute[this.newRoute.length-1];n.x===s.x&&n.y===s.y||this.newRoute.push({x:s.x,y:s.y,z:n.z}),this.newVias.push(s),this.newRoute.push({x:s.x,y:s.y,z:e.z}),this.currentStepSize=this.maxStepSize;const i=this.pathSegments.findIndex(t=>t.start===e);if(-1!==i)this.tailDistanceAlongPath=this.pathSegments[i].startDistance,this.headDistanceAlongPath=this.tailDistanceAlongPath,this.lastValidPath=null,this.lastValidPathHeadDistance=this.tailDistanceAlongPath;else if(t<this.inputRoute.route.length){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("Could not find segment start after layer change, path might be incomplete."),this.solved=!0)}else console.warn("Layer change occurred at the end of the path."),this.solved=!0;return}const h=this.find45DegreePath(s,n);if(!h&&this.lastHeadMoveDistance>this.minStepSize)this.stepBackAndReduceStepSize();else{if(!h&&!this.lastValidPath){const t=this.getPointAtDistance(this.tailDistanceAlongPath);this.tailDistanceAlongPath+=this.minStepSize,this.moveHead(this.minStepSize);const e=this.getNearestIndexForDistance(this.tailDistanceAlongPath),s=this.inputRoute.route[e],n=this.inputRoute.route[this.inputRoute.route.length-1];return void(this.arePointsEqual(t,s)||this.arePointsEqual(s,n)||this.newRoute.push(s))}if(h)return this.lastValidPath=h,void(this.lastValidPathHeadDistance=this.headDistanceAlongPath);this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null,this.tailDistanceAlongPath=this.lastValidPathHeadDistance,this.moveHead(this.minStepSize))}}visualize(){const t=this.getVisualsForNewRouteAndObstacles(),e=this.getPointAtDistance(this.tailDistanceAlongPath),s=this.getPointAtDistance(this.headDistanceAlongPath);t.points.push({x:e.x,y:e.y,color:"yellow",label:["Tail",`z: ${e.z}`].join("\n")}),t.points.push({x:s.x,y:s.y,color:"orange",label:["Head",`z: ${s.z}`].join("\n")});const n=this.getPointAtDistance(this.headDistanceAlongPath+this.currentStepSize);t.points.push({x:n.x,y:n.y,color:"red",label:["Tentative Head",`z: ${n.z}`].join("\n")});let i=0;for(;i<this.totalPathLength;){const e=this.getPointAtDistance(i);t.circles.push({center:{x:e.x,y:e.y},radius:.05,fill:"rgba(100, 100, 100, 0.5)"}),i+=this.totalPathLength/20}if(this.lastValidPath&&this.lastValidPath.length>1)for(let e=0;e<this.lastValidPath.length-1;e++)t.lines.push({points:[{x:this.lastValidPath[e].x,y:this.lastValidPath[e].y},{x:this.lastValidPath[e+1].x,y:this.lastValidPath[e+1].y}],strokeColor:"rgba(0, 255, 255, 0.9)",strokeDash:"3, 3"});return t}},gn=class extends e{simplifiedHdRoutes;currentUnsimplifiedHdRouteIndex=0;activeSubSolver=null;unsimplifiedHdRoutes;obstacles;connMap;colorMap;outline;constructor(t){super(),this.MAX_ITERATIONS=1e8,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.obstacles=t.obstacles,this.connMap=t.connMap||new is({}),this.colorMap=t.colorMap||{},this.outline=t.outline,this.simplifiedHdRoutes=[]}_step(){const t=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];if(!this.activeSubSolver)return t?(this.activeSubSolver=new mn({inputRoute:t,otherHdRoutes:this.unsimplifiedHdRoutes.slice(this.currentUnsimplifiedHdRouteIndex+1).concat(this.simplifiedHdRoutes),obstacles:this.obstacles,connMap:this.connMap,colorMap:this.colorMap,outline:this.outline}),void this.currentUnsimplifiedHdRouteIndex++):void(this.solved=!0);this.activeSubSolver.step(),this.activeSubSolver.solved&&(this.simplifiedHdRoutes.push(this.activeSubSolver.simplifiedRoute),this.activeSubSolver=null)}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Multi Simplified Path Solver"};for(const e of this.unsimplifiedHdRoutes)if(!this.simplifiedHdRoutes.some(t=>t.connectionName===e.connectionName)){for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeColor:1===e.route[s].z?"rgba(0, 0, 255, 0.4)":"rgba(255, 0, 0, 0.4)",strokeWidth:.15,strokeDash:1===e.route[s].z?[.5,.5]:void 0});for(const s of e.vias||[])t.circles.push({center:s,radius:e.viaDiameter/2||.3,fill:"rgba(0, 0, 255, 0.4)"})}for(const e of this.simplifiedHdRoutes){const s=this.colorMap?.[e.connectionName]||"rgba(128, 128, 128, 0.8)";for(let n=0;n<e.route.length-1;n++)t.lines.push({points:[{x:e.route[n].x,y:e.route[n].y},{x:e.route[n+1].x,y:e.route[n+1].y}],strokeWidth:.15,strokeColor:s,strokeDash:1===e.route[n].z?[.5,.5]:void 0,step:1});for(const s of e.vias||[])t.circles.push({center:s,radius:e.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)",step:1})}for(const e of this.unsimplifiedHdRoutes){for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeWidth:.15,strokeColor:"rgba(255, 0, 0, 0.2)",strokeDash:[.5,.5],step:0,layer:`z${e.route[s].z.toString()}`});for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 0, 0.2)",step:0})}for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});if(this.currentUnsimplifiedHdRouteIndex<this.unsimplifiedHdRoutes.length){const e=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];e.route.length>0&&t.circles.push({center:{x:e.route[0].x,y:e.route[0].y},radius:.2,fill:"yellow",label:"Current"})}return t}},yn=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)&&Ks(this.nodes[t],this.nodes[e])&&this.doNodesHaveSharedLayer(this.nodes[t],this.nodes[e])&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[this.nodes[t].capacityMeshNodeId,this.nodes[e].capacityMeshNodeId]})}this.handleTargetNodes(),this.solved=!0}handleTargetNodes(){const t=this.nodes.filter(t=>t._containsTarget);for(const e of t){if(this.edges.some(t=>t.nodeIds.includes(e.capacityMeshNodeId)))continue;let t=null,s=1/0;for(const n of this.nodes){if(n._containsObstacle)continue;if(n._containsTarget)continue;const i=h(e.center,n.center);i<s&&(s=i,t=n)}t&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[e.capacityMeshNodeId,t.capacityMeshNodeId]})}}doNodesHaveSharedLayer(t,e){return t.availableZ.some(t=>e.availableZ.includes(t))}visualize(){const t=new Map;for(const e of this.edges)for(const s of e.nodeIds)t.set(s,1+(t.get(s)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const s=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+s*e.width*.05,y:e.center.y-s*e.width*.05},fill:e._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}for(const t of this.edges){const s=this.nodeMap.get(t.nodeIds[0]),n=this.nodeMap.get(t.nodeIds[1]);if(s?.center&&n?.center){const t=Math.min(...s.availableZ),i=Math.min(...n.availableZ),o={x:s.center.x+t*s.width*.05,y:s.center.y-t*s.width*.05},a={x:n.center.x+i*n.width*.05,y:n.center.y-i*n.width*.05},r=Array.from(new Set([...s.availableZ,...n.availableZ])).sort();e.lines.push({layer:`z${r.join(",")}`,points:[o,a],strokeDash:s.availableZ.join(",")===n.availableZ.join(",")?void 0:"10 5"})}}return e}},xn=class extends yn{constructor(t){super(t),this.nodes=t,this.MAX_ITERATIONS=1e7,this.nodeTree=new Js(this.nodes),this.currentNodeIndex=0,this.edgeSet=new Set}nodeTree;currentNodeIndex;edgeSet;_step(){if(this.currentNodeIndex>=this.nodes.length)return this.handleTargetNodes(),void(this.solved=!0);const t=this.nodes[this.currentNodeIndex],e=this.nodeTree.getNodesInArea(t.center.x,t.center.y,2*t.width,2*t.height);for(const s of e){if(!Ks(t,s))continue;const e=t._strawNode&&s._strawNode&&t._strawParentCapacityMeshNodeId===s._strawParentCapacityMeshNodeId;t.capacityMeshNodeId===s.capacityMeshNodeId||e||!this.doNodesHaveSharedLayer(t,s)||this.edgeSet.has(`${t.capacityMeshNodeId}-${s.capacityMeshNodeId}`)||(this.edgeSet.add(`${t.capacityMeshNodeId}-${s.capacityMeshNodeId}`),this.edgeSet.add(`${s.capacityMeshNodeId}-${t.capacityMeshNodeId}`),this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[t.capacityMeshNodeId,s.capacityMeshNodeId]}))}this.currentNodeIndex++}},Mn=class extends e{removedNodeIds;targetNodeIds;leaves;leavesIndex;adjacencyList;nodeMap;nodes;edges;constructor({nodes:t,edges:e}){super(),this.MAX_ITERATIONS=t.length,this.nodes=t,this.edges=e,this.removedNodeIds=new Set,this.targetNodeIds=new Set(t.filter(t=>t._containsTarget).map(t=>t.capacityMeshNodeId)),this.adjacencyList=new Map(t.map(({capacityMeshNodeId:t})=>[t,new Set]));for(const{nodeIds:[t,s]}of e)this.adjacencyList.get(t).add(s),this.adjacencyList.get(s).add(t);this.leavesIndex=0,this.leaves=[...this.adjacencyList.entries()].filter(([t,e])=>1===e.size).filter(([t,e])=>!this.targetNodeIds.has(t)).map(([t,e])=>t)}_step(){if(this.leavesIndex===this.leaves.length)return void(this.solved=!0);const t=this.leaves[this.leavesIndex],e=this.adjacencyList.get(t);if(!e||0===e.size)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));const[s]=e,n=s?this.adjacencyList.get(s):void 0;if(!s||!n)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));n.delete(t),this.removedNodeIds.add(t),this.adjacencyList.delete(t),1!==n.size||this.targetNodeIds.has(s)||this.leaves.push(s),this.leavesIndex+=1,this.leavesIndex===this.leaves.length&&(this.solved=!0)}visualize(){if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}const t=new Map;for(const e of this.edges)for(const s of e.nodeIds)t.set(s,1+(t.get(s)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const s=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+s*e.width*.05,y:e.center.y-s*e.width*.05},fill:e._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};for(const t of this.edges){const s=this.nodeMap.get(t.nodeIds[0]),n=this.nodeMap.get(t.nodeIds[1]);if(s?.center&&n?.center){const i=Math.min(...s.availableZ),o=Math.min(...n.availableZ),a={x:s.center.x+i*s.width*.05,y:s.center.y-i*s.width*.05},r={x:n.center.x+o*n.width*.05,y:n.center.y-o*n.width*.05},h=Array.from(new Set([...s.availableZ,...n.availableZ])).sort();e.lines.push({layer:`z${h.join(",")}`,points:[a,r],strokeDash:s.availableZ.join(",")===n.availableZ.join(",")?void 0:"10 5",strokeColor:t.nodeIds.some(t=>this.removedNodeIds.has(t))?ct("black",.9):void 0})}}return e}},vn=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 Sn(t,e){const s=t.x-e.x,n=t.y-e.y;return s*s+n*n}function bn(t,e,s){const n=Sn(e,s);if(0===n)return Sn(t,e);let i=((t.x-e.x)*(s.x-e.x)+(t.y-e.y)*(s.y-e.y))/n;i=Math.max(0,Math.min(1,i));return Sn(t,{x:e.x+i*(s.x-e.x),y:e.y+i*(s.y-e.y)})}function Nn(t,e,s,n){if(i(t,e,s,n))return 0;const o={x:t.x,y:t.y},a={x:e.x,y:e.y},r={x:s.x,y:s.y},h={x:n.x,y:n.y};return Math.min(bn(o,r,h),bn(a,r,h),bn(r,o,a),bn(h,o,a))}var In=class{segmentBuckets;viaBuckets;routes;CELL_SIZE;constructor(t,e=1){this.segmentBuckets=new Map,this.viaBuckets=new Map,this.routes=new Map,this.CELL_SIZE=e;for(const e of t)if(e&&e.connectionName)if(this.routes.has(e.connectionName))console.warn(`Skipping duplicate route connectionName: ${e.connectionName}`);else{if(this.routes.set(e.connectionName,e),e.route&&e.route.length>=2)for(let t=0;t<e.route.length-1;t++){const s=e.route[t],n=e.route[t+1];if(s.x===n.x&&s.y===n.y)continue;const i=[s,n],o=vn(i),a={segmentId:`${e.connectionName}-seg-${t}`,segment:i,parentRoute:e},r=Math.floor(o.minX/this.CELL_SIZE),h=Math.floor((o.maxX+1e-9)/this.CELL_SIZE),c=Math.floor(o.minY/this.CELL_SIZE),d=Math.floor((o.maxY+1e-9)/this.CELL_SIZE);for(let t=r;t<=h;t++)for(let e=c;e<=d;e++){const s=`${t}x${e}`;let n=this.segmentBuckets.get(s);n||(n=[],this.segmentBuckets.set(s,n)),n.push(a)}}if(e.vias&&e.vias.length>0)for(let t=0;t<e.vias.length;t++){const s=e.vias[t];if(null==s)continue;const n={viaId:`${e.connectionName}-via-${t}`,x:s.x,y:s.y,parentRoute:e},i=`${Math.floor(s.x/this.CELL_SIZE)}x${Math.floor(s.y/this.CELL_SIZE)}`;let o=this.viaBuckets.get(i);o||(o=[],this.viaBuckets.set(i,o)),o.push(n)}}else console.warn("Skipping route with missing data:",e)}getConflictingRoutesForSegment(t,e,s){const n=vn([t,e]),i=n.minX-s,o=n.minY-s,a=n.maxX+s,r=n.maxY+s,h=Math.floor(i/this.CELL_SIZE),c=Math.floor((a+1e-9)/this.CELL_SIZE),d=Math.floor(o/this.CELL_SIZE),l=Math.floor((r+1e-9)/this.CELL_SIZE),u=new Map,p=new Set,f=new Set,m={x:t.x,y:t.y},g={x:e.x,y:e.y};for(let n=h;n<=c;n++)for(let i=d;i<=l;i++){const o=`${n}x${i}`,a=this.segmentBuckets.get(o);if(a)for(const n of a){if(p.has(n.segmentId))continue;p.add(n.segmentId);const i=n.parentRoute,[o,a]=n.segment,r=s+i.traceThickness/2,h=r*r,c=Nn(t,e,o,a);if(c<h){const t=i.connectionName,e=u.get(t);(!e||c<e.minDistSq)&&u.set(t,{route:i,minDistSq:c})}}const r=this.viaBuckets.get(o);if(r)for(const t of r){if(f.has(t.viaId))continue;f.add(t.viaId);const e=t.parentRoute,n={x:t.x,y:t.y},i=s+e.viaDiameter/2,o=i*i,a=bn(n,m,g);if(a<o){const t=e.connectionName,s=u.get(t);(!s||a<s.minDistSq)&&u.set(t,{route:e,minDistSq:a})}}}const y=[];for(const t of u.values())y.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return y}getConflictingRoutesNearPoint(t,e){const s=t.x-e,n=t.y-e,i=t.x+e,o=t.y+e,a=Math.floor(s/this.CELL_SIZE),r=Math.floor((i+1e-9)/this.CELL_SIZE),h=Math.floor(n/this.CELL_SIZE),c=Math.floor((o+1e-9)/this.CELL_SIZE),d=new Map,l=new Set,u=new Set;for(let s=a;s<=r;s++)for(let n=h;n<=c;n++){const i=`${s}x${n}`,o=this.segmentBuckets.get(i);if(o)for(const s of o){if(l.has(s.segmentId))continue;l.add(s.segmentId);const n=s.parentRoute,i={x:s.segment[0].x,y:s.segment[0].y},o={x:s.segment[1].x,y:s.segment[1].y},a=e+n.traceThickness/2,r=a*a,h=bn(t,i,o);if(h<r){const t=n.connectionName,e=d.get(t);(!e||h<e.minDistSq)&&d.set(t,{route:n,minDistSq:h})}}const a=this.viaBuckets.get(i);if(a)for(const s of a){if(u.has(s.viaId))continue;u.add(s.viaId);const n=s.parentRoute,i={x:s.x,y:s.y},o=e+n.viaDiameter/2,a=o*o,r=Sn(t,i);if(r<a){const t=n.connectionName,e=d.get(t);(!e||r<e.minDistSq)&&d.set(t,{route:n,minDistSq:r})}}}const p=[];for(const t of d.values())p.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return p}},Pn=class extends e{obstacleSHI;hdRouteSHI;unsimplifiedRoute;routeSections;currentSectionIndex;TRACE_THICKNESS=.15;OBSTACLE_MARGIN=.1;constructor(t){super(),this.currentSectionIndex=1,this.obstacleSHI=t.obstacleSHI,this.hdRouteSHI=t.hdRouteSHI,this.unsimplifiedRoute=t.unsimplifiedRoute,this.routeSections=this.breakRouteIntoSections(this.unsimplifiedRoute)}breakRouteIntoSections(t){const e=[],s=t.route;if(0===s.length)return[];let n={startIndex:0,endIndex:-1,z:s[0].z,points:[s[0]]};for(let t=1;t<s.length;t++)s[t].z===n.z?n.points.push(s[t]):(n.endIndex=t-1,e.push(n),n={startIndex:t,endIndex:-1,z:s[t].z,points:[s[t]]});return n.endIndex=s.length-1,e.push(n),e}_step(){if(this.currentSectionIndex>=this.routeSections.length-1)return void(this.solved=!0);const t=this.routeSections[this.currentSectionIndex-1],e=this.routeSections[this.currentSectionIndex],s=this.routeSections[this.currentSectionIndex+1];if(t.z!==s.z)return void this.currentSectionIndex++;const n=t.z;if(this.canSectionMoveToLayer({currentSection:e,targetZ:n}))return e.z=n,e.points=e.points.map(t=>({...t,z:n})),void(this.currentSectionIndex+=2);this.currentSectionIndex++}canSectionMoveToLayer({currentSection:t,targetZ:e}){for(let s=0;s<t.points.length-1;s++){const n={...t.points[s],z:e},i={...t.points[s+1],z:e},o=this.hdRouteSHI.getConflictingRoutesForSegment(n,i,this.TRACE_THICKNESS);for(const{conflictingRoute:t,distance:e}of o)if(t.connectionName!==this.unsimplifiedRoute.connectionName&&e<this.TRACE_THICKNESS+t.traceThickness)return!1;const a={centerX:(n.x+i.x)/2,centerY:(n.y+i.y)/2,width:Math.abs(n.x-i.x),height:Math.abs(n.y-i.y)},r=this.obstacleSHI.searchArea(a.centerX,a.centerY,a.width+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN),a.height+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN));for(const t of r){if(v(n,i,t)<this.TRACE_THICKNESS+this.OBSTACLE_MARGIN)return!1}}return!0}getConstructorParams(){return{obstacleSHI:this.obstacleSHI,hdRouteSHI:this.hdRouteSHI,unsimplifiedRoute:this.unsimplifiedRoute}}getOptimizedHdRoute(){const t=this.routeSections.flatMap(t=>t.points),e=[];for(let s=0;s<t.length-1;s++)t[s].z!==t[s+1].z&&e.push({x:t[s].x,y:t[s].y});return{connectionName:this.unsimplifiedRoute.connectionName,route:t,traceThickness:this.unsimplifiedRoute.traceThickness,vias:e,viaDiameter:this.unsimplifiedRoute.viaDiameter}}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Single Route Useless Via Removal Solver"};for(let e=0;e<this.routeSections.length;e++){const s=this.routeSections[e];t.lines.push({points:s.points,strokeWidth:this.TRACE_THICKNESS,strokeColor:e===this.currentSectionIndex?"orange":0===s.z?"red":"blue"})}return t}},Cn=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 kt("flatbush",t.obstacles),this.hdRouteSHI=new In(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 Pn({hdRouteSHI:this.hdRouteSHI,obstacleSHI:this.obstacleSHI,unsimplifiedRoute:t}):this.solved=!0}getOptimizedHdRoutes(){return this.optimizedHdRoutes}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Useless Via Removal Solver"};for(const e of this.input.obstacles){let s="rgba(128, 128, 128, 0.2)";const n=e.zLayers?.includes(0),i=e.zLayers?.includes(1);n&&i?s="rgba(128, 0, 128, 0.2)":n?s="rgba(255, 0, 0, 0.2)":i&&(s="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:s,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.optimizedHdRoutes){if(0===e.route.length)continue;this.input.colorMap[e.connectionName];for(let s=0;s<e.route.length-1;s++){const n=e.route[s],i=e.route[s+1];n.z===i.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:i.x,y:i.y}],strokeColor:0===n.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${n.z})`})}for(const s of e.vias)t.circles.push({center:{x:s.x,y:s.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`})}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}};function _n(t,e,s,n={}){return{solverName:t,solverClass:e,getConstructorParams:s,onSolved:n.onSolved}}var Tn=class extends e{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,void 0===e.capacityDepth){const s=t.bounds.maxX-t.bounds.minX,n=t.bounds.maxY-t.bounds.minY,i=Math.max(s,n),o=e.targetMinCapacity??.5;e.capacityDepth=ut(i,o)}this.connMap=os(t),this.colorMap=ht(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ne():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;uselessViaRemovalSolver1;uselessViaRemovalSolver2;multiSimplifiedPathSolver1;multiSimplifiedPathSolver2;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[_n("netToPointPairsSolver",cs,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ht(t.srjWithPointPairs,this.connMap),t.connMap=os(t.srjWithPointPairs)}}),_n("nodeSolver",Zt,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),_n("singleLayerNodeMerger",tn,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),_n("strawSolver",qs,t=>[{nodes:t.singleLayerNodeMerger?.newNodes}],{onSolved:t=>{t.capacityNodes=t.strawSolver?.getResultNodes()}}),_n("edgeSolver",xn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),_n("deadEndSolver",Mn,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)))}}),_n("initialPathingSolver",Ds,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),_n("pathingOptimizer",Gs,t=>[{initialPathingSolver:t.initialPathingSolver,simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,cacheProvider:t.cacheProvider,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),_n("edgeToPortSegmentSolver",Vt,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.pathingOptimizer?.getCapacityPaths()||[],colorMap:t.colorMap}]),_n("segmentToPointSolver",Kt,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),_n("unravelMultiSectionSolver",zs,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),_n("highDensityRouteSolver",ns,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap}]),_n("highDensityStitchSolver",ps,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),_n("uselessViaRemovalSolver1",Cn,t=>[{unsimplifiedHdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),_n("multiSimplifiedPathSolver1",gn,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver1?.getOptimizedHdRoutes()||t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}]),_n("uselessViaRemovalSolver2",Cn,t=>[{unsimplifiedHdRoutes:t.multiSimplifiedPathSolver1.simplifiedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),_n("multiSimplifiedPathSolver2",gn,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver2?.getOptimizedHdRoutes(),obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}])];currentPipelineStepIndex=0;_step(){const t=this.pipelineDef[this.currentPipelineStepIndex];if(!t)return void(this.solved=!0);if(this.activeSubSolver)return this.activeSubSolver.step(),void(this.activeSubSolver.solved?(this.endTimeOfPhase[t.solverName]=performance.now(),this.timeSpentOnPhase[t.solverName]=this.endTimeOfPhase[t.solverName]-this.startTimeOfPhase[t.solverName],t.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStepIndex++):this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null));const e=t.getConstructorParams(this);this.activeSubSolver=new t.solverClass(...e),this[t.solverName]=this.activeSubSolver,this.timeSpentOnPhase[t.solverName]=0,this.startTimeOfPhase[t.solverName]=performance.now()}solveUntilPhase(t){for(;this.getCurrentPhase()!==t;)this.step()}getCurrentPhase(){return this.pipelineDef[this.currentPipelineStepIndex]?.solverName??"none"}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();const e=this.netToPointPairsSolver?.visualize(),s=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),i=this.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(),m=this.uselessViaRemovalSolver1?.visualize(),g=this.uselessViaRemovalSolver2?.visualize(),y=this.multiSimplifiedPathSolver1?.visualize(),x=this.multiSimplifiedPathSolver2?.visualize(),M=this.srj.outline,v=[];if(v.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]}),v.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const S={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:v},b=[S,e,s,n,i,o,a,r,h,c,d,l,u,p?t(S,p):null,f,m,y,g,x,this.solved?t(S,fs(this.getOutputSimpleRouteJson())):null].filter(Boolean);return t(...b)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const s=this.highDensityRouteSolver.routes[e];if(t.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[s.connectionName]}),t.length>200)break}return{lines:t}}if(this.pathingOptimizer){const t=[];for(const e of this.pathingOptimizer.connectionsWithNodes)e.path&&t.push({points:e.path.map(t=>({x:t.center.x,y:t.center.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}getOriginalConnectionName(t){const e=t.match(/^(.+?)_mst\d+$/);return e?e[1]:t}_getOutputHdRoutes(){return this.multiSimplifiedPathSolver2?.simplifiedHdRoutes??this.uselessViaRemovalSolver2?.getOptimizedHdRoutes()??this.multiSimplifiedPathSolver1?.simplifiedHdRoutes??this.uselessViaRemovalSolver1?.getOptimizedHdRoutes()??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const s of this.netToPointPairsSolver?.newConnections??[]){const n=this.srj.connections.find(t=>t.name===s.name)?.netConnectionName,i=e.filter(t=>t.connectionName===s.name);for(let e=0;e<i.length;e++){const o=i[e],a={type:"pcb_trace",pcb_trace_id:`${s.name}_${e}`,connection_name:n??this.getOriginalConnectionName(s.name),route:ls(o,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},En=Tn;export{Tn as AutoroutingPipelineSolver,En as CapacityMeshSolver,Qt as InMemoryCache,ee as LocalStorageCache,ut as calculateOptimalCapacityDepth,fs as convertSrjToGraphicsObject,ne as getGlobalInMemoryCache,se as getGlobalLocalStorageCache,lt as getTunedTotalCapacity1,ie as setupGlobalCaches};//# sourceMappingURL=index.js.map