@tscircuit/capacity-autorouter 0.0.255 → 0.0.256
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 +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var t=Object.create,e=Object.defineProperty,n=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,o=Object.getPrototypeOf,i=Object.prototype.hasOwnProperty,r=(t,e)=>function(){return e||(0,t[s(t)[0]])((e={exports:{}}).exports,e),e.exports},a=(r,a,c)=>(c=null!=r?t(o(r)):{},((t,o,r,a)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let c of s(o))i.call(t,c)||c===r||e(t,c,{get:()=>o[c],enumerable:!(a=n(o,c))||a.enumerable});return t})(!a&&r&&r.__esModule?c:e(c,"default",{value:r,enumerable:!0}),r)),c=r({"node_modules/is-buffer/index.js"(t,e){function n(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}e.exports=function(t){return null!=t&&(n(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&n(t.slice(0,0))}(t)||!!t._isBuffer)}}}),h=r({"node_modules/kind-of/index.js"(t,e){var n=c(),s=Object.prototype.toString;e.exports=function(t){if(void 0===t)return"undefined";if(null===t)return"null";if(!0===t||!1===t||t instanceof Boolean)return"boolean";if("string"==typeof t||t instanceof String)return"string";if("number"==typeof t||t instanceof Number)return"number";if("function"==typeof t||t instanceof Function)return"function";if(void 0!==Array.isArray&&Array.isArray(t))return"array";if(t instanceof RegExp)return"regexp";if(t instanceof Date)return"date";var e=s.call(t);return"[object RegExp]"===e?"regexp":"[object Date]"===e?"date":"[object Arguments]"===e?"arguments":"[object Error]"===e?"error":n(t)?"buffer":"[object Set]"===e?"set":"[object WeakSet]"===e?"weakset":"[object Map]"===e?"map":"[object WeakMap]"===e?"weakmap":"[object Symbol]"===e?"symbol":"[object Int8Array]"===e?"int8array":"[object Uint8Array]"===e?"uint8array":"[object Uint8ClampedArray]"===e?"uint8clampedarray":"[object Int16Array]"===e?"int16array":"[object Uint16Array]"===e?"uint16array":"[object Int32Array]"===e?"int32array":"[object Uint32Array]"===e?"uint32array":"[object Float32Array]"===e?"float32array":"[object Float64Array]"===e?"float64array":"object"}}}),d=r({"node_modules/rename-keys/index.js"(t,e){!function(){function t(t,e){if("function"!=typeof e)return t;var n={};for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&(n[e(s,t[s])||s]=t[s]);return n}void 0!==e&&e.exports?e.exports=t:"function"==typeof define&&define.amd?define([],function(){return t}):window.rename=t}()}}),l=r({"node_modules/deep-rename-keys/index.js"(t,e){var n=h(),s=d();e.exports=function t(e,o){var i=n(e);if("object"!==i&&"array"!==i)throw new Error("expected an object");var r=[];for(var a in"object"===i&&(e=s(e,o),r={}),e)if(e.hasOwnProperty(a)){var c=e[a];"object"===n(c)||"array"===n(c)?r[a]=t(c,o):r[a]=c}return r}}}),u=r({"node_modules/xml-reader/node_modules/eventemitter3/index.js"(t,e){var n=Object.prototype.hasOwnProperty,s="~";function o(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new o,this._eventsCount=0}Object.create&&(o.prototype=Object.create(null),(new o).__proto__||(s=!1)),r.prototype.eventNames=function(){var t,e,o=[];if(0===this._eventsCount)return o;for(e in t=this._events)n.call(t,e)&&o.push(s?e.slice(1):e);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(t)):o},r.prototype.listeners=function(t,e){var n=s?s+t:t,o=this._events[n];if(e)return!!o;if(!o)return[];if(o.fn)return[o.fn];for(var i=0,r=o.length,a=new Array(r);i<r;i++)a[i]=o[i].fn;return a},r.prototype.emit=function(t,e,n,o,i,r){var a=s?s+t:t;if(!this._events[a])return!1;var c,h,d=this._events[a],l=arguments.length;if(d.fn){switch(d.once&&this.removeListener(t,d.fn,void 0,!0),l){case 1:return d.fn.call(d.context),!0;case 2:return d.fn.call(d.context,e),!0;case 3:return d.fn.call(d.context,e,n),!0;case 4:return d.fn.call(d.context,e,n,o),!0;case 5:return d.fn.call(d.context,e,n,o,i),!0;case 6:return d.fn.call(d.context,e,n,o,i,r),!0}for(h=1,c=new Array(l-1);h<l;h++)c[h-1]=arguments[h];d.fn.apply(d.context,c)}else{var u,p=d.length;for(h=0;h<p;h++)switch(d[h].once&&this.removeListener(t,d[h].fn,void 0,!0),l){case 1:d[h].fn.call(d[h].context);break;case 2:d[h].fn.call(d[h].context,e);break;case 3:d[h].fn.call(d[h].context,e,n);break;case 4:d[h].fn.call(d[h].context,e,n,o);break;default:if(!c)for(u=1,c=new Array(l-1);u<l;u++)c[u-1]=arguments[u];d[h].fn.apply(d[h].context,c)}}return!0},r.prototype.on=function(t,e,n){var o=new i(e,n||this),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.once=function(t,e,n){var o=new i(e,n||this,!0),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=s?s+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new o:delete this._events[r],this;var a=this._events[r];if(a.fn)a.fn!==e||i&&!a.once||n&&a.context!==n||(0===--this._eventsCount?this._events=new o:delete this._events[r]);else{for(var c=0,h=[],d=a.length;c<d;c++)(a[c].fn!==e||i&&!a[c].once||n&&a[c].context!==n)&&h.push(a[c]);h.length?this._events[r]=1===h.length?h[0]:h:0===--this._eventsCount?this._events=new o:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=s?s+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new o:delete this._events[e])):(this._events=new o,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=s,r.EventEmitter=r,void 0!==e&&(e.exports=r)}}),p=r({"node_modules/xml-lexer/node_modules/eventemitter3/index.js"(t,e){var n=Object.prototype.hasOwnProperty,s="~";function o(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new o,this._eventsCount=0}Object.create&&(o.prototype=Object.create(null),(new o).__proto__||(s=!1)),r.prototype.eventNames=function(){var t,e,o=[];if(0===this._eventsCount)return o;for(e in t=this._events)n.call(t,e)&&o.push(s?e.slice(1):e);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(t)):o},r.prototype.listeners=function(t,e){var n=s?s+t:t,o=this._events[n];if(e)return!!o;if(!o)return[];if(o.fn)return[o.fn];for(var i=0,r=o.length,a=new Array(r);i<r;i++)a[i]=o[i].fn;return a},r.prototype.emit=function(t,e,n,o,i,r){var a=s?s+t:t;if(!this._events[a])return!1;var c,h,d=this._events[a],l=arguments.length;if(d.fn){switch(d.once&&this.removeListener(t,d.fn,void 0,!0),l){case 1:return d.fn.call(d.context),!0;case 2:return d.fn.call(d.context,e),!0;case 3:return d.fn.call(d.context,e,n),!0;case 4:return d.fn.call(d.context,e,n,o),!0;case 5:return d.fn.call(d.context,e,n,o,i),!0;case 6:return d.fn.call(d.context,e,n,o,i,r),!0}for(h=1,c=new Array(l-1);h<l;h++)c[h-1]=arguments[h];d.fn.apply(d.context,c)}else{var u,p=d.length;for(h=0;h<p;h++)switch(d[h].once&&this.removeListener(t,d[h].fn,void 0,!0),l){case 1:d[h].fn.call(d[h].context);break;case 2:d[h].fn.call(d[h].context,e);break;case 3:d[h].fn.call(d[h].context,e,n);break;case 4:d[h].fn.call(d[h].context,e,n,o);break;default:if(!c)for(u=1,c=new Array(l-1);u<l;u++)c[u-1]=arguments[u];d[h].fn.apply(d[h].context,c)}}return!0},r.prototype.on=function(t,e,n){var o=new i(e,n||this),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.once=function(t,e,n){var o=new i(e,n||this,!0),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=s?s+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new o:delete this._events[r],this;var a=this._events[r];if(a.fn)a.fn!==e||i&&!a.once||n&&a.context!==n||(0===--this._eventsCount?this._events=new o:delete this._events[r]);else{for(var c=0,h=[],d=a.length;c<d;c++)(a[c].fn!==e||i&&!a[c].once||n&&a[c].context!==n)&&h.push(a[c]);h.length?this._events[r]=1===h.length?h[0]:h:0===--this._eventsCount?this._events=new o:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=s?s+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new o:delete this._events[e])):(this._events=new o,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=s,r.EventEmitter=r,void 0!==e&&(e.exports=r)}}),m=r({"node_modules/xml-lexer/dist/lexer.js"(t,e){function n(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var s=p(),o=function(){},i={data:"state-data",cdata:"state-cdata",tagBegin:"state-tag-begin",tagName:"state-tag-name",tagEnd:"state-tag-end",attributeNameStart:"state-attribute-name-start",attributeName:"state-attribute-name",attributeNameEnd:"state-attribute-name-end",attributeValueBegin:"state-attribute-value-begin",attributeValue:"state-attribute-value"},r={lt:"action-lt",gt:"action-gt",space:"action-space",equal:"action-equal",quote:"action-quote",slash:"action-slash",char:"action-char",error:"action-error"},a={text:"text",openTag:"open-tag",closeTag:"close-tag",attributeName:"attribute-name",attributeValue:"attribute-value"},c={" ":r.space,"\t":r.space,"\n":r.space,"\r":r.space,"<":r.lt,">":r.gt,'"':r.quote,"'":r.quote,"=":r.equal,"/":r.slash};e.exports={State:i,Action:r,Type:a,create:function(t){var e,h,d,l,u,p,m,f,g,y;t=Object.assign({debug:!1},t);var x=new s,v=i.data,S="",P="",b="",M="",N="",I="",C=function(e,n){if("?"!==P[0]&&"!"!==P[0]){var s={type:e,value:n};t.debug&&console.log("emit:",s),x.emit("data",s)}};x.stateMachine=(n(y={},i.data,(n(e={},r.lt,function(){S.trim()&&C(a.text,S),P="",N=!1,v=i.tagBegin}),n(e,r.char,function(t){S+=t}),e)),n(y,i.cdata,n({},r.char,function(t){"]]>"===(S+=t).substr(-3)&&(C(a.text,S.slice(0,-3)),S="",v=i.data)})),n(y,i.tagBegin,(n(h={},r.space,o),n(h,r.char,function(t){P=t,v=i.tagName}),n(h,r.slash,function(){P="",N=!0}),h)),n(y,i.tagName,(n(d={},r.space,function(){N?v=i.tagEnd:(v=i.attributeNameStart,C(a.openTag,P))}),n(d,r.gt,function(){C(N?a.closeTag:a.openTag,P),S="",v=i.data}),n(d,r.slash,function(){v=i.tagEnd,C(a.openTag,P)}),n(d,r.char,function(t){"![CDATA["===(P+=t)&&(v=i.cdata,S="",P="")}),d)),n(y,i.tagEnd,(n(l={},r.gt,function(){C(a.closeTag,P),S="",v=i.data}),n(l,r.char,o),l)),n(y,i.attributeNameStart,(n(u={},r.char,function(t){b=t,v=i.attributeName}),n(u,r.gt,function(){S="",v=i.data}),n(u,r.space,o),n(u,r.slash,function(){N=!0,v=i.tagEnd}),u)),n(y,i.attributeName,(n(p={},r.space,function(){v=i.attributeNameEnd}),n(p,r.equal,function(){C(a.attributeName,b),v=i.attributeValueBegin}),n(p,r.gt,function(){M="",C(a.attributeName,b),C(a.attributeValue,M),S="",v=i.data}),n(p,r.slash,function(){N=!0,M="",C(a.attributeName,b),C(a.attributeValue,M),v=i.tagEnd}),n(p,r.char,function(t){b+=t}),p)),n(y,i.attributeNameEnd,(n(m={},r.space,o),n(m,r.equal,function(){C(a.attributeName,b),v=i.attributeValueBegin}),n(m,r.gt,function(){M="",C(a.attributeName,b),C(a.attributeValue,M),S="",v=i.data}),n(m,r.char,function(t){M="",C(a.attributeName,b),C(a.attributeValue,M),b=t,v=i.attributeName}),m)),n(y,i.attributeValueBegin,(n(f={},r.space,o),n(f,r.quote,function(t){I=t,M="",v=i.attributeValue}),n(f,r.gt,function(){C(a.attributeValue,M=""),S="",v=i.data}),n(f,r.char,function(t){I="",M=t,v=i.attributeValue}),f)),n(y,i.attributeValue,(n(g={},r.space,function(t){I?M+=t:(C(a.attributeValue,M),v=i.attributeNameStart)}),n(g,r.quote,function(t){I===t?(C(a.attributeValue,M),v=i.attributeNameStart):M+=t}),n(g,r.gt,function(t){I?M+=t:(C(a.attributeValue,M),S="",v=i.data)}),n(g,r.slash,function(t){I?M+=t:(C(a.attributeValue,M),N=!0,v=i.tagEnd)}),n(g,r.char,function(t){M+=t}),g)),y);var _=function(e){t.debug&&console.log(v,e);var n=x.stateMachine[v],s=n[function(t){return c[t]||r.char}(e)]||n[r.error]||n[r.char];s(e)};return x.write=function(t){for(var e=t.length,n=0;n<e;n++)_(t[n])},x}}}}),f=r({"node_modules/xml-reader/dist/reader.js"(t,e){var n=u(),s=m(),o=s.Type,i={element:"element",text:"text"},r=function(t){return Object.assign({name:"",type:i.element,value:"",parent:null,attributes:{},children:[]},t)},a=function(t){t=Object.assign({stream:!1,parentNodes:!0,doneEvent:"done",tagPrefix:"tag:",emitTopLevelOnly:!1,debug:!1},t);var e=void 0,a=void 0,c=void 0,h=void 0,d=new n,l=function(n){switch(n.type){case o.openTag:if(null===c)(c=a).name=n.value;else{var s=r({name:n.value,parent:c});c.children.push(s),c=s}break;case o.closeTag:var l=c.parent;if(t.parentNodes||(c.parent=null),c.name!==n.value)break;t.stream&&l===a&&(a.children=[],c.parent=null),t.emitTopLevelOnly&&l!==a||(d.emit(t.tagPrefix+c.name,c),d.emit("tag",c.name,c)),c===a&&(e.removeAllListeners("data"),d.emit(t.doneEvent,c),a=null),c=l;break;case o.text:c&&c.children.push(r({type:i.text,value:n.value,parent:t.parentNodes?c:null}));break;case o.attributeName:h=n.value,c.attributes[h]="";break;case o.attributeValue:c.attributes[h]=n.value}};return d.reset=function(){(e=s.create({debug:t.debug})).on("data",l),a=r(),c=null,h="",d.parse=e.write},d.reset(),d};e.exports={parseSync:function(t,e){e=Object.assign({},e,{stream:!1,tagPrefix:":"});var n=a(e),s=void 0;return n.on("done",function(t){s=t}),n.parse(t),s},create:a,NodeType:i}}}),g=(...t)=>{const e={points:[],lines:[],circles:[],rects:[]};return t.forEach((t,n)=>{t&&(t.lines&&(e.lines=[...e.lines||[],...t.lines.map(t=>({...t,step:n}))]),t.points&&(e.points=[...e.points||[],...t.points.map(t=>({...t,step:n}))]),t.circles&&(e.circles=[...e.circles||[],...t.circles.map(t=>({...t,step:n}))]),t.rects&&(e.rects=[...e.rects||[],...t.rects.map(t=>({...t,step:n}))]))}),e},y=class{MAX_ITERATIONS=1e3;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};cacheHit;cacheKey;cacheToSolveSpaceTransform;step(){if(!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,console.error(this.error),this.failed=!0,t}!this.solved&&this.iterations>this.MAX_ITERATIONS&&this.tryFinalAcceptance(),!this.solved&&this.iterations>this.MAX_ITERATIONS&&(this.error=`${this.constructor.name} ran out of iterations (MAX_ITERATIONS=${this.MAX_ITERATIONS})`,this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}};function x(){return x=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var s in n)({}).hasOwnProperty.call(n,s)&&(t[s]=n[s])}return t},x.apply(null,arguments)}function v(t,e){return(v=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t})(t,e)}function S(t){return(S=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 b(t){var e="function"==typeof Map?new Map:void 0;return b=function(t){if(null===t||!function(t){try{return-1!==Function.toString.call(t).indexOf("[native code]")}catch(e){return"function"==typeof t}}(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,n)}function n(){return function(t,e,n){if(P())return Reflect.construct.apply(null,arguments);var s=[null];s.push.apply(s,e);var o=new(t.bind.apply(t,s));return n&&v(o,n.prototype),o}(t,arguments,S(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),v(n,t)},b(t)}var M={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 N(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];var s,o=e[0],i=[];for(s=1;s<e.length;s+=1)i.push(e[s]);return i.forEach(function(t){o=o.replace(/%[a-z]/,t)}),o}var I=function(t){var e,n;function s(e){var n;if("production"===process.env.NODE_ENV)n=t.call(this,"An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#"+e+" for more information.")||this;else{for(var s=arguments.length,o=new Array(s>1?s-1:0),i=1;i<s;i++)o[i-1]=arguments[i];n=t.call(this,N.apply(void 0,[M[e]].concat(o)))||this}return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(n)}return n=t,(e=s).prototype=Object.create(n.prototype),e.prototype.constructor=e,v(e,n),s}(b(Error));function C(t,e){return t.substr(-e.length)===e}var _=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;function T(t){return"string"!=typeof t?t:t.match(_)?parseFloat(t):t}var E=function(t){return function(e,n){void 0===n&&(n="16px");var s=e,o=n;if("string"==typeof e){if(!C(e,"px"))throw new I(69,t,e);s=T(e)}if("string"==typeof n){if(!C(n,"px"))throw new I(70,t,n);o=T(n)}if("string"==typeof s)throw new I(71,e,t);if("string"==typeof o)throw new I(72,n,t);return""+s/o+t}};E("em"),E("rem");function R(t){return Math.round(255*t)}function w(t,e,n){return R(t)+","+R(e)+","+R(n)}function A(t,e,n,s){if(void 0===s&&(s=w),0===e)return s(n,n,n);var o=(t%360+360)%360/60,i=(1-Math.abs(2*n-1))*e,r=i*(1-Math.abs(o%2-1)),a=0,c=0,h=0;o>=0&&o<1?(a=i,c=r):o>=1&&o<2?(a=r,c=i):o>=2&&o<3?(c=i,h=r):o>=3&&o<4?(c=r,h=i):o>=4&&o<5?(a=r,h=i):o>=5&&o<6&&(a=i,h=r);var d=n-i/2;return s(a+d,c+d,h+d)}var O={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 z=/^#[a-fA-F0-9]{6}$/,D=/^#[a-fA-F0-9]{8}$/,L=/^#[a-fA-F0-9]{3}$/,F=/^#[a-fA-F0-9]{4}$/,X=/^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i,Y=/^rgb(?:a)?\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i,$=/^hsl\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*\)$/i,k=/^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 B(t){if("string"!=typeof t)throw new I(3);var e=function(t){if("string"!=typeof t)return t;var e=t.toLowerCase();return O[e]?"#"+O[e]:t}(t);if(e.match(z))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(D)){var n=parseFloat((parseInt(""+e[7]+e[8],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[2],16),green:parseInt(""+e[3]+e[4],16),blue:parseInt(""+e[5]+e[6],16),alpha:n}}if(e.match(L))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(F)){var s=parseFloat((parseInt(""+e[4]+e[4],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[1],16),green:parseInt(""+e[2]+e[2],16),blue:parseInt(""+e[3]+e[3],16),alpha:s}}var o=X.exec(e);if(o)return{red:parseInt(""+o[1],10),green:parseInt(""+o[2],10),blue:parseInt(""+o[3],10)};var i=Y.exec(e.substring(0,50));if(i)return{red:parseInt(""+i[1],10),green:parseInt(""+i[2],10),blue:parseInt(""+i[3],10),alpha:parseFloat(""+i[4])>1?parseFloat(""+i[4])/100:parseFloat(""+i[4])};var r=$.exec(e);if(r){var a="rgb("+A(parseInt(""+r[1],10),parseInt(""+r[2],10)/100,parseInt(""+r[3],10)/100)+")",c=X.exec(a);if(!c)throw new I(4,e,a);return{red:parseInt(""+c[1],10),green:parseInt(""+c[2],10),blue:parseInt(""+c[3],10)}}var h=k.exec(e.substring(0,50));if(h){var d="rgb("+A(parseInt(""+h[1],10),parseInt(""+h[2],10)/100,parseInt(""+h[3],10)/100)+")",l=X.exec(d);if(!l)throw new I(4,e,d);return{red:parseInt(""+l[1],10),green:parseInt(""+l[2],10),blue:parseInt(""+l[3],10),alpha:parseFloat(""+h[4])>1?parseFloat(""+h[4])/100:parseFloat(""+h[4])}}throw new I(5)}function j(t){return function(t){var e,n=t.red/255,s=t.green/255,o=t.blue/255,i=Math.max(n,s,o),r=Math.min(n,s,o),a=(i+r)/2;if(i===r)return void 0!==t.alpha?{hue:0,saturation:0,lightness:a,alpha:t.alpha}:{hue:0,saturation:0,lightness:a};var c=i-r,h=a>.5?c/(2-i-r):c/(i+r);switch(i){case n:e=(s-o)/c+(s<o?6:0);break;case s:e=(o-n)/c+2;break;default:e=(n-s)/c+4}return e*=60,void 0!==t.alpha?{hue:e,saturation:h,lightness:a,alpha:t.alpha}:{hue:e,saturation:h,lightness:a}}(B(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 H(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function U(t){return H(Math.round(255*t))}function V(t,e,n){return W("#"+U(t)+U(e)+U(n))}function Z(t,e,n){return A(t,e,n,V)}function G(t,e,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n)return W("#"+H(t)+H(e)+H(n));if("object"==typeof t&&void 0===e&&void 0===n)return W("#"+H(t.red)+H(t.green)+H(t.blue));throw new I(6)}function J(t,e,n,s){if("string"==typeof t&&"number"==typeof e){var o=B(t);return"rgba("+o.red+","+o.green+","+o.blue+","+e+")"}if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof s)return s>=1?G(t,e,n):"rgba("+t+","+e+","+n+","+s+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===s)return t.alpha>=1?G(t.red,t.green,t.blue):"rgba("+t.red+","+t.green+","+t.blue+","+t.alpha+")";throw new I(7)}function q(t){if("object"!=typeof t)throw new I(8);if(function(t){return"number"==typeof t.red&&"number"==typeof t.green&&"number"==typeof t.blue&&"number"==typeof t.alpha}(t))return J(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 G(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&"number"==typeof t.alpha}(t))return function(t,e,n,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof s)return s>=1?Z(t,e,n):"rgba("+A(t,e,n)+","+s+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===s)return t.alpha>=1?Z(t.hue,t.saturation,t.lightness):"rgba("+A(t.hue,t.saturation,t.lightness)+","+t.alpha+")";throw new I(2)}(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&("number"!=typeof t.alpha||void 0===t.alpha)}(t))return function(t,e,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n)return Z(t,e,n);if("object"==typeof t&&void 0===e&&void 0===n)return Z(t.hue,t.saturation,t.lightness);throw new I(1)}(t);throw new I(8)}function K(t,e,n){return function(){var s=n.concat(Array.prototype.slice.call(arguments));return s.length>=e?t.apply(this,s):K(t,e,s)}}function Q(t){return K(t,t.length,[])}Q(function(t,e){if("transparent"===e)return e;var n=j(e);return q(x({},n,{hue:n.hue+parseFloat(t)}))});function tt(t,e,n){return Math.max(t,Math.min(e,n))}Q(function(t,e){if("transparent"===e)return e;var n=j(e);return q(x({},n,{lightness:tt(0,1,n.lightness-parseFloat(t))}))});Q(function(t,e){if("transparent"===e)return e;var n=j(e);return q(x({},n,{saturation:tt(0,1,n.saturation-parseFloat(t))}))});Q(function(t,e){if("transparent"===e)return e;var n=j(e);return q(x({},n,{lightness:tt(0,1,n.lightness+parseFloat(t))}))});var et=Q(function(t,e,n){if("transparent"===e)return n;if("transparent"===n)return e;if(0===t)return n;var s=B(e),o=x({},s,{alpha:"number"==typeof s.alpha?s.alpha:1}),i=B(n),r=x({},i,{alpha:"number"==typeof i.alpha?i.alpha:1}),a=o.alpha-r.alpha,c=2*parseFloat(t)-1,h=((c*a===-1?c:c+a)/(1+c*a)+1)/2,d=1-h;return J({red:Math.floor(o.red*h+r.red*d),green:Math.floor(o.green*h+r.green*d),blue:Math.floor(o.blue*h+r.blue*d),alpha:o.alpha*parseFloat(t)+r.alpha*(1-parseFloat(t))})});Q(function(t,e){if("transparent"===e)return e;var n=B(e);return J(x({},n,{alpha:tt(0,1,(100*("number"==typeof n.alpha?n.alpha:1)+100*parseFloat(t))/100)}))});Q(function(t,e){if("transparent"===e)return e;var n=j(e);return q(x({},n,{saturation:tt(0,1,n.saturation+parseFloat(t))}))});Q(function(t,e){return"transparent"===e?e:q(x({},j(e),{hue:parseFloat(t)}))});Q(function(t,e){return"transparent"===e?e:q(x({},j(e),{lightness:parseFloat(t)}))});Q(function(t,e){return"transparent"===e?e:q(x({},j(e),{saturation:parseFloat(t)}))});Q(function(t,e){return"transparent"===e?e:et(parseFloat(t),"rgb(0, 0, 0)",e)});Q(function(t,e){return"transparent"===e?e:et(parseFloat(t),"rgb(255, 255, 255)",e)});var nt=Q(function(t,e){if("transparent"===e)return e;var n=B(e);return J(x({},n,{alpha:tt(0,1,+(100*("number"==typeof n.alpha?n.alpha:1)-100*parseFloat(t)).toFixed(2)/100)}))}),st=["blue","orange","purple","cyan","magenta","yellowgreen","darkgoldenrod","deeppink"],ot=(t,e)=>{const n={};for(let s=0;s<t.connections.length;s++){const o=t.connections[s],i=e?.getNetConnectedToId(o.name);i&&!n[i]&&(n[i]=`hsl(${300*s/t.connections.length}, 100%, 50%)`),n[o.name]=(i?n[i]:null)??`hsl(${340*s/t.connections.length}, 100%, 50%)`}return n},it=(t,e)=>{try{return nt(e,t)}catch(e){return console.error(e),t}},rt=(t,e=1)=>{if(!t)return"rgba(0, 0, 0, 0.5)";const n=300*t.split("").reduce((t,e)=>t+e.charCodeAt(0),0)/t.length;return e<1?`hsla(${n}, 100%, 50%, ${e})`:`hsl(${n}, 100%, 50%)`};import at from"object-hash";var ct=class{cacheHitsByPrefix={};cacheMissesByPrefix={};isSyncCache=!0;cacheHits=0;cacheMisses=0;cache=new Map;getCachedSolutionSync(t){const e=this.cache.get(t);if(void 0!==e){this.cacheHits++;const n=t.split(":")[0];return this.cacheHitsByPrefix[n]=(this.cacheHitsByPrefix[n]||0)+1,structuredClone(e)}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){this.cache.set(t,structuredClone(e))}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){this.cache.clear(),this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}getAllCacheKeys(){return Array.from(this.cache.keys())}},ht="tscircuit_autorouter_cache_",dt=class{isSyncCache=!0;cacheHits=0;cacheMisses=0;cacheHitsByPrefix={};cacheMissesByPrefix={};constructor(){}getKey(t){return`${ht}${t}`}getCachedSolutionSync(t){if("undefined"==typeof localStorage)return;const e=this.getKey(t);try{const n=localStorage.getItem(e);if(null!==n){const e=JSON.parse(n);this.cacheHits++;const s=t.split(":")[0];return this.cacheHitsByPrefix[s]=(this.cacheHitsByPrefix[s]||0)+1,e}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}catch(n){console.error(`Error getting cached solution sync for ${e}:`,n),this.cacheMisses++;const s=t.split(":")[0];return void(this.cacheMissesByPrefix[s]=(this.cacheMissesByPrefix[s]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){if("undefined"==typeof localStorage)return;const n=this.getKey(t);try{const t=JSON.stringify(e);localStorage.setItem(n,t)}catch(t){console.error(`Error setting cached solution sync for ${n}:`,t),t instanceof DOMException&&("QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&console.warn(`LocalStorage quota exceeded. Failed to cache solution for ${n}. Consider clearing the cache.`)}}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){if("undefined"!=typeof localStorage)try{const t=[];for(let e=0;e<localStorage.length;e++){const n=localStorage.key(e);n?.startsWith(ht)&&t.push(n)}t.forEach(t=>localStorage.removeItem(t)),console.log(`Cleared ${t.length} items from LocalStorage cache.`)}catch(t){console.error("Error clearing LocalStorage cache:",t)}finally{this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}}getAllCacheKeys(){const t=[];for(let e=0;e<1e4;e++){const n=localStorage.key(e);if(!n)break;n.includes(ht)&&t.push(n)}return t}};function lt(){return globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE||pt(),globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE}function ut(){return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE||pt(),globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE}function pt(){globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE??=new dt,globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE??=new ct}function mt(t){const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-n,maxY:t.center.y+n}}function ft(t,e,n){return Math.max(e,Math.min(n,t))}function gt(t,e,n,s){const o=yt(t,e,n),i=yt(t,e,s),r=yt(n,s,t),a=yt(n,s,e);return o!==i&&r!==a||(!(0!==o||!xt(t,n,e))||(!(0!==i||!xt(t,s,e))||(!(0!==r||!xt(n,t,s))||!(0!==a||!xt(n,e,s)))))}function yt(t,e,n){const s=(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y);return 0===s?0:s>0?1:2}function xt(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function vt(t,e,n){const s=(n.x-e.x)**2+(n.y-e.y)**2;if(0===s)return St(t,e);let o=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/s;o=Math.max(0,Math.min(1,o));return St(t,{x:e.x+o*(n.x-e.x),y:e.y+o*(n.y-e.y)})}function St(t,e){const n=t.x-e.x,s=t.y-e.y;return Math.sqrt(n*n+s*s)}function Pt(t,e,n,s){const o=e.x-t.x,i=e.y-t.y,r=s.x-n.x,a=s.y-n.y,c=t.x-n.x,h=t.y-n.y,d=o*a-i*r;if(Math.abs(d)<1e-10)return null;const l=(h*r-c*a)/d,u=(o*h-i*c)/d,p=1e-9;if(l>=-1e-9&&l<=1+p&&u>=-1e-9&&u<=1+p){return{x:t.x+l*o,y:t.y+l*i}}return null}function bt(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var Mt=t=>{if("minX"in t)return t;const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,minY:t.center.y-n,maxX:t.center.x+e,maxY:t.center.y+n}},Nt=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}],It=t=>{const e=[];for(let n=0;n<t.length;n++){const s=t[n],o=t[(n+1)%t.length];e.push([s,o])}return e},Ct=(t,e,n)=>{const s=(t.y-e.y)*(n.x-e.x)-(t.x-e.x)*(n.y-e.y);if(Math.abs(s)>1e-9)return!1;const o=(t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y);if(o<0)return!1;return!(o>(n.x-e.x)**2+(n.y-e.y)**2)},_t=(t,e)=>{if(e.length<3)return!1;const n=It(e);for(const[e,s]of n)if(Ct(t,e,s))return!0;let s=!1;for(let n=0,o=e.length-1;n<e.length;o=n++){const i=e[n].x,r=e[n].y,a=e[o].x,c=e[o].y;r>t.y!=c>t.y&&t.x<(a-i)*(t.y-r)/(c-r)+i&&(s=!s)}return s},Tt=(t,e)=>{const n=Nt(t),s=[[n[0],n[1]],[n[1],n[2]],[n[2],n[3]],[n[3],n[0]]],o=It(e);for(const[t,e]of o)for(const[n,o]of s)if(gt(t,e,n,o))return!0;return!1},Et=(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))||(!!Nt(t).some(t=>_t(t,e))||Tt(t,e))))(Mt(t),e),Rt=(t,e)=>((t,e)=>!(e.length<3)&&(!!Nt(t).every(t=>_t(t,e))&&!Tt(t,e)))(Mt(t),e);function wt(t,e,n,s){if(t.x===e.x&&t.y===e.y)return vt(t,n,s);if(n.x===s.x&&n.y===s.y)return vt(n,t,e);if(gt(t,e,n,s))return 0;const o=[vt(t,n,s),vt(e,n,s),vt(n,t,e),vt(s,t,e)];return Math.min(...o)}function At(t,e,n){const s=n.width/2,o=n.height/2;return function(t,e,n){const s={x:n.minX,y:n.minY},o={x:n.maxX,y:n.minY},i={x:n.minX,y:n.maxY},r={x:n.maxX,y:n.maxY};if(gt(t,e,s,o)||gt(t,e,o,r)||gt(t,e,r,i)||gt(t,e,i,s))return 0;if(t.x>=n.minX&&t.x<=n.maxX&&t.y>=n.minY&&t.y<=n.maxY&&e.x>=n.minX&&e.x<=n.maxX&&e.y>=n.minY&&e.y<=n.maxY)return 0;const a=[vt(s,t,e),vt(o,t,e),vt(i,t,e),vt(r,t,e)];if(t.x>=n.minX&&t.x<=n.maxX&&t.y>=n.minY&&t.y<=n.maxY)return 0;if(e.x>=n.minX&&e.x<=n.maxX&&e.y>=n.minY&&e.y<=n.maxY)return 0;if(t.x<n.minX||t.x>n.maxX||t.y<n.minY||t.y>n.maxY){const e=ft(t.x,n.minX,n.maxX),s=ft(t.y,n.minY,n.maxY);a.push(St(t,{x:e,y:s}))}if(e.x<n.minX||e.x>n.maxX||e.y<n.minY||e.y>n.maxY){const t=ft(e.x,n.minX,n.maxX),s=ft(e.y,n.minY,n.maxY);a.push(St(e,{x:t,y:s}))}return Math.min(...a)}(t,e,{minX:n.center.x-s,maxX:n.center.x+s,minY:n.center.y-o,maxY:n.center.y+o})}function Ot(t,e,n){const s=n.x-e.x,o=n.y-e.y,i=s*s+o*o;if(0===i)return{x:e.x,y:e.y};let r=((t.x-e.x)*s+(t.y-e.y)*o)/i;r=Math.max(0,Math.min(1,r));return{x:e.x+r*s,y:e.y+r*o}}var zt=class{heap=[];constructor(t){this.heap=[];for(const e of t)this.enqueue(e)}getLeftChildIndex(t){return 2*t+1}getRightChildIndex(t){return 2*t+2}getParentIndex(t){return Math.floor((t-1)/2)}hasLeftChild(t){return this.getLeftChildIndex(t)<this.heap.length}hasRightChild(t){return this.getRightChildIndex(t)<this.heap.length}hasParent(t){return this.getParentIndex(t)>=0}leftChild(t){return this.heap[this.getLeftChildIndex(t)]}rightChild(t){return this.heap[this.getRightChildIndex(t)]}parent(t){return this.heap[this.getParentIndex(t)]}swap(t,e){const n=this.heap[t];this.heap[t]=this.heap[e],this.heap[e]=n}dequeue(){if(0===this.heap.length)return null;const t=this.heap[0];return this.heap[0]=this.heap[this.heap.length-1],this.heap.pop(),this.heapifyDown(),t}peek(){return 0===this.heap.length?null:this.heap[0]}enqueue(t){this.heap.push(t),this.heapifyUp()}heapifyUp(){let t=this.heap.length-1;for(;this.hasParent(t)&&this.parent(t).f>this.heap[t].f;)this.swap(this.getParentIndex(t),t),t=this.getParentIndex(t)}heapifyDown(){let t=0;for(;this.hasLeftChild(t);){let e=this.getLeftChildIndex(t);if(this.hasRightChild(t)&&this.rightChild(t).f<this.leftChild(t).f&&(e=this.getRightChildIndex(t)),this.heap[t].f<this.heap[e].f)break;this.swap(t,e),t=e}}getTopN(t){return[...this.heap].sort((t,e)=>t.f-e.f).slice(0,t)}},Dt=class extends y{obstacleRoutes;bounds;boundsSize;boundsCenter;A;B;straightLineDistance;viaDiameter;traceThickness;obstacleMargin;layerCount;minCellSize=.05;cellStep=.05;GREEDY_MULTIPLER=1.1;numRoutes;VIA_PENALTY_FACTOR=.3;CELL_SIZE_FACTOR;exploredNodes;candidates;connectionName;solvedPath=null;futureConnections;hyperParameters;connMap;debug_exploredNodesOrdered;debug_nodesTooCloseToObstacle;debug_nodePathToParentIntersectsObstacle;debugEnabled=!0;initialNodeGridOffset;constructor(t){super(),this.bounds=t.bounds,this.connMap=t.connMap,this.hyperParameters=t.hyperParameters??{},this.CELL_SIZE_FACTOR=this.hyperParameters.CELL_SIZE_FACTOR??1,this.boundsSize={width:this.bounds.maxX-this.bounds.minX,height:this.bounds.maxY-this.bounds.minY},this.boundsCenter={x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2},this.connectionName=t.connectionName,this.obstacleRoutes=t.obstacleRoutes,this.A=t.A,this.B=t.B,this.viaDiameter=t.viaDiameter??.6,this.traceThickness=t.traceThickness??.15,this.obstacleMargin=t.obstacleMargin??.2,this.layerCount=t.layerCount??2,this.exploredNodes=new Set,this.straightLineDistance=St(this.A,this.B),this.futureConnections=t.futureConnections??[],this.MAX_ITERATIONS=1e4,this.debug_exploredNodesOrdered=[],this.debug_nodesTooCloseToObstacle=new Set,this.debug_nodePathToParentIntersectsObstacle=new Set,this.numRoutes=this.obstacleRoutes.length+this.futureConnections.length;const e=Math.ceil(5*(this.numRoutes+1));let n=this.boundsSize.width/this.cellStep,s=this.boundsSize.height/this.cellStep;for(;n*s>e**2&&!(2*this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,n=this.boundsSize.width/this.cellStep,s=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR;const o=Math.abs(this.A.x-this.bounds.minX)<.001&&Math.abs(this.B.x-this.bounds.minX)<.001||Math.abs(this.A.x-this.bounds.maxX)<.001&&Math.abs(this.B.x-this.bounds.maxX)<.001||Math.abs(this.A.y-this.bounds.minY)<.001&&Math.abs(this.B.y-this.bounds.minY)<.001||Math.abs(this.A.y-this.bounds.maxY)<.001&&Math.abs(this.B.y-this.bounds.maxY)<.001;this.futureConnections&&0===this.futureConnections.length&&0===this.obstacleRoutes.length&&!o&&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 zt([{...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,n=t.z===e.z?[t,e]:[t,{...this.boundsCenter,z:this.A.z},{...this.boundsCenter,z:e.z},e];this.solvedPath={connectionName:this.connectionName,route:n,traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:this.A.z===this.B.z?[]:[this.boundsCenter]}}get viaPenaltyDistance(){return this.cellStep+this.straightLineDistance*this.VIA_PENALTY_FACTOR}isNodeTooCloseToObstacle(t,e,n){if(e??=this.obstacleMargin,n&&t.parent){const n=this.getViasInNodePath(t.parent);for(const s of n)if(St(t,s)<this.viaDiameter/2+e)return!0}for(const s of this.obstacleRoutes){const o=this.connMap?.areIdsConnected?.(this.connectionName,s.connectionName);if(!o){const o=Lt(s);for(const s of o)if((n||s.z===t.z)&&vt(t,s.A,s.B)<this.traceThickness+e)return!0}for(const n of s.vias)if(St(t,n)<this.viaDiameter/2+this.traceThickness/2+e)return!0}return!1}isNodeTooCloseToEdge(t,e){const n=e?this.viaDiameter/2+this.obstacleMargin/2:this.obstacleMargin/2,s=t.x<this.bounds.minX+n||t.x>this.bounds.maxX-n||t.y<this.bounds.minY+n||t.y>this.bounds.maxY-n;return!(s&&!e&&(St(t,this.B)<2*n||St(t,this.A)<2*n))&&s}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!s)for(const s of Lt(n))if(s.z===t.z&>(t,e,s.A,s.B))return!0}return!1}computeH(t){return St(t,this.B)+(t.z!==this.B.z?this.viaPenaltyDistance:0)}computeG(t){return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+St(t,t.parent)}computeF(t,e){return t+e*this.GREEDY_MULTIPLER}getNodeKey(t){return`${Math.round(t.x/this.cellStep)*this.cellStep},${Math.round(t.y/this.cellStep)*this.cellStep},${t.z}`}getNeighbors(t){const e=[],{maxX:n,minX:s,maxY:o,minY:i}=this.bounds;for(let r=-1;r<=1;r++)for(let a=-1;a<=1;a++){if(0===r&&0===a)continue;const c={...t,parent:t,x:Ft(t.x+r*this.cellStep,s,n),y:Ft(t.y+a*this.cellStep,i,o)},h=this.getNodeKey(c);this.exploredNodes.has(h)||(this.isNodeTooCloseToObstacle(c)?(this.debug_nodesTooCloseToObstacle.add(h),this.exploredNodes.add(h)):this.isNodeTooCloseToEdge(c,!1)?this.exploredNodes.add(h):this.doesPathToParentIntersectObstacle(c)?(this.debug_nodePathToParentIntersectsObstacle.add(h),this.exploredNodes.add(h)):(c.g=this.computeG(c),c.h=this.computeH(c),c.f=this.computeF(c.g,c.h),e.push(c)))}for(let n=0;n<this.layerCount;n++){if(n===t.z)continue;const s={...t,parent:t,z:n};this.exploredNodes.has(this.getNodeKey(s))||this.isNodeTooCloseToObstacle(s,this.viaDiameter/2+this.obstacleMargin/2,!0)||this.isNodeTooCloseToEdge(s,!0)||(s.g=this.computeG(s),s.h=this.computeH(s),s.f=this.computeF(s.g,s.h),e.push(s))}return e}getNodePath(t){const e=[];for(;t;)e.push(t),t=t.parent;return e}getViasInNodePath(t){const e=this.getNodePath(t),n=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&n.push({x:e[t].x,y:e[t].y});return n}setSolvedPath(t){const e=this.getNodePath(t);e.reverse();const n=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&n.push({x:e[t].x,y:e[t].y});this.solvedPath={connectionName:this.connectionName,traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,route:e.map(t=>({x:t.x,y:t.y,z:t.z})).concat([this.B]),vias:n}}computeProgress(t,e,n){n||(e+=this.viaPenaltyDistance);const s=1-e/this.straightLineDistance;return Math.max(this.progress||0,2/Math.PI*Math.atan(.112*s/(1-s)))}_step(){let t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;for(;t&&e&&this.exploredNodes.has(e);)t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;if(!t||!e)return this.failed=!0,void(this.error="Ran out of candidate nodes to explore");this.exploredNodes.add(e),this.debug_exploredNodesOrdered.push(e);const n=St(t,this.B);this.progress=this.computeProgress(t,n,t.z===this.B.z),n<=this.cellStep*Math.SQRT2&&t.z===this.B.z&&!this.doesPathToParentIntersectObstacle({...t,parent:t,x:this.B.x,y:this.B.y})&&(this.solved=!0,this.setSolvedPath(t));const s=this.getNeighbors(t);for(const t of s)this.candidates.enqueue(t)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.points.push({x:this.A.x,y:this.A.y,label:`Input A\nz: ${this.A.z}`,color:"orange"}),t.points.push({x:this.B.x,y:this.B.y,label:`Input B\nz: ${this.B.z}`,color:"orange"}),t.lines.push({points:[this.A,this.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:"Direct Input Connection"});for(let e=0;e<this.obstacleRoutes.length;e++){const n=this.obstacleRoutes[e];for(let s=0;s<n.route.length-1;s++){const o=n.route[s].z;t.lines.push({points:[n.route[s],n.route[s+1]],strokeColor:0===o?"rgba(255, 0, 0, 0.75)":"rgba(255, 128, 0, 0.25)",strokeWidth:n.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`})}}for(let e=0;e<this.debug_exploredNodesOrdered.length;e++){const n=this.debug_exploredNodesOrdered[e],[s,o,i]=n.split(",").map(Number);this.debug_nodesTooCloseToObstacle.has(n)||(this.debug_nodePathToParentIntersectsObstacle.has(n)||t.rects.push({center:{x:s+this.initialNodeGridOffset.x+i*this.cellStep/20,y:o+this.initialNodeGridOffset.y+i*this.cellStep/20},fill:0===i?`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=${i})`}))}if(this.candidates.peek()){const e=this.candidates.peek();t.rects.push({center:{x:e.x+e.z*this.cellStep/20,y:e.y+e.z*this.cellStep/20},fill:"rgba(0, 255, 0, 0.8)",width:.9*this.cellStep,height:.9*this.cellStep,label:`Next (z=${e.z})`})}for(const e of this.obstacleRoutes)for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:this.viaDiameter/2,fill:"rgba(255, 0, 0, 0.5)",label:"Via"});if(this.solvedPath){t.lines.push({points:this.solvedPath.route,strokeColor:"green",label:"Solved Route"});for(const e of this.solvedPath.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"green",label:"Via"})}return t}};function Lt(t){const e=[];for(let n=0;n<t.route.length-1;n++)t.route[n].z===t.route[n+1].z&&e.push({z:t.route[n].z,A:t.route[n],B:t.route[n+1]});return e}function Ft(t,e,n){return Math.max(e,Math.min(t,n))}var Xt=class extends Dt{FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR=2;FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR=1;FUTURE_CONNECTION_PROXIMITY_VD=10;MISALIGNED_DIST_PENALTY_FACTOR=5;VIA_PENALTY_FACTOR_2=1;FLIP_TRACE_ALIGNMENT_DIRECTION=!1;constructor(t){super(t);for(const e in t.hyperParameters)this[e]=t.hyperParameters[e];const e=this.boundsSize.width/this.viaDiameter,n=Math.max(1,this.numRoutes);this.VIA_PENALTY_FACTOR=e/n*.3*this.VIA_PENALTY_FACTOR_2}getClosestFutureConnectionPoint(t){let e=1/0,n=null;for(const s of this.futureConnections)for(const o of s.points){const s=St(t,o)+(t.z!==o.z?this.viaPenaltyDistance:0);s<e&&(e=s,n=o)}return n}diminishCloseToGoal(t){const e=St(t,this.B);return 1-Math.exp(-e/this.straightLineDistance*5)}getFutureConnectionPenalty(t,e){let n=0;const s=this.getClosestFutureConnectionPoint(t),o=St(t,this.B);if(s){const i=St(t,s);if(o<=i)return 0;const r=i/(this.viaDiameter*this.FUTURE_CONNECTION_PROXIMITY_VD);n=(e?this.straightLineDistance*this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR:this.straightLineDistance*this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR)*Math.exp(5*-r)}return n}computeH(t){const e=St(t,this.B)**1.6;this.straightLineDistance;return e+(t.z!==this.B.z?this.viaPenaltyDistance:0)+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}computeG(t){const e=Math.abs(t.x-t.parent.x),n=Math.abs(t.y-t.parent.y),s=Math.sqrt(e**2+n**2),o=t.z%2==0,i=this.FLIP_TRACE_ALIGNMENT_DIRECTION?o?e:n:o?n:e;return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+s+i*this.MISALIGNED_DIST_PENALTY_FACTOR+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}};function Yt(t){let e=t;for(let t=0;t<10;t++)e=16807*e%2147483647;let n=e;e=(69069*t+1)%2147483647;for(let t=0;t<10;t++)e=48271*e%2147483647;let s=e;return()=>{let t=n;n=s,t^=t<<23,t^=t>>>17,t^=s,t^=s>>>26,s=t;const e=(n+s)/4294967296;return e-Math.floor(e)}}var $t={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 kt(t,e){if(0===e)return t;if(0===t.length)return t;if(t.length<=4){const n=$t[t.length];return n[e%n.length].map(e=>t[e])}const n=Yt(e),s=t.slice();for(let t=0;t<s.length;t++){const e=Math.floor(n()*s.length),o=Math.floor(n()*(t+1));[s[e],s[o]]=[s[o],s[e]]}return s}function Bt(t){const e={minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2};for(const n of t.portPoints)n.x<e.minX&&(e.minX=n.x),n.x>e.maxX&&(e.maxX=n.x),n.y<e.minY&&(e.minY=n.y),n.y>e.maxY&&(e.maxY=n.y);return e}var jt=t=>{let e=1/0;const n=t.portPoints;for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++){const o=n[t],i=n[s];if(o.z!==i.z)continue;if(o.rootConnectionName&&o.rootConnectionName===i.rootConnectionName)continue;const r=Math.sqrt((o.x-i.x)**2+(o.y-i.y)**2);e=Math.min(e,r)}return e===1/0?0:e},Wt=class extends y{nodeWithPortPoints;colorMap;unsolvedConnections;totalConnections;solvedRoutes;failedSubSolvers;hyperParameters;minDistBetweenEnteringPoints;viaDiameter;traceWidth;activeSubSolver=null;connMap;get failedSolvers(){return this.failedSubSolvers}get activeSolver(){return this.activeSubSolver}constructor(t){const{nodeWithPortPoints:e,colorMap:n}=t;super(),this.nodeWithPortPoints=e,this.colorMap=n??{},this.solvedRoutes=[],this.hyperParameters=t.hyperParameters??{},this.failedSubSolvers=[],this.connMap=t.connMap,this.viaDiameter=t.viaDiameter??.6,this.traceWidth=t.traceWidth??.15;const s=new Map;for(const{connectionName:t,x:n,y:o,z:i}of e.portPoints)s.set(t,[...s.get(t)??[],{x:n,y:o,z:i??0}]);this.unsolvedConnections=Array.from(s.entries().map(([t,e])=>({connectionName:t,points:e}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=kt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},n)=>({...e,points:kt(t,7117*n+(this.hyperParameters.SHUFFLE_SEED??0))}))),this.totalConnections=this.unsolvedConnections.length,this.MAX_ITERATIONS=1e3*this.totalConnections**1.5,this.minDistBetweenEnteringPoints=jt(this.nodeWithPortPoints)}computeProgress(){return(this.solvedRoutes.length+(this.activeSubSolver?.progress||0))/this.totalConnections}_step(){if(this.activeSubSolver)return this.activeSubSolver.step(),this.progress=this.computeProgress(),void(this.activeSubSolver.solved?(this.solvedRoutes.push(this.activeSubSolver.solvedPath),this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSubSolvers.push(this.activeSubSolver),this.activeSubSolver=null,this.error=this.failedSubSolvers.map(t=>t.error).join("\n"),this.failed=!0));const t=this.unsolvedConnections.pop();if(this.progress=this.computeProgress(),!t)return void(this.solved=0===this.failedSubSolvers.length);if(1===t.points.length)return;if(2===t.points.length){const[e,n]=t.points,s=Math.abs(e.x-n.x)<1e-6,o=Math.abs(e.y-n.y)<1e-6;if(s&&o&&e.z===n.z)return;if(s&&o&&e.z!==n.z){const s={x:this.nodeWithPortPoints.center.x,y:this.nodeWithPortPoints.center.y},o=[{x:e.x,y:e.y,z:e.z},{...s,z:e.z},{...s,z:n.z},{x:n.x,y:n.y,z:n.z}].filter((t,e,n)=>0===e||Math.abs(t.x-n[e-1].x)>1e-6||Math.abs(t.y-n[e-1].y)>1e-6||t.z!==n[e-1].z);return void this.solvedRoutes.push({connectionName:t.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:o,vias:[s]})}}const{connectionName:e,points:n}=t;this.activeSubSolver=new Xt({connectionName:e,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:Bt(this.nodeWithPortPoints),A:{x:n[0].x,y:n[0].y,z:n[0].z},B:{x:n[n.length-1].x,y:n[n.length-1].y,z:n[n.length-1].z},obstacleRoutes:this.connMap?this.solvedRoutes.filter(t=>!this.connMap.areIdsConnected(t.connectionName,e)):this.solvedRoutes,futureConnections:this.unsolvedConnections,layerCount:this.nodeWithPortPoints.portPoints.reduce((t,e)=>Math.max(t,(e.z??0)+1),2),hyperParameters:this.hyperParameters,connMap:this.connMap,viaDiameter:this.viaDiameter,traceThickness:this.traceWidth})}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:[e.connectionName,`layer: ${e.z}`].join("\n"),color:this.colorMap[e.connectionName]??"blue"});for(let e=0;e<this.solvedRoutes.length;e++){const n=this.solvedRoutes[e];if(n.route.length>0){const s=this.colorMap[n.connectionName]??"blue";for(let o=0;o<n.route.length-1;o++){const i=n.route[o],r=n.route[o+1];t.lines.push({points:[i,r],strokeColor:0===i.z?it(s,.2):it(s,.8),layer:`route-layer-${i.z}`,step:e,strokeWidth:n.traceThickness})}for(const o of n.vias)t.circles.push({center:{x:o.x,y:o.y},radius:n.viaDiameter/2,fill:it(s,.5),layer:"via",step:e})}}const e=Bt(this.nodeWithPortPoints),{minX:n,minY:s,maxX:o,maxY:i}=e;return t.lines.push({points:[{x:n,y:s},{x:o,y:s},{x:o,y:i},{x:n,y:i},{x:n,y:s}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}},Ht=t=>Math.round(200*t)/200,Ut=t=>"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t));pt();var Vt=class extends Wt{cacheProvider;cacheHit=!1;hasAttemptedToUseCache=!1;initialUnsolvedConnections;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?ut():t.cacheProvider,this.initialUnsolvedConnections=Ut(this.unsolvedConnections),(this.solved||this.failed)&&this.cacheProvider&&!this.cacheHit&&this.saveToCacheSync()}_step(){if(!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync())return;const t=this.solved,e=this.failed;super._step(),!this.cacheProvider||this.cacheHit||!this.solved&&!this.failed||t||e||this.saveToCacheSync()}computeCacheKeyAndTransform(){const t=this.nodeWithPortPoints.center,e=this.initialUnsolvedConnections.map(({connectionName:e,points:n})=>({connectionName:e,points:n.map(n=>({connectionName:e,x:Ht(n.x-t.x),y:Ht(n.y-t.y),z:n.z??0}))})),n=Object.fromEntries(Object.entries(this.hyperParameters??{}).filter(([,t])=>void 0!==t).sort(([t],[e])=>t.localeCompare(e))),s=this.connMap?this.initialUnsolvedConnections.map(({connectionName:t})=>({connectionName:t,connectedIds:[...new Set(this.connMap.getIdsConnectedToNet(t)??[])].sort()})):void 0,o={node:{width:Ht(this.nodeWithPortPoints.width),height:Ht(this.nodeWithPortPoints.height),center:{x:Ht(this.nodeWithPortPoints.center.x),y:Ht(this.nodeWithPortPoints.center.y)},availableZ:this.nodeWithPortPoints.availableZ?[...this.nodeWithPortPoints.availableZ].sort():void 0},normalizedConnections:e,normalizedHyperParameters:n,minDistBetweenEnteringPoints:Ht(this.minDistBetweenEnteringPoints),normalizedConnMap:s},i=`intranode-solver:${at(o)}`,r={};return this.cacheKey=i,this.cacheToSolveSpaceTransform=r,{cacheKey:i,cacheToSolveSpaceTransform:r}}applyCachedSolution(t){t.success?(this.solvedRoutes=Ut(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:Ut(this.solvedRoutes)};try{this.cacheProvider.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}},Zt=class extends y{GREEDY_MULTIPLIER=1.2;MIN_SUBSTEPS=1;supervisedSolvers;winningSolver;getHyperParameterDefs(){throw new Error("Not implemented")}getCombinationDefs(){return null}getHyperParameterCombinations(t){t||(t=this.getHyperParameterDefs());const e=[];if(0===t.length)return[{}];const[n,...s]=t,o=this.getHyperParameterCombinations(s);return n.possibleValues.forEach(t=>{o.forEach(n=>{e.push({...n,...t})})}),e}initializeSolvers(){const t=this.getHyperParameterDefs(),e=this.getCombinationDefs()??[t.map(t=>t.name)];this.supervisedSolvers=[];for(const n of e){const e=this.getHyperParameterCombinations(t.filter(t=>n.includes(t.name)));for(const t of e){const e=this.generateSolver(t),n=this.computeG(e);this.supervisedSolvers.push({hyperParameters:t,solver:e,h:0,g:n,f:n})}}}generateSolver(t){throw new Error("Not implemented")}computeG(t){return t.iterations/t.MAX_ITERATIONS}computeH(t){return 1-(t.progress||0)}computeF(t,e){return t+e*this.GREEDY_MULTIPLIER}getSupervisedSolverWithBestFitness(){let t=1/0,e=null;for(const n of this.supervisedSolvers??[]){if(n.solver.solved)return n;if(n.solver.failed)continue;const s=n.f;s<t&&(t=s,e=n)}return e}getFailureMessage(){return`All solvers failed in hyper solver. Example failures: ${this.supervisedSolvers?.sort((t,e)=>e.f-t.f)?.slice(0,5).map(t=>t.solver.error).join(", ")}`}_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();this.activeSubSolver=t.solver,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 Gt({A:t,B:e,C:n,D:s,E:o,F:i,radius:r,margin:a,subdivisions:c=0}){const h=(t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}),d=(t,e,n)=>{const s=e.x-t.x,o=e.y-t.y,i=Math.sqrt(s*s+o*o),r=s/i,a=o/i,c=-a,h=r;return{midpoint:{x:(t.x+e.x)/2,y:(t.y+e.y)/2},A_Opp:{x:t.x-r*n,y:t.y-a*n},A_Right:{x:t.x+c*n,y:t.y+h*n},A_Left:{x:t.x-c*n,y:t.y-h*n},B_Opp:{x:e.x+r*n,y:e.y+a*n},B_Right:{x:e.x+c*n,y:e.y+h*n},B_Left:{x:e.x-c*n,y:e.y-h*n}}},l=(t,e)=>{const n=St(t,e.start),s=St(t,e.end),o=St(e.start,e.end);return Math.abs(n+s-o)<1e-4},u=(t,e)=>{const{start:n,end:s}=t,{start:o,end:i}=e;if(l(n,e)||l(s,e)||l(o,t)||l(i,t))return!0;const r=s.x-n.x,a=s.y-n.y,c=i.x-o.x,h=i.y-o.y,d=r*h-a*c;if(Math.abs(d)<1e-4)return!1;const u=o.x-n.x,p=o.y-n.y,m=(u*h-p*c)/d,f=(u*a-p*r)/d;return m>0&&m<1&&f>0&&f<1},p=(t,e)=>{const n=[];for(let e=0;e<t.length-1;e++)n.push({start:t[e],end:t[e+1]});const s=[];for(let t=0;t<e.length-1;t++)s.push({start:e[t],end:e[t+1]});for(const t of n)for(const e of s)if(u(t,e))return!0;return!1},m=t=>{let e=0;for(let n=1;n<t.length;n++){const s=t[n].x-t[n-1].x,o=t[n].y-t[n-1].y;e+=Math.sqrt(s*s+o*o)}return e},f=(t,e)=>{const{start:n,end:s}=t,o=s.x-n.x,i=s.y-n.y,r=o*o+i*i;if(0===r)return{...n,t:0};const a=Math.max(0,Math.min(1,((e.x-n.x)*o+(e.y-n.y)*i)/r));return{x:n.x+a*o,y:n.y+a*i,t:a}},g=(e,n,s)=>{const o=f(e,n);if(St(o,n)>=s)return o;const i=o.x-n.x,r=o.y-n.y,a=Math.sqrt(i*i+r*r);if(0===a){const i=e.end.x-e.start.x,r=e.end.y-e.start.y,a=Math.sqrt(i*i+r*r);return{x:n.x+s*i/a,y:n.y+s*r/a,t:o.t,isSpecial:!0,specialType:n===t?"A":"B"}}return{x:n.x+s*i/a,y:n.y+s*r/a,t:o.t,isSpecial:!0,specialType:n===t?"A":"B"}},y=d(t,e,r),x=d(t,e,r+a),v=(t,e,n,s,o)=>{const i=t.points;if(i.length<2)return i;const a=n+s,c=[i[0]];for(let t=0;t<i.length-1;t++){const n={start:i[t],end:i[t+1]};if(vt(e,n.start,n.end)<a){const t=f(n,e),s=t.x-e.x,o=t.y-e.y,i=Math.sqrt(s*s+o*o);let h=null;if(i>1e-6)h={x:e.x+a*s/i,y:e.y+a*o/i};else{const t=n.end.x-n.start.x,s=n.end.y-n.start.y,o=Math.sqrt(t*t+s*s);o>1e-6&&(h={x:e.x+a*t/o,y:e.y+a*s/o})}h&&St(n.start,h)>r/10&&c.push(h)}St(c[c.length-1],n.end)>r/10&&c.push(n.end)}if(c.length>1){const t=[c[0]];for(let e=1;e<c.length;e++)St(t[t.length-1],c[e])>r/10&&t.push(c[e]);return t}return c},S=(()=>{const t=[[n,y.B_Left,y.B_Opp,y.B_Right,h(y.midpoint,h(y.B_Right,y.A_Right)),h(y.midpoint,h(y.A_Left,y.B_Left)),y.A_Left,y.A_Opp,y.A_Right,s],[n,y.B_Right,y.B_Opp,y.B_Left,h(y.midpoint,h(y.A_Left,y.B_Left)),h(y.midpoint,h(y.A_Right,y.B_Right)),y.A_Right,y.A_Opp,y.A_Left,s],[s,y.B_Left,y.B_Opp,y.B_Right,h(y.midpoint,h(y.A_Right,y.B_Right)),h(y.midpoint,h(y.A_Left,y.B_Left)),y.A_Left,y.A_Opp,y.A_Right,n],[s,y.B_Right,y.B_Opp,y.B_Left,h(y.midpoint,h(y.A_Left,y.B_Left)),h(y.midpoint,h(y.A_Right,y.B_Right)),y.A_Right,y.A_Opp,y.A_Left,n]],e=[];for(let n=0;n<t.length;n++){const s=t[n],o={start:s[0],end:s[1]},i={start:s[s.length-2],end:s[s.length-1]},r={start:s[3],end:s[4]};u(o,i)||u(o,r)||u(i,r)||e.push({index:n+1,path:s,length:m(s)})}if(0===e.length)return{index:0,path:[]};const o=e.sort((t,e)=>t.length-e.length)[0],i=[...o.path],r=i[0],a=St(r,i[2]),c=St(r,i[3]),d=a<c?2:3;(a<St(r,i[1])||c<St(r,i[1]))&&i.splice(1,d-1);const l=i[i.length-1],p=St(l,i[i.length-3]),f=St(l,i[i.length-4]),g=p<f?i.length-3:i.length-4;return(p<St(l,i[i.length-2])||f<St(l,i[i.length-2]))&&i.splice(g+1,i.length-g-2),{index:o.index,path:i,startsAt:i[0]===n?"C":"D",goesTo:i[i.length-1]===n?"C":"D"}})(),P=c>0?((n,s)=>{if(n.length<2)return n;const o=[n[0]];for(let i=0;i<n.length-1;i++){const a={start:n[i],end:n[i+1]},c={x:(a.start.x+a.end.x)/2,y:(a.start.y+a.end.y)/2},h=St(c,t),d=St(c,e);if((h<=r||d<=r)&&Math.abs(h-d)>1e-4){const n=f(a,t),i=f(a,e),c=St(n,t),h=St(i,e)<r,d=c<r?g(a,t,r):null,l=h?g(a,e,r):null;let u=[];if(St(a.start,a.end)>r/2&&s>0)for(let n=1;n<=s;n++){const o=n/(s+1),i={x:a.start.x+o*(a.end.x-a.start.x),y:a.start.y+o*(a.end.y-a.start.y),t:o,isSpecial:!1},c=St(i,t),h=St(i,e);c<r||h<r||(d&&Math.abs(i.t-d.t)<.1||l&&Math.abs(i.t-l.t)<.1||u.push(i))}if(d&&u.push(d),l&&u.push(l),u.sort((t,e)=>t.t-e.t),u.length>1){const t=[u[0]];for(let e=1;e<u.length;e++){const n=t[t.length-1],s=u[e];St(n,s)>r/10&&t.push(s)}u=t}u.forEach(t=>o.push(t))}o.push(n[i+1])}if(o.length>1){const t=[o[0]];for(let e=1;e<o.length;e++){const n=t[t.length-1],s=o[e];St(n,s)>r/10&&t.push(s)}return t}return o})(S.path,c):S.path;let b=(()=>{if(0===S.path.length)return null;const n=(()=>{const n=h(y.A_Right,y.B_Right),s=h(y.B_Left,y.A_Left);return[{startsAt:"E",goesTo:"B",points:[o,e]},{startsAt:"E",goesTo:"A",points:[o,t]},{startsAt:"F",goesTo:"B",points:[i,e]},{startsAt:"F",goesTo:"A",points:[i,t]},{startsAt:"E",goesTo:"B",points:[o,n,e]},{startsAt:"E",goesTo:"A",points:[o,n,t]},{startsAt:"F",goesTo:"B",points:[i,n,e]},{startsAt:"F",goesTo:"A",points:[i,n,t]},{startsAt:"E",goesTo:"B",points:[o,s,e]},{startsAt:"E",goesTo:"A",points:[o,s,t]},{startsAt:"F",goesTo:"B",points:[i,s,e]},{startsAt:"F",goesTo:"A",points:[i,s,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Right,n,e]},{startsAt:"F",goesTo:"B",points:[i,x.B_Right,n,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Left,s,t]},{startsAt:"F",goesTo:"A",points:[i,x.A_Left,s,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Opp,x.B_Left,s,t]},{startsAt:"F",goesTo:"B",points:[i,x.A_Opp,x.A_Left,s,e]},{startsAt:"F",goesTo:"A",points:[i,x.B_Opp,x.B_Right,n,t]},{startsAt:"F",goesTo:"A",points:[i,x.B_Opp,x.B_Left,s,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Opp,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Opp,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Left,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Right,x.B_Opp,x.B_Left,s,t]},{startsAt:"F",goesTo:"B",points:[i,x.A_Right,x.A_Opp,x.A_Left,s,e]},{startsAt:"F",goesTo:"A",points:[i,x.B_Left,x.B_Opp,x.B_Right,n,t]},{startsAt:"F",goesTo:"A",points:[i,x.B_Right,x.B_Opp,x.B_Left,s,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Right,x.A_Opp,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Left,x.B_Opp,x.B_Right,n,t]}].map((t,e)=>({...t,index:e}))})(),s=n.filter(t=>"E"===t.startsAt),r=n.filter(t=>"F"===t.startsAt),a=[],c=[];for(const t of s)if(!p(t.points,S.path)){a.push(t);break}for(const t of r)if(!p(t.points,S.path)){c.push(t);break}return 0===a.length||0===c.length?null:{line1:a[0],line2:c[0]}})();if(b){const n="A"===b.line1.goesTo?e:t,s="A"===b.line2.goesTo?e:t,o=v(b.line1,n,r,a),i=v(b.line2,s,r,a);b={line1:{...b.line1,points:o},line2:{...b.line2,points:i}}}return{jPair:b,optimalPath:{startsAt:S.startsAt,goesTo:S.goesTo,points:P}}}var Jt=class extends y{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;escapeLayer=1;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return this.failed=!0,void(this.error=`Expected 2 routes, but got ${this.routes.length}`);const[e,n]=this.routes;if(!(e.startPort.z===e.endPort.z))return this.failed=!0,void(this.error="Route A must start and end on the same layer");if(!(n.startPort.z===n.endPort.z))return this.failed=!0,void(this.error="Route B must start and end on the same layer");if(!(e.startPort.z===n.startPort.z))return this.failed=!0,void(this.error="Both routes must be on the same layer");0===e.startPort.z?this.escapeLayer=1:this.escapeLayer=0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e)?.push(t)}for(const[e,s]of n.entries())2===s.length&&t.push({startPort:{...s[0],z:s[0].z??0},endPort:{...s[1],z:s[1].z??0},connectionName:e});return t}calculateBounds(){return{minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2}}doRoutesCross(t,e){return gt(t.startPort,t.endPort,e.startPort,e.endPort)}calculateViaPositions(t,e){const n=this.bounds.maxX-this.bounds.minX,s=this.bounds.maxY-this.bounds.minY,o=this.bounds.minX,i=this.bounds.minY,r={width:n-2*this.obstacleMargin-this.viaDiameter,height:s-2*this.obstacleMargin-this.viaDiameter,x:o+this.obstacleMargin+this.viaDiameter/2,y:i+this.obstacleMargin+this.viaDiameter/2},a=this.viaDiameter+this.obstacleMargin,c=e.startPort,h=e.endPort,d=[{x:r.x,y:r.y},{x:r.x+r.width,y:r.y},{x:r.x+r.width,y:r.y+r.height},{x:r.x,y:r.y+r.height}],l=(t,e)=>St(t,e),u=[];d.forEach((t,e)=>{l(t,c)>=a&&l(t,h)>=a&&u.push({...t,type:"corner",index:e})});const p=[{p1:d[0],p2:d[1]},{p1:d[1],p2:d[2]},{p1:d[2],p2:d[3]},{p1:d[3],p2:d[0]}];if([c,h].forEach((t,e)=>{p.forEach((n,s)=>{((t,e)=>{const n=t.x,s=t.y,o=t.r,i=e.p1.x,r=e.p1.y,a=e.p2.x,c=e.p2.y;if(Math.abs(a-i)<.001){const t=i,e=o*o-(t-n)**2;if(e<0)return[];if(Math.abs(e)<.001){const e=s;return e>=Math.min(r,c)&&e<=Math.max(r,c)?[{x:t,y:e}]:[]}const a=s+Math.sqrt(e),h=s-Math.sqrt(e),d=[];return a>=Math.min(r,c)&&a<=Math.max(r,c)&&d.push({x:t,y:a}),h>=Math.min(r,c)&&h<=Math.max(r,c)&&d.push({x:t,y:h}),d}const h=(c-r)/(a-i),d=r-h*i,l=1+h*h,u=2*(h*d-h*s-n),p=u*u-4*l*(n*n+(d-s)*(d-s)-o*o);if(p<0)return[];if(Math.abs(p)<.001){const t=-u/(2*l),e=h*t+d;return t>=Math.min(i,a)&&t<=Math.max(i,a)&&e>=Math.min(r,c)&&e<=Math.max(r,c)?[{x:t,y:e}]:[]}const m=(-u+Math.sqrt(p))/(2*l),f=(-u-Math.sqrt(p))/(2*l),g=h*m+d,y=h*f+d,x=[];return m>=Math.min(i,a)&&m<=Math.max(i,a)&&g>=Math.min(r,c)&&g<=Math.max(r,c)&&x.push({x:m,y:g}),f>=Math.min(i,a)&&f<=Math.max(i,a)&&y>=Math.min(r,c)&&y<=Math.max(r,c)&&x.push({x:f,y:y}),x})({...t,r:a},n).forEach(t=>{l(t,0===e?h:c)>=a&&u.push({...t,type:"intersection",circle:e,edge:s})})})}),u.length<2){const t=.8*a;if(d.forEach((e,n)=>{l(e,c)>=t&&l(e,h)>=t&&!u.some(t=>t.x===e.x&&t.y===e.y)&&u.push({...e,type:"relaxed_corner",index:n})}),u.length<2){const t=[...d].sort((t,e)=>{const n=Math.min(l(t,c),l(t,h));return Math.min(l(e,c),l(e,h))-n});for(const e of t)if(!u.some(t=>t.x===e.x&&t.y===e.y)&&(u.push({...e,type:"forced_corner"}),u.length>=2))break}}if(u.length<2)return null;let m=0,f=[u[0],u[u.length>1?1:0]];for(let t=0;t<u.length;t++)for(let e=t+1;e<u.length;e++){const n=l(u[t],u[e]);n>m&&(m=n,f=[u[t],u[e]])}let g={x:f[0].x,y:f[0].y},y={x:f[1].x,y:f[1].y};const x=St(g,t.startPort);return St(y,t.startPort)<x&&([g,y]=[y,g]),{via1:g,via2:y}}trySolveAOverB(t,e,n=!1){const s=n?this.calculateViaPositions(t,e):this.calculateViaPositions(e,t);if(!s)return!1;this.debugViaPositions.push(s);const{via1:o,via2:i}=this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(s));this.debugViaPositions.push({via1:o,via2:i});const{jPair:r,optimalPath:a}=Gt({A:o,B:i,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(!r)return!1;const c={connectionName:t.connectionName,route:a.points.map(e=>({x:e.x,y:e.y,z:t.startPort.z??0})),traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};r.line2.points.reverse();const h={connectionName:e.connectionName,route:[...r.line1.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0})),{...r.line1.points[r.line1.points.length-1],z:this.escapeLayer},{...r.line2.points[0],z:this.escapeLayer},...r.line2.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0}))],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[o,i]};return this.solvedRoutes.push(c,h),!0}pushViasFromEndpoints(t){const e={...t.via1},n={...t.via2},s=[this.routes[0].startPort,this.routes[0].endPort,this.routes[1].startPort,this.routes[1].endPort],o=this.getMinDistanceBetweenViaCenters(),i=this.viaDiameter/2+2*this.traceThickness+2*this.obstacleMargin;for(let t=0;t<10;t++){let r=!1,a=!1;const c=.9**t;for(const t of s){const s=St(e,t);if(s<i){const n=(i-s)*c,o=e.x-t.x,a=e.y-t.y,h=Math.sqrt(o*o+a*a);h>1e-6&&(e.x+=o/h*n,e.y+=a/h*n,r=!0)}const o=St(n,t);if(o<i){const e=(i-o)*c,s=n.x-t.x,r=n.y-t.y,h=Math.sqrt(s*s+r*r);h>1e-6&&(n.x+=s/h*e,n.y+=r/h*e,a=!0)}}const h=St(e,n);if(h<o){const t=(o-h)/2,s=n.x-e.x,i=n.y-e.y,c=Math.sqrt(s*s+i*i);c>1e-6?(e.x-=s/c*t,e.y-=i/c*t,n.x+=s/c*t,n.y+=i/c*t,r=!0,a=!0):(e.x-=t,n.x+=t,r=!0,a=!0)}if(!r&&!a)break}const r=St(e,n);if(r<o){const t=(o-r)/2,s=n.x-e.x,i=n.y-e.y,a=Math.sqrt(s*s+i*i);a>1e-6?(e.x-=s/a*t,e.y-=i/a*t,n.x+=s/a*t,n.y+=i/a*t):(e.x-=t,n.x+=t)}return{via1:e,via2:n}}getMinDistanceBetweenViaCenters(){return this.viaDiameter+this.traceThickness+2*this.obstacleMargin}moveViasAsCloseAsPossible(t){const{via1:e,via2:n}=t,s=this.getMinDistanceBetweenViaCenters(),o=St(e,n);if(o<=s)return t;const i=n.x-e.x,r=n.y-e.y,a=Math.sqrt(i*i+r*r),c=i/a,h=r/a,d=(e.x,n.x,e.y,n.y,(o-s)/2);return{via1:{x:e.x+c*d,y:e.y+h*d},via2:{x:n.x-c*d,y:n.y-h*d}}}handleRoutesDontCross(){const[t,e]=this.routes,n={connectionName:t.connectionName,route:[{x:t.startPort.x,y:t.startPort.y,z:t.startPort.z??0},{x:t.endPort.x,y:t.endPort.y,z:t.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]},s={connectionName:e.connectionName,route:[{x:e.startPort.x,y:e.startPort.y,z:e.startPort.z??0},{x:e.endPort.x,y:e.endPort.y,z:e.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};this.solvedRoutes.push(n,s),this.solved=!0}_step(){if(2!==this.routes.length)return void(this.failed=!0);const[t,e]=this.routes;this.doRoutesCross(t,e)?this.trySolveAOverB(t,e)||this.trySolveAOverB(e,t)||this.trySolveAOverB(t,e,!0)||this.trySolveAOverB(e,t,!0)?this.solved=!0:(this.failed=!0,this.error="All crossover strategies failed"):this.handleRoutesDontCross()}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.rects.push({center:{x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2},width:this.bounds.maxX-this.bounds.minX,height:this.bounds.maxY-this.bounds.minY,stroke:"rgba(0, 0, 0, 0.5)",fill:"rgba(240, 240, 240, 0.1)"});for(const[e,n]of[["Route A",this.routes[0]],["Route B",this.routes[1]]])t.points.push({x:n.startPort.x,y:n.startPort.y,label:`${e}\n${n.connectionName} start`,color:"orange"}),t.points.push({x:n.endPort.x,y:n.endPort.y,label:`${e}\n${n.connectionName} end`,color:"orange"}),t.lines.push({points:[n.startPort,n.endPort],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e}\n${n.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via1:n,via2:s}=this.debugViaPositions[e],o=["rgba(255, 165, 0, 0.3)","rgba(128, 0, 128, 0.3)"],i=o[e%o.length];t.circles.push({center:n,radius:this.viaDiameter/2,fill:i,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via A (attempt ${e+1})`}),t.circles.push({center:s,radius:this.viaDiameter/2,fill:i,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via B (attempt ${e+1})`});const r=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:n,radius:r,stroke:i,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 1 Safety Margin (attempt ${e+1})`}),t.circles.push({center:s,radius:r,stroke:i,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 2 Safety Margin (attempt ${e+1})`}),t.lines.push({points:[this.routes[e%2].startPort,n,s,this.routes[e%2].endPort],strokeColor:`${i.substring(0,i.lastIndexOf(","))}, 0.3)`,strokeDash:[5,5],label:`Potential Route (attempt ${e+1})`})}for(let e=0;e<this.solvedRoutes.length;e++){const n=this.solvedRoutes[e],s=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1];t.lines.push({points:[o,i],strokeColor:s,strokeDash:1===o.z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${o.z}`}),o._label&&t.points.push({x:o.x,y:o.y,label:o._label})}for(const e of n.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Solved Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}};function qt(t,e,n,s,o){const i={x:(t.x+e.x+n.x)/3,y:(t.y+e.y+n.y)/3},r=(t,e)=>Math.sqrt((e.x-t.x)**2+(e.y-t.y)**2),a=i=>{const a=r(i,t),c=r(i,e),h=r(i,n),d=i.x>=o.minX&&i.x<=o.maxX&&i.y>=o.minY&&i.y<=o.maxY;return a>=s&&c>=s&&h>=s&&d};if(a(i))return i;const c=(t,e,n)=>{const s=t.x-e.x,o=t.y-e.y,i=Math.sqrt(s*s+o*o);return i<1e-10?{x:e.x+n,y:e.y}:{x:e.x+s/i*n,y:e.y+o/i*n}},h=(t,e,n)=>{const s=e.x-t.x,o=e.y-t.y,i=Math.sqrt(s*s+o*o);if(i>2*n-1e-10||i<1e-10)return[];const a=i*i/(2*i),c=Math.sqrt(Math.max(0,n*n-a*a)),h=t.x+s*a/i,d=t.y+o*a/i,l={x:h+c*o/i,y:d-c*s/i},u={x:h-c*o/i,y:d+c*s/i},p=[],m=1e-6;return Math.abs(r(l,t)-n)<m&&Math.abs(r(l,e)-n)<m&&p.push(l),Math.abs(r(u,t)-n)<m&&Math.abs(r(u,e)-n)<m&&p.push(u),p},d=[c(i,t,s),c(i,e,s),c(i,n,s),...h(t,e,s),...h(e,n,s),...h(n,t,s)],l=d.filter(a);if(l.length>0){const t=l.filter(t=>!(t=>{const e=1e-6;return Math.abs(t.x-o.minX)<e||Math.abs(t.x-o.maxX)<e||Math.abs(t.y-o.minY)<e||Math.abs(t.y-o.maxY)<e})(t));if(t.length>0)return t.sort((t,e)=>r(t,i)-r(e,i)),t[0]}let u=null,p=1/0;for(let t=o.minX+1;t<o.maxX;t+=5)for(let e=o.minY+1;e<o.maxY;e+=5){const n={x:t,y:e};if(a(n)){const t=r(n,i);t<p&&(p=t,u=n)}}if(null!==u)return u;const m=[];for(let t=0;t<=100;t++){const e=t/100;m.push({x:o.minX+e*(o.maxX-o.minX),y:o.minY}),m.push({x:o.maxX,y:o.minY+e*(o.maxY-o.minY)}),m.push({x:o.maxX-e*(o.maxX-o.minX),y:o.maxY}),m.push({x:o.minX,y:o.maxY-e*(o.maxY-o.minY)})}const f=m.filter(a);if(f.length>0)return f.sort((t,e)=>r(t,i)-r(e,i)),f[0];let g=1/0,y={x:o.minX,y:o.minY};for(const i of[...d,...m])if(i.x>=o.minX&&i.x<=o.maxX&&i.y>=o.minY&&i.y<=o.maxY){const o=Math.max(0,s-r(i,t))+Math.max(0,s-r(i,e))+Math.max(0,s-r(i,n));o<g&&(g=o,y=i)}return y}function Kt(t,e,n){const s=Qt(e,t,n.center,n.radius),o=Qt(t,e,n.center,n.radius),i=te(s,e),r=te(t,o),a=1e-6;let c;if(i>a&&r>a){c={x:(s.x+o.x)/2,y:(s.y+o.y)/2};const i=te(s,c),r=te(o,c);if(Math.abs(i-r)>.5*Math.min(i,r)){const n=te(t,s),i=te(e,o),r=n+i;if(r>a){const t=i/r,e=n/r;c={x:s.x*t+o.x*e,y:s.y*t+o.y*e}}}const h=te(c,n.center);if(h<1.05*n.radius){const t={x:(c.x-n.center.x)/h,y:(c.y-n.center.y)/h};c={x:n.center.x+t.x*n.radius*1.2,y:n.center.y+t.y*n.radius*1.2}}}else{const s={x:(t.x+e.x)/2,y:(t.y+e.y)/2},o=te(s,n.center);if(o<1.1*n.radius){const t={x:(s.x-n.center.x)/o,y:(s.y-n.center.y)/o};c={x:n.center.x+t.x*n.radius*1.2,y:n.center.y+t.y*n.radius*1.2}}else c=s}return{B:s,D:o,E:c}}function Qt(t,e,n,s){const o=[n.x-t.x,n.y-t.y],i=Math.sqrt(o[0]*o[0]+o[1]*o[1]);if(i<=s){if(i<1e-8){const o=[e.x-t.x,e.y-t.y],i=Math.sqrt(o[0]*o[0]+o[1]*o[1]);return i<1e-8?{x:n.x+s,y:n.y}:{x:n.x+o[0]/i*s,y:n.y+o[1]/i*s}}const r=[o[0]/i,o[1]/i];return{x:n.x-r[0]*s,y:n.y-r[1]*s}}const r=[e.x-t.x,e.y-t.y],a=Math.sqrt(i*i-s*s),c=[o[0]/i,o[1]/i],h=[-c[1],c[0]],d=[c[1],-c[0]],l=r[0]*h[0]+r[1]*h[1]>r[0]*d[0]+r[1]*d[1]?h:d,u=s/i,p=a/i,m=[c[0]*p+l[0]*u,c[1]*p+l[1]*u];return{x:t.x+a*m[0],y:t.y+a*m[1]}}function te(t,e){const n=e.x-t.x,s=e.y-t.y;return Math.sqrt(n*n+s*s)}var ee=1e-9;function ne(t,e,n,s="cw"){const o=se(t,n),i=se(e,n);return Math.abs(i-o)<ee?{left:0,top:0,right:0,bottom:0}:function(t,e,n,s){const o=n.maxX-n.minX,i=n.maxY-n.minY;if(o<ee&&i<ee)return{left:0,top:0,right:0,bottom:0};const r=2*(o+i);if(r<ee)return{left:0,top:0,right:0,bottom:0};const a=o/r*(2*Math.PI),c=(o+i)/r*(2*Math.PI),h=(o+o+i)/r*(2*Math.PI),d=2*Math.PI,l=[{name:"top",start:0,end:a,length:o},{name:"right",start:a,end:c,length:i},{name:"bottom",start:c,end:h,length:o},{name:"left",start:h,end:d,length:i}],u={left:0,top:0,right:0,bottom:0},p=(t,e,n,s,o)=>{const i=e>2*Math.PI-ee?2*Math.PI:e;if(i<=t+ee)return 0;if(o){const e=Math.max(t,n),o=Math.min(i,2*Math.PI),r=Math.max(0,o-e),a=Math.max(t,0),c=Math.min(i,s);return r+Math.max(0,c-a)}{const e=Math.max(t,n),o=Math.min(i,s);return Math.max(0,o-e)}};for(const n of l){const o=n.end-n.start;if(o<ee||n.length<ee)continue;let i=0;if("cw"===s){const s=t>e+ee;i=p(n.start,n.end,t,e,s)}else{const s=e>t+ee;i=p(n.start,n.end,e,t,s)}if(i>ee){const t=i/o;u[n.name]+=Math.max(0,Number.isFinite(t)?t:0)}}for(const t in u)u[t]=Math.max(0,Math.min(1,u[t]));return u}(o,i,n,s)}function se(t,e){const n=e.maxX-e.minX,s=e.maxY-e.minY;if(n<ee&&s<ee)return 0;const o=2*(n+s);if(o<ee)return 0;let i=0;if(Math.abs(t.y-e.maxY)<ee&&t.x>=e.minX-ee&&t.x<=e.maxX+ee)i=Math.max(0,Math.min(n,t.x-e.minX));else if(Math.abs(t.x-e.maxX)<ee&&t.y>=e.minY-ee&&t.y<=e.maxY+ee)i=n+Math.max(0,Math.min(s,e.maxY-t.y));else if(Math.abs(t.y-e.minY)<ee&&t.x>=e.minX-ee&&t.x<=e.maxX+ee)i=n+s+Math.max(0,Math.min(n,e.maxX-t.x));else{if(!(Math.abs(t.x-e.minX)<ee&&t.y>=e.minY-ee&&t.y<=e.maxY+ee))throw new Error(`Point (${t.x}, ${t.y}) does not lie on the boundary defined by ${JSON.stringify(e)}`);i=n+s+n+Math.max(0,Math.min(s,t.y-e.minY))}return i=Math.max(0,Math.min(o,i)),o>ee?i/o*(2*Math.PI):0}function oe(t,e,n,s){return function({angleA:t,angleB:e,angleC:n}){const s=Math.cos(t),o=Math.sin(t),i=Math.cos(e),r=Math.sin(e),a=Math.cos(n);return(i-s)*(Math.sin(n)-o)-(r-o)*(a-s)<0?"ccw":"cw"}({angleA:se(t,s),angleB:se(e,s),angleC:se(n,s)})}var ie=class extends y{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return this.failed=!0,void(this.error=`Expected 2 routes, but got ${this.routes.length}`);const[e,n]=this.routes,s=e.A.z!==e.B.z,o=n.A.z!==n.B.z;return s&&o||!s&&!o?(this.failed=!0,void(this.error="Exactly one route must have a layer transition")):void 0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e)?.push(t)}for(const[e,s]of n.entries())2===s.length&&t.push({A:{...s[0],z:s[0].z??0},B:{...s[1],z:s[1].z??0},connectionName:e});return t}calculateBounds(){return{minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2}}doRoutesCross(t,e){return gt(t.A,t.B,e.A,e.B)}calculateViaPosition(t,e){const n=e.A.z,s=t.A.z!==n?t.A:t.B,o=2*this.obstacleMargin+this.viaDiameter/2+this.traceThickness,i=this.obstacleMargin+this.viaDiameter/2,r=e.A,a=s,c=e.B,h=oe(r,a,c,this.bounds),d=function(t,e,n,s,o){const i=ne(t,e,s,o),r=ne(e,n,s,o),a={left:Math.min(1,i.left+r.left),top:Math.min(1,i.top+r.top),right:Math.min(1,i.right+r.right),bottom:Math.min(1,i.bottom+r.bottom)};for(const t in a)Math.abs(a[t])<ee&&(a[t]=0);return a}(r,a,c,this.bounds,h),l={minX:this.bounds.minX+(d.left>.5?o:i),minY:this.bounds.minY+(d.bottom>.5?o:i),maxX:this.bounds.maxX-(d.right>.5?o:i),maxY:this.bounds.maxY-(d.top>.5?o:i)};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),qt(r,a,c,o,l)}createTransitionRoute(t,e,n,s){return{connectionName:s,route:[{x:t.x,y:t.y,z:t.z??0},{x:n.x,y:n.y,z:t.z??0},{x:n.x,y:n.y,z:e.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[n]}}createFlatRoute(t,e,n,s,o,i){s.z,t.z;const r=this.viaDiameter/2+this.traceThickness/2+this.obstacleMargin,a=((t,e,n,s)=>{const o=n.x-t.x,i=n.y-t.y;return((t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}))({x:t.x+o*e,y:t.y+i*e},{x:n.x-o*s,y:n.y-i*s})})(n,this.viaDiameter,s.z!==t.z?s:o,this.traceThickness),c={center:{x:n.x,y:n.y},radius:r},h=Kt(t,a,c).E,d=Kt(a,e,c).E,l=Kt(t,h,c).E,u=Kt(h,a,c).E,p=Kt(a,d,c).E,m=Kt(d,e,c).E,f=Kt(u,p,c).E;return{connectionName:i,route:[{x:t.x,y:t.y,z:t.z??0},{x:l.x,y:l.y,z:t.z??0},{x:h.x,y:h.y,z:t.z??0},{x:u.x,y:u.y,z:t.z??0},{x:f.x,y:f.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:m.x,y:m.y,z:t.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]}}trySolve(){const[t,e]=this.routes,n=t.A.z!==t.B.z,s=n?t:e,o=n?e:t,i=this.calculateViaPosition(s,o);if(!i)return!1;this.debugViaPositions.push({via:i});const r=this.createTransitionRoute(s.A,s.B,i,s.connectionName),a=this.createFlatRoute(o.A,o.B,i,s.A,s.B,o.connectionName);return this.solvedRoutes.push(r,a),!0}_step(){if(!this.doRoutesCross(this.routes[0],this.routes[1]))return this.failed=!0,void(this.error="Can only solve routes that have a single transition crossing");this.trySolve()?this.solved=!0:(this.failed=!0,this.error="Failed to find a valid via position and route path")}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.rects.push({center:{x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2},width:this.bounds.maxX-this.bounds.minX,height:this.bounds.maxY-this.bounds.minY,stroke:"rgba(0, 0, 0, 0.5)",fill:"rgba(240, 240, 240, 0.1)",label:"PCB Bounds"});for(const e of this.routes)t.points.push({x:e.A.x,y:e.A.y,label:`${e.connectionName} start (z=${e.A.z})`,color:"orange"}),t.points.push({x:e.B.x,y:e.B.y,label:`${e.connectionName} end (z=${e.B.z})`,color:"orange"}),t.lines.push({points:[e.A,e.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via:n}=this.debugViaPositions[e];t.circles.push({center:n,radius:this.viaDiameter/2,fill:"rgba(255, 165, 0, 0.7)",stroke:"rgba(0, 0, 0, 0.5)",label:`Computed Via (attempt ${e+1})`});const s=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:n,radius:s,stroke:"rgba(255, 165, 0, 0.7)",fill:"rgba(0, 0, 0, 0)",label:"Safety Margin"})}for(let e=0;e<this.solvedRoutes.length;e++){const n=this.solvedRoutes[e],s=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1];t.lines.push({points:[o,i],strokeColor:s,strokeDash:o.z!==n.route[0].z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${o.z}`})}for(const e of n.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}},re=class extends y{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;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.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),1!==this.routes.length)return this.failed=!0,void(this.error=`Expected 1 route, but got ${this.routes.length}`);const e=this.routes[0];if(void 0===e.A.z||void 0===e.B.z)return this.failed=!0,void(this.error="Route points should have predefined z values");if(e.A.z===e.B.z)return this.failed=!0,void(this.error="Only one route provided, but it has no transition");const n=this.viaDiameter/2+this.obstacleMargin,s={x:ft((e.A.x+e.B.x)/2,this.bounds.minX+n,this.bounds.maxX-n),y:ft((e.A.y+e.B.y)/2,this.bounds.minY+n,this.bounds.maxY-n)};this.solvedRoutes.push(this.createTransitionRoute(e.A,e.B,s,e.connectionName)),this.solved=!0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e).push(t)}for(const[e,s]of n.entries())2===s.length&&t.push({A:{...s[0]},B:{...s[1]},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}}createTransitionRoute(t,e,n,s){return{connectionName:s,route:[{x:t.x,y:t.y,z:t.z},{x:n.x,y:n.y,z:t.z},{x:n.x,y:n.y,z:e.z},{x:e.x,y:e.y,z:e.z}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[n]}}_step(){this.solved=!0}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(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"}),this.routes.length>0)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.solvedRoutes.length;e++){const n=this.solvedRoutes[e],s="rgba(0, 255, 0, 0.75)";for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1];t.lines.push({points:[o,i],strokeColor:s,strokeDash:o.z!==n.route[0].z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${o.z}`})}for(const e of n.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Via Margin"})}return t}},ae=(t,e)=>{const n={};return t.portPoints.forEach((e,s)=>{n[e.connectionName]=`hsl(${360*s/t.portPoints.length}, 100%, 50%)`}),n},ce=class extends y{bounds;maxViaCount;portPairMap;colorMap;nodeWidth;availableZ;hyperParameters;VIA_INTERSECTION_BUFFER_DISTANCE=.05;PLACEHOLDER_WALL_BUFFER_DISTANCE=.1;NEW_HEAD_WALL_BUFFER_DISTANCE=.05;viaDiameter;unprocessedConnections;completedPaths=new Map;placeholderPaths=new Map;currentHead;currentConnectionName;currentPath;currentViaCount;constructor({nodeWithPortPoints:t,colorMap:e,hyperParameters:n,viaDiameter:s}){super(),this.MAX_ITERATIONS=1e5,this.colorMap=e??ae(t),this.maxViaCount=5,this.bounds=Bt(t),this.nodeWidth=this.bounds.maxX-this.bounds.minX,this.portPairMap=(t=>{const e=new Map;return t.portPoints.forEach(t=>{e.has(t.connectionName)?e.get(t.connectionName).end=t:e.set(t.connectionName,{start:t,end:null,connectionName:t.connectionName})}),e})(t),this.stats.solutionsFound=0,this.availableZ=t.availableZ??[0,1],this.hyperParameters=n??{SHUFFLE_SEED:0},this.viaDiameter=s??.6,this.unprocessedConnections=Array.from(this.portPairMap.keys()).sort(),n?.SHUFFLE_SEED&&(this.unprocessedConnections=kt(this.unprocessedConnections,n.SHUFFLE_SEED));for(const[t,{start:e,end:n}]of this.portPairMap.entries())if(e.z===n.z){const s=Math.abs(e.x-n.x)<1e-9,o=Math.abs(e.y-n.y)<1e-9;s||o?this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),this._padByPlaceholderWallBuffer(n),n]):this.placeholderPaths.set(t,[e,n])}else{const s=(e.x+n.x)/2,o=(e.y+n.y)/2,i=this._padByPlaceholderWallBuffer({x:s,y:o,z:e.z}),r=this._padByPlaceholderWallBuffer({x:s,y:o,z:n.z});this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),i,r,this._padByPlaceholderWallBuffer(n),n])}this.currentConnectionName=this.unprocessedConnections.pop();const o=this.portPairMap.get(this.currentConnectionName).start;this.currentHead=this._padByNewHeadWallBuffer(o),this.currentPath=[o,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}_padByNewHeadWallBuffer(t){return{x:ft(t.x,this.bounds.minX+this.NEW_HEAD_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.NEW_HEAD_WALL_BUFFER_DISTANCE),y:ft(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:ft(t.x,this.bounds.minX+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),y:ft(t.y,this.bounds.minY+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxY-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),z:t.z}}_step(){if(this.solved)return;const t=this.portPairMap.get(this.currentConnectionName).end,e=[this.currentHead,t];let n=null,s=null;const o=t=>{for(const o of t.values())for(let t=0;t<o.length-1;t++){const i=[o[t],o[t+1]];if(i[0].x===i[1].x&&i[0].y===i[1].y)continue;if(i[0].z!==this.currentHead.z)continue;const r=Pt(e[0],e[1],i[0],i[1]);if(r){const t=St(this.currentHead,r);if(t<1e-6)continue;(!n||t<n.dist)&&(n={point:r,dist:t},s=i[0].z)}}};o(this.completedPaths),o(this.placeholderPaths);const i=this.currentHead.z!==t.z;if((n||i)&&(this.currentViaCount++,this.currentViaCount>=this.maxViaCount))return this.failed=!0,void(this.error=`Exceeded max via count of ${this.maxViaCount}`);if(n){let t;const e=n.dist;if(e<=this.VIA_INTERSECTION_BUFFER_DISTANCE+1e-6)t=bt(this.currentHead,n.point);else{const s=n.point,o=s.x-this.currentHead.x,i=s.y-this.currentHead.y,r=(e-this.VIA_INTERSECTION_BUFFER_DISTANCE)/e;t={x:this.currentHead.x+o*r,y:this.currentHead.y+i*r}}const o=this.availableZ.find(t=>t!==s);if(void 0===o)return this.error="Could not determine next Z level for via placement!",void(this.failed=!0);const i={...t,z:this.currentHead.z},r={...t,z:o};this.currentPath.push(i,r),this.currentHead=r}else if(i){let e;const n=St(this.currentHead,t);if(n<this.VIA_INTERSECTION_BUFFER_DISTANCE)e=bt(this.currentHead,t);else{const s=t.x-this.currentHead.x,o=t.y-this.currentHead.y,i=(n-this.VIA_INTERSECTION_BUFFER_DISTANCE)/n;e={x:this.currentHead.x+s*i,y:this.currentHead.y+o*i}}const s=t.z,o={...e,z:this.currentHead.z},i={...e,z:s};this.currentPath.push(o,i),this.currentHead=i}else if(this.currentPath.push(t),this.completedPaths.set(this.currentConnectionName,this.currentPath),0===this.unprocessedConnections.length)this.solved=!0,this.stats.solutionsFound=1;else{this.currentConnectionName=this.unprocessedConnections.pop();const{start:t}=this.portPairMap.get(this.currentConnectionName);this.currentHead=this._padByNewHeadWallBuffer(t),this.currentPath=[t,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}}visualize(){const t={points:[],lines:[],circles:[],rects:[],title:"Via Possibilities Solver State",coordinateSystem:"cartesian"},e=this.colorMap;t.lines.push({points:[{x:this.bounds.minX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.minY}],strokeColor:"gray",strokeWidth:.01});for(const[e,{start:n,end:s}]of this.portPairMap.entries()){const o=this.colorMap[e]??"black";t.points.push({x:n.x,y:n.y,color:o,label:`Port: ${e} Start (z${n.z})`}),t.points.push({x:s.x,y:s.y,color:o,label:`Port: ${e} End (z${s.z})`})}const n=(n,s)=>{for(const[o,i]of n.entries()){const n=e[o]??"black";for(let e=0;e<i.length-1;e++){const r=i[e],a=i[e+1];r.x===a.x&&r.y===a.y&&r.z!==a.z?t.circles.push({center:{x:r.x,y:r.y},radius:this.viaDiameter/2,fill:it(n,.5),label:`${s}: ${o} Via (z${r.z}->z${a.z})`}):t.lines.push({points:[r,a],strokeColor:it(n,.5),strokeDash:0===r.z?void 0:[.1,.1],strokeWidth:.1,label:`${s}: ${o} (z${r.z})`})}}};if(n(this.placeholderPaths,"Placeholder"),n(this.completedPaths,"Completed"),this.currentPath&&this.currentPath.length>0){const n=e[this.currentConnectionName]??"orange";for(let e=0;e<this.currentPath.length-1;e++){const s=this.currentPath[e],o=this.currentPath[e+1];s.x===o.x&&s.y===o.y&&s.z!==o.z?t.circles.push({center:{x:s.x,y:s.y},radius:this.viaDiameter/2,fill:it(n,.5),label:`Current: ${this.currentConnectionName} Via (z${s.z}->z${o.z})`}):t.lines.push({points:[s,o],strokeColor:it(n,.5),strokeWidth:.15,strokeDash:"2,2",label:`Current: ${this.currentConnectionName} (z${s.z})`})}t.points.push({x:this.currentHead.x,y:this.currentHead.y,color:"green",label:`Current Head: ${this.currentConnectionName} (z${this.currentHead.z})`})}return t}},he=t=>Math.round(1e4*t),de=t=>{let e=0,n=[];const s=[];for(const e of t.portPoints){if(n.some(t=>t.connectionName===e.connectionName))continue;if(s.some(t=>t.connectionName===e.connectionName))continue;const o={connectionName:e.connectionName,z:e.z,points:[{x:he(e.x),y:he(e.y),z:e.z}]};for(const n of t.portPoints)e.connectionName===n.connectionName&&(e.x===n.x&&e.y===n.y||o.points.push({x:he(n.x),y:he(n.y),z:n.z}));o.points.some(t=>t.z!==o.z)?s.push(o):n.push(o)}n=n.filter(t=>t.points.length>1);for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++){const o=n[t],i=n[s];o.z===i.z&>(o.points[0],o.points[1],i.points[0],i.points[1])&&e++}let o=0;for(let t=0;t<s.length;t++)for(let e=t+1;e<s.length;e++){const n=s[t],i=s[e];gt(n.points[0],n.points[1],i.points[0],i.points[1])&&o++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:s.length,numTransitionPairCrossings:o}},le=1e-9;function ue(t,e,n=le){return Math.abs(t-e)<n}function pe(t,e,n,s){return t*s-e*n}function me(t,e,n,s){const o={x:e.x-t.x,y:e.y-t.y},i={x:s.x-n.x,y:s.y-n.y},r=pe(o.x,o.y,i.x,i.y);if(ue(r,0))return null;const a={x:n.x-t.x,y:n.y-t.y},c=pe(a.x,a.y,i.x,i.y)/r,h=pe(a.x,a.y,o.x,o.y)/r;return c<-le||c>1+le||h<-le||h>1+le?null:{x:t.x+c*o.x,y:t.y+c*o.y}}function fe(t){let e=0;for(let n=0,s=t.length;n<s;++n){const o=(n+1)%s;e+=t[n].x*t[o].y-t[o].x*t[n].y}return.5*e}function ge(t){let e=0,n=0,s=0;for(let o=0,i=t.length;o<i;++o){const r=(o+1)%i,a=t[o].x*t[r].y-t[r].x*t[o].y;e+=a,n+=(t[o].x+t[r].x)*a,s+=(t[o].y+t[r].y)*a}return e*=.5,ue(e,0)?null:(n/=6*e,s/=6*e,{x:n,y:s})}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 ve(t,e){const n=[...e,...[{start:{x:t.minX,y:t.minY},end:{x:t.maxX,y:t.minY}},{start:{x:t.maxX,y:t.minY},end:{x:t.maxX,y:t.maxY}},{start:{x:t.maxX,y:t.maxY},end:{x:t.minX,y:t.maxY}},{start:{x:t.minX,y:t.maxY},end:{x:t.minX,y:t.minY}}]],s=n.map(()=>[]);for(let t=0;t<n.length;++t){const e=n[t];s[t].push(e.start,e.end)}for(let t=0;t<n.length;++t)for(let e=t+1;e<n.length;++e){const o=me(n[t].start,n[t].end,n[e].start,n[e].end);o&&(s[t].push(o),s[e].push(o))}const o=new Map,i=[];function r(t){const e=function(t,e=le){return`${Math.round(t.x/e)}:${Math.round(t.y/e)}`}(t);if(!o.has(e)){const n=i.length;return o.set(e,n),i.push(new ye(t.x,t.y)),n}return o.get(e)}const a=[];for(let t=0;t<n.length;++t){const e=n[t],o=s[t].slice();o.sort((t,n)=>{const s=e.end.x-e.start.x,o=e.end.y-e.start.y;return(ue(Math.abs(s),0)?(t.y-e.start.y)/o:(t.x-e.start.x)/s)-(ue(Math.abs(s),0)?(n.y-e.start.y)/o:(n.x-e.start.x)/s)});for(let t=0;t<o.length-1;++t){const n=o[t],s=o[t+1],c=r(n),h=r(s);c!==h&&(a.push([c,h]),e.connectionName&&(i[c].connectionNames.add(e.connectionName),i[h].connectionNames.add(e.connectionName)))}}const c=[];for(const[t,e]of a){const n=new xe(t,e),s=new xe(e,t);n.twin=c.length+1,s.twin=c.length;const o=c.length;c.push(n,s),i[t].out.push(o),i[e].out.push(o+1)}for(let t=0;t<i.length;++t){const e=i[t];e.out.sort((t,n)=>{const s=c[t],o=c[n],r=i[s.dest],a=i[o.dest];return Math.atan2(r.y-e.y,r.x-e.x)-Math.atan2(a.y-e.y,a.x-e.x)});const n=e.out.length;for(let t=0;t<n;++t){const s=e.out[t],o=e.out[(t-1+n)%n],i=c[s];null!==i.twin&&(c[i.twin].next=o)}}const h=[],d=[];for(let t=0;t<c.length;++t){if(c[t].visited)continue;let e=t;const n=[],s=[];do{if(null===e)break;const t=c[e];t.visited=!0,n.push(i[t.orig]),s.push(e),e=t.next}while(null!==e&&e!==t&&!c[e].visited);if(n.length<3)continue;if(fe(n)>le){const t=ge(n);t&&(h.push(t),d.push({vertices:n.map(t=>({x:t.x,y:t.y,connectionNames:t.connectionNames.size>0?t.connectionNames:void 0})),centroid:t}))}}return{centroids:h,faces:d,allVertices:i}}function Se(t,e){if(t>e)throw new Error("oneCount cannot be greater than length");if(t<0||e<0)throw new Error("oneCount and length must be non-negative");const n=[];return function t(s,o,i){i!==e?(s[i]=0,t(s,o,i+1),o>0&&(s[i]=1,t(s,o-1,i+1))):0===o&&n.push([...s])}(Array(e).fill(0),t,0),n}var Pe=t=>{if(0===t.length)return[[]];const e=[];for(let n=0;n<t.length;n++){const s=t[n],o=[...t.slice(0,n),...t.slice(n+1)],i=Pe(o);for(const t of i)e.push([s,...t])}return e};var be=t=>{const{start:e,end:n,segmentsPerPolyline:s,viaPositions:o,viaCount:i,availableZ:r}=t,a=function(t,e){const n=new Array(t).fill(0);if(0===e)return n;if(e===t)return n.fill(1);if(e<=t/2){const s=Math.floor(t/e),o=Math.floor((t-(s*(e-1)+1))/2);for(let t=0;t<e;t++)n[o+t*s]=1}else{const s=t-e,o=Math.floor(t/s),i=Math.floor((t-(o*(s-1)+1))/2);n.fill(1);for(let t=0;t<s;t++)n[i+t*o]=0}return n}(s,i),c=a.map(()=>null);let h=0,d=e.z1;const l=r.indexOf(e.z1);for(let t=0;t<a.length;t++)if(1===a[t]){const e=r[(l+h+1)%r.length];c[t]={...o[h],z1:d,z2:e},d=e,h++}let u=e;for(let t=0;t<c.length;t++){if(c[t]){u=c[t];continue}let e=n,s=c.length;for(let n=t+1;n<c.length;n++)if(c[n]){e=c[n],s=n;break}const o=s-t,i=e.x-u.x,r=e.y-u.y;for(let e=1/(o+1),n=0;t+n!==s;e+=1/(o+1),n++)c[t+n]={x:u.x+i*e,y:u.y+r*e,z1:u.z2,z2:u.z2}}return c},Me=1e-9;function Ne(t,e){return Math.abs(t-e)<Me}function Ie(t){return`${Math.round(t.x/Me)}:${Math.round(t.y/Me)}`}function Ce(t,e,n,s){return t*s-e*n}function _e(t,e,n,s){const o={x:e.x-t.x,y:e.y-t.y},i={x:s.x-n.x,y:s.y-n.y},r=Ce(o.x,o.y,i.x,i.y),a={x:n.x-t.x,y:n.y-t.y};if(Ne(r,0))return null;const c=Ce(a.x,a.y,i.x,i.y)/r,h=Ce(a.x,a.y,o.x,o.y)/r;return c>=-1e-9&&c<=1+Me&&h>=-1e-9&&h<=1+Me?{x:t.x+c*o.x,y:t.y+c*o.y}:null}function Te(t,e,n){return Ne(Math.hypot(t.x-e.x,t.y-e.y)+Math.hypot(t.x-n.x,t.y-n.y),Math.hypot(e.x-n.x,e.y-n.y))}function Ee(t,e){const n=[],s=new Map;for(const e of t){const t=[e.start,...e.mPoints,e.end];for(let o=0;o<t.length-1;o++){const i=t[o],r=t[o+1],a=i.z2;if(n.push({start:{x:i.x,y:i.y},end:{x:r.x,y:r.y},connectionName:e.connectionName,layer:a}),i.z1!==i.z2){const t=Ie(i);s.has(t)||s.set(t,{point:i,connectionName:e.connectionName})}}const o=t[t.length-1];if(o.z1!==o.z2){const t=Ie(o);s.has(t)||s.set(t,{point:o,connectionName:e.connectionName})}}const o=[{start:{x:e.minX,y:e.minY},end:{x:e.maxX,y:e.minY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.minY},end:{x:e.maxX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.maxY},end:{x:e.minX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.minX,y:e.maxY},end:{x:e.minX,y:e.minY},connectionName:null,layer:0}];n.push(...o);const i=new Map;let r=0;function a(t,e){const n=Ie(t);let o=i.get(n);if(!o){const e=s.has(n);o={id:r++,x:t.x,y:t.y,isVia:e,connectionNames:new Set,outgoingEdges:[]},i.set(n,o),e&&s.get(n)&&o.connectionNames.add(s.get(n).connectionName)}return e&&o.connectionNames.add(e),o}for(const t of n)a(t.start,t.connectionName),a(t.end,t.connectionName);const c=new Map;for(const t of n)c.set(t,[]);for(let t=0;t<n.length;t++)for(let e=t+1;e<n.length;e++){if(n[t].layer!==n[e].layer)continue;const s=_e(n[t].start,n[t].end,n[e].start,n[e].end);s&&(a(s),Te(s,n[t].start,n[t].end)&&c.get(n[t]).push(s),Te(s,n[e].start,n[e].end)&&c.get(n[e]).push(s))}const h=[];let d=0;for(const t of n){const e=[t.start,...c.get(t),t.end];e.sort((e,n)=>{const s=t.end.x-t.start.x,o=t.end.y-t.start.y;return Math.abs(s)>Math.abs(o)?(e.x-t.start.x)/s-(n.x-t.start.x)/s:Math.abs(o)<Me?0:(e.y-t.start.y)/o-(n.y-t.start.y)/o});const n=[];if(e.length>0){n.push(e[0]);for(let t=1;t<e.length;t++)Ne(e[t].x,e[t-1].x)&&Ne(e[t].y,e[t-1].y)||n.push(e[t])}for(let e=0;e<n.length-1;e++){const s=n[e],o=n[e+1],i=a(s,t.connectionName),r=a(o,t.connectionName);if(i===r)continue;const c={id:d++,origin:i,twin:null,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1},l={id:d++,origin:r,twin:c,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1};c.twin=l,h.push(c,l),i.outgoingEdges.push(c),r.outgoingEdges.push(l)}}for(const t of i.values()){t.outgoingEdges.sort((e,n)=>{const s=e.twin.origin,o=n.twin.origin;return Math.atan2(s.y-t.y,s.x-t.x)-Math.atan2(o.y-t.y,o.x-t.x)});const e=t.outgoingEdges.length;for(let n=0;n<e;n++){const s=t.outgoingEdges[n],o=t.outgoingEdges[(n-1+e)%e];s.twin&&(s.twin.next=o)}}const l=[];let u=0,p=null,m=-1/0;for(const t of h){if(t.visited)continue;const e={id:u++,outerComponent:t,innerComponents:[],isOuterFace:!1};l.push(e);let n=t;const s=[],o=[],i=new Set;let r=0;do{if(!n||n.visited){console.warn("Face traversal encountered visited edge or null, breaking loop.",e.id),s.length=0;break}n.visited=!0,n.face=e,s.push(n),o.push(n.origin),null!==n.connectionName&&i.add(n.connectionName);const t=n.origin,a=n.twin.origin;r+=t.x*a.y-a.x*t.y,n=n.next}while(n!==t&&null!==n);if(n===t){if(r=.5*Math.abs(r),r>m&&(m=r,p&&(p.isOuterFace=!1),p=e,e.isOuterFace=!0),!e.isOuterFace&&s.length>0){if([...i].filter(t=>null!==t).length>1){let t=!1;for(const e of o)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 Re=class extends y{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.viaDiameter=t.viaDiameter??this.viaDiameter,this.cellSize=this.nodeWithPortPoints.width/1024,this.candidates=[],this.availableZ=this.nodeWithPortPoints.availableZ??[0,1],this.bounds={minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2};const e=this.nodeWithPortPoints.width*this.nodeWithPortPoints.height,n=(this.viaDiameter+2*this.obstacleMargin+this.traceWidth/2)**2,s=new Set(this.nodeWithPortPoints.portPoints.map(t=>t.connectionName)).size;this.uniqueConnections=s;const{numSameLayerCrossings:o,numEntryExitLayerChanges:i}=de(this.nodeWithPortPoints);if(this.minViaCount=2*o+i,this.maxViaCount=Math.min(Math.floor(e/n),Math.ceil(1.5*s)),this.minViaCount>this.SEGMENTS_PER_POLYLINE*(s/2))return this.failed=!0,void(this.error=`Not possible to solve problem with given SEGMENTS_PER_POLYLINE (${this.SEGMENTS_PER_POLYLINE}), atleast ${this.minViaCount} vias are required`);this.maxViaCount>this.SEGMENTS_PER_POLYLINE&&(this.maxViaCount=this.SEGMENTS_PER_POLYLINE),this.maxViaCount<this.minViaCount&&(this.maxViaCount=this.minViaCount)}computeMinGapBtwPolyLines(t){const e=[],n=[],s=[];for(let e=0;e<t.length;e++){const o=t[e],i=[o.start,...o.mPoints,o.end],r=new Map(this.availableZ.map(t=>[t,[]]));for(let t=0;t<i.length-1;t++){const e=[i[t],i[t+1]],n=e[0].z2;r.has(n)||r.set(n,[]),r.get(n).push(e)}n.push(r),s.push(i.filter(t=>t.z1!==t.z2))}for(let o=0;o<t.length;o++){const i=n[o],r=s[o];for(let a=o+1;a<t.length;a++){if(this.connMap?.areIdsConnected(t[o].connectionName,t[a].connectionName))continue;const c=n[a],h=s[a];let d=1;for(const t of this.availableZ){const e=i.get(t)??[],n=c.get(t)??[];for(const t of e)for(const e of n)d=Math.min(d,wt(t[0],t[1],e[0],e[1])-this.traceWidth);for(const t of r)for(const e of n)d=Math.min(d,vt(t,e[0],e[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of h)for(const n of e)d=Math.min(d,vt(t,n[0],n[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of r)for(const e of h)d=Math.min(d,St(t,e)-this.viaDiameter)}e.push(d)}}return e}insertCandidate(t){let e=0,n=this.candidates.length-1;for(;e<=n;){const s=Math.floor((e+n)/2);this.candidates[s].f<t.f?e=s+1:n=s-1}this.candidates.splice(e,0,t)}setupInitialPolyLines(){const t=new Map;this.nodeWithPortPoints.portPoints.forEach(e=>{t.has(e.connectionName)?t.get(e.connectionName).end={...e,z1:e.z??0,z2:e.z??0}:t.set(e.connectionName,{start:{...e,z1:e.z??0,z2:e.z??0},end:null})});for(const[e,n]of t.entries())null===n.end&&t.delete(e);if(0===t.size)return this.failed=!0,void(this.error="No port pairs found, can't solve");const e=Array.from(t.entries()),n=((t,e,n,s)=>{const o=[];for(const[,n]of t){const t=n.start.z1!==n.end.z1,s=[];for(let n=0;n<=e;n++){const e=n%2!=0;t&&e?s.push(n):t||e||s.push(n)}o.push(s)}if(0===o.length)return[[]];let i=(t=>{if(!t||0===t.length)return[[]];let e=[[]];for(const n of t){const t=[];for(const s of e)for(const e of n)t.push([...s,e]);e=t}return e})(o).filter(t=>{for(let e=0;e<t.length;e++)if(t.reduce((t,e)=>t+e,0)<s)return!1;return!0});return i=i.filter(e=>{for(let n=0;n<t.length;n++){const[,s]=t[n];if(s.start.z1!==s.start.z2&&0===e[n])return!1}return!0}),i=i.filter(e=>{for(let n=0;n<t.length;n++){const[,s]=t[n];if(t[n][1].start.z1===t[n][1].start.z2)for(let o=n+1;o<t.length;o++){if(t[o][1].start.z1!==t[o][1].start.z2)continue;const[,i]=t[o];if(s.start.z1===s.end.z1&&i.start.z1===i.end.z1&&s.start.z1===i.start.z1&>(s.start,s.end,i.start,i.end)&&e[n]+e[o]<2)return!1}}return!0}),i=i.filter(t=>!(t.reduce((t,e)=>t+e,0)>n)),i})(e,this.SEGMENTS_PER_POLYLINE,this.maxViaCount,this.minViaCount),s=(t=>{const{bounds:e,portPairsEntries:n,viaCountVariants:s}=t,{centroids:o}=ve(e,n.map(([t,e])=>e)),i=[];for(const t of s){const n=t.reduce((t,e)=>t+e,0);let s=o;if(o.length<n){s=[];const t=Math.ceil(Math.sqrt(n)),o=t;for(let n=0;n<t;n++)for(let i=0;i<o;i++)s.push({x:e.minX+(i+1)/(o+1)*(e.maxX-e.minX),y:e.minY+(n+1)/(t+1)*(e.maxY-e.minY)})}const r=Se(n,s.length);for(const e of r){const n=[];for(let t=0;t<e.length;t++)1===e[t]&&n.push(s[t]);i.push({viaPositions:n,viaCountVariant:t})}}return i})({portPairsEntries:e,viaCountVariants:n,bounds:this.bounds}),o=[];for(const{viaCountVariant:t,viaPositions:e}of s){const n=Pe(e);for(const e of n)o.push({viaCountVariant:t,viaPositions:e})}for(const{viaPositions:t,viaCountVariant:n}of o){const s=[];let o=0;for(let i=0;i<e.length;i++){const[r,a]=e[i],c=n[i],h=t.slice(o,o+c),d=be({start:a.start,end:a.end,segmentsPerPolyline:this.SEGMENTS_PER_POLYLINE,viaPositions:h,viaCount:c,availableZ:this.availableZ});o+=c,s.push({connectionName:r,start:a.start,end:a.end,mPoints:d})}if(Ee(s,this.bounds))continue;const i=this.computeMinGapBtwPolyLines(s),r=this.computeH({minGaps:i,forces:[]}),a={polyLines:s,g:0,h:r,f:r,viaCount:n.reduce((t,e)=>t+e,0),minGaps:i};if(this.checkIfSolved(a))return void(this.candidates=[a]);if(this.candidates.push(a),this.candidates.length>this.MAX_CANDIDATES)return}this.candidates.sort((t,e)=>t.f-e.f)}computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){let e=0;for(const n of t.forces??[])for(const t of n)for(const n of t.values())e+=n.fx*n.fx+n.fy*n.fy;return e}getNeighbors(t){const{polyLines:e}=t,n=e.length,s=.02,o=.008,i=1e-6,r=Array.from({length:n},(t,n)=>Array.from({length:e[n].mPoints.length},()=>new Map)),a=(t,n,s,o,i)=>{if(n>0&&n<e[t].mPoints.length+1){const e=n-1,a=r[t][e],c=a.get(s)||{fx:0,fy:0};a.set(s,{fx:c.fx+o,fy:c.fy+i})}};for(let t=0;t<n;t++)for(let o=t+1;o<n;o++){const n=e[t],r=e[o],c=[n.start,...n.mPoints,n.end],h=[r.start,...r.mPoints,r.end],d=[],l=[];for(let t=0;t<c.length-1;t++)d.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&&l.push({point:t,layers:[t.z1,t.z2],index:e})});const u=[],p=[];for(let t=0;t<h.length-1;t++)u.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&&p.push({point:t,layers:[t.z1,t.z2],index:e})});for(const e of d)for(const n of u)if(e.layer===n.layer){if(wt(e.p1,e.p2,n.p1,n.p2)<i)continue;const s={x:(e.p1.x+e.p2.x)/2,y:(e.p1.y+e.p2.y)/2},r={x:(n.p1.x+n.p2.x)/2,y:(n.p1.y+n.p2.y)/2},c=s.x-r.x,h=s.y-r.y,d=c*c+h*h;if(d>i){const s=Math.sqrt(d),r=(Math.exp(-6*s),`seg:${o}:${n.p1Idx}:${n.p2Idx}`),c=`seg:${t}:${e.p1Idx}:${e.p2Idx}`,h=(t,e,n,s,o,r,c)=>{const h=Ot(t,n.p1,n.p2),d=t.x-h.x,l=t.y-h.y,u=d*d+l*l;if(u<=i)return;const p=Math.sqrt(u),m=.02*Math.exp(-6*p),f=d/p*m,g=l/p*m;a(s,e,r,f,g),a(o,n.p1Idx,c,-f/2,-g/2),a(o,n.p2Idx,c,-f/2,-g/2)};h(e.p1,e.p1Idx,n,t,o,r,c),h(e.p2,e.p2Idx,n,t,o,r,c),h(n.p1,n.p1Idx,e,o,t,c,r),h(n.p2,n.p2Idx,e,o,t,c,r)}}for(const e of l)for(const n of u)if(e.layers.includes(n.layer)){const r=Ot(e.point,n.p1,n.p2),c=e.point.x-r.x,h=e.point.y-r.y,d=c*c+h*h;if(d>i){const r=Math.sqrt(d);let l=2,u=r;r<this.viaDiameter/2?(l*=4,u=Math.max(i,r)):u=Math.max(i,r-this.viaDiameter/2);const p=l*s*Math.exp(-6*u),m=c/r*p,f=h/r*p,g=`seg:${o}:${n.p1Idx}:${n.p2Idx}`;a(t,e.index,g,m,f);const y=`via:${t}:${e.index}`;a(o,n.p1Idx,y,-m/2,-f/2),a(o,n.p2Idx,y,-m/2,-f/2)}}for(const e of p)for(const n of d)if(e.layers.includes(n.layer)){const r=Ot(e.point,n.p1,n.p2),c=e.point.x-r.x,h=e.point.y-r.y,d=c*c+h*h;if(d>i){const r=Math.sqrt(d);let l=2,u=r;r<this.viaDiameter/2?(l*=4,u=Math.max(i,r)):u=Math.max(i,r-this.viaDiameter/2);const p=l*s*Math.exp(-6*u),m=c/r*p,f=h/r*p,g=`seg:${t}:${n.p1Idx}:${n.p2Idx}`;a(o,e.index,g,m,f);const y=`via:${o}:${e.index}`;a(t,n.p1Idx,y,-m/2,-f/2),a(t,n.p2Idx,y,-m/2,-f/2)}}for(const e of l)for(const n of p){if(e.layers.filter(t=>n.layers.includes(t)).length>0){const r=e.point.x-n.point.x,c=e.point.y-n.point.y,h=r*r+c*c;if(h>i){const d=Math.sqrt(h);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(i,d)):u=Math.max(i,d-this.viaDiameter);const p=l*s*Math.exp(-6*u),m=r/d*p,f=c/d*p,g=`via:${o}:${n.index}`,y=`via:${t}:${e.index}`;a(t,e.index,g,m,f),a(o,n.index,y,-m,-f)}}}}for(let t=0;t<n;t++){const n=e[t],o=[n.start,...n.mPoints,n.end],r=[];if(o.forEach((t,e)=>{t.z1!==t.z2&&r.push({point:t,layers:[t.z1,t.z2],index:e})}),!(r.length<2))for(let e=0;e<r.length;e++)for(let n=e+1;n<r.length;n++){const o=r[e],c=r[n],h=o.point.x-c.point.x,d=o.point.y-c.point.y,l=h*h+d*d;if(l>i){const e=Math.sqrt(l);let n=2,r=e;e<this.viaDiameter?(n*=4,r=Math.max(i,e)):r=Math.max(i,e-this.viaDiameter);const u=n*s*Math.exp(-6*r),p=h/e*u,m=d/e*u,f=`via:${t}:${c.index}`,g=`via:${t}:${o.index}`;a(t,o.index,f,p,m),a(t,c.index,g,-p,-m)}}}const c=e.map(t=>({...t,mPoints:t.mPoints.map(t=>({...t}))}));let h=!1;for(let t=0;t<n;t++)for(let e=0;e<c[t].mPoints.length;e++){const n=c[t].mPoints[e],s=r[t][e],a={fx:0,fy:0};for(const t of s.values())a.fx+=t.fx,a.fy+=t.fy;const d=n.z1!==n.z2;let l=n.x+a.fx,u=n.y+a.fy;if(d){const t=this.viaDiameter/2;let e=0,s=0;const i=this.viaDiameter/2+this.BOUNDARY_PADDING,r=this.bounds.minX+i,c=this.bounds.maxX-i,h=this.bounds.minY+i,d=this.bounds.maxY-i,p=r+t-n.x,m=n.x-(c-t),f=h+t-n.y,g=n.y-(d-t);p>0?e=o*(Math.exp(p/(2*this.obstacleMargin))-1):m>0&&(e=-.008*(Math.exp(m/(2*this.obstacleMargin))-1)),f>0?s=o*(Math.exp(f/(2*this.obstacleMargin))-1):g>0&&(s=-.008*(Math.exp(g/(2*this.obstacleMargin))-1)),a.fx+=e,a.fy+=s,l=n.x+a.fx,u=n.y+a.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(a.fx)<i&&Math.abs(a.fy)<i||(Math.abs(n.x-l)>i||Math.abs(n.y-u)>i)&&(n.x=l,n.y=u,h=!0)}if(!h)return[];const d=this.computeMinGapBtwPolyLines(c),l=this.computeG(c,t),u=this.computeH({minGaps:d,forces:r});return[{polyLines:c,g:l,h:u,f:Math.round(5*l)/5+u,minGaps:d,forces:r,viaCount:t.viaCount}]}checkIfSolved(t){const e=t.minGaps.every(t=>t>=this.obstacleMargin),n=t.polyLines.every(t=>t.mPoints.every(t=>{const e=(t.z1!==t.z2?this.viaDiameter/2:this.traceWidth/2)+this.BOUNDARY_PADDING;return((t,e,n=0)=>t.x>=e.minX+n&&t.x<=e.maxX-n&&t.y>=e.minY+n&&t.y<=e.maxY-n)(t,this.bounds,e)}));return e&&n}tryFinalAcceptance(){const t=this.hyperParameters?.MINIMUM_FINAL_ACCEPTANCE_GAP??void 0;if(void 0===t||null===this.lastCandidate||0===this.lastCandidate.minGaps.length)return;return Math.min(...this.lastCandidate.minGaps)>=t?(this.solved=!0,void this._setSolvedRoutes()):void 0}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return this.failed=!0,void(this.error="No candidates left")}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();if(!t)return void(this.failed=!0);const e=this.getNeighbors(t);for(const t of e)this.insertCandidate(t)}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"MultiHeadPolyLineIntraNodeSolver Visualization"};t.lines.push({points:[{x:this.bounds.minX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.minY}],strokeColor:"gray"});const e=this.lastCandidate??this.candidates[0];if(e?.hasClosedSameLayerFace){const e=.1*(this.bounds.maxX-this.bounds.minX),n=.1*(this.bounds.maxY-this.bounds.minY);t.rects.push({center:{x:this.bounds.maxX+.6*e,y:this.bounds.maxY+.6*n},width:e,height:n,fill:"red",label:"HAS CLOSED FACE"})}for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:`${e.connectionName} (Port z=${e.z??0})`,color:this.colorMap[e.connectionName]??"blue"});return e&&e.polyLines.forEach((n,s)=>{const o=this.colorMap[n.connectionName]??"purple",i=[n.start,...n.mPoints,n.end];for(let e=0;e<i.length-1;e++){const s=i[e],r=i[e+1],a=s.z2,c=0===a,h=c?o:it(o,.5);t.lines.push({points:[s,r],strokeColor:h,strokeWidth:this.traceWidth,strokeDash:c?void 0:[.15,.15],label:`${n.connectionName} segment (z=${a})`})}i.forEach((r,a)=>{const c=r.z1!==r.z2,h=r.z1,d=a>0&&a<i.length-1;let l="",u="";if(d){const o=a-1,i=e.forces?.[s]?.[o];if(i&&i.size>0){const s={fx:0,fy:0};i.forEach((i,a)=>{if(s.fx+=i.fx,s.fy+=i.fy,Math.abs(i.fx)>1e-6||Math.abs(i.fy)>1e-6){const s=a.split(":"),c=s[0],h=parseInt(s[1],10),d=e.polyLines[h],l=this.colorMap[d.connectionName]??"gray",u=20,p={x:r.x+i.fx*u,y:r.y+i.fy*u};let m=d.connectionName;if("via"===c){m+=` Via ${parseInt(s[2],10)}`}else if("seg"===c){m+=` Seg ${parseInt(s[2],10)}-${parseInt(s[3],10)}`}t.lines.push({points:[r,p],strokeColor:l,strokeWidth:.02,strokeDash:"2,2",label:`Force by ${m} on ${n.connectionName} mPoint ${o}`})}}),(Math.abs(s.fx)>1e-6||Math.abs(s.fy)>1e-6)&&(u=`\nNet Force: (${s.fx.toFixed(3)}, ${s.fy.toFixed(3)})`)}}if(c)l=`Via (${n.connectionName} z=${r.z1} -> z=${r.z2})${u}`,t.circles.push({center:r,radius:this.viaDiameter/2,fill:it(o,.5),label:l});else if(d){const e=0===h?o:it(o,.5);l=`mPoint (${n.connectionName} z=${h})${u}`,t.circles.push({center:r,radius:this.cellSize/8,fill:e,label:l})}})}),t}_setSolvedRoutes(){if(!this.solved||!this.lastCandidate)return[];const t=[];for(const e of this.lastCandidate.polyLines){const n=[],s=[],o=[e.start,...e.mPoints,e.end];for(let t=0;t<o.length;t++){const e=o[t];n.push({x:e.x,y:e.y,z:e.z1}),e.z1!==e.z2&&(s.push({x:e.x,y:e.y}),n.push({x:e.x,y:e.y,z:e.z2}))}t.push({connectionName:e.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:n,vias:s})}this.solvedRoutes=t}},we=class extends Re{computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){const{minGaps:e}=t;let n=0;for(const t of e)t<0&&(n+=this.obstacleMargin),t<this.obstacleMargin&&(n+=this.obstacleMargin-t);return.011*n}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return void(this.failed=!0)}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();let e=!1,n=0;const s=void 0===t.magForceApplied?1:10;for(let o=0;o<s;o++){const s=this.applyForcesToPolyLines(t.polyLines);if(n+=s.magForceApplied,e=s.lastStepMoved,!s.lastStepMoved)break}if(t.magForceApplied=n,t.minGaps=this.computeMinGapBtwPolyLines(t.polyLines),this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();t.g=this.computeG(t.polyLines,t),t.h=this.computeH(t),t.f=t.g+t.h,e&&this.insertCandidate(t)}applyForcesToPolyLines(t){let e=0;const n=t.length,s=.02,o=.008,i=1e-6,r=Array.from({length:n},(e,n)=>Array.from({length:t[n].mPoints.length},()=>({fx:0,fy:0}))),a=(e,n,s,o)=>{if(n>0&&n<t[e].mPoints.length+1){const t=n-1;r[e][t].fx+=s,r[e][t].fy+=o}},c=(t,e,n,s,o)=>{const r=Ot(t,n.p1,n.p2),c=t.x-r.x,h=t.y-r.y,d=c*c+h*h;if(d<=i)return;const l=Math.sqrt(d),u=.02*Math.exp(-6*l),p=c/l*u,m=h/l*u;a(s,e,p,m),a(o,n.p1Idx,-p/2,-m/2),a(o,n.p2Idx,-p/2,-m/2)};for(let e=0;e<n;e++)for(let o=e+1;o<n;o++){const n=t[e],r=t[o],h=[n.start,...n.mPoints,n.end],d=[r.start,...r.mPoints,r.end],l=[],u=[];for(let t=0;t<h.length-1;t++)l.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&&u.push({point:t,layers:[t.z1,t.z2],index:e})});const p=[],m=[];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&&m.push({point:t,layers:[t.z1,t.z2],index:e})});for(const t of l)for(const n of p)if(t.layer===n.layer){wt(t.p1,t.p2,n.p1,n.p2);c(t.p1,t.p1Idx,n,e,o),c(t.p2,t.p2Idx,n,e,o),c(n.p1,n.p1Idx,t,o,e),c(n.p2,n.p2Idx,t,o,e)}for(const t of u)for(const n of p)if(t.layers.includes(n.layer)){const r=Ot(t.point,n.p1,n.p2),c=t.point.x-r.x,h=t.point.y-r.y,d=c*c+h*h;if(d>i){const r=Math.sqrt(d);let l=2,u=r;r<this.viaDiameter/2?(l*=4,u=Math.max(i,r)):u=Math.max(i,r-this.viaDiameter/2);const p=l*s*Math.exp(-6*u),m=c/r*p,f=h/r*p;a(e,t.index,m,f),a(o,n.p1Idx,-m/2,-f/2),a(o,n.p2Idx,-m/2,-f/2)}}for(const t of m)for(const n of l)if(t.layers.includes(n.layer)){const r=Ot(t.point,n.p1,n.p2),c=t.point.x-r.x,h=t.point.y-r.y,d=c*c+h*h;if(d>i){const r=Math.sqrt(d);let l=2,u=r;r<this.viaDiameter/2?(l*=4,u=Math.max(i,r)):u=Math.max(i,r-this.viaDiameter/2);const p=l*s*Math.exp(-6*u),m=c/r*p,f=h/r*p;a(o,t.index,m,f),a(e,n.p1Idx,-m/2,-f/2),a(e,n.p2Idx,-m/2,-f/2)}}for(const t of u)for(const n of m){if(t.layers.filter(t=>n.layers.includes(t)).length>0){const r=t.point.x-n.point.x,c=t.point.y-n.point.y,h=r*r+c*c;if(h>i){const d=Math.sqrt(h);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(i,d)):u=Math.max(i,d-this.viaDiameter);const p=l*s*Math.exp(-6*u),m=r/d*p,f=c/d*p;a(e,t.index,m,f),a(o,n.index,-m,-f)}}}}for(let e=0;e<n;e++){const n=t[e],o=[n.start,...n.mPoints,n.end],r=[];if(o.forEach((t,e)=>{t.z1!==t.z2&&r.push({point:t,layers:[t.z1,t.z2],index:e})}),!(r.length<2))for(let t=0;t<r.length;t++)for(let n=t+1;n<r.length;n++){const o=r[t],c=r[n],h=o.point.x-c.point.x,d=o.point.y-c.point.y,l=h*h+d*d;if(l>i){const t=Math.sqrt(l);let n=2,r=t;t<this.viaDiameter?(n*=4,r=Math.max(i,t)):r=Math.max(i,t-this.viaDiameter);const u=n*s*Math.exp(-6*r),p=h/t*u,m=d/t*u;a(e,o.index,p,m),a(e,c.index,-p,-m)}}}let h=!1;for(let s=0;s<n;s++)for(let n=0;n<t[s].mPoints.length;n++){const a=t[s].mPoints[n],c=r[s][n],d=a.z1!==a.z2;let l=c.fx,u=c.fy,p=a.x+l,m=a.y+u;if(d){const t=this.viaDiameter/2;let e=0,n=0;const s=this.viaDiameter/2+this.BOUNDARY_PADDING,i=this.bounds.minX+s,r=this.bounds.maxX-s,c=this.bounds.minY+s,h=this.bounds.maxY-s,d=i+t-a.x,f=a.x-(r-t),g=c+t-a.y,y=a.y-(h-t);d>0?e=o*(Math.exp(d/(2*this.obstacleMargin))-1):f>0&&(e=-.008*(Math.exp(f/(2*this.obstacleMargin))-1)),g>0?n=o*(Math.exp(g/(2*this.obstacleMargin))-1):y>0&&(n=-.008*(Math.exp(y/(2*this.obstacleMargin))-1)),l+=e,u+=n,p=a.x+l,m=a.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)),m=Math.max(this.bounds.minY+t,Math.min(this.bounds.maxY-t,m))}if(Math.abs(l)<i&&Math.abs(u)<i)continue;e+=Math.sqrt(l*l+u*u),(Math.abs(a.x-p)>i||Math.abs(a.y-m)>i)&&(a.x=p,a.y=m,h=!0)}return{lastStepMoved:h,magForceApplied:e}}},Ae=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 Oe=class extends we{constructor(t){super(t),this.MAX_ITERATIONS=1e3}createInitialCandidateFromSeed(t){const e=new ce({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,hyperParameters:{SHUFFLE_SEED:t},viaDiameter:this.viaDiameter});if(e.solve(),e.failed||!e.solved)return this.failed=!0,this.error=`ViaPossibilitiesSolver2 failed with: ${e.error}`,null;const n=[];let s=0;for(const[t,o]of e.completedPaths.entries()){if(o.length<2){console.warn(`Skipping connection "${t}" due to insufficient points (${o.length}) in ViaPossibilitiesSolver2 path.`);continue}const e=o[0],i=o[o.length-1],r=o.slice(1,-1),a=[];let c=0,h=e.z;for(let t=0;t<r.length;t++){const e=r[t],n=t+1<r.length?r[t+1]:i,s=h,o=t+1<r.length&&e.x===n.x&&e.y===n.y&&e.z!==n.z?n.z:e.z;a.push({x:e.x,y:e.y,z1:s,z2:o}),s!==o?(c++,t++,h=o):h=e.z}s+=c;const d=this.SEGMENTS_PER_POLYLINE;let l=a.length+1;for(;l<d;){let n=-1,s=-1,o=null,r=null;const c=[{...e,z1:e.z,z2:e.z,connectionName:t},...a,{...i,z1:i.z,z2:i.z,connectionName:t}];for(let t=0;t<c.length-1;t++){const e=c[t],i=c[t+1];if(e.x===i.x&&e.y===i.y)continue;const a=St(e,i);a>n&&(n=a,s=t,o=e,r=i)}if(-1===s||!o||!r){console.warn(`Could not find longest segment for ${t} while trying to reach ${d} segments.`);break}const h=(o.x+r.x)/2,u=(o.y+r.y)/2,p=o.z2,m={x:h,y:u,z1:p,z2:p};a.splice(s,0,m),l++}n.push({connectionName:t,start:{...e,z1:e.z,z2:e.z},end:{...i,z1:i.z,z2:i.z},mPoints:a})}if(0===n.length)return this.failed=!0,this.error="No valid polylines generated from ViaPossibilitiesSolver2.",console.error(this.error),null;const o=this.computeMinGapBtwPolyLines(n),i=this.computeH({minGaps:o,forces:[]}),r={polyLines:n,g:0,h:i,f:0+i,viaCount:s,minGaps:o};return r.g=this.computeG(n,r),r.f=r.g+r.h,r}setupInitialPolyLines(){this.candidates=[];const t=Math.min(2e3,function(t){if(!Number.isInteger(t)||t<0)throw new RangeError("n must be a non-negative integer");let e=1;for(let n=2;n<=t;n++)e*=n;return e}(this.uniqueConnections)),e=new Set;for(let n=0;n<t;n++){const t=this.createInitialCandidateFromSeed(n);if(!t)continue;const s=Ae(t.polyLines);e.has(s)||(e.add(s),this.candidates.push(t))}this.candidates.sort((t,e)=>t.f-e.f)}},ze=class extends Zt{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"],["closedFormSingleTrace"],["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:"closedFormSingleTrace",possibleValues:[{CLOSED_FORM_SINGLE_TRANSITION:!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 Jt({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING?new ie({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.CLOSED_FORM_SINGLE_TRANSITION?new re({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.MULTI_HEAD_POLYLINE_SOLVER?new Oe({nodeWithPortPoints:this.nodeWithPortPoints,connMap:this.connMap,hyperParameters:t,viaDiameter:this.constructorParams.viaDiameter}):new Vt({...this.constructorParams,hyperParameters:t})}onSolve(t){this.solvedRoutes=t.solver.solvedRoutes.map(t=>{const e=this.nodeWithPortPoints.portPoints.find(e=>e.connectionName===t.connectionName);return e?.rootConnectionName?{...t,rootConnectionName:e.rootConnectionName}:t})}};function De(t,e,n){const s=[];let o=null;for(let i=0;i<t.length;i++){const r=t[i];o?o.z===r.z?o.points.push({x:r.x,y:r.y}):(s.push(o),o={points:[{x:r.x,y:r.y}],z:r.z,connectionName:e,color:n}):o={points:[{x:r.x,y:r.y}],z:r.z,connectionName:e,color:n},i===t.length-1&&o&&s.push(o)}return s}var Le=class extends y{unsolvedNodePortPoints;routes;colorMap;defaultViaDiameter=.6;defaultTraceThickness=.15;viaDiameter;traceWidth;failedSolvers;activeSubSolver=null;connMap;constructor({nodePortPoints:t,colorMap:e,connMap:n,viaDiameter:s,traceWidth:o}){super(),this.unsolvedNodePortPoints=t,this.colorMap=e??{},this.connMap=n,this.routes=[],this.failedSolvers=[],this.MAX_ITERATIONS=1e6,this.viaDiameter=s??this.defaultViaDiameter,this.traceWidth=o??this.defaultTraceThickness}_step(){if(this.updateCacheStats(),this.activeSubSolver)return this.activeSubSolver.step(),this.activeSubSolver.solved?(this.routes.push(...this.activeSubSolver.solvedRoutes),this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSolvers.push(this.activeSubSolver),this.activeSubSolver=null),void this.updateCacheStats();if(0===this.unsolvedNodePortPoints.length)return this.failedSolvers.length>0?(this.solved=!1,this.failed=!0,this.error=`Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0,5).map(t=>t.nodeWithPortPoints.capacityMeshNodeId)}. err0: ${this.failedSolvers[0].error}.`,void this.updateCacheStats()):(this.solved=!0,void this.updateCacheStats());const t=this.unsolvedNodePortPoints.pop();this.activeSubSolver=new ze({nodeWithPortPoints:t,colorMap:this.colorMap,connMap:this.connMap,viaDiameter:this.viaDiameter,traceWidth:this.traceWidth}),this.updateCacheStats()}updateCacheStats(){const t=ut();this.stats.intraNodeCacheHits=t.cacheHits,this.stats.intraNodeCacheMisses=t.cacheMisses}visualize(){let t={lines:[],points:[],rects:[],circles:[]};for(const e of this.routes){const n=De(e.route,e.connectionName,this.colorMap[e.connectionName]);for(const s of n)t.lines.push({points:s.points,label:s.connectionName,strokeColor:0===s.z?s.color:it(s.color,.75),layer:`z${s.z}`,strokeWidth:e.traceThickness,strokeDash:0!==s.z?"10, 5":void 0});for(const n of e.vias)t.circles.push({center:n,layer:"z0,1",radius:e.viaDiameter/2,fill:this.colorMap[e.connectionName],label:`${e.connectionName} via`})}for(const e of this.failedSolvers){const n=e.nodeWithPortPoints,s=.1*n.width,o=.1*n.height;t.rects.push({center:{x:n.center.x-s/2,y:n.center.y-o/2},layer:"did_not_connect",width:s,height:o,fill:"red",label:`Failed: ${n.capacityMeshNodeId}`});const i={};for(const t of n.portPoints)i[t.connectionName]||(i[t.connectionName]=[]),i[t.connectionName].push({x:t.x,y:t.y,z:t.z});for(const[e,n]of Object.entries(i))for(let e=0;e<n.length-1;e++){const s=n[e],o=n[e+1];t.lines.push({points:[s,o],strokeColor:"red",strokeDash:"10, 5",layer:"did_not_connect"})}}return this.activeSubSolver&&(t=g(t,this.activeSubSolver.visualize())),t}},Fe=class{netMap;idToNetMap;constructor(t){this.netMap=t,this.idToNetMap={};for(const[e,n]of Object.entries(t))for(const t of n)this.idToNetMap[t]=e}addConnections(t){for(const e of t){const t=new Set;for(const n of e){const e=this.idToNetMap[n];e&&t.add(e)}let n;if(0===t.size)n=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[n]=[];else if(1===t.size)n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(const e of t)if(e!==n){this.netMap[n].push(...this.netMap[e]),this.netMap[e]=this.netMap[n];for(const t of this.netMap[n])this.idToNetMap[t]=n}}for(const t of e)this.netMap[n].includes(t)||this.netMap[n].push(t),this.idToNetMap[t]=n}}getIdsConnectedToNet(t){return this.netMap[t]||[]}getNetConnectedToId(t){return this.idToNetMap[t]}areIdsConnected(t,e){if(t===e)return!0;const n=this.getNetConnectedToId(t);if(!n)return!1;const s=this.getNetConnectedToId(e);return!!s&&(n===s||s===t||s===t)}areAllIdsConnected(t){const e=this.getNetConnectedToId(t[0]);for(const n of t){const t=this.getNetConnectedToId(n);if(void 0===t)return!1;if(t!==e)return!1}return!0}},Xe=(t,e)=>"top"===t?0:"bottom"===t?e-1:parseInt(t.slice(5)),Ye=t=>`${Math.round(100*t.x)},${Math.round(100*t.y)}`,$e=t=>{const e=new Fe({});for(const n of t.connections){if(n.rootConnectionName&&e.addConnections([[n.name,n.rootConnectionName]]),n.netConnectionName&&e.addConnections([[n.name,n.netConnectionName]]),n.mergedConnectionNames)for(const t of n.mergedConnectionNames)e.addConnections([[n.name,t]]);for(const s of n.pointsToConnect)e.addConnections([[n.name,`${Ye(s)}:${"layers"in s?s.layers.map(e=>Xe(e,t.layerCount)).sort().join("-"):Xe(s.layer,t.layerCount)}`]]),"pcb_port_id"in s&&s.pcb_port_id&&e.addConnections([[n.name,s.pcb_port_id]])}for(const n of t.obstacles){const s=n.offBoardConnectsTo??[],o=Array.from(new Set([n.obstacleId,...n.connectedTo,...s,`${Ye(n.center)}:${n.layers.map(e=>Xe(e,t.layerCount)).sort().join("-")}`].filter(Boolean)));o.length>0&&e.addConnections([o])}return e},ke=(t,e=1,n={})=>{const s=n.viaDiameter??.6,o=n.obstacleMargin??.2,i=(("width"in t?t.width:t)/(s/2+o)/2)**1.1*e;return 1===t.availableZ?.length&&i>1?1:i},Be=(t,e=.5,n=16)=>{let s=0,o=t;for(;s<n;){if(ke({width:o})<=e)break;o/=2,s++}return Math.max(1,s)},je=(t,e)=>{if(1===t&&1===e)return"inner1";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}`},We=(t,e)=>{const n=[];if(0===t.route.length)return n;let s=[],o=t.route[0].z;for(let i=0;i<t.route.length;i++){const r=t.route[i];if(r.z!==o){const i=je(o,e);for(const e of s)n.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:i});if(t.vias.some(t=>Math.abs(t.x-r.x)<.001&&Math.abs(t.y-r.y)<.001)){const t=je(o,e),s=je(r.z,e);n.push({route_type:"via",x:r.x,y:r.y,from_layer:t,to_layer:s})}s=[r],o=r.z}else s.push(r)}const i=je(o,e);for(const e of s)n.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:i});if(t.jumpers&&t.jumpers.length>0){const s=je(t.route[0]?.z??0,e);for(const e of t.jumpers)n.push({route_type:"jumper",start:e.start,end:e.end,footprint:e.footprint,layer:s})}return n};function He(t){return"layers"in t&&Array.isArray(t.layers)}function Ue(t){return He(t)?t.layers[0]:t.layer}function Ve(t){return He(t)?t.layers:[t.layer]}var Ze={"0603":{length:1.65,width:.95,padLength:.8,padWidth:.95},1206:{length:3.2,width:1.6,padLength:.6,padWidth:1.6},"1206x4_pair":{length:2.7,width:.5,padLength:.8,padWidth:.5}};function Ge(t,e={}){const n=[],s=[],o=e.color??"gray",i=e.label,r=Ze[t.footprint]??Ze["0603"],a=t.end.x-t.start.x,c=t.end.y-t.start.y,h=Math.abs(a)>Math.abs(c),d=h?r.padLength:r.padWidth,l=h?r.padWidth:r.padLength;return n.push({center:t.start,width:d,height:l,fill:it(o,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper",label:i?`${i} (start)`:void 0}),n.push({center:t.end,width:d,height:l,fill:it(o,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper",label:i?`${i} (end)`:void 0}),s.push({points:[t.start,t.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*r.padWidth,layer:"jumper-body"}),{rects:n,lines:s}}function Je(t,e={}){const n={rects:[],lines:[]};for(const s of t){const{rects:t,lines:o}=Ge(s,e);n.rects.push(...t),n.lines.push(...o)}return n}var qe=1e5,Ke=.001,Qe=class extends y{mergedHdRoute;remainingHdRoutes;start;end;colorMap;constructor(t){if(super(),this.remainingHdRoutes=[...t.hdRoutes],this.colorMap=t.colorMap??{},0===t.hdRoutes.length){this.start=t.start,this.end=t.end;const e=[{x:t.start.x,y:t.start.y,z:t.start.z}],n=[];return t.start.z!==t.end.z&&(e.push({x:t.start.x,y:t.start.y,z:t.end.z}),n.push({x:t.start.x,y:t.start.y})),e.push({x:t.end.x,y:t.end.y,z:t.end.z}),this.mergedHdRoute={connectionName:t.connectionName,rootConnectionName:t.hdRoutes[0]?.rootConnectionName,route:e,vias:n,jumpers:[],viaDiameter:t.defaultViaDiameter??.6,traceThickness:t.defaultTraceThickness??.15},void(this.solved=!0)}let e=1/0,n=t.hdRoutes[0],s="start-to-end";for(const o of t.hdRoutes){const i=o.route[0],r=o.route[o.route.length-1],a=St(t.start,i),c=St(t.start,r),h=St(t.end,i),d=St(t.end,r),l=Math.min(a,c,h,d);l<e&&(e=l,n=o,s=Math.min(h,d)<Math.min(a,c)?"end-to-start":"start-to-end")}"start-to-end"===s?(this.start=t.start,this.end=t.end):(this.start=t.end,this.end=t.start);const o=n.route[0],i=n.route[n.route.length-1],r=St(this.start,o)<=St(this.start,i)?o:i;this.mergedHdRoute={connectionName:t.connectionName,rootConnectionName:n.rootConnectionName,route:[{x:this.start.x,y:this.start.y,z:r.z}],vias:[],jumpers:[],viaDiameter:n.viaDiameter,traceThickness:n.traceThickness}}getDisjointedRoute(){for(const t of this.remainingHdRoutes){if([t.route[0],t.route[t.route.length-1]].some(e=>!this.remainingHdRoutes.some(n=>{if(n===t)return!1;return[n.route[0],n.route[n.route.length-1]].some(t=>t.z===e.z&&St(e,t)<.001)})))return{firstRoute:t}}return{firstRoute:this.remainingHdRoutes[0]}}_step(){if(0===this.remainingHdRoutes.length){const t=this.mergedHdRoute.route[this.mergedHdRoute.route.length-1];return this.mergedHdRoute.route.push({x:this.end.x,y:this.end.y,z:t.z}),void(this.solved=!0)}const t=this.mergedHdRoute.route[this.mergedHdRoute.route.length-1];let e=-1,n="first",s=1/0;for(let o=0;o<this.remainingHdRoutes.length;o++){const i=this.remainingHdRoutes[o],r=i.route[0],a=i.route[i.route.length-1],c=St(t,r),h=St(t,a);let d=1/0;d=t.z===r.z?c<Ke?c:qe+c:c<Ke?1e3+c:qe+c,d<s&&(s=d,e=o,n="first");let l=1/0;l=t.z===a.z?h<Ke?h:qe+h:h<Ke?1e3+h:qe+h,l<s&&(s=l,e=o,n="last")}if(-1===e)return void(this.remainingHdRoutes=[]);const o=this.remainingHdRoutes[e];let i;this.remainingHdRoutes.splice(e,1),i="first"===n?o.route:[...o.route].reverse(),i.length>0&&St(t,i[0])<Ke&&t.z===i[0].z?this.mergedHdRoute.route.push(...i.slice(1)):this.mergedHdRoute.route.push(...i),this.mergedHdRoute.vias.push(...o.vias),o.jumpers&&this.mergedHdRoute.jumpers.push(...o.jumpers)}visualize(){const t={points:[],lines:[],circles:[],rects:[],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"});if(this.mergedHdRoute.jumpers&&this.mergedHdRoute.jumpers.length>0){const e=Je(this.mergedHdRoute.jumpers,{color:"green",label:this.mergedHdRoute.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}for(const[e,n]of this.remainingHdRoutes.entries()){const s=this.colorMap[n.connectionName]??"gray";n.route.length>1&&t.lines?.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:s});for(let o=0;o<n.route.length;o++){const i=n.route[o];t.points?.push({x:i.x+(e%2-.5)/500+(o%8-4)/1e3,y:i.y+(e%2-.5)/500+(o%8-4)/1e3,color:s,label:`Route ${n.connectionName} ${i===n.route[0]?"First":i===n.route[n.route.length-1]?"Last":""}`})}for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s});if(n.jumpers&&n.jumpers.length>0){const e=Je(n.jumpers,{color:s,label:n.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}return t}},tn=class{netMap;idToNetMap;constructor(t){this.netMap=t,this.idToNetMap={};for(const[e,n]of Object.entries(t))for(const t of n)this.idToNetMap[t]=e}addConnections(t){for(const e of t){const t=new Set;for(const n of e){const e=this.idToNetMap[n];e&&t.add(e)}let n;if(0===t.size)n=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[n]=[];else if(1===t.size)n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(const e of t)if(e!==n){const t=this.netMap[n],s=this.netMap[e];if(t&&s){t.push(...s),this.netMap[e]=t;for(const e of t)this.idToNetMap[e]=n}}}for(const t of e){const e=this.netMap[n];e&&!e.includes(t)&&e.push(t),this.idToNetMap[t]=n}}}getIdsConnectedToNet(t){return this.netMap[t]||[]}getNetConnectedToId(t){return this.idToNetMap[t]}areIdsConnected(t,e){if(t===e)return!0;const n=this.getNetConnectedToId(t);if(!n)return!1;const s=this.getNetConnectedToId(e);return!!s&&(n===s||s===t||s===t)}areAllIdsConnected(t){if(0===t.length)return!0;const e=this.getNetConnectedToId(t[0]);if(!e)return!1;for(const n of t){const t=this.getNetConnectedToId(n);if(void 0===t)return!1;if(t!==e)return!1}return!0}},en=t=>`${Math.round(100*t.x)},${Math.round(100*t.y)},${Math.round(100*t.z)}`,nn=class extends y{unsolvedRoutes;activeSolver=null;mergedHdRoutes=[];colorMap={};defaultTraceThickness;defaultViaDiameter;constructor(t){super(),this.colorMap=t.colorMap??{};const e=t.hdRoutes[0];this.defaultTraceThickness=e?.traceThickness??.15,this.defaultViaDiameter=e?.viaDiameter??t.defaultViaDiameter??.6;const n=new tn({}),s=[],o=new Map;for(let e=0;e<t.hdRoutes.length;e++){const n=t.hdRoutes[e],o=n.route[0],i=n.route[n.route.length-1];s.push([`route_island_${e}`,`${n.connectionName}:${en(o)}`,`${n.connectionName}:${en(i)}`])}n.addConnections(s);for(const t of s)for(const e of t.slice(1))o.set(e,(o.get(e)??0)+1);this.unsolvedRoutes=[];const i=Array.from(new Set(Object.values(n.idToNetMap)));for(const e of i){const s=n.getIdsConnectedToNet(e),i=t.hdRoutes.filter((t,e)=>s.includes(`route_island_${e}`));if(0===i.length)continue;const r=t.connections.find(t=>t.name===i[0].connectionName),a=i.flatMap(t=>[t.route[0],t.route[t.route.length-1]]),c=[];for(const t of a){const e=`${i[0].connectionName}:${en(t)}`;1===o.get(e)&&c.push(t)}if(0===c.length){console.log("no possible endpoints, can't stitch");continue}let h,d;2!==c.length?(h={...r.pointsToConnect[0],z:Xe(Ue(r.pointsToConnect[0]),t.layerCount)},d={...r.pointsToConnect[1],z:Xe(Ue(r.pointsToConnect[1]),t.layerCount)}):(h=c[0],d=c[1],St(h,r.pointsToConnect[1])<St(d,r.pointsToConnect[0])&&([h,d]=[d,h])),this.unsolvedRoutes.push({connectionName:i[0].connectionName,hdRoutes:i,start:h,end:d})}this.MAX_ITERATIONS=1e5}_step(){if(this.activeSolver)return this.activeSolver.step(),void(this.activeSolver.solved?(this.activeSolver instanceof Qe&&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 Qe({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:[],rects:[],title:"Multiple High Density Route Stitch Solver"};if(this.activeSolver){const e=this.activeSolver.visualize();e.points?.length&&t.points?.push(...e.points),e.lines?.length&&t.lines?.push(...e.lines),e.circles?.length&&t.circles?.push(...e.circles),e.rects?.length&&(t.rects||(t.rects=[]),t.rects.push(...e.rects))}for(const[e,n]of this.mergedHdRoutes.entries()){const s=this.colorMap[n.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1],r=0!==o.z?it(s,.5):s;t.lines?.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:r,strokeWidth:n.traceThickness})}for(const e of n.route){const n=0!==e.z?it(s,.5):s;t.points?.push({x:e.x,y:e.y,color:n})}for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s});if(n.jumpers&&n.jumpers.length>0){const e=Je(n.jumpers,{color:s,label:n.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}for(const e of this.unsolvedRoutes){const n=this.colorMap[e.connectionName]??"gray";t.points?.push({x:e.start.x,y:e.start.y,color:n,label:`${e.connectionName} Start (z=${e.start.z})`},{x:e.end.x,y:e.end.y,color:n,label:`${e.connectionName} End (z=${e.end.z})`}),t.lines?.push({points:[{x:e.start.x,y:e.start.y},{x:e.end.x,y:e.end.y}],strokeColor:n,strokeDash:"2 2"});for(const s of e.hdRoutes){s.route.length>1&&t.lines?.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:it(n,.5),strokeDash:"10 5"});for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n});if(s.jumpers&&s.jumpers.length>0){const e=Je(s.jumpers,{color:n,label:s.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}}return t}},sn=t=>{const e=[],n=[],s=[],o=[],i=ot(t),r=(t.minViaDiameter??.6)/2;if(t.connections)for(const e of t.connections)for(const t of e.pointsToConnect){const n=Ve(t);s.push({x:t.x,y:t.y,color:i[e.name],layer:n[0]??("z"in t?je(t.z,2):"top"),label:`${e.name} (${n.join(",")})`})}if(t.traces)for(const s of t.traces){let a=t.minTraceWidth;const c=s.route.filter(t=>"jumper"===t.route_type),h=(t,e)=>{const n=.01;for(const s of c){const o=Math.abs(t.x-s.start.x)<n&&Math.abs(t.y-s.start.y)<n&&Math.abs(e.x-s.end.x)<n&&Math.abs(e.y-s.end.y)<n,i=Math.abs(t.x-s.end.x)<n&&Math.abs(t.y-s.end.y)<n&&Math.abs(e.x-s.start.x)<n&&Math.abs(e.y-s.start.y)<n;if(o||i)return!0}return!1};for(let t=0;t<s.route.length-1;t++){const c=s.route[t],d=s.route[t+1];if("via"===c.route_type)n.push({center:{x:c.x,y:c.y},radius:r,fill:"blue",stroke:"none",layer:"z0,1"});else if("jumper"===c.route_type){const t=i[s.connection_name]??"rgba(255, 165, 0, 0.8)",n=c.footprint,r=Ze["1206x4_pair"===n?"1206x4_pair":"0603"]??Ze["0603"],a=c.end.x-c.start.x,h=c.end.y-c.start.y,d=Math.abs(a)>Math.abs(h),l=d?r.padLength:r.padWidth,u=d?r.padWidth:r.padLength;o.push({center:c.start,width:l,height:u,fill:it(t,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),o.push({center:c.end,width:l,height:u,fill:it(t,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),e.push({points:[c.start,c.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*r.padWidth,layer:"jumper-body"})}else if("wire"===c.route_type&&"wire"===d.route_type&&d.layer===c.layer){if(h({x:c.x,y:c.y},{x:d.x,y:d.y}))continue;a=c.width;const t=i[s.connection_name],n="top"===c.layer,o=t??{top:"red",bottom:"blue",inner1:"green",inner2:"yellow"}[c.layer];e.push({points:[{x:c.x,y:c.y},{x:d.x,y:d.y}],layer:`z${Xe(c.layer,2)}`,strokeWidth:a,strokeColor:n?o:it(o,.5),...n?{}:{strokeDash:"3 2"}})}}}for(const e of t.obstacles)o.push({center:e.center,width:e.width,height:e.height,fill:"rgba(255,0,0,0.5)",layer:`z${e.layers.map(t=>Xe(t,2)).join(",")}`});if(t.jumpers)for(const e of t.jumpers)for(const t of e.pads)o.push({center:t.center,width:t.width,height:t.height,fill:"rgba(255, 165, 0, 0.3)",stroke:"rgba(255, 165, 0, 0.8)",layer:"jumper"});return{rects:o,circles:n,lines:e,points:s}};function on(t,e){const n=t.center.x-t.width/2,s=t.center.x+t.width/2,o=t.center.y-t.height/2,i=t.center.y+t.height/2,r=e.center.x-e.width/2,a=e.center.x+e.width/2,c=e.center.y-e.height/2,h=e.center.y+e.height/2,d=.001,l=(Math.abs(s-r)<d||Math.abs(n-a)<d)&&Math.min(i,h)-Math.max(o,c)>=d,u=(Math.abs(i-c)<d||Math.abs(o-h)<d)&&Math.min(s,a)-Math.max(n,r)>=d;return l||u}var rn=class extends y{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)&&on(this.nodes[t],this.nodes[e])&&this.doNodesHaveSharedLayer(this.nodes[t],this.nodes[e])&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[this.nodes[t].capacityMeshNodeId,this.nodes[e].capacityMeshNodeId]})}this.handleTargetNodes(),this.solved=!0}handleTargetNodes(){const t=this.nodes.filter(t=>t._containsTarget);for(const e of t){if(this.edges.some(t=>t.nodeIds.includes(e.capacityMeshNodeId)))continue;let t=null,n=1/0;for(const s of this.nodes){if(s._containsObstacle)continue;if(s._containsTarget)continue;const o=St(e.center,s.center);o<n&&(n=o,t=s)}t&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[e.capacityMeshNodeId,t.capacityMeshNodeId]})}}doNodesHaveSharedLayer(t,e){return t.availableZ.some(t=>e.availableZ.includes(t))}visualize(){const t=new Map;for(const e of this.edges)for(const n of e.nodeIds)t.set(n,1+(t.get(n)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const n=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+n*e.width*.05,y:e.center.y-n*e.width*.05},fill:e._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}for(const t of this.edges){const n=this.nodeMap.get(t.nodeIds[0]),s=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&s?.center){const t=Math.min(...n.availableZ),o=Math.min(...s.availableZ),i={x:n.center.x+t*n.width*.05,y:n.center.y-t*n.width*.05},r={x:s.center.x+o*s.width*.05,y:s.center.y-o*s.width*.05},a=Array.from(new Set([...n.availableZ,...s.availableZ])).sort();e.lines.push({layer:`z${a.join(",")}`,points:[i,r],strokeDash:n.availableZ.join(",")===s.availableZ.join(",")?void 0:"10 5"})}}return e}},an=class{constructor(t){this.nodes=t,this.buckets=new Map;for(const e of t){const t=e.center.x-e.width/2,n=e.center.y-e.height/2,s=e.center.x+e.width/2,o=e.center.y+e.height/2;for(let i=t;i<=s;i+=this.CELL_SIZE)for(let t=n;t<=o;t+=this.CELL_SIZE){const n=this.getBucketKey(i,t),s=this.buckets.get(n);s?s.push(e):this.buckets.set(n,[e])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,n,s){const o=[],i=new Set,r=e-s/2,a=t+n/2,c=e+s/2;for(let e=t-n/2;e<=a;e+=this.CELL_SIZE)for(let t=r;t<=c;t+=this.CELL_SIZE){const n=this.getBucketKey(e,t),s=this.buckets.get(n)||[];for(const t of s)i.has(t.capacityMeshNodeId)||(i.add(t.capacityMeshNodeId),o.push(t))}return o}},cn=class extends rn{constructor(t){super(t),this.nodes=t,this.MAX_ITERATIONS=1e7,this.nodeTree=new an(this.nodes),this.currentNodeIndex=0,this.edgeSet=new Set}nodeTree;currentNodeIndex;edgeSet;_step(){if(this.currentNodeIndex>=this.nodes.length)return this.handleTargetNodes(),void(this.solved=!0);const t=this.nodes[this.currentNodeIndex],e=this.nodeTree.getNodesInArea(t.center.x,t.center.y,2*t.width,2*t.height);for(const n of e){if(!on(t,n))continue;const e=t._strawNode&&n._strawNode&&t._strawParentCapacityMeshNodeId===n._strawParentCapacityMeshNodeId;t.capacityMeshNodeId===n.capacityMeshNodeId||e||!this.doNodesHaveSharedLayer(t,n)||this.edgeSet.has(`${t.capacityMeshNodeId}-${n.capacityMeshNodeId}`)||(this.edgeSet.add(`${t.capacityMeshNodeId}-${n.capacityMeshNodeId}`),this.edgeSet.add(`${n.capacityMeshNodeId}-${t.capacityMeshNodeId}`),this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[t.capacityMeshNodeId,n.capacityMeshNodeId]}))}this.currentNodeIndex++}},hn=class{parent={};constructor(t){for(const e of t)this.parent[e]=e}find(t){return this.parent[t]===t?t:this.parent[t]=this.find(this.parent[t])}union(t,e){const n=this.find(t),s=this.find(e);n!==s&&(this.parent[s]=n)}getGroup(t){const e=this.find(t),n=[];for(const t in this.parent)this.find(t)===e&&n.push(t);return n}},dn=class{point;left=null;right=null;constructor(t){this.point=t}},ln=class{root=null;constructor(t){t.length>0&&(this.root=this.buildTree(t,0))}buildTree(t,e){const n=e%2==0?"x":"y";t.sort((t,e)=>t[n]-e[n]);const s=Math.floor(t.length/2),o=new dn(t[s]);return s>0&&(o.left=this.buildTree(t.slice(0,s),e+1)),s<t.length-1&&(o.right=this.buildTree(t.slice(s+1),e+1)),o}findNearestNeighbor(t){if(!this.root)throw new Error("Tree is empty");const e=this.root.point,n=this.distance(t,e);return this.nearestNeighborSearch(this.root,t,0,e,n),e}nearestNeighborSearch(t,e,n,s,o){if(!t)return s;const i=n%2?"x":"y",r=this.distance(e,t.point);r<o&&(s=t.point,o=r);const a=e[i]-t.point[i],c=a<=0?t.left:t.right,h=a<=0?t.right:t.left;return s=this.nearestNeighborSearch(c,e,n+1,s,o),o=this.distance(e,s),Math.abs(a)<o&&(s=this.nearestNeighborSearch(h,e,n+1,s,o)),s}findKNearestNeighbors(t,e){if(!this.root)return[];const n=[];return this.kNearestNeighborSearch(this.root,t,0,n,e),n.sort((t,e)=>t.distance-e.distance).slice(0,e).map(t=>t.point)}kNearestNeighborSearch(t,e,n,s,o){if(!t)return;const i=n%2?"x":"y",r=this.distance(e,t.point);s.push({point:t.point,distance:r});const a=e[i]-t.point[i],c=a<=0?t.left:t.right,h=a<=0?t.right:t.left;this.kNearestNeighborSearch(c,e,n+1,s,o);let d=1/0;s.length>=o&&(s.sort((t,e)=>t.distance-e.distance),d=s[o-1]?.distance||1/0),(Math.abs(a)<d||s.length<o)&&this.kNearestNeighborSearch(h,e,n+1,s,o)}distance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}},un=class{parent=new Map;rank=new Map;constructor(t){for(const e of t){const t=this.pointToKey(e);this.parent.set(t,t),this.rank.set(t,0)}}pointToKey(t){return`${t.x},${t.y}`}find(t){const e=this.pointToKey(t);if(!this.parent.has(e))throw new Error(`Point ${e} not found in DisjointSet`);let n=e;for(;n!==this.parent.get(n);)n=this.parent.get(n);let s=e;for(;s!==n;){const t=this.parent.get(s);this.parent.set(s,n),s=t}return n}union(t,e){const n=this.find(t),s=this.find(e);if(n===s)return!1;const o=this.rank.get(n)||0,i=this.rank.get(s)||0;return o<i?this.parent.set(n,s):o>i?this.parent.set(s,n):(this.parent.set(s,n),this.rank.set(n,o+1)),!0}};function pn(t){if(t.length<=1)return[];const e=new ln(t),n=[],s=Math.min(10,t.length-1);for(const o of t){const t=e.findKNearestNeighbors(o,s+1);for(const e of t){if(o.x===e.x&&o.y===e.y)continue;const t=Math.sqrt((o.x-e.x)**2+(o.y-e.y)**2);n.push({from:o,to:e,weight:t})}}n.sort((t,e)=>t.weight-e.weight);const o=new un(t),i=[];for(const e of n)if(o.union(e.from,e.to)&&(i.push(e),i.length===t.length-1))break;return i}function mn(t){if(t.pointId)return t.pointId;let e="";var n;return"layer"in(n=t)&&"string"==typeof n.layer?e=t.layer:He(t)&&t.layers&&(e=t.layers.sort().join("-")),`${t.x.toFixed(4)},${t.y.toFixed(4)},${e}`}var fn=class extends y{constructor(t,e={}){super(),this.ogSrj=t,this.colorMap=e,this.unprocessedConnections=function(t){if(0===t.length)return[];const e=t.map((t,e)=>`conn_${e}`),n=new hn(e),s=new Map;t.forEach((t,e)=>{const n=`conn_${e}`;t.pointsToConnect.forEach(t=>{const e=mn(t);s.has(e)||s.set(e,[]),s.get(e).push(n)})});for(const t of s.values())if(t.length>1){const e=t[0];for(let s=1;s<t.length;s++)n.union(e,t[s])}const o=new Map;t.forEach((t,e)=>{const s=`conn_${e}`,i=n.find(s);o.has(i)||o.set(i,[]),o.get(i).push(t)});const i=[];for(const t of o.values()){if(1===t.length){i.push(t[0]);continue}const e=new Map,n=new Set;let s=!1;const o=[],r=new Set;let a;t.forEach(t=>{t.pointsToConnect.forEach(t=>e.set(mn(t),t)),n.add(t.name),t.isOffBoard&&(s=!0),t.externallyConnectedPointIds&&o.push(...t.externallyConnectedPointIds),t.netConnectionName&&r.add(t.netConnectionName),void 0===a&&void 0!==t.nominalTraceWidth&&(a=t.nominalTraceWidth)});const c={name:Array.from(n).join("__"),mergedConnectionNames:Array.from(n),pointsToConnect:Array.from(e.values()),isOffBoard:s,externallyConnectedPointIds:o.length>0?o:void 0,netConnectionName:r.size>0?Array.from(r).join("__"):void 0,nominalTraceWidth:a};i.push(c)}return i}([...t.connections]),this.newConnections=[]}unprocessedConnections;newConnections;_step(){if(0===this.unprocessedConnections.length)return void(this.solved=!0);const t=this.unprocessedConnections.pop(),e=t.externallyConnectedPointIds??[],n=new Map;e.forEach((t,e)=>t.forEach(t=>n.set(t,e)));const s=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const s=n.get(t.pointId),o=n.get(e.pointId);return void 0!==s&&s===o};if(2===t.pointsToConnect.length){if(s(t.pointsToConnect[0],t.pointsToConnect[1]))return;return void this.newConnections.push({...t,rootConnectionName:t.name})}const o=pn(t.pointsToConnect);let i=0;for(const e of o)s(e.from,e.to)||this.newConnections.push({pointsToConnect:[e.from,e.to],name:`${t.name}_mst${i++}`,rootConnectionName:t.name,mergedConnectionNames:t.mergedConnectionNames,netConnectionName:t.netConnectionName})}getNewSimpleRouteJson(){return{...this.ogSrj,connections:this.newConnections}}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Net To Point Pairs Visualization"};return this.unprocessedConnections.forEach(e=>{e.pointsToConnect.forEach(n=>{t.points.push({x:n.x,y:n.y,color:"red",label:e.name})});const n=e.pointsToConnect.length**2,s=Yt(0),o=new Set;for(let i=0;i<Math.max(n,2*e.pointsToConnect.length);i++){const n=Math.floor(s()*e.pointsToConnect.length),i=Math.floor(s()*e.pointsToConnect.length);o.has(`${n}-${i}`)||(o.add(`${n}-${i}`),t.lines.push({points:[e.pointsToConnect[n],e.pointsToConnect[i]],strokeColor:"rgba(255,0,0,0.25)"}))}}),this.newConnections.forEach(e=>{const n=this.colorMap?.[e.name]||"blue";e.pointsToConnect.forEach(s=>{t.points.push({x:s.x,y:s.y,color:n,label:e.name})});for(let s=0;s<e.pointsToConnect.length-1;s++)for(let o=s+1;o<e.pointsToConnect.length;o++)t.lines.push({points:[e.pointsToConnect[s],e.pointsToConnect[o]],strokeColor:n})}),t}},gn=class extends fn{constructor(t,e={}){const n=t.connections.flatMap(t=>t.pointsToConnect),s=new Map;for(const t of n)t.pointId&&s.set(t.pointId,t);const o=n.map(t=>t.pointId).filter(t=>!!t),i=new hn(o),r=[];for(const e of t.connections)e.isOffBoard?e.pointsToConnect.length>=2&&e.pointsToConnect[0].pointId&&e.pointsToConnect[1].pointId&&i.union(e.pointsToConnect[0].pointId,e.pointsToConnect[1].pointId):r.push(e);super({...t,connections:r},e),this.ogSrj=t,this.colorMap=e,this.connectionPointDsu=i,this.connectionPointMap=s,this.ogSrj=t}connectionPointDsu;connectionPointMap;_findBestConnectionPointsFromDisjointSets(t,e){if(!t.pointId||!e.pointId)return{pointsToConnect:[t,e]};const n=this.connectionPointDsu.getGroup(t.pointId).map(t=>this.connectionPointMap.get(t)),s=this.connectionPointDsu.getGroup(e.pointId).map(t=>this.connectionPointMap.get(t));let o=t,i=e,r=1/0;for(const t of n)for(const e of s){const n=Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));n<r&&(r=n,o=t,i=e)}return{pointsToConnect:[o,i]}}_step(){if(0===this.unprocessedConnections.length)return void(this.solved=!0);const t=this.unprocessedConnections.pop(),e=t.externallyConnectedPointIds??[],n=new Map;e.forEach((t,e)=>t.forEach(t=>n.set(t,e)));const s=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const s=n.get(t.pointId),o=n.get(e.pointId);return void 0!==s&&s===o};if(2===t.pointsToConnect.length){if(s(t.pointsToConnect[0],t.pointsToConnect[1]))return;const e=this._findBestConnectionPointsFromDisjointSets(t.pointsToConnect[0],t.pointsToConnect[1]);return void this.newConnections.push({...t,pointsToConnect:e.pointsToConnect,rootConnectionName:t.name})}const o=pn(t.pointsToConnect);let i=0;for(const e of o){if(s(e.from,e.to))continue;const n=this._findBestConnectionPointsFromDisjointSets(e.from,e.to);this.newConnections.push({pointsToConnect:n.pointsToConnect,name:`${t.name}_mst${i++}`,rootConnectionName:t.name,mergedConnectionNames:t.mergedConnectionNames,netConnectionName:t.netConnectionName})}}};function yn(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:xn,sin:vn,PI:Sn}=Math,{tan:Pn}=Math;a(l()),a(f());function bn(t,e){if(t.points)for(const n of t.points)n.step=e;if(t.lines)for(const n of t.lines)n.step=e;if(t.rects)for(const n of t.rects)n.step=e;if(t.circles)for(const n of t.circles)n.step=e;if(t.texts)for(const n of t.texts)n.step=e;return t}var Mn=class{MAX_ITERATIONS=1e5;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};_setupDone=!1;setup(){this._setupDone||(this._setup(),this._setupDone=!0)}_setup(){}step(){if(this._setupDone||this.setup(),!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,console.error(this.error),this.failed=!0,t}!this.solved&&this.iterations>=this.MAX_ITERATIONS&&this.tryFinalAcceptance(),!this.solved&&this.iterations>=this.MAX_ITERATIONS&&(this.error=`${this.constructor.name} ran out of iterations`,console.error(this.error),this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}getOutput(){return null}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}};function Nn(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var In=class extends Mn{startTimeOfStage={};endTimeOfStage={};timeSpentOnStage={};firstIterationOfStage={};currentPipelineStageIndex=0;inputProblem;pipelineOutputs={};constructor(t){super(),this.inputProblem=t,this.MAX_ITERATIONS=1e6}_step(){const t=this.pipelineDef[this.currentPipelineStageIndex];if(!t)return void(this.solved=!0);if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved){this.endTimeOfStage[t.solverName]=performance.now(),this.timeSpentOnStage[t.solverName]=this.endTimeOfStage[t.solverName]-this.startTimeOfStage[t.solverName];const e=this.activeSubSolver.getOutput();null!==e&&(this.pipelineOutputs[t.solverName]=e),t.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStageIndex++}else this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null);return}const e=t.getConstructorParams(this);this.activeSubSolver=new t.solverClass(...e),this[t.solverName]=this.activeSubSolver,this.timeSpentOnStage[t.solverName]=0,this.startTimeOfStage[t.solverName]=performance.now(),this.firstIterationOfStage[t.solverName]=this.iterations}solveUntilStage(t){for(;this.getCurrentStageName().toLowerCase()!==t.toLowerCase()&&(this.step(),!this.failed&&!this.solved););}getCurrentStageName(){return this.pipelineDef[this.currentPipelineStageIndex]?.solverName??"none"}getStageProgress(){const t=this.pipelineDef.length;if(0===t)return 1;const e=this.activeSubSolver?.progress??0;return(this.currentPipelineStageIndex+e)/t}getStageStats(){const t={};for(const e of this.pipelineDef){const n=this.timeSpentOnStage[e.solverName]||0,s=this.firstIterationOfStage[e.solverName]||0,o=this.iterations,i=e.solverName===this.getCurrentStageName()?o-s:0,r=this.currentPipelineStageIndex>this.pipelineDef.findIndex(t=>t.solverName===e.solverName);t[e.solverName]={timeSpent:n,iterations:i,completed:r}}return t}initialVisualize(){return null}finalVisualize(){return null}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();let t=0;const e=this.initialVisualize();e&&(bn(e,0),t=1);let n=null;this.solved&&(n=this.finalVisualize());const s=[e].filter(Boolean).concat(this.pipelineDef.map((e,n)=>{const s=this[e.solverName],o=s?.visualize();return o?(bn(o,n+t),o):null}).filter(Boolean));return 0===s.length?{points:[],rects:[],lines:[],circles:[],texts:[]}:(this.solved&&n&&(bn(n,s.length+t+1),s.push(n)),1===s.length?s[0]:{points:s.flatMap(t=>t.points||[]),rects:s.flatMap(t=>t.rects||[]),lines:s.flatMap(t=>t.lines||[]),circles:s.flatMap(t=>t.circles||[]),texts:s.flatMap(t=>t.texts||[])})}preview(){return this.activeSubSolver?this.activeSubSolver.preview():super.preview()}computeProgress(){return this.getStageProgress()}getStageOutput(t){return this.pipelineOutputs[t]}getAllOutputs(){return{...this.pipelineOutputs}}hasStageOutput(t){return t in this.pipelineOutputs}getSolver(t){return this[t]}},Cn=class{constructor(){this.ids=[],this.values=[],this.length=0}clear(){this.length=0}push(t,e){let n=this.length++;for(;n>0;){const t=n-1>>1,s=this.values[t];if(e>=s)break;this.ids[n]=this.ids[t],this.values[n]=s,n=t}this.ids[n]=t,this.values[n]=e}pop(){if(0===this.length)return;const t=this.ids,e=this.values,n=t[0],s=--this.length;if(s>0){const n=t[s],o=e[s];let i=0;const r=s>>1;for(;i<r;){const n=1+(i<<1),r=n+1,a=n+(+(r<s)&+(e[r]<e[n]));if(e[a]>=o)break;t[i]=t[a],e[i]=e[a],i=a}t[i]=n,e[i]=o}return n}peek(){return this.length>0?this.ids[0]:void 0}peekValue(){return this.length>0?this.values[0]:void 0}shrink(){this.ids.length=this.values.length=this.length}},_n=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],Tn=class t{static from(e,n=0){if(n%8!=0)throw new Error("byteOffset must be 8-byte aligned.");if(!e||void 0===e.byteLength||e.buffer)throw new Error("Data must be an instance of ArrayBuffer or SharedArrayBuffer.");const[s,o]=new Uint8Array(e,n+0,2);if(251!==s)throw new Error("Data does not appear to be in a Flatbush format.");const i=o>>4;if(3!==i)throw new Error(`Got v${i} data when expected v3.`);const r=_n[15&o];if(!r)throw new Error("Unrecognized array type.");const[a]=new Uint16Array(e,n+2,1),[c]=new Uint32Array(e,n+4,1);return new t(c,a,r,void 0,e,n)}constructor(t,e=16,n=Float64Array,s=ArrayBuffer,o,i=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=i;let r=t,a=r;this._levelBounds=[4*r];do{r=Math.ceil(r/this.nodeSize),a+=r,this._levelBounds.push(4*a)}while(1!==r);this.ArrayType=n,this.IndexArrayType=a<16384?Uint16Array:Uint32Array;const c=_n.indexOf(n),h=4*a*n.BYTES_PER_ELEMENT;if(c<0)throw new Error(`Unexpected typed array class: ${n}.`);if(o)this.data=o,this._boxes=new n(o,i+8,4*a),this._indices=new this.IndexArrayType(o,i+8+h,a),this._pos=4*a,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 o=this.data=new s(8+h+a*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new n(o,8,4*a),this._indices=new this.IndexArrayType(o,8+h,a),this._pos=0,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,new Uint8Array(o,0,2).set([251,48+c]),new Uint16Array(o,2,1)[0]=e,new Uint32Array(o,4,1)[0]=t}this._queue=new Cn}add(t,e,n=t,s=e){const o=this._pos>>2,i=this._boxes;return this._indices[o]=o,i[this._pos++]=t,i[this._pos++]=e,i[this._pos++]=n,i[this._pos++]=s,t<this.minX&&(this.minX=t),e<this.minY&&(this.minY=e),n>this.maxX&&(this.maxX=n),s>this.maxY&&(this.maxY=s),o}finish(){if(this._pos>>2!==this.numItems)throw new Error(`Added ${this._pos>>2} items when expected ${this.numItems}.`);const t=this._boxes;if(this.numItems<=this.nodeSize)return t[this._pos++]=this.minX,t[this._pos++]=this.minY,t[this._pos++]=this.maxX,void(t[this._pos++]=this.maxY);const e=this.maxX-this.minX||1,n=this.maxY-this.minY||1,s=new Uint32Array(this.numItems);for(let o=0,i=0;o<this.numItems;o++){const r=t[i++],a=t[i++],c=t[i++],h=t[i++],d=Math.floor(65535*((r+c)/2-this.minX)/e),l=Math.floor(65535*((a+h)/2-this.minY)/n);s[o]=An(d,l)}Rn(s,t,this._indices,0,this.numItems-1,this.nodeSize);for(let e=0,n=0;e<this._levelBounds.length-1;e++){const s=this._levelBounds[e];for(;n<s;){const e=n;let o=t[n++],i=t[n++],r=t[n++],a=t[n++];for(let e=1;e<this.nodeSize&&n<s;e++)o=Math.min(o,t[n++]),i=Math.min(i,t[n++]),r=Math.max(r,t[n++]),a=Math.max(a,t[n++]);this._indices[this._pos>>2]=e,t[this._pos++]=o,t[this._pos++]=i,t[this._pos++]=r,t[this._pos++]=a}}}search(t,e,n,s,o){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let i=this._boxes.length-4;const r=[],a=[];for(;void 0!==i;){const c=Math.min(i+4*this.nodeSize,En(i,this._levelBounds));for(let h=i;h<c;h+=4){const c=this._boxes[h];if(n<c)continue;const d=this._boxes[h+1];if(s<d)continue;const l=this._boxes[h+2];if(t>l)continue;const u=this._boxes[h+3];if(e>u)continue;const p=0|this._indices[h>>2];i>=4*this.numItems?r.push(p):(void 0===o||o(p,c,d,l,u))&&a.push(p)}i=r.pop()}return a}neighbors(t,e,n=1/0,s=1/0,o){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let i=this._boxes.length-4;const r=this._queue,a=[],c=s*s;t:for(;void 0!==i;){const s=Math.min(i+4*this.nodeSize,En(i,this._levelBounds));for(let n=i;n<s;n+=4){const s=0|this._indices[n>>2],a=this._boxes[n],h=this._boxes[n+1],d=this._boxes[n+2],l=this._boxes[n+3],u=t<a?a-t:t>d?t-d:0,p=e<h?h-e:e>l?e-l:0,m=u*u+p*p;m>c||(i>=4*this.numItems?r.push(s<<1,m):(void 0===o||o(s))&&r.push(1+(s<<1),m))}for(;r.length&&1&r.peek();){if(r.peekValue()>c)break t;if(a.push(r.pop()>>1),a.length===n)break t}i=r.length?r.pop()>>1:void 0}return r.clear(),a}};function En(t,e){let n=0,s=e.length-1;for(;n<s;){const o=n+s>>1;e[o]>t?s=o:n=o+1}return e[n]}function Rn(t,e,n,s,o,i){if(Math.floor(s/i)>=Math.floor(o/i))return;const r=t[s],a=t[s+o>>1],c=t[o];let h=c;const d=Math.max(r,a);c>d?h=d:d===r?h=Math.max(a,c):d===a&&(h=Math.max(r,c));let l=s-1,u=o+1;for(;;){do{l++}while(t[l]<h);do{u--}while(t[u]>h);if(l>=u)break;wn(t,e,n,l,u)}Rn(t,e,n,s,u,i),Rn(t,e,n,u+1,o,i)}function wn(t,e,n,s,o){const i=t[s];t[s]=t[o],t[o]=i;const r=4*s,a=4*o,c=e[r],h=e[r+1],d=e[r+2],l=e[r+3];e[r]=e[a],e[r+1]=e[a+1],e[r+2]=e[a+2],e[r+3]=e[a+3],e[a]=c,e[a+1]=h,e[a+2]=d,e[a+3]=l;const u=n[s];n[s]=n[o],n[o]=u}function An(t,e){let n=t^e,s=65535^n,o=65535^(t|e),i=t&(65535^e),r=n|s>>1,a=n>>1^n,c=o>>1^s&i>>1^o,h=n&o>>1^i>>1^i;n=r,s=a,o=c,i=h,r=n&n>>2^s&s>>2,a=n&s>>2^s&(n^s)>>2,c^=n&o>>2^s&i>>2,h^=s&o>>2^(n^s)&i>>2,n=r,s=a,o=c,i=h,r=n&n>>4^s&s>>4,a=n&s>>4^s&(n^s)>>4,c^=n&o>>4^s&i>>4,h^=s&o>>4^(n^s)&i>>4,n=r,s=a,o=c,i=h,c^=n&o>>8^s&i>>8,h^=s&o>>8^(n^s)&i>>8,n=c^c>>1,s=h^h>>1;let d=t^e,l=s|65535^(d|n);return d=16711935&(d|d<<8),d=252645135&(d|d<<4),d=858993459&(d|d<<2),d=1431655765&(d|d<<1),l=16711935&(l|l<<8),l=252645135&(l|l<<4),l=858993459&(l|l<<2),l=1431655765&(l|l<<1),(l<<1|d)>>>0}function On(t,e,n=0,s=t.length-1,o=Dn){for(;s>n;){if(s-n>600){const i=s-n+1,r=e-n+1,a=Math.log(i),c=.5*Math.exp(2*a/3),h=.5*Math.sqrt(a*c*(i-c)/i)*(r-i/2<0?-1:1);On(t,e,Math.max(n,Math.floor(e-r*c/i+h)),Math.min(s,Math.floor(e+(i-r)*c/i+h)),o)}const i=t[e];let r=n,a=s;for(zn(t,n,e),o(t[s],i)>0&&zn(t,n,s);r<a;){for(zn(t,r,a),r++,a--;o(t[r],i)<0;)r++;for(;o(t[a],i)>0;)a--}0===o(t[n],i)?zn(t,n,a):(a++,zn(t,a,s)),a<=e&&(n=a+1),e<=a&&(s=a-1)}}function zn(t,e,n){const s=t[e];t[e]=t[n],t[n]=s}function Dn(t,e){return t<e?-1:t>e?1:0}var Ln=class{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(.4*this._maxEntries)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const n=[];if(!Zn(t,e))return n;const s=this.toBBox,o=[];for(;e;){for(let i=0;i<e.children.length;i++){const r=e.children[i],a=e.leaf?s(r):r;Zn(t,a)&&(e.leaf?n.push(r):Vn(t,a)?this._all(r,n):o.push(r))}e=o.pop()}return n}collides(t){let e=this.data;if(!Zn(t,e))return!1;const n=[];for(;e;){for(let s=0;s<e.children.length;s++){const o=e.children[s],i=e.leaf?this.toBBox(o):o;if(Zn(t,i)){if(e.leaf||Vn(t,i))return!0;n.push(o)}}e=n.pop()}return!1}load(t){if(!t||!t.length)return this;if(t.length<this._minEntries){for(let e=0;e<t.length;e++)this.insert(t[e]);return this}let e=this._build(t.slice(),0,t.length-1,0);if(this.data.children.length)if(this.data.height===e.height)this._splitRoot(this.data,e);else{if(this.data.height<e.height){const t=this.data;this.data=e,e=t}this._insert(e,this.data.height-e.height-1,!0)}else this.data=e;return this}insert(t){return t&&this._insert(t,this.data.height-1),this}clear(){return this.data=Gn([]),this}remove(t,e){if(!t)return this;let n=this.data;const s=this.toBBox(t),o=[],i=[];let r,a,c;for(;n||o.length;){if(n||(n=o.pop(),a=o[o.length-1],r=i.pop(),c=!0),n.leaf){const s=Fn(t,n.children,e);if(-1!==s)return n.children.splice(s,1),o.push(n),this._condense(o),this}c||n.leaf||!Vn(n,s)?a?(r++,n=a.children[r],c=!1):n=null:(o.push(n),i.push(r),r=0,a=n,n=n.children[0])}return this}toBBox(t){return t}compareMinX(t,e){return t.minX-e.minX}compareMinY(t,e){return t.minY-e.minY}toJSON(){return this.data}fromJSON(t){return this.data=t,this}_all(t,e){const n=[];for(;t;)t.leaf?e.push(...t.children):n.push(...t.children),t=n.pop();return e}_build(t,e,n,s){const o=n-e+1;let i,r=this._maxEntries;if(o<=r)return i=Gn(t.slice(e,n+1)),Xn(i,this.toBBox),i;s||(s=Math.ceil(Math.log(o)/Math.log(r)),r=Math.ceil(o/Math.pow(r,s-1))),i=Gn([]),i.leaf=!1,i.height=s;const a=Math.ceil(o/r),c=a*Math.ceil(Math.sqrt(r));Jn(t,e,n,c,this.compareMinX);for(let o=e;o<=n;o+=c){const e=Math.min(o+c-1,n);Jn(t,o,e,a,this.compareMinY);for(let n=o;n<=e;n+=a){const o=Math.min(n+a-1,e);i.children.push(this._build(t,n,o,s-1))}}return Xn(i,this.toBBox),i}_chooseSubtree(t,e,n,s){for(;s.push(e),!e.leaf&&s.length-1!==n;){let n,s=1/0,o=1/0;for(let i=0;i<e.children.length;i++){const r=e.children[i],a=jn(r),c=Hn(t,r)-a;c<o?(o=c,s=a<s?a:s,n=r):c===o&&a<s&&(s=a,n=r)}e=n||e.children[0]}return e}_insert(t,e,n){const s=n?t:this.toBBox(t),o=[],i=this._chooseSubtree(s,this.data,e,o);for(i.children.push(t),$n(i,s);e>=0&&o[e].children.length>this._maxEntries;)this._split(o,e),e--;this._adjustParentBBoxes(s,o,e)}_split(t,e){const n=t[e],s=n.children.length,o=this._minEntries;this._chooseSplitAxis(n,o,s);const i=this._chooseSplitIndex(n,o,s),r=Gn(n.children.splice(i,n.children.length-i));r.height=n.height,r.leaf=n.leaf,Xn(n,this.toBBox),Xn(r,this.toBBox),e?t[e-1].children.push(r):this._splitRoot(n,r)}_splitRoot(t,e){this.data=Gn([t,e]),this.data.height=t.height+1,this.data.leaf=!1,Xn(this.data,this.toBBox)}_chooseSplitIndex(t,e,n){let s,o=1/0,i=1/0;for(let r=e;r<=n-e;r++){const e=Yn(t,0,r,this.toBBox),a=Yn(t,r,n,this.toBBox),c=Un(e,a),h=jn(e)+jn(a);c<o?(o=c,s=r,i=h<i?h:i):c===o&&h<i&&(i=h,s=r)}return s||n-e}_chooseSplitAxis(t,e,n){const s=t.leaf?this.compareMinX:kn,o=t.leaf?this.compareMinY:Bn;this._allDistMargin(t,e,n,s)<this._allDistMargin(t,e,n,o)&&t.children.sort(s)}_allDistMargin(t,e,n,s){t.children.sort(s);const o=this.toBBox,i=Yn(t,0,e,o),r=Yn(t,n-e,n,o);let a=Wn(i)+Wn(r);for(let s=e;s<n-e;s++){const e=t.children[s];$n(i,t.leaf?o(e):e),a+=Wn(i)}for(let s=n-e-1;s>=e;s--){const e=t.children[s];$n(r,t.leaf?o(e):e),a+=Wn(r)}return a}_adjustParentBBoxes(t,e,n){for(let s=n;s>=0;s--)$n(e[s],t)}_condense(t){for(let e,n=t.length-1;n>=0;n--)0===t[n].children.length?n>0?(e=t[n-1].children,e.splice(e.indexOf(t[n]),1)):this.clear():Xn(t[n],this.toBBox)}};function Fn(t,e,n){if(!n)return e.indexOf(t);for(let s=0;s<e.length;s++)if(n(t,e[s]))return s;return-1}function Xn(t,e){Yn(t,0,t.children.length,e,t)}function Yn(t,e,n,s,o){o||(o=Gn(null)),o.minX=1/0,o.minY=1/0,o.maxX=-1/0,o.maxY=-1/0;for(let i=e;i<n;i++){const e=t.children[i];$n(o,t.leaf?s(e):e)}return o}function $n(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 kn(t,e){return t.minX-e.minX}function Bn(t,e){return t.minY-e.minY}function jn(t){return(t.maxX-t.minX)*(t.maxY-t.minY)}function Wn(t){return t.maxX-t.minX+(t.maxY-t.minY)}function Hn(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 Un(t,e){const n=Math.max(t.minX,e.minX),s=Math.max(t.minY,e.minY),o=Math.min(t.maxX,e.maxX),i=Math.min(t.maxY,e.maxY);return Math.max(0,o-n)*Math.max(0,i-s)}function Vn(t,e){return t.minX<=e.minX&&t.minY<=e.minY&&e.maxX<=t.maxX&&e.maxY<=t.maxY}function Zn(t,e){return e.minX<=t.maxX&&e.minY<=t.maxY&&e.maxX>=t.minX&&e.maxY>=t.minY}function Gn(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function Jn(t,e,n,s,o){const i=[e,n];for(;i.length;){if((n=i.pop())-(e=i.pop())<=s)continue;const r=e+Math.ceil((n-e)/s/2)*s;On(t,r,e,n,o),i.push(e,r,r,n)}}var qn=1e-4;var Kn=[{facingDirection:"x-",dx:-1,dy:0,startX:-.5,startY:.5,endX:-.5,endY:-.5},{facingDirection:"x+",dx:1,dy:0,startX:.5,startY:.5,endX:.5,endY:-.5},{facingDirection:"y-",dx:0,dy:-1,startX:-.5,startY:-.5,endX:.5,endY:-.5},{facingDirection:"y+",dx:0,dy:1,startX:.5,startY:.5,endX:-.5,endY:.5}],Qn={"x-":Kn.find(t=>"x-"===t.facingDirection),"x+":Kn.find(t=>"x+"===t.facingDirection),"y-":Kn.find(t=>"y-"===t.facingDirection),"y+":Kn.find(t=>"y+"===t.facingDirection)},ts={"x-":{x:-1,y:0},"x+":{x:1,y:0},"y-":{x:0,y:-1},"y+":{x:0,y:1}},es=(t,e)=>{const{dir:n,amt:s}=e,o=ts[n];return t.map(t=>({x:t.x+o.x*s,y:t.y+o.y*s}))},ns=1e-4,ss=class extends Mn{constructor(t){super(),this.input=t;for(const t of this.input.meshNodes)for(const e of Kn){let n={x:t.center.x+t.width*e.startX,y:t.center.y+t.height*e.startY},s={x:t.center.x+t.width*e.endX,y:t.center.y+t.height*e.endY};n.x>s.x&&([n,s]=[s,n]),Math.abs(n.x-s.x)<ns&&n.y>s.y&&([n,s]=[s,n]);for(const o of t.availableZ)this.unprocessedEdges.push({parent:t,start:n,end:s,facingDirection:e.facingDirection,z:o})}this.allEdges=[...this.unprocessedEdges],this.edgeSpatialIndex=new Tn(this.allEdges.length);for(const t of this.allEdges)this.edgeSpatialIndex.add(t.start.x,t.start.y,t.end.x,t.end.y);this.edgeSpatialIndex.finish()}allEdges;unprocessedEdges=[];segmentsWithAdjacentEmptySpace=[];edgeSpatialIndex;lastCandidateEdge=null;lastOverlappingEdges=null;lastUncoveredSegments=null;_step(){if(0===this.unprocessedEdges.length)return this.solved=!0,this.lastCandidateEdge=null,this.lastOverlappingEdges=null,void(this.lastUncoveredSegments=null);const t=this.unprocessedEdges.shift();this.lastCandidateEdge=t;const e=this.edgeSpatialIndex.search(t.start.x-ns,t.start.y-ns,t.end.x+ns,t.end.y+ns).map(t=>this.allEdges[t]).filter(e=>e.z===t.z);this.lastOverlappingEdges=e;const n=function(t,e){const n=Math.abs(t.start.y-t.end.y)<qn,s=Math.abs(t.start.x-t.end.x)<qn;if(!n&&!s)return[];const o=n?"x":"y",i=n?"y":"x",r=t.start[i],a=t.start[o],c=t.end[o],h=Math.min(a,c),d=Math.max(a,c),l=t=>Math.max(h,Math.min(d,t)),u=[];for(const n of e){if(n===t)continue;const e=Math.abs(n.start.y-n.end.y)<qn,s=Math.abs(n.start.x-n.end.x)<qn;if("x"===o&&!e)continue;if("y"===o&&!s)continue;if(Math.abs(n.start[i]-r)>qn)continue;const a=Math.min(n.start[o],n.end[o]),c=Math.max(n.start[o],n.end[o]),h=l(a),d=l(c);d-h>qn&&u.push({s:h,e:d})}if(0===u.length)return[{...t,start:{...t.start},end:{...t.end}}];u.sort((t,e)=>t.s-e.s);const p=[];for(const t of u){const e=p[p.length-1];!e||t.s>e.e+qn?p.push({...t}):e.e=Math.max(e.e,t.e)}const m=[];let f=h;for(const t of p)if(t.s>f+qn&&m.push({s:f,e:t.s}),f=Math.max(f,t.e),f>=d-qn)break;return d>f+qn&&m.push({s:f,e:d}),0===m.length?[]:m.filter(t=>t.e-t.s>qn).map(e=>{const n="x"===o?{x:e.s,y:r}:{x:r,y:e.s},s="x"===o?{x:e.e,y:r}:{x:r,y:e.e};return{parent:t.parent,facingDirection:t.facingDirection,start:n,end:s,z:t.z}})}(t,e);this.lastUncoveredSegments=n,this.segmentsWithAdjacentEmptySpace.push(...n)}getOutput(){return{segmentsWithAdjacentEmptySpace:this.segmentsWithAdjacentEmptySpace}}visualize(){const t={title:"FindSegmentsWithAdjacentEmptySpace",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]};for(const e of this.input.meshNodes)t.rects.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(0, 0, 0, 0.1)"});for(const e of this.unprocessedEdges)t.lines.push({points:es([e.start,e.end],{dir:e.facingDirection,amt:-.1}),strokeColor:"rgba(0, 0, 255, 0.5)",strokeDash:"5 5"});for(const e of this.segmentsWithAdjacentEmptySpace)t.lines.push({points:[e.start,e.end],strokeColor:"rgba(0,255,0, 0.5)"});if(this.lastCandidateEdge&&t.lines.push({points:[this.lastCandidateEdge.start,this.lastCandidateEdge.end],strokeColor:"blue"}),this.lastOverlappingEdges)for(const e of this.lastOverlappingEdges)t.lines.push({points:es([e.start,e.end],{dir:e.facingDirection,amt:.05}),strokeColor:"red",strokeDash:"2 2"});if(this.lastUncoveredSegments)for(const e of this.lastUncoveredSegments)t.lines.push({points:es([e.start,e.end],{dir:e.facingDirection,amt:-.05}),strokeColor:"green",strokeDash:"2 2"});return t}},os=t=>({minX:Math.min(...t.map(t=>t.x)),minY:Math.min(...t.map(t=>t.y)),maxX:Math.max(...t.map(t=>t.x)),maxY:Math.max(...t.map(t=>t.y))}),is=1e-4,rs=class extends Mn{constructor(t){super(),this.input=t,this.unprocessedSegments=[...this.input.segmentsWithAdjacentEmptySpace],this.rectSpatialIndex=new Ln,this.rectSpatialIndex.load(this.input.boardVoid?.boardVoidRects.map((t,e)=>({capacityMeshNodeId:`void-rect-${e}`,center:{x:t.x+t.width/2,y:t.y+t.height/2},width:t.width,height:t.height,availableZ:Array.from({length:this.input.boardVoid?.layerCount||0},(t,e)=>e),layer:"void",minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height}))||[]),this.rectSpatialIndex.load(this.input.inputMeshNodes.map(t=>({...t,minX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxX:t.center.x+t.width/2,maxY:t.center.y+t.height/2})))}unprocessedSegments=[];expandedSegments=[];lastSegment=null;lastSearchBounds=null;lastCollidingNodes=null;lastSearchCorner1=null;lastSearchCorner2=null;lastExpandedSegment=null;rectSpatialIndex;_step(){if(0===this.unprocessedSegments.length)return void(this.solved=!0);const t=this.unprocessedSegments.shift();this.lastSegment=t;const{dx:e,dy:n}=Qn[t.facingDirection],s=t.end.x-t.start.x,o=t.end.y-t.start.y,i=Math.sqrt(s**2+o**2),r=s/i,a=o/i;let c=null,h=1;const d={x:t.start.x+e*is+r*is*10,y:t.start.y+n*is+a*is*10},l={x:t.end.x+e*is-r*is*10,y:t.end.y+n*is-a*is*10};for(this.lastSearchCorner1=d,this.lastSearchCorner2=l;(!c||0===c.length)&&h<1e3;){const s=os([d,l,{x:d.x+e*h,y:d.y+n*h},{x:l.x+e*h,y:l.y+n*h}]);this.lastSearchBounds=s,c=this.rectSpatialIndex.search(s).filter(e=>e.availableZ.includes(t.z)).filter(e=>e.capacityMeshNodeId!==t.parent.capacityMeshNodeId),h*=4}if(!c||0===c.length)return;this.lastCollidingNodes=c;let u=1/0;for(const e of c){const n=At(t.start,t.end,e);n<u&&(u=n)}const p=u,m=os([t.start,t.end,{x:t.start.x+e*p,y:t.start.y+n*p},{x:t.end.x+e*p,y:t.end.y+n*p}]),f={x:(m.minX+m.maxX)/2,y:(m.minY+m.maxY)/2},g=m.maxX-m.minX,y=m.maxY-m.minY,x={segment:t,newNode:{capacityMeshNodeId:`new-${t.parent.capacityMeshNodeId}-${this.expandedSegments.length}`,center:f,width:g,height:y,availableZ:[t.z],layer:t.parent.layer}};this.lastExpandedSegment=x,g<is||y<is||(this.expandedSegments.push(x),this.rectSpatialIndex.insert({...x.newNode,...m}))}getOutput(){return{expandedSegments:this.expandedSegments}}visualize(){const t={title:"ExpandEdgesToEmptySpace",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]};for(const e of this.input.inputMeshNodes)t.rects.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(0, 0, 0, 0.1)",layer:`z${e.availableZ.join(",")}`,label:[`node ${e.capacityMeshNodeId}`,`z:${e.availableZ.join(",")}`].join("\n")});for(const{newNode:e}of this.expandedSegments)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"green",label:`expandedSegment (z=${e.availableZ.join(",")})`,layer:`z${e.availableZ.join(",")}`});if(this.lastSegment&&t.lines.push({points:[this.lastSegment.start,this.lastSegment.end],strokeColor:"rgba(0, 0, 255, 0.5)"}),this.lastSearchBounds&&t.rects.push({center:{x:(this.lastSearchBounds.minX+this.lastSearchBounds.maxX)/2,y:(this.lastSearchBounds.minY+this.lastSearchBounds.maxY)/2},width:this.lastSearchBounds.maxX-this.lastSearchBounds.minX,height:this.lastSearchBounds.maxY-this.lastSearchBounds.minY,fill:"rgba(0, 0, 255, 0.25)"}),this.lastSearchCorner1&&this.lastSearchCorner2&&(t.points.push({x:this.lastSearchCorner1.x,y:this.lastSearchCorner1.y,color:"rgba(0, 0, 255, 0.5)",label:["searchCorner1",`z=${this.lastSegment?.z}`].join("\n")}),t.points.push({x:this.lastSearchCorner2.x,y:this.lastSearchCorner2.y,color:"rgba(0, 0, 255, 0.5)",label:["searchCorner2",`z=${this.lastSegment?.z}`].join("\n")})),this.lastExpandedSegment&&t.rects.push({center:this.lastExpandedSegment.newNode.center,width:this.lastExpandedSegment.newNode.width,height:this.lastExpandedSegment.newNode.height,fill:"purple",label:`expandedSegment (z=${this.lastExpandedSegment.segment.z})`}),this.lastCollidingNodes)for(const e of this.lastCollidingNodes)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(255, 0, 0, 0.5)"});return t}},as=class extends In{findSegmentsWithAdjacentEmptySpaceSolver;expandEdgesToEmptySpaceSolver;pipelineDef=[Nn("findSegmentsWithAdjacentEmptySpaceSolver",ss,t=>[{meshNodes:t.inputProblem.meshNodes}],{onSolved:()=>{}}),Nn("expandEdgesToEmptySpaceSolver",rs,t=>[{inputMeshNodes:t.inputProblem.meshNodes,segmentsWithAdjacentEmptySpace:t.findSegmentsWithAdjacentEmptySpaceSolver.getOutput().segmentsWithAdjacentEmptySpace,boardVoid:t.inputProblem.boardVoid}],{onSolved:()=>{}})];getOutput(){const t=(this.expandEdgesToEmptySpaceSolver?.getOutput().expandedSegments??[]).map(t=>t.newNode);return{outputNodes:[...this.inputProblem.meshNodes,...t]}}initialVisualize(){const t={title:"GapFillSolverPipeline - Initial",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]};for(const e of this.inputProblem.meshNodes)t.rects.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(0, 0, 0, 0.3)",fill:"rgba(100, 100, 100, 0.1)",layer:`z${e.availableZ.join(",")}`,label:[`node ${e.capacityMeshNodeId}`,`z:${e.availableZ.join(",")}`].join("\n")});return t}finalVisualize(){const t={title:"GapFillSolverPipeline - Final",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]},{outputNodes:e}=this.getOutput(),n=this.expandEdgesToEmptySpaceSolver?.getOutput().expandedSegments??[],s=new Set(n.map(t=>t.newNode.capacityMeshNodeId));for(const n of e){const e=s.has(n.capacityMeshNodeId);t.rects.push({center:n.center,width:n.width,height:n.height,stroke:e?"rgba(0, 128, 0, 0.8)":"rgba(0, 0, 0, 0.3)",fill:e?"rgba(0, 200, 0, 0.3)":"rgba(100, 100, 100, 0.1)",layer:`z${n.availableZ.join(",")}`,label:[`${e?"[expanded] ":""}node ${n.capacityMeshNodeId}`,`z:${n.availableZ.join(",")}`].join("\n")})}return t}},cs=1e-9,hs=(t,e,n)=>Math.max(e,Math.min(n,t)),ds=(t,e)=>t>e+cs,ls=(t,e)=>t>e-cs,us=(t,e)=>t<e-cs,ps=(t,e)=>t<e+cs;function ms(t,e){return!(t.x+t.width<=e.x+cs||e.x+e.width<=t.x+cs||t.y+t.height<=e.y+cs||e.y+e.height<=t.y+cs)}function fs(t,e){const n=[[e.x,e.y,e.x+e.width,e.y],[e.x+e.width,e.y,e.x+e.width,e.y+e.height],[e.x+e.width,e.y+e.height,e.x,e.y+e.height],[e.x,e.y+e.height,e.x,e.y]];let s=1/0;for(const[e,o,i,r]of n){const n=t.x-e,a=t.y-o,c=i-e,h=r-o,d=c*c+h*h;let l=0!==d?(n*c+a*h)/d:0;l=hs(l,0,1);const u=e+l*c,p=o+l*h;s=Math.min(s,Math.hypot(t.x-u,t.y-p))}return s}function gs(t,e){const n=Math.max(t[0],e[0]),s=Math.min(t[1],e[1]);return s>n+cs?[n,s]:null}function ys(t,e){if(!ms(t,e))return[t];const n=gs([t.x,t.x+t.width],[e.x,e.x+e.width]),s=gs([t.y,t.y+t.height],[e.y,e.y+e.height]);if(!n||!s)return[t];const[o,i]=n,[r,a]=s,c=[];o>t.x+cs&&c.push({x:t.x,y:t.y,width:o-t.x,height:t.height}),t.x+t.width>i+cs&&c.push({x:i,y:t.y,width:t.x+t.width-i,height:t.height});const h=Math.max(0,i-o);return h>cs&&r>t.y+cs&&c.push({x:o,y:t.y,width:h,height:r-t.y}),h>cs&&t.y+t.height>a+cs&&c.push({x:o,y:a,width:h,height:t.y+t.height-a}),c.filter(t=>t.width>cs&&t.height>cs)}function xs(t,e){let n=!1;for(let s=0,o=e.length-1;s<e.length;o=s++){const i=e[s].x,r=e[s].y,a=e[o].x,c=e[o].y;r>t.y!=c>t.y&&t.x<(a-i)*(t.y-r)/(c-r)+i&&(n=!n)}return n}function vs(t,e){if(!e||e.length<3)return[];const n=e.length>100?function(t,e){const n=t=>Math.round(t/e)*e,s=new Set,o=[];for(const e of t){const t=n(e.x),i=n(e.y),r=`${t},${i}`;s.has(r)||(s.add(r),o.push({x:t,y:i}))}return o}(e,Math.max(t.width,t.height)/100):e,s=new Set([t.x,t.x+t.width]),o=new Set([t.y,t.y+t.height]);for(const t of n)s.add(t.x),o.add(t.y);const i=Array.from(s).sort((t,e)=>t-e),r=Array.from(o).sort((t,e)=>t-e),a=[];for(let n=0;n<i.length-1;n++)for(let s=0;s<r.length-1;s++){const o=i[n],c=i[n+1],h=r[s],d=r[s+1],l=(o+c)/2,u=(h+d)/2;l>=t.x&&l<=t.x+t.width&&u>=t.y&&u<=t.y+t.height&&(xs({x:l,y:u},e)||a.push({x:o,y:h,width:c-o,height:d-h}))}const c=[];a.sort((t,e)=>Math.abs(t.y-e.y)>cs?t.y-e.y:t.x-e.x);let h=null;for(const t of a){if(!h){h=t;continue}const e=Math.abs(h.y-t.y)<cs,n=Math.abs(h.height-t.height)<cs,s=Math.abs(h.x+h.width-t.x)<cs;e&&n&&s?h.width+=t.width:(c.push(h),h=t)}h&&c.push(h),c.sort((t,e)=>Math.abs(t.x-e.x)>cs?t.x-e.x:t.y-e.y);const d=[];h=null;for(const t of c){if(!h){h=t;continue}const e=Math.abs(h.x-t.x)<cs,n=Math.abs(h.width-t.width)<cs,s=Math.abs(h.y+h.height-t.y)<cs;e&&n&&s?h.height+=t.height:(d.push(h),h=t)}return h&&d.push(h),d}function Ss(t){const e=t.toLowerCase();if("top"===e)return-1e6;if("bottom"===e)return 1e6;const n=/^inner(\d+)$/i.exec(e);return n?parseInt(n[1],10)||0:100+e.charCodeAt(0)}function Ps(t){const e=function(t){return Array.from(new Set(t)).sort((t,e)=>{const n=Ss(t),s=Ss(e);return n!==s?n-s:t.localeCompare(e)})}((t.obstacles??[]).flatMap(t=>t.layers??[])),n=Math.max(1,t.layerCount||e.length||1),s=Array.from({length:n},(t,e)=>0===e?"top":e===n-1?"bottom":`inner${e}`),o=[],i=new Set,r=t=>{const e=t.toLowerCase();i.has(e)||(i.add(e),o.push(t))};s.forEach(r),e.forEach(r);const a=o.slice(0,n),c=new Map;return a.forEach((t,e)=>c.set(t.toLowerCase(),e)),o.slice(a.length).forEach(t=>{const e=t.toLowerCase();c.set(e,(t=>{if(a.length<=1)return 0;if("top"===t)return 0;if("bottom"===t)return a.length-1;const e=/^inner(\d+)$/i.exec(t);if(e){if(a.length<=2)return a.length-1;const t=parseInt(e[1],10),n=a.length-2;return Math.min(n,Math.max(1,Number.isFinite(t)?t:1))}return 0})(e))}),{layerNames:a,zIndexByName:c}}function bs(t,e){if(t.zLayers?.length)return Array.from(new Set(t.zLayers)).sort((t,e)=>t-e);const n=(t.layers??[]).map(t=>e.get(t.toLowerCase())).filter(t=>"number"==typeof t);return Array.from(new Set(n)).sort((t,e)=>t-e)}function Ms(t){const e=t.width,n=t.height;return"number"!=typeof e||"number"!=typeof n?null:{x:t.center.x-e/2,y:t.center.y-n/2,width:e,height:n}}var Ns=1e-9,Is=t=>Math.abs(t.rect.x+t.rect.width/2-t.startX)<Ns&&Math.abs(t.rect.y+t.rect.height/2-t.startY)<Ns&&Math.abs(t.rect.width-t.initialW)<Ns&&Math.abs(t.rect.height-t.initialH)<Ns,Cs=({rect:t,bounds:e})=>({x:t.x,y:t.y,width:e.x+e.width-t.x,height:t.height}),_s=({rect:t,bounds:e})=>({x:t.x,y:t.y,width:t.width,height:e.y+e.height-t.y}),Ts=({rect:t,bounds:e})=>({x:e.x,y:t.y,width:t.x-e.x,height:t.height}),Es=({rect:t,bounds:e})=>({x:t.x,y:e.y,width:t.width,height:t.y-e.y});function Rs(t){const{r:e,bounds:n,blockers:s,maxAspect:o}=t;let i=n.x+n.width-e.x;for(const t of s){if(e.y+e.height>t.y+cs&&t.y+t.height>e.y+cs)if(ls(t.x,e.x+e.width))i=Math.min(i,t.x-e.x);else if(t.x+t.width>e.x+e.width-cs&&t.x<e.x+e.width+cs)return 0}let r=Math.max(0,i-e.width);if(r<=0)return 0;if(null!=o){const t=e.width,n=e.height;t>=n&&(r=Math.min(r,o*n-t))}return Math.max(0,r)}function ws(t){const{r:e,bounds:n,blockers:s,maxAspect:o}=t;let i=n.y+n.height-e.y;for(const t of s){if(e.x+e.width>t.x+cs&&t.x+t.width>e.x+cs)if(ls(t.y,e.y+e.height))i=Math.min(i,t.y-e.y);else if(t.y+t.height>e.y+e.height-cs&&t.y<e.y+e.height+cs)return 0}let r=Math.max(0,i-e.height);if(r<=0)return 0;if(null!=o){const t=e.width,n=e.height;n>=t&&(r=Math.min(r,o*t-n))}return Math.max(0,r)}function As(t){const{r:e,bounds:n,blockers:s,maxAspect:o}=t;let i=n.x;for(const t of s){if(e.y+e.height>t.y+cs&&t.y+t.height>e.y+cs)if(ps(t.x+t.width,e.x))i=Math.max(i,t.x+t.width);else if(t.x<e.x+cs&&t.x+t.width>e.x-cs)return 0}let r=Math.max(0,e.x-i);if(r<=0)return 0;if(null!=o){const t=e.width,n=e.height;t>=n&&(r=Math.min(r,o*n-t))}return Math.max(0,r)}function Os(t){const{r:e,bounds:n,blockers:s,maxAspect:o}=t;let i=n.y;for(const t of s){if(e.x+e.width>t.x+cs&&t.x+t.width>e.x+cs)if(ps(t.y+t.height,e.y))i=Math.max(i,t.y+t.height);else if(t.y<e.y+cs&&t.y+t.height>e.y-cs)return 0}let r=Math.max(0,e.y-i);if(r<=0)return 0;if(null!=o){const t=e.width,n=e.height;n>=t&&(r=Math.min(r,o*t-n))}return Math.max(0,r)}var zs=t=>({x:t.minX,y:t.minY,width:t.maxX-t.minX,height:t.maxY-t.minY}),Ds=t=>{const{rect:e,seen:n,blockers:s}=t,o=`${e.x}|${e.y}|${e.width}|${e.height}`;n.has(o)||(n.add(o),s.push(e))};function Ls(t){const{startX:e,startY:n,gridSize:s,bounds:o,obsticalIndexByLayer:i,placedIndexByLayer:r,initialCellRatio:a,maxAspectRatio:c,minReq:h}=t,d=Math.max(1e-9,s*a),l=Math.max(d,h.width),u=Math.max(d,h.height),p=[],m=new Set,f=r.length,g=s=>{const a=(t=>{const{bounds:e,rect:n}=t,s=Math.max(e.x,n.x),o=Math.max(e.y,n.y),i=Math.min(e.x+e.width,n.x+n.width),r=Math.min(e.y+e.height,n.y+n.height);return i<=s+cs||r<=o+cs?null:{minX:s,minY:o,maxX:i,maxY:r}})({bounds:o,rect:s});if(a)for(const s of t.zLayers){const t=i[s];if(t)for(const e of t.search(a))Ds({rect:zs(e),seen:m,blockers:p});const o=r[s];if(o)for(const t of o.search(a)){if(!(t.zLayers.length>=f))continue;const s=zs(t);Is({rect:s,startX:e,startY:n,initialW:l,initialH:u})||Ds({rect:s,seen:m,blockers:p})}}},y=[{ox:0,oy:0},{ox:-l,oy:0},{ox:0,oy:-u},{ox:-l,oy:-u},{ox:-l/2,oy:-u/2}];let x=null,v=0;t:for(const t of y){let s={x:e+t.ox,y:n+t.oy,width:l,height:u};if(g(s),us(s.x,o.x)||us(s.y,o.y)||ds(s.x+s.width,o.x+o.width)||ds(s.y+s.height,o.y+o.height))continue;for(const t of p)if(ms(s,t))continue t;const i=1e-6,r=1e3;let a=!0,d=0;for(;a&&d<r;){d++,a=!1;const t={bounds:o,blockers:p,maxAspect:c};g(Cs({rect:s,bounds:o}));const e=Rs({...t,r:s});e>i&&(s={...s,width:s.width+e},g(s),a=!0),g(_s({rect:s,bounds:o}));const n=ws({...t,r:s});n>i&&(s={...s,height:s.height+n},g(s),a=!0),g(Ts({rect:s,bounds:o}));const r=As({...t,r:s});r>i&&(s={x:s.x-r,y:s.y,width:s.width+r,height:s.height},g(s),a=!0),g(Es({rect:s,bounds:o}));const h=Os({...t,r:s});h>i&&(s={x:s.x,y:s.y-h,width:s.width,height:s.height+h},g(s),a=!0)}if(s.width+cs>=h.width&&s.height+cs>=h.height){const t=s.width*s.height;t>v&&(x=s,v=t)}}return x}function Fs(t){const e=Math.max(t.width,t.height);return[e/8,e/16,e/32]}function Xs(t){const e={minX:t.point.x,minY:t.point.y,maxX:t.point.x,maxY:t.point.y};for(let n=0;n<t.layerCount;n++){const s=t.obstacleIndexByLayer[n],o=!!s&&s.search(e).length>0,i=t.placedIndexByLayer[n],r=!!i&&i.search(e).length>0;if(!o&&!r)return!1}return!0}function Ys(t){const{x:e,y:n,z:s,layerCount:o,minSpan:i,maxSpan:r,obstacleIndexByLayer:a,additionalBlockersByLayer:c}=t,h=t=>{const s={minX:e,minY:n,maxX:e,maxY:n},o=a[t];if(o&&o.search(s).length>0)return!1;return!(c?.[t]??[]).some(t=>{return(o={x:e,y:n}).x>=(s=t).x-cs&&o.x<=s.x+s.width+cs&&o.y>=s.y-cs&&o.y<=s.y+s.height+cs;var s,o})};let d=s,l=s;for(;d-1>=0&&h(d-1);)d--;for(;l+1<o&&h(l+1);)l++;if("number"==typeof r){const t=hs(r,1,o);for(;l-d+1>t;)s-d>l-s?d++:l--}const u=[];for(let t=d;t<=l;t++)u.push(t);return u.length>=i?u:[]}function $s(t){const{lineStart:e,lineEnd:n,coveringIntervals:s,minSegmentLength:o}=t;if(0===s.length){return[{start:e,end:n,center:(e+n)/2}]}const i=[...s].sort((t,e)=>t.start-e.start),r=[];let a={...i[0]};for(let t=1;t<i.length;t++){const e=i[t];e.start<=a.end+cs?a.end=Math.max(a.end,e.end):(r.push(a),a={...e})}r.push(a);const c=[];if(r[0].start>e+cs){const t=e,n=r[0].start;n-t>=o&&c.push({start:t,end:n,center:(t+n)/2})}for(let t=0;t<r.length-1;t++){const e=r[t].end,n=r[t+1].start;n-e>=o&&c.push({start:e,end:n,center:(e+n)/2})}if(r[r.length-1].end<n-cs){const t=r[r.length-1].end,e=n;e-t>=o&&c.push({start:t,end:e,center:(t+e)/2})}return c}function ks(t){const{bounds:e,minSize:n,layerCount:s,obstacleIndexByLayer:o,placedIndexByLayer:i,hardPlacedByLayer:r}=t,a=[],c=Math.max(.15*n,3*cs),h=new Set;function d(t){const{x:n,y:c,z:d}=t;if(n<e.x+cs||c<e.y+cs||n>e.x+e.width-cs||c>e.y+e.height-cs)return;if(function(t){return Xs({layerCount:s,obstacleIndexByLayer:o,placedIndexByLayer:i,point:t})}({x:n,y:c}))return;const l=[...o[d]?.all()??[],...r[d]??[]],u=Math.min(fs({x:n,y:c},e),...l.length?l.map(t=>fs({x:n,y:c},t)):[1/0]),p=(t=>`${t.z}|${t.x.toFixed(6)}|${t.y.toFixed(6)}`)({x:n,y:c,z:d});if(h.has(p))return;h.add(p);const m=Ys({x:n,y:c,z:d,layerCount:s,minSpan:1,maxSpan:void 0,obstacleIndexByLayer:o,additionalBlockersByLayer:r});a.push({x:n,y:c,z:d,distance:u,zSpanLen:m.length,isEdgeSeed:!0})}for(let t=0;t<s;t++){const s=[...o[t]?.all()??[],...r[t]??[]],i=[{x:e.x+c,y:e.y+c},{x:e.x+e.width-c,y:e.y+c},{x:e.x+c,y:e.y+e.height-c},{x:e.x+e.width-c,y:e.y+e.height-c}];for(const e of i)d({x:e.x,y:e.y,z:t});const a=e.y+c,h=s.filter(t=>t.y<=a&&t.y+t.height>=a).map(t=>({start:Math.max(e.x,t.x),end:Math.min(e.x+e.width,t.x+t.width)})),l=$s({lineStart:e.x+c,lineEnd:e.x+e.width-c,coveringIntervals:h,minSegmentLength:.5*n});for(const e of l){const s=e.end-e.start;s>=n&&(d({x:e.center,y:a,z:t}),s>1.5*n&&(d({x:e.start+.4*n,y:a,z:t}),d({x:e.end-.4*n,y:a,z:t})))}const u=e.y+e.height-c,p=s.filter(t=>t.y<=u&&t.y+t.height>=u).map(t=>({start:Math.max(e.x,t.x),end:Math.min(e.x+e.width,t.x+t.width)})),m=$s({lineStart:e.x+c,lineEnd:e.x+e.width-c,coveringIntervals:p,minSegmentLength:.5*n});for(const e of m){const s=e.end-e.start;s>=n&&(d({x:e.center,y:u,z:t}),s>1.5*n&&(d({x:e.start+.4*n,y:u,z:t}),d({x:e.end-.4*n,y:u,z:t})))}const f=e.x+c,g=s.filter(t=>t.x<=f&&t.x+t.width>=f).map(t=>({start:Math.max(e.y,t.y),end:Math.min(e.y+e.height,t.y+t.height)})),y=$s({lineStart:e.y+c,lineEnd:e.y+e.height-c,coveringIntervals:g,minSegmentLength:.5*n});for(const e of y){const s=e.end-e.start;s>=n&&(d({x:f,y:e.center,z:t}),s>1.5*n&&(d({x:f,y:e.start+.4*n,z:t}),d({x:f,y:e.end-.4*n,z:t})))}const x=e.x+e.width-c,v=s.filter(t=>t.x<=x&&t.x+t.width>=x).map(t=>({start:Math.max(e.y,t.y),end:Math.min(e.y+e.height,t.y+t.height)})),S=$s({lineStart:e.y+c,lineEnd:e.y+e.height-c,coveringIntervals:v,minSegmentLength:.5*n});for(const e of S){const s=e.end-e.start;s>=n&&(d({x:x,y:e.center,z:t}),s>1.5*n&&(d({x:x,y:e.start+.4*n,z:t}),d({x:x,y:e.end-.4*n,z:t})))}for(const o of s){const i=o.x-c;if(i>e.x+cs&&i<e.x+e.width-cs){const e=s.filter(t=>t!==o&&t.x<=i&&t.x+t.width>=i).map(t=>({start:Math.max(o.y,t.y),end:Math.min(o.y+o.height,t.y+t.height)})),r=$s({lineStart:o.y,lineEnd:o.y+o.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of r)d({x:i,y:e.center,z:t})}const r=o.x+o.width+c;if(r>e.x+cs&&r<e.x+e.width-cs){const e=s.filter(t=>t!==o&&t.x<=r&&t.x+t.width>=r).map(t=>({start:Math.max(o.y,t.y),end:Math.min(o.y+o.height,t.y+t.height)})),i=$s({lineStart:o.y,lineEnd:o.y+o.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of i)d({x:r,y:e.center,z:t})}const a=o.y-c;if(a>e.y+cs&&a<e.y+e.height-cs){const e=s.filter(t=>t!==o&&t.y<=a&&t.y+t.height>=a).map(t=>({start:Math.max(o.x,t.x),end:Math.min(o.x+o.width,t.x+t.width)})),i=$s({lineStart:o.x,lineEnd:o.x+o.width,coveringIntervals:e,minSegmentLength:.5*n});for(const e of i)d({x:e.center,y:a,z:t})}const h=o.y+o.height+c;if(h>e.y+cs&&h<e.y+e.height-cs){const e=s.filter(t=>t!==o&&t.y<=h&&t.y+t.height>=h).map(t=>({start:Math.max(o.x,t.x),end:Math.min(o.x+o.width,t.x+t.width)})),i=$s({lineStart:o.x,lineEnd:o.x+o.width,coveringIntervals:e,minSegmentLength:.5*n});for(const e of i)d({x:e.center,y:h,z:t})}}}return a.sort((t,e)=>e.zSpanLen-t.zSpanLen||e.distance-t.distance),a}var Bs=(t,e)=>({...t,minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height,zLayers:e.zLayers});function js(t,e){const n=t.placed[e],{rect:s,zLayers:o}=n,i=t.layerCount,r=[],a=[];for(let n=0;n<t.placed.length;n++){if(n===e)continue;const c=t.placed[n];if(c.zLayers.length>=i)continue;const h=c.zLayers.filter(t=>o.includes(t));if(0===h.length)continue;if(!ms(c.rect,s))continue;const d=ys(c.rect,s);r.push(n);const l=c.zLayers.filter(t=>!o.includes(t));l.length>0&&a.push({rect:c.rect,zLayers:l});const u=Math.min(t.options.minSingle.width,t.options.minMulti.width),p=Math.min(t.options.minSingle.height,t.options.minMulti.height);for(const t of d)t.width+cs>=u&&t.height+cs>=p&&a.push({rect:t,zLayers:h.slice()})}const c=(t,e)=>t.minX===e.minX&&t.minY===e.minY&&t.maxX===e.maxX&&t.maxY===e.maxY;r.sort((t,e)=>e-t).forEach(e=>{const n=t.placed.splice(e,1)[0];if(t.placedIndexByLayer)for(const e of n.zLayers){const s=t.placedIndexByLayer[e];s&&s.remove(Bs(n.rect,{zLayers:n.zLayers}),c)}});for(const e of a){t.placed.push(e);for(const n of e.zLayers)if(t.placedIndexByLayer){const s=t.placedIndexByLayer[n];s&&s.insert(Bs(e.rect,{zLayers:e.zLayers.slice()}))}}}var Ws=t=>{const e=[{fill:"#dbeafe",stroke:"#3b82f6"},{fill:"#fef3c7",stroke:"#f59e0b"},{fill:"#d1fae5",stroke:"#10b981"},{fill:"#e9d5ff",stroke:"#a855f7"},{fill:"#fed7aa",stroke:"#f97316"},{fill:"#fecaca",stroke:"#ef4444"}];return e[Math.min(...t)%e.length]},Hs=class extends Mn{constructor(t){super(),this.input=t}srj;layerNames;layerCount;bounds;options;boardVoidRects;gridIndex;candidates;placed;placedIndexByLayer;expansionIndex;edgeAnalysisDone;totalSeedsThisGrid;consumedSeedsThisGrid;_setup(){const t=this.input.simpleRouteJson,e=this.input.gridOptions??{},{layerNames:n,zIndexByName:s}=Ps(t),o=Math.max(1,n.length,t.layerCount||1),i={x:t.bounds.minX,y:t.bounds.minY,width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},r=Math.max(.01,t.minTraceWidth||.15),a={...{gridSizes:[],initialCellRatio:.2,maxAspectRatio:3,minSingle:{width:2*r,height:2*r},minMulti:{width:4*r,height:4*r,minLayers:Math.min(2,Math.max(1,t.layerCount||1))},preferMultiLayer:!0,maxMultiLayerSpan:void 0},...e,gridSizes:e.gridSizes??Fs(i)};this.srj=t,this.layerNames=n,this.layerCount=o,this.bounds=i,this.options=a,this.boardVoidRects=this.input.boardVoidRects,this.gridIndex=0,this.candidates=[],this.placed=[],this.placedIndexByLayer=Array.from({length:o},()=>new Ln),this.expansionIndex=0,this.edgeAnalysisDone=!1,this.totalSeedsThisGrid=0,this.consumedSeedsThisGrid=0,this.stats={gridIndex:this.gridIndex}}_step(){this._stepGrid(),this.stats.gridIndex=this.gridIndex,this.stats.placed=this.placed.length}_stepGrid(){const{gridSizes:t,initialCellRatio:e,maxAspectRatio:n,minSingle:s,minMulti:o,preferMultiLayer:i,maxMultiLayerSpan:r}=this.options,a=t[this.gridIndex],c=function(t){const e=Array.from({length:t.layerCount},()=>[]);for(const n of t.placed)if(n.zLayers.length>=t.layerCount)for(const t of n.zLayers)e[t].push(n.rect);return e}({layerCount:this.layerCount,placed:this.placed});if(0===this.candidates.length&&0===this.consumedSeedsThisGrid&&(this.candidates=function(t){const{bounds:e,gridSize:n,layerCount:s,obstacleIndexByLayer:o,placedIndexByLayer:i,hardPlacedByLayer:r}=t,a=new Map;for(let t=e.x;t<e.x+e.width;t+=n)for(let c=e.y;c<e.y+e.height;c+=n){if(Math.abs(t-e.x)<cs||Math.abs(c-e.y)<cs||t>e.x+e.width-n-cs||c>e.y+e.height-n-cs)continue;if(Xs({layerCount:s,obstacleIndexByLayer:o,placedIndexByLayer:i,point:{x:t,y:c}}))continue;let h=[],d=0;for(let e=0;e<s;e++){const n=Ys({x:t,y:c,z:e,layerCount:s,minSpan:1,maxSpan:void 0,obstacleIndexByLayer:o,additionalBlockersByLayer:r});n.length>h.length&&(h=n,d=e)}const l=h.length?h[Math.floor(h.length/2)]:d,u=[...o[l]?.all()??[],...r[l]??[]],p=Math.min(fs({x:t,y:c},e),...u.length?u.map(e=>fs({x:t,y:c},e)):[1/0]),m=`${t.toFixed(6)}|${c.toFixed(6)}`,f={x:t,y:c,z:l,distance:p,zSpanLen:h.length},g=a.get(m);(!g||f.zSpanLen>(g.zSpanLen??0)||f.zSpanLen===g.zSpanLen&&f.distance>g.distance)&&a.set(m,f)}const c=Array.from(a.values());return c.sort((t,e)=>e.zSpanLen-t.zSpanLen||e.distance-t.distance),c}({bounds:this.bounds,gridSize:a,layerCount:this.layerCount,hardPlacedByLayer:c,obstacleIndexByLayer:this.input.obstacleIndexByLayer,placedIndexByLayer:this.placedIndexByLayer}),this.totalSeedsThisGrid=this.candidates.length,this.consumedSeedsThisGrid=0),0===this.candidates.length){if(this.gridIndex+1<t.length)return this.gridIndex+=1,this.totalSeedsThisGrid=0,void(this.consumedSeedsThisGrid=0);if(!this.edgeAnalysisDone){const t=Math.min(s.width,s.height);return this.candidates=ks({bounds:this.bounds,minSize:t,layerCount:this.layerCount,obstacleIndexByLayer:this.input.obstacleIndexByLayer,placedIndexByLayer:this.placedIndexByLayer,hardPlacedByLayer:c}),this.edgeAnalysisDone=!0,this.totalSeedsThisGrid=this.candidates.length,void(this.consumedSeedsThisGrid=0)}return this.solved=!0,void(this.expansionIndex=0)}const h=this.candidates.shift();this.consumedSeedsThisGrid+=1;const d=Ys({x:h.x,y:h.y,z:h.z,layerCount:this.layerCount,minSpan:o.minLayers,maxSpan:r,obstacleIndexByLayer:this.input.obstacleIndexByLayer,additionalBlockersByLayer:c}),l=[];d.length>=o.minLayers&&l.push({kind:"multi",layers:d,minReq:{width:o.width,height:o.height}}),l.push({kind:"single",layers:[h.z],minReq:{width:s.width,height:s.height}});const u=i?l:l.reverse();for(const t of u){const s=Ls({startX:h.x,startY:h.y,gridSize:a,bounds:this.bounds,obsticalIndexByLayer:this.input.obstacleIndexByLayer,placedIndexByLayer:this.placedIndexByLayer,initialCellRatio:e,maxAspectRatio:n,minReq:t.minReq,zLayers:t.layers});if(!s)continue;const o={rect:s,zLayers:[...t.layers]},i=this.placed.push(o)-1;for(const e of t.layers){const t=this.placedIndexByLayer[e];t&&t.insert(Bs(s,{zLayers:o.zLayers}))}return js({layerCount:this.layerCount,placed:this.placed,options:this.options,placedIndexByLayer:this.placedIndexByLayer},i),void(this.candidates=this.candidates.filter(t=>!Xs({layerCount:this.layerCount,obstacleIndexByLayer:this.input.obstacleIndexByLayer,placedIndexByLayer:this.placedIndexByLayer,point:{x:t.x,y:t.y}})))}}computeProgress(){if(this.solved)return 1;const t=this.options.gridSizes.length,e=this.gridIndex/(t+1),n=Math.max(1,this.totalSeedsThisGrid),s=n?this.consumedSeedsThisGrid/n:1;return Math.min(.999,e+s*(1/(t+1)))}getOutput(){return{srj:this.srj,layerNames:this.layerNames,layerCount:this.layerCount,bounds:this.bounds,options:this.options,boardVoidRects:this.boardVoidRects,gridIndex:this.gridIndex,candidates:this.candidates,placed:this.placed,expansionIndex:this.expansionIndex,edgeAnalysisDone:this.edgeAnalysisDone,totalSeedsThisGrid:this.totalSeedsThisGrid,consumedSeedsThisGrid:this.consumedSeedsThisGrid}}visualize(){const t=[],e=[],n=[],s=this.srj??this.input.simpleRouteJson,o=s.bounds.minX,i=s.bounds.maxX,r=s.bounds.minY,a=s.bounds.maxY;s.outline&&s.outline.length>1?n.push({points:[...s.outline,s.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):t.push({center:{x:(o+i)/2,y:(r+a)/2},width:i-o,height:a-r,fill:"none",stroke:"#111827",label:"board"});for(const e of s.obstacles??[])"rect"!==e.type&&"oval"!==e.type||t.push({center:{x:e.center.x,y:e.center.y},width:e.width,height:e.height,fill:"#fee2e2",stroke:"#ef4444",layer:"obstacle",label:"obstacle"});if(this.boardVoidRects){let e=null;if(s.outline&&s.outline.length>0){const t=s.outline.map(t=>t.x),n=s.outline.map(t=>t.y),o=Math.min(...t),i=Math.min(...n);e={x:o,y:i,width:Math.max(...t)-o,height:Math.max(...n)-i}}for(const n of this.boardVoidRects)e&&!ms(n,e)||t.push({center:{x:n.x+n.width/2,y:n.y+n.height/2},width:n.width,height:n.height,fill:"rgba(0, 0, 0, 0.5)",stroke:"none",label:"void"})}if(this.candidates?.length)for(const t of this.candidates)e.push({x:t.x,y:t.y,fill:"#9333ea",stroke:"#6b21a8",label:`z:${t.z}`});if(this.placed?.length)for(const e of this.placed){const n=Ws(e.zLayers);t.push({center:{x:e.rect.x+e.rect.width/2,y:e.rect.y+e.rect.height/2},width:e.rect.width,height:e.rect.height,fill:n.fill,stroke:n.stroke,layer:`z${e.zLayers.join(",")}`,label:`free\nz:${e.zLayers.join(",")}`})}return{title:"RectDiff Grid",coordinateSystem:"cartesian",rects:t,points:e,lines:n}}};var Us=(t,e)=>t.minX===e.minX&&t.minY===e.minY&&t.maxX===e.maxX&&t.maxY===e.maxY,Vs=class extends Mn{constructor(t){super(),this.input=t}placedIndexByLayer=[];_meshNodes=[];_setup(){this.stats={gridIndex:this.input.gridIndex},this.placedIndexByLayer=Array.from({length:this.input.layerCount},()=>new Ln);for(const t of this.input.placed)for(const e of t.zLayers){const n=this.placedIndexByLayer[e];n&&n.insert(Bs(t.rect,{zLayers:t.zLayers}))}}_step(){this.solved||(this._stepExpansion(),this.stats.gridIndex=this.input.gridIndex,this.stats.placed=this.input.placed.length,this.input.expansionIndex>=this.input.placed.length&&this.finalizeIfNeeded())}_stepExpansion(){if(this.input.expansionIndex>=this.input.placed.length)return;const t=this.input.expansionIndex,e=this.input.placed[t],n=this.input.options.gridSizes[this.input.options.gridSizes.length-1],s=e.rect,o=Ls({startX:e.rect.x+e.rect.width/2,startY:e.rect.y+e.rect.height/2,gridSize:n,bounds:this.input.bounds,obsticalIndexByLayer:this.input.obstacleIndexByLayer,placedIndexByLayer:this.placedIndexByLayer,initialCellRatio:0,maxAspectRatio:null,minReq:{width:e.rect.width,height:e.rect.height},zLayers:e.zLayers});if(o){this.input.placed[t]={rect:o,zLayers:e.zLayers};for(const t of e.zLayers){const n=this.placedIndexByLayer[t];n&&(n.remove(Bs(s,{zLayers:e.zLayers}),Us),n.insert(Bs(o,{zLayers:e.zLayers})))}js({layerCount:this.input.layerCount,placed:this.input.placed,options:this.input.options,placedIndexByLayer:this.placedIndexByLayer},t)}this.input.expansionIndex+=1}finalizeIfNeeded(){if(this.solved)return;const t=function(t){const e=t.placed.map(t=>({minX:t.rect.x,minY:t.rect.y,maxX:t.rect.x+t.rect.width,maxY:t.rect.y+t.rect.height,zLayers:[...t.zLayers].sort((t,e)=>t-e)})),{zIndexByName:n}=Ps(t.srj),s=new Map;for(const e of t.srj.obstacles??[]){const t=Ms(e);if(!t)continue;const o=e.zLayers?.length&&e.zLayers.length>0?e.zLayers:bs(e,n),i=`${t.x}:${t.y}:${t.width}:${t.height}`;let r=s.get(i);r||(r={rect:t,layers:new Set},s.set(i,r)),o.forEach(t=>r.layers.add(t))}for(const{rect:t,layers:n}of s.values())e.push({minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height,zLayers:Array.from(n).sort((t,e)=>t-e),isObstacle:!0});return e}({placed:this.input.placed,srj:this.input.srj,boardVoidRects:this.input.boardVoidRects});this._meshNodes=function(t){let e=0;const n=[];for(const s of t){const t=Math.max(0,s.maxX-s.minX),o=Math.max(0,s.maxY-s.minY);t<=0||o<=0||0===s.zLayers.length||n.push({capacityMeshNodeId:"cmn_"+e++,center:{x:(s.minX+s.maxX)/2,y:(s.minY+s.maxY)/2},width:t,height:o,layer:"top",availableZ:s.zLayers.slice(),_containsObstacle:s.isObstacle,_containsTarget:s.isObstacle})}return n}(t),this.solved=!0}computeProgress(){if(this.solved)return 1;const t=this.input.options.gridSizes.length,e=t/(t+1),n=Math.max(1,this.input.placed.length),s=n?this.input.expansionIndex/n:1;return Math.min(.999,e+s*(1/(t+1)))}getOutput(){if(this.solved)return{meshNodes:this._meshNodes};return{meshNodes:this.input.placed.map((t,e)=>({capacityMeshNodeId:`expand-preview-${e}`,center:{x:t.rect.x+t.rect.width/2,y:t.rect.y+t.rect.height/2},width:t.rect.width,height:t.rect.height,availableZ:t.zLayers.slice(),layer:`z${t.zLayers.join(",")}`}))}}visualize(){const t=[];for(const e of this.input.placed??[])t.push({center:{x:e.rect.x+e.rect.width/2,y:e.rect.y+e.rect.height/2},width:e.rect.width,height:e.rect.height,stroke:"rgba(37, 99, 235, 0.9)",fill:"rgba(191, 219, 254, 0.5)",layer:`z${e.zLayers.join(",")}`,label:`expanded\nz:${e.zLayers.join(",")}`});return{title:"RectDiff Expansion",coordinateSystem:"cartesian",rects:t,points:[],lines:[]}}},Zs=class extends In{rectDiffSeedingSolver;rectDiffExpansionSolver;obstacleIndexByLayer;constructor(t){super(t);const{obstacleIndexByLayer:e}=(t=>{const{srj:e,boardVoidRects:n}=t,{layerNames:s,zIndexByName:o}=Ps(e),i=Math.max(1,s.length,e.layerCount||1),r=(e.bounds.minX,e.bounds.minY,e.bounds.maxX,e.bounds.minX,e.bounds.maxY,e.bounds.minY,Array.from({length:i},()=>new Ln)),a=(t,e)=>{const n={...t,minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height,zLayers:[e]};r[e]?.insert(n)};if(e.outline&&e.outline.length>2)for(const t of n??[])for(let e=0;e<i;e++)a(t,e);for(const t of e.obstacles??[]){const e=Ms(t);if(!e)continue;const n=bs(t,o),s=n.filter(t=>t<0||t>=i);if(s.length)throw new Error(`RectDiff: obstacle uses z-layer indices ${s.join(",")} outside 0-${i-1}`);t.zLayers&&0!==t.zLayers.length||!n.length||(t.zLayers=n);for(const t of n)a(e,t)}return{obstacleIndexByLayer:r}})({srj:t.simpleRouteJson,boardVoidRects:t.boardVoidRects});this.obstacleIndexByLayer=e}pipelineDef=[Nn("rectDiffSeedingSolver",Hs,t=>[{simpleRouteJson:t.inputProblem.simpleRouteJson,gridOptions:t.inputProblem.gridOptions,obstacleIndexByLayer:t.obstacleIndexByLayer,boardVoidRects:t.inputProblem.boardVoidRects}]),Nn("rectDiffExpansionSolver",Vs,t=>{const e=t.rectDiffSeedingSolver?.getOutput();if(!e)throw new Error("RectDiffSeedingSolver did not produce output");return[{srj:t.inputProblem.simpleRouteJson,layerNames:e.layerNames??[],boardVoidRects:t.inputProblem.boardVoidRects??[],layerCount:t.inputProblem.simpleRouteJson.layerCount,bounds:e.bounds,candidates:e.candidates,consumedSeedsThisGrid:e.placed.length,totalSeedsThisGrid:e.candidates.length,placed:e.placed,edgeAnalysisDone:e.edgeAnalysisDone,gridIndex:e.gridIndex,expansionIndex:e.expansionIndex,obstacleIndexByLayer:t.obstacleIndexByLayer,options:e.options}]})];getConstructorParams(){return[this.inputProblem]}getOutput(){if(this.rectDiffExpansionSolver)return this.rectDiffExpansionSolver.getOutput();if(this.rectDiffSeedingSolver){return{meshNodes:this.rectDiffSeedingSolver.getOutput().placed.map((t,e)=>({capacityMeshNodeId:`grid-${e}`,center:{x:t.rect.x+t.rect.width/2,y:t.rect.y+t.rect.height/2},width:t.rect.width,height:t.rect.height,availableZ:t.zLayers,layer:`z${t.zLayers.join(",")}`}))}}return{meshNodes:[]}}visualize(){return this.rectDiffExpansionSolver?this.rectDiffExpansionSolver.visualize():this.rectDiffSeedingSolver?this.rectDiffSeedingSolver.visualize():{title:"RectDiff Grid Pipeline",coordinateSystem:"cartesian",rects:[],points:[],lines:[]}}};function Gs(t,e="RectDiff"){const n=[],s=[],o=t.bounds.minX,i=t.bounds.maxX,r=t.bounds.minY,a=t.bounds.maxY;t.outline&&t.outline.length>1?s.push({points:[...t.outline,t.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):n.push({center:{x:(o+i)/2,y:(r+a)/2},width:i-o,height:a-r,fill:"none",stroke:"#111827",label:"board"});for(const e of t.obstacles??[])"rect"!==e.type&&"oval"!==e.type||n.push({center:{x:e.center.x,y:e.center.y},width:e.width,height:e.height,fill:"#fee2e2",stroke:"#ef4444",layer:"obstacle",label:"obstacle"});return{title:e,coordinateSystem:"cartesian",rects:n,points:[],lines:s}}var Js=class extends In{rectDiffGridSolverPipeline;gapFillSolver;boardVoidRects;pipelineDef=[Nn("rectDiffGridSolverPipeline",Zs,t=>[{simpleRouteJson:t.inputProblem.simpleRouteJson,gridOptions:t.inputProblem.gridOptions,boardVoidRects:t.boardVoidRects}]),Nn("gapFillSolver",as,t=>[{meshNodes:t.rectDiffGridSolverPipeline?.getOutput().meshNodes??[],boardVoid:{boardVoidRects:t.boardVoidRects||[],layerCount:t.inputProblem.simpleRouteJson.layerCount||0}}])];_setup(){this.inputProblem.simpleRouteJson.outline&&(this.boardVoidRects=vs({x:this.inputProblem.simpleRouteJson.bounds.minX,y:this.inputProblem.simpleRouteJson.bounds.minY,width:this.inputProblem.simpleRouteJson.bounds.maxX-this.inputProblem.simpleRouteJson.bounds.minX,height:this.inputProblem.simpleRouteJson.bounds.maxY-this.inputProblem.simpleRouteJson.bounds.minY},this.inputProblem.simpleRouteJson.outline??[]))}getConstructorParams(){return[this.inputProblem]}getOutput(){const t=this.gapFillSolver?.getOutput();return t?{meshNodes:t.outputNodes}:this.rectDiffGridSolverPipeline?this.rectDiffGridSolverPipeline.getOutput():{meshNodes:[]}}initialVisualize(){const t=Gs(this.inputProblem.simpleRouteJson,"RectDiffPipeline - Initial"),e=this.rectDiffGridSolverPipeline?.getOutput().meshNodes??[];for(const n of e)t.rects.push({center:n.center,width:n.width,height:n.height,stroke:"rgba(0, 0, 0, 0.3)",fill:"rgba(100, 100, 100, 0.1)",layer:`z${n.availableZ.join(",")}`,label:[`node ${n.capacityMeshNodeId}`,`z:${n.availableZ.join(",")}`].join("\n")});return t}finalVisualize(){const t=Gs(this.inputProblem.simpleRouteJson,"RectDiffPipeline - Final"),{meshNodes:e}=this.getOutput(),n=new Set((this.rectDiffGridSolverPipeline?.getOutput().meshNodes??[]).map(t=>t.capacityMeshNodeId));for(const s of e){const e=!n.has(s.capacityMeshNodeId);t.rects.push({center:s.center,width:s.width,height:s.height,stroke:e?"rgba(0, 128, 0, 0.8)":"rgba(0, 0, 0, 0.3)",fill:e?"rgba(0, 200, 0, 0.3)":"rgba(100, 100, 100, 0.1)",layer:`z${s.availableZ.join(",")}`,label:[`${e?"[expanded] ":""}node ${s.capacityMeshNodeId}`,`z:${s.availableZ.join(",")}`].join("\n")})}return t}},qs=class{tree;constructor(t=9){this.tree=new Ln(t)}insert(t,e,n,s,o){this.tree.insert({minX:e,minY:n,maxX:s,maxY:o,data:t})}bulkLoad(t){const e=t.map(({item:t,minX:e,minY:n,maxX:s,maxY:o})=>({minX:e,minY:n,maxX:s,maxY:o,data:t}));this.tree.load(e)}search(t,e,n,s){return this.tree.search({minX:t,minY:e,maxX:n,maxY:s}).map(t=>t.data)}clear(){this.tree.clear()}},Ks=class{index;items=[];currentIndex=0;capacity;constructor(t){this.capacity=Math.max(1,t),this.index=new Tn(this.capacity)}insert(t,e,n,s,o){if(this.currentIndex>=this.index.numItems)throw new Error("Exceeded initial capacity");this.items[this.currentIndex]=t,this.index.add(e,n,s,o),this.currentIndex++}finish(){this.index.finish()}search(t,e,n,s){return this.index.search(t,e,n,s).map(t=>this.items[t]||null).filter(Boolean)}clear(){this.items=[],this.currentIndex=0,this.index=new Tn(this.capacity)}},Qs=class{idx;storage=[];constructor(t="native",e=[]){"flatbush"===t?0===e.length?(this.idx=new qs,t="rbush"):this.idx=new Ks(e.length):this.idx="rbush"===t?new qs:new class{shi=new to(e);insert(t){}search(t,e,n,s){const o=(t+n)/2,i=(e+s)/2,r=n-t,a=s-e;return this.shi.getNodesInArea(o,i,r,a)}clear(){}},e.forEach(t=>this.insert(t)),"flatbush"===t&&e.length>0&&this.idx.finish?.()}insert(t){this.storage.push(t),this.idx.insert(t,t.center.x-t.width/2,t.center.y-t.height/2,t.center.x+t.width/2,t.center.y+t.height/2)}search(t){return this.idx.search(t.minX,t.minY,t.maxX,t.maxY)}searchArea(t,e,n,s){return this.search({minX:t-n/2,minY:e-s/2,maxX:t+n/2,maxY:e+s/2})}},to=class{constructor(t){this.obstacles=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],s=n.center.x-n.width/2,o=n.center.y-n.height/2,i=n.center.x+n.width/2,r=n.center.y+n.height/2;for(let t=s;t<=i;t+=this.CELL_SIZE)for(let s=o;s<=r;s+=this.CELL_SIZE){const o=this.getBucketKey(t,s),i=this.buckets.get(o);i?i.push([n,e]):this.buckets.set(o,[[n,e]])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,n,s){const o=[],i=new Set,r=e-s/2,a=t+n/2,c=e+s/2;for(let e=t-n/2;e<=a;e+=this.CELL_SIZE)for(let t=r;t<=c;t+=this.CELL_SIZE){const n=this.getBucketKey(e,t),s=this.buckets.get(n)||[];for(const t of s)i.has(t[1])||(i.add(t[1]),o.push(t[0]))}return o}},eo=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 no(t,e){const n=t.x-e.x,s=t.y-e.y;return n*n+s*s}function so(t,e,n){const s=no(e,n);if(0===s)return no(t,e);let o=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/s;o=Math.max(0,Math.min(1,o));return no(t,{x:e.x+o*(n.x-e.x),y:e.y+o*(n.y-e.y)})}function oo(t,e,n,s){if(gt(t,e,n,s))return 0;const o={x:t.x,y:t.y},i={x:e.x,y:e.y},r={x:n.x,y:n.y},a={x:s.x,y:s.y};return Math.min(so(o,r,a),so(i,r,a),so(r,o,i),so(a,o,i))}var io=class{segmentBuckets;viaBuckets;CELL_SIZE;constructor(t,e=1){this.segmentBuckets=new Map,this.viaBuckets=new Map,this.CELL_SIZE=e;for(const e of t)if(e&&e.connectionName){if(e.route&&e.route.length>=2)for(let t=0;t<e.route.length-1;t++){const n=e.route[t],s=e.route[t+1];if(n.x===s.x&&n.y===s.y)continue;if(n.insideJumperPad&&s.insideJumperPad)continue;const o=[n,s],i=eo(o),r={segmentId:`${e.connectionName}-seg-${t}`,segment:o,parentRoute:e},a=Math.floor(i.minX/this.CELL_SIZE),c=Math.floor((i.maxX+1e-9)/this.CELL_SIZE),h=Math.floor(i.minY/this.CELL_SIZE),d=Math.floor((i.maxY+1e-9)/this.CELL_SIZE);for(let t=a;t<=c;t++)for(let e=h;e<=d;e++){const n=`${t}x${e}`;let s=this.segmentBuckets.get(n);s||(s=[],this.segmentBuckets.set(n,s)),s.push(r)}}if(e.vias&&e.vias.length>0)for(let t=0;t<e.vias.length;t++){const n=e.vias[t];if(null==n)continue;const s={viaId:`${e.connectionName}-via-${t}`,x:n.x,y:n.y,parentRoute:e},o=`${Math.floor(n.x/this.CELL_SIZE)}x${Math.floor(n.y/this.CELL_SIZE)}`;let i=this.viaBuckets.get(o);i||(i=[],this.viaBuckets.set(o,i)),i.push(s)}}else console.warn("Skipping route with missing data:",e)}getConflictingRoutesForSegment(t,e,n){const s=eo([t,e]),o=s.minX-n,i=s.minY-n,r=s.maxX+n,a=s.maxY+n,c=Math.floor(o/this.CELL_SIZE),h=Math.floor((r+1e-9)/this.CELL_SIZE),d=Math.floor(i/this.CELL_SIZE),l=Math.floor((a+1e-9)/this.CELL_SIZE),u=new Map,p=new Set,m=new Set,f={x:t.x,y:t.y},g={x:e.x,y:e.y};for(let s=c;s<=h;s++)for(let o=d;o<=l;o++){const i=`${s}x${o}`,r=this.segmentBuckets.get(i);if(r)for(const s of r){if(p.has(s.segmentId))continue;p.add(s.segmentId);const o=s.parentRoute,[i,r]=s.segment,a=n+o.traceThickness/2,c=a*a,h=oo(t,e,i,r);if(h<c){const t=o.connectionName,e=u.get(t);(!e||h<e.minDistSq)&&u.set(t,{route:o,minDistSq:h})}}const a=this.viaBuckets.get(i);if(a)for(const t of a){if(m.has(t.viaId))continue;m.add(t.viaId);const e=t.parentRoute,s={x:t.x,y:t.y},o=n+e.viaDiameter/2,i=o*o,r=so(s,f,g);if(r<i){const t=e.connectionName,n=u.get(t);(!n||r<n.minDistSq)&&u.set(t,{route:e,minDistSq:r})}}}const y=[];for(const t of u.values())y.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return y}removeRoute(t){for(const[e,n]of this.segmentBuckets){const s=n.filter(e=>e.parentRoute.connectionName!==t);0===s.length?this.segmentBuckets.delete(e):s.length!==n.length&&this.segmentBuckets.set(e,s)}for(const[e,n]of this.viaBuckets){const s=n.filter(e=>e.parentRoute.connectionName!==t);0===s.length?this.viaBuckets.delete(e):s.length!==n.length&&this.viaBuckets.set(e,s)}}addRoute(t){if(!t||!t.connectionName)return void console.warn("Skipping route with missing data:",t);if(t.route&&t.route.length>=2)for(let e=0;e<t.route.length-1;e++){const n=t.route[e],s=t.route[e+1];if(n.x===s.x&&n.y===s.y)continue;if(n.insideJumperPad&&s.insideJumperPad)continue;const o=[n,s],i=eo(o),r={segmentId:`${t.connectionName}-seg-${e}`,segment:o,parentRoute:t},a=Math.floor(i.minX/this.CELL_SIZE),c=Math.floor((i.maxX+1e-9)/this.CELL_SIZE),h=Math.floor(i.minY/this.CELL_SIZE),d=Math.floor((i.maxY+1e-9)/this.CELL_SIZE);for(let t=a;t<=c;t++)for(let e=h;e<=d;e++){const n=`${t}x${e}`;let s=this.segmentBuckets.get(n);s||(s=[],this.segmentBuckets.set(n,s)),s.push(r)}}if(t.vias&&t.vias.length>0)for(let e=0;e<t.vias.length;e++){const n=t.vias[e];if(null==n)continue;const s={viaId:`${t.connectionName}-via-${e}`,x:n.x,y:n.y,parentRoute:t},o=`${Math.floor(n.x/this.CELL_SIZE)}x${Math.floor(n.y/this.CELL_SIZE)}`;let i=this.viaBuckets.get(o);i||(i=[],this.viaBuckets.set(o,i)),i.push(s)}}getConflictingRoutesNearPoint(t,e){const n=t.x-e,s=t.y-e,o=t.x+e,i=t.y+e,r=Math.floor(n/this.CELL_SIZE),a=Math.floor((o+1e-9)/this.CELL_SIZE),c=Math.floor(s/this.CELL_SIZE),h=Math.floor((i+1e-9)/this.CELL_SIZE),d=new Map,l=new Set,u=new Set;for(let n=r;n<=a;n++)for(let s=c;s<=h;s++){const o=`${n}x${s}`,i=this.segmentBuckets.get(o);if(i)for(const n of i){if(l.has(n.segmentId))continue;l.add(n.segmentId);const s=n.parentRoute,o={x:n.segment[0].x,y:n.segment[0].y},i={x:n.segment[1].x,y:n.segment[1].y},r=e+s.traceThickness/2,a=r*r,c=so(t,o,i);if(c<a){const t=s.connectionName,e=d.get(t);(!e||c<e.minDistSq)&&d.set(t,{route:s,minDistSq:c})}}const r=this.viaBuckets.get(o);if(r)for(const n of r){if(u.has(n.viaId))continue;u.add(n.viaId);const s=n.parentRoute,o={x:n.x,y:n.y},i=e+s.viaDiameter/2,r=i*i,a=no(t,o);if(a<r){const t=s.connectionName,e=d.get(t);(!e||a<e.minDistSq)&&d.set(t,{route:s,minDistSq:a})}}}const p=[];for(const t of d.values())p.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return p}},ro=class extends y{obstacleSHI;hdRouteSHI;unsimplifiedRoute;routeSections;currentSectionIndex;TRACE_THICKNESS=.15;OBSTACLE_MARGIN=.1;constructor(t){super(),this.currentSectionIndex=0,this.obstacleSHI=t.obstacleSHI,this.hdRouteSHI=t.hdRouteSHI,this.unsimplifiedRoute=t.unsimplifiedRoute,this.routeSections=this.breakRouteIntoSections(this.unsimplifiedRoute)}breakRouteIntoSections(t){const e=[],n=t.route;if(0===n.length)return[];let s={startIndex:0,endIndex:-1,z:n[0].z,points:[n[0]]};for(let t=1;t<n.length;t++)n[t].z===s.z?s.points.push(n[t]):(s.endIndex=t-1,e.push(s),s={startIndex:t,endIndex:-1,z:n[t].z,points:[n[t]]});return s.endIndex=n.length-1,e.push(s),e}_step(){if(this.currentSectionIndex>=this.routeSections.length)return void(this.solved=!0);if(0===this.currentSectionIndex&&this.routeSections.length>1){const t=this.routeSections[0],e=this.routeSections[1];if(t.z!==e.z){const n=e.z,s=t.points[0];if(this.canEndpointConnectOnLayer(s.x,s.y,n)&&this.canSectionMoveToLayer({currentSection:t,targetZ:n}))return t.z=n,t.points=t.points.map(t=>({...t,z:n})),void(this.currentSectionIndex=2)}return void this.currentSectionIndex++}if(this.currentSectionIndex===this.routeSections.length-1){if(this.routeSections.length>=2){const t=this.routeSections[this.routeSections.length-1],e=this.routeSections[this.routeSections.length-2];if(t.z!==e.z){const n=e.z,s=t.points[t.points.length-1];this.canEndpointConnectOnLayer(s.x,s.y,n)&&this.canSectionMoveToLayer({currentSection:t,targetZ:n})&&(t.z=n,t.points=t.points.map(t=>({...t,z:n})))}}return void(this.solved=!0)}const t=this.routeSections[this.currentSectionIndex-1],e=this.routeSections[this.currentSectionIndex],n=this.routeSections[this.currentSectionIndex+1];if(t.z!==n.z)return void this.currentSectionIndex++;const s=t.z;if(this.canSectionMoveToLayer({currentSection:e,targetZ:s}))return e.z=s,e.points=e.points.map(t=>({...t,z:s})),void(this.currentSectionIndex+=2);this.currentSectionIndex++}canEndpointConnectOnLayer(t,e,n){const s=this.obstacleSHI.searchArea(t,e,2,2).filter(n=>{if(!n.connectedTo?.includes(this.unsimplifiedRoute.connectionName))return!1;const s=n.width/2+.05,o=n.height/2+.05,i=Math.abs(t-n.center.x)<=s,r=Math.abs(e-n.center.y)<=o;return i&&r});return!(s.length>0)||s.some(t=>t.zLayers?.includes(n))}canSectionMoveToLayer({currentSection:t,targetZ:e}){for(let n=0;n<t.points.length-1;n++){const s={...t.points[n],z:e},o={...t.points[n+1],z:e},i=this.hdRouteSHI.getConflictingRoutesForSegment(s,o,this.TRACE_THICKNESS);for(const{conflictingRoute:t,distance:e}of i)if(t.connectionName!==this.unsimplifiedRoute.connectionName&&e<this.TRACE_THICKNESS+t.traceThickness)return!1;const r={centerX:(s.x+o.x)/2,centerY:(s.y+o.y)/2,width:Math.abs(s.x-o.x),height:Math.abs(s.y-o.y)},a=this.obstacleSHI.searchArea(r.centerX,r.centerY,r.width+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN),r.height+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN));for(const t of a){if(t.connectedTo?.includes(this.unsimplifiedRoute.connectionName))continue;if(t.zLayers?.includes(e)){if(Math.abs(s.x-t.center.x)<.01&&Math.abs(s.y-t.center.y)<.01||Math.abs(o.x-t.center.x)<.01&&Math.abs(o.y-t.center.y)<.01)continue}if(At(s,o,t)<this.TRACE_THICKNESS+this.OBSTACLE_MARGIN)return!1}}return!0}getConstructorParams(){return{obstacleSHI:this.obstacleSHI,hdRouteSHI:this.hdRouteSHI,unsimplifiedRoute:this.unsimplifiedRoute}}getOptimizedHdRoute(){const t=this.routeSections.flatMap(t=>t.points),e=[];for(let n=0;n<t.length-1;n++)t[n].z!==t[n+1].z&&e.push({x:t[n].x,y:t[n].y});return{connectionName:this.unsimplifiedRoute.connectionName,rootConnectionName:this.unsimplifiedRoute.rootConnectionName,route:t,traceThickness:this.unsimplifiedRoute.traceThickness,vias:e,viaDiameter:this.unsimplifiedRoute.viaDiameter,jumpers:this.unsimplifiedRoute.jumpers}}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Single Route Useless Via Removal Solver"};for(let e=0;e<this.routeSections.length;e++){const n=this.routeSections[e];t.lines.push({points:n.points,strokeWidth:this.TRACE_THICKNESS,strokeColor:e===this.currentSectionIndex?"orange":0===n.z?"red":"blue"})}return t}},ao=class extends y{constructor(t){super(),this.input=t,this.MAX_ITERATIONS=1e6,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.optimizedHdRoutes=[],this.unprocessedRoutes=[...t.unsimplifiedHdRoutes],this.obstacleSHI=new Qs("flatbush",t.obstacles),this.hdRouteSHI=new io(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 ro({hdRouteSHI:this.hdRouteSHI,obstacleSHI:this.obstacleSHI,unsimplifiedRoute:t}):this.solved=!0}getOptimizedHdRoutes(){return this.optimizedHdRoutes}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Useless Via Removal Solver"};for(const e of this.input.obstacles){let n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),o=e.zLayers?.includes(1);s&&o?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":o&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.optimizedHdRoutes){if(0===e.route.length)continue;const n=this.input.colorMap[e.connectionName]||"#888888";for(let n=0;n<e.route.length-1;n++){const s=e.route[n],o=e.route[n+1];s.z===o.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:o.x,y:o.y}],strokeColor:0===s.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const s=Je(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...s.rects??[]),t.lines.push(...s.lines??[])}}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},co=class extends y{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,rootConnectionName:this.inputRoute.rootConnectionName,traceThickness:this.inputRoute.traceThickness,viaDiameter:this.inputRoute.viaDiameter,route:this.newRoute,vias:this.newVias,jumpers:this.inputRoute.jumpers}}isValidPath(t){throw new Error("Not implemented")}_step(){throw new Error("Not implemented")}getVisualsForNewRouteAndObstacles(){const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Simplified Path Solver"};for(let e=0;e<this.inputRoute.route.length-1;e++)t.lines.push({points:[{x:this.inputRoute.route[e].x,y:this.inputRoute.route[e].y},{x:this.inputRoute.route[e+1].x,y:this.inputRoute.route[e+1].y}],strokeColor:"rgba(255, 0, 0, 0.8)",strokeDash:1===this.inputRoute.route[e].z?"5, 5":void 0,layer:`z${this.inputRoute.route[e].z.toString()}`});for(let e=0;e<this.newRoute.length;e++)e<this.newRoute.length-1&&t.lines.push({points:[{x:this.newRoute[e].x,y:this.newRoute[e].y},{x:this.newRoute[e+1].x,y:this.newRoute[e+1].y}],strokeWidth:.15,strokeColor:"rgba(0, 255, 0, 0.8)",strokeDash:1===this.newRoute[e].z?[.4,.4]:void 0,layer:`z${this.newRoute[e].z.toString()}`}),t.points.push({x:this.newRoute[e].x,y:this.newRoute[e].y,color:"rgba(0, 255, 0, 0.8)",label:`z: ${this.newRoute[e].z}`,layer:`z${this.newRoute[e].z.toString()}`});for(const e of this.newVias)t.circles.push({center:e,radius:this.inputRoute.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)"});for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});for(const e of this.otherHdRoutes)for(let n=0;n<e.route.length-1;n++)t.lines.push({points:[{x:e.route[n].x,y:e.route[n].y},{x:e.route[n+1].x,y:e.route[n+1].y}],strokeWidth:.15,strokeColor:0===e.route[n].z?"rgba(255, 0, 255, 0.5)":1===e.route[n].z?"rgba(128, 0, 128, 0.5)":"rgba(0, 0, 255, 0.5)",layer:`z${e.route[n].z.toString()}`});if("filteredObstaclePathSegments"in this){const e=this.filteredObstaclePathSegments;for(const[n,s]of e)t.lines.push({points:[n,s]})}return t}};function ho(t,e,n,s){if(gt(t,e,n,s))return 0;const o=lo(t,n,s),i=lo(e,n,s),r=lo(n,t,e),a=lo(s,t,e);return Math.min(o,i,r,a)}function lo(t,e,n){const s={x:n.x-e.x,y:n.y-e.y},o=uo({x:t.x-e.x,y:t.y-e.y},s);if(o<=0)return po(t,e);const i=uo(s,s);if(i<=o)return po(t,n);const r=o/i;return po(t,{x:e.x+r*s.x,y:e.y+r*s.y})}function uo(t,e){return t.x*e.x+t.y*e.y}function po(t,e){const n=e.x-t.x,s=e.y-t.y;return Math.sqrt(n*n+s*s)}var mo=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)}),fo=class{constructor(t){this.segments=t,this.buckets=new Map;const e=new Map;for(const n of t){const t=this.getSegmentKey(n);if(e.has(t))continue;e.set(t,n);const s=mo(n),o=Math.floor(s.minX/this.CELL_SIZE),i=Math.floor(s.maxX/this.CELL_SIZE),r=Math.floor(s.minY/this.CELL_SIZE),a=Math.floor(s.maxY/this.CELL_SIZE);for(let e=o;e<=i;e++)for(let s=r;s<=a;s++){const o=`${e}x${s}`,i=this.buckets.get(o),r=[n[0],n[1],t];i?i.push(r):this.buckets.set(o,[r])}}}buckets;CELL_SIZE=.4;SEGMENT_MARGIN=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getSegmentKey(t){return`${t[0].x}-${t[0].y}-${t[0].z}-${t[1].x}-${t[1].y}-${t[1].z}`}getSegmentsThatCouldIntersect(t,e){const n=[],s=new Set,o=Math.min(t.x,e.x)-this.SEGMENT_MARGIN,i=Math.min(t.y,e.y)-this.SEGMENT_MARGIN,r=Math.max(t.x,e.x)+this.SEGMENT_MARGIN,a=Math.max(t.y,e.y)+this.SEGMENT_MARGIN,c=Math.floor(o/this.CELL_SIZE),h=Math.floor(r/this.CELL_SIZE),d=Math.floor(i/this.CELL_SIZE),l=Math.floor(a/this.CELL_SIZE);for(let t=c;t<=h;t++)for(let e=d;e<=l;e++){const o=`${t}x${e}`,i=this.buckets.get(o);if(i)for(const t of i){const e=t[2];s.has(e)||(s.add(e),n.push(t))}}return n}},go=1e-6,yo=(t,e,n)=>vt(t,e,n)<=go,xo=(t,e)=>Math.abs(t.x-e.x)<=go&&Math.abs(t.y-e.y)<=go,vo=(t,e)=>{if(!e||e.length<3)return!1;for(let n=0;n<e.length;n++){const s=e[n],o=e[(n+1)%e.length];if(yo(t,s,o))return!0}let n=!1;for(let s=0,o=e.length-1;s<e.length;o=s++){const i=e[s],r=e[o];i.y>t.y!=r.y>t.y&&t.x<(r.x-i.x)*(t.y-i.y)/(r.y-i.y)+i.x&&(n=!n)}return n},So=class extends co{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=[];filteredJumperPads=[];jumperPadPointIndices=new Set;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=mt(t),s=mt(e),o=Math.max(n.minX-s.maxX,s.minX-n.maxX,0),i=Math.max(n.minY-s.maxY,s.minY-n.maxY,0);return Math.hypot(o,i)}(n,t)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2}),this.filteredObstaclePathSegments=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const n=t.route,s=[];for(let t=0;t<n.length-1;t++){const o=n[t],i=n[t+1],r=Math.min(o.x,i.x),a=Math.max(o.x,i.x),c=Math.min(o.y,i.y),h=Math.max(o.y,i.y);r<=e.maxX&&a>=e.minX&&c<=e.maxY&&h>=e.minY&&s.push([o,i])}return s}),this.segmentTree=new fo(this.filteredObstaclePathSegments),this.filteredVias=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const n=t.vias,s=[];for(const o of n){const n=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2+t.viaDiameter/2,i=o.x-n,r=o.x+n,a=o.y-n,c=o.y+n;i<=e.maxX&&r>=e.minX&&a<=e.maxY&&c>=e.minY&&s.push({...o,diameter:t.viaDiameter})}return s});const s=(t,n)=>{const s=[];for(const o of t){const t=Ze[o.footprint]??Ze["0603"],i=o.end.x-o.start.x,r=o.end.y-o.start.y,a=Math.abs(i)>Math.abs(r),c=a?t.padLength:t.padWidth,h=a?t.padWidth:t.padLength,d=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2;o.start.x-c/2-d<=e.maxX&&o.start.x+c/2+d>=e.minX&&o.start.y-h/2-d<=e.maxY&&o.start.y+h/2+d>=e.minY&&s.push({center:o.start,width:c,height:h,connectionName:n}),o.end.x-c/2-d<=e.maxX&&o.end.x+c/2+d>=e.minX&&o.end.y-h/2-d<=e.maxY&&o.end.y+h/2+d>=e.minY&&s.push({center:o.end,width:c,height:h,connectionName:n})}return s};if(this.filteredJumperPads=this.otherHdRoutes.flatMap(t=>this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName)?[]:s(t.jumpers??[],t.connectionName)),this.inputRoute.jumpers&&this.inputRoute.jumpers.length>0){this.filteredJumperPads.push(...s(this.inputRoute.jumpers,this.inputRoute.connectionName));for(const t of this.inputRoute.jumpers)for(let e=0;e<this.inputRoute.route.length;e++){const n=this.inputRoute.route[e];(Math.abs(n.x-t.start.x)<.01&&Math.abs(n.y-t.start.y)<.01||Math.abs(n.x-t.end.x)<.01&&Math.abs(n.y-t.end.y)<.01)&&this.jumperPadPointIndices.add(e)}}this.computePathSegments()}computePathSegments(){let t=0;for(let e=0;e<this.inputRoute.route.length-1;e++){const n=this.inputRoute.route[e],s=this.inputRoute.route[e+1],o=Math.sqrt((s.x-n.x)**2+(s.y-n.y)**2)+e/1e4;this.pathSegments.push({start:n,end:s,length:o,startDistance:t,endDistance:t+o}),t+=o}this.totalPathLength=t}arePointsEqual(t,e){return t.x===e.x&&t.y===e.y&&t.z===e.z}getPointAtDistance(t){t=Math.max(0,Math.min(t,this.totalPathLength));const e=this.pathSegments.find(e=>t>=e.startDistance&&t<=e.endDistance);if(!e)return this.inputRoute.route[this.inputRoute.route.length-1];const n=(t-e.startDistance)/e.length;return{x:e.start.x+n*(e.end.x-e.start.x),y:e.start.y+n*(e.end.y-e.start.y),z:n<.5?e.start.z:e.end.z}}getNearestIndexForDistance(t){if(t<=0)return 0;if(t>=this.totalPathLength)return this.inputRoute.route.length-1;const e=this.pathSegments.findIndex(e=>t>=e.startDistance&&t<=e.endDistance);if(-1===e)return 0;const n=this.pathSegments[e],s=(n.startDistance+n.endDistance)/2;return t>s?e+1:e}isValidPathSegment(t,e){for(const n of this.filteredObstacles){if(!n.zLayers?.includes(t.z))continue;if(At(t,e,n)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2)return!1}const n=this.segmentTree.getSegmentsThatCouldIntersect(t,e);for(const[s,o,i]of n)if(s.z===t.z&&o.z===t.z){if(ho({x:t.x,y:t.y},{x:e.x,y:e.y},{x:s.x,y:s.y},{x:o.x,y:o.y})<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS)return!1}for(const n of this.filteredVias)if(vt(n,t,e)<this.OBSTACLE_MARGIN+n.diameter/2+this.TRACE_THICKNESS/2)return!1;for(const n of this.filteredJumperPads){if(At(t,e,n)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2)return!1}if(this.outline&&this.outline.length>=3){const n=(({start:t,end:e,polygon:n,margin:s=.2})=>{if(!n||n.length<3)return!1;const o=vo(t,n),i=vo(e,n);if(!o||!i)return!0;for(let o=0;o<n.length;o++){const i=n[o],r=n[(o+1)%n.length],a=yo(t,i,r),c=yo(e,i,r);if(a&&c)continue;if(!gt(t,e,i,r)){if(!a&&!c&&ho(t,e,i,r)<s-go)return!0;continue}const h=Pt(t,e,i,r);if(!(h&&(a&&xo(h,t)||c&&xo(h,e))||h&&(xo(h,t)||xo(h,e))))return!0}return!1})({start:{x:t.x,y:t.y},end:{x:e.x,y:e.y},polygon:this.outline});if(n)return!1}return!0}isValidPath(t){if(t.length<2)return!0;for(let e=0;e<t.length-1;e++)if(t[e].z!==t[e+1].z)return!1;for(let e=0;e<t.length-1;e++)if(!this.isValidPathSegment(t[e],t[e+1]))return!1;return!0}find45DegreePath(t,e){if(this.arePointsEqual(t,e))return[t];if(t.z!==e.z)return null;const n=((t,e)=>{const n=[],s=Math.abs(e.x-t.x),o=Math.abs(e.y-t.y),i=e.x>t.x?1:-1,r=e.y>t.y?1:-1,a={x:e.x-i*Math.abs(e.y-t.y),y:t.y};(a.x-t.x)*i>=0&&(a.x-e.x)*i<=0&&n.push([t,a,e]);const c={x:t.x,y:e.y-r*Math.abs(e.x-t.x)};(c.y-t.y)*r>=0&&(c.y-e.y)*r<=0&&n.push([t,c,e]);const h=Math.min(s,o),d={x:t.x+i*h,y:t.y+r*h};return(d.x-t.x)*i>=0&&(d.x-e.x)*i<=0&&(d.y-t.y)*r>=0&&(d.y-e.y)*r<=0&&n.push([t,d,e]),n})({x:t.x,y:t.y},{x:e.x,y:e.y});for(const e of n){const n=e.map(e=>({x:e.x,y:e.y,z:t.z}));if(this.isValidPath(n))return n}return null}addPathToResult(t){if(0!==t.length){for(let e=0;e<t.length;e++)0===e&&this.newRoute.length>0&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t[e])||this.newRoute.push(t[e]);this.currentStepSize=this.maxStepSize}}moveHead(t){this.lastHeadMoveDistance=t,this.headDistanceAlongPath=Math.min(this.headDistanceAlongPath+t,this.totalPathLength)}stepBackAndReduceStepSize(){this.headDistanceAlongPath=Math.max(this.tailDistanceAlongPath,this.headDistanceAlongPath-this.lastHeadMoveDistance),this.currentStepSize=Math.max(this.minStepSize,this.currentStepSize*this.STEP_SIZE_REDUCTION_FACTOR)}_step(){const t=this.tailDistanceAlongPath>=this.totalPathLength,e=this.headDistanceAlongPath>=this.totalPathLength;if(t){const t=this.inputRoute.route[this.inputRoute.route.length-1];return 0!==this.newRoute.length&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t)||this.newRoute.push(t),void(this.solved=!0)}if(e){const t=this.getPointAtDistance(this.tailDistanceAlongPath),e=this.inputRoute.route[this.inputRoute.route.length-1],n=this.find45DegreePath(t,e);if(n)return this.addPathToResult(n),void(this.solved=!0);this.lastValidPath=null,this.tailDistanceAlongPath=this.totalPathLength,this.headDistanceAlongPath=this.totalPathLength;const s=[];for(const t of this.inputRoute.route)0!==s.length&&this.arePointsEqual(s[s.length-1],t)||s.push(t);return this.newRoute=s,this.newVias=[...this.inputRoute.vias],void(this.solved=!0)}this.moveHead(this.currentStepSize);const n=this.getPointAtDistance(this.tailDistanceAlongPath),s=this.getPointAtDistance(this.headDistanceAlongPath),o=this.getNearestIndexForDistance(this.tailDistanceAlongPath),i=this.getNearestIndexForDistance(this.headDistanceAlongPath);let r=!1,a=-1;for(let t=o;t<i;t++)if(t+1<this.inputRoute.route.length&&this.inputRoute.route[t].z!==this.inputRoute.route[t+1].z){r=!0;const e=t;a=this.pathSegments[e].startDistance;break}if(r&&this.lastHeadMoveDistance>this.minStepSize)return void this.stepBackAndReduceStepSize();let c=!1,h=-1,d=-1;for(let t=o+1;t<=i;t++)if(this.jumperPadPointIndices.has(t)){c=!0,h=t,d=t>0&&t-1<this.pathSegments.length?this.pathSegments[t-1].endDistance:this.pathSegments[0]?.startDistance??0;break}if(c&&this.lastHeadMoveDistance>this.minStepSize)return void this.stepBackAndReduceStepSize();if(c&&h>=0){const t=this.inputRoute.route[h];this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null);const e=this.newRoute[this.newRoute.length-1];return e&&e.x===t.x&&e.y===t.y||this.newRoute.push({x:t.x,y:t.y,z:t.z}),this.currentStepSize=this.maxStepSize,this.tailDistanceAlongPath=d,this.headDistanceAlongPath=this.tailDistanceAlongPath,this.lastValidPath=null,void(this.lastValidPathHeadDistance=this.tailDistanceAlongPath)}if(r&&a>0){const t=this.getNearestIndexForDistance(a)+1,e=this.inputRoute.route[t],n={x:e.x,y:e.y};this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null);const s=this.newRoute[this.newRoute.length-1];s.x===n.x&&s.y===n.y||this.newRoute.push({x:n.x,y:n.y,z:s.z}),this.newVias.push(n),this.newRoute.push({x:n.x,y:n.y,z:e.z}),this.currentStepSize=this.maxStepSize;const o=this.pathSegments.findIndex(t=>t.start===e);if(-1!==o)this.tailDistanceAlongPath=this.pathSegments[o].startDistance,this.headDistanceAlongPath=this.tailDistanceAlongPath,this.lastValidPath=null,this.lastValidPathHeadDistance=this.tailDistanceAlongPath;else if(t<this.inputRoute.route.length){if(t===this.inputRoute.route.length-1)return void(this.solved=!0);console.warn("Fallback used for tailDistanceAlongPath after layer change");const e=this.pathSegments.find(e=>e.start===this.inputRoute.route[t]);e?(this.tailDistanceAlongPath=e.startDistance,this.headDistanceAlongPath=this.tailDistanceAlongPath,this.lastValidPath=null,this.lastValidPathHeadDistance=this.tailDistanceAlongPath):(console.error(`[${this.inputRoute.connectionName}] Could not find segment start after layer change. Path might be incomplete.\n Index sought: ${t}, Point: (${this.inputRoute.route[t].x.toFixed(3)}, ${this.inputRoute.route[t].y.toFixed(3)}, z=${this.inputRoute.route[t].z})\n Route Length: ${this.inputRoute.route.length}, Path Segments: ${this.pathSegments.length}`),this.solved=!0)}else console.warn("Layer change occurred at the end of the path."),this.solved=!0;return}const l=this.find45DegreePath(n,s);if(!l&&this.lastHeadMoveDistance>this.minStepSize)this.stepBackAndReduceStepSize();else{if(!l&&!this.lastValidPath){const t=this.getPointAtDistance(this.tailDistanceAlongPath);this.tailDistanceAlongPath+=this.minStepSize,this.moveHead(this.minStepSize);const e=this.getNearestIndexForDistance(this.tailDistanceAlongPath),n=this.inputRoute.route[e],s=this.inputRoute.route[this.inputRoute.route.length-1];return void(this.arePointsEqual(t,n)||this.arePointsEqual(n,s)||this.newRoute.push(n))}if(l)return this.lastValidPath=l,void(this.lastValidPathHeadDistance=this.headDistanceAlongPath);this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null,this.tailDistanceAlongPath=this.lastValidPathHeadDistance,this.moveHead(this.minStepSize))}}visualize(){const t=this.getVisualsForNewRouteAndObstacles(),e=this.getPointAtDistance(this.tailDistanceAlongPath),n=this.getPointAtDistance(this.headDistanceAlongPath);t.points.push({x:e.x,y:e.y,color:"yellow",label:["Tail",`z: ${e.z}`].join("\n")}),t.points.push({x:n.x,y:n.y,color:"orange",label:["Head",`z: ${n.z}`].join("\n")});const s=this.getPointAtDistance(this.headDistanceAlongPath+this.currentStepSize);t.points.push({x:s.x,y:s.y,color:"red",label:["Tentative Head",`z: ${s.z}`].join("\n")});let o=0;for(;o<this.totalPathLength;){const e=this.getPointAtDistance(o);t.circles.push({center:{x:e.x,y:e.y},radius:.05,fill:"rgba(100, 100, 100, 0.5)"}),o+=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}},Po=class extends y{simplifiedHdRoutes;currentUnsimplifiedHdRouteIndex=0;activeSubSolver=null;unsimplifiedHdRoutes;obstacles;connMap;colorMap;outline;defaultViaDiameter;constructor(t){super(),this.MAX_ITERATIONS=1e8,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.obstacles=t.obstacles,this.connMap=t.connMap||new Fe({}),this.colorMap=t.colorMap||{},this.outline=t.outline,this.defaultViaDiameter=t.defaultViaDiameter??.6,this.simplifiedHdRoutes=[]}_step(){const t=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];if(!this.activeSubSolver)return t?(this.activeSubSolver=new So({inputRoute:t,otherHdRoutes:this.unsimplifiedHdRoutes.slice(this.currentUnsimplifiedHdRouteIndex+1).concat(this.simplifiedHdRoutes),obstacles:this.obstacles,connMap:this.connMap,colorMap:this.colorMap,outline:this.outline}),void this.currentUnsimplifiedHdRouteIndex++):void(this.solved=!0);this.activeSubSolver.step(),this.activeSubSolver.solved&&(this.simplifiedHdRoutes.push(this.activeSubSolver.simplifiedRoute),this.activeSubSolver=null)}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Multi Simplified Path Solver"};for(const e of this.unsimplifiedHdRoutes)if(!this.simplifiedHdRoutes.some(t=>t.connectionName===e.connectionName)){for(let n=0;n<e.route.length-1;n++)t.lines.push({points:[{x:e.route[n].x,y:e.route[n].y},{x:e.route[n+1].x,y:e.route[n+1].y}],strokeColor:1===e.route[n].z?"rgba(0, 0, 255, 0.4)":"rgba(255, 0, 0, 0.4)",strokeWidth:.15,strokeDash:1===e.route[n].z?[.5,.5]:void 0});for(const n of e.vias||[])t.circles.push({center:n,radius:(e.viaDiameter??this.defaultViaDiameter)/2,fill:"rgba(0, 0, 255, 0.4)"})}for(const e of this.simplifiedHdRoutes){const n=this.colorMap?.[e.connectionName]||"rgba(128, 128, 128, 0.8)";for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeWidth:.15,strokeColor:n,strokeDash:1===e.route[s].z?[.5,.5]:void 0,step:1});for(const n of e.vias||[])t.circles.push({center:n,radius:e.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)",step:1})}for(const e of this.unsimplifiedHdRoutes){for(let n=0;n<e.route.length-1;n++)t.lines.push({points:[{x:e.route[n].x,y:e.route[n].y},{x:e.route[n+1].x,y:e.route[n+1].y}],strokeWidth:.15,strokeColor:"rgba(255, 0, 0, 0.2)",strokeDash:[.5,.5],step:0,layer:`z${e.route[n].z.toString()}`});for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 0, 0.2)",step:0})}for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});if(this.currentUnsimplifiedHdRouteIndex<this.unsimplifiedHdRoutes.length){const e=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];e.route.length>0&&t.circles.push({center:{x:e.route[0].x,y:e.route[0].y},radius:.2,fill:"yellow",label:"Current"})}return t}},bo=class extends y{constructor(t){super(),this.input=t,this.MAX_ITERATIONS=1e6,this.inputHdRoutes=t.inputHdRoutes,this.mergedViaHdRoutes=structuredClone(this.inputHdRoutes),this.unprocessedRoutes=[...t.inputHdRoutes],this.colorMap=t.colorMap,this.outline=t.outline,this.obstacles=t.obstacles,this.obstacleSHI=new Qs("flatbush",t.obstacles),this.hdRouteSHI=new io(this.inputHdRoutes),this.vias=[],this.offendingVias=[],this.connMap=t.connMap,this.viasByNet=new Map,this.rebuildVias()}inputHdRoutes;mergedViaHdRoutes;unprocessedRoutes;vias;offendingVias;currentViaRoutes=[];connMap;colorMap;outline;obstacles;viasByNet;obstacleSHI=null;hdRouteSHI=null;rebuildVias(){this.vias=[],this.viasByNet=new Map;for(let t=0;t<this.mergedViaHdRoutes.length;t++){const e=this.mergedViaHdRoutes[t];for(let n=0;n<e.vias.length;n++){const s=e.vias[n],o={x:s.x,y:s.y,diameter:e.viaDiameter,net:this.connMap?.idToNetMap[e.connectionName]??"",layers:[...new Set(e.route.map(t=>t.z))],routeIndex:t};this.vias.push(o);const i=this.viasByNet.get(o.net);i?i.push(o):this.viasByNet.set(o.net,[o])}}}findNextOffendingPair(){for(let t=0;t<this.vias.length-1;t++){const e=this.vias[t],n=this.viasByNet.get(e.net);if(!n)continue;const s=n.indexOf(e);for(let t=s>=0?s+1:0;t<n.length;t++){const s=n[t],o=e.x-s.x,i=e.y-s.y,r=o*o+i*i,a=e.diameter/2+s.diameter/2;if(r<=a*a&&0!==r)return[e,s]}}return null}handleOffendingPair(t,e){const n=t.layers.length<e.layers.length?t:e,s=n===t?e:t,o=this.mergedViaHdRoutes[n.routeIndex].route;for(let t=0;t<n.layers.length;t++)for(let t=o.length-1;t>=1;t--){const e=o[t-1],i=o[t];if(i.x===n.x&&i.y===n.y){o.splice(t,0,{x:s.x,y:s.y,z:i.z}),o.splice(t,0,{x:s.x,y:s.y,z:e.z});const r=this.mergedViaHdRoutes[n.routeIndex];return r.vias=r.vias.map(t=>t.x===n.x&&t.y===n.y?{x:s.x,y:s.y}:t),void this.rebuildVias()}}this.rebuildVias()}_step(){const t=this.findNextOffendingPair();t?this.handleOffendingPair(t[0],t[1]):this.solved=!0}getMergedViaHdRoutes(){return this.mergedViaHdRoutes}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Same Net Via Merger Solver"};for(const e of this.input.obstacles){let n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),o=e.zLayers?.includes(1);s&&o?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":o&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.mergedViaHdRoutes){if(0===e.route.length)continue;const n=this.input.colorMap[e.connectionName]||"#888888";for(let n=0;n<e.route.length-1;n++){const s=e.route[n],o=e.route[n+1];s.z===o.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:o.x,y:o.y}],strokeColor:0===s.z?"rgba(255, 0, 0, 0.5)":"rgba(0, 0, 255, 0.5)",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const s=Je(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...s.rects??[]),t.lines.push(...s.lines??[])}}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},Mo=class extends y{constructor(t){super(),this.simplificationConfig=t,this.hdRoutes=[...t.hdRoutes],this.MAX_ITERATIONS=1e8}hdRoutes=[];simplificationPipelineLoops=0;MAX_SIMPLIFICATION_PIPELINE_LOOPS=2;PHASE_ORDER=["via_removal","via_merging","path_simplification"];currentPhase="via_removal";extractResult=null;get simplifiedHdRoutes(){return this.hdRoutes}_step(){if(this.simplificationPipelineLoops>=this.MAX_SIMPLIFICATION_PIPELINE_LOOPS)this.solved=!0;else{if(this.activeSubSolver){if(this.activeSubSolver.step(),!this.activeSubSolver.failed&&!this.activeSubSolver.solved)return;if(this.activeSubSolver.solved){if(this.extractResult&&(this.hdRoutes=this.extractResult(this.activeSubSolver)),this.activeSubSolver=null,this.extractResult=null,"via_removal"===this.currentPhase?this.currentPhase="via_merging":"via_merging"===this.currentPhase?this.currentPhase="path_simplification":(this.currentPhase="via_removal",this.simplificationPipelineLoops++),this.simplificationPipelineLoops>=this.MAX_SIMPLIFICATION_PIPELINE_LOOPS)return void(this.solved=!0)}else if(this.activeSubSolver.failed)return this.failed=!0,void(this.error=this.activeSubSolver.error??"Sub-solver failed without error message")}if(!this.activeSubSolver&&!this.solved)switch(this.currentPhase){case"via_removal":this.activeSubSolver=new ao({unsimplifiedHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,colorMap:this.simplificationConfig.colorMap,layerCount:this.simplificationConfig.layerCount}),this.extractResult=t=>t.getOptimizedHdRoutes()??[];break;case"via_merging":this.activeSubSolver=new bo({inputHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,colorMap:this.simplificationConfig.colorMap,layerCount:this.simplificationConfig.layerCount,connMap:this.simplificationConfig.connMap,outline:this.simplificationConfig.outline}),this.extractResult=t=>t.getMergedViaHdRoutes()??[];break;case"path_simplification":this.activeSubSolver=new Po({unsimplifiedHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,connMap:this.simplificationConfig.connMap,colorMap:this.simplificationConfig.colorMap,outline:this.simplificationConfig.outline,defaultViaDiameter:this.simplificationConfig.defaultViaDiameter}),this.extractResult=t=>t.simplifiedHdRoutes;break;default:this.failed=!0,this.error=`Unknown phase: ${this.currentPhase}`}}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Trace Simplification Solver"};for(const e of this.simplificationConfig.obstacles){let n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),o=e.zLayers?.includes(1);s&&o?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":o&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.hdRoutes)if(0!==e.route.length){for(let n=0;n<e.route.length-1;n++){const s=e.route[n],o=e.route[n+1];s.z===o.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:o.x,y:o.y}],strokeColor:0===s.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const n=Je(e.jumpers,{color:"orange",label:e.connectionName});t.rects.push(...n.rects??[]),t.lines.push(...n.lines??[])}}return t}};function No(t){const e=new Map;for(const n of t)for(const t of n.nodeIds)e.set(t,[...e.get(t)??[],n]);return e}var Io=class extends y{nodes;edges;traceWidth;obstacleMargin;minPortSpacing;nodeMap;nodeEdgeMap;sharedEdgeSegments=[];edgeSegmentMap=new Map;portPointMap=new Map;colorMap;constructor({nodes:t,edges:e,traceWidth:n,obstacleMargin:s,colorMap:o}){super(),this.nodes=t,this.edges=e,this.traceWidth=n,this.obstacleMargin=s??.15,this.minPortSpacing=this.traceWidth+this.obstacleMargin,this.colorMap=o??{},this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=No(e),this.MAX_ITERATIONS=1}_step(){this.computeAllSharedEdgeSegments(),this.solved=!0}computeAllSharedEdgeSegments(){for(const t of this.edges){const[e,n]=t.nodeIds,s=this.nodeMap.get(e),o=this.nodeMap.get(n);if(!s||!o)continue;const i=this.computeSharedEdgeSegment(t,s,o);if(i){this.sharedEdgeSegments.push(i),this.edgeSegmentMap.set(t.capacityMeshEdgeId,i);for(const t of i.portPoints)this.portPointMap.set(t.segmentPortPointId,t)}}}computeSharedEdgeSegment(t,e,n){const s=this.findOverlappingSegment(e,n);if(!s)return null;const o=e.availableZ.filter(t=>n.availableZ.includes(t));if(0===o.length)return null;const i=Math.sqrt((s.end.x-s.start.x)**2+(s.end.y-s.start.y)**2),r=3*this.minPortSpacing/4,a=Math.max(0,i-2*r);if(a<=0&&!e._containsTarget&&!n._containsTarget)return null;let c=Math.max(1,Math.floor(a/this.minPortSpacing)+1);if(e._offBoardConnectionId||n._offBoardConnectionId){if(e._offBoardConnectionId&&!n._offBoardConnectionId){if(this.shouldSkipOffBoardPortPoint(e,n))return null}else if(n._offBoardConnectionId&&!e._offBoardConnectionId&&this.shouldSkipOffBoardPortPoint(n,e))return null;c=1}const h=[],d=s.end.x-s.start.x,l=s.end.y-s.start.y,u=(s.start.x+s.end.x)/2,p=(s.start.y+s.end.y)/2;c>5&&(c=5+Math.floor(c/4));const m=[];for(let t=0;t<c;t++){let e;e=0===i||1===c?.5:(r+a*t/(c-1))/i;const n=s.start.x+d*e,o=s.start.y+l*e,h=Math.sqrt((n-u)**2+(o-p)**2);m.push({x:n,y:o,distToCenter:h})}const f=m.reduce((t,e)=>e.distToCenter<t.distToCenter?e:t);for(let s=0;s<c;s++){const{x:i,y:r}=m[s],a=Math.sqrt((i-f.x)**2+(r-f.y)**2);for(const c of o){const o={segmentPortPointId:`${t.capacityMeshEdgeId}_pp${s}_z${c}`,x:i,y:r,availableZ:[c],nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],edgeId:t.capacityMeshEdgeId,connectionName:null,distToCentermostPortOnZ:a};h.push(o)}}return{edgeId:t.capacityMeshEdgeId,nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],start:s.start,end:s.end,availableZ:o,portPoints:h}}shouldSkipOffBoardPortPoint(t,e){const n=this.nodeEdgeMap.get(e.capacityMeshNodeId)??[];for(const s of n){const n=s.nodeIds[0]===e.capacityMeshNodeId?s.nodeIds[1]:s.nodeIds[0];if(n===t.capacityMeshNodeId)continue;const o=this.nodeMap.get(n);if(o?._offBoardConnectionId!==t._offBoardConnectionId)continue;if(2!==this.nodes.filter(e=>e._offBoardConnectionId===t._offBoardConnectionId).length)continue;const i={x:(t.center.x+o.center.x)/2,y:(t.center.y+o.center.y)/2};if(i.x>=e.center.x-e.width/2&&i.x<=e.center.x+e.width/2&&i.y>=e.center.y-e.height/2&&i.y<=e.center.y+e.height/2)return!0}return!1}findOverlappingSegment(t,e){const n={start:Math.max(t.center.x-t.width/2,e.center.x-e.width/2),end:Math.min(t.center.x+t.width/2,e.center.x+e.width/2)},s={start:Math.max(t.center.y-t.height/2,e.center.y-e.height/2),end:Math.min(t.center.y+t.height/2,e.center.y+e.height/2)},o=n.end-n.start,i=s.end-s.start;if(o<-1e-4||i<-1e-4)return null;if(o<i){const t=(n.start+n.end)/2;return{start:{x:t,y:s.start},end:{x:t,y:s.end}}}{const t=(s.start+s.end)/2;return{start:{x:n.start,y:t},end:{x:n.end,y:t}}}}getAvailablePortPointsBetweenNodes(t,e){const n=this.edges.find(n=>n.nodeIds[0]===t&&n.nodeIds[1]===e||n.nodeIds[0]===e&&n.nodeIds[1]===t);if(!n)return[];const s=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return s?s.portPoints.filter(t=>null===t.connectionName):[]}getPortPointsForEdge(t,e){const n=this.edges.find(n=>n.nodeIds[0]===t&&n.nodeIds[1]===e||n.nodeIds[0]===e&&n.nodeIds[1]===t);if(!n)return[];const s=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return s?.portPoints??[]}assignPortPoint(t,e,n){const s=this.portPointMap.get(t);return!!s&&(null===s.connectionName&&(s.connectionName=e,s.rootConnectionName=n,!0))}releasePortPoint(t){const e=this.portPointMap.get(t);return!!e&&(e.connectionName=null,e.rootConnectionName=void 0,!0)}getAvailablePortCountForEdge(t,e){return this.getAvailablePortPointsBetweenNodes(t,e).length}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.sharedEdgeSegments){t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.5)"});for(const n of e.portPoints){const e=n.connectionName?this.colorMap[n.connectionName]??"blue":"rgba(0, 200, 0, 0.7)";t.circles.push({center:{x:n.x,y:n.y},radius:this.traceWidth/2,fill:e,layer:`z${n.availableZ.join(",")}`,label:[n.segmentPortPointId,n.connectionName,n.availableZ.join(","),`cd: ${n.distToCentermostPortOnZ}`,`connects: ${n.nodeIds.join(",")}`].filter(Boolean).join("\n")})}}return t}},Co=(t,e,n,s)=>{if(t?._containsTarget)return 0;if(1===(t.availableZ?.length??2)&&(e>0||n>0||s>0))return 1;return((.82*e+.41*n+.2*s)/2)**1.1/ke(t)};function _o(t,e,n,s,o){const i=n-e,r=o-s,a=1e-6;if(Math.abs(t.y-o)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(o-t.y);if(Math.abs(t.y-s)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-s);const c=Math.abs(t.y-o),h=Math.abs(t.x-n),d=Math.abs(t.y-s),l=Math.abs(t.x-e),u=Math.min(c,h,d,l);return u===c?Math.max(0,Math.min(i,t.x-e)):u===h?i+Math.max(0,Math.min(r,o-t.y)):u===d?i+r+Math.max(0,Math.min(i,n-t.x)):2*i+r+Math.max(0,Math.min(r,t.y-s))}function To(t,e,n=1e-6){return Math.abs(t-e)<n}function Eo(t){if(t.length<2)return 0;const e=t.map(([t,e])=>t<e?[t,e]:[e,t]);let n=0;for(let t=0;t<e.length;t++){const[s,o]=e[t];for(let i=t+1;i<e.length;i++){const[t,r]=e[i];To(s,t)||To(s,r)||To(o,t)||To(o,r)||(s<t&&t<o&&o<r||t<s&&s<r&&r<o)&&n++}}return n}var Ro=t=>{const e=t.center.x-t.width/2,n=t.center.x+t.width/2,s=t.center.y-t.height/2,o=t.center.y+t.height/2,i=new Map;for(const e of t.portPoints){const t=i.get(e.connectionName)??[];t.some(t=>t.x===e.x&&t.y===e.y&&t.z===e.z)||t.push({x:e.x,y:e.y,z:e.z}),i.set(e.connectionName,t)}const r=new Map,a=[];let c=0;for(const[t,h]of i){if(h.length<2)continue;const t=h[0],i=h[1],d=_o(t,e,n,s,o),l=_o(i,e,n,s,o);if(t.z===i.z){const e=t.z,n=r.get(e)??[];n.push([d,l]),r.set(e,n)}else c++,a.push([d,l])}let h=0;for(const[t,e]of r)h+=Eo(e);return{numSameLayerCrossings:h,numEntryExitLayerChanges:c,numTransitionPairCrossings:Eo(a)}},wo=(t,e)=>{const n=Math.ceil(e/7),s=(Math.floor(t.width/5)+.1)*(Math.floor(t.height/5.5)+.1);return Math.min(1,n/s)};function Ao(t,e,n,s){const o=e.x-n/2,i=e.x+n/2,r=e.y-s/2,a=e.y+s/2,c=Math.abs(t.y-a),h=Math.abs(t.x-i),d=Math.abs(t.y-r),l=Math.abs(t.x-o),u=Math.min(c,h,d,l);return u>.001?"interior":u===c?"top":u===h?"right":u===d?"bottom":"left"}function Oo(t,e,n,s,o){const i=Ao(t,n,s,o),r=Ao(e,n,s,o);return"interior"!==i&&i===r}function zo(t,e,n,s,o){const i=Ao(t,n,s,o);let r;if("top"===i||"bottom"===i){const n=s;r=Math.abs(e.x-t.x)/n}else{const n=o;r=Math.abs(e.y-t.y)/n}r=Math.min(1,Math.max(0,r));const a=(t.x+e.x)/2,c=(t.y+e.y)/2;return{x:a+(n.x-a)*r,y:c+(n.y-c)*r}}function Do(t){return"computeNodePf"in t&&"function"==typeof t.computeNodePf}function Lo(t){const e={lines:[],points:[],rects:[],circles:[]};for(const n of t.inputNodes){let s=0,o=0,i={numSameLayerCrossings:0,numEntryExitLayerChanges:0,numTransitionPairCrossings:0},r=0;if(Do(t)){s=t.computeNodePf(n),o=t.nodeMemoryPfMap.get(n.capacityMeshNodeId)??0;const e=t.buildNodeWithPortPointsForCrossing(n);i=Ro(e);const a=new Set,c=t.nodeAssignedPortPoints.get(n.capacityMeshNodeId)??[];for(const t of c)t.connectionName&&a.add(t.connectionName);r=a.size}else{s=t.nodePfMap.get(n.capacityMeshNodeId)??0;const e=t.nodeAssignedPortPoints.get(n.capacityMeshNodeId)??[],o={capacityMeshNodeId:n.capacityMeshNodeId,center:n.center,width:n.width,height:n.height,portPoints:e,availableZ:n.availableZ};i=Ro(o);const a=new Set;for(const t of e)t.connectionName&&a.add(t.connectionName);r=a.size}const a=Math.min(255,Math.floor(512*s)),c=Math.max(0,255-Math.floor(512*s));let h=`rgba(${a}, ${c}, ${c}, ${s<.001?"0.1":"0.3"})`;n._containsObstacle&&(h="rgba(255, 0, 0, 0.3)"),n._offBoardConnectedCapacityMeshNodeIds?.length&&(h="rgba(255, 165, 0, 0.3)"),e.rects.push({center:n.center,width:n.width-.2,height:n.height-.2,layer:`z${n.availableZ.join(",")}`,fill:h,label:`${n.capacityMeshNodeId}\npf: ${s.toFixed(3)}, memPf: ${o.toFixed(3)}\nC#: ${r}\nxSame: ${i.numSameLayerCrossings}, xLC: ${i.numEntryExitLayerChanges}, xTransition: ${i.numTransitionPairCrossings}\nobCmid: ${n._offBoardConnectedCapacityMeshNodeIds?.join(",")}\nobs: ${n._containsObstacle?"yes":"no"}`})}if(Do(t))for(const[n,s]of t.portPointMap){const o=t.assignedPortPoints.get(n),i=o?t.colorMap[o.connectionName]??"blue":"rgba(150, 150, 150, 0.5)";e.circles.push({center:{x:s.x,y:s.y},radius:.05,fill:i,layer:`z${s.z}`,label:[n,`conn: ${o?.connectionName}`,`cd: ${s.distToCentermostPortOnZ}`,`connects: ${s.connectionNodeIds.join(",")}`,`rootConn: ${o?.rootConnectionName}`].filter(Boolean).join("\n")})}const n=Do(t)?t.connectionsWithResults:t.connectionResults;for(const s of n){if(!s.path)continue;const n=s.connection,o=t.colorMap[n.name]??"blue",i=[];for(const t of s.path)i.push({x:t.point.x,y:t.point.y,z:t.z,nodeId:t.currentNodeId});for(let n=0;n<i.length-1;n++){const s=i[n],r=i[n+1],a=s.z===r.z,c=s.z;let h;h=a?0===c?void 0:"10 5":"3 3 10";const d=s.nodeId?t.nodeMap.get(s.nodeId):null;if(d&&Oo(s,r,d.center,d.width,d.height)){const t=zo(s,r,d.center,d.width,d.height);e.lines.push({points:[{x:s.x,y:s.y},{x:t.x,y:t.y}],strokeColor:o,strokeDash:h}),e.lines.push({points:[{x:t.x,y:t.y},{x:r.x,y:r.y}],strokeColor:o,strokeDash:h})}else e.lines.push({points:[{x:s.x,y:s.y},{x:r.x,y:r.y}],strokeColor:o,strokeDash:h})}}if(Do(t)&&!t.solved&&t.candidates&&t.candidates.length>0){const n=t.currentConnection,s=n?t.colorMap[n.connection.name]??"blue":"blue";if(n){const[o,i]=n.nodeIds,r=t.nodeMap.get(o),a=t.nodeMap.get(i),c=n.connection.pointsToConnect[0],h=n.connection.pointsToConnect[n.connection.pointsToConnect.length-1];if(r&&a){const t=c?{x:c.x,y:c.y}:r.center,o=h?{x:h.x,y:h.y}:a.center;e.lines.push({points:[t,o],strokeColor:it(s,.5),strokeDash:"5 5"}),e.points.push({x:t.x,y:t.y,color:s,label:[`Start: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.points.push({x:o.x,y:o.y,color:s,label:[`End: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.circles.push({center:o,radius:.08,stroke:s,label:`Goal: ${n.connection.name}`})}}const o=[...t.candidates].sort((t,e)=>t.f-e.f).slice(0,1);for(const i of o){const o=[];let r=i;for(;r;)o.unshift({x:r.point.x,y:r.point.y,z:r.z,lastMoveWasOffBoard:r.lastMoveWasOffBoard,nodeId:r.currentNodeId}),r=r.prevCandidate;for(let n=0;n<o.length-1;n++){const i=o[n],r=o[n+1],a=i.z===r.z,c=i.z;let h;h=r.lastMoveWasOffBoard?"2 2":a?0===c?void 0:"10 5":"3 3 10";const d=i.nodeId?t.nodeMap.get(i.nodeId):null,l=.02*i.z;if(d&&Oo(i,r,d.center,d.width,d.height)){const t=zo(i,r,d.center,d.width,d.height);e.lines.push({points:[{x:i.x+l,y:i.y+l},{x:t.x+l,y:t.y+l}],strokeColor:it(s,.25),strokeDash:h}),e.lines.push({points:[{x:t.x+l,y:t.y+l},{x:r.x+l,y:r.y+l}],strokeColor:it(s,.25),strokeDash:h})}else e.lines.push({points:[{x:i.x+l,y:i.y+l},{x:r.x+l,y:r.y+l}],strokeColor:it(s,.25),strokeDash:h})}if(o.length>=1){const r=o[o.length-1];let a=0,c=0,h=0,d=0,l=0,u=0;const p=t.nodeMap.get(i.prevCandidate?.currentNodeId);if(p&&i.prevCandidate&&i.portPoint&&n){const e=n.connection.name,s={x:i.prevCandidate.point.x,y:i.prevCandidate.point.y,z:i.prevCandidate.z,connectionName:e},o={x:i.portPoint.x,y:i.portPoint.y,z:i.portPoint.z,connectionName:e},r=t.buildNodeWithPortPointsForCrossing(p,[s,o]),m=de(r);h=m.numSameLayerCrossings,d=m.numTransitionPairCrossings,l=m.numEntryExitLayerChanges;const f=t.capacityMeshNodeMap.get(p.capacityMeshNodeId);f&&(c=t.JUMPER_PF_FN_ENABLED&&1===p.availableZ.length?wo(f,h):Co(f,h,l,d),a=c**2*t.NODE_PF_FACTOR),u=i.prevCandidate.g>0?i.g-i.prevCandidate.g:i.g}if(!n)continue;const[m,f]=n.nodeIds,g=t.nodeMap.get(f),y=g?Math.sqrt((r.x-g.center.x)**2+(r.y-g.center.y)**2):0,x=t.avgNodePitch>0?y/t.avgNodePitch:0,v=x*t.BASE_CANDIDATE_COST,S=t.nodeMemoryPfMap.get(i.currentNodeId)??0,P=-Math.log(1-S)*t.MEMORY_PF_FACTOR;e.circles.push({center:r,radius:.03,fill:it(s,.25),layer:`z${i.z}`,label:[`f: ${i.f.toFixed(2)}`,`g: ${i.g.toFixed(2)} (nodeDelta: ${u.toFixed(2)})`,`h: ${i.h.toFixed(2)}`,` dist: ${y.toFixed(2)}`,` estHops: ${x.toFixed(1)}`,` estStepCost: ${v.toFixed(2)}`,` memRiskCost: ${P.toFixed(2)}`,`z: ${i.z}`,`node: ${i.currentNodeId}`,`Cost(Pf): ${a.toFixed(3)}`,`Pf: ${c.toFixed(3)}`,`xSame: ${h}, xTrans: ${d}, xLC: ${l}`,`routeOffBoard=${t.currentConnectionShouldRouteOffBoard}`,`offBoardTouched=${i.hasTouchedOffBoardNode??!1}`,`lastMoveWasOffBoard=${i.lastMoveWasOffBoard??!1}`].join("\n")})}}}return e}function Fo(t,e){const n=[],s=e.filter(t=>t._containsTarget),o=new Map;for(const i of t.connections){const t=[];for(const n of i.pointsToConnect){let o=e[0],i=Number.MAX_VALUE;for(const t of s){const e=Math.sqrt((t.center.x-n.x)**2+(t.center.y-n.y)**2);e<i&&(i=e,o=t)}t.push(o)}if(t.length<2)throw new Error(`Not enough nodes for connection "${i.name}", only ${t.length} found`);o.set(i.name,t.map(t=>t.capacityMeshNodeId)),n.push({connection:i,nodeIds:[t[0].capacityMeshNodeId,t[t.length-1].capacityMeshNodeId],straightLineDistance:St(t[0].center,t[t.length-1].center)})}return{unshuffledConnectionsWithResults:n,connectionNameToGoalNodeIds:o}}function Xo(t,e){const n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),s=e.map(t=>(t.width+t.height)/2).filter(t=>Number.isFinite(t)&&t>0),o=s.length>0?s.reduce((t,e)=>t+e,0)/s.length:1,i=e.filter(t=>t._offBoardConnectionId),r=new Map,a=new Map,c=new Map;for(const t of e)a.set(t.capacityMeshNodeId,[]),c.set(t.capacityMeshNodeId,[]);for(const t of e)for(const e of t.portPoints){r.set(e.portPointId,e);for(const t of e.connectionNodeIds){const n=a.get(t);n&&!n.some(t=>t.portPointId===e.portPointId)&&n.push(e)}}const{unshuffledConnectionsWithResults:h,connectionNameToGoalNodeIds:d}=Fo(t,e);return{nodeMap:n,avgNodePitch:o,offBoardNodes:i,portPointMap:r,nodePortPointsMap:a,nodeAssignedPortPoints:c,unshuffledConnectionsWithResults:h,connectionNameToGoalNodeIds:d}}function Yo(t,e,n){let s=0;const o=n?.NODE_MAX_PF??.99999;for(const n of t){const t=e.get(n.capacityMeshNodeId);if(!t)continue;if(t._containsTarget)continue;const i=Ro(n),r=Math.min(Co(t,i.numSameLayerCrossings,i.numEntryExitLayerChanges,i.numTransitionPairCrossings),o);s+=Math.log(1-r)}return s}function $o(t,e){if(e._containsTarget)return 0;const n=Ro(t);return Co(e,n.numSameLayerCrossings,n.numEntryExitLayerChanges,n.numTransitionPairCrossings)}function ko(t,e,n,s,o){const i=n-e,r=o-s,a=1e-6;if(Math.abs(t.y-o)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(o-t.y);if(Math.abs(t.y-s)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-s);const c=Math.abs(t.y-o),h=Math.abs(t.x-n),d=Math.abs(t.y-s),l=Math.abs(t.x-e),u=Math.min(c,h,d,l);return u===c?Math.max(0,Math.min(i,t.x-e)):u===h?i+Math.max(0,Math.min(r,o-t.y)):u===d?i+r+Math.max(0,Math.min(i,n-t.x)):2*i+r+Math.max(0,Math.min(r,t.y-s))}function Bo(t,e,n){let s=0;const o=n?.NODE_MAX_PF??.99999;for(const n of t){const t=e.get(n.capacityMeshNodeId);if(!t)continue;if(t._containsTarget)continue;const i=Ro(n),r=Math.min(wo(t,i.numSameLayerCrossings),o);s+=Math.log(1-r)}return s}function jo(t){let e=t;return()=>{e+=1831565813;let t=e;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296}}var Wo=[{SHUFFLE_SEED:100,NODE_PF_FACTOR:100,NODE_PF_MAX_PENALTY:100,MEMORY_PF_FACTOR:0,EXPANSION_DEGREES:10,FORCE_CENTER_FIRST:!0,FORCE_OFF_BOARD_FREQUENCY:0,CENTER_OFFSET_DIST_PENALTY_FACTOR:0}],Ho=class extends y{simpleRouteJson;inputNodes;capacityMeshNodes;capacityMeshEdges;colorMap;nodeMap;capacityMeshNodeMap;connectionResults;assignedPortPoints;nodeAssignedPortPoints;sections=[];activeSubSolver=null;currentSection=null;sectionScoreBeforeOptimization=0;currentSectionCenterNodeId=null;currentScheduleIndex=0;nodePfMap=new Map;attemptsToFixNode=new Map;sectionAttempts=0;MAX_ATTEMPTS_PER_NODE=100;MAX_SECTION_ATTEMPTS=50;ACCEPTABLE_PF=.05;FRACTION_TO_REPLACE=.2;JUMPER_PF_FN_ENABLED=!1;SHUFFLE_SEEDS_PER_SECTION=null;ALWAYS_RIP_INTERSECTIONS=!0;effort=1;HYPERPARAMETER_SCHEDULE=Wo;constructor(t){super(),this.MAX_ITERATIONS=1e6,this.simpleRouteJson=t.simpleRouteJson,this.inputNodes=t.inputNodes,this.capacityMeshNodes=t.capacityMeshNodes,this.capacityMeshEdges=t.capacityMeshEdges,this.colorMap=t.colorMap??{},this.effort=t.effort??1,void 0!==t.FRACTION_TO_REPLACE&&(this.FRACTION_TO_REPLACE=t.FRACTION_TO_REPLACE),void 0!==t.ALWAYS_RIP_INTERSECTIONS&&(this.ALWAYS_RIP_INTERSECTIONS=t.ALWAYS_RIP_INTERSECTIONS),void 0!==t.MAX_ATTEMPTS_PER_NODE&&(this.MAX_ATTEMPTS_PER_NODE=t.MAX_ATTEMPTS_PER_NODE),void 0!==t.MAX_SECTION_ATTEMPTS&&(this.MAX_SECTION_ATTEMPTS=t.MAX_SECTION_ATTEMPTS),void 0!==t.HYPERPARAMETER_SCHEDULE&&(this.HYPERPARAMETER_SCHEDULE=t.HYPERPARAMETER_SCHEDULE),this.JUMPER_PF_FN_ENABLED=t.JUMPER_PF_FN_ENABLED??this.JUMPER_PF_FN_ENABLED,this.SHUFFLE_SEEDS_PER_SECTION=t.SHUFFLE_SEEDS_PER_SECTION,this.MAX_SECTION_ATTEMPTS*=this.effort,this.nodeMap=new Map(t.inputNodes.map(t=>[t.capacityMeshNodeId,t])),this.capacityMeshNodeMap=new Map(t.capacityMeshNodes.map(t=>[t.capacityMeshNodeId,t])),this.connectionResults=[...t.initialConnectionResults],this.assignedPortPoints=new Map(t.initialAssignedPortPoints),this.nodeAssignedPortPoints=new Map(t.initialNodeAssignedPortPoints),this.nodePfMap=this.computeInitialPfMap();const e=this.computeBoardScore();this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.nodesExamined=0,this.stats.sectionAttempts=0,this.stats.sectionScores={},this.stats.initialBoardScore=e,this.stats.currentBoardScore=e,this.stats.errors=0}computeInitialPfMap(){const t=new Map;for(const e of this.capacityMeshNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];if(0===n.length)continue;const s={capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ},o=this.JUMPER_PF_FN_ENABLED&&1===e.availableZ.length?wo(e,Ro(s).numSameLayerCrossings):$o(s,e);t.set(e.capacityMeshNodeId,o)}return t}computeBoardScore(){const t=this.getNodesWithPortPoints();return this.computeScoreForNodes(t)}computeScoreForNodes(t){return this.JUMPER_PF_FN_ENABLED?Bo(t,this.capacityMeshNodeMap):Yo(t,this.capacityMeshNodeMap)}recomputePfForNodes(t){for(const e of t){const t=this.capacityMeshNodeMap.get(e);if(!t)continue;const n=this.nodeAssignedPortPoints.get(e)??[];if(0===n.length){this.nodePfMap.set(e,0);continue}const s={capacityMeshNodeId:e,center:t.center,width:t.width,height:t.height,portPoints:n,availableZ:t.availableZ},o=this.JUMPER_PF_FN_ENABLED&&1===t.availableZ.length?wo(t,Ro(s).numSameLayerCrossings):$o(s,t);this.nodePfMap.set(e,o)}}getCreatePortPointSectionInput(){return{inputNodes:this.inputNodes,capacityMeshNodes:this.capacityMeshNodes,capacityMeshEdges:this.capacityMeshEdges,nodeMap:this.nodeMap,connectionResults:this.connectionResults}}createSection(t){return function(t,e){const{inputNodes:n,capacityMeshNodes:s,capacityMeshEdges:o,connectionResults:i}=t,{centerOfSectionCapacityNodeId:r,expansionDegrees:a}=e,c=new Map;for(const t of o){const[e,n]=t.nodeIds;c.has(e)||c.set(e,new Set),c.has(n)||c.set(n,new Set),c.get(e).add(n),c.get(n).add(e)}const h=new Set,d=new Set,l=[];for(l.push({nodeId:r,depth:0}),d.add(r);l.length>0;){const{nodeId:t,depth:e}=l.shift();if(h.add(t),e<a){const n=c.get(t)??new Set;for(const t of n)d.has(t)||(d.add(t),l.push({nodeId:t,depth:e+1}))}}const u=n.filter(t=>h.has(t.capacityMeshNodeId)),p=s.filter(t=>h.has(t.capacityMeshNodeId)),m=[],f=[];for(const t of o){const[e,n]=t.nodeIds,s=h.has(e),o=h.has(n);s&&o?m.push(t):(s||o)&&f.push(t)}const g=u.map(t=>{const e=t.portPoints.filter(t=>{const[e,n]=t.connectionNodeIds,s=h.has(e),o=h.has(n);return s||o});return{...t,portPoints:e}}),y=function(t,e){const n=[];for(const s of t){if(!s.path||0===s.path.length)continue;const t=s.connection.name,o=s.connection.rootConnectionName,i=[];for(let t=0;t<s.path.length;t++){const n=s.path[t];e.has(n.currentNodeId)&&i.push(t)}if(0===i.length)continue;const r=i[0],a=i[i.length-1];let c=r,h=a;if(r>0){const t=s.path[0].currentNodeId;(s.nodeIds[0]===t||s.nodeIds[1]===t)&&(c=0)}if(a<s.path.length-1){const t=s.path.length-1,e=s.path[t].currentNodeId;(s.nodeIds[0]===e||s.nodeIds[1]===e)&&(h=t)}const d=s.path.slice(c,h+1),l=c>0,u=h<s.path.length-1;n.push({connectionName:t,rootConnectionName:o,points:d.map(t=>({x:t.point.x,y:t.point.y,z:t.z,nodeId:t.currentNodeId,portPointId:t.portPoint?.portPointId})),originalStartIndex:c,originalEndIndex:h,hasEntryFromOutside:l,hasExitToOutside:u})}return n}(i??[],h);return{centerNodeId:r,expansionDegrees:a,nodeIds:h,inputNodes:g,capacityMeshNodes:p,internalEdges:m,boundaryEdges:f,sectionPaths:y}}(this.getCreatePortPointSectionInput(),t)}getSectionNodesWithPortPoints(t){const e=[];for(const n of t.nodeIds){const t=this.nodeMap.get(n),s=this.capacityMeshNodeMap.get(n);if(!t||!s)continue;const o=this.nodeAssignedPortPoints.get(n)??[];o.length>0&&e.push({capacityMeshNodeId:n,center:t.center,width:t.width,height:t.height,portPoints:o,availableZ:t.availableZ})}return e}getNodesWithPortPoints(){const t=[];for(const e of this.inputNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];n.length>0&&t.push({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ})}return t}findHighestPfNode(){let t=null,e=0;for(const[n,s]of this.nodePfMap.entries()){s*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_ATTEMPTS_PER_NODE)**2>e&&(e=s,t=n)}return!t||e<this.ACCEPTABLE_PF?null:t}currentSectionCutPathInfo=new Map;currentSectionKeptPortPoints=new Map;currentSectionFixedRoutes=[];determineConnectionsToRip(t,e){const n=31337*this.sectionAttempts,s=jo(n);if(this.FRACTION_TO_REPLACE>=1)return new Set(e);const o=function(t,e){const n=jo(e),s=[...t];for(let t=s.length-1;t>0;t--){const e=Math.floor(n()*(t+1));[s[t],s[e]]=[s[e],s[t]]}return s}(e,n),i=Math.max(1,Math.ceil(o.length*this.FRACTION_TO_REPLACE)),r=new Set(o.slice(0,i));if(this.ALWAYS_RIP_INTERSECTIONS){const n=function(t){const{section:e,nodePfMap:n,capacityMeshNodeMap:s,nodeAssignedPortPoints:o,acceptablePf:i}=t,r=[];for(const t of e.nodeIds){if((n.get(t)??0)<=i)continue;const e=s.get(t);if(!e)continue;const a=o.get(t)??[];if(a.length<2)continue;const c=e.center.x-e.width/2,h=e.center.x+e.width/2,d=e.center.y-e.height/2,l=e.center.y+e.height/2,u=new Map;for(const t of a){const e=u.get(t.connectionName)??[];e.some(e=>e.x===t.x&&e.y===t.y&&e.z===t.z)||e.push({x:t.x,y:t.y,z:t.z}),u.set(t.connectionName,e)}const p=new Map;for(const[t,e]of u){if(e.length<2)continue;const n=e[0],s=e[1];if(n.z!==s.z)continue;const o=ko(n,c,h,d,l),i=ko(s,c,h,d,l),r=n.z,a=p.get(r)??[];a.push({connectionName:t,t1:o,t2:i}),p.set(r,a)}const m=1e-6;for(const[,t]of p){const e=t.map(t=>({connectionName:t.connectionName,a:Math.min(t.t1,t.t2),b:Math.max(t.t1,t.t2)}));for(let t=0;t<e.length;t++){const{connectionName:n,a:s,b:o}=e[t];for(let i=t+1;i<e.length;i++){const{connectionName:t,a:a,b:c}=e[i];Math.abs(s-a)<m||Math.abs(s-c)<m||Math.abs(o-a)<m||Math.abs(o-c)<m||(s<a&&a<o&&o<c||a<s&&s<c&&c<o)&&r.push([n,t])}}}}return r}({section:t,nodePfMap:this.nodePfMap,capacityMeshNodeMap:this.capacityMeshNodeMap,nodeAssignedPortPoints:this.nodeAssignedPortPoints,acceptablePf:this.ACCEPTABLE_PF});for(const[t,o]of n){if(r.has(t)||r.has(o))continue;const n=e.includes(t),i=e.includes(o);if(n&&i){const e=s()<.5;r.add(e?t:o)}else n?r.add(t):i&&r.add(o)}}return this.stats.lastRipCount=r.size,r}createSectionSimpleRouteJson(t){const e=[];this.currentSectionCutPathInfo.clear(),this.currentSectionKeptPortPoints.clear(),this.currentSectionFixedRoutes=[];const n=[],s=[];for(const e of this.connectionResults){if(!e.path||0===e.path.length)continue;const[o,i]=e.nodeIds,r=t.nodeIds.has(o),a=t.nodeIds.has(i);r&&a&&(s.push(e),n.push(e.connection.name))}const o=[];for(const e of t.sectionPaths){if(!e.hasEntryFromOutside&&!e.hasExitToOutside)continue;if(e.points.length<2)continue;const t=this.connectionResults.find(t=>t.connection.name===e.connectionName);t&&(o.push({sectionPath:e,originalResult:t}),n.includes(e.connectionName)||n.push(e.connectionName))}const i=this.determineConnectionsToRip(t,n);for(const t of s)i.has(t.connection.name)&&e.push(t.connection);for(const{sectionPath:t,originalResult:n}of o){if(!i.has(t.connectionName))continue;const s=`__cut__${t.connectionName}__${t.originalStartIndex}`;this.colorMap[s]=this.colorMap[t.connectionName];const o=t.points[0],r=t.points[t.points.length-1],a={name:s,rootConnectionName:t.rootConnectionName??t.connectionName,pointsToConnect:[{x:o.x,y:o.y,layers:[`layer${o.z+1}`]},{x:r.x,y:r.y,layers:[`layer${r.z+1}`]}]};e.push(a),this.currentSectionCutPathInfo.set(s,{sectionPath:t,originalConnectionResult:n})}const r=new Set(n.filter(t=>!i.has(t)));if(r.size>0){for(const e of t.nodeIds){const t=(this.nodeAssignedPortPoints.get(e)??[]).filter(t=>r.has(t.connectionName));t.length>0&&this.currentSectionKeptPortPoints.set(e,t)}for(const t of s)r.has(t.connection.name)&&this.currentSectionFixedRoutes.push(t);for(const{sectionPath:t,originalResult:e}of o)if(r.has(t.connectionName)){const n={connection:{name:t.connectionName,rootConnectionName:t.rootConnectionName,pointsToConnect:e.connection.pointsToConnect},path:t.points.map(t=>({prevCandidate:null,portPoint:null,currentNodeId:t.nodeId,point:{x:t.x,y:t.y},z:t.z,f:0,g:0,h:0,distanceTraveled:0})),portPoints:t.points.map(e=>({portPointId:e.portPointId,x:e.x,y:e.y,z:e.z,connectionName:t.connectionName,rootConnectionName:t.rootConnectionName})),nodeIds:e.nodeIds,straightLineDistance:e.straightLineDistance};this.currentSectionFixedRoutes.push(n)}}return{...this.simpleRouteJson,connections:e}}prepareSectionInputNodesForCutPaths(t){const e=new Set;for(const[,t]of this.currentSectionCutPathInfo.entries()){const{sectionPath:n}=t;if(0===n.points.length)continue;const s=n.points[0].nodeId;e.add(s);const o=n.points[n.points.length-1].nodeId;e.add(o)}return t.inputNodes.map(t=>e.has(t.capacityMeshNodeId)?{...t,_containsTarget:!0}:t)}getHyperParametersForScheduleIndex(t,e){const n=this.HYPERPARAMETER_SCHEDULE[t];return{...n,SHUFFLE_SEED:(n.SHUFFLE_SEED??0)+17*e}}createSectionSolver(t){const e=this.createSectionSimpleRouteJson(t),n=this.prepareSectionInputNodesForCutPaths(t),s=Xo(e,n);for(const[t,e]of this.currentSectionKeptPortPoints){const n=s.nodeAssignedPortPoints.get(t)??[];s.nodeAssignedPortPoints.set(t,[...n,...e])}return new Vo({simpleRouteJson:e,inputNodes:n,capacityMeshNodes:t.capacityMeshNodes,colorMap:this.colorMap,nodeMemoryPfMap:this.nodePfMap,numShuffleSeeds:this.SHUFFLE_SEEDS_PER_SECTION??2*e.connections.length*this.effort,hyperParameters:{...this.getHyperParametersForScheduleIndex(this.currentScheduleIndex,this.sectionAttempts)},precomputedInitialParams:s,fixedRoutes:this.currentSectionFixedRoutes})}reattachSection(t,e,n,s){const o=[],i=[];for(const t of e)t.connection.name.startsWith("__cut__")?i.push(t):o.push(t);const r=new Set(o.map(t=>t.connection.name));this.connectionResults=this.connectionResults.filter(t=>!r.has(t.connection.name)),this.connectionResults.push(...o);for(const[e,n]of this.nodeAssignedPortPoints.entries()){if(!t.nodeIds.has(e))continue;const s=n.filter(t=>!r.has(t.connectionName));this.nodeAssignedPortPoints.set(e,s)}for(const[t,e]of this.assignedPortPoints.entries())r.has(e.connectionName)&&this.assignedPortPoints.delete(t);for(const e of i){const n=this.currentSectionCutPathInfo.get(e.connection.name);if(!n||!e.path)continue;const{sectionPath:s,originalConnectionResult:o}=n,i=o.path;if(!i)continue;const r=s.connectionName;for(const[e,n]of this.nodeAssignedPortPoints.entries()){const s=n.filter(n=>n.connectionName!==r||!t.nodeIds.has(e));this.nodeAssignedPortPoints.set(e,s)}const a=i.slice(0,s.originalStartIndex),c=i.slice(s.originalEndIndex+1),h=[];let d=a.length>0?a[a.length-1]:null;for(const t of e.path){const e={...t,prevCandidate:d};h.push(e),d=e}if(c.length>0&&h.length>0&&(c[0]={...c[0],prevCandidate:h[h.length-1]}),o.path=[...a,...h,...c],e.portPoints)for(const n of e.portPoints){const e={...n,connectionName:r,rootConnectionName:s.rootConnectionName??r};for(const s of t.inputNodes)for(const t of s.portPoints)if(Math.abs(t.x-n.x)<.001&&Math.abs(t.y-n.y)<.001&&t.z===n.z){for(const n of t.connectionNodeIds){const t=this.nodeAssignedPortPoints.get(n)??[];t.push(e),this.nodeAssignedPortPoints.set(n,t)}break}}}for(const[t,e]of n.entries())e.connectionName.startsWith("__cut__")||this.assignedPortPoints.set(t,e);for(const[t,e]of s.entries()){const n=e.filter(t=>!t.connectionName.startsWith("__cut__"));if(n.length>0){const e=this.nodeAssignedPortPoints.get(t)??[];this.nodeAssignedPortPoints.set(t,[...e,...n])}}}_step(){if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved||this.activeSubSolver.failed){if(this.activeSubSolver.failed){if(this.currentScheduleIndex++,this.activeSubSolver.error&&this.stats.errors++,this.currentScheduleIndex<this.HYPERPARAMETER_SCHEDULE.length&&this.currentSectionCenterNodeId){const t=this.HYPERPARAMETER_SCHEDULE[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:this.currentSectionCenterNodeId,expansionDegrees:t.EXPANSION_DEGREES}),this.activeSubSolver=this.createSectionSolver(this.currentSection)}else this.stats.failedOptimizations++,this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0;return}const t=this.activeSubSolver.getNodesWithPortPoints().map(t=>({...t,portPoints:t.portPoints.map(t=>{if(t.connectionName.startsWith("__cut__")){const e=t.connectionName.slice(7),n=e.lastIndexOf("__"),s=n>=0?e.slice(0,n):e;return{...t,connectionName:s}}return t})})),e=new Set;for(const n of t)for(const t of n.portPoints)e.add(t.connectionName);const n=this.getSectionNodesWithPortPoints(this.currentSection).map(t=>({...t,portPoints:t.portPoints.filter(t=>e.has(t.connectionName))})).filter(t=>t.portPoints.length>0),s=this.computeScoreForNodes(n),o=this.computeScoreForNodes(t),i=`attempt${this.sectionAttempts}`;if(this.stats.lastSectionScore=o,o>s){const t=this.stats.currentBoardScore;this.stats.lastBoardScore=t;const e=[...this.connectionResults],n=new Map(this.assignedPortPoints),s=new Map(Array.from(this.nodeAssignedPortPoints.entries()).map(([t,e])=>[t,[...e]]));this.reattachSection(this.currentSection,this.activeSubSolver.connectionsWithResults,this.activeSubSolver.assignedPortPoints,this.activeSubSolver.nodeAssignedPortPoints),this.recomputePfForNodes(this.currentSection.nodeIds);const o=this.computeBoardScore();this.stats.sectionScores[i]=o,o>t?(this.stats.successfulOptimizations++,this.stats.currentBoardScore=o):(this.connectionResults=e,this.assignedPortPoints=n,this.nodeAssignedPortPoints=s,this.recomputePfForNodes(this.currentSection.nodeIds),this.stats.failedOptimizations++),this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0}else if(this.currentScheduleIndex++,this.currentScheduleIndex<this.HYPERPARAMETER_SCHEDULE.length&&this.currentSectionCenterNodeId){const t=this.HYPERPARAMETER_SCHEDULE[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:this.currentSectionCenterNodeId,expansionDegrees:t.EXPANSION_DEGREES}),this.activeSubSolver=this.createSectionSolver(this.currentSection)}else this.stats.failedOptimizations++,this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0}return}if(this.sectionAttempts>=this.MAX_SECTION_ATTEMPTS)return void(this.solved=!0);const t=this.findHighestPfNode();if(!t)return void(this.solved=!0);this.sectionAttempts++,this.stats.sectionAttempts=this.sectionAttempts,this.stats.nodesExamined++,this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.currentSectionCenterNodeId=t,this.currentScheduleIndex=0;const e=this.HYPERPARAMETER_SCHEDULE[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:t,expansionDegrees:e.EXPANSION_DEGREES});const n=this.getSectionNodesWithPortPoints(this.currentSection);this.sectionScoreBeforeOptimization=this.computeScoreForNodes(n);if(0===this.createSectionSimpleRouteJson(this.currentSection).connections.length)return this.currentSection=null,void(this.currentSectionCenterNodeId=null);this.activeSubSolver=this.createSectionSolver(this.currentSection)}computeProgress(){return this.sectionAttempts/this.MAX_SECTION_ATTEMPTS}visualize(){return this.solved?Lo(this):this.activeSubSolver?this.activeSubSolver.visualize():this.currentSection?function(t,e){const n={lines:[],points:[],rects:[],circles:[]};for(const e of t.inputNodes){const s=e.capacityMeshNodeId===t.centerNodeId,o=s?"rgba(0, 200, 0, 0.3)":"rgba(200, 200, 200, 0.3)";n.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,layer:`z${e.availableZ.join(",")}`,fill:o,label:`${e.capacityMeshNodeId}${s?" (CENTER)":""}`})}for(const e of t.inputNodes)for(const t of e.portPoints){const e="rgba(150, 150, 150, 0.5)";n.circles.push({center:{x:t.x,y:t.y},radius:.05,fill:e,layer:`z${t.z}`,label:[t.portPointId,`cd: ${t.distToCentermostPortOnZ}`,`connects: ${t.connectionNodeIds.join(",")}`].filter(Boolean).join("\n")})}for(const s of t.sectionPaths){const t=e?.[s.connectionName]??"blue";for(let e=0;e<s.points.length-1;e++){const o=s.points[e],i=s.points[e+1],r=o.z===i.z,a=o.z;let c;c=r?0===a?"5 5":"10 5":"3 3 10",n.lines.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:t,strokeDash:c})}}return n}(this.currentSection,this.colorMap):Lo(this)}},Uo=class extends y{constructor(t){super(),this.input=t;const{simpleRouteJson:e,capacityMeshNodes:n,inputNodes:s,colorMap:o,nodeMemoryPfMap:i,hyperParameters:r,precomputedInitialParams:a,fixedRoutes:c}=t;if(this.input=structuredClone(t),this.MAX_ITERATIONS=1e8,this.simpleRouteJson=e,this.inputNodes=s,this.colorMap=o??{},this.capacityMeshNodeMap=new Map(n.map(t=>[t.capacityMeshNodeId,t])),this.nodeMemoryPfMap=i??new Map,this.hyperParameters=r??{},a){this.nodeMap=a.nodeMap,this.avgNodePitch=a.avgNodePitch,this.offBoardNodes=a.offBoardNodes,this.portPointMap=a.portPointMap,this.nodePortPointsMap=a.nodePortPointsMap,this.connectionNameToGoalNodeIds=a.connectionNameToGoalNodeIds;const{nodeAssignedPortPoints:t}=function(t){const e=new Map;for(const[n,s]of t.nodeAssignedPortPoints)e.set(n,[...s]);return{nodeAssignedPortPoints:e}}(a);this.nodeAssignedPortPoints=t,this.connectionsWithResults=kt(structuredClone(a.unshuffledConnectionsWithResults),this.hyperParameters.SHUFFLE_SEED??0)}else{this.nodeMap=new Map(s.map(t=>[t.capacityMeshNodeId,t]));const t=s.map(t=>(t.width+t.height)/2).filter(t=>Number.isFinite(t)&&t>0);this.avgNodePitch=t.length>0?t.reduce((t,e)=>t+e,0)/t.length:1,this.offBoardNodes=s.filter(t=>t._offBoardConnectionId),this.portPointMap=new Map,this.nodePortPointsMap=new Map;for(const t of s)this.nodePortPointsMap.set(t.capacityMeshNodeId,[]),this.nodeAssignedPortPoints.set(t.capacityMeshNodeId,[]);for(const t of s)for(const e of t.portPoints){this.portPointMap.set(e.portPointId,e);for(const t of e.connectionNodeIds){const n=this.nodePortPointsMap.get(t);n&&!n.some(t=>t.portPointId===e.portPointId)&&n.push(e)}}const{connectionsWithResults:e,connectionNameToGoalNodeIds:n}=this.getConnectionsWithNodes();this.connectionsWithResults=e,this.connectionNameToGoalNodeIds=n}if(c&&c.length>0)for(const t of c)if(this.connectionsWithResults.push(t),t.portPoints)for(const e of t.portPoints)e.portPointId&&this.assignedPortPoints.set(e.portPointId,{connectionName:e.connectionName,rootConnectionName:e.rootConnectionName});for(const t of this.connectionsWithResults)t.path?this.processedConnectionQueue.push(t):this.unprocessedConnectionQueue.push(t);this.totalConnectionCount=this.connectionsWithResults.length}hyperParameters;simpleRouteJson;inputNodes;nodeMap;nodePortPointsMap;portPointMap;connectionsWithResults=[];failedConnection=null;assignedPortPoints=new Map;nodeAssignedPortPoints=new Map;PORT_POINT_REUSE_FACTOR=1e3;BASE_COST_FOR_NOT_GOING_OFF_BOARD=100;get NODE_PF_FACTOR(){return this.hyperParameters.NODE_PF_FACTOR??50}get RANDOM_WALK_DISTANCE(){return this.hyperParameters.RANDOM_WALK_DISTANCE??0}get MEMORY_PF_FACTOR(){return this.hyperParameters.MEMORY_PF_FACTOR??0}get CENTER_OFFSET_FOCUS_SHIFT(){return this.hyperParameters.CENTER_OFFSET_FOCUS_SHIFT??0}get RANDOM_COST_MAGNITUDE(){return this.hyperParameters.RANDOM_COST_MAGNITUDE??0}get BASE_CANDIDATE_COST(){return this.hyperParameters.BASE_CANDIDATE_COST??0}get NODE_PF_MAX_PENALTY(){return this.hyperParameters.NODE_PF_MAX_PENALTY??1e4}get FORCE_CENTER_FIRST(){return this.hyperParameters.FORCE_CENTER_FIRST??!0}get FORCE_OFF_BOARD_FREQUENCY(){return 0===this.offBoardNodes.length?0:this.hyperParameters.FORCE_OFF_BOARD_FREQUENCY??0}get FORCE_OFF_BOARD_SEED(){return this.hyperParameters.FORCE_OFF_BOARD_SEED??0}get NODE_MAX_PF(){return Math.min(.99999,1-Math.exp(-this.NODE_PF_MAX_PENALTY))}get CENTER_OFFSET_DIST_PENALTY_FACTOR(){return this.hyperParameters.CENTER_OFFSET_DIST_PENALTY_FACTOR??0}get STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR(){return this.hyperParameters.STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR??0}colorMap;get GREEDY_MULTIPLIER(){return this.hyperParameters.GREEDY_MULTIPLIER??1.3}MAX_CANDIDATES_IN_MEMORY=5e3;get MAX_ITERATIONS_PER_PATH(){return this.hyperParameters.MAX_ITERATIONS_PER_PATH??1e4}ITERATIONS_PER_MM_FOR_PATH=30;BASE_ITERATIONS_PER_PATH=1e4;get RIPPING_ENABLED(){return this.hyperParameters.RIPPING_ENABLED??!1}get RIPPING_PF_THRESHOLD(){return this.hyperParameters.RIPPING_PF_THRESHOLD??.3}get MAX_RIPS(){return this.hyperParameters.MAX_RIPS??100}get RANDOM_RIP_FRACTION(){return this.hyperParameters.RANDOM_RIP_FRACTION??0}get JUMPER_PF_FN_ENABLED(){return this.hyperParameters.JUMPER_PF_FN_ENABLED??!1}jumpersPerMmSquared=.1;testedRipConnections=new Map;totalRipCount=0;get MIN_ALLOWED_BOARD_SCORE(){return this.hyperParameters.MIN_ALLOWED_BOARD_SCORE??-1e4}nodeMemoryPfMap;unprocessedConnectionQueue=[];processedConnectionQueue=[];currentConnection=null;totalConnectionCount=0;currentPathIterations=0;candidates;visitedPortPoints;connectionNameToGoalNodeIds;capacityMeshNodeMap;avgNodePitch;currentConnectionShouldRouteOffBoard=!1;activeCandidateStraightLineDistance;offBoardNodes=[];baseNodeCostCache=new Map;getConstructorParams(){return this.input}clearCostCaches(){this.baseNodeCostCache.clear()}clampPf(t){return Number.isFinite(t)?Math.min(Math.max(t,0),.999999):.999999}pfToFailureCost(t){const e=this.clampPf(t);return e>=this.NODE_MAX_PF?this.NODE_PF_MAX_PENALTY:-Math.log(1-e)}getBaseNodeFailureCost(t){const e=this.baseNodeCostCache.get(t);if(null!=e)return e;const n=this.nodeMap.get(t);if(!n)return 0;const s=this.computeNodePf(n),o=this.pfToFailureCost(s);return this.baseNodeCostCache.set(t,o),o}computeBoardScore(){const t=this.getNodesWithPortPoints();return this.JUMPER_PF_FN_ENABLED?Bo(t,this.capacityMeshNodeMap):Yo(t,this.capacityMeshNodeMap)}getMaxIterationsForCurrentPath(){const t=this.activeCandidateStraightLineDistance??0;return Math.min(this.BASE_ITERATIONS_PER_PATH+this.ITERATIONS_PER_MM_FOR_PATH*t,this.MAX_ITERATIONS_PER_PATH)}getNodeDeltaFailureCostForSegment(t,e,n){const s=this.nodeMap.get(t);if(!s)return 0;const o=this.getBaseNodeFailureCost(t),i=this.computeNodePf(s,[e,n]),r=this.pfToFailureCost(i),a=Math.max(0,r-o);return i>=this.NODE_MAX_PF?this.NODE_PF_MAX_PENALTY:a*this.NODE_PF_FACTOR}getConnectionsWithNodes(){const{unshuffledConnectionsWithResults:t,connectionNameToGoalNodeIds:e}=Fo(this.simpleRouteJson,this.inputNodes);return{connectionsWithResults:kt(t,this.hyperParameters.SHUFFLE_SEED??0),connectionNameToGoalNodeIds:e}}buildNodeWithPortPointsForCrossing(t,e){const n=this.nodeAssignedPortPoints.get(t.capacityMeshNodeId)??[],s=e?[...n,...e]:n;return{capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:s,availableZ:t.availableZ}}computeNodePf(t,e){if(t._containsTarget)return 0;const n=this.buildNodeWithPortPointsForCrossing(t,e),s=Ro(n);return this.JUMPER_PF_FN_ENABLED&&1===t.availableZ.length?wo(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),s.numSameLayerCrossings):Co(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),s.numSameLayerCrossings,s.numEntryExitLayerChanges,s.numTransitionPairCrossings)}getPortPointReusePenalty(t,e){const n=this.assignedPortPoints.get(t);return n?e===n.rootConnectionName?0:this.PORT_POINT_REUSE_FACTOR:0}getOtherNodeId(t,e){const[n,s]=t.connectionNodeIds;return n===e?s:s===e?n:null}computeG(t,e,n,s,o){const i=t.currentNodeId,r=t.point,a={x:r.x,y:r.y,z:t.z,connectionName:s,rootConnectionName:o},c={x:e.x,y:e.y,z:e.z,connectionName:s,rootConnectionName:o},h=this.getNodeDeltaFailureCostForSegment(i,a,c);return t.g+h}computeGToEndTarget(t,e,n,s){const o=t.currentNodeId,i={x:t.point.x,y:t.point.y,z:t.z,connectionName:n,rootConnectionName:s},r={x:e.x,y:e.y,z:t.z,connectionName:n,rootConnectionName:s},a=this.getNodeDeltaFailureCostForSegment(o,i,r);return t.g+a}computeDistanceToNearestOffBoardNode(t){if(0===this.offBoardNodes.length)return 1/0;let e=1/0;for(const n of this.offBoardNodes){const s=St(t,n.center);s<e&&(e=s)}return e}computeH(t,e,n,s,o,i){if(this.RANDOM_WALK_DISTANCE>0&&o<this.RANDOM_WALK_DISTANCE)return 0;if(this.currentConnectionShouldRouteOffBoard&&!i)return this.BASE_COST_FOR_NOT_GOING_OFF_BOARD+this.computeDistanceToNearestOffBoardNode(t);const r=this.nodeMap.get(n);if(!r)return 0;const a=St(t,r.center),c=this.avgNodePitch>0?a/this.avgNodePitch:0,h=this.clampPf(this.nodeMemoryPfMap.get(e)??0),d=this.pfToFailureCost(h)*this.MEMORY_PF_FACTOR,l=c*this.BASE_CANDIDATE_COST,u=this.CENTER_OFFSET_DIST_PENALTY_FACTOR*t.distToCentermostPortOnZ**2;let p=0;if(this.STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR>0&&this.currentConnection){const e=vt(t,this.currentConnection.connection.pointsToConnect[0],this.currentConnection.connection.pointsToConnect[1]);p=this.STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR*e}return a+l+d+u+p}getVisitedPortPointKey(t,e){return this.currentConnectionShouldRouteOffBoard&&e?`${t}:touched_off_board`:t}getAvailableExitPortPoints(t,e){const n=this.currentConnection?.connection.rootConnectionName,s=this.nodePortPointsMap.get(t)??[],o=[];for(const t of s){const s=this.getVisitedPortPointKey(t.portPointId,e);if(this.visitedPortPoints?.has(s))continue;const i=this.assignedPortPoints.get(t.portPointId);i&&i?.rootConnectionName!==n||o.push(t)}return o}getAvailableExitPortPointsWithOmissions(t,e,n){const s=this.nodePortPointsMap.get(t)??[],o=this.currentConnection?.connection.rootConnectionName,i=new Map;for(const e of s){const s=this.getVisitedPortPointKey(e.portPointId,n);if(this.visitedPortPoints?.has(s))continue;const o=this.getOtherNodeId(e,t);if(!o)continue;this.nodeMap.get(o);const r=`${o}|${e.z}`,a=i.get(r)??[];a.push(e),i.set(r,a)}const r=[];for(const[,t]of i){t.sort((t,e)=>t.distToCentermostPortOnZ-e.distToCentermostPortOnZ);const e=t[0];if(!e)continue;const n=this.assignedPortPoints.get(e.portPointId),s=n&&n.rootConnectionName===o;if(!n||s){r.push(e);continue}const i=[...t].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y),a=[];let c=[];for(const t of i){const e=this.assignedPortPoints.get(t.portPointId);!e||e.rootConnectionName===o?c.push(t):c.length>0&&(a.push(c),c=[])}c.length>0&&a.push(c);for(const t of a){const e=Math.floor(t.length/2);r.push(t[e])}}return r}getAvailableExitPortPointsForOffboardConnection(t,e){const n=this.nodeMap.get(t);if(!n)return[];const s=this.currentConnection?.connection.rootConnectionName,o=[];for(const i of n?._offBoardConnectedCapacityMeshNodeIds??[]){if(i===t)continue;if(!this.nodeMap.get(i))continue;const n=this.nodePortPointsMap.get(i)??[];for(const t of n){const n=this.getVisitedPortPointKey(t.portPointId,e);if(this.visitedPortPoints?.has(n))continue;const r=this.assignedPortPoints.get(t.portPointId);r&&r.rootConnectionName!==s||o.push({...t,throughNodeId:i})}}return o}canTravelThroughObstacle(t,e,n){const s=this.connectionNameToGoalNodeIds.get(e);return s?.includes(t.capacityMeshNodeId)||Boolean(t._offBoardConnectionId)}isAtEndGoal(t,e){return t===e}getBacktrackedPath(t){const e=[];let n=t;for(;n;){if(n.lastMoveWasOffBoard&&n.throughNodeId){const t=this.nodeMap.get(n.throughNodeId),s=n.prevCandidate?this.nodeMap.get(n.prevCandidate.currentNodeId):null;e.push(n),t&&e.push({prevCandidate:null,portPoint:null,currentNodeId:n.throughNodeId,point:t.center,z:n.z,f:0,g:0,h:0,distanceTraveled:0}),s&&s._offBoardConnectionId&&e.push({prevCandidate:null,portPoint:null,currentNodeId:n.prevCandidate.currentNodeId,point:s.center,z:n.z,f:0,g:0,h:0,distanceTraveled:0})}else e.push(n);n=n.prevCandidate}return e.reverse()}assignPortPointsForPath(t,e,n){const s=[];for(let o=0;o<t.length;o++){const i=t[o];if(!i.portPoint){const r=0===o,a=o===t.length-1;if(!r&&!a){const t={x:i.point.x,y:i.point.y,z:i.z,connectionName:e,rootConnectionName:n};s.push(t);const o=this.nodeAssignedPortPoints.get(i.currentNodeId)??[];o.push(t),this.nodeAssignedPortPoints.set(i.currentNodeId,o)}continue}const r=i.portPoint;this.assignedPortPoints.set(r.portPointId,{connectionName:e,rootConnectionName:n});const a={portPointId:r.portPointId,x:r.x,y:r.y,z:r.z,connectionName:e,rootConnectionName:n};s.push(a);for(const t of r.connectionNodeIds){const e=this.nodeAssignedPortPoints.get(t)??[];e.push(a),this.nodeAssignedPortPoints.set(t,e)}}const o=Array.from(new Set(t.map(t=>t.currentNodeId)));for(const t of o){const s=this.nodeMap.get(t);if(s&&s._offBoardConnectionId)for(const t of s?._offBoardConnectedCapacityMeshNodeIds??[]){const s=this.nodePortPointsMap.get(t)??[];for(const t of s)this.assignedPortPoints.set(t.portPointId,{connectionName:e,rootConnectionName:n})}}return s}addTargetPointsToNodes(t,e){const n=t[0],s=t[t.length-1],o=e.pointsToConnect[0],i=e.pointsToConnect[e.pointsToConnect.length-1];if(n&&o){const t=this.nodeAssignedPortPoints.get(n.currentNodeId)??[];t.push({x:o.x,y:o.y,z:n.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(n.currentNodeId,t)}if(s&&i){const t=this.nodeAssignedPortPoints.get(s.currentNodeId)??[];t.push({x:i.x,y:i.y,z:s.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(s.currentNodeId,t)}}isPortPointInPathChain(t,e){let n=t;for(;n;){if(n.portPoint?.portPointId===e)return!0;n=n.prevCandidate}return!1}isNodeInPathChain(t,e){let n=t;for(;n;){if(n.currentNodeId===e)return!0;n=n.prevCandidate}return!1}_step(){if(this.currentConnection||(this.currentConnection=this.unprocessedConnectionQueue.shift()??null),!this.currentConnection){const t=this.computeBoardScore();return this.stats={boardScore:t},t<this.MIN_ALLOWED_BOARD_SCORE?(this.failedConnection=null,this.failed=!0,void(this.error=`Board score ${t.toFixed(2)} is less than MIN_ALLOWED_BOARD_SCORE ${this.MIN_ALLOWED_BOARD_SCORE.toFixed(2)}`)):void(this.solved=!0)}const t=this.currentConnection;this.activeCandidateStraightLineDistance=t.straightLineDistance,this.currentPathIterations++;const e=this.getMaxIterationsForCurrentPath();if(this.currentPathIterations>e)return this.failedConnection=t,this.processedConnectionQueue.push(t),this.currentConnection=null,this.candidates=null,this.visitedPortPoints=null,this.currentPathIterations=0,this.failed=!0,void(this.error=`Exceeded max iterations for path (${e}) on connection ${t.connection.name}`);const[n,s]=t.nodeIds,o=this.nodeMap.get(n),i=this.nodeMap.get(s);if(!o||!i)return this.processedConnectionQueue.push(t),this.currentConnection=null,void(this.currentPathIterations=0);const r=t.connection.name,a=t.connection.rootConnectionName,c=t.connection.pointsToConnect[0];if(!this.candidates){if(this.clearCostCaches(),this.FORCE_OFF_BOARD_FREQUENCY>0){const t=Yt(17*(this.hyperParameters.SHUFFLE_SEED??0)+this.FORCE_OFF_BOARD_SEED+this.processedConnectionQueue.length);this.currentConnectionShouldRouteOffBoard=t()<this.FORCE_OFF_BOARD_FREQUENCY}else this.currentConnectionShouldRouteOffBoard=!1;this.candidates=[],this.visitedPortPoints=new Set;for(const t of o.availableZ){const e=c?{x:c.x,y:c.y}:o.center,i=this.computeH({...e,distToCentermostPortOnZ:0},n,s,t,0,!1),r=0+i*this.GREEDY_MULTIPLIER;this.candidates.push({prevCandidate:null,portPoint:null,currentNodeId:n,point:e,z:t,f:r,g:0,h:i,distanceTraveled:0,hasTouchedOffBoardNode:!1})}}this.candidates.sort((t,e)=>t.f-e.f);let h,d=this.candidates.shift();for(;d?.portPoint&&this.visitedPortPoints;){const t=this.getVisitedPortPointKey(d.portPoint.portPointId,d.hasTouchedOffBoardNode);if(!this.visitedPortPoints.has(t))break;d=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),!d)return this.error=`Ran out of candidates on connection ${r}`,this.failedConnection=t,this.processedConnectionQueue.push(t),this.currentConnection=null,this.candidates=null,this.visitedPortPoints=null,this.currentPathIterations=0,void(this.failed=!0);if(d.portPoint&&this.visitedPortPoints){const t=this.getVisitedPortPointKey(d.portPoint.portPointId,d.hasTouchedOffBoardNode);this.visitedPortPoints.add(t)}if(this.isAtEndGoal(d.currentNodeId,s)){const e=t.connection.pointsToConnect[t.connection.pointsToConnect.length-1],n=e?{x:e.x,y:e.y}:i.center,o=this.computeGToEndTarget(d,n,r,a),c={prevCandidate:d,portPoint:null,currentNodeId:s,point:n,z:d.z,g:o,h:0,f:o,distanceTraveled:d.distanceTraveled+St(d.point,n)},h=this.getBacktrackedPath(c);return t.path=h,t.portPoints=this.assignPortPointsForPath(h,r,a),this.addTargetPointsToNodes(h,t.connection),this.clearCostCaches(),this.RIPPING_ENABLED&&this.processRippingForPath(h,r),this.processedConnectionQueue.push(t),this.currentConnection=null,this.progress=this.processedConnectionQueue.length/this.totalConnectionCount,this.candidates=null,this.visitedPortPoints=null,void(this.currentPathIterations=0)}const l=this.nodeMap.get(d.currentNodeId);h=l?._offBoardConnectionId?this.getAvailableExitPortPointsForOffboardConnection(d.currentNodeId,d.hasTouchedOffBoardNode):this.FORCE_CENTER_FIRST?this.getAvailableExitPortPointsWithOmissions(d.currentNodeId,s,d.hasTouchedOffBoardNode):this.getAvailableExitPortPoints(d.currentNodeId,d.hasTouchedOffBoardNode);for(const t of h){if(this.isPortPointInPathChain(d,t.portPointId))continue;if(this.visitedPortPoints?.has(t.portPointId))continue;const e=this.getOtherNodeId(t,t.throughNodeId??d.currentNodeId);if(!e)continue;if(this.isNodeInPathChain(d,e))continue;const n="throughNodeId"in t?t.throughNodeId:void 0,o=n?this.nodeMap.get(n):null,i=this.nodeMap.get(e);if(!i)continue;if(i._containsObstacle&&!this.canTravelThroughObstacle(i,r,a))continue;const c=this.computeG(d,t,e,r,a);if(!this.RIPPING_ENABLED&&c>-this.MIN_ALLOWED_BOARD_SCORE)continue;const h=d.distanceTraveled+St(d.point,t),u=d.hasTouchedOffBoardNode||Boolean(i._offBoardConnectionId),p=this.computeH(t,e,s,t.z,h,u),m=c+p*this.GREEDY_MULTIPLIER,f=Boolean(l?._offBoardConnectionId)&&Boolean(o?._offBoardConnectionId);this.candidates.push({prevCandidate:d,portPoint:t,currentNodeId:e,point:{x:t.x,y:t.y},z:t.z,f:m,g:c,h:p,distanceTraveled:h,lastMoveWasOffBoard:f,throughNodeId:f?n:void 0,hasTouchedOffBoardNode:u||Boolean(i._offBoardConnectionId)||Boolean(l?._offBoardConnectionId)})}}getNodesWithPortPoints(){const t=[];for(const e of this.inputNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];n.length>0&&t.push({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ})}return t}getConnectionsInNode(t,e){const n=[],s=new Set;for(const o of this.connectionsWithResults)if(o.path&&o.connection.name!==e&&!s.has(o.connection.name))for(const e of o.path)if(e.currentNodeId===t){n.push(o),s.add(o.connection.name);break}return n}computeNodePfWithoutConnection(t,e){if(t._containsTarget)return{pf:0,totalCrossings:0};const n=(this.nodeAssignedPortPoints.get(t.capacityMeshNodeId)??[]).filter(t=>t.connectionName!==e),s={capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:n,availableZ:t.availableZ},o=Ro(s),i=o.numSameLayerCrossings+o.numEntryExitLayerChanges+o.numTransitionPairCrossings;return{pf:Co(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),o.numSameLayerCrossings,o.numEntryExitLayerChanges,o.numTransitionPairCrossings),totalCrossings:i}}computeNodeCrossings(t){if(t._containsTarget)return 0;const e=this.buildNodeWithPortPointsForCrossing(t),n=Ro(e);return n.numSameLayerCrossings+n.numEntryExitLayerChanges+n.numTransitionPairCrossings}ripConnection(t){const e=t.connection.name;for(const[t,n]of this.assignedPortPoints.entries())n.connectionName===e&&this.assignedPortPoints.delete(t);for(const[t,n]of this.nodeAssignedPortPoints.entries()){const s=n.filter(t=>t.connectionName!==e);this.nodeAssignedPortPoints.set(t,s)}t.path=void 0,t.portPoints=void 0}requeueConnection(t){this.totalRipCount++;const e=this.processedConnectionQueue.indexOf(t);if(-1!==e)return this.processedConnectionQueue.splice(e,1),this.unprocessedConnectionQueue.push(t),!0;const n=this.unprocessedConnectionQueue.indexOf(t);return-1!==n&&(this.unprocessedConnectionQueue.splice(n,1),this.unprocessedConnectionQueue.unshift(t)),!0}processRippingForPath(t,e){const n=Array.from(new Set(t.map(t=>t.currentNodeId)));let s=!1;for(const t of n){if(this.totalRipCount>this.MAX_RIPS)break;const n=this.nodeMap.get(t);if(!n)continue;let o=this.computeNodePf(n);if(o<=this.RIPPING_PF_THRESHOLD)continue;this.testedRipConnections.has(t)||this.testedRipConnections.set(t,new Set);const i=this.testedRipConnections.get(t),r=kt(this.getConnectionsInNode(t,e),(this.hyperParameters.SHUFFLE_SEED??0)+this.processedConnectionQueue.length);for(const t of r){if(o<=this.RIPPING_PF_THRESHOLD)break;const e=t.connection.name;i.add(e);const{pf:r}=this.computeNodePfWithoutConnection(n,e);this.ripConnection(t);if(!this.requeueConnection(t))return;o=r,s=!0,this.clearCostCaches()}}s&&this.RANDOM_RIP_FRACTION>0&&this.processRandomRipping(e)}processRandomRipping(t){const e=this.processedConnectionQueue.filter(e=>void 0!==e.path&&e.connection.name!==t);if(0===e.length)return;const n=Math.max(1,Math.floor(this.RANDOM_RIP_FRACTION*e.length)),s=kt(e,(this.hyperParameters.SHUFFLE_SEED??0)+this.totalRipCount+this.processedConnectionQueue.length);for(let t=0;t<n&&t<s.length&&!(this.totalRipCount>this.MAX_RIPS);t++){const e=s[t];this.ripConnection(e);if(!this.requeueConnection(e))return;this.clearCostCaches()}}visualize(){let t={};if(this.failed){const e=this.failedConnection?.connection.pointsToConnect[0],n=this.failedConnection?.connection.pointsToConnect[1];e&&n&&(t={lines:[{points:[e,n],label:`Failed Connection ${this.failedConnection?.connection.name}`,strokeWidth:1,strokeColor:"red",strokeDash:[2,2]}]})}return e=Lo(this),n=t,{...e,rects:[...e.rects??[],...n.rects??[]],points:[...e.points??[],...n.points??[]],lines:[...e.lines??[],...n.lines??[]],circles:[...e.circles??[],...n.circles??[]],arrows:[...e.arrows??[],...n.arrows??[]],texts:[...e.texts??[],...n.texts??[]]};var e,n}},Vo=class extends Zt{params;precomputedInitialParams;constructor(t){super(),this.params=t,this.MAX_ITERATIONS=1e8,this.GREEDY_MULTIPLIER=1.2,this.MIN_SUBSTEPS=50,this.precomputedInitialParams=t.precomputedInitialParams??Xo(t.simpleRouteJson,t.inputNodes)}getHyperParameterDefs(){const t=this.params.numShuffleSeeds??50;return[{name:"SHUFFLE_SEED",possibleValues:Array.from({length:t},(t,e)=>({SHUFFLE_SEED:e+1700*(this.params.hyperParameters?.SHUFFLE_SEED??0)}))}]}getCombinationDefs(){return[["SHUFFLE_SEED"]]}generateSolver(t){return new Uo({simpleRouteJson:this.params.simpleRouteJson,capacityMeshNodes:this.params.capacityMeshNodes,inputNodes:this.params.inputNodes,colorMap:this.params.colorMap,nodeMemoryPfMap:this.params.nodeMemoryPfMap,hyperParameters:{...this.params.hyperParameters,...t,MIN_ALLOWED_BOARD_SCORE:this.params.minAllowedBoardScore??t.MIN_ALLOWED_BOARD_SCORE??this.params.hyperParameters?.MIN_ALLOWED_BOARD_SCORE},precomputedInitialParams:this.precomputedInitialParams,fixedRoutes:this.params.fixedRoutes})}computeG(t){return-t.computeBoardScore()}computeH(t){const e=t.progress||0;if(e<.1)return 0;return-(t.computeBoardScore()/e)*(1-e)}getNodesWithPortPoints(){if(this.winningSolver)return this.winningSolver.getNodesWithPortPoints();const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.getNodesWithPortPoints():[]}get connectionsWithResults(){if(this.winningSolver)return this.winningSolver.connectionsWithResults;const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.connectionsWithResults:[]}get inputNodes(){if(this.winningSolver)return this.winningSolver.inputNodes;const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.inputNodes:this.params.inputNodes}get nodeMap(){if(this.winningSolver)return this.winningSolver.nodeMap;const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.nodeMap:new Map(this.params.inputNodes.map(t=>[t.capacityMeshNodeId,t]))}get assignedPortPoints(){if(this.winningSolver)return this.winningSolver.assignedPortPoints;const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.assignedPortPoints:new Map}get nodeAssignedPortPoints(){if(this.winningSolver)return this.winningSolver.nodeAssignedPortPoints;const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.nodeAssignedPortPoints:new Map}computeBoardScore(){if(this.winningSolver)return this.winningSolver.computeBoardScore();const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.computeBoardScore():0}onSolve(t){this.stats={...t.solver.stats,winningHyperParameters:this.winningSolver?.hyperParameters}}visualize(){return this.winningSolver?this.winningSolver.visualize():super.visualize()}};function Zo(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Go=class extends y{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth,this.effort=e.effort??1,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,o=Math.max(n,s),i=e.targetMinCapacity??.5;e.capacityDepth=Be(o,i)}this.connMap=$e(t),this.colorMap=ot(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;colorMap;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;viaDiameter;minTraceWidth;effort;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[Zo("netToPointPairsSolver",gn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ot(t.srjWithPointPairs,this.connMap),t.connMap=$e(t.srjWithPointPairs)}}),Zo("nodeSolver",Js,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Zo("edgeSolver",cn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Zo("availableSegmentPointSolver",Io,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),Zo("portPointPathingSolver",Vo,t=>{const e=t.capacityNodes.map(t=>({capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:[],availableZ:t.availableZ,_containsTarget:t._containsTarget,_containsObstacle:t._containsObstacle})),n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),s=t.availableSegmentPointSolver;for(const t of s.sharedEdgeSegments)for(const e of t.portPoints){const[t,s]=e.nodeIds,o={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[t,s],distToCentermostPortOnZ:e.distToCentermostPortOnZ},i=n.get(t);i&&i.portPoints.push(o)}return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e,capacityMeshNodes:t.capacityNodes,colorMap:t.colorMap,numShuffleSeeds:200,hyperParameters:{NODE_PF_MAX_PENALTY:100,FORCE_OFF_BOARD_FREQUENCY:0,STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR:4}}]}),Zo("multiSectionPortPointOptimizer",Ho,t=>{const e=t.portPointPathingSolver;return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e.inputNodes,capacityMeshNodes:t.capacityNodes,capacityMeshEdges:t.capacityEdges,colorMap:t.colorMap,initialConnectionResults:e.connectionsWithResults,initialAssignedPortPoints:e.assignedPortPoints,initialNodeAssignedPortPoints:e.nodeAssignedPortPoints,effort:t.effort}]}),Zo("highDensityRouteSolver",Le,t=>[{nodePortPoints:t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),Zo("highDensityStitchSolver",nn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),Zo("traceSimplificationSolver",Mo,t=>[{hdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline,defaultViaDiameter:t.viaDiameter,layerCount:t.srj.layerCount,iterations:2}])];getConstructorParams(){return[this.srj,this.opts]}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 t=this.netToPointPairsSolver?.visualize(),e=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),s=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),i=this.edgeSolver?.visualize(),r=this.deadEndSolver?.visualize(),a=this.availableSegmentPointSolver?.visualize(),c=this.portPointPathingSolver?.visualize(),h=this.multiSectionPortPointOptimizer?.visualize(),d=this.highDensityRouteSolver?.visualize(),l=this.highDensityStitchSolver?.visualize(),u=this.traceSimplificationSolver?.visualize(),p=this.srj.outline,m=[];if(m.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)"}),p&&p.length>=2){const t=p.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),m.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const f={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:m},y=[f,t,e,n,s,o,i,r,a,c,h,d?g(f,d):null,l,u,this.solved?g(f,sn(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...y)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.connectionName]}),t.length>200)break}return{lines:t}}if(this.portPointPathingSolver){const t=[];for(const e of this.portPointPathingSolver.connectionsWithResults)e.path&&t.push({points:e.path.map(t=>({x:t.point.x,y:t.point.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,o=e.filter(t=>t.connectionName===n.name);for(let e=0;e<o.length;e++){const i=o[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:We(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Jo=Go,qo=class extends y{nodes;edges;capacityPaths;nodeMap;nodeEdgeMap;unprocessedNodeIds;nodePortSegments;colorMap;constructor({nodes:t,edges:e,capacityPaths:n,colorMap:s}){super(),this.nodes=t,this.edges=e,this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=No(e),this.capacityPaths=n,this.colorMap=s??{},this.unprocessedNodeIds=[...new Set(n.flatMap(t=>t.nodeIds))],this.nodePortSegments=new Map}step(){const t=this.unprocessedNodeIds.pop();if(!t)return void(this.solved=!0);const e=[];for(const n of this.capacityPaths){const s=n.nodeIds.indexOf(t);-1!==s&&e.push({path:n,indexOfNodeInPath:s})}const n=this.nodeMap.get(t),s=[];for(const{path:o,indexOfNodeInPath:i}of e){const e=o.nodeIds[i-1],r=o.nodeIds[i+1];for(const i of[e,r]){const e=this.nodeMap.get(i);if(!e)continue;const r=Ko(n,e),a=e.availableZ.filter(t=>n.availableZ.includes(t));if(0===a.length)continue;const c={capacityMeshNodeId:t,start:r.start,end:r.end,connectionNames:[o.connectionName],rootConnectionNames:o.rootConnectionName?[o.rootConnectionName]:void 0,availableZ:a};s.push(c)}}const o=function(t){const e=[],n=t.map(t=>({...t,connectionNames:[...t.connectionNames],rootConnectionNames:t.rootConnectionNames?[...t.rootConnectionNames]:[],availableZ:[...t.availableZ].sort((t,e)=>t-e)}));for(;n.length>0;){const t=n.pop();let s=!1;for(let n=0;n<e.length;n++){const o=e[n],i=ti(o.start,t.start)&&ti(o.end,t.end)||ti(o.start,t.end)&&ti(o.end,t.start),r=ei(o.availableZ,t.availableZ);if(i&&r){const e=new Set(o.connectionNames);t.connectionNames.forEach(t=>e.add(t)),o.connectionNames=Array.from(e);const n=new Set(o.rootConnectionNames||[]);t.rootConnectionNames?.forEach(t=>n.add(t)),o.rootConnectionNames=Array.from(n),s=!0;break}}s||e.push(t)}return e}(s);this.nodePortSegments.set(t,o)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};return this.nodePortSegments.forEach((e,n)=>{this.nodeMap.get(n);e.forEach(e=>{e.start.x,e.end.x;for(let s=0;s<e.connectionNames.length;s++){const o={x:.05*Math.max(...e.availableZ),y:.05*Math.max(...e.availableZ)},i={x:(e.start.x+e.end.x)/2,y:(e.start.y+e.end.y)/2},r={x:i.x+o.x,y:i.y+o.y};o.x>0&&t.lines.push({points:[i,r],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5"}),t.points.push({x:r.x,y:r.y,label:`${n}: ${e.connectionNames.join(", ")}\navailableZ: ${e.availableZ.join(",")}\nnodePortSegmentId: ${e.nodePortSegmentId}`}),t.lines.push({points:[e.start,e.end],strokeColor:it(this.colorMap[e.connectionNames[s]],.6)})}})}),t}};function Ko(t,e){const n={start:Math.max(t.center.x-t.width/2,e.center.x-e.width/2),end:Math.min(t.center.x+t.width/2,e.center.x+e.width/2)},s={start:Math.max(t.center.y-t.height/2,e.center.y-e.height/2),end:Math.min(t.center.y+t.height/2,e.center.y+e.height/2)};if(n.end-n.start<s.end-s.start){const t=(n.start+n.end)/2;return{start:{x:t,y:s.start},end:{x:t,y:s.end}}}{const t=(s.start+s.end)/2;return{start:{x:n.start,y:t},end:{x:n.end,y:t}}}}var Qo=1e-9;function ti(t,e){return Math.abs(t.x-e.x)<Qo&&Math.abs(t.y-e.y)<Qo}function ei(t,e){if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++)if(t[n]!==e[n])return!1;return!0}var ni=class extends y{unsolvedSegments;solvedSegments;nodeMap;colorMap;constructor({segments:t,colorMap:e,nodes:n}){super(),this.MAX_ITERATIONS=1e5,this.unsolvedSegments=t,this.solvedSegments=[],this.colorMap=e??{},this.nodeMap=Object.fromEntries(n.map(t=>[t.capacityMeshNodeId,t]))}_step(){let t=!1;const e=[...this.unsolvedSegments];for(const n of e){const e=n.connectionNames.length;if((!("assignedPoints"in n)||n.assignedPoints?.length!==e)&&1===e){const e={x:(n.start.x+n.end.x)/2,y:(n.start.y+n.end.y)/2,z:n.availableZ[0]};n.assignedPoints=[{connectionName:n.connectionNames[0],rootConnectionName:n.rootConnectionNames?.[0],point:e}],this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(n),1),this.solvedSegments.push(n),t=!0}}if(!t&&e.length>0){let n=e[0];for(const t of e)t.connectionNames.length<n.connectionNames.length&&(n=t);const s=[...n.connectionNames].sort(),o=n.end.x-n.start.x,i=n.end.y-n.start.y,r=s.length,a=[];for(let t=1;t<=r;t++){const e=t/(r+1);a.push({x:n.start.x+o*e,y:n.start.y+i*e,z:n.availableZ[0]})}n.assignedPoints=s.map((t,e)=>({connectionName:t,rootConnectionName:n.rootConnectionNames?.[n.connectionNames.indexOf(t)],point:a[e]})),this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(n),1),this.solvedSegments.push(n),t=!0}0===this.unsolvedSegments.length&&(this.solved=!0)}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.solvedSegments){const n=e.capacityMeshNodeId,s=this.nodeMap[n];t.has(n)||t.set(n,{capacityMeshNodeId:n,portPoints:[],center:s.center,width:s.width,height:s.height}),t.get(n).portPoints.push(...e.assignedPoints.map(t=>({...t.point,connectionName:t.connectionName})))}return Array.from(t.values())}visualize(){const t={points:[],lines:this.solvedSegments.map(t=>({points:[t.start,t.end],step:4})),rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Segment to Point Solver"};for(let e=0;e<this.solvedSegments.length;e++){const n=this.solvedSegments[e];for(let e=0;e<n.assignedPoints.length;e++){const s=n.assignedPoints[e],o={x:s.point.x,y:s.point.y},i={x:s.point.x+.05*s.point.z,y:s.point.y+.05*s.point.z};0!==s.point.z&&t.lines.push({points:[o,i],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5",step:4}),t.points.push({x:i.x,y:i.y,label:[`${n.capacityMeshNodeId}-${s.connectionName}`,`z: ${n.availableZ.join(",")}`,`nodePortSegmentId: ${n.nodePortSegmentId}`].join("\n"),color:this.colorMap[s.connectionName],step:4})}}const e=[],n={};for(const t of this.solvedSegments){const e=t.capacityMeshNodeId;n[e]||(n[e]={});for(const s of t.assignedPoints)n[e][s.connectionName]||(n[e][s.connectionName]=[]),n[e][s.connectionName].push({x:s.point.x,y:s.point.y})}for(const t in n)for(const s in n[t]){const o=n[t][s];o.length>1&&e.push({points:o,step:4,strokeDash:"5 5",strokeColor:this.colorMap[s]||"#000"})}return t.lines.push(...e),t}};function si(t){const{nodeId:e,nodeIdToSegmentIds:n,segmentIdToNodeIds:s,hops:o}=t;if(0===o)return[e];const i=new Set([e]),r=[{nodeId:e,remainingHops:o}];for(;r.length>0;){const{nodeId:t,remainingHops:e}=r.shift();if(0===e)continue;const o=n.get(t)||[];for(const t of o){const n=s.get(t)||[];for(const t of n)i.has(t)||(i.add(t),r.push({nodeId:t,remainingHops:e-1}))}}return Array.from(i)}var oi=t=>Array.from(t.entries()).map(([t,{x:e,y:n,z:s}])=>`${t}(${e?.toFixed(3)??""},${n?.toFixed(3)??""},${s??""})`).sort().join("&"),ii=(t,e,n,s)=>{const o=Math.min(t,e),i=Math.max(t,e),r=Math.min(n,s);return o<=Math.max(n,s)&&i>=r},ri=(t,e,n,s)=>{const o=[],i=new Map(t.originalPointMap);for(const[t,e]of n.entries()){const n=i.get(t);i.set(t,{x:e.x??n.x,y:e.y??n.y,z:e.z??n.z})}for(const n of t.allNodeIds){if(!e.get(n))continue;const r=t.segmentPairsInNode.get(n);for(const t of r){const e=i.get(t[0]),s=i.get(t[1]);e.z!==s.z&&o.push({type:"transition_via",segmentPoints:t,capacityMeshNodeId:n,probabilityOfFailure:0})}for(let t=0;t<r.length;t++)for(let e=t+1;e<r.length;e++){if(s?.areIdsConnected(r[t][0],r[t][1]))continue;const a=r[t],c=r[e],h=i.get(a[0]),d=i.get(a[1]),l=i.get(c[0]),u=i.get(c[1]);if(!ii(h.z,d.z,l.z,u.z))continue;const p=gt(h,d,l,u),m=h.z===d.z&&l.z===u.z&&h.z===l.z;p&&(m?o.push({type:"same_layer_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,crossingLine1:a,crossingLine2:c,probabilityOfFailure:0}):h.z===d.z&&l.z!==u.z?o.push({type:"single_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,sameLayerCrossingLine:a,transitionCrossingLine:c,probabilityOfFailure:0}):h.z!==d.z&&l.z===u.z?o.push({type:"single_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,sameLayerCrossingLine:c,transitionCrossingLine:a,probabilityOfFailure:0}):h.z!==d.z&&l.z!==u.z&&o.push({type:"double_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,crossingLine1:a,crossingLine2:c,probabilityOfFailure:0}))}}return o},ai=(t,e,n)=>{if("change_layer"===e.type)for(const n of e.segmentPointIds){const s=t.get(n)||{};t.set(n,{...s,z:e.newZ})}else if("swap_position_on_segment"===e.type){const[s,o]=e.segmentPointIds,i=n(s),r=n(o),a=t.get(s)||{},c=t.get(o)||{};t.set(s,{...a,x:r.x,y:r.y}),t.set(o,{...c,x:i.x,y:i.y})}else if("combined"===e.type)for(const s of e.operations)ai(t,s,n)},ci=(t,e)=>{const n=new Map,s=new Map,o=new Map,i=[];let r=0;for(const a of t)for(const t of a.assignedPoints){const c={segmentPointId:"SP"+r++,segmentId:a.nodePortSegmentId,capacityMeshNodeIds:e.get(a.nodePortSegmentId),connectionName:t.connectionName,rootConnectionName:t.rootConnectionName,x:t.point.x,y:t.point.y,z:t.point.z,directlyConnectedSegmentPointIds:[]};n.set(c.segmentPointId,c);for(const t of c.capacityMeshNodeIds)s.set(t,[...s.get(t)??[],c.segmentPointId]);o.set(a.nodePortSegmentId,[...o.get(a.nodePortSegmentId)??[],c.segmentPointId]),i.push(c)}return{segmentPointMap:n,nodeToSegmentPointMap:s,segmentToSegmentPointMap:o}},hi=class extends y{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,ke(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=si({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS}),n=si({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS+1}),s=Array.from(new Set(n).difference(new Set(e)));t?.segmentPointMap||(t=ci(this.dedupedSegments,this.segmentIdToNodeIds));const o=new Map;for(const e of n)o.set(e,t.nodeToSegmentPointMap.get(e));const i=new Map;for(const e of n)for(const n of o.get(e)){const e=t.segmentPointMap.get(n);i.set(n,e)}const r=Array.from(i.values()),a=new Map;for(const t of r)a.set(t.segmentId,[...a.get(t.segmentId)??[],t.segmentPointId]);for(const[e,n]of o.entries())for(let e=0;e<n.length;e++){const s=t.segmentPointMap.get(n[e]);for(let o=e+1;o<n.length;o++){const e=t.segmentPointMap.get(n[o]);e.segmentPointId!==s.segmentPointId&&(e.segmentId!==s.segmentId&&e.connectionName===s.connectionName&&(e.directlyConnectedSegmentPointIds.includes(s.segmentPointId)||(s.directlyConnectedSegmentPointIds.push(e.segmentPointId),e.directlyConnectedSegmentPointIds.push(s.segmentPointId))))}}const c=new Map;for(const t of n)c.set(t,[]);for(const e of r)for(const n of e.capacityMeshNodeIds){const s=c.get(n);if(s)for(const o of e.directlyConnectedSegmentPointIds){const i=t.segmentPointMap.get(o);i.segmentPointId!==e.segmentPointId&&(i.capacityMeshNodeIds.some(t=>t===n)&&(s.some(([t,n])=>t===e.segmentPointId&&n===i.segmentPointId||t===i.segmentPointId&&n===e.segmentPointId)||s.push([e.segmentPointId,i.segmentPointId])))}}const h=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)&&h.add(e)}const d=new Set;for(const t of r){const n=t.capacityMeshNodeIds.some(t=>e.includes(t)),s=this.dedupedSegmentMap.get(t.segmentId),o=s&&s.availableZ.length>1;(n||o)&&d.add(t.segmentPointId)}const l=new Set;for(const t of r){if(t.capacityMeshNodeIds.some(t=>this.nodeMap.get(t)?._containsTarget)){const e=this.dedupedSegmentMap.get(t.segmentId);e&&1===e.availableZ.length&&l.add(t.segmentPointId)}}return{allNodeIds:n,mutableNodeIds:e,immutableNodeIds:s,mutableSegmentIds:h,segmentPairsInNode:c,segmentPointMap:i,segmentPointsInNode:o,segmentPointsInSegment:a,originalPointMap:i,mutableSegmentPointIds:d,zLockedSegmentPointIds:l}}createInitialCandidate(){const t=new Map,e=ri(this.unravelSection,this.nodeMap,t),n=this.computeG({issues:e,originalCandidate:{},operationsPerformed:0,operation:{}});return{pointModifications:t,g:n,h:0,f:n,operationsPerformed:0,candidateHash:oi(t),issues:ri(this.unravelSection,this.nodeMap,t)}}get nextCandidate(){return this.candidates[0]??null}getPointInCandidate(t,e){const n=this.unravelSection.segmentPointMap.get(e),s=t.pointModifications.get(e);return{x:s?.x??n.x,y:s?.y??n.y,z:s?.z??n.z,segmentId:n.segmentId}}getConnectionSegmentPointIds(t){const e=[];for(const[n,s]of this.unravelSection.segmentPointMap.entries())s.connectionName===t&&e.push(n);return e}canConnectionUseLayer(t,e){for(const n of t){const t=this.unravelSection.segmentPointMap.get(n),s=this.dedupedSegmentMap.get(t.segmentId);if(!s||!s.availableZ.includes(e))return!1}return!0}getOperationsForIssue(t,e){const n=[];if("transition_via"===e.type){const[s,o]=e.segmentPoints,i=this.getPointInCandidate(t,s),r=this.getPointInCandidate(t,o),a=this.unravelSection.segmentPointMap.get(s),c=(this.unravelSection.segmentPointMap.get(o),this.dedupedSegmentMap.get(i.segmentId).availableZ),h=this.dedupedSegmentMap.get(r.segmentId).availableZ,d=this.unravelSection.zLockedSegmentPointIds.has(s),l=this.unravelSection.zLockedSegmentPointIds.has(o),u=this.getConnectionSegmentPointIds(a.connectionName);if(this.canConnectionUseLayer(u,r.z)){const t=u.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));t.length>0&&n.push({type:"change_layer",newZ:r.z,segmentPointIds:t})}if(this.canConnectionUseLayer(u,i.z)){const t=u.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));t.length>0&&n.push({type:"change_layer",newZ:i.z,segmentPointIds:t})}this.unravelSection.mutableSegmentPointIds.has(s)&&!d&&c.includes(r.z)&&n.push({type:"change_layer",newZ:r.z,segmentPointIds:[s]}),this.unravelSection.mutableSegmentPointIds.has(o)&&!l&&h.includes(i.z)&&n.push({type:"change_layer",newZ:i.z,segmentPointIds:[o]})}if("same_layer_crossing"===e.type){const[t,s]=e.crossingLine1,[o,i]=e.crossingLine2,r=[],a=this.unravelSection.segmentPointMap.get(t),c=this.unravelSection.segmentPointMap.get(s),h=this.unravelSection.segmentPointMap.get(o),d=this.unravelSection.segmentPointMap.get(i),l=this.unravelSection.mutableSegmentPointIds.has(t),u=this.unravelSection.mutableSegmentPointIds.has(s),p=this.unravelSection.mutableSegmentPointIds.has(o),m=this.unravelSection.mutableSegmentPointIds.has(i),f=this.unravelSection.zLockedSegmentPointIds.has(t),g=this.unravelSection.zLockedSegmentPointIds.has(s),y=this.unravelSection.zLockedSegmentPointIds.has(o),x=this.unravelSection.zLockedSegmentPointIds.has(i);l&&p&&a.segmentId===h.segmentId&&r.push([t,o]),l&&m&&a.segmentId===d.segmentId&&r.push([t,i]),u&&p&&c.segmentId===h.segmentId&&r.push([s,o]),u&&m&&c.segmentId===d.segmentId&&r.push([s,i]);for(const[t,e]of r)n.push({type:"swap_position_on_segment",segmentPointIds:[t,e]});const v=this.getConnectionSegmentPointIds(a.connectionName),S=this.getConnectionSegmentPointIds(h.connectionName),P=new Set;for(const t of this.unravelSection.segmentPointMap.values()){const e=this.dedupedSegmentMap.get(t.segmentId);if(e)for(const t of e.availableZ)P.add(t)}for(const t of P)if(t!==a.z&&this.canConnectionUseLayer(v,t)){const e=v.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));e.length>0&&n.push({type:"change_layer",newZ:t,segmentPointIds:e})}for(const t of P)if(t!==h.z&&this.canConnectionUseLayer(S,t)){const e=S.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));e.length>0&&n.push({type:"change_layer",newZ:t,segmentPointIds:e})}const b=this.dedupedSegmentMap.get(a.segmentId),M=this.dedupedSegmentMap.get(c.segmentId),N=this.dedupedSegmentMap.get(h.segmentId),I=this.dedupedSegmentMap.get(d.segmentId),C=(t,e)=>t.every(t=>t.availableZ.includes(e));if(l&&u&&!f&&!g){const e=0===a.z?1:0;C([b,M],e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t,s]})}if(p&&m&&!y&&!x){const t=0===h.z?1:0;C([N,I],t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[o,i]})}if(l&&!f){const e=0===a.z?1:0;b.availableZ.includes(e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t]})}if(u&&!g){const t=0===c.z?1:0;M.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[s]})}if(p&&!y){const t=0===h.z?1:0;N.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[o]})}if(m&&!x){const t=0===d.z?1:0;I.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[i]})}}return n}computeG(t){const{issues:e,originalCandidate:n,operationsPerformed:s,operation:o}=t,i=new Map;for(const t of e){i.has(t.capacityMeshNodeId)||i.set(t.capacityMeshNodeId,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0});const e=i.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 r=0;for(const[t,{numEntryExitLayerChanges:e,numSameLayerCrossings:n,numTransitionCrossings:s}]of i){const o=this.nodeMap.get(t),i=Math.min(Co(o,n,e,s),.999999);r+=Math.log(1-i)}var a;return(a=r)<-Math.LN2?Math.log(1-Math.exp(a)):Math.log(-Math.expm1(a))}getUnexploredNeighborByApplyingOperation(t,e){const n=new Map(t.pointModifications);ai(n,e,e=>this.getPointInCandidate(t,e));const s=oi(n);if(this.queuedOrExploredCandidatePointModificationHashes.has(s))return null;const o=ri(this.unravelSection,this.nodeMap,n),i=t.operationsPerformed+1,r=this.computeG({issues:o,originalCandidate:t,operationsPerformed:i,operation:e});return{issues:o,g:r,h:0,f:r,pointModifications:n,candidateHash:s,operationsPerformed:i}}getNeighborOperationsForCandidate(t){return t.issues.flatMap(e=>this.getOperationsForIssue(t,e))}getNeighbors(t){const e=[],n=this.getNeighborOperationsForCandidate(t);for(const s of n){const n=this.getUnexploredNeighborByApplyingOperation(t,s);n&&e.push(n)}return e}_step(){const t=this.candidates.shift();this.iterationsSinceImprovement++,this.iterationsSinceImprovement>this.hyperParameters.MAX_ITERATIONS_WITHOUT_IMPROVEMENT?this.solved=!0:t?(this.lastProcessedCandidate=t,t.f<(this.bestCandidate?.f??1/0)&&(this.bestCandidate=t,this.iterationsSinceImprovement=0),this.getNeighbors(t).forEach(t=>{this.queuedOrExploredCandidatePointModificationHashes.has(t.candidateHash)||(this.queuedOrExploredCandidatePointModificationHashes.add(t.candidateHash),this.candidates.push(t))}),this.candidates.sort((t,e)=>t.f-e.f),this.candidates.length=Math.min(this.candidates.length,this.MAX_CANDIDATES)):this.solved=!0}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Section Solver"};let e=null;if(e=null!==this.selectedCandidateIndex?"best"===this.selectedCandidateIndex?this.bestCandidate:"original"===this.selectedCandidateIndex?this.originalCandidate:this.candidates[this.selectedCandidateIndex]:this.solved?this.bestCandidate:this.lastProcessedCandidate||this.candidates[0],!e)return t;const n=new Map;for(const[t,s]of this.unravelSection.segmentPointMap){const o={...s},i=e.pointModifications.get(t);i&&(void 0!==i.x&&(o.x=i.x),void 0!==i.y&&(o.y=i.y),void 0!==i.z&&(o.z=i.z)),n.set(t,o)}for(const[e,s]of n)t.points.push({x:s.x,y:s.y,label:`${e}\nSegment: ${s.segmentId} ${this.unravelSection.mutableSegmentIds.has(s.segmentId)?"MUTABLE":"IMMUTABLE"}\nLayer: ${s.z}`,color:this.colorMap[s.connectionName]||"#000"});const s=new Map;for(const t of this.unravelSection.allNodeIds)s.set(t,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0,estPf:0});for(const t of e.issues){const e=s.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"!==t.type&&"single_transition_crossing"!==t.type||e.numEntryExitLayerChanges++}for(const[t,e]of s.entries()){const n=this.nodeMap.get(t);e.estPf=Co(n,e.numSameLayerCrossings,e.numEntryExitLayerChanges,e.numTransitionCrossings)}for(const e of this.unravelSection.allNodeIds){const n=this.nodeMap.get(e),o=this.unravelSection.mutableNodeIds.includes(e),i=s.get(e),r=[`${e} (${o?"MUT":"IMM"})`,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Pf: ${i.estPf.toFixed(3)}`,`TC: ${i.numTransitionCrossings}`,`SLC: ${i.numSameLayerCrossings}`,`EELC: ${i.numEntryExitLayerChanges}`].join("\n");t.rects.push({center:n.center,label:r,color:o?"green":"red",width:n.width/8,height:n.height/8})}for(const[e,s]of this.unravelSection.segmentPointsInSegment){if(s.length<=1)continue;const o=s.map(t=>n.get(t));for(let n=0;n<o.length-1;n++)t.lines.push({points:[{x:o[n].x,y:o[n].y},{x:o[n+1].x,y:o[n+1].y}],strokeColor:this.colorMap[e]||"#000"})}for(const[e,s]of n)for(const o of s.directlyConnectedSegmentPointIds)if(e<o){const e=n.get(o);if(!e)continue;const i=s.z===e.z,r=s.z;let a;a=i?0===r?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:s.x,y:s.y},{x:e.x,y:e.y}],strokeDash:a,strokeColor:this.colorMap[s.connectionName]||"#000"})}for(const s of e.issues){const e=this.nodeMap.get(s.capacityMeshNodeId);if("transition_via"===s.type)for(const o of s.segmentPoints){const s=n.get(o);t.circles.push({center:{x:s.x,y:s.y},radius:e.width/16,stroke:"#ff0000",fill:"rgba(255, 0, 0, 0.2)",label:`Via Issue\n${o}\nLayer: ${s.z}`})}else if("same_layer_crossing"===s.type)for(const[o,i]of[s.crossingLine1,s.crossingLine2]){const s=n.get(o),r=n.get(i);t.lines.push({points:[{x:s.x,y:s.y},{x:r.x,y:r.y}],strokeColor:"rgba(255,0,0,0.2)",strokeWidth:e.width/32})}}for(const[s,o]of e.pointModifications){const e=n.get(s),o=this.unravelSection.segmentPointMap.get(s);t.circles.push({center:{x:e.x,y:e.y},radius:.05,stroke:"#0000ff",fill:"rgba(0, 0, 255, 0.2)",label:`${s}\nOriginal: (${o.x.toFixed(2)}, ${o.y.toFixed(2)}, ${o.z})\nNew: (${e.x.toFixed(2)}, ${e.y.toFixed(2)}, ${e.z})`})}return t}};import di from"object-hash";var li=t=>(Math.round(20*t)/20).toFixed(2),ui=t=>(Math.round(1e3*t)/1e3).toFixed(3);pt();var pi=class extends hi{cacheHit=!1;cacheProvider;hasAttemptedToUseCache=!1;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?lt():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}computeCacheKeyAndTransform(){const t=this.nodeMap.get(this.rootNodeId),e=function(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}(-t.center.x,-t.center.y),n=new Map,s=new Map,o=new Map,i=new Map,r=new Map,a=new Map;let c=0,h=0,d=0;const l=[...this.unravelSection.allNodeIds].sort((t,e)=>{const n=this.nodeMap.get(t),s=this.nodeMap.get(e);return n.center.x!==s.center.x?n.center.x-s.center.x:n.center.y-s.center.y});for(const t of l){const e="node_"+c++;n.set(t,e),s.set(e,t)}const u=[...Array.from(this.unravelSection.segmentPointMap.entries()).sort(([,t],[,e])=>t.x!==e.x?t.x-e.x:t.y-e.y).map(([t])=>t)].sort();for(const t of u){const e="sp_"+d++;r.set(t,e),a.set(e,t);const n=this.unravelSection.segmentPointMap.get(t).segmentId;if(!o.has(n)){const t="seg_"+h++;o.set(n,t),i.set(t,n)}}const p={};for(const[t,s]of n.entries()){const n=this.nodeMap.get(t),o=yn(e,n.center);p[s]={width:n.width,height:n.height,availableZ:n.availableZ,center:{x:li(o.x),y:li(o.y)}}}const m={};for(const[t,n]of r.entries()){const s=this.unravelSection.segmentPointMap.get(t),o=yn(e,{x:s.x,y:s.y});m[n]={x:li(o.x),y:li(o.y),z:s.z}}const f={hyperParameters:this.hyperParameters,normalizedNodes:p,normalizedSegmentPoints:m,mutableHops:this.MUTABLE_HOPS},g=`unravelsec:${di(f)}`,y={realToCacheTransform:e,nodeIdMap:n,segmentIdMap:o,segmentPointIdMap:r,reverseNodeIdMap:s,reverseSegmentIdMap:i,reverseSegmentPointIdMap:a};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:n}=this.cacheToSolveSpaceTransform,s=new Map;for(const[n,o]of t.bestCandidatePointModificationsDelta){const t=e.get(n);if(!t){console.warn(`Could not find original ID for normalized SP ID: ${n} when applying cache.`);continue}const i=this.unravelSection.segmentPointMap.get(t);if(!i){console.warn(`Could not find original segment point for ID: ${t} when applying cache.`);continue}const r={};if(void 0!==o.dx){const t=parseFloat(o.dx);Number.isNaN(t)?console.warn(`Failed to parse cached dx coordinate: ${o.dx}`):r.x=i.x+t}if(void 0!==o.dy){const t=parseFloat(o.dy);Number.isNaN(t)?console.warn(`Failed to parse cached dy coordinate: ${o.dy}`):r.y=i.y+t}void 0!==o.dz&&(r.z=i.z+o.dz),Object.keys(r).length>0&&s.set(t,r)}const o=ri(this.unravelSection,this.nodeMap,s);this.bestCandidate={pointModifications:s,issues:o,f:t.bestCandidateF,g:t.bestCandidateF,h:0,operationsPerformed:-1,candidateHash:oi(s)},this.cacheHit=!0,this.solved=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(this.failed)return void this.cacheProvider?.setCachedSolutionSync(this.cacheKey,{success:!1});if(!this.bestCandidate)return;const{segmentPointIdMap:t}=this.cacheToSolveSpaceTransform,e=[];for(const[n,s]of this.bestCandidate.pointModifications.entries()){const o=t.get(n);if(!o){console.warn(`Could not find normalized ID for original SP ID: ${n} when saving to cache.`);continue}const i=this.unravelSection.segmentPointMap.get(n);if(!i){console.warn(`Could not find original segment point for ID: ${n} when saving cache.`);continue}const r={};let a=!1;if(void 0!==s.x){const t=s.x-i.x,e=ui(t);0!==parseFloat(e)&&(r.dx=e,a=!0)}if(void 0!==s.y){const t=s.y-i.y,e=ui(t);0!==parseFloat(e)&&(r.dy=e,a=!0)}if(void 0!==s.z){const t=s.z-i.z;0!==t&&(r.dz=t,a=!0)}a&&e.push([o,r])}const n={success:!0,bestCandidatePointModificationsDelta:e,bestCandidateF:this.bestCandidate.f};this.cacheProvider?.setCachedSolutionSync(this.cacheKey,n)}},mi=class extends y{nodeMap;dedupedSegmentMap;dedupedSegments;nodeIdToSegmentIds;segmentIdToNodeIds;nodeToSegmentPointMap;segmentToSegmentPointMap;colorMap;tunedNodeCapacityMap;MAX_NODE_ATTEMPTS=2;MUTABLE_HOPS=1;ACCEPTABLE_PF=.05;MAX_ITERATIONS_WITHOUT_IMPROVEMENT=200;nodePfMap;attemptsToFixNode;activeSubSolver=null;segmentPointMap;cacheProvider=null;constructor({assignedSegments:t,colorMap:e,nodes:n,cacheProvider:s}){super(),this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.cacheHits=0,this.stats.cacheMisses=0,this.cacheProvider=s??null,this.MAX_ITERATIONS=1e6,this.dedupedSegments=(t=>{const e=[],n=new Map;let s=-1;for(const o of t){const t=`${o.start.x}-${o.start.y}-${o.end.x}-${o.end.y}-${o.availableZ.join(",")}`,i=n.get(t);i?o.nodePortSegmentId=i.nodePortSegmentId:(s++,o.nodePortSegmentId=`SEG${s}`,n.set(t,o),e.push(o))}return e})(t),this.dedupedSegmentMap=new Map;for(const t of this.dedupedSegments)this.dedupedSegmentMap.set(t.nodePortSegmentId,t);this.nodeMap=new Map;for(const t of n)this.nodeMap.set(t.capacityMeshNodeId,t);this.nodeIdToSegmentIds=new Map,this.segmentIdToNodeIds=new Map,this.attemptsToFixNode=new Map;for(const e of t)this.segmentIdToNodeIds.set(e.nodePortSegmentId,[...this.segmentIdToNodeIds.get(e.nodePortSegmentId)??[],e.capacityMeshNodeId]),this.nodeIdToSegmentIds.set(e.capacityMeshNodeId,[...this.nodeIdToSegmentIds.get(e.capacityMeshNodeId)??[],e.nodePortSegmentId]);this.colorMap=e??{},this.tunedNodeCapacityMap=new Map;for(const[t,e]of this.nodeMap)this.tunedNodeCapacityMap.set(t,ke(e));const{segmentPointMap:o,nodeToSegmentPointMap:i,segmentToSegmentPointMap:r}=ci(this.dedupedSegments,this.segmentIdToNodeIds);this.segmentPointMap=o,this.nodeToSegmentPointMap=i,this.segmentToSegmentPointMap=r,this.nodePfMap=this.computeInitialPfMap()}computeInitialPfMap(){const t=new Map;for(const[e,n]of this.nodeMap.entries())t.set(e,this.computeNodePf(n));return t}computeNodePf(t){const{numSameLayerCrossings:e,numEntryExitLayerChanges:n,numTransitionCrossings:s}=(t=>{let e=0,n=0,s=0;const o=new Map;for(const e of t)o.has(e.connectionName)||o.set(e.connectionName,[]),o.get(e.connectionName).push(e);const i=[],r=[];for(const[t,e]of o.entries()){if(e.length<2)continue;const s=e[0];for(let o=1;o<e.length;o++){const a=e[o],c={connectionName:t,z:s.z,points:[s,a]};s.z!==a.z?(n++,r.push({connectionName:t,points:[s,a]})):i.push(c)}}for(let t=0;t<i.length;t++)for(let n=t+1;n<i.length;n++){const s=i[t],o=i[n];s.z===o.z&>(s.points[0],s.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 n=r[t],o=r[e];gt(n.points[0],n.points[1],o.points[0],o.points[1])&&s++}for(let t=0;t<r.length;t++)for(let e=0;e<i.length;e++){const n=r[t],o=i[e];gt(n.points[0],n.points[1],o.points[0],o.points[1])&&s++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:n,numTransitionCrossings:s}})((this.nodeToSegmentPointMap.get(t.capacityMeshNodeId)??[]).map(t=>this.segmentPointMap.get(t)));return Co(t,e,n,s)}_step(){if(this.iterations>=this.MAX_ITERATIONS-1)return void(this.solved=!0);if(!this.activeSubSolver){let t=null,e=0;for(const[n,s]of this.nodePfMap.entries()){s*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_NODE_ATTEMPTS)>e&&(e=s,t=n)}if(!t||e<this.ACCEPTABLE_PF)return void(this.solved=!0);this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.activeSubSolver=new pi({dedupedSegments:this.dedupedSegments,dedupedSegmentMap:this.dedupedSegmentMap,nodeMap:this.nodeMap,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,colorMap:this.colorMap,rootNodeId:t,MUTABLE_HOPS:this.MUTABLE_HOPS,segmentPointMap:this.segmentPointMap,nodeToSegmentPointMap:this.nodeToSegmentPointMap,segmentToSegmentPointMap:this.segmentToSegmentPointMap,cacheProvider:this.cacheProvider})}this.activeSubSolver.step();const{bestCandidate:t,originalCandidate:e,lastProcessedCandidate:n}=this.activeSubSolver;if(this.activeSubSolver.failed)return this.stats.failedOptimizations+=1,void(this.activeSubSolver=null);if(this.activeSubSolver.solved){this.activeSubSolver.cacheHit?this.stats.cacheHits+=1:this.stats.cacheMisses+=1;if(t&&t.g<e.g){this.stats.successfulOptimizations+=1;for(const[e,n]of t.pointModifications.entries()){const t=this.segmentPointMap.get(e);t.x=n.x??t.x,t.y=n.y??t.y,t.z=n.z??t.z}for(const t of this.activeSubSolver.unravelSection.allNodeIds)this.nodePfMap.set(t,this.computeNodePf(this.nodeMap.get(t)))}else this.stats.failedOptimizations+=1;this.activeSubSolver=null}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Multi Section Solver"};for(const[e,n]of this.nodeMap.entries()){const s=this.nodePfMap.get(e)||0,o=Math.min(s,1),i=`rgb(${Math.floor(255*o)}, ${Math.floor(255*(1-o))}, 0)`;0===(this.attemptsToFixNode.get(e)??0)&&0===o||t.rects.push({center:n.center,label:[e,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Pf: ${s.toFixed(3)}`].join("\n"),color:i,width:n.width/8,height:n.height/8})}for(const e of this.segmentPointMap.values()){const n=this.dedupedSegmentMap.get(e.segmentId);t.points.push({x:e.x,y:e.y,label:[e.segmentPointId,e.segmentId,`z: ${e.z}`,`segment.availableZ: ${n?.availableZ.join(",")}`].join("\n"),color:this.colorMap[e.connectionName]||"#000"})}const e=new Map;for(const t of this.segmentPointMap.values())e.has(t.segmentId)||e.set(t.segmentId,[]),e.get(t.segmentId).push(t);for(const[n,s]of e.entries()){if(s.length<2)continue;const e=[...s].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y);for(let s=0;s<e.length-1;s++)t.lines.push({points:[{x:e[s].x,y:e[s].y},{x:e[s+1].x,y:e[s+1].y}],strokeColor:this.colorMap[n]||"#000"})}const n=new Set,s=Array.from(this.segmentPointMap.values());for(let e=0;e<s.length;e++){const o=s[e];for(let i=e+1;i<s.length;i++){const e=s[i];if(o.connectionName!==e.connectionName||o.segmentId===e.segmentId)continue;if(o.capacityMeshNodeIds.some(t=>e.capacityMeshNodeIds.includes(t))){const s=`${o.segmentPointId}-${e.segmentPointId}`;if(n.has(s))continue;n.add(s);const i=o.z===e.z,r=o.z;let a;a=i?0===r?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:o.x,y:o.y},{x:e.x,y:e.y}],strokeDash:a,strokeColor:this.colorMap[o.connectionName]||"#666"})}}}return t}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.dedupedSegments){const n=e.nodePortSegmentId;for(const e of this.segmentIdToNodeIds.get(n)){const n=this.nodeMap.get(e);t.has(e)||t.set(e,{capacityMeshNodeId:e,portPoints:[],center:n.center,width:n.width,height:n.height})}}for(const e of this.segmentPointMap.values())for(const n of e.capacityMeshNodeIds){const s=t.get(n);s&&s.portPoints.push({x:e.x,y:e.y,z:e.z,connectionName:e.connectionName,rootConnectionName:e.rootConnectionName})}return Array.from(t.values())}},fi=(t,e={})=>{const n=Math.min(...t.availableZ);return{center:!e.rectMargin||e.zOffset?{x:t.center.x+n*t.width*(e.zOffset??.05),y:t.center.y-n*t.width*(e.zOffset??.05)}:t.center,width:e.rectMargin?t.width-2*e.rectMargin:Math.max(t.width-.5,.8*t.width),height:e.rectMargin?t.height-2*e.rectMargin:Math.max(t.height-.5,.8*t.height),fill:t._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[t.availableZ.join(",")]??"rgba(0,200,200,0.1)",layer:`z${t.availableZ.join(",")}`,label:[t.capacityMeshNodeId,`availableZ: ${t.availableZ.join(",")}`,""+(t._containsTarget?"containsTarget":""),""+(t._containsObstacle?"containsObstacle":"")].filter(Boolean).join("\n")}},gi=class extends y{connectionsWithNodes;usedNodeCapacityMap;simpleRouteJson;nodes;edges;GREEDY_MULTIPLIER=1.1;MAX_CANDIDATES_IN_MEMORY=1e5;nodeMap;nodeEdgeMap;connectionNameToGoalNodeIds;colorMap;maxDepthOfNodes;activeCandidateStraightLineDistance;debug_lastNodeCostMap;hyperParameters;constructor({simpleRouteJson:t,nodes:e,edges:n,colorMap:s,MAX_ITERATIONS:o=1e6,hyperParameters:i={}}){super(),this.MAX_ITERATIONS=o,this.simpleRouteJson=t,this.nodes=e,this.edges=n,this.colorMap=s??{};const{connectionsWithNodes:r,connectionNameToGoalNodeIds:a}=this.getConnectionsWithNodes();this.connectionsWithNodes=r,this.connectionNameToGoalNodeIds=a,this.hyperParameters=i,this.usedNodeCapacityMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,0])),this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=No(this.edges),this.maxDepthOfNodes=Math.max(...this.nodes.map(t=>t._depth??0)),this.debug_lastNodeCostMap=new Map}getTotalCapacity(t){const e=t._depth??0;return(this.maxDepthOfNodes-e+1)**2}getConnectionsWithNodes(){const t=[],e=this.nodes.filter(t=>t._containsTarget),n=new Map;for(const s of this.simpleRouteJson.connections){const o=[];for(const t of s.pointsToConnect){let n=this.nodes[0],s=Number.MAX_VALUE;for(const o of e){const e=Math.sqrt((o.center.x-t.x)**2+(o.center.y-t.y)**2);e<s&&(s=e,n=o)}o.push(n)}if(o.length<2)throw new Error(`Not enough nodes for connection "${s.name}", only ${o.length} found`);n.set(s.name,o.map(t=>t.capacityMeshNodeId)),t.push({connection:s,nodes:o,pathFound:!1,straightLineDistance:St(o[0].center,o[o.length-1].center)})}return t.sort((t,e)=>t.straightLineDistance-e.straightLineDistance),{connectionsWithNodes:t,connectionNameToGoalNodeIds:n}}currentConnectionIndex=0;candidates;visitedNodes;computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)}getBacktrackedPath(t){const e=[];let n=t;for(;n;)e.push(n.node),n=n.prevCandidate;return e}getNeighboringNodes(t){return this.nodeEdgeMap.get(t.capacityMeshNodeId).flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t))}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const n=e.path;n&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,rootConnectionName:e.connection.rootConnectionName,nodeIds:n.map(t=>t.capacityMeshNodeId)})}return t}doesNodeHaveCapacityForTrace(t,e){const n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.getTotalCapacity(t);if(1===t.availableZ.length&&!t._containsTarget&&n>0)return!1;let o=0;return t.availableZ.length>1&&1===e.availableZ.length&&(o+=.5),n+o<s}canTravelThroughObstacle(t,e){const n=this.connectionNameToGoalNodeIds.get(e);return n?.includes(t.capacityMeshNodeId)??!1}getDistanceBetweenNodes(t,e){return Math.sqrt((t.center.x-e.center.x)**2+(t.center.y-e.center.y)**2)}reduceCapacityAlongPath(t){for(const e of t.path??[])this.usedNodeCapacityMap.set(e.capacityMeshNodeId,this.usedNodeCapacityMap.get(e.capacityMeshNodeId)+1)}isConnectedToEndGoal(t,e){return this.nodeEdgeMap.get(t.capacityMeshNodeId).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}_step(){const t=this.connectionsWithNodes[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const[e,n]=t.nodes;this.candidates||(this.candidates=[{prevCandidate:null,node:e,f:0,g:0,h:0}],this.debug_lastNodeCostMap=new Map,this.visitedNodes=new Set([e.capacityMeshNodeId]),this.activeCandidateStraightLineDistance=St(e.center,n.center)),this.candidates.sort((t,e)=>t.f-e.f);const s=this.candidates.shift();if(this.candidates.length>this.MAX_CANDIDATES_IN_MEMORY&&this.candidates.splice(this.MAX_CANDIDATES_IN_MEMORY,this.candidates.length-this.MAX_CANDIDATES_IN_MEMORY),!s)return console.error(`Ran out of candidates on connection ${t.connection.name}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,void(this.failed=!0);if(this.isConnectedToEndGoal(s.node,n))return t.path=this.getBacktrackedPath({prevCandidate:s,node:n,f:0,g:0,h:0}),this.reduceCapacityAlongPath(t),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);const o=this.getNeighboringNodes(s.node);for(const t of o){if(this.visitedNodes?.has(t.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(t,s.node))continue;const e=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;if(t._containsObstacle&&!this.canTravelThroughObstacle(t,e))continue;const o=this.computeG(s,t,n),i=this.computeH(s,t,n),r=o+i*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:r,g:o,h:i});const a={prevCandidate:s,node:t,f:r,g:o,h:i};this.candidates.push(a)}this.visitedNodes.add(s.node.capacityMeshNodeId)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(this.connectionsWithNodes)for(let e=0;e<this.connectionsWithNodes.length;e++){const n=this.connectionsWithNodes[e];if(n.path&&n.path.length>0){const s=n.path.map(({center:{x:t,y:n},width:s,availableZ:o})=>({x:t+.005*s*(e%10+e%19),y:n+.005*s*(e%10+e%19),availableZ:o}));t.lines.push({points:s,strokeColor:this.colorMap[n.connection.name]});for(let e=0;e<s.length;e++){const o=s[e];t.points.push({x:o.x,y:o.y,label:[`conn: ${n.connection.name}`,`node: ${n.path[e].capacityMeshNodeId}`,`z: ${o.availableZ.join(",")}`].join("\n")})}}}for(const e of this.nodes){const n=this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,s=this.getTotalCapacity(e),o=this.debug_lastNodeCostMap.get(e.capacityMeshNodeId);t.rects.push({...fi(e,{rectMargin:.025,zOffset:.01}),label:[`${e.capacityMeshNodeId}`,`${n}/${s}`,`${e.width.toFixed(2)}x${e.height.toFixed(2)}`,`g: ${void 0!==o?.g?o.g.toFixed(2):"?"}`,`h: ${void 0!==o?.h?o.h.toFixed(2):"?"}`,`f: ${void 0!==o?.f?o.f.toFixed(2):"?"}`,`z: ${e.availableZ.join(", ")}`].join("\n"),stroke:n>s+.5?"red":void 0})}if(this.connectionsWithNodes)for(const e of this.connectionsWithNodes)if(e.connection?.pointsToConnect)for(const n of e.connection.pointsToConnect)t.points.push({x:n.x,y:n.y,label:[`pointsToConnect ${e.connection.name}`].join("\n")});let e=this.connectionsWithNodes[this.currentConnectionIndex];if(!this.candidates&&this.currentConnectionIndex>0&&!this.connectionsWithNodes[this.currentConnectionIndex-1].path&&(e=this.connectionsWithNodes[this.currentConnectionIndex-1]),e){const[n,s]=e.connection.pointsToConnect;t.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.y}],strokeColor:"red",strokeDash:"10 5"})}if(this.candidates){const e=this.candidates.slice(0,5),n=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;e.forEach((e,s)=>{const o=.5*(1-s/5),i=this.getBacktrackedPath(e);t.lines.push({points:i.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:it(this.colorMap[n]??"red",1-o)})})}return t}},yi=class extends gi{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 ke(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){const e=t.width+t.height,n=.05,s=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0);if(s>2)return n;return(e-n)*Math.max(1,(2-s)/(e-n))+n}getDistanceBetweenNodes(t,e){const n=t.center.x-e.center.x,s=t.center.y-e.center.y;return Math.sqrt(n**2+s**2)}computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)+this.getNodeCapacityPenalty(e)}},xi=class extends yi{doesNodeHaveCapacityForTrace(t,e){return!0}getNodeCapacityPenalty(t){const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let n=1;return 1===t.availableZ.length&&(n=10),(.05+2*Math.abs(e))*n}};function vi(t,e,n){const s=e.x-t.x,o=e.y-t.y;if(Math.abs(s)<1e-9&&Math.abs(o)<1e-9)return t;const i=n.width/2,r=n.height/2,a=n.center.x-i,c=n.center.x+i,h=n.center.y-r,d=n.center.y+r;let l=0,u=1/0;if(Math.abs(s)>1e-9){const e=(a-t.x)/s,n=(c-t.x)/s;l=Math.max(l,Math.min(e,n)),u=Math.min(u,Math.max(e,n))}else if(t.x<a||t.x>c)return t;if(Math.abs(o)>1e-9){const e=(h-t.y)/o,n=(d-t.y)/o;l=Math.max(l,Math.min(e,n)),u=Math.min(u,Math.max(e,n))}else if(t.y<h||t.y>d)return t;if(u<l||l===1/0||l<-1e9)return t;return{x:t.x+s*l,y:t.y+o*l}}function Si(t,e){const n=t.center,s=e.center,o=vi(n,s,t),i=vi(s,n,e),r=s.x-n.x,a=s.y-n.y,c=Math.sqrt(r*r+a*a);let h=o,d=i;if(c>1e-9){const n={x:r/c,y:a/c},s=.3*t.width,l=.3*e.width;s+l<Math.sqrt((i.x-o.x)**2+(i.y-o.y)**2)?(h={x:o.x+n.x*s,y:o.y+n.y*s},d={x:i.x-n.x*l,y:i.y-n.y*l}):(h=o,d=i)}return{lineStart:h,lineEnd:d}}var Pi=t=>{const{usedCapacity:e,totalCapacity:n,layerCount:s}=t;if(e<n)return 0;if(n<1&&e<=1)return 0;if(1===s&&e>1)return 1-.01**e;const o=e/n-1;return 1-Math.exp(-2*o)},bi=(t,e,n)=>{if(n._containsTarget)return 0;if(t<=e)return 0;const s=1-Pi({usedCapacity:t,totalCapacity:e,layerCount:n.availableZ.length});return s<=0?-1e9:Math.log(s)},Mi=({totalNodeCapacityMap:t,usedNodeCapacityMap:e,nodeMap:n,sectionNodeIds:s})=>{let o=0;const i=s??new Set(e.keys());for(const s of i){if(!t.has(s))continue;const i=n.get(s);if(!i)continue;const r=t.get(s),a=e.get(s)??0;o+=bi(a,r,i)}return o};function Ni({sectionNodes:t,sectionEdges:e,sectionConnectionTerminals:n,completedPaths:s,nodeMap:o,colorMap:i,centerNodeId:r,title:a,nodeOpacity:c=.1,usedNodeCapacityMap:h,totalCapacityMap:d}){const l={points:[],lines:[],rects:[],circles:[],title:a},u=new Set(t.map(t=>t.capacityMeshNodeId));for(const e of t){let t=`rgba(128, 128, 128, ${c})`,n=`rgba(128, 128, 128, ${c})`;const s=e.availableZ??[],o=s.includes(0),i=s.includes(1);o&&i?(t=`rgba(128, 0, 128, ${c})`,n=`rgba(128, 0, 128, ${c})`):o?(t=`rgba(0, 0, 255, ${c})`,n=`rgba(0, 0, 255, ${c})`):i&&(t=`rgba(255, 0, 0, ${c})`,n=`rgba(255, 0, 0, ${c})`),r&&e.capacityMeshNodeId===r&&(t=`rgba(0, 255, 0, ${c})`,n=`rgba(0, 128, 0, ${c})`),l.rects.push({...fi(e),fill:t,stroke:n,label:`${e.capacityMeshNodeId}\n(Section Node)\nZ: ${s.join(",")}`});const a=l.rects.length-1;if(h&&d){const t=h.get(e.capacityMeshNodeId)??0,n=d.get(e.capacityMeshNodeId)??0,s=n>0?(t/n*100).toFixed(1):"N/A",o=Pi({usedCapacity:t,totalCapacity:n,layerCount:e.availableZ.length});l.rects[a].label+=`\n${t.toFixed(1)} / ${n.toFixed(1)}\n${s}% (Pf: ${(100*o).toFixed(1)}%)`,o>.2&&(l.rects[a].stroke=it("red",.7*(.8+c)))}}for(const t of e){const[e,n]=t.nodeIds,s=o.get(e),i=o.get(n);if(s&&i){const{lineStart:t,lineEnd:e}=Si(s,i);l.lines.push({points:[t,e],strokeColor:`rgba(0, 0, 0, ${.2*Math.min(1,c/.1)})`})}}return n.forEach((t,e)=>{const n=o.get(t.startNodeId),s=o.get(t.endNodeId),r=i[t.connectionName]??"black",a=n&&u.has(n.capacityMeshNodeId),c=s&&u.has(s.capacityMeshNodeId),h=(e+e/50)%5;let d=0,p=0,m=0,f=0;if(a&&n){const e=.02*Math.min(n.width,n.height);d=e*h,p=e*h,l.points.push({x:n.center.x+d,y:n.center.y+p,color:r,label:`Start: ${t.connectionName}\n(${t.startNodeId})`}),l.lines.push({points:[{x:n.center.x,y:n.center.y},{x:n.center.x+d,y:n.center.y+p}],strokeColor:"gray",strokeDash:"2 2"})}if(c&&s){const e=.02*Math.min(s.width,s.height);m=e*h,f=e*h,l.points.push({x:s.center.x+m,y:s.center.y+f,color:r,label:`End: ${t.connectionName}\n(${t.endNodeId})`}),l.lines.push({points:[{x:s.center.x,y:s.center.y},{x:s.center.x+m,y:s.center.y+f}],strokeColor:"gray",strokeDash:"2 2"})}a&&c&&n&&s&&l.lines.push({points:[{x:n.center.x+d,y:n.center.y+p},{x:s.center.x+m,y:s.center.y+f}],strokeColor:r,strokeDash:"5 5"})}),s&&s.forEach((t,e)=>{if(t.path&&t.path.length>0){const n=i[t.connectionName]??"gray",s={x:(e+e/50)%5*.03,y:(e+e/50)%5*.03};l.lines.push({points:t.path.map(({center:{x:t,y:e}})=>({x:t+s.x,y:e+s.y})),strokeColor:it(n,.2)})}}),l}var Ii=class extends y{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??No(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=Mi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:e}),t.hyperParameters?.SHUFFLE_SEED&&(this.sectionConnectionTerminals=kt(this.sectionConnectionTerminals,t.hyperParameters?.SHUFFLE_SEED))}getTotalCapacity(t){return ke(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){if(!this.nodeMap.has(t.capacityMeshNodeId))return 1/0;const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let n=1;return 1===t.availableZ.length&&(n=10),(.05+e**2*4)*n}getDistanceBetweenNodes(t,e){const n=t.center.x-e.center.x,s=t.center.y-e.center.y;return Math.sqrt(n**2+s**2)}computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)+this.getNodeCapacityPenalty(e)}getBacktrackedPath(t){const e=[];let n=t;for(;n;){if(e.push(n.node),!this.nodeMap.has(n.node.capacityMeshNodeId)){console.warn("Backtracked path went outside section bounds");break}n=n.prevCandidate}return e.reverse()}getNeighboringNodes(t){return this.nodeMap.has(t.capacityMeshNodeId)?this.nodeEdgeMap.get(t.capacityMeshNodeId)?.flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t)).filter(Boolean)??[]:[]}isConnectedToEndGoal(t,e){return!(!this.nodeMap.has(t.capacityMeshNodeId)||!this.nodeMap.has(e.capacityMeshNodeId))&&(this.nodeEdgeMap.get(t.capacityMeshNodeId)??[]).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}doesNodeHaveCapacityForTrace(t,e){return!0}reduceCapacityAlongPath(t){for(const e of t)if(this.usedNodeCapacityMap.has(e.capacityMeshNodeId)){const t=e.capacityMeshNodeId,n=this.nodeMap.get(t);if(!n){console.warn(`Node ${t} from path not found in section's nodeMap during score update.`);continue}const s=this.totalNodeCapacityMap.get(t),o=this.usedNodeCapacityMap.get(t)??0,i=bi(o,s,n);this.currentSectionScore-=i;const r=o+1;this.usedNodeCapacityMap.set(t,r);const a=bi(r,s,n);this.currentSectionScore+=a}}getSolvedSectionScore(){return this.currentSectionScore}_step(){const t=this.sectionConnectionTerminals[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const e=this.nodeMap.get(t.startNodeId),n=this.nodeMap.get(t.endNodeId);if(!e||!n)return console.error(`Start or end node not found in section for connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);this.candidates||this._setupAStar(e,n);const s=this.candidates;if(0===s.length)return void this._handleCandidatesExhausted(t);s.sort((t,e)=>t.f-e.f);const o=s.shift();if(s.length>this.MAX_CANDIDATES_IN_MEMORY&&s.splice(this.MAX_CANDIDATES_IN_MEMORY,s.length-this.MAX_CANDIDATES_IN_MEMORY),this.visitedNodes.add(o.node.capacityMeshNodeId),o.node.capacityMeshNodeId===n.capacityMeshNodeId)return void this._handleGoalReached(o,t,n);const i=this.getNeighboringNodes(o.node);for(const e of i){if(this.queuedNodes?.has(e.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(e,o.node))continue;if(e._containsObstacle){const n=e.capacityMeshNodeId===t.startNodeId,s=e.capacityMeshNodeId===t.endNodeId;if(!n&&!s)continue}const i=this.computeG(o,e,n),r=this.computeH(o,e,n),a=i+r*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(e.capacityMeshNodeId,{f:a,g:i,h:r});const c={prevCandidate:o,node:e,f:a,g:i,h:r};this.queuedNodes?.add(e.capacityMeshNodeId),s.push(c)}}computeProgress(){const t=this.sectionConnectionTerminals.length;if(0===t)return 1;let e=this.currentConnectionIndex/t;if(this.currentConnectionIndex<t&&this.candidates&&this.candidates.length>0&&this.activeCandidateStraightLineDistance&&this.activeCandidateStraightLineDistance>0){const n=this.candidates.reduce((t,e)=>e.f<t.f?e:t);e+=Math.max(0,Math.min(1,1-n.h/this.activeCandidateStraightLineDistance))/t}else this.solved&&(e=1);return Math.min(1,e)}_setupAStar(t,e){this.candidates=[{prevCandidate:null,node:t,f:0,g:0,h:0}],this.visitedNodes=new Set([t.capacityMeshNodeId]),this.debug_lastNodeCostMap=new Map,this.activeCandidateStraightLineDistance=St(t.center,e.center);const n=this.computeH(null,t,e);this.candidates[0].h=n,this.candidates[0].f=n*this.GREEDY_MULTIPLIER,this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:this.candidates[0].f,g:0,h:n}),this.queuedNodes=new Set([t.capacityMeshNodeId])}_handleCandidatesExhausted(t){console.error(`Ran out of candidates for section connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}_handleGoalReached(t,e,n){const s=this.getBacktrackedPath(t);e.path=s,this.reduceCapacityAlongPath(s),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}visualize(){const t=this.sectionConnectionTerminals.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connectionName,path:t.path})),e=Ni({sectionNodes:this.sectionNodes,sectionEdges:this.sectionEdges,sectionConnectionTerminals:this.sectionConnectionTerminals,completedPaths:t,nodeMap:this.nodeMap,colorMap:this.colorMap,centerNodeId:null,title:`Section Pathing: Conn ${this.currentConnectionIndex+1}/${this.sectionConnectionTerminals.length} (${this.sectionNodes.length} nodes)`,nodeOpacity:.1});for(const t of this.sectionNodes){const n=e.rects.findIndex(e=>e.label?.includes(t.capacityMeshNodeId));if(-1!==n){const s=this.debug_lastNodeCostMap.get(t.capacityMeshNodeId),o=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,i=this.getTotalCapacity(t),r=`${o.toFixed(1)}/${i.toFixed(1)}`,a=s?`f:${s.f.toFixed(1)} g:${s.g.toFixed(1)} h:${s.h.toFixed(1)}`:"cost:?";e.rects[n].label=[t.capacityMeshNodeId,`Cap: ${r}`,a,`Z: ${t.availableZ.join(",")}`].join("\n"),o>i&&(e.rects[n].stroke=it("red",.7))}}if(this.candidates&&this.candidates.length>0){const t=this.candidates.slice().sort((t,e)=>t.f-e.f).slice(0,5),n=this.sectionConnectionTerminals[this.currentConnectionIndex],s=n?.connectionName??"unknown",o=this.colorMap[s]??"purple";t.forEach((t,n)=>{const s=.8*(1-n/5),i=this.getBacktrackedPath(t);i.length>0&&e.lines.push({points:i.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:it(o,1-s),strokeWidth:.05})})}return e}},Ci=t=>Array.from({length:t},(t,e)=>e),_i=class extends Zt{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:Ci(2).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings6_for3",possibleValues:Ci(6).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings24_for4",possibleValues:Ci(24).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings30",possibleValues:Ci(30).map(t=>({SHUFFLE_SEED:t}))}]}generateSolver(t){return new Ii({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}onSolve({solver:t}){this.winningSolver=t}get centerNodeId(){return this.constructorParams.centerNodeId}get sectionNodes(){return this.constructorParams.sectionNodes}get sectionConnectionTerminals(){return this.winningSolver?.sectionConnectionTerminals}};import Ti from"object-hash";var Ei=t=>Math.floor(10*t)/10,Ri=class extends _i{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?ut():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}_computeBfsOrderingOfNodesInSection(){const t=new Set(this.constructorParams.centerNodeId),e=[],n=[{ancestorCapacitySum:0,capacity:0,g:0,capacityMeshNodeId:this.constructorParams.centerNodeId}];for(;n.length>0;){n.sort((t,e)=>e.g-t.g);const s=n.pop();if(!s)break;e.push(s.capacityMeshNodeId);const o=this.constructorParams.nodeEdgeMap.get(s.capacityMeshNodeId).flatMap(t=>t.nodeIds).filter(e=>!t.has(e)).filter(t=>this.sectionNodeIdSet.has(t));for(const e of o){t.add(e);const o=this.constructorParams.nodeMap.get(e),i=ke(o);n.push({ancestorCapacitySum:s.g,capacity:i,g:s.g+i,capacityMeshNodeId:e})}}return e}computeCacheKeyAndTransform(){const t=this._computeBfsOrderingOfNodesInSection(),e=new Map,n=new Map;t.forEach((t,s)=>{const o=`node${s}`;e.set(t,o),n.set(o,t)});const s={};for(const n of t){const t=e.get(n),o=this.constructorParams.nodeMap.get(n),i=ke(o);s[t]=Ei(i).toFixed(1)}const o=new Set,i=[];for(const n of t){const t=e.get(n),s=this.constructorParams.nodeEdgeMap.get(n)??[];for(const r of s){const s=r.nodeIds.find(t=>t!==n);if(this.sectionNodeIdSet.has(s)){const n=[t,e.get(s)].sort(),r=`${n[0]}-${n[1]}`;o.has(r)||(i.push(n),o.add(r))}}}i.sort((t,e)=>t[0]!==e[0]?t[0].localeCompare(e[0]):t[1].localeCompare(e[1]));const r={},a=new Map,c=new Map;for(const t of this.constructorParams.sectionConnectionTerminals){const n=e.get(t.startNodeId),s=e.get(t.endNodeId),[o,i]=[n,s].sort(),h=`${o}->${i}`,d=c.get(h)??0;c.set(h,d+1);const l=`${o}->${i}::${d}`;r[l]={start:o,end:i},a.set(l,t.connectionName)}const h=`capacitypathing:${Ti({node_capacity_map:s,node_edge_map:i,terminals:r})}`,d={cacheSpaceToRealConnectionId:a,cacheSpaceToRealNodeId:n};return this.cacheKey=h,this.cacheToSolveSpaceTransform=d,{cacheKey:h,cacheToSolveSpaceTransform:d}}applyCachedSolution(t){if(!this.cacheToSolveSpaceTransform)return console.error("Cache transform not available, cannot apply cached solution."),void(this.failed=!0);if(!t.success)return this.failed=!0,void(this.cacheHit=!0);this.cachedSectionConnectionTerminals=[];const{cacheSpaceToRealNodeId:e,cacheSpaceToRealConnectionId:n}=this.cacheToSolveSpaceTransform;for(const[s,o]of Object.entries(t.solutionPaths)){const t=n.get(s);if(!t){console.warn(`Could not find real connection name for ${s}`);continue}const i=this.constructorParams.sectionConnectionTerminals.find(e=>e.connectionName===t);if(!i){console.warn(`Could not find original terminal for connection name ${t}`);continue}const r=o.map(n=>{const s=e.get(n);if(!s)throw new Error(`Could not map cache node ID ${n} to real node ID for connection ${t}`);const o=this.constructorParams.nodeMap.get(s);if(!o)throw new Error(`Could not find node with ID ${s} in nodeMap for connection ${t}`);return o});this.cachedSectionConnectionTerminals.push({...i,path:r})}this.sectionScore=t.sectionScore,this.solved=!0,this.cacheHit=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(!this.cacheKey)return void console.error("Cannot save to cache without cache key.");if(!this.cacheToSolveSpaceTransform)return void console.error("Cache transform not available, cannot save solution to cache.");let t;if(this.failed)t={success:!1};else{if(!this.solved)return;{const e={},{cacheSpaceToRealNodeId:n,cacheSpaceToRealConnectionId:s}=this.cacheToSolveSpaceTransform,o=new Map;for(const[t,e]of n)o.set(e,t);const i=new Map;for(const[t,e]of s)i.set(e,t);const r=[];if(super.sectionConnectionTerminals)for(const t of super.sectionConnectionTerminals)if(t.path&&t.path.length>0){const e=t.path.map(t=>t.capacityMeshNodeId);r.push([t.connectionName,e])}for(const[t,n]of r){const s=i.get(t);if(!s){console.warn(`Could not find cache space connection ID for ${t} when saving to cache.`);continue}const r=n.map(e=>{const n=o.get(e);if(!n)throw new Error(`Could not map real node ID ${e} to cache node ID for connection ${t} when saving to cache.`);return n});e[s]=r}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 Ni({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"})}},wi=class extends y{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=No(this.edges),this.colorMap=t.colorMap??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=No(this.edges),this.initialSolver=t.initialPathingSolver||new xi({simpleRouteJson:this.simpleRouteJson,nodes:this.nodes,edges:this.edges,colorMap:this.colorMap}),this.activeSubSolver=this.initialSolver;for(const t of this.nodes){const e=this.initialSolver.getTotalCapacity(t);this.totalNodeCapacityMap.set(t.capacityMeshNodeId,e)}this.allNodeIdsSet=new Set(this.nodes.map(t=>t.capacityMeshNodeId))}_stepInitialization(){if(this.initialSolver?.step(),this.initialSolver?.failed)return this.failed=!0,void(this.error=this.initialSolver.error);if(this.initialSolver?.solved){this.usedNodeCapacityMap=new Map(this.initialSolver.usedNodeCapacityMap);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,s),this.nodeOptimizationAttemptCountMap.set(t.capacityMeshNodeId,0)}this.connectionsWithNodes=this.initialSolver.connectionsWithNodes,this.stats.startingScore=Mi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet}),this.stage="section-optimization"}}_getNextNodeToOptimize(){let t=0,e=0,n=null;for(const s of this.nodes){if(s._containsTarget)continue;const o=this.nodeOptimizationAttemptCountMap.get(s.capacityMeshNodeId),i=this.totalNodeCapacityMap.get(s.capacityMeshNodeId),r=Pi({usedCapacity:this.usedNodeCapacityMap.get(s.capacityMeshNodeId)??0,totalCapacity:i,layerCount:s.availableZ.length}),a=r/(o+1);o<this.currentSchedule.MAX_ATTEMPTS_PER_NODE&&a>t&&r>this.currentSchedule.MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE&&(t=a,e=r,n=s.capacityMeshNodeId)}return n}getOverallScore(){let t=0;for(const e of this.nodes){if(e._containsTarget)continue;const n=this.totalNodeCapacityMap.get(e.capacityMeshNodeId),s=Pi({usedCapacity:this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,totalCapacity:n,layerCount:e.availableZ.length});s>t&&(t=s)}return{highestNodePf:t,score:Mi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet})}}_stepSectionOptimization(){if(!this.sectionSolver){const t=this._getNextNodeToOptimize();if(!t){const{highestNodePf:t,score:e}=this.getOverallScore();return this.stats.scheduleScores[this.currentScheduleIndex].endingHighestNodePf=t,this.stats.scheduleScores[this.currentScheduleIndex].endingScore=e,this.currentScheduleIndex++,void(this.currentSchedule||(this.solved=!0))}const e=(t=>{const{centerNodeId:e,connectionsWithNodes:n,nodeMap:s,edges:o,nodeEdgeMap:i,expansionDegrees:r}=t,a=new Set,c=[{nodeId:e,depth:0}];a.add(e);let h=0;for(;h<c.length;){const{nodeId:t,depth:e}=c[h++];if(e>=r)continue;const n=i.get(t)?.flatMap(e=>e.nodeIds.filter(e=>e!==t))??[];for(const t of n)a.has(t)||(a.add(t),c.push({nodeId:t,depth:e+1}))}const d=Array.from(a).map(t=>s.get(t)),l=o.filter(t=>{const[e,n]=t.nodeIds;return a.has(e)&&a.has(n)}),u=[];for(const t of n){if(!t.path)continue;let e=null,n=null;for(const n of t.path)if(a.has(n.capacityMeshNodeId)){e=n.capacityMeshNodeId;break}for(let e=t.path.length-1;e>=0;e--){const s=t.path[e];if(a.has(s.capacityMeshNodeId)){n=s.capacityMeshNodeId;break}}e&&n&&u.push({connectionName:t.connection.name,startNodeId:e,endNodeId:n})}return{sectionConnectionTerminals:u,sectionNodes:d,sectionEdges:l,centerNodeId:e}})({centerNodeId:t,connectionsWithNodes:this.connectionsWithNodes,nodeMap:this.nodeMap,edges:this.edges,expansionDegrees:this.currentSchedule.MAX_EXPANSION_DEGREES,nodeEdgeMap:this.nodeEdgeMap});this.stats.scheduleScores[this.currentScheduleIndex].sectionAttempts++,this.currentSection=e,this.sectionSolver=new Ri({sectionNodes:this.currentSection.sectionNodes,sectionEdges:this.currentSection.sectionEdges,sectionConnectionTerminals:this.currentSection.sectionConnectionTerminals,colorMap:this.colorMap,centerNodeId:this.currentSection.centerNodeId,nodeEdgeMap:this.nodeEdgeMap,hyperParameters:{EXPANSION_DEGREES:this.currentSchedule.MAX_EXPANSION_DEGREES},cacheProvider:this.cacheProvider}),this.activeSubSolver=this.sectionSolver,this.nodeOptimizationAttemptCountMap.set(t,(this.nodeOptimizationAttemptCountMap.get(t)??0)+1)}if(this.sectionSolver.step(),(this.sectionSolver.failed||this.sectionSolver.solved)&&(this.sectionSolver.cacheHit?this.stats.cacheHits++:this.stats.cacheMisses++),this.sectionSolver.failed)return console.warn(`Section solver failed for node ${this.currentSection.centerNodeId}. Error: ${this.sectionSolver.error}`),this.stats.failedSectionSolvers++,this.stats.failedOptimizations++,this.sectionSolver=null,void(this.activeSubSolver=null);if(this.sectionSolver.solved){const t=this.sectionSolver.sectionConnectionTerminals,e=this.sectionSolver.sectionNodes,n=this.sectionSolver.centerNodeId;if(this.sectionSolver=null,this.activeSubSolver=null,!t)return void console.warn(`Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`);const s=new Set(e.map(t=>t.capacityMeshNodeId)),o=Mi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:s}),i=new Map(this.usedNodeCapacityMap),r=t;for(const t of r){const e=this.connectionsWithNodes.find(e=>e.connection.name===t.connectionName);if(e?.path)for(const t of e.path)if(s.has(t.capacityMeshNodeId)){const e=i.get(t.capacityMeshNodeId)??0;i.set(t.capacityMeshNodeId,Math.max(0,e-1))}}for(const t of r)if(t.path)for(const e of t.path)s.has(e.capacityMeshNodeId)&&i.set(e.capacityMeshNodeId,(i.get(e.capacityMeshNodeId)??0)+1);Mi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:i,nodeMap:this.nodeMap,sectionNodeIds:s})>o?(this.stats.successfulOptimizations++,this._mergeSolvedSectionPaths({centerNodeId:n,sectionConnectionTerminals:t}),this._recalculateNodeCapacityUsage()):this.stats.failedOptimizations++}}_mergeSolvedSectionPaths({centerNodeId:t,sectionConnectionTerminals:e}){for(const n of e){if(!n.path){console.warn(`No path found for connection ${n.connectionName} in section ${t}`);continue}const e=this.connectionsWithNodes.find(t=>t.connection.name===n.connectionName);if(!e||!e.path){console.warn(`Original connection or path not found for ${n.connectionName} while merging section ${t}`);continue}const s=e.path,o=n.path,i=s.findIndex(t=>t.capacityMeshNodeId===n.startNodeId),r=s.findIndex(t=>t.capacityMeshNodeId===n.endNodeId);if(-1===i||-1===r){console.warn(`Could not find start/end nodes (${n.startNodeId}/${n.endNodeId}) in original path for ${n.connectionName}`);continue}const[a,c]=i<=r?[i,r]:[r,i],h=s.slice(0,a),d=s.slice(c+1);let l=o;if(o.length>0&&s[a]&&o[0].capacityMeshNodeId!==s[a].capacityMeshNodeId){if(o[o.length-1].capacityMeshNodeId!==s[a].capacityMeshNodeId){console.warn(`New section path for ${n.connectionName} doesn't align with original path boundaries. Skipping merge for this connection.`);continue}l=[...o].reverse()}e.path=[...h,...l,...d]}}_recalculateNodeCapacityUsage(){this.usedNodeCapacityMap.clear();for(const t of this.connectionsWithNodes)if(t.path)for(const e of t.path)this.usedNodeCapacityMap.set(e.capacityMeshNodeId,(this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0)+1);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,s)}}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const n=e.path;n&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:n.map(t=>t.capacityMeshNodeId)})}return t}_step(){this.iterations>=this.MAX_ITERATIONS-1?this.solved=!0:"initialization"===this.stage?this._stepInitialization():"section-optimization"===this.stage&&this._stepSectionOptimization()}visualize(){const t=this.connectionsWithNodes.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connection.name,path:t.path}));return Ni({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)"})}},Ai=class extends y{multiLayerNodes;strawNodes;skippedNodes;unprocessedNodes;strawSize;nodeIdCounter;constructor(t){super(),this.MAX_ITERATIONS=1e5,this.strawSize=t.strawSize??.5,this.multiLayerNodes=[],this.strawNodes=[],this.skippedNodes=[],this.nodeIdCounter=0,this.unprocessedNodes=[];for(const e of t.nodes)1===e.availableZ.length?this.unprocessedNodes.push(e):this.multiLayerNodes.push(e)}getCapacityOfMultiLayerNodesWithinBounds(t){let e=0;for(const n of this.multiLayerNodes){const s=n.center.x-n.width/2,o=n.center.x+n.width/2,i=n.center.y-n.height/2,r=n.center.y+n.height/2,a=Math.max(t.minX,s),c=Math.min(t.maxX,o),h=Math.max(t.minY,i),d=Math.min(t.maxY,r);if(a<c&&h<d){const t=(c-a)*(d-h)/(n.width*n.height);e+=ke(n)*t}}return e}getSurroundingCapacities(t){const e=Math.min(t.width,t.height);return{leftSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2-e,maxX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),rightSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x+t.width/2,maxX:t.center.x+t.width/2+e,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),topSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2-e,maxY:t.center.y-t.height/2}),bottomSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y+t.height/2,maxY:t.center.y+t.height/2+e})}}createStrawsForNode(t){const e=[],{leftSurroundingCapacity:n,rightSurroundingCapacity:s,topSurroundingCapacity:o,bottomSurroundingCapacity:i}=this.getSurroundingCapacities(t);if(1*(n+s)>o+i){const n=Math.floor(t.height/this.strawSize),s=t.height/n;for(let o=0;o<n;o++){const n=t.center.y-t.height/2+o*s+s/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${o}`,center:{x:t.center.x,y:n},width:t.width,height:s,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}else{const n=Math.floor(t.width/this.strawSize),s=t.width/n;for(let o=0;o<n;o++){const n=t.center.x-t.width/2+o*s+s/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${o}`,center:{x:n,y:t.center.y},width:s,height:t.height,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}return e}getResultNodes(){return[...this.multiLayerNodes,...this.strawNodes,...this.skippedNodes]}_step(){const t=this.unprocessedNodes.pop();if(!t)return void(this.solved=!0);if(t.width<this.strawSize&&t.height<this.strawSize)return void this.skippedNodes.push(t);if(t._containsTarget)return void this.skippedNodes.push(t);const e=this.createStrawsForNode(t);this.strawNodes.push(...e),0===e.length&&this.strawNodes.push(t)}visualize(){const t={rects:[],lines:[],points:[],circles:[],title:"Straw Solver"};for(const e of this.unprocessedNodes)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(200, 200, 200, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nUnprocessed\n${e.width}x${e.height}`});for(const e of this.strawNodes){const n=0===e.availableZ[0]?"rgba(0, 150, 255, 0.5)":"rgba(255, 100, 0, 0.5)";t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nLayer: ${e.availableZ[0]}\n${e.width}x${e.height}`,layer:`z${e.availableZ.join(",")}`})}for(const e of this.multiLayerNodes)t.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,fill:"rgba(100, 255, 100, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",layer:`z${e.availableZ.join(",")}`,label:`${e.capacityMeshNodeId}\nLayers: ${e.availableZ.join(",")}\n${e.width}x${e.height}`});return t}},Oi=class extends y{removedNodeIds;targetNodeIds;leaves;leavesIndex;adjacencyList;nodeMap;nodes;edges;constructor({nodes:t,edges:e}){super(),this.MAX_ITERATIONS=t.length,this.nodes=t,this.edges=e,this.removedNodeIds=new Set,this.targetNodeIds=new Set(t.filter(t=>t._containsTarget).map(t=>t.capacityMeshNodeId)),this.adjacencyList=new Map(t.map(({capacityMeshNodeId:t})=>[t,new Set]));for(const{nodeIds:[t,n]}of e)this.adjacencyList.get(t).add(n),this.adjacencyList.get(n).add(t);this.leavesIndex=0,this.leaves=[...this.adjacencyList.entries()].filter(([t,e])=>1===e.size).filter(([t,e])=>!this.targetNodeIds.has(t)).map(([t,e])=>t)}_step(){if(this.leavesIndex===this.leaves.length)return void(this.solved=!0);const t=this.leaves[this.leavesIndex],e=this.adjacencyList.get(t);if(!e||0===e.size)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));const[n]=e,s=n?this.adjacencyList.get(n):void 0;if(!n||!s)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));s.delete(t),this.removedNodeIds.add(t),this.adjacencyList.delete(t),1!==s.size||this.targetNodeIds.has(n)||this.leaves.push(n),this.leavesIndex+=1,this.leavesIndex===this.leaves.length&&(this.solved=!0)}visualize(){if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}const t=new Map;for(const e of this.edges)for(const n of e.nodeIds)t.set(n,1+(t.get(n)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const n=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+n*e.width*.05,y:e.center.y-n*e.width*.05},fill:e._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};for(const t of this.edges){const n=this.nodeMap.get(t.nodeIds[0]),s=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&s?.center){const o=Math.min(...n.availableZ),i=Math.min(...s.availableZ),r={x:n.center.x+o*n.width*.05,y:n.center.y-o*n.width*.05},a={x:s.center.x+i*s.width*.05,y:s.center.y-i*s.width*.05},c=Array.from(new Set([...n.availableZ,...s.availableZ])).sort();e.lines.push({layer:`z${c.join(",")}`,points:[r,a],strokeDash:n.availableZ.join(",")===s.availableZ.join(",")?void 0:"10 5",strokeColor:t.nodeIds.some(t=>this.removedNodeIds.has(t))?it("black",.9):void 0})}}return e}};function zi(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Di=class extends y{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,o=Math.max(n,s),i=e.targetMinCapacity??.5;e.capacityDepth=Be(o,i)}this.connMap=$e(t),this.colorMap=ot(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;initialPathingSolver;pathingOptimizer;edgeToPortSegmentSolver;colorMap;segmentToPointSolver;unravelMultiSectionSolver;segmentToPointOptimizer;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;viaDiameter;minTraceWidth;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[zi("netToPointPairsSolver",gn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ot(t.srjWithPointPairs,this.connMap),t.connMap=$e(t.srjWithPointPairs)}}),zi("nodeSolver",Js,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),zi("strawSolver",Ai,t=>[{nodes:t.capacityNodes}],{onSolved:t=>{t.capacityNodes=t.strawSolver?.getResultNodes()}}),zi("edgeSolver",cn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),zi("deadEndSolver",Oi,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges}],{onSolved:t=>{const e=t.deadEndSolver?.removedNodeIds;t.capacityNodes=t.capacityNodes.filter(t=>!e.has(t.capacityMeshNodeId)),t.capacityEdges=t.capacityEdges.filter(t=>t.nodeIds.every(t=>!e.has(t)))}}),zi("initialPathingSolver",xi,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),zi("pathingOptimizer",wi,t=>[{initialPathingSolver:t.initialPathingSolver,simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,cacheProvider:t.cacheProvider,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),zi("edgeToPortSegmentSolver",qo,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.pathingOptimizer?.getCapacityPaths()||[],colorMap:t.colorMap}]),zi("segmentToPointSolver",ni,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),zi("unravelMultiSectionSolver",mi,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),zi("highDensityRouteSolver",Le,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),zi("highDensityStitchSolver",nn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),zi("traceSimplificationSolver",Mo,t=>[{hdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline,defaultViaDiameter:t.viaDiameter,layerCount:t.srj.layerCount,iterations:2}])];getConstructorParams(){return[this.srj,this.opts]}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 t=this.netToPointPairsSolver?.visualize(),e=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),s=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),i=this.edgeSolver?.visualize(),r=this.deadEndSolver?.visualize(),a=this.initialPathingSolver?.visualize(),c=this.pathingOptimizer?.visualize(),h=this.edgeToPortSegmentSolver?.visualize(),d=this.segmentToPointSolver?.visualize(),l=this.unravelMultiSectionSolver?.visualize()??this.segmentToPointOptimizer?.visualize(),u=this.highDensityRouteSolver?.visualize(),p=this.highDensityStitchSolver?.visualize(),m=this.traceSimplificationSolver?.visualize(),f=this.srj.outline,y=[];if(y.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),f&&f.length>=2){const t=f.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),y.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const x={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:t.layers?.join(", ")}))],lines:y},v=[x,t,e,n,s,o,i,r,a,c,h,d,l,u?g(x,u):null,p,m,this.solved?g(x,sn(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...v)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.connectionName]}),t.length>200)break}return{lines:t}}if(this.pathingOptimizer){const t=[];for(const e of this.pathingOptimizer.connectionsWithNodes)e.path&&t.push({points:e.path.map(t=>({x:t.center.x,y:t.center.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,o=e.filter(t=>t.connectionName===n.name);for(let e=0;e<o.length;e++){const i=o[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:We(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Li=.1,Fi=.1;function Xi(t,e,n,s,o,i){return(o-t)*(s-e)-(i-e)*(n-t)}function Yi(t,e,n,s,o,i){return Math.min(t,n)<=o&&o<=Math.max(t,n)&&Math.min(e,s)<=i&&i<=Math.max(e,s)}function $i(t,e,n,s,o,i,r,a){const c=Xi(o,i,r,a,t,e),h=Xi(o,i,r,a,n,s),d=Xi(t,e,n,s,o,i),l=Xi(t,e,n,s,r,a);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)||(!(0!==c||!Yi(o,i,r,a,t,e))||(!(0!==h||!Yi(o,i,r,a,n,s))||(!(0!==d||!Yi(t,e,n,s,o,i))||!(0!==l||!Yi(t,e,n,s,r,a)))))}function ki(t,e,n,s,o,i){const r=o-n,a=i-s,c=t-n,h=e-s,d=r*r+a*a;if(0===d){return{x:n,y:s,distSq:c*c+h*h}}let l=(c*r+h*a)/d;l=Math.max(0,Math.min(1,l));const u=n+l*r,p=s+l*a,m=t-u,f=e-p;return{x:u,y:p,distSq:m*m+f*f}}var Bi=class extends y{unsolvedNodes;allNodes;routes;colorMap;traceWidth;viaDiameter;numMovablePoints;currentNode=null;lastNode=null;currentNodeStep=0;routesInProgress=[];pushMargin;currentNodeBounds=null;constructor({nodePortPoints:t,colorMap:e,traceWidth:n=.1,viaDiameter:s=.6,pushMargin:o=.3,numMovablePoints:i=2}){if(super(),i<1||i>3)throw new Error(`numMovablePoints must be 1, 2, or 3, got ${i}`);this.allNodes=[...t],this.unsolvedNodes=[...t],this.colorMap=e??{},this.routes=[],this.traceWidth=n,this.viaDiameter=s,this.numMovablePoints=i,this.pushMargin=o,this.MAX_ITERATIONS=10*t.length+1}_step(){if(null===this.currentNode){if(0===this.unsolvedNodes.length)return void(this.solved=!0);this.lastNode=this.currentNode,this.currentNode=this.unsolvedNodes.pop(),this.currentNodeStep=0,this.routesInProgress=[],this._initializeRoutesForCurrentNode()}this.currentNodeStep>0&&this._runForceDirectedStep(),this.currentNodeStep++,this.currentNodeStep>=10&&(this._finalizeRoutesForCurrentNode(),this.lastNode=this.currentNode,this.currentNode=null)}_initializeRoutesForCurrentNode(){const t=this.currentNode,e=t.center.x-t.width/2,n=t.center.x+t.width/2,s=t.center.y-t.height/2,o=t.center.y+t.height/2;this.currentNodeBounds={minX:e,maxX:n,minY:s,maxY:o};const i=new Map;for(const e of t.portPoints)i.has(e.connectionName)||i.set(e.connectionName,[]),i.get(e.connectionName).push({x:e.x,y:e.y,z:e.z,rootConnectionName:e.rootConnectionName});for(const[t,e]of i){if(e.length<2)continue;const n=e[0],s=e[e.length-1],o=n.z,i=s.x-n.x,r=s.y-n.y,a=Math.sqrt(i*i+r*r),c=a>0?i/a:0,h=a>0?r/a:0,d=[];this.numMovablePoints>=1&&d.push({x:n.x+c*Fi,y:n.y+h*Fi,z:o,rootConnectionName:n.rootConnectionName,connectionName:t}),this.numMovablePoints>=2&&d.push({x:s.x-c*Fi,y:s.y-h*Fi,z:o,rootConnectionName:n.rootConnectionName,connectionName:t}),this.numMovablePoints>=3&&d.push({x:n.x+i/2,y:n.y+r/2,z:o,rootConnectionName:n.rootConnectionName,connectionName:t}),this.routesInProgress.push({connectionName:t,rootConnectionName:n.rootConnectionName,startPoint:{x:n.x,y:n.y,z:o},endPoint:{x:s.x,y:s.y,z:o},movablePoints:d})}}_runForceDirectedStep(){const t=this.currentNodeBounds,e=[];for(const t of this.routesInProgress)e.push(...t.movablePoints);const n=new Map;for(const t of e)n.set(t,{fx:0,fy:0});const s=.3+this.pushMargin,o=new Map;for(const t of this.routesInProgress){const e=[{x:t.startPoint.x,y:t.startPoint.y,movablePoint:null}];1===t.movablePoints.length?e.push({x:t.movablePoints[0].x,y:t.movablePoints[0].y,movablePoint:t.movablePoints[0]}):2===t.movablePoints.length?(e.push({x:t.movablePoints[0].x,y:t.movablePoints[0].y,movablePoint:t.movablePoints[0]}),e.push({x:t.movablePoints[1].x,y:t.movablePoints[1].y,movablePoint:t.movablePoints[1]})):3===t.movablePoints.length&&(e.push({x:t.movablePoints[0].x,y:t.movablePoints[0].y,movablePoint:t.movablePoints[0]}),e.push({x:t.movablePoints[2].x,y:t.movablePoints[2].y,movablePoint:t.movablePoints[2]}),e.push({x:t.movablePoints[1].x,y:t.movablePoints[1].y,movablePoint:t.movablePoints[1]})),e.push({x:t.endPoint.x,y:t.endPoint.y,movablePoint:null}),o.set(t,e)}for(const i of e){const e=n.get(i),r=i.x-t.minX,a=t.maxX-i.x,c=t.maxY-i.y,h=i.y-t.minY;r<s&&(e.fx+=Li*(s-r)),a<s&&(e.fx-=Li*(s-a)),h<s&&(e.fy+=Li*(s-h)),c<s&&(e.fy-=Li*(s-c));for(const t of this.routesInProgress){if(t.rootConnectionName===i.rootConnectionName)continue;const r=o.get(t);for(let t=0;t<r.length-1;t++){const o=r[t],a=r[t+1],c=ki(i.x,i.y,o.x,o.y,a.x,a.y),h=Math.sqrt(c.distSq);if(h>0&&h<2*s){const t=i.x-c.x,s=i.y-c.y,r=.002/c.distSq,h=r*t,d=r*s;e.fx+=h,e.fy+=d;const l=o.movablePoint,u=a.movablePoint;if(l&&u){const t=n.get(l),e=n.get(u);t.fx-=h/2,t.fy-=d/2,e.fx-=h/2,e.fy-=d/2}else if(l){const t=n.get(l);t.fx-=h,t.fy-=d}else if(u){const t=n.get(u);t.fx-=h,t.fy-=d}}}}}const i=t=>t.movablePoint?{x:t.movablePoint.x,y:t.movablePoint.y}:{x:t.x,y:t.y},r=t=>{let e=null;for(const n of this.routesInProgress)if(n.movablePoints.includes(t)){e=n;break}if(!e)return!1;const n=o.get(e);let s=-1;for(let e=0;e<n.length;e++)if(n[e].movablePoint===t){s=e;break}if(-1===s)return!1;const r=[];if(s>0){const e=i(n[s-1]);r.push({ax:e.x,ay:e.y,bx:t.x,by:t.y})}if(s<n.length-1){const e=i(n[s+1]);r.push({ax:t.x,ay:t.y,bx:e.x,by:e.y})}for(const t of this.routesInProgress){if(t.rootConnectionName===e.rootConnectionName)continue;const n=o.get(t);for(let t=0;t<n.length-1;t++){const e=i(n[t]),s=i(n[t+1]);for(const t of r)if($i(t.ax,t.ay,t.bx,t.by,e.x,e.y,s.x,s.y))return!0}}return!1};for(const s of e){const e=n.get(s);s.forceX=e.fx,s.forceY=e.fy;const o=s.x,i=s.y;s.x+=e.fx,s.y+=e.fy,s.x=Math.max(t.minX,Math.min(t.maxX,s.x)),s.y=Math.max(t.minY,Math.min(t.maxY,s.y)),r(s)&&(s.x=o,s.y=i)}}_finalizeRoutesForCurrentNode(){for(const t of this.routesInProgress){const{connectionName:e,rootConnectionName:n,startPoint:s,endPoint:o,movablePoints:i}=t,r=[{x:s.x,y:s.y,z:s.z}];1===i.length?r.push({x:i[0].x,y:i[0].y,z:i[0].z}):2===i.length?(r.push({x:i[0].x,y:i[0].y,z:i[0].z}),r.push({x:i[1].x,y:i[1].y,z:i[1].z})):3===i.length&&(r.push({x:i[0].x,y:i[0].y,z:i[0].z}),r.push({x:i[2].x,y:i[2].y,z:i[2].z}),r.push({x:i[1].x,y:i[1].y,z:i[1].z})),r.push({x:o.x,y:o.y,z:o.z});const a={connectionName:e,rootConnectionName:n,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:r,vias:[]};this.routes.push(a)}this.routesInProgress=[]}_getNodeBounds(t){return{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}}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.unsolvedNodes){if(e===this.currentNode)continue;const n=this._getNodeBounds(e);t.rects.push({center:{x:(n.minX+n.maxX)/2,y:(n.minY+n.maxY)/2},width:n.maxX-n.minX,height:n.maxY-n.minY,fill:"rgba(0, 0, 0, 0.08)",stroke:"rgba(0, 0, 0, 0.2)",label:e.capacityMeshNodeId})}if(this.lastNode){const e=this._getNodeBounds(this.lastNode);t.rects.push({center:{x:(e.minX+e.maxX)/2,y:(e.minY+e.maxY)/2},width:e.maxX-e.minX,height:e.maxY-e.minY,fill:"rgba(0, 200, 0, 0.15)",stroke:"rgba(0, 0, 255, 0.6)"})}if(this.currentNode){const e=this._getNodeBounds(this.currentNode);t.rects.push({center:{x:(e.minX+e.maxX)/2,y:(e.minY+e.maxY)/2},width:e.maxX-e.minX,height:e.maxY-e.minY,fill:"rgba(0, 200, 0, 0.15)",stroke:"rgba(0, 200, 0, 0.6)"})}for(const e of this.unsolvedNodes){const n=new Map;for(const t of e.portPoints)n.has(t.connectionName)||n.set(t.connectionName,[]),n.get(t.connectionName).push({x:t.x,y:t.y});for(const[e,s]of n)s.length<2||t.lines.push({points:s.map(t=>({x:t.x,y:t.y})),label:e,strokeColor:"gray",strokeWidth:this.traceWidth})}for(const e of this.routes){const n=De(e.route,e.connectionName,this.colorMap[e.connectionName]);for(const s of n)t.lines.push({points:s.points,label:s.connectionName,strokeColor:0===s.z?s.color:it(s.color,.75),layer:`z${s.z}`,strokeWidth:e.traceThickness,strokeDash:0!==s.z?"10, 5":void 0});const s=e.route;for(let e=0;e<s.length;e++){const n=s[e],o=0===e,i=e===s.length-1,r=!o&&!i;let a;a=o?"start":i?"end":`M${e}`,t.points.push({x:n.x,y:n.y,label:a,color:r?"orange":"blue"})}}for(const e of this.routesInProgress){const{startPoint:n,endPoint:s,movablePoints:o,connectionName:i}=e,r=this.colorMap[i]??"gray",a=[{x:n.x,y:n.y}];1===o.length?a.push({x:o[0].x,y:o[0].y}):2===o.length?(a.push({x:o[0].x,y:o[0].y}),a.push({x:o[1].x,y:o[1].y})):3===o.length&&(a.push({x:o[0].x,y:o[0].y}),a.push({x:o[2].x,y:o[2].y}),a.push({x:o[1].x,y:o[1].y})),a.push({x:s.x,y:s.y}),t.lines.push({points:a,label:i,strokeColor:r,strokeWidth:this.traceWidth}),t.points.push({x:n.x,y:n.y,label:"start",color:"blue"});for(let e=0;e<o.length;e++){const n=o[e];if(t.points.push({x:n.x,y:n.y,label:`M${e+1}`,color:"orange"}),void 0!==n.forceX&&void 0!==n.forceY){if(Math.sqrt(n.forceX*n.forceX+n.forceY*n.forceY)>.001){const s=5;t.lines.push({points:[{x:n.x,y:n.y},{x:n.x+n.forceX*s,y:n.y+n.forceY*s}],strokeColor:"red",strokeWidth:.02,label:`F${e+1}`});const o=.05,i=n.x+n.forceX*s,r=n.y+n.forceY*s,a=Math.atan2(n.forceY,n.forceX);t.lines.push({points:[{x:i,y:r},{x:i-o*Math.cos(a-Math.PI/6),y:r-o*Math.sin(a-Math.PI/6)}],strokeColor:"red",strokeWidth:.02}),t.lines.push({points:[{x:i,y:r},{x:i-o*Math.cos(a+Math.PI/6),y:r-o*Math.sin(a+Math.PI/6)}],strokeColor:"purple",strokeWidth:.02})}}}t.points.push({x:s.x,y:s.y,label:"end",color:"blue"})}return t}};function ji(t){const{pos:e,segments:n,dir:s,keepoutRadius:o}=t;let i=1/0;const r=o/4,a={x:e.x-s.x*r,y:e.y-s.y*r},c={x:e.x+s.x*r,y:e.y+s.y*r};for(const t of n){const e=wt(a,c,t.start,t.end);i=Math.min(i,e)}return i}function Wi(t,e,n,s){const o=Hi(n,s,t),i=Hi(n,s,e),r=Hi(t,e,n),a=Hi(t,e,s);if((o>0&&i<0||o<0&&i>0)&&(r>0&&a<0||r<0&&a>0))return!0;const c=1e-4;return!!(Math.abs(o)<c&&Ui(n,s,t))||(!!(Math.abs(i)<c&&Ui(n,s,e))||(!!(Math.abs(r)<c&&Ui(t,e,n))||!!(Math.abs(a)<c&&Ui(t,e,s))))}function Hi(t,e,n){return(n.x-t.x)*(e.y-t.y)-(e.x-t.x)*(n.y-t.y)}function Ui(t,e,n){return n.x>=Math.min(t.x,e.x)-1e-4&&n.x<=Math.max(t.x,e.x)+1e-4&&n.y>=Math.min(t.y,e.y)-1e-4&&n.y<=Math.max(t.y,e.y)+1e-4}function Vi(t,e,n){for(const s of n)if(Wi(t,e,s.start,s.end))return!1;return!0}var Zi=1e-4;function Gi(t){const e=t.width/2,n=t.height/2,s=t.center.x,o=t.center.y,i={x:s-e,y:o+n},r={x:s+e,y:o+n},a={x:s-e,y:o-n},c={x:s+e,y:o-n};return[{start:i,end:r},{start:r,end:c},{start:c,end:a},{start:a,end:i}]}function Ji(t,e,n=.1){const s=e.x-t.x,o=e.y-t.y,i=Math.sqrt(s*s+o*o);if(0===i)return[];const r=-(o/i),a=s/i,c=n/2;return[{start:{x:t.x+r*c,y:t.y+a*c},end:{x:e.x+r*c,y:e.y+a*c}},{start:{x:t.x-r*c,y:t.y-a*c},end:{x:e.x-r*c,y:e.y-a*c}}]}function qi(t,e,n){const s=Math.hypot(t.start.x-e.x,t.start.y-e.y),o=Math.hypot(t.end.x-e.x,t.end.y-e.y);if(s<=n||o<=n)return!0;const i=t.end.x-t.start.x,r=t.end.y-t.start.y,a=i*i+r*r;if(0===a)return!1;const c=Math.max(0,Math.min(1,((e.x-t.start.x)*i+(e.y-t.start.y)*r)/a)),h=t.start.x+c*i,d=t.start.y+c*r;return Math.hypot(h-e.x,d-e.y)<=n}function Ki(t,e,n){if(!n||0===n.length)return!1;for(const s of n){const n=Math.abs(t.x-s.start.x)<Zi&&Math.abs(t.y-s.start.y)<Zi&&Math.abs(e.x-s.end.x)<Zi&&Math.abs(e.y-s.end.y)<Zi,o=Math.abs(t.x-s.end.x)<Zi&&Math.abs(t.y-s.end.y)<Zi&&Math.abs(e.x-s.start.x)<Zi&&Math.abs(e.y-s.start.y)<Zi;if(n||o)return!0}return!1}function Qi(t,e,n,s,o){const i=[];for(let r=0;r<t.length-1;r++){const a=t[r],c=t[r+1];Ki(a,c,o)||qi({start:a,end:c},n,s+e)&&i.push(...Ji(a,c,e))}return i}var tr=1e-4;function er(t,e,n,s){const o=e.x-t.x,i=e.y-t.y,r=s.x-n.x,a=s.y-n.y,c=o*a-i*r;if(Math.abs(c)<1e-10)return null;const h=n.x-t.x,d=n.y-t.y,l=(h*a-d*r)/c,u=(h*i-d*o)/c,p=1e-6;return l>p&&l<.999999&&u>p&&u<.999999?{x:t.x+l*o,y:t.y+l*i}:null}function nr(t,e){if(!e||0===e.length)return!1;for(const n of e)if(Math.abs(t.x-n.start.x)<tr&&Math.abs(t.y-n.start.y)<tr||Math.abs(t.x-n.end.x)<tr&&Math.abs(t.y-n.end.y)<tr)return!0;return!1}function sr(t,e,n,s){if(!s||0===s.length)return!1;for(let o=e;o<=n;o++)if(o>=0&&o<t.length&&nr(t[o],s))return!0;return!1}var or=1e-4,ir=class extends y{constructor(t){super(),this.input=t,this.MAX_ITERATIONS=1e6,this.originalHdRoutes=[...t.hdRoutes],this.hdRoutes=t.hdRoutes,this.KEEPOUT_RADIUS_SCHEDULE=t.keepoutRadiusSchedule??[.3,.5,.5],this.currentKeepoutRadius=this.KEEPOUT_RADIUS_SCHEDULE[0]??.15,this.unprocessedRoutes=[...this.hdRoutes],this.smoothedCursorRoutes=[...this.unprocessedRoutes];const e=[...t.obstacles,...this.getJumperPadObstacles()];this.obstacleSHI=new Qs("flatbush",e),this.boardOutlineRoutes=this.createBoardOutlineRoutes(),this.hdRouteSHI=new io([...this.hdRoutes,...this.boardOutlineRoutes]);for(const[t,e,n]of this.hdRoutes.flatMap(t=>[[t.route[0],t.connectionName,t.rootConnectionName],[t.route[t.route.length-1],t.connectionName,t.rootConnectionName]])){const s=this.obstacleSHI.searchArea(t.x,t.y,.01,.01).filter(e=>e.zLayers?.includes(t.z));if(0===s.length)continue;const o=s[0];this.input.connMap.addConnections([[e,n,...o.offBoardConnectsTo??[],o.obstacleId,...o.connectedTo].filter(Boolean)])}}originalHdRoutes;hdRoutes;redrawnHdRoutes=[];KEEPOUT_RADIUS_SCHEDULE;currentScheduleIndex=0;currentKeepoutRadius;unprocessedRoutes=[];smoothedCursorRoutes=[];processedRoutes=[];currentTrace=null;cursorPosition=null;lastCursorPosition=null;drawPosition=null;currentTraceSegmentIndex=0;currentTraceSegmentT=0;recordedDrawPositions=[];lastCollidingSegments=[];currentTraceJumperSegments=new Map;obstacleSHI;hdRouteSHI;boardOutlineRoutes=[];getSmoothDistance(){return this.currentKeepoutRadius}getJumperPadObstacles(){const t=[];if(!this.input.jumpers)return t;for(const e of this.input.jumpers)for(const n of e.pads)t.push({...n,zLayers:[0]});return t}buildJumperSegmentMap(t){const e=new Map;if(!t.jumpers||0===t.jumpers.length)return e;const n=t.route;for(const s of t.jumpers){let t=-1,o=1/0;for(let e=0;e<n.length-1;e++){const i=n[e],r=n[e+1],a=Math.sqrt((i.x-s.start.x)**2+(i.y-s.start.y)**2),c=Math.sqrt((r.x-s.end.x)**2+(r.y-s.end.y)**2),h=a+c,d=Math.sqrt((i.x-s.end.x)**2+(i.y-s.end.y)**2),l=Math.sqrt((r.x-s.start.x)**2+(r.y-s.start.y)**2),u=d+l,p=Math.min(h,u);(h<=u?a:d)<1&&(h<=u?c:l)<1&&p<o&&(o=p,t=e)}t>=0&&e.set(t,s)}return e}_step(){if(!this.currentTrace){const t=this.unprocessedRoutes.shift();if(!t)return this.currentScheduleIndex++,this.currentScheduleIndex<this.KEEPOUT_RADIUS_SCHEDULE.length?(this.currentKeepoutRadius=this.KEEPOUT_RADIUS_SCHEDULE[this.currentScheduleIndex],this.unprocessedRoutes=kt([...this.processedRoutes],this.currentScheduleIndex),this.smoothedCursorRoutes=[...this.unprocessedRoutes],this.processedRoutes=[],void(this.hdRouteSHI=new io([...this.unprocessedRoutes,...this.boardOutlineRoutes]))):(this.redrawnHdRoutes=this.processedRoutes,void(this.solved=!0));if(this.currentTrace=t,this.currentTrace.route.length<2)return this.processedRoutes.push(this.currentTrace),void(this.currentTrace=null);this.currentTraceJumperSegments=this.buildJumperSegmentMap(this.currentTrace);const e=this.currentTrace.route[0];return this.cursorPosition={...e},this.lastCursorPosition={...e},this.drawPosition={x:e.x,y:e.y},this.currentTraceSegmentIndex=0,this.currentTraceSegmentT=0,void(this.recordedDrawPositions=[{...e}])}this.lastCursorPosition={...this.cursorPosition};const t=this.stepCursorForward();if("end"===t)return void this.finalizeCurrentTrace();if("jumper"===t)return void(this.drawPosition={x:this.cursorPosition.x,y:this.cursorPosition.y});const e=this.getCollidingSegments(this.cursorPosition);this.lastCollidingSegments=e;const n=function(t){const{cursorPosition:e,lastCursorPosition:n,collidingSegments:s,keepoutRadius:o}=t;if(0===s.length)return null;const i=1e-4,r=e.x-n.x,a=e.y-n.y,c=Math.sqrt(r*r+a*a),h=c>i?{x:r/c,y:a/c}:{x:1,y:0},d=-h.y,l=h.x,u=ji({pos:e,segments:s,dir:h,keepoutRadius:o});if(u>=o)return null;for(let t=1;t<=20;t++){const n=t/20*o,i={x:e.x+d*n,y:e.y+l*n},r=ji({pos:i,segments:s,dir:h,keepoutRadius:o}),a={x:e.x-d*n,y:e.y-l*n},c=ji({pos:a,segments:s,dir:h,keepoutRadius:o}),u=r>=o&&Vi(e,i,s),p=c>=o&&Vi(e,a,s);if(u&&p)return r>=c?i:a;if(u)return i;if(p)return a}const p=o,m=[];for(let t=-60;t<=60;t++){const n=t/60*p,i={x:e.x+d*n,y:e.y+l*n},r=ji({pos:i,segments:s,dir:h,keepoutRadius:o}),a=Vi(e,i,s);m.push({pos:i,clearance:r,dist:Math.abs(n),pathClear:a,index:t})}const f=m.filter(t=>t.pathClear),g=m.findIndex(t=>0===t.index),y=g>=0?g:Math.floor(m.length/2);let x=null;for(let t=y+1;t<m.length-1;t++){const e=m[t-1],n=m[t],s=m[t+1];if(n.clearance>=e.clearance&&n.clearance>=s.clearance){x=n;break}}let v=null;for(let t=y-1;t>0;t--){const e=m[t-1],n=m[t],s=m[t+1];if(n.clearance>=e.clearance&&n.clearance>=s.clearance){v=n;break}}let S=null,P=null;if(f.length>0){const t=f.findIndex(t=>0===t.index),e=t>=0?t:Math.floor(f.length/2);for(let t=e+1;t<f.length-1;t++){const e=f[t-1],n=f[t],s=f[t+1];if(n.clearance>=e.clearance&&n.clearance>=s.clearance){S=n;break}}for(let t=e-1;t>0;t--){const e=f[t-1],n=f[t],s=f[t+1];if(n.clearance>=e.clearance&&n.clearance>=s.clearance){P=n;break}}}const b=[x,v,S,P,m.find(t=>0===t.index)].filter(t=>null!=t),M=new Set,N=b.filter(t=>{const e=`${t.pos.x.toFixed(6)},${t.pos.y.toFixed(6)}`;return!M.has(e)&&(M.add(e),!0)});if(0===N.length){let t=m[0];if(!t)return null;for(const e of m)e.clearance>t.clearance&&(t=e);return Math.sqrt((t.pos.x-e.x)**2+(t.pos.y-e.y)**2)>i?t.pos:null}let I;if(u<.15*o){I=N[0];for(const t of N)t.clearance>I.clearance&&(I=t)}else{const t=N.filter(t=>t.pathClear),e=t.length>0?t:N;I=e[0];for(const t of e)t.clearance>I.clearance&&(I=t)}return Math.sqrt((I.pos.x-e.x)**2+(I.pos.y-e.y)**2)>i?I.pos:null}({cursorPosition:this.cursorPosition,lastCursorPosition:this.lastCursorPosition,collidingSegments:e,keepoutRadius:this.currentKeepoutRadius});this.drawPosition=n??{...this.cursorPosition};const s=this.recordedDrawPositions[this.recordedDrawPositions.length-1];if(s&&this.drawPosition){const t={x:s.x,y:s.y,z:s.z},e={x:this.drawPosition.x,y:this.drawPosition.y,z:this.cursorPosition.z};this.segmentIntersectsOtherRoutes(t,e)&&(this.drawPosition={...this.cursorPosition})}this.recordedDrawPositions.push({x:this.drawPosition.x,y:this.drawPosition.y,z:this.cursorPosition.z})}getStepDistance(){return this.currentKeepoutRadius/2}getJumperAtCurrentSegmentStart(){return this.currentTraceSegmentT>or?null:this.currentTraceJumperSegments.get(this.currentTraceSegmentIndex)??null}stepCursorForward(){if(!this.currentTrace||!this.cursorPosition)return"end";const t=this.currentTrace.route;let e=this.getStepDistance();for(;e>0;){if(this.currentTraceSegmentIndex>=t.length-1)return"end";const n=this.getJumperAtCurrentSegmentStart();if(n){const e=t[this.currentTraceSegmentIndex],s=t[this.currentTraceSegmentIndex+1],o=Math.sqrt((e.x-n.start.x)**2+(e.y-n.start.y)**2),i=Math.sqrt((e.x-n.end.x)**2+(e.y-n.end.y)**2),r=o<=i?n.start:n.end,a=o<=i?n.end:n.start;return this.recordedDrawPositions.push({x:r.x,y:r.y,z:e.z,insideJumperPad:!0}),this.recordedDrawPositions.push({x:a.x,y:a.y,z:s.z,insideJumperPad:!0}),this.cursorPosition={x:a.x,y:a.y,z:s.z},this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0,"jumper"}const s=t[this.currentTraceSegmentIndex],o=t[this.currentTraceSegmentIndex+1],i=o.x-s.x,r=o.y-s.y,a=Math.sqrt(i*i+r*r);if(0===a){this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0;continue}const c=this.currentTraceSegmentT*a,h=a-c;if(e<=h){const t=c+e;return this.currentTraceSegmentT=t/a,this.cursorPosition={x:s.x+i*this.currentTraceSegmentT,y:s.y+r*this.currentTraceSegmentT,z:s.z},"stepped"}if(e-=h,this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0,this.currentTraceSegmentIndex>=t.length-1){const e=t[t.length-1];return this.cursorPosition={...e},"end"}}return"stepped"}getCollidingSegments(t){if(!this.currentTrace)return[];const e=this.currentTrace.rootConnectionName??this.currentTrace.connectionName,n=2*this.currentKeepoutRadius,s=[],o=this.obstacleSHI.searchArea(t.x,t.y,n,n);for(const n of o){if(n.zLayers&&!n.zLayers.includes(t.z))continue;if(n.connectedTo.includes(e))continue;if(n.obstacleId&&this.input.connMap.areIdsConnected(e,n.obstacleId))continue;let o=!1;for(const t of n.connectedTo)if(this.input.connMap.areIdsConnected(e,t)){o=!0;break}o||s.push(...Gi(n))}const i=this.hdRouteSHI.getConflictingRoutesNearPoint({x:t.x,y:t.y},n);for(const{conflictingRoute:o}of i){const i=o.rootConnectionName??o.connectionName;if(i===e)continue;if(this.input.connMap.areIdsConnected(e,i))continue;const r=o.traceThickness??.15;s.push(...Qi(o.route,r,{x:t.x,y:t.y},n,o.jumpers))}return s}positionHasCollision(t,e=0){const n=this.getCollidingSegments(t);for(const s of n)if(vt(t,s.start,s.end)<=this.currentKeepoutRadius+e)return!0;return!1}segmentIntersectsOtherRoutes(t,e){if(!this.currentTrace)return!1;const n=this.currentTrace.rootConnectionName??this.currentTrace.connectionName,s=[...this.unprocessedRoutes,...this.smoothedCursorRoutes,...this.processedRoutes];for(const o of s){if((o.rootConnectionName??o.connectionName)!==n)for(let n=0;n<o.route.length-1;n++){const s=o.route[n],i=o.route[n+1];if((s.z===t.z||i.z===t.z)&&((!s.insideJumperPad||!i.insideJumperPad)&>({x:t.x,y:t.y},{x:e.x,y:e.y},{x:s.x,y:s.y},{x:i.x,y:i.y})))return!0}}return!1}finalizeCurrentTrace(){if(!this.currentTrace)return;const t=this.currentTrace.route[this.currentTrace.route.length-1],e=this.recordedDrawPositions[this.recordedDrawPositions.length-1];e&&e.x===t.x&&e.y===t.y||this.recordedDrawPositions.push({...t});const n=function(t,e){if(t.length<4)return t;let n=[...t],s=!0;for(;s;){s=!1;for(let t=0;t<n.length-1&&!s;t++){const o=n[t],i=n[t+1];if(o.z===i.z)for(let r=t+2;r<n.length-1&&!s;r++){if(r===t+1)continue;const a=n[r],c=n[r+1];if(a.z!==c.z||o.z!==a.z)continue;const h=er(o,i,a,c);if(h){if(sr(n,t+1,r,e))continue;const i=[];for(let e=0;e<=t;e++)i.push(n[e]);i.push({x:h.x,y:h.y,z:o.z});for(let t=r+1;t<n.length;t++)i.push(n[t]);n=i,s=!0}}}}return n}(this.simplifyRoute(this.recordedDrawPositions,this.currentTrace.jumpers),this.currentTrace.jumpers),s={connectionName:this.currentTrace.connectionName,rootConnectionName:this.currentTrace.rootConnectionName,traceThickness:this.currentTrace.traceThickness,viaDiameter:this.currentTrace.viaDiameter,route:n,vias:[...this.currentTrace.vias],jumpers:this.currentTrace.jumpers};this.processedRoutes.push(s),this.hdRouteSHI.removeRoute(this.currentTrace.connectionName),this.hdRouteSHI.addRoute(s),this.currentTrace=null,this.cursorPosition=null,this.lastCursorPosition=null,this.drawPosition=null,this.recordedDrawPositions=[]}isJumperEndpoint(t,e){if(!e||0===e.length)return!1;for(const n of e)if(Math.abs(t.x-n.start.x)<or&&Math.abs(t.y-n.start.y)<or||Math.abs(t.x-n.end.x)<or&&Math.abs(t.y-n.end.y)<or)return!0;return!1}simplifyRoute(t,e){if(t.length<=2)return t;const n=[t[0]];for(let s=1;s<t.length-1;s++){const o=n[n.length-1],i=t[s],r=t[s+1];if(this.isJumperEndpoint(i,e)){n.push(i);continue}if(i.z!==o.z||i.z!==r.z){n.push(i);continue}const a=i.x-o.x,c=i.y-o.y,h=r.x-i.x,d=a*(r.y-i.y)-c*h,l=1e-6;Math.abs(d)>l&&n.push(i)}return n.push(t[t.length-1]),n}createBoardOutlineRoutes(){const t=[];if(!this.input.srj)return t;const{outline:e,bounds:n}=this.input.srj;let s;s=e&&e.length>=3?e:[{x:n.minX,y:n.minY},{x:n.maxX,y:n.minY},{x:n.maxX,y:n.maxY},{x:n.minX,y:n.maxY}];const o=this.input.srj.layerCount??2;for(let e=0;e<s.length;e++){const n=s[e],i=s[(e+1)%s.length];for(let s=0;s<o;s++)t.push({connectionName:`__board_outline___${e}_z${s}`,traceThickness:.01,viaDiameter:0,route:[{x:n.x,y:n.y,z:s},{x:i.x,y:i.y,z:s}],vias:[]})}return t}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:`Trace Keepout Solver (radius: ${this.currentKeepoutRadius.toFixed(2)})`};for(const e of this.originalHdRoutes)if(0!==e.route.length)for(let n=0;n<e.route.length-1;n++){const s=e.route[n],o=e.route[n+1];s.z===o.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:o.x,y:o.y}],strokeColor:"rgba(0,0,0,0.25)",strokeWidth:1.5*(e.traceThickness??.15)})}if(this.input.jumpers)for(const e of this.input.jumpers){for(const n of e.pads){const e=n.connectedTo.length>0?n.connectedTo.join(", "):"unused",s=n.connectedTo.length>0?this.input.colorMap[n.connectedTo[0]]||"#888888":"rgba(128, 128, 128, 0.5)";t.rects.push({center:n.center,width:n.width,height:n.height,fill:s,stroke:"rgba(0, 0, 0, 0.5)",label:`Jumper pad (${e})`})}e.pads.length>=2&&t.lines.push({points:[e.pads[0].center,e.pads[1].center],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.2,label:"Jumper body"})}for(const e of this.input.obstacles){let n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),o=e.zLayers?.includes(1);s&&o?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":o&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}if(this.input.srj){const{outline:e,bounds:n}=this.input.srj;let s;s=e&&e.length>=3?e:[{x:n.minX,y:n.minY},{x:n.maxX,y:n.minY},{x:n.maxX,y:n.maxY},{x:n.minX,y:n.maxY}];for(let e=0;e<s.length;e++){const n=s[e],o=s[(e+1)%s.length];t.lines.push({points:[{x:n.x,y:n.y},{x:o.x,y:o.y}],strokeColor:"rgba(0, 128, 0, 0.6)",strokeWidth:.1,label:"Board outline"})}}for(const e of this.processedRoutes){if(0===e.route.length)continue;const n=this.input.colorMap[e.connectionName]||"#888888",s=new Set;if(e.jumpers&&e.jumpers.length>0)for(const t of e.jumpers)for(let n=0;n<e.route.length-1;n++){const o=e.route[n],i=e.route[n+1],r=Math.abs(o.x-t.start.x)<or&&Math.abs(o.y-t.start.y)<or&&Math.abs(i.x-t.end.x)<or&&Math.abs(i.y-t.end.y)<or,a=Math.abs(o.x-t.end.x)<or&&Math.abs(o.y-t.end.y)<or&&Math.abs(i.x-t.start.x)<or&&Math.abs(i.y-t.start.y)<or;if(r||a){s.add(n);break}}for(let n=0;n<e.route.length-1;n++){const o=e.route[n],i=e.route[n+1];s.has(n)?t.lines.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:"rgba(128, 128, 128, 0.6)",strokeDash:"2 2",label:`${e.connectionName} (jumper segment - fixed)`}):o.z===i.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:0===o.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${o.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const s=Je(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...s.rects??[]),t.lines.push(...s.lines??[])}}if(this.currentTrace&&this.recordedDrawPositions.length>0){this.input.colorMap[this.currentTrace.connectionName];for(let e=0;e<this.recordedDrawPositions.length-1;e++){const n=this.recordedDrawPositions[e],s=this.recordedDrawPositions[e+1];t.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.y}],strokeColor:"green",strokeWidth:this.currentTrace.traceThickness})}if(this.cursorPosition&&(t.circles.push({center:{x:this.cursorPosition.x,y:this.cursorPosition.y},radius:this.currentKeepoutRadius,stroke:"orange",fill:"none"}),t.points.push({x:this.cursorPosition.x,y:this.cursorPosition.y,color:"orange",label:"Cursor"}),this.lastCursorPosition)){const e=this.cursorPosition.x-this.lastCursorPosition.x,n=this.cursorPosition.y-this.lastCursorPosition.y,s=Math.sqrt(e*e+n*n),o=s>1e-4?{x:e/s,y:n/s}:{x:1,y:0},i=this.currentKeepoutRadius/4,r={x:this.cursorPosition.x-o.x*i,y:this.cursorPosition.y-o.y*i},a={x:this.cursorPosition.x+o.x*i,y:this.cursorPosition.y+o.y*i};t.lines.push({points:[r,a],strokeColor:"cyan",strokeWidth:.05,label:"Projected segment"})}this.drawPosition&&t.points.push({x:this.drawPosition.x,y:this.drawPosition.y,color:"lime",label:"Draw"});for(const e of this.lastCollidingSegments)t.lines.push({points:[{x:e.start.x,y:e.start.y},{x:e.end.x,y:e.end.y}],strokeColor:"rgba(255, 0, 255, 0.8)",strokeWidth:.02,label:"Colliding segment"})}if(!this.solved)for(const e of this.smoothedCursorRoutes)if(0!==e.route.length)for(let n=0;n<e.route.length-1;n++){const s=e.route[n],o=e.route[n+1];s.z===o.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:o.x,y:o.y}],strokeColor:"gray"})}return t}getRedrawnHdRoutes(){return this.redrawnHdRoutes}},rr=class extends y{hdRoutes;hdRoutesWithWidths=[];nominalTraceWidth;minTraceWidth;obstacleMargin;TRACE_WIDTH_SCHEDULE;unprocessedRoutes=[];processedRoutes=[];currentTrace=null;cursorPosition=null;currentTraceSegmentIndex=0;currentTraceSegmentT=0;currentScheduleIndex=0;currentTargetWidth=0;hasInsufficientClearance=!1;lastCollidingObstacles=[];lastCollidingRoutes=[];lastClearance=1/0;obstacles=[];obstacleSHI;hdRouteSHI;connMap;colorMap;constructor(t){super(),this.MAX_ITERATIONS=1e6,this.hdRoutes=[...t.hdRoutes],this.minTraceWidth=t.minTraceWidth,this.nominalTraceWidth=t.nominalTraceWidth??2*t.minTraceWidth,this.obstacleMargin=t.obstacleMargin??.15;const e=(this.nominalTraceWidth+this.minTraceWidth)/2;this.TRACE_WIDTH_SCHEDULE=[this.nominalTraceWidth,e],this.unprocessedRoutes=[...this.hdRoutes],this.connMap=t.connMap,this.colorMap=t.colorMap,this.obstacles=t.obstacles??[],this.obstacles.length>0&&(this.obstacleSHI=new Qs("flatbush",this.obstacles)),this.hdRouteSHI=new io(this.hdRoutes)}_step(){if(!this.currentTrace){const t=this.unprocessedRoutes.shift();return t?(this.currentTrace=t,this.currentTrace.route.length<2?(this.processedRoutes.push({...this.currentTrace,traceThickness:this.minTraceWidth}),void(this.currentTrace=null)):(this.currentScheduleIndex=0,this.currentTargetWidth=this.TRACE_WIDTH_SCHEDULE[0],void this.initializeCursor())):(this.hdRoutesWithWidths=this.processedRoutes,void(this.solved=!0))}if(!this.stepCursorForward())return void this.finalizeCurrentTrace(this.currentTargetWidth);this.getClearanceAtPosition(this.cursorPosition)<this.currentTargetWidth/2+this.obstacleMargin&&(this.hasInsufficientClearance=!0,this.currentScheduleIndex++,this.currentScheduleIndex<this.TRACE_WIDTH_SCHEDULE.length?(this.currentTargetWidth=this.TRACE_WIDTH_SCHEDULE[this.currentScheduleIndex],this.initializeCursor()):this.finalizeCurrentTrace(this.minTraceWidth))}initializeCursor(){if(!this.currentTrace)return;const t=this.currentTrace.route[0];this.cursorPosition={...t},this.currentTraceSegmentIndex=0,this.currentTraceSegmentT=0,this.hasInsufficientClearance=!1}stepCursorForward(){if(!this.currentTrace||!this.cursorPosition)return!1;const t=this.currentTrace.route;let e=.1;for(;e>0;){if(this.currentTraceSegmentIndex>=t.length-1)return!1;const n=t[this.currentTraceSegmentIndex],s=t[this.currentTraceSegmentIndex+1];if(n.insideJumperPad&&s.insideJumperPad){this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0;continue}const o=s.x-n.x,i=s.y-n.y,r=Math.sqrt(o*o+i*i);if(0===r){this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0;continue}const a=this.currentTraceSegmentT*r,c=r-a;if(e<=c){const t=a+e;return this.currentTraceSegmentT=t/r,this.cursorPosition={x:n.x+o*this.currentTraceSegmentT,y:n.y+i*this.currentTraceSegmentT,z:n.z},!0}if(e-=c,this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0,this.currentTraceSegmentIndex>=t.length-1){const e=t[t.length-1];return this.cursorPosition={...e},!1}}return!0}isObstacleOwnJumperPad(t){if(!this.currentTrace?.jumpers)return!1;for(const e of this.currentTrace.jumpers){const n=Math.sqrt((t.center.x-e.start.x)**2+(t.center.y-e.start.y)**2),s=Math.sqrt((t.center.x-e.end.x)**2+(t.center.y-e.end.y)**2),o=Math.max(t.width,t.height)/2+.01;if(n<o||s<o)return!0}return!1}getClearanceAtPosition(t){if(!this.currentTrace)return 1/0;const e=this.currentTrace.rootConnectionName??this.currentTrace.connectionName,n=2*this.nominalTraceWidth;let s=1/0;if(this.lastCollidingObstacles=[],this.lastCollidingRoutes=[],this.obstacleSHI){const o=this.obstacleSHI.searchArea(t.x,t.y,n,n);for(const n of o){if(n.zLayers&&!n.zLayers.includes(t.z))continue;if(n.connectedTo.includes(e))continue;if(n.obstacleId&&this.connMap?.areIdsConnected(e,n.obstacleId))continue;let o=!1;if(this.connMap)for(const t of n.connectedTo)if(this.connMap.areIdsConnected(e,t)){o=!0;break}if(o)continue;if(this.isObstacleOwnJumperPad(n))continue;const i=n.center.x-n.width/2,r=n.center.x+n.width/2,a=n.center.y-n.height/2,c=n.center.y+n.height/2,h=Math.max(i-t.x,0,t.x-r),d=Math.max(a-t.y,0,t.y-c),l=Math.sqrt(h*h+d*d);l<this.currentTargetWidth/2+this.obstacleMargin&&this.lastCollidingObstacles.push(n),l<s&&(s=l)}}const o=this.hdRouteSHI.getConflictingRoutesNearPoint({x:t.x,y:t.y},n);for(const{conflictingRoute:t,distance:n}of o){const o=t.rootConnectionName??t.connectionName;if(o===e)continue;if(this.connMap?.areIdsConnected(e,o))continue;const i=n-(t.traceThickness??.15)/2;i<this.currentTargetWidth/2+this.obstacleMargin&&this.lastCollidingRoutes.push(t),i<s&&(s=i)}return this.lastClearance=s,s}finalizeCurrentTrace(t){if(!this.currentTrace)return;const e={connectionName:this.currentTrace.connectionName,rootConnectionName:this.currentTrace.rootConnectionName,traceThickness:t,viaDiameter:this.currentTrace.viaDiameter,route:[...this.currentTrace.route],vias:[...this.currentTrace.vias],jumpers:this.currentTrace.jumpers};this.processedRoutes.push(e),this.currentTrace=null,this.cursorPosition=null,this.hasInsufficientClearance=!1}visualize(){const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:`Trace Width Solver (schedule: [${this.TRACE_WIDTH_SCHEDULE.map(t=>t.toFixed(2)).join(", ")}]mm, fallback: ${this.minTraceWidth.toFixed(2)}mm, margin: ${this.obstacleMargin.toFixed(2)}mm)`},e=new Set(this.lastCollidingObstacles.map(t=>t.obstacleId)),n=new Set(this.lastCollidingRoutes.map(t=>t.connectionName));for(const n of this.obstacles){const s=e.has(n.obstacleId),o=n.zLayers?.includes(0),i=n.zLayers?.includes(1);let r;r=s?"rgba(255, 0, 0, 0.6)":o&&i?"rgba(128, 0, 128, 0.15)":o?"rgba(255, 0, 0, 0.15)":i?"rgba(0, 0, 255, 0.15)":"rgba(128, 128, 128, 0.15)",t.rects.push({center:n.center,width:n.width,height:n.height,fill:r,stroke:s?"red":void 0,label:s?`COLLIDING: ${n.obstacleId??"obstacle"}`:`${n.obstacleId??"obstacle"} (Z: ${n.zLayers?.join(", ")})`})}for(const e of this.processedRoutes){if(0===e.route.length)continue;const n=e.traceThickness===this.nominalTraceWidth,s=e.traceThickness===this.TRACE_WIDTH_SCHEDULE[1],o=n?"green":s?"yellow":"orange";for(let n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];s.insideJumperPad&&i.insideJumperPad||s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:o,strokeWidth:e.traceThickness,label:`${e.connectionName} (w=${e.traceThickness.toFixed(2)})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const n=Je(e.jumpers,{color:o,label:e.connectionName});t.rects.push(...n.rects??[]),t.lines.push(...n.lines??[])}}if(this.currentTrace){for(let e=0;e<this.currentTrace.route.length-1;e++){const n=this.currentTrace.route[e],s=this.currentTrace.route[e+1];n.insideJumperPad&&s.insideJumperPad||n.z===s.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.y}],strokeColor:"cyan",strokeWidth:this.currentTrace.traceThickness??this.minTraceWidth,label:`Processing: ${this.currentTrace.connectionName}`})}this.cursorPosition&&(t.circles.push({center:{x:this.cursorPosition.x,y:this.cursorPosition.y},radius:this.currentTargetWidth/2,stroke:this.hasInsufficientClearance?"red":"green",fill:"none",label:`Testing width: ${this.currentTargetWidth.toFixed(2)}mm (clearance: ${this.lastClearance.toFixed(2)}mm)`}),t.points.push({x:this.cursorPosition.x,y:this.cursorPosition.y,color:"orange",label:"Cursor"}))}for(const e of this.unprocessedRoutes){if(0===e.route.length)continue;const s=n.has(e.connectionName);for(let n=0;n<e.route.length-1;n++){const o=e.route[n],i=e.route[n+1];o.z===i.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:s?"rgba(255, 0, 0, 0.8)":"rgba(128, 128, 128, 0.3)",strokeWidth:e.traceThickness??this.minTraceWidth,label:s?`COLLIDING: ${e.connectionName}`:e.connectionName})}}return t}getHdRoutesWithWidths(){return this.hdRoutesWithWidths}},ar=class extends y{constructor(t){super(),this.input=t,this.unprocessedObstacles=this.input.srj.obstacles.filter(t=>t.offBoardConnectsTo&&t.offBoardConnectsTo.length>0),this.unprocessedObstacles.forEach((t,e)=>{t.obstacleId=t.obstacleId??`__obs${e}`,t.zLayers=t.zLayers??t.layers.map(t=>Xe(t,this.input.srj.layerCount))}),this.offBoardConnMap=new tn({}),this.offBoardConnMap.addConnections(this.unprocessedObstacles.filter(t=>t.offBoardConnectsTo?.length).map(t=>[t.obstacleId,...t.offBoardConnectsTo??[]])),this.nodeTree=new an(this.input.capacityMeshNodes)}unprocessedObstacles;nodeTree;offBoardConnMap;nodesInNet=new Map;lastProcessedObstacle;_step(){const t=this.unprocessedObstacles.pop();if(this.lastProcessedObstacle=t,!t)return void(this.solved=!0);const e=this.offBoardConnMap.getNetConnectedToId(t.obstacleId),n=this.nodeTree.getNodesInArea(t.center.x,t.center.y,.01,.01).filter(e=>e.availableZ.some(e=>t.zLayers?.includes(e))).filter(e=>Math.abs(e.center.x-t.center.x)<.01&&Math.abs(e.center.y-t.center.y)<.01),s=n.map(t=>t.capacityMeshNodeId),o=this.nodesInNet.get(e)??[],i=[...o.map(t=>t.capacityMeshNodeId),...s];for(const t of o)t._offBoardConnectedCapacityMeshNodeIds=i;for(const t of n)t._offBoardConnectedCapacityMeshNodeIds=i,t._offBoardConnectionId=e;this.nodesInNet.set(e,[...o,...n])}getOutput(){return{capacityNodes:this.input.capacityMeshNodes}}visualize(){const t={rects:[],lines:[],points:[],circles:[]},e=new Set;for(const[t,n]of this.nodesInNet)for(const t of n)e.add(t.capacityMeshNodeId);for(const n of this.input.capacityMeshNodes)e.has(n.capacityMeshNodeId)||t.rects.push({center:n.center,width:n.width-.1,height:n.height-.1,fill:"rgba(0, 0, 0, 0.2)"});this.lastProcessedObstacle&&t.rects.push({center:this.lastProcessedObstacle.center,width:this.lastProcessedObstacle.width,height:this.lastProcessedObstacle.height,fill:"rgba(255, 0, 0, 0.5)"});for(const[e,n]of this.nodesInNet.entries()){for(const s of n)t.rects.push({center:s.center,width:s.width,height:s.height,fill:rt(e,.2),label:`OffBoardConn: ${e}`});for(const s of n)for(const o of n)s.capacityMeshNodeId!==o.capacityMeshNodeId&&t.lines.push({points:[s.center,o.center],strokeColor:rt(e,1)})}return t}},cr=({connMap:t,connectionsWithResults:e,inputNodes:n,obstacles:s})=>{const o=s.filter(t=>t.offBoardConnectsTo?.length);if(0===o.length)return;const i=new Fe({});i.addConnections(o.map((t,e)=>{const n=t.obstacleId??`__obs${e}`;return t.obstacleId=n,[n,...t.offBoardConnectsTo??[]]}));const r=new Map(n.map(t=>[t.capacityMeshNodeId,t]));for(const n of e){if(!n.path)continue;const e=n.connection.rootConnectionName??n.connection.name,s=new Set;for(const t of n.path){const e=r.get(t.currentNodeId);if(e?._offBoardConnectionId&&s.add(e._offBoardConnectionId),t.throughNodeId){const e=r.get(t.throughNodeId);e?._offBoardConnectionId&&s.add(e._offBoardConnectionId)}}for(const n of s){const s=i.getIdsConnectedToNet(n);s?.length&&t.addConnections([[e,...s]])}}};function hr(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var dr=class extends y{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth,this.effort=e.effort??1,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,o=Math.max(n,s),i=e.targetMinCapacity??.5;e.capacityDepth=Be(o,i)}this.connMap=$e(t),this.colorMap=ot(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;relateNodesToOffBoardConnections;colorMap;highDensityRouteSolver;simpleHighDensityRouteSolver;highDensitySolver;highDensityStitchSolver;singleLayerNodeMerger;offboardPathFragmentSolver;strawSolver;deadEndSolver;traceSimplificationSolver;traceKeepoutSolver;traceWidthSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;viaDiameter;minTraceWidth;effort;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[hr("netToPointPairsSolver",fn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ot(t.srjWithPointPairs,this.connMap),t.connMap=$e(t.srjWithPointPairs)}}),hr("nodeSolver",Js,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),hr("relateNodesToOffBoardConnections",ar,t=>[{capacityMeshNodes:t.capacityNodes,srj:t.srj}],{onSolved:t=>{t.capacityNodes=t.relateNodesToOffBoardConnections?.getOutput().capacityNodes}}),hr("edgeSolver",cn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),hr("availableSegmentPointSolver",Io,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),hr("portPointPathingSolver",Vo,t=>{const e=t.capacityNodes.map(t=>({capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:[],availableZ:t.availableZ,_containsTarget:t._containsTarget,_containsObstacle:t._containsObstacle,_offBoardConnectionId:t._offBoardConnectionId,_offBoardConnectedCapacityMeshNodeIds:t._offBoardConnectedCapacityMeshNodeIds})),n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),s=t.availableSegmentPointSolver;for(const t of s.sharedEdgeSegments)for(const e of t.portPoints){const[s,o]=e.nodeIds,i={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[s,o],distToCentermostPortOnZ:e.distToCentermostPortOnZ,connectsToOffBoardNode:t.nodeIds.some(t=>n.get(t)?._offBoardConnectionId)},r=n.get(s);r&&r.portPoints.push(i)}return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e,capacityMeshNodes:t.capacityNodes,colorMap:t.colorMap,numShuffleSeeds:100*t.effort,hyperParameters:{JUMPER_PF_FN_ENABLED:!1,NODE_PF_FACTOR:100,NODE_PF_MAX_PENALTY:100,CENTER_OFFSET_DIST_PENALTY_FACTOR:0,FORCE_CENTER_FIRST:!0}}]},{onSolved:t=>{const e=t.portPointPathingSolver;e&&cr({connMap:t.connMap,connectionsWithResults:e.connectionsWithResults,inputNodes:e.inputNodes,obstacles:t.srj.obstacles})}}),hr("multiSectionPortPointOptimizer",Ho,t=>{const e=t.portPointPathingSolver;return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e.inputNodes,capacityMeshNodes:t.capacityNodes,capacityMeshEdges:t.capacityEdges,colorMap:t.colorMap,initialConnectionResults:e.connectionsWithResults,initialAssignedPortPoints:e.assignedPortPoints,initialNodeAssignedPortPoints:e.nodeAssignedPortPoints}]}),hr("highDensitySolver",Bi,t=>[{nodePortPoints:t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth,connMap:t.connMap}]),hr("highDensityStitchSolver",nn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensitySolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),hr("traceSimplificationSolver",Mo,t=>[{hdRoutes:t.highDensityStitchSolver?.mergedHdRoutes??t.highDensitySolver?.routes??t.highDensityRouteSolver?.routes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline,defaultViaDiameter:t.viaDiameter,layerCount:t.srj.layerCount,iterations:2}]),hr("traceKeepoutSolver",ir,t=>[{hdRoutes:t.traceSimplificationSolver?.simplifiedHdRoutes??[],obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,srj:t.srj}]),hr("traceWidthSolver",rr,t=>[{hdRoutes:t.traceKeepoutSolver?.redrawnHdRoutes??[],obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,nominalTraceWidth:t.srj.nominalTraceWidth,minTraceWidth:t.minTraceWidth,obstacleMargin:t.srj.defaultObstacleMargin??.15}])];getConstructorParams(){return[this.srj,this.opts]}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 t=this.netToPointPairsSolver?.visualize(),e=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),s=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),i=this.edgeSolver?.visualize(),r=this.deadEndSolver?.visualize(),a=this.availableSegmentPointSolver?.visualize(),c=this.offboardPathFragmentSolver?.visualize(),h=this.portPointPathingSolver?.visualize(),d=this.multiSectionPortPointOptimizer?.visualize(),l=this.highDensityRouteSolver?.visualize(),u=this.highDensitySolver?.visualize(),p=this.simpleHighDensityRouteSolver?.visualize(),m=this.highDensityStitchSolver?.visualize(),f=this.traceSimplificationSolver?.visualize(),y=this.traceKeepoutSolver?.visualize(),x=this.traceWidthSolver?.visualize(),v=this.srj.outline,S=[];if(S.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)"}),v&&v.length>=2){const t=v.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),S.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const P={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:["obstacle",t.offBoardConnectsTo?`offboardConnections: ${t.offBoardConnectsTo?.join(", ")}`:"",t.layers?.join(", ")].filter(Boolean).join("\n")}))],lines:S},b=[P,t,e,n,s,o,i,r,a,c,h,d,l?g(P,l):null,u?g(P,u):null,p?g(P,p):null,m,f,y,x,this.solved?g(P,sn(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...b)}preview(){const t=this.highDensitySolver?.routes??this.simpleHighDensityRouteSolver?.routes??this.highDensityRouteSolver?.routes;if(t){const e=[];for(let n=t.length-1;n>=0;n--){const s=t[n];if(e.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[s.connectionName]}),e.length>200)break}return{lines:e}}if(this.portPointPathingSolver){const t=[];for(const e of this.portPointPathingSolver.connectionsWithResults)e.path&&t.push({points:e.path.map(t=>({x:t.point.x,y:t.point.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.traceWidthSolver?.hdRoutesWithWidths??this.traceKeepoutSolver?.redrawnHdRoutes??this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver?.mergedHdRoutes??this.highDensitySolver?.routes??this.simpleHighDensityRouteSolver?.routes??this.highDensityRouteSolver?.routes}getConnectedOffboardObstacles(){const t={},e=new Set(this.srj.connections.map(t=>t.rootConnectionName??t.name));for(const[n,s]of this.srj.obstacles.entries()){if(!s.offBoardConnectsTo?.length)continue;const o=s.obstacleId??`__obs${n}`;s.obstacleId=o;const i=this.connMap.getNetConnectedToId(o);if(!i)continue;const r=this.connMap.getIdsConnectedToNet(i).find(t=>e.has(t));r&&(t[o]=r)}return t}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver&&!this.simpleHighDensityRouteSolver&&!this.highDensitySolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,o=e.filter(t=>t.connectionName===n.name);for(let e=0;e<o.length;e++){const i=o[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:We(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},lr=class{MAX_ITERATIONS=1e5;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};_setupDone=!1;setup(){this._setupDone||(this._setup(),this._setupDone=!0)}_setup(){}step(){if(this._setupDone||this.setup(),!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,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`,this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}getOutput(){return null}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}},ur=t=>({x:(t.minX+t.maxX)/2,y:(t.minY+t.maxY)/2}),pr={padWidth:.8,padHeight:.5,leftPadCenterX:-1.35,rightPadCenterX:1.35,row1CenterY:1.905,row2CenterY:.635,row3CenterY:-.635,row4CenterY:-1.905},mr=t=>{let e=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,s=Number.POSITIVE_INFINITY,o=Number.NEGATIVE_INFINITY;for(const i of t){const{bounds:t}=i.d;e=Math.min(e,t.minX),n=Math.max(n,t.maxX),s=Math.min(s,t.minY),o=Math.max(o,t.maxY)}return{minX:e,maxX:n,minY:s,maxY:o}};function fr(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}}function gr(t){return void 0===t}function yr(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}function xr(...t){const e=(t,e)=>({a:t.a*e.a+t.c*e.b,c:t.a*e.c+t.c*e.d,e:t.a*e.e+t.c*e.f+t.e,b:t.b*e.a+t.d*e.b,d:t.b*e.c+t.d*e.d,f:t.b*e.e+t.d*e.f+t.f});switch((t=Array.isArray(t[0])?t[0]:t).length){case 0:throw new Error("no matrices provided");case 1:return t[0];case 2:return e(t[0],t[1]);default:{const[n,s,...o]=t;return xr(e(n,s),...o)}}}var{cos:vr,sin:Sr,PI:Pr}=Math;var{tan:br}=Math,Mr=({cols:t,rows:e,marginX:n,marginY:s,innerColChannelPointCount:o=1,innerRowChannelPointCount:i=1,regionsBetweenPads:r=!1,outerPaddingX:a=.5,outerPaddingY:c=.5,outerChannelXPointCount:h,outerChannelYPointCount:d,orientation:l="vertical",center:u,bounds:p,parallelTracesUnderJumperCount:m=4})=>{const f=[],g=[],{padWidth:y,padHeight:x,leftPadCenterX:v,rightPadCenterX:S,row1CenterY:P,row2CenterY:b,row3CenterY:M,row4CenterY:N}=pr,I=y/2,C=x/2,_=S-v+y,T=_+n,E=P-N+x,R=E+s;let w=a,A=c;if(p){const o=t*_+(t-1)*n,i=e*E+(e-1)*s;w=(("horizontal"===l?p.maxY-p.minY:p.maxX-p.minX)-o)/2,A=(("horizontal"===l?p.maxX-p.minX:p.maxY-p.minY)-i)/2}const O=h??Math.max(1,Math.floor(w/.4)),z=d??Math.max(1,Math.floor(A/.4)),D=[],L=[],F=(t,e,n,s)=>({regionId:t,ports:[],d:{bounds:e,center:ur(e),isPad:n,isThroughJumper:s}}),X=(t,e,n)=>{const s=e.d.bounds,o=n.d.bounds;let i,r;Math.abs(s.maxX-o.minX)<.001?(i=s.maxX,r=(Math.max(s.minY,o.minY)+Math.min(s.maxY,o.maxY))/2):Math.abs(s.minX-o.maxX)<.001?(i=s.minX,r=(Math.max(s.minY,o.minY)+Math.min(s.maxY,o.maxY))/2):Math.abs(s.maxY-o.minY)<.001?(i=(Math.max(s.minX,o.minX)+Math.min(s.maxX,o.maxX))/2,r=s.maxY):(i=(Math.max(s.minX,o.minX)+Math.min(s.maxX,o.maxX))/2,r=s.minY);const a={portId:t,region1:e,region2:n,d:{x:i,y:r}};return e.ports.push(a),n.ports.push(a),a},Y=(t,e,n,s)=>{if(s<=0)return[];if(1===s)return[X(t,e,n)];const o=e.d.bounds,i=n.d.bounds,r=[];let a,c,h,d;Math.abs(o.maxX-i.minX)<.001?(a=!0,c=o.maxX,h=Math.max(o.minY,i.minY),d=Math.min(o.maxY,i.maxY)):Math.abs(o.minX-i.maxX)<.001?(a=!0,c=o.minX,h=Math.max(o.minY,i.minY),d=Math.min(o.maxY,i.maxY)):Math.abs(o.maxY-i.minY)<.001?(a=!1,c=o.maxY,h=Math.max(o.minX,i.minX),d=Math.min(o.maxX,i.maxX)):(a=!1,c=o.minY,h=Math.max(o.minX,i.minX),d=Math.min(o.maxX,i.maxX));for(let o=0;o<s;o++){const i=h+(o+.5)/s*(d-h),l={portId:`${t}:${o}`,region1:e,region2:n,d:{x:a?c:i,y:a?i:c}};e.ports.push(l),n.ports.push(l),r.push(l)}return r};for(let n=0;n<e;n++){D[n]=[];for(let a=0;a<t;a++){const c=`cell_${n}_${a}`,h=a*T,d=-n*R,l=h+v,u=d+P,p=h+v,y=d+b,x=h+v,_=d+M,E=h+v,$=d+N,k=h+S,B=d+N,j=h+S,W=d+M,H=h+S,U=d+b,V=h+S,Z=d+P,G=(t,e)=>({minX:t-I,maxX:t+I,minY:e-C,maxY:e+C}),J=G(l,u),q=G(p,y),K=G(x,_),Q=G(E,$),tt=G(k,B),et=G(j,W),nt=G(H,U),st=G(V,Z),ot={minX:J.maxX,maxX:st.minX,minY:Q.minY,maxY:J.maxY},it=.3,rt={minX:l,maxX:V,minY:u-it/2,maxY:u+it/2},at={minX:p,maxX:H,minY:y-it/2,maxY:y+it/2},ct={minX:x,maxX:j,minY:_-it/2,maxY:_+it/2},ht={minX:E,maxX:k,minY:$-it/2,maxY:$+it/2},dt=J.minX,lt=st.maxX,ut=Q.minY,pt=J.maxY,mt=F(`${c}:pad1`,J,!0),ft=F(`${c}:pad2`,q,!0),gt=F(`${c}:pad3`,K,!0),yt=F(`${c}:pad4`,Q,!0),xt=F(`${c}:pad5`,tt,!0),vt=F(`${c}:pad6`,et,!0),St=F(`${c}:pad7`,nt,!0),Pt=F(`${c}:pad8`,st,!0),bt=F(`${c}:underjumper`,ot,!1),Mt=F(`${c}:throughjumper1`,rt,!1,!0),Nt=F(`${c}:throughjumper2`,at,!1,!0),It=F(`${c}:throughjumper3`,ct,!1,!0),Ct=F(`${c}:throughjumper4`,ht,!1,!0);f.push(mt,ft,gt,yt,xt,vt,St,Pt,bt,Mt,Nt,It,Ct);const _t=(l+V)/2,Tt=(u+$)/2;L.push({center:{x:_t,y:Tt},orientation:"vertical",padRegions:[mt,ft,gt,yt,xt,vt,St,Pt]});let Et=null,Rt=null,wt=null,At=null,Ot=null,zt=null;r&&(Et=F(`${c}:L-BP12`,{minX:J.minX,maxX:J.maxX,minY:q.maxY,maxY:J.minY},!1),Rt=F(`${c}:L-BP23`,{minX:q.minX,maxX:q.maxX,minY:K.maxY,maxY:q.minY},!1),wt=F(`${c}:L-BP34`,{minX:K.minX,maxX:K.maxX,minY:Q.maxY,maxY:K.minY},!1),At=F(`${c}:R-BP87`,{minX:st.minX,maxX:st.maxX,minY:nt.maxY,maxY:st.minY},!1),Ot=F(`${c}:R-BP76`,{minX:nt.minX,maxX:nt.maxX,minY:et.maxY,maxY:nt.minY},!1),zt=F(`${c}:R-BP65`,{minX:et.minX,maxX:et.maxX,minY:tt.maxY,maxY:et.minY},!1),f.push(Et,Rt,wt,At,Ot,zt));const Dt=0===a,Lt=n===e-1,Ft=a===t-1;let Xt;if(Ft)Xt=lt+w;else{Xt=(a+1)*T+v-I}let Yt=null;0===n&&(Yt=F(`${c}:T`,{minX:Dt?dt-w:dt,maxX:Xt,minY:pt,maxY:pt+A},!1),f.push(Yt));let $t=null;$t=F(`${c}:B`,{minX:Dt?dt-w:dt,maxX:Xt,minY:ut-(Lt?A:s),maxY:ut},!1),f.push($t);let kt=null;Dt&&(kt=F(`${c}:L`,{minX:dt-w,maxX:dt,minY:ut,maxY:pt},!1),f.push(kt));const Bt=F(`${c}:R`,{minX:lt,maxX:Xt,minY:ut,maxY:pt},!1);if(f.push(Bt),D[n][a]={pad1:mt,pad2:ft,pad3:gt,pad4:yt,pad5:xt,pad6:vt,pad7:St,pad8:Pt,underjumper:bt,throughjumper1:Mt,throughjumper2:Nt,throughjumper3:It,throughjumper4:Ct,top:Yt,bottom:$t,left:kt,right:Bt,leftBP12:Et,leftBP23:Rt,leftBP34:wt,rightBP87:At,rightBP76:Ot,rightBP65:zt},Yt)if(kt&&g.push(...Y(`${c}:T-L`,Yt,kt,O)),g.push(...Y(`${c}:T-R`,Yt,Bt,Ft?O:o)),g.push(X(`${c}:T-P1`,Yt,mt)),g.push(X(`${c}:T-P8`,Yt,Pt)),r){const t=bt.d.bounds,e=(t.maxX-t.minX)/(m+1);for(let n=1;n<=m;n++){const s={portId:`${c}:T-UJ${n}`,region1:Yt,region2:bt,d:{x:t.minX+e*n,y:t.maxY}};Yt.ports.push(s),bt.ports.push(s),g.push(s)}}else g.push(X(`${c}:T-UJ`,Yt,bt));if($t)if(kt&&g.push(...Y(`${c}:B-L`,$t,kt,O)),g.push(...Y(`${c}:B-R`,$t,Bt,Ft?O:o)),g.push(X(`${c}:B-P4`,$t,yt)),g.push(X(`${c}:B-P5`,$t,xt)),r){const t=bt.d.bounds,e=(t.maxX-t.minX)/(m+1);for(let n=1;n<=m;n++){const s={portId:`${c}:B-UJ${n}`,region1:$t,region2:bt,d:{x:t.minX+e*n,y:t.minY}};$t.ports.push(s),bt.ports.push(s),g.push(s)}}else g.push(X(`${c}:B-UJ`,$t,bt));kt&&(g.push(X(`${c}:L-P1`,kt,mt)),g.push(X(`${c}:L-P2`,kt,ft)),g.push(X(`${c}:L-P3`,kt,gt)),g.push(X(`${c}:L-P4`,kt,yt))),g.push(X(`${c}:R-P5`,Bt,xt)),g.push(X(`${c}:R-P6`,Bt,vt)),g.push(X(`${c}:R-P7`,Bt,St)),g.push(X(`${c}:R-P8`,Bt,Pt)),r&&(kt&&(g.push(X(`${c}:L-BP12`,kt,Et)),g.push(X(`${c}:L-BP23`,kt,Rt)),g.push(X(`${c}:L-BP34`,kt,wt))),g.push(X(`${c}:UJ-LBP12`,Et,bt)),g.push(X(`${c}:UJ-LBP23`,Rt,bt)),g.push(X(`${c}:UJ-LBP34`,wt,bt)),g.push(X(`${c}:R-BP87`,Bt,At)),g.push(X(`${c}:R-BP76`,Bt,Ot)),g.push(X(`${c}:R-BP65`,Bt,zt)),g.push(X(`${c}:UJ-RBP87`,At,bt)),g.push(X(`${c}:UJ-RBP76`,Ot,bt)),g.push(X(`${c}:UJ-RBP65`,zt,bt)));const jt={portId:`${c}:TJ1-P1`,region1:Mt,region2:mt,d:{x:l,y:u}};Mt.ports.push(jt),mt.ports.push(jt),g.push(jt);const Wt={portId:`${c}:TJ1-P8`,region1:Mt,region2:Pt,d:{x:V,y:Z}};Mt.ports.push(Wt),Pt.ports.push(Wt),g.push(Wt);const Ht={portId:`${c}:TJ2-P2`,region1:Nt,region2:ft,d:{x:p,y:y}};Nt.ports.push(Ht),ft.ports.push(Ht),g.push(Ht);const Ut={portId:`${c}:TJ2-P7`,region1:Nt,region2:St,d:{x:H,y:U}};Nt.ports.push(Ut),St.ports.push(Ut),g.push(Ut);const Vt={portId:`${c}:TJ3-P3`,region1:It,region2:gt,d:{x:x,y:_}};It.ports.push(Vt),gt.ports.push(Vt),g.push(Vt);const Zt={portId:`${c}:TJ3-P6`,region1:It,region2:vt,d:{x:j,y:W}};It.ports.push(Zt),vt.ports.push(Zt),g.push(Zt);const Gt={portId:`${c}:TJ4-P4`,region1:Ct,region2:yt,d:{x:E,y:$}};Ct.ports.push(Gt),yt.ports.push(Gt),g.push(Gt);const Jt={portId:`${c}:TJ4-P5`,region1:Ct,region2:xt,d:{x:k,y:B}};if(Ct.ports.push(Jt),xt.ports.push(Jt),g.push(Jt),a>0){const t=D[n][a-1];g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-P1`,t.right,mt)),g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-P2`,t.right,ft)),g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-P3`,t.right,gt)),g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-P4`,t.right,yt)),r&&(g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP12`,t.right,Et)),g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP23`,t.right,Rt)),g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP34`,t.right,wt))),Yt&&t.top&&g.push(...Y(`cell_${n}_${a-1}->cell_${n}_${a}:T-T`,t.top,Yt,z)),$t&&t.bottom&&g.push(...Y(`cell_${n}_${a-1}->cell_${n}_${a}:B-B`,t.bottom,$t,Lt?z:i))}if(n>0){const t=D[n-1][a];if(kt&&g.push(...Y(`cell_${n-1}_${a}->cell_${n}_${a}:B-L`,t.bottom,kt,O)),g.push(X(`cell_${n-1}_${a}->cell_${n}_${a}:B-P1`,t.bottom,mt)),r){const e=bt.d.bounds,s=(e.maxX-e.minX)/(m+1);for(let o=1;o<=m;o++){const i=e.minX+s*o,r={portId:`cell_${n-1}_${a}->cell_${n}_${a}:B-UJ${o}`,region1:t.bottom,region2:bt,d:{x:i,y:e.maxY}};t.bottom.ports.push(r),bt.ports.push(r),g.push(r)}}else g.push(X(`cell_${n-1}_${a}->cell_${n}_${a}:B-UJ`,t.bottom,bt));g.push(X(`cell_${n-1}_${a}->cell_${n}_${a}:B-P8`,t.bottom,Pt)),g.push(...Y(`cell_${n-1}_${a}->cell_${n}_${a}:B-R`,t.bottom,Bt,Ft?O:o))}}}let $={regions:f,ports:g,jumperLocations:L};const k="horizontal"===l;if(k||void 0!==u||void 0!==p){const t=mr($.regions),e=ur(t),n=[];let s;s=u||(p?ur(p):e),n.push(yr(s.x,s.y)),k&&n.push(function(t,e,n){const s=vr(t),o=Sr(t),i={a:s,c:-o,e:0,b:o,d:s,f:0};return gr(e)||gr(n)?i:xr([yr(e,n),i,yr(-e,-n)])}(-Math.PI/2)),n.push(yr(-e.x,-e.y));const o=function(...t){return xr(...t)}(...n);$=((t,e)=>{const n=t.regions.map(t=>{const{bounds:n,center:s,...o}=t.d,i=[{x:n.minX,y:n.minY},{x:n.maxX,y:n.minY},{x:n.minX,y:n.maxY},{x:n.maxX,y:n.maxY}].map(t=>fr(e,t)),r={minX:Math.min(...i.map(t=>t.x)),maxX:Math.max(...i.map(t=>t.x)),minY:Math.min(...i.map(t=>t.y)),maxY:Math.max(...i.map(t=>t.y))},a=fr(e,s);return{...t,ports:[],d:{...o,bounds:r,center:a}}}),s=new Map;for(let e=0;e<t.regions.length;e++)s.set(t.regions[e],n[e]);const o=t.ports.map(t=>{const n=fr(e,t.d),o=s.get(t.region1),i=s.get(t.region2),r={...t,region1:o,region2:i,d:n};return o.ports.push(r),i.ports.push(r),r}),i=t.jumperLocations?.map(t=>{const n=fr(e,t.center),o=t.padRegions.map(t=>s.get(t)),i=fr(e,{x:1,y:0}),r=fr(e,{x:0,y:0}),a=i.x-r.x,c=i.y-r.y;return{center:n,orientation:Math.abs(c)>Math.abs(a)?"horizontal"===t.orientation?"vertical":"horizontal":t.orientation,padRegions:o}});return{regions:n,ports:o,...i&&{jumperLocations:i}}})($,o)}return $},Nr=(t,e,n,s)=>{const o={portId:t,region1:e,region2:n,d:{x:s.x,y:s.y}};return e.ports.push(o),n.ports.push(o),o},Ir=(t,e,n)=>{const s=.2;return{regionId:t,ports:[],d:{bounds:{minX:e-s,maxX:e+s,minY:n-s,maxY:n+s},center:{x:e,y:n},isPad:!1,isConnectionRegion:!0}}},Cr=(t,e,n,s)=>{for(const s of n){if(s.d.isPad||s.d.isThroughJumper)continue;const n=s.d.bounds;if(Math.abs(t-n.minX)<.01&&e>=n.minY&&e<=n.maxY)return{region:s,portPosition:{x:n.minX,y:e}};if(Math.abs(t-n.maxX)<.01&&e>=n.minY&&e<=n.maxY)return{region:s,portPosition:{x:n.maxX,y:e}};if(Math.abs(e-n.minY)<.01&&t>=n.minX&&t<=n.maxX)return{region:s,portPosition:{x:t,y:n.minY}};if(Math.abs(e-n.maxY)<.01&&t>=n.minX&&t<=n.maxX)return{region:s,portPosition:{x:t,y:n.maxY}}}let o=null,i=Number.POSITIVE_INFINITY,r={x:t,y:e};for(const a of n){if(a.d.isPad||a.d.isThroughJumper)continue;const n=a.d.bounds;if(!(Math.abs(n.minX-s.minX)<.01||Math.abs(n.maxX-s.maxX)<.01||Math.abs(n.minY-s.minY)<.01||Math.abs(n.maxY-s.maxY)<.01))continue;const c=Math.max(n.minX,Math.min(n.maxX,t)),h=Math.max(n.minY,Math.min(n.maxY,e)),d=Math.sqrt((t-c)**2+(e-h)**2);d<i&&(i=d,o=a,r=t<n.minX?{x:n.minX,y:h}:t>n.maxX?{x:n.maxX,y:h}:e<n.minY?{x:c,y:n.minY}:e>n.maxY?{x:c,y:n.maxY}:{x:c,y:h})}return o?{region:o,portPosition:r}:null},_r=class{heap=[];maxSize;constructor(t=[],e=1e4){if(this.maxSize=e,t.length>0){this.heap=[...t].sort((t,e)=>t.f-e.f).slice(0,this.maxSize);for(let t=Math.floor(this.heap.length/2)-1;t>=0;t--)this._siftDown(t)}}get size(){return this.heap.length}isEmpty(){return 0===this.heap.length}peek(){return this.isEmpty()?null:this.heap[0]??null}peekMany(t){return[...this.heap].sort((t,e)=>t.f-e.f).slice(0,t)}dequeue(){if(this.isEmpty())return null;const t=this.heap[0],e=this.heap.pop();return 0===this.heap.length&&void 0!==e||void 0!==e&&(this.heap[0]=e,this._siftDown(0)),t}enqueue(t){this.heap.length>=this.maxSize||(this.heap.push(t),this._siftUp(this.heap.length-1))}_siftUp(t){let e=t;for(;e>0;){const t=this._parentIndex(e);if(this.heap[t].f<=this.heap[e].f)break;this._swap(e,t),e=t}}_siftDown(t){let e=t;const n=this.heap.length;for(;;){const t=this._leftChildIndex(e),s=this._rightChildIndex(e);let o=e;if(t<n&&this.heap[t].f<this.heap[o].f&&(o=t),s<n&&this.heap[s].f<this.heap[o].f&&(o=s),o===e)break;this._swap(e,o),e=o}}_swap(t,e){[this.heap[t],this.heap[e]]=[this.heap[e],this.heap[t]]}_parentIndex(t){return Math.floor((t-1)/2)}_leftChildIndex(t){return 2*t+1}_rightChildIndex(t){return 2*t+2}},Tr=class extends lr{constructor(t){super(),this.input=t,this.graph=(t=>{if(t.ports.length>0&&"region1"in t.ports[0]&&"object"==typeof t.ports[0].region1)return t;const e=new Map,n=new Map;for(const e of t.regions){const{assignments:t,...s}=e;n.set(e.regionId,{...s,ports:[],assignments:void 0})}for(const s of t.ports){const t=n.get(s.region1Id??s.region1?.regionId),o=n.get(s.region2Id??s.region2?.regionId),i={portId:s.portId,region1:t,region2:o,d:s.d};e.set(s.portId,i),t.ports.push(i),o.ports.push(i)}return{ports:Array.from(e.values()),regions:Array.from(n.values())}})(t.inputGraph);for(const t of this.graph.regions)t.assignments=[];this.connections=((t,e)=>{const n=[];for(const s of t)"startRegionId"in s?n.push({connectionId:s.connectionId,mutuallyConnectedNetworkId:s.connectionId,startRegion:e.regions.find(t=>t.regionId===s.startRegionId),endRegion:e.regions.find(t=>t.regionId===s.endRegionId)}):n.push(s);return n})(t.inputConnections,this.graph),void 0!==t.greedyMultiplier&&(this.greedyMultiplier=t.greedyMultiplier),void 0!==t.rippingEnabled&&(this.rippingEnabled=t.rippingEnabled),void 0!==t.ripCost&&(this.ripCost=t.ripCost),this.unprocessedConnections=[...this.connections],this.candidateQueue=new _r,this.beginNewConnection()}graph;connections;candidateQueue;unprocessedConnections;solvedRoutes=[];currentConnection=null;currentEndRegion=null;greedyMultiplier=1;rippingEnabled=!1;ripCost=0;lastCandidate=null;visitedPointsForCurrentConnection=new Map;getConstructorParams(){return{inputGraph:(e=this.graph,{ports:e.ports.map(t=>({portId:t.portId,region1Id:t.region1.regionId,region2Id:t.region2.regionId,d:t.d})),regions:e.regions.map(t=>({regionId:t.regionId,pointIds:t.ports.map(t=>t.portId),d:t.d}))}),inputConnections:(t=this.connections,t.map(t=>({connectionId:t.connectionId,startRegionId:t.startRegion.regionId,endRegionId:t.endRegion.regionId}))),greedyMultiplier:this.greedyMultiplier,rippingEnabled:this.rippingEnabled,ripCost:this.ripCost};var t,e}computeH(t){return this.estimateCostToEnd(t.port)}estimateCostToEnd(t){return 0}getPortUsagePenalty(t){return 0}computeIncreasedRegionCostIfPortsAreUsed(t,e,n){return 0}getRipsRequiredForPortUsage(t,e,n){return[]}computeG(t){return t.parent.g+this.computeIncreasedRegionCostIfPortsAreUsed(t.lastRegion,t.lastPort,t.port)+(t.ripRequired?this.ripCost:0)+this.getPortUsagePenalty(t.port)}selectCandidatesForEnteringRegion(t){return t}getNextCandidates(t){const e=t.nextRegion,n=t.port,s={};for(const o of e.ports){if(o===t.port)continue;const i=o.assignment&&o.assignment.connection.mutuallyConnectedNetworkId!==this.currentConnection.mutuallyConnectedNetworkId,r={port:o,hops:t.hops+1,parent:t,lastRegion:e,nextRegion:o.region1===e?o.region2:o.region1,lastPort:n,ripRequired:i};!this.rippingEnabled&&r.ripRequired||(s[r.nextRegion.regionId]??=[],s[r.nextRegion.regionId].push(r))}const o=[];for(const t in s){const e=s[t];o.push(...this.selectCandidatesForEnteringRegion(e))}for(const t of o)t.g=this.computeG(t),t.h=this.computeH(t),t.f=t.g+t.h*this.greedyMultiplier;return o}processSolvedRoute(t){const e={path:[],connection:this.currentConnection,requiredRip:!1};let n=t,s=!1;for(;n;)s||=!!n.ripRequired,e.path.unshift(n),n=n.parent;const o=new Set;if(s){e.requiredRip=!0;for(const t of e.path)t.port.assignment&&t.port.assignment.connection.mutuallyConnectedNetworkId!==this.currentConnection.mutuallyConnectedNetworkId&&o.add(t.port.assignment.solvedRoute)}for(const t of e.path){if(!t.lastPort||!t.lastRegion)continue;const e=this.getRipsRequiredForPortUsage(t.lastRegion,t.lastPort,t.port);for(const t of e)o.add(t.solvedRoute)}if(o.size>0){e.requiredRip=!0;for(const t of o)this.ripSolvedRoute(t)}for(const t of e.path){if(t.port.assignment={solvedRoute:e,connection:this.currentConnection},!t.lastPort)continue;const n={regionPort1:t.lastPort,regionPort2:t.port,region:t.lastRegion,connection:this.currentConnection,solvedRoute:e};t.lastRegion.assignments?.push(n)}this.solvedRoutes.push(e),this.routeSolvedHook(e)}routeSolvedHook(t){}routeStartedHook(t){}ripSolvedRoute(t){for(const e of t.path.map(t=>t.port))e.ripCount=(e.ripCount??0)+1,e.region1.assignments=e.region1.assignments?.filter(t=>t.regionPort1!==e&&t.regionPort2!==e),e.region2.assignments=e.region2.assignments?.filter(t=>t.regionPort1!==e&&t.regionPort2!==e),e.assignment=void 0;this.solvedRoutes=this.solvedRoutes.filter(e=>e!==t),this.unprocessedConnections.push(t.connection)}beginNewConnection(){this.currentConnection=this.unprocessedConnections.shift(),this.currentEndRegion=this.currentConnection.endRegion,this.candidateQueue=new _r,this.visitedPointsForCurrentConnection.clear(),this.routeStartedHook(this.currentConnection);for(const t of this.currentConnection.startRegion.ports)this.candidateQueue.enqueue({port:t,g:0,h:0,f:0,hops:0,ripRequired:!1,nextRegion:t.region1===this.currentConnection.startRegion?t.region2:t.region1})}_step(){let t=this.candidateQueue.dequeue();if(!t)return this.failed=!0,void(this.error="Ran out of candidates");let e=this.visitedPointsForCurrentConnection.get(t.port.portId);for(;t&&void 0!==e&&!(t.g<e)&&(t=this.candidateQueue.dequeue(),t);)e=this.visitedPointsForCurrentConnection.get(t.port.portId);if(!t)return this.failed=!0,void(this.error="Ran out of candidates");if(this.lastCandidate=t,this.visitedPointsForCurrentConnection.set(t.port.portId,t.g),t.nextRegion===this.currentEndRegion)return this.processSolvedRoute(t),0===this.unprocessedConnections.length?void(this.solved=!0):void this.beginNewConnection();const n=this.getNextCandidates(t);for(const t of n)this.candidateQueue.enqueue(t)}},Er=(t,e=.8)=>{let n=0;for(let e=0;e<t.length;e++)n=17777*t.charCodeAt(e)+((n<<5)-n);return`hsla(${Math.abs(n)%360}, 70%, 50%, ${e})`};function Rr(t,e,n,s,o){const i=n-e,r=o-s,a=1e-6;if(Math.abs(t.y-o)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(o-t.y);if(Math.abs(t.y-s)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-s);const c=Math.abs(t.y-o),h=Math.abs(t.x-n),d=Math.abs(t.y-s),l=Math.abs(t.x-e),u=Math.min(c,h,d,l);return u===c?Math.max(0,Math.min(i,t.x-e)):u===h?i+Math.max(0,Math.min(r,o-t.y)):u===d?i+r+Math.max(0,Math.min(i,n-t.x)):2*i+r+Math.max(0,Math.min(r,t.y-s))}function wr(t,e,n=1e-6){return Math.abs(t-e)<n}function Ar(t,e){const[n,s]=t[0]<t[1]?t:[t[1],t[0]],[o,i]=e[0]<e[1]?e:[e[1],e[0]];return!(wr(n,o)||wr(n,i)||wr(s,o)||wr(s,i))&&(n<o&&o<s&&s<i||o<n&&n<i&&i<s)}var Or=.06393718451067248,zr=.06194817180037216,Dr=6.0761550028071145,Lr=.1315528159128946,Fr=40.00702225250195,Xr=.4316469416682083,Yr=class extends Tr{UNIT_OF_COST="distance";portUsagePenalty=Or;portUsagePenaltySq=zr;crossingPenalty=Dr;crossingPenaltySq=Lr;ripCost=Fr;baseMaxIterations=4e3;additionalMaxIterationsPerConnection=4e3;constructor(t){super({greedyMultiplier:Xr,rippingEnabled:!0,...t}),this.ripCost=t.ripCost??this.ripCost,this.portUsagePenalty=t.portUsagePenalty??this.portUsagePenalty,this.crossingPenalty=t.crossingPenalty??this.crossingPenalty,this.baseMaxIterations=t.baseMaxIterations??this.baseMaxIterations,this.additionalMaxIterationsPerConnection=t.additionalMaxIterationsPerConnection??this.additionalMaxIterationsPerConnection,this.MAX_ITERATIONS=this.baseMaxIterations+t.inputConnections.length*this.additionalMaxIterationsPerConnection,this.populateDistanceToEndMaps()}populateDistanceToEndMaps(){const t=new Set(this.connections.map(t=>t.endRegion));for(const e of t){const t=new Map,n=[];for(t.set(e.regionId,0),n.push({region:e,distance:0});n.length>0;){const{region:e,distance:s}=n.shift();for(const o of e.ports){const i=o.region1===e?o.region2:o.region1;t.has(i.regionId)||(t.set(i.regionId,s+1),n.push({region:i,distance:s+1}))}}for(const n of this.graph.ports){n.distanceToEndMap||(n.distanceToEndMap={});const s=t.get(n.region1.regionId)??1/0,o=t.get(n.region2.regionId)??1/0;n.distanceToEndMap[e.regionId]=Math.min(s,o)}}}estimateCostToEnd(t){const e=this.currentEndRegion.regionId;return t.distanceToEndMap[e]}getPortUsagePenalty(t){const e=t.ripCount??0;return e*this.portUsagePenalty+e*this.portUsagePenaltySq}computeIncreasedRegionCostIfPortsAreUsed(t,e,n){const s=function(t,e,n){const{minX:s,maxX:o,minY:i,maxY:r}=t.d.bounds,a=[Rr(e.d,s,o,i,r),Rr(n.d,s,o,i,r)];let c=0;const h=t.assignments??[];for(const t of h)Ar(a,[Rr(t.regionPort1.d,s,o,i,r),Rr(t.regionPort2.d,s,o,i,r)])&&c++;return c}(t,e,n);return s*this.crossingPenalty+s*this.crossingPenaltySq}getRipsRequiredForPortUsage(t,e,n){const s=function(t,e,n){const{minX:s,maxX:o,minY:i,maxY:r}=t.d.bounds,a=[Rr(e.d,s,o,i,r),Rr(n.d,s,o,i,r)],c=[],h=t.assignments??[];for(const t of h)Ar(a,[Rr(t.regionPort1.d,s,o,i,r),Rr(t.regionPort2.d,s,o,i,r)])&&c.push(t);return c}(t,e,n);return s.filter(t=>t.connection.mutuallyConnectedNetworkId!==this.currentConnection.mutuallyConnectedNetworkId)}routeSolvedHook(t){}routeStartedHook(t){}visualize(){return(t=>{const e=((t,e)=>{const n={arrows:[],circles:[],title:"Jumper Graph",lines:[],points:[],rects:[],texts:[],coordinateSystem:"cartesian"};for(const e of t.regions){const{bounds:t,isPad:s,isThroughJumper:o,isConnectionRegion:i}=e.d,r=(t.minX+t.maxX)/2,a=(t.minY+t.maxY)/2,c=t.maxX-t.minX,h=t.maxY-t.minY;let d;d=i?"rgba(255, 100, 255, 0.6)":o?"rgba(100, 200, 100, 0.5)":s?"rgba(255, 200, 100, 0.5)":"rgba(200, 200, 255, 0.1)",n.rects.push({center:{x:r,y:a},width:c-.1,height:h-.1,fill:d})}if(!e?.hidePortPoints)for(const e of t.ports){const t=e.region1.regionId.split(":").pop()??e.region1.regionId,s=e.region2.regionId.split(":").pop()??e.region2.regionId;n.circles.push({center:{x:e.d.x,y:e.d.y},radius:.05,fill:"rgba(128, 128, 128, 0.5)",label:`${t}-${s}`})}if(!e?.hideRegionPortLines)for(const e of t.ports){const t={x:(e.region1.d.bounds.minX+e.region1.d.bounds.maxX)/2,y:(e.region1.d.bounds.minY+e.region1.d.bounds.maxY)/2},s={x:(e.region2.d.bounds.minX+e.region2.d.bounds.maxX)/2,y:(e.region2.d.bounds.minY+e.region2.d.bounds.maxY)/2};n.lines.push({points:[t,{x:e.d.x,y:e.d.y},s],strokeColor:"rgba(100, 100, 100, 0.3)"})}if(e?.connections&&!e?.hideConnectionLines)for(const t of e.connections){const e=t.startRegion,s=t.endRegion,o={x:(e.d.bounds.minX+e.d.bounds.maxX)/2,y:(e.d.bounds.minY+e.d.bounds.maxY)/2},i={x:(s.d.bounds.minX+s.d.bounds.maxX)/2,y:(s.d.bounds.minY+s.d.bounds.maxY)/2},r=(o.x+i.x)/2,a=(o.y+i.y)/2;n.lines.push({points:[o,i],strokeColor:"rgba(255, 50, 150, 0.8)",strokeDash:"3 3"}),n.points.push({x:r,y:a,color:"rgba(200, 0, 100, 1)",label:t.connectionId})}return n})({regions:t.graph.regions,ports:t.graph.ports},{connections:t.connections,...t.iterations>0?{hideRegionPortLines:!0,hideConnectionLines:!0,hidePortPoints:!0}:{}});if(t.currentConnection&&!t.solved){const n=Er(t.currentConnection.connectionId),s=t.currentConnection.startRegion,o=t.currentConnection.endRegion,i={x:(s.d.bounds.minX+s.d.bounds.maxX)/2,y:(s.d.bounds.minY+s.d.bounds.maxY)/2},r={x:(o.d.bounds.minX+o.d.bounds.maxX)/2,y:(o.d.bounds.minY+o.d.bounds.maxY)/2};e.lines.push({points:[i,r],strokeColor:n,strokeDash:"10 5"}),e.points.push({x:i.x-.1,y:i.y+.1,color:n,label:[t.currentConnection.connectionId,"start"].join("\n")}),e.points.push({x:r.x-.1,y:r.y+.1,color:n,label:[t.currentConnection.connectionId,"end"].join("\n")})}for(const n of t.solvedRoutes){const t=Er(n.connection.connectionId),s=[];for(const t of n.path){const e=t.port;s.push({x:e.d.x,y:e.d.y})}s.length>0&&e.lines.push({points:s,strokeColor:t})}const n=t.candidateQueue.peekMany(10);for(let t=0;t<n.length;t++){const s=n[t],o=s.port,i=0===t;e.points.push({x:o.d.x,y:o.d.y,color:i?"green":"rgba(128, 128, 128, 0.25)",label:[s.port.portId,`g: ${s.g.toFixed(2)}`,`h: ${s.h.toFixed(2)}`,`f: ${s.f.toFixed(2)}`].join("\n")})}const s=n[0];if(!t.solved&&s&&t.currentConnection){const n=Er(t.currentConnection.connectionId),o=[];let i=s;for(;i;){const t=i.port;o.unshift({x:t.d.x,y:t.d.y}),i=i.parent}o.length>1&&e.lines.push({points:o,strokeColor:n})}return e})(this)}},$r=Object.create,kr=Object.defineProperty,Br=Object.getOwnPropertyDescriptor,jr=Object.getOwnPropertyNames,Wr=Object.getPrototypeOf,Hr=Object.prototype.hasOwnProperty,Ur=(t,e)=>function(){return e||(0,t[jr(t)[0]])((e={exports:{}}).exports,e),e.exports},Vr=(t,e,n)=>(n=null!=t?$r(Wr(t)):{},((t,e,n,s)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let o of jr(e))Hr.call(t,o)||o===n||kr(t,o,{get:()=>e[o],enumerable:!(s=Br(e,o))||s.enumerable});return t})(!e&&t&&t.__esModule?n:kr(n,"default",{value:t,enumerable:!0}),t)),Zr=Ur({"node_modules/is-buffer/index.js"(t,e){function n(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}e.exports=function(t){return null!=t&&(n(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&n(t.slice(0,0))}(t)||!!t._isBuffer)}}}),Gr=Ur({"node_modules/kind-of/index.js"(t,e){var n=Zr(),s=Object.prototype.toString;e.exports=function(t){if(void 0===t)return"undefined";if(null===t)return"null";if(!0===t||!1===t||t instanceof Boolean)return"boolean";if("string"==typeof t||t instanceof String)return"string";if("number"==typeof t||t instanceof Number)return"number";if("function"==typeof t||t instanceof Function)return"function";if(void 0!==Array.isArray&&Array.isArray(t))return"array";if(t instanceof RegExp)return"regexp";if(t instanceof Date)return"date";var e=s.call(t);return"[object RegExp]"===e?"regexp":"[object Date]"===e?"date":"[object Arguments]"===e?"arguments":"[object Error]"===e?"error":n(t)?"buffer":"[object Set]"===e?"set":"[object WeakSet]"===e?"weakset":"[object Map]"===e?"map":"[object WeakMap]"===e?"weakmap":"[object Symbol]"===e?"symbol":"[object Int8Array]"===e?"int8array":"[object Uint8Array]"===e?"uint8array":"[object Uint8ClampedArray]"===e?"uint8clampedarray":"[object Int16Array]"===e?"int16array":"[object Uint16Array]"===e?"uint16array":"[object Int32Array]"===e?"int32array":"[object Uint32Array]"===e?"uint32array":"[object Float32Array]"===e?"float32array":"[object Float64Array]"===e?"float64array":"object"}}}),Jr=Ur({"node_modules/rename-keys/index.js"(t,e){!function(){function t(t,e){if("function"!=typeof e)return t;var n={};for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&(n[e(s,t[s])||s]=t[s]);return n}void 0!==e&&e.exports?e.exports=t:"function"==typeof define&&define.amd?define([],function(){return t}):window.rename=t}()}}),qr=Ur({"node_modules/deep-rename-keys/index.js"(t,e){var n=Gr(),s=Jr();e.exports=function t(e,o){var i=n(e);if("object"!==i&&"array"!==i)throw new Error("expected an object");var r=[];for(var a in"object"===i&&(e=s(e,o),r={}),e)if(e.hasOwnProperty(a)){var c=e[a];"object"===n(c)||"array"===n(c)?r[a]=t(c,o):r[a]=c}return r}}}),Kr=Ur({"node_modules/eventemitter3/index.js"(t,e){var n=Object.prototype.hasOwnProperty,s="~";function o(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new o,this._eventsCount=0}Object.create&&(o.prototype=Object.create(null),(new o).__proto__||(s=!1)),r.prototype.eventNames=function(){var t,e,o=[];if(0===this._eventsCount)return o;for(e in t=this._events)n.call(t,e)&&o.push(s?e.slice(1):e);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(t)):o},r.prototype.listeners=function(t,e){var n=s?s+t:t,o=this._events[n];if(e)return!!o;if(!o)return[];if(o.fn)return[o.fn];for(var i=0,r=o.length,a=new Array(r);i<r;i++)a[i]=o[i].fn;return a},r.prototype.emit=function(t,e,n,o,i,r){var a=s?s+t:t;if(!this._events[a])return!1;var c,h,d=this._events[a],l=arguments.length;if(d.fn){switch(d.once&&this.removeListener(t,d.fn,void 0,!0),l){case 1:return d.fn.call(d.context),!0;case 2:return d.fn.call(d.context,e),!0;case 3:return d.fn.call(d.context,e,n),!0;case 4:return d.fn.call(d.context,e,n,o),!0;case 5:return d.fn.call(d.context,e,n,o,i),!0;case 6:return d.fn.call(d.context,e,n,o,i,r),!0}for(h=1,c=new Array(l-1);h<l;h++)c[h-1]=arguments[h];d.fn.apply(d.context,c)}else{var u,p=d.length;for(h=0;h<p;h++)switch(d[h].once&&this.removeListener(t,d[h].fn,void 0,!0),l){case 1:d[h].fn.call(d[h].context);break;case 2:d[h].fn.call(d[h].context,e);break;case 3:d[h].fn.call(d[h].context,e,n);break;case 4:d[h].fn.call(d[h].context,e,n,o);break;default:if(!c)for(u=1,c=new Array(l-1);u<l;u++)c[u-1]=arguments[u];d[h].fn.apply(d[h].context,c)}}return!0},r.prototype.on=function(t,e,n){var o=new i(e,n||this),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.once=function(t,e,n){var o=new i(e,n||this,!0),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=s?s+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new o:delete this._events[r],this;var a=this._events[r];if(a.fn)a.fn!==e||i&&!a.once||n&&a.context!==n||(0===--this._eventsCount?this._events=new o:delete this._events[r]);else{for(var c=0,h=[],d=a.length;c<d;c++)(a[c].fn!==e||i&&!a[c].once||n&&a[c].context!==n)&&h.push(a[c]);h.length?this._events[r]=1===h.length?h[0]:h:0===--this._eventsCount?this._events=new o:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=s?s+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new o:delete this._events[e])):(this._events=new o,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=s,r.EventEmitter=r,void 0!==e&&(e.exports=r)}}),Qr=Ur({"node_modules/xml-lexer/dist/lexer.js"(t,e){function n(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var s=Kr(),o=function(){},i={data:"state-data",cdata:"state-cdata",tagBegin:"state-tag-begin",tagName:"state-tag-name",tagEnd:"state-tag-end",attributeNameStart:"state-attribute-name-start",attributeName:"state-attribute-name",attributeNameEnd:"state-attribute-name-end",attributeValueBegin:"state-attribute-value-begin",attributeValue:"state-attribute-value"},r={lt:"action-lt",gt:"action-gt",space:"action-space",equal:"action-equal",quote:"action-quote",slash:"action-slash",char:"action-char",error:"action-error"},a={text:"text",openTag:"open-tag",closeTag:"close-tag",attributeName:"attribute-name",attributeValue:"attribute-value"},c={" ":r.space,"\t":r.space,"\n":r.space,"\r":r.space,"<":r.lt,">":r.gt,'"':r.quote,"'":r.quote,"=":r.equal,"/":r.slash};e.exports={State:i,Action:r,Type:a,create:function(t){var e,h,d,l,u,p,m,f,g,y;t=Object.assign({debug:!1},t);var x=new s,v=i.data,S="",P="",b="",M="",N="",I="",C=function(e,n){if("?"!==P[0]&&"!"!==P[0]){var s={type:e,value:n};t.debug&&console.log("emit:",s),x.emit("data",s)}};x.stateMachine=(n(y={},i.data,(n(e={},r.lt,function(){S.trim()&&C(a.text,S),P="",N=!1,v=i.tagBegin}),n(e,r.char,function(t){S+=t}),e)),n(y,i.cdata,n({},r.char,function(t){"]]>"===(S+=t).substr(-3)&&(C(a.text,S.slice(0,-3)),S="",v=i.data)})),n(y,i.tagBegin,(n(h={},r.space,o),n(h,r.char,function(t){P=t,v=i.tagName}),n(h,r.slash,function(){P="",N=!0}),h)),n(y,i.tagName,(n(d={},r.space,function(){N?v=i.tagEnd:(v=i.attributeNameStart,C(a.openTag,P))}),n(d,r.gt,function(){C(N?a.closeTag:a.openTag,P),S="",v=i.data}),n(d,r.slash,function(){v=i.tagEnd,C(a.openTag,P)}),n(d,r.char,function(t){"![CDATA["===(P+=t)&&(v=i.cdata,S="",P="")}),d)),n(y,i.tagEnd,(n(l={},r.gt,function(){C(a.closeTag,P),S="",v=i.data}),n(l,r.char,o),l)),n(y,i.attributeNameStart,(n(u={},r.char,function(t){b=t,v=i.attributeName}),n(u,r.gt,function(){S="",v=i.data}),n(u,r.space,o),n(u,r.slash,function(){N=!0,v=i.tagEnd}),u)),n(y,i.attributeName,(n(p={},r.space,function(){v=i.attributeNameEnd}),n(p,r.equal,function(){C(a.attributeName,b),v=i.attributeValueBegin}),n(p,r.gt,function(){M="",C(a.attributeName,b),C(a.attributeValue,M),S="",v=i.data}),n(p,r.slash,function(){N=!0,M="",C(a.attributeName,b),C(a.attributeValue,M),v=i.tagEnd}),n(p,r.char,function(t){b+=t}),p)),n(y,i.attributeNameEnd,(n(m={},r.space,o),n(m,r.equal,function(){C(a.attributeName,b),v=i.attributeValueBegin}),n(m,r.gt,function(){M="",C(a.attributeName,b),C(a.attributeValue,M),S="",v=i.data}),n(m,r.char,function(t){M="",C(a.attributeName,b),C(a.attributeValue,M),b=t,v=i.attributeName}),m)),n(y,i.attributeValueBegin,(n(f={},r.space,o),n(f,r.quote,function(t){I=t,M="",v=i.attributeValue}),n(f,r.gt,function(){C(a.attributeValue,M=""),S="",v=i.data}),n(f,r.char,function(t){I="",M=t,v=i.attributeValue}),f)),n(y,i.attributeValue,(n(g={},r.space,function(t){I?M+=t:(C(a.attributeValue,M),v=i.attributeNameStart)}),n(g,r.quote,function(t){I===t?(C(a.attributeValue,M),v=i.attributeNameStart):M+=t}),n(g,r.gt,function(t){I?M+=t:(C(a.attributeValue,M),S="",v=i.data)}),n(g,r.slash,function(t){I?M+=t:(C(a.attributeValue,M),N=!0,v=i.tagEnd)}),n(g,r.char,function(t){M+=t}),g)),y);var _=function(e){t.debug&&console.log(v,e);var n=x.stateMachine[v],s=n[function(t){return c[t]||r.char}(e)]||n[r.error]||n[r.char];s(e)};return x.write=function(t){for(var e=t.length,n=0;n<e;n++)_(t[n])},x}}}}),ta=Ur({"node_modules/xml-reader/dist/reader.js"(t,e){var n=Kr(),s=Qr(),o=s.Type,i={element:"element",text:"text"},r=function(t){return Object.assign({name:"",type:i.element,value:"",parent:null,attributes:{},children:[]},t)},a=function(t){t=Object.assign({stream:!1,parentNodes:!0,doneEvent:"done",tagPrefix:"tag:",emitTopLevelOnly:!1,debug:!1},t);var e=void 0,a=void 0,c=void 0,h=void 0,d=new n,l=function(n){switch(n.type){case o.openTag:if(null===c)(c=a).name=n.value;else{var s=r({name:n.value,parent:c});c.children.push(s),c=s}break;case o.closeTag:var l=c.parent;if(t.parentNodes||(c.parent=null),c.name!==n.value)break;t.stream&&l===a&&(a.children=[],c.parent=null),t.emitTopLevelOnly&&l!==a||(d.emit(t.tagPrefix+c.name,c),d.emit("tag",c.name,c)),c===a&&(e.removeAllListeners("data"),d.emit(t.doneEvent,c),a=null),c=l;break;case o.text:c&&c.children.push(r({type:i.text,value:n.value,parent:t.parentNodes?c:null}));break;case o.attributeName:h=n.value,c.attributes[h]="";break;case o.attributeValue:c.attributes[h]=n.value}};return d.reset=function(){(e=s.create({debug:t.debug})).on("data",l),a=r(),c=null,h="",d.parse=e.write},d.reset(),d};e.exports={parseSync:function(t,e){e=Object.assign({},e,{stream:!1,tagPrefix:":"});var n=a(e),s=void 0;return n.on("done",function(t){s=t}),n.parse(t),s},create:a,NodeType:i}}}),{cos:ea,sin:na,PI:sa}=Math,{tan:oa}=Math,ia=(Vr(qr()),Vr(ta()),class{MAX_ITERATIONS=1e5;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};_setupDone=!1;setup(){this._setupDone||(this._setup(),this._setupDone=!0)}_setup(){}step(){if(this._setupDone||this.setup(),!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,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`,this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}getOutput(){return null}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}}),ra=t=>t?`hsl(${(t=>{let e=0;for(let n=0;n<t.length;n++)e=779*t.charCodeAt(n)+((e<<5)-e);return e})(t)%360}, 100%, 50%)`:"rgba(0, 0, 0, 0.5)",aa=t=>[[{x:t.minX,y:t.minY},{x:t.maxX,y:t.minY}],[{x:t.maxX,y:t.minY},{x:t.maxX,y:t.maxY}],[{x:t.maxX,y:t.maxY},{x:t.minX,y:t.maxY}],[{x:t.minX,y:t.maxY},{x:t.minX,y:t.minY}]];function ca(t,e){const{minX:n,maxX:s,minY:o,maxY:i}=e,r=s-n,a=i-o,c=1e-6;return Math.abs(t.y-i)<c?t.x-n:Math.abs(t.x-s)<c?r+(i-t.y):Math.abs(t.y-o)<c?r+a+(s-t.x):Math.abs(t.x-n)<c?2*r+a+(t.y-o):0}function ha(t,e){const{minX:n,maxX:s,minY:o,maxY:i}=e,r=1e-6,a=Math.abs(t.y-i)<r,c=Math.abs(t.y-o)<r,h=Math.abs(t.x-s)<r,d=Math.abs(t.x-n)<r;if(a&&h)return{x:-Math.SQRT1_2,y:-Math.SQRT1_2};if(a&&d)return{x:Math.SQRT1_2,y:-Math.SQRT1_2};if(c&&h)return{x:-Math.SQRT1_2,y:Math.SQRT1_2};if(c&&d)return{x:Math.SQRT1_2,y:Math.SQRT1_2};if(a)return{x:0,y:-1};if(c)return{x:0,y:1};if(h)return{x:-1,y:0};if(d)return{x:1,y:0};const l=(o+i)/2,u=(n+s)/2-t.x,p=l-t.y,m=Math.hypot(u,p);return m>0?{x:u/m,y:p/m}:{x:0,y:-1}}function da(t,e,n,s,o,i,r,a,c,h){for(let d=0;d<=h;d++){const l=d/h,u=1-l,p=u*u,m=p*u,f=l*l,g=f*l,y=2*d;c[y]=m*t+3*p*l*n+3*u*f*o+g*r,c[y+1]=m*e+3*p*l*s+3*u*f*i+g*a}}function la(t,e,n,s,o){const i=[];for(let r=0;r<=o;r++){const a=r/o,c=1-a,h=c*c,d=h*c,l=a*a,u=l*a;i.push({x:d*t.x+3*h*a*e.x+3*c*l*n.x+u*s.x,y:d*t.y+3*h*a*e.y+3*c*l*n.y+u*s.y})}return i}function ua(t,e,n,s,o,i){const r=o-n,a=i-s,c=r*r+a*a;if(0===c){const o=t-n,i=e-s;return o*o+i*i}const h=Math.max(0,Math.min(1,((t-n)*r+(e-s)*a)/c)),d=t-(n+h*r),l=e-(s+h*a);return d*d+l*l}function pa(t,e,n,s,o,i,r,a){const c=(r-o)*(e-i)-(a-i)*(t-o),h=(r-o)*(s-i)-(a-i)*(n-o),d=(n-t)*(i-e)-(s-e)*(o-t),l=(n-t)*(a-e)-(s-e)*(r-t);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)?0:Math.min(ua(t,e,o,i,r,a),ua(n,s,o,i,r,a),ua(o,i,t,e,n,s),ua(r,a,t,e,n,s))}function ma(t,e,n,s,o,i,r,a){const c=(r-o)*(e-i)-(a-i)*(t-o),h=(r-o)*(s-i)-(a-i)*(n-o),d=(n-t)*(i-e)-(s-e)*(o-t),l=(n-t)*(a-e)-(s-e)*(r-t);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)}function fa(t,e,n,s,o){const i=t=>(t%o+o)%o,r=i(t),a=i(e),c=i(n),h=i(s),[d,l]=r<a?[r,a]:[a,r];return c>d&&c<l&&h>d&&h<l}function ga(t,e){let n=1/0,s=-1/0,o=1/0,i=-1/0;for(let r=0;r<e;r++){const e=t[2*r],a=t[2*r+1];e<n&&(n=e),e>s&&(s=e),a<o&&(o=a),a>i&&(i=a)}return{minX:n,maxX:s,minY:o,maxY:i}}var ya=class extends ia{constructor(t){super(),this.problem=t;for(const t of this.problem.obstacles)t.outerSegments=aa(t);this.precomputeObstacles()}outputTraces=[];traces=[];optimizationStep=0;maxOptimizationSteps=100;sampledPoints=[];traceBounds=[];obstacleSegments=new Float64Array(0);obstacleNetworkIds=[];numObstacleSegments=0;collisionPairs=[];lastCost=1/0;stagnantSteps=0;effectiveTraceToTraceSpacing=0;getConstructorParams(){return this.problem}precomputeObstacles(){const{obstacles:t}=this.problem;let e=0;for(const n of t)n.outerSegments&&(e+=n.outerSegments.length);this.obstacleSegments=new Float64Array(4*e),this.obstacleNetworkIds=[],this.numObstacleSegments=e;let n=0;for(const e of t)if(e.outerSegments)for(const t of e.outerSegments)this.obstacleSegments[n++]=t[0].x,this.obstacleSegments[n++]=t[0].y,this.obstacleSegments[n++]=t[1].x,this.obstacleSegments[n++]=t[1].y,this.obstacleNetworkIds.push(e.networkId)}initializeTraces(){const{bounds:t,waypointPairs:e}=this.problem,{minX:n,maxX:s,minY:o,maxY:i}=t,r=s-n,a=i-o,c=2*r+2*a,h=function(t){return{x:(t.minX+t.maxX)/2,y:(t.minY+t.maxY)/2}}(t),d=e.map((e,n)=>({pair:e,t1:ca(e.start,t),t2:ca(e.end,t),idx:n})),l=d.map(()=>[]),u=d.map(()=>[]);for(const t of d)for(const e of d)if(t.idx!==e.idx){if(t.pair.networkId&&e.pair.networkId&&t.pair.networkId===e.pair.networkId)continue;fa(e.t1,e.t2,t.t1,t.t2,c)&&(l[t.idx].push(e.idx),u[e.idx].push(t.idx))}const p=l.map(t=>t.length),m=Math.max(...p,1);this.traces=d.map(({pair:e,t1:n,t2:s,idx:o})=>{const i=ha(e.start,t),c=ha(e.end,t),d=Math.hypot(e.end.x-e.start.x,e.end.y-e.start.y),f=p[o]/m,g=(e.start.x+e.end.x)/2,y=(e.start.y+e.end.y)/2,x=d*(.25+.15*(1-Math.hypot(g-h.x,y-h.y)/Math.hypot(r/2,a/2)))*(1-.3*f),v=.05*Math.min(r,a),S=Math.max(v,x),P=Math.max(v,x);return{waypointPair:e,ctrl1:{x:e.start.x+S*i.x,y:e.start.y+S*i.y},ctrl2:{x:e.end.x+P*c.x,y:e.end.y+P*c.y},networkId:e.networkId,t1:n,t2:s,perpDir1:i,perpDir2:c,d1:S,d2:P,containedBy:l[o],contains:u[o]}}),this.sampledPoints=this.traces.map(()=>new Float64Array(12)),this.traceBounds=this.traces.map(()=>({minX:0,maxX:0,minY:0,maxY:0})),this.updateSampledTraces(),this.updateCollisionPairs()}updateSampledTraces(){for(let t=0;t<this.traces.length;t++){const e=this.traces[t];da(e.waypointPair.start.x,e.waypointPair.start.y,e.ctrl1.x,e.ctrl1.y,e.ctrl2.x,e.ctrl2.y,e.waypointPair.end.x,e.waypointPair.end.y,this.sampledPoints[t],5),this.traceBounds[t]=ga(this.sampledPoints[t],6)}}updateSingleTraceSample(t){const e=this.traces[t];da(e.waypointPair.start.x,e.waypointPair.start.y,e.ctrl1.x,e.ctrl1.y,e.ctrl2.x,e.ctrl2.y,e.waypointPair.end.x,e.waypointPair.end.y,this.sampledPoints[t],5),this.traceBounds[t]=ga(this.sampledPoints[t],6)}updateControlPointsFromDistances(t){const e=this.traces[t],{minX:n,maxX:s,minY:o,maxY:i}=this.problem.bounds,r=1e-6;let a=e.waypointPair.start.x+e.d1*e.perpDir1.x,c=e.waypointPair.start.y+e.d1*e.perpDir1.y,h=e.waypointPair.end.x+e.d2*e.perpDir2.x,d=e.waypointPair.end.y+e.d2*e.perpDir2.y;const l=e.waypointPair.start;Math.abs(l.x-n)<r&&(a=Math.max(a,n)),Math.abs(l.x-s)<r&&(a=Math.min(a,s)),Math.abs(l.y-o)<r&&(c=Math.max(c,o)),Math.abs(l.y-i)<r&&(c=Math.min(c,i));const u=e.waypointPair.end;Math.abs(u.x-n)<r&&(h=Math.max(h,n)),Math.abs(u.x-s)<r&&(h=Math.min(h,s)),Math.abs(u.y-o)<r&&(d=Math.max(d,o)),Math.abs(u.y-i)<r&&(d=Math.min(d,i)),a=Math.max(n,Math.min(s,a)),c=Math.max(o,Math.min(i,c)),h=Math.max(n,Math.min(s,h)),d=Math.max(o,Math.min(i,d)),e.ctrl1.x=a,e.ctrl1.y=c,e.ctrl2.x=h,e.ctrl2.y=d}updateCollisionPairs(){const t=this.effectiveTraceToTraceSpacing;this.collisionPairs=[];for(let e=0;e<this.traces.length;e++)for(let n=e+1;n<this.traces.length;n++){const s=this.traces[e],o=this.traces[n];if(s.networkId&&o.networkId&&s.networkId===o.networkId)continue;const i=this.traceBounds[e],r=this.traceBounds[n];i.maxX+t>=r.minX&&r.maxX+t>=i.minX&&i.maxY+t>=r.minY&&r.maxY+t>=i.minY&&this.collisionPairs.push([e,n])}}computeTotalCost(){const{preferredObstacleToTraceSpacing:t}=this.problem,e=this.effectiveTraceToTraceSpacing,n=e**2,s=t**2;let o=0;for(const[t,s]of this.collisionPairs){const i=this.sampledPoints[t],r=this.sampledPoints[s];for(let t=0;t<5;t++){const s=i[2*t],a=i[2*t+1],c=i[2*(t+1)],h=i[2*(t+1)+1];for(let t=0;t<5;t++){const i=pa(s,a,c,h,r[2*t],r[2*t+1],r[2*(t+1)],r[2*(t+1)+1]);if(i<n){o+=(e-Math.sqrt(i))**2,i<1e-18&&(o+=20*n)}}}}for(let e=0;e<this.traces.length;e++){const n=this.traces[e],i=this.sampledPoints[e],r=this.traceBounds[e];for(let e=0;e<this.numObstacleSegments;e++){if(n.networkId&&this.obstacleNetworkIds[e]&&n.networkId===this.obstacleNetworkIds[e])continue;const a=4*e,c=this.obstacleSegments[a],h=this.obstacleSegments[a+1],d=this.obstacleSegments[a+2],l=this.obstacleSegments[a+3],u=Math.min(c,d),p=Math.max(c,d),m=Math.min(h,l),f=Math.max(h,l);if(!(r.maxX+t<u||p+t<r.minX||r.maxY+t<m||f+t<r.minY))for(let e=0;e<5;e++){const n=pa(i[2*e],i[2*e+1],i[2*(e+1)],i[2*(e+1)+1],c,h,d,l);if(n<s){o+=(t-Math.sqrt(n))**2,n<1e-18&&(o+=20*s)}}}}return o}computeCostForTrace(t){const{preferredObstacleToTraceSpacing:e}=this.problem,n=this.effectiveTraceToTraceSpacing,s=n**2,o=e**2,i=this.traces[t],r=this.sampledPoints[t],a=this.traceBounds[t];let c=0;for(let e=0;e<this.traces.length;e++){if(e===t)continue;const o=this.traces[e];if(i.networkId&&o.networkId&&i.networkId===o.networkId)continue;const h=this.traceBounds[e];if(a.maxX+n<h.minX||h.maxX+n<a.minX||a.maxY+n<h.minY||h.maxY+n<a.minY)continue;const d=this.sampledPoints[e];for(let t=0;t<5;t++){const e=r[2*t],o=r[2*t+1],i=r[2*(t+1)],a=r[2*(t+1)+1];for(let t=0;t<5;t++){const r=pa(e,o,i,a,d[2*t],d[2*t+1],d[2*(t+1)],d[2*(t+1)+1]);if(r<s){c+=(n-Math.sqrt(r))**2,r<1e-18&&(c+=20*s)}}}}for(let t=0;t<this.numObstacleSegments;t++){if(i.networkId&&this.obstacleNetworkIds[t]&&i.networkId===this.obstacleNetworkIds[t])continue;const n=4*t,s=this.obstacleSegments[n],h=this.obstacleSegments[n+1],d=this.obstacleSegments[n+2],l=this.obstacleSegments[n+3],u=Math.min(s,d),p=Math.max(s,d),m=Math.min(h,l),f=Math.max(h,l);if(!(a.maxX+e<u||p+e<a.minX||a.maxY+e<m||f+e<a.minY))for(let t=0;t<5;t++){const n=pa(r[2*t],r[2*t+1],r[2*(t+1)],r[2*(t+1)+1],s,h,d,l);if(n<o){c+=(e-Math.sqrt(n))**2,n<1e-18&&(c+=20*o)}}}return c}tracesIntersect(t,e){const n=this.traces[t],s=this.traces[e],o=15,i=new Float64Array(32),r=new Float64Array(32);da(n.waypointPair.start.x,n.waypointPair.start.y,n.ctrl1.x,n.ctrl1.y,n.ctrl2.x,n.ctrl2.y,n.waypointPair.end.x,n.waypointPair.end.y,i,o),da(s.waypointPair.start.x,s.waypointPair.start.y,s.ctrl1.x,s.ctrl1.y,s.ctrl2.x,s.ctrl2.y,s.waypointPair.end.x,s.waypointPair.end.y,r,o);for(let t=0;t<o;t++){const e=i[2*t],n=i[2*t+1],s=i[2*(t+1)],a=i[2*(t+1)+1];for(let t=0;t<o;t++){if(ma(e,n,s,a,r[2*t],r[2*t+1],r[2*(t+1)],r[2*(t+1)+1]))return!0}}return!1}findIntersectingPairs(){const t=[];for(let e=0;e<this.traces.length;e++)for(let n=e+1;n<this.traces.length;n++){const s=this.traces[e],o=this.traces[n];if(s.networkId&&o.networkId&&s.networkId===o.networkId)continue;const i=this.traceBounds[e],r=this.traceBounds[n];i.maxX<r.minX||r.maxX<i.minX||i.maxY<r.minY||r.maxY<i.minY||this.tracesIntersect(e,n)&&t.push([e,n])}return t}resolveIntersections(){const{bounds:t,preferredTraceToTraceSpacing:e}=this.problem,{minX:n,maxX:s,minY:o,maxY:i}=t,r=Math.min(s-n,i-o),a=.02*r,c=1.5*r,h=this.findIntersectingPairs();if(0===h.length)return 0;let d=0;for(const[t,n]of h){const s=this.traces[t],o=this.traces[n];if(!this.tracesIntersect(t,n))continue;let i,r;if(s.containedBy.includes(n))i=n,r=t;else if(o.containedBy.includes(t))i=t,r=n;else{(s.d1+s.d2)/2<(o.d1+o.d2)/2?(i=t,r=n):(i=n,r=t)}const h=this.traces[i],l=this.traces[r],u=h.d1,p=h.d2,m=l.d1,f=l.d2,g=2*e,y=[{innerMult:1,outerMult:0},{innerMult:0,outerMult:1},{innerMult:.5,outerMult:.5},{innerMult:2,outerMult:0},{innerMult:1,outerMult:1},{innerMult:3,outerMult:0},{innerMult:2,outerMult:1},{innerMult:4,outerMult:0}];let x=this.computeTotalCost(),v=null;for(const t of y)if(h.d1=u,h.d2=p,l.d1=m,l.d2=f,l.d1=Math.min(c,m+g*t.innerMult),l.d2=Math.min(c,f+g*t.innerMult),h.d1=Math.max(a,u-g*t.outerMult),h.d2=Math.max(a,p-g*t.outerMult),this.updateControlPointsFromDistances(r),this.updateControlPointsFromDistances(i),this.updateSingleTraceSample(r),this.updateSingleTraceSample(i),!this.tracesIntersect(i,r)){const e=this.computeTotalCost();(null===v||e<x)&&(x=e,v=t)}v?(l.d1=Math.min(c,m+g*v.innerMult),l.d2=Math.min(c,f+g*v.innerMult),h.d1=Math.max(a,u-g*v.outerMult),h.d2=Math.max(a,p-g*v.outerMult),this.updateControlPointsFromDistances(r),this.updateControlPointsFromDistances(i),this.updateSingleTraceSample(r),this.updateSingleTraceSample(i),d++):(h.d1=u,h.d2=p,l.d1=m,l.d2=f,this.updateControlPointsFromDistances(i),this.updateControlPointsFromDistances(r),this.updateSingleTraceSample(i),this.updateSingleTraceSample(r))}return d}optimizeStep(){const{bounds:t}=this.problem,{minX:e,maxX:n,minY:s,maxY:o}=t,i=Math.min(n-e,o-s),r=this.effectiveTraceToTraceSpacing,a=4*(1-this.optimizationStep/this.maxOptimizationSteps)+.5,c=.02*i,h=1.5*i,d=[];for(let t=0;t<this.traces.length;t++)d.push({idx:t,cost:this.computeCostForTrace(t)});d.sort((t,e)=>e.cost-t.cost);for(const{idx:t,cost:e}of d){if(0===e)continue;const n=this.traces[t],s=e>100?2:1,o=[a*s,1.5*a*s,.5*a];for(const s of o){const o=e>100?[s,-s,2*s,2*-s,3*s,3*-s,2*r,2*-r]:[s,-s,2*s,2*-s];let i=this.computeCostForTrace(t),a=n.d1,d=n.d2;const l=n.d1,u=n.d2;for(const e of o){n.d1=Math.max(c,Math.min(h,l+e)),this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t);const s=this.computeCostForTrace(t);s<i&&(i=s,a=n.d1,d=u),n.d1=l,this.updateControlPointsFromDistances(t),n.d2=Math.max(c,Math.min(h,u+e)),this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t);const o=this.computeCostForTrace(t);o<i&&(i=o,a=l,d=n.d2),n.d2=u,this.updateControlPointsFromDistances(t),n.d1=Math.max(c,Math.min(h,l+e)),n.d2=Math.max(c,Math.min(h,u+e)),this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t);const r=this.computeCostForTrace(t);r<i&&(i=r,a=n.d1,d=n.d2),n.d1=l,n.d2=u,this.updateControlPointsFromDistances(t),n.d1=Math.max(c,Math.min(h,l+e)),n.d2=Math.max(c,Math.min(h,u-e)),this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t);const p=this.computeCostForTrace(t);p<i&&(i=p,a=n.d1,d=n.d2),n.d1=l,n.d2=u,this.updateControlPointsFromDistances(t)}if(n.d1=a,n.d2=d,this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t),i<.9*e)break}}this.optimizationStep%10==0&&this.updateCollisionPairs()}buildOutputTraces(){this.outputTraces=this.traces.map(t=>({waypointPair:t.waypointPair,points:la(t.waypointPair.start,t.ctrl1,t.ctrl2,t.waypointPair.end,20),networkId:t.networkId}))}_step(){if(0===this.traces.length&&(this.effectiveTraceToTraceSpacing=3*this.problem.preferredTraceToTraceSpacing,this.initializeTraces(),this.lastCost=this.computeTotalCost(),this.stagnantSteps=0),this.optimizationStep<this.maxOptimizationSteps){const t=3,e=t+(1-t)*(this.optimizationStep/this.maxOptimizationSteps);if(this.effectiveTraceToTraceSpacing=this.problem.preferredTraceToTraceSpacing*e,this.optimizeStep(),this.optimizationStep++,this.optimizationStep%10==0){this.resolveIntersections()>0&&this.updateCollisionPairs()}const n=this.computeTotalCost();if(0===n)this.optimizationStep=this.maxOptimizationSteps;else if(n>=.99*this.lastCost){if(this.stagnantSteps++,this.stagnantSteps>10){this.resolveIntersections()>0?(this.updateCollisionPairs(),this.stagnantSteps=0):this.stagnantSteps>15&&(this.optimizationStep=this.maxOptimizationSteps)}}else this.stagnantSteps=0;this.lastCost=n}this.optimizationStep>=this.maxOptimizationSteps&&(this.resolveIntersections(),this.buildOutputTraces(),this.solved=!0)}visualize(){return this.traces.length>0&&this.buildOutputTraces(),((t,e=[])=>{const n={arrows:[],circles:[],lines:[],rects:[],coordinateSystem:"cartesian",points:[],texts:[],title:"Curvy Trace Problem"};n.lines.push({points:[{x:t.bounds.minX,y:t.bounds.minY},{x:t.bounds.maxX,y:t.bounds.minY},{x:t.bounds.maxX,y:t.bounds.maxY},{x:t.bounds.minX,y:t.bounds.maxY},{x:t.bounds.minX,y:t.bounds.minY}],strokeColor:"rgba(0, 0, 0, 0.1)"});for(const e of t.waypointPairs)n.points.push({...e.start,label:`start ${e.networkId??""}`,color:ra(e.networkId)}),n.points.push({...e.end,label:`end ${e.networkId??""}`,color:ra(e.networkId)});for(const e of t.obstacles)n.rects.push({center:e.center,width:e.maxX-e.minX,height:e.maxY-e.minY,fill:"rgba(128, 128, 128, 0.3)",stroke:"rgba(128, 128, 128, 0.8)",label:`netId: ${e.networkId}`});for(const t of e)n.lines.push({points:t.points,strokeColor:ra(t.networkId)});return n})(this.problem,this.outputTraces)}},xa=class extends y{constructorParams;nodeWithPortPoints;colorMap;traceWidth;hyperParameters;jumperGraphSolver=null;xyConnections=[];graphBounds=null;jumperLocations=[];solvedRoutes=[];jumpers=[];phase="jumperGraph";curvySolvers=[];currentCurvySolverIndex=0;routeInfos=[];regionCurvedPaths=new Map;constructor(t){super(),this.constructorParams=t,this.nodeWithPortPoints=t.nodeWithPortPoints,this.colorMap=t.colorMap??{},this.traceWidth=t.traceWidth??.15,this.hyperParameters=t.hyperParameters??{},this.MAX_ITERATIONS=1e6,0===Object.keys(this.colorMap).length&&(this.colorMap=this._buildColorMap())}getConstructorParams(){return this.constructorParams}_buildColorMap(){const t=["#e6194b","#3cb44b","#ffe119","#4363d8","#f58231","#911eb4","#46f0f0","#f032e6","#bcf60c","#fabebe"],e={},n=new Set;for(const t of this.nodeWithPortPoints.portPoints)n.add(t.connectionName);let s=0;for(const o of Array.from(n))e[o]=t[s%t.length],s++;return e}_getPatternConfig(){return{cols:this.hyperParameters.COLS??1,rows:this.hyperParameters.ROWS??1}}_initializeGraph(){const t=this.nodeWithPortPoints,e=this._getPatternConfig(),n=this.hyperParameters.ORIENTATION??"vertical",s={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};this.graphBounds=s;const o=Mr({cols:e.cols,rows:e.rows,marginX:Math.max(1.2,.3*e.cols),marginY:Math.max(1.2,.3*e.rows),outerPaddingX:.4,outerPaddingY:.4,parallelTracesUnderJumperCount:3,innerColChannelPointCount:3,innerRowChannelPointCount:3,outerChannelXPointCount:3,outerChannelYPointCount:3,regionsBetweenPads:!0,orientation:n,bounds:s});if(o.regions.length>0){let t=1/0,e=-1/0,n=1/0,i=-1/0;for(const s of o.regions){if(!s.d?.isPad)continue;const o=s.d?.bounds;o&&(t=Math.min(t,o.minX),e=Math.max(e,o.maxX),n=Math.min(n,o.minY),i=Math.max(i,o.maxY))}const r=1;if(t-r<s.minX||e+r>s.maxX||n-r<s.minY||i+r>s.maxY)return this.error=`baseGraph bounds (${t.toFixed(2)}, ${n.toFixed(2)}, ${e.toFixed(2)}, ${i.toFixed(2)}) exceed node bounds (${s.minX.toFixed(2)}, ${s.minY.toFixed(2)}, ${s.maxX.toFixed(2)}, ${s.maxY.toFixed(2)})`,this.failed=!0,!1}this.jumperLocations=o.jumperLocations?.map(t=>({center:t.center,orientation:t.orientation,padRegions:t.padRegions}))??[];const i=new Map;for(const e of t.portPoints){const t=i.get(e.connectionName);t?t.points.push(e):i.set(e.connectionName,{points:[e],rootConnectionName:e.rootConnectionName})}this.xyConnections=[];for(const[t,e]of Array.from(i.entries()))e.points.length<2||this.xyConnections.push({start:{x:e.points[0].x,y:e.points[0].y},end:{x:e.points[1].x,y:e.points[1].y},connectionId:t});if(0===this.xyConnections.length)return this.solved=!0,!0;const r=((t,e)=>{const n=[...t.regions],s=[...t.ports],o=[],i=mr(t.regions);for(const r of e){const{start:e,end:a,connectionId:c}=r,h=Ir(`conn:${c}:start`,e.x,e.y);n.push(h);const d=Ir(`conn:${c}:end`,a.x,a.y);n.push(d);const l=Cr(e.x,e.y,t.regions,i);if(l){const t=Nr(`conn:${c}:start-port`,h,l.region,l.portPosition);s.push(t)}const u=Cr(a.x,a.y,t.regions,i);if(u){const t=Nr(`conn:${c}:end-port`,d,u.region,u.portPosition);s.push(t)}const p={connectionId:c,mutuallyConnectedNetworkId:c,startRegion:h,endRegion:d};o.push(p)}return{regions:n,ports:s,connections:o}})(o,this.xyConnections);return this.jumperGraphSolver=new Yr({inputGraph:{regions:r.regions,ports:r.ports},inputConnections:r.connections}),this.jumperGraphSolver.MAX_ITERATIONS*=3,!0}_step(){switch(this.phase){case"jumperGraph":this._stepJumperGraph();break;case"curvyTrace":this._stepCurvyTrace();break;case"done":this.solved=!0}}_stepJumperGraph(){if(!this.jumperGraphSolver){if(this._initializeGraph(),this.solved)return;if(!this.jumperGraphSolver)return void(this.failed=!0)}this.activeSubSolver=this.jumperGraphSolver,this.jumperGraphSolver.step(),this.jumperGraphSolver.solved?(this._initializeCurvyTraceSolvers(),this.curvySolvers.length>0?this.phase="curvyTrace":(this._finalizeCurvyTraceResults(),this.phase="done",this.solved=!0)):this.jumperGraphSolver.failed&&(this.error=this.jumperGraphSolver.error,this.failed=!0)}_stepCurvyTrace(){if(this.currentCurvySolverIndex>=this.curvySolvers.length)return this._finalizeCurvyTraceResults(),this.phase="done",void(this.solved=!0);const t=this.curvySolvers[this.currentCurvySolverIndex],e=t.solver;if(this.activeSubSolver=e,e.step(),e.solved){const n=t.regionId;this.regionCurvedPaths.has(n)||this.regionCurvedPaths.set(n,new Map);for(const t of e.outputTraces){const e=t.networkId??"",s=t.points.map(t=>({x:t.x,y:t.y})),o={path:s,start:s[0]??{x:0,y:0},end:s[s.length-1]??{x:0,y:0}};this.regionCurvedPaths.get(n).has(e)||this.regionCurvedPaths.get(n).set(e,[]),this.regionCurvedPaths.get(n).get(e).push(o)}this.currentCurvySolverIndex++}else e.failed&&this.currentCurvySolverIndex++}_initializeCurvyTraceSolvers(){if(!this.jumperGraphSolver)return;const t=new Set,e=[];for(const t of this.jumperLocations)for(const n of t.padRegions){const t=n.d.bounds,s=n.d.center;e.push({minX:t.minX,minY:t.minY,maxX:t.maxX,maxY:t.maxY,center:{x:s.x,y:s.y},networkIds:[]})}const n=new Map;for(let e=0;e<this.jumperGraphSolver.solvedRoutes.length;e++){const s=this.jumperGraphSolver.solvedRoutes[e],o=s.connection.connectionId,i=this.nodeWithPortPoints.portPoints.find(t=>t.connectionName===o)?.rootConnectionName,r=[],a=[];let c=null,h=null;for(let d=0;d<s.path.length;d++){const l=s.path[d],u=l.port,p=l.lastRegion,m=u.region1,f=u.region2;let g;if(p)m&&m.regionId!==p.regionId?g=m:f&&f.regionId!==p.regionId&&(g=f);else{const t=s.path[d+1],e=t?.lastRegion;if(e&&(m&&m.regionId===e.regionId?g=m:f&&f.regionId===e.regionId&&(g=f)),!g){const t=t=>t?.regionId?.startsWith("conn:");g=!m||t(m)||m.d?.isPad||m.d?.isThroughJumper?!f||t(f)||f.d?.isPad||f.d?.isThroughJumper?!m||m.d?.isPad||m.d?.isThroughJumper?(!f||f.d?.isPad||f.d?.isThroughJumper)&&m||f:m:f:m}}if(g&&(!c||g.regionId!==c.regionId)){if(c&&h){a.push({regionId:c.regionId,region:c,entryPort:h,exitPort:u});const t=c.regionId;n.has(t)||n.set(t,[]),n.get(t).push({regionId:c.regionId,region:c,routeIndex:e,connectionName:o,rootConnectionName:i,entryPort:h,exitPort:u})}c=g,h=u}if(p?.d?.isThroughJumper&&!t.has(p.regionId)){t.add(p.regionId);const e=p.d.bounds,n=p.d.center;e.maxX-e.minX>e.maxY-e.minY?r.push({route_type:"jumper",start:{x:e.minX,y:n.y},end:{x:e.maxX,y:n.y},footprint:"1206x4_pair"}):r.push({route_type:"jumper",start:{x:n.x,y:e.minY},end:{x:n.x,y:e.maxY},footprint:"1206x4_pair"})}}if(c&&h){const t=s.path[s.path.length-1];a.push({regionId:c.regionId,region:c,entryPort:h,exitPort:t?.port||null})}this.routeInfos.push({connectionId:o,rootConnectionName:i,jumpers:r,traversals:a})}for(let t=0;t<this.routeInfos.length;t++){const n=this.routeInfos[t],s=n.rootConnectionName??n.connectionId;for(const t of n.jumpers){const n=[t.start,t.end];for(const t of n)for(const n of e){const e=Math.abs(n.center.x-t.x),o=Math.abs(n.center.y-t.y);e<.1&&o<.1&&(n.networkIds.includes(s)||n.networkIds.push(s))}}}for(const[t,s]of n){if(0===s.length)continue;const n=s[0].region;if(n.d.isPad||n.d.isThroughJumper)continue;const o=n.d.bounds,i=[];for(const t of s)i.push({start:{x:t.entryPort.d.x,y:t.entryPort.d.y},end:{x:t.exitPort.d.x,y:t.exitPort.d.y},networkId:t.rootConnectionName??t.connectionName});const r=.01,a=e.filter(t=>t.minX<=o.maxX+r&&t.maxX>=o.minX-r&&t.minY<=o.maxY+r&&t.maxY>=o.minY-r).map(t=>{const e=s.map(t=>t.rootConnectionName??t.connectionName),n=t.networkIds.find(t=>e.includes(t));return{minX:t.minX,minY:t.minY,maxX:t.maxX,maxY:t.maxY,center:t.center,networkId:n}}),c={bounds:o,waypointPairs:i,obstacles:a,preferredTraceToTraceSpacing:2*this.traceWidth,preferredObstacleToTraceSpacing:2*this.traceWidth},h=new ya(c);this.curvySolvers.push({solver:h,regionId:t,traversals:s.map(t=>({routeIndex:t.routeIndex,connectionName:t.connectionName,rootConnectionName:t.rootConnectionName}))})}}_finalizeCurvyTraceResults(){const t=(t,e)=>Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2);for(let e=0;e<this.routeInfos.length;e++){const n=this.routeInfos[e],s=[];for(const e of n.traversals){const o=e.regionId,i=n.rootConnectionName??n.connectionId,r=this.regionCurvedPaths.get(o)?.get(i);let a=null;if(r&&r.length>0){const n={x:e.entryPort.d.x,y:e.entryPort.d.y},s=e.exitPort?{x:e.exitPort.d.x,y:e.exitPort.d.y}:null;let o=null,i=1/0;for(const e of r){const r=t(e.start,n)+(s?t(e.end,s):0);r<i&&(i=r,o=e)}o&&i<.5&&(a=o.path)}if(a&&a.length>0){for(let t=s.length>0?1:0;t<a.length;t++)s.push({x:a[t].x,y:a[t].y,z:0})}else 0===s.length&&s.push({x:e.entryPort.d.x,y:e.entryPort.d.y,z:0}),e.exitPort&&s.push({x:e.exitPort.d.x,y:e.exitPort.d.y,z:0})}this.solvedRoutes.push({connectionName:n.connectionId,rootConnectionName:n.rootConnectionName,traceThickness:this.traceWidth,route:s,jumpers:n.jumpers})}}getOutput(){return this.solvedRoutes}getOutputJumpers(){if(this.jumpers.length>0)return this.jumpers;const t=new Map;for(const e of this.solvedRoutes)for(const n of e.jumpers){const s=[n.start,n.end];for(const n of s){const s=`${n.x.toFixed(3)},${n.y.toFixed(3)}`,o=t.get(s)??[];e.rootConnectionName&&!o.includes(e.rootConnectionName)&&o.push(e.rootConnectionName),o.includes(e.connectionName)||o.push(e.connectionName),t.set(s,o)}}const e=Ze["1206x4_pair"];for(const n of this.jumperLocations){const s="horizontal"===n.orientation,o=n.padRegions.map(e=>{const n=e.d.bounds,s=e.d.center,o=n.maxX-n.minX,i=n.maxY-n.minY,r=`${s.x.toFixed(3)},${s.y.toFixed(3)}`;return{type:"rect",center:s,width:o,height:i,layers:["top"],connectedTo:[...t.get(r)??[]]}}),i={jumper_footprint:"1206x4",center:n.center,orientation:n.orientation,width:s?e.length:e.width,height:s?e.width:e.length,pads:o};this.jumpers.push(i)}return this.jumpers=this.jumpers.filter(t=>t.pads.some(t=>t.connectedTo.length>0)),this.jumpers}visualize(){if(this.jumperGraphSolver&&!this.solved)return this.jumperGraphSolver.visualize();const t={lines:[],points:[],rects:[],circles:[]},e=this.nodeWithPortPoints,n={minX:e.center.x-e.width/2,maxX:e.center.x+e.width/2,minY:e.center.y-e.height/2,maxY:e.center.y+e.height/2};t.lines.push({points:[{x:n.minX,y:n.minY},{x:n.maxX,y:n.minY},{x:n.maxX,y:n.maxY},{x:n.minX,y:n.maxY},{x:n.minX,y:n.minY}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"});for(const n of e.portPoints)t.points.push({x:n.x,y:n.y,label:n.connectionName,color:this.colorMap[n.connectionName]??"blue"});for(const e of this.solvedRoutes){const n=this.colorMap[e.connectionName]??"blue";for(let s=0;s<e.route.length-1;s++){const o=e.route[s],i=e.route[s+1];t.lines.push({points:[o,i],strokeColor:it(n,.2),strokeWidth:e.traceThickness,layer:"route-layer-0"})}for(const s of e.jumpers)this._drawJumperPads(t,s,it(n,.5))}return t}_drawJumperPads(t,e,n){const s=Ze[e.footprint],o=e.end.x-e.start.x,i=e.end.y-e.start.y,r=Math.abs(o)>Math.abs(i),a=r?s.padLength:s.padWidth,c=r?s.padWidth:s.padLength;t.rects.push({center:{x:e.start.x,y:e.start.y},width:a,height:c,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.rects.push({center:{x:e.end.x,y:e.end.y},width:a,height:c,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*s.padWidth,layer:"jumper-body"})}},va=class extends Zt{constructorParams;nodeWithPortPoints;colorMap;traceWidth;connMap;baseHyperParameters;solvedRoutes=[];jumpers=[];constructor(t){super(),this.constructorParams=t,this.nodeWithPortPoints=t.nodeWithPortPoints,this.colorMap=t.colorMap??{},this.traceWidth=t.traceWidth??.15,this.connMap=t.connMap,this.baseHyperParameters=t.hyperParameters??{},this.MAX_ITERATIONS=1e6,this.GREEDY_MULTIPLIER=1,this.MIN_SUBSTEPS=1e3}getConstructorParams(){return this.constructorParams}getHyperParameterDefs(){return[{name:"cols",possibleValues:[{COLS:1},{COLS:2},{COLS:3},{COLS:4},{COLS:6},{COLS:8}]},{name:"rows",possibleValues:[{ROWS:1},{ROWS:2},{ROWS:3},{ROWS:4}]},{name:"orientation",possibleValues:[{ORIENTATION:"vertical"},{ORIENTATION:"horizontal"}]}]}getCombinationDefs(){return[["cols","rows","orientation"]]}generateSolver(t){return new xa({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,traceWidth:this.traceWidth,hyperParameters:{COLS:t.COLS,ROWS:t.ROWS,ORIENTATION:t.ORIENTATION}})}computeG(t){const e=t.hyperParameters.COLS*t.hyperParameters.ROWS;return t.iterations/1e4+.25*e}computeH(t){return 1-(t.progress||0)}onSolve(t){this.solvedRoutes=t.solver.solvedRoutes,this.jumpers=t.solver.getOutputJumpers()}getOutput(){return this.solvedRoutes}getOutputJumpers(){return this.jumpers}visualize(){return this.winningSolver?this.winningSolver.visualize():super.visualize()}},Sa=class extends y{nodeWithPortPoints;colorMap;traceWidth;viaDiameter;adjacentObstacles;routes=[];curvyTraceSolver;phase="initializing";constructor(t){super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.colorMap=t.colorMap??{},this.traceWidth=t.traceWidth??.15,this.viaDiameter=t.viaDiameter??.6,this.adjacentObstacles=t.adjacentObstacles??[],this.MAX_ITERATIONS=1e3}_step(){switch(this.phase){case"initializing":this._initializeCurvySolver();break;case"solving":this._stepCurvySolver();break;case"done":this.solved=!0}}_initializeCurvySolver(){const t=this.nodeWithPortPoints,e={minX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxX:t.center.x+t.width/2,maxY:t.center.y+t.height/2},n=new Map;for(const e of t.portPoints)n.has(e.connectionName)||n.set(e.connectionName,[]),n.get(e.connectionName).push(e);const s=[];for(const[t,e]of n){if(e.length<2)continue;const n=e[0],o=e[e.length-1];s.push({start:{x:n.x,y:n.y},end:{x:o.x,y:o.y},networkId:t})}if(0===s.length)return void(this.phase="done");const o={bounds:e,waypointPairs:s,obstacles:this.adjacentObstacles.map(t=>({minX:t.minX,minY:t.minY,maxX:t.maxX,maxY:t.maxY,center:{x:(t.minX+t.maxX)/2,y:(t.minY+t.maxY)/2},networkId:t.networkId})),preferredTraceToTraceSpacing:2*this.traceWidth,preferredObstacleToTraceSpacing:2*this.traceWidth};this.curvyTraceSolver=new ya(o),this.phase="solving"}_stepCurvySolver(){this.curvyTraceSolver?(this.activeSubSolver=this.curvyTraceSolver,this.curvyTraceSolver.step(),this.curvyTraceSolver.solved?(this._convertOutputTraces(),this.phase="done"):this.curvyTraceSolver.failed&&(this.error=this.curvyTraceSolver.error,this.failed=!0)):this.phase="done"}_convertOutputTraces(){if(!this.curvyTraceSolver)return;const t=this.nodeWithPortPoints,e=new Map;for(const n of t.portPoints){const t=n.connectionName;e.has(t)||e.set(t,{connectionName:n.connectionName,rootConnectionName:n.rootConnectionName,z:n.z})}for(const t of this.curvyTraceSolver.outputTraces){const n=t.networkId??"",s=e.get(n);if(!s)continue;const o={connectionName:s.connectionName,rootConnectionName:s.rootConnectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:t.points.map(t=>({x:t.x,y:t.y,z:s.z})),vias:[]};this.routes.push(o)}}getConstructorParams(){return{nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,traceWidth:this.traceWidth,viaDiameter:this.viaDiameter,adjacentObstacles:this.adjacentObstacles}}visualize(){const t={lines:[],points:[],rects:[],circles:[]},e=this.nodeWithPortPoints;t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(0, 200, 0, 0.1)",stroke:"rgba(0, 200, 0, 0.5)",label:e.capacityMeshNodeId});for(const e of this.adjacentObstacles)t.rects.push({center:{x:(e.minX+e.maxX)/2,y:(e.minY+e.maxY)/2},width:e.maxX-e.minX,height:e.maxY-e.minY,fill:"rgba(255, 0, 0, 0.1)",stroke:"rgba(255, 0, 0, 0.3)",label:`obstacle: ${e.networkId??""}`});if(this.curvyTraceSolver){const e=this.curvyTraceSolver.visualize();e.lines&&t.lines.push(...e.lines),e.points&&t.points.push(...e.points),e.rects&&t.rects.push(...e.rects),e.circles&&t.circles.push(...e.circles)}for(const e of this.routes){const n=this.colorMap[e.connectionName]??"gray";t.lines.push({points:e.route.map(t=>({x:t.x,y:t.y})),strokeColor:n,strokeWidth:this.traceWidth,label:e.connectionName})}for(const n of e.portPoints){const e=this.colorMap[n.connectionName]??"gray";t.points.push({x:n.x,y:n.y,color:e,label:n.connectionName})}return t}};function Pa(t){return{connectionName:t.connectionName,rootConnectionName:t.rootConnectionName,traceThickness:t.traceThickness,viaDiameter:0,route:t.route,vias:[],jumpers:t.jumpers}}var ba=class extends y{allNodes;nodeAnalyses;routes;colorMap;traceWidth;viaDiameter;connMap;hyperParameters;capacityMeshNodes;capacityMeshEdges;capacityMeshNodeMap;nodeAdjacencyMap;nodesWithoutCrossings;nodesWithCrossings;curvyIntraNodeSolvers;currentCurvySolverIndex;jumperSolvers;currentJumperSolverIndex;phase;jumpers=[];constructor({nodePortPoints:t,colorMap:e,traceWidth:n=.15,viaDiameter:s=.6,connMap:o,hyperParameters:i,capacityMeshNodes:r=[],capacityMeshEdges:a=[]}){super(),this.allNodes=[...t],this.colorMap=e??{},this.routes=[],this.traceWidth=n,this.viaDiameter=s,this.connMap=o,this.hyperParameters=i,this.capacityMeshNodes=r,this.capacityMeshEdges=a,this.capacityMeshNodeMap=new Map(r.map(t=>[t.capacityMeshNodeId,t])),this.nodeAdjacencyMap=this._buildNodeAdjacencyMap(),this.nodesWithoutCrossings=[],this.nodesWithCrossings=[],this.nodeAnalyses=[],this.curvyIntraNodeSolvers=[],this.currentCurvySolverIndex=0,this.jumperSolvers=[],this.currentJumperSolverIndex=0,this.phase="analyzing",this._analyzeNodes();const c=1e3*this.nodesWithoutCrossings.length,h=1e5*this.nodesWithCrossings.length;this.MAX_ITERATIONS=c+h+100}_buildNodeAdjacencyMap(){const t=new Map;for(const e of this.capacityMeshEdges){const[n,s]=e.nodeIds;t.has(n)||t.set(n,new Set),t.has(s)||t.set(s,new Set),t.get(n).add(s),t.get(s).add(n)}return t}_analyzeNodes(){for(const t of this.allNodes){const e=Ro(t),n={node:t,hasCrossings:e.numSameLayerCrossings>0,numSameLayerCrossings:e.numSameLayerCrossings};this.nodeAnalyses.push(n),e.numSameLayerCrossings>0?this.nodesWithCrossings.push(t):this.nodesWithoutCrossings.push(t)}this.nodesWithoutCrossings.length>0?(this.phase="curvy",this._initializeCurvySolvers()):this.nodesWithCrossings.length>0?(this.phase="jumpers",this._initializeJumperSolvers()):this.phase="done"}_step(){switch(this.phase){case"analyzing":this.nodesWithoutCrossings.length>0?(this.phase="curvy",this._initializeCurvySolvers()):this.nodesWithCrossings.length>0?(this.phase="jumpers",this._initializeJumperSolvers()):this.phase="done";break;case"curvy":this._stepCurvySolvers();break;case"jumpers":this._stepJumperSolvers();break;case"done":this.solved=!0}}_getAdjacentObstacles(t){const e=[],n=this.nodeAdjacencyMap.get(t.capacityMeshNodeId);if(!n||0===n.size)return e;const s=new Map(this.allNodes.map(t=>[t.capacityMeshNodeId,t]));for(const t of n){const n=this.capacityMeshNodeMap.get(t);if(!n)continue;if(!n._containsObstacle&&!n._containsTarget)continue;const o=n.center.x-n.width/2,i=n.center.y-n.height/2,r=n.center.x+n.width/2,a=n.center.y+n.height/2;let c;if(n._containsTarget)if(n._targetConnectionName)c=n._targetConnectionName;else{const e=s.get(t);e&&e.portPoints.length>0&&(c=e.portPoints[0].rootConnectionName??e.portPoints[0].connectionName)}e.push({minX:o,minY:i,maxX:r,maxY:a,networkId:c})}return e}_initializeCurvySolvers(){for(const t of this.nodesWithoutCrossings){const e=this._getAdjacentObstacles(t),n=new Sa({nodeWithPortPoints:t,colorMap:this.colorMap,traceWidth:this.traceWidth,viaDiameter:this.viaDiameter,adjacentObstacles:e});this.curvyIntraNodeSolvers.push(n)}}_stepCurvySolvers(){if(0===this.curvyIntraNodeSolvers.length)return this.phase=this.nodesWithCrossings.length>0?"jumpers":"done",void("jumpers"===this.phase&&this._initializeJumperSolvers());const t=this.curvyIntraNodeSolvers[this.currentCurvySolverIndex];if(this.activeSubSolver=t,!t)return this.phase=this.nodesWithCrossings.length>0?"jumpers":"done",void("jumpers"===this.phase&&this._initializeJumperSolvers());if(t.step(),t.solved){this.routes.push(...t.routes),this.currentCurvySolverIndex++;for(let t=this.currentCurvySolverIndex;t<this.curvyIntraNodeSolvers.length;t++){this.curvyIntraNodeSolvers[t];const e=this.nodesWithoutCrossings[t],n=this._getAdjacentObstacles(e),s=new Sa({nodeWithPortPoints:e,colorMap:this.colorMap,traceWidth:this.traceWidth,viaDiameter:this.viaDiameter,adjacentObstacles:n});this.curvyIntraNodeSolvers[t]=s}this.currentCurvySolverIndex>=this.curvyIntraNodeSolvers.length&&(this.phase=this.nodesWithCrossings.length>0?"jumpers":"done","jumpers"===this.phase&&this._initializeJumperSolvers())}else t.failed&&(this.error=`CurvyIntraNodeSolver failed for node: ${t.nodeWithPortPoints.capacityMeshNodeId}: ${t.error}`,this.failed=!0)}_initializeJumperSolvers(){for(const t of this.nodesWithCrossings){const e=new va({nodeWithPortPoints:t,colorMap:this.colorMap,traceWidth:this.traceWidth,connMap:this.connMap});this.jumperSolvers.push(e)}}_stepJumperSolvers(){if(0===this.jumperSolvers.length)return this.phase="done",void(this.solved=!0);const t=this.jumperSolvers[this.currentJumperSolverIndex];if(this.activeSubSolver=t,!t)return this.phase="done",void(this.solved=!0);if(t.step(),t.solved){for(const e of t.solvedRoutes)this.routes.push(Pa(e));this.jumpers.push(...t.getOutputJumpers()),this.currentJumperSolverIndex++,this.currentJumperSolverIndex>=this.jumperSolvers.length&&(this.phase="done",this.solved=!0)}else t.failed&&(this.error=`HyperJumperPrepatternSolver2 failed for node: ${t.nodeWithPortPoints.capacityMeshNodeId}: ${t.error}`,this.failed=!0)}computeProgress(){const t=this.allNodes.length;if(0===t)return 1;let e=0;e+=this.currentCurvySolverIndex;const n=this.curvyIntraNodeSolvers[this.currentCurvySolverIndex];n&&(e+=n.progress),e+=this.currentJumperSolverIndex;const s=this.jumperSolvers[this.currentJumperSolverIndex];return s&&(e+=s.progress),e/t}getConstructorParams(){return{nodePortPoints:this.allNodes,colorMap:this.colorMap,traceWidth:this.traceWidth,viaDiameter:this.viaDiameter,connMap:this.connMap,hyperParameters:this.hyperParameters,capacityMeshNodes:this.capacityMeshNodes,capacityMeshEdges:this.capacityMeshEdges}}getOutputJumpers(){return this.jumpers}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(this.failed&&this.activeSubSolver)return this.activeSubSolver.visualize();if("curvy"===this.phase&&this.curvyIntraNodeSolvers[this.currentCurvySolverIndex])return this.curvyIntraNodeSolvers[this.currentCurvySolverIndex].visualize();if("jumpers"===this.phase&&this.jumperSolvers[this.currentJumperSolverIndex])return this.jumperSolvers[this.currentJumperSolverIndex].visualize();for(const e of this.routes){const n=e.rootConnectionName??e.connectionName,s=De(e.route,e.connectionName,this.colorMap[n]);for(const n of s)t.lines.push({points:n.points,label:n.connectionName,strokeColor:0===n.z?n.color:it(n.color,.75),layer:`z${n.z}`,strokeWidth:e.traceThickness,strokeDash:0!==n.z?"10, 5":void 0});for(const s of e.vias)t.circles.push({center:s,radius:e.viaDiameter/2,fill:it(this.colorMap[n]??"gray",.5),layer:"via"});if("jumpers"in e&&e.jumpers)for(const s of e.jumpers){const e=this.colorMap[n]??"gray",o=s.footprint??"1206",i=Ze[o],r=s.end.x-s.start.x,a=s.end.y-s.start.y,c=Math.abs(r)>Math.abs(a),h=c?i.padLength:i.padWidth,d=c?i.padWidth:i.padLength;t.rects.push({center:s.start,width:h,height:d,fill:it(e,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.rects.push({center:s.end,width:h,height:d,fill:it(e,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.lines.push({points:[s.start,s.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*i.padWidth,layer:"jumper-body"})}}for(const e of this.nodeAnalyses){const n=e.node;n.center.x,n.width,n.center.x,n.width,n.center.y,n.height,n.center.y,n.height;t.rects.push({center:n.center,width:n.width,height:n.height,fill:e.hasCrossings?"rgba(255, 200, 0, 0.1)":"rgba(0, 200, 0, 0.1)",stroke:e.hasCrossings?"rgba(255, 150, 0, 0.5)":"rgba(0, 150, 0, 0.5)",label:[n.capacityMeshNodeId,e.hasCrossings?`crossings: ${e.numSameLayerCrossings}`:"no crossings"].join("\n")})}return t}},Ma=class extends y{unsolvedRoutes;mergedHdRoutes=[];colorMap={};defaultTraceThickness;defaultViaDiameter;constructor(t){super(),this.colorMap=t.colorMap??{};const e=t.hdRoutes[0];this.defaultTraceThickness=e?.traceThickness??.15,this.defaultViaDiameter=e?.viaDiameter??t.defaultViaDiameter??.6;const n=new Map;for(const e of t.connectionPathResults)n.set(e.connection.name,e);const s=new Map;for(const e of t.hdRoutes){const t=s.get(e.connectionName);t?t.push(e):s.set(e.connectionName,[e])}this.unsolvedRoutes=[];for(const[e,o]of s.entries()){const s=t.connections.find(t=>t.name===e);if(!s)continue;const i=n.get(e);let r=[];i?.path&&(r=i.path.map(t=>t.currentNodeId));const a={...s.pointsToConnect[0],z:Xe(Ue(s.pointsToConnect[0]),t.layerCount)},c={...s.pointsToConnect[1],z:Xe(Ue(s.pointsToConnect[1]),t.layerCount)};this.unsolvedRoutes.push({connectionName:e,hdRoutes:o,nodeOrder:r,start:a,end:c})}this.MAX_ITERATIONS=1e5}_step(){const t=this.unsolvedRoutes.pop();if(!t)return void(this.solved=!0);const e=this.stitchOrderedRoutes(t);this.mergedHdRoutes.push(e)}stitchOrderedRoutes(t){const{connectionName:e,hdRoutes:n,nodeOrder:s,start:o,end:i}=t;if(0===n.length)return{connectionName:e,traceThickness:this.defaultTraceThickness,viaDiameter:this.defaultViaDiameter,route:[o,i],vias:[],jumpers:[]};let r;r=s.length>0?this.orderRoutesByNodePath(n,s,o,e):this.orderRoutesByProximity(n,o);const a=[],c=[],h=[];a.push({x:o.x,y:o.y,z:o.z});for(let t=0;t<r.length;t++){const e=r[t],n=a[a.length-1],s=e.route[0],o=e.route[e.route.length-1],i=St(n,s),d=St(n,o),l=Math.min(i,d);if(t>0&&l>1)continue;let u;u=i<=d?[...e.route]:[...e.route].reverse();const p=.001;u.length>0&&St(n,u[0])<p&&(u=u.slice(1)),a.push(...u),c.push(...e.vias),e.jumpers&&h.push(...e.jumpers)}const d=St(a[a.length-1],i);return d>.001&&d<5&&a.push({x:i.x,y:i.y,z:i.z}),{connectionName:e,rootConnectionName:n[0]?.rootConnectionName,traceThickness:n[0]?.traceThickness??this.defaultTraceThickness,viaDiameter:n[0]?.viaDiameter??this.defaultViaDiameter,route:a,vias:c,jumpers:h}}orderRoutesByNodePath(t,e,n,s){if(0===t.length)return[];const o=new Set(t);let i=null,r=1/0;for(const t of o){const e=t.route[0],s=t.route[t.route.length-1],o=Math.min(St(n,e),St(n,s));o<r&&(r=o,i=t)}if(!i)return[];o.delete(i);const a=i.route[0],c=i.route[i.route.length-1];let h,d;St(n,a)<=St(n,c)?(h=a,d=c):(h=c,d=a);const l=(t,e)=>{let n=0;for(const s of o){if(s===e)continue;const o=s.route[0],i=s.route[s.route.length-1];(St(t,o)<10||St(t,i)<10)&&n++}return n},u=[i];let p=d;for(;o.size>0;){let t=null,e=1/0,n=-1;for(const s of o){const o=s.route[0],i=s.route[s.route.length-1],r=St(p,o),a=St(p,i),c=Math.min(r,a);if(c>=10)continue;const h=l(r<=a?i:o,s),d=0===h,u=0===n,m=c-e;let f=!1;f=null===t||(!!(!d&&u&&m<5)||!(d&&!u&&m>-5)&&c<e),f&&(e=c,t=s,n=h)}if(!t)break;{u.push(t),o.delete(t);const e=t.route[0],n=t.route[t.route.length-1];p=St(p,e)<=St(p,n)?n:e}}const m=[];for(p=h;o.size>0;){let t=null,e=1/0,s=-1;const i=St(p,n);for(const r of o){const o=r.route[0],a=r.route[r.route.length-1],c=St(p,o),h=St(p,a),d=Math.min(c,h);if(d>=10)continue;const u=c<=h?a:o;if(St(u,n)>i+2)continue;const m=l(u,r),f=0===m,g=0===s,y=d-e;let x=!1;x=null===t||(!!(!f&&g&&y<5)||!(f&&!g&&y>-5)&&d<e),x&&(e=d,t=r,s=m)}if(!t)break;{m.unshift(t),o.delete(t);const e=t.route[0],n=t.route[t.route.length-1];p=St(p,e)<=St(p,n)?n:e}}const f=[...m,...u];if(o.size>0){const e=[...o].map(t=>{const e=t.route[0],n=t.route[t.route.length-1];return`start=(${e.x.toFixed(2)},${e.y.toFixed(2)}) end=(${n.x.toFixed(2)},${n.y.toFixed(2)})`});console.warn(`[StitchSolver] Skipped ${o.size} routes for connection ${t[0]?.connectionName??"?"}, skipped routes: ${e.join("; ")}`)}return f}orderRoutesByProximity(t,e){const n=new Set(t),s=[];let o=e;for(;n.size>0;){let t=null,e=1/0,i=!1;for(const s of n){const n=s.route[0],r=s.route[s.route.length-1],a=St(o,n),c=St(o,r);a<e&&(e=a,t=s,i=!1),c<e&&(e=c,t=s,i=!0)}if(!t)break;{s.push(t),n.delete(t);const e=t.route[0],r=t.route[t.route.length-1];o=i?e:r}}return s}visualize(){const t={points:[],lines:[],circles:[],rects:[],title:"Multiple High Density Route Stitch Solver 2"};for(const[e,n]of this.mergedHdRoutes.entries()){const s=this.colorMap[n.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1],r=0!==o.z?it(s,.5):s;t.lines?.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:r,strokeWidth:n.traceThickness})}for(const e of n.route){const n=0!==e.z?it(s,.5):s;t.points?.push({x:e.x,y:e.y,color:n})}for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s});if(n.jumpers&&n.jumpers.length>0){const e=Je(n.jumpers,{color:s,label:n.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}for(const e of this.unsolvedRoutes){const n=this.colorMap[e.connectionName]??"gray";t.points?.push({x:e.start.x,y:e.start.y,color:n,label:`${e.connectionName} Start`},{x:e.end.x,y:e.end.y,color:n,label:`${e.connectionName} End`});for(let s=0;s<e.hdRoutes.length;s++){const o=e.hdRoutes[s];if(o.route.length>1&&t.lines?.push({points:o.route.map(t=>({x:t.x,y:t.y})),strokeColor:it(n,.5),strokeDash:"10 5",label:`segment ${s}`}),o.jumpers&&o.jumpers.length>0){const e=Je(o.jumpers,{color:n,label:o.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}}return t}};function Na(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Ia=class extends y{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth,this.effort=e.effort??1,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,o=Math.max(n,s),i=e.targetMinCapacity??.5;e.capacityDepth=Be(o,i)}this.connMap=$e(t),this.colorMap=ot(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;traceKeepoutSolver;nodeSolver;nodeTargetMerger;edgeSolver;relateNodesToOffBoardConnections;colorMap;highDensityRouteSolver;simpleHighDensityRouteSolver;highDensitySolver;highDensityStitchSolver;singleLayerNodeMerger;offboardPathFragmentSolver;strawSolver;deadEndSolver;traceSimplificationSolver;traceWidthSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;viaDiameter;minTraceWidth;effort;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[Na("netToPointPairsSolver",fn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ot(t.srjWithPointPairs,this.connMap),t.connMap=$e(t.srjWithPointPairs)}}),Na("nodeSolver",Js,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Na("relateNodesToOffBoardConnections",ar,t=>[{capacityMeshNodes:t.capacityNodes,srj:t.srj}],{onSolved:t=>{t.capacityNodes=t.relateNodesToOffBoardConnections?.getOutput().capacityNodes}}),Na("edgeSolver",cn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Na("availableSegmentPointSolver",Io,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),Na("portPointPathingSolver",Vo,t=>{const e=t.capacityNodes.map(t=>({capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:[],availableZ:t.availableZ,_containsTarget:t._containsTarget,_containsObstacle:t._containsObstacle,_offBoardConnectionId:t._offBoardConnectionId,_offBoardConnectedCapacityMeshNodeIds:t._offBoardConnectedCapacityMeshNodeIds})),n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),s=t.availableSegmentPointSolver;for(const t of s.sharedEdgeSegments)for(const e of t.portPoints){const[s,o]=e.nodeIds,i={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[s,o],distToCentermostPortOnZ:e.distToCentermostPortOnZ,connectsToOffBoardNode:t.nodeIds.some(t=>n.get(t)?._offBoardConnectionId)},r=n.get(s);r&&r.portPoints.push(i)}return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e,capacityMeshNodes:t.capacityNodes,colorMap:t.colorMap,numShuffleSeeds:10*t.effort,hyperParameters:{JUMPER_PF_FN_ENABLED:!0,NODE_PF_FACTOR:100,MAX_RIPS:100*t.effort,RIPPING_ENABLED:!0,RIPPING_PF_THRESHOLD:.9-.7*(1-1/t.effort),RANDOM_RIP_FRACTION:.05,NODE_PF_MAX_PENALTY:1e3,STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR:0,CENTER_OFFSET_DIST_PENALTY_FACTOR:0,FORCE_CENTER_FIRST:!0}}]},{onSolved:t=>{const e=t.portPointPathingSolver;e&&cr({connMap:t.connMap,connectionsWithResults:e.connectionsWithResults,inputNodes:e.inputNodes,obstacles:t.srj.obstacles})}}),Na("highDensitySolver",ba,t=>[{nodePortPoints:t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth,connMap:t.connMap,capacityMeshNodes:t.capacityNodes??[],capacityMeshEdges:t.capacityEdges??[]}]),Na("highDensityStitchSolver",Ma,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensitySolver.routes,connectionPathResults:t.multiSectionPortPointOptimizer?.connectionResults??t.portPointPathingSolver?.connectionsWithResults??[],colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),Na("traceKeepoutSolver",ir,t=>[{hdRoutes:t.traceSimplificationSolver?.simplifiedHdRoutes??t.highDensityStitchSolver?.mergedHdRoutes??[],obstacles:t.srj.obstacles,jumpers:t.highDensitySolver?.getOutputJumpers()??[],connMap:t.connMap,colorMap:t.colorMap,srj:t.srj}])];getConstructorParams(){return[this.srj,this.opts]}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 t=this.netToPointPairsSolver?.visualize(),e=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),s=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),i=this.edgeSolver?.visualize(),r=this.traceKeepoutSolver?.visualize(),a=this.deadEndSolver?.visualize(),c=this.availableSegmentPointSolver?.visualize(),h=this.offboardPathFragmentSolver?.visualize(),d=this.portPointPathingSolver?.visualize(),l=this.multiSectionPortPointOptimizer?.visualize(),u=this.highDensityRouteSolver?.visualize(),p=this.highDensitySolver?.visualize(),m=this.simpleHighDensityRouteSolver?.visualize(),f=this.highDensityStitchSolver?.visualize(),y=this.traceSimplificationSolver?.visualize(),x=this.traceWidthSolver?.visualize(),v=this.srj.outline,S=[];if(S.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)"}),v&&v.length>=2){const t=v.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),S.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const P={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:["obstacle",t.offBoardConnectsTo?`offboardConnections: ${t.offBoardConnectsTo?.join(", ")}`:"",t.layers?.join(", ")].filter(Boolean).join("\n")}))],lines:S},b=[P,t,e,n,s,o,i,a,c,h,d,l,u?g(P,u):null,p?g(P,p):null,m?g(P,m):null,f,y,r,x,this.solved?g(P,sn(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...b)}preview(){const t=this.highDensitySolver?.routes??this.simpleHighDensityRouteSolver?.routes??this.highDensityRouteSolver?.routes;if(t){const e=[];for(let n=t.length-1;n>=0;n--){const s=t[n];if(e.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[s.connectionName]}),e.length>200)break}return{lines:e}}if(this.portPointPathingSolver){const t=[];for(const e of this.portPointPathingSolver.connectionsWithResults)e.path&&t.push({points:e.path.map(t=>({x:t.point.x,y:t.point.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.traceWidthSolver?.hdRoutesWithWidths??this.traceKeepoutSolver?.redrawnHdRoutes??this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver?.mergedHdRoutes??this.highDensitySolver?.routes??this.simpleHighDensityRouteSolver?.routes??this.highDensityRouteSolver?.routes}getConnectedOffboardObstacles(){const t={},e=new Set(this.srj.connections.map(t=>t.rootConnectionName??t.name));for(const[n,s]of this.srj.obstacles.entries()){if(!s.offBoardConnectsTo?.length)continue;const o=s.obstacleId??`__obs${n}`;s.obstacleId=o;const i=this.connMap.getNetConnectedToId(o);if(!i)continue;const r=this.connMap.getIdsConnectedToNet(i).find(t=>e.has(t));r&&(t[o]=r)}return t}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver&&!this.simpleHighDensityRouteSolver&&!this.highDensitySolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,o=e.filter(t=>t.connectionName===n.name);for(let e=0;e<o.length;e++){const i=o[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:We(i,this.srj.layerCount)};t.push(r)}}return t}getOutputJumpers(){return this.highDensitySolver?this.highDensitySolver.getOutputJumpers():[]}getOutputSimpleRouteJson(){const t=this.getOutputJumpers();return{...this.srj,traces:this.getOutputSimplifiedPcbTraces(),jumpers:t.length>0?t:void 0}}},Ca=class{constructor(t){this.targets=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],s=Math.floor(n.bounds.minX/this.CELL_SIZE)*this.CELL_SIZE,o=Math.floor(n.bounds.minY/this.CELL_SIZE)*this.CELL_SIZE,i=n.bounds.maxX,r=n.bounds.maxY;for(let t=s;t<=i;t+=this.CELL_SIZE)for(let s=o;s<=r;s+=this.CELL_SIZE){const o=this.getBucketKey(t,s),i=this.buckets.get(o);i?i.push([n,e]):this.buckets.set(o,[[n,e]])}}}buckets;CELL_SIZE=5;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getTargetsInArea(t,e,n,s){const o=[],i=new Set,r=Math.floor((t-n/2)/this.CELL_SIZE)*this.CELL_SIZE,a=Math.floor((e-s/2)/this.CELL_SIZE)*this.CELL_SIZE,c=t+n/2,h=e+s/2;for(let t=r;t<=c;t+=this.CELL_SIZE)for(let e=a;e<=h;e+=this.CELL_SIZE){const n=this.getBucketKey(t,e),s=this.buckets.get(n)||[];for(const t of s)i.has(t[1])||(i.add(t[1]),o.push(t[0]))}return o}},_a=class extends y{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.MAX_DEPTH=e?.capacityDepth??this.MAX_DEPTH,this.MAX_ITERATIONS=1e5,this.layerCount=t.layerCount??2,this.outlinePolygon=t.outline&&t.outline.length>=3?t.outline:void 0;for(const e of t.obstacles)if(!e.zLayers){const n=[];for(const s of e.layers)n.push(Xe(s,t.layerCount));e.zLayers=n}const n={x:(t.bounds.minX+t.bounds.maxX)/2,y:(t.bounds.minY+t.bounds.maxY)/2},s={width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},o=Math.max(s.width,s.height);this.unfinishedNodes=[{capacityMeshNodeId:this.getNextNodeId(),center:n,width:o,height:o,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 Qs("flatbush",this.srj.obstacles),this.targets=this.computeTargets(),this.targetTree=new Ca(this.targets)}unfinishedNodes;finishedNodes;nodeToXYOverlappingObstaclesMap;layerCount;outlinePolygon;MAX_DEPTH=4;targets;targetTree;obstacleTree;computeTargets(){const t=[];for(const e of this.srj.connections)for(const n of e.pointsToConnect){const s=Ve(n),o=this.obstacleTree.searchArea(n.x,n.y,.01,.01).filter(t=>t.zLayers.some(t=>s.some(e=>t===Xe(e,this.layerCount))));let i={minX:n.x-.005,minY:n.y-.005,maxX:n.x+.005,maxY:n.y+.005};o.length>0&&(i={minX:Math.min(...o.map(t=>t.center.x-t.width/2)),minY:Math.min(...o.map(t=>t.center.y-t.height/2)),maxX:Math.max(...o.map(t=>t.center.x+t.width/2)),maxY:Math.max(...o.map(t=>t.center.y+t.height/2))});const r={...n,connectionName:e.name,availableZ:s.map(t=>Xe(t,this.layerCount)),bounds:i};t.push(r)}return t}getNodeBounds(t){const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-n,maxY:t.center.y+n}}getNodeRect(t){return{center:{x:t.center.x,y:t.center.y},width:t.width,height:t.height}}_nextNodeCounter=0;getNextNodeId(){return"cn"+this._nextNodeCounter++}getCapacityFromDepth(t){return(this.MAX_DEPTH-t+1)**2}getTargetIfNodeContainsTarget(t){const e=t.width>4*this.targetTree.CELL_SIZE?this.targets:this.targetTree.getTargetsInArea(t.center.x,t.center.y,t.width,t.height);for(const n of e)if(n.bounds.minX<=t.center.x+t.width/2&&n.bounds.maxX>=t.center.x-t.width/2&&n.bounds.minY<=t.center.y+t.height/2&&n.bounds.maxY>=t.center.y-t.height/2&&n.availableZ.some(e=>t.availableZ.includes(e)))return n;return null}getXYOverlappingObstacles(t){const e=this.nodeToXYOverlappingObstaclesMap.get(t.capacityMeshNodeId);if(e)return e;const n=[],s=this.getNodeBounds(t),o=s.minX,i=s.maxX,r=s.minY,a=s.maxY,c=t._parent?this.getXYOverlappingObstacles(t._parent):this.srj.obstacles;for(const t of c){const e=t.center.x-t.width/2,s=t.center.x+t.width/2,c=t.center.y-t.height/2,h=t.center.y+t.height/2;i>=e&&o<=s&&a>=c&&r<=h?n.push(t):(o>=e&&i<=s&&r>=c&&a<=h||e>=o&&s<=i&&c>=r&&h<=a)&&n.push(t)}return this.nodeToXYOverlappingObstaclesMap.set(t.capacityMeshNodeId,n),n}getXYZOverlappingObstacles(t){const e=this.getXYOverlappingObstacles(t),n=[];for(const s of e)t.availableZ.some(t=>s.zLayers.includes(t))&&n.push(s);return n}doesNodeOverlapObstacle(t){if(this.getXYZOverlappingObstacles(t).length>0)return!0;const e=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!Rt(e,this.outlinePolygon))return!0}return e.minX<this.srj.bounds.minX||e.maxX>this.srj.bounds.maxX||e.minY<this.srj.bounds.minY||e.maxY>this.srj.bounds.maxY}isNodeCompletelyInsideObstacle(t){const e=this.getXYZOverlappingObstacles(t),n=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!Et(e,this.outlinePolygon))return!0}for(const t of e){const e=t.center.x-t.width/2,s=t.center.x+t.width/2,o=t.center.y-t.height/2,i=t.center.y+t.height/2;if(n.minX>=e&&n.maxX<=s&&n.minY>=o&&n.maxY<=i)return!0}return!1}getChildNodes(t){if(t._depth===this.MAX_DEPTH)return[];const e=[],n={width:t.width/2,height:t.height/2},s=[{x:t.center.x-n.width/2,y:t.center.y-n.height/2},{x:t.center.x+n.width/2,y:t.center.y-n.height/2},{x:t.center.x-n.width/2,y:t.center.y+n.height/2},{x:t.center.x+n.width/2,y:t.center.y+n.height/2}];for(const o of s){const s={capacityMeshNodeId:this.getNextNodeId(),center:o,width:n.width,height:n.height,layer:t.layer,availableZ:t.availableZ,_depth:(t._depth??0)+1,_parent:t};s._containsObstacle=this.doesNodeOverlapObstacle(s);const i=this.getTargetIfNodeContainsTarget(s);i&&(s._targetConnectionName=i.connectionName,s.availableZ=i.availableZ,s._containsTarget=!0),s._containsObstacle&&(s._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(s)),s._completelyInsideObstacle&&!s._containsTarget||e.push(s)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||!(!t._containsObstacle||t._completelyInsideObstacle))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),n=[],s=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t);e?s.push(t):e||t._containsObstacle?!e&&t._containsTarget&&n.push(t):n.push(t)}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Mesh Visualization"};if(this.outlinePolygon&&this.outlinePolygon.length>=2){const e=this.outlinePolygon.map(t=>({x:t.x,y:t.y}));e.push({...e[0]}),t.lines.push({points:e,strokeColor:"rgba(0, 136, 255, 0.95)",label:"outline"});for(const e of this.outlinePolygon)t.points.push({x:e.x,y:e.y,color:"rgba(0, 136, 255, 0.95)"})}for(const e of this.srj.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:1===e.zLayers?.length&&e.zLayers?.includes(1)?"rgba(0,0,255,0.3)":"rgba(255,0,0,0.3)",stroke:"red",label:["obstacle",`z: ${e.zLayers.join(",")}`].join("\n")});const e=[...this.finishedNodes,...this.unfinishedNodes];for(const n of e){const e=Math.min(...n.availableZ),s=this.unfinishedNodes.length>0&&n===this.unfinishedNodes[this.unfinishedNodes.length-1];t.rects.push({center:{x:n.center.x+e*n.width*.05,y:n.center.y-e*n.width*.05},width:Math.max(n.width-2,.8*n.width),height:Math.max(n.height-2,.8*n.height),fill:n._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[n.availableZ.join(",")]??"rgba(0,200,200,0.1)",stroke:s?"rgba(255,165,0,0.5)":void 0,label:[n.capacityMeshNodeId,`availableZ: ${n.availableZ.join(",")}`,`target? ${n._containsTarget??!1}`,`obs? ${n._containsObstacle??!1}`,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`capacity: ${ke(n).toFixed(2)}`].join("\n")})}return t.rects.sort((t,e)=>t.center.y-e.center.y),this.srj.connections.forEach((e,n)=>{const s=st[n%st.length];for(const o of e.pointsToConnect){const e=Ve(o);t.points.push({x:o.x,y:o.y,label:`conn-${n} (${e.join(",")})`,color:s})}}),t}},Ta=class extends _a{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e,this.VIA_DIAMETER=t.minViaDiameter??this.VIA_DIAMETER}VIA_DIAMETER=.6;OBSTACLE_MARGIN=.1;OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES=.2;isNodeCompletelyOutsideBounds(t){if(this.outlinePolygon){const e=this.getNodeRect(t);if(!Et(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!!Et(e,this.outlinePolygon)&&!Rt(e,this.outlinePolygon)}return t.center.x-t.width/2<this.srj.bounds.minX||t.center.x+t.width/2>this.srj.bounds.maxX||t.center.y-t.height/2<this.srj.bounds.minY||t.center.y+t.height/2>this.srj.bounds.maxY}getObstacleCoveragePercentage(t){const e=this.getXYZOverlappingObstacles(t);if(0===e.length)return 0;const n=t.center.x-t.width/2,s=t.center.x+t.width/2,o=t.center.y-t.height/2,i=t.center.y+t.height/2,r=t.width*t.height;let a=0;for(const t of e){const e=Math.max(n,t.center.x-t.width/2),r=Math.min(s,t.center.x+t.width/2),c=Math.max(o,t.center.y-t.height/2),h=Math.min(i,t.center.y+t.height/2);if(e<r&&c<h){a+=(r-e)*(h-c)}}return a/r}shouldFilterSingleLayerNodeForObstacle(t){if(1!==t.availableZ.length)return!1;if(!t._containsObstacle)return!1;return this.getObstacleCoveragePercentage(t)>this.OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES}shouldFilterNodeForObstacle(t){return!!t._containsObstacle&&(1!==t.availableZ.length||this.shouldFilterSingleLayerNodeForObstacle(t))}createChildNodeAtPosition(t,e){const n={capacityMeshNodeId:this.getNextNodeId(),center:e.center,width:e.width,height:e.height,layer:t.layer,availableZ:e.availableZ,_depth:e._depth??(t._depth??0)+1,_parent:t},s=this.getXYZOverlappingObstacles(n);n._containsObstacle=s.length>0||this.isNodePartiallyOutsideBounds(n);const o=this.getTargetIfNodeContainsTarget(n);return o&&(n._targetConnectionName=o.connectionName,n._containsTarget=!0),n._containsObstacle&&(n._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(n)),n}getZSubdivisionChildNodes(t){if(1===t.availableZ.length)return[];const e=[],n=t.availableZ.map(t=>[t]);for(const s of n){const n=this.createChildNodeAtPosition(t,{center:{...t.center},width:t.width,height:t.height,availableZ:s,_depth:t._depth});this.isNodeCompletelyOutsideBounds(n)||e.push(n)}return e}getChildNodes(t){if(t._depth>=this.MAX_DEPTH)return[];const e=[],n={width:t.width/2,height:t.height/2},s=[{x:t.center.x-n.width/2,y:t.center.y-n.height/2},{x:t.center.x+n.width/2,y:t.center.y-n.height/2},{x:t.center.x-n.width/2,y:t.center.y+n.height/2},{x:t.center.x+n.width/2,y:t.center.y+n.height/2}];for(const o of s){const s=this.createChildNodeAtPosition(t,{center:o,width:n.width,height:n.height,availableZ:t.availableZ});this.isNodeCompletelyOutsideBounds(s)||e.push(s)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||(1===t.availableZ.length&&t._depth<=this.MAX_DEPTH||!(!t._containsObstacle||t._completelyInsideObstacle)))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),n=[],s=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),o=t.availableZ.length>1&&!e&&(t._containsObstacle||t.width<this.VIA_DIAMETER+this.OBSTACLE_MARGIN);if(e)s.push(t);else if(e||this.shouldFilterNodeForObstacle(t)||o)if(!e&&t._containsTarget)if(o){const e=this.getZSubdivisionChildNodes(t);n.push(...e.filter(t=>t._containsTarget||!this.shouldFilterNodeForObstacle(t)))}else n.push(t);else o&&n.push(...this.getZSubdivisionChildNodes(t).filter(t=>!this.shouldFilterNodeForObstacle(t)));else n.push(t)}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}},Ea=class extends Ta{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e}MAX_SIZE_FOR_SINGLE_LAYER_NODES=2;isObstacleAssignable(t){return Boolean(t?.netIsAssignable)}getOverlappingAssignableObstacles(t){return this.getXYZOverlappingObstacles(t).filter(t=>this.isObstacleAssignable(t))}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||(!(!t._containsObstacle||t._completelyInsideObstacle)||1===t.availableZ.length&&(t.width>this.MAX_SIZE_FOR_SINGLE_LAYER_NODES||t.height>this.MAX_SIZE_FOR_SINGLE_LAYER_NODES)))}shouldFilterNodeForObstacle(t){if(!t._containsObstacle)return!1;return!(this.getOverlappingAssignableObstacles(t).length>0)&&(1!==t.availableZ.length||this.shouldFilterSingleLayerNodeForObstacle(t))}insertAssignableObstaclesAsNodes(){const t=this.srj.obstacles.filter(t=>this.isObstacleAssignable(t)),e=new Map;for(const n of t){const t=[];for(const e of this.finishedNodes){this.getXYZOverlappingObstacles(e).some(t=>t===n)&&t.push(e)}e.set(n,t)}const n=new Set;for(const t of e.values())for(const e of t)n.add(e);this.finishedNodes=this.finishedNodes.filter(t=>!n.has(t));for(const n of t){const t=e.get(n)||[],s=n.layers&&n.layers.length>0?Array.from(new Set(n.layers.map(t=>Xe(t,this.srj.layerCount)))).sort((t,e)=>t-e):Array.from({length:this.srj.layerCount},(t,e)=>this.srj.layerCount-e-1);let o=n.center.x-n.width/2,i=n.center.x+n.width/2,r=n.center.y-n.height/2,a=n.center.y+n.height/2;for(const e of t){const t=e.center.x-e.width/2,n=e.center.x+e.width/2,s=e.center.y-e.height/2,c=e.center.y+e.height/2;o=Math.min(o,t),i=Math.max(i,n),r=Math.min(r,s),a=Math.max(a,c)}const c=i-o,h=a-r,d=(o+i)/2,l=(r+a)/2;let u=!1;for(const t of this.srj.connections){for(const e of t.pointsToConnect)if(e.x>=o&&e.x<=i&&e.y>=r&&e.y<=a){u=!0;break}if(u)break}const p={capacityMeshNodeId:`assignable_via_${n.center.x}_${n.center.y}`,center:{x:d,y:l},width:c,height:h,layer:1===s.length?`z${s[0]}`:`z${s.join(",")}`,availableZ:s,_depth:0,_containsTarget:u,_containsObstacle:!1,_completelyInsideObstacle:!1};p._assignedViaObstacle=n,this.finishedNodes.push(p)}}_step(){const t=this.unfinishedNodes.pop();if(!t)return this.insertAssignableObstaclesAsNodes(),void(this.solved=!0);const e=this.getChildNodes(t),n=[],s=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),o=t.availableZ.length>1&&!e;if(e)s.push(t);else{if(o){const e=this.getZSubdivisionChildNodes(t);for(const t of e)!t._containsTarget&&this.shouldFilterNodeForObstacle(t)||(this.shouldNodeBeXYSubdivided(t)?s.push(t):(t._containsObstacle=!1,n.push(t)));continue}this.shouldFilterNodeForObstacle(t)&&!t._containsTarget||n.push(t)}}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}},Ra=.005,wa=class extends y{nodeMap;currentBatchNodeIds;absorbedNodeIds;nextBatchNodeIds;batchHadModifications;hasComputedAdjacentNodeIds=!1;newNodes;constructor(t){super(),this.nodeMap=new Map,this.MAX_ITERATIONS=1e5;for(const e of t)this.nodeMap.set(e.capacityMeshNodeId,e);this.newNodes=[],this.absorbedNodeIds=new Set;const e=[];for(const n of t)n._assignedViaObstacle?(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId)):n._containsTarget?n.availableZ.length>1?(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId)):e.push([n,n.width*n.height]):(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId));e.sort((t,e)=>t[1]-e[1]);for(const[t,n]of e){const e={...t,center:{...t.center}};this.nodeMap.set(t.capacityMeshNodeId,e)}this.currentBatchNodeIds=e.map(([t])=>t.capacityMeshNodeId),this.nextBatchNodeIds=[],this.batchHadModifications=!1}computeAdjacentNodeIdsForFirstBatch(t){const e=Math.max(...t.map(t=>Math.max(...t.availableZ))),n=[];for(let s=0;s<=e;s++)n.push(new an(t.filter(t=>t.availableZ[0]===s)));for(const e of t){const t=[],s=n[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const n of s)n._containsTarget&&n._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!n._containsTarget||n._targetConnectionName!==e._targetConnectionName)||n.capacityMeshNodeId!==e.capacityMeshNodeId&&on(e,n)&&t.push(n);e._adjacentNodeIds=t.map(t=>t.capacityMeshNodeId)}}getAdjacentSameLayerUnprocessedNodes(t){const e=[],n=Array.from(new Set((t._adjacentNodeIds??[]).map(t=>this.nodeMap.get(t)))).filter(e=>e&&e.capacityMeshNodeId!==t.capacityMeshNodeId);n.sort((t,e)=>t.width*t.height-e.width*e.height);for(const t of n)this.absorbedNodeIds.has(t.capacityMeshNodeId)||e.push(t);return e}_step(){this.hasComputedAdjacentNodeIds||(this.computeAdjacentNodeIdsForFirstBatch(this.currentBatchNodeIds.map(t=>this.nodeMap.get(t))),this.hasComputedAdjacentNodeIds=!0);let t=this.currentBatchNodeIds.pop();for(;t&&this.absorbedNodeIds.has(t);)t=this.currentBatchNodeIds.pop();if(!t)return this.batchHadModifications?(this.currentBatchNodeIds=this.nextBatchNodeIds.sort((t,e)=>{const n=this.nodeMap.get(t),s=this.nodeMap.get(e);return n.width*n.height-s.width*s.height}),this.nextBatchNodeIds=[],void(this.batchHadModifications=!1)):(this.solved=!0,void this.newNodes.push(...this.nextBatchNodeIds.map(t=>this.nodeMap.get(t))));const e=this.nodeMap.get(t);let n=!1;const s=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===s.length)return void this.nextBatchNodeIds.push(t);const o=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))))},i=s.filter(t=>t.center.x<e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(i.length>0){const{width:t,height:s}=i[0],r=i.every(e=>e.width===t&&e.height===s);Math.abs(i.reduce((t,e)=>t+e.height,0)-e.height)<Ra&&r&&(e.width+=t,e.center.x=e.center.x-t/2,o(i),n=!0)}const r=s.filter(t=>t.center.x>e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(r.length>0&&!n){const{width:t,height:s}=r[0],i=r.every(e=>e.width===t&&e.height===s);Math.abs(r.reduce((t,e)=>t+e.height,0)-e.height)<Ra&&i&&(e.width+=t,e.center.x=e.center.x+t/2,o(r),n=!0)}const a=s.filter(t=>t.center.y>e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(a.length>0&&!n){const{width:t,height:s}=a[0],i=a.every(e=>e.width===t&&e.height===s);Math.abs(a.reduce((t,e)=>t+e.width,0)-e.width)<Ra&&i&&(e.height+=s,e.center.y=e.center.y+s/2,o(a),n=!0)}const c=s.filter(t=>t.center.y<e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(c.length>0&&!n){const{width:t,height:s}=c[0],i=c.every(e=>e.width===t&&e.height===s);Math.abs(c.reduce((t,e)=>t+e.width,0)-e.width)<Ra&&i&&(e.height+=s,e.center.y=e.center.y-s/2,o(c),n=!0)}n?(this.batchHadModifications=!0,this.currentBatchNodeIds.push(t)):this.nextBatchNodeIds.unshift(t)}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Single Layer Node Merger (Only Merge Targets)"};for(const e of this.newNodes)t.rects.push(fi(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let n;e&&(n=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const s of this.currentBatchNodeIds){const o=this.nodeMap.get(s);if(!this.absorbedNodeIds.has(s)&&o){const i=fi(o,{rectMargin:.01});s===e?i.stroke="rgba(0, 255, 0, 0.8)":n?.some(t=>t.capacityMeshNodeId===s)?i.stroke="rgba(128, 0, 128, 0.8)":i.stroke="rgba(255, 165, 0, 0.8)",i.layer=`z${o.availableZ.join(",")}`,i.label=`${i.label}\n(unprocessed)`,t.rects.push(i)}}for(const e of this.nextBatchNodeIds){const n=this.nodeMap.get(e);if(!this.absorbedNodeIds.has(e)&&n){const e=fi(n,{rectMargin:.01});e.layer=`z${n.availableZ.join(",")}`,e.stroke="rgba(0, 217, 255, 0.8)",e.label=`${e.label}\nx: ${n.center.x}, y: ${n.center.y}\n${n.width}x${n.height}\n(next batch)`,t.rects.push(e)}}return t}},Aa=class extends y{newNodes;obstacleToNodesMap;obstaclesToProcess;mergedNodeIds;constructor(t){super(),this.MAX_ITERATIONS=1e4,this.newNodes=[],this.obstacleToNodesMap=new Map,this.mergedNodeIds=new Set;for(const e of t){const t=e._assignedViaObstacle;if(t){const n=this.obstacleToNodesMap.get(t)||[];n.push(e),this.obstacleToNodesMap.set(t,n)}else this.newNodes.push(e)}this.obstaclesToProcess=Array.from(this.obstacleToNodesMap.keys())}_step(){const t=this.obstaclesToProcess.pop();if(!t)return void(this.solved=!0);const e=this.obstacleToNodesMap.get(t);if(!e||0===e.length)return;let n=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,o=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;const r=new Set;let a=!1;for(const t of e){const e=t.center.x-t.width/2,c=t.center.x+t.width/2,h=t.center.y-t.height/2,d=t.center.y+t.height/2;n=Math.min(n,e),s=Math.max(s,c),o=Math.min(o,h),i=Math.max(i,d);for(const e of t.availableZ)r.add(e);t._containsTarget&&(a=!0)}const c=s-n,h=i-o,d=(n+s)/2,l=(o+i)/2,u=Array.from(r).sort((t,e)=>t-e),p={capacityMeshNodeId:`merged_via_${t.center.x}_${t.center.y}`,center:{x:d,y:l},width:c,height:h,layer:1===u.length?`z${u[0]}`:`z${u.join(",")}`,availableZ:u,_containsTarget:a,_containsObstacle:!1,_completelyInsideObstacle:!1};p._assignedViaObstacle=t;for(const t of e)this.mergedNodeIds.add(t.capacityMeshNodeId);this.newNodes.push(p)}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Assignable Via Node Merger"};for(const e of this.newNodes){const n=fi(e);e._assignedViaObstacle&&(n.stroke="rgba(255, 0, 255, 0.8)",n.label=`${n.label||""}\n(merged via)`),t.rects.push(n)}const e=this.obstaclesToProcess[this.obstaclesToProcess.length-1];if(e){const n=this.obstacleToNodesMap.get(e)||[];for(const e of n){const n=fi(e,{rectMargin:.01});n.stroke="rgba(0, 255, 0, 0.8)",n.label=`${n.label||""}\n(to be merged)`,t.rects.push(n)}}return t}},Oa=class extends y{constructor(t){const{simpleRouteJson:e,nodes:n,edges:s,colorMap:o,MAX_ITERATIONS:i=1e6,hyperParameters:r={}}=t;super(),this.inputParams=t,this.hyperParameters=r,this.MAX_ITERATIONS=i,this.simpleRouteJson=e,this.nodes=n,this.edges=s,this.colorMap=o??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=No(this.edges);const a=this.nodes.filter(t=>t._containsTarget);this.unprocessedConnectionPairs=kt(this.simpleRouteJson.connections.map(t=>{const[e,n]=t.pointsToConnect;return{start:a.find(t=>St(t.center,e)<t.width/2),end:a.find(t=>St(t.center,n)<t.width/2),connection:t}}),this.hyperParameters.SHUFFLE_SEED??0),this.viaNodes=this.nodes.filter(t=>t.availableZ.length>1)}GREEDY_MULTIPLIER=1.5;simpleRouteJson;nodes;edges;colorMap;MAX_ITERATIONS;hyperParameters;usedNodeMap=new Map;nodeMap;nodeEdgeMap;unprocessedConnectionPairs;solvedRoutes=[];activeConnectionPair=null;ogUnprocessedSubpaths=null;unprocessedSubpaths=null;solvedSubpaths=null;activeSubpath=null;viaNodes=[];closestViaForConnectionStartMap=new Map;closestViaForConnectionEndMap=new Map;getConstructorParams(){return this.inputParams}lastStepOperation="none";computeClosestViaForAllConnections(){this.closestViaForConnectionStartMap.clear(),this.closestViaForConnectionEndMap.clear();for(const t of this.unprocessedConnectionPairs){const e=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId));if(e.length>0){const n=e.reduce((e,n)=>{const s=this._dist(e,t.start);return this._dist(n,t.start)<s?n:e});this.closestViaForConnectionStartMap.set(t,n);const s=e.reduce((e,n)=>{const s=this._dist(e,t.end);return this._dist(n,t.end)<s?n:e});this.closestViaForConnectionEndMap.set(t,s)}}}_step(){if(!this.activeConnectionPair)return this.activeConnectionPair=this.unprocessedConnectionPairs.shift(),this.activeConnectionPair?(this.computeClosestViaForAllConnections(),void(this.lastStepOperation="dequeueConnectionPair")):void(this.solved=!0);if(this.activeConnectionPair&&!this.unprocessedSubpaths)return this.unprocessedSubpaths=this.breakConnectionPairIntoSubpaths(this.activeConnectionPair),this.ogUnprocessedSubpaths=this.unprocessedSubpaths.slice(),this.solvedSubpaths=[],void(this.lastStepOperation="breakConnectionPairIntoSubpaths");if(this.activeSubpath){if(this.activeSubpath&&(this.stepSolveSubpath(this.activeSubpath),this.activeSubpath.solved))return this.solvedSubpaths.push(this.activeSubpath),this.activeSubpath=null,this.clearCandidateNodes(),void(this.lastStepOperation="finishedSolvingSubpath");this.lastStepOperation="stepSolveSubpath"}else{if(this.activeSubpath=this.unprocessedSubpaths.shift(),!this.activeSubpath){const t=this.activeConnectionPair;return this.activeConnectionPair=null,this.unprocessedSubpaths=null,this.ogUnprocessedSubpaths=null,this.activeSubpath=null,this.solvedRoutes.push(this.createSolvedRoute(this.solvedSubpaths,t)),void(this.lastStepOperation="finishedSolvingConnectionPair")}this.lastStepOperation="dequeueSubpath"}}queuedCandidateNodes=[];visitedNodes=new Set;_dist(t,e){return Math.hypot(t.center.x-e.center.x,t.center.y-e.center.y)}stepSolveSubpath(t){const{start:e,end:n}=t;if(e.capacityMeshNodeId===n.capacityMeshNodeId)return t.path=[e],t.solved=!0,void this.usedNodeMap.set(e.capacityMeshNodeId,!0);if(0===this.queuedCandidateNodes.length&&0===this.visitedNodes.size){const t=this._dist(e,n),s={prevCandidate:null,node:e,g:0,h:t,f:this.GREEDY_MULTIPLIER*t};this.queuedCandidateNodes.push(s)}let s;for(this.queuedCandidateNodes.sort((t,e)=>t.f-e.f);this.queuedCandidateNodes.length&&!s;){const t=this.queuedCandidateNodes.shift();this.visitedNodes.has(t.node.capacityMeshNodeId)||(s=t)}if(!s)return this.failed=!0,void(this.error="No viable candidates left");if(this.visitedNodes.add(s.node.capacityMeshNodeId),s.node.capacityMeshNodeId===n.capacityMeshNodeId){const e=[];let n=s;for(;n;)e.unshift(n.node),this.usedNodeMap.set(n.node.capacityMeshNodeId,!0),n=n.prevCandidate;return t.path=e,void(t.solved=!0)}const o=this.getNeighbors(s.node);for(const t of o){const e=t.capacityMeshNodeId;if(this.visitedNodes.has(e))continue;const o=this.computeG(s,t,n),i=this.computeH(s,t,n),r=o+this.GREEDY_MULTIPLIER*i,a=this.queuedCandidateNodes.findIndex(t=>t.node.capacityMeshNodeId===e);if(a>=0){if(this.queuedCandidateNodes[a].g<=o)continue;this.queuedCandidateNodes.splice(a,1)}this.queuedCandidateNodes.push({prevCandidate:s,node:t,g:o,h:i,f:r})}}getNeighbors(t){const e=new Set,n=this.nodeEdgeMap.get(t.capacityMeshNodeId)??[];for(const s of n){const[n,o]=s.nodeIds,i=n===t.capacityMeshNodeId?o:n,r=this.nodeMap.get(i);r&&e.add(r)}const s=this.activeSubpath?.layer;return Array.from(e).filter(t=>!(t.capacityMeshNodeId!==this.activeSubpath?.end.capacityMeshNodeId)||!t._containsObstacle&&(!t._containsTarget&&(!this.usedNodeMap.has(t.capacityMeshNodeId)&&!(void 0!==s&&!t.availableZ.includes(s)))))}clearCandidateNodes(){this.queuedCandidateNodes=[],this.visitedNodes=new Set}computeG(t,e,n){const s=this._dist(t.node,e);return t.g+s}computeH(t,e,n){return this._dist(e,n)}createSolvedRoute(t,e){const n=[];for(let e=0;e<t.length;e++){const s=t[e];s.path?0===e?n.push(...s.path):n.push(...s.path.slice(1)):(0===e&&n.push(s.start),e===t.length-1&&n.push(s.end))}return{connection:e.connection,path:n}}breakConnectionPairIntoSubpaths(t){var e,n;if(!(e=[this.hyperParameters.DIRECTIVE_SEED??0,this.solvedRoutes.length],n=this.hyperParameters.FORCE_VIA_TRAVEL_CHANCE??0,Yt(e.reduce((t,e)=>t+16807*e%2147483647,0))()<n))return[{start:t.start,end:t.end,solved:!1,layer:t.start.availableZ[0]??0}];const s=this.getClosestVia(t.start),o=this.getFarVia(s,t.end),i=t.start.availableZ[0]??0,r=t.end.availableZ[0]??0,a=[];return a.push({start:t.start,end:s,solved:!1,layer:i}),i===r?(a.push({start:s,end:o,solved:!1,layer:0===i?1:0}),a.push({start:o,end:t.end,solved:!1,layer:r})):a.push({start:s,end:t.end,solved:!1,layer:r}),a}getClosestVia(t){if(0===this.viaNodes.length)return t;const e=new Set;for(const[t,n]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&e.add(n.capacityMeshNodeId);for(const[t,n]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&e.add(n.capacityMeshNodeId);const n=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId)).filter(t=>!e.has(t.capacityMeshNodeId));if(0===n.length){const e=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId));return 0===e.length?t:(e.sort((e,n)=>this._dist(e,t)-this._dist(n,t)),e[0])}n.sort((e,n)=>this._dist(e,t)-this._dist(n,t));const s=this.hyperParameters.MAX_CLOSEST_VIA_SKIP??0;if(s>0&&n.length>1){const t=Yt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length),e=Math.floor(t()*(s+1));return n[Math.min(e,n.length-1)]}return n[0]}getFarVia(t,e){if(0===this.viaNodes.length)return t;const n=null!=this.hyperParameters.FAR_VIA_MIN_DISTANCE?this.hyperParameters.FAR_VIA_MIN_DISTANCE:50,s=new Set;for(const[t,e]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&s.add(e.capacityMeshNodeId);for(const[t,e]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&s.add(e.capacityMeshNodeId);const o=this.viaNodes.filter(e=>!this.usedNodeMap.has(e.capacityMeshNodeId)&&e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!s.has(e.capacityMeshNodeId)&&this._dist(e,t)>=n);if(0===o.length){const s=this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)&&this._dist(e,t)>=n).sort((t,n)=>this._dist(t,e)-this._dist(n,e));if(s.length>0)return s[0];return this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)).sort((t,n)=>this._dist(t,e)-this._dist(n,e))[0]??t}o.sort((t,n)=>this._dist(t,e)-this._dist(n,e));const i=this.hyperParameters.MAX_FURTHEST_VIA_SKIP??0;if(i>0&&o.length>1){const t=Yt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length+1e3),e=Math.floor(t()*(i+1));return o[Math.min(e,o.length-1)]}return o[0]}getCapacityPaths(){const t=[];for(const e of this.solvedRoutes){const n=e.path;n&&n.length>0&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:n.map(t=>t.capacityMeshNodeId)})}return t}visualize(){const t={lines:[],points:[],rects:[],circles:[]},e=t=>!!t&&"number"==typeof t.x&&"number"==typeof t.y&&!Number.isNaN(t.x)&&!Number.isNaN(t.y)&&Number.isFinite(t.x)&&Number.isFinite(t.y),n=t=>"number"==typeof t&&!Number.isNaN(t)&&Number.isFinite(t);for(const s of this.nodes){const o=this.queuedCandidateNodes.some(t=>t.node.capacityMeshNodeId===s.capacityMeshNodeId),i=this.queuedCandidateNodes.find(t=>t.node.capacityMeshNodeId===s.capacityMeshNodeId);if(e(s.center)&&n(s.width)&&n(s.height)){const e=fi(s,{rectMargin:.025,zOffset:.01});t.rects.push({...e,fill:o?"rgba(255, 128, 255, 0.5)":s._containsTarget?"rgba(0, 150, 255, 0.15)":s._containsObstacle?"rgba(255, 0, 0, 0.1)":"rgba(200, 200, 200, 0.05)",label:[`ID: ${s.capacityMeshNodeId}`,`Size: ${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Z: ${s.availableZ.join(", ")}`,i?`g: ${i.g.toFixed(2)}`:"",i?`h: ${i.h.toFixed(2)}`:"",i?`f: ${i.f.toFixed(2)}`:"",s._containsTarget?"TARGET":"",s._containsObstacle?"OBSTACLE":""].filter(t=>t).join("\n")})}}for(const n of this.edges){const[s,o]=n.nodeIds,i=this.nodeMap.get(s),r=this.nodeMap.get(o);i?.center&&r?.center&&e(i.center)&&e(r.center)&&t.lines.push({points:[i.center,r.center],strokeColor:"rgba(150, 150, 150, 0.2)"})}for(let n=0;n<this.solvedRoutes.length;n++){const s=this.solvedRoutes[n],o=s.path,i="blue";for(let s=0;s<o.length-1;s++){const r=o[s],a=o[s+1];if(r?.center&&a?.center&&e(r.center)&&e(a.center)){const e=r.availableZ.includes(1)&&a.availableZ.includes(1),s=n%5*.02;t.lines.push({points:[{x:r.center.x+s,y:r.center.y+s},{x:a.center.x+s,y:a.center.y+s}],strokeColor:i,strokeDash:e?"5 5":void 0})}}if(o.length>0){const n=o[0],i=o[o.length-1];n?.center&&e(n.center)&&t.points.push({x:n.center.x,y:n.center.y,label:`START: ${s.connection.name}`}),i?.center&&e(i.center)&&t.points.push({x:i.center.x,y:i.center.y,label:`END: ${s.connection.name}`})}}if(this.solvedSubpaths)for(let n=0;n<this.solvedSubpaths.length;n++){const s=this.solvedSubpaths[n];if(s.path&&s.path.length>1)for(let n=0;n<s.path.length-1;n++){const o=s.path[n],i=s.path[n+1];o?.center&&i?.center&&e(o.center)&&e(i.center)&&t.lines.push({points:[o.center,i.center],strokeColor:"green",strokeDash:1===s.layer?"3 3":void 0})}}if(this.activeSubpath){const n=this.activeSubpath.start?.center,s=this.activeSubpath.end?.center;n&&s&&e(n)&&e(s)&&(t.lines.push({points:[n,s],strokeColor:"orange",strokeDash:"5 5"}),t.points.push({x:n.x,y:n.y,label:"ACTIVE START"}),t.points.push({x:s.x,y:s.y,label:"ACTIVE END"}))}const s=this.queuedCandidateNodes.slice(0,10).sort((t,e)=>t.f-e.f);for(let n=0;n<s.length;n++){const o=.6*(1-n/10),i=[];let r=s[n];for(;r;)i.push(r.node),r=r.prevCandidate;if(i.reverse(),i.length>1){const n=i.map(t=>t.center).filter(t=>e(t));n.length>1&&t.lines.push({points:n,strokeColor:it("purple",1-o),strokeDash:1===this.activeSubpath?.layer?"4 2":void 0})}}if(this.activeConnectionPair){const n=this.activeConnectionPair.start?.center,s=this.activeConnectionPair.end?.center;n&&s&&e(n)&&e(s)&&t.lines.push({points:[n,s],strokeColor:"cyan",strokeDash:"20 5"})}if(this.ogUnprocessedSubpaths&&3===this.ogUnprocessedSubpaths.length){const[,s]=this.ogUnprocessedSubpaths;if(s.start?.center&&e(s.start.center)){const e=Math.max(s.start.width||0,s.start.height||0);n(e)&&e>0&&(t.circles.push({center:s.start.center,radius:e,stroke:"blue"}),t.points.push({x:s.start.center.x,y:s.start.center.y,label:"DIRECTIVE VIA 1"}))}if(s.end?.center&&e(s.end.center)){const e=Math.max(s.end.width||0,s.end.height||0);n(e)&&e>0&&(t.circles.push({center:s.end.center,radius:e,stroke:"purple"}),t.points.push({x:s.end.center.x,y:s.end.center.y,label:"DIRECTIVE VIA 2"}))}}if(this.queuedCandidateNodes.length>0)for(const n of this.queuedCandidateNodes){const s=n.node;s?.center&&e(s.center)&&t.circles.push({center:s.center,radius:.05,fill:"rgba(255, 255, 0, 0.6)",stroke:"yellow"})}if(this.visitedNodes.size>0)for(const n of this.visitedNodes){const s=this.nodeMap.get(n);s?.center&&e(s.center)&&t.circles.push({center:s.center,radius:.08,fill:"rgba(128, 128, 128, 0.5)",stroke:"gray"})}return t}},za=class extends Zt{constructorParams;constructor(t){super(),this.constructorParams=t,this.MAX_ITERATIONS=t.MAX_ITERATIONS??12e4,this.MIN_SUBSTEPS=5,this.GREEDY_MULTIPLIER=1.35}getHyperParameterDefs(){return[{name:"traceOrderingSeed",possibleValues:[{SHUFFLE_SEED:0},{SHUFFLE_SEED:1},{SHUFFLE_SEED:2},{SHUFFLE_SEED:3},{SHUFFLE_SEED:4},{SHUFFLE_SEED:5},{SHUFFLE_SEED:6},{SHUFFLE_SEED:7},{SHUFFLE_SEED:8},{SHUFFLE_SEED:9}]},{name:"forceViaTravelChance",possibleValues:[{FORCE_VIA_TRAVEL_CHANCE:.6},{FORCE_VIA_TRAVEL_CHANCE:.8},{FORCE_VIA_TRAVEL_CHANCE:.9}]}]}computeG(t){const e=t.unprocessedConnectionPairs.length+t.solvedRoutes.length+(t.activeConnectionPair?1:0),n=t.solvedRoutes.length,s=e>0?n/e:0;return t.iterations/t.MAX_ITERATIONS+(1-s)}computeH(t){const e=t.unprocessedConnectionPairs.length+t.solvedRoutes.length+(t.activeConnectionPair?1:0),n=t.solvedRoutes.length;return e>0?1-n/e:0}generateSolver(t){return new Oa({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}};function Da(t){const e=new Map;for(const n of t)e.set(n.capacityMeshNodeId,n);return e}function La(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var Fa=class extends y{capacityNodes;capacityEdges;enhancedEdges=[];animationState="showing_nodes";assignableNodes=[];shownNodes=[];pendingEdges=[];createdEdges=[];nextEdgeId=0;nodeMap=new Map;constructor(t){super(),this.capacityNodes=t.capacityNodes,this.capacityEdges=t.capacityEdges,this.nodeMap=Da(this.capacityNodes),this.enhancedEdges=[...this.capacityEdges],this.initializeAssignableNodes(),this.initializePendingEdges(),this.MAX_ITERATIONS=this.assignableNodes.length+this.pendingEdges.length+10}initializeAssignableNodes(){for(const t of this.capacityNodes){const e=t._assignedViaObstacle;e?.offBoardConnectsTo&&e.offBoardConnectsTo.length>0&&this.assignableNodes.push(t)}}initializePendingEdges(){const t=new Map;for(const e of this.assignableNodes){const n=e._assignedViaObstacle;if(n?.offBoardConnectsTo)for(const s of n.offBoardConnectsTo)t.has(s)||t.set(s,[]),t.get(s).push(e)}this.pendingEdges=[];for(const[e,n]of t)if(n.length>1)for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++)this.pendingEdges.push({node1:n[t],node2:n[s],netName:e})}_step(){switch(this.animationState){case"showing_nodes":if(this.assignableNodes.length>0){const t=this.assignableNodes.shift();this.shownNodes.push(t)}else this.animationState="showing_edges";break;case"showing_edges":if(this.pendingEdges.length>0){const{node1:t,node2:e,netName:n}=this.pendingEdges.shift(),s=this.createOffboardEdge(t,e,n);this.enhancedEdges.push(s),this.createdEdges.push(s)}else this.animationState="done",this.solved=!0;break;case"done":this.solved=!0}}createOffboardEdge(t,e,n){return{capacityMeshEdgeId:"offboard_"+this.nextEdgeId++,nodeIds:[t.capacityMeshNodeId,e.capacityMeshNodeId],isOffboardEdge:!0,offboardNetName:n}}visualize(){const t=[],e=[],n=[],s=new Set(this.shownNodes.map(t=>t.capacityMeshNodeId));for(const e of this.capacityEdges){if(e.isOffboardEdge)continue;if(s.has(e.nodeIds[0])||s.has(e.nodeIds[1])){const n=this.nodeMap.get(e.nodeIds[0]),s=this.nodeMap.get(e.nodeIds[1]);n&&s&&t.push({points:[n.center,s.center],strokeColor:"rgba(0, 200, 0, 0.5)",strokeWidth:.05})}}for(let t=0;t<this.shownNodes.length;t++){const s=this.shownNodes[t],o=s._assignedViaObstacle,i=t===this.shownNodes.length-1&&"showing_nodes"===this.animationState;n.push({center:s.center,width:s.width,height:s.height,fill:i?"rgba(255, 165, 0, 0.5)":"rgba(173, 216, 230, 0.5)",stroke:i?"orange":"blue",strokeWidth:i?.15:.1}),e.push({x:s.center.x,y:s.center.y,color:i?"orange":"blue",label:`${i?"NEW: ":""}${s.capacityMeshNodeId}\n${o?.offBoardConnectsTo?.join(", ")||""}`})}for(let n=0;n<this.createdEdges.length;n++){const s=this.createdEdges[n],o=n===this.createdEdges.length-1&&"showing_edges"===this.animationState,i=this.nodeMap.get(s.nodeIds[0]),r=this.nodeMap.get(s.nodeIds[1]);if(i&&r){t.push({points:[i.center,r.center],strokeColor:o?"red":"orange",strokeWidth:o?.2:.1,strokeDasharray:"0.3,0.15"});const n=La(i.center,r.center);e.push({x:n.x,y:n.y,color:o?"red":"orange",label:`${o?"NEW: ":""}⚡ ${s.offboardNetName}`})}}let o="Offboard Capacity Node Solver";switch(this.animationState){case"showing_nodes":o+=` - Showing nodes (${this.shownNodes.length}/${this.shownNodes.length+this.assignableNodes.length})`;break;case"showing_edges":o+=` - Creating edges (${this.createdEdges.length}/${this.createdEdges.length+this.pendingEdges.length})`;break;case"done":o+=` - Done (${this.shownNodes.length} nodes, ${this.createdEdges.length} edges)`}return{lines:t,points:e,rects:n,title:o}}getVirtualOffboardNodes(){return[]}getOffboardEdges(){return this.enhancedEdges.filter(t=>t.isOffboardEdge)}};function Xa(t,e){return t.x>=e.center.x-e.width/2&&t.x<=e.center.x+e.width/2&&t.y>=e.center.y-e.height/2&&t.y<=e.center.y+e.height/2}var Ya=class extends y{inputPaths;capacityEdges;originalConnections;fragmentedPaths=[];fragmentedConnections=[];fragmentedOriginalConnectionNames=new Set;nextFragmentId=0;animationState="showing_original_path";currentPath=null;currentFragments=[];currentFragmentIndex=0;nodeMap=new Map;constructor({capacityPaths:t,capacityEdges:e,capacityNodes:n,connections:s}){super(),this.inputPaths=[...t],this.capacityEdges=e,this.originalConnections=s,this.nodeMap=Da(n)}_step(){switch(this.animationState){case"showing_original_path":if(0===this.inputPaths.length)return this.animationState="done",void(this.solved=!0);this.currentPath=this.inputPaths.shift(),this.currentFragments=this.splitPath(this.currentPath),this.currentFragmentIndex=0;this.currentFragments.some(t=>t.isFragmentedPath)?this.animationState="showing_fragment":this.fragmentedPaths.push(...this.currentFragments);break;case"showing_fragment":if(this.currentFragmentIndex<this.currentFragments.length){const t=this.currentFragments[this.currentFragmentIndex];this.fragmentedPaths.push(t),this.currentFragmentIndex++}else this.currentPath&&(this.fragmentedOriginalConnectionNames.add(this.currentPath.connectionName),this.createFragmentConnections(this.currentPath,this.currentFragments)),this.currentPath=null,this.currentFragments=[],this.currentFragmentIndex=0,this.animationState="showing_original_path";break;case"done":this.solved=!0}}createFragmentConnections(t,e){const n=this.originalConnections.find(e=>e.name===t.connectionName);if(n)for(let t=0;t<e.length;t++){const s=e[t];if(!s.isFragmentedPath)continue;const o=n.pointsToConnect.filter(t=>{for(const e of s.nodeIds){const n=this.nodeMap.get(e);if(n&&Xa(t,n))return!0}return!1}),i=0===t,r=i?s.nodeIds[s.nodeIds.length-1]:s.nodeIds[0],a=this.nodeMap.get(r);if(o.length>0&&a){const t=o[0],e={x:a.center.x,y:a.center.y,layer:Ue(t)},r=i?[...o,e]:[e,...o];this.fragmentedConnections.push({name:s.connectionName,pointsToConnect:r,netConnectionName:n.netConnectionName,rootConnectionName:n.rootConnectionName})}}}splitPath(t){const{nodeIds:e}=t;if(e.length<2)return[t];const n=[];for(let t=0;t<e.length-1;t++){const s=this.capacityEdges.find(n=>n.nodeIds[0]===e[t]&&n.nodeIds[1]===e[t+1]||n.nodeIds[0]===e[t+1]&&n.nodeIds[1]===e[t]);s&&s.isOffboardEdge&&n.push(t)}if(0===n.length)return[t];const s=[];let o=0,i=0;for(const r of n){const n=e.slice(o,r+1);if(n.length>=1){const e=this.nextFragmentId++;s.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${i++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}o=r+1}if(o<e.length){const n=e.slice(o);if(n.length>=1){const e=this.nextFragmentId++;s.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${i++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}}return s.length>0?s:[t]}getFragmentedPaths(){return this.fragmentedPaths}getFragmentedConnections(){return this.fragmentedConnections}getFragmentedOriginalConnectionNames(){return this.fragmentedOriginalConnectionNames}visualize(){const t=[],e=[],n=[];if("showing_original_path"===this.animationState&&this.currentPath&&this.drawPath({path:this.currentPath,color:"gray",lines:t,points:e,rects:n,labelPrefix:"Original: "}),this.fragmentedPaths.forEach((s,o)=>{if(s.isFragmentedPath){const i=o%2==0?"blue":"red";this.drawPath({path:s,color:i,lines:t,points:e,rects:n,labelPrefix:`Frag ${o}: `})}else this.drawPath({path:s,color:"green",lines:t,points:e,rects:n,labelPrefix:""})}),"showing_fragment"===this.animationState&&this.currentFragmentIndex>0){const s=this.fragmentedPaths.length-1;if(s>=0){const o=this.fragmentedPaths[s];o.isFragmentedPath&&this.drawPath({path:o,color:"orange",lines:t,points:e,rects:n,labelPrefix:"NEW: "})}}for(const e of this.capacityEdges)if(e.isOffboardEdge){const n=this.nodeMap.get(e.nodeIds[0]),s=this.nodeMap.get(e.nodeIds[1]);n&&s&&t.push({points:[n.center,s.center],strokeColor:"orange",strokeWidth:.15,strokeDasharray:"0.3,0.15"})}let s="Offboard Path Fragment Solver";return"showing_original_path"===this.animationState?s+=" - Analyzing path...":"showing_fragment"===this.animationState?s+=` - Fragment ${this.currentFragmentIndex}/${this.currentFragments.length}`:s+=` - Done (${this.fragmentedPaths.filter(t=>t.isFragmentedPath).length} fragments)`,{lines:t,points:e,rects:n,title:s}}drawPath(t){const{path:e,color:n,lines:s,points:o,rects:i,labelPrefix:r}=t,a=[];for(let t=0;t<e.nodeIds.length;t++){const s=e.nodeIds[t],c=this.nodeMap.get(s);c&&(a.push(c.center),i.push({center:c.center,width:.8*c.width,height:.8*c.height,stroke:n,strokeWidth:.05,fill:`${n}33`}),0!==t&&t!==e.nodeIds.length-1||o.push({x:c.center.x,y:c.center.y,color:n,label:`${r}${e.connectionName}\n${s}`}))}a.length>1&&s.push({points:a,strokeColor:n,strokeWidth:.1})}};function $a(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var ka=class extends y{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,o=Math.max(n,s),i=e.targetMinCapacity??.5;e.capacityDepth=Be(o,i)}this.connMap=$e(t),this.colorMap=ot(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;initialPathingSolver;initialPathingHyperSolver;pathingOptimizer;edgeToPortSegmentSolver;colorMap;segmentToPointSolver;unravelMultiSectionSolver;segmentToPointOptimizer;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;mergeAssignableViaNodes;offboardCapacityNodeSolver;offboardPathFragmentSolver;strawSolver;deadEndSolver;uselessViaRemovalSolver1;uselessViaRemovalSolver2;multiSimplifiedPathSolver1;multiSimplifiedPathSolver2;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[$a("netToPointPairsSolver",fn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ot(t.srjWithPointPairs,this.connMap),t.connMap=$e(t.srjWithPointPairs)}}),$a("nodeSolver",Ea,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),$a("mergeAssignableViaNodes",Aa,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.mergeAssignableViaNodes?.newNodes}}),$a("singleLayerNodeMerger",wa,t=>[t.capacityNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),$a("edgeSolver",cn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),$a("offboardCapacityNodeSolver",Fa,t=>[{capacityNodes:t.capacityNodes,capacityEdges:t.capacityEdges||[]}],{onSolved:t=>{t.capacityEdges=t.offboardCapacityNodeSolver?.enhancedEdges||t.capacityEdges}}),$a("deadEndSolver",Oi,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges}],{onSolved:t=>{const e=t.deadEndSolver?.removedNodeIds;t.capacityNodes=t.capacityNodes.filter(t=>!e.has(t.capacityMeshNodeId)),t.capacityEdges=t.capacityEdges.filter(t=>t.nodeIds.every(t=>!e.has(t)))}}),$a("initialPathingHyperSolver",za,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}],{onSolved:t=>{const e=t.initialPathingHyperSolver?.winningSolver;e&&(t.initialPathingSolver=e)}}),$a("offboardPathFragmentSolver",Ya,t=>[{capacityPaths:t.initialPathingSolver?.getCapacityPaths()||[],capacityEdges:t.capacityEdges||[],capacityNodes:t.capacityNodes||[],connections:t.srjWithPointPairs?.connections||[]}],{onSolved:t=>{const e=t.offboardPathFragmentSolver;if(!e)return;const n=e.getFragmentedPaths();for(const e of n)if(e.isFragmentedPath&&e.mstPairConnectionName){const n=t.colorMap[e.mstPairConnectionName];n&&!t.colorMap[e.connectionName]&&(t.colorMap[e.connectionName]=n)}const s=e.getFragmentedOriginalConnectionNames(),o=e.getFragmentedConnections();s.size>0&&t.srjWithPointPairs&&(t.srjWithPointPairs={...t.srjWithPointPairs,connections:[...t.srjWithPointPairs.connections.filter(t=>!s.has(t.name)),...o]},t.connMap=$e(t.srjWithPointPairs))}}),$a("edgeToPortSegmentSolver",qo,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.offboardPathFragmentSolver?.getFragmentedPaths()||t.initialPathingSolver?.getCapacityPaths()||[],colorMap:t.colorMap}]),$a("segmentToPointSolver",ni,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),$a("unravelMultiSectionSolver",mi,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),$a("highDensityRouteSolver",Le,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap}]),$a("highDensityStitchSolver",nn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),$a("uselessViaRemovalSolver1",ao,t=>[{unsimplifiedHdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),$a("multiSimplifiedPathSolver1",Po,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver1?.getOptimizedHdRoutes()||t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}]),$a("uselessViaRemovalSolver2",ao,t=>[{unsimplifiedHdRoutes:t.multiSimplifiedPathSolver1.simplifiedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),$a("multiSimplifiedPathSolver2",Po,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver2?.getOptimizedHdRoutes(),obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}])];getConstructorParams(){return[this.srj,this.opts]}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 t=this.netToPointPairsSolver?.visualize(),e=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),s=this.mergeAssignableViaNodes?.visualize(),o=this.singleLayerNodeMerger?.visualize(),i=this.strawSolver?.visualize(),r=this.edgeSolver?.visualize(),a=(this.offboardCapacityNodeSolver?.visualize(),this.deadEndSolver?.visualize()),c=this.initialPathingSolver?.visualize(),h=this.offboardPathFragmentSolver?.visualize(),d=this.pathingOptimizer?.visualize(),l=this.edgeToPortSegmentSolver?.visualize(),u=this.segmentToPointSolver?.visualize(),p=this.unravelMultiSectionSolver?.visualize()??this.segmentToPointOptimizer?.visualize(),m=this.highDensityRouteSolver?.visualize(),f=this.highDensityStitchSolver?.visualize(),y=this.uselessViaRemovalSolver1?.visualize(),x=this.uselessViaRemovalSolver2?.visualize(),v=this.multiSimplifiedPathSolver1?.visualize(),S=this.multiSimplifiedPathSolver2?.visualize(),P=this.srj.outline,b=[];if(b.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),P&&P.length>=2){const t=P.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),b.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const M={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:t.layers?.join(", ")}))],lines:b},N=[M,t,e,n,s,o,i,r,a,c,h,d,l,u,p,m?g(M,m):null,f,y,v,x,S,this.solved?g(M,sn(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...N)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.connectionName]}),t.length>200)break}return{lines:t}}if(this.pathingOptimizer){const t=[];for(const e of this.pathingOptimizer.connectionsWithNodes)e.path&&t.push({points:e.path.map(t=>({x:t.center.x,y:t.center.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.multiSimplifiedPathSolver2?.simplifiedHdRoutes??this.uselessViaRemovalSolver2?.getOptimizedHdRoutes()??this.multiSimplifiedPathSolver1?.simplifiedHdRoutes??this.uselessViaRemovalSolver1?.getOptimizedHdRoutes()??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes(),n=this.srjWithPointPairs?.connections??[];for(const s of n){const n=s.netConnectionName,o=s.rootConnectionName,i=e.filter(t=>t.connectionName===s.name);for(let e=0;e<i.length;e++){const r=i[e],a={type:"pcb_trace",pcb_trace_id:`${s.name}_${e}`,connection_name:n??o??s.name,route:We(r,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Ba=1.8,ja=.95,Wa=.8,Ha=.95,Ua=class extends y{obstacleRoutes;bounds;boundsSize;boundsCenter;A;B;roundedGoalPosition;straightLineDistance;traceThickness;obstacleMargin;minCellSize=.05;cellStep=.05;GREEDY_MULTIPLER=1.1;numRoutes;JUMPER_PENALTY_FACTOR;FUTURE_CONNECTION_START_END_PENALTY;FUTURE_CONNECTION_START_END_PROXIMITY;FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY;FUTURE_CONNECTION_JUMPER_PAD_PENALTY;JUMPER_JUMPER_PAD_PROXIMITY;JUMPER_JUMPER_PAD_PENALTY;FUTURE_CONNECTION_LINE_PROXIMITY;FUTURE_CONNECTION_LINE_PENALTY;OBSTACLE_PROX_PENALTY_FACTOR;OBSTACLE_PROX_SIGMA;EDGE_PROX_PENALTY_FACTOR;EDGE_PROX_SIGMA;ALLOW_DIAGONAL;MIN_TRAVEL_BEFORE_JUMPER;CELL_SIZE_FACTOR;exploredNodes;candidates;connectionName;rootConnectionName;solvedPath=null;futureConnections;hyperParameters;connMap;debug_exploredNodesOrdered;debug_exploredNodeValues;debug_nodesTooCloseToObstacle;debug_nodePathToParentIntersectsObstacle;debugEnabled=!0;initialNodeGridOffset;existingJumpers;constructor(t){super(),this.bounds=t.bounds,this.connMap=t.connMap,this.hyperParameters=t.hyperParameters??{};const e=Math.sqrt((t.bounds.maxX-t.bounds.minX)**2+(t.bounds.maxY-t.bounds.minY)**2);this.CELL_SIZE_FACTOR=this.hyperParameters.CELL_SIZE_FACTOR??1,this.JUMPER_PENALTY_FACTOR=.2,this.FUTURE_CONNECTION_START_END_PROXIMITY??=8,this.FUTURE_CONNECTION_START_END_PENALTY??=3,this.FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY=this.hyperParameters.FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY??e/4,this.FUTURE_CONNECTION_JUMPER_PAD_PENALTY=this.hyperParameters.FUTURE_CONNECTION_JUMPER_PAD_PENALTY??1e3,this.JUMPER_JUMPER_PAD_PROXIMITY=this.hyperParameters.JUMPER_JUMPER_PAD_PROXIMITY??5,this.JUMPER_JUMPER_PAD_PENALTY=this.hyperParameters.JUMPER_JUMPER_PAD_PENALTY??0,this.FUTURE_CONNECTION_LINE_PROXIMITY=this.hyperParameters.FUTURE_CONNECTION_LINE_PROXIMITY??10,this.FUTURE_CONNECTION_LINE_PENALTY=this.hyperParameters.FUTURE_CONNECTION_LINE_PENALTY??5,this.OBSTACLE_PROX_PENALTY_FACTOR=this.hyperParameters.OBSTACLE_PROX_PENALTY_FACTOR??2,this.OBSTACLE_PROX_SIGMA=this.hyperParameters.OBSTACLE_PROX_SIGMA??2,this.EDGE_PROX_PENALTY_FACTOR=this.hyperParameters.EDGE_PROX_PENALTY_FACTOR??1,this.EDGE_PROX_SIGMA=this.hyperParameters.EDGE_PROX_SIGMA??1,this.ALLOW_DIAGONAL=this.hyperParameters.ALLOW_DIAGONAL??!0,this.MIN_TRAVEL_BEFORE_JUMPER??=3,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.rootConnectionName=t.rootConnectionName,this.obstacleRoutes=t.obstacleRoutes,this.A={...t.A,z:0},this.B={...t.B,z:0},this.traceThickness=t.traceThickness??.15,this.obstacleMargin=t.obstacleMargin??.2,this.exploredNodes=new Set,this.straightLineDistance=St(this.A,this.B),this.futureConnections=t.futureConnections??[],this.MAX_ITERATIONS=1e4,this.debug_exploredNodesOrdered=[],this.debug_exploredNodeValues=new Map,this.debug_nodesTooCloseToObstacle=new Set,this.debug_nodePathToParentIntersectsObstacle=new Set,this.numRoutes=this.obstacleRoutes.length+this.futureConnections.length,this.existingJumpers=[];for(const t of this.obstacleRoutes)t.jumpers&&this.existingJumpers.push(...t.jumpers);const n=Math.ceil(5*(this.numRoutes+1));let s=this.boundsSize.width/this.cellStep,o=this.boundsSize.height/this.cellStep;for(;s*o>n**2&&!(this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,s=this.boundsSize.width/this.cellStep,o=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR;const i=Math.abs(this.A.x-this.bounds.minX)<.001&&Math.abs(this.B.x-this.bounds.minX)<.001||Math.abs(this.A.x-this.bounds.maxX)<.001&&Math.abs(this.B.x-this.bounds.maxX)<.001||Math.abs(this.A.y-this.bounds.minY)<.001&&Math.abs(this.B.y-this.bounds.minY)<.001||Math.abs(this.A.y-this.bounds.maxY)<.001&&Math.abs(this.B.y-this.bounds.maxY)<.001;this.futureConnections&&0===this.futureConnections.length&&0===this.obstacleRoutes.length&&!i&&this.handleSimpleCases();const r={x:t.A.x,y:t.A.y};this.initialNodeGridOffset={x:r.x-Math.round(t.A.x/this.cellStep)*this.cellStep,y:r.y-Math.round(t.A.y/this.cellStep)*this.cellStep},this.roundedGoalPosition={x:Math.round(t.B.x/this.cellStep)*this.cellStep,y:Math.round(t.B.y/this.cellStep)*this.cellStep,z:0};const a={distFromStart:0,weightedMmNearObstacle:0,weightedMmNearEdge:0,weightedMmNearFutureConnectionStartEnd:0,weightedMmNearFutureConnectionLine:0,jumperPenalty:0,jumperPadFutureConnectionPenalty:0,total:0},c={distanceToGoal:0,obstacleProximity:0,edgeProximity:0,futureConnectionStartEndProximityPenalty:0,futureConnectionLine:0,total:0,obstacleProximityRate:0,edgeProximityRate:0,futureConnectionStartEndProximityRate:0,futureConnectionLineRate:0};this.candidates=new zt([{...t.A,...r,z:0,g:0,h:0,f:0,jumperCount:0,gComponents:a,hComponents:c,parent:{...t.A,z:0,g:0,h:0,f:0,gComponents:a,hComponents:c,parent:null}}])}handleSimpleCases(){this.solved=!0;const{A:t,B:e}=this;this.solvedPath={connectionName:this.connectionName,rootConnectionName:this.rootConnectionName,route:[{x:t.x,y:t.y,z:0},{x:e.x,y:e.y,z:0}],traceThickness:this.traceThickness,jumpers:[]}}get jumperPenaltyDistance(){return Ba+this.straightLineDistance*this.JUMPER_PENALTY_FACTOR}isNodeTooCloseToObstacle(t,e){e??=this.obstacleMargin;for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!s){const s=Va(n);for(const n of s)if(vt(t,n.A,n.B)<this.traceThickness+e)return!0}for(const s of n.jumpers||[])if(this.isNodeTooCloseToJumper(t,s,e))return!0}return!1}isNodeTooCloseToJumper(t,e,n){const s=e.end.x-e.start.x,o=e.end.y-e.start.y,i=Math.abs(s)>Math.abs(o),r=(i?Wa:Ha)/2+n,a=(i?Ha:Wa)/2+n;return Math.abs(t.x-e.start.x)<r&&Math.abs(t.y-e.start.y)<a||Math.abs(t.x-e.end.x)<r&&Math.abs(t.y-e.end.y)<a}isNodeTooCloseToEdge(t){const e=t.gComponents?.distFromStart??0<this.obstacleMargin/2?-this.obstacleMargin/2:this.obstacleMargin/2,n=t.x<this.bounds.minX+e||t.x>this.bounds.maxX-e||t.y<this.bounds.minY+e||t.y>this.bounds.maxY-e;return(!n||!(St(t,this.B)<2*e||St(t,this.A)<2*e))&&n}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!s){for(const s of Va(n))if(gt(t,e,s.A,s.B))return!0;for(const s of n.jumpers||[])if(this.doesSegmentIntersectJumperPads(t,e,s))return!0}}return!1}doesSegmentIntersectJumperPads(t,e,n){const s=this.obstacleMargin,o=n.end.x-n.start.x,i=n.end.y-n.start.y,r=Math.abs(o)>Math.abs(i),a=(r?Wa:Ha)/2+s,c=(r?Ha:Wa)/2+s;return!!this.doesSegmentIntersectRect(t,e,n.start,a,c)||!!this.doesSegmentIntersectRect(t,e,n.end,a,c)}doesSegmentIntersectRect(t,e,n,s,o){const i=n.x-s,r=n.x+s,a=n.y-o,c=n.y+o;if(t.x>=i&&t.x<=r&&t.y>=a&&t.y<=c)return!0;if(e.x>=i&&e.x<=r&&e.y>=a&&e.y<=c)return!0;const h=[{A:{x:i,y:a},B:{x:r,y:a}},{A:{x:r,y:a},B:{x:r,y:c}},{A:{x:r,y:c},B:{x:i,y:c}},{A:{x:i,y:c},B:{x:i,y:a}}];for(const n of h)if(gt(t,e,n.A,n.B))return!0;return!1}findObstaclesBetween(t,e){const n=[];for(const s of this.obstacleRoutes){const o=this.connMap?.areIdsConnected?.(this.connectionName,s.connectionName);if(!o)for(const o of Va(s))gt(t,e,o.A,o.B)&&n.push({A:o.A,B:o.B})}return n}computeHComponents(t){const e=St(t,this.roundedGoalPosition),n=this.getObstacleProximityPenalty(t),s=this.getEdgeProximityPenalty(t),o=this.getFutureConnectionStartEndPenalty(t),i=this.getFutureConnectionLinePenalty(t),r=t.parent,a=r?.hComponents,c=r?St(t,r):0,h=(t,n)=>{if(void 0===n||c<1e-9||e<1e-9)return t;const s=(t-n)/c;return(t+Math.max(0,t+s*e))/2},d=h(n,a?.obstacleProximityRate),l=h(s,a?.edgeProximityRate),u=h(o,a?.futureConnectionStartEndProximityRate),p=h(i,a?.futureConnectionLineRate),m=d*e,f=l*e,g=u*e,y=p*e;return{distanceToGoal:e,obstacleProximity:m,edgeProximity:f,futureConnectionStartEndProximityPenalty:g,futureConnectionLine:y,total:e+m+f+g+y,obstacleProximityRate:n,edgeProximityRate:s,futureConnectionStartEndProximityRate:o,futureConnectionLineRate:i}}computeH(t){return this.computeHComponents(t).total}computeGComponents(t){const e=t.parent,n=e?St(t,e):0,s=e?.gComponents??{distFromStart:0,weightedMmNearObstacle:0,weightedMmNearEdge:0,weightedMmNearFutureConnectionStartEnd:0,weightedMmNearFutureConnectionLine:0,jumperPenalty:0,jumperPadFutureConnectionPenalty:0,total:0},o=s.distFromStart+n,i=s.weightedMmNearObstacle+this.getObstacleProximityPenalty(t)*n,r=s.weightedMmNearEdge+this.getEdgeProximityPenalty(t)*n,a=s.weightedMmNearFutureConnectionStartEnd+this.getFutureConnectionStartEndPenalty(t)*n,c=s.weightedMmNearFutureConnectionLine+this.getFutureConnectionLinePenalty(t)*n;let h=s.jumperPenalty,d=s.jumperPadFutureConnectionPenalty;t.isJumperExit&&(h+=this.jumperPenaltyDistance,d+=this.getJumperPadFutureConnectionPenalty(t));return{distFromStart:o,weightedMmNearObstacle:i,weightedMmNearEdge:r,weightedMmNearFutureConnectionStartEnd:a,weightedMmNearFutureConnectionLine:c,jumperPenalty:h,jumperPadFutureConnectionPenalty:d,total:o+i+r+a+c+h+d}}computeG(t){return this.computeGComponents(t).total}computeF(t,e){return t+e*this.GREEDY_MULTIPLER}getClosestFutureConnectionPoint(t){let e=1/0,n=null;for(const s of this.futureConnections)for(const o of s.points){const s=St(t,o);s<e&&(e=s,n=o)}return n}getFutureConnectionStartEndPenalty(t){let e=0;const n=this.getClosestFutureConnectionPoint(t);if(n){const s=St(t,n);if(s>this.FUTURE_CONNECTION_START_END_PROXIMITY)return 0;const o=s/this.FUTURE_CONNECTION_START_END_PROXIMITY;e=this.FUTURE_CONNECTION_START_END_PENALTY*(1-o)**2}return e}getFutureConnectionLinePenalty(t){if(0===this.futureConnections.length)return 0;let e=1/0;const n=Math.min(1,(t.hComponents?.distanceToGoal??0)/this.FUTURE_CONNECTION_LINE_PROXIMITY)**2;for(const n of this.futureConnections){if(n.points.length<2)continue;const s=vt(t,n.points[0],n.points[n.points.length-1]);e=Math.min(e,s)}if(e*=n,e<this.FUTURE_CONNECTION_LINE_PROXIMITY){const t=Math.max(.1,e/this.FUTURE_CONNECTION_LINE_PROXIMITY);return this.FUTURE_CONNECTION_LINE_PENALTY*(1-t)**2}return 0}getJumperPadFutureConnectionPenalty(t){if(!t.isJumperExit||!t.jumperEntry)return 0;const e=t.jumperEntry,n={x:t.x,y:t.y};let s=1/0;for(const t of this.futureConnections)for(const o of t.points){const t=St(e,o),i=St(n,o),r=Math.min(t,i);s=Math.min(s,r)}if(s<this.FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY){const t=s/this.FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY;return this.FUTURE_CONNECTION_JUMPER_PAD_PENALTY*(1-t)}return 0}getClearanceToObstacles(t){let e=1/0;for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!s){for(const s of Va(n))e=Math.min(e,vt(t,s.A,s.B));for(const s of n.jumpers||[])e=Math.min(e,this.distanceToJumperPads(t,s))}}return e}distanceToJumperPads(t,e){const n=e.end.x-e.start.x,s=e.end.y-e.start.y,o=Math.abs(n)>Math.abs(s),i=(o?Wa:Ha)/2,r=(o?Ha:Wa)/2;return Math.min(this.pointToRectDistance(t,e.start,i,r),this.pointToRectDistance(t,e.end,i,r))}pointToRectDistance(t,e,n,s){const o=Math.max(Math.abs(t.x-e.x)-n,0),i=Math.max(Math.abs(t.y-e.y)-s,0);return Math.hypot(o,i)}getClearanceToEdge(t){return Math.min(t.x-this.bounds.minX,this.bounds.maxX-t.x,t.y-this.bounds.minY,this.bounds.maxY-t.y)}getObstacleProximityPenalty(t){const e=this.getClearanceToObstacles(t),n=Math.max(0,e-(this.traceThickness+this.obstacleMargin)),s=this.OBSTACLE_PROX_SIGMA;return this.OBSTACLE_PROX_PENALTY_FACTOR*Math.exp(-n/s)}getEdgeProximityPenalty(t){const e=this.getClearanceToEdge(t),n=this.EDGE_PROX_SIGMA;if(e>2*this.EDGE_PROX_SIGMA)return 0;const s=St(t,this.B),o=Math.min(1,s/(2*this.EDGE_PROX_SIGMA));return this.EDGE_PROX_PENALTY_FACTOR*Math.exp(-e/n)*o}getNodeKey(t){const e=t.isJumperExit?"_j":"";return`${Math.round(t.x/this.cellStep)*this.cellStep},${Math.round(t.y/this.cellStep)*this.cellStep},${t.z}${e}`}getJumperNeighbors(t){const e=[];if((t.gComponents?.distFromStart??0)<this.MIN_TRAVEL_BEFORE_JUMPER)return e;const n=[{dx:1,dy:0},{dx:-1,dy:0},{dx:0,dy:1},{dx:0,dy:-1}];for(const s of n){const n=2*Ba,o=t.x+s.dx*n,i=t.y+s.dy*n,r=this.findObstaclesBetween(t,{x:o,y:i});if(r.length>0)for(const n of r){const o=this.calculateJumperExit(t,n,s);o&&!this.exploredNodes.has(this.getNodeKey(o))&&(this.isNodeTooCloseToObstacle(o)||this.isNodeTooCloseToEdge(o)||!this.isJumperPlacementValid(t,o)||(o.gComponents=this.computeGComponents(o),o.hComponents=this.computeHComponents(o),o.g=o.gComponents.total,o.h=o.hComponents.total,o.f=this.computeF(o.g,o.h),e.push(o)))}}return e}calculateJumperExit(t,e,n){const s=Ba,o=Math.sqrt(n.dx*n.dx+n.dy*n.dy),i=n.dx/o,r=n.dy/o,a=t.x+i*s,c=t.y+r*s;return a<this.bounds.minX||a>this.bounds.maxX||c<this.bounds.minY||c>this.bounds.maxY?null:{x:a,y:c,z:0,parent:t,g:0,h:0,f:0,jumperEntry:{x:t.x,y:t.y},isJumperExit:!0,jumperCount:(t.jumperCount??0)+1}}isJumperTooCloseToTraces(t,e){const n=e.x-t.x,s=e.y-t.y,o=Math.abs(n)>Math.abs(s),i=(o?Wa:Ha)/2,r=(o?Ha:Wa)/2,a=this.obstacleMargin,c=[t,e];for(const t of c){const e=[t,{x:t.x-i,y:t.y-r},{x:t.x+i,y:t.y-r},{x:t.x-i,y:t.y+r},{x:t.x+i,y:t.y+r},{x:t.x-i,y:t.y},{x:t.x+i,y:t.y},{x:t.x,y:t.y-r},{x:t.x,y:t.y+r}];for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(s)continue;const o=Va(n);for(const n of o){for(const t of e)if(vt(t,n.A,n.B)<this.traceThickness+a)return!0;if(this.doesSegmentIntersectRect(n.A,n.B,t,i+a,r+a))return!0}}}return!1}isJumperPlacementValid(t,e){if(this.isJumperTooCloseToTraces(t,e))return!1;const n={route_type:"jumper",start:{x:t.x,y:t.y},end:{x:e.x,y:e.y},footprint:"0603"};for(const t of this.existingJumpers)if(this.doJumpersOverlap(n,t))return!1;const s=this.getJumpersInPath(t);for(const t of s)if(this.doJumpersOverlap(n,t))return!1;return!0}doJumpersOverlap(t,e){const n=this.obstacleMargin,s=Math.min(t.start.x,t.end.x)-ja/2-n,o=Math.max(t.start.x,t.end.x)+ja/2+n,i=Math.min(t.start.y,t.end.y)-ja/2-n,r=Math.max(t.start.y,t.end.y)+ja/2+n,a=Math.min(e.start.x,e.end.x)-ja/2-n,c=Math.max(e.start.x,e.end.x)+ja/2+n,h=Math.min(e.start.y,e.end.y)-ja/2-n,d=Math.max(e.start.y,e.end.y)+ja/2+n;return!(o<a||s>c||r<h||i>d)}getJumpersInPath(t){const e=[];let n=t;for(;n&&n.parent;)n.isJumperExit&&n.jumperEntry&&e.push({route_type:"jumper",start:n.jumperEntry,end:{x:n.x,y:n.y},footprint:"0603"}),n=n.parent;return e}getNeighbors(t){const e=[],{maxX:n,minX:s,maxY:o,minY:i}=this.bounds;for(let r=-1;r<=1;r++)for(let a=-1;a<=1;a++){if(0===r&&0===a)continue;if(!this.ALLOW_DIAGONAL&&0!==r&&0!==a)continue;const c=t.x+r*this.cellStep,h=t.y+a*this.cellStep,d=Za(c,s,n),l=Za(h,i,o),u={...t,parent:t,x:d,y:l,isJumperExit:!1,jumperEntry:void 0,jumperCount:t.jumperCount??0},p=this.getNodeKey(u);this.exploredNodes.has(p)||(this.isNodeTooCloseToObstacle(u)?(this.debug_nodesTooCloseToObstacle.add(p),this.exploredNodes.add(p)):this.isNodeTooCloseToEdge(u)?this.debug_nodesTooCloseToObstacle.add(p):this.doesPathToParentIntersectObstacle(u)?(this.debug_nodePathToParentIntersectsObstacle.add(p),this.exploredNodes.add(p)):(u.gComponents=this.computeGComponents(u),u.hComponents=this.computeHComponents(u),u.g=u.gComponents.total,u.h=u.hComponents.total,u.f=this.computeF(u.g,u.h),e.push(u)))}const r=this.getJumperNeighbors(t);return e.push(...r),e}getNodePath(t){const e=[];let n=t;for(;n;)e.push(n),n=n.parent;return e}setSolvedPath(t){const e=this.getNodePath(t);e.reverse();const n=[];for(let t=0;t<e.length;t++){const s=e[t];s.isJumperExit&&s.jumperEntry&&n.push({route_type:"jumper",start:s.jumperEntry,end:{x:s.x,y:s.y},footprint:"0603"})}this.solvedPath={connectionName:this.connectionName,rootConnectionName:this.rootConnectionName,traceThickness:this.traceThickness,route:e.map(t=>({x:t.x,y:t.y,z:0})).concat([{x:this.B.x,y:this.B.y,z:0}]),jumpers:n}}computeProgress(t,e){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 this.failed=!0,void(this.error="Ran out of candidate nodes to explore");this.exploredNodes.add(e),this.debug_exploredNodesOrdered.push(e),this.debug_exploredNodeValues.set(e,{g:t.g,h:t.h,f:t.f,gComponents:t.gComponents,hComponents:t.hComponents});const n=St(t,this.roundedGoalPosition);this.progress=this.computeProgress(t,n),n<=this.cellStep*Math.SQRT2&&!this.doesPathToParentIntersectObstacle({...t,parent:t,x:this.B.x,y:this.B.y})&&(this.solved=!0,this.setSolvedPath(t));const s=this.getNeighbors(t);for(const t of s)this.candidates.enqueue(t)}drawJumperPads(t,e,n,s,o){const i=e.end.x-e.start.x,r=e.end.y-e.start.y,a=Wa,c=Ha,h=Math.abs(i)>Math.abs(r),d=h?a:c,l=h?c:a;t.rects.push({center:{x:e.start.x,y:e.start.y},width:d,height:l,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:s??"jumper",step:o}),t.rects.push({center:{x:e.end.x,y:e.end.y},width:d,height:l,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:s??"jumper",step:o}),t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*c,layer:s??"jumper-body",step:o})}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.points.push({x:this.A.x,y:this.A.y,label:`Input A\nz: ${this.A.z}`,color:"orange"}),t.points.push({x:this.B.x,y:this.B.y,label:`Input B\nz: ${this.B.z}`,color:"orange"}),t.lines.push({points:[this.A,this.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:"Direct Input Connection"});for(let e=0;e<this.obstacleRoutes.length;e++){const n=this.obstacleRoutes[e];for(let s=0;s<n.route.length-1;s++)t.lines.push({points:[n.route[s],n.route[s+1]],strokeColor:"rgba(255, 0, 0, 0.75)",strokeWidth:n.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`});for(const s of n.jumpers||[])this.drawJumperPads(t,s,"rgba(255, 0, 0, 0.5)",`obstacle-jumper-${e}`)}for(let e=0;e<this.futureConnections.length;e++){const n=this.futureConnections[e];if(n.points.length<2)continue;const s=n.points[0],o=n.points[n.points.length-1];t.lines.push({points:[s,o],strokeColor:"rgba(0, 100, 255, 0.6)",strokeWidth:this.traceThickness,label:`Future: ${n.connectionName}`,layer:`future-connection-${e}`})}for(let e=0;e<this.debug_exploredNodesOrdered.length;e++){const n=this.debug_exploredNodesOrdered[e];if(this.debug_nodesTooCloseToObstacle.has(n))continue;if(this.debug_nodePathToParentIntersectsObstacle.has(n))continue;const[s,o]=n.split(",").map(Number),i=n.endsWith("_j"),r=this.debug_exploredNodeValues.get(n),a=r?.gComponents,c=r?.hComponents,h=c?.distanceToGoal??0,d=[i?"Explored (jumper)":"Explored"];d.push(`g.distFromStart: ${a?.distFromStart.toFixed(2)??"?"}`),d.push(`g.nearObstacle: ${a?.weightedMmNearObstacle.toFixed(2)??"?"}`),d.push(`g.nearEdge: ${a?.weightedMmNearEdge.toFixed(2)??"?"}`),d.push(`g.nearFutStrtEnd: ${a?.weightedMmNearFutureConnectionStartEnd.toFixed(2)??"?"}`),d.push(`g.nearFutLine: ${a?.weightedMmNearFutureConnectionLine.toFixed(2)??"?"}`),d.push(`g.jumper: ${a?.jumperPenalty.toFixed(2)??"?"}`),d.push(`g.jumperPadFutPenalty: ${a?.jumperPadFutureConnectionPenalty.toFixed(2)??"?"}`),d.push(`h.goalDist: ${h.toFixed(2)}`),d.push(`h.obstacleProx: ${c?.obstacleProximity.toFixed(2)??"?"} (${h>0?((c?.obstacleProximity??0)/h).toFixed(3):0}/mm)`),d.push(`h.edgeProx: ${c?.edgeProximity.toFixed(2)??"?"} (${h>0?((c?.edgeProximity??0)/h).toFixed(3):0}/mm)`),d.push(`h.futureConnPt: ${c?.futureConnectionStartEndProximityPenalty.toFixed(2)??"?"} (${h>0?((c?.futureConnectionStartEndProximityPenalty??0)/h).toFixed(3):0}/mm)`),d.push(`h.futureConnLine: ${c?.futureConnectionLine.toFixed(2)??"?"} (${h>0?((c?.futureConnectionLine??0)/h).toFixed(3):0}/mm)`),d.push(`g: ${r?.g.toFixed(2)??"?"}`),d.push(`h: ${r?.h.toFixed(2)??"?"}`),d.push(`f: ${r?.f.toFixed(2)??"?"}`);const l=d.join("\n");t.rects.push({center:{x:s+this.initialNodeGridOffset.x,y:o+this.initialNodeGridOffset.y},fill:i?`rgba(0,255,255,${.4-e/this.debug_exploredNodesOrdered.length*.3})`:`rgba(255,0,255,${.3-e/this.debug_exploredNodesOrdered.length*.2})`,width:.9*this.cellStep,height:.9*this.cellStep,label:l})}if(this.candidates.peek()){const e=this.candidates.peek();t.rects.push({center:{x:e.x,y:e.y},fill:"rgba(0, 255, 0, 0.8)",width:.9*this.cellStep,height:.9*this.cellStep,label:"Next"})}const e=this.candidates.getTopN(5);for(let n=0;n<e.length;n++){const s=e[n],o=s.isJumperExit??!1,i=s.gComponents,r=s.hComponents,a=r?.distanceToGoal??0,c=[`Candidate #${n+1}${o?" (jumper)":""}`];c.push(`g.distFromStart: ${i?.distFromStart.toFixed(2)??"?"}`),c.push(`g.nearObstacle: ${i?.weightedMmNearObstacle.toFixed(2)??"?"}`),c.push(`g.nearEdge: ${i?.weightedMmNearEdge.toFixed(2)??"?"}`),c.push(`g.nearFutureConnPt: ${i?.weightedMmNearFutureConnectionStartEnd.toFixed(2)??"?"}`),c.push(`g.nearFutureConnLine: ${i?.weightedMmNearFutureConnectionLine.toFixed(2)??"?"}`),c.push(`g.jumper: ${i?.jumperPenalty.toFixed(2)??"?"}`),c.push(`g.jumperPadFutureConn: ${i?.jumperPadFutureConnectionPenalty.toFixed(2)??"?"}`),c.push(`g: ${s.g.toFixed(2)}`),c.push(`h.goalDist: ${a.toFixed(2)}`),c.push(`h.obstacleProx: ${r?.obstacleProximity.toFixed(2)??"?"} (${a>0?((r?.obstacleProximity??0)/a).toFixed(3):0}/mm)`),c.push(`h.edgeProx: ${r?.edgeProximity.toFixed(2)??"?"} (${a>0?((r?.edgeProximity??0)/a).toFixed(3):0}/mm)`),c.push(`h.futureConnPt: ${r?.futureConnectionStartEndProximityPenalty.toFixed(2)??"?"} (${a>0?((r?.futureConnectionStartEndProximityPenalty??0)/a).toFixed(3):0}/mm)`),c.push(`h.futureConnLine: ${r?.futureConnectionLine.toFixed(2)??"?"} (${a>0?((r?.futureConnectionLine??0)/a).toFixed(3):0}/mm)`),c.push(`h: ${s.h.toFixed(2)}`),c.push(`f: ${s.f.toFixed(2)}`);const h=c.join("\n");t.points.push({x:s.x,y:s.y,color:"gray",label:h})}if(this.solvedPath){t.lines.push({points:this.solvedPath.route,strokeColor:"green",label:"Solved Route",strokeWidth:this.traceThickness});for(const e of this.solvedPath.jumpers)this.drawJumperPads(t,e,"rgba(0, 200, 0, 0.8)","solved-jumper")}const{minX:n,minY:s,maxX:o,maxY:i}=this.bounds;return t.lines.push({points:[{x:n,y:s},{x:o,y:s},{x:o,y:i},{x:n,y:i},{x:n,y:s}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}};function Va(t){const e=[];for(let n=0;n<t.route.length-1;n++)if(t.route[n].z===t.route[n+1].z){const s=t.route[n],o=t.route[n+1],i=t.jumpers?.some(t=>{const e=Math.abs(t.start.x-s.x)<.001&&Math.abs(t.start.y-s.y)<.001&&Math.abs(t.end.x-o.x)<.001&&Math.abs(t.end.y-o.y)<.001,n=Math.abs(t.start.x-o.x)<.001&&Math.abs(t.start.y-o.y)<.001&&Math.abs(t.end.x-s.x)<.001&&Math.abs(t.end.y-s.y)<.001;return e||n});i||e.push({z:s.z,A:s,B:o})}return e}function Za(t,e,n){return Math.max(e,Math.min(t,n))}var Ga=.8,Ja=.95,qa=class extends y{nodeWithPortPoints;colorMap;unsolvedConnections;totalConnections;solvedRoutes;failedSubSolvers;hyperParameters;minDistBetweenEnteringPoints;traceWidth;activeSubSolver=null;lastActiveSubSolver=null;connMap;get failedSolvers(){return this.failedSubSolvers}get activeSolver(){return this.activeSubSolver}constructor(t){const{nodeWithPortPoints:e,colorMap:n}=t;super(),this.nodeWithPortPoints=e,this.colorMap=n??{},this.solvedRoutes=[],this.hyperParameters=t.hyperParameters??{},this.failedSubSolvers=[],this.connMap=t.connMap,this.traceWidth=t.traceWidth??.15;const s=new Map;for(const{connectionName:t,rootConnectionName:n,x:o,y:i}of e.portPoints){const e=s.get(t);s.set(t,{rootConnectionName:e?.rootConnectionName??n,points:[...e?.points??[],{x:o,y:i,z:0}]})}this.unsolvedConnections=Array.from(s.entries().map(([t,{rootConnectionName:e,points:n}])=>({connectionName:t,rootConnectionName:e,points:n}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=kt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},n)=>({...e,points:kt(t,7117*n+(this.hyperParameters.SHUFFLE_SEED??0))}))),this.totalConnections=this.unsolvedConnections.length,this.MAX_ITERATIONS=1e3*this.totalConnections**1.5,this.minDistBetweenEnteringPoints=jt(this.nodeWithPortPoints)}getConstructorParams(){return{nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,hyperParameters:this.hyperParameters,connMap:this.connMap,traceWidth:this.traceWidth}}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.lastActiveSubSolver=this.activeSubSolver,this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSubSolvers.push(this.activeSubSolver),this.lastActiveSubSolver=this.activeSubSolver,this.activeSubSolver=null,this.error=this.failedSubSolvers.map(t=>t.error).join("\n"),this.failed=!0));const t=this.unsolvedConnections.pop();if(this.progress=this.computeProgress(),!t)return void(this.solved=0===this.failedSubSolvers.length);if(1===t.points.length)return;if(2===t.points.length){const[e,n]=t.points,s=Math.abs(e.x-n.x)<1e-6,o=Math.abs(e.y-n.y)<1e-6;if(s&&o)return}const{connectionName:e,rootConnectionName:n,points:s}=t;this.activeSubSolver=new Ua({connectionName:e,rootConnectionName:n,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:Bt(this.nodeWithPortPoints),A:{x:s[0].x,y:s[0].y,z:0},B:{x:s[s.length-1].x,y:s[s.length-1].y,z:0},obstacleRoutes:this.solvedRoutes.filter(t=>(!n||t.rootConnectionName!==n)&&!this.connMap?.areIdsConnected(t.connectionName,e)),futureConnections:this.unsolvedConnections,hyperParameters:this.hyperParameters,connMap:this.connMap,traceThickness:this.traceWidth})}drawJumperPads(t,e,n,s){const o=e.end.x-e.start.x,i=e.end.y-e.start.y,r=Ga,a=Ja,c=Math.abs(o)>Math.abs(i),h=c?r:a,d=c?a:r;t.rects.push({center:{x:e.start.x,y:e.start.y},width:h,height:d,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.rects.push({center:{x:e.end.x,y:e.end.y},width:h,height:d,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*a,layer:"jumper-body"})}visualize(){if(this.activeSubSolver&&!this.solved)return this.activeSubSolver.visualize();if(this.failed&&this.lastActiveSubSolver)return this.lastActiveSubSolver.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: 0 (single-layer)"].join("\n"),color:this.colorMap[e.connectionName]??"blue"});for(let e=0;e<this.solvedRoutes.length;e++){const n=this.solvedRoutes[e];if(n.route.length>0){const s=this.colorMap[n.connectionName]??"blue";for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1];t.lines.push({points:[o,i],strokeColor:it(s,.2),layer:"route-layer-0",strokeWidth:n.traceThickness})}for(const o of n.jumpers)this.drawJumperPads(t,o,it(s,.5),e)}}const e=Bt(this.nodeWithPortPoints),{minX:n,minY:s,maxX:o,maxY:i}=e;return t.lines.push({points:[{x:n,y:s},{x:o,y:s},{x:o,y:i},{x:n,y:i},{x:n,y:s}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}};export{ka as AssignableAutoroutingPipeline1Solver,dr as AssignableAutoroutingPipeline2,Ia as AssignableAutoroutingPipeline3,Di as AutoroutingPipeline1_OriginalUnravel,Go as AutoroutingPipelineSolver,Jo as CapacityMeshSolver,Sa as CurvyIntraNodeSolver,ba as HighDensitySolver,ct as InMemoryCache,qa as IntraNodeSolverWithJumpers,dt as LocalStorageCache,Ua as SingleHighDensityRouteWithJumpersSolver,Be as calculateOptimalCapacityDepth,sn as convertSrjToGraphicsObject,ut as getGlobalInMemoryCache,lt as getGlobalLocalStorageCache,ke as getTunedTotalCapacity1,pt as setupGlobalCaches};
|
|
1
|
+
var t=Object.create,e=Object.defineProperty,n=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,o=Object.getPrototypeOf,i=Object.prototype.hasOwnProperty,r=(t,e)=>function(){return e||(0,t[s(t)[0]])((e={exports:{}}).exports,e),e.exports},a=(r,a,c)=>(c=null!=r?t(o(r)):{},((t,o,r,a)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let c of s(o))i.call(t,c)||c===r||e(t,c,{get:()=>o[c],enumerable:!(a=n(o,c))||a.enumerable});return t})(!a&&r&&r.__esModule?c:e(c,"default",{value:r,enumerable:!0}),r)),c=r({"node_modules/is-buffer/index.js"(t,e){function n(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}e.exports=function(t){return null!=t&&(n(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&n(t.slice(0,0))}(t)||!!t._isBuffer)}}}),h=r({"node_modules/kind-of/index.js"(t,e){var n=c(),s=Object.prototype.toString;e.exports=function(t){if(void 0===t)return"undefined";if(null===t)return"null";if(!0===t||!1===t||t instanceof Boolean)return"boolean";if("string"==typeof t||t instanceof String)return"string";if("number"==typeof t||t instanceof Number)return"number";if("function"==typeof t||t instanceof Function)return"function";if(void 0!==Array.isArray&&Array.isArray(t))return"array";if(t instanceof RegExp)return"regexp";if(t instanceof Date)return"date";var e=s.call(t);return"[object RegExp]"===e?"regexp":"[object Date]"===e?"date":"[object Arguments]"===e?"arguments":"[object Error]"===e?"error":n(t)?"buffer":"[object Set]"===e?"set":"[object WeakSet]"===e?"weakset":"[object Map]"===e?"map":"[object WeakMap]"===e?"weakmap":"[object Symbol]"===e?"symbol":"[object Int8Array]"===e?"int8array":"[object Uint8Array]"===e?"uint8array":"[object Uint8ClampedArray]"===e?"uint8clampedarray":"[object Int16Array]"===e?"int16array":"[object Uint16Array]"===e?"uint16array":"[object Int32Array]"===e?"int32array":"[object Uint32Array]"===e?"uint32array":"[object Float32Array]"===e?"float32array":"[object Float64Array]"===e?"float64array":"object"}}}),d=r({"node_modules/rename-keys/index.js"(t,e){!function(){function t(t,e){if("function"!=typeof e)return t;var n={};for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&(n[e(s,t[s])||s]=t[s]);return n}void 0!==e&&e.exports?e.exports=t:"function"==typeof define&&define.amd?define([],function(){return t}):window.rename=t}()}}),l=r({"node_modules/deep-rename-keys/index.js"(t,e){var n=h(),s=d();e.exports=function t(e,o){var i=n(e);if("object"!==i&&"array"!==i)throw new Error("expected an object");var r=[];for(var a in"object"===i&&(e=s(e,o),r={}),e)if(e.hasOwnProperty(a)){var c=e[a];"object"===n(c)||"array"===n(c)?r[a]=t(c,o):r[a]=c}return r}}}),u=r({"node_modules/xml-reader/node_modules/eventemitter3/index.js"(t,e){var n=Object.prototype.hasOwnProperty,s="~";function o(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new o,this._eventsCount=0}Object.create&&(o.prototype=Object.create(null),(new o).__proto__||(s=!1)),r.prototype.eventNames=function(){var t,e,o=[];if(0===this._eventsCount)return o;for(e in t=this._events)n.call(t,e)&&o.push(s?e.slice(1):e);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(t)):o},r.prototype.listeners=function(t,e){var n=s?s+t:t,o=this._events[n];if(e)return!!o;if(!o)return[];if(o.fn)return[o.fn];for(var i=0,r=o.length,a=new Array(r);i<r;i++)a[i]=o[i].fn;return a},r.prototype.emit=function(t,e,n,o,i,r){var a=s?s+t:t;if(!this._events[a])return!1;var c,h,d=this._events[a],l=arguments.length;if(d.fn){switch(d.once&&this.removeListener(t,d.fn,void 0,!0),l){case 1:return d.fn.call(d.context),!0;case 2:return d.fn.call(d.context,e),!0;case 3:return d.fn.call(d.context,e,n),!0;case 4:return d.fn.call(d.context,e,n,o),!0;case 5:return d.fn.call(d.context,e,n,o,i),!0;case 6:return d.fn.call(d.context,e,n,o,i,r),!0}for(h=1,c=new Array(l-1);h<l;h++)c[h-1]=arguments[h];d.fn.apply(d.context,c)}else{var u,p=d.length;for(h=0;h<p;h++)switch(d[h].once&&this.removeListener(t,d[h].fn,void 0,!0),l){case 1:d[h].fn.call(d[h].context);break;case 2:d[h].fn.call(d[h].context,e);break;case 3:d[h].fn.call(d[h].context,e,n);break;case 4:d[h].fn.call(d[h].context,e,n,o);break;default:if(!c)for(u=1,c=new Array(l-1);u<l;u++)c[u-1]=arguments[u];d[h].fn.apply(d[h].context,c)}}return!0},r.prototype.on=function(t,e,n){var o=new i(e,n||this),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.once=function(t,e,n){var o=new i(e,n||this,!0),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=s?s+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new o:delete this._events[r],this;var a=this._events[r];if(a.fn)a.fn!==e||i&&!a.once||n&&a.context!==n||(0===--this._eventsCount?this._events=new o:delete this._events[r]);else{for(var c=0,h=[],d=a.length;c<d;c++)(a[c].fn!==e||i&&!a[c].once||n&&a[c].context!==n)&&h.push(a[c]);h.length?this._events[r]=1===h.length?h[0]:h:0===--this._eventsCount?this._events=new o:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=s?s+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new o:delete this._events[e])):(this._events=new o,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=s,r.EventEmitter=r,void 0!==e&&(e.exports=r)}}),p=r({"node_modules/xml-lexer/node_modules/eventemitter3/index.js"(t,e){var n=Object.prototype.hasOwnProperty,s="~";function o(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new o,this._eventsCount=0}Object.create&&(o.prototype=Object.create(null),(new o).__proto__||(s=!1)),r.prototype.eventNames=function(){var t,e,o=[];if(0===this._eventsCount)return o;for(e in t=this._events)n.call(t,e)&&o.push(s?e.slice(1):e);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(t)):o},r.prototype.listeners=function(t,e){var n=s?s+t:t,o=this._events[n];if(e)return!!o;if(!o)return[];if(o.fn)return[o.fn];for(var i=0,r=o.length,a=new Array(r);i<r;i++)a[i]=o[i].fn;return a},r.prototype.emit=function(t,e,n,o,i,r){var a=s?s+t:t;if(!this._events[a])return!1;var c,h,d=this._events[a],l=arguments.length;if(d.fn){switch(d.once&&this.removeListener(t,d.fn,void 0,!0),l){case 1:return d.fn.call(d.context),!0;case 2:return d.fn.call(d.context,e),!0;case 3:return d.fn.call(d.context,e,n),!0;case 4:return d.fn.call(d.context,e,n,o),!0;case 5:return d.fn.call(d.context,e,n,o,i),!0;case 6:return d.fn.call(d.context,e,n,o,i,r),!0}for(h=1,c=new Array(l-1);h<l;h++)c[h-1]=arguments[h];d.fn.apply(d.context,c)}else{var u,p=d.length;for(h=0;h<p;h++)switch(d[h].once&&this.removeListener(t,d[h].fn,void 0,!0),l){case 1:d[h].fn.call(d[h].context);break;case 2:d[h].fn.call(d[h].context,e);break;case 3:d[h].fn.call(d[h].context,e,n);break;case 4:d[h].fn.call(d[h].context,e,n,o);break;default:if(!c)for(u=1,c=new Array(l-1);u<l;u++)c[u-1]=arguments[u];d[h].fn.apply(d[h].context,c)}}return!0},r.prototype.on=function(t,e,n){var o=new i(e,n||this),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.once=function(t,e,n){var o=new i(e,n||this,!0),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=s?s+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new o:delete this._events[r],this;var a=this._events[r];if(a.fn)a.fn!==e||i&&!a.once||n&&a.context!==n||(0===--this._eventsCount?this._events=new o:delete this._events[r]);else{for(var c=0,h=[],d=a.length;c<d;c++)(a[c].fn!==e||i&&!a[c].once||n&&a[c].context!==n)&&h.push(a[c]);h.length?this._events[r]=1===h.length?h[0]:h:0===--this._eventsCount?this._events=new o:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=s?s+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new o:delete this._events[e])):(this._events=new o,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=s,r.EventEmitter=r,void 0!==e&&(e.exports=r)}}),m=r({"node_modules/xml-lexer/dist/lexer.js"(t,e){function n(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var s=p(),o=function(){},i={data:"state-data",cdata:"state-cdata",tagBegin:"state-tag-begin",tagName:"state-tag-name",tagEnd:"state-tag-end",attributeNameStart:"state-attribute-name-start",attributeName:"state-attribute-name",attributeNameEnd:"state-attribute-name-end",attributeValueBegin:"state-attribute-value-begin",attributeValue:"state-attribute-value"},r={lt:"action-lt",gt:"action-gt",space:"action-space",equal:"action-equal",quote:"action-quote",slash:"action-slash",char:"action-char",error:"action-error"},a={text:"text",openTag:"open-tag",closeTag:"close-tag",attributeName:"attribute-name",attributeValue:"attribute-value"},c={" ":r.space,"\t":r.space,"\n":r.space,"\r":r.space,"<":r.lt,">":r.gt,'"':r.quote,"'":r.quote,"=":r.equal,"/":r.slash};e.exports={State:i,Action:r,Type:a,create:function(t){var e,h,d,l,u,p,m,f,g,y;t=Object.assign({debug:!1},t);var x=new s,v=i.data,S="",P="",b="",M="",N="",I="",C=function(e,n){if("?"!==P[0]&&"!"!==P[0]){var s={type:e,value:n};t.debug&&console.log("emit:",s),x.emit("data",s)}};x.stateMachine=(n(y={},i.data,(n(e={},r.lt,function(){S.trim()&&C(a.text,S),P="",N=!1,v=i.tagBegin}),n(e,r.char,function(t){S+=t}),e)),n(y,i.cdata,n({},r.char,function(t){"]]>"===(S+=t).substr(-3)&&(C(a.text,S.slice(0,-3)),S="",v=i.data)})),n(y,i.tagBegin,(n(h={},r.space,o),n(h,r.char,function(t){P=t,v=i.tagName}),n(h,r.slash,function(){P="",N=!0}),h)),n(y,i.tagName,(n(d={},r.space,function(){N?v=i.tagEnd:(v=i.attributeNameStart,C(a.openTag,P))}),n(d,r.gt,function(){C(N?a.closeTag:a.openTag,P),S="",v=i.data}),n(d,r.slash,function(){v=i.tagEnd,C(a.openTag,P)}),n(d,r.char,function(t){"![CDATA["===(P+=t)&&(v=i.cdata,S="",P="")}),d)),n(y,i.tagEnd,(n(l={},r.gt,function(){C(a.closeTag,P),S="",v=i.data}),n(l,r.char,o),l)),n(y,i.attributeNameStart,(n(u={},r.char,function(t){b=t,v=i.attributeName}),n(u,r.gt,function(){S="",v=i.data}),n(u,r.space,o),n(u,r.slash,function(){N=!0,v=i.tagEnd}),u)),n(y,i.attributeName,(n(p={},r.space,function(){v=i.attributeNameEnd}),n(p,r.equal,function(){C(a.attributeName,b),v=i.attributeValueBegin}),n(p,r.gt,function(){M="",C(a.attributeName,b),C(a.attributeValue,M),S="",v=i.data}),n(p,r.slash,function(){N=!0,M="",C(a.attributeName,b),C(a.attributeValue,M),v=i.tagEnd}),n(p,r.char,function(t){b+=t}),p)),n(y,i.attributeNameEnd,(n(m={},r.space,o),n(m,r.equal,function(){C(a.attributeName,b),v=i.attributeValueBegin}),n(m,r.gt,function(){M="",C(a.attributeName,b),C(a.attributeValue,M),S="",v=i.data}),n(m,r.char,function(t){M="",C(a.attributeName,b),C(a.attributeValue,M),b=t,v=i.attributeName}),m)),n(y,i.attributeValueBegin,(n(f={},r.space,o),n(f,r.quote,function(t){I=t,M="",v=i.attributeValue}),n(f,r.gt,function(){C(a.attributeValue,M=""),S="",v=i.data}),n(f,r.char,function(t){I="",M=t,v=i.attributeValue}),f)),n(y,i.attributeValue,(n(g={},r.space,function(t){I?M+=t:(C(a.attributeValue,M),v=i.attributeNameStart)}),n(g,r.quote,function(t){I===t?(C(a.attributeValue,M),v=i.attributeNameStart):M+=t}),n(g,r.gt,function(t){I?M+=t:(C(a.attributeValue,M),S="",v=i.data)}),n(g,r.slash,function(t){I?M+=t:(C(a.attributeValue,M),N=!0,v=i.tagEnd)}),n(g,r.char,function(t){M+=t}),g)),y);var _=function(e){t.debug&&console.log(v,e);var n=x.stateMachine[v],s=n[function(t){return c[t]||r.char}(e)]||n[r.error]||n[r.char];s(e)};return x.write=function(t){for(var e=t.length,n=0;n<e;n++)_(t[n])},x}}}}),f=r({"node_modules/xml-reader/dist/reader.js"(t,e){var n=u(),s=m(),o=s.Type,i={element:"element",text:"text"},r=function(t){return Object.assign({name:"",type:i.element,value:"",parent:null,attributes:{},children:[]},t)},a=function(t){t=Object.assign({stream:!1,parentNodes:!0,doneEvent:"done",tagPrefix:"tag:",emitTopLevelOnly:!1,debug:!1},t);var e=void 0,a=void 0,c=void 0,h=void 0,d=new n,l=function(n){switch(n.type){case o.openTag:if(null===c)(c=a).name=n.value;else{var s=r({name:n.value,parent:c});c.children.push(s),c=s}break;case o.closeTag:var l=c.parent;if(t.parentNodes||(c.parent=null),c.name!==n.value)break;t.stream&&l===a&&(a.children=[],c.parent=null),t.emitTopLevelOnly&&l!==a||(d.emit(t.tagPrefix+c.name,c),d.emit("tag",c.name,c)),c===a&&(e.removeAllListeners("data"),d.emit(t.doneEvent,c),a=null),c=l;break;case o.text:c&&c.children.push(r({type:i.text,value:n.value,parent:t.parentNodes?c:null}));break;case o.attributeName:h=n.value,c.attributes[h]="";break;case o.attributeValue:c.attributes[h]=n.value}};return d.reset=function(){(e=s.create({debug:t.debug})).on("data",l),a=r(),c=null,h="",d.parse=e.write},d.reset(),d};e.exports={parseSync:function(t,e){e=Object.assign({},e,{stream:!1,tagPrefix:":"});var n=a(e),s=void 0;return n.on("done",function(t){s=t}),n.parse(t),s},create:a,NodeType:i}}}),g=(...t)=>{const e={points:[],lines:[],circles:[],rects:[]};return t.forEach((t,n)=>{t&&(t.lines&&(e.lines=[...e.lines||[],...t.lines.map(t=>({...t,step:n}))]),t.points&&(e.points=[...e.points||[],...t.points.map(t=>({...t,step:n}))]),t.circles&&(e.circles=[...e.circles||[],...t.circles.map(t=>({...t,step:n}))]),t.rects&&(e.rects=[...e.rects||[],...t.rects.map(t=>({...t,step:n}))]))}),e},y=class{MAX_ITERATIONS=1e3;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};cacheHit;cacheKey;cacheToSolveSpaceTransform;step(){if(!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,console.error(this.error),this.failed=!0,t}!this.solved&&this.iterations>this.MAX_ITERATIONS&&this.tryFinalAcceptance(),!this.solved&&this.iterations>this.MAX_ITERATIONS&&(this.error=`${this.constructor.name} ran out of iterations (MAX_ITERATIONS=${this.MAX_ITERATIONS})`,this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}};function x(){return x=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var s in n)({}).hasOwnProperty.call(n,s)&&(t[s]=n[s])}return t},x.apply(null,arguments)}function v(t,e){return(v=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t})(t,e)}function S(t){return(S=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 b(t){var e="function"==typeof Map?new Map:void 0;return b=function(t){if(null===t||!function(t){try{return-1!==Function.toString.call(t).indexOf("[native code]")}catch(e){return"function"==typeof t}}(t))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,n)}function n(){return function(t,e,n){if(P())return Reflect.construct.apply(null,arguments);var s=[null];s.push.apply(s,e);var o=new(t.bind.apply(t,s));return n&&v(o,n.prototype),o}(t,arguments,S(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),v(n,t)},b(t)}var M={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 N(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];var s,o=e[0],i=[];for(s=1;s<e.length;s+=1)i.push(e[s]);return i.forEach(function(t){o=o.replace(/%[a-z]/,t)}),o}var I=function(t){var e,n;function s(e){var n;if("production"===process.env.NODE_ENV)n=t.call(this,"An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#"+e+" for more information.")||this;else{for(var s=arguments.length,o=new Array(s>1?s-1:0),i=1;i<s;i++)o[i-1]=arguments[i];n=t.call(this,N.apply(void 0,[M[e]].concat(o)))||this}return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(n)}return n=t,(e=s).prototype=Object.create(n.prototype),e.prototype.constructor=e,v(e,n),s}(b(Error));function C(t,e){return t.substr(-e.length)===e}var _=/^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;function T(t){return"string"!=typeof t?t:t.match(_)?parseFloat(t):t}var E=function(t){return function(e,n){void 0===n&&(n="16px");var s=e,o=n;if("string"==typeof e){if(!C(e,"px"))throw new I(69,t,e);s=T(e)}if("string"==typeof n){if(!C(n,"px"))throw new I(70,t,n);o=T(n)}if("string"==typeof s)throw new I(71,e,t);if("string"==typeof o)throw new I(72,n,t);return""+s/o+t}};E("em"),E("rem");function R(t){return Math.round(255*t)}function w(t,e,n){return R(t)+","+R(e)+","+R(n)}function A(t,e,n,s){if(void 0===s&&(s=w),0===e)return s(n,n,n);var o=(t%360+360)%360/60,i=(1-Math.abs(2*n-1))*e,r=i*(1-Math.abs(o%2-1)),a=0,c=0,h=0;o>=0&&o<1?(a=i,c=r):o>=1&&o<2?(a=r,c=i):o>=2&&o<3?(c=i,h=r):o>=3&&o<4?(c=r,h=i):o>=4&&o<5?(a=r,h=i):o>=5&&o<6&&(a=i,h=r);var d=n-i/2;return s(a+d,c+d,h+d)}var O={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 z=/^#[a-fA-F0-9]{6}$/,D=/^#[a-fA-F0-9]{8}$/,L=/^#[a-fA-F0-9]{3}$/,F=/^#[a-fA-F0-9]{4}$/,X=/^rgb\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*\)$/i,Y=/^rgb(?:a)?\(\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,)?\s*(\d{1,3})\s*(?:,|\/)\s*([-+]?\d*[.]?\d+[%]?)\s*\)$/i,$=/^hsl\(\s*(\d{0,3}[.]?[0-9]+(?:deg)?)\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*(?:,)?\s*(\d{1,3}[.]?[0-9]?)%\s*\)$/i,k=/^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 B(t){if("string"!=typeof t)throw new I(3);var e=function(t){if("string"!=typeof t)return t;var e=t.toLowerCase();return O[e]?"#"+O[e]:t}(t);if(e.match(z))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(D)){var n=parseFloat((parseInt(""+e[7]+e[8],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[2],16),green:parseInt(""+e[3]+e[4],16),blue:parseInt(""+e[5]+e[6],16),alpha:n}}if(e.match(L))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(F)){var s=parseFloat((parseInt(""+e[4]+e[4],16)/255).toFixed(2));return{red:parseInt(""+e[1]+e[1],16),green:parseInt(""+e[2]+e[2],16),blue:parseInt(""+e[3]+e[3],16),alpha:s}}var o=X.exec(e);if(o)return{red:parseInt(""+o[1],10),green:parseInt(""+o[2],10),blue:parseInt(""+o[3],10)};var i=Y.exec(e.substring(0,50));if(i)return{red:parseInt(""+i[1],10),green:parseInt(""+i[2],10),blue:parseInt(""+i[3],10),alpha:parseFloat(""+i[4])>1?parseFloat(""+i[4])/100:parseFloat(""+i[4])};var r=$.exec(e);if(r){var a="rgb("+A(parseInt(""+r[1],10),parseInt(""+r[2],10)/100,parseInt(""+r[3],10)/100)+")",c=X.exec(a);if(!c)throw new I(4,e,a);return{red:parseInt(""+c[1],10),green:parseInt(""+c[2],10),blue:parseInt(""+c[3],10)}}var h=k.exec(e.substring(0,50));if(h){var d="rgb("+A(parseInt(""+h[1],10),parseInt(""+h[2],10)/100,parseInt(""+h[3],10)/100)+")",l=X.exec(d);if(!l)throw new I(4,e,d);return{red:parseInt(""+l[1],10),green:parseInt(""+l[2],10),blue:parseInt(""+l[3],10),alpha:parseFloat(""+h[4])>1?parseFloat(""+h[4])/100:parseFloat(""+h[4])}}throw new I(5)}function j(t){return function(t){var e,n=t.red/255,s=t.green/255,o=t.blue/255,i=Math.max(n,s,o),r=Math.min(n,s,o),a=(i+r)/2;if(i===r)return void 0!==t.alpha?{hue:0,saturation:0,lightness:a,alpha:t.alpha}:{hue:0,saturation:0,lightness:a};var c=i-r,h=a>.5?c/(2-i-r):c/(i+r);switch(i){case n:e=(s-o)/c+(s<o?6:0);break;case s:e=(o-n)/c+2;break;default:e=(n-s)/c+4}return e*=60,void 0!==t.alpha?{hue:e,saturation:h,lightness:a,alpha:t.alpha}:{hue:e,saturation:h,lightness:a}}(B(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 H(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function U(t){return H(Math.round(255*t))}function V(t,e,n){return W("#"+U(t)+U(e)+U(n))}function Z(t,e,n){return A(t,e,n,V)}function G(t,e,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n)return W("#"+H(t)+H(e)+H(n));if("object"==typeof t&&void 0===e&&void 0===n)return W("#"+H(t.red)+H(t.green)+H(t.blue));throw new I(6)}function J(t,e,n,s){if("string"==typeof t&&"number"==typeof e){var o=B(t);return"rgba("+o.red+","+o.green+","+o.blue+","+e+")"}if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof s)return s>=1?G(t,e,n):"rgba("+t+","+e+","+n+","+s+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===s)return t.alpha>=1?G(t.red,t.green,t.blue):"rgba("+t.red+","+t.green+","+t.blue+","+t.alpha+")";throw new I(7)}function q(t){if("object"!=typeof t)throw new I(8);if(function(t){return"number"==typeof t.red&&"number"==typeof t.green&&"number"==typeof t.blue&&"number"==typeof t.alpha}(t))return J(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 G(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&"number"==typeof t.alpha}(t))return function(t,e,n,s){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof s)return s>=1?Z(t,e,n):"rgba("+A(t,e,n)+","+s+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===s)return t.alpha>=1?Z(t.hue,t.saturation,t.lightness):"rgba("+A(t.hue,t.saturation,t.lightness)+","+t.alpha+")";throw new I(2)}(t);if(function(t){return"number"==typeof t.hue&&"number"==typeof t.saturation&&"number"==typeof t.lightness&&("number"!=typeof t.alpha||void 0===t.alpha)}(t))return function(t,e,n){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n)return Z(t,e,n);if("object"==typeof t&&void 0===e&&void 0===n)return Z(t.hue,t.saturation,t.lightness);throw new I(1)}(t);throw new I(8)}function K(t,e,n){return function(){var s=n.concat(Array.prototype.slice.call(arguments));return s.length>=e?t.apply(this,s):K(t,e,s)}}function Q(t){return K(t,t.length,[])}Q(function(t,e){if("transparent"===e)return e;var n=j(e);return q(x({},n,{hue:n.hue+parseFloat(t)}))});function tt(t,e,n){return Math.max(t,Math.min(e,n))}Q(function(t,e){if("transparent"===e)return e;var n=j(e);return q(x({},n,{lightness:tt(0,1,n.lightness-parseFloat(t))}))});Q(function(t,e){if("transparent"===e)return e;var n=j(e);return q(x({},n,{saturation:tt(0,1,n.saturation-parseFloat(t))}))});Q(function(t,e){if("transparent"===e)return e;var n=j(e);return q(x({},n,{lightness:tt(0,1,n.lightness+parseFloat(t))}))});var et=Q(function(t,e,n){if("transparent"===e)return n;if("transparent"===n)return e;if(0===t)return n;var s=B(e),o=x({},s,{alpha:"number"==typeof s.alpha?s.alpha:1}),i=B(n),r=x({},i,{alpha:"number"==typeof i.alpha?i.alpha:1}),a=o.alpha-r.alpha,c=2*parseFloat(t)-1,h=((c*a===-1?c:c+a)/(1+c*a)+1)/2,d=1-h;return J({red:Math.floor(o.red*h+r.red*d),green:Math.floor(o.green*h+r.green*d),blue:Math.floor(o.blue*h+r.blue*d),alpha:o.alpha*parseFloat(t)+r.alpha*(1-parseFloat(t))})});Q(function(t,e){if("transparent"===e)return e;var n=B(e);return J(x({},n,{alpha:tt(0,1,(100*("number"==typeof n.alpha?n.alpha:1)+100*parseFloat(t))/100)}))});Q(function(t,e){if("transparent"===e)return e;var n=j(e);return q(x({},n,{saturation:tt(0,1,n.saturation+parseFloat(t))}))});Q(function(t,e){return"transparent"===e?e:q(x({},j(e),{hue:parseFloat(t)}))});Q(function(t,e){return"transparent"===e?e:q(x({},j(e),{lightness:parseFloat(t)}))});Q(function(t,e){return"transparent"===e?e:q(x({},j(e),{saturation:parseFloat(t)}))});Q(function(t,e){return"transparent"===e?e:et(parseFloat(t),"rgb(0, 0, 0)",e)});Q(function(t,e){return"transparent"===e?e:et(parseFloat(t),"rgb(255, 255, 255)",e)});var nt=Q(function(t,e){if("transparent"===e)return e;var n=B(e);return J(x({},n,{alpha:tt(0,1,+(100*("number"==typeof n.alpha?n.alpha:1)-100*parseFloat(t)).toFixed(2)/100)}))}),st=["blue","orange","purple","cyan","magenta","yellowgreen","darkgoldenrod","deeppink"],ot=(t,e)=>{const n={};for(let s=0;s<t.connections.length;s++){const o=t.connections[s],i=e?.getNetConnectedToId(o.name);i&&!n[i]&&(n[i]=`hsl(${300*s/t.connections.length}, 100%, 50%)`),n[o.name]=(i?n[i]:null)??`hsl(${340*s/t.connections.length}, 100%, 50%)`}return n},it=(t,e)=>{try{return nt(e,t)}catch(e){return console.error(e),t}},rt=(t,e=1)=>{if(!t)return"rgba(0, 0, 0, 0.5)";const n=300*t.split("").reduce((t,e)=>t+e.charCodeAt(0),0)/t.length;return e<1?`hsla(${n}, 100%, 50%, ${e})`:`hsl(${n}, 100%, 50%)`};import at from"object-hash";var ct=class{cacheHitsByPrefix={};cacheMissesByPrefix={};isSyncCache=!0;cacheHits=0;cacheMisses=0;cache=new Map;getCachedSolutionSync(t){const e=this.cache.get(t);if(void 0!==e){this.cacheHits++;const n=t.split(":")[0];return this.cacheHitsByPrefix[n]=(this.cacheHitsByPrefix[n]||0)+1,structuredClone(e)}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){this.cache.set(t,structuredClone(e))}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){this.cache.clear(),this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}getAllCacheKeys(){return Array.from(this.cache.keys())}},ht="tscircuit_autorouter_cache_",dt=class{isSyncCache=!0;cacheHits=0;cacheMisses=0;cacheHitsByPrefix={};cacheMissesByPrefix={};constructor(){}getKey(t){return`${ht}${t}`}getCachedSolutionSync(t){if("undefined"==typeof localStorage)return;const e=this.getKey(t);try{const n=localStorage.getItem(e);if(null!==n){const e=JSON.parse(n);this.cacheHits++;const s=t.split(":")[0];return this.cacheHitsByPrefix[s]=(this.cacheHitsByPrefix[s]||0)+1,e}{this.cacheMisses++;const e=t.split(":")[0];return void(this.cacheMissesByPrefix[e]=(this.cacheMissesByPrefix[e]||0)+1)}}catch(n){console.error(`Error getting cached solution sync for ${e}:`,n),this.cacheMisses++;const s=t.split(":")[0];return void(this.cacheMissesByPrefix[s]=(this.cacheMissesByPrefix[s]||0)+1)}}async getCachedSolution(t){return this.getCachedSolutionSync(t)}setCachedSolutionSync(t,e){if("undefined"==typeof localStorage)return;const n=this.getKey(t);try{const t=JSON.stringify(e);localStorage.setItem(n,t)}catch(t){console.error(`Error setting cached solution sync for ${n}:`,t),t instanceof DOMException&&("QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&console.warn(`LocalStorage quota exceeded. Failed to cache solution for ${n}. Consider clearing the cache.`)}}async setCachedSolution(t,e){this.setCachedSolutionSync(t,e)}clearCache(){if("undefined"!=typeof localStorage)try{const t=[];for(let e=0;e<localStorage.length;e++){const n=localStorage.key(e);n?.startsWith(ht)&&t.push(n)}t.forEach(t=>localStorage.removeItem(t)),console.log(`Cleared ${t.length} items from LocalStorage cache.`)}catch(t){console.error("Error clearing LocalStorage cache:",t)}finally{this.cacheHits=0,this.cacheMisses=0,this.cacheHitsByPrefix={},this.cacheMissesByPrefix={}}}getAllCacheKeys(){const t=[];for(let e=0;e<1e4;e++){const n=localStorage.key(e);if(!n)break;n.includes(ht)&&t.push(n)}return t}};function lt(){return globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE||pt(),globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE}function ut(){return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE||pt(),globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE}function pt(){globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE??=new dt,globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE??=new ct}function mt(t){const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-n,maxY:t.center.y+n}}function ft(t,e,n){return Math.max(e,Math.min(n,t))}function gt(t,e,n,s){const o=yt(t,e,n),i=yt(t,e,s),r=yt(n,s,t),a=yt(n,s,e);return o!==i&&r!==a||(!(0!==o||!xt(t,n,e))||(!(0!==i||!xt(t,s,e))||(!(0!==r||!xt(n,t,s))||!(0!==a||!xt(n,e,s)))))}function yt(t,e,n){const s=(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y);return 0===s?0:s>0?1:2}function xt(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function vt(t,e,n){const s=(n.x-e.x)**2+(n.y-e.y)**2;if(0===s)return St(t,e);let o=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/s;o=Math.max(0,Math.min(1,o));return St(t,{x:e.x+o*(n.x-e.x),y:e.y+o*(n.y-e.y)})}function St(t,e){const n=t.x-e.x,s=t.y-e.y;return Math.sqrt(n*n+s*s)}function Pt(t,e,n,s){const o=e.x-t.x,i=e.y-t.y,r=s.x-n.x,a=s.y-n.y,c=t.x-n.x,h=t.y-n.y,d=o*a-i*r;if(Math.abs(d)<1e-10)return null;const l=(h*r-c*a)/d,u=(o*h-i*c)/d,p=1e-9;if(l>=-1e-9&&l<=1+p&&u>=-1e-9&&u<=1+p){return{x:t.x+l*o,y:t.y+l*i}}return null}function bt(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var Mt=t=>{if("minX"in t)return t;const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,minY:t.center.y-n,maxX:t.center.x+e,maxY:t.center.y+n}},Nt=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}],It=t=>{const e=[];for(let n=0;n<t.length;n++){const s=t[n],o=t[(n+1)%t.length];e.push([s,o])}return e},Ct=(t,e,n)=>{const s=(t.y-e.y)*(n.x-e.x)-(t.x-e.x)*(n.y-e.y);if(Math.abs(s)>1e-9)return!1;const o=(t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y);if(o<0)return!1;return!(o>(n.x-e.x)**2+(n.y-e.y)**2)},_t=(t,e)=>{if(e.length<3)return!1;const n=It(e);for(const[e,s]of n)if(Ct(t,e,s))return!0;let s=!1;for(let n=0,o=e.length-1;n<e.length;o=n++){const i=e[n].x,r=e[n].y,a=e[o].x,c=e[o].y;r>t.y!=c>t.y&&t.x<(a-i)*(t.y-r)/(c-r)+i&&(s=!s)}return s},Tt=(t,e)=>{const n=Nt(t),s=[[n[0],n[1]],[n[1],n[2]],[n[2],n[3]],[n[3],n[0]]],o=It(e);for(const[t,e]of o)for(const[n,o]of s)if(gt(t,e,n,o))return!0;return!1},Et=(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))||(!!Nt(t).some(t=>_t(t,e))||Tt(t,e))))(Mt(t),e),Rt=(t,e)=>((t,e)=>!(e.length<3)&&(!!Nt(t).every(t=>_t(t,e))&&!Tt(t,e)))(Mt(t),e);function wt(t,e,n,s){if(t.x===e.x&&t.y===e.y)return vt(t,n,s);if(n.x===s.x&&n.y===s.y)return vt(n,t,e);if(gt(t,e,n,s))return 0;const o=[vt(t,n,s),vt(e,n,s),vt(n,t,e),vt(s,t,e)];return Math.min(...o)}function At(t,e,n){const s=n.width/2,o=n.height/2;return function(t,e,n){const s={x:n.minX,y:n.minY},o={x:n.maxX,y:n.minY},i={x:n.minX,y:n.maxY},r={x:n.maxX,y:n.maxY};if(gt(t,e,s,o)||gt(t,e,o,r)||gt(t,e,r,i)||gt(t,e,i,s))return 0;if(t.x>=n.minX&&t.x<=n.maxX&&t.y>=n.minY&&t.y<=n.maxY&&e.x>=n.minX&&e.x<=n.maxX&&e.y>=n.minY&&e.y<=n.maxY)return 0;const a=[vt(s,t,e),vt(o,t,e),vt(i,t,e),vt(r,t,e)];if(t.x>=n.minX&&t.x<=n.maxX&&t.y>=n.minY&&t.y<=n.maxY)return 0;if(e.x>=n.minX&&e.x<=n.maxX&&e.y>=n.minY&&e.y<=n.maxY)return 0;if(t.x<n.minX||t.x>n.maxX||t.y<n.minY||t.y>n.maxY){const e=ft(t.x,n.minX,n.maxX),s=ft(t.y,n.minY,n.maxY);a.push(St(t,{x:e,y:s}))}if(e.x<n.minX||e.x>n.maxX||e.y<n.minY||e.y>n.maxY){const t=ft(e.x,n.minX,n.maxX),s=ft(e.y,n.minY,n.maxY);a.push(St(e,{x:t,y:s}))}return Math.min(...a)}(t,e,{minX:n.center.x-s,maxX:n.center.x+s,minY:n.center.y-o,maxY:n.center.y+o})}function Ot(t,e,n){const s=n.x-e.x,o=n.y-e.y,i=s*s+o*o;if(0===i)return{x:e.x,y:e.y};let r=((t.x-e.x)*s+(t.y-e.y)*o)/i;r=Math.max(0,Math.min(1,r));return{x:e.x+r*s,y:e.y+r*o}}var zt=class{heap=[];constructor(t){this.heap=[];for(const e of t)this.enqueue(e)}getLeftChildIndex(t){return 2*t+1}getRightChildIndex(t){return 2*t+2}getParentIndex(t){return Math.floor((t-1)/2)}hasLeftChild(t){return this.getLeftChildIndex(t)<this.heap.length}hasRightChild(t){return this.getRightChildIndex(t)<this.heap.length}hasParent(t){return this.getParentIndex(t)>=0}leftChild(t){return this.heap[this.getLeftChildIndex(t)]}rightChild(t){return this.heap[this.getRightChildIndex(t)]}parent(t){return this.heap[this.getParentIndex(t)]}swap(t,e){const n=this.heap[t];this.heap[t]=this.heap[e],this.heap[e]=n}dequeue(){if(0===this.heap.length)return null;const t=this.heap[0];return this.heap[0]=this.heap[this.heap.length-1],this.heap.pop(),this.heapifyDown(),t}peek(){return 0===this.heap.length?null:this.heap[0]}enqueue(t){this.heap.push(t),this.heapifyUp()}heapifyUp(){let t=this.heap.length-1;for(;this.hasParent(t)&&this.parent(t).f>this.heap[t].f;)this.swap(this.getParentIndex(t),t),t=this.getParentIndex(t)}heapifyDown(){let t=0;for(;this.hasLeftChild(t);){let e=this.getLeftChildIndex(t);if(this.hasRightChild(t)&&this.rightChild(t).f<this.leftChild(t).f&&(e=this.getRightChildIndex(t)),this.heap[t].f<this.heap[e].f)break;this.swap(t,e),t=e}}getTopN(t){return[...this.heap].sort((t,e)=>t.f-e.f).slice(0,t)}},Dt=class extends y{obstacleRoutes;bounds;boundsSize;boundsCenter;A;B;straightLineDistance;viaDiameter;traceThickness;obstacleMargin;layerCount;minCellSize=.05;cellStep=.05;GREEDY_MULTIPLER=1.1;numRoutes;VIA_PENALTY_FACTOR=.3;CELL_SIZE_FACTOR;exploredNodes;candidates;connectionName;solvedPath=null;futureConnections;hyperParameters;connMap;debug_exploredNodesOrdered;debug_nodesTooCloseToObstacle;debug_nodePathToParentIntersectsObstacle;debugEnabled=!0;initialNodeGridOffset;constructor(t){super(),this.bounds=t.bounds,this.connMap=t.connMap,this.hyperParameters=t.hyperParameters??{},this.CELL_SIZE_FACTOR=this.hyperParameters.CELL_SIZE_FACTOR??1,this.boundsSize={width:this.bounds.maxX-this.bounds.minX,height:this.bounds.maxY-this.bounds.minY},this.boundsCenter={x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2},this.connectionName=t.connectionName,this.obstacleRoutes=t.obstacleRoutes,this.A=t.A,this.B=t.B,this.viaDiameter=t.viaDiameter??.6,this.traceThickness=t.traceThickness??.15,this.obstacleMargin=t.obstacleMargin??.2,this.layerCount=t.layerCount??2,this.exploredNodes=new Set,this.straightLineDistance=St(this.A,this.B),this.futureConnections=t.futureConnections??[],this.MAX_ITERATIONS=1e4,this.debug_exploredNodesOrdered=[],this.debug_nodesTooCloseToObstacle=new Set,this.debug_nodePathToParentIntersectsObstacle=new Set,this.numRoutes=this.obstacleRoutes.length+this.futureConnections.length;const e=Math.ceil(5*(this.numRoutes+1));let n=this.boundsSize.width/this.cellStep,s=this.boundsSize.height/this.cellStep;for(;n*s>e**2&&!(2*this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,n=this.boundsSize.width/this.cellStep,s=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR;const o=Math.abs(this.A.x-this.bounds.minX)<.001&&Math.abs(this.B.x-this.bounds.minX)<.001||Math.abs(this.A.x-this.bounds.maxX)<.001&&Math.abs(this.B.x-this.bounds.maxX)<.001||Math.abs(this.A.y-this.bounds.minY)<.001&&Math.abs(this.B.y-this.bounds.minY)<.001||Math.abs(this.A.y-this.bounds.maxY)<.001&&Math.abs(this.B.y-this.bounds.maxY)<.001;this.futureConnections&&0===this.futureConnections.length&&0===this.obstacleRoutes.length&&!o&&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 zt([{...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,n=t.z===e.z?[t,e]:[t,{...this.boundsCenter,z:this.A.z},{...this.boundsCenter,z:e.z},e];this.solvedPath={connectionName:this.connectionName,route:n,traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:this.A.z===this.B.z?[]:[this.boundsCenter]}}get viaPenaltyDistance(){return this.cellStep+this.straightLineDistance*this.VIA_PENALTY_FACTOR}isNodeTooCloseToObstacle(t,e,n){if(e??=this.obstacleMargin,n&&t.parent){const n=this.getViasInNodePath(t.parent);for(const s of n)if(St(t,s)<this.viaDiameter/2+e)return!0}for(const s of this.obstacleRoutes){const o=this.connMap?.areIdsConnected?.(this.connectionName,s.connectionName);if(!o){const o=Lt(s);for(const s of o)if((n||s.z===t.z)&&vt(t,s.A,s.B)<this.traceThickness+e)return!0}for(const n of s.vias)if(St(t,n)<this.viaDiameter/2+this.traceThickness/2+e)return!0}return!1}isNodeTooCloseToEdge(t,e){const n=e?this.viaDiameter/2+this.obstacleMargin/2:this.obstacleMargin/2,s=t.x<this.bounds.minX+n||t.x>this.bounds.maxX-n||t.y<this.bounds.minY+n||t.y>this.bounds.maxY-n;return!(s&&!e&&(St(t,this.B)<2*n||St(t,this.A)<2*n))&&s}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!s)for(const s of Lt(n))if(s.z===t.z&>(t,e,s.A,s.B))return!0}return!1}computeH(t){return St(t,this.B)+(t.z!==this.B.z?this.viaPenaltyDistance:0)}computeG(t){return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+St(t,t.parent)}computeF(t,e){return t+e*this.GREEDY_MULTIPLER}getNodeKey(t){return`${Math.round(t.x/this.cellStep)*this.cellStep},${Math.round(t.y/this.cellStep)*this.cellStep},${t.z}`}getNeighbors(t){const e=[],{maxX:n,minX:s,maxY:o,minY:i}=this.bounds;for(let r=-1;r<=1;r++)for(let a=-1;a<=1;a++){if(0===r&&0===a)continue;const c={...t,parent:t,x:Ft(t.x+r*this.cellStep,s,n),y:Ft(t.y+a*this.cellStep,i,o)},h=this.getNodeKey(c);this.exploredNodes.has(h)||(this.isNodeTooCloseToObstacle(c)?(this.debug_nodesTooCloseToObstacle.add(h),this.exploredNodes.add(h)):this.isNodeTooCloseToEdge(c,!1)?this.exploredNodes.add(h):this.doesPathToParentIntersectObstacle(c)?(this.debug_nodePathToParentIntersectsObstacle.add(h),this.exploredNodes.add(h)):(c.g=this.computeG(c),c.h=this.computeH(c),c.f=this.computeF(c.g,c.h),e.push(c)))}for(let n=0;n<this.layerCount;n++){if(n===t.z)continue;const s={...t,parent:t,z:n};this.exploredNodes.has(this.getNodeKey(s))||this.isNodeTooCloseToObstacle(s,this.viaDiameter/2+this.obstacleMargin/2,!0)||this.isNodeTooCloseToEdge(s,!0)||(s.g=this.computeG(s),s.h=this.computeH(s),s.f=this.computeF(s.g,s.h),e.push(s))}return e}getNodePath(t){const e=[];for(;t;)e.push(t),t=t.parent;return e}getViasInNodePath(t){const e=this.getNodePath(t),n=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&n.push({x:e[t].x,y:e[t].y});return n}setSolvedPath(t){const e=this.getNodePath(t);e.reverse();const n=[];for(let t=0;t<e.length-1;t++)e[t].z!==e[t+1].z&&n.push({x:e[t].x,y:e[t].y});this.solvedPath={connectionName:this.connectionName,traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,route:e.map(t=>({x:t.x,y:t.y,z:t.z})).concat([this.B]),vias:n}}computeProgress(t,e,n){n||(e+=this.viaPenaltyDistance);const s=1-e/this.straightLineDistance;return Math.max(this.progress||0,2/Math.PI*Math.atan(.112*s/(1-s)))}_step(){let t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;for(;t&&e&&this.exploredNodes.has(e);)t=this.candidates.dequeue(),e=t?this.getNodeKey(t):void 0;if(!t||!e)return this.failed=!0,void(this.error="Ran out of candidate nodes to explore");this.exploredNodes.add(e),this.debug_exploredNodesOrdered.push(e);const n=St(t,this.B);this.progress=this.computeProgress(t,n,t.z===this.B.z),n<=this.cellStep*Math.SQRT2&&t.z===this.B.z&&!this.doesPathToParentIntersectObstacle({...t,parent:t,x:this.B.x,y:this.B.y})&&(this.solved=!0,this.setSolvedPath(t));const s=this.getNeighbors(t);for(const t of s)this.candidates.enqueue(t)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.points.push({x:this.A.x,y:this.A.y,label:`Input A\nz: ${this.A.z}`,color:"orange"}),t.points.push({x:this.B.x,y:this.B.y,label:`Input B\nz: ${this.B.z}`,color:"orange"}),t.lines.push({points:[this.A,this.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:"Direct Input Connection"});for(let e=0;e<this.obstacleRoutes.length;e++){const n=this.obstacleRoutes[e];for(let s=0;s<n.route.length-1;s++){const o=n.route[s].z;t.lines.push({points:[n.route[s],n.route[s+1]],strokeColor:0===o?"rgba(255, 0, 0, 0.75)":"rgba(255, 128, 0, 0.25)",strokeWidth:n.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`})}}for(let e=0;e<this.debug_exploredNodesOrdered.length;e++){const n=this.debug_exploredNodesOrdered[e],[s,o,i]=n.split(",").map(Number);this.debug_nodesTooCloseToObstacle.has(n)||(this.debug_nodePathToParentIntersectsObstacle.has(n)||t.rects.push({center:{x:s+this.initialNodeGridOffset.x+i*this.cellStep/20,y:o+this.initialNodeGridOffset.y+i*this.cellStep/20},fill:0===i?`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=${i})`}))}if(this.candidates.peek()){const e=this.candidates.peek();t.rects.push({center:{x:e.x+e.z*this.cellStep/20,y:e.y+e.z*this.cellStep/20},fill:"rgba(0, 255, 0, 0.8)",width:.9*this.cellStep,height:.9*this.cellStep,label:`Next (z=${e.z})`})}for(const e of this.obstacleRoutes)for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:this.viaDiameter/2,fill:"rgba(255, 0, 0, 0.5)",label:"Via"});if(this.solvedPath){t.lines.push({points:this.solvedPath.route,strokeColor:"green",label:"Solved Route"});for(const e of this.solvedPath.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"green",label:"Via"})}return t}};function Lt(t){const e=[];for(let n=0;n<t.route.length-1;n++)t.route[n].z===t.route[n+1].z&&e.push({z:t.route[n].z,A:t.route[n],B:t.route[n+1]});return e}function Ft(t,e,n){return Math.max(e,Math.min(t,n))}var Xt=class extends Dt{FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR=2;FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR=1;FUTURE_CONNECTION_PROXIMITY_VD=10;MISALIGNED_DIST_PENALTY_FACTOR=5;VIA_PENALTY_FACTOR_2=1;FLIP_TRACE_ALIGNMENT_DIRECTION=!1;constructor(t){super(t);for(const e in t.hyperParameters)this[e]=t.hyperParameters[e];const e=this.boundsSize.width/this.viaDiameter,n=Math.max(1,this.numRoutes);this.VIA_PENALTY_FACTOR=e/n*.3*this.VIA_PENALTY_FACTOR_2}getClosestFutureConnectionPoint(t){let e=1/0,n=null;for(const s of this.futureConnections)for(const o of s.points){const s=St(t,o)+(t.z!==o.z?this.viaPenaltyDistance:0);s<e&&(e=s,n=o)}return n}diminishCloseToGoal(t){const e=St(t,this.B);return 1-Math.exp(-e/this.straightLineDistance*5)}getFutureConnectionPenalty(t,e){let n=0;const s=this.getClosestFutureConnectionPoint(t),o=St(t,this.B);if(s){const i=St(t,s);if(o<=i)return 0;const r=i/(this.viaDiameter*this.FUTURE_CONNECTION_PROXIMITY_VD);n=(e?this.straightLineDistance*this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR:this.straightLineDistance*this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR)*Math.exp(5*-r)}return n}computeH(t){const e=St(t,this.B)**1.6;this.straightLineDistance;return e+(t.z!==this.B.z?this.viaPenaltyDistance:0)+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}computeG(t){const e=Math.abs(t.x-t.parent.x),n=Math.abs(t.y-t.parent.y),s=Math.sqrt(e**2+n**2),o=t.z%2==0,i=this.FLIP_TRACE_ALIGNMENT_DIRECTION?o?e:n:o?n:e;return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+s+i*this.MISALIGNED_DIST_PENALTY_FACTOR+this.getFutureConnectionPenalty(t,t.z!==t.parent?.z)}};function Yt(t){let e=t;for(let t=0;t<10;t++)e=16807*e%2147483647;let n=e;e=(69069*t+1)%2147483647;for(let t=0;t<10;t++)e=48271*e%2147483647;let s=e;return()=>{let t=n;n=s,t^=t<<23,t^=t>>>17,t^=s,t^=s>>>26,s=t;const e=(n+s)/4294967296;return e-Math.floor(e)}}var $t={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 kt(t,e){if(0===e)return t;if(0===t.length)return t;if(t.length<=4){const n=$t[t.length];return n[e%n.length].map(e=>t[e])}const n=Yt(e),s=t.slice();for(let t=0;t<s.length;t++){const e=Math.floor(n()*s.length),o=Math.floor(n()*(t+1));[s[e],s[o]]=[s[o],s[e]]}return s}function Bt(t){const e={minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2};for(const n of t.portPoints)n.x<e.minX&&(e.minX=n.x),n.x>e.maxX&&(e.maxX=n.x),n.y<e.minY&&(e.minY=n.y),n.y>e.maxY&&(e.maxY=n.y);return e}var jt=t=>{let e=1/0;const n=t.portPoints;for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++){const o=n[t],i=n[s];if(o.z!==i.z)continue;if(o.rootConnectionName&&o.rootConnectionName===i.rootConnectionName)continue;const r=Math.sqrt((o.x-i.x)**2+(o.y-i.y)**2);e=Math.min(e,r)}return e===1/0?0:e},Wt=class extends y{nodeWithPortPoints;colorMap;unsolvedConnections;totalConnections;solvedRoutes;failedSubSolvers;hyperParameters;minDistBetweenEnteringPoints;viaDiameter;traceWidth;activeSubSolver=null;connMap;get failedSolvers(){return this.failedSubSolvers}get activeSolver(){return this.activeSubSolver}constructor(t){const{nodeWithPortPoints:e,colorMap:n}=t;super(),this.nodeWithPortPoints=e,this.colorMap=n??{},this.solvedRoutes=[],this.hyperParameters=t.hyperParameters??{},this.failedSubSolvers=[],this.connMap=t.connMap,this.viaDiameter=t.viaDiameter??.6,this.traceWidth=t.traceWidth??.15;const s=new Map;for(const{connectionName:t,x:n,y:o,z:i}of e.portPoints)s.set(t,[...s.get(t)??[],{x:n,y:o,z:i??0}]);this.unsolvedConnections=Array.from(s.entries().map(([t,e])=>({connectionName:t,points:e}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=kt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},n)=>({...e,points:kt(t,7117*n+(this.hyperParameters.SHUFFLE_SEED??0))}))),this.totalConnections=this.unsolvedConnections.length,this.MAX_ITERATIONS=1e3*this.totalConnections**1.5,this.minDistBetweenEnteringPoints=jt(this.nodeWithPortPoints)}computeProgress(){return(this.solvedRoutes.length+(this.activeSubSolver?.progress||0))/this.totalConnections}_step(){if(this.activeSubSolver)return this.activeSubSolver.step(),this.progress=this.computeProgress(),void(this.activeSubSolver.solved?(this.solvedRoutes.push(this.activeSubSolver.solvedPath),this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSubSolvers.push(this.activeSubSolver),this.activeSubSolver=null,this.error=this.failedSubSolvers.map(t=>t.error).join("\n"),this.failed=!0));const t=this.unsolvedConnections.pop();if(this.progress=this.computeProgress(),!t)return void(this.solved=0===this.failedSubSolvers.length);if(1===t.points.length)return;if(2===t.points.length){const[e,n]=t.points,s=Math.abs(e.x-n.x)<1e-6,o=Math.abs(e.y-n.y)<1e-6;if(s&&o&&e.z===n.z)return;if(s&&o&&e.z!==n.z){const s={x:this.nodeWithPortPoints.center.x,y:this.nodeWithPortPoints.center.y},o=[{x:e.x,y:e.y,z:e.z},{...s,z:e.z},{...s,z:n.z},{x:n.x,y:n.y,z:n.z}].filter((t,e,n)=>0===e||Math.abs(t.x-n[e-1].x)>1e-6||Math.abs(t.y-n[e-1].y)>1e-6||t.z!==n[e-1].z);return void this.solvedRoutes.push({connectionName:t.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:o,vias:[s]})}}const{connectionName:e,points:n}=t;this.activeSubSolver=new Xt({connectionName:e,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:Bt(this.nodeWithPortPoints),A:{x:n[0].x,y:n[0].y,z:n[0].z},B:{x:n[n.length-1].x,y:n[n.length-1].y,z:n[n.length-1].z},obstacleRoutes:this.connMap?this.solvedRoutes.filter(t=>!this.connMap.areIdsConnected(t.connectionName,e)):this.solvedRoutes,futureConnections:this.unsolvedConnections,layerCount:this.nodeWithPortPoints.portPoints.reduce((t,e)=>Math.max(t,(e.z??0)+1),2),hyperParameters:this.hyperParameters,connMap:this.connMap,viaDiameter:this.viaDiameter,traceThickness:this.traceWidth})}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:[e.connectionName,`layer: ${e.z}`].join("\n"),color:this.colorMap[e.connectionName]??"blue"});for(let e=0;e<this.solvedRoutes.length;e++){const n=this.solvedRoutes[e];if(n.route.length>0){const s=this.colorMap[n.connectionName]??"blue";for(let o=0;o<n.route.length-1;o++){const i=n.route[o],r=n.route[o+1];t.lines.push({points:[i,r],strokeColor:0===i.z?it(s,.2):it(s,.8),layer:`route-layer-${i.z}`,step:e,strokeWidth:n.traceThickness})}for(const o of n.vias)t.circles.push({center:{x:o.x,y:o.y},radius:n.viaDiameter/2,fill:it(s,.5),layer:"via",step:e})}}const e=Bt(this.nodeWithPortPoints),{minX:n,minY:s,maxX:o,maxY:i}=e;return t.lines.push({points:[{x:n,y:s},{x:o,y:s},{x:o,y:i},{x:n,y:i},{x:n,y:s}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}},Ht=t=>Math.round(200*t)/200,Ut=t=>"function"==typeof structuredClone?structuredClone(t):JSON.parse(JSON.stringify(t));pt();var Vt=class extends Wt{cacheProvider;cacheHit=!1;hasAttemptedToUseCache=!1;initialUnsolvedConnections;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?ut():t.cacheProvider,this.initialUnsolvedConnections=Ut(this.unsolvedConnections),(this.solved||this.failed)&&this.cacheProvider&&!this.cacheHit&&this.saveToCacheSync()}_step(){if(!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync())return;const t=this.solved,e=this.failed;super._step(),!this.cacheProvider||this.cacheHit||!this.solved&&!this.failed||t||e||this.saveToCacheSync()}computeCacheKeyAndTransform(){const t=this.nodeWithPortPoints.center,e=this.initialUnsolvedConnections.map(({connectionName:e,points:n})=>({connectionName:e,points:n.map(n=>({connectionName:e,x:Ht(n.x-t.x),y:Ht(n.y-t.y),z:n.z??0}))})),n=Object.fromEntries(Object.entries(this.hyperParameters??{}).filter(([,t])=>void 0!==t).sort(([t],[e])=>t.localeCompare(e))),s=this.connMap?this.initialUnsolvedConnections.map(({connectionName:t})=>({connectionName:t,connectedIds:[...new Set(this.connMap.getIdsConnectedToNet(t)??[])].sort()})):void 0,o={node:{width:Ht(this.nodeWithPortPoints.width),height:Ht(this.nodeWithPortPoints.height),center:{x:Ht(this.nodeWithPortPoints.center.x),y:Ht(this.nodeWithPortPoints.center.y)},availableZ:this.nodeWithPortPoints.availableZ?[...this.nodeWithPortPoints.availableZ].sort():void 0},normalizedConnections:e,normalizedHyperParameters:n,minDistBetweenEnteringPoints:Ht(this.minDistBetweenEnteringPoints),normalizedConnMap:s},i=`intranode-solver:${at(o)}`,r={};return this.cacheKey=i,this.cacheToSolveSpaceTransform=r,{cacheKey:i,cacheToSolveSpaceTransform:r}}applyCachedSolution(t){t.success?(this.solvedRoutes=Ut(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:Ut(this.solvedRoutes)};try{this.cacheProvider.setCachedSolutionSync(this.cacheKey,t)}catch(t){console.error("Error saving solution to cache:",t)}}},Zt=class extends y{GREEDY_MULTIPLIER=1.2;MIN_SUBSTEPS=1;supervisedSolvers;winningSolver;getHyperParameterDefs(){throw new Error("Not implemented")}getCombinationDefs(){return null}getHyperParameterCombinations(t){t||(t=this.getHyperParameterDefs());const e=[];if(0===t.length)return[{}];const[n,...s]=t,o=this.getHyperParameterCombinations(s);return n.possibleValues.forEach(t=>{o.forEach(n=>{e.push({...n,...t})})}),e}initializeSolvers(){const t=this.getHyperParameterDefs(),e=this.getCombinationDefs()??[t.map(t=>t.name)];this.supervisedSolvers=[];for(const n of e){const e=this.getHyperParameterCombinations(t.filter(t=>n.includes(t.name)));for(const t of e){const e=this.generateSolver(t),n=this.computeG(e);this.supervisedSolvers.push({hyperParameters:t,solver:e,h:0,g:n,f:n})}}}generateSolver(t){throw new Error("Not implemented")}computeG(t){return t.iterations/t.MAX_ITERATIONS}computeH(t){return 1-(t.progress||0)}computeF(t,e){return t+e*this.GREEDY_MULTIPLIER}getSupervisedSolverWithBestFitness(){let t=1/0,e=null;for(const n of this.supervisedSolvers??[]){if(n.solver.solved)return n;if(n.solver.failed)continue;const s=n.f;s<t&&(t=s,e=n)}return e}getFailureMessage(){return`All solvers failed in hyper solver. Example failures: ${this.supervisedSolvers?.sort((t,e)=>e.f-t.f)?.slice(0,5).map(t=>t.solver.error).join(", ")}`}_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();this.activeSubSolver=t.solver,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 Gt({A:t,B:e,C:n,D:s,E:o,F:i,radius:r,margin:a,subdivisions:c=0}){const h=(t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}),d=(t,e,n)=>{const s=e.x-t.x,o=e.y-t.y,i=Math.sqrt(s*s+o*o),r=s/i,a=o/i,c=-a,h=r;return{midpoint:{x:(t.x+e.x)/2,y:(t.y+e.y)/2},A_Opp:{x:t.x-r*n,y:t.y-a*n},A_Right:{x:t.x+c*n,y:t.y+h*n},A_Left:{x:t.x-c*n,y:t.y-h*n},B_Opp:{x:e.x+r*n,y:e.y+a*n},B_Right:{x:e.x+c*n,y:e.y+h*n},B_Left:{x:e.x-c*n,y:e.y-h*n}}},l=(t,e)=>{const n=St(t,e.start),s=St(t,e.end),o=St(e.start,e.end);return Math.abs(n+s-o)<1e-4},u=(t,e)=>{const{start:n,end:s}=t,{start:o,end:i}=e;if(l(n,e)||l(s,e)||l(o,t)||l(i,t))return!0;const r=s.x-n.x,a=s.y-n.y,c=i.x-o.x,h=i.y-o.y,d=r*h-a*c;if(Math.abs(d)<1e-4)return!1;const u=o.x-n.x,p=o.y-n.y,m=(u*h-p*c)/d,f=(u*a-p*r)/d;return m>0&&m<1&&f>0&&f<1},p=(t,e)=>{const n=[];for(let e=0;e<t.length-1;e++)n.push({start:t[e],end:t[e+1]});const s=[];for(let t=0;t<e.length-1;t++)s.push({start:e[t],end:e[t+1]});for(const t of n)for(const e of s)if(u(t,e))return!0;return!1},m=t=>{let e=0;for(let n=1;n<t.length;n++){const s=t[n].x-t[n-1].x,o=t[n].y-t[n-1].y;e+=Math.sqrt(s*s+o*o)}return e},f=(t,e)=>{const{start:n,end:s}=t,o=s.x-n.x,i=s.y-n.y,r=o*o+i*i;if(0===r)return{...n,t:0};const a=Math.max(0,Math.min(1,((e.x-n.x)*o+(e.y-n.y)*i)/r));return{x:n.x+a*o,y:n.y+a*i,t:a}},g=(e,n,s)=>{const o=f(e,n);if(St(o,n)>=s)return o;const i=o.x-n.x,r=o.y-n.y,a=Math.sqrt(i*i+r*r);if(0===a){const i=e.end.x-e.start.x,r=e.end.y-e.start.y,a=Math.sqrt(i*i+r*r);return{x:n.x+s*i/a,y:n.y+s*r/a,t:o.t,isSpecial:!0,specialType:n===t?"A":"B"}}return{x:n.x+s*i/a,y:n.y+s*r/a,t:o.t,isSpecial:!0,specialType:n===t?"A":"B"}},y=d(t,e,r),x=d(t,e,r+a),v=(t,e,n,s,o)=>{const i=t.points;if(i.length<2)return i;const a=n+s,c=[i[0]];for(let t=0;t<i.length-1;t++){const n={start:i[t],end:i[t+1]};if(vt(e,n.start,n.end)<a){const t=f(n,e),s=t.x-e.x,o=t.y-e.y,i=Math.sqrt(s*s+o*o);let h=null;if(i>1e-6)h={x:e.x+a*s/i,y:e.y+a*o/i};else{const t=n.end.x-n.start.x,s=n.end.y-n.start.y,o=Math.sqrt(t*t+s*s);o>1e-6&&(h={x:e.x+a*t/o,y:e.y+a*s/o})}h&&St(n.start,h)>r/10&&c.push(h)}St(c[c.length-1],n.end)>r/10&&c.push(n.end)}if(c.length>1){const t=[c[0]];for(let e=1;e<c.length;e++)St(t[t.length-1],c[e])>r/10&&t.push(c[e]);return t}return c},S=(()=>{const t=[[n,y.B_Left,y.B_Opp,y.B_Right,h(y.midpoint,h(y.B_Right,y.A_Right)),h(y.midpoint,h(y.A_Left,y.B_Left)),y.A_Left,y.A_Opp,y.A_Right,s],[n,y.B_Right,y.B_Opp,y.B_Left,h(y.midpoint,h(y.A_Left,y.B_Left)),h(y.midpoint,h(y.A_Right,y.B_Right)),y.A_Right,y.A_Opp,y.A_Left,s],[s,y.B_Left,y.B_Opp,y.B_Right,h(y.midpoint,h(y.A_Right,y.B_Right)),h(y.midpoint,h(y.A_Left,y.B_Left)),y.A_Left,y.A_Opp,y.A_Right,n],[s,y.B_Right,y.B_Opp,y.B_Left,h(y.midpoint,h(y.A_Left,y.B_Left)),h(y.midpoint,h(y.A_Right,y.B_Right)),y.A_Right,y.A_Opp,y.A_Left,n]],e=[];for(let n=0;n<t.length;n++){const s=t[n],o={start:s[0],end:s[1]},i={start:s[s.length-2],end:s[s.length-1]},r={start:s[3],end:s[4]};u(o,i)||u(o,r)||u(i,r)||e.push({index:n+1,path:s,length:m(s)})}if(0===e.length)return{index:0,path:[]};const o=e.sort((t,e)=>t.length-e.length)[0],i=[...o.path],r=i[0],a=St(r,i[2]),c=St(r,i[3]),d=a<c?2:3;(a<St(r,i[1])||c<St(r,i[1]))&&i.splice(1,d-1);const l=i[i.length-1],p=St(l,i[i.length-3]),f=St(l,i[i.length-4]),g=p<f?i.length-3:i.length-4;return(p<St(l,i[i.length-2])||f<St(l,i[i.length-2]))&&i.splice(g+1,i.length-g-2),{index:o.index,path:i,startsAt:i[0]===n?"C":"D",goesTo:i[i.length-1]===n?"C":"D"}})(),P=c>0?((n,s)=>{if(n.length<2)return n;const o=[n[0]];for(let i=0;i<n.length-1;i++){const a={start:n[i],end:n[i+1]},c={x:(a.start.x+a.end.x)/2,y:(a.start.y+a.end.y)/2},h=St(c,t),d=St(c,e);if((h<=r||d<=r)&&Math.abs(h-d)>1e-4){const n=f(a,t),i=f(a,e),c=St(n,t),h=St(i,e)<r,d=c<r?g(a,t,r):null,l=h?g(a,e,r):null;let u=[];if(St(a.start,a.end)>r/2&&s>0)for(let n=1;n<=s;n++){const o=n/(s+1),i={x:a.start.x+o*(a.end.x-a.start.x),y:a.start.y+o*(a.end.y-a.start.y),t:o,isSpecial:!1},c=St(i,t),h=St(i,e);c<r||h<r||(d&&Math.abs(i.t-d.t)<.1||l&&Math.abs(i.t-l.t)<.1||u.push(i))}if(d&&u.push(d),l&&u.push(l),u.sort((t,e)=>t.t-e.t),u.length>1){const t=[u[0]];for(let e=1;e<u.length;e++){const n=t[t.length-1],s=u[e];St(n,s)>r/10&&t.push(s)}u=t}u.forEach(t=>o.push(t))}o.push(n[i+1])}if(o.length>1){const t=[o[0]];for(let e=1;e<o.length;e++){const n=t[t.length-1],s=o[e];St(n,s)>r/10&&t.push(s)}return t}return o})(S.path,c):S.path;let b=(()=>{if(0===S.path.length)return null;const n=(()=>{const n=h(y.A_Right,y.B_Right),s=h(y.B_Left,y.A_Left);return[{startsAt:"E",goesTo:"B",points:[o,e]},{startsAt:"E",goesTo:"A",points:[o,t]},{startsAt:"F",goesTo:"B",points:[i,e]},{startsAt:"F",goesTo:"A",points:[i,t]},{startsAt:"E",goesTo:"B",points:[o,n,e]},{startsAt:"E",goesTo:"A",points:[o,n,t]},{startsAt:"F",goesTo:"B",points:[i,n,e]},{startsAt:"F",goesTo:"A",points:[i,n,t]},{startsAt:"E",goesTo:"B",points:[o,s,e]},{startsAt:"E",goesTo:"A",points:[o,s,t]},{startsAt:"F",goesTo:"B",points:[i,s,e]},{startsAt:"F",goesTo:"A",points:[i,s,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Right,n,e]},{startsAt:"F",goesTo:"B",points:[i,x.B_Right,n,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Left,s,t]},{startsAt:"F",goesTo:"A",points:[i,x.A_Left,s,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Opp,x.B_Left,s,t]},{startsAt:"F",goesTo:"B",points:[i,x.A_Opp,x.A_Left,s,e]},{startsAt:"F",goesTo:"A",points:[i,x.B_Opp,x.B_Right,n,t]},{startsAt:"F",goesTo:"A",points:[i,x.B_Opp,x.B_Left,s,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Opp,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Opp,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Left,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Right,x.B_Opp,x.B_Left,s,t]},{startsAt:"F",goesTo:"B",points:[i,x.A_Right,x.A_Opp,x.A_Left,s,e]},{startsAt:"F",goesTo:"A",points:[i,x.B_Left,x.B_Opp,x.B_Right,n,t]},{startsAt:"F",goesTo:"A",points:[i,x.B_Right,x.B_Opp,x.B_Left,s,t]},{startsAt:"E",goesTo:"B",points:[o,x.A_Right,x.A_Opp,x.A_Left,s,e]},{startsAt:"E",goesTo:"A",points:[o,x.B_Left,x.B_Opp,x.B_Right,n,t]}].map((t,e)=>({...t,index:e}))})(),s=n.filter(t=>"E"===t.startsAt),r=n.filter(t=>"F"===t.startsAt),a=[],c=[];for(const t of s)if(!p(t.points,S.path)){a.push(t);break}for(const t of r)if(!p(t.points,S.path)){c.push(t);break}return 0===a.length||0===c.length?null:{line1:a[0],line2:c[0]}})();if(b){const n="A"===b.line1.goesTo?e:t,s="A"===b.line2.goesTo?e:t,o=v(b.line1,n,r,a),i=v(b.line2,s,r,a);b={line1:{...b.line1,points:o},line2:{...b.line2,points:i}}}return{jPair:b,optimalPath:{startsAt:S.startsAt,goesTo:S.goesTo,points:P}}}var Jt=class extends y{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;escapeLayer=1;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return this.failed=!0,void(this.error=`Expected 2 routes, but got ${this.routes.length}`);const[e,n]=this.routes;if(!(e.startPort.z===e.endPort.z))return this.failed=!0,void(this.error="Route A must start and end on the same layer");if(!(n.startPort.z===n.endPort.z))return this.failed=!0,void(this.error="Route B must start and end on the same layer");if(!(e.startPort.z===n.startPort.z))return this.failed=!0,void(this.error="Both routes must be on the same layer");0===e.startPort.z?this.escapeLayer=1:this.escapeLayer=0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e)?.push(t)}for(const[e,s]of n.entries())2===s.length&&t.push({startPort:{...s[0],z:s[0].z??0},endPort:{...s[1],z:s[1].z??0},connectionName:e});return t}calculateBounds(){return{minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2}}doRoutesCross(t,e){return gt(t.startPort,t.endPort,e.startPort,e.endPort)}calculateViaPositions(t,e){const n=this.bounds.maxX-this.bounds.minX,s=this.bounds.maxY-this.bounds.minY,o=this.bounds.minX,i=this.bounds.minY,r={width:n-2*this.obstacleMargin-this.viaDiameter,height:s-2*this.obstacleMargin-this.viaDiameter,x:o+this.obstacleMargin+this.viaDiameter/2,y:i+this.obstacleMargin+this.viaDiameter/2},a=this.viaDiameter+this.obstacleMargin,c=e.startPort,h=e.endPort,d=[{x:r.x,y:r.y},{x:r.x+r.width,y:r.y},{x:r.x+r.width,y:r.y+r.height},{x:r.x,y:r.y+r.height}],l=(t,e)=>St(t,e),u=[];d.forEach((t,e)=>{l(t,c)>=a&&l(t,h)>=a&&u.push({...t,type:"corner",index:e})});const p=[{p1:d[0],p2:d[1]},{p1:d[1],p2:d[2]},{p1:d[2],p2:d[3]},{p1:d[3],p2:d[0]}];if([c,h].forEach((t,e)=>{p.forEach((n,s)=>{((t,e)=>{const n=t.x,s=t.y,o=t.r,i=e.p1.x,r=e.p1.y,a=e.p2.x,c=e.p2.y;if(Math.abs(a-i)<.001){const t=i,e=o*o-(t-n)**2;if(e<0)return[];if(Math.abs(e)<.001){const e=s;return e>=Math.min(r,c)&&e<=Math.max(r,c)?[{x:t,y:e}]:[]}const a=s+Math.sqrt(e),h=s-Math.sqrt(e),d=[];return a>=Math.min(r,c)&&a<=Math.max(r,c)&&d.push({x:t,y:a}),h>=Math.min(r,c)&&h<=Math.max(r,c)&&d.push({x:t,y:h}),d}const h=(c-r)/(a-i),d=r-h*i,l=1+h*h,u=2*(h*d-h*s-n),p=u*u-4*l*(n*n+(d-s)*(d-s)-o*o);if(p<0)return[];if(Math.abs(p)<.001){const t=-u/(2*l),e=h*t+d;return t>=Math.min(i,a)&&t<=Math.max(i,a)&&e>=Math.min(r,c)&&e<=Math.max(r,c)?[{x:t,y:e}]:[]}const m=(-u+Math.sqrt(p))/(2*l),f=(-u-Math.sqrt(p))/(2*l),g=h*m+d,y=h*f+d,x=[];return m>=Math.min(i,a)&&m<=Math.max(i,a)&&g>=Math.min(r,c)&&g<=Math.max(r,c)&&x.push({x:m,y:g}),f>=Math.min(i,a)&&f<=Math.max(i,a)&&y>=Math.min(r,c)&&y<=Math.max(r,c)&&x.push({x:f,y:y}),x})({...t,r:a},n).forEach(t=>{l(t,0===e?h:c)>=a&&u.push({...t,type:"intersection",circle:e,edge:s})})})}),u.length<2){const t=.8*a;if(d.forEach((e,n)=>{l(e,c)>=t&&l(e,h)>=t&&!u.some(t=>t.x===e.x&&t.y===e.y)&&u.push({...e,type:"relaxed_corner",index:n})}),u.length<2){const t=[...d].sort((t,e)=>{const n=Math.min(l(t,c),l(t,h));return Math.min(l(e,c),l(e,h))-n});for(const e of t)if(!u.some(t=>t.x===e.x&&t.y===e.y)&&(u.push({...e,type:"forced_corner"}),u.length>=2))break}}if(u.length<2)return null;let m=0,f=[u[0],u[u.length>1?1:0]];for(let t=0;t<u.length;t++)for(let e=t+1;e<u.length;e++){const n=l(u[t],u[e]);n>m&&(m=n,f=[u[t],u[e]])}let g={x:f[0].x,y:f[0].y},y={x:f[1].x,y:f[1].y};const x=St(g,t.startPort);return St(y,t.startPort)<x&&([g,y]=[y,g]),{via1:g,via2:y}}trySolveAOverB(t,e,n=!1){const s=n?this.calculateViaPositions(t,e):this.calculateViaPositions(e,t);if(!s)return!1;this.debugViaPositions.push(s);const{via1:o,via2:i}=this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(s));this.debugViaPositions.push({via1:o,via2:i});const{jPair:r,optimalPath:a}=Gt({A:o,B:i,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(!r)return!1;const c={connectionName:t.connectionName,route:a.points.map(e=>({x:e.x,y:e.y,z:t.startPort.z??0})),traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};r.line2.points.reverse();const h={connectionName:e.connectionName,route:[...r.line1.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0})),{...r.line1.points[r.line1.points.length-1],z:this.escapeLayer},{...r.line2.points[0],z:this.escapeLayer},...r.line2.points.map(t=>({x:t.x,y:t.y,z:e.startPort.z??0}))],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[o,i]};return this.solvedRoutes.push(c,h),!0}pushViasFromEndpoints(t){const e={...t.via1},n={...t.via2},s=[this.routes[0].startPort,this.routes[0].endPort,this.routes[1].startPort,this.routes[1].endPort],o=this.getMinDistanceBetweenViaCenters(),i=this.viaDiameter/2+2*this.traceThickness+2*this.obstacleMargin;for(let t=0;t<10;t++){let r=!1,a=!1;const c=.9**t;for(const t of s){const s=St(e,t);if(s<i){const n=(i-s)*c,o=e.x-t.x,a=e.y-t.y,h=Math.sqrt(o*o+a*a);h>1e-6&&(e.x+=o/h*n,e.y+=a/h*n,r=!0)}const o=St(n,t);if(o<i){const e=(i-o)*c,s=n.x-t.x,r=n.y-t.y,h=Math.sqrt(s*s+r*r);h>1e-6&&(n.x+=s/h*e,n.y+=r/h*e,a=!0)}}const h=St(e,n);if(h<o){const t=(o-h)/2,s=n.x-e.x,i=n.y-e.y,c=Math.sqrt(s*s+i*i);c>1e-6?(e.x-=s/c*t,e.y-=i/c*t,n.x+=s/c*t,n.y+=i/c*t,r=!0,a=!0):(e.x-=t,n.x+=t,r=!0,a=!0)}if(!r&&!a)break}const r=St(e,n);if(r<o){const t=(o-r)/2,s=n.x-e.x,i=n.y-e.y,a=Math.sqrt(s*s+i*i);a>1e-6?(e.x-=s/a*t,e.y-=i/a*t,n.x+=s/a*t,n.y+=i/a*t):(e.x-=t,n.x+=t)}return{via1:e,via2:n}}getMinDistanceBetweenViaCenters(){return this.viaDiameter+this.traceThickness+2*this.obstacleMargin}moveViasAsCloseAsPossible(t){const{via1:e,via2:n}=t,s=this.getMinDistanceBetweenViaCenters(),o=St(e,n);if(o<=s)return t;const i=n.x-e.x,r=n.y-e.y,a=Math.sqrt(i*i+r*r),c=i/a,h=r/a,d=(e.x,n.x,e.y,n.y,(o-s)/2);return{via1:{x:e.x+c*d,y:e.y+h*d},via2:{x:n.x-c*d,y:n.y-h*d}}}handleRoutesDontCross(){const[t,e]=this.routes,n={connectionName:t.connectionName,route:[{x:t.startPort.x,y:t.startPort.y,z:t.startPort.z??0},{x:t.endPort.x,y:t.endPort.y,z:t.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]},s={connectionName:e.connectionName,route:[{x:e.startPort.x,y:e.startPort.y,z:e.startPort.z??0},{x:e.endPort.x,y:e.endPort.y,z:e.endPort.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]};this.solvedRoutes.push(n,s),this.solved=!0}_step(){if(2!==this.routes.length)return void(this.failed=!0);const[t,e]=this.routes;this.doRoutesCross(t,e)?this.trySolveAOverB(t,e)||this.trySolveAOverB(e,t)||this.trySolveAOverB(t,e,!0)||this.trySolveAOverB(e,t,!0)?this.solved=!0:(this.failed=!0,this.error="All crossover strategies failed"):this.handleRoutesDontCross()}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.rects.push({center:{x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2},width:this.bounds.maxX-this.bounds.minX,height:this.bounds.maxY-this.bounds.minY,stroke:"rgba(0, 0, 0, 0.5)",fill:"rgba(240, 240, 240, 0.1)"});for(const[e,n]of[["Route A",this.routes[0]],["Route B",this.routes[1]]])t.points.push({x:n.startPort.x,y:n.startPort.y,label:`${e}\n${n.connectionName} start`,color:"orange"}),t.points.push({x:n.endPort.x,y:n.endPort.y,label:`${e}\n${n.connectionName} end`,color:"orange"}),t.lines.push({points:[n.startPort,n.endPort],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e}\n${n.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via1:n,via2:s}=this.debugViaPositions[e],o=["rgba(255, 165, 0, 0.3)","rgba(128, 0, 128, 0.3)"],i=o[e%o.length];t.circles.push({center:n,radius:this.viaDiameter/2,fill:i,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via A (attempt ${e+1})`}),t.circles.push({center:s,radius:this.viaDiameter/2,fill:i,stroke:"rgba(0, 0, 0, 0.3)",label:`Computed Via B (attempt ${e+1})`});const r=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:n,radius:r,stroke:i,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 1 Safety Margin (attempt ${e+1})`}),t.circles.push({center:s,radius:r,stroke:i,fill:"rgba(0, 0, 0, 0)",label:`Debug Via 2 Safety Margin (attempt ${e+1})`}),t.lines.push({points:[this.routes[e%2].startPort,n,s,this.routes[e%2].endPort],strokeColor:`${i.substring(0,i.lastIndexOf(","))}, 0.3)`,strokeDash:[5,5],label:`Potential Route (attempt ${e+1})`})}for(let e=0;e<this.solvedRoutes.length;e++){const n=this.solvedRoutes[e],s=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1];t.lines.push({points:[o,i],strokeColor:s,strokeDash:1===o.z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${o.z}`}),o._label&&t.points.push({x:o.x,y:o.y,label:o._label})}for(const e of n.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Solved Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}};function qt(t,e,n,s,o){const i={x:(t.x+e.x+n.x)/3,y:(t.y+e.y+n.y)/3},r=(t,e)=>Math.sqrt((e.x-t.x)**2+(e.y-t.y)**2),a=i=>{const a=r(i,t),c=r(i,e),h=r(i,n),d=i.x>=o.minX&&i.x<=o.maxX&&i.y>=o.minY&&i.y<=o.maxY;return a>=s&&c>=s&&h>=s&&d};if(a(i))return i;const c=(t,e,n)=>{const s=t.x-e.x,o=t.y-e.y,i=Math.sqrt(s*s+o*o);return i<1e-10?{x:e.x+n,y:e.y}:{x:e.x+s/i*n,y:e.y+o/i*n}},h=(t,e,n)=>{const s=e.x-t.x,o=e.y-t.y,i=Math.sqrt(s*s+o*o);if(i>2*n-1e-10||i<1e-10)return[];const a=i*i/(2*i),c=Math.sqrt(Math.max(0,n*n-a*a)),h=t.x+s*a/i,d=t.y+o*a/i,l={x:h+c*o/i,y:d-c*s/i},u={x:h-c*o/i,y:d+c*s/i},p=[],m=1e-6;return Math.abs(r(l,t)-n)<m&&Math.abs(r(l,e)-n)<m&&p.push(l),Math.abs(r(u,t)-n)<m&&Math.abs(r(u,e)-n)<m&&p.push(u),p},d=[c(i,t,s),c(i,e,s),c(i,n,s),...h(t,e,s),...h(e,n,s),...h(n,t,s)],l=d.filter(a);if(l.length>0){const t=l.filter(t=>!(t=>{const e=1e-6;return Math.abs(t.x-o.minX)<e||Math.abs(t.x-o.maxX)<e||Math.abs(t.y-o.minY)<e||Math.abs(t.y-o.maxY)<e})(t));if(t.length>0)return t.sort((t,e)=>r(t,i)-r(e,i)),t[0]}let u=null,p=1/0;for(let t=o.minX+1;t<o.maxX;t+=5)for(let e=o.minY+1;e<o.maxY;e+=5){const n={x:t,y:e};if(a(n)){const t=r(n,i);t<p&&(p=t,u=n)}}if(null!==u)return u;const m=[];for(let t=0;t<=100;t++){const e=t/100;m.push({x:o.minX+e*(o.maxX-o.minX),y:o.minY}),m.push({x:o.maxX,y:o.minY+e*(o.maxY-o.minY)}),m.push({x:o.maxX-e*(o.maxX-o.minX),y:o.maxY}),m.push({x:o.minX,y:o.maxY-e*(o.maxY-o.minY)})}const f=m.filter(a);if(f.length>0)return f.sort((t,e)=>r(t,i)-r(e,i)),f[0];let g=1/0,y={x:o.minX,y:o.minY};for(const i of[...d,...m])if(i.x>=o.minX&&i.x<=o.maxX&&i.y>=o.minY&&i.y<=o.maxY){const o=Math.max(0,s-r(i,t))+Math.max(0,s-r(i,e))+Math.max(0,s-r(i,n));o<g&&(g=o,y=i)}return y}function Kt(t,e,n){const s=Qt(e,t,n.center,n.radius),o=Qt(t,e,n.center,n.radius),i=te(s,e),r=te(t,o),a=1e-6;let c;if(i>a&&r>a){c={x:(s.x+o.x)/2,y:(s.y+o.y)/2};const i=te(s,c),r=te(o,c);if(Math.abs(i-r)>.5*Math.min(i,r)){const n=te(t,s),i=te(e,o),r=n+i;if(r>a){const t=i/r,e=n/r;c={x:s.x*t+o.x*e,y:s.y*t+o.y*e}}}const h=te(c,n.center);if(h<1.05*n.radius){const t={x:(c.x-n.center.x)/h,y:(c.y-n.center.y)/h};c={x:n.center.x+t.x*n.radius*1.2,y:n.center.y+t.y*n.radius*1.2}}}else{const s={x:(t.x+e.x)/2,y:(t.y+e.y)/2},o=te(s,n.center);if(o<1.1*n.radius){const t={x:(s.x-n.center.x)/o,y:(s.y-n.center.y)/o};c={x:n.center.x+t.x*n.radius*1.2,y:n.center.y+t.y*n.radius*1.2}}else c=s}return{B:s,D:o,E:c}}function Qt(t,e,n,s){const o=[n.x-t.x,n.y-t.y],i=Math.sqrt(o[0]*o[0]+o[1]*o[1]);if(i<=s){if(i<1e-8){const o=[e.x-t.x,e.y-t.y],i=Math.sqrt(o[0]*o[0]+o[1]*o[1]);return i<1e-8?{x:n.x+s,y:n.y}:{x:n.x+o[0]/i*s,y:n.y+o[1]/i*s}}const r=[o[0]/i,o[1]/i];return{x:n.x-r[0]*s,y:n.y-r[1]*s}}const r=[e.x-t.x,e.y-t.y],a=Math.sqrt(i*i-s*s),c=[o[0]/i,o[1]/i],h=[-c[1],c[0]],d=[c[1],-c[0]],l=r[0]*h[0]+r[1]*h[1]>r[0]*d[0]+r[1]*d[1]?h:d,u=s/i,p=a/i,m=[c[0]*p+l[0]*u,c[1]*p+l[1]*u];return{x:t.x+a*m[0],y:t.y+a*m[1]}}function te(t,e){const n=e.x-t.x,s=e.y-t.y;return Math.sqrt(n*n+s*s)}var ee=1e-9;function ne(t,e,n,s="cw"){const o=se(t,n),i=se(e,n);return Math.abs(i-o)<ee?{left:0,top:0,right:0,bottom:0}:function(t,e,n,s){const o=n.maxX-n.minX,i=n.maxY-n.minY;if(o<ee&&i<ee)return{left:0,top:0,right:0,bottom:0};const r=2*(o+i);if(r<ee)return{left:0,top:0,right:0,bottom:0};const a=o/r*(2*Math.PI),c=(o+i)/r*(2*Math.PI),h=(o+o+i)/r*(2*Math.PI),d=2*Math.PI,l=[{name:"top",start:0,end:a,length:o},{name:"right",start:a,end:c,length:i},{name:"bottom",start:c,end:h,length:o},{name:"left",start:h,end:d,length:i}],u={left:0,top:0,right:0,bottom:0},p=(t,e,n,s,o)=>{const i=e>2*Math.PI-ee?2*Math.PI:e;if(i<=t+ee)return 0;if(o){const e=Math.max(t,n),o=Math.min(i,2*Math.PI),r=Math.max(0,o-e),a=Math.max(t,0),c=Math.min(i,s);return r+Math.max(0,c-a)}{const e=Math.max(t,n),o=Math.min(i,s);return Math.max(0,o-e)}};for(const n of l){const o=n.end-n.start;if(o<ee||n.length<ee)continue;let i=0;if("cw"===s){const s=t>e+ee;i=p(n.start,n.end,t,e,s)}else{const s=e>t+ee;i=p(n.start,n.end,e,t,s)}if(i>ee){const t=i/o;u[n.name]+=Math.max(0,Number.isFinite(t)?t:0)}}for(const t in u)u[t]=Math.max(0,Math.min(1,u[t]));return u}(o,i,n,s)}function se(t,e){const n=e.maxX-e.minX,s=e.maxY-e.minY;if(n<ee&&s<ee)return 0;const o=2*(n+s);if(o<ee)return 0;let i=0;if(Math.abs(t.y-e.maxY)<ee&&t.x>=e.minX-ee&&t.x<=e.maxX+ee)i=Math.max(0,Math.min(n,t.x-e.minX));else if(Math.abs(t.x-e.maxX)<ee&&t.y>=e.minY-ee&&t.y<=e.maxY+ee)i=n+Math.max(0,Math.min(s,e.maxY-t.y));else if(Math.abs(t.y-e.minY)<ee&&t.x>=e.minX-ee&&t.x<=e.maxX+ee)i=n+s+Math.max(0,Math.min(n,e.maxX-t.x));else{if(!(Math.abs(t.x-e.minX)<ee&&t.y>=e.minY-ee&&t.y<=e.maxY+ee))throw new Error(`Point (${t.x}, ${t.y}) does not lie on the boundary defined by ${JSON.stringify(e)}`);i=n+s+n+Math.max(0,Math.min(s,t.y-e.minY))}return i=Math.max(0,Math.min(o,i)),o>ee?i/o*(2*Math.PI):0}function oe(t,e,n,s){return function({angleA:t,angleB:e,angleC:n}){const s=Math.cos(t),o=Math.sin(t),i=Math.cos(e),r=Math.sin(e),a=Math.cos(n);return(i-s)*(Math.sin(n)-o)-(r-o)*(a-s)<0?"ccw":"cw"}({angleA:se(t,s),angleB:se(e,s),angleC:se(n,s)})}var ie=class extends y{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;layerCount=2;debugViaPositions;solvedRoutes=[];bounds;constructor(t){if(super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.viaDiameter=t?.viaDiameter??.6,this.traceThickness=t?.traceThickness??.15,this.obstacleMargin=t?.obstacleMargin??.1,this.layerCount=t?.layerCount??2,this.debugViaPositions=[],this.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),2!==this.routes.length)return this.failed=!0,void(this.error=`Expected 2 routes, but got ${this.routes.length}`);const[e,n]=this.routes,s=e.A.z!==e.B.z,o=n.A.z!==n.B.z;return s&&o||!s&&!o?(this.failed=!0,void(this.error="Exactly one route must have a layer transition")):void 0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e)?.push(t)}for(const[e,s]of n.entries())2===s.length&&t.push({A:{...s[0],z:s[0].z??0},B:{...s[1],z:s[1].z??0},connectionName:e});return t}calculateBounds(){return{minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2}}doRoutesCross(t,e){return gt(t.A,t.B,e.A,e.B)}calculateViaPosition(t,e){const n=e.A.z,s=t.A.z!==n?t.A:t.B,o=2*this.obstacleMargin+this.viaDiameter/2+this.traceThickness,i=this.obstacleMargin+this.viaDiameter/2,r=e.A,a=s,c=e.B,h=oe(r,a,c,this.bounds),d=function(t,e,n,s,o){const i=ne(t,e,s,o),r=ne(e,n,s,o),a={left:Math.min(1,i.left+r.left),top:Math.min(1,i.top+r.top),right:Math.min(1,i.right+r.right),bottom:Math.min(1,i.bottom+r.bottom)};for(const t in a)Math.abs(a[t])<ee&&(a[t]=0);return a}(r,a,c,this.bounds,h),l={minX:this.bounds.minX+(d.left>.5?o:i),minY:this.bounds.minY+(d.bottom>.5?o:i),maxX:this.bounds.maxX-(d.right>.5?o:i),maxY:this.bounds.maxY-(d.top>.5?o:i)};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),qt(r,a,c,o,l)}createTransitionRoute(t,e,n,s){return{connectionName:s,route:[{x:t.x,y:t.y,z:t.z??0},{x:n.x,y:n.y,z:t.z??0},{x:n.x,y:n.y,z:e.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[n]}}createFlatRoute(t,e,n,s,o,i){s.z,t.z;const r=this.viaDiameter/2+this.traceThickness/2+this.obstacleMargin,a=((t,e,n,s)=>{const o=n.x-t.x,i=n.y-t.y;return((t,e)=>({x:(t.x+e.x)/2,y:(t.y+e.y)/2}))({x:t.x+o*e,y:t.y+i*e},{x:n.x-o*s,y:n.y-i*s})})(n,this.viaDiameter,s.z!==t.z?s:o,this.traceThickness),c={center:{x:n.x,y:n.y},radius:r},h=Kt(t,a,c).E,d=Kt(a,e,c).E,l=Kt(t,h,c).E,u=Kt(h,a,c).E,p=Kt(a,d,c).E,m=Kt(d,e,c).E,f=Kt(u,p,c).E;return{connectionName:i,route:[{x:t.x,y:t.y,z:t.z??0},{x:l.x,y:l.y,z:t.z??0},{x:h.x,y:h.y,z:t.z??0},{x:u.x,y:u.y,z:t.z??0},{x:f.x,y:f.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:m.x,y:m.y,z:t.z??0},{x:e.x,y:e.y,z:e.z??0}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[]}}trySolve(){const[t,e]=this.routes,n=t.A.z!==t.B.z,s=n?t:e,o=n?e:t,i=this.calculateViaPosition(s,o);if(!i)return!1;this.debugViaPositions.push({via:i});const r=this.createTransitionRoute(s.A,s.B,i,s.connectionName),a=this.createFlatRoute(o.A,o.B,i,s.A,s.B,o.connectionName);return this.solvedRoutes.push(r,a),!0}_step(){if(!this.doRoutesCross(this.routes[0],this.routes[1]))return this.failed=!0,void(this.error="Can only solve routes that have a single transition crossing");this.trySolve()?this.solved=!0:(this.failed=!0,this.error="Failed to find a valid via position and route path")}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.rects.push({center:{x:(this.bounds.minX+this.bounds.maxX)/2,y:(this.bounds.minY+this.bounds.maxY)/2},width:this.bounds.maxX-this.bounds.minX,height:this.bounds.maxY-this.bounds.minY,stroke:"rgba(0, 0, 0, 0.5)",fill:"rgba(240, 240, 240, 0.1)",label:"PCB Bounds"});for(const e of this.routes)t.points.push({x:e.A.x,y:e.A.y,label:`${e.connectionName} start (z=${e.A.z})`,color:"orange"}),t.points.push({x:e.B.x,y:e.B.y,label:`${e.connectionName} end (z=${e.B.z})`,color:"orange"}),t.lines.push({points:[e.A,e.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:`${e.connectionName} direct`});for(let e=0;e<this.debugViaPositions.length;e++){const{via:n}=this.debugViaPositions[e];t.circles.push({center:n,radius:this.viaDiameter/2,fill:"rgba(255, 165, 0, 0.7)",stroke:"rgba(0, 0, 0, 0.5)",label:`Computed Via (attempt ${e+1})`});const s=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:n,radius:s,stroke:"rgba(255, 165, 0, 0.7)",fill:"rgba(0, 0, 0, 0)",label:"Safety Margin"})}for(let e=0;e<this.solvedRoutes.length;e++){const n=this.solvedRoutes[e],s=e%2==0?"rgba(0, 255, 0, 0.75)":"rgba(255, 0, 255, 0.75)";for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1];t.lines.push({points:[o,i],strokeColor:s,strokeDash:o.z!==n.route[0].z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${o.z}`})}for(const e of n.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Via Margin"})}return t}getSolvedRoutes(){return this.solvedRoutes}},re=class extends y{nodeWithPortPoints;routes;viaDiameter;traceThickness;obstacleMargin;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.routes=this.extractRoutesFromNode(),this.bounds=this.calculateBounds(),1!==this.routes.length)return this.failed=!0,void(this.error=`Expected 1 route, but got ${this.routes.length}`);const e=this.routes[0];if(void 0===e.A.z||void 0===e.B.z)return this.failed=!0,void(this.error="Route points should have predefined z values");if(e.A.z===e.B.z)return this.failed=!0,void(this.error="Only one route provided, but it has no transition");const n=this.viaDiameter/2+this.obstacleMargin,s={x:ft((e.A.x+e.B.x)/2,this.bounds.minX+n,this.bounds.maxX-n),y:ft((e.A.y+e.B.y)/2,this.bounds.minY+n,this.bounds.maxY-n)};this.solvedRoutes.push(this.createTransitionRoute(e.A,e.B,s,e.connectionName)),this.solved=!0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e).push(t)}for(const[e,s]of n.entries())2===s.length&&t.push({A:{...s[0]},B:{...s[1]},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}}createTransitionRoute(t,e,n,s){return{connectionName:s,route:[{x:t.x,y:t.y,z:t.z},{x:n.x,y:n.y,z:t.z},{x:n.x,y:n.y,z:e.z},{x:e.x,y:e.y,z:e.z}],traceThickness:this.traceThickness,viaDiameter:this.viaDiameter,vias:[n]}}_step(){this.solved=!0}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(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"}),this.routes.length>0)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.solvedRoutes.length;e++){const n=this.solvedRoutes[e],s="rgba(0, 255, 0, 0.75)";for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1];t.lines.push({points:[o,i],strokeColor:s,strokeDash:o.z!==n.route[0].z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${o.z}`})}for(const e of n.vias)t.circles.push({center:e,radius:this.viaDiameter/2,fill:"rgba(0, 0, 255, 0.8)",stroke:"black",label:"Solved Via"}),t.circles.push({center:e,radius:this.viaDiameter/2+this.obstacleMargin,fill:"rgba(0, 0, 255, 0.3)",stroke:"black",label:"Via Margin"})}return t}},ae=(t,e)=>{const n={};return t.portPoints.forEach((e,s)=>{n[e.connectionName]=`hsl(${360*s/t.portPoints.length}, 100%, 50%)`}),n},ce=class extends y{bounds;maxViaCount;portPairMap;colorMap;nodeWidth;availableZ;hyperParameters;VIA_INTERSECTION_BUFFER_DISTANCE=.05;PLACEHOLDER_WALL_BUFFER_DISTANCE=.1;NEW_HEAD_WALL_BUFFER_DISTANCE=.05;viaDiameter;unprocessedConnections;completedPaths=new Map;placeholderPaths=new Map;currentHead;currentConnectionName;currentPath;currentViaCount;constructor({nodeWithPortPoints:t,colorMap:e,hyperParameters:n,viaDiameter:s}){super(),this.MAX_ITERATIONS=1e5,this.colorMap=e??ae(t),this.maxViaCount=5,this.bounds=Bt(t),this.nodeWidth=this.bounds.maxX-this.bounds.minX,this.portPairMap=(t=>{const e=new Map;return t.portPoints.forEach(t=>{e.has(t.connectionName)?e.get(t.connectionName).end=t:e.set(t.connectionName,{start:t,end:null,connectionName:t.connectionName})}),e})(t),this.stats.solutionsFound=0,this.availableZ=t.availableZ??[0,1],this.hyperParameters=n??{SHUFFLE_SEED:0},this.viaDiameter=s??.6,this.unprocessedConnections=Array.from(this.portPairMap.keys()).sort(),n?.SHUFFLE_SEED&&(this.unprocessedConnections=kt(this.unprocessedConnections,n.SHUFFLE_SEED));for(const[t,{start:e,end:n}]of this.portPairMap.entries())if(e.z===n.z){const s=Math.abs(e.x-n.x)<1e-9,o=Math.abs(e.y-n.y)<1e-9;s||o?this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),this._padByPlaceholderWallBuffer(n),n]):this.placeholderPaths.set(t,[e,n])}else{const s=(e.x+n.x)/2,o=(e.y+n.y)/2,i=this._padByPlaceholderWallBuffer({x:s,y:o,z:e.z}),r=this._padByPlaceholderWallBuffer({x:s,y:o,z:n.z});this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),i,r,this._padByPlaceholderWallBuffer(n),n])}this.currentConnectionName=this.unprocessedConnections.pop();const o=this.portPairMap.get(this.currentConnectionName).start;this.currentHead=this._padByNewHeadWallBuffer(o),this.currentPath=[o,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}_padByNewHeadWallBuffer(t){return{x:ft(t.x,this.bounds.minX+this.NEW_HEAD_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.NEW_HEAD_WALL_BUFFER_DISTANCE),y:ft(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:ft(t.x,this.bounds.minX+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxX-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),y:ft(t.y,this.bounds.minY+this.PLACEHOLDER_WALL_BUFFER_DISTANCE,this.bounds.maxY-this.PLACEHOLDER_WALL_BUFFER_DISTANCE),z:t.z}}_step(){if(this.solved)return;const t=this.portPairMap.get(this.currentConnectionName).end,e=[this.currentHead,t];let n=null,s=null;const o=t=>{for(const o of t.values())for(let t=0;t<o.length-1;t++){const i=[o[t],o[t+1]];if(i[0].x===i[1].x&&i[0].y===i[1].y)continue;if(i[0].z!==this.currentHead.z)continue;const r=Pt(e[0],e[1],i[0],i[1]);if(r){const t=St(this.currentHead,r);if(t<1e-6)continue;(!n||t<n.dist)&&(n={point:r,dist:t},s=i[0].z)}}};o(this.completedPaths),o(this.placeholderPaths);const i=this.currentHead.z!==t.z;if((n||i)&&(this.currentViaCount++,this.currentViaCount>=this.maxViaCount))return this.failed=!0,void(this.error=`Exceeded max via count of ${this.maxViaCount}`);if(n){let t;const e=n.dist;if(e<=this.VIA_INTERSECTION_BUFFER_DISTANCE+1e-6)t=bt(this.currentHead,n.point);else{const s=n.point,o=s.x-this.currentHead.x,i=s.y-this.currentHead.y,r=(e-this.VIA_INTERSECTION_BUFFER_DISTANCE)/e;t={x:this.currentHead.x+o*r,y:this.currentHead.y+i*r}}const o=this.availableZ.find(t=>t!==s);if(void 0===o)return this.error="Could not determine next Z level for via placement!",void(this.failed=!0);const i={...t,z:this.currentHead.z},r={...t,z:o};this.currentPath.push(i,r),this.currentHead=r}else if(i){let e;const n=St(this.currentHead,t);if(n<this.VIA_INTERSECTION_BUFFER_DISTANCE)e=bt(this.currentHead,t);else{const s=t.x-this.currentHead.x,o=t.y-this.currentHead.y,i=(n-this.VIA_INTERSECTION_BUFFER_DISTANCE)/n;e={x:this.currentHead.x+s*i,y:this.currentHead.y+o*i}}const s=t.z,o={...e,z:this.currentHead.z},i={...e,z:s};this.currentPath.push(o,i),this.currentHead=i}else if(this.currentPath.push(t),this.completedPaths.set(this.currentConnectionName,this.currentPath),0===this.unprocessedConnections.length)this.solved=!0,this.stats.solutionsFound=1;else{this.currentConnectionName=this.unprocessedConnections.pop();const{start:t}=this.portPairMap.get(this.currentConnectionName);this.currentHead=this._padByNewHeadWallBuffer(t),this.currentPath=[t,this.currentHead],this.currentViaCount=0,this.placeholderPaths.delete(this.currentConnectionName)}}visualize(){const t={points:[],lines:[],circles:[],rects:[],title:"Via Possibilities Solver State",coordinateSystem:"cartesian"},e=this.colorMap;t.lines.push({points:[{x:this.bounds.minX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.minY}],strokeColor:"gray",strokeWidth:.01});for(const[e,{start:n,end:s}]of this.portPairMap.entries()){const o=this.colorMap[e]??"black";t.points.push({x:n.x,y:n.y,color:o,label:`Port: ${e} Start (z${n.z})`}),t.points.push({x:s.x,y:s.y,color:o,label:`Port: ${e} End (z${s.z})`})}const n=(n,s)=>{for(const[o,i]of n.entries()){const n=e[o]??"black";for(let e=0;e<i.length-1;e++){const r=i[e],a=i[e+1];r.x===a.x&&r.y===a.y&&r.z!==a.z?t.circles.push({center:{x:r.x,y:r.y},radius:this.viaDiameter/2,fill:it(n,.5),label:`${s}: ${o} Via (z${r.z}->z${a.z})`}):t.lines.push({points:[r,a],strokeColor:it(n,.5),strokeDash:0===r.z?void 0:[.1,.1],strokeWidth:.1,label:`${s}: ${o} (z${r.z})`})}}};if(n(this.placeholderPaths,"Placeholder"),n(this.completedPaths,"Completed"),this.currentPath&&this.currentPath.length>0){const n=e[this.currentConnectionName]??"orange";for(let e=0;e<this.currentPath.length-1;e++){const s=this.currentPath[e],o=this.currentPath[e+1];s.x===o.x&&s.y===o.y&&s.z!==o.z?t.circles.push({center:{x:s.x,y:s.y},radius:this.viaDiameter/2,fill:it(n,.5),label:`Current: ${this.currentConnectionName} Via (z${s.z}->z${o.z})`}):t.lines.push({points:[s,o],strokeColor:it(n,.5),strokeWidth:.15,strokeDash:"2,2",label:`Current: ${this.currentConnectionName} (z${s.z})`})}t.points.push({x:this.currentHead.x,y:this.currentHead.y,color:"green",label:`Current Head: ${this.currentConnectionName} (z${this.currentHead.z})`})}return t}},he=t=>Math.round(1e4*t),de=t=>{let e=0,n=[];const s=[];for(const e of t.portPoints){if(n.some(t=>t.connectionName===e.connectionName))continue;if(s.some(t=>t.connectionName===e.connectionName))continue;const o={connectionName:e.connectionName,z:e.z,points:[{x:he(e.x),y:he(e.y),z:e.z}]};for(const n of t.portPoints)e.connectionName===n.connectionName&&(e.x===n.x&&e.y===n.y||o.points.push({x:he(n.x),y:he(n.y),z:n.z}));o.points.some(t=>t.z!==o.z)?s.push(o):n.push(o)}n=n.filter(t=>t.points.length>1);for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++){const o=n[t],i=n[s];o.z===i.z&>(o.points[0],o.points[1],i.points[0],i.points[1])&&e++}let o=0;for(let t=0;t<s.length;t++)for(let e=t+1;e<s.length;e++){const n=s[t],i=s[e];gt(n.points[0],n.points[1],i.points[0],i.points[1])&&o++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:s.length,numTransitionPairCrossings:o}},le=1e-9;function ue(t,e,n=le){return Math.abs(t-e)<n}function pe(t,e,n,s){return t*s-e*n}function me(t,e,n,s){const o={x:e.x-t.x,y:e.y-t.y},i={x:s.x-n.x,y:s.y-n.y},r=pe(o.x,o.y,i.x,i.y);if(ue(r,0))return null;const a={x:n.x-t.x,y:n.y-t.y},c=pe(a.x,a.y,i.x,i.y)/r,h=pe(a.x,a.y,o.x,o.y)/r;return c<-le||c>1+le||h<-le||h>1+le?null:{x:t.x+c*o.x,y:t.y+c*o.y}}function fe(t){let e=0;for(let n=0,s=t.length;n<s;++n){const o=(n+1)%s;e+=t[n].x*t[o].y-t[o].x*t[n].y}return.5*e}function ge(t){let e=0,n=0,s=0;for(let o=0,i=t.length;o<i;++o){const r=(o+1)%i,a=t[o].x*t[r].y-t[r].x*t[o].y;e+=a,n+=(t[o].x+t[r].x)*a,s+=(t[o].y+t[r].y)*a}return e*=.5,ue(e,0)?null:(n/=6*e,s/=6*e,{x:n,y:s})}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 ve(t,e){const n=[...e,...[{start:{x:t.minX,y:t.minY},end:{x:t.maxX,y:t.minY}},{start:{x:t.maxX,y:t.minY},end:{x:t.maxX,y:t.maxY}},{start:{x:t.maxX,y:t.maxY},end:{x:t.minX,y:t.maxY}},{start:{x:t.minX,y:t.maxY},end:{x:t.minX,y:t.minY}}]],s=n.map(()=>[]);for(let t=0;t<n.length;++t){const e=n[t];s[t].push(e.start,e.end)}for(let t=0;t<n.length;++t)for(let e=t+1;e<n.length;++e){const o=me(n[t].start,n[t].end,n[e].start,n[e].end);o&&(s[t].push(o),s[e].push(o))}const o=new Map,i=[];function r(t){const e=function(t,e=le){return`${Math.round(t.x/e)}:${Math.round(t.y/e)}`}(t);if(!o.has(e)){const n=i.length;return o.set(e,n),i.push(new ye(t.x,t.y)),n}return o.get(e)}const a=[];for(let t=0;t<n.length;++t){const e=n[t],o=s[t].slice();o.sort((t,n)=>{const s=e.end.x-e.start.x,o=e.end.y-e.start.y;return(ue(Math.abs(s),0)?(t.y-e.start.y)/o:(t.x-e.start.x)/s)-(ue(Math.abs(s),0)?(n.y-e.start.y)/o:(n.x-e.start.x)/s)});for(let t=0;t<o.length-1;++t){const n=o[t],s=o[t+1],c=r(n),h=r(s);c!==h&&(a.push([c,h]),e.connectionName&&(i[c].connectionNames.add(e.connectionName),i[h].connectionNames.add(e.connectionName)))}}const c=[];for(const[t,e]of a){const n=new xe(t,e),s=new xe(e,t);n.twin=c.length+1,s.twin=c.length;const o=c.length;c.push(n,s),i[t].out.push(o),i[e].out.push(o+1)}for(let t=0;t<i.length;++t){const e=i[t];e.out.sort((t,n)=>{const s=c[t],o=c[n],r=i[s.dest],a=i[o.dest];return Math.atan2(r.y-e.y,r.x-e.x)-Math.atan2(a.y-e.y,a.x-e.x)});const n=e.out.length;for(let t=0;t<n;++t){const s=e.out[t],o=e.out[(t-1+n)%n],i=c[s];null!==i.twin&&(c[i.twin].next=o)}}const h=[],d=[];for(let t=0;t<c.length;++t){if(c[t].visited)continue;let e=t;const n=[],s=[];do{if(null===e)break;const t=c[e];t.visited=!0,n.push(i[t.orig]),s.push(e),e=t.next}while(null!==e&&e!==t&&!c[e].visited);if(n.length<3)continue;if(fe(n)>le){const t=ge(n);t&&(h.push(t),d.push({vertices:n.map(t=>({x:t.x,y:t.y,connectionNames:t.connectionNames.size>0?t.connectionNames:void 0})),centroid:t}))}}return{centroids:h,faces:d,allVertices:i}}function Se(t,e){if(t>e)throw new Error("oneCount cannot be greater than length");if(t<0||e<0)throw new Error("oneCount and length must be non-negative");const n=[];return function t(s,o,i){i!==e?(s[i]=0,t(s,o,i+1),o>0&&(s[i]=1,t(s,o-1,i+1))):0===o&&n.push([...s])}(Array(e).fill(0),t,0),n}var Pe=t=>{if(0===t.length)return[[]];const e=[];for(let n=0;n<t.length;n++){const s=t[n],o=[...t.slice(0,n),...t.slice(n+1)],i=Pe(o);for(const t of i)e.push([s,...t])}return e};var be=t=>{const{start:e,end:n,segmentsPerPolyline:s,viaPositions:o,viaCount:i,availableZ:r}=t,a=function(t,e){const n=new Array(t).fill(0);if(0===e)return n;if(e===t)return n.fill(1);if(e<=t/2){const s=Math.floor(t/e),o=Math.floor((t-(s*(e-1)+1))/2);for(let t=0;t<e;t++)n[o+t*s]=1}else{const s=t-e,o=Math.floor(t/s),i=Math.floor((t-(o*(s-1)+1))/2);n.fill(1);for(let t=0;t<s;t++)n[i+t*o]=0}return n}(s,i),c=a.map(()=>null);let h=0,d=e.z1;const l=r.indexOf(e.z1);for(let t=0;t<a.length;t++)if(1===a[t]){const e=r[(l+h+1)%r.length];c[t]={...o[h],z1:d,z2:e},d=e,h++}let u=e;for(let t=0;t<c.length;t++){if(c[t]){u=c[t];continue}let e=n,s=c.length;for(let n=t+1;n<c.length;n++)if(c[n]){e=c[n],s=n;break}const o=s-t,i=e.x-u.x,r=e.y-u.y;for(let e=1/(o+1),n=0;t+n!==s;e+=1/(o+1),n++)c[t+n]={x:u.x+i*e,y:u.y+r*e,z1:u.z2,z2:u.z2}}return c},Me=1e-9;function Ne(t,e){return Math.abs(t-e)<Me}function Ie(t){return`${Math.round(t.x/Me)}:${Math.round(t.y/Me)}`}function Ce(t,e,n,s){return t*s-e*n}function _e(t,e,n,s){const o={x:e.x-t.x,y:e.y-t.y},i={x:s.x-n.x,y:s.y-n.y},r=Ce(o.x,o.y,i.x,i.y),a={x:n.x-t.x,y:n.y-t.y};if(Ne(r,0))return null;const c=Ce(a.x,a.y,i.x,i.y)/r,h=Ce(a.x,a.y,o.x,o.y)/r;return c>=-1e-9&&c<=1+Me&&h>=-1e-9&&h<=1+Me?{x:t.x+c*o.x,y:t.y+c*o.y}:null}function Te(t,e,n){return Ne(Math.hypot(t.x-e.x,t.y-e.y)+Math.hypot(t.x-n.x,t.y-n.y),Math.hypot(e.x-n.x,e.y-n.y))}function Ee(t,e){const n=[],s=new Map;for(const e of t){const t=[e.start,...e.mPoints,e.end];for(let o=0;o<t.length-1;o++){const i=t[o],r=t[o+1],a=i.z2;if(n.push({start:{x:i.x,y:i.y},end:{x:r.x,y:r.y},connectionName:e.connectionName,layer:a}),i.z1!==i.z2){const t=Ie(i);s.has(t)||s.set(t,{point:i,connectionName:e.connectionName})}}const o=t[t.length-1];if(o.z1!==o.z2){const t=Ie(o);s.has(t)||s.set(t,{point:o,connectionName:e.connectionName})}}const o=[{start:{x:e.minX,y:e.minY},end:{x:e.maxX,y:e.minY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.minY},end:{x:e.maxX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.maxX,y:e.maxY},end:{x:e.minX,y:e.maxY},connectionName:null,layer:0},{start:{x:e.minX,y:e.maxY},end:{x:e.minX,y:e.minY},connectionName:null,layer:0}];n.push(...o);const i=new Map;let r=0;function a(t,e){const n=Ie(t);let o=i.get(n);if(!o){const e=s.has(n);o={id:r++,x:t.x,y:t.y,isVia:e,connectionNames:new Set,outgoingEdges:[]},i.set(n,o),e&&s.get(n)&&o.connectionNames.add(s.get(n).connectionName)}return e&&o.connectionNames.add(e),o}for(const t of n)a(t.start,t.connectionName),a(t.end,t.connectionName);const c=new Map;for(const t of n)c.set(t,[]);for(let t=0;t<n.length;t++)for(let e=t+1;e<n.length;e++){if(n[t].layer!==n[e].layer)continue;const s=_e(n[t].start,n[t].end,n[e].start,n[e].end);s&&(a(s),Te(s,n[t].start,n[t].end)&&c.get(n[t]).push(s),Te(s,n[e].start,n[e].end)&&c.get(n[e]).push(s))}const h=[];let d=0;for(const t of n){const e=[t.start,...c.get(t),t.end];e.sort((e,n)=>{const s=t.end.x-t.start.x,o=t.end.y-t.start.y;return Math.abs(s)>Math.abs(o)?(e.x-t.start.x)/s-(n.x-t.start.x)/s:Math.abs(o)<Me?0:(e.y-t.start.y)/o-(n.y-t.start.y)/o});const n=[];if(e.length>0){n.push(e[0]);for(let t=1;t<e.length;t++)Ne(e[t].x,e[t-1].x)&&Ne(e[t].y,e[t-1].y)||n.push(e[t])}for(let e=0;e<n.length-1;e++){const s=n[e],o=n[e+1],i=a(s,t.connectionName),r=a(o,t.connectionName);if(i===r)continue;const c={id:d++,origin:i,twin:null,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1},l={id:d++,origin:r,twin:c,next:null,face:null,connectionName:t.connectionName,layer:t.layer,visited:!1};c.twin=l,h.push(c,l),i.outgoingEdges.push(c),r.outgoingEdges.push(l)}}for(const t of i.values()){t.outgoingEdges.sort((e,n)=>{const s=e.twin.origin,o=n.twin.origin;return Math.atan2(s.y-t.y,s.x-t.x)-Math.atan2(o.y-t.y,o.x-t.x)});const e=t.outgoingEdges.length;for(let n=0;n<e;n++){const s=t.outgoingEdges[n],o=t.outgoingEdges[(n-1+e)%e];s.twin&&(s.twin.next=o)}}const l=[];let u=0,p=null,m=-1/0;for(const t of h){if(t.visited)continue;const e={id:u++,outerComponent:t,innerComponents:[],isOuterFace:!1};l.push(e);let n=t;const s=[],o=[],i=new Set;let r=0;do{if(!n||n.visited){console.warn("Face traversal encountered visited edge or null, breaking loop.",e.id),s.length=0;break}n.visited=!0,n.face=e,s.push(n),o.push(n.origin),null!==n.connectionName&&i.add(n.connectionName);const t=n.origin,a=n.twin.origin;r+=t.x*a.y-a.x*t.y,n=n.next}while(n!==t&&null!==n);if(n===t){if(r=.5*Math.abs(r),r>m&&(m=r,p&&(p.isOuterFace=!1),p=e,e.isOuterFace=!0),!e.isOuterFace&&s.length>0){if([...i].filter(t=>null!==t).length>1){let t=!1;for(const e of o)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 Re=class extends y{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.viaDiameter=t.viaDiameter??this.viaDiameter,this.cellSize=this.nodeWithPortPoints.width/1024,this.candidates=[],this.availableZ=this.nodeWithPortPoints.availableZ??[0,1],this.bounds={minX:this.nodeWithPortPoints.center.x-this.nodeWithPortPoints.width/2,maxX:this.nodeWithPortPoints.center.x+this.nodeWithPortPoints.width/2,minY:this.nodeWithPortPoints.center.y-this.nodeWithPortPoints.height/2,maxY:this.nodeWithPortPoints.center.y+this.nodeWithPortPoints.height/2};const e=this.nodeWithPortPoints.width*this.nodeWithPortPoints.height,n=(this.viaDiameter+2*this.obstacleMargin+this.traceWidth/2)**2,s=new Set(this.nodeWithPortPoints.portPoints.map(t=>t.connectionName)).size;this.uniqueConnections=s;const{numSameLayerCrossings:o,numEntryExitLayerChanges:i}=de(this.nodeWithPortPoints);if(this.minViaCount=2*o+i,this.maxViaCount=Math.min(Math.floor(e/n),Math.ceil(1.5*s)),this.minViaCount>this.SEGMENTS_PER_POLYLINE*(s/2))return this.failed=!0,void(this.error=`Not possible to solve problem with given SEGMENTS_PER_POLYLINE (${this.SEGMENTS_PER_POLYLINE}), atleast ${this.minViaCount} vias are required`);this.maxViaCount>this.SEGMENTS_PER_POLYLINE&&(this.maxViaCount=this.SEGMENTS_PER_POLYLINE),this.maxViaCount<this.minViaCount&&(this.maxViaCount=this.minViaCount)}computeMinGapBtwPolyLines(t){const e=[],n=[],s=[];for(let e=0;e<t.length;e++){const o=t[e],i=[o.start,...o.mPoints,o.end],r=new Map(this.availableZ.map(t=>[t,[]]));for(let t=0;t<i.length-1;t++){const e=[i[t],i[t+1]],n=e[0].z2;r.has(n)||r.set(n,[]),r.get(n).push(e)}n.push(r),s.push(i.filter(t=>t.z1!==t.z2))}for(let o=0;o<t.length;o++){const i=n[o],r=s[o];for(let a=o+1;a<t.length;a++){if(this.connMap?.areIdsConnected(t[o].connectionName,t[a].connectionName))continue;const c=n[a],h=s[a];let d=1;for(const t of this.availableZ){const e=i.get(t)??[],n=c.get(t)??[];for(const t of e)for(const e of n)d=Math.min(d,wt(t[0],t[1],e[0],e[1])-this.traceWidth);for(const t of r)for(const e of n)d=Math.min(d,vt(t,e[0],e[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of h)for(const n of e)d=Math.min(d,vt(t,n[0],n[1])-this.traceWidth/2-this.viaDiameter/2);for(const t of r)for(const e of h)d=Math.min(d,St(t,e)-this.viaDiameter)}e.push(d)}}return e}insertCandidate(t){let e=0,n=this.candidates.length-1;for(;e<=n;){const s=Math.floor((e+n)/2);this.candidates[s].f<t.f?e=s+1:n=s-1}this.candidates.splice(e,0,t)}setupInitialPolyLines(){const t=new Map;this.nodeWithPortPoints.portPoints.forEach(e=>{t.has(e.connectionName)?t.get(e.connectionName).end={...e,z1:e.z??0,z2:e.z??0}:t.set(e.connectionName,{start:{...e,z1:e.z??0,z2:e.z??0},end:null})});for(const[e,n]of t.entries())null===n.end&&t.delete(e);if(0===t.size)return this.failed=!0,void(this.error="No port pairs found, can't solve");const e=Array.from(t.entries()),n=((t,e,n,s)=>{const o=[];for(const[,n]of t){const t=n.start.z1!==n.end.z1,s=[];for(let n=0;n<=e;n++){const e=n%2!=0;t&&e?s.push(n):t||e||s.push(n)}o.push(s)}if(0===o.length)return[[]];let i=(t=>{if(!t||0===t.length)return[[]];let e=[[]];for(const n of t){const t=[];for(const s of e)for(const e of n)t.push([...s,e]);e=t}return e})(o).filter(t=>{for(let e=0;e<t.length;e++)if(t.reduce((t,e)=>t+e,0)<s)return!1;return!0});return i=i.filter(e=>{for(let n=0;n<t.length;n++){const[,s]=t[n];if(s.start.z1!==s.start.z2&&0===e[n])return!1}return!0}),i=i.filter(e=>{for(let n=0;n<t.length;n++){const[,s]=t[n];if(t[n][1].start.z1===t[n][1].start.z2)for(let o=n+1;o<t.length;o++){if(t[o][1].start.z1!==t[o][1].start.z2)continue;const[,i]=t[o];if(s.start.z1===s.end.z1&&i.start.z1===i.end.z1&&s.start.z1===i.start.z1&>(s.start,s.end,i.start,i.end)&&e[n]+e[o]<2)return!1}}return!0}),i=i.filter(t=>!(t.reduce((t,e)=>t+e,0)>n)),i})(e,this.SEGMENTS_PER_POLYLINE,this.maxViaCount,this.minViaCount),s=(t=>{const{bounds:e,portPairsEntries:n,viaCountVariants:s}=t,{centroids:o}=ve(e,n.map(([t,e])=>e)),i=[];for(const t of s){const n=t.reduce((t,e)=>t+e,0);let s=o;if(o.length<n){s=[];const t=Math.ceil(Math.sqrt(n)),o=t;for(let n=0;n<t;n++)for(let i=0;i<o;i++)s.push({x:e.minX+(i+1)/(o+1)*(e.maxX-e.minX),y:e.minY+(n+1)/(t+1)*(e.maxY-e.minY)})}const r=Se(n,s.length);for(const e of r){const n=[];for(let t=0;t<e.length;t++)1===e[t]&&n.push(s[t]);i.push({viaPositions:n,viaCountVariant:t})}}return i})({portPairsEntries:e,viaCountVariants:n,bounds:this.bounds}),o=[];for(const{viaCountVariant:t,viaPositions:e}of s){const n=Pe(e);for(const e of n)o.push({viaCountVariant:t,viaPositions:e})}for(const{viaPositions:t,viaCountVariant:n}of o){const s=[];let o=0;for(let i=0;i<e.length;i++){const[r,a]=e[i],c=n[i],h=t.slice(o,o+c),d=be({start:a.start,end:a.end,segmentsPerPolyline:this.SEGMENTS_PER_POLYLINE,viaPositions:h,viaCount:c,availableZ:this.availableZ});o+=c,s.push({connectionName:r,start:a.start,end:a.end,mPoints:d})}if(Ee(s,this.bounds))continue;const i=this.computeMinGapBtwPolyLines(s),r=this.computeH({minGaps:i,forces:[]}),a={polyLines:s,g:0,h:r,f:r,viaCount:n.reduce((t,e)=>t+e,0),minGaps:i};if(this.checkIfSolved(a))return void(this.candidates=[a]);if(this.candidates.push(a),this.candidates.length>this.MAX_CANDIDATES)return}this.candidates.sort((t,e)=>t.f-e.f)}computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){let e=0;for(const n of t.forces??[])for(const t of n)for(const n of t.values())e+=n.fx*n.fx+n.fy*n.fy;return e}getNeighbors(t){const{polyLines:e}=t,n=e.length,s=.02,o=.008,i=1e-6,r=Array.from({length:n},(t,n)=>Array.from({length:e[n].mPoints.length},()=>new Map)),a=(t,n,s,o,i)=>{if(n>0&&n<e[t].mPoints.length+1){const e=n-1,a=r[t][e],c=a.get(s)||{fx:0,fy:0};a.set(s,{fx:c.fx+o,fy:c.fy+i})}};for(let t=0;t<n;t++)for(let o=t+1;o<n;o++){const n=e[t],r=e[o],c=[n.start,...n.mPoints,n.end],h=[r.start,...r.mPoints,r.end],d=[],l=[];for(let t=0;t<c.length-1;t++)d.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&&l.push({point:t,layers:[t.z1,t.z2],index:e})});const u=[],p=[];for(let t=0;t<h.length-1;t++)u.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&&p.push({point:t,layers:[t.z1,t.z2],index:e})});for(const e of d)for(const n of u)if(e.layer===n.layer){if(wt(e.p1,e.p2,n.p1,n.p2)<i)continue;const s={x:(e.p1.x+e.p2.x)/2,y:(e.p1.y+e.p2.y)/2},r={x:(n.p1.x+n.p2.x)/2,y:(n.p1.y+n.p2.y)/2},c=s.x-r.x,h=s.y-r.y,d=c*c+h*h;if(d>i){const s=Math.sqrt(d),r=(Math.exp(-6*s),`seg:${o}:${n.p1Idx}:${n.p2Idx}`),c=`seg:${t}:${e.p1Idx}:${e.p2Idx}`,h=(t,e,n,s,o,r,c)=>{const h=Ot(t,n.p1,n.p2),d=t.x-h.x,l=t.y-h.y,u=d*d+l*l;if(u<=i)return;const p=Math.sqrt(u),m=.02*Math.exp(-6*p),f=d/p*m,g=l/p*m;a(s,e,r,f,g),a(o,n.p1Idx,c,-f/2,-g/2),a(o,n.p2Idx,c,-f/2,-g/2)};h(e.p1,e.p1Idx,n,t,o,r,c),h(e.p2,e.p2Idx,n,t,o,r,c),h(n.p1,n.p1Idx,e,o,t,c,r),h(n.p2,n.p2Idx,e,o,t,c,r)}}for(const e of l)for(const n of u)if(e.layers.includes(n.layer)){const r=Ot(e.point,n.p1,n.p2),c=e.point.x-r.x,h=e.point.y-r.y,d=c*c+h*h;if(d>i){const r=Math.sqrt(d);let l=2,u=r;r<this.viaDiameter/2?(l*=4,u=Math.max(i,r)):u=Math.max(i,r-this.viaDiameter/2);const p=l*s*Math.exp(-6*u),m=c/r*p,f=h/r*p,g=`seg:${o}:${n.p1Idx}:${n.p2Idx}`;a(t,e.index,g,m,f);const y=`via:${t}:${e.index}`;a(o,n.p1Idx,y,-m/2,-f/2),a(o,n.p2Idx,y,-m/2,-f/2)}}for(const e of p)for(const n of d)if(e.layers.includes(n.layer)){const r=Ot(e.point,n.p1,n.p2),c=e.point.x-r.x,h=e.point.y-r.y,d=c*c+h*h;if(d>i){const r=Math.sqrt(d);let l=2,u=r;r<this.viaDiameter/2?(l*=4,u=Math.max(i,r)):u=Math.max(i,r-this.viaDiameter/2);const p=l*s*Math.exp(-6*u),m=c/r*p,f=h/r*p,g=`seg:${t}:${n.p1Idx}:${n.p2Idx}`;a(o,e.index,g,m,f);const y=`via:${o}:${e.index}`;a(t,n.p1Idx,y,-m/2,-f/2),a(t,n.p2Idx,y,-m/2,-f/2)}}for(const e of l)for(const n of p){if(e.layers.filter(t=>n.layers.includes(t)).length>0){const r=e.point.x-n.point.x,c=e.point.y-n.point.y,h=r*r+c*c;if(h>i){const d=Math.sqrt(h);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(i,d)):u=Math.max(i,d-this.viaDiameter);const p=l*s*Math.exp(-6*u),m=r/d*p,f=c/d*p,g=`via:${o}:${n.index}`,y=`via:${t}:${e.index}`;a(t,e.index,g,m,f),a(o,n.index,y,-m,-f)}}}}for(let t=0;t<n;t++){const n=e[t],o=[n.start,...n.mPoints,n.end],r=[];if(o.forEach((t,e)=>{t.z1!==t.z2&&r.push({point:t,layers:[t.z1,t.z2],index:e})}),!(r.length<2))for(let e=0;e<r.length;e++)for(let n=e+1;n<r.length;n++){const o=r[e],c=r[n],h=o.point.x-c.point.x,d=o.point.y-c.point.y,l=h*h+d*d;if(l>i){const e=Math.sqrt(l);let n=2,r=e;e<this.viaDiameter?(n*=4,r=Math.max(i,e)):r=Math.max(i,e-this.viaDiameter);const u=n*s*Math.exp(-6*r),p=h/e*u,m=d/e*u,f=`via:${t}:${c.index}`,g=`via:${t}:${o.index}`;a(t,o.index,f,p,m),a(t,c.index,g,-p,-m)}}}const c=e.map(t=>({...t,mPoints:t.mPoints.map(t=>({...t}))}));let h=!1;for(let t=0;t<n;t++)for(let e=0;e<c[t].mPoints.length;e++){const n=c[t].mPoints[e],s=r[t][e],a={fx:0,fy:0};for(const t of s.values())a.fx+=t.fx,a.fy+=t.fy;const d=n.z1!==n.z2;let l=n.x+a.fx,u=n.y+a.fy;if(d){const t=this.viaDiameter/2;let e=0,s=0;const i=this.viaDiameter/2+this.BOUNDARY_PADDING,r=this.bounds.minX+i,c=this.bounds.maxX-i,h=this.bounds.minY+i,d=this.bounds.maxY-i,p=r+t-n.x,m=n.x-(c-t),f=h+t-n.y,g=n.y-(d-t);p>0?e=o*(Math.exp(p/(2*this.obstacleMargin))-1):m>0&&(e=-.008*(Math.exp(m/(2*this.obstacleMargin))-1)),f>0?s=o*(Math.exp(f/(2*this.obstacleMargin))-1):g>0&&(s=-.008*(Math.exp(g/(2*this.obstacleMargin))-1)),a.fx+=e,a.fy+=s,l=n.x+a.fx,u=n.y+a.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(a.fx)<i&&Math.abs(a.fy)<i||(Math.abs(n.x-l)>i||Math.abs(n.y-u)>i)&&(n.x=l,n.y=u,h=!0)}if(!h)return[];const d=this.computeMinGapBtwPolyLines(c),l=this.computeG(c,t),u=this.computeH({minGaps:d,forces:r});return[{polyLines:c,g:l,h:u,f:Math.round(5*l)/5+u,minGaps:d,forces:r,viaCount:t.viaCount}]}checkIfSolved(t){const e=t.minGaps.every(t=>t>=this.obstacleMargin),n=t.polyLines.every(t=>t.mPoints.every(t=>{const e=(t.z1!==t.z2?this.viaDiameter/2:this.traceWidth/2)+this.BOUNDARY_PADDING;return((t,e,n=0)=>t.x>=e.minX+n&&t.x<=e.maxX-n&&t.y>=e.minY+n&&t.y<=e.maxY-n)(t,this.bounds,e)}));return e&&n}tryFinalAcceptance(){const t=this.hyperParameters?.MINIMUM_FINAL_ACCEPTANCE_GAP??void 0;if(void 0===t||null===this.lastCandidate||0===this.lastCandidate.minGaps.length)return;return Math.min(...this.lastCandidate.minGaps)>=t?(this.solved=!0,void this._setSolvedRoutes()):void 0}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return this.failed=!0,void(this.error="No candidates left")}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();if(!t)return void(this.failed=!0);const e=this.getNeighbors(t);for(const t of e)this.insertCandidate(t)}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"MultiHeadPolyLineIntraNodeSolver Visualization"};t.lines.push({points:[{x:this.bounds.minX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.minY},{x:this.bounds.maxX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.maxY},{x:this.bounds.minX,y:this.bounds.minY}],strokeColor:"gray"});const e=this.lastCandidate??this.candidates[0];if(e?.hasClosedSameLayerFace){const e=.1*(this.bounds.maxX-this.bounds.minX),n=.1*(this.bounds.maxY-this.bounds.minY);t.rects.push({center:{x:this.bounds.maxX+.6*e,y:this.bounds.maxY+.6*n},width:e,height:n,fill:"red",label:"HAS CLOSED FACE"})}for(const e of this.nodeWithPortPoints.portPoints)t.points.push({x:e.x,y:e.y,label:`${e.connectionName} (Port z=${e.z??0})`,color:this.colorMap[e.connectionName]??"blue"});return e&&e.polyLines.forEach((n,s)=>{const o=this.colorMap[n.connectionName]??"purple",i=[n.start,...n.mPoints,n.end];for(let e=0;e<i.length-1;e++){const s=i[e],r=i[e+1],a=s.z2,c=0===a,h=c?o:it(o,.5);t.lines.push({points:[s,r],strokeColor:h,strokeWidth:this.traceWidth,strokeDash:c?void 0:[.15,.15],label:`${n.connectionName} segment (z=${a})`})}i.forEach((r,a)=>{const c=r.z1!==r.z2,h=r.z1,d=a>0&&a<i.length-1;let l="",u="";if(d){const o=a-1,i=e.forces?.[s]?.[o];if(i&&i.size>0){const s={fx:0,fy:0};i.forEach((i,a)=>{if(s.fx+=i.fx,s.fy+=i.fy,Math.abs(i.fx)>1e-6||Math.abs(i.fy)>1e-6){const s=a.split(":"),c=s[0],h=parseInt(s[1],10),d=e.polyLines[h],l=this.colorMap[d.connectionName]??"gray",u=20,p={x:r.x+i.fx*u,y:r.y+i.fy*u};let m=d.connectionName;if("via"===c){m+=` Via ${parseInt(s[2],10)}`}else if("seg"===c){m+=` Seg ${parseInt(s[2],10)}-${parseInt(s[3],10)}`}t.lines.push({points:[r,p],strokeColor:l,strokeWidth:.02,strokeDash:"2,2",label:`Force by ${m} on ${n.connectionName} mPoint ${o}`})}}),(Math.abs(s.fx)>1e-6||Math.abs(s.fy)>1e-6)&&(u=`\nNet Force: (${s.fx.toFixed(3)}, ${s.fy.toFixed(3)})`)}}if(c)l=`Via (${n.connectionName} z=${r.z1} -> z=${r.z2})${u}`,t.circles.push({center:r,radius:this.viaDiameter/2,fill:it(o,.5),label:l});else if(d){const e=0===h?o:it(o,.5);l=`mPoint (${n.connectionName} z=${h})${u}`,t.circles.push({center:r,radius:this.cellSize/8,fill:e,label:l})}})}),t}_setSolvedRoutes(){if(!this.solved||!this.lastCandidate)return[];const t=[];for(const e of this.lastCandidate.polyLines){const n=[],s=[],o=[e.start,...e.mPoints,e.end];for(let t=0;t<o.length;t++){const e=o[t];n.push({x:e.x,y:e.y,z:e.z1}),e.z1!==e.z2&&(s.push({x:e.x,y:e.y}),n.push({x:e.x,y:e.y,z:e.z2}))}t.push({connectionName:e.connectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:n,vias:s})}this.solvedRoutes=t}},we=class extends Re{computeG(t,e){return e.g+5e-6+5e-6*e.viaCount*100}computeH(t){const{minGaps:e}=t;let n=0;for(const t of e)t<0&&(n+=this.obstacleMargin),t<this.obstacleMargin&&(n+=this.obstacleMargin-t);return.011*n}_step(){if("setup"===this.phase)return this.setupInitialPolyLines(),void(this.phase="solving");const t=this.candidates.shift();if(!t){if(this.tryFinalAcceptance(),this.solved)return;return void(this.failed=!0)}if(this.lastCandidate=t,this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();let e=!1,n=0;const s=void 0===t.magForceApplied?1:10;for(let o=0;o<s;o++){const s=this.applyForcesToPolyLines(t.polyLines);if(n+=s.magForceApplied,e=s.lastStepMoved,!s.lastStepMoved)break}if(t.magForceApplied=n,t.minGaps=this.computeMinGapBtwPolyLines(t.polyLines),this.checkIfSolved(t))return this.solved=!0,void this._setSolvedRoutes();t.g=this.computeG(t.polyLines,t),t.h=this.computeH(t),t.f=t.g+t.h,e&&this.insertCandidate(t)}applyForcesToPolyLines(t){let e=0;const n=t.length,s=.02,o=.008,i=1e-6,r=Array.from({length:n},(e,n)=>Array.from({length:t[n].mPoints.length},()=>({fx:0,fy:0}))),a=(e,n,s,o)=>{if(n>0&&n<t[e].mPoints.length+1){const t=n-1;r[e][t].fx+=s,r[e][t].fy+=o}},c=(t,e,n,s,o)=>{const r=Ot(t,n.p1,n.p2),c=t.x-r.x,h=t.y-r.y,d=c*c+h*h;if(d<=i)return;const l=Math.sqrt(d),u=.02*Math.exp(-6*l),p=c/l*u,m=h/l*u;a(s,e,p,m),a(o,n.p1Idx,-p/2,-m/2),a(o,n.p2Idx,-p/2,-m/2)};for(let e=0;e<n;e++)for(let o=e+1;o<n;o++){const n=t[e],r=t[o],h=[n.start,...n.mPoints,n.end],d=[r.start,...r.mPoints,r.end],l=[],u=[];for(let t=0;t<h.length-1;t++)l.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&&u.push({point:t,layers:[t.z1,t.z2],index:e})});const p=[],m=[];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&&m.push({point:t,layers:[t.z1,t.z2],index:e})});for(const t of l)for(const n of p)if(t.layer===n.layer){wt(t.p1,t.p2,n.p1,n.p2);c(t.p1,t.p1Idx,n,e,o),c(t.p2,t.p2Idx,n,e,o),c(n.p1,n.p1Idx,t,o,e),c(n.p2,n.p2Idx,t,o,e)}for(const t of u)for(const n of p)if(t.layers.includes(n.layer)){const r=Ot(t.point,n.p1,n.p2),c=t.point.x-r.x,h=t.point.y-r.y,d=c*c+h*h;if(d>i){const r=Math.sqrt(d);let l=2,u=r;r<this.viaDiameter/2?(l*=4,u=Math.max(i,r)):u=Math.max(i,r-this.viaDiameter/2);const p=l*s*Math.exp(-6*u),m=c/r*p,f=h/r*p;a(e,t.index,m,f),a(o,n.p1Idx,-m/2,-f/2),a(o,n.p2Idx,-m/2,-f/2)}}for(const t of m)for(const n of l)if(t.layers.includes(n.layer)){const r=Ot(t.point,n.p1,n.p2),c=t.point.x-r.x,h=t.point.y-r.y,d=c*c+h*h;if(d>i){const r=Math.sqrt(d);let l=2,u=r;r<this.viaDiameter/2?(l*=4,u=Math.max(i,r)):u=Math.max(i,r-this.viaDiameter/2);const p=l*s*Math.exp(-6*u),m=c/r*p,f=h/r*p;a(o,t.index,m,f),a(e,n.p1Idx,-m/2,-f/2),a(e,n.p2Idx,-m/2,-f/2)}}for(const t of u)for(const n of m){if(t.layers.filter(t=>n.layers.includes(t)).length>0){const r=t.point.x-n.point.x,c=t.point.y-n.point.y,h=r*r+c*c;if(h>i){const d=Math.sqrt(h);let l=2,u=d;d<this.viaDiameter?(l*=4,u=Math.max(i,d)):u=Math.max(i,d-this.viaDiameter);const p=l*s*Math.exp(-6*u),m=r/d*p,f=c/d*p;a(e,t.index,m,f),a(o,n.index,-m,-f)}}}}for(let e=0;e<n;e++){const n=t[e],o=[n.start,...n.mPoints,n.end],r=[];if(o.forEach((t,e)=>{t.z1!==t.z2&&r.push({point:t,layers:[t.z1,t.z2],index:e})}),!(r.length<2))for(let t=0;t<r.length;t++)for(let n=t+1;n<r.length;n++){const o=r[t],c=r[n],h=o.point.x-c.point.x,d=o.point.y-c.point.y,l=h*h+d*d;if(l>i){const t=Math.sqrt(l);let n=2,r=t;t<this.viaDiameter?(n*=4,r=Math.max(i,t)):r=Math.max(i,t-this.viaDiameter);const u=n*s*Math.exp(-6*r),p=h/t*u,m=d/t*u;a(e,o.index,p,m),a(e,c.index,-p,-m)}}}let h=!1;for(let s=0;s<n;s++)for(let n=0;n<t[s].mPoints.length;n++){const a=t[s].mPoints[n],c=r[s][n],d=a.z1!==a.z2;let l=c.fx,u=c.fy,p=a.x+l,m=a.y+u;if(d){const t=this.viaDiameter/2;let e=0,n=0;const s=this.viaDiameter/2+this.BOUNDARY_PADDING,i=this.bounds.minX+s,r=this.bounds.maxX-s,c=this.bounds.minY+s,h=this.bounds.maxY-s,d=i+t-a.x,f=a.x-(r-t),g=c+t-a.y,y=a.y-(h-t);d>0?e=o*(Math.exp(d/(2*this.obstacleMargin))-1):f>0&&(e=-.008*(Math.exp(f/(2*this.obstacleMargin))-1)),g>0?n=o*(Math.exp(g/(2*this.obstacleMargin))-1):y>0&&(n=-.008*(Math.exp(y/(2*this.obstacleMargin))-1)),l+=e,u+=n,p=a.x+l,m=a.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)),m=Math.max(this.bounds.minY+t,Math.min(this.bounds.maxY-t,m))}if(Math.abs(l)<i&&Math.abs(u)<i)continue;e+=Math.sqrt(l*l+u*u),(Math.abs(a.x-p)>i||Math.abs(a.y-m)>i)&&(a.x=p,a.y=m,h=!0)}return{lastStepMoved:h,magForceApplied:e}}},Ae=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 Oe=class extends we{constructor(t){super(t),this.MAX_ITERATIONS=1e3}createInitialCandidateFromSeed(t){const e=new ce({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,hyperParameters:{SHUFFLE_SEED:t},viaDiameter:this.viaDiameter});if(e.solve(),e.failed||!e.solved)return this.failed=!0,this.error=`ViaPossibilitiesSolver2 failed with: ${e.error}`,null;const n=[];let s=0;for(const[t,o]of e.completedPaths.entries()){if(o.length<2){console.warn(`Skipping connection "${t}" due to insufficient points (${o.length}) in ViaPossibilitiesSolver2 path.`);continue}const e=o[0],i=o[o.length-1],r=o.slice(1,-1),a=[];let c=0,h=e.z;for(let t=0;t<r.length;t++){const e=r[t],n=t+1<r.length?r[t+1]:i,s=h,o=t+1<r.length&&e.x===n.x&&e.y===n.y&&e.z!==n.z?n.z:e.z;a.push({x:e.x,y:e.y,z1:s,z2:o}),s!==o?(c++,t++,h=o):h=e.z}s+=c;const d=this.SEGMENTS_PER_POLYLINE;let l=a.length+1;for(;l<d;){let n=-1,s=-1,o=null,r=null;const c=[{...e,z1:e.z,z2:e.z,connectionName:t},...a,{...i,z1:i.z,z2:i.z,connectionName:t}];for(let t=0;t<c.length-1;t++){const e=c[t],i=c[t+1];if(e.x===i.x&&e.y===i.y)continue;const a=St(e,i);a>n&&(n=a,s=t,o=e,r=i)}if(-1===s||!o||!r){console.warn(`Could not find longest segment for ${t} while trying to reach ${d} segments.`);break}const h=(o.x+r.x)/2,u=(o.y+r.y)/2,p=o.z2,m={x:h,y:u,z1:p,z2:p};a.splice(s,0,m),l++}n.push({connectionName:t,start:{...e,z1:e.z,z2:e.z},end:{...i,z1:i.z,z2:i.z},mPoints:a})}if(0===n.length)return this.failed=!0,this.error="No valid polylines generated from ViaPossibilitiesSolver2.",console.error(this.error),null;const o=this.computeMinGapBtwPolyLines(n),i=this.computeH({minGaps:o,forces:[]}),r={polyLines:n,g:0,h:i,f:0+i,viaCount:s,minGaps:o};return r.g=this.computeG(n,r),r.f=r.g+r.h,r}setupInitialPolyLines(){this.candidates=[];const t=Math.min(2e3,function(t){if(!Number.isInteger(t)||t<0)throw new RangeError("n must be a non-negative integer");let e=1;for(let n=2;n<=t;n++)e*=n;return e}(this.uniqueConnections)),e=new Set;for(let n=0;n<t;n++){const t=this.createInitialCandidateFromSeed(n);if(!t)continue;const s=Ae(t.polyLines);e.has(s)||(e.add(s),this.candidates.push(t))}this.candidates.sort((t,e)=>t.f-e.f)}},ze=class extends Zt{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"],["closedFormSingleTrace"],["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:"closedFormSingleTrace",possibleValues:[{CLOSED_FORM_SINGLE_TRANSITION:!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 Jt({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING?new ie({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.CLOSED_FORM_SINGLE_TRANSITION?new re({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.MULTI_HEAD_POLYLINE_SOLVER?new Oe({nodeWithPortPoints:this.nodeWithPortPoints,connMap:this.connMap,hyperParameters:t,viaDiameter:this.constructorParams.viaDiameter}):new Vt({...this.constructorParams,hyperParameters:t})}onSolve(t){this.solvedRoutes=t.solver.solvedRoutes.map(t=>{const e=this.nodeWithPortPoints.portPoints.find(e=>e.connectionName===t.connectionName);return e?.rootConnectionName?{...t,rootConnectionName:e.rootConnectionName}:t})}};function De(t,e,n){const s=[];let o=null;for(let i=0;i<t.length;i++){const r=t[i];o?o.z===r.z?o.points.push({x:r.x,y:r.y}):(s.push(o),o={points:[{x:r.x,y:r.y}],z:r.z,connectionName:e,color:n}):o={points:[{x:r.x,y:r.y}],z:r.z,connectionName:e,color:n},i===t.length-1&&o&&s.push(o)}return s}var Le=class extends y{unsolvedNodePortPoints;routes;colorMap;defaultViaDiameter=.6;defaultTraceThickness=.15;viaDiameter;traceWidth;failedSolvers;activeSubSolver=null;connMap;constructor({nodePortPoints:t,colorMap:e,connMap:n,viaDiameter:s,traceWidth:o}){super(),this.unsolvedNodePortPoints=t,this.colorMap=e??{},this.connMap=n,this.routes=[],this.failedSolvers=[],this.MAX_ITERATIONS=1e6,this.viaDiameter=s??this.defaultViaDiameter,this.traceWidth=o??this.defaultTraceThickness}_step(){if(this.updateCacheStats(),this.activeSubSolver)return this.activeSubSolver.step(),this.activeSubSolver.solved?(this.routes.push(...this.activeSubSolver.solvedRoutes),this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSolvers.push(this.activeSubSolver),this.activeSubSolver=null),void this.updateCacheStats();if(0===this.unsolvedNodePortPoints.length)return this.failedSolvers.length>0?(this.solved=!1,this.failed=!0,this.error=`Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0,5).map(t=>t.nodeWithPortPoints.capacityMeshNodeId)}. err0: ${this.failedSolvers[0].error}.`,void this.updateCacheStats()):(this.solved=!0,void this.updateCacheStats());const t=this.unsolvedNodePortPoints.pop();this.activeSubSolver=new ze({nodeWithPortPoints:t,colorMap:this.colorMap,connMap:this.connMap,viaDiameter:this.viaDiameter,traceWidth:this.traceWidth}),this.updateCacheStats()}updateCacheStats(){const t=ut();this.stats.intraNodeCacheHits=t.cacheHits,this.stats.intraNodeCacheMisses=t.cacheMisses}visualize(){let t={lines:[],points:[],rects:[],circles:[]};for(const e of this.routes){const n=De(e.route,e.connectionName,this.colorMap[e.connectionName]);for(const s of n)t.lines.push({points:s.points,label:s.connectionName,strokeColor:0===s.z?s.color:it(s.color,.75),layer:`z${s.z}`,strokeWidth:e.traceThickness,strokeDash:0!==s.z?"10, 5":void 0});for(const n of e.vias)t.circles.push({center:n,layer:"z0,1",radius:e.viaDiameter/2,fill:this.colorMap[e.connectionName],label:`${e.connectionName} via`})}for(const e of this.failedSolvers){const n=e.nodeWithPortPoints,s=.1*n.width,o=.1*n.height;t.rects.push({center:{x:n.center.x-s/2,y:n.center.y-o/2},layer:"did_not_connect",width:s,height:o,fill:"red",label:`Failed: ${n.capacityMeshNodeId}`});const i={};for(const t of n.portPoints)i[t.connectionName]||(i[t.connectionName]=[]),i[t.connectionName].push({x:t.x,y:t.y,z:t.z});for(const[e,n]of Object.entries(i))for(let e=0;e<n.length-1;e++){const s=n[e],o=n[e+1];t.lines.push({points:[s,o],strokeColor:"red",strokeDash:"10, 5",layer:"did_not_connect"})}}return this.activeSubSolver&&(t=g(t,this.activeSubSolver.visualize())),t}},Fe=class{netMap;idToNetMap;constructor(t){this.netMap=t,this.idToNetMap={};for(const[e,n]of Object.entries(t))for(const t of n)this.idToNetMap[t]=e}addConnections(t){for(const e of t){const t=new Set;for(const n of e){const e=this.idToNetMap[n];e&&t.add(e)}let n;if(0===t.size)n=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[n]=[];else if(1===t.size)n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(const e of t)if(e!==n){this.netMap[n].push(...this.netMap[e]),this.netMap[e]=this.netMap[n];for(const t of this.netMap[n])this.idToNetMap[t]=n}}for(const t of e)this.netMap[n].includes(t)||this.netMap[n].push(t),this.idToNetMap[t]=n}}getIdsConnectedToNet(t){return this.netMap[t]||[]}getNetConnectedToId(t){return this.idToNetMap[t]}areIdsConnected(t,e){if(t===e)return!0;const n=this.getNetConnectedToId(t);if(!n)return!1;const s=this.getNetConnectedToId(e);return!!s&&(n===s||s===t||s===t)}areAllIdsConnected(t){const e=this.getNetConnectedToId(t[0]);for(const n of t){const t=this.getNetConnectedToId(n);if(void 0===t)return!1;if(t!==e)return!1}return!0}},Xe=(t,e)=>"top"===t?0:"bottom"===t?e-1:parseInt(t.slice(5)),Ye=t=>`${Math.round(100*t.x)},${Math.round(100*t.y)}`,$e=t=>{const e=new Fe({});for(const n of t.connections){if(n.rootConnectionName&&e.addConnections([[n.name,n.rootConnectionName]]),n.netConnectionName&&e.addConnections([[n.name,n.netConnectionName]]),n.mergedConnectionNames)for(const t of n.mergedConnectionNames)e.addConnections([[n.name,t]]);for(const s of n.pointsToConnect)e.addConnections([[n.name,`${Ye(s)}:${"layers"in s?s.layers.map(e=>Xe(e,t.layerCount)).sort().join("-"):Xe(s.layer,t.layerCount)}`]]),"pcb_port_id"in s&&s.pcb_port_id&&e.addConnections([[n.name,s.pcb_port_id]])}for(const n of t.obstacles){const s=n.offBoardConnectsTo??[],o=Array.from(new Set([n.obstacleId,...n.connectedTo,...s,`${Ye(n.center)}:${n.layers.map(e=>Xe(e,t.layerCount)).sort().join("-")}`].filter(Boolean)));o.length>0&&e.addConnections([o])}return e},ke=(t,e=1,n={})=>{const s=n.viaDiameter??.6,o=n.obstacleMargin??.2,i=(("width"in t?t.width:t)/(s/2+o)/2)**1.1*e;return 1===t.availableZ?.length&&i>1?1:i},Be=(t,e=.5,n=16)=>{let s=0,o=t;for(;s<n;){if(ke({width:o})<=e)break;o/=2,s++}return Math.max(1,s)},je=(t,e)=>{if(1===t&&1===e)return"inner1";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}`},We=(t,e)=>{const n=[];if(0===t.route.length)return n;let s=[],o=t.route[0].z;for(let i=0;i<t.route.length;i++){const r=t.route[i];if(r.z!==o){const i=je(o,e);for(const e of s)n.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:i});if(t.vias.some(t=>Math.abs(t.x-r.x)<.001&&Math.abs(t.y-r.y)<.001)){const t=je(o,e),s=je(r.z,e);n.push({route_type:"via",x:r.x,y:r.y,from_layer:t,to_layer:s})}s=[r],o=r.z}else s.push(r)}const i=je(o,e);for(const e of s)n.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:i});if(t.jumpers&&t.jumpers.length>0){const s=je(t.route[0]?.z??0,e);for(const e of t.jumpers)n.push({route_type:"jumper",start:e.start,end:e.end,footprint:e.footprint,layer:s})}return n};function He(t){return"layers"in t&&Array.isArray(t.layers)}function Ue(t){return He(t)?t.layers[0]:t.layer}function Ve(t){return He(t)?t.layers:[t.layer]}var Ze={"0603":{length:1.65,width:.95,padLength:.8,padWidth:.95},1206:{length:3.2,width:1.6,padLength:.6,padWidth:1.6},"1206x4_pair":{length:2.7,width:.5,padLength:.8,padWidth:.5}};function Ge(t,e={}){const n=[],s=[],o=e.color??"gray",i=e.label,r=Ze[t.footprint]??Ze["0603"],a=t.end.x-t.start.x,c=t.end.y-t.start.y,h=Math.abs(a)>Math.abs(c),d=h?r.padLength:r.padWidth,l=h?r.padWidth:r.padLength;return n.push({center:t.start,width:d,height:l,fill:it(o,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper",label:i?`${i} (start)`:void 0}),n.push({center:t.end,width:d,height:l,fill:it(o,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper",label:i?`${i} (end)`:void 0}),s.push({points:[t.start,t.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*r.padWidth,layer:"jumper-body"}),{rects:n,lines:s}}function Je(t,e={}){const n={rects:[],lines:[]};for(const s of t){const{rects:t,lines:o}=Ge(s,e);n.rects.push(...t),n.lines.push(...o)}return n}var qe=1e5,Ke=.001,Qe=class extends y{mergedHdRoute;remainingHdRoutes;start;end;colorMap;constructor(t){if(super(),this.remainingHdRoutes=[...t.hdRoutes],this.colorMap=t.colorMap??{},0===t.hdRoutes.length){this.start=t.start,this.end=t.end;const e=[{x:t.start.x,y:t.start.y,z:t.start.z}],n=[];return t.start.z!==t.end.z&&(e.push({x:t.start.x,y:t.start.y,z:t.end.z}),n.push({x:t.start.x,y:t.start.y})),e.push({x:t.end.x,y:t.end.y,z:t.end.z}),this.mergedHdRoute={connectionName:t.connectionName,rootConnectionName:t.hdRoutes[0]?.rootConnectionName,route:e,vias:n,jumpers:[],viaDiameter:t.defaultViaDiameter??.6,traceThickness:t.defaultTraceThickness??.15},void(this.solved=!0)}let e=1/0,n=t.hdRoutes[0],s="start-to-end";for(const o of t.hdRoutes){const i=o.route[0],r=o.route[o.route.length-1],a=St(t.start,i),c=St(t.start,r),h=St(t.end,i),d=St(t.end,r),l=Math.min(a,c,h,d);l<e&&(e=l,n=o,s=Math.min(h,d)<Math.min(a,c)?"end-to-start":"start-to-end")}"start-to-end"===s?(this.start=t.start,this.end=t.end):(this.start=t.end,this.end=t.start);const o=n.route[0],i=n.route[n.route.length-1],r=St(this.start,o)<=St(this.start,i)?o:i;this.mergedHdRoute={connectionName:t.connectionName,rootConnectionName:n.rootConnectionName,route:[{x:this.start.x,y:this.start.y,z:r.z}],vias:[],jumpers:[],viaDiameter:n.viaDiameter,traceThickness:n.traceThickness}}getDisjointedRoute(){for(const t of this.remainingHdRoutes){if([t.route[0],t.route[t.route.length-1]].some(e=>!this.remainingHdRoutes.some(n=>{if(n===t)return!1;return[n.route[0],n.route[n.route.length-1]].some(t=>t.z===e.z&&St(e,t)<.001)})))return{firstRoute:t}}return{firstRoute:this.remainingHdRoutes[0]}}_step(){if(0===this.remainingHdRoutes.length){const t=this.mergedHdRoute.route[this.mergedHdRoute.route.length-1];return this.mergedHdRoute.route.push({x:this.end.x,y:this.end.y,z:t.z}),void(this.solved=!0)}const t=this.mergedHdRoute.route[this.mergedHdRoute.route.length-1];let e=-1,n="first",s=1/0;for(let o=0;o<this.remainingHdRoutes.length;o++){const i=this.remainingHdRoutes[o],r=i.route[0],a=i.route[i.route.length-1],c=St(t,r),h=St(t,a);let d=1/0;d=t.z===r.z?c<Ke?c:qe+c:c<Ke?1e3+c:qe+c,d<s&&(s=d,e=o,n="first");let l=1/0;l=t.z===a.z?h<Ke?h:qe+h:h<Ke?1e3+h:qe+h,l<s&&(s=l,e=o,n="last")}if(-1===e)return void(this.remainingHdRoutes=[]);const o=this.remainingHdRoutes[e];let i;this.remainingHdRoutes.splice(e,1),i="first"===n?o.route:[...o.route].reverse(),i.length>0&&St(t,i[0])<Ke&&t.z===i[0].z?this.mergedHdRoute.route.push(...i.slice(1)):this.mergedHdRoute.route.push(...i),this.mergedHdRoute.vias.push(...o.vias),o.jumpers&&this.mergedHdRoute.jumpers.push(...o.jumpers)}visualize(){const t={points:[],lines:[],circles:[],rects:[],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"});if(this.mergedHdRoute.jumpers&&this.mergedHdRoute.jumpers.length>0){const e=Je(this.mergedHdRoute.jumpers,{color:"green",label:this.mergedHdRoute.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}for(const[e,n]of this.remainingHdRoutes.entries()){const s=this.colorMap[n.connectionName]??"gray";n.route.length>1&&t.lines?.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:s});for(let o=0;o<n.route.length;o++){const i=n.route[o];t.points?.push({x:i.x+(e%2-.5)/500+(o%8-4)/1e3,y:i.y+(e%2-.5)/500+(o%8-4)/1e3,color:s,label:`Route ${n.connectionName} ${i===n.route[0]?"First":i===n.route[n.route.length-1]?"Last":""}`})}for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s});if(n.jumpers&&n.jumpers.length>0){const e=Je(n.jumpers,{color:s,label:n.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}return t}},tn=class{netMap;idToNetMap;constructor(t){this.netMap=t,this.idToNetMap={};for(const[e,n]of Object.entries(t))for(const t of n)this.idToNetMap[t]=e}addConnections(t){for(const e of t){const t=new Set;for(const n of e){const e=this.idToNetMap[n];e&&t.add(e)}let n;if(0===t.size)n=`connectivity_net${Object.keys(this.netMap).length}`,this.netMap[n]=[];else if(1===t.size)n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;else{n=t.values().next().value??`connectivity_net${Object.keys(this.netMap).length}`;for(const e of t)if(e!==n){const t=this.netMap[n],s=this.netMap[e];if(t&&s){t.push(...s),this.netMap[e]=t;for(const e of t)this.idToNetMap[e]=n}}}for(const t of e){const e=this.netMap[n];e&&!e.includes(t)&&e.push(t),this.idToNetMap[t]=n}}}getIdsConnectedToNet(t){return this.netMap[t]||[]}getNetConnectedToId(t){return this.idToNetMap[t]}areIdsConnected(t,e){if(t===e)return!0;const n=this.getNetConnectedToId(t);if(!n)return!1;const s=this.getNetConnectedToId(e);return!!s&&(n===s||s===t||s===t)}areAllIdsConnected(t){if(0===t.length)return!0;const e=this.getNetConnectedToId(t[0]);if(!e)return!1;for(const n of t){const t=this.getNetConnectedToId(n);if(void 0===t)return!1;if(t!==e)return!1}return!0}},en=t=>`${Math.round(100*t.x)},${Math.round(100*t.y)},${Math.round(100*t.z)}`,nn=class extends y{unsolvedRoutes;activeSolver=null;mergedHdRoutes=[];colorMap={};defaultTraceThickness;defaultViaDiameter;constructor(t){super(),this.colorMap=t.colorMap??{};const e=t.hdRoutes[0];this.defaultTraceThickness=e?.traceThickness??.15,this.defaultViaDiameter=e?.viaDiameter??t.defaultViaDiameter??.6;const n=new tn({}),s=[],o=new Map;for(let e=0;e<t.hdRoutes.length;e++){const n=t.hdRoutes[e],o=n.route[0],i=n.route[n.route.length-1];s.push([`route_island_${e}`,`${n.connectionName}:${en(o)}`,`${n.connectionName}:${en(i)}`])}n.addConnections(s);for(const t of s)for(const e of t.slice(1))o.set(e,(o.get(e)??0)+1);this.unsolvedRoutes=[];const i=Array.from(new Set(Object.values(n.idToNetMap)));for(const e of i){const s=n.getIdsConnectedToNet(e),i=t.hdRoutes.filter((t,e)=>s.includes(`route_island_${e}`));if(0===i.length)continue;const r=t.connections.find(t=>t.name===i[0].connectionName),a=i.flatMap(t=>[t.route[0],t.route[t.route.length-1]]),c=[];for(const t of a){const e=`${i[0].connectionName}:${en(t)}`;1===o.get(e)&&c.push(t)}if(0===c.length){console.log("no possible endpoints, can't stitch");continue}let h,d;2!==c.length?(h={...r.pointsToConnect[0],z:Xe(Ue(r.pointsToConnect[0]),t.layerCount)},d={...r.pointsToConnect[1],z:Xe(Ue(r.pointsToConnect[1]),t.layerCount)}):(h=c[0],d=c[1],St(h,r.pointsToConnect[1])<St(d,r.pointsToConnect[0])&&([h,d]=[d,h])),this.unsolvedRoutes.push({connectionName:i[0].connectionName,hdRoutes:i,start:h,end:d})}this.MAX_ITERATIONS=1e5}_step(){if(this.activeSolver)return this.activeSolver.step(),void(this.activeSolver.solved?(this.activeSolver instanceof Qe&&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 Qe({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:[],rects:[],title:"Multiple High Density Route Stitch Solver"};if(this.activeSolver){const e=this.activeSolver.visualize();e.points?.length&&t.points?.push(...e.points),e.lines?.length&&t.lines?.push(...e.lines),e.circles?.length&&t.circles?.push(...e.circles),e.rects?.length&&(t.rects||(t.rects=[]),t.rects.push(...e.rects))}for(const[e,n]of this.mergedHdRoutes.entries()){const s=this.colorMap[n.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1],r=0!==o.z?it(s,.5):s;t.lines?.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:r,strokeWidth:n.traceThickness})}for(const e of n.route){const n=0!==e.z?it(s,.5):s;t.points?.push({x:e.x,y:e.y,color:n})}for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s});if(n.jumpers&&n.jumpers.length>0){const e=Je(n.jumpers,{color:s,label:n.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}for(const e of this.unsolvedRoutes){const n=this.colorMap[e.connectionName]??"gray";t.points?.push({x:e.start.x,y:e.start.y,color:n,label:`${e.connectionName} Start (z=${e.start.z})`},{x:e.end.x,y:e.end.y,color:n,label:`${e.connectionName} End (z=${e.end.z})`}),t.lines?.push({points:[{x:e.start.x,y:e.start.y},{x:e.end.x,y:e.end.y}],strokeColor:n,strokeDash:"2 2"});for(const s of e.hdRoutes){s.route.length>1&&t.lines?.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:it(n,.5),strokeDash:"10 5"});for(const e of s.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:s.viaDiameter/2,fill:n});if(s.jumpers&&s.jumpers.length>0){const e=Je(s.jumpers,{color:n,label:s.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}}return t}},sn=t=>{const e=[],n=[],s=[],o=[],i=ot(t),r=(t.minViaDiameter??.6)/2;if(t.connections)for(const e of t.connections)for(const t of e.pointsToConnect){const n=Ve(t);s.push({x:t.x,y:t.y,color:i[e.name],layer:n[0]??("z"in t?je(t.z,2):"top"),label:`${e.name} (${n.join(",")})`})}if(t.traces)for(const s of t.traces){let a=t.minTraceWidth;const c=s.route.filter(t=>"jumper"===t.route_type),h=(t,e)=>{const n=.01;for(const s of c){const o=Math.abs(t.x-s.start.x)<n&&Math.abs(t.y-s.start.y)<n&&Math.abs(e.x-s.end.x)<n&&Math.abs(e.y-s.end.y)<n,i=Math.abs(t.x-s.end.x)<n&&Math.abs(t.y-s.end.y)<n&&Math.abs(e.x-s.start.x)<n&&Math.abs(e.y-s.start.y)<n;if(o||i)return!0}return!1};for(let t=0;t<s.route.length-1;t++){const c=s.route[t],d=s.route[t+1];if("via"===c.route_type)n.push({center:{x:c.x,y:c.y},radius:r,fill:"blue",stroke:"none",layer:"z0,1"});else if("jumper"===c.route_type){const t=i[s.connection_name]??"rgba(255, 165, 0, 0.8)",n=c.footprint,r=Ze["1206x4_pair"===n?"1206x4_pair":"0603"]??Ze["0603"],a=c.end.x-c.start.x,h=c.end.y-c.start.y,d=Math.abs(a)>Math.abs(h),l=d?r.padLength:r.padWidth,u=d?r.padWidth:r.padLength;o.push({center:c.start,width:l,height:u,fill:it(t,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),o.push({center:c.end,width:l,height:u,fill:it(t,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),e.push({points:[c.start,c.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*r.padWidth,layer:"jumper-body"})}else if("wire"===c.route_type&&"wire"===d.route_type&&d.layer===c.layer){if(h({x:c.x,y:c.y},{x:d.x,y:d.y}))continue;a=c.width;const t=i[s.connection_name],n="top"===c.layer,o=t??{top:"red",bottom:"blue",inner1:"green",inner2:"yellow"}[c.layer];e.push({points:[{x:c.x,y:c.y},{x:d.x,y:d.y}],layer:`z${Xe(c.layer,2)}`,strokeWidth:a,strokeColor:n?o:it(o,.5),...n?{}:{strokeDash:"3 2"}})}}}for(const e of t.obstacles)o.push({center:e.center,width:e.width,height:e.height,fill:"rgba(255,0,0,0.5)",layer:`z${e.layers.map(t=>Xe(t,2)).join(",")}`});if(t.jumpers)for(const e of t.jumpers)for(const t of e.pads)o.push({center:t.center,width:t.width,height:t.height,fill:"rgba(255, 165, 0, 0.3)",stroke:"rgba(255, 165, 0, 0.8)",layer:"jumper"});return{rects:o,circles:n,lines:e,points:s}};function on(t,e){const n=t.center.x-t.width/2,s=t.center.x+t.width/2,o=t.center.y-t.height/2,i=t.center.y+t.height/2,r=e.center.x-e.width/2,a=e.center.x+e.width/2,c=e.center.y-e.height/2,h=e.center.y+e.height/2,d=.001,l=(Math.abs(s-r)<d||Math.abs(n-a)<d)&&Math.min(i,h)-Math.max(o,c)>=d,u=(Math.abs(i-c)<d||Math.abs(o-h)<d)&&Math.min(s,a)-Math.max(n,r)>=d;return l||u}var rn=class extends y{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)&&on(this.nodes[t],this.nodes[e])&&this.doNodesHaveSharedLayer(this.nodes[t],this.nodes[e])&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[this.nodes[t].capacityMeshNodeId,this.nodes[e].capacityMeshNodeId]})}this.handleTargetNodes(),this.solved=!0}handleTargetNodes(){const t=this.nodes.filter(t=>t._containsTarget);for(const e of t){if(this.edges.some(t=>t.nodeIds.includes(e.capacityMeshNodeId)))continue;let t=null,n=1/0;for(const s of this.nodes){if(s._containsObstacle)continue;if(s._containsTarget)continue;const o=St(e.center,s.center);o<n&&(n=o,t=s)}t&&this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[e.capacityMeshNodeId,t.capacityMeshNodeId]})}}doNodesHaveSharedLayer(t,e){return t.availableZ.some(t=>e.availableZ.includes(t))}visualize(){const t=new Map;for(const e of this.edges)for(const n of e.nodeIds)t.set(n,1+(t.get(n)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const n=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+n*e.width*.05,y:e.center.y-n*e.width*.05},fill:e._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}for(const t of this.edges){const n=this.nodeMap.get(t.nodeIds[0]),s=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&s?.center){const t=Math.min(...n.availableZ),o=Math.min(...s.availableZ),i={x:n.center.x+t*n.width*.05,y:n.center.y-t*n.width*.05},r={x:s.center.x+o*s.width*.05,y:s.center.y-o*s.width*.05},a=Array.from(new Set([...n.availableZ,...s.availableZ])).sort();e.lines.push({layer:`z${a.join(",")}`,points:[i,r],strokeDash:n.availableZ.join(",")===s.availableZ.join(",")?void 0:"10 5"})}}return e}},an=class{constructor(t){this.nodes=t,this.buckets=new Map;for(const e of t){const t=e.center.x-e.width/2,n=e.center.y-e.height/2,s=e.center.x+e.width/2,o=e.center.y+e.height/2;for(let i=t;i<=s;i+=this.CELL_SIZE)for(let t=n;t<=o;t+=this.CELL_SIZE){const n=this.getBucketKey(i,t),s=this.buckets.get(n);s?s.push(e):this.buckets.set(n,[e])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,n,s){const o=[],i=new Set,r=e-s/2,a=t+n/2,c=e+s/2;for(let e=t-n/2;e<=a;e+=this.CELL_SIZE)for(let t=r;t<=c;t+=this.CELL_SIZE){const n=this.getBucketKey(e,t),s=this.buckets.get(n)||[];for(const t of s)i.has(t.capacityMeshNodeId)||(i.add(t.capacityMeshNodeId),o.push(t))}return o}},cn=class extends rn{constructor(t){super(t),this.nodes=t,this.MAX_ITERATIONS=1e7,this.nodeTree=new an(this.nodes),this.currentNodeIndex=0,this.edgeSet=new Set}nodeTree;currentNodeIndex;edgeSet;_step(){if(this.currentNodeIndex>=this.nodes.length)return this.handleTargetNodes(),void(this.solved=!0);const t=this.nodes[this.currentNodeIndex],e=this.nodeTree.getNodesInArea(t.center.x,t.center.y,2*t.width,2*t.height);for(const n of e){if(!on(t,n))continue;const e=t._strawNode&&n._strawNode&&t._strawParentCapacityMeshNodeId===n._strawParentCapacityMeshNodeId;t.capacityMeshNodeId===n.capacityMeshNodeId||e||!this.doNodesHaveSharedLayer(t,n)||this.edgeSet.has(`${t.capacityMeshNodeId}-${n.capacityMeshNodeId}`)||(this.edgeSet.add(`${t.capacityMeshNodeId}-${n.capacityMeshNodeId}`),this.edgeSet.add(`${n.capacityMeshNodeId}-${t.capacityMeshNodeId}`),this.edges.push({capacityMeshEdgeId:this.getNextCapacityMeshEdgeId(),nodeIds:[t.capacityMeshNodeId,n.capacityMeshNodeId]}))}this.currentNodeIndex++}},hn=class{parent={};constructor(t){for(const e of t)this.parent[e]=e}find(t){return this.parent[t]===t?t:this.parent[t]=this.find(this.parent[t])}union(t,e){const n=this.find(t),s=this.find(e);n!==s&&(this.parent[s]=n)}getGroup(t){const e=this.find(t),n=[];for(const t in this.parent)this.find(t)===e&&n.push(t);return n}},dn=class{point;left=null;right=null;constructor(t){this.point=t}},ln=class{root=null;constructor(t){t.length>0&&(this.root=this.buildTree(t,0))}buildTree(t,e){const n=e%2==0?"x":"y";t.sort((t,e)=>t[n]-e[n]);const s=Math.floor(t.length/2),o=new dn(t[s]);return s>0&&(o.left=this.buildTree(t.slice(0,s),e+1)),s<t.length-1&&(o.right=this.buildTree(t.slice(s+1),e+1)),o}findNearestNeighbor(t){if(!this.root)throw new Error("Tree is empty");const e=this.root.point,n=this.distance(t,e);return this.nearestNeighborSearch(this.root,t,0,e,n),e}nearestNeighborSearch(t,e,n,s,o){if(!t)return s;const i=n%2?"x":"y",r=this.distance(e,t.point);r<o&&(s=t.point,o=r);const a=e[i]-t.point[i],c=a<=0?t.left:t.right,h=a<=0?t.right:t.left;return s=this.nearestNeighborSearch(c,e,n+1,s,o),o=this.distance(e,s),Math.abs(a)<o&&(s=this.nearestNeighborSearch(h,e,n+1,s,o)),s}findKNearestNeighbors(t,e){if(!this.root)return[];const n=[];return this.kNearestNeighborSearch(this.root,t,0,n,e),n.sort((t,e)=>t.distance-e.distance).slice(0,e).map(t=>t.point)}kNearestNeighborSearch(t,e,n,s,o){if(!t)return;const i=n%2?"x":"y",r=this.distance(e,t.point);s.push({point:t.point,distance:r});const a=e[i]-t.point[i],c=a<=0?t.left:t.right,h=a<=0?t.right:t.left;this.kNearestNeighborSearch(c,e,n+1,s,o);let d=1/0;s.length>=o&&(s.sort((t,e)=>t.distance-e.distance),d=s[o-1]?.distance||1/0),(Math.abs(a)<d||s.length<o)&&this.kNearestNeighborSearch(h,e,n+1,s,o)}distance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}},un=class{parent=new Map;rank=new Map;constructor(t){for(const e of t){const t=this.pointToKey(e);this.parent.set(t,t),this.rank.set(t,0)}}pointToKey(t){return`${t.x},${t.y}`}find(t){const e=this.pointToKey(t);if(!this.parent.has(e))throw new Error(`Point ${e} not found in DisjointSet`);let n=e;for(;n!==this.parent.get(n);)n=this.parent.get(n);let s=e;for(;s!==n;){const t=this.parent.get(s);this.parent.set(s,n),s=t}return n}union(t,e){const n=this.find(t),s=this.find(e);if(n===s)return!1;const o=this.rank.get(n)||0,i=this.rank.get(s)||0;return o<i?this.parent.set(n,s):o>i?this.parent.set(s,n):(this.parent.set(s,n),this.rank.set(n,o+1)),!0}};function pn(t){if(t.length<=1)return[];const e=new ln(t),n=[],s=Math.min(10,t.length-1);for(const o of t){const t=e.findKNearestNeighbors(o,s+1);for(const e of t){if(o.x===e.x&&o.y===e.y)continue;const t=Math.sqrt((o.x-e.x)**2+(o.y-e.y)**2);n.push({from:o,to:e,weight:t})}}n.sort((t,e)=>t.weight-e.weight);const o=new un(t),i=[];for(const e of n)if(o.union(e.from,e.to)&&(i.push(e),i.length===t.length-1))break;return i}function mn(t){if(t.pointId)return t.pointId;let e="";var n;return"layer"in(n=t)&&"string"==typeof n.layer?e=t.layer:He(t)&&t.layers&&(e=t.layers.sort().join("-")),`${t.x.toFixed(4)},${t.y.toFixed(4)},${e}`}var fn=class extends y{constructor(t,e={}){super(),this.ogSrj=t,this.colorMap=e,this.unprocessedConnections=function(t){if(0===t.length)return[];const e=t.map((t,e)=>`conn_${e}`),n=new hn(e),s=new Map;t.forEach((t,e)=>{const n=`conn_${e}`;t.pointsToConnect.forEach(t=>{const e=mn(t);s.has(e)||s.set(e,[]),s.get(e).push(n)})});for(const t of s.values())if(t.length>1){const e=t[0];for(let s=1;s<t.length;s++)n.union(e,t[s])}const o=new Map;t.forEach((t,e)=>{const s=`conn_${e}`,i=n.find(s);o.has(i)||o.set(i,[]),o.get(i).push(t)});const i=[];for(const t of o.values()){if(1===t.length){i.push(t[0]);continue}const e=new Map,n=new Set;let s=!1;const o=[],r=new Set;let a;t.forEach(t=>{t.pointsToConnect.forEach(t=>e.set(mn(t),t)),n.add(t.name),t.isOffBoard&&(s=!0),t.externallyConnectedPointIds&&o.push(...t.externallyConnectedPointIds),t.netConnectionName&&r.add(t.netConnectionName),void 0===a&&void 0!==t.nominalTraceWidth&&(a=t.nominalTraceWidth)});const c={name:Array.from(n).join("__"),mergedConnectionNames:Array.from(n),pointsToConnect:Array.from(e.values()),isOffBoard:s,externallyConnectedPointIds:o.length>0?o:void 0,netConnectionName:r.size>0?Array.from(r).join("__"):void 0,nominalTraceWidth:a};i.push(c)}return i}([...t.connections]),this.newConnections=[]}unprocessedConnections;newConnections;_step(){if(0===this.unprocessedConnections.length)return void(this.solved=!0);const t=this.unprocessedConnections.pop(),e=t.externallyConnectedPointIds??[],n=new Map;e.forEach((t,e)=>t.forEach(t=>n.set(t,e)));const s=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const s=n.get(t.pointId),o=n.get(e.pointId);return void 0!==s&&s===o};if(2===t.pointsToConnect.length){if(s(t.pointsToConnect[0],t.pointsToConnect[1]))return;return void this.newConnections.push({...t,rootConnectionName:t.name})}const o=pn(t.pointsToConnect);let i=0;for(const e of o)s(e.from,e.to)||this.newConnections.push({pointsToConnect:[e.from,e.to],name:`${t.name}_mst${i++}`,rootConnectionName:t.name,mergedConnectionNames:t.mergedConnectionNames,netConnectionName:t.netConnectionName})}getNewSimpleRouteJson(){return{...this.ogSrj,connections:this.newConnections}}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Net To Point Pairs Visualization"};return this.unprocessedConnections.forEach(e=>{e.pointsToConnect.forEach(n=>{t.points.push({x:n.x,y:n.y,color:"red",label:e.name})});const n=e.pointsToConnect.length**2,s=Yt(0),o=new Set;for(let i=0;i<Math.max(n,2*e.pointsToConnect.length);i++){const n=Math.floor(s()*e.pointsToConnect.length),i=Math.floor(s()*e.pointsToConnect.length);o.has(`${n}-${i}`)||(o.add(`${n}-${i}`),t.lines.push({points:[e.pointsToConnect[n],e.pointsToConnect[i]],strokeColor:"rgba(255,0,0,0.25)"}))}}),this.newConnections.forEach(e=>{const n=this.colorMap?.[e.name]||"blue";e.pointsToConnect.forEach(s=>{t.points.push({x:s.x,y:s.y,color:n,label:e.name})});for(let s=0;s<e.pointsToConnect.length-1;s++)for(let o=s+1;o<e.pointsToConnect.length;o++)t.lines.push({points:[e.pointsToConnect[s],e.pointsToConnect[o]],strokeColor:n})}),t}},gn=class extends fn{constructor(t,e={}){const n=t.connections.flatMap(t=>t.pointsToConnect),s=new Map;for(const t of n)t.pointId&&s.set(t.pointId,t);const o=n.map(t=>t.pointId).filter(t=>!!t),i=new hn(o),r=[];for(const e of t.connections)e.isOffBoard?e.pointsToConnect.length>=2&&e.pointsToConnect[0].pointId&&e.pointsToConnect[1].pointId&&i.union(e.pointsToConnect[0].pointId,e.pointsToConnect[1].pointId):r.push(e);super({...t,connections:r},e),this.ogSrj=t,this.colorMap=e,this.connectionPointDsu=i,this.connectionPointMap=s,this.ogSrj=t}connectionPointDsu;connectionPointMap;_findBestConnectionPointsFromDisjointSets(t,e){if(!t.pointId||!e.pointId)return{pointsToConnect:[t,e]};const n=this.connectionPointDsu.getGroup(t.pointId).map(t=>this.connectionPointMap.get(t)),s=this.connectionPointDsu.getGroup(e.pointId).map(t=>this.connectionPointMap.get(t));let o=t,i=e,r=1/0;for(const t of n)for(const e of s){const n=Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));n<r&&(r=n,o=t,i=e)}return{pointsToConnect:[o,i]}}_step(){if(0===this.unprocessedConnections.length)return void(this.solved=!0);const t=this.unprocessedConnections.pop(),e=t.externallyConnectedPointIds??[],n=new Map;e.forEach((t,e)=>t.forEach(t=>n.set(t,e)));const s=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const s=n.get(t.pointId),o=n.get(e.pointId);return void 0!==s&&s===o};if(2===t.pointsToConnect.length){if(s(t.pointsToConnect[0],t.pointsToConnect[1]))return;const e=this._findBestConnectionPointsFromDisjointSets(t.pointsToConnect[0],t.pointsToConnect[1]);return void this.newConnections.push({...t,pointsToConnect:e.pointsToConnect,rootConnectionName:t.name})}const o=pn(t.pointsToConnect);let i=0;for(const e of o){if(s(e.from,e.to))continue;const n=this._findBestConnectionPointsFromDisjointSets(e.from,e.to);this.newConnections.push({pointsToConnect:n.pointsToConnect,name:`${t.name}_mst${i++}`,rootConnectionName:t.name,mergedConnectionNames:t.mergedConnectionNames,netConnectionName:t.netConnectionName})}}};function yn(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:xn,sin:vn,PI:Sn}=Math,{tan:Pn}=Math;a(l()),a(f());function bn(t,e){if(t.points)for(const n of t.points)n.step=e;if(t.lines)for(const n of t.lines)n.step=e;if(t.rects)for(const n of t.rects)n.step=e;if(t.circles)for(const n of t.circles)n.step=e;if(t.texts)for(const n of t.texts)n.step=e;return t}var Mn=class{MAX_ITERATIONS=1e5;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};_setupDone=!1;setup(){this._setupDone||(this._setup(),this._setupDone=!0)}_setup(){}step(){if(this._setupDone||this.setup(),!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,console.error(this.error),this.failed=!0,t}!this.solved&&this.iterations>=this.MAX_ITERATIONS&&this.tryFinalAcceptance(),!this.solved&&this.iterations>=this.MAX_ITERATIONS&&(this.error=`${this.constructor.name} ran out of iterations`,console.error(this.error),this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}getOutput(){return null}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}};function Nn(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var In=class extends Mn{startTimeOfStage={};endTimeOfStage={};timeSpentOnStage={};firstIterationOfStage={};currentPipelineStageIndex=0;inputProblem;pipelineOutputs={};constructor(t){super(),this.inputProblem=t,this.MAX_ITERATIONS=1e6}_step(){const t=this.pipelineDef[this.currentPipelineStageIndex];if(!t)return void(this.solved=!0);if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved){this.endTimeOfStage[t.solverName]=performance.now(),this.timeSpentOnStage[t.solverName]=this.endTimeOfStage[t.solverName]-this.startTimeOfStage[t.solverName];const e=this.activeSubSolver.getOutput();null!==e&&(this.pipelineOutputs[t.solverName]=e),t.onSolved?.(this),this.activeSubSolver=null,this.currentPipelineStageIndex++}else this.activeSubSolver.failed&&(this.error=this.activeSubSolver?.error,this.failed=!0,this.activeSubSolver=null);return}const e=t.getConstructorParams(this);this.activeSubSolver=new t.solverClass(...e),this[t.solverName]=this.activeSubSolver,this.timeSpentOnStage[t.solverName]=0,this.startTimeOfStage[t.solverName]=performance.now(),this.firstIterationOfStage[t.solverName]=this.iterations}solveUntilStage(t){for(;this.getCurrentStageName().toLowerCase()!==t.toLowerCase()&&(this.step(),!this.failed&&!this.solved););}getCurrentStageName(){return this.pipelineDef[this.currentPipelineStageIndex]?.solverName??"none"}getStageProgress(){const t=this.pipelineDef.length;if(0===t)return 1;const e=this.activeSubSolver?.progress??0;return(this.currentPipelineStageIndex+e)/t}getStageStats(){const t={};for(const e of this.pipelineDef){const n=this.timeSpentOnStage[e.solverName]||0,s=this.firstIterationOfStage[e.solverName]||0,o=this.iterations,i=e.solverName===this.getCurrentStageName()?o-s:0,r=this.currentPipelineStageIndex>this.pipelineDef.findIndex(t=>t.solverName===e.solverName);t[e.solverName]={timeSpent:n,iterations:i,completed:r}}return t}initialVisualize(){return null}finalVisualize(){return null}visualize(){if(!this.solved&&this.activeSubSolver)return this.activeSubSolver.visualize();let t=0;const e=this.initialVisualize();e&&(bn(e,0),t=1);let n=null;this.solved&&(n=this.finalVisualize());const s=[e].filter(Boolean).concat(this.pipelineDef.map((e,n)=>{const s=this[e.solverName],o=s?.visualize();return o?(bn(o,n+t),o):null}).filter(Boolean));return 0===s.length?{points:[],rects:[],lines:[],circles:[],texts:[]}:(this.solved&&n&&(bn(n,s.length+t+1),s.push(n)),1===s.length?s[0]:{points:s.flatMap(t=>t.points||[]),rects:s.flatMap(t=>t.rects||[]),lines:s.flatMap(t=>t.lines||[]),circles:s.flatMap(t=>t.circles||[]),texts:s.flatMap(t=>t.texts||[])})}preview(){return this.activeSubSolver?this.activeSubSolver.preview():super.preview()}computeProgress(){return this.getStageProgress()}getStageOutput(t){return this.pipelineOutputs[t]}getAllOutputs(){return{...this.pipelineOutputs}}hasStageOutput(t){return t in this.pipelineOutputs}getSolver(t){return this[t]}},Cn=class{constructor(){this.ids=[],this.values=[],this.length=0}clear(){this.length=0}push(t,e){let n=this.length++;for(;n>0;){const t=n-1>>1,s=this.values[t];if(e>=s)break;this.ids[n]=this.ids[t],this.values[n]=s,n=t}this.ids[n]=t,this.values[n]=e}pop(){if(0===this.length)return;const t=this.ids,e=this.values,n=t[0],s=--this.length;if(s>0){const n=t[s],o=e[s];let i=0;const r=s>>1;for(;i<r;){const n=1+(i<<1),r=n+1,a=n+(+(r<s)&+(e[r]<e[n]));if(e[a]>=o)break;t[i]=t[a],e[i]=e[a],i=a}t[i]=n,e[i]=o}return n}peek(){return this.length>0?this.ids[0]:void 0}peekValue(){return this.length>0?this.values[0]:void 0}shrink(){this.ids.length=this.values.length=this.length}},_n=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],Tn=class t{static from(e,n=0){if(n%8!=0)throw new Error("byteOffset must be 8-byte aligned.");if(!e||void 0===e.byteLength||e.buffer)throw new Error("Data must be an instance of ArrayBuffer or SharedArrayBuffer.");const[s,o]=new Uint8Array(e,n+0,2);if(251!==s)throw new Error("Data does not appear to be in a Flatbush format.");const i=o>>4;if(3!==i)throw new Error(`Got v${i} data when expected v3.`);const r=_n[15&o];if(!r)throw new Error("Unrecognized array type.");const[a]=new Uint16Array(e,n+2,1),[c]=new Uint32Array(e,n+4,1);return new t(c,a,r,void 0,e,n)}constructor(t,e=16,n=Float64Array,s=ArrayBuffer,o,i=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=i;let r=t,a=r;this._levelBounds=[4*r];do{r=Math.ceil(r/this.nodeSize),a+=r,this._levelBounds.push(4*a)}while(1!==r);this.ArrayType=n,this.IndexArrayType=a<16384?Uint16Array:Uint32Array;const c=_n.indexOf(n),h=4*a*n.BYTES_PER_ELEMENT;if(c<0)throw new Error(`Unexpected typed array class: ${n}.`);if(o)this.data=o,this._boxes=new n(o,i+8,4*a),this._indices=new this.IndexArrayType(o,i+8+h,a),this._pos=4*a,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 o=this.data=new s(8+h+a*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new n(o,8,4*a),this._indices=new this.IndexArrayType(o,8+h,a),this._pos=0,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,new Uint8Array(o,0,2).set([251,48+c]),new Uint16Array(o,2,1)[0]=e,new Uint32Array(o,4,1)[0]=t}this._queue=new Cn}add(t,e,n=t,s=e){const o=this._pos>>2,i=this._boxes;return this._indices[o]=o,i[this._pos++]=t,i[this._pos++]=e,i[this._pos++]=n,i[this._pos++]=s,t<this.minX&&(this.minX=t),e<this.minY&&(this.minY=e),n>this.maxX&&(this.maxX=n),s>this.maxY&&(this.maxY=s),o}finish(){if(this._pos>>2!==this.numItems)throw new Error(`Added ${this._pos>>2} items when expected ${this.numItems}.`);const t=this._boxes;if(this.numItems<=this.nodeSize)return t[this._pos++]=this.minX,t[this._pos++]=this.minY,t[this._pos++]=this.maxX,void(t[this._pos++]=this.maxY);const e=this.maxX-this.minX||1,n=this.maxY-this.minY||1,s=new Uint32Array(this.numItems);for(let o=0,i=0;o<this.numItems;o++){const r=t[i++],a=t[i++],c=t[i++],h=t[i++],d=Math.floor(65535*((r+c)/2-this.minX)/e),l=Math.floor(65535*((a+h)/2-this.minY)/n);s[o]=An(d,l)}Rn(s,t,this._indices,0,this.numItems-1,this.nodeSize);for(let e=0,n=0;e<this._levelBounds.length-1;e++){const s=this._levelBounds[e];for(;n<s;){const e=n;let o=t[n++],i=t[n++],r=t[n++],a=t[n++];for(let e=1;e<this.nodeSize&&n<s;e++)o=Math.min(o,t[n++]),i=Math.min(i,t[n++]),r=Math.max(r,t[n++]),a=Math.max(a,t[n++]);this._indices[this._pos>>2]=e,t[this._pos++]=o,t[this._pos++]=i,t[this._pos++]=r,t[this._pos++]=a}}}search(t,e,n,s,o){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let i=this._boxes.length-4;const r=[],a=[];for(;void 0!==i;){const c=Math.min(i+4*this.nodeSize,En(i,this._levelBounds));for(let h=i;h<c;h+=4){const c=this._boxes[h];if(n<c)continue;const d=this._boxes[h+1];if(s<d)continue;const l=this._boxes[h+2];if(t>l)continue;const u=this._boxes[h+3];if(e>u)continue;const p=0|this._indices[h>>2];i>=4*this.numItems?r.push(p):(void 0===o||o(p,c,d,l,u))&&a.push(p)}i=r.pop()}return a}neighbors(t,e,n=1/0,s=1/0,o){if(this._pos!==this._boxes.length)throw new Error("Data not yet indexed - call index.finish().");let i=this._boxes.length-4;const r=this._queue,a=[],c=s*s;t:for(;void 0!==i;){const s=Math.min(i+4*this.nodeSize,En(i,this._levelBounds));for(let n=i;n<s;n+=4){const s=0|this._indices[n>>2],a=this._boxes[n],h=this._boxes[n+1],d=this._boxes[n+2],l=this._boxes[n+3],u=t<a?a-t:t>d?t-d:0,p=e<h?h-e:e>l?e-l:0,m=u*u+p*p;m>c||(i>=4*this.numItems?r.push(s<<1,m):(void 0===o||o(s))&&r.push(1+(s<<1),m))}for(;r.length&&1&r.peek();){if(r.peekValue()>c)break t;if(a.push(r.pop()>>1),a.length===n)break t}i=r.length?r.pop()>>1:void 0}return r.clear(),a}};function En(t,e){let n=0,s=e.length-1;for(;n<s;){const o=n+s>>1;e[o]>t?s=o:n=o+1}return e[n]}function Rn(t,e,n,s,o,i){if(Math.floor(s/i)>=Math.floor(o/i))return;const r=t[s],a=t[s+o>>1],c=t[o];let h=c;const d=Math.max(r,a);c>d?h=d:d===r?h=Math.max(a,c):d===a&&(h=Math.max(r,c));let l=s-1,u=o+1;for(;;){do{l++}while(t[l]<h);do{u--}while(t[u]>h);if(l>=u)break;wn(t,e,n,l,u)}Rn(t,e,n,s,u,i),Rn(t,e,n,u+1,o,i)}function wn(t,e,n,s,o){const i=t[s];t[s]=t[o],t[o]=i;const r=4*s,a=4*o,c=e[r],h=e[r+1],d=e[r+2],l=e[r+3];e[r]=e[a],e[r+1]=e[a+1],e[r+2]=e[a+2],e[r+3]=e[a+3],e[a]=c,e[a+1]=h,e[a+2]=d,e[a+3]=l;const u=n[s];n[s]=n[o],n[o]=u}function An(t,e){let n=t^e,s=65535^n,o=65535^(t|e),i=t&(65535^e),r=n|s>>1,a=n>>1^n,c=o>>1^s&i>>1^o,h=n&o>>1^i>>1^i;n=r,s=a,o=c,i=h,r=n&n>>2^s&s>>2,a=n&s>>2^s&(n^s)>>2,c^=n&o>>2^s&i>>2,h^=s&o>>2^(n^s)&i>>2,n=r,s=a,o=c,i=h,r=n&n>>4^s&s>>4,a=n&s>>4^s&(n^s)>>4,c^=n&o>>4^s&i>>4,h^=s&o>>4^(n^s)&i>>4,n=r,s=a,o=c,i=h,c^=n&o>>8^s&i>>8,h^=s&o>>8^(n^s)&i>>8,n=c^c>>1,s=h^h>>1;let d=t^e,l=s|65535^(d|n);return d=16711935&(d|d<<8),d=252645135&(d|d<<4),d=858993459&(d|d<<2),d=1431655765&(d|d<<1),l=16711935&(l|l<<8),l=252645135&(l|l<<4),l=858993459&(l|l<<2),l=1431655765&(l|l<<1),(l<<1|d)>>>0}function On(t,e,n=0,s=t.length-1,o=Dn){for(;s>n;){if(s-n>600){const i=s-n+1,r=e-n+1,a=Math.log(i),c=.5*Math.exp(2*a/3),h=.5*Math.sqrt(a*c*(i-c)/i)*(r-i/2<0?-1:1);On(t,e,Math.max(n,Math.floor(e-r*c/i+h)),Math.min(s,Math.floor(e+(i-r)*c/i+h)),o)}const i=t[e];let r=n,a=s;for(zn(t,n,e),o(t[s],i)>0&&zn(t,n,s);r<a;){for(zn(t,r,a),r++,a--;o(t[r],i)<0;)r++;for(;o(t[a],i)>0;)a--}0===o(t[n],i)?zn(t,n,a):(a++,zn(t,a,s)),a<=e&&(n=a+1),e<=a&&(s=a-1)}}function zn(t,e,n){const s=t[e];t[e]=t[n],t[n]=s}function Dn(t,e){return t<e?-1:t>e?1:0}var Ln=class{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(.4*this._maxEntries)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const n=[];if(!Zn(t,e))return n;const s=this.toBBox,o=[];for(;e;){for(let i=0;i<e.children.length;i++){const r=e.children[i],a=e.leaf?s(r):r;Zn(t,a)&&(e.leaf?n.push(r):Vn(t,a)?this._all(r,n):o.push(r))}e=o.pop()}return n}collides(t){let e=this.data;if(!Zn(t,e))return!1;const n=[];for(;e;){for(let s=0;s<e.children.length;s++){const o=e.children[s],i=e.leaf?this.toBBox(o):o;if(Zn(t,i)){if(e.leaf||Vn(t,i))return!0;n.push(o)}}e=n.pop()}return!1}load(t){if(!t||!t.length)return this;if(t.length<this._minEntries){for(let e=0;e<t.length;e++)this.insert(t[e]);return this}let e=this._build(t.slice(),0,t.length-1,0);if(this.data.children.length)if(this.data.height===e.height)this._splitRoot(this.data,e);else{if(this.data.height<e.height){const t=this.data;this.data=e,e=t}this._insert(e,this.data.height-e.height-1,!0)}else this.data=e;return this}insert(t){return t&&this._insert(t,this.data.height-1),this}clear(){return this.data=Gn([]),this}remove(t,e){if(!t)return this;let n=this.data;const s=this.toBBox(t),o=[],i=[];let r,a,c;for(;n||o.length;){if(n||(n=o.pop(),a=o[o.length-1],r=i.pop(),c=!0),n.leaf){const s=Fn(t,n.children,e);if(-1!==s)return n.children.splice(s,1),o.push(n),this._condense(o),this}c||n.leaf||!Vn(n,s)?a?(r++,n=a.children[r],c=!1):n=null:(o.push(n),i.push(r),r=0,a=n,n=n.children[0])}return this}toBBox(t){return t}compareMinX(t,e){return t.minX-e.minX}compareMinY(t,e){return t.minY-e.minY}toJSON(){return this.data}fromJSON(t){return this.data=t,this}_all(t,e){const n=[];for(;t;)t.leaf?e.push(...t.children):n.push(...t.children),t=n.pop();return e}_build(t,e,n,s){const o=n-e+1;let i,r=this._maxEntries;if(o<=r)return i=Gn(t.slice(e,n+1)),Xn(i,this.toBBox),i;s||(s=Math.ceil(Math.log(o)/Math.log(r)),r=Math.ceil(o/Math.pow(r,s-1))),i=Gn([]),i.leaf=!1,i.height=s;const a=Math.ceil(o/r),c=a*Math.ceil(Math.sqrt(r));Jn(t,e,n,c,this.compareMinX);for(let o=e;o<=n;o+=c){const e=Math.min(o+c-1,n);Jn(t,o,e,a,this.compareMinY);for(let n=o;n<=e;n+=a){const o=Math.min(n+a-1,e);i.children.push(this._build(t,n,o,s-1))}}return Xn(i,this.toBBox),i}_chooseSubtree(t,e,n,s){for(;s.push(e),!e.leaf&&s.length-1!==n;){let n,s=1/0,o=1/0;for(let i=0;i<e.children.length;i++){const r=e.children[i],a=jn(r),c=Hn(t,r)-a;c<o?(o=c,s=a<s?a:s,n=r):c===o&&a<s&&(s=a,n=r)}e=n||e.children[0]}return e}_insert(t,e,n){const s=n?t:this.toBBox(t),o=[],i=this._chooseSubtree(s,this.data,e,o);for(i.children.push(t),$n(i,s);e>=0&&o[e].children.length>this._maxEntries;)this._split(o,e),e--;this._adjustParentBBoxes(s,o,e)}_split(t,e){const n=t[e],s=n.children.length,o=this._minEntries;this._chooseSplitAxis(n,o,s);const i=this._chooseSplitIndex(n,o,s),r=Gn(n.children.splice(i,n.children.length-i));r.height=n.height,r.leaf=n.leaf,Xn(n,this.toBBox),Xn(r,this.toBBox),e?t[e-1].children.push(r):this._splitRoot(n,r)}_splitRoot(t,e){this.data=Gn([t,e]),this.data.height=t.height+1,this.data.leaf=!1,Xn(this.data,this.toBBox)}_chooseSplitIndex(t,e,n){let s,o=1/0,i=1/0;for(let r=e;r<=n-e;r++){const e=Yn(t,0,r,this.toBBox),a=Yn(t,r,n,this.toBBox),c=Un(e,a),h=jn(e)+jn(a);c<o?(o=c,s=r,i=h<i?h:i):c===o&&h<i&&(i=h,s=r)}return s||n-e}_chooseSplitAxis(t,e,n){const s=t.leaf?this.compareMinX:kn,o=t.leaf?this.compareMinY:Bn;this._allDistMargin(t,e,n,s)<this._allDistMargin(t,e,n,o)&&t.children.sort(s)}_allDistMargin(t,e,n,s){t.children.sort(s);const o=this.toBBox,i=Yn(t,0,e,o),r=Yn(t,n-e,n,o);let a=Wn(i)+Wn(r);for(let s=e;s<n-e;s++){const e=t.children[s];$n(i,t.leaf?o(e):e),a+=Wn(i)}for(let s=n-e-1;s>=e;s--){const e=t.children[s];$n(r,t.leaf?o(e):e),a+=Wn(r)}return a}_adjustParentBBoxes(t,e,n){for(let s=n;s>=0;s--)$n(e[s],t)}_condense(t){for(let e,n=t.length-1;n>=0;n--)0===t[n].children.length?n>0?(e=t[n-1].children,e.splice(e.indexOf(t[n]),1)):this.clear():Xn(t[n],this.toBBox)}};function Fn(t,e,n){if(!n)return e.indexOf(t);for(let s=0;s<e.length;s++)if(n(t,e[s]))return s;return-1}function Xn(t,e){Yn(t,0,t.children.length,e,t)}function Yn(t,e,n,s,o){o||(o=Gn(null)),o.minX=1/0,o.minY=1/0,o.maxX=-1/0,o.maxY=-1/0;for(let i=e;i<n;i++){const e=t.children[i];$n(o,t.leaf?s(e):e)}return o}function $n(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 kn(t,e){return t.minX-e.minX}function Bn(t,e){return t.minY-e.minY}function jn(t){return(t.maxX-t.minX)*(t.maxY-t.minY)}function Wn(t){return t.maxX-t.minX+(t.maxY-t.minY)}function Hn(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 Un(t,e){const n=Math.max(t.minX,e.minX),s=Math.max(t.minY,e.minY),o=Math.min(t.maxX,e.maxX),i=Math.min(t.maxY,e.maxY);return Math.max(0,o-n)*Math.max(0,i-s)}function Vn(t,e){return t.minX<=e.minX&&t.minY<=e.minY&&e.maxX<=t.maxX&&e.maxY<=t.maxY}function Zn(t,e){return e.minX<=t.maxX&&e.minY<=t.maxY&&e.maxX>=t.minX&&e.maxY>=t.minY}function Gn(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function Jn(t,e,n,s,o){const i=[e,n];for(;i.length;){if((n=i.pop())-(e=i.pop())<=s)continue;const r=e+Math.ceil((n-e)/s/2)*s;On(t,r,e,n,o),i.push(e,r,r,n)}}var qn=1e-4;var Kn=[{facingDirection:"x-",dx:-1,dy:0,startX:-.5,startY:.5,endX:-.5,endY:-.5},{facingDirection:"x+",dx:1,dy:0,startX:.5,startY:.5,endX:.5,endY:-.5},{facingDirection:"y-",dx:0,dy:-1,startX:-.5,startY:-.5,endX:.5,endY:-.5},{facingDirection:"y+",dx:0,dy:1,startX:.5,startY:.5,endX:-.5,endY:.5}],Qn={"x-":Kn.find(t=>"x-"===t.facingDirection),"x+":Kn.find(t=>"x+"===t.facingDirection),"y-":Kn.find(t=>"y-"===t.facingDirection),"y+":Kn.find(t=>"y+"===t.facingDirection)},ts={"x-":{x:-1,y:0},"x+":{x:1,y:0},"y-":{x:0,y:-1},"y+":{x:0,y:1}},es=(t,e)=>{const{dir:n,amt:s}=e,o=ts[n];return t.map(t=>({x:t.x+o.x*s,y:t.y+o.y*s}))},ns=1e-4,ss=class extends Mn{constructor(t){super(),this.input=t;for(const t of this.input.meshNodes)for(const e of Kn){let n={x:t.center.x+t.width*e.startX,y:t.center.y+t.height*e.startY},s={x:t.center.x+t.width*e.endX,y:t.center.y+t.height*e.endY};n.x>s.x&&([n,s]=[s,n]),Math.abs(n.x-s.x)<ns&&n.y>s.y&&([n,s]=[s,n]);for(const o of t.availableZ)this.unprocessedEdges.push({parent:t,start:n,end:s,facingDirection:e.facingDirection,z:o})}this.allEdges=[...this.unprocessedEdges],this.edgeSpatialIndex=new Tn(this.allEdges.length);for(const t of this.allEdges)this.edgeSpatialIndex.add(t.start.x,t.start.y,t.end.x,t.end.y);this.edgeSpatialIndex.finish()}allEdges;unprocessedEdges=[];segmentsWithAdjacentEmptySpace=[];edgeSpatialIndex;lastCandidateEdge=null;lastOverlappingEdges=null;lastUncoveredSegments=null;_step(){if(0===this.unprocessedEdges.length)return this.solved=!0,this.lastCandidateEdge=null,this.lastOverlappingEdges=null,void(this.lastUncoveredSegments=null);const t=this.unprocessedEdges.shift();this.lastCandidateEdge=t;const e=this.edgeSpatialIndex.search(t.start.x-ns,t.start.y-ns,t.end.x+ns,t.end.y+ns).map(t=>this.allEdges[t]).filter(e=>e.z===t.z);this.lastOverlappingEdges=e;const n=function(t,e){const n=Math.abs(t.start.y-t.end.y)<qn,s=Math.abs(t.start.x-t.end.x)<qn;if(!n&&!s)return[];const o=n?"x":"y",i=n?"y":"x",r=t.start[i],a=t.start[o],c=t.end[o],h=Math.min(a,c),d=Math.max(a,c),l=t=>Math.max(h,Math.min(d,t)),u=[];for(const n of e){if(n===t)continue;const e=Math.abs(n.start.y-n.end.y)<qn,s=Math.abs(n.start.x-n.end.x)<qn;if("x"===o&&!e)continue;if("y"===o&&!s)continue;if(Math.abs(n.start[i]-r)>qn)continue;const a=Math.min(n.start[o],n.end[o]),c=Math.max(n.start[o],n.end[o]),h=l(a),d=l(c);d-h>qn&&u.push({s:h,e:d})}if(0===u.length)return[{...t,start:{...t.start},end:{...t.end}}];u.sort((t,e)=>t.s-e.s);const p=[];for(const t of u){const e=p[p.length-1];!e||t.s>e.e+qn?p.push({...t}):e.e=Math.max(e.e,t.e)}const m=[];let f=h;for(const t of p)if(t.s>f+qn&&m.push({s:f,e:t.s}),f=Math.max(f,t.e),f>=d-qn)break;return d>f+qn&&m.push({s:f,e:d}),0===m.length?[]:m.filter(t=>t.e-t.s>qn).map(e=>{const n="x"===o?{x:e.s,y:r}:{x:r,y:e.s},s="x"===o?{x:e.e,y:r}:{x:r,y:e.e};return{parent:t.parent,facingDirection:t.facingDirection,start:n,end:s,z:t.z}})}(t,e);this.lastUncoveredSegments=n,this.segmentsWithAdjacentEmptySpace.push(...n)}getOutput(){return{segmentsWithAdjacentEmptySpace:this.segmentsWithAdjacentEmptySpace}}visualize(){const t={title:"FindSegmentsWithAdjacentEmptySpace",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]};for(const e of this.input.meshNodes)t.rects.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(0, 0, 0, 0.1)"});for(const e of this.unprocessedEdges)t.lines.push({points:es([e.start,e.end],{dir:e.facingDirection,amt:-.1}),strokeColor:"rgba(0, 0, 255, 0.5)",strokeDash:"5 5"});for(const e of this.segmentsWithAdjacentEmptySpace)t.lines.push({points:[e.start,e.end],strokeColor:"rgba(0,255,0, 0.5)"});if(this.lastCandidateEdge&&t.lines.push({points:[this.lastCandidateEdge.start,this.lastCandidateEdge.end],strokeColor:"blue"}),this.lastOverlappingEdges)for(const e of this.lastOverlappingEdges)t.lines.push({points:es([e.start,e.end],{dir:e.facingDirection,amt:.05}),strokeColor:"red",strokeDash:"2 2"});if(this.lastUncoveredSegments)for(const e of this.lastUncoveredSegments)t.lines.push({points:es([e.start,e.end],{dir:e.facingDirection,amt:-.05}),strokeColor:"green",strokeDash:"2 2"});return t}},os=t=>({minX:Math.min(...t.map(t=>t.x)),minY:Math.min(...t.map(t=>t.y)),maxX:Math.max(...t.map(t=>t.x)),maxY:Math.max(...t.map(t=>t.y))}),is=1e-4,rs=class extends Mn{constructor(t){super(),this.input=t,this.unprocessedSegments=[...this.input.segmentsWithAdjacentEmptySpace],this.rectSpatialIndex=new Ln,this.rectSpatialIndex.load(this.input.boardVoid?.boardVoidRects.map((t,e)=>({capacityMeshNodeId:`void-rect-${e}`,center:{x:t.x+t.width/2,y:t.y+t.height/2},width:t.width,height:t.height,availableZ:Array.from({length:this.input.boardVoid?.layerCount||0},(t,e)=>e),layer:"void",minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height}))||[]),this.rectSpatialIndex.load(this.input.inputMeshNodes.map(t=>({...t,minX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxX:t.center.x+t.width/2,maxY:t.center.y+t.height/2})))}unprocessedSegments=[];expandedSegments=[];lastSegment=null;lastSearchBounds=null;lastCollidingNodes=null;lastSearchCorner1=null;lastSearchCorner2=null;lastExpandedSegment=null;rectSpatialIndex;_step(){if(0===this.unprocessedSegments.length)return void(this.solved=!0);const t=this.unprocessedSegments.shift();this.lastSegment=t;const{dx:e,dy:n}=Qn[t.facingDirection],s=t.end.x-t.start.x,o=t.end.y-t.start.y,i=Math.sqrt(s**2+o**2),r=s/i,a=o/i;let c=null,h=1;const d={x:t.start.x+e*is+r*is*10,y:t.start.y+n*is+a*is*10},l={x:t.end.x+e*is-r*is*10,y:t.end.y+n*is-a*is*10};for(this.lastSearchCorner1=d,this.lastSearchCorner2=l;(!c||0===c.length)&&h<1e3;){const s=os([d,l,{x:d.x+e*h,y:d.y+n*h},{x:l.x+e*h,y:l.y+n*h}]);this.lastSearchBounds=s,c=this.rectSpatialIndex.search(s).filter(e=>e.availableZ.includes(t.z)).filter(e=>e.capacityMeshNodeId!==t.parent.capacityMeshNodeId),h*=4}if(!c||0===c.length)return;this.lastCollidingNodes=c;let u=1/0;for(const e of c){const n=At(t.start,t.end,e);n<u&&(u=n)}const p=u,m=os([t.start,t.end,{x:t.start.x+e*p,y:t.start.y+n*p},{x:t.end.x+e*p,y:t.end.y+n*p}]),f={x:(m.minX+m.maxX)/2,y:(m.minY+m.maxY)/2},g=m.maxX-m.minX,y=m.maxY-m.minY,x={segment:t,newNode:{capacityMeshNodeId:`new-${t.parent.capacityMeshNodeId}-${this.expandedSegments.length}`,center:f,width:g,height:y,availableZ:[t.z],layer:t.parent.layer}};this.lastExpandedSegment=x,g<is||y<is||(this.expandedSegments.push(x),this.rectSpatialIndex.insert({...x.newNode,...m}))}getOutput(){return{expandedSegments:this.expandedSegments}}visualize(){const t={title:"ExpandEdgesToEmptySpace",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]};for(const e of this.input.inputMeshNodes)t.rects.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(0, 0, 0, 0.1)",layer:`z${e.availableZ.join(",")}`,label:[`node ${e.capacityMeshNodeId}`,`z:${e.availableZ.join(",")}`].join("\n")});for(const{newNode:e}of this.expandedSegments)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"green",label:`expandedSegment (z=${e.availableZ.join(",")})`,layer:`z${e.availableZ.join(",")}`});if(this.lastSegment&&t.lines.push({points:[this.lastSegment.start,this.lastSegment.end],strokeColor:"rgba(0, 0, 255, 0.5)"}),this.lastSearchBounds&&t.rects.push({center:{x:(this.lastSearchBounds.minX+this.lastSearchBounds.maxX)/2,y:(this.lastSearchBounds.minY+this.lastSearchBounds.maxY)/2},width:this.lastSearchBounds.maxX-this.lastSearchBounds.minX,height:this.lastSearchBounds.maxY-this.lastSearchBounds.minY,fill:"rgba(0, 0, 255, 0.25)"}),this.lastSearchCorner1&&this.lastSearchCorner2&&(t.points.push({x:this.lastSearchCorner1.x,y:this.lastSearchCorner1.y,color:"rgba(0, 0, 255, 0.5)",label:["searchCorner1",`z=${this.lastSegment?.z}`].join("\n")}),t.points.push({x:this.lastSearchCorner2.x,y:this.lastSearchCorner2.y,color:"rgba(0, 0, 255, 0.5)",label:["searchCorner2",`z=${this.lastSegment?.z}`].join("\n")})),this.lastExpandedSegment&&t.rects.push({center:this.lastExpandedSegment.newNode.center,width:this.lastExpandedSegment.newNode.width,height:this.lastExpandedSegment.newNode.height,fill:"purple",label:`expandedSegment (z=${this.lastExpandedSegment.segment.z})`}),this.lastCollidingNodes)for(const e of this.lastCollidingNodes)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(255, 0, 0, 0.5)"});return t}},as=class extends In{findSegmentsWithAdjacentEmptySpaceSolver;expandEdgesToEmptySpaceSolver;pipelineDef=[Nn("findSegmentsWithAdjacentEmptySpaceSolver",ss,t=>[{meshNodes:t.inputProblem.meshNodes}],{onSolved:()=>{}}),Nn("expandEdgesToEmptySpaceSolver",rs,t=>[{inputMeshNodes:t.inputProblem.meshNodes,segmentsWithAdjacentEmptySpace:t.findSegmentsWithAdjacentEmptySpaceSolver.getOutput().segmentsWithAdjacentEmptySpace,boardVoid:t.inputProblem.boardVoid}],{onSolved:()=>{}})];getOutput(){const t=(this.expandEdgesToEmptySpaceSolver?.getOutput().expandedSegments??[]).map(t=>t.newNode);return{outputNodes:[...this.inputProblem.meshNodes,...t]}}initialVisualize(){const t={title:"GapFillSolverPipeline - Initial",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]};for(const e of this.inputProblem.meshNodes)t.rects.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(0, 0, 0, 0.3)",fill:"rgba(100, 100, 100, 0.1)",layer:`z${e.availableZ.join(",")}`,label:[`node ${e.capacityMeshNodeId}`,`z:${e.availableZ.join(",")}`].join("\n")});return t}finalVisualize(){const t={title:"GapFillSolverPipeline - Final",coordinateSystem:"cartesian",rects:[],points:[],lines:[],circles:[],arrows:[],texts:[]},{outputNodes:e}=this.getOutput(),n=this.expandEdgesToEmptySpaceSolver?.getOutput().expandedSegments??[],s=new Set(n.map(t=>t.newNode.capacityMeshNodeId));for(const n of e){const e=s.has(n.capacityMeshNodeId);t.rects.push({center:n.center,width:n.width,height:n.height,stroke:e?"rgba(0, 128, 0, 0.8)":"rgba(0, 0, 0, 0.3)",fill:e?"rgba(0, 200, 0, 0.3)":"rgba(100, 100, 100, 0.1)",layer:`z${n.availableZ.join(",")}`,label:[`${e?"[expanded] ":""}node ${n.capacityMeshNodeId}`,`z:${n.availableZ.join(",")}`].join("\n")})}return t}},cs=1e-9,hs=(t,e,n)=>Math.max(e,Math.min(n,t)),ds=(t,e)=>t>e+cs,ls=(t,e)=>t>e-cs,us=(t,e)=>t<e-cs,ps=(t,e)=>t<e+cs;function ms(t,e){return!(t.x+t.width<=e.x+cs||e.x+e.width<=t.x+cs||t.y+t.height<=e.y+cs||e.y+e.height<=t.y+cs)}function fs(t,e){const n=[[e.x,e.y,e.x+e.width,e.y],[e.x+e.width,e.y,e.x+e.width,e.y+e.height],[e.x+e.width,e.y+e.height,e.x,e.y+e.height],[e.x,e.y+e.height,e.x,e.y]];let s=1/0;for(const[e,o,i,r]of n){const n=t.x-e,a=t.y-o,c=i-e,h=r-o,d=c*c+h*h;let l=0!==d?(n*c+a*h)/d:0;l=hs(l,0,1);const u=e+l*c,p=o+l*h;s=Math.min(s,Math.hypot(t.x-u,t.y-p))}return s}function gs(t,e){const n=Math.max(t[0],e[0]),s=Math.min(t[1],e[1]);return s>n+cs?[n,s]:null}function ys(t,e){if(!ms(t,e))return[t];const n=gs([t.x,t.x+t.width],[e.x,e.x+e.width]),s=gs([t.y,t.y+t.height],[e.y,e.y+e.height]);if(!n||!s)return[t];const[o,i]=n,[r,a]=s,c=[];o>t.x+cs&&c.push({x:t.x,y:t.y,width:o-t.x,height:t.height}),t.x+t.width>i+cs&&c.push({x:i,y:t.y,width:t.x+t.width-i,height:t.height});const h=Math.max(0,i-o);return h>cs&&r>t.y+cs&&c.push({x:o,y:t.y,width:h,height:r-t.y}),h>cs&&t.y+t.height>a+cs&&c.push({x:o,y:a,width:h,height:t.y+t.height-a}),c.filter(t=>t.width>cs&&t.height>cs)}function xs(t,e){let n=!1;for(let s=0,o=e.length-1;s<e.length;o=s++){const i=e[s].x,r=e[s].y,a=e[o].x,c=e[o].y;r>t.y!=c>t.y&&t.x<(a-i)*(t.y-r)/(c-r)+i&&(n=!n)}return n}function vs(t,e){if(!e||e.length<3)return[];const n=e.length>100?function(t,e){const n=t=>Math.round(t/e)*e,s=new Set,o=[];for(const e of t){const t=n(e.x),i=n(e.y),r=`${t},${i}`;s.has(r)||(s.add(r),o.push({x:t,y:i}))}return o}(e,Math.max(t.width,t.height)/100):e,s=new Set([t.x,t.x+t.width]),o=new Set([t.y,t.y+t.height]);for(const t of n)s.add(t.x),o.add(t.y);const i=Array.from(s).sort((t,e)=>t-e),r=Array.from(o).sort((t,e)=>t-e),a=[];for(let n=0;n<i.length-1;n++)for(let s=0;s<r.length-1;s++){const o=i[n],c=i[n+1],h=r[s],d=r[s+1],l=(o+c)/2,u=(h+d)/2;l>=t.x&&l<=t.x+t.width&&u>=t.y&&u<=t.y+t.height&&(xs({x:l,y:u},e)||a.push({x:o,y:h,width:c-o,height:d-h}))}const c=[];a.sort((t,e)=>Math.abs(t.y-e.y)>cs?t.y-e.y:t.x-e.x);let h=null;for(const t of a){if(!h){h=t;continue}const e=Math.abs(h.y-t.y)<cs,n=Math.abs(h.height-t.height)<cs,s=Math.abs(h.x+h.width-t.x)<cs;e&&n&&s?h.width+=t.width:(c.push(h),h=t)}h&&c.push(h),c.sort((t,e)=>Math.abs(t.x-e.x)>cs?t.x-e.x:t.y-e.y);const d=[];h=null;for(const t of c){if(!h){h=t;continue}const e=Math.abs(h.x-t.x)<cs,n=Math.abs(h.width-t.width)<cs,s=Math.abs(h.y+h.height-t.y)<cs;e&&n&&s?h.height+=t.height:(d.push(h),h=t)}return h&&d.push(h),d}function Ss(t){const e=t.toLowerCase();if("top"===e)return-1e6;if("bottom"===e)return 1e6;const n=/^inner(\d+)$/i.exec(e);return n?parseInt(n[1],10)||0:100+e.charCodeAt(0)}function Ps(t){const e=function(t){return Array.from(new Set(t)).sort((t,e)=>{const n=Ss(t),s=Ss(e);return n!==s?n-s:t.localeCompare(e)})}((t.obstacles??[]).flatMap(t=>t.layers??[])),n=Math.max(1,t.layerCount||e.length||1),s=Array.from({length:n},(t,e)=>0===e?"top":e===n-1?"bottom":`inner${e}`),o=[],i=new Set,r=t=>{const e=t.toLowerCase();i.has(e)||(i.add(e),o.push(t))};s.forEach(r),e.forEach(r);const a=o.slice(0,n),c=new Map;return a.forEach((t,e)=>c.set(t.toLowerCase(),e)),o.slice(a.length).forEach(t=>{const e=t.toLowerCase();c.set(e,(t=>{if(a.length<=1)return 0;if("top"===t)return 0;if("bottom"===t)return a.length-1;const e=/^inner(\d+)$/i.exec(t);if(e){if(a.length<=2)return a.length-1;const t=parseInt(e[1],10),n=a.length-2;return Math.min(n,Math.max(1,Number.isFinite(t)?t:1))}return 0})(e))}),{layerNames:a,zIndexByName:c}}function bs(t,e){if(t.zLayers?.length)return Array.from(new Set(t.zLayers)).sort((t,e)=>t-e);const n=(t.layers??[]).map(t=>e.get(t.toLowerCase())).filter(t=>"number"==typeof t);return Array.from(new Set(n)).sort((t,e)=>t-e)}function Ms(t){const e=t.width,n=t.height;return"number"!=typeof e||"number"!=typeof n?null:{x:t.center.x-e/2,y:t.center.y-n/2,width:e,height:n}}var Ns=1e-9,Is=t=>Math.abs(t.rect.x+t.rect.width/2-t.startX)<Ns&&Math.abs(t.rect.y+t.rect.height/2-t.startY)<Ns&&Math.abs(t.rect.width-t.initialW)<Ns&&Math.abs(t.rect.height-t.initialH)<Ns,Cs=({rect:t,bounds:e})=>({x:t.x,y:t.y,width:e.x+e.width-t.x,height:t.height}),_s=({rect:t,bounds:e})=>({x:t.x,y:t.y,width:t.width,height:e.y+e.height-t.y}),Ts=({rect:t,bounds:e})=>({x:e.x,y:t.y,width:t.x-e.x,height:t.height}),Es=({rect:t,bounds:e})=>({x:t.x,y:e.y,width:t.width,height:t.y-e.y});function Rs(t){const{r:e,bounds:n,blockers:s,maxAspect:o}=t;let i=n.x+n.width-e.x;for(const t of s){if(e.y+e.height>t.y+cs&&t.y+t.height>e.y+cs)if(ls(t.x,e.x+e.width))i=Math.min(i,t.x-e.x);else if(t.x+t.width>e.x+e.width-cs&&t.x<e.x+e.width+cs)return 0}let r=Math.max(0,i-e.width);if(r<=0)return 0;if(null!=o){const t=e.width,n=e.height;t>=n&&(r=Math.min(r,o*n-t))}return Math.max(0,r)}function ws(t){const{r:e,bounds:n,blockers:s,maxAspect:o}=t;let i=n.y+n.height-e.y;for(const t of s){if(e.x+e.width>t.x+cs&&t.x+t.width>e.x+cs)if(ls(t.y,e.y+e.height))i=Math.min(i,t.y-e.y);else if(t.y+t.height>e.y+e.height-cs&&t.y<e.y+e.height+cs)return 0}let r=Math.max(0,i-e.height);if(r<=0)return 0;if(null!=o){const t=e.width,n=e.height;n>=t&&(r=Math.min(r,o*t-n))}return Math.max(0,r)}function As(t){const{r:e,bounds:n,blockers:s,maxAspect:o}=t;let i=n.x;for(const t of s){if(e.y+e.height>t.y+cs&&t.y+t.height>e.y+cs)if(ps(t.x+t.width,e.x))i=Math.max(i,t.x+t.width);else if(t.x<e.x+cs&&t.x+t.width>e.x-cs)return 0}let r=Math.max(0,e.x-i);if(r<=0)return 0;if(null!=o){const t=e.width,n=e.height;t>=n&&(r=Math.min(r,o*n-t))}return Math.max(0,r)}function Os(t){const{r:e,bounds:n,blockers:s,maxAspect:o}=t;let i=n.y;for(const t of s){if(e.x+e.width>t.x+cs&&t.x+t.width>e.x+cs)if(ps(t.y+t.height,e.y))i=Math.max(i,t.y+t.height);else if(t.y<e.y+cs&&t.y+t.height>e.y-cs)return 0}let r=Math.max(0,e.y-i);if(r<=0)return 0;if(null!=o){const t=e.width,n=e.height;n>=t&&(r=Math.min(r,o*t-n))}return Math.max(0,r)}var zs=t=>({x:t.minX,y:t.minY,width:t.maxX-t.minX,height:t.maxY-t.minY}),Ds=t=>{const{rect:e,seen:n,blockers:s}=t,o=`${e.x}|${e.y}|${e.width}|${e.height}`;n.has(o)||(n.add(o),s.push(e))};function Ls(t){const{startX:e,startY:n,gridSize:s,bounds:o,obsticalIndexByLayer:i,placedIndexByLayer:r,initialCellRatio:a,maxAspectRatio:c,minReq:h}=t,d=Math.max(1e-9,s*a),l=Math.max(d,h.width),u=Math.max(d,h.height),p=[],m=new Set,f=r.length,g=s=>{const a=(t=>{const{bounds:e,rect:n}=t,s=Math.max(e.x,n.x),o=Math.max(e.y,n.y),i=Math.min(e.x+e.width,n.x+n.width),r=Math.min(e.y+e.height,n.y+n.height);return i<=s+cs||r<=o+cs?null:{minX:s,minY:o,maxX:i,maxY:r}})({bounds:o,rect:s});if(a)for(const s of t.zLayers){const t=i[s];if(t)for(const e of t.search(a))Ds({rect:zs(e),seen:m,blockers:p});const o=r[s];if(o)for(const t of o.search(a)){if(!(t.zLayers.length>=f))continue;const s=zs(t);Is({rect:s,startX:e,startY:n,initialW:l,initialH:u})||Ds({rect:s,seen:m,blockers:p})}}},y=[{ox:0,oy:0},{ox:-l,oy:0},{ox:0,oy:-u},{ox:-l,oy:-u},{ox:-l/2,oy:-u/2}];let x=null,v=0;t:for(const t of y){let s={x:e+t.ox,y:n+t.oy,width:l,height:u};if(g(s),us(s.x,o.x)||us(s.y,o.y)||ds(s.x+s.width,o.x+o.width)||ds(s.y+s.height,o.y+o.height))continue;for(const t of p)if(ms(s,t))continue t;const i=1e-6,r=1e3;let a=!0,d=0;for(;a&&d<r;){d++,a=!1;const t={bounds:o,blockers:p,maxAspect:c};g(Cs({rect:s,bounds:o}));const e=Rs({...t,r:s});e>i&&(s={...s,width:s.width+e},g(s),a=!0),g(_s({rect:s,bounds:o}));const n=ws({...t,r:s});n>i&&(s={...s,height:s.height+n},g(s),a=!0),g(Ts({rect:s,bounds:o}));const r=As({...t,r:s});r>i&&(s={x:s.x-r,y:s.y,width:s.width+r,height:s.height},g(s),a=!0),g(Es({rect:s,bounds:o}));const h=Os({...t,r:s});h>i&&(s={x:s.x,y:s.y-h,width:s.width,height:s.height+h},g(s),a=!0)}if(s.width+cs>=h.width&&s.height+cs>=h.height){const t=s.width*s.height;t>v&&(x=s,v=t)}}return x}function Fs(t){const e=Math.max(t.width,t.height);return[e/8,e/16,e/32]}function Xs(t){const e={minX:t.point.x,minY:t.point.y,maxX:t.point.x,maxY:t.point.y};for(let n=0;n<t.layerCount;n++){const s=t.obstacleIndexByLayer[n],o=!!s&&s.search(e).length>0,i=t.placedIndexByLayer[n],r=!!i&&i.search(e).length>0;if(!o&&!r)return!1}return!0}function Ys(t){const{x:e,y:n,z:s,layerCount:o,minSpan:i,maxSpan:r,obstacleIndexByLayer:a,additionalBlockersByLayer:c}=t,h=t=>{const s={minX:e,minY:n,maxX:e,maxY:n},o=a[t];if(o&&o.search(s).length>0)return!1;return!(c?.[t]??[]).some(t=>{return(o={x:e,y:n}).x>=(s=t).x-cs&&o.x<=s.x+s.width+cs&&o.y>=s.y-cs&&o.y<=s.y+s.height+cs;var s,o})};let d=s,l=s;for(;d-1>=0&&h(d-1);)d--;for(;l+1<o&&h(l+1);)l++;if("number"==typeof r){const t=hs(r,1,o);for(;l-d+1>t;)s-d>l-s?d++:l--}const u=[];for(let t=d;t<=l;t++)u.push(t);return u.length>=i?u:[]}function $s(t){const{lineStart:e,lineEnd:n,coveringIntervals:s,minSegmentLength:o}=t;if(0===s.length){return[{start:e,end:n,center:(e+n)/2}]}const i=[...s].sort((t,e)=>t.start-e.start),r=[];let a={...i[0]};for(let t=1;t<i.length;t++){const e=i[t];e.start<=a.end+cs?a.end=Math.max(a.end,e.end):(r.push(a),a={...e})}r.push(a);const c=[];if(r[0].start>e+cs){const t=e,n=r[0].start;n-t>=o&&c.push({start:t,end:n,center:(t+n)/2})}for(let t=0;t<r.length-1;t++){const e=r[t].end,n=r[t+1].start;n-e>=o&&c.push({start:e,end:n,center:(e+n)/2})}if(r[r.length-1].end<n-cs){const t=r[r.length-1].end,e=n;e-t>=o&&c.push({start:t,end:e,center:(t+e)/2})}return c}function ks(t){const{bounds:e,minSize:n,layerCount:s,obstacleIndexByLayer:o,placedIndexByLayer:i,hardPlacedByLayer:r}=t,a=[],c=Math.max(.15*n,3*cs),h=new Set;function d(t){const{x:n,y:c,z:d}=t;if(n<e.x+cs||c<e.y+cs||n>e.x+e.width-cs||c>e.y+e.height-cs)return;if(function(t){return Xs({layerCount:s,obstacleIndexByLayer:o,placedIndexByLayer:i,point:t})}({x:n,y:c}))return;const l=[...o[d]?.all()??[],...r[d]??[]],u=Math.min(fs({x:n,y:c},e),...l.length?l.map(t=>fs({x:n,y:c},t)):[1/0]),p=(t=>`${t.z}|${t.x.toFixed(6)}|${t.y.toFixed(6)}`)({x:n,y:c,z:d});if(h.has(p))return;h.add(p);const m=Ys({x:n,y:c,z:d,layerCount:s,minSpan:1,maxSpan:void 0,obstacleIndexByLayer:o,additionalBlockersByLayer:r});a.push({x:n,y:c,z:d,distance:u,zSpanLen:m.length,isEdgeSeed:!0})}for(let t=0;t<s;t++){const s=[...o[t]?.all()??[],...r[t]??[]],i=[{x:e.x+c,y:e.y+c},{x:e.x+e.width-c,y:e.y+c},{x:e.x+c,y:e.y+e.height-c},{x:e.x+e.width-c,y:e.y+e.height-c}];for(const e of i)d({x:e.x,y:e.y,z:t});const a=e.y+c,h=s.filter(t=>t.y<=a&&t.y+t.height>=a).map(t=>({start:Math.max(e.x,t.x),end:Math.min(e.x+e.width,t.x+t.width)})),l=$s({lineStart:e.x+c,lineEnd:e.x+e.width-c,coveringIntervals:h,minSegmentLength:.5*n});for(const e of l){const s=e.end-e.start;s>=n&&(d({x:e.center,y:a,z:t}),s>1.5*n&&(d({x:e.start+.4*n,y:a,z:t}),d({x:e.end-.4*n,y:a,z:t})))}const u=e.y+e.height-c,p=s.filter(t=>t.y<=u&&t.y+t.height>=u).map(t=>({start:Math.max(e.x,t.x),end:Math.min(e.x+e.width,t.x+t.width)})),m=$s({lineStart:e.x+c,lineEnd:e.x+e.width-c,coveringIntervals:p,minSegmentLength:.5*n});for(const e of m){const s=e.end-e.start;s>=n&&(d({x:e.center,y:u,z:t}),s>1.5*n&&(d({x:e.start+.4*n,y:u,z:t}),d({x:e.end-.4*n,y:u,z:t})))}const f=e.x+c,g=s.filter(t=>t.x<=f&&t.x+t.width>=f).map(t=>({start:Math.max(e.y,t.y),end:Math.min(e.y+e.height,t.y+t.height)})),y=$s({lineStart:e.y+c,lineEnd:e.y+e.height-c,coveringIntervals:g,minSegmentLength:.5*n});for(const e of y){const s=e.end-e.start;s>=n&&(d({x:f,y:e.center,z:t}),s>1.5*n&&(d({x:f,y:e.start+.4*n,z:t}),d({x:f,y:e.end-.4*n,z:t})))}const x=e.x+e.width-c,v=s.filter(t=>t.x<=x&&t.x+t.width>=x).map(t=>({start:Math.max(e.y,t.y),end:Math.min(e.y+e.height,t.y+t.height)})),S=$s({lineStart:e.y+c,lineEnd:e.y+e.height-c,coveringIntervals:v,minSegmentLength:.5*n});for(const e of S){const s=e.end-e.start;s>=n&&(d({x:x,y:e.center,z:t}),s>1.5*n&&(d({x:x,y:e.start+.4*n,z:t}),d({x:x,y:e.end-.4*n,z:t})))}for(const o of s){const i=o.x-c;if(i>e.x+cs&&i<e.x+e.width-cs){const e=s.filter(t=>t!==o&&t.x<=i&&t.x+t.width>=i).map(t=>({start:Math.max(o.y,t.y),end:Math.min(o.y+o.height,t.y+t.height)})),r=$s({lineStart:o.y,lineEnd:o.y+o.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of r)d({x:i,y:e.center,z:t})}const r=o.x+o.width+c;if(r>e.x+cs&&r<e.x+e.width-cs){const e=s.filter(t=>t!==o&&t.x<=r&&t.x+t.width>=r).map(t=>({start:Math.max(o.y,t.y),end:Math.min(o.y+o.height,t.y+t.height)})),i=$s({lineStart:o.y,lineEnd:o.y+o.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of i)d({x:r,y:e.center,z:t})}const a=o.y-c;if(a>e.y+cs&&a<e.y+e.height-cs){const e=s.filter(t=>t!==o&&t.y<=a&&t.y+t.height>=a).map(t=>({start:Math.max(o.x,t.x),end:Math.min(o.x+o.width,t.x+t.width)})),i=$s({lineStart:o.x,lineEnd:o.x+o.width,coveringIntervals:e,minSegmentLength:.5*n});for(const e of i)d({x:e.center,y:a,z:t})}const h=o.y+o.height+c;if(h>e.y+cs&&h<e.y+e.height-cs){const e=s.filter(t=>t!==o&&t.y<=h&&t.y+t.height>=h).map(t=>({start:Math.max(o.x,t.x),end:Math.min(o.x+o.width,t.x+t.width)})),i=$s({lineStart:o.x,lineEnd:o.x+o.width,coveringIntervals:e,minSegmentLength:.5*n});for(const e of i)d({x:e.center,y:h,z:t})}}}return a.sort((t,e)=>e.zSpanLen-t.zSpanLen||e.distance-t.distance),a}var Bs=(t,e)=>({...t,minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height,zLayers:e.zLayers});function js(t,e){const n=t.placed[e],{rect:s,zLayers:o}=n,i=t.layerCount,r=[],a=[];for(let n=0;n<t.placed.length;n++){if(n===e)continue;const c=t.placed[n];if(c.zLayers.length>=i)continue;const h=c.zLayers.filter(t=>o.includes(t));if(0===h.length)continue;if(!ms(c.rect,s))continue;const d=ys(c.rect,s);r.push(n);const l=c.zLayers.filter(t=>!o.includes(t));l.length>0&&a.push({rect:c.rect,zLayers:l});const u=Math.min(t.options.minSingle.width,t.options.minMulti.width),p=Math.min(t.options.minSingle.height,t.options.minMulti.height);for(const t of d)t.width+cs>=u&&t.height+cs>=p&&a.push({rect:t,zLayers:h.slice()})}const c=(t,e)=>t.minX===e.minX&&t.minY===e.minY&&t.maxX===e.maxX&&t.maxY===e.maxY;r.sort((t,e)=>e-t).forEach(e=>{const n=t.placed.splice(e,1)[0];if(t.placedIndexByLayer)for(const e of n.zLayers){const s=t.placedIndexByLayer[e];s&&s.remove(Bs(n.rect,{zLayers:n.zLayers}),c)}});for(const e of a){t.placed.push(e);for(const n of e.zLayers)if(t.placedIndexByLayer){const s=t.placedIndexByLayer[n];s&&s.insert(Bs(e.rect,{zLayers:e.zLayers.slice()}))}}}var Ws=t=>{const e=[{fill:"#dbeafe",stroke:"#3b82f6"},{fill:"#fef3c7",stroke:"#f59e0b"},{fill:"#d1fae5",stroke:"#10b981"},{fill:"#e9d5ff",stroke:"#a855f7"},{fill:"#fed7aa",stroke:"#f97316"},{fill:"#fecaca",stroke:"#ef4444"}];return e[Math.min(...t)%e.length]},Hs=class extends Mn{constructor(t){super(),this.input=t}srj;layerNames;layerCount;bounds;options;boardVoidRects;gridIndex;candidates;placed;placedIndexByLayer;expansionIndex;edgeAnalysisDone;totalSeedsThisGrid;consumedSeedsThisGrid;_setup(){const t=this.input.simpleRouteJson,e=this.input.gridOptions??{},{layerNames:n,zIndexByName:s}=Ps(t),o=Math.max(1,n.length,t.layerCount||1),i={x:t.bounds.minX,y:t.bounds.minY,width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},r=Math.max(.01,t.minTraceWidth||.15),a={...{gridSizes:[],initialCellRatio:.2,maxAspectRatio:3,minSingle:{width:2*r,height:2*r},minMulti:{width:4*r,height:4*r,minLayers:Math.min(2,Math.max(1,t.layerCount||1))},preferMultiLayer:!0,maxMultiLayerSpan:void 0},...e,gridSizes:e.gridSizes??Fs(i)};this.srj=t,this.layerNames=n,this.layerCount=o,this.bounds=i,this.options=a,this.boardVoidRects=this.input.boardVoidRects,this.gridIndex=0,this.candidates=[],this.placed=[],this.placedIndexByLayer=Array.from({length:o},()=>new Ln),this.expansionIndex=0,this.edgeAnalysisDone=!1,this.totalSeedsThisGrid=0,this.consumedSeedsThisGrid=0,this.stats={gridIndex:this.gridIndex}}_step(){this._stepGrid(),this.stats.gridIndex=this.gridIndex,this.stats.placed=this.placed.length}_stepGrid(){const{gridSizes:t,initialCellRatio:e,maxAspectRatio:n,minSingle:s,minMulti:o,preferMultiLayer:i,maxMultiLayerSpan:r}=this.options,a=t[this.gridIndex],c=function(t){const e=Array.from({length:t.layerCount},()=>[]);for(const n of t.placed)if(n.zLayers.length>=t.layerCount)for(const t of n.zLayers)e[t].push(n.rect);return e}({layerCount:this.layerCount,placed:this.placed});if(0===this.candidates.length&&0===this.consumedSeedsThisGrid&&(this.candidates=function(t){const{bounds:e,gridSize:n,layerCount:s,obstacleIndexByLayer:o,placedIndexByLayer:i,hardPlacedByLayer:r}=t,a=new Map;for(let t=e.x;t<e.x+e.width;t+=n)for(let c=e.y;c<e.y+e.height;c+=n){if(Math.abs(t-e.x)<cs||Math.abs(c-e.y)<cs||t>e.x+e.width-n-cs||c>e.y+e.height-n-cs)continue;if(Xs({layerCount:s,obstacleIndexByLayer:o,placedIndexByLayer:i,point:{x:t,y:c}}))continue;let h=[],d=0;for(let e=0;e<s;e++){const n=Ys({x:t,y:c,z:e,layerCount:s,minSpan:1,maxSpan:void 0,obstacleIndexByLayer:o,additionalBlockersByLayer:r});n.length>h.length&&(h=n,d=e)}const l=h.length?h[Math.floor(h.length/2)]:d,u=[...o[l]?.all()??[],...r[l]??[]],p=Math.min(fs({x:t,y:c},e),...u.length?u.map(e=>fs({x:t,y:c},e)):[1/0]),m=`${t.toFixed(6)}|${c.toFixed(6)}`,f={x:t,y:c,z:l,distance:p,zSpanLen:h.length},g=a.get(m);(!g||f.zSpanLen>(g.zSpanLen??0)||f.zSpanLen===g.zSpanLen&&f.distance>g.distance)&&a.set(m,f)}const c=Array.from(a.values());return c.sort((t,e)=>e.zSpanLen-t.zSpanLen||e.distance-t.distance),c}({bounds:this.bounds,gridSize:a,layerCount:this.layerCount,hardPlacedByLayer:c,obstacleIndexByLayer:this.input.obstacleIndexByLayer,placedIndexByLayer:this.placedIndexByLayer}),this.totalSeedsThisGrid=this.candidates.length,this.consumedSeedsThisGrid=0),0===this.candidates.length){if(this.gridIndex+1<t.length)return this.gridIndex+=1,this.totalSeedsThisGrid=0,void(this.consumedSeedsThisGrid=0);if(!this.edgeAnalysisDone){const t=Math.min(s.width,s.height);return this.candidates=ks({bounds:this.bounds,minSize:t,layerCount:this.layerCount,obstacleIndexByLayer:this.input.obstacleIndexByLayer,placedIndexByLayer:this.placedIndexByLayer,hardPlacedByLayer:c}),this.edgeAnalysisDone=!0,this.totalSeedsThisGrid=this.candidates.length,void(this.consumedSeedsThisGrid=0)}return this.solved=!0,void(this.expansionIndex=0)}const h=this.candidates.shift();this.consumedSeedsThisGrid+=1;const d=Ys({x:h.x,y:h.y,z:h.z,layerCount:this.layerCount,minSpan:o.minLayers,maxSpan:r,obstacleIndexByLayer:this.input.obstacleIndexByLayer,additionalBlockersByLayer:c}),l=[];d.length>=o.minLayers&&l.push({kind:"multi",layers:d,minReq:{width:o.width,height:o.height}}),l.push({kind:"single",layers:[h.z],minReq:{width:s.width,height:s.height}});const u=i?l:l.reverse();for(const t of u){const s=Ls({startX:h.x,startY:h.y,gridSize:a,bounds:this.bounds,obsticalIndexByLayer:this.input.obstacleIndexByLayer,placedIndexByLayer:this.placedIndexByLayer,initialCellRatio:e,maxAspectRatio:n,minReq:t.minReq,zLayers:t.layers});if(!s)continue;const o={rect:s,zLayers:[...t.layers]},i=this.placed.push(o)-1;for(const e of t.layers){const t=this.placedIndexByLayer[e];t&&t.insert(Bs(s,{zLayers:o.zLayers}))}return js({layerCount:this.layerCount,placed:this.placed,options:this.options,placedIndexByLayer:this.placedIndexByLayer},i),void(this.candidates=this.candidates.filter(t=>!Xs({layerCount:this.layerCount,obstacleIndexByLayer:this.input.obstacleIndexByLayer,placedIndexByLayer:this.placedIndexByLayer,point:{x:t.x,y:t.y}})))}}computeProgress(){if(this.solved)return 1;const t=this.options.gridSizes.length,e=this.gridIndex/(t+1),n=Math.max(1,this.totalSeedsThisGrid),s=n?this.consumedSeedsThisGrid/n:1;return Math.min(.999,e+s*(1/(t+1)))}getOutput(){return{srj:this.srj,layerNames:this.layerNames,layerCount:this.layerCount,bounds:this.bounds,options:this.options,boardVoidRects:this.boardVoidRects,gridIndex:this.gridIndex,candidates:this.candidates,placed:this.placed,expansionIndex:this.expansionIndex,edgeAnalysisDone:this.edgeAnalysisDone,totalSeedsThisGrid:this.totalSeedsThisGrid,consumedSeedsThisGrid:this.consumedSeedsThisGrid}}visualize(){const t=[],e=[],n=[],s=this.srj??this.input.simpleRouteJson,o=s.bounds.minX,i=s.bounds.maxX,r=s.bounds.minY,a=s.bounds.maxY;s.outline&&s.outline.length>1?n.push({points:[...s.outline,s.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):t.push({center:{x:(o+i)/2,y:(r+a)/2},width:i-o,height:a-r,fill:"none",stroke:"#111827",label:"board"});for(const e of s.obstacles??[])"rect"!==e.type&&"oval"!==e.type||t.push({center:{x:e.center.x,y:e.center.y},width:e.width,height:e.height,fill:"#fee2e2",stroke:"#ef4444",layer:"obstacle",label:"obstacle"});if(this.boardVoidRects){let e=null;if(s.outline&&s.outline.length>0){const t=s.outline.map(t=>t.x),n=s.outline.map(t=>t.y),o=Math.min(...t),i=Math.min(...n);e={x:o,y:i,width:Math.max(...t)-o,height:Math.max(...n)-i}}for(const n of this.boardVoidRects)e&&!ms(n,e)||t.push({center:{x:n.x+n.width/2,y:n.y+n.height/2},width:n.width,height:n.height,fill:"rgba(0, 0, 0, 0.5)",stroke:"none",label:"void"})}if(this.candidates?.length)for(const t of this.candidates)e.push({x:t.x,y:t.y,fill:"#9333ea",stroke:"#6b21a8",label:`z:${t.z}`});if(this.placed?.length)for(const e of this.placed){const n=Ws(e.zLayers);t.push({center:{x:e.rect.x+e.rect.width/2,y:e.rect.y+e.rect.height/2},width:e.rect.width,height:e.rect.height,fill:n.fill,stroke:n.stroke,layer:`z${e.zLayers.join(",")}`,label:`free\nz:${e.zLayers.join(",")}`})}return{title:"RectDiff Grid",coordinateSystem:"cartesian",rects:t,points:e,lines:n}}};var Us=(t,e)=>t.minX===e.minX&&t.minY===e.minY&&t.maxX===e.maxX&&t.maxY===e.maxY,Vs=class extends Mn{constructor(t){super(),this.input=t}placedIndexByLayer=[];_meshNodes=[];_setup(){this.stats={gridIndex:this.input.gridIndex},this.placedIndexByLayer=Array.from({length:this.input.layerCount},()=>new Ln);for(const t of this.input.placed)for(const e of t.zLayers){const n=this.placedIndexByLayer[e];n&&n.insert(Bs(t.rect,{zLayers:t.zLayers}))}}_step(){this.solved||(this._stepExpansion(),this.stats.gridIndex=this.input.gridIndex,this.stats.placed=this.input.placed.length,this.input.expansionIndex>=this.input.placed.length&&this.finalizeIfNeeded())}_stepExpansion(){if(this.input.expansionIndex>=this.input.placed.length)return;const t=this.input.expansionIndex,e=this.input.placed[t],n=this.input.options.gridSizes[this.input.options.gridSizes.length-1],s=e.rect,o=Ls({startX:e.rect.x+e.rect.width/2,startY:e.rect.y+e.rect.height/2,gridSize:n,bounds:this.input.bounds,obsticalIndexByLayer:this.input.obstacleIndexByLayer,placedIndexByLayer:this.placedIndexByLayer,initialCellRatio:0,maxAspectRatio:null,minReq:{width:e.rect.width,height:e.rect.height},zLayers:e.zLayers});if(o){this.input.placed[t]={rect:o,zLayers:e.zLayers};for(const t of e.zLayers){const n=this.placedIndexByLayer[t];n&&(n.remove(Bs(s,{zLayers:e.zLayers}),Us),n.insert(Bs(o,{zLayers:e.zLayers})))}js({layerCount:this.input.layerCount,placed:this.input.placed,options:this.input.options,placedIndexByLayer:this.placedIndexByLayer},t)}this.input.expansionIndex+=1}finalizeIfNeeded(){if(this.solved)return;const t=function(t){const e=t.placed.map(t=>({minX:t.rect.x,minY:t.rect.y,maxX:t.rect.x+t.rect.width,maxY:t.rect.y+t.rect.height,zLayers:[...t.zLayers].sort((t,e)=>t-e)})),{zIndexByName:n}=Ps(t.srj),s=new Map;for(const e of t.srj.obstacles??[]){const t=Ms(e);if(!t)continue;const o=e.zLayers?.length&&e.zLayers.length>0?e.zLayers:bs(e,n),i=`${t.x}:${t.y}:${t.width}:${t.height}`;let r=s.get(i);r||(r={rect:t,layers:new Set},s.set(i,r)),o.forEach(t=>r.layers.add(t))}for(const{rect:t,layers:n}of s.values())e.push({minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height,zLayers:Array.from(n).sort((t,e)=>t-e),isObstacle:!0});return e}({placed:this.input.placed,srj:this.input.srj,boardVoidRects:this.input.boardVoidRects});this._meshNodes=function(t){let e=0;const n=[];for(const s of t){const t=Math.max(0,s.maxX-s.minX),o=Math.max(0,s.maxY-s.minY);t<=0||o<=0||0===s.zLayers.length||n.push({capacityMeshNodeId:"cmn_"+e++,center:{x:(s.minX+s.maxX)/2,y:(s.minY+s.maxY)/2},width:t,height:o,layer:"top",availableZ:s.zLayers.slice(),_containsObstacle:s.isObstacle,_containsTarget:s.isObstacle})}return n}(t),this.solved=!0}computeProgress(){if(this.solved)return 1;const t=this.input.options.gridSizes.length,e=t/(t+1),n=Math.max(1,this.input.placed.length),s=n?this.input.expansionIndex/n:1;return Math.min(.999,e+s*(1/(t+1)))}getOutput(){if(this.solved)return{meshNodes:this._meshNodes};return{meshNodes:this.input.placed.map((t,e)=>({capacityMeshNodeId:`expand-preview-${e}`,center:{x:t.rect.x+t.rect.width/2,y:t.rect.y+t.rect.height/2},width:t.rect.width,height:t.rect.height,availableZ:t.zLayers.slice(),layer:`z${t.zLayers.join(",")}`}))}}visualize(){const t=[];for(const e of this.input.placed??[])t.push({center:{x:e.rect.x+e.rect.width/2,y:e.rect.y+e.rect.height/2},width:e.rect.width,height:e.rect.height,stroke:"rgba(37, 99, 235, 0.9)",fill:"rgba(191, 219, 254, 0.5)",layer:`z${e.zLayers.join(",")}`,label:`expanded\nz:${e.zLayers.join(",")}`});return{title:"RectDiff Expansion",coordinateSystem:"cartesian",rects:t,points:[],lines:[]}}},Zs=class extends In{rectDiffSeedingSolver;rectDiffExpansionSolver;obstacleIndexByLayer;constructor(t){super(t);const{obstacleIndexByLayer:e}=(t=>{const{srj:e,boardVoidRects:n}=t,{layerNames:s,zIndexByName:o}=Ps(e),i=Math.max(1,s.length,e.layerCount||1),r=(e.bounds.minX,e.bounds.minY,e.bounds.maxX,e.bounds.minX,e.bounds.maxY,e.bounds.minY,Array.from({length:i},()=>new Ln)),a=(t,e)=>{const n={...t,minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height,zLayers:[e]};r[e]?.insert(n)};if(e.outline&&e.outline.length>2)for(const t of n??[])for(let e=0;e<i;e++)a(t,e);for(const t of e.obstacles??[]){const e=Ms(t);if(!e)continue;const n=bs(t,o),s=n.filter(t=>t<0||t>=i);if(s.length)throw new Error(`RectDiff: obstacle uses z-layer indices ${s.join(",")} outside 0-${i-1}`);t.zLayers&&0!==t.zLayers.length||!n.length||(t.zLayers=n);for(const t of n)a(e,t)}return{obstacleIndexByLayer:r}})({srj:t.simpleRouteJson,boardVoidRects:t.boardVoidRects});this.obstacleIndexByLayer=e}pipelineDef=[Nn("rectDiffSeedingSolver",Hs,t=>[{simpleRouteJson:t.inputProblem.simpleRouteJson,gridOptions:t.inputProblem.gridOptions,obstacleIndexByLayer:t.obstacleIndexByLayer,boardVoidRects:t.inputProblem.boardVoidRects}]),Nn("rectDiffExpansionSolver",Vs,t=>{const e=t.rectDiffSeedingSolver?.getOutput();if(!e)throw new Error("RectDiffSeedingSolver did not produce output");return[{srj:t.inputProblem.simpleRouteJson,layerNames:e.layerNames??[],boardVoidRects:t.inputProblem.boardVoidRects??[],layerCount:t.inputProblem.simpleRouteJson.layerCount,bounds:e.bounds,candidates:e.candidates,consumedSeedsThisGrid:e.placed.length,totalSeedsThisGrid:e.candidates.length,placed:e.placed,edgeAnalysisDone:e.edgeAnalysisDone,gridIndex:e.gridIndex,expansionIndex:e.expansionIndex,obstacleIndexByLayer:t.obstacleIndexByLayer,options:e.options}]})];getConstructorParams(){return[this.inputProblem]}getOutput(){if(this.rectDiffExpansionSolver)return this.rectDiffExpansionSolver.getOutput();if(this.rectDiffSeedingSolver){return{meshNodes:this.rectDiffSeedingSolver.getOutput().placed.map((t,e)=>({capacityMeshNodeId:`grid-${e}`,center:{x:t.rect.x+t.rect.width/2,y:t.rect.y+t.rect.height/2},width:t.rect.width,height:t.rect.height,availableZ:t.zLayers,layer:`z${t.zLayers.join(",")}`}))}}return{meshNodes:[]}}visualize(){return this.rectDiffExpansionSolver?this.rectDiffExpansionSolver.visualize():this.rectDiffSeedingSolver?this.rectDiffSeedingSolver.visualize():{title:"RectDiff Grid Pipeline",coordinateSystem:"cartesian",rects:[],points:[],lines:[]}}};function Gs(t,e="RectDiff"){const n=[],s=[],o=t.bounds.minX,i=t.bounds.maxX,r=t.bounds.minY,a=t.bounds.maxY;t.outline&&t.outline.length>1?s.push({points:[...t.outline,t.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):n.push({center:{x:(o+i)/2,y:(r+a)/2},width:i-o,height:a-r,fill:"none",stroke:"#111827",label:"board"});for(const e of t.obstacles??[])"rect"!==e.type&&"oval"!==e.type||n.push({center:{x:e.center.x,y:e.center.y},width:e.width,height:e.height,fill:"#fee2e2",stroke:"#ef4444",layer:"obstacle",label:"obstacle"});return{title:e,coordinateSystem:"cartesian",rects:n,points:[],lines:s}}var Js=class extends In{rectDiffGridSolverPipeline;gapFillSolver;boardVoidRects;pipelineDef=[Nn("rectDiffGridSolverPipeline",Zs,t=>[{simpleRouteJson:t.inputProblem.simpleRouteJson,gridOptions:t.inputProblem.gridOptions,boardVoidRects:t.boardVoidRects}]),Nn("gapFillSolver",as,t=>[{meshNodes:t.rectDiffGridSolverPipeline?.getOutput().meshNodes??[],boardVoid:{boardVoidRects:t.boardVoidRects||[],layerCount:t.inputProblem.simpleRouteJson.layerCount||0}}])];_setup(){this.inputProblem.simpleRouteJson.outline&&(this.boardVoidRects=vs({x:this.inputProblem.simpleRouteJson.bounds.minX,y:this.inputProblem.simpleRouteJson.bounds.minY,width:this.inputProblem.simpleRouteJson.bounds.maxX-this.inputProblem.simpleRouteJson.bounds.minX,height:this.inputProblem.simpleRouteJson.bounds.maxY-this.inputProblem.simpleRouteJson.bounds.minY},this.inputProblem.simpleRouteJson.outline??[]))}getConstructorParams(){return[this.inputProblem]}getOutput(){const t=this.gapFillSolver?.getOutput();return t?{meshNodes:t.outputNodes}:this.rectDiffGridSolverPipeline?this.rectDiffGridSolverPipeline.getOutput():{meshNodes:[]}}initialVisualize(){const t=Gs(this.inputProblem.simpleRouteJson,"RectDiffPipeline - Initial"),e=this.rectDiffGridSolverPipeline?.getOutput().meshNodes??[];for(const n of e)t.rects.push({center:n.center,width:n.width,height:n.height,stroke:"rgba(0, 0, 0, 0.3)",fill:"rgba(100, 100, 100, 0.1)",layer:`z${n.availableZ.join(",")}`,label:[`node ${n.capacityMeshNodeId}`,`z:${n.availableZ.join(",")}`].join("\n")});return t}finalVisualize(){const t=Gs(this.inputProblem.simpleRouteJson,"RectDiffPipeline - Final"),{meshNodes:e}=this.getOutput(),n=new Set((this.rectDiffGridSolverPipeline?.getOutput().meshNodes??[]).map(t=>t.capacityMeshNodeId));for(const s of e){const e=!n.has(s.capacityMeshNodeId);t.rects.push({center:s.center,width:s.width,height:s.height,stroke:e?"rgba(0, 128, 0, 0.8)":"rgba(0, 0, 0, 0.3)",fill:e?"rgba(0, 200, 0, 0.3)":"rgba(100, 100, 100, 0.1)",layer:`z${s.availableZ.join(",")}`,label:[`${e?"[expanded] ":""}node ${s.capacityMeshNodeId}`,`z:${s.availableZ.join(",")}`].join("\n")})}return t}},qs=class{tree;constructor(t=9){this.tree=new Ln(t)}insert(t,e,n,s,o){this.tree.insert({minX:e,minY:n,maxX:s,maxY:o,data:t})}bulkLoad(t){const e=t.map(({item:t,minX:e,minY:n,maxX:s,maxY:o})=>({minX:e,minY:n,maxX:s,maxY:o,data:t}));this.tree.load(e)}search(t,e,n,s){return this.tree.search({minX:t,minY:e,maxX:n,maxY:s}).map(t=>t.data)}clear(){this.tree.clear()}},Ks=class{index;items=[];currentIndex=0;capacity;constructor(t){this.capacity=Math.max(1,t),this.index=new Tn(this.capacity)}insert(t,e,n,s,o){if(this.currentIndex>=this.index.numItems)throw new Error("Exceeded initial capacity");this.items[this.currentIndex]=t,this.index.add(e,n,s,o),this.currentIndex++}finish(){this.index.finish()}search(t,e,n,s){return this.index.search(t,e,n,s).map(t=>this.items[t]||null).filter(Boolean)}clear(){this.items=[],this.currentIndex=0,this.index=new Tn(this.capacity)}},Qs=class{idx;storage=[];constructor(t="native",e=[]){"flatbush"===t?0===e.length?(this.idx=new qs,t="rbush"):this.idx=new Ks(e.length):this.idx="rbush"===t?new qs:new class{shi=new to(e);insert(t){}search(t,e,n,s){const o=(t+n)/2,i=(e+s)/2,r=n-t,a=s-e;return this.shi.getNodesInArea(o,i,r,a)}clear(){}},e.forEach(t=>this.insert(t)),"flatbush"===t&&e.length>0&&this.idx.finish?.()}insert(t){this.storage.push(t),this.idx.insert(t,t.center.x-t.width/2,t.center.y-t.height/2,t.center.x+t.width/2,t.center.y+t.height/2)}search(t){return this.idx.search(t.minX,t.minY,t.maxX,t.maxY)}searchArea(t,e,n,s){return this.search({minX:t-n/2,minY:e-s/2,maxX:t+n/2,maxY:e+s/2})}},to=class{constructor(t){this.obstacles=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],s=n.center.x-n.width/2,o=n.center.y-n.height/2,i=n.center.x+n.width/2,r=n.center.y+n.height/2;for(let t=s;t<=i;t+=this.CELL_SIZE)for(let s=o;s<=r;s+=this.CELL_SIZE){const o=this.getBucketKey(t,s),i=this.buckets.get(o);i?i.push([n,e]):this.buckets.set(o,[[n,e]])}}}buckets;CELL_SIZE=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getNodesInArea(t,e,n,s){const o=[],i=new Set,r=e-s/2,a=t+n/2,c=e+s/2;for(let e=t-n/2;e<=a;e+=this.CELL_SIZE)for(let t=r;t<=c;t+=this.CELL_SIZE){const n=this.getBucketKey(e,t),s=this.buckets.get(n)||[];for(const t of s)i.has(t[1])||(i.add(t[1]),o.push(t[0]))}return o}},eo=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 no(t,e){const n=t.x-e.x,s=t.y-e.y;return n*n+s*s}function so(t,e,n){const s=no(e,n);if(0===s)return no(t,e);let o=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/s;o=Math.max(0,Math.min(1,o));return no(t,{x:e.x+o*(n.x-e.x),y:e.y+o*(n.y-e.y)})}function oo(t,e,n,s){if(gt(t,e,n,s))return 0;const o={x:t.x,y:t.y},i={x:e.x,y:e.y},r={x:n.x,y:n.y},a={x:s.x,y:s.y};return Math.min(so(o,r,a),so(i,r,a),so(r,o,i),so(a,o,i))}var io=class{segmentBuckets;viaBuckets;CELL_SIZE;constructor(t,e=1){this.segmentBuckets=new Map,this.viaBuckets=new Map,this.CELL_SIZE=e;for(const e of t)if(e&&e.connectionName){if(e.route&&e.route.length>=2)for(let t=0;t<e.route.length-1;t++){const n=e.route[t],s=e.route[t+1];if(n.x===s.x&&n.y===s.y)continue;if(n.insideJumperPad&&s.insideJumperPad)continue;const o=[n,s],i=eo(o),r={segmentId:`${e.connectionName}-seg-${t}`,segment:o,parentRoute:e},a=Math.floor(i.minX/this.CELL_SIZE),c=Math.floor((i.maxX+1e-9)/this.CELL_SIZE),h=Math.floor(i.minY/this.CELL_SIZE),d=Math.floor((i.maxY+1e-9)/this.CELL_SIZE);for(let t=a;t<=c;t++)for(let e=h;e<=d;e++){const n=`${t}x${e}`;let s=this.segmentBuckets.get(n);s||(s=[],this.segmentBuckets.set(n,s)),s.push(r)}}if(e.vias&&e.vias.length>0)for(let t=0;t<e.vias.length;t++){const n=e.vias[t];if(null==n)continue;const s={viaId:`${e.connectionName}-via-${t}`,x:n.x,y:n.y,parentRoute:e},o=`${Math.floor(n.x/this.CELL_SIZE)}x${Math.floor(n.y/this.CELL_SIZE)}`;let i=this.viaBuckets.get(o);i||(i=[],this.viaBuckets.set(o,i)),i.push(s)}}else console.warn("Skipping route with missing data:",e)}getConflictingRoutesForSegment(t,e,n){const s=eo([t,e]),o=s.minX-n,i=s.minY-n,r=s.maxX+n,a=s.maxY+n,c=Math.floor(o/this.CELL_SIZE),h=Math.floor((r+1e-9)/this.CELL_SIZE),d=Math.floor(i/this.CELL_SIZE),l=Math.floor((a+1e-9)/this.CELL_SIZE),u=new Map,p=new Set,m=new Set,f={x:t.x,y:t.y},g={x:e.x,y:e.y};for(let s=c;s<=h;s++)for(let o=d;o<=l;o++){const i=`${s}x${o}`,r=this.segmentBuckets.get(i);if(r)for(const s of r){if(p.has(s.segmentId))continue;p.add(s.segmentId);const o=s.parentRoute,[i,r]=s.segment,a=n+o.traceThickness/2,c=a*a,h=oo(t,e,i,r);if(h<c){const t=o.connectionName,e=u.get(t);(!e||h<e.minDistSq)&&u.set(t,{route:o,minDistSq:h})}}const a=this.viaBuckets.get(i);if(a)for(const t of a){if(m.has(t.viaId))continue;m.add(t.viaId);const e=t.parentRoute,s={x:t.x,y:t.y},o=n+e.viaDiameter/2,i=o*o,r=so(s,f,g);if(r<i){const t=e.connectionName,n=u.get(t);(!n||r<n.minDistSq)&&u.set(t,{route:e,minDistSq:r})}}}const y=[];for(const t of u.values())y.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return y}removeRoute(t){for(const[e,n]of this.segmentBuckets){const s=n.filter(e=>e.parentRoute.connectionName!==t);0===s.length?this.segmentBuckets.delete(e):s.length!==n.length&&this.segmentBuckets.set(e,s)}for(const[e,n]of this.viaBuckets){const s=n.filter(e=>e.parentRoute.connectionName!==t);0===s.length?this.viaBuckets.delete(e):s.length!==n.length&&this.viaBuckets.set(e,s)}}addRoute(t){if(!t||!t.connectionName)return void console.warn("Skipping route with missing data:",t);if(t.route&&t.route.length>=2)for(let e=0;e<t.route.length-1;e++){const n=t.route[e],s=t.route[e+1];if(n.x===s.x&&n.y===s.y)continue;if(n.insideJumperPad&&s.insideJumperPad)continue;const o=[n,s],i=eo(o),r={segmentId:`${t.connectionName}-seg-${e}`,segment:o,parentRoute:t},a=Math.floor(i.minX/this.CELL_SIZE),c=Math.floor((i.maxX+1e-9)/this.CELL_SIZE),h=Math.floor(i.minY/this.CELL_SIZE),d=Math.floor((i.maxY+1e-9)/this.CELL_SIZE);for(let t=a;t<=c;t++)for(let e=h;e<=d;e++){const n=`${t}x${e}`;let s=this.segmentBuckets.get(n);s||(s=[],this.segmentBuckets.set(n,s)),s.push(r)}}if(t.vias&&t.vias.length>0)for(let e=0;e<t.vias.length;e++){const n=t.vias[e];if(null==n)continue;const s={viaId:`${t.connectionName}-via-${e}`,x:n.x,y:n.y,parentRoute:t},o=`${Math.floor(n.x/this.CELL_SIZE)}x${Math.floor(n.y/this.CELL_SIZE)}`;let i=this.viaBuckets.get(o);i||(i=[],this.viaBuckets.set(o,i)),i.push(s)}}getConflictingRoutesNearPoint(t,e){const n=t.x-e,s=t.y-e,o=t.x+e,i=t.y+e,r=Math.floor(n/this.CELL_SIZE),a=Math.floor((o+1e-9)/this.CELL_SIZE),c=Math.floor(s/this.CELL_SIZE),h=Math.floor((i+1e-9)/this.CELL_SIZE),d=new Map,l=new Set,u=new Set;for(let n=r;n<=a;n++)for(let s=c;s<=h;s++){const o=`${n}x${s}`,i=this.segmentBuckets.get(o);if(i)for(const n of i){if(l.has(n.segmentId))continue;l.add(n.segmentId);const s=n.parentRoute,o={x:n.segment[0].x,y:n.segment[0].y},i={x:n.segment[1].x,y:n.segment[1].y},r=e+s.traceThickness/2,a=r*r,c=so(t,o,i);if(c<a){const t=s.connectionName,e=d.get(t);(!e||c<e.minDistSq)&&d.set(t,{route:s,minDistSq:c})}}const r=this.viaBuckets.get(o);if(r)for(const n of r){if(u.has(n.viaId))continue;u.add(n.viaId);const s=n.parentRoute,o={x:n.x,y:n.y},i=e+s.viaDiameter/2,r=i*i,a=no(t,o);if(a<r){const t=s.connectionName,e=d.get(t);(!e||a<e.minDistSq)&&d.set(t,{route:s,minDistSq:a})}}}const p=[];for(const t of d.values())p.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return p}},ro=class extends y{obstacleSHI;hdRouteSHI;unsimplifiedRoute;routeSections;currentSectionIndex;TRACE_THICKNESS=.15;OBSTACLE_MARGIN=.1;constructor(t){super(),this.currentSectionIndex=0,this.obstacleSHI=t.obstacleSHI,this.hdRouteSHI=t.hdRouteSHI,this.unsimplifiedRoute=t.unsimplifiedRoute,this.routeSections=this.breakRouteIntoSections(this.unsimplifiedRoute)}breakRouteIntoSections(t){const e=[],n=t.route;if(0===n.length)return[];let s={startIndex:0,endIndex:-1,z:n[0].z,points:[n[0]]};for(let t=1;t<n.length;t++)n[t].z===s.z?s.points.push(n[t]):(s.endIndex=t-1,e.push(s),s={startIndex:t,endIndex:-1,z:n[t].z,points:[n[t]]});return s.endIndex=n.length-1,e.push(s),e}_step(){if(this.currentSectionIndex>=this.routeSections.length)return void(this.solved=!0);if(0===this.currentSectionIndex&&this.routeSections.length>1){const t=this.routeSections[0],e=this.routeSections[1];if(t.z!==e.z){const n=e.z,s=t.points[0];if(this.canEndpointConnectOnLayer(s.x,s.y,n)&&this.canSectionMoveToLayer({currentSection:t,targetZ:n}))return t.z=n,t.points=t.points.map(t=>({...t,z:n})),void(this.currentSectionIndex=2)}return void this.currentSectionIndex++}if(this.currentSectionIndex===this.routeSections.length-1){if(this.routeSections.length>=2){const t=this.routeSections[this.routeSections.length-1],e=this.routeSections[this.routeSections.length-2];if(t.z!==e.z){const n=e.z,s=t.points[t.points.length-1];this.canEndpointConnectOnLayer(s.x,s.y,n)&&this.canSectionMoveToLayer({currentSection:t,targetZ:n})&&(t.z=n,t.points=t.points.map(t=>({...t,z:n})))}}return void(this.solved=!0)}const t=this.routeSections[this.currentSectionIndex-1],e=this.routeSections[this.currentSectionIndex],n=this.routeSections[this.currentSectionIndex+1];if(t.z!==n.z)return void this.currentSectionIndex++;const s=t.z;if(this.canSectionMoveToLayer({currentSection:e,targetZ:s}))return e.z=s,e.points=e.points.map(t=>({...t,z:s})),void(this.currentSectionIndex+=2);this.currentSectionIndex++}canEndpointConnectOnLayer(t,e,n){const s=this.obstacleSHI.searchArea(t,e,2,2).filter(n=>{if(!n.connectedTo?.includes(this.unsimplifiedRoute.connectionName))return!1;const s=n.width/2+.05,o=n.height/2+.05,i=Math.abs(t-n.center.x)<=s,r=Math.abs(e-n.center.y)<=o;return i&&r});return!(s.length>0)||s.some(t=>t.zLayers?.includes(n))}canSectionMoveToLayer({currentSection:t,targetZ:e}){for(let n=0;n<t.points.length-1;n++){const s={...t.points[n],z:e},o={...t.points[n+1],z:e},i=this.hdRouteSHI.getConflictingRoutesForSegment(s,o,this.TRACE_THICKNESS);for(const{conflictingRoute:t,distance:e}of i)if(t.connectionName!==this.unsimplifiedRoute.connectionName&&e<this.TRACE_THICKNESS+t.traceThickness)return!1;const r={centerX:(s.x+o.x)/2,centerY:(s.y+o.y)/2,width:Math.abs(s.x-o.x),height:Math.abs(s.y-o.y)},a=this.obstacleSHI.searchArea(r.centerX,r.centerY,r.width+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN),r.height+2*(this.TRACE_THICKNESS+this.OBSTACLE_MARGIN));for(const t of a){if(t.connectedTo?.includes(this.unsimplifiedRoute.connectionName))continue;if(t.zLayers?.includes(e)){if(Math.abs(s.x-t.center.x)<.01&&Math.abs(s.y-t.center.y)<.01||Math.abs(o.x-t.center.x)<.01&&Math.abs(o.y-t.center.y)<.01)continue}if(At(s,o,t)<this.TRACE_THICKNESS+this.OBSTACLE_MARGIN)return!1}}return!0}getConstructorParams(){return{obstacleSHI:this.obstacleSHI,hdRouteSHI:this.hdRouteSHI,unsimplifiedRoute:this.unsimplifiedRoute}}getOptimizedHdRoute(){const t=this.routeSections.flatMap(t=>t.points),e=[];for(let n=0;n<t.length-1;n++)t[n].z!==t[n+1].z&&e.push({x:t[n].x,y:t[n].y});return{connectionName:this.unsimplifiedRoute.connectionName,rootConnectionName:this.unsimplifiedRoute.rootConnectionName,route:t,traceThickness:this.unsimplifiedRoute.traceThickness,vias:e,viaDiameter:this.unsimplifiedRoute.viaDiameter,jumpers:this.unsimplifiedRoute.jumpers}}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Single Route Useless Via Removal Solver"};for(let e=0;e<this.routeSections.length;e++){const n=this.routeSections[e];t.lines.push({points:n.points,strokeWidth:this.TRACE_THICKNESS,strokeColor:e===this.currentSectionIndex?"orange":0===n.z?"red":"blue"})}return t}},ao=class extends y{constructor(t){super(),this.input=t,this.MAX_ITERATIONS=1e6,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.optimizedHdRoutes=[],this.unprocessedRoutes=[...t.unsimplifiedHdRoutes],this.obstacleSHI=new Qs("flatbush",t.obstacles),this.hdRouteSHI=new io(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 ro({hdRouteSHI:this.hdRouteSHI,obstacleSHI:this.obstacleSHI,unsimplifiedRoute:t}):this.solved=!0}getOptimizedHdRoutes(){return this.optimizedHdRoutes}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Useless Via Removal Solver"};for(const e of this.input.obstacles){let n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),o=e.zLayers?.includes(1);s&&o?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":o&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.optimizedHdRoutes){if(0===e.route.length)continue;const n=this.input.colorMap[e.connectionName]||"#888888";for(let n=0;n<e.route.length-1;n++){const s=e.route[n],o=e.route[n+1];s.z===o.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:o.x,y:o.y}],strokeColor:0===s.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const s=Je(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...s.rects??[]),t.lines.push(...s.lines??[])}}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},co=class extends y{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,rootConnectionName:this.inputRoute.rootConnectionName,traceThickness:this.inputRoute.traceThickness,viaDiameter:this.inputRoute.viaDiameter,route:this.newRoute,vias:this.newVias,jumpers:this.inputRoute.jumpers}}isValidPath(t){throw new Error("Not implemented")}_step(){throw new Error("Not implemented")}getVisualsForNewRouteAndObstacles(){const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Simplified Path Solver"};for(let e=0;e<this.inputRoute.route.length-1;e++)t.lines.push({points:[{x:this.inputRoute.route[e].x,y:this.inputRoute.route[e].y},{x:this.inputRoute.route[e+1].x,y:this.inputRoute.route[e+1].y}],strokeColor:"rgba(255, 0, 0, 0.8)",strokeDash:1===this.inputRoute.route[e].z?"5, 5":void 0,layer:`z${this.inputRoute.route[e].z.toString()}`});for(let e=0;e<this.newRoute.length;e++)e<this.newRoute.length-1&&t.lines.push({points:[{x:this.newRoute[e].x,y:this.newRoute[e].y},{x:this.newRoute[e+1].x,y:this.newRoute[e+1].y}],strokeWidth:.15,strokeColor:"rgba(0, 255, 0, 0.8)",strokeDash:1===this.newRoute[e].z?[.4,.4]:void 0,layer:`z${this.newRoute[e].z.toString()}`}),t.points.push({x:this.newRoute[e].x,y:this.newRoute[e].y,color:"rgba(0, 255, 0, 0.8)",label:`z: ${this.newRoute[e].z}`,layer:`z${this.newRoute[e].z.toString()}`});for(const e of this.newVias)t.circles.push({center:e,radius:this.inputRoute.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)"});for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});for(const e of this.otherHdRoutes)for(let n=0;n<e.route.length-1;n++)t.lines.push({points:[{x:e.route[n].x,y:e.route[n].y},{x:e.route[n+1].x,y:e.route[n+1].y}],strokeWidth:.15,strokeColor:0===e.route[n].z?"rgba(255, 0, 255, 0.5)":1===e.route[n].z?"rgba(128, 0, 128, 0.5)":"rgba(0, 0, 255, 0.5)",layer:`z${e.route[n].z.toString()}`});if("filteredObstaclePathSegments"in this){const e=this.filteredObstaclePathSegments;for(const[n,s]of e)t.lines.push({points:[n,s]})}return t}};function ho(t,e,n,s){if(gt(t,e,n,s))return 0;const o=lo(t,n,s),i=lo(e,n,s),r=lo(n,t,e),a=lo(s,t,e);return Math.min(o,i,r,a)}function lo(t,e,n){const s={x:n.x-e.x,y:n.y-e.y},o=uo({x:t.x-e.x,y:t.y-e.y},s);if(o<=0)return po(t,e);const i=uo(s,s);if(i<=o)return po(t,n);const r=o/i;return po(t,{x:e.x+r*s.x,y:e.y+r*s.y})}function uo(t,e){return t.x*e.x+t.y*e.y}function po(t,e){const n=e.x-t.x,s=e.y-t.y;return Math.sqrt(n*n+s*s)}var mo=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)}),fo=class{constructor(t){this.segments=t,this.buckets=new Map;const e=new Map;for(const n of t){const t=this.getSegmentKey(n);if(e.has(t))continue;e.set(t,n);const s=mo(n),o=Math.floor(s.minX/this.CELL_SIZE),i=Math.floor(s.maxX/this.CELL_SIZE),r=Math.floor(s.minY/this.CELL_SIZE),a=Math.floor(s.maxY/this.CELL_SIZE);for(let e=o;e<=i;e++)for(let s=r;s<=a;s++){const o=`${e}x${s}`,i=this.buckets.get(o),r=[n[0],n[1],t];i?i.push(r):this.buckets.set(o,[r])}}}buckets;CELL_SIZE=.4;SEGMENT_MARGIN=.4;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getSegmentKey(t){return`${t[0].x}-${t[0].y}-${t[0].z}-${t[1].x}-${t[1].y}-${t[1].z}`}getSegmentsThatCouldIntersect(t,e){const n=[],s=new Set,o=Math.min(t.x,e.x)-this.SEGMENT_MARGIN,i=Math.min(t.y,e.y)-this.SEGMENT_MARGIN,r=Math.max(t.x,e.x)+this.SEGMENT_MARGIN,a=Math.max(t.y,e.y)+this.SEGMENT_MARGIN,c=Math.floor(o/this.CELL_SIZE),h=Math.floor(r/this.CELL_SIZE),d=Math.floor(i/this.CELL_SIZE),l=Math.floor(a/this.CELL_SIZE);for(let t=c;t<=h;t++)for(let e=d;e<=l;e++){const o=`${t}x${e}`,i=this.buckets.get(o);if(i)for(const t of i){const e=t[2];s.has(e)||(s.add(e),n.push(t))}}return n}},go=1e-6,yo=(t,e,n)=>vt(t,e,n)<=go,xo=(t,e)=>Math.abs(t.x-e.x)<=go&&Math.abs(t.y-e.y)<=go,vo=(t,e)=>{if(!e||e.length<3)return!1;for(let n=0;n<e.length;n++){const s=e[n],o=e[(n+1)%e.length];if(yo(t,s,o))return!0}let n=!1;for(let s=0,o=e.length-1;s<e.length;o=s++){const i=e[s],r=e[o];i.y>t.y!=r.y>t.y&&t.x<(r.x-i.x)*(t.y-i.y)/(r.y-i.y)+i.x&&(n=!n)}return n},So=class extends co{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=[];filteredJumperPads=[];jumperPadPointIndices=new Set;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=mt(t),s=mt(e),o=Math.max(n.minX-s.maxX,s.minX-n.maxX,0),i=Math.max(n.minY-s.maxY,s.minY-n.maxY,0);return Math.hypot(o,i)}(n,t)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2}),this.filteredObstaclePathSegments=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const n=t.route,s=[];for(let t=0;t<n.length-1;t++){const o=n[t],i=n[t+1],r=Math.min(o.x,i.x),a=Math.max(o.x,i.x),c=Math.min(o.y,i.y),h=Math.max(o.y,i.y);r<=e.maxX&&a>=e.minX&&c<=e.maxY&&h>=e.minY&&s.push([o,i])}return s}),this.segmentTree=new fo(this.filteredObstaclePathSegments),this.filteredVias=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const n=t.vias,s=[];for(const o of n){const n=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2+t.viaDiameter/2,i=o.x-n,r=o.x+n,a=o.y-n,c=o.y+n;i<=e.maxX&&r>=e.minX&&a<=e.maxY&&c>=e.minY&&s.push({...o,diameter:t.viaDiameter})}return s});const s=(t,n)=>{const s=[];for(const o of t){const t=Ze[o.footprint]??Ze["0603"],i=o.end.x-o.start.x,r=o.end.y-o.start.y,a=Math.abs(i)>Math.abs(r),c=a?t.padLength:t.padWidth,h=a?t.padWidth:t.padLength,d=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2;o.start.x-c/2-d<=e.maxX&&o.start.x+c/2+d>=e.minX&&o.start.y-h/2-d<=e.maxY&&o.start.y+h/2+d>=e.minY&&s.push({center:o.start,width:c,height:h,connectionName:n}),o.end.x-c/2-d<=e.maxX&&o.end.x+c/2+d>=e.minX&&o.end.y-h/2-d<=e.maxY&&o.end.y+h/2+d>=e.minY&&s.push({center:o.end,width:c,height:h,connectionName:n})}return s};if(this.filteredJumperPads=this.otherHdRoutes.flatMap(t=>this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName)?[]:s(t.jumpers??[],t.connectionName)),this.inputRoute.jumpers&&this.inputRoute.jumpers.length>0){this.filteredJumperPads.push(...s(this.inputRoute.jumpers,this.inputRoute.connectionName));for(const t of this.inputRoute.jumpers)for(let e=0;e<this.inputRoute.route.length;e++){const n=this.inputRoute.route[e];(Math.abs(n.x-t.start.x)<.01&&Math.abs(n.y-t.start.y)<.01||Math.abs(n.x-t.end.x)<.01&&Math.abs(n.y-t.end.y)<.01)&&this.jumperPadPointIndices.add(e)}}this.computePathSegments()}computePathSegments(){let t=0;for(let e=0;e<this.inputRoute.route.length-1;e++){const n=this.inputRoute.route[e],s=this.inputRoute.route[e+1],o=Math.sqrt((s.x-n.x)**2+(s.y-n.y)**2)+e/1e4;this.pathSegments.push({start:n,end:s,length:o,startDistance:t,endDistance:t+o}),t+=o}this.totalPathLength=t}arePointsEqual(t,e){return t.x===e.x&&t.y===e.y&&t.z===e.z}getPointAtDistance(t){t=Math.max(0,Math.min(t,this.totalPathLength));const e=this.pathSegments.find(e=>t>=e.startDistance&&t<=e.endDistance);if(!e)return this.inputRoute.route[this.inputRoute.route.length-1];const n=(t-e.startDistance)/e.length;return{x:e.start.x+n*(e.end.x-e.start.x),y:e.start.y+n*(e.end.y-e.start.y),z:n<.5?e.start.z:e.end.z}}getNearestIndexForDistance(t){if(t<=0)return 0;if(t>=this.totalPathLength)return this.inputRoute.route.length-1;const e=this.pathSegments.findIndex(e=>t>=e.startDistance&&t<=e.endDistance);if(-1===e)return 0;const n=this.pathSegments[e],s=(n.startDistance+n.endDistance)/2;return t>s?e+1:e}isValidPathSegment(t,e){for(const n of this.filteredObstacles){if(!n.zLayers?.includes(t.z))continue;if(At(t,e,n)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2)return!1}const n=this.segmentTree.getSegmentsThatCouldIntersect(t,e);for(const[s,o,i]of n)if(s.z===t.z&&o.z===t.z){if(ho({x:t.x,y:t.y},{x:e.x,y:e.y},{x:s.x,y:s.y},{x:o.x,y:o.y})<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS)return!1}for(const n of this.filteredVias)if(vt(n,t,e)<this.OBSTACLE_MARGIN+n.diameter/2+this.TRACE_THICKNESS/2)return!1;for(const n of this.filteredJumperPads){if(At(t,e,n)<this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2)return!1}if(this.outline&&this.outline.length>=3){const n=(({start:t,end:e,polygon:n,margin:s=.2})=>{if(!n||n.length<3)return!1;const o=vo(t,n),i=vo(e,n);if(!o||!i)return!0;for(let o=0;o<n.length;o++){const i=n[o],r=n[(o+1)%n.length],a=yo(t,i,r),c=yo(e,i,r);if(a&&c)continue;if(!gt(t,e,i,r)){if(!a&&!c&&ho(t,e,i,r)<s-go)return!0;continue}const h=Pt(t,e,i,r);if(!(h&&(a&&xo(h,t)||c&&xo(h,e))||h&&(xo(h,t)||xo(h,e))))return!0}return!1})({start:{x:t.x,y:t.y},end:{x:e.x,y:e.y},polygon:this.outline});if(n)return!1}return!0}isValidPath(t){if(t.length<2)return!0;for(let e=0;e<t.length-1;e++)if(t[e].z!==t[e+1].z)return!1;for(let e=0;e<t.length-1;e++)if(!this.isValidPathSegment(t[e],t[e+1]))return!1;return!0}find45DegreePath(t,e){if(this.arePointsEqual(t,e))return[t];if(t.z!==e.z)return null;const n=((t,e)=>{const n=[],s=Math.abs(e.x-t.x),o=Math.abs(e.y-t.y),i=e.x>t.x?1:-1,r=e.y>t.y?1:-1,a={x:e.x-i*Math.abs(e.y-t.y),y:t.y};(a.x-t.x)*i>=0&&(a.x-e.x)*i<=0&&n.push([t,a,e]);const c={x:t.x,y:e.y-r*Math.abs(e.x-t.x)};(c.y-t.y)*r>=0&&(c.y-e.y)*r<=0&&n.push([t,c,e]);const h=Math.min(s,o),d={x:t.x+i*h,y:t.y+r*h};return(d.x-t.x)*i>=0&&(d.x-e.x)*i<=0&&(d.y-t.y)*r>=0&&(d.y-e.y)*r<=0&&n.push([t,d,e]),n})({x:t.x,y:t.y},{x:e.x,y:e.y});for(const e of n){const n=e.map(e=>({x:e.x,y:e.y,z:t.z}));if(this.isValidPath(n))return n}return null}addPathToResult(t){if(0!==t.length){for(let e=0;e<t.length;e++)0===e&&this.newRoute.length>0&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t[e])||this.newRoute.push(t[e]);this.currentStepSize=this.maxStepSize}}moveHead(t){this.lastHeadMoveDistance=t,this.headDistanceAlongPath=Math.min(this.headDistanceAlongPath+t,this.totalPathLength)}stepBackAndReduceStepSize(){this.headDistanceAlongPath=Math.max(this.tailDistanceAlongPath,this.headDistanceAlongPath-this.lastHeadMoveDistance),this.currentStepSize=Math.max(this.minStepSize,this.currentStepSize*this.STEP_SIZE_REDUCTION_FACTOR)}_step(){const t=this.tailDistanceAlongPath>=this.totalPathLength,e=this.headDistanceAlongPath>=this.totalPathLength;if(t){const t=this.inputRoute.route[this.inputRoute.route.length-1];return 0!==this.newRoute.length&&this.arePointsEqual(this.newRoute[this.newRoute.length-1],t)||this.newRoute.push(t),void(this.solved=!0)}if(e){const t=this.getPointAtDistance(this.tailDistanceAlongPath),e=this.inputRoute.route[this.inputRoute.route.length-1],n=this.find45DegreePath(t,e);if(n)return this.addPathToResult(n),void(this.solved=!0);this.lastValidPath=null,this.tailDistanceAlongPath=this.totalPathLength,this.headDistanceAlongPath=this.totalPathLength;const s=[];for(const t of this.inputRoute.route)0!==s.length&&this.arePointsEqual(s[s.length-1],t)||s.push(t);return this.newRoute=s,this.newVias=[...this.inputRoute.vias],void(this.solved=!0)}this.moveHead(this.currentStepSize);const n=this.getPointAtDistance(this.tailDistanceAlongPath),s=this.getPointAtDistance(this.headDistanceAlongPath),o=this.getNearestIndexForDistance(this.tailDistanceAlongPath),i=this.getNearestIndexForDistance(this.headDistanceAlongPath);let r=!1,a=-1;for(let t=o;t<i;t++)if(t+1<this.inputRoute.route.length&&this.inputRoute.route[t].z!==this.inputRoute.route[t+1].z){r=!0;const e=t;a=this.pathSegments[e].startDistance;break}if(r&&this.lastHeadMoveDistance>this.minStepSize)return void this.stepBackAndReduceStepSize();let c=!1,h=-1,d=-1;for(let t=o+1;t<=i;t++)if(this.jumperPadPointIndices.has(t)){c=!0,h=t,d=t>0&&t-1<this.pathSegments.length?this.pathSegments[t-1].endDistance:this.pathSegments[0]?.startDistance??0;break}if(c&&this.lastHeadMoveDistance>this.minStepSize)return void this.stepBackAndReduceStepSize();if(c&&h>=0){const t=this.inputRoute.route[h];this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null);const e=this.newRoute[this.newRoute.length-1];return e&&e.x===t.x&&e.y===t.y||this.newRoute.push({x:t.x,y:t.y,z:t.z}),this.currentStepSize=this.maxStepSize,this.tailDistanceAlongPath=d,this.headDistanceAlongPath=this.tailDistanceAlongPath,this.lastValidPath=null,void(this.lastValidPathHeadDistance=this.tailDistanceAlongPath)}if(r&&a>0){const t=this.getNearestIndexForDistance(a)+1,e=this.inputRoute.route[t],n={x:e.x,y:e.y};this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null);const s=this.newRoute[this.newRoute.length-1];s.x===n.x&&s.y===n.y||this.newRoute.push({x:n.x,y:n.y,z:s.z}),this.newVias.push(n),this.newRoute.push({x:n.x,y:n.y,z:e.z}),this.currentStepSize=this.maxStepSize;const o=this.pathSegments.findIndex(t=>t.start===e);if(-1!==o)this.tailDistanceAlongPath=this.pathSegments[o].startDistance,this.headDistanceAlongPath=this.tailDistanceAlongPath,this.lastValidPath=null,this.lastValidPathHeadDistance=this.tailDistanceAlongPath;else if(t<this.inputRoute.route.length){if(t===this.inputRoute.route.length-1)return void(this.solved=!0);console.warn("Fallback used for tailDistanceAlongPath after layer change");const e=this.pathSegments.find(e=>e.start===this.inputRoute.route[t]);e?(this.tailDistanceAlongPath=e.startDistance,this.headDistanceAlongPath=this.tailDistanceAlongPath,this.lastValidPath=null,this.lastValidPathHeadDistance=this.tailDistanceAlongPath):(console.error(`[${this.inputRoute.connectionName}] Could not find segment start after layer change. Path might be incomplete.\n Index sought: ${t}, Point: (${this.inputRoute.route[t].x.toFixed(3)}, ${this.inputRoute.route[t].y.toFixed(3)}, z=${this.inputRoute.route[t].z})\n Route Length: ${this.inputRoute.route.length}, Path Segments: ${this.pathSegments.length}`),this.solved=!0)}else console.warn("Layer change occurred at the end of the path."),this.solved=!0;return}const l=this.find45DegreePath(n,s);if(!l&&this.lastHeadMoveDistance>this.minStepSize)this.stepBackAndReduceStepSize();else{if(!l&&!this.lastValidPath){const t=this.getPointAtDistance(this.tailDistanceAlongPath);this.tailDistanceAlongPath+=this.minStepSize,this.moveHead(this.minStepSize);const e=this.getNearestIndexForDistance(this.tailDistanceAlongPath),n=this.inputRoute.route[e],s=this.inputRoute.route[this.inputRoute.route.length-1];return void(this.arePointsEqual(t,n)||this.arePointsEqual(n,s)||this.newRoute.push(n))}if(l)return this.lastValidPath=l,void(this.lastValidPathHeadDistance=this.headDistanceAlongPath);this.lastValidPath&&(this.addPathToResult(this.lastValidPath),this.lastValidPath=null,this.tailDistanceAlongPath=this.lastValidPathHeadDistance,this.moveHead(this.minStepSize))}}visualize(){const t=this.getVisualsForNewRouteAndObstacles(),e=this.getPointAtDistance(this.tailDistanceAlongPath),n=this.getPointAtDistance(this.headDistanceAlongPath);t.points.push({x:e.x,y:e.y,color:"yellow",label:["Tail",`z: ${e.z}`].join("\n")}),t.points.push({x:n.x,y:n.y,color:"orange",label:["Head",`z: ${n.z}`].join("\n")});const s=this.getPointAtDistance(this.headDistanceAlongPath+this.currentStepSize);t.points.push({x:s.x,y:s.y,color:"red",label:["Tentative Head",`z: ${s.z}`].join("\n")});let o=0;for(;o<this.totalPathLength;){const e=this.getPointAtDistance(o);t.circles.push({center:{x:e.x,y:e.y},radius:.05,fill:"rgba(100, 100, 100, 0.5)"}),o+=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}},Po=class extends y{simplifiedHdRoutes;currentUnsimplifiedHdRouteIndex=0;activeSubSolver=null;unsimplifiedHdRoutes;obstacles;connMap;colorMap;outline;defaultViaDiameter;constructor(t){super(),this.MAX_ITERATIONS=1e8,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.obstacles=t.obstacles,this.connMap=t.connMap||new Fe({}),this.colorMap=t.colorMap||{},this.outline=t.outline,this.defaultViaDiameter=t.defaultViaDiameter??.6,this.simplifiedHdRoutes=[]}_step(){const t=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];if(!this.activeSubSolver)return t?(this.activeSubSolver=new So({inputRoute:t,otherHdRoutes:this.unsimplifiedHdRoutes.slice(this.currentUnsimplifiedHdRouteIndex+1).concat(this.simplifiedHdRoutes),obstacles:this.obstacles,connMap:this.connMap,colorMap:this.colorMap,outline:this.outline}),void this.currentUnsimplifiedHdRouteIndex++):void(this.solved=!0);this.activeSubSolver.step(),this.activeSubSolver.solved&&(this.simplifiedHdRoutes.push(this.activeSubSolver.simplifiedRoute),this.activeSubSolver=null)}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:"Multi Simplified Path Solver"};for(const e of this.unsimplifiedHdRoutes)if(!this.simplifiedHdRoutes.some(t=>t.connectionName===e.connectionName)){for(let n=0;n<e.route.length-1;n++)t.lines.push({points:[{x:e.route[n].x,y:e.route[n].y},{x:e.route[n+1].x,y:e.route[n+1].y}],strokeColor:1===e.route[n].z?"rgba(0, 0, 255, 0.4)":"rgba(255, 0, 0, 0.4)",strokeWidth:.15,strokeDash:1===e.route[n].z?[.5,.5]:void 0});for(const n of e.vias||[])t.circles.push({center:n,radius:(e.viaDiameter??this.defaultViaDiameter)/2,fill:"rgba(0, 0, 255, 0.4)"})}for(const e of this.simplifiedHdRoutes){const n=this.colorMap?.[e.connectionName]||"rgba(128, 128, 128, 0.8)";for(let s=0;s<e.route.length-1;s++)t.lines.push({points:[{x:e.route[s].x,y:e.route[s].y},{x:e.route[s+1].x,y:e.route[s+1].y}],strokeWidth:.15,strokeColor:n,strokeDash:1===e.route[s].z?[.5,.5]:void 0,step:1});for(const n of e.vias||[])t.circles.push({center:n,radius:e.viaDiameter/2,fill:"rgba(0, 0, 255, 0.5)",step:1})}for(const e of this.unsimplifiedHdRoutes){for(let n=0;n<e.route.length-1;n++)t.lines.push({points:[{x:e.route[n].x,y:e.route[n].y},{x:e.route[n+1].x,y:e.route[n+1].y}],strokeWidth:.15,strokeColor:"rgba(255, 0, 0, 0.2)",strokeDash:[.5,.5],step:0,layer:`z${e.route[n].z.toString()}`});for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 0, 0.2)",step:0})}for(const e of this.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:e.layers?.includes("top")?"rgba(255, 0, 0, 0.3)":e.layers?.includes("bottom")?"rgba(0, 0, 255, 0.3)":"rgba(128, 128, 128, 0.3)"});if(this.currentUnsimplifiedHdRouteIndex<this.unsimplifiedHdRoutes.length){const e=this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];e.route.length>0&&t.circles.push({center:{x:e.route[0].x,y:e.route[0].y},radius:.2,fill:"yellow",label:"Current"})}return t}},bo=class extends y{constructor(t){super(),this.input=t,this.MAX_ITERATIONS=1e6,this.inputHdRoutes=t.inputHdRoutes,this.mergedViaHdRoutes=structuredClone(this.inputHdRoutes),this.unprocessedRoutes=[...t.inputHdRoutes],this.colorMap=t.colorMap,this.outline=t.outline,this.obstacles=t.obstacles,this.obstacleSHI=new Qs("flatbush",t.obstacles),this.hdRouteSHI=new io(this.inputHdRoutes),this.vias=[],this.offendingVias=[],this.connMap=t.connMap,this.viasByNet=new Map,this.rebuildVias()}inputHdRoutes;mergedViaHdRoutes;unprocessedRoutes;vias;offendingVias;currentViaRoutes=[];connMap;colorMap;outline;obstacles;viasByNet;obstacleSHI=null;hdRouteSHI=null;rebuildVias(){this.vias=[],this.viasByNet=new Map;for(let t=0;t<this.mergedViaHdRoutes.length;t++){const e=this.mergedViaHdRoutes[t];for(let n=0;n<e.vias.length;n++){const s=e.vias[n],o={x:s.x,y:s.y,diameter:e.viaDiameter,net:this.connMap?.idToNetMap[e.connectionName]??"",layers:[...new Set(e.route.map(t=>t.z))],routeIndex:t};this.vias.push(o);const i=this.viasByNet.get(o.net);i?i.push(o):this.viasByNet.set(o.net,[o])}}}findNextOffendingPair(){for(let t=0;t<this.vias.length-1;t++){const e=this.vias[t],n=this.viasByNet.get(e.net);if(!n)continue;const s=n.indexOf(e);for(let t=s>=0?s+1:0;t<n.length;t++){const s=n[t],o=e.x-s.x,i=e.y-s.y,r=o*o+i*i,a=e.diameter/2+s.diameter/2;if(r<=a*a&&0!==r)return[e,s]}}return null}handleOffendingPair(t,e){const n=t.layers.length<e.layers.length?t:e,s=n===t?e:t,o=this.mergedViaHdRoutes[n.routeIndex].route;for(let t=0;t<n.layers.length;t++)for(let t=o.length-1;t>=1;t--){const e=o[t-1],i=o[t];if(i.x===n.x&&i.y===n.y){o.splice(t,0,{x:s.x,y:s.y,z:i.z}),o.splice(t,0,{x:s.x,y:s.y,z:e.z});const r=this.mergedViaHdRoutes[n.routeIndex];return r.vias=r.vias.map(t=>t.x===n.x&&t.y===n.y?{x:s.x,y:s.y}:t),void this.rebuildVias()}}this.rebuildVias()}_step(){const t=this.findNextOffendingPair();t?this.handleOffendingPair(t[0],t[1]):this.solved=!0}getMergedViaHdRoutes(){return this.mergedViaHdRoutes}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Same Net Via Merger Solver"};for(const e of this.input.obstacles){let n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),o=e.zLayers?.includes(1);s&&o?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":o&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.mergedViaHdRoutes){if(0===e.route.length)continue;const n=this.input.colorMap[e.connectionName]||"#888888";for(let n=0;n<e.route.length-1;n++){const s=e.route[n],o=e.route[n+1];s.z===o.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:o.x,y:o.y}],strokeColor:0===s.z?"rgba(255, 0, 0, 0.5)":"rgba(0, 0, 255, 0.5)",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const s=Je(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...s.rects??[]),t.lines.push(...s.lines??[])}}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},Mo=class extends y{constructor(t){super(),this.simplificationConfig=t,this.hdRoutes=[...t.hdRoutes],this.MAX_ITERATIONS=1e8}hdRoutes=[];simplificationPipelineLoops=0;MAX_SIMPLIFICATION_PIPELINE_LOOPS=2;PHASE_ORDER=["via_removal","via_merging","path_simplification"];currentPhase="via_removal";extractResult=null;get simplifiedHdRoutes(){return this.hdRoutes}_step(){if(this.simplificationPipelineLoops>=this.MAX_SIMPLIFICATION_PIPELINE_LOOPS)this.solved=!0;else{if(this.activeSubSolver){if(this.activeSubSolver.step(),!this.activeSubSolver.failed&&!this.activeSubSolver.solved)return;if(this.activeSubSolver.solved){if(this.extractResult&&(this.hdRoutes=this.extractResult(this.activeSubSolver)),this.activeSubSolver=null,this.extractResult=null,"via_removal"===this.currentPhase?this.currentPhase="via_merging":"via_merging"===this.currentPhase?this.currentPhase="path_simplification":(this.currentPhase="via_removal",this.simplificationPipelineLoops++),this.simplificationPipelineLoops>=this.MAX_SIMPLIFICATION_PIPELINE_LOOPS)return void(this.solved=!0)}else if(this.activeSubSolver.failed)return this.failed=!0,void(this.error=this.activeSubSolver.error??"Sub-solver failed without error message")}if(!this.activeSubSolver&&!this.solved)switch(this.currentPhase){case"via_removal":this.activeSubSolver=new ao({unsimplifiedHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,colorMap:this.simplificationConfig.colorMap,layerCount:this.simplificationConfig.layerCount}),this.extractResult=t=>t.getOptimizedHdRoutes()??[];break;case"via_merging":this.activeSubSolver=new bo({inputHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,colorMap:this.simplificationConfig.colorMap,layerCount:this.simplificationConfig.layerCount,connMap:this.simplificationConfig.connMap,outline:this.simplificationConfig.outline}),this.extractResult=t=>t.getMergedViaHdRoutes()??[];break;case"path_simplification":this.activeSubSolver=new Po({unsimplifiedHdRoutes:this.hdRoutes,obstacles:this.simplificationConfig.obstacles,connMap:this.simplificationConfig.connMap,colorMap:this.simplificationConfig.colorMap,outline:this.simplificationConfig.outline,defaultViaDiameter:this.simplificationConfig.defaultViaDiameter}),this.extractResult=t=>t.simplifiedHdRoutes;break;default:this.failed=!0,this.error=`Unknown phase: ${this.currentPhase}`}}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Trace Simplification Solver"};for(const e of this.simplificationConfig.obstacles){let n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),o=e.zLayers?.includes(1);s&&o?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":o&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}for(const e of this.hdRoutes)if(0!==e.route.length){for(let n=0;n<e.route.length-1;n++){const s=e.route[n],o=e.route[n+1];s.z===o.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:o.x,y:o.y}],strokeColor:0===s.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const n=Je(e.jumpers,{color:"orange",label:e.connectionName});t.rects.push(...n.rects??[]),t.lines.push(...n.lines??[])}}return t}};function No(t){const e=new Map;for(const n of t)for(const t of n.nodeIds)e.set(t,[...e.get(t)??[],n]);return e}var Io=class extends y{nodes;edges;traceWidth;obstacleMargin;minPortSpacing;nodeMap;nodeEdgeMap;sharedEdgeSegments=[];edgeSegmentMap=new Map;portPointMap=new Map;colorMap;constructor({nodes:t,edges:e,traceWidth:n,obstacleMargin:s,colorMap:o}){super(),this.nodes=t,this.edges=e,this.traceWidth=n,this.obstacleMargin=s??.15,this.minPortSpacing=this.traceWidth+this.obstacleMargin,this.colorMap=o??{},this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=No(e),this.MAX_ITERATIONS=1}_step(){this.computeAllSharedEdgeSegments(),this.solved=!0}computeAllSharedEdgeSegments(){for(const t of this.edges){const[e,n]=t.nodeIds,s=this.nodeMap.get(e),o=this.nodeMap.get(n);if(!s||!o)continue;const i=this.computeSharedEdgeSegment(t,s,o);if(i){this.sharedEdgeSegments.push(i),this.edgeSegmentMap.set(t.capacityMeshEdgeId,i);for(const t of i.portPoints)this.portPointMap.set(t.segmentPortPointId,t)}}}computeSharedEdgeSegment(t,e,n){const s=this.findOverlappingSegment(e,n);if(!s)return null;const o=e.availableZ.filter(t=>n.availableZ.includes(t));if(0===o.length)return null;const i=Math.sqrt((s.end.x-s.start.x)**2+(s.end.y-s.start.y)**2),r=3*this.minPortSpacing/4,a=Math.max(0,i-2*r);if(a<=0&&!e._containsTarget&&!n._containsTarget)return null;let c=Math.max(1,Math.floor(a/this.minPortSpacing)+1);if(e._offBoardConnectionId||n._offBoardConnectionId){if(e._offBoardConnectionId&&!n._offBoardConnectionId){if(this.shouldSkipOffBoardPortPoint(e,n))return null}else if(n._offBoardConnectionId&&!e._offBoardConnectionId&&this.shouldSkipOffBoardPortPoint(n,e))return null;c=1}const h=[],d=s.end.x-s.start.x,l=s.end.y-s.start.y,u=(s.start.x+s.end.x)/2,p=(s.start.y+s.end.y)/2;c>5&&(c=5+Math.floor(c/4));const m=[];for(let t=0;t<c;t++){let e;e=0===i||1===c?.5:(r+a*t/(c-1))/i;const n=s.start.x+d*e,o=s.start.y+l*e,h=Math.sqrt((n-u)**2+(o-p)**2);m.push({x:n,y:o,distToCenter:h})}const f=m.reduce((t,e)=>e.distToCenter<t.distToCenter?e:t);for(let s=0;s<c;s++){const{x:i,y:r}=m[s],a=Math.sqrt((i-f.x)**2+(r-f.y)**2);for(const c of o){const o={segmentPortPointId:`${t.capacityMeshEdgeId}_pp${s}_z${c}`,x:i,y:r,availableZ:[c],nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],edgeId:t.capacityMeshEdgeId,connectionName:null,distToCentermostPortOnZ:a};h.push(o)}}return{edgeId:t.capacityMeshEdgeId,nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],start:s.start,end:s.end,availableZ:o,portPoints:h}}shouldSkipOffBoardPortPoint(t,e){const n=this.nodeEdgeMap.get(e.capacityMeshNodeId)??[];for(const s of n){const n=s.nodeIds[0]===e.capacityMeshNodeId?s.nodeIds[1]:s.nodeIds[0];if(n===t.capacityMeshNodeId)continue;const o=this.nodeMap.get(n);if(o?._offBoardConnectionId!==t._offBoardConnectionId)continue;if(2!==this.nodes.filter(e=>e._offBoardConnectionId===t._offBoardConnectionId).length)continue;const i={x:(t.center.x+o.center.x)/2,y:(t.center.y+o.center.y)/2};if(i.x>=e.center.x-e.width/2&&i.x<=e.center.x+e.width/2&&i.y>=e.center.y-e.height/2&&i.y<=e.center.y+e.height/2)return!0}return!1}findOverlappingSegment(t,e){const n={start:Math.max(t.center.x-t.width/2,e.center.x-e.width/2),end:Math.min(t.center.x+t.width/2,e.center.x+e.width/2)},s={start:Math.max(t.center.y-t.height/2,e.center.y-e.height/2),end:Math.min(t.center.y+t.height/2,e.center.y+e.height/2)},o=n.end-n.start,i=s.end-s.start;if(o<-1e-4||i<-1e-4)return null;if(o<i){const t=(n.start+n.end)/2;return{start:{x:t,y:s.start},end:{x:t,y:s.end}}}{const t=(s.start+s.end)/2;return{start:{x:n.start,y:t},end:{x:n.end,y:t}}}}getAvailablePortPointsBetweenNodes(t,e){const n=this.edges.find(n=>n.nodeIds[0]===t&&n.nodeIds[1]===e||n.nodeIds[0]===e&&n.nodeIds[1]===t);if(!n)return[];const s=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return s?s.portPoints.filter(t=>null===t.connectionName):[]}getPortPointsForEdge(t,e){const n=this.edges.find(n=>n.nodeIds[0]===t&&n.nodeIds[1]===e||n.nodeIds[0]===e&&n.nodeIds[1]===t);if(!n)return[];const s=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return s?.portPoints??[]}assignPortPoint(t,e,n){const s=this.portPointMap.get(t);return!!s&&(null===s.connectionName&&(s.connectionName=e,s.rootConnectionName=n,!0))}releasePortPoint(t){const e=this.portPointMap.get(t);return!!e&&(e.connectionName=null,e.rootConnectionName=void 0,!0)}getAvailablePortCountForEdge(t,e){return this.getAvailablePortPointsBetweenNodes(t,e).length}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.sharedEdgeSegments){t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.5)"});for(const n of e.portPoints){const e=n.connectionName?this.colorMap[n.connectionName]??"blue":"rgba(0, 200, 0, 0.7)";t.circles.push({center:{x:n.x,y:n.y},radius:this.traceWidth/2,fill:e,layer:`z${n.availableZ.join(",")}`,label:[n.segmentPortPointId,n.connectionName,n.availableZ.join(","),`cd: ${n.distToCentermostPortOnZ}`,`connects: ${n.nodeIds.join(",")}`].filter(Boolean).join("\n")})}}return t}},Co=(t,e,n,s)=>{if(t?._containsTarget)return 0;if(1===(t.availableZ?.length??2)&&(e>0||n>0||s>0))return 1;return((.82*e+.41*n+.2*s)/2)**1.1/ke(t)};function _o(t,e,n,s,o){const i=n-e,r=o-s,a=1e-6;if(Math.abs(t.y-o)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(o-t.y);if(Math.abs(t.y-s)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-s);const c=Math.abs(t.y-o),h=Math.abs(t.x-n),d=Math.abs(t.y-s),l=Math.abs(t.x-e),u=Math.min(c,h,d,l);return u===c?Math.max(0,Math.min(i,t.x-e)):u===h?i+Math.max(0,Math.min(r,o-t.y)):u===d?i+r+Math.max(0,Math.min(i,n-t.x)):2*i+r+Math.max(0,Math.min(r,t.y-s))}function To(t,e,n=1e-6){return Math.abs(t-e)<n}function Eo(t){if(t.length<2)return 0;const e=t.map(([t,e])=>t<e?[t,e]:[e,t]);let n=0;for(let t=0;t<e.length;t++){const[s,o]=e[t];for(let i=t+1;i<e.length;i++){const[t,r]=e[i];To(s,t)||To(s,r)||To(o,t)||To(o,r)||(s<t&&t<o&&o<r||t<s&&s<r&&r<o)&&n++}}return n}var Ro=t=>{const e=t.center.x-t.width/2,n=t.center.x+t.width/2,s=t.center.y-t.height/2,o=t.center.y+t.height/2,i=new Map;for(const e of t.portPoints){const t=i.get(e.connectionName)??[];t.some(t=>t.x===e.x&&t.y===e.y&&t.z===e.z)||t.push({x:e.x,y:e.y,z:e.z}),i.set(e.connectionName,t)}const r=new Map,a=[];let c=0;for(const[t,h]of i){if(h.length<2)continue;const t=h[0],i=h[1],d=_o(t,e,n,s,o),l=_o(i,e,n,s,o);if(t.z===i.z){const e=t.z,n=r.get(e)??[];n.push([d,l]),r.set(e,n)}else c++,a.push([d,l])}let h=0;for(const[t,e]of r)h+=Eo(e);return{numSameLayerCrossings:h,numEntryExitLayerChanges:c,numTransitionPairCrossings:Eo(a)}},wo=(t,e)=>{const n=Math.ceil(e/7),s=(Math.floor(t.width/5)+.1)*(Math.floor(t.height/5.5)+.1);return Math.min(1,n/s)};function Ao(t,e,n,s){const o=e.x-n/2,i=e.x+n/2,r=e.y-s/2,a=e.y+s/2,c=Math.abs(t.y-a),h=Math.abs(t.x-i),d=Math.abs(t.y-r),l=Math.abs(t.x-o),u=Math.min(c,h,d,l);return u>.001?"interior":u===c?"top":u===h?"right":u===d?"bottom":"left"}function Oo(t,e,n,s,o){const i=Ao(t,n,s,o),r=Ao(e,n,s,o);return"interior"!==i&&i===r}function zo(t,e,n,s,o){const i=Ao(t,n,s,o);let r;if("top"===i||"bottom"===i){const n=s;r=Math.abs(e.x-t.x)/n}else{const n=o;r=Math.abs(e.y-t.y)/n}r=Math.min(1,Math.max(0,r));const a=(t.x+e.x)/2,c=(t.y+e.y)/2;return{x:a+(n.x-a)*r,y:c+(n.y-c)*r}}function Do(t){return"computeNodePf"in t&&"function"==typeof t.computeNodePf}function Lo(t){const e={lines:[],points:[],rects:[],circles:[]};for(const n of t.inputNodes){let s=0,o=0,i={numSameLayerCrossings:0,numEntryExitLayerChanges:0,numTransitionPairCrossings:0},r=0;if(Do(t)){s=t.computeNodePf(n),o=t.nodeMemoryPfMap.get(n.capacityMeshNodeId)??0;const e=t.buildNodeWithPortPointsForCrossing(n);i=Ro(e);const a=new Set,c=t.nodeAssignedPortPoints.get(n.capacityMeshNodeId)??[];for(const t of c)t.connectionName&&a.add(t.connectionName);r=a.size}else{s=t.nodePfMap.get(n.capacityMeshNodeId)??0;const e=t.nodeAssignedPortPoints.get(n.capacityMeshNodeId)??[],o={capacityMeshNodeId:n.capacityMeshNodeId,center:n.center,width:n.width,height:n.height,portPoints:e,availableZ:n.availableZ};i=Ro(o);const a=new Set;for(const t of e)t.connectionName&&a.add(t.connectionName);r=a.size}const a=Math.min(255,Math.floor(512*s)),c=Math.max(0,255-Math.floor(512*s));let h=`rgba(${a}, ${c}, ${c}, ${s<.001?"0.1":"0.3"})`;n._containsObstacle&&(h="rgba(255, 0, 0, 0.3)"),n._offBoardConnectedCapacityMeshNodeIds?.length&&(h="rgba(255, 165, 0, 0.3)"),e.rects.push({center:n.center,width:n.width-.2,height:n.height-.2,layer:`z${n.availableZ.join(",")}`,fill:h,label:`${n.capacityMeshNodeId}\npf: ${s.toFixed(3)}, memPf: ${o.toFixed(3)}\nC#: ${r}\nxSame: ${i.numSameLayerCrossings}, xLC: ${i.numEntryExitLayerChanges}, xTransition: ${i.numTransitionPairCrossings}\nobCmid: ${n._offBoardConnectedCapacityMeshNodeIds?.join(",")}\nobs: ${n._containsObstacle?"yes":"no"}`})}if(Do(t))for(const[n,s]of t.portPointMap){const o=t.assignedPortPoints.get(n),i=o?t.colorMap[o.connectionName]??"blue":"rgba(150, 150, 150, 0.5)";e.circles.push({center:{x:s.x,y:s.y},radius:.05,fill:i,layer:`z${s.z}`,label:[n,`conn: ${o?.connectionName}`,`cd: ${s.distToCentermostPortOnZ}`,`connects: ${s.connectionNodeIds.join(",")}`,`rootConn: ${o?.rootConnectionName}`].filter(Boolean).join("\n")})}const n=Do(t)?t.connectionsWithResults:t.connectionResults;for(const s of n){if(!s.path)continue;const n=s.connection,o=t.colorMap[n.name]??"blue",i=[];for(const t of s.path)i.push({x:t.point.x,y:t.point.y,z:t.z,nodeId:t.currentNodeId});for(let n=0;n<i.length-1;n++){const s=i[n],r=i[n+1],a=s.z===r.z,c=s.z;let h;h=a?0===c?void 0:"10 5":"3 3 10";const d=s.nodeId?t.nodeMap.get(s.nodeId):null;if(d&&Oo(s,r,d.center,d.width,d.height)){const t=zo(s,r,d.center,d.width,d.height);e.lines.push({points:[{x:s.x,y:s.y},{x:t.x,y:t.y}],strokeColor:o,strokeDash:h}),e.lines.push({points:[{x:t.x,y:t.y},{x:r.x,y:r.y}],strokeColor:o,strokeDash:h})}else e.lines.push({points:[{x:s.x,y:s.y},{x:r.x,y:r.y}],strokeColor:o,strokeDash:h})}}if(Do(t)&&!t.solved&&t.candidates&&t.candidates.length>0){const n=t.currentConnection,s=n?t.colorMap[n.connection.name]??"blue":"blue";if(n){const[o,i]=n.nodeIds,r=t.nodeMap.get(o),a=t.nodeMap.get(i),c=n.connection.pointsToConnect[0],h=n.connection.pointsToConnect[n.connection.pointsToConnect.length-1];if(r&&a){const t=c?{x:c.x,y:c.y}:r.center,o=h?{x:h.x,y:h.y}:a.center;e.lines.push({points:[t,o],strokeColor:it(s,.5),strokeDash:"5 5"}),e.points.push({x:t.x,y:t.y,color:s,label:[`Start: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.points.push({x:o.x,y:o.y,color:s,label:[`End: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.circles.push({center:o,radius:.08,stroke:s,label:`Goal: ${n.connection.name}`})}}const o=[...t.candidates].sort((t,e)=>t.f-e.f).slice(0,1);for(const i of o){const o=[];let r=i;for(;r;)o.unshift({x:r.point.x,y:r.point.y,z:r.z,lastMoveWasOffBoard:r.lastMoveWasOffBoard,nodeId:r.currentNodeId}),r=r.prevCandidate;for(let n=0;n<o.length-1;n++){const i=o[n],r=o[n+1],a=i.z===r.z,c=i.z;let h;h=r.lastMoveWasOffBoard?"2 2":a?0===c?void 0:"10 5":"3 3 10";const d=i.nodeId?t.nodeMap.get(i.nodeId):null,l=.02*i.z;if(d&&Oo(i,r,d.center,d.width,d.height)){const t=zo(i,r,d.center,d.width,d.height);e.lines.push({points:[{x:i.x+l,y:i.y+l},{x:t.x+l,y:t.y+l}],strokeColor:it(s,.25),strokeDash:h}),e.lines.push({points:[{x:t.x+l,y:t.y+l},{x:r.x+l,y:r.y+l}],strokeColor:it(s,.25),strokeDash:h})}else e.lines.push({points:[{x:i.x+l,y:i.y+l},{x:r.x+l,y:r.y+l}],strokeColor:it(s,.25),strokeDash:h})}if(o.length>=1){const r=o[o.length-1];let a=0,c=0,h=0,d=0,l=0,u=0;const p=t.nodeMap.get(i.prevCandidate?.currentNodeId);if(p&&i.prevCandidate&&i.portPoint&&n){const e=n.connection.name,s={x:i.prevCandidate.point.x,y:i.prevCandidate.point.y,z:i.prevCandidate.z,connectionName:e},o={x:i.portPoint.x,y:i.portPoint.y,z:i.portPoint.z,connectionName:e},r=t.buildNodeWithPortPointsForCrossing(p,[s,o]),m=de(r);h=m.numSameLayerCrossings,d=m.numTransitionPairCrossings,l=m.numEntryExitLayerChanges;const f=t.capacityMeshNodeMap.get(p.capacityMeshNodeId);f&&(c=t.JUMPER_PF_FN_ENABLED&&1===p.availableZ.length?wo(f,h):Co(f,h,l,d),a=c**2*t.NODE_PF_FACTOR),u=i.prevCandidate.g>0?i.g-i.prevCandidate.g:i.g}if(!n)continue;const[m,f]=n.nodeIds,g=t.nodeMap.get(f),y=g?Math.sqrt((r.x-g.center.x)**2+(r.y-g.center.y)**2):0,x=t.avgNodePitch>0?y/t.avgNodePitch:0,v=x*t.BASE_CANDIDATE_COST,S=t.nodeMemoryPfMap.get(i.currentNodeId)??0,P=-Math.log(1-S)*t.MEMORY_PF_FACTOR;e.circles.push({center:r,radius:.03,fill:it(s,.25),layer:`z${i.z}`,label:[`f: ${i.f.toFixed(2)}`,`g: ${i.g.toFixed(2)} (nodeDelta: ${u.toFixed(2)})`,`h: ${i.h.toFixed(2)}`,` dist: ${y.toFixed(2)}`,` estHops: ${x.toFixed(1)}`,` estStepCost: ${v.toFixed(2)}`,` memRiskCost: ${P.toFixed(2)}`,`z: ${i.z}`,`node: ${i.currentNodeId}`,`Cost(Pf): ${a.toFixed(3)}`,`Pf: ${c.toFixed(3)}`,`xSame: ${h}, xTrans: ${d}, xLC: ${l}`,`routeOffBoard=${t.currentConnectionShouldRouteOffBoard}`,`offBoardTouched=${i.hasTouchedOffBoardNode??!1}`,`lastMoveWasOffBoard=${i.lastMoveWasOffBoard??!1}`].join("\n")})}}}return e}function Fo(t,e){const n=[],s=e.filter(t=>t._containsTarget),o=new Map;for(const i of t.connections){const t=[];for(const n of i.pointsToConnect){let o=e[0],i=Number.MAX_VALUE;for(const t of s){const e=Math.sqrt((t.center.x-n.x)**2+(t.center.y-n.y)**2);e<i&&(i=e,o=t)}t.push(o)}if(t.length<2)throw new Error(`Not enough nodes for connection "${i.name}", only ${t.length} found`);o.set(i.name,t.map(t=>t.capacityMeshNodeId)),n.push({connection:i,nodeIds:[t[0].capacityMeshNodeId,t[t.length-1].capacityMeshNodeId],straightLineDistance:St(t[0].center,t[t.length-1].center)})}return{unshuffledConnectionsWithResults:n,connectionNameToGoalNodeIds:o}}function Xo(t,e){const n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),s=e.map(t=>(t.width+t.height)/2).filter(t=>Number.isFinite(t)&&t>0),o=s.length>0?s.reduce((t,e)=>t+e,0)/s.length:1,i=e.filter(t=>t._offBoardConnectionId),r=new Map,a=new Map,c=new Map;for(const t of e)a.set(t.capacityMeshNodeId,[]),c.set(t.capacityMeshNodeId,[]);for(const t of e)for(const e of t.portPoints){r.set(e.portPointId,e);for(const t of e.connectionNodeIds){const n=a.get(t);n&&!n.some(t=>t.portPointId===e.portPointId)&&n.push(e)}}const{unshuffledConnectionsWithResults:h,connectionNameToGoalNodeIds:d}=Fo(t,e);return{nodeMap:n,avgNodePitch:o,offBoardNodes:i,portPointMap:r,nodePortPointsMap:a,nodeAssignedPortPoints:c,unshuffledConnectionsWithResults:h,connectionNameToGoalNodeIds:d}}function Yo(t,e,n){let s=0;const o=n?.NODE_MAX_PF??.99999;for(const n of t){const t=e.get(n.capacityMeshNodeId);if(!t)continue;if(t._containsTarget)continue;const i=Ro(n),r=Math.min(Co(t,i.numSameLayerCrossings,i.numEntryExitLayerChanges,i.numTransitionPairCrossings),o);s+=Math.log(1-r)}return s}function $o(t,e){if(e._containsTarget)return 0;const n=Ro(t);return Co(e,n.numSameLayerCrossings,n.numEntryExitLayerChanges,n.numTransitionPairCrossings)}function ko(t,e,n,s,o){const i=n-e,r=o-s,a=1e-6;if(Math.abs(t.y-o)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(o-t.y);if(Math.abs(t.y-s)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-s);const c=Math.abs(t.y-o),h=Math.abs(t.x-n),d=Math.abs(t.y-s),l=Math.abs(t.x-e),u=Math.min(c,h,d,l);return u===c?Math.max(0,Math.min(i,t.x-e)):u===h?i+Math.max(0,Math.min(r,o-t.y)):u===d?i+r+Math.max(0,Math.min(i,n-t.x)):2*i+r+Math.max(0,Math.min(r,t.y-s))}function Bo(t,e,n){let s=0;const o=n?.NODE_MAX_PF??.99999;for(const n of t){const t=e.get(n.capacityMeshNodeId);if(!t)continue;if(t._containsTarget)continue;const i=Ro(n),r=Math.min(wo(t,i.numSameLayerCrossings),o);s+=Math.log(1-r)}return s}function jo(t){let e=t;return()=>{e+=1831565813;let t=e;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296}}var Wo=[{SHUFFLE_SEED:100,NODE_PF_FACTOR:100,NODE_PF_MAX_PENALTY:100,MEMORY_PF_FACTOR:0,EXPANSION_DEGREES:10,FORCE_CENTER_FIRST:!0,FORCE_OFF_BOARD_FREQUENCY:0,CENTER_OFFSET_DIST_PENALTY_FACTOR:0}],Ho=class extends y{simpleRouteJson;inputNodes;capacityMeshNodes;capacityMeshEdges;colorMap;nodeMap;capacityMeshNodeMap;connectionResults;assignedPortPoints;nodeAssignedPortPoints;sections=[];activeSubSolver=null;currentSection=null;sectionScoreBeforeOptimization=0;currentSectionCenterNodeId=null;currentScheduleIndex=0;nodePfMap=new Map;attemptsToFixNode=new Map;sectionAttempts=0;MAX_ATTEMPTS_PER_NODE=100;MAX_SECTION_ATTEMPTS=50;ACCEPTABLE_PF=.05;FRACTION_TO_REPLACE=.2;JUMPER_PF_FN_ENABLED=!1;SHUFFLE_SEEDS_PER_SECTION=null;ALWAYS_RIP_INTERSECTIONS=!0;effort=1;HYPERPARAMETER_SCHEDULE=Wo;constructor(t){super(),this.MAX_ITERATIONS=1e6,this.simpleRouteJson=t.simpleRouteJson,this.inputNodes=t.inputNodes,this.capacityMeshNodes=t.capacityMeshNodes,this.capacityMeshEdges=t.capacityMeshEdges,this.colorMap=t.colorMap??{},this.effort=t.effort??1,void 0!==t.FRACTION_TO_REPLACE&&(this.FRACTION_TO_REPLACE=t.FRACTION_TO_REPLACE),void 0!==t.ALWAYS_RIP_INTERSECTIONS&&(this.ALWAYS_RIP_INTERSECTIONS=t.ALWAYS_RIP_INTERSECTIONS),void 0!==t.MAX_ATTEMPTS_PER_NODE&&(this.MAX_ATTEMPTS_PER_NODE=t.MAX_ATTEMPTS_PER_NODE),void 0!==t.MAX_SECTION_ATTEMPTS&&(this.MAX_SECTION_ATTEMPTS=t.MAX_SECTION_ATTEMPTS),void 0!==t.HYPERPARAMETER_SCHEDULE&&(this.HYPERPARAMETER_SCHEDULE=t.HYPERPARAMETER_SCHEDULE),this.JUMPER_PF_FN_ENABLED=t.JUMPER_PF_FN_ENABLED??this.JUMPER_PF_FN_ENABLED,this.SHUFFLE_SEEDS_PER_SECTION=t.SHUFFLE_SEEDS_PER_SECTION,this.MAX_SECTION_ATTEMPTS*=this.effort,this.nodeMap=new Map(t.inputNodes.map(t=>[t.capacityMeshNodeId,t])),this.capacityMeshNodeMap=new Map(t.capacityMeshNodes.map(t=>[t.capacityMeshNodeId,t])),this.connectionResults=[...t.initialConnectionResults],this.assignedPortPoints=new Map(t.initialAssignedPortPoints),this.nodeAssignedPortPoints=new Map(t.initialNodeAssignedPortPoints),this.nodePfMap=this.computeInitialPfMap();const e=this.computeBoardScore();this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.nodesExamined=0,this.stats.sectionAttempts=0,this.stats.sectionScores={},this.stats.initialBoardScore=e,this.stats.currentBoardScore=e,this.stats.errors=0}computeInitialPfMap(){const t=new Map;for(const e of this.capacityMeshNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];if(0===n.length)continue;const s={capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ},o=this.JUMPER_PF_FN_ENABLED&&1===e.availableZ.length?wo(e,Ro(s).numSameLayerCrossings):$o(s,e);t.set(e.capacityMeshNodeId,o)}return t}computeBoardScore(){const t=this.getNodesWithPortPoints();return this.computeScoreForNodes(t)}computeScoreForNodes(t){return this.JUMPER_PF_FN_ENABLED?Bo(t,this.capacityMeshNodeMap):Yo(t,this.capacityMeshNodeMap)}recomputePfForNodes(t){for(const e of t){const t=this.capacityMeshNodeMap.get(e);if(!t)continue;const n=this.nodeAssignedPortPoints.get(e)??[];if(0===n.length){this.nodePfMap.set(e,0);continue}const s={capacityMeshNodeId:e,center:t.center,width:t.width,height:t.height,portPoints:n,availableZ:t.availableZ},o=this.JUMPER_PF_FN_ENABLED&&1===t.availableZ.length?wo(t,Ro(s).numSameLayerCrossings):$o(s,t);this.nodePfMap.set(e,o)}}getCreatePortPointSectionInput(){return{inputNodes:this.inputNodes,capacityMeshNodes:this.capacityMeshNodes,capacityMeshEdges:this.capacityMeshEdges,nodeMap:this.nodeMap,connectionResults:this.connectionResults}}createSection(t){return function(t,e){const{inputNodes:n,capacityMeshNodes:s,capacityMeshEdges:o,connectionResults:i}=t,{centerOfSectionCapacityNodeId:r,expansionDegrees:a}=e,c=new Map;for(const t of o){const[e,n]=t.nodeIds;c.has(e)||c.set(e,new Set),c.has(n)||c.set(n,new Set),c.get(e).add(n),c.get(n).add(e)}const h=new Set,d=new Set,l=[];for(l.push({nodeId:r,depth:0}),d.add(r);l.length>0;){const{nodeId:t,depth:e}=l.shift();if(h.add(t),e<a){const n=c.get(t)??new Set;for(const t of n)d.has(t)||(d.add(t),l.push({nodeId:t,depth:e+1}))}}const u=n.filter(t=>h.has(t.capacityMeshNodeId)),p=s.filter(t=>h.has(t.capacityMeshNodeId)),m=[],f=[];for(const t of o){const[e,n]=t.nodeIds,s=h.has(e),o=h.has(n);s&&o?m.push(t):(s||o)&&f.push(t)}const g=u.map(t=>{const e=t.portPoints.filter(t=>{const[e,n]=t.connectionNodeIds,s=h.has(e),o=h.has(n);return s||o});return{...t,portPoints:e}}),y=function(t,e){const n=[];for(const s of t){if(!s.path||0===s.path.length)continue;const t=s.connection.name,o=s.connection.rootConnectionName,i=[];for(let t=0;t<s.path.length;t++){const n=s.path[t];e.has(n.currentNodeId)&&i.push(t)}if(0===i.length)continue;const r=i[0],a=i[i.length-1];let c=r,h=a;if(r>0){const t=s.path[0].currentNodeId;(s.nodeIds[0]===t||s.nodeIds[1]===t)&&(c=0)}if(a<s.path.length-1){const t=s.path.length-1,e=s.path[t].currentNodeId;(s.nodeIds[0]===e||s.nodeIds[1]===e)&&(h=t)}const d=s.path.slice(c,h+1),l=c>0,u=h<s.path.length-1;n.push({connectionName:t,rootConnectionName:o,points:d.map(t=>({x:t.point.x,y:t.point.y,z:t.z,nodeId:t.currentNodeId,portPointId:t.portPoint?.portPointId})),originalStartIndex:c,originalEndIndex:h,hasEntryFromOutside:l,hasExitToOutside:u})}return n}(i??[],h);return{centerNodeId:r,expansionDegrees:a,nodeIds:h,inputNodes:g,capacityMeshNodes:p,internalEdges:m,boundaryEdges:f,sectionPaths:y}}(this.getCreatePortPointSectionInput(),t)}getSectionNodesWithPortPoints(t){const e=[];for(const n of t.nodeIds){const t=this.nodeMap.get(n),s=this.capacityMeshNodeMap.get(n);if(!t||!s)continue;const o=this.nodeAssignedPortPoints.get(n)??[];o.length>0&&e.push({capacityMeshNodeId:n,center:t.center,width:t.width,height:t.height,portPoints:o,availableZ:t.availableZ})}return e}getNodesWithPortPoints(){const t=[];for(const e of this.inputNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];n.length>0&&t.push({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ})}return t}findHighestPfNode(){let t=null,e=0;for(const[n,s]of this.nodePfMap.entries()){s*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_ATTEMPTS_PER_NODE)**2>e&&(e=s,t=n)}return!t||e<this.ACCEPTABLE_PF?null:t}currentSectionCutPathInfo=new Map;currentSectionKeptPortPoints=new Map;currentSectionFixedRoutes=[];determineConnectionsToRip(t,e){const n=31337*this.sectionAttempts,s=jo(n);if(this.FRACTION_TO_REPLACE>=1)return new Set(e);const o=function(t,e){const n=jo(e),s=[...t];for(let t=s.length-1;t>0;t--){const e=Math.floor(n()*(t+1));[s[t],s[e]]=[s[e],s[t]]}return s}(e,n),i=Math.max(1,Math.ceil(o.length*this.FRACTION_TO_REPLACE)),r=new Set(o.slice(0,i));if(this.ALWAYS_RIP_INTERSECTIONS){const n=function(t){const{section:e,nodePfMap:n,capacityMeshNodeMap:s,nodeAssignedPortPoints:o,acceptablePf:i}=t,r=[];for(const t of e.nodeIds){if((n.get(t)??0)<=i)continue;const e=s.get(t);if(!e)continue;const a=o.get(t)??[];if(a.length<2)continue;const c=e.center.x-e.width/2,h=e.center.x+e.width/2,d=e.center.y-e.height/2,l=e.center.y+e.height/2,u=new Map;for(const t of a){const e=u.get(t.connectionName)??[];e.some(e=>e.x===t.x&&e.y===t.y&&e.z===t.z)||e.push({x:t.x,y:t.y,z:t.z}),u.set(t.connectionName,e)}const p=new Map;for(const[t,e]of u){if(e.length<2)continue;const n=e[0],s=e[1];if(n.z!==s.z)continue;const o=ko(n,c,h,d,l),i=ko(s,c,h,d,l),r=n.z,a=p.get(r)??[];a.push({connectionName:t,t1:o,t2:i}),p.set(r,a)}const m=1e-6;for(const[,t]of p){const e=t.map(t=>({connectionName:t.connectionName,a:Math.min(t.t1,t.t2),b:Math.max(t.t1,t.t2)}));for(let t=0;t<e.length;t++){const{connectionName:n,a:s,b:o}=e[t];for(let i=t+1;i<e.length;i++){const{connectionName:t,a:a,b:c}=e[i];Math.abs(s-a)<m||Math.abs(s-c)<m||Math.abs(o-a)<m||Math.abs(o-c)<m||(s<a&&a<o&&o<c||a<s&&s<c&&c<o)&&r.push([n,t])}}}}return r}({section:t,nodePfMap:this.nodePfMap,capacityMeshNodeMap:this.capacityMeshNodeMap,nodeAssignedPortPoints:this.nodeAssignedPortPoints,acceptablePf:this.ACCEPTABLE_PF});for(const[t,o]of n){if(r.has(t)||r.has(o))continue;const n=e.includes(t),i=e.includes(o);if(n&&i){const e=s()<.5;r.add(e?t:o)}else n?r.add(t):i&&r.add(o)}}return this.stats.lastRipCount=r.size,r}createSectionSimpleRouteJson(t){const e=[];this.currentSectionCutPathInfo.clear(),this.currentSectionKeptPortPoints.clear(),this.currentSectionFixedRoutes=[];const n=[],s=[];for(const e of this.connectionResults){if(!e.path||0===e.path.length)continue;const[o,i]=e.nodeIds,r=t.nodeIds.has(o),a=t.nodeIds.has(i);r&&a&&(s.push(e),n.push(e.connection.name))}const o=[];for(const e of t.sectionPaths){if(!e.hasEntryFromOutside&&!e.hasExitToOutside)continue;if(e.points.length<2)continue;const t=this.connectionResults.find(t=>t.connection.name===e.connectionName);t&&(o.push({sectionPath:e,originalResult:t}),n.includes(e.connectionName)||n.push(e.connectionName))}const i=this.determineConnectionsToRip(t,n);for(const t of s)i.has(t.connection.name)&&e.push(t.connection);for(const{sectionPath:t,originalResult:n}of o){if(!i.has(t.connectionName))continue;const s=`__cut__${t.connectionName}__${t.originalStartIndex}`;this.colorMap[s]=this.colorMap[t.connectionName];const o=t.points[0],r=t.points[t.points.length-1],a={name:s,rootConnectionName:t.rootConnectionName??t.connectionName,pointsToConnect:[{x:o.x,y:o.y,layers:[`layer${o.z+1}`]},{x:r.x,y:r.y,layers:[`layer${r.z+1}`]}]};e.push(a),this.currentSectionCutPathInfo.set(s,{sectionPath:t,originalConnectionResult:n})}const r=new Set(n.filter(t=>!i.has(t)));if(r.size>0){for(const e of t.nodeIds){const t=(this.nodeAssignedPortPoints.get(e)??[]).filter(t=>r.has(t.connectionName));t.length>0&&this.currentSectionKeptPortPoints.set(e,t)}for(const t of s)r.has(t.connection.name)&&this.currentSectionFixedRoutes.push(t);for(const{sectionPath:t,originalResult:e}of o)if(r.has(t.connectionName)){const n={connection:{name:t.connectionName,rootConnectionName:t.rootConnectionName,pointsToConnect:e.connection.pointsToConnect},path:t.points.map(t=>({prevCandidate:null,portPoint:null,currentNodeId:t.nodeId,point:{x:t.x,y:t.y},z:t.z,f:0,g:0,h:0,distanceTraveled:0})),portPoints:t.points.map(e=>({portPointId:e.portPointId,x:e.x,y:e.y,z:e.z,connectionName:t.connectionName,rootConnectionName:t.rootConnectionName})),nodeIds:e.nodeIds,straightLineDistance:e.straightLineDistance};this.currentSectionFixedRoutes.push(n)}}return{...this.simpleRouteJson,connections:e}}prepareSectionInputNodesForCutPaths(t){const e=new Set;for(const[,t]of this.currentSectionCutPathInfo.entries()){const{sectionPath:n}=t;if(0===n.points.length)continue;const s=n.points[0].nodeId;e.add(s);const o=n.points[n.points.length-1].nodeId;e.add(o)}return t.inputNodes.map(t=>e.has(t.capacityMeshNodeId)?{...t,_containsTarget:!0}:t)}getHyperParametersForScheduleIndex(t,e){const n=this.HYPERPARAMETER_SCHEDULE[t];return{...n,SHUFFLE_SEED:(n.SHUFFLE_SEED??0)+17*e}}createSectionSolver(t){const e=this.createSectionSimpleRouteJson(t),n=this.prepareSectionInputNodesForCutPaths(t),s=Xo(e,n);for(const[t,e]of this.currentSectionKeptPortPoints){const n=s.nodeAssignedPortPoints.get(t)??[];s.nodeAssignedPortPoints.set(t,[...n,...e])}return new Vo({simpleRouteJson:e,inputNodes:n,capacityMeshNodes:t.capacityMeshNodes,colorMap:this.colorMap,nodeMemoryPfMap:this.nodePfMap,numShuffleSeeds:this.SHUFFLE_SEEDS_PER_SECTION??2*e.connections.length*this.effort,hyperParameters:{...this.getHyperParametersForScheduleIndex(this.currentScheduleIndex,this.sectionAttempts)},precomputedInitialParams:s,fixedRoutes:this.currentSectionFixedRoutes})}reattachSection(t,e,n,s){const o=[],i=[];for(const t of e)t.connection.name.startsWith("__cut__")?i.push(t):o.push(t);const r=new Set(o.map(t=>t.connection.name));this.connectionResults=this.connectionResults.filter(t=>!r.has(t.connection.name)),this.connectionResults.push(...o);for(const[e,n]of this.nodeAssignedPortPoints.entries()){if(!t.nodeIds.has(e))continue;const s=n.filter(t=>!r.has(t.connectionName));this.nodeAssignedPortPoints.set(e,s)}for(const[t,e]of this.assignedPortPoints.entries())r.has(e.connectionName)&&this.assignedPortPoints.delete(t);for(const e of i){const n=this.currentSectionCutPathInfo.get(e.connection.name);if(!n||!e.path)continue;const{sectionPath:s,originalConnectionResult:o}=n,i=o.path;if(!i)continue;const r=s.connectionName;for(const[e,n]of this.nodeAssignedPortPoints.entries()){const s=n.filter(n=>n.connectionName!==r||!t.nodeIds.has(e));this.nodeAssignedPortPoints.set(e,s)}const a=i.slice(0,s.originalStartIndex),c=i.slice(s.originalEndIndex+1),h=[];let d=a.length>0?a[a.length-1]:null;for(const t of e.path){const e={...t,prevCandidate:d};h.push(e),d=e}if(c.length>0&&h.length>0&&(c[0]={...c[0],prevCandidate:h[h.length-1]}),o.path=[...a,...h,...c],e.portPoints)for(const n of e.portPoints){const e={...n,connectionName:r,rootConnectionName:s.rootConnectionName??r};for(const s of t.inputNodes)for(const t of s.portPoints)if(Math.abs(t.x-n.x)<.001&&Math.abs(t.y-n.y)<.001&&t.z===n.z){for(const n of t.connectionNodeIds){const t=this.nodeAssignedPortPoints.get(n)??[];t.push(e),this.nodeAssignedPortPoints.set(n,t)}break}}}for(const[t,e]of n.entries())e.connectionName.startsWith("__cut__")||this.assignedPortPoints.set(t,e);for(const[t,e]of s.entries()){const n=e.filter(t=>!t.connectionName.startsWith("__cut__"));if(n.length>0){const e=this.nodeAssignedPortPoints.get(t)??[];this.nodeAssignedPortPoints.set(t,[...e,...n])}}}_step(){if(this.activeSubSolver){if(this.activeSubSolver.step(),this.activeSubSolver.solved||this.activeSubSolver.failed){if(this.activeSubSolver.failed){if(this.currentScheduleIndex++,this.activeSubSolver.error&&this.stats.errors++,this.currentScheduleIndex<this.HYPERPARAMETER_SCHEDULE.length&&this.currentSectionCenterNodeId){const t=this.HYPERPARAMETER_SCHEDULE[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:this.currentSectionCenterNodeId,expansionDegrees:t.EXPANSION_DEGREES}),this.activeSubSolver=this.createSectionSolver(this.currentSection)}else this.stats.failedOptimizations++,this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0;return}const t=this.activeSubSolver.getNodesWithPortPoints().map(t=>({...t,portPoints:t.portPoints.map(t=>{if(t.connectionName.startsWith("__cut__")){const e=t.connectionName.slice(7),n=e.lastIndexOf("__"),s=n>=0?e.slice(0,n):e;return{...t,connectionName:s}}return t})})),e=new Set;for(const n of t)for(const t of n.portPoints)e.add(t.connectionName);const n=this.getSectionNodesWithPortPoints(this.currentSection).map(t=>({...t,portPoints:t.portPoints.filter(t=>e.has(t.connectionName))})).filter(t=>t.portPoints.length>0),s=this.computeScoreForNodes(n),o=this.computeScoreForNodes(t),i=`attempt${this.sectionAttempts}`;if(this.stats.lastSectionScore=o,o>s){const t=this.stats.currentBoardScore;this.stats.lastBoardScore=t;const e=[...this.connectionResults],n=new Map(this.assignedPortPoints),s=new Map(Array.from(this.nodeAssignedPortPoints.entries()).map(([t,e])=>[t,[...e]]));this.reattachSection(this.currentSection,this.activeSubSolver.connectionsWithResults,this.activeSubSolver.assignedPortPoints,this.activeSubSolver.nodeAssignedPortPoints),this.recomputePfForNodes(this.currentSection.nodeIds);const o=this.computeBoardScore();this.stats.sectionScores[i]=o,o>t?(this.stats.successfulOptimizations++,this.stats.currentBoardScore=o):(this.connectionResults=e,this.assignedPortPoints=n,this.nodeAssignedPortPoints=s,this.recomputePfForNodes(this.currentSection.nodeIds),this.stats.failedOptimizations++),this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0}else if(this.currentScheduleIndex++,this.currentScheduleIndex<this.HYPERPARAMETER_SCHEDULE.length&&this.currentSectionCenterNodeId){const t=this.HYPERPARAMETER_SCHEDULE[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:this.currentSectionCenterNodeId,expansionDegrees:t.EXPANSION_DEGREES}),this.activeSubSolver=this.createSectionSolver(this.currentSection)}else this.stats.failedOptimizations++,this.activeSubSolver=null,this.currentSection=null,this.currentSectionCenterNodeId=null,this.currentScheduleIndex=0}return}if(this.sectionAttempts>=this.MAX_SECTION_ATTEMPTS)return void(this.solved=!0);const t=this.findHighestPfNode();if(!t)return void(this.solved=!0);this.sectionAttempts++,this.stats.sectionAttempts=this.sectionAttempts,this.stats.nodesExamined++,this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.currentSectionCenterNodeId=t,this.currentScheduleIndex=0;const e=this.HYPERPARAMETER_SCHEDULE[this.currentScheduleIndex];this.currentSection=this.createSection({centerOfSectionCapacityNodeId:t,expansionDegrees:e.EXPANSION_DEGREES});const n=this.getSectionNodesWithPortPoints(this.currentSection);this.sectionScoreBeforeOptimization=this.computeScoreForNodes(n);if(0===this.createSectionSimpleRouteJson(this.currentSection).connections.length)return this.currentSection=null,void(this.currentSectionCenterNodeId=null);this.activeSubSolver=this.createSectionSolver(this.currentSection)}computeProgress(){return this.sectionAttempts/this.MAX_SECTION_ATTEMPTS}visualize(){return this.solved?Lo(this):this.activeSubSolver?this.activeSubSolver.visualize():this.currentSection?function(t,e){const n={lines:[],points:[],rects:[],circles:[]};for(const e of t.inputNodes){const s=e.capacityMeshNodeId===t.centerNodeId,o=s?"rgba(0, 200, 0, 0.3)":"rgba(200, 200, 200, 0.3)";n.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,layer:`z${e.availableZ.join(",")}`,fill:o,label:`${e.capacityMeshNodeId}${s?" (CENTER)":""}`})}for(const e of t.inputNodes)for(const t of e.portPoints){const e="rgba(150, 150, 150, 0.5)";n.circles.push({center:{x:t.x,y:t.y},radius:.05,fill:e,layer:`z${t.z}`,label:[t.portPointId,`cd: ${t.distToCentermostPortOnZ}`,`connects: ${t.connectionNodeIds.join(",")}`].filter(Boolean).join("\n")})}for(const s of t.sectionPaths){const t=e?.[s.connectionName]??"blue";for(let e=0;e<s.points.length-1;e++){const o=s.points[e],i=s.points[e+1],r=o.z===i.z,a=o.z;let c;c=r?0===a?"5 5":"10 5":"3 3 10",n.lines.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:t,strokeDash:c})}}return n}(this.currentSection,this.colorMap):Lo(this)}},Uo=class extends y{constructor(t){super(),this.input=t;const{simpleRouteJson:e,capacityMeshNodes:n,inputNodes:s,colorMap:o,nodeMemoryPfMap:i,hyperParameters:r,precomputedInitialParams:a,fixedRoutes:c}=t;if(this.input=structuredClone(t),this.MAX_ITERATIONS=1e8,this.simpleRouteJson=e,this.inputNodes=s,this.colorMap=o??{},this.capacityMeshNodeMap=new Map(n.map(t=>[t.capacityMeshNodeId,t])),this.nodeMemoryPfMap=i??new Map,this.hyperParameters=r??{},a){this.nodeMap=a.nodeMap,this.avgNodePitch=a.avgNodePitch,this.offBoardNodes=a.offBoardNodes,this.portPointMap=a.portPointMap,this.nodePortPointsMap=a.nodePortPointsMap,this.connectionNameToGoalNodeIds=a.connectionNameToGoalNodeIds;const{nodeAssignedPortPoints:t}=function(t){const e=new Map;for(const[n,s]of t.nodeAssignedPortPoints)e.set(n,[...s]);return{nodeAssignedPortPoints:e}}(a);this.nodeAssignedPortPoints=t,this.connectionsWithResults=kt(structuredClone(a.unshuffledConnectionsWithResults),this.hyperParameters.SHUFFLE_SEED??0)}else{this.nodeMap=new Map(s.map(t=>[t.capacityMeshNodeId,t]));const t=s.map(t=>(t.width+t.height)/2).filter(t=>Number.isFinite(t)&&t>0);this.avgNodePitch=t.length>0?t.reduce((t,e)=>t+e,0)/t.length:1,this.offBoardNodes=s.filter(t=>t._offBoardConnectionId),this.portPointMap=new Map,this.nodePortPointsMap=new Map;for(const t of s)this.nodePortPointsMap.set(t.capacityMeshNodeId,[]),this.nodeAssignedPortPoints.set(t.capacityMeshNodeId,[]);for(const t of s)for(const e of t.portPoints){this.portPointMap.set(e.portPointId,e);for(const t of e.connectionNodeIds){const n=this.nodePortPointsMap.get(t);n&&!n.some(t=>t.portPointId===e.portPointId)&&n.push(e)}}const{connectionsWithResults:e,connectionNameToGoalNodeIds:n}=this.getConnectionsWithNodes();this.connectionsWithResults=e,this.connectionNameToGoalNodeIds=n}if(c&&c.length>0)for(const t of c)if(this.connectionsWithResults.push(t),t.portPoints)for(const e of t.portPoints)e.portPointId&&this.assignedPortPoints.set(e.portPointId,{connectionName:e.connectionName,rootConnectionName:e.rootConnectionName});for(const t of this.connectionsWithResults)t.path?this.processedConnectionQueue.push(t):this.unprocessedConnectionQueue.push(t);this.totalConnectionCount=this.connectionsWithResults.length}hyperParameters;simpleRouteJson;inputNodes;nodeMap;nodePortPointsMap;portPointMap;connectionsWithResults=[];failedConnection=null;assignedPortPoints=new Map;nodeAssignedPortPoints=new Map;PORT_POINT_REUSE_FACTOR=1e3;BASE_COST_FOR_NOT_GOING_OFF_BOARD=100;get NODE_PF_FACTOR(){return this.hyperParameters.NODE_PF_FACTOR??50}get RANDOM_WALK_DISTANCE(){return this.hyperParameters.RANDOM_WALK_DISTANCE??0}get MEMORY_PF_FACTOR(){return this.hyperParameters.MEMORY_PF_FACTOR??0}get CENTER_OFFSET_FOCUS_SHIFT(){return this.hyperParameters.CENTER_OFFSET_FOCUS_SHIFT??0}get RANDOM_COST_MAGNITUDE(){return this.hyperParameters.RANDOM_COST_MAGNITUDE??0}get BASE_CANDIDATE_COST(){return this.hyperParameters.BASE_CANDIDATE_COST??0}get NODE_PF_MAX_PENALTY(){return this.hyperParameters.NODE_PF_MAX_PENALTY??1e4}get FORCE_CENTER_FIRST(){return this.hyperParameters.FORCE_CENTER_FIRST??!0}get FORCE_OFF_BOARD_FREQUENCY(){return 0===this.offBoardNodes.length?0:this.hyperParameters.FORCE_OFF_BOARD_FREQUENCY??0}get FORCE_OFF_BOARD_SEED(){return this.hyperParameters.FORCE_OFF_BOARD_SEED??0}get NODE_MAX_PF(){return Math.min(.99999,1-Math.exp(-this.NODE_PF_MAX_PENALTY))}get CENTER_OFFSET_DIST_PENALTY_FACTOR(){return this.hyperParameters.CENTER_OFFSET_DIST_PENALTY_FACTOR??0}get STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR(){return this.hyperParameters.STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR??0}colorMap;get GREEDY_MULTIPLIER(){return this.hyperParameters.GREEDY_MULTIPLIER??1.3}MAX_CANDIDATES_IN_MEMORY=5e3;get MAX_ITERATIONS_PER_PATH(){return this.hyperParameters.MAX_ITERATIONS_PER_PATH??1e4}ITERATIONS_PER_MM_FOR_PATH=30;BASE_ITERATIONS_PER_PATH=1e4;get RIPPING_ENABLED(){return this.hyperParameters.RIPPING_ENABLED??!1}get RIPPING_PF_THRESHOLD(){return this.hyperParameters.RIPPING_PF_THRESHOLD??.3}get MAX_RIPS(){return this.hyperParameters.MAX_RIPS??100}get RANDOM_RIP_FRACTION(){return this.hyperParameters.RANDOM_RIP_FRACTION??0}get JUMPER_PF_FN_ENABLED(){return this.hyperParameters.JUMPER_PF_FN_ENABLED??!1}jumpersPerMmSquared=.1;testedRipConnections=new Map;totalRipCount=0;get MIN_ALLOWED_BOARD_SCORE(){return this.hyperParameters.MIN_ALLOWED_BOARD_SCORE??-1e4}nodeMemoryPfMap;unprocessedConnectionQueue=[];processedConnectionQueue=[];currentConnection=null;totalConnectionCount=0;currentPathIterations=0;candidates;visitedPortPoints;connectionNameToGoalNodeIds;capacityMeshNodeMap;avgNodePitch;currentConnectionShouldRouteOffBoard=!1;activeCandidateStraightLineDistance;offBoardNodes=[];baseNodeCostCache=new Map;getConstructorParams(){return this.input}clearCostCaches(){this.baseNodeCostCache.clear()}clampPf(t){return Number.isFinite(t)?Math.min(Math.max(t,0),.999999):.999999}pfToFailureCost(t){const e=this.clampPf(t);return e>=this.NODE_MAX_PF?this.NODE_PF_MAX_PENALTY:-Math.log(1-e)}getBaseNodeFailureCost(t){const e=this.baseNodeCostCache.get(t);if(null!=e)return e;const n=this.nodeMap.get(t);if(!n)return 0;const s=this.computeNodePf(n),o=this.pfToFailureCost(s);return this.baseNodeCostCache.set(t,o),o}computeBoardScore(){const t=this.getNodesWithPortPoints();return this.JUMPER_PF_FN_ENABLED?Bo(t,this.capacityMeshNodeMap):Yo(t,this.capacityMeshNodeMap)}getMaxIterationsForCurrentPath(){const t=this.activeCandidateStraightLineDistance??0;return Math.min(this.BASE_ITERATIONS_PER_PATH+this.ITERATIONS_PER_MM_FOR_PATH*t,this.MAX_ITERATIONS_PER_PATH)}getNodeDeltaFailureCostForSegment(t,e,n){const s=this.nodeMap.get(t);if(!s)return 0;const o=this.getBaseNodeFailureCost(t),i=this.computeNodePf(s,[e,n]),r=this.pfToFailureCost(i),a=Math.max(0,r-o);return i>=this.NODE_MAX_PF?this.NODE_PF_MAX_PENALTY:a*this.NODE_PF_FACTOR}getConnectionsWithNodes(){const{unshuffledConnectionsWithResults:t,connectionNameToGoalNodeIds:e}=Fo(this.simpleRouteJson,this.inputNodes);return{connectionsWithResults:kt(t,this.hyperParameters.SHUFFLE_SEED??0),connectionNameToGoalNodeIds:e}}buildNodeWithPortPointsForCrossing(t,e){const n=this.nodeAssignedPortPoints.get(t.capacityMeshNodeId)??[],s=e?[...n,...e]:n;return{capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:s,availableZ:t.availableZ}}computeNodePf(t,e){if(t._containsTarget)return 0;const n=this.buildNodeWithPortPointsForCrossing(t,e),s=Ro(n);return this.JUMPER_PF_FN_ENABLED&&1===t.availableZ.length?wo(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),s.numSameLayerCrossings):Co(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),s.numSameLayerCrossings,s.numEntryExitLayerChanges,s.numTransitionPairCrossings)}getPortPointReusePenalty(t,e){const n=this.assignedPortPoints.get(t);return n?e===n.rootConnectionName?0:this.PORT_POINT_REUSE_FACTOR:0}getOtherNodeId(t,e){const[n,s]=t.connectionNodeIds;return n===e?s:s===e?n:null}computeG(t,e,n,s,o){const i=t.currentNodeId,r=t.point,a={x:r.x,y:r.y,z:t.z,connectionName:s,rootConnectionName:o},c={x:e.x,y:e.y,z:e.z,connectionName:s,rootConnectionName:o},h=this.getNodeDeltaFailureCostForSegment(i,a,c);return t.g+h}computeGToEndTarget(t,e,n,s){const o=t.currentNodeId,i={x:t.point.x,y:t.point.y,z:t.z,connectionName:n,rootConnectionName:s},r={x:e.x,y:e.y,z:t.z,connectionName:n,rootConnectionName:s},a=this.getNodeDeltaFailureCostForSegment(o,i,r);return t.g+a}computeDistanceToNearestOffBoardNode(t){if(0===this.offBoardNodes.length)return 1/0;let e=1/0;for(const n of this.offBoardNodes){const s=St(t,n.center);s<e&&(e=s)}return e}computeH(t,e,n,s,o,i){if(this.RANDOM_WALK_DISTANCE>0&&o<this.RANDOM_WALK_DISTANCE)return 0;if(this.currentConnectionShouldRouteOffBoard&&!i)return this.BASE_COST_FOR_NOT_GOING_OFF_BOARD+this.computeDistanceToNearestOffBoardNode(t);const r=this.nodeMap.get(n);if(!r)return 0;const a=St(t,r.center),c=this.avgNodePitch>0?a/this.avgNodePitch:0,h=this.clampPf(this.nodeMemoryPfMap.get(e)??0),d=this.pfToFailureCost(h)*this.MEMORY_PF_FACTOR,l=c*this.BASE_CANDIDATE_COST,u=this.CENTER_OFFSET_DIST_PENALTY_FACTOR*t.distToCentermostPortOnZ**2;let p=0;if(this.STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR>0&&this.currentConnection){const e=vt(t,this.currentConnection.connection.pointsToConnect[0],this.currentConnection.connection.pointsToConnect[1]);p=this.STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR*e}return a+l+d+u+p}getVisitedPortPointKey(t,e){return this.currentConnectionShouldRouteOffBoard&&e?`${t}:touched_off_board`:t}getAvailableExitPortPoints(t,e){const n=this.currentConnection?.connection.rootConnectionName,s=this.nodePortPointsMap.get(t)??[],o=[];for(const t of s){const s=this.getVisitedPortPointKey(t.portPointId,e);if(this.visitedPortPoints?.has(s))continue;const i=this.assignedPortPoints.get(t.portPointId);i&&i?.rootConnectionName!==n||o.push(t)}return o}getAvailableExitPortPointsWithOmissions(t,e,n){const s=this.nodePortPointsMap.get(t)??[],o=this.currentConnection?.connection.rootConnectionName,i=new Map;for(const e of s){const s=this.getVisitedPortPointKey(e.portPointId,n);if(this.visitedPortPoints?.has(s))continue;const o=this.getOtherNodeId(e,t);if(!o)continue;this.nodeMap.get(o);const r=`${o}|${e.z}`,a=i.get(r)??[];a.push(e),i.set(r,a)}const r=[];for(const[,t]of i){t.sort((t,e)=>t.distToCentermostPortOnZ-e.distToCentermostPortOnZ);const e=t[0];if(!e)continue;const n=this.assignedPortPoints.get(e.portPointId),s=n&&n.rootConnectionName===o;if(!n||s){r.push(e);continue}const i=[...t].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y),a=[];let c=[];for(const t of i){const e=this.assignedPortPoints.get(t.portPointId);!e||e.rootConnectionName===o?c.push(t):c.length>0&&(a.push(c),c=[])}c.length>0&&a.push(c);for(const t of a){const e=Math.floor(t.length/2);r.push(t[e])}}return r}getAvailableExitPortPointsForOffboardConnection(t,e){const n=this.nodeMap.get(t);if(!n)return[];const s=this.currentConnection?.connection.rootConnectionName,o=[];for(const i of n?._offBoardConnectedCapacityMeshNodeIds??[]){if(i===t)continue;if(!this.nodeMap.get(i))continue;const n=this.nodePortPointsMap.get(i)??[];for(const t of n){const n=this.getVisitedPortPointKey(t.portPointId,e);if(this.visitedPortPoints?.has(n))continue;const r=this.assignedPortPoints.get(t.portPointId);r&&r.rootConnectionName!==s||o.push({...t,throughNodeId:i})}}return o}canTravelThroughObstacle(t,e,n){const s=this.connectionNameToGoalNodeIds.get(e);return s?.includes(t.capacityMeshNodeId)||Boolean(t._offBoardConnectionId)}isAtEndGoal(t,e){return t===e}getBacktrackedPath(t){const e=[];let n=t;for(;n;){if(n.lastMoveWasOffBoard&&n.throughNodeId){const t=this.nodeMap.get(n.throughNodeId),s=n.prevCandidate?this.nodeMap.get(n.prevCandidate.currentNodeId):null;e.push(n),t&&e.push({prevCandidate:null,portPoint:null,currentNodeId:n.throughNodeId,point:t.center,z:n.z,f:0,g:0,h:0,distanceTraveled:0}),s&&s._offBoardConnectionId&&e.push({prevCandidate:null,portPoint:null,currentNodeId:n.prevCandidate.currentNodeId,point:s.center,z:n.z,f:0,g:0,h:0,distanceTraveled:0})}else e.push(n);n=n.prevCandidate}return e.reverse()}assignPortPointsForPath(t,e,n){const s=[];for(let o=0;o<t.length;o++){const i=t[o];if(!i.portPoint){const r=0===o,a=o===t.length-1;if(!r&&!a){const t={x:i.point.x,y:i.point.y,z:i.z,connectionName:e,rootConnectionName:n};s.push(t);const o=this.nodeAssignedPortPoints.get(i.currentNodeId)??[];o.push(t),this.nodeAssignedPortPoints.set(i.currentNodeId,o)}continue}const r=i.portPoint;this.assignedPortPoints.set(r.portPointId,{connectionName:e,rootConnectionName:n});const a={portPointId:r.portPointId,x:r.x,y:r.y,z:r.z,connectionName:e,rootConnectionName:n};s.push(a);for(const t of r.connectionNodeIds){const e=this.nodeAssignedPortPoints.get(t)??[];e.push(a),this.nodeAssignedPortPoints.set(t,e)}}const o=Array.from(new Set(t.map(t=>t.currentNodeId)));for(const t of o){const s=this.nodeMap.get(t);if(s&&s._offBoardConnectionId)for(const t of s?._offBoardConnectedCapacityMeshNodeIds??[]){const s=this.nodePortPointsMap.get(t)??[];for(const t of s)this.assignedPortPoints.set(t.portPointId,{connectionName:e,rootConnectionName:n})}}return s}addTargetPointsToNodes(t,e){const n=t[0],s=t[t.length-1],o=e.pointsToConnect[0],i=e.pointsToConnect[e.pointsToConnect.length-1];if(n&&o){const t=this.nodeAssignedPortPoints.get(n.currentNodeId)??[];t.push({x:o.x,y:o.y,z:n.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(n.currentNodeId,t)}if(s&&i){const t=this.nodeAssignedPortPoints.get(s.currentNodeId)??[];t.push({x:i.x,y:i.y,z:s.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(s.currentNodeId,t)}}isPortPointInPathChain(t,e){let n=t;for(;n;){if(n.portPoint?.portPointId===e)return!0;n=n.prevCandidate}return!1}isNodeInPathChain(t,e){let n=t;for(;n;){if(n.currentNodeId===e)return!0;n=n.prevCandidate}return!1}_step(){if(this.currentConnection||(this.currentConnection=this.unprocessedConnectionQueue.shift()??null),!this.currentConnection){const t=this.computeBoardScore();return this.stats={boardScore:t},t<this.MIN_ALLOWED_BOARD_SCORE?(this.failedConnection=null,this.failed=!0,void(this.error=`Board score ${t.toFixed(2)} is less than MIN_ALLOWED_BOARD_SCORE ${this.MIN_ALLOWED_BOARD_SCORE.toFixed(2)}`)):void(this.solved=!0)}const t=this.currentConnection;this.activeCandidateStraightLineDistance=t.straightLineDistance,this.currentPathIterations++;const e=this.getMaxIterationsForCurrentPath();if(this.currentPathIterations>e)return this.failedConnection=t,this.processedConnectionQueue.push(t),this.currentConnection=null,this.candidates=null,this.visitedPortPoints=null,this.currentPathIterations=0,this.failed=!0,void(this.error=`Exceeded max iterations for path (${e}) on connection ${t.connection.name}`);const[n,s]=t.nodeIds,o=this.nodeMap.get(n),i=this.nodeMap.get(s);if(!o||!i)return this.processedConnectionQueue.push(t),this.currentConnection=null,void(this.currentPathIterations=0);const r=t.connection.name,a=t.connection.rootConnectionName,c=t.connection.pointsToConnect[0];if(!this.candidates){if(this.clearCostCaches(),this.FORCE_OFF_BOARD_FREQUENCY>0){const t=Yt(17*(this.hyperParameters.SHUFFLE_SEED??0)+this.FORCE_OFF_BOARD_SEED+this.processedConnectionQueue.length);this.currentConnectionShouldRouteOffBoard=t()<this.FORCE_OFF_BOARD_FREQUENCY}else this.currentConnectionShouldRouteOffBoard=!1;this.candidates=[],this.visitedPortPoints=new Set;for(const t of o.availableZ){const e=c?{x:c.x,y:c.y}:o.center,i=this.computeH({...e,distToCentermostPortOnZ:0},n,s,t,0,!1),r=0+i*this.GREEDY_MULTIPLIER;this.candidates.push({prevCandidate:null,portPoint:null,currentNodeId:n,point:e,z:t,f:r,g:0,h:i,distanceTraveled:0,hasTouchedOffBoardNode:!1})}}this.candidates.sort((t,e)=>t.f-e.f);let h,d=this.candidates.shift();for(;d?.portPoint&&this.visitedPortPoints;){const t=this.getVisitedPortPointKey(d.portPoint.portPointId,d.hasTouchedOffBoardNode);if(!this.visitedPortPoints.has(t))break;d=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),!d)return this.error=`Ran out of candidates on connection ${r}`,this.failedConnection=t,this.processedConnectionQueue.push(t),this.currentConnection=null,this.candidates=null,this.visitedPortPoints=null,this.currentPathIterations=0,void(this.failed=!0);if(d.portPoint&&this.visitedPortPoints){const t=this.getVisitedPortPointKey(d.portPoint.portPointId,d.hasTouchedOffBoardNode);this.visitedPortPoints.add(t)}if(this.isAtEndGoal(d.currentNodeId,s)){const e=t.connection.pointsToConnect[t.connection.pointsToConnect.length-1],n=e?{x:e.x,y:e.y}:i.center,o=this.computeGToEndTarget(d,n,r,a),c={prevCandidate:d,portPoint:null,currentNodeId:s,point:n,z:d.z,g:o,h:0,f:o,distanceTraveled:d.distanceTraveled+St(d.point,n)},h=this.getBacktrackedPath(c);return t.path=h,t.portPoints=this.assignPortPointsForPath(h,r,a),this.addTargetPointsToNodes(h,t.connection),this.clearCostCaches(),this.RIPPING_ENABLED&&this.processRippingForPath(h,r),this.processedConnectionQueue.push(t),this.currentConnection=null,this.progress=this.processedConnectionQueue.length/this.totalConnectionCount,this.candidates=null,this.visitedPortPoints=null,void(this.currentPathIterations=0)}const l=this.nodeMap.get(d.currentNodeId);h=l?._offBoardConnectionId?this.getAvailableExitPortPointsForOffboardConnection(d.currentNodeId,d.hasTouchedOffBoardNode):this.FORCE_CENTER_FIRST?this.getAvailableExitPortPointsWithOmissions(d.currentNodeId,s,d.hasTouchedOffBoardNode):this.getAvailableExitPortPoints(d.currentNodeId,d.hasTouchedOffBoardNode);for(const t of h){if(this.isPortPointInPathChain(d,t.portPointId))continue;if(this.visitedPortPoints?.has(t.portPointId))continue;const e=this.getOtherNodeId(t,t.throughNodeId??d.currentNodeId);if(!e)continue;if(this.isNodeInPathChain(d,e))continue;const n="throughNodeId"in t?t.throughNodeId:void 0,o=n?this.nodeMap.get(n):null,i=this.nodeMap.get(e);if(!i)continue;if(i._containsObstacle&&!this.canTravelThroughObstacle(i,r,a))continue;const c=this.computeG(d,t,e,r,a);if(!this.RIPPING_ENABLED&&c>-this.MIN_ALLOWED_BOARD_SCORE)continue;const h=d.distanceTraveled+St(d.point,t),u=d.hasTouchedOffBoardNode||Boolean(i._offBoardConnectionId),p=this.computeH(t,e,s,t.z,h,u),m=c+p*this.GREEDY_MULTIPLIER,f=Boolean(l?._offBoardConnectionId)&&Boolean(o?._offBoardConnectionId);this.candidates.push({prevCandidate:d,portPoint:t,currentNodeId:e,point:{x:t.x,y:t.y},z:t.z,f:m,g:c,h:p,distanceTraveled:h,lastMoveWasOffBoard:f,throughNodeId:f?n:void 0,hasTouchedOffBoardNode:u||Boolean(i._offBoardConnectionId)||Boolean(l?._offBoardConnectionId)})}}getNodesWithPortPoints(){const t=[];for(const e of this.inputNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];n.length>0&&t.push({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ})}return t}getConnectionsInNode(t,e){const n=[],s=new Set;for(const o of this.connectionsWithResults)if(o.path&&o.connection.name!==e&&!s.has(o.connection.name))for(const e of o.path)if(e.currentNodeId===t){n.push(o),s.add(o.connection.name);break}return n}computeNodePfWithoutConnection(t,e){if(t._containsTarget)return{pf:0,totalCrossings:0};const n=(this.nodeAssignedPortPoints.get(t.capacityMeshNodeId)??[]).filter(t=>t.connectionName!==e),s={capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:n,availableZ:t.availableZ},o=Ro(s),i=o.numSameLayerCrossings+o.numEntryExitLayerChanges+o.numTransitionPairCrossings;return{pf:Co(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),o.numSameLayerCrossings,o.numEntryExitLayerChanges,o.numTransitionPairCrossings),totalCrossings:i}}computeNodeCrossings(t){if(t._containsTarget)return 0;const e=this.buildNodeWithPortPointsForCrossing(t),n=Ro(e);return n.numSameLayerCrossings+n.numEntryExitLayerChanges+n.numTransitionPairCrossings}ripConnection(t){const e=t.connection.name;for(const[t,n]of this.assignedPortPoints.entries())n.connectionName===e&&this.assignedPortPoints.delete(t);for(const[t,n]of this.nodeAssignedPortPoints.entries()){const s=n.filter(t=>t.connectionName!==e);this.nodeAssignedPortPoints.set(t,s)}t.path=void 0,t.portPoints=void 0}requeueConnection(t){this.totalRipCount++;const e=this.processedConnectionQueue.indexOf(t);if(-1!==e)return this.processedConnectionQueue.splice(e,1),this.unprocessedConnectionQueue.push(t),!0;const n=this.unprocessedConnectionQueue.indexOf(t);return-1!==n&&(this.unprocessedConnectionQueue.splice(n,1),this.unprocessedConnectionQueue.unshift(t)),!0}processRippingForPath(t,e){const n=Array.from(new Set(t.map(t=>t.currentNodeId)));let s=!1;for(const t of n){if(this.totalRipCount>this.MAX_RIPS)break;const n=this.nodeMap.get(t);if(!n)continue;let o=this.computeNodePf(n);if(o<=this.RIPPING_PF_THRESHOLD)continue;this.testedRipConnections.has(t)||this.testedRipConnections.set(t,new Set);const i=this.testedRipConnections.get(t),r=kt(this.getConnectionsInNode(t,e),(this.hyperParameters.SHUFFLE_SEED??0)+this.processedConnectionQueue.length);for(const t of r){if(o<=this.RIPPING_PF_THRESHOLD)break;const e=t.connection.name;i.add(e);const{pf:r}=this.computeNodePfWithoutConnection(n,e);this.ripConnection(t);if(!this.requeueConnection(t))return;o=r,s=!0,this.clearCostCaches()}}s&&this.RANDOM_RIP_FRACTION>0&&this.processRandomRipping(e)}processRandomRipping(t){const e=this.processedConnectionQueue.filter(e=>void 0!==e.path&&e.connection.name!==t);if(0===e.length)return;const n=Math.max(1,Math.floor(this.RANDOM_RIP_FRACTION*e.length)),s=kt(e,(this.hyperParameters.SHUFFLE_SEED??0)+this.totalRipCount+this.processedConnectionQueue.length);for(let t=0;t<n&&t<s.length&&!(this.totalRipCount>this.MAX_RIPS);t++){const e=s[t];this.ripConnection(e);if(!this.requeueConnection(e))return;this.clearCostCaches()}}visualize(){let t={};if(this.failed){const e=this.failedConnection?.connection.pointsToConnect[0],n=this.failedConnection?.connection.pointsToConnect[1];e&&n&&(t={lines:[{points:[e,n],label:`Failed Connection ${this.failedConnection?.connection.name}`,strokeWidth:1,strokeColor:"red",strokeDash:[2,2]}]})}return e=Lo(this),n=t,{...e,rects:[...e.rects??[],...n.rects??[]],points:[...e.points??[],...n.points??[]],lines:[...e.lines??[],...n.lines??[]],circles:[...e.circles??[],...n.circles??[]],arrows:[...e.arrows??[],...n.arrows??[]],texts:[...e.texts??[],...n.texts??[]]};var e,n}},Vo=class extends Zt{params;precomputedInitialParams;constructor(t){super(),this.params=t,this.MAX_ITERATIONS=1e8,this.GREEDY_MULTIPLIER=1.2,this.MIN_SUBSTEPS=50,this.precomputedInitialParams=t.precomputedInitialParams??Xo(t.simpleRouteJson,t.inputNodes)}getHyperParameterDefs(){const t=this.params.numShuffleSeeds??50;return[{name:"SHUFFLE_SEED",possibleValues:Array.from({length:t},(t,e)=>({SHUFFLE_SEED:e+1700*(this.params.hyperParameters?.SHUFFLE_SEED??0)}))}]}getCombinationDefs(){return[["SHUFFLE_SEED"]]}generateSolver(t){return new Uo({simpleRouteJson:this.params.simpleRouteJson,capacityMeshNodes:this.params.capacityMeshNodes,inputNodes:this.params.inputNodes,colorMap:this.params.colorMap,nodeMemoryPfMap:this.params.nodeMemoryPfMap,hyperParameters:{...this.params.hyperParameters,...t,MIN_ALLOWED_BOARD_SCORE:this.params.minAllowedBoardScore??t.MIN_ALLOWED_BOARD_SCORE??this.params.hyperParameters?.MIN_ALLOWED_BOARD_SCORE},precomputedInitialParams:this.precomputedInitialParams,fixedRoutes:this.params.fixedRoutes})}computeG(t){return-t.computeBoardScore()}computeH(t){const e=t.progress||0;if(e<.1)return 0;return-(t.computeBoardScore()/e)*(1-e)}getNodesWithPortPoints(){if(this.winningSolver)return this.winningSolver.getNodesWithPortPoints();const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.getNodesWithPortPoints():[]}get connectionsWithResults(){if(this.winningSolver)return this.winningSolver.connectionsWithResults;const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.connectionsWithResults:[]}get inputNodes(){if(this.winningSolver)return this.winningSolver.inputNodes;const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.inputNodes:this.params.inputNodes}get nodeMap(){if(this.winningSolver)return this.winningSolver.nodeMap;const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.nodeMap:new Map(this.params.inputNodes.map(t=>[t.capacityMeshNodeId,t]))}get assignedPortPoints(){if(this.winningSolver)return this.winningSolver.assignedPortPoints;const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.assignedPortPoints:new Map}get nodeAssignedPortPoints(){if(this.winningSolver)return this.winningSolver.nodeAssignedPortPoints;const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.nodeAssignedPortPoints:new Map}computeBoardScore(){if(this.winningSolver)return this.winningSolver.computeBoardScore();const t=this.getSupervisedSolverWithBestFitness();return t?t.solver.computeBoardScore():0}onSolve(t){this.stats={...t.solver.stats,winningHyperParameters:this.winningSolver?.hyperParameters}}visualize(){return this.winningSolver?this.winningSolver.visualize():super.visualize()}};function Zo(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Go=class extends y{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth,this.effort=e.effort??1,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,o=Math.max(n,s),i=e.targetMinCapacity??.5;e.capacityDepth=Be(o,i)}this.connMap=$e(t),this.colorMap=ot(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;colorMap;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;viaDiameter;minTraceWidth;effort;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[Zo("netToPointPairsSolver",gn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ot(t.srjWithPointPairs,this.connMap),t.connMap=$e(t.srjWithPointPairs)}}),Zo("nodeSolver",Js,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Zo("edgeSolver",cn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Zo("availableSegmentPointSolver",Io,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),Zo("portPointPathingSolver",Vo,t=>{const e=t.capacityNodes.map(t=>({capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:[],availableZ:t.availableZ,_containsTarget:t._containsTarget,_containsObstacle:t._containsObstacle})),n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),s=t.availableSegmentPointSolver;for(const t of s.sharedEdgeSegments)for(const e of t.portPoints){const[t,s]=e.nodeIds,o={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[t,s],distToCentermostPortOnZ:e.distToCentermostPortOnZ},i=n.get(t);i&&i.portPoints.push(o)}return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e,capacityMeshNodes:t.capacityNodes,colorMap:t.colorMap,numShuffleSeeds:200,hyperParameters:{NODE_PF_MAX_PENALTY:100,FORCE_OFF_BOARD_FREQUENCY:0,STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR:4}}]}),Zo("multiSectionPortPointOptimizer",Ho,t=>{const e=t.portPointPathingSolver;return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e.inputNodes,capacityMeshNodes:t.capacityNodes,capacityMeshEdges:t.capacityEdges,colorMap:t.colorMap,initialConnectionResults:e.connectionsWithResults,initialAssignedPortPoints:e.assignedPortPoints,initialNodeAssignedPortPoints:e.nodeAssignedPortPoints,effort:t.effort}]}),Zo("highDensityRouteSolver",Le,t=>[{nodePortPoints:t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),Zo("highDensityStitchSolver",nn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),Zo("traceSimplificationSolver",Mo,t=>[{hdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline,defaultViaDiameter:t.viaDiameter,layerCount:t.srj.layerCount,iterations:2}])];getConstructorParams(){return[this.srj,this.opts]}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 t=this.netToPointPairsSolver?.visualize(),e=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),s=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),i=this.edgeSolver?.visualize(),r=this.deadEndSolver?.visualize(),a=this.availableSegmentPointSolver?.visualize(),c=this.portPointPathingSolver?.visualize(),h=this.multiSectionPortPointOptimizer?.visualize(),d=this.highDensityRouteSolver?.visualize(),l=this.highDensityStitchSolver?.visualize(),u=this.traceSimplificationSolver?.visualize(),p=this.srj.outline,m=[];if(m.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)"}),p&&p.length>=2){const t=p.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),m.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const f={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:m},y=[f,t,e,n,s,o,i,r,a,c,h,d?g(f,d):null,l,u,this.solved?g(f,sn(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...y)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.connectionName]}),t.length>200)break}return{lines:t}}if(this.portPointPathingSolver){const t=[];for(const e of this.portPointPathingSolver.connectionsWithResults)e.path&&t.push({points:e.path.map(t=>({x:t.point.x,y:t.point.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,o=e.filter(t=>t.connectionName===n.name);for(let e=0;e<o.length;e++){const i=o[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:We(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Jo=Go,qo=class extends y{nodes;edges;capacityPaths;nodeMap;nodeEdgeMap;unprocessedNodeIds;nodePortSegments;colorMap;constructor({nodes:t,edges:e,capacityPaths:n,colorMap:s}){super(),this.nodes=t,this.edges=e,this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=No(e),this.capacityPaths=n,this.colorMap=s??{},this.unprocessedNodeIds=[...new Set(n.flatMap(t=>t.nodeIds))],this.nodePortSegments=new Map}step(){const t=this.unprocessedNodeIds.pop();if(!t)return void(this.solved=!0);const e=[];for(const n of this.capacityPaths){const s=n.nodeIds.indexOf(t);-1!==s&&e.push({path:n,indexOfNodeInPath:s})}const n=this.nodeMap.get(t),s=[];for(const{path:o,indexOfNodeInPath:i}of e){const e=o.nodeIds[i-1],r=o.nodeIds[i+1];for(const i of[e,r]){const e=this.nodeMap.get(i);if(!e)continue;const r=Ko(n,e),a=e.availableZ.filter(t=>n.availableZ.includes(t));if(0===a.length)continue;const c={capacityMeshNodeId:t,start:r.start,end:r.end,connectionNames:[o.connectionName],rootConnectionNames:o.rootConnectionName?[o.rootConnectionName]:void 0,availableZ:a};s.push(c)}}const o=function(t){const e=[],n=t.map(t=>({...t,connectionNames:[...t.connectionNames],rootConnectionNames:t.rootConnectionNames?[...t.rootConnectionNames]:[],availableZ:[...t.availableZ].sort((t,e)=>t-e)}));for(;n.length>0;){const t=n.pop();let s=!1;for(let n=0;n<e.length;n++){const o=e[n],i=ti(o.start,t.start)&&ti(o.end,t.end)||ti(o.start,t.end)&&ti(o.end,t.start),r=ei(o.availableZ,t.availableZ);if(i&&r){const e=new Set(o.connectionNames);t.connectionNames.forEach(t=>e.add(t)),o.connectionNames=Array.from(e);const n=new Set(o.rootConnectionNames||[]);t.rootConnectionNames?.forEach(t=>n.add(t)),o.rootConnectionNames=Array.from(n),s=!0;break}}s||e.push(t)}return e}(s);this.nodePortSegments.set(t,o)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};return this.nodePortSegments.forEach((e,n)=>{this.nodeMap.get(n);e.forEach(e=>{e.start.x,e.end.x;for(let s=0;s<e.connectionNames.length;s++){const o={x:.05*Math.max(...e.availableZ),y:.05*Math.max(...e.availableZ)},i={x:(e.start.x+e.end.x)/2,y:(e.start.y+e.end.y)/2},r={x:i.x+o.x,y:i.y+o.y};o.x>0&&t.lines.push({points:[i,r],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5"}),t.points.push({x:r.x,y:r.y,label:`${n}: ${e.connectionNames.join(", ")}\navailableZ: ${e.availableZ.join(",")}\nnodePortSegmentId: ${e.nodePortSegmentId}`}),t.lines.push({points:[e.start,e.end],strokeColor:it(this.colorMap[e.connectionNames[s]],.6)})}})}),t}};function Ko(t,e){const n={start:Math.max(t.center.x-t.width/2,e.center.x-e.width/2),end:Math.min(t.center.x+t.width/2,e.center.x+e.width/2)},s={start:Math.max(t.center.y-t.height/2,e.center.y-e.height/2),end:Math.min(t.center.y+t.height/2,e.center.y+e.height/2)};if(n.end-n.start<s.end-s.start){const t=(n.start+n.end)/2;return{start:{x:t,y:s.start},end:{x:t,y:s.end}}}{const t=(s.start+s.end)/2;return{start:{x:n.start,y:t},end:{x:n.end,y:t}}}}var Qo=1e-9;function ti(t,e){return Math.abs(t.x-e.x)<Qo&&Math.abs(t.y-e.y)<Qo}function ei(t,e){if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++)if(t[n]!==e[n])return!1;return!0}var ni=class extends y{unsolvedSegments;solvedSegments;nodeMap;colorMap;constructor({segments:t,colorMap:e,nodes:n}){super(),this.MAX_ITERATIONS=1e5,this.unsolvedSegments=t,this.solvedSegments=[],this.colorMap=e??{},this.nodeMap=Object.fromEntries(n.map(t=>[t.capacityMeshNodeId,t]))}_step(){let t=!1;const e=[...this.unsolvedSegments];for(const n of e){const e=n.connectionNames.length;if((!("assignedPoints"in n)||n.assignedPoints?.length!==e)&&1===e){const e={x:(n.start.x+n.end.x)/2,y:(n.start.y+n.end.y)/2,z:n.availableZ[0]};n.assignedPoints=[{connectionName:n.connectionNames[0],rootConnectionName:n.rootConnectionNames?.[0],point:e}],this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(n),1),this.solvedSegments.push(n),t=!0}}if(!t&&e.length>0){let n=e[0];for(const t of e)t.connectionNames.length<n.connectionNames.length&&(n=t);const s=[...n.connectionNames].sort(),o=n.end.x-n.start.x,i=n.end.y-n.start.y,r=s.length,a=[];for(let t=1;t<=r;t++){const e=t/(r+1);a.push({x:n.start.x+o*e,y:n.start.y+i*e,z:n.availableZ[0]})}n.assignedPoints=s.map((t,e)=>({connectionName:t,rootConnectionName:n.rootConnectionNames?.[n.connectionNames.indexOf(t)],point:a[e]})),this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(n),1),this.solvedSegments.push(n),t=!0}0===this.unsolvedSegments.length&&(this.solved=!0)}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.solvedSegments){const n=e.capacityMeshNodeId,s=this.nodeMap[n];t.has(n)||t.set(n,{capacityMeshNodeId:n,portPoints:[],center:s.center,width:s.width,height:s.height}),t.get(n).portPoints.push(...e.assignedPoints.map(t=>({...t.point,connectionName:t.connectionName})))}return Array.from(t.values())}visualize(){const t={points:[],lines:this.solvedSegments.map(t=>({points:[t.start,t.end],step:4})),rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Segment to Point Solver"};for(let e=0;e<this.solvedSegments.length;e++){const n=this.solvedSegments[e];for(let e=0;e<n.assignedPoints.length;e++){const s=n.assignedPoints[e],o={x:s.point.x,y:s.point.y},i={x:s.point.x+.05*s.point.z,y:s.point.y+.05*s.point.z};0!==s.point.z&&t.lines.push({points:[o,i],strokeColor:"rgba(0, 0, 0, 0.25)",strokeDash:"5 5",step:4}),t.points.push({x:i.x,y:i.y,label:[`${n.capacityMeshNodeId}-${s.connectionName}`,`z: ${n.availableZ.join(",")}`,`nodePortSegmentId: ${n.nodePortSegmentId}`].join("\n"),color:this.colorMap[s.connectionName],step:4})}}const e=[],n={};for(const t of this.solvedSegments){const e=t.capacityMeshNodeId;n[e]||(n[e]={});for(const s of t.assignedPoints)n[e][s.connectionName]||(n[e][s.connectionName]=[]),n[e][s.connectionName].push({x:s.point.x,y:s.point.y})}for(const t in n)for(const s in n[t]){const o=n[t][s];o.length>1&&e.push({points:o,step:4,strokeDash:"5 5",strokeColor:this.colorMap[s]||"#000"})}return t.lines.push(...e),t}};function si(t){const{nodeId:e,nodeIdToSegmentIds:n,segmentIdToNodeIds:s,hops:o}=t;if(0===o)return[e];const i=new Set([e]),r=[{nodeId:e,remainingHops:o}];for(;r.length>0;){const{nodeId:t,remainingHops:e}=r.shift();if(0===e)continue;const o=n.get(t)||[];for(const t of o){const n=s.get(t)||[];for(const t of n)i.has(t)||(i.add(t),r.push({nodeId:t,remainingHops:e-1}))}}return Array.from(i)}var oi=t=>Array.from(t.entries()).map(([t,{x:e,y:n,z:s}])=>`${t}(${e?.toFixed(3)??""},${n?.toFixed(3)??""},${s??""})`).sort().join("&"),ii=(t,e,n,s)=>{const o=Math.min(t,e),i=Math.max(t,e),r=Math.min(n,s);return o<=Math.max(n,s)&&i>=r},ri=(t,e,n,s)=>{const o=[],i=new Map(t.originalPointMap);for(const[t,e]of n.entries()){const n=i.get(t);i.set(t,{x:e.x??n.x,y:e.y??n.y,z:e.z??n.z})}for(const n of t.allNodeIds){if(!e.get(n))continue;const r=t.segmentPairsInNode.get(n);for(const t of r){const e=i.get(t[0]),s=i.get(t[1]);e.z!==s.z&&o.push({type:"transition_via",segmentPoints:t,capacityMeshNodeId:n,probabilityOfFailure:0})}for(let t=0;t<r.length;t++)for(let e=t+1;e<r.length;e++){if(s?.areIdsConnected(r[t][0],r[t][1]))continue;const a=r[t],c=r[e],h=i.get(a[0]),d=i.get(a[1]),l=i.get(c[0]),u=i.get(c[1]);if(!ii(h.z,d.z,l.z,u.z))continue;const p=gt(h,d,l,u),m=h.z===d.z&&l.z===u.z&&h.z===l.z;p&&(m?o.push({type:"same_layer_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,crossingLine1:a,crossingLine2:c,probabilityOfFailure:0}):h.z===d.z&&l.z!==u.z?o.push({type:"single_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,sameLayerCrossingLine:a,transitionCrossingLine:c,probabilityOfFailure:0}):h.z!==d.z&&l.z===u.z?o.push({type:"single_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,sameLayerCrossingLine:c,transitionCrossingLine:a,probabilityOfFailure:0}):h.z!==d.z&&l.z!==u.z&&o.push({type:"double_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,crossingLine1:a,crossingLine2:c,probabilityOfFailure:0}))}}return o},ai=(t,e,n)=>{if("change_layer"===e.type)for(const n of e.segmentPointIds){const s=t.get(n)||{};t.set(n,{...s,z:e.newZ})}else if("swap_position_on_segment"===e.type){const[s,o]=e.segmentPointIds,i=n(s),r=n(o),a=t.get(s)||{},c=t.get(o)||{};t.set(s,{...a,x:r.x,y:r.y}),t.set(o,{...c,x:i.x,y:i.y})}else if("combined"===e.type)for(const s of e.operations)ai(t,s,n)},ci=(t,e)=>{const n=new Map,s=new Map,o=new Map,i=[];let r=0;for(const a of t)for(const t of a.assignedPoints){const c={segmentPointId:"SP"+r++,segmentId:a.nodePortSegmentId,capacityMeshNodeIds:e.get(a.nodePortSegmentId),connectionName:t.connectionName,rootConnectionName:t.rootConnectionName,x:t.point.x,y:t.point.y,z:t.point.z,directlyConnectedSegmentPointIds:[]};n.set(c.segmentPointId,c);for(const t of c.capacityMeshNodeIds)s.set(t,[...s.get(t)??[],c.segmentPointId]);o.set(a.nodePortSegmentId,[...o.get(a.nodePortSegmentId)??[],c.segmentPointId]),i.push(c)}return{segmentPointMap:n,nodeToSegmentPointMap:s,segmentToSegmentPointMap:o}},hi=class extends y{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,ke(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=si({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS}),n=si({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS+1}),s=Array.from(new Set(n).difference(new Set(e)));t?.segmentPointMap||(t=ci(this.dedupedSegments,this.segmentIdToNodeIds));const o=new Map;for(const e of n)o.set(e,t.nodeToSegmentPointMap.get(e));const i=new Map;for(const e of n)for(const n of o.get(e)){const e=t.segmentPointMap.get(n);i.set(n,e)}const r=Array.from(i.values()),a=new Map;for(const t of r)a.set(t.segmentId,[...a.get(t.segmentId)??[],t.segmentPointId]);for(const[e,n]of o.entries())for(let e=0;e<n.length;e++){const s=t.segmentPointMap.get(n[e]);for(let o=e+1;o<n.length;o++){const e=t.segmentPointMap.get(n[o]);e.segmentPointId!==s.segmentPointId&&(e.segmentId!==s.segmentId&&e.connectionName===s.connectionName&&(e.directlyConnectedSegmentPointIds.includes(s.segmentPointId)||(s.directlyConnectedSegmentPointIds.push(e.segmentPointId),e.directlyConnectedSegmentPointIds.push(s.segmentPointId))))}}const c=new Map;for(const t of n)c.set(t,[]);for(const e of r)for(const n of e.capacityMeshNodeIds){const s=c.get(n);if(s)for(const o of e.directlyConnectedSegmentPointIds){const i=t.segmentPointMap.get(o);i.segmentPointId!==e.segmentPointId&&(i.capacityMeshNodeIds.some(t=>t===n)&&(s.some(([t,n])=>t===e.segmentPointId&&n===i.segmentPointId||t===i.segmentPointId&&n===e.segmentPointId)||s.push([e.segmentPointId,i.segmentPointId])))}}const h=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)&&h.add(e)}const d=new Set;for(const t of r){const n=t.capacityMeshNodeIds.some(t=>e.includes(t)),s=this.dedupedSegmentMap.get(t.segmentId),o=s&&s.availableZ.length>1;(n||o)&&d.add(t.segmentPointId)}const l=new Set;for(const t of r){if(t.capacityMeshNodeIds.some(t=>this.nodeMap.get(t)?._containsTarget)){const e=this.dedupedSegmentMap.get(t.segmentId);e&&1===e.availableZ.length&&l.add(t.segmentPointId)}}return{allNodeIds:n,mutableNodeIds:e,immutableNodeIds:s,mutableSegmentIds:h,segmentPairsInNode:c,segmentPointMap:i,segmentPointsInNode:o,segmentPointsInSegment:a,originalPointMap:i,mutableSegmentPointIds:d,zLockedSegmentPointIds:l}}createInitialCandidate(){const t=new Map,e=ri(this.unravelSection,this.nodeMap,t),n=this.computeG({issues:e,originalCandidate:{},operationsPerformed:0,operation:{}});return{pointModifications:t,g:n,h:0,f:n,operationsPerformed:0,candidateHash:oi(t),issues:ri(this.unravelSection,this.nodeMap,t)}}get nextCandidate(){return this.candidates[0]??null}getPointInCandidate(t,e){const n=this.unravelSection.segmentPointMap.get(e),s=t.pointModifications.get(e);return{x:s?.x??n.x,y:s?.y??n.y,z:s?.z??n.z,segmentId:n.segmentId}}getConnectionSegmentPointIds(t){const e=[];for(const[n,s]of this.unravelSection.segmentPointMap.entries())s.connectionName===t&&e.push(n);return e}canConnectionUseLayer(t,e){for(const n of t){const t=this.unravelSection.segmentPointMap.get(n),s=this.dedupedSegmentMap.get(t.segmentId);if(!s||!s.availableZ.includes(e))return!1}return!0}getOperationsForIssue(t,e){const n=[];if("transition_via"===e.type){const[s,o]=e.segmentPoints,i=this.getPointInCandidate(t,s),r=this.getPointInCandidate(t,o),a=this.unravelSection.segmentPointMap.get(s),c=(this.unravelSection.segmentPointMap.get(o),this.dedupedSegmentMap.get(i.segmentId).availableZ),h=this.dedupedSegmentMap.get(r.segmentId).availableZ,d=this.unravelSection.zLockedSegmentPointIds.has(s),l=this.unravelSection.zLockedSegmentPointIds.has(o),u=this.getConnectionSegmentPointIds(a.connectionName);if(this.canConnectionUseLayer(u,r.z)){const t=u.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));t.length>0&&n.push({type:"change_layer",newZ:r.z,segmentPointIds:t})}if(this.canConnectionUseLayer(u,i.z)){const t=u.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));t.length>0&&n.push({type:"change_layer",newZ:i.z,segmentPointIds:t})}this.unravelSection.mutableSegmentPointIds.has(s)&&!d&&c.includes(r.z)&&n.push({type:"change_layer",newZ:r.z,segmentPointIds:[s]}),this.unravelSection.mutableSegmentPointIds.has(o)&&!l&&h.includes(i.z)&&n.push({type:"change_layer",newZ:i.z,segmentPointIds:[o]})}if("same_layer_crossing"===e.type){const[t,s]=e.crossingLine1,[o,i]=e.crossingLine2,r=[],a=this.unravelSection.segmentPointMap.get(t),c=this.unravelSection.segmentPointMap.get(s),h=this.unravelSection.segmentPointMap.get(o),d=this.unravelSection.segmentPointMap.get(i),l=this.unravelSection.mutableSegmentPointIds.has(t),u=this.unravelSection.mutableSegmentPointIds.has(s),p=this.unravelSection.mutableSegmentPointIds.has(o),m=this.unravelSection.mutableSegmentPointIds.has(i),f=this.unravelSection.zLockedSegmentPointIds.has(t),g=this.unravelSection.zLockedSegmentPointIds.has(s),y=this.unravelSection.zLockedSegmentPointIds.has(o),x=this.unravelSection.zLockedSegmentPointIds.has(i);l&&p&&a.segmentId===h.segmentId&&r.push([t,o]),l&&m&&a.segmentId===d.segmentId&&r.push([t,i]),u&&p&&c.segmentId===h.segmentId&&r.push([s,o]),u&&m&&c.segmentId===d.segmentId&&r.push([s,i]);for(const[t,e]of r)n.push({type:"swap_position_on_segment",segmentPointIds:[t,e]});const v=this.getConnectionSegmentPointIds(a.connectionName),S=this.getConnectionSegmentPointIds(h.connectionName),P=new Set;for(const t of this.unravelSection.segmentPointMap.values()){const e=this.dedupedSegmentMap.get(t.segmentId);if(e)for(const t of e.availableZ)P.add(t)}for(const t of P)if(t!==a.z&&this.canConnectionUseLayer(v,t)){const e=v.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));e.length>0&&n.push({type:"change_layer",newZ:t,segmentPointIds:e})}for(const t of P)if(t!==h.z&&this.canConnectionUseLayer(S,t)){const e=S.filter(t=>this.unravelSection.mutableSegmentPointIds.has(t)&&!this.unravelSection.zLockedSegmentPointIds.has(t));e.length>0&&n.push({type:"change_layer",newZ:t,segmentPointIds:e})}const b=this.dedupedSegmentMap.get(a.segmentId),M=this.dedupedSegmentMap.get(c.segmentId),N=this.dedupedSegmentMap.get(h.segmentId),I=this.dedupedSegmentMap.get(d.segmentId),C=(t,e)=>t.every(t=>t.availableZ.includes(e));if(l&&u&&!f&&!g){const e=0===a.z?1:0;C([b,M],e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t,s]})}if(p&&m&&!y&&!x){const t=0===h.z?1:0;C([N,I],t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[o,i]})}if(l&&!f){const e=0===a.z?1:0;b.availableZ.includes(e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t]})}if(u&&!g){const t=0===c.z?1:0;M.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[s]})}if(p&&!y){const t=0===h.z?1:0;N.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[o]})}if(m&&!x){const t=0===d.z?1:0;I.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[i]})}}return n}computeG(t){const{issues:e,originalCandidate:n,operationsPerformed:s,operation:o}=t,i=new Map;for(const t of e){i.has(t.capacityMeshNodeId)||i.set(t.capacityMeshNodeId,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0});const e=i.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 r=0;for(const[t,{numEntryExitLayerChanges:e,numSameLayerCrossings:n,numTransitionCrossings:s}]of i){const o=this.nodeMap.get(t),i=Math.min(Co(o,n,e,s),.999999);r+=Math.log(1-i)}var a;return(a=r)<-Math.LN2?Math.log(1-Math.exp(a)):Math.log(-Math.expm1(a))}getUnexploredNeighborByApplyingOperation(t,e){const n=new Map(t.pointModifications);ai(n,e,e=>this.getPointInCandidate(t,e));const s=oi(n);if(this.queuedOrExploredCandidatePointModificationHashes.has(s))return null;const o=ri(this.unravelSection,this.nodeMap,n),i=t.operationsPerformed+1,r=this.computeG({issues:o,originalCandidate:t,operationsPerformed:i,operation:e});return{issues:o,g:r,h:0,f:r,pointModifications:n,candidateHash:s,operationsPerformed:i}}getNeighborOperationsForCandidate(t){return t.issues.flatMap(e=>this.getOperationsForIssue(t,e))}getNeighbors(t){const e=[],n=this.getNeighborOperationsForCandidate(t);for(const s of n){const n=this.getUnexploredNeighborByApplyingOperation(t,s);n&&e.push(n)}return e}_step(){const t=this.candidates.shift();this.iterationsSinceImprovement++,this.iterationsSinceImprovement>this.hyperParameters.MAX_ITERATIONS_WITHOUT_IMPROVEMENT?this.solved=!0:t?(this.lastProcessedCandidate=t,t.f<(this.bestCandidate?.f??1/0)&&(this.bestCandidate=t,this.iterationsSinceImprovement=0),this.getNeighbors(t).forEach(t=>{this.queuedOrExploredCandidatePointModificationHashes.has(t.candidateHash)||(this.queuedOrExploredCandidatePointModificationHashes.add(t.candidateHash),this.candidates.push(t))}),this.candidates.sort((t,e)=>t.f-e.f),this.candidates.length=Math.min(this.candidates.length,this.MAX_CANDIDATES)):this.solved=!0}visualize(){const t={points:[],lines:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Section Solver"};let e=null;if(e=null!==this.selectedCandidateIndex?"best"===this.selectedCandidateIndex?this.bestCandidate:"original"===this.selectedCandidateIndex?this.originalCandidate:this.candidates[this.selectedCandidateIndex]:this.solved?this.bestCandidate:this.lastProcessedCandidate||this.candidates[0],!e)return t;const n=new Map;for(const[t,s]of this.unravelSection.segmentPointMap){const o={...s},i=e.pointModifications.get(t);i&&(void 0!==i.x&&(o.x=i.x),void 0!==i.y&&(o.y=i.y),void 0!==i.z&&(o.z=i.z)),n.set(t,o)}for(const[e,s]of n)t.points.push({x:s.x,y:s.y,label:`${e}\nSegment: ${s.segmentId} ${this.unravelSection.mutableSegmentIds.has(s.segmentId)?"MUTABLE":"IMMUTABLE"}\nLayer: ${s.z}`,color:this.colorMap[s.connectionName]||"#000"});const s=new Map;for(const t of this.unravelSection.allNodeIds)s.set(t,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0,estPf:0});for(const t of e.issues){const e=s.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"!==t.type&&"single_transition_crossing"!==t.type||e.numEntryExitLayerChanges++}for(const[t,e]of s.entries()){const n=this.nodeMap.get(t);e.estPf=Co(n,e.numSameLayerCrossings,e.numEntryExitLayerChanges,e.numTransitionCrossings)}for(const e of this.unravelSection.allNodeIds){const n=this.nodeMap.get(e),o=this.unravelSection.mutableNodeIds.includes(e),i=s.get(e),r=[`${e} (${o?"MUT":"IMM"})`,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Pf: ${i.estPf.toFixed(3)}`,`TC: ${i.numTransitionCrossings}`,`SLC: ${i.numSameLayerCrossings}`,`EELC: ${i.numEntryExitLayerChanges}`].join("\n");t.rects.push({center:n.center,label:r,color:o?"green":"red",width:n.width/8,height:n.height/8})}for(const[e,s]of this.unravelSection.segmentPointsInSegment){if(s.length<=1)continue;const o=s.map(t=>n.get(t));for(let n=0;n<o.length-1;n++)t.lines.push({points:[{x:o[n].x,y:o[n].y},{x:o[n+1].x,y:o[n+1].y}],strokeColor:this.colorMap[e]||"#000"})}for(const[e,s]of n)for(const o of s.directlyConnectedSegmentPointIds)if(e<o){const e=n.get(o);if(!e)continue;const i=s.z===e.z,r=s.z;let a;a=i?0===r?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:s.x,y:s.y},{x:e.x,y:e.y}],strokeDash:a,strokeColor:this.colorMap[s.connectionName]||"#000"})}for(const s of e.issues){const e=this.nodeMap.get(s.capacityMeshNodeId);if("transition_via"===s.type)for(const o of s.segmentPoints){const s=n.get(o);t.circles.push({center:{x:s.x,y:s.y},radius:e.width/16,stroke:"#ff0000",fill:"rgba(255, 0, 0, 0.2)",label:`Via Issue\n${o}\nLayer: ${s.z}`})}else if("same_layer_crossing"===s.type)for(const[o,i]of[s.crossingLine1,s.crossingLine2]){const s=n.get(o),r=n.get(i);t.lines.push({points:[{x:s.x,y:s.y},{x:r.x,y:r.y}],strokeColor:"rgba(255,0,0,0.2)",strokeWidth:e.width/32})}}for(const[s,o]of e.pointModifications){const e=n.get(s),o=this.unravelSection.segmentPointMap.get(s);t.circles.push({center:{x:e.x,y:e.y},radius:.05,stroke:"#0000ff",fill:"rgba(0, 0, 255, 0.2)",label:`${s}\nOriginal: (${o.x.toFixed(2)}, ${o.y.toFixed(2)}, ${o.z})\nNew: (${e.x.toFixed(2)}, ${e.y.toFixed(2)}, ${e.z})`})}return t}};import di from"object-hash";var li=t=>(Math.round(20*t)/20).toFixed(2),ui=t=>(Math.round(1e3*t)/1e3).toFixed(3);pt();var pi=class extends hi{cacheHit=!1;cacheProvider;hasAttemptedToUseCache=!1;constructor(t){super(t),this.cacheProvider=void 0===t.cacheProvider?lt():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}computeCacheKeyAndTransform(){const t=this.nodeMap.get(this.rootNodeId),e=function(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}(-t.center.x,-t.center.y),n=new Map,s=new Map,o=new Map,i=new Map,r=new Map,a=new Map;let c=0,h=0,d=0;const l=[...this.unravelSection.allNodeIds].sort((t,e)=>{const n=this.nodeMap.get(t),s=this.nodeMap.get(e);return n.center.x!==s.center.x?n.center.x-s.center.x:n.center.y-s.center.y});for(const t of l){const e="node_"+c++;n.set(t,e),s.set(e,t)}const u=[...Array.from(this.unravelSection.segmentPointMap.entries()).sort(([,t],[,e])=>t.x!==e.x?t.x-e.x:t.y-e.y).map(([t])=>t)].sort();for(const t of u){const e="sp_"+d++;r.set(t,e),a.set(e,t);const n=this.unravelSection.segmentPointMap.get(t).segmentId;if(!o.has(n)){const t="seg_"+h++;o.set(n,t),i.set(t,n)}}const p={};for(const[t,s]of n.entries()){const n=this.nodeMap.get(t),o=yn(e,n.center);p[s]={width:n.width,height:n.height,availableZ:n.availableZ,center:{x:li(o.x),y:li(o.y)}}}const m={};for(const[t,n]of r.entries()){const s=this.unravelSection.segmentPointMap.get(t),o=yn(e,{x:s.x,y:s.y});m[n]={x:li(o.x),y:li(o.y),z:s.z}}const f={hyperParameters:this.hyperParameters,normalizedNodes:p,normalizedSegmentPoints:m,mutableHops:this.MUTABLE_HOPS},g=`unravelsec:${di(f)}`,y={realToCacheTransform:e,nodeIdMap:n,segmentIdMap:o,segmentPointIdMap:r,reverseNodeIdMap:s,reverseSegmentIdMap:i,reverseSegmentPointIdMap:a};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:n}=this.cacheToSolveSpaceTransform,s=new Map;for(const[n,o]of t.bestCandidatePointModificationsDelta){const t=e.get(n);if(!t){console.warn(`Could not find original ID for normalized SP ID: ${n} when applying cache.`);continue}const i=this.unravelSection.segmentPointMap.get(t);if(!i){console.warn(`Could not find original segment point for ID: ${t} when applying cache.`);continue}const r={};if(void 0!==o.dx){const t=parseFloat(o.dx);Number.isNaN(t)?console.warn(`Failed to parse cached dx coordinate: ${o.dx}`):r.x=i.x+t}if(void 0!==o.dy){const t=parseFloat(o.dy);Number.isNaN(t)?console.warn(`Failed to parse cached dy coordinate: ${o.dy}`):r.y=i.y+t}void 0!==o.dz&&(r.z=i.z+o.dz),Object.keys(r).length>0&&s.set(t,r)}const o=ri(this.unravelSection,this.nodeMap,s);this.bestCandidate={pointModifications:s,issues:o,f:t.bestCandidateF,g:t.bestCandidateF,h:0,operationsPerformed:-1,candidateHash:oi(s)},this.cacheHit=!0,this.solved=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(this.failed)return void this.cacheProvider?.setCachedSolutionSync(this.cacheKey,{success:!1});if(!this.bestCandidate)return;const{segmentPointIdMap:t}=this.cacheToSolveSpaceTransform,e=[];for(const[n,s]of this.bestCandidate.pointModifications.entries()){const o=t.get(n);if(!o){console.warn(`Could not find normalized ID for original SP ID: ${n} when saving to cache.`);continue}const i=this.unravelSection.segmentPointMap.get(n);if(!i){console.warn(`Could not find original segment point for ID: ${n} when saving cache.`);continue}const r={};let a=!1;if(void 0!==s.x){const t=s.x-i.x,e=ui(t);0!==parseFloat(e)&&(r.dx=e,a=!0)}if(void 0!==s.y){const t=s.y-i.y,e=ui(t);0!==parseFloat(e)&&(r.dy=e,a=!0)}if(void 0!==s.z){const t=s.z-i.z;0!==t&&(r.dz=t,a=!0)}a&&e.push([o,r])}const n={success:!0,bestCandidatePointModificationsDelta:e,bestCandidateF:this.bestCandidate.f};this.cacheProvider?.setCachedSolutionSync(this.cacheKey,n)}},mi=class extends y{nodeMap;dedupedSegmentMap;dedupedSegments;nodeIdToSegmentIds;segmentIdToNodeIds;nodeToSegmentPointMap;segmentToSegmentPointMap;colorMap;tunedNodeCapacityMap;MAX_NODE_ATTEMPTS=2;MUTABLE_HOPS=1;ACCEPTABLE_PF=.05;MAX_ITERATIONS_WITHOUT_IMPROVEMENT=200;nodePfMap;attemptsToFixNode;activeSubSolver=null;segmentPointMap;cacheProvider=null;constructor({assignedSegments:t,colorMap:e,nodes:n,cacheProvider:s}){super(),this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.cacheHits=0,this.stats.cacheMisses=0,this.cacheProvider=s??null,this.MAX_ITERATIONS=1e6,this.dedupedSegments=(t=>{const e=[],n=new Map;let s=-1;for(const o of t){const t=`${o.start.x}-${o.start.y}-${o.end.x}-${o.end.y}-${o.availableZ.join(",")}`,i=n.get(t);i?o.nodePortSegmentId=i.nodePortSegmentId:(s++,o.nodePortSegmentId=`SEG${s}`,n.set(t,o),e.push(o))}return e})(t),this.dedupedSegmentMap=new Map;for(const t of this.dedupedSegments)this.dedupedSegmentMap.set(t.nodePortSegmentId,t);this.nodeMap=new Map;for(const t of n)this.nodeMap.set(t.capacityMeshNodeId,t);this.nodeIdToSegmentIds=new Map,this.segmentIdToNodeIds=new Map,this.attemptsToFixNode=new Map;for(const e of t)this.segmentIdToNodeIds.set(e.nodePortSegmentId,[...this.segmentIdToNodeIds.get(e.nodePortSegmentId)??[],e.capacityMeshNodeId]),this.nodeIdToSegmentIds.set(e.capacityMeshNodeId,[...this.nodeIdToSegmentIds.get(e.capacityMeshNodeId)??[],e.nodePortSegmentId]);this.colorMap=e??{},this.tunedNodeCapacityMap=new Map;for(const[t,e]of this.nodeMap)this.tunedNodeCapacityMap.set(t,ke(e));const{segmentPointMap:o,nodeToSegmentPointMap:i,segmentToSegmentPointMap:r}=ci(this.dedupedSegments,this.segmentIdToNodeIds);this.segmentPointMap=o,this.nodeToSegmentPointMap=i,this.segmentToSegmentPointMap=r,this.nodePfMap=this.computeInitialPfMap()}computeInitialPfMap(){const t=new Map;for(const[e,n]of this.nodeMap.entries())t.set(e,this.computeNodePf(n));return t}computeNodePf(t){const{numSameLayerCrossings:e,numEntryExitLayerChanges:n,numTransitionCrossings:s}=(t=>{let e=0,n=0,s=0;const o=new Map;for(const e of t)o.has(e.connectionName)||o.set(e.connectionName,[]),o.get(e.connectionName).push(e);const i=[],r=[];for(const[t,e]of o.entries()){if(e.length<2)continue;const s=e[0];for(let o=1;o<e.length;o++){const a=e[o],c={connectionName:t,z:s.z,points:[s,a]};s.z!==a.z?(n++,r.push({connectionName:t,points:[s,a]})):i.push(c)}}for(let t=0;t<i.length;t++)for(let n=t+1;n<i.length;n++){const s=i[t],o=i[n];s.z===o.z&>(s.points[0],s.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 n=r[t],o=r[e];gt(n.points[0],n.points[1],o.points[0],o.points[1])&&s++}for(let t=0;t<r.length;t++)for(let e=0;e<i.length;e++){const n=r[t],o=i[e];gt(n.points[0],n.points[1],o.points[0],o.points[1])&&s++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:n,numTransitionCrossings:s}})((this.nodeToSegmentPointMap.get(t.capacityMeshNodeId)??[]).map(t=>this.segmentPointMap.get(t)));return Co(t,e,n,s)}_step(){if(this.iterations>=this.MAX_ITERATIONS-1)return void(this.solved=!0);if(!this.activeSubSolver){let t=null,e=0;for(const[n,s]of this.nodePfMap.entries()){s*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_NODE_ATTEMPTS)>e&&(e=s,t=n)}if(!t||e<this.ACCEPTABLE_PF)return void(this.solved=!0);this.attemptsToFixNode.set(t,(this.attemptsToFixNode.get(t)??0)+1),this.activeSubSolver=new pi({dedupedSegments:this.dedupedSegments,dedupedSegmentMap:this.dedupedSegmentMap,nodeMap:this.nodeMap,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,colorMap:this.colorMap,rootNodeId:t,MUTABLE_HOPS:this.MUTABLE_HOPS,segmentPointMap:this.segmentPointMap,nodeToSegmentPointMap:this.nodeToSegmentPointMap,segmentToSegmentPointMap:this.segmentToSegmentPointMap,cacheProvider:this.cacheProvider})}this.activeSubSolver.step();const{bestCandidate:t,originalCandidate:e,lastProcessedCandidate:n}=this.activeSubSolver;if(this.activeSubSolver.failed)return this.stats.failedOptimizations+=1,void(this.activeSubSolver=null);if(this.activeSubSolver.solved){this.activeSubSolver.cacheHit?this.stats.cacheHits+=1:this.stats.cacheMisses+=1;if(t&&t.g<e.g){this.stats.successfulOptimizations+=1;for(const[e,n]of t.pointModifications.entries()){const t=this.segmentPointMap.get(e);t.x=n.x??t.x,t.y=n.y??t.y,t.z=n.z??t.z}for(const t of this.activeSubSolver.unravelSection.allNodeIds)this.nodePfMap.set(t,this.computeNodePf(this.nodeMap.get(t)))}else this.stats.failedOptimizations+=1;this.activeSubSolver=null}}visualize(){if(this.activeSubSolver)return this.activeSubSolver.visualize();const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Unravel Multi Section Solver"};for(const[e,n]of this.nodeMap.entries()){const s=this.nodePfMap.get(e)||0,o=Math.min(s,1),i=`rgb(${Math.floor(255*o)}, ${Math.floor(255*(1-o))}, 0)`;0===(this.attemptsToFixNode.get(e)??0)&&0===o||t.rects.push({center:n.center,label:[e,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Pf: ${s.toFixed(3)}`].join("\n"),color:i,width:n.width/8,height:n.height/8})}for(const e of this.segmentPointMap.values()){const n=this.dedupedSegmentMap.get(e.segmentId);t.points.push({x:e.x,y:e.y,label:[e.segmentPointId,e.segmentId,`z: ${e.z}`,`segment.availableZ: ${n?.availableZ.join(",")}`].join("\n"),color:this.colorMap[e.connectionName]||"#000"})}const e=new Map;for(const t of this.segmentPointMap.values())e.has(t.segmentId)||e.set(t.segmentId,[]),e.get(t.segmentId).push(t);for(const[n,s]of e.entries()){if(s.length<2)continue;const e=[...s].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y);for(let s=0;s<e.length-1;s++)t.lines.push({points:[{x:e[s].x,y:e[s].y},{x:e[s+1].x,y:e[s+1].y}],strokeColor:this.colorMap[n]||"#000"})}const n=new Set,s=Array.from(this.segmentPointMap.values());for(let e=0;e<s.length;e++){const o=s[e];for(let i=e+1;i<s.length;i++){const e=s[i];if(o.connectionName!==e.connectionName||o.segmentId===e.segmentId)continue;if(o.capacityMeshNodeIds.some(t=>e.capacityMeshNodeIds.includes(t))){const s=`${o.segmentPointId}-${e.segmentPointId}`;if(n.has(s))continue;n.add(s);const i=o.z===e.z,r=o.z;let a;a=i?0===r?void 0:"10 5":"3 3 10",t.lines.push({points:[{x:o.x,y:o.y},{x:e.x,y:e.y}],strokeDash:a,strokeColor:this.colorMap[o.connectionName]||"#666"})}}}return t}getNodesWithPortPoints(){if(!this.solved)throw new Error("CapacitySegmentToPointSolver not solved, can't give port points yet");const t=new Map;for(const e of this.dedupedSegments){const n=e.nodePortSegmentId;for(const e of this.segmentIdToNodeIds.get(n)){const n=this.nodeMap.get(e);t.has(e)||t.set(e,{capacityMeshNodeId:e,portPoints:[],center:n.center,width:n.width,height:n.height})}}for(const e of this.segmentPointMap.values())for(const n of e.capacityMeshNodeIds){const s=t.get(n);s&&s.portPoints.push({x:e.x,y:e.y,z:e.z,connectionName:e.connectionName,rootConnectionName:e.rootConnectionName})}return Array.from(t.values())}},fi=(t,e={})=>{const n=Math.min(...t.availableZ);return{center:!e.rectMargin||e.zOffset?{x:t.center.x+n*t.width*(e.zOffset??.05),y:t.center.y-n*t.width*(e.zOffset??.05)}:t.center,width:e.rectMargin?t.width-2*e.rectMargin:Math.max(t.width-.5,.8*t.width),height:e.rectMargin?t.height-2*e.rectMargin:Math.max(t.height-.5,.8*t.height),fill:t._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[t.availableZ.join(",")]??"rgba(0,200,200,0.1)",layer:`z${t.availableZ.join(",")}`,label:[t.capacityMeshNodeId,`availableZ: ${t.availableZ.join(",")}`,""+(t._containsTarget?"containsTarget":""),""+(t._containsObstacle?"containsObstacle":"")].filter(Boolean).join("\n")}},gi=class extends y{connectionsWithNodes;usedNodeCapacityMap;simpleRouteJson;nodes;edges;GREEDY_MULTIPLIER=1.1;MAX_CANDIDATES_IN_MEMORY=1e5;nodeMap;nodeEdgeMap;connectionNameToGoalNodeIds;colorMap;maxDepthOfNodes;activeCandidateStraightLineDistance;debug_lastNodeCostMap;hyperParameters;constructor({simpleRouteJson:t,nodes:e,edges:n,colorMap:s,MAX_ITERATIONS:o=1e6,hyperParameters:i={}}){super(),this.MAX_ITERATIONS=o,this.simpleRouteJson=t,this.nodes=e,this.edges=n,this.colorMap=s??{};const{connectionsWithNodes:r,connectionNameToGoalNodeIds:a}=this.getConnectionsWithNodes();this.connectionsWithNodes=r,this.connectionNameToGoalNodeIds=a,this.hyperParameters=i,this.usedNodeCapacityMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,0])),this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=No(this.edges),this.maxDepthOfNodes=Math.max(...this.nodes.map(t=>t._depth??0)),this.debug_lastNodeCostMap=new Map}getTotalCapacity(t){const e=t._depth??0;return(this.maxDepthOfNodes-e+1)**2}getConnectionsWithNodes(){const t=[],e=this.nodes.filter(t=>t._containsTarget),n=new Map;for(const s of this.simpleRouteJson.connections){const o=[];for(const t of s.pointsToConnect){let n=this.nodes[0],s=Number.MAX_VALUE;for(const o of e){const e=Math.sqrt((o.center.x-t.x)**2+(o.center.y-t.y)**2);e<s&&(s=e,n=o)}o.push(n)}if(o.length<2)throw new Error(`Not enough nodes for connection "${s.name}", only ${o.length} found`);n.set(s.name,o.map(t=>t.capacityMeshNodeId)),t.push({connection:s,nodes:o,pathFound:!1,straightLineDistance:St(o[0].center,o[o.length-1].center)})}return t.sort((t,e)=>t.straightLineDistance-e.straightLineDistance),{connectionsWithNodes:t,connectionNameToGoalNodeIds:n}}currentConnectionIndex=0;candidates;visitedNodes;computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)}getBacktrackedPath(t){const e=[];let n=t;for(;n;)e.push(n.node),n=n.prevCandidate;return e}getNeighboringNodes(t){return this.nodeEdgeMap.get(t.capacityMeshNodeId).flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t))}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const n=e.path;n&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,rootConnectionName:e.connection.rootConnectionName,nodeIds:n.map(t=>t.capacityMeshNodeId)})}return t}doesNodeHaveCapacityForTrace(t,e){const n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=this.getTotalCapacity(t);if(1===t.availableZ.length&&!t._containsTarget&&n>0)return!1;let o=0;return t.availableZ.length>1&&1===e.availableZ.length&&(o+=.5),n+o<s}canTravelThroughObstacle(t,e){const n=this.connectionNameToGoalNodeIds.get(e);return n?.includes(t.capacityMeshNodeId)??!1}getDistanceBetweenNodes(t,e){return Math.sqrt((t.center.x-e.center.x)**2+(t.center.y-e.center.y)**2)}reduceCapacityAlongPath(t){for(const e of t.path??[])this.usedNodeCapacityMap.set(e.capacityMeshNodeId,this.usedNodeCapacityMap.get(e.capacityMeshNodeId)+1)}isConnectedToEndGoal(t,e){return this.nodeEdgeMap.get(t.capacityMeshNodeId).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}_step(){const t=this.connectionsWithNodes[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const[e,n]=t.nodes;this.candidates||(this.candidates=[{prevCandidate:null,node:e,f:0,g:0,h:0}],this.debug_lastNodeCostMap=new Map,this.visitedNodes=new Set([e.capacityMeshNodeId]),this.activeCandidateStraightLineDistance=St(e.center,n.center)),this.candidates.sort((t,e)=>t.f-e.f);const s=this.candidates.shift();if(this.candidates.length>this.MAX_CANDIDATES_IN_MEMORY&&this.candidates.splice(this.MAX_CANDIDATES_IN_MEMORY,this.candidates.length-this.MAX_CANDIDATES_IN_MEMORY),!s)return console.error(`Ran out of candidates on connection ${t.connection.name}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,void(this.failed=!0);if(this.isConnectedToEndGoal(s.node,n))return t.path=this.getBacktrackedPath({prevCandidate:s,node:n,f:0,g:0,h:0}),this.reduceCapacityAlongPath(t),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);const o=this.getNeighboringNodes(s.node);for(const t of o){if(this.visitedNodes?.has(t.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(t,s.node))continue;const e=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;if(t._containsObstacle&&!this.canTravelThroughObstacle(t,e))continue;const o=this.computeG(s,t,n),i=this.computeH(s,t,n),r=o+i*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:r,g:o,h:i});const a={prevCandidate:s,node:t,f:r,g:o,h:i};this.candidates.push(a)}this.visitedNodes.add(s.node.capacityMeshNodeId)}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(this.connectionsWithNodes)for(let e=0;e<this.connectionsWithNodes.length;e++){const n=this.connectionsWithNodes[e];if(n.path&&n.path.length>0){const s=n.path.map(({center:{x:t,y:n},width:s,availableZ:o})=>({x:t+.005*s*(e%10+e%19),y:n+.005*s*(e%10+e%19),availableZ:o}));t.lines.push({points:s,strokeColor:this.colorMap[n.connection.name]});for(let e=0;e<s.length;e++){const o=s[e];t.points.push({x:o.x,y:o.y,label:[`conn: ${n.connection.name}`,`node: ${n.path[e].capacityMeshNodeId}`,`z: ${o.availableZ.join(",")}`].join("\n")})}}}for(const e of this.nodes){const n=this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,s=this.getTotalCapacity(e),o=this.debug_lastNodeCostMap.get(e.capacityMeshNodeId);t.rects.push({...fi(e,{rectMargin:.025,zOffset:.01}),label:[`${e.capacityMeshNodeId}`,`${n}/${s}`,`${e.width.toFixed(2)}x${e.height.toFixed(2)}`,`g: ${void 0!==o?.g?o.g.toFixed(2):"?"}`,`h: ${void 0!==o?.h?o.h.toFixed(2):"?"}`,`f: ${void 0!==o?.f?o.f.toFixed(2):"?"}`,`z: ${e.availableZ.join(", ")}`].join("\n"),stroke:n>s+.5?"red":void 0})}if(this.connectionsWithNodes)for(const e of this.connectionsWithNodes)if(e.connection?.pointsToConnect)for(const n of e.connection.pointsToConnect)t.points.push({x:n.x,y:n.y,label:[`pointsToConnect ${e.connection.name}`].join("\n")});let e=this.connectionsWithNodes[this.currentConnectionIndex];if(!this.candidates&&this.currentConnectionIndex>0&&!this.connectionsWithNodes[this.currentConnectionIndex-1].path&&(e=this.connectionsWithNodes[this.currentConnectionIndex-1]),e){const[n,s]=e.connection.pointsToConnect;t.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.y}],strokeColor:"red",strokeDash:"10 5"})}if(this.candidates){const e=this.candidates.slice(0,5),n=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;e.forEach((e,s)=>{const o=.5*(1-s/5),i=this.getBacktrackedPath(e);t.lines.push({points:i.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:it(this.colorMap[n]??"red",1-o)})})}return t}},yi=class extends gi{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 ke(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){const e=t.width+t.height,n=.05,s=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0);if(s>2)return n;return(e-n)*Math.max(1,(2-s)/(e-n))+n}getDistanceBetweenNodes(t,e){const n=t.center.x-e.center.x,s=t.center.y-e.center.y;return Math.sqrt(n**2+s**2)}computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)+this.getNodeCapacityPenalty(e)}},xi=class extends yi{doesNodeHaveCapacityForTrace(t,e){return!0}getNodeCapacityPenalty(t){const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let n=1;return 1===t.availableZ.length&&(n=10),(.05+2*Math.abs(e))*n}};function vi(t,e,n){const s=e.x-t.x,o=e.y-t.y;if(Math.abs(s)<1e-9&&Math.abs(o)<1e-9)return t;const i=n.width/2,r=n.height/2,a=n.center.x-i,c=n.center.x+i,h=n.center.y-r,d=n.center.y+r;let l=0,u=1/0;if(Math.abs(s)>1e-9){const e=(a-t.x)/s,n=(c-t.x)/s;l=Math.max(l,Math.min(e,n)),u=Math.min(u,Math.max(e,n))}else if(t.x<a||t.x>c)return t;if(Math.abs(o)>1e-9){const e=(h-t.y)/o,n=(d-t.y)/o;l=Math.max(l,Math.min(e,n)),u=Math.min(u,Math.max(e,n))}else if(t.y<h||t.y>d)return t;if(u<l||l===1/0||l<-1e9)return t;return{x:t.x+s*l,y:t.y+o*l}}function Si(t,e){const n=t.center,s=e.center,o=vi(n,s,t),i=vi(s,n,e),r=s.x-n.x,a=s.y-n.y,c=Math.sqrt(r*r+a*a);let h=o,d=i;if(c>1e-9){const n={x:r/c,y:a/c},s=.3*t.width,l=.3*e.width;s+l<Math.sqrt((i.x-o.x)**2+(i.y-o.y)**2)?(h={x:o.x+n.x*s,y:o.y+n.y*s},d={x:i.x-n.x*l,y:i.y-n.y*l}):(h=o,d=i)}return{lineStart:h,lineEnd:d}}var Pi=t=>{const{usedCapacity:e,totalCapacity:n,layerCount:s}=t;if(e<n)return 0;if(n<1&&e<=1)return 0;if(1===s&&e>1)return 1-.01**e;const o=e/n-1;return 1-Math.exp(-2*o)},bi=(t,e,n)=>{if(n._containsTarget)return 0;if(t<=e)return 0;const s=1-Pi({usedCapacity:t,totalCapacity:e,layerCount:n.availableZ.length});return s<=0?-1e9:Math.log(s)},Mi=({totalNodeCapacityMap:t,usedNodeCapacityMap:e,nodeMap:n,sectionNodeIds:s})=>{let o=0;const i=s??new Set(e.keys());for(const s of i){if(!t.has(s))continue;const i=n.get(s);if(!i)continue;const r=t.get(s),a=e.get(s)??0;o+=bi(a,r,i)}return o};function Ni({sectionNodes:t,sectionEdges:e,sectionConnectionTerminals:n,completedPaths:s,nodeMap:o,colorMap:i,centerNodeId:r,title:a,nodeOpacity:c=.1,usedNodeCapacityMap:h,totalCapacityMap:d}){const l={points:[],lines:[],rects:[],circles:[],title:a},u=new Set(t.map(t=>t.capacityMeshNodeId));for(const e of t){let t=`rgba(128, 128, 128, ${c})`,n=`rgba(128, 128, 128, ${c})`;const s=e.availableZ??[],o=s.includes(0),i=s.includes(1);o&&i?(t=`rgba(128, 0, 128, ${c})`,n=`rgba(128, 0, 128, ${c})`):o?(t=`rgba(0, 0, 255, ${c})`,n=`rgba(0, 0, 255, ${c})`):i&&(t=`rgba(255, 0, 0, ${c})`,n=`rgba(255, 0, 0, ${c})`),r&&e.capacityMeshNodeId===r&&(t=`rgba(0, 255, 0, ${c})`,n=`rgba(0, 128, 0, ${c})`),l.rects.push({...fi(e),fill:t,stroke:n,label:`${e.capacityMeshNodeId}\n(Section Node)\nZ: ${s.join(",")}`});const a=l.rects.length-1;if(h&&d){const t=h.get(e.capacityMeshNodeId)??0,n=d.get(e.capacityMeshNodeId)??0,s=n>0?(t/n*100).toFixed(1):"N/A",o=Pi({usedCapacity:t,totalCapacity:n,layerCount:e.availableZ.length});l.rects[a].label+=`\n${t.toFixed(1)} / ${n.toFixed(1)}\n${s}% (Pf: ${(100*o).toFixed(1)}%)`,o>.2&&(l.rects[a].stroke=it("red",.7*(.8+c)))}}for(const t of e){const[e,n]=t.nodeIds,s=o.get(e),i=o.get(n);if(s&&i){const{lineStart:t,lineEnd:e}=Si(s,i);l.lines.push({points:[t,e],strokeColor:`rgba(0, 0, 0, ${.2*Math.min(1,c/.1)})`})}}return n.forEach((t,e)=>{const n=o.get(t.startNodeId),s=o.get(t.endNodeId),r=i[t.connectionName]??"black",a=n&&u.has(n.capacityMeshNodeId),c=s&&u.has(s.capacityMeshNodeId),h=(e+e/50)%5;let d=0,p=0,m=0,f=0;if(a&&n){const e=.02*Math.min(n.width,n.height);d=e*h,p=e*h,l.points.push({x:n.center.x+d,y:n.center.y+p,color:r,label:`Start: ${t.connectionName}\n(${t.startNodeId})`}),l.lines.push({points:[{x:n.center.x,y:n.center.y},{x:n.center.x+d,y:n.center.y+p}],strokeColor:"gray",strokeDash:"2 2"})}if(c&&s){const e=.02*Math.min(s.width,s.height);m=e*h,f=e*h,l.points.push({x:s.center.x+m,y:s.center.y+f,color:r,label:`End: ${t.connectionName}\n(${t.endNodeId})`}),l.lines.push({points:[{x:s.center.x,y:s.center.y},{x:s.center.x+m,y:s.center.y+f}],strokeColor:"gray",strokeDash:"2 2"})}a&&c&&n&&s&&l.lines.push({points:[{x:n.center.x+d,y:n.center.y+p},{x:s.center.x+m,y:s.center.y+f}],strokeColor:r,strokeDash:"5 5"})}),s&&s.forEach((t,e)=>{if(t.path&&t.path.length>0){const n=i[t.connectionName]??"gray",s={x:(e+e/50)%5*.03,y:(e+e/50)%5*.03};l.lines.push({points:t.path.map(({center:{x:t,y:e}})=>({x:t+s.x,y:e+s.y})),strokeColor:it(n,.2)})}}),l}var Ii=class extends y{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??No(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=Mi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:e}),t.hyperParameters?.SHUFFLE_SEED&&(this.sectionConnectionTerminals=kt(this.sectionConnectionTerminals,t.hyperParameters?.SHUFFLE_SEED))}getTotalCapacity(t){return ke(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){if(!this.nodeMap.has(t.capacityMeshNodeId))return 1/0;const e=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0)-1;if(e>0)return 0;let n=1;return 1===t.availableZ.length&&(n=10),(.05+e**2*4)*n}getDistanceBetweenNodes(t,e){const n=t.center.x-e.center.x,s=t.center.y-e.center.y;return Math.sqrt(n**2+s**2)}computeG(t,e,n){return t.g+this.getDistanceBetweenNodes(t.node,e)+this.getNodeCapacityPenalty(e)}computeH(t,e,n){return this.getDistanceBetweenNodes(e,n)+this.getNodeCapacityPenalty(e)}getBacktrackedPath(t){const e=[];let n=t;for(;n;){if(e.push(n.node),!this.nodeMap.has(n.node.capacityMeshNodeId)){console.warn("Backtracked path went outside section bounds");break}n=n.prevCandidate}return e.reverse()}getNeighboringNodes(t){return this.nodeMap.has(t.capacityMeshNodeId)?this.nodeEdgeMap.get(t.capacityMeshNodeId)?.flatMap(e=>e.nodeIds.filter(e=>e!==t.capacityMeshNodeId)).map(t=>this.nodeMap.get(t)).filter(Boolean)??[]:[]}isConnectedToEndGoal(t,e){return!(!this.nodeMap.has(t.capacityMeshNodeId)||!this.nodeMap.has(e.capacityMeshNodeId))&&(this.nodeEdgeMap.get(t.capacityMeshNodeId)??[]).some(t=>t.nodeIds.includes(e.capacityMeshNodeId))}doesNodeHaveCapacityForTrace(t,e){return!0}reduceCapacityAlongPath(t){for(const e of t)if(this.usedNodeCapacityMap.has(e.capacityMeshNodeId)){const t=e.capacityMeshNodeId,n=this.nodeMap.get(t);if(!n){console.warn(`Node ${t} from path not found in section's nodeMap during score update.`);continue}const s=this.totalNodeCapacityMap.get(t),o=this.usedNodeCapacityMap.get(t)??0,i=bi(o,s,n);this.currentSectionScore-=i;const r=o+1;this.usedNodeCapacityMap.set(t,r);const a=bi(r,s,n);this.currentSectionScore+=a}}getSolvedSectionScore(){return this.currentSectionScore}_step(){const t=this.sectionConnectionTerminals[this.currentConnectionIndex];if(!t)return void(this.solved=!0);const e=this.nodeMap.get(t.startNodeId),n=this.nodeMap.get(t.endNodeId);if(!e||!n)return console.error(`Start or end node not found in section for connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);this.candidates||this._setupAStar(e,n);const s=this.candidates;if(0===s.length)return void this._handleCandidatesExhausted(t);s.sort((t,e)=>t.f-e.f);const o=s.shift();if(s.length>this.MAX_CANDIDATES_IN_MEMORY&&s.splice(this.MAX_CANDIDATES_IN_MEMORY,s.length-this.MAX_CANDIDATES_IN_MEMORY),this.visitedNodes.add(o.node.capacityMeshNodeId),o.node.capacityMeshNodeId===n.capacityMeshNodeId)return void this._handleGoalReached(o,t,n);const i=this.getNeighboringNodes(o.node);for(const e of i){if(this.queuedNodes?.has(e.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(e,o.node))continue;if(e._containsObstacle){const n=e.capacityMeshNodeId===t.startNodeId,s=e.capacityMeshNodeId===t.endNodeId;if(!n&&!s)continue}const i=this.computeG(o,e,n),r=this.computeH(o,e,n),a=i+r*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(e.capacityMeshNodeId,{f:a,g:i,h:r});const c={prevCandidate:o,node:e,f:a,g:i,h:r};this.queuedNodes?.add(e.capacityMeshNodeId),s.push(c)}}computeProgress(){const t=this.sectionConnectionTerminals.length;if(0===t)return 1;let e=this.currentConnectionIndex/t;if(this.currentConnectionIndex<t&&this.candidates&&this.candidates.length>0&&this.activeCandidateStraightLineDistance&&this.activeCandidateStraightLineDistance>0){const n=this.candidates.reduce((t,e)=>e.f<t.f?e:t);e+=Math.max(0,Math.min(1,1-n.h/this.activeCandidateStraightLineDistance))/t}else this.solved&&(e=1);return Math.min(1,e)}_setupAStar(t,e){this.candidates=[{prevCandidate:null,node:t,f:0,g:0,h:0}],this.visitedNodes=new Set([t.capacityMeshNodeId]),this.debug_lastNodeCostMap=new Map,this.activeCandidateStraightLineDistance=St(t.center,e.center);const n=this.computeH(null,t,e);this.candidates[0].h=n,this.candidates[0].f=n*this.GREEDY_MULTIPLIER,this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:this.candidates[0].f,g:0,h:n}),this.queuedNodes=new Set([t.capacityMeshNodeId])}_handleCandidatesExhausted(t){console.error(`Ran out of candidates for section connection ${t.connectionName}`),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}_handleGoalReached(t,e,n){const s=this.getBacktrackedPath(t);e.path=s,this.reduceCapacityAlongPath(s),this.currentConnectionIndex++,this.candidates=null,this.visitedNodes=null,this.queuedNodes=null}visualize(){const t=this.sectionConnectionTerminals.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connectionName,path:t.path})),e=Ni({sectionNodes:this.sectionNodes,sectionEdges:this.sectionEdges,sectionConnectionTerminals:this.sectionConnectionTerminals,completedPaths:t,nodeMap:this.nodeMap,colorMap:this.colorMap,centerNodeId:null,title:`Section Pathing: Conn ${this.currentConnectionIndex+1}/${this.sectionConnectionTerminals.length} (${this.sectionNodes.length} nodes)`,nodeOpacity:.1});for(const t of this.sectionNodes){const n=e.rects.findIndex(e=>e.label?.includes(t.capacityMeshNodeId));if(-1!==n){const s=this.debug_lastNodeCostMap.get(t.capacityMeshNodeId),o=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,i=this.getTotalCapacity(t),r=`${o.toFixed(1)}/${i.toFixed(1)}`,a=s?`f:${s.f.toFixed(1)} g:${s.g.toFixed(1)} h:${s.h.toFixed(1)}`:"cost:?";e.rects[n].label=[t.capacityMeshNodeId,`Cap: ${r}`,a,`Z: ${t.availableZ.join(",")}`].join("\n"),o>i&&(e.rects[n].stroke=it("red",.7))}}if(this.candidates&&this.candidates.length>0){const t=this.candidates.slice().sort((t,e)=>t.f-e.f).slice(0,5),n=this.sectionConnectionTerminals[this.currentConnectionIndex],s=n?.connectionName??"unknown",o=this.colorMap[s]??"purple";t.forEach((t,n)=>{const s=.8*(1-n/5),i=this.getBacktrackedPath(t);i.length>0&&e.lines.push({points:i.map(({center:{x:t,y:e}})=>({x:t,y:e})),strokeColor:it(o,1-s),strokeWidth:.05})})}return e}},Ci=t=>Array.from({length:t},(t,e)=>e),_i=class extends Zt{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:Ci(2).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings6_for3",possibleValues:Ci(6).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings24_for4",possibleValues:Ci(24).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings30",possibleValues:Ci(30).map(t=>({SHUFFLE_SEED:t}))}]}generateSolver(t){return new Ii({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}onSolve({solver:t}){this.winningSolver=t}get centerNodeId(){return this.constructorParams.centerNodeId}get sectionNodes(){return this.constructorParams.sectionNodes}get sectionConnectionTerminals(){return this.winningSolver?.sectionConnectionTerminals}};import Ti from"object-hash";var Ei=t=>Math.floor(10*t)/10,Ri=class extends _i{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?ut():t.cacheProvider}_step(){!this.hasAttemptedToUseCache&&this.cacheProvider&&this.attemptToUseCacheSync()||(super._step(),(this.solved||this.failed)&&this.cacheProvider&&this.saveToCacheSync())}_computeBfsOrderingOfNodesInSection(){const t=new Set(this.constructorParams.centerNodeId),e=[],n=[{ancestorCapacitySum:0,capacity:0,g:0,capacityMeshNodeId:this.constructorParams.centerNodeId}];for(;n.length>0;){n.sort((t,e)=>e.g-t.g);const s=n.pop();if(!s)break;e.push(s.capacityMeshNodeId);const o=this.constructorParams.nodeEdgeMap.get(s.capacityMeshNodeId).flatMap(t=>t.nodeIds).filter(e=>!t.has(e)).filter(t=>this.sectionNodeIdSet.has(t));for(const e of o){t.add(e);const o=this.constructorParams.nodeMap.get(e),i=ke(o);n.push({ancestorCapacitySum:s.g,capacity:i,g:s.g+i,capacityMeshNodeId:e})}}return e}computeCacheKeyAndTransform(){const t=this._computeBfsOrderingOfNodesInSection(),e=new Map,n=new Map;t.forEach((t,s)=>{const o=`node${s}`;e.set(t,o),n.set(o,t)});const s={};for(const n of t){const t=e.get(n),o=this.constructorParams.nodeMap.get(n),i=ke(o);s[t]=Ei(i).toFixed(1)}const o=new Set,i=[];for(const n of t){const t=e.get(n),s=this.constructorParams.nodeEdgeMap.get(n)??[];for(const r of s){const s=r.nodeIds.find(t=>t!==n);if(this.sectionNodeIdSet.has(s)){const n=[t,e.get(s)].sort(),r=`${n[0]}-${n[1]}`;o.has(r)||(i.push(n),o.add(r))}}}i.sort((t,e)=>t[0]!==e[0]?t[0].localeCompare(e[0]):t[1].localeCompare(e[1]));const r={},a=new Map,c=new Map;for(const t of this.constructorParams.sectionConnectionTerminals){const n=e.get(t.startNodeId),s=e.get(t.endNodeId),[o,i]=[n,s].sort(),h=`${o}->${i}`,d=c.get(h)??0;c.set(h,d+1);const l=`${o}->${i}::${d}`;r[l]={start:o,end:i},a.set(l,t.connectionName)}const h=`capacitypathing:${Ti({node_capacity_map:s,node_edge_map:i,terminals:r})}`,d={cacheSpaceToRealConnectionId:a,cacheSpaceToRealNodeId:n};return this.cacheKey=h,this.cacheToSolveSpaceTransform=d,{cacheKey:h,cacheToSolveSpaceTransform:d}}applyCachedSolution(t){if(!this.cacheToSolveSpaceTransform)return console.error("Cache transform not available, cannot apply cached solution."),void(this.failed=!0);if(!t.success)return this.failed=!0,void(this.cacheHit=!0);this.cachedSectionConnectionTerminals=[];const{cacheSpaceToRealNodeId:e,cacheSpaceToRealConnectionId:n}=this.cacheToSolveSpaceTransform;for(const[s,o]of Object.entries(t.solutionPaths)){const t=n.get(s);if(!t){console.warn(`Could not find real connection name for ${s}`);continue}const i=this.constructorParams.sectionConnectionTerminals.find(e=>e.connectionName===t);if(!i){console.warn(`Could not find original terminal for connection name ${t}`);continue}const r=o.map(n=>{const s=e.get(n);if(!s)throw new Error(`Could not map cache node ID ${n} to real node ID for connection ${t}`);const o=this.constructorParams.nodeMap.get(s);if(!o)throw new Error(`Could not find node with ID ${s} in nodeMap for connection ${t}`);return o});this.cachedSectionConnectionTerminals.push({...i,path:r})}this.sectionScore=t.sectionScore,this.solved=!0,this.cacheHit=!0}attemptToUseCacheSync(){if(this.hasAttemptedToUseCache=!0,!this.cacheProvider?.isSyncCache)return console.log("Cache provider is not synchronous, skipping sync cache check."),!1;if(this.cacheKey||this.computeCacheKeyAndTransform(),!this.cacheKey)return console.error("Failed to compute cache key."),!1;try{const t=this.cacheProvider.getCachedSolutionSync(this.cacheKey);if(t)return this.applyCachedSolution(t),!0}catch(t){console.error("Error attempting to use cache:",t)}return!1}saveToCacheSync(){if(!this.cacheKey)return void console.error("Cannot save to cache without cache key.");if(!this.cacheToSolveSpaceTransform)return void console.error("Cache transform not available, cannot save solution to cache.");let t;if(this.failed)t={success:!1};else{if(!this.solved)return;{const e={},{cacheSpaceToRealNodeId:n,cacheSpaceToRealConnectionId:s}=this.cacheToSolveSpaceTransform,o=new Map;for(const[t,e]of n)o.set(e,t);const i=new Map;for(const[t,e]of s)i.set(e,t);const r=[];if(super.sectionConnectionTerminals)for(const t of super.sectionConnectionTerminals)if(t.path&&t.path.length>0){const e=t.path.map(t=>t.capacityMeshNodeId);r.push([t.connectionName,e])}for(const[t,n]of r){const s=i.get(t);if(!s){console.warn(`Could not find cache space connection ID for ${t} when saving to cache.`);continue}const r=n.map(e=>{const n=o.get(e);if(!n)throw new Error(`Could not map real node ID ${e} to cache node ID for connection ${t} when saving to cache.`);return n});e[s]=r}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 Ni({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"})}},wi=class extends y{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=No(this.edges),this.colorMap=t.colorMap??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=No(this.edges),this.initialSolver=t.initialPathingSolver||new xi({simpleRouteJson:this.simpleRouteJson,nodes:this.nodes,edges:this.edges,colorMap:this.colorMap}),this.activeSubSolver=this.initialSolver;for(const t of this.nodes){const e=this.initialSolver.getTotalCapacity(t);this.totalNodeCapacityMap.set(t.capacityMeshNodeId,e)}this.allNodeIdsSet=new Set(this.nodes.map(t=>t.capacityMeshNodeId))}_stepInitialization(){if(this.initialSolver?.step(),this.initialSolver?.failed)return this.failed=!0,void(this.error=this.initialSolver.error);if(this.initialSolver?.solved){this.usedNodeCapacityMap=new Map(this.initialSolver.usedNodeCapacityMap);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,s),this.nodeOptimizationAttemptCountMap.set(t.capacityMeshNodeId,0)}this.connectionsWithNodes=this.initialSolver.connectionsWithNodes,this.stats.startingScore=Mi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet}),this.stage="section-optimization"}}_getNextNodeToOptimize(){let t=0,e=0,n=null;for(const s of this.nodes){if(s._containsTarget)continue;const o=this.nodeOptimizationAttemptCountMap.get(s.capacityMeshNodeId),i=this.totalNodeCapacityMap.get(s.capacityMeshNodeId),r=Pi({usedCapacity:this.usedNodeCapacityMap.get(s.capacityMeshNodeId)??0,totalCapacity:i,layerCount:s.availableZ.length}),a=r/(o+1);o<this.currentSchedule.MAX_ATTEMPTS_PER_NODE&&a>t&&r>this.currentSchedule.MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE&&(t=a,e=r,n=s.capacityMeshNodeId)}return n}getOverallScore(){let t=0;for(const e of this.nodes){if(e._containsTarget)continue;const n=this.totalNodeCapacityMap.get(e.capacityMeshNodeId),s=Pi({usedCapacity:this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,totalCapacity:n,layerCount:e.availableZ.length});s>t&&(t=s)}return{highestNodePf:t,score:Mi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:this.allNodeIdsSet})}}_stepSectionOptimization(){if(!this.sectionSolver){const t=this._getNextNodeToOptimize();if(!t){const{highestNodePf:t,score:e}=this.getOverallScore();return this.stats.scheduleScores[this.currentScheduleIndex].endingHighestNodePf=t,this.stats.scheduleScores[this.currentScheduleIndex].endingScore=e,this.currentScheduleIndex++,void(this.currentSchedule||(this.solved=!0))}const e=(t=>{const{centerNodeId:e,connectionsWithNodes:n,nodeMap:s,edges:o,nodeEdgeMap:i,expansionDegrees:r}=t,a=new Set,c=[{nodeId:e,depth:0}];a.add(e);let h=0;for(;h<c.length;){const{nodeId:t,depth:e}=c[h++];if(e>=r)continue;const n=i.get(t)?.flatMap(e=>e.nodeIds.filter(e=>e!==t))??[];for(const t of n)a.has(t)||(a.add(t),c.push({nodeId:t,depth:e+1}))}const d=Array.from(a).map(t=>s.get(t)),l=o.filter(t=>{const[e,n]=t.nodeIds;return a.has(e)&&a.has(n)}),u=[];for(const t of n){if(!t.path)continue;let e=null,n=null;for(const n of t.path)if(a.has(n.capacityMeshNodeId)){e=n.capacityMeshNodeId;break}for(let e=t.path.length-1;e>=0;e--){const s=t.path[e];if(a.has(s.capacityMeshNodeId)){n=s.capacityMeshNodeId;break}}e&&n&&u.push({connectionName:t.connection.name,startNodeId:e,endNodeId:n})}return{sectionConnectionTerminals:u,sectionNodes:d,sectionEdges:l,centerNodeId:e}})({centerNodeId:t,connectionsWithNodes:this.connectionsWithNodes,nodeMap:this.nodeMap,edges:this.edges,expansionDegrees:this.currentSchedule.MAX_EXPANSION_DEGREES,nodeEdgeMap:this.nodeEdgeMap});this.stats.scheduleScores[this.currentScheduleIndex].sectionAttempts++,this.currentSection=e,this.sectionSolver=new Ri({sectionNodes:this.currentSection.sectionNodes,sectionEdges:this.currentSection.sectionEdges,sectionConnectionTerminals:this.currentSection.sectionConnectionTerminals,colorMap:this.colorMap,centerNodeId:this.currentSection.centerNodeId,nodeEdgeMap:this.nodeEdgeMap,hyperParameters:{EXPANSION_DEGREES:this.currentSchedule.MAX_EXPANSION_DEGREES},cacheProvider:this.cacheProvider}),this.activeSubSolver=this.sectionSolver,this.nodeOptimizationAttemptCountMap.set(t,(this.nodeOptimizationAttemptCountMap.get(t)??0)+1)}if(this.sectionSolver.step(),(this.sectionSolver.failed||this.sectionSolver.solved)&&(this.sectionSolver.cacheHit?this.stats.cacheHits++:this.stats.cacheMisses++),this.sectionSolver.failed)return console.warn(`Section solver failed for node ${this.currentSection.centerNodeId}. Error: ${this.sectionSolver.error}`),this.stats.failedSectionSolvers++,this.stats.failedOptimizations++,this.sectionSolver=null,void(this.activeSubSolver=null);if(this.sectionSolver.solved){const t=this.sectionSolver.sectionConnectionTerminals,e=this.sectionSolver.sectionNodes,n=this.sectionSolver.centerNodeId;if(this.sectionSolver=null,this.activeSubSolver=null,!t)return void console.warn(`Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`);const s=new Set(e.map(t=>t.capacityMeshNodeId)),o=Mi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:s}),i=new Map(this.usedNodeCapacityMap),r=t;for(const t of r){const e=this.connectionsWithNodes.find(e=>e.connection.name===t.connectionName);if(e?.path)for(const t of e.path)if(s.has(t.capacityMeshNodeId)){const e=i.get(t.capacityMeshNodeId)??0;i.set(t.capacityMeshNodeId,Math.max(0,e-1))}}for(const t of r)if(t.path)for(const e of t.path)s.has(e.capacityMeshNodeId)&&i.set(e.capacityMeshNodeId,(i.get(e.capacityMeshNodeId)??0)+1);Mi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:i,nodeMap:this.nodeMap,sectionNodeIds:s})>o?(this.stats.successfulOptimizations++,this._mergeSolvedSectionPaths({centerNodeId:n,sectionConnectionTerminals:t}),this._recalculateNodeCapacityUsage()):this.stats.failedOptimizations++}}_mergeSolvedSectionPaths({centerNodeId:t,sectionConnectionTerminals:e}){for(const n of e){if(!n.path){console.warn(`No path found for connection ${n.connectionName} in section ${t}`);continue}const e=this.connectionsWithNodes.find(t=>t.connection.name===n.connectionName);if(!e||!e.path){console.warn(`Original connection or path not found for ${n.connectionName} while merging section ${t}`);continue}const s=e.path,o=n.path,i=s.findIndex(t=>t.capacityMeshNodeId===n.startNodeId),r=s.findIndex(t=>t.capacityMeshNodeId===n.endNodeId);if(-1===i||-1===r){console.warn(`Could not find start/end nodes (${n.startNodeId}/${n.endNodeId}) in original path for ${n.connectionName}`);continue}const[a,c]=i<=r?[i,r]:[r,i],h=s.slice(0,a),d=s.slice(c+1);let l=o;if(o.length>0&&s[a]&&o[0].capacityMeshNodeId!==s[a].capacityMeshNodeId){if(o[o.length-1].capacityMeshNodeId!==s[a].capacityMeshNodeId){console.warn(`New section path for ${n.connectionName} doesn't align with original path boundaries. Skipping merge for this connection.`);continue}l=[...o].reverse()}e.path=[...h,...l,...d]}}_recalculateNodeCapacityUsage(){this.usedNodeCapacityMap.clear();for(const t of this.connectionsWithNodes)if(t.path)for(const e of t.path)this.usedNodeCapacityMap.set(e.capacityMeshNodeId,(this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0)+1);for(const t of this.nodes){const e=this.totalNodeCapacityMap.get(t.capacityMeshNodeId)??0,n=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,s=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,s)}}getCapacityPaths(){const t=[];for(const e of this.connectionsWithNodes){const n=e.path;n&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:n.map(t=>t.capacityMeshNodeId)})}return t}_step(){this.iterations>=this.MAX_ITERATIONS-1?this.solved=!0:"initialization"===this.stage?this._stepInitialization():"section-optimization"===this.stage&&this._stepSectionOptimization()}visualize(){const t=this.connectionsWithNodes.filter(t=>t.path&&t.path.length>0).map(t=>({connectionName:t.connection.name,path:t.path}));return Ni({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)"})}},Ai=class extends y{multiLayerNodes;strawNodes;skippedNodes;unprocessedNodes;strawSize;nodeIdCounter;constructor(t){super(),this.MAX_ITERATIONS=1e5,this.strawSize=t.strawSize??.5,this.multiLayerNodes=[],this.strawNodes=[],this.skippedNodes=[],this.nodeIdCounter=0,this.unprocessedNodes=[];for(const e of t.nodes)1===e.availableZ.length?this.unprocessedNodes.push(e):this.multiLayerNodes.push(e)}getCapacityOfMultiLayerNodesWithinBounds(t){let e=0;for(const n of this.multiLayerNodes){const s=n.center.x-n.width/2,o=n.center.x+n.width/2,i=n.center.y-n.height/2,r=n.center.y+n.height/2,a=Math.max(t.minX,s),c=Math.min(t.maxX,o),h=Math.max(t.minY,i),d=Math.min(t.maxY,r);if(a<c&&h<d){const t=(c-a)*(d-h)/(n.width*n.height);e+=ke(n)*t}}return e}getSurroundingCapacities(t){const e=Math.min(t.width,t.height);return{leftSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2-e,maxX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),rightSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x+t.width/2,maxX:t.center.x+t.width/2+e,minY:t.center.y-t.height/2,maxY:t.center.y+t.height/2}),topSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y-t.height/2-e,maxY:t.center.y-t.height/2}),bottomSurroundingCapacity:this.getCapacityOfMultiLayerNodesWithinBounds({minX:t.center.x-t.width/2,maxX:t.center.x+t.width/2,minY:t.center.y+t.height/2,maxY:t.center.y+t.height/2+e})}}createStrawsForNode(t){const e=[],{leftSurroundingCapacity:n,rightSurroundingCapacity:s,topSurroundingCapacity:o,bottomSurroundingCapacity:i}=this.getSurroundingCapacities(t);if(1*(n+s)>o+i){const n=Math.floor(t.height/this.strawSize),s=t.height/n;for(let o=0;o<n;o++){const n=t.center.y-t.height/2+o*s+s/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${o}`,center:{x:t.center.x,y:n},width:t.width,height:s,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}else{const n=Math.floor(t.width/this.strawSize),s=t.width/n;for(let o=0;o<n;o++){const n=t.center.x-t.width/2+o*s+s/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${o}`,center:{x:n,y:t.center.y},width:s,height:t.height,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}return e}getResultNodes(){return[...this.multiLayerNodes,...this.strawNodes,...this.skippedNodes]}_step(){const t=this.unprocessedNodes.pop();if(!t)return void(this.solved=!0);if(t.width<this.strawSize&&t.height<this.strawSize)return void this.skippedNodes.push(t);if(t._containsTarget)return void this.skippedNodes.push(t);const e=this.createStrawsForNode(t);this.strawNodes.push(...e),0===e.length&&this.strawNodes.push(t)}visualize(){const t={rects:[],lines:[],points:[],circles:[],title:"Straw Solver"};for(const e of this.unprocessedNodes)t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(200, 200, 200, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nUnprocessed\n${e.width}x${e.height}`});for(const e of this.strawNodes){const n=0===e.availableZ[0]?"rgba(0, 150, 255, 0.5)":"rgba(255, 100, 0, 0.5)";t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,stroke:"rgba(0, 0, 0, 0.5)",label:`${e.capacityMeshNodeId}\nLayer: ${e.availableZ[0]}\n${e.width}x${e.height}`,layer:`z${e.availableZ.join(",")}`})}for(const e of this.multiLayerNodes)t.rects.push({center:e.center,width:.9*e.width,height:.9*e.height,fill:"rgba(100, 255, 100, 0.5)",stroke:"rgba(0, 0, 0, 0.5)",layer:`z${e.availableZ.join(",")}`,label:`${e.capacityMeshNodeId}\nLayers: ${e.availableZ.join(",")}\n${e.width}x${e.height}`});return t}},Oi=class extends y{removedNodeIds;targetNodeIds;leaves;leavesIndex;adjacencyList;nodeMap;nodes;edges;constructor({nodes:t,edges:e}){super(),this.MAX_ITERATIONS=t.length,this.nodes=t,this.edges=e,this.removedNodeIds=new Set,this.targetNodeIds=new Set(t.filter(t=>t._containsTarget).map(t=>t.capacityMeshNodeId)),this.adjacencyList=new Map(t.map(({capacityMeshNodeId:t})=>[t,new Set]));for(const{nodeIds:[t,n]}of e)this.adjacencyList.get(t).add(n),this.adjacencyList.get(n).add(t);this.leavesIndex=0,this.leaves=[...this.adjacencyList.entries()].filter(([t,e])=>1===e.size).filter(([t,e])=>!this.targetNodeIds.has(t)).map(([t,e])=>t)}_step(){if(this.leavesIndex===this.leaves.length)return void(this.solved=!0);const t=this.leaves[this.leavesIndex],e=this.adjacencyList.get(t);if(!e||0===e.size)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));const[n]=e,s=n?this.adjacencyList.get(n):void 0;if(!n||!s)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));s.delete(t),this.removedNodeIds.add(t),this.adjacencyList.delete(t),1!==s.size||this.targetNodeIds.has(n)||this.leaves.push(n),this.leavesIndex+=1,this.leavesIndex===this.leaves.length&&(this.solved=!0)}visualize(){if(!this.nodeMap){this.nodeMap=new Map;for(const t of this.nodes)this.nodeMap.set(t.capacityMeshNodeId,t)}const t=new Map;for(const e of this.edges)for(const n of e.nodeIds)t.set(n,1+(t.get(n)??0));const e={lines:[],points:[],rects:this.nodes.map(e=>{const n=Math.min(...e.availableZ);return{width:Math.max(e.width-2,.8*e.width),height:Math.max(e.height-2,.8*e.height),center:{x:e.center.x+n*e.width*.05,y:e.center.y-n*e.width*.05},fill:e._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[e.availableZ.join(",")]??"rgba(0,200,200,0.1)",label:[e.capacityMeshNodeId,`availableZ: ${e.availableZ.join(",")}`,`target? ${e._containsTarget??!1}`,`obs? ${e._containsObstacle??!1}`,`conn: ${t.get(e.capacityMeshNodeId)??0}`].join("\n"),layer:`z${e.availableZ.join(",")}`}}),circles:[]};for(const t of this.edges){const n=this.nodeMap.get(t.nodeIds[0]),s=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&s?.center){const o=Math.min(...n.availableZ),i=Math.min(...s.availableZ),r={x:n.center.x+o*n.width*.05,y:n.center.y-o*n.width*.05},a={x:s.center.x+i*s.width*.05,y:s.center.y-i*s.width*.05},c=Array.from(new Set([...n.availableZ,...s.availableZ])).sort();e.lines.push({layer:`z${c.join(",")}`,points:[r,a],strokeDash:n.availableZ.join(",")===s.availableZ.join(",")?void 0:"10 5",strokeColor:t.nodeIds.some(t=>this.removedNodeIds.has(t))?it("black",.9):void 0})}}return e}};function zi(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Di=class extends y{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,o=Math.max(n,s),i=e.targetMinCapacity??.5;e.capacityDepth=Be(o,i)}this.connMap=$e(t),this.colorMap=ot(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;initialPathingSolver;pathingOptimizer;edgeToPortSegmentSolver;colorMap;segmentToPointSolver;unravelMultiSectionSolver;segmentToPointOptimizer;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;viaDiameter;minTraceWidth;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[zi("netToPointPairsSolver",gn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ot(t.srjWithPointPairs,this.connMap),t.connMap=$e(t.srjWithPointPairs)}}),zi("nodeSolver",Js,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),zi("strawSolver",Ai,t=>[{nodes:t.capacityNodes}],{onSolved:t=>{t.capacityNodes=t.strawSolver?.getResultNodes()}}),zi("edgeSolver",cn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),zi("deadEndSolver",Oi,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges}],{onSolved:t=>{const e=t.deadEndSolver?.removedNodeIds;t.capacityNodes=t.capacityNodes.filter(t=>!e.has(t.capacityMeshNodeId)),t.capacityEdges=t.capacityEdges.filter(t=>t.nodeIds.every(t=>!e.has(t)))}}),zi("initialPathingSolver",xi,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),zi("pathingOptimizer",wi,t=>[{initialPathingSolver:t.initialPathingSolver,simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,cacheProvider:t.cacheProvider,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),zi("edgeToPortSegmentSolver",qo,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.pathingOptimizer?.getCapacityPaths()||[],colorMap:t.colorMap}]),zi("segmentToPointSolver",ni,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),zi("unravelMultiSectionSolver",mi,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),zi("highDensityRouteSolver",Le,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),zi("highDensityStitchSolver",nn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),zi("traceSimplificationSolver",Mo,t=>[{hdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline,defaultViaDiameter:t.viaDiameter,layerCount:t.srj.layerCount,iterations:2}])];getConstructorParams(){return[this.srj,this.opts]}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 t=this.netToPointPairsSolver?.visualize(),e=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),s=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),i=this.edgeSolver?.visualize(),r=this.deadEndSolver?.visualize(),a=this.initialPathingSolver?.visualize(),c=this.pathingOptimizer?.visualize(),h=this.edgeToPortSegmentSolver?.visualize(),d=this.segmentToPointSolver?.visualize(),l=this.unravelMultiSectionSolver?.visualize()??this.segmentToPointOptimizer?.visualize(),u=this.highDensityRouteSolver?.visualize(),p=this.highDensityStitchSolver?.visualize(),m=this.traceSimplificationSolver?.visualize(),f=this.srj.outline,y=[];if(y.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),f&&f.length>=2){const t=f.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),y.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const x={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:t.layers?.join(", ")}))],lines:y},v=[x,t,e,n,s,o,i,r,a,c,h,d,l,u?g(x,u):null,p,m,this.solved?g(x,sn(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...v)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.connectionName]}),t.length>200)break}return{lines:t}}if(this.pathingOptimizer){const t=[];for(const e of this.pathingOptimizer.connectionsWithNodes)e.path&&t.push({points:e.path.map(t=>({x:t.center.x,y:t.center.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,o=e.filter(t=>t.connectionName===n.name);for(let e=0;e<o.length;e++){const i=o[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:We(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Li=.1,Fi=.1;function Xi(t,e,n,s,o,i){return(o-t)*(s-e)-(i-e)*(n-t)}function Yi(t,e,n,s,o,i){return Math.min(t,n)<=o&&o<=Math.max(t,n)&&Math.min(e,s)<=i&&i<=Math.max(e,s)}function $i(t,e,n,s,o,i,r,a){const c=Xi(o,i,r,a,t,e),h=Xi(o,i,r,a,n,s),d=Xi(t,e,n,s,o,i),l=Xi(t,e,n,s,r,a);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)||(!(0!==c||!Yi(o,i,r,a,t,e))||(!(0!==h||!Yi(o,i,r,a,n,s))||(!(0!==d||!Yi(t,e,n,s,o,i))||!(0!==l||!Yi(t,e,n,s,r,a)))))}function ki(t,e,n,s,o,i){const r=o-n,a=i-s,c=t-n,h=e-s,d=r*r+a*a;if(0===d){return{x:n,y:s,distSq:c*c+h*h}}let l=(c*r+h*a)/d;l=Math.max(0,Math.min(1,l));const u=n+l*r,p=s+l*a,m=t-u,f=e-p;return{x:u,y:p,distSq:m*m+f*f}}var Bi=class extends y{unsolvedNodes;allNodes;routes;colorMap;traceWidth;viaDiameter;numMovablePoints;currentNode=null;lastNode=null;currentNodeStep=0;routesInProgress=[];pushMargin;currentNodeBounds=null;constructor({nodePortPoints:t,colorMap:e,traceWidth:n=.1,viaDiameter:s=.6,pushMargin:o=.3,numMovablePoints:i=2}){if(super(),i<1||i>3)throw new Error(`numMovablePoints must be 1, 2, or 3, got ${i}`);this.allNodes=[...t],this.unsolvedNodes=[...t],this.colorMap=e??{},this.routes=[],this.traceWidth=n,this.viaDiameter=s,this.numMovablePoints=i,this.pushMargin=o,this.MAX_ITERATIONS=10*t.length+1}_step(){if(null===this.currentNode){if(0===this.unsolvedNodes.length)return void(this.solved=!0);this.lastNode=this.currentNode,this.currentNode=this.unsolvedNodes.pop(),this.currentNodeStep=0,this.routesInProgress=[],this._initializeRoutesForCurrentNode()}this.currentNodeStep>0&&this._runForceDirectedStep(),this.currentNodeStep++,this.currentNodeStep>=10&&(this._finalizeRoutesForCurrentNode(),this.lastNode=this.currentNode,this.currentNode=null)}_initializeRoutesForCurrentNode(){const t=this.currentNode,e=t.center.x-t.width/2,n=t.center.x+t.width/2,s=t.center.y-t.height/2,o=t.center.y+t.height/2;this.currentNodeBounds={minX:e,maxX:n,minY:s,maxY:o};const i=new Map;for(const e of t.portPoints)i.has(e.connectionName)||i.set(e.connectionName,[]),i.get(e.connectionName).push({x:e.x,y:e.y,z:e.z,rootConnectionName:e.rootConnectionName});for(const[t,e]of i){if(e.length<2)continue;const n=e[0],s=e[e.length-1],o=n.z,i=s.x-n.x,r=s.y-n.y,a=Math.sqrt(i*i+r*r),c=a>0?i/a:0,h=a>0?r/a:0,d=[];this.numMovablePoints>=1&&d.push({x:n.x+c*Fi,y:n.y+h*Fi,z:o,rootConnectionName:n.rootConnectionName,connectionName:t}),this.numMovablePoints>=2&&d.push({x:s.x-c*Fi,y:s.y-h*Fi,z:o,rootConnectionName:n.rootConnectionName,connectionName:t}),this.numMovablePoints>=3&&d.push({x:n.x+i/2,y:n.y+r/2,z:o,rootConnectionName:n.rootConnectionName,connectionName:t}),this.routesInProgress.push({connectionName:t,rootConnectionName:n.rootConnectionName,startPoint:{x:n.x,y:n.y,z:o},endPoint:{x:s.x,y:s.y,z:o},movablePoints:d})}}_runForceDirectedStep(){const t=this.currentNodeBounds,e=[];for(const t of this.routesInProgress)e.push(...t.movablePoints);const n=new Map;for(const t of e)n.set(t,{fx:0,fy:0});const s=.3+this.pushMargin,o=new Map;for(const t of this.routesInProgress){const e=[{x:t.startPoint.x,y:t.startPoint.y,movablePoint:null}];1===t.movablePoints.length?e.push({x:t.movablePoints[0].x,y:t.movablePoints[0].y,movablePoint:t.movablePoints[0]}):2===t.movablePoints.length?(e.push({x:t.movablePoints[0].x,y:t.movablePoints[0].y,movablePoint:t.movablePoints[0]}),e.push({x:t.movablePoints[1].x,y:t.movablePoints[1].y,movablePoint:t.movablePoints[1]})):3===t.movablePoints.length&&(e.push({x:t.movablePoints[0].x,y:t.movablePoints[0].y,movablePoint:t.movablePoints[0]}),e.push({x:t.movablePoints[2].x,y:t.movablePoints[2].y,movablePoint:t.movablePoints[2]}),e.push({x:t.movablePoints[1].x,y:t.movablePoints[1].y,movablePoint:t.movablePoints[1]})),e.push({x:t.endPoint.x,y:t.endPoint.y,movablePoint:null}),o.set(t,e)}for(const i of e){const e=n.get(i),r=i.x-t.minX,a=t.maxX-i.x,c=t.maxY-i.y,h=i.y-t.minY;r<s&&(e.fx+=Li*(s-r)),a<s&&(e.fx-=Li*(s-a)),h<s&&(e.fy+=Li*(s-h)),c<s&&(e.fy-=Li*(s-c));for(const t of this.routesInProgress){if(t.rootConnectionName===i.rootConnectionName)continue;const r=o.get(t);for(let t=0;t<r.length-1;t++){const o=r[t],a=r[t+1],c=ki(i.x,i.y,o.x,o.y,a.x,a.y),h=Math.sqrt(c.distSq);if(h>0&&h<2*s){const t=i.x-c.x,s=i.y-c.y,r=.002/c.distSq,h=r*t,d=r*s;e.fx+=h,e.fy+=d;const l=o.movablePoint,u=a.movablePoint;if(l&&u){const t=n.get(l),e=n.get(u);t.fx-=h/2,t.fy-=d/2,e.fx-=h/2,e.fy-=d/2}else if(l){const t=n.get(l);t.fx-=h,t.fy-=d}else if(u){const t=n.get(u);t.fx-=h,t.fy-=d}}}}}const i=t=>t.movablePoint?{x:t.movablePoint.x,y:t.movablePoint.y}:{x:t.x,y:t.y},r=t=>{let e=null;for(const n of this.routesInProgress)if(n.movablePoints.includes(t)){e=n;break}if(!e)return!1;const n=o.get(e);let s=-1;for(let e=0;e<n.length;e++)if(n[e].movablePoint===t){s=e;break}if(-1===s)return!1;const r=[];if(s>0){const e=i(n[s-1]);r.push({ax:e.x,ay:e.y,bx:t.x,by:t.y})}if(s<n.length-1){const e=i(n[s+1]);r.push({ax:t.x,ay:t.y,bx:e.x,by:e.y})}for(const t of this.routesInProgress){if(t.rootConnectionName===e.rootConnectionName)continue;const n=o.get(t);for(let t=0;t<n.length-1;t++){const e=i(n[t]),s=i(n[t+1]);for(const t of r)if($i(t.ax,t.ay,t.bx,t.by,e.x,e.y,s.x,s.y))return!0}}return!1};for(const s of e){const e=n.get(s);s.forceX=e.fx,s.forceY=e.fy;const o=s.x,i=s.y;s.x+=e.fx,s.y+=e.fy,s.x=Math.max(t.minX,Math.min(t.maxX,s.x)),s.y=Math.max(t.minY,Math.min(t.maxY,s.y)),r(s)&&(s.x=o,s.y=i)}}_finalizeRoutesForCurrentNode(){for(const t of this.routesInProgress){const{connectionName:e,rootConnectionName:n,startPoint:s,endPoint:o,movablePoints:i}=t,r=[{x:s.x,y:s.y,z:s.z}];1===i.length?r.push({x:i[0].x,y:i[0].y,z:i[0].z}):2===i.length?(r.push({x:i[0].x,y:i[0].y,z:i[0].z}),r.push({x:i[1].x,y:i[1].y,z:i[1].z})):3===i.length&&(r.push({x:i[0].x,y:i[0].y,z:i[0].z}),r.push({x:i[2].x,y:i[2].y,z:i[2].z}),r.push({x:i[1].x,y:i[1].y,z:i[1].z})),r.push({x:o.x,y:o.y,z:o.z});const a={connectionName:e,rootConnectionName:n,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:r,vias:[]};this.routes.push(a)}this.routesInProgress=[]}_getNodeBounds(t){return{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}}visualize(){const t={lines:[],points:[],rects:[],circles:[]};for(const e of this.unsolvedNodes){if(e===this.currentNode)continue;const n=this._getNodeBounds(e);t.rects.push({center:{x:(n.minX+n.maxX)/2,y:(n.minY+n.maxY)/2},width:n.maxX-n.minX,height:n.maxY-n.minY,fill:"rgba(0, 0, 0, 0.08)",stroke:"rgba(0, 0, 0, 0.2)",label:e.capacityMeshNodeId})}if(this.lastNode){const e=this._getNodeBounds(this.lastNode);t.rects.push({center:{x:(e.minX+e.maxX)/2,y:(e.minY+e.maxY)/2},width:e.maxX-e.minX,height:e.maxY-e.minY,fill:"rgba(0, 200, 0, 0.15)",stroke:"rgba(0, 0, 255, 0.6)"})}if(this.currentNode){const e=this._getNodeBounds(this.currentNode);t.rects.push({center:{x:(e.minX+e.maxX)/2,y:(e.minY+e.maxY)/2},width:e.maxX-e.minX,height:e.maxY-e.minY,fill:"rgba(0, 200, 0, 0.15)",stroke:"rgba(0, 200, 0, 0.6)"})}for(const e of this.unsolvedNodes){const n=new Map;for(const t of e.portPoints)n.has(t.connectionName)||n.set(t.connectionName,[]),n.get(t.connectionName).push({x:t.x,y:t.y});for(const[e,s]of n)s.length<2||t.lines.push({points:s.map(t=>({x:t.x,y:t.y})),label:e,strokeColor:"gray",strokeWidth:this.traceWidth})}for(const e of this.routes){const n=De(e.route,e.connectionName,this.colorMap[e.connectionName]);for(const s of n)t.lines.push({points:s.points,label:s.connectionName,strokeColor:0===s.z?s.color:it(s.color,.75),layer:`z${s.z}`,strokeWidth:e.traceThickness,strokeDash:0!==s.z?"10, 5":void 0});const s=e.route;for(let e=0;e<s.length;e++){const n=s[e],o=0===e,i=e===s.length-1,r=!o&&!i;let a;a=o?"start":i?"end":`M${e}`,t.points.push({x:n.x,y:n.y,label:a,color:r?"orange":"blue"})}}for(const e of this.routesInProgress){const{startPoint:n,endPoint:s,movablePoints:o,connectionName:i}=e,r=this.colorMap[i]??"gray",a=[{x:n.x,y:n.y}];1===o.length?a.push({x:o[0].x,y:o[0].y}):2===o.length?(a.push({x:o[0].x,y:o[0].y}),a.push({x:o[1].x,y:o[1].y})):3===o.length&&(a.push({x:o[0].x,y:o[0].y}),a.push({x:o[2].x,y:o[2].y}),a.push({x:o[1].x,y:o[1].y})),a.push({x:s.x,y:s.y}),t.lines.push({points:a,label:i,strokeColor:r,strokeWidth:this.traceWidth}),t.points.push({x:n.x,y:n.y,label:"start",color:"blue"});for(let e=0;e<o.length;e++){const n=o[e];if(t.points.push({x:n.x,y:n.y,label:`M${e+1}`,color:"orange"}),void 0!==n.forceX&&void 0!==n.forceY){if(Math.sqrt(n.forceX*n.forceX+n.forceY*n.forceY)>.001){const s=5;t.lines.push({points:[{x:n.x,y:n.y},{x:n.x+n.forceX*s,y:n.y+n.forceY*s}],strokeColor:"red",strokeWidth:.02,label:`F${e+1}`});const o=.05,i=n.x+n.forceX*s,r=n.y+n.forceY*s,a=Math.atan2(n.forceY,n.forceX);t.lines.push({points:[{x:i,y:r},{x:i-o*Math.cos(a-Math.PI/6),y:r-o*Math.sin(a-Math.PI/6)}],strokeColor:"red",strokeWidth:.02}),t.lines.push({points:[{x:i,y:r},{x:i-o*Math.cos(a+Math.PI/6),y:r-o*Math.sin(a+Math.PI/6)}],strokeColor:"purple",strokeWidth:.02})}}}t.points.push({x:s.x,y:s.y,label:"end",color:"blue"})}return t}};function ji(t){const{pos:e,segments:n,dir:s,keepoutRadius:o}=t;let i=1/0;const r=o/4,a={x:e.x-s.x*r,y:e.y-s.y*r},c={x:e.x+s.x*r,y:e.y+s.y*r};for(const t of n){const e=wt(a,c,t.start,t.end);i=Math.min(i,e)}return i}function Wi(t,e,n,s){const o=Hi(n,s,t),i=Hi(n,s,e),r=Hi(t,e,n),a=Hi(t,e,s);if((o>0&&i<0||o<0&&i>0)&&(r>0&&a<0||r<0&&a>0))return!0;const c=1e-4;return!!(Math.abs(o)<c&&Ui(n,s,t))||(!!(Math.abs(i)<c&&Ui(n,s,e))||(!!(Math.abs(r)<c&&Ui(t,e,n))||!!(Math.abs(a)<c&&Ui(t,e,s))))}function Hi(t,e,n){return(n.x-t.x)*(e.y-t.y)-(e.x-t.x)*(n.y-t.y)}function Ui(t,e,n){return n.x>=Math.min(t.x,e.x)-1e-4&&n.x<=Math.max(t.x,e.x)+1e-4&&n.y>=Math.min(t.y,e.y)-1e-4&&n.y<=Math.max(t.y,e.y)+1e-4}function Vi(t,e,n){for(const s of n)if(Wi(t,e,s.start,s.end))return!1;return!0}var Zi=1e-4;function Gi(t){const e=t.width/2,n=t.height/2,s=t.center.x,o=t.center.y,i={x:s-e,y:o+n},r={x:s+e,y:o+n},a={x:s-e,y:o-n},c={x:s+e,y:o-n};return[{start:i,end:r},{start:r,end:c},{start:c,end:a},{start:a,end:i}]}function Ji(t,e,n=.1){const s=e.x-t.x,o=e.y-t.y,i=Math.sqrt(s*s+o*o);if(0===i)return[];const r=-(o/i),a=s/i,c=n/2;return[{start:{x:t.x+r*c,y:t.y+a*c},end:{x:e.x+r*c,y:e.y+a*c}},{start:{x:t.x-r*c,y:t.y-a*c},end:{x:e.x-r*c,y:e.y-a*c}}]}function qi(t,e,n){const s=Math.hypot(t.start.x-e.x,t.start.y-e.y),o=Math.hypot(t.end.x-e.x,t.end.y-e.y);if(s<=n||o<=n)return!0;const i=t.end.x-t.start.x,r=t.end.y-t.start.y,a=i*i+r*r;if(0===a)return!1;const c=Math.max(0,Math.min(1,((e.x-t.start.x)*i+(e.y-t.start.y)*r)/a)),h=t.start.x+c*i,d=t.start.y+c*r;return Math.hypot(h-e.x,d-e.y)<=n}function Ki(t,e,n){if(!n||0===n.length)return!1;for(const s of n){const n=Math.abs(t.x-s.start.x)<Zi&&Math.abs(t.y-s.start.y)<Zi&&Math.abs(e.x-s.end.x)<Zi&&Math.abs(e.y-s.end.y)<Zi,o=Math.abs(t.x-s.end.x)<Zi&&Math.abs(t.y-s.end.y)<Zi&&Math.abs(e.x-s.start.x)<Zi&&Math.abs(e.y-s.start.y)<Zi;if(n||o)return!0}return!1}function Qi(t,e,n,s,o){const i=[];for(let r=0;r<t.length-1;r++){const a=t[r],c=t[r+1];Ki(a,c,o)||qi({start:a,end:c},n,s+e)&&i.push(...Ji(a,c,e))}return i}var tr=1e-4;function er(t,e,n,s){const o=e.x-t.x,i=e.y-t.y,r=s.x-n.x,a=s.y-n.y,c=o*a-i*r;if(Math.abs(c)<1e-10)return null;const h=n.x-t.x,d=n.y-t.y,l=(h*a-d*r)/c,u=(h*i-d*o)/c,p=1e-6;return l>p&&l<.999999&&u>p&&u<.999999?{x:t.x+l*o,y:t.y+l*i}:null}function nr(t,e){if(!e||0===e.length)return!1;for(const n of e)if(Math.abs(t.x-n.start.x)<tr&&Math.abs(t.y-n.start.y)<tr||Math.abs(t.x-n.end.x)<tr&&Math.abs(t.y-n.end.y)<tr)return!0;return!1}function sr(t,e,n,s){if(!s||0===s.length)return!1;for(let o=e;o<=n;o++)if(o>=0&&o<t.length&&nr(t[o],s))return!0;return!1}var or=1e-4,ir=class extends y{constructor(t){super(),this.input=t,this.MAX_ITERATIONS=1e6,this.originalHdRoutes=[...t.hdRoutes],this.hdRoutes=t.hdRoutes,this.KEEPOUT_RADIUS_SCHEDULE=t.keepoutRadiusSchedule??[.3,.5,.5],this.currentKeepoutRadius=this.KEEPOUT_RADIUS_SCHEDULE[0]??.15,this.unprocessedRoutes=[...this.hdRoutes],this.smoothedCursorRoutes=[...this.unprocessedRoutes];const e=[...t.obstacles,...this.getJumperPadObstacles()];this.obstacleSHI=new Qs("flatbush",e),this.boardOutlineRoutes=this.createBoardOutlineRoutes(),this.hdRouteSHI=new io([...this.hdRoutes,...this.boardOutlineRoutes]);for(const[t,e,n]of this.hdRoutes.flatMap(t=>[[t.route[0],t.connectionName,t.rootConnectionName],[t.route[t.route.length-1],t.connectionName,t.rootConnectionName]])){const s=this.obstacleSHI.searchArea(t.x,t.y,.01,.01).filter(e=>e.zLayers?.includes(t.z));if(0===s.length)continue;const o=s[0];this.input.connMap.addConnections([[e,n,...o.offBoardConnectsTo??[],o.obstacleId,...o.connectedTo].filter(Boolean)])}}originalHdRoutes;hdRoutes;redrawnHdRoutes=[];KEEPOUT_RADIUS_SCHEDULE;currentScheduleIndex=0;currentKeepoutRadius;unprocessedRoutes=[];smoothedCursorRoutes=[];processedRoutes=[];currentTrace=null;cursorPosition=null;lastCursorPosition=null;drawPosition=null;currentTraceSegmentIndex=0;currentTraceSegmentT=0;recordedDrawPositions=[];lastCollidingSegments=[];currentTraceJumperSegments=new Map;obstacleSHI;hdRouteSHI;boardOutlineRoutes=[];getSmoothDistance(){return this.currentKeepoutRadius}getJumperPadObstacles(){const t=[];if(!this.input.jumpers)return t;for(const e of this.input.jumpers)for(const n of e.pads)t.push({...n,zLayers:[0]});return t}buildJumperSegmentMap(t){const e=new Map;if(!t.jumpers||0===t.jumpers.length)return e;const n=t.route;for(const s of t.jumpers){let t=-1,o=1/0;for(let e=0;e<n.length-1;e++){const i=n[e],r=n[e+1],a=Math.sqrt((i.x-s.start.x)**2+(i.y-s.start.y)**2),c=Math.sqrt((r.x-s.end.x)**2+(r.y-s.end.y)**2),h=a+c,d=Math.sqrt((i.x-s.end.x)**2+(i.y-s.end.y)**2),l=Math.sqrt((r.x-s.start.x)**2+(r.y-s.start.y)**2),u=d+l,p=Math.min(h,u);(h<=u?a:d)<1&&(h<=u?c:l)<1&&p<o&&(o=p,t=e)}t>=0&&e.set(t,s)}return e}_step(){if(!this.currentTrace){const t=this.unprocessedRoutes.shift();if(!t)return this.currentScheduleIndex++,this.currentScheduleIndex<this.KEEPOUT_RADIUS_SCHEDULE.length?(this.currentKeepoutRadius=this.KEEPOUT_RADIUS_SCHEDULE[this.currentScheduleIndex],this.unprocessedRoutes=kt([...this.processedRoutes],this.currentScheduleIndex),this.smoothedCursorRoutes=[...this.unprocessedRoutes],this.processedRoutes=[],void(this.hdRouteSHI=new io([...this.unprocessedRoutes,...this.boardOutlineRoutes]))):(this.redrawnHdRoutes=this.processedRoutes,void(this.solved=!0));if(this.currentTrace=t,this.currentTrace.route.length<2)return this.processedRoutes.push(this.currentTrace),void(this.currentTrace=null);this.currentTraceJumperSegments=this.buildJumperSegmentMap(this.currentTrace);const e=this.currentTrace.route[0];return this.cursorPosition={...e},this.lastCursorPosition={...e},this.drawPosition={x:e.x,y:e.y},this.currentTraceSegmentIndex=0,this.currentTraceSegmentT=0,void(this.recordedDrawPositions=[{...e}])}this.lastCursorPosition={...this.cursorPosition};const t=this.stepCursorForward();if("end"===t)return void this.finalizeCurrentTrace();if("jumper"===t)return void(this.drawPosition={x:this.cursorPosition.x,y:this.cursorPosition.y});const e=this.getCollidingSegments(this.cursorPosition);this.lastCollidingSegments=e;const n=function(t){const{cursorPosition:e,lastCursorPosition:n,collidingSegments:s,keepoutRadius:o}=t;if(0===s.length)return null;const i=1e-4,r=e.x-n.x,a=e.y-n.y,c=Math.sqrt(r*r+a*a),h=c>i?{x:r/c,y:a/c}:{x:1,y:0},d=-h.y,l=h.x,u=ji({pos:e,segments:s,dir:h,keepoutRadius:o});if(u>=o)return null;for(let t=1;t<=20;t++){const n=t/20*o,i={x:e.x+d*n,y:e.y+l*n},r=ji({pos:i,segments:s,dir:h,keepoutRadius:o}),a={x:e.x-d*n,y:e.y-l*n},c=ji({pos:a,segments:s,dir:h,keepoutRadius:o}),u=r>=o&&Vi(e,i,s),p=c>=o&&Vi(e,a,s);if(u&&p)return r>=c?i:a;if(u)return i;if(p)return a}const p=o,m=[];for(let t=-60;t<=60;t++){const n=t/60*p,i={x:e.x+d*n,y:e.y+l*n},r=ji({pos:i,segments:s,dir:h,keepoutRadius:o}),a=Vi(e,i,s);m.push({pos:i,clearance:r,dist:Math.abs(n),pathClear:a,index:t})}const f=m.filter(t=>t.pathClear),g=m.findIndex(t=>0===t.index),y=g>=0?g:Math.floor(m.length/2);let x=null;for(let t=y+1;t<m.length-1;t++){const e=m[t-1],n=m[t],s=m[t+1];if(n.clearance>=e.clearance&&n.clearance>=s.clearance){x=n;break}}let v=null;for(let t=y-1;t>0;t--){const e=m[t-1],n=m[t],s=m[t+1];if(n.clearance>=e.clearance&&n.clearance>=s.clearance){v=n;break}}let S=null,P=null;if(f.length>0){const t=f.findIndex(t=>0===t.index),e=t>=0?t:Math.floor(f.length/2);for(let t=e+1;t<f.length-1;t++){const e=f[t-1],n=f[t],s=f[t+1];if(n.clearance>=e.clearance&&n.clearance>=s.clearance){S=n;break}}for(let t=e-1;t>0;t--){const e=f[t-1],n=f[t],s=f[t+1];if(n.clearance>=e.clearance&&n.clearance>=s.clearance){P=n;break}}}const b=[x,v,S,P,m.find(t=>0===t.index)].filter(t=>null!=t),M=new Set,N=b.filter(t=>{const e=`${t.pos.x.toFixed(6)},${t.pos.y.toFixed(6)}`;return!M.has(e)&&(M.add(e),!0)});if(0===N.length){let t=m[0];if(!t)return null;for(const e of m)e.clearance>t.clearance&&(t=e);return Math.sqrt((t.pos.x-e.x)**2+(t.pos.y-e.y)**2)>i?t.pos:null}let I;if(u<.15*o){I=N[0];for(const t of N)t.clearance>I.clearance&&(I=t)}else{const t=N.filter(t=>t.pathClear),e=t.length>0?t:N;I=e[0];for(const t of e)t.clearance>I.clearance&&(I=t)}return Math.sqrt((I.pos.x-e.x)**2+(I.pos.y-e.y)**2)>i?I.pos:null}({cursorPosition:this.cursorPosition,lastCursorPosition:this.lastCursorPosition,collidingSegments:e,keepoutRadius:this.currentKeepoutRadius});this.drawPosition=n??{...this.cursorPosition};const s=this.recordedDrawPositions[this.recordedDrawPositions.length-1];if(s&&this.drawPosition){const t={x:s.x,y:s.y,z:s.z},e={x:this.drawPosition.x,y:this.drawPosition.y,z:this.cursorPosition.z};this.segmentIntersectsOtherRoutes(t,e)&&(this.drawPosition={...this.cursorPosition})}this.recordedDrawPositions.push({x:this.drawPosition.x,y:this.drawPosition.y,z:this.cursorPosition.z})}getStepDistance(){return this.currentKeepoutRadius/2}getJumperAtCurrentSegmentStart(){return this.currentTraceSegmentT>or?null:this.currentTraceJumperSegments.get(this.currentTraceSegmentIndex)??null}stepCursorForward(){if(!this.currentTrace||!this.cursorPosition)return"end";const t=this.currentTrace.route;let e=this.getStepDistance();for(;e>0;){if(this.currentTraceSegmentIndex>=t.length-1)return"end";const n=this.getJumperAtCurrentSegmentStart();if(n){const e=t[this.currentTraceSegmentIndex],s=t[this.currentTraceSegmentIndex+1],o=Math.sqrt((e.x-n.start.x)**2+(e.y-n.start.y)**2),i=Math.sqrt((e.x-n.end.x)**2+(e.y-n.end.y)**2),r=o<=i?n.start:n.end,a=o<=i?n.end:n.start;return this.recordedDrawPositions.push({x:r.x,y:r.y,z:e.z,insideJumperPad:!0}),this.recordedDrawPositions.push({x:a.x,y:a.y,z:s.z,insideJumperPad:!0}),this.cursorPosition={x:a.x,y:a.y,z:s.z},this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0,"jumper"}const s=t[this.currentTraceSegmentIndex],o=t[this.currentTraceSegmentIndex+1],i=o.x-s.x,r=o.y-s.y,a=Math.sqrt(i*i+r*r);if(0===a){this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0;continue}const c=this.currentTraceSegmentT*a,h=a-c;if(e<=h){const t=c+e;return this.currentTraceSegmentT=t/a,this.cursorPosition={x:s.x+i*this.currentTraceSegmentT,y:s.y+r*this.currentTraceSegmentT,z:s.z},"stepped"}if(e-=h,this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0,this.currentTraceSegmentIndex>=t.length-1){const e=t[t.length-1];return this.cursorPosition={...e},"end"}}return"stepped"}getCollidingSegments(t){if(!this.currentTrace)return[];const e=this.currentTrace.rootConnectionName??this.currentTrace.connectionName,n=2*this.currentKeepoutRadius,s=[],o=this.obstacleSHI.searchArea(t.x,t.y,n,n);for(const n of o){if(n.zLayers&&!n.zLayers.includes(t.z))continue;if(n.connectedTo.includes(e))continue;if(n.obstacleId&&this.input.connMap.areIdsConnected(e,n.obstacleId))continue;let o=!1;for(const t of n.connectedTo)if(this.input.connMap.areIdsConnected(e,t)){o=!0;break}o||s.push(...Gi(n))}const i=this.hdRouteSHI.getConflictingRoutesNearPoint({x:t.x,y:t.y},n);for(const{conflictingRoute:o}of i){const i=o.rootConnectionName??o.connectionName;if(i===e)continue;if(this.input.connMap.areIdsConnected(e,i))continue;const r=o.traceThickness??.15;s.push(...Qi(o.route,r,{x:t.x,y:t.y},n,o.jumpers))}return s}positionHasCollision(t,e=0){const n=this.getCollidingSegments(t);for(const s of n)if(vt(t,s.start,s.end)<=this.currentKeepoutRadius+e)return!0;return!1}segmentIntersectsOtherRoutes(t,e){if(!this.currentTrace)return!1;const n=this.currentTrace.rootConnectionName??this.currentTrace.connectionName,s=[...this.unprocessedRoutes,...this.smoothedCursorRoutes,...this.processedRoutes];for(const o of s){if((o.rootConnectionName??o.connectionName)!==n)for(let n=0;n<o.route.length-1;n++){const s=o.route[n],i=o.route[n+1];if((s.z===t.z||i.z===t.z)&&((!s.insideJumperPad||!i.insideJumperPad)&>({x:t.x,y:t.y},{x:e.x,y:e.y},{x:s.x,y:s.y},{x:i.x,y:i.y})))return!0}}return!1}finalizeCurrentTrace(){if(!this.currentTrace)return;const t=this.currentTrace.route[this.currentTrace.route.length-1],e=this.recordedDrawPositions[this.recordedDrawPositions.length-1];e&&e.x===t.x&&e.y===t.y||this.recordedDrawPositions.push({...t});const n=function(t,e){if(t.length<4)return t;let n=[...t],s=!0;for(;s;){s=!1;for(let t=0;t<n.length-1&&!s;t++){const o=n[t],i=n[t+1];if(o.z===i.z)for(let r=t+2;r<n.length-1&&!s;r++){if(r===t+1)continue;const a=n[r],c=n[r+1];if(a.z!==c.z||o.z!==a.z)continue;const h=er(o,i,a,c);if(h){if(sr(n,t+1,r,e))continue;const i=[];for(let e=0;e<=t;e++)i.push(n[e]);i.push({x:h.x,y:h.y,z:o.z});for(let t=r+1;t<n.length;t++)i.push(n[t]);n=i,s=!0}}}}return n}(this.simplifyRoute(this.recordedDrawPositions,this.currentTrace.jumpers),this.currentTrace.jumpers),s={connectionName:this.currentTrace.connectionName,rootConnectionName:this.currentTrace.rootConnectionName,traceThickness:this.currentTrace.traceThickness,viaDiameter:this.currentTrace.viaDiameter,route:n,vias:[...this.currentTrace.vias],jumpers:this.currentTrace.jumpers};this.processedRoutes.push(s),this.hdRouteSHI.removeRoute(this.currentTrace.connectionName),this.hdRouteSHI.addRoute(s),this.currentTrace=null,this.cursorPosition=null,this.lastCursorPosition=null,this.drawPosition=null,this.recordedDrawPositions=[]}isJumperEndpoint(t,e){if(!e||0===e.length)return!1;for(const n of e)if(Math.abs(t.x-n.start.x)<or&&Math.abs(t.y-n.start.y)<or||Math.abs(t.x-n.end.x)<or&&Math.abs(t.y-n.end.y)<or)return!0;return!1}simplifyRoute(t,e){if(t.length<=2)return t;const n=[t[0]];for(let s=1;s<t.length-1;s++){const o=n[n.length-1],i=t[s],r=t[s+1];if(this.isJumperEndpoint(i,e)){n.push(i);continue}if(i.z!==o.z||i.z!==r.z){n.push(i);continue}const a=i.x-o.x,c=i.y-o.y,h=r.x-i.x,d=a*(r.y-i.y)-c*h,l=1e-6;Math.abs(d)>l&&n.push(i)}return n.push(t[t.length-1]),n}createBoardOutlineRoutes(){const t=[];if(!this.input.srj)return t;const{outline:e,bounds:n}=this.input.srj;let s;s=e&&e.length>=3?e:[{x:n.minX,y:n.minY},{x:n.maxX,y:n.minY},{x:n.maxX,y:n.maxY},{x:n.minX,y:n.maxY}];const o=this.input.srj.layerCount??2;for(let e=0;e<s.length;e++){const n=s[e],i=s[(e+1)%s.length];for(let s=0;s<o;s++)t.push({connectionName:`__board_outline___${e}_z${s}`,traceThickness:.01,viaDiameter:0,route:[{x:n.x,y:n.y,z:s},{x:i.x,y:i.y,z:s}],vias:[]})}return t}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:`Trace Keepout Solver (radius: ${this.currentKeepoutRadius.toFixed(2)})`};for(const e of this.originalHdRoutes)if(0!==e.route.length)for(let n=0;n<e.route.length-1;n++){const s=e.route[n],o=e.route[n+1];s.z===o.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:o.x,y:o.y}],strokeColor:"rgba(0,0,0,0.25)",strokeWidth:1.5*(e.traceThickness??.15)})}if(this.input.jumpers)for(const e of this.input.jumpers){for(const n of e.pads){const e=n.connectedTo.length>0?n.connectedTo.join(", "):"unused",s=n.connectedTo.length>0?this.input.colorMap[n.connectedTo[0]]||"#888888":"rgba(128, 128, 128, 0.5)";t.rects.push({center:n.center,width:n.width,height:n.height,fill:s,stroke:"rgba(0, 0, 0, 0.5)",label:`Jumper pad (${e})`})}e.pads.length>=2&&t.lines.push({points:[e.pads[0].center,e.pads[1].center],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.2,label:"Jumper body"})}for(const e of this.input.obstacles){let n="rgba(128, 128, 128, 0.2)";const s=e.zLayers?.includes(0),o=e.zLayers?.includes(1);s&&o?n="rgba(128, 0, 128, 0.2)":s?n="rgba(255, 0, 0, 0.2)":o&&(n="rgba(0, 0, 255, 0.2)"),t.rects.push({center:e.center,width:e.width,height:e.height,fill:n,label:`Obstacle (Z: ${e.zLayers?.join(", ")})`})}if(this.input.srj){const{outline:e,bounds:n}=this.input.srj;let s;s=e&&e.length>=3?e:[{x:n.minX,y:n.minY},{x:n.maxX,y:n.minY},{x:n.maxX,y:n.maxY},{x:n.minX,y:n.maxY}];for(let e=0;e<s.length;e++){const n=s[e],o=s[(e+1)%s.length];t.lines.push({points:[{x:n.x,y:n.y},{x:o.x,y:o.y}],strokeColor:"rgba(0, 128, 0, 0.6)",strokeWidth:.1,label:"Board outline"})}}for(const e of this.processedRoutes){if(0===e.route.length)continue;const n=this.input.colorMap[e.connectionName]||"#888888",s=new Set;if(e.jumpers&&e.jumpers.length>0)for(const t of e.jumpers)for(let n=0;n<e.route.length-1;n++){const o=e.route[n],i=e.route[n+1],r=Math.abs(o.x-t.start.x)<or&&Math.abs(o.y-t.start.y)<or&&Math.abs(i.x-t.end.x)<or&&Math.abs(i.y-t.end.y)<or,a=Math.abs(o.x-t.end.x)<or&&Math.abs(o.y-t.end.y)<or&&Math.abs(i.x-t.start.x)<or&&Math.abs(i.y-t.start.y)<or;if(r||a){s.add(n);break}}for(let n=0;n<e.route.length-1;n++){const o=e.route[n],i=e.route[n+1];s.has(n)?t.lines.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:"rgba(128, 128, 128, 0.6)",strokeDash:"2 2",label:`${e.connectionName} (jumper segment - fixed)`}):o.z===i.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:0===o.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${o.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const s=Je(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...s.rects??[]),t.lines.push(...s.lines??[])}}if(this.currentTrace&&this.recordedDrawPositions.length>0){this.input.colorMap[this.currentTrace.connectionName];for(let e=0;e<this.recordedDrawPositions.length-1;e++){const n=this.recordedDrawPositions[e],s=this.recordedDrawPositions[e+1];t.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.y}],strokeColor:"green",strokeWidth:this.currentTrace.traceThickness})}if(this.cursorPosition&&(t.circles.push({center:{x:this.cursorPosition.x,y:this.cursorPosition.y},radius:this.currentKeepoutRadius,stroke:"orange",fill:"none"}),t.points.push({x:this.cursorPosition.x,y:this.cursorPosition.y,color:"orange",label:"Cursor"}),this.lastCursorPosition)){const e=this.cursorPosition.x-this.lastCursorPosition.x,n=this.cursorPosition.y-this.lastCursorPosition.y,s=Math.sqrt(e*e+n*n),o=s>1e-4?{x:e/s,y:n/s}:{x:1,y:0},i=this.currentKeepoutRadius/4,r={x:this.cursorPosition.x-o.x*i,y:this.cursorPosition.y-o.y*i},a={x:this.cursorPosition.x+o.x*i,y:this.cursorPosition.y+o.y*i};t.lines.push({points:[r,a],strokeColor:"cyan",strokeWidth:.05,label:"Projected segment"})}this.drawPosition&&t.points.push({x:this.drawPosition.x,y:this.drawPosition.y,color:"lime",label:"Draw"});for(const e of this.lastCollidingSegments)t.lines.push({points:[{x:e.start.x,y:e.start.y},{x:e.end.x,y:e.end.y}],strokeColor:"rgba(255, 0, 255, 0.8)",strokeWidth:.02,label:"Colliding segment"})}if(!this.solved)for(const e of this.smoothedCursorRoutes)if(0!==e.route.length)for(let n=0;n<e.route.length-1;n++){const s=e.route[n],o=e.route[n+1];s.z===o.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:o.x,y:o.y}],strokeColor:"gray"})}return t}getRedrawnHdRoutes(){return this.redrawnHdRoutes}},rr=class extends y{hdRoutes;hdRoutesWithWidths=[];nominalTraceWidth;minTraceWidth;obstacleMargin;TRACE_WIDTH_SCHEDULE;unprocessedRoutes=[];processedRoutes=[];currentTrace=null;cursorPosition=null;currentTraceSegmentIndex=0;currentTraceSegmentT=0;currentScheduleIndex=0;currentTargetWidth=0;hasInsufficientClearance=!1;lastCollidingObstacles=[];lastCollidingRoutes=[];lastClearance=1/0;obstacles=[];obstacleSHI;hdRouteSHI;connMap;colorMap;constructor(t){super(),this.MAX_ITERATIONS=1e6,this.hdRoutes=[...t.hdRoutes],this.minTraceWidth=t.minTraceWidth,this.nominalTraceWidth=t.nominalTraceWidth??2*t.minTraceWidth,this.obstacleMargin=t.obstacleMargin??.15;const e=(this.nominalTraceWidth+this.minTraceWidth)/2;this.TRACE_WIDTH_SCHEDULE=[this.nominalTraceWidth,e],this.unprocessedRoutes=[...this.hdRoutes],this.connMap=t.connMap,this.colorMap=t.colorMap,this.obstacles=t.obstacles??[],this.obstacles.length>0&&(this.obstacleSHI=new Qs("flatbush",this.obstacles)),this.hdRouteSHI=new io(this.hdRoutes)}_step(){if(!this.currentTrace){const t=this.unprocessedRoutes.shift();return t?(this.currentTrace=t,this.currentTrace.route.length<2?(this.processedRoutes.push({...this.currentTrace,traceThickness:this.minTraceWidth}),void(this.currentTrace=null)):(this.currentScheduleIndex=0,this.currentTargetWidth=this.TRACE_WIDTH_SCHEDULE[0],void this.initializeCursor())):(this.hdRoutesWithWidths=this.processedRoutes,void(this.solved=!0))}if(!this.stepCursorForward())return void this.finalizeCurrentTrace(this.currentTargetWidth);this.getClearanceAtPosition(this.cursorPosition)<this.currentTargetWidth/2+this.obstacleMargin&&(this.hasInsufficientClearance=!0,this.currentScheduleIndex++,this.currentScheduleIndex<this.TRACE_WIDTH_SCHEDULE.length?(this.currentTargetWidth=this.TRACE_WIDTH_SCHEDULE[this.currentScheduleIndex],this.initializeCursor()):this.finalizeCurrentTrace(this.minTraceWidth))}initializeCursor(){if(!this.currentTrace)return;const t=this.currentTrace.route[0];this.cursorPosition={...t},this.currentTraceSegmentIndex=0,this.currentTraceSegmentT=0,this.hasInsufficientClearance=!1}stepCursorForward(){if(!this.currentTrace||!this.cursorPosition)return!1;const t=this.currentTrace.route;let e=.1;for(;e>0;){if(this.currentTraceSegmentIndex>=t.length-1)return!1;const n=t[this.currentTraceSegmentIndex],s=t[this.currentTraceSegmentIndex+1];if(n.insideJumperPad&&s.insideJumperPad){this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0;continue}const o=s.x-n.x,i=s.y-n.y,r=Math.sqrt(o*o+i*i);if(0===r){this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0;continue}const a=this.currentTraceSegmentT*r,c=r-a;if(e<=c){const t=a+e;return this.currentTraceSegmentT=t/r,this.cursorPosition={x:n.x+o*this.currentTraceSegmentT,y:n.y+i*this.currentTraceSegmentT,z:n.z},!0}if(e-=c,this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0,this.currentTraceSegmentIndex>=t.length-1){const e=t[t.length-1];return this.cursorPosition={...e},!1}}return!0}isObstacleOwnJumperPad(t){if(!this.currentTrace?.jumpers)return!1;for(const e of this.currentTrace.jumpers){const n=Math.sqrt((t.center.x-e.start.x)**2+(t.center.y-e.start.y)**2),s=Math.sqrt((t.center.x-e.end.x)**2+(t.center.y-e.end.y)**2),o=Math.max(t.width,t.height)/2+.01;if(n<o||s<o)return!0}return!1}getClearanceAtPosition(t){if(!this.currentTrace)return 1/0;const e=this.currentTrace.rootConnectionName??this.currentTrace.connectionName,n=2*this.nominalTraceWidth;let s=1/0;if(this.lastCollidingObstacles=[],this.lastCollidingRoutes=[],this.obstacleSHI){const o=this.obstacleSHI.searchArea(t.x,t.y,n,n);for(const n of o){if(n.zLayers&&!n.zLayers.includes(t.z))continue;if(n.connectedTo.includes(e))continue;if(n.obstacleId&&this.connMap?.areIdsConnected(e,n.obstacleId))continue;let o=!1;if(this.connMap)for(const t of n.connectedTo)if(this.connMap.areIdsConnected(e,t)){o=!0;break}if(o)continue;if(this.isObstacleOwnJumperPad(n))continue;const i=n.center.x-n.width/2,r=n.center.x+n.width/2,a=n.center.y-n.height/2,c=n.center.y+n.height/2,h=Math.max(i-t.x,0,t.x-r),d=Math.max(a-t.y,0,t.y-c),l=Math.sqrt(h*h+d*d);l<this.currentTargetWidth/2+this.obstacleMargin&&this.lastCollidingObstacles.push(n),l<s&&(s=l)}}const o=this.hdRouteSHI.getConflictingRoutesNearPoint({x:t.x,y:t.y},n);for(const{conflictingRoute:t,distance:n}of o){const o=t.rootConnectionName??t.connectionName;if(o===e)continue;if(this.connMap?.areIdsConnected(e,o))continue;const i=n-(t.traceThickness??.15)/2;i<this.currentTargetWidth/2+this.obstacleMargin&&this.lastCollidingRoutes.push(t),i<s&&(s=i)}return this.lastClearance=s,s}finalizeCurrentTrace(t){if(!this.currentTrace)return;const e={connectionName:this.currentTrace.connectionName,rootConnectionName:this.currentTrace.rootConnectionName,traceThickness:t,viaDiameter:this.currentTrace.viaDiameter,route:[...this.currentTrace.route],vias:[...this.currentTrace.vias],jumpers:this.currentTrace.jumpers};this.processedRoutes.push(e),this.currentTrace=null,this.cursorPosition=null,this.hasInsufficientClearance=!1}visualize(){const t={lines:[],points:[],circles:[],rects:[],coordinateSystem:"cartesian",title:`Trace Width Solver (schedule: [${this.TRACE_WIDTH_SCHEDULE.map(t=>t.toFixed(2)).join(", ")}]mm, fallback: ${this.minTraceWidth.toFixed(2)}mm, margin: ${this.obstacleMargin.toFixed(2)}mm)`},e=new Set(this.lastCollidingObstacles.map(t=>t.obstacleId)),n=new Set(this.lastCollidingRoutes.map(t=>t.connectionName));for(const n of this.obstacles){const s=e.has(n.obstacleId),o=n.zLayers?.includes(0),i=n.zLayers?.includes(1);let r;r=s?"rgba(255, 0, 0, 0.6)":o&&i?"rgba(128, 0, 128, 0.15)":o?"rgba(255, 0, 0, 0.15)":i?"rgba(0, 0, 255, 0.15)":"rgba(128, 128, 128, 0.15)",t.rects.push({center:n.center,width:n.width,height:n.height,fill:r,stroke:s?"red":void 0,label:s?`COLLIDING: ${n.obstacleId??"obstacle"}`:`${n.obstacleId??"obstacle"} (Z: ${n.zLayers?.join(", ")})`})}for(const e of this.processedRoutes){if(0===e.route.length)continue;const n=e.traceThickness===this.nominalTraceWidth,s=e.traceThickness===this.TRACE_WIDTH_SCHEDULE[1],o=n?"green":s?"yellow":"orange";for(let n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];s.insideJumperPad&&i.insideJumperPad||s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:o,strokeWidth:e.traceThickness,label:`${e.connectionName} (w=${e.traceThickness.toFixed(2)})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const n=Je(e.jumpers,{color:o,label:e.connectionName});t.rects.push(...n.rects??[]),t.lines.push(...n.lines??[])}}if(this.currentTrace){for(let e=0;e<this.currentTrace.route.length-1;e++){const n=this.currentTrace.route[e],s=this.currentTrace.route[e+1];n.insideJumperPad&&s.insideJumperPad||n.z===s.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.y}],strokeColor:"cyan",strokeWidth:this.currentTrace.traceThickness??this.minTraceWidth,label:`Processing: ${this.currentTrace.connectionName}`})}this.cursorPosition&&(t.circles.push({center:{x:this.cursorPosition.x,y:this.cursorPosition.y},radius:this.currentTargetWidth/2,stroke:this.hasInsufficientClearance?"red":"green",fill:"none",label:`Testing width: ${this.currentTargetWidth.toFixed(2)}mm (clearance: ${this.lastClearance.toFixed(2)}mm)`}),t.points.push({x:this.cursorPosition.x,y:this.cursorPosition.y,color:"orange",label:"Cursor"}))}for(const e of this.unprocessedRoutes){if(0===e.route.length)continue;const s=n.has(e.connectionName);for(let n=0;n<e.route.length-1;n++){const o=e.route[n],i=e.route[n+1];o.z===i.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:s?"rgba(255, 0, 0, 0.8)":"rgba(128, 128, 128, 0.3)",strokeWidth:e.traceThickness??this.minTraceWidth,label:s?`COLLIDING: ${e.connectionName}`:e.connectionName})}}return t}getHdRoutesWithWidths(){return this.hdRoutesWithWidths}},ar=class extends y{constructor(t){super(),this.input=t,this.unprocessedObstacles=this.input.srj.obstacles.filter(t=>t.offBoardConnectsTo&&t.offBoardConnectsTo.length>0),this.unprocessedObstacles.forEach((t,e)=>{t.obstacleId=t.obstacleId??`__obs${e}`,t.zLayers=t.zLayers??t.layers.map(t=>Xe(t,this.input.srj.layerCount))}),this.offBoardConnMap=new tn({}),this.offBoardConnMap.addConnections(this.unprocessedObstacles.filter(t=>t.offBoardConnectsTo?.length).map(t=>[t.obstacleId,...t.offBoardConnectsTo??[]])),this.nodeTree=new an(this.input.capacityMeshNodes)}unprocessedObstacles;nodeTree;offBoardConnMap;nodesInNet=new Map;lastProcessedObstacle;_step(){const t=this.unprocessedObstacles.pop();if(this.lastProcessedObstacle=t,!t)return void(this.solved=!0);const e=this.offBoardConnMap.getNetConnectedToId(t.obstacleId),n=this.nodeTree.getNodesInArea(t.center.x,t.center.y,.01,.01).filter(e=>e.availableZ.some(e=>t.zLayers?.includes(e))).filter(e=>Math.abs(e.center.x-t.center.x)<.01&&Math.abs(e.center.y-t.center.y)<.01),s=n.map(t=>t.capacityMeshNodeId),o=this.nodesInNet.get(e)??[],i=[...o.map(t=>t.capacityMeshNodeId),...s];for(const t of o)t._offBoardConnectedCapacityMeshNodeIds=i;for(const t of n)t._offBoardConnectedCapacityMeshNodeIds=i,t._offBoardConnectionId=e;this.nodesInNet.set(e,[...o,...n])}getOutput(){return{capacityNodes:this.input.capacityMeshNodes}}visualize(){const t={rects:[],lines:[],points:[],circles:[]},e=new Set;for(const[t,n]of this.nodesInNet)for(const t of n)e.add(t.capacityMeshNodeId);for(const n of this.input.capacityMeshNodes)e.has(n.capacityMeshNodeId)||t.rects.push({center:n.center,width:n.width-.1,height:n.height-.1,fill:"rgba(0, 0, 0, 0.2)"});this.lastProcessedObstacle&&t.rects.push({center:this.lastProcessedObstacle.center,width:this.lastProcessedObstacle.width,height:this.lastProcessedObstacle.height,fill:"rgba(255, 0, 0, 0.5)"});for(const[e,n]of this.nodesInNet.entries()){for(const s of n)t.rects.push({center:s.center,width:s.width,height:s.height,fill:rt(e,.2),label:`OffBoardConn: ${e}`});for(const s of n)for(const o of n)s.capacityMeshNodeId!==o.capacityMeshNodeId&&t.lines.push({points:[s.center,o.center],strokeColor:rt(e,1)})}return t}},cr=({connMap:t,connectionsWithResults:e,inputNodes:n,obstacles:s})=>{const o=s.filter(t=>t.offBoardConnectsTo?.length);if(0===o.length)return;const i=new Fe({});i.addConnections(o.map((t,e)=>{const n=t.obstacleId??`__obs${e}`;return t.obstacleId=n,[n,...t.offBoardConnectsTo??[]]}));const r=new Map(n.map(t=>[t.capacityMeshNodeId,t]));for(const n of e){if(!n.path)continue;const e=n.connection.rootConnectionName??n.connection.name,s=new Set;for(const t of n.path){const e=r.get(t.currentNodeId);if(e?._offBoardConnectionId&&s.add(e._offBoardConnectionId),t.throughNodeId){const e=r.get(t.throughNodeId);e?._offBoardConnectionId&&s.add(e._offBoardConnectionId)}}for(const n of s){const s=i.getIdsConnectedToNet(n);s?.length&&t.addConnections([[e,...s]])}}};function hr(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var dr=class extends y{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth,this.effort=e.effort??1,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,o=Math.max(n,s),i=e.targetMinCapacity??.5;e.capacityDepth=Be(o,i)}this.connMap=$e(t),this.colorMap=ot(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;relateNodesToOffBoardConnections;colorMap;highDensityRouteSolver;simpleHighDensityRouteSolver;highDensitySolver;highDensityStitchSolver;singleLayerNodeMerger;offboardPathFragmentSolver;strawSolver;deadEndSolver;traceSimplificationSolver;traceKeepoutSolver;traceWidthSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;viaDiameter;minTraceWidth;effort;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[hr("netToPointPairsSolver",fn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ot(t.srjWithPointPairs,this.connMap),t.connMap=$e(t.srjWithPointPairs)}}),hr("nodeSolver",Js,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),hr("relateNodesToOffBoardConnections",ar,t=>[{capacityMeshNodes:t.capacityNodes,srj:t.srj}],{onSolved:t=>{t.capacityNodes=t.relateNodesToOffBoardConnections?.getOutput().capacityNodes}}),hr("edgeSolver",cn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),hr("availableSegmentPointSolver",Io,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),hr("portPointPathingSolver",Vo,t=>{const e=t.capacityNodes.map(t=>({capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:[],availableZ:t.availableZ,_containsTarget:t._containsTarget,_containsObstacle:t._containsObstacle,_offBoardConnectionId:t._offBoardConnectionId,_offBoardConnectedCapacityMeshNodeIds:t._offBoardConnectedCapacityMeshNodeIds})),n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),s=t.availableSegmentPointSolver;for(const t of s.sharedEdgeSegments)for(const e of t.portPoints){const[s,o]=e.nodeIds,i={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[s,o],distToCentermostPortOnZ:e.distToCentermostPortOnZ,connectsToOffBoardNode:t.nodeIds.some(t=>n.get(t)?._offBoardConnectionId)},r=n.get(s);r&&r.portPoints.push(i)}return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e,capacityMeshNodes:t.capacityNodes,colorMap:t.colorMap,numShuffleSeeds:100*t.effort,hyperParameters:{JUMPER_PF_FN_ENABLED:!1,NODE_PF_FACTOR:100,NODE_PF_MAX_PENALTY:100,CENTER_OFFSET_DIST_PENALTY_FACTOR:0,FORCE_CENTER_FIRST:!0}}]},{onSolved:t=>{const e=t.portPointPathingSolver;e&&cr({connMap:t.connMap,connectionsWithResults:e.connectionsWithResults,inputNodes:e.inputNodes,obstacles:t.srj.obstacles})}}),hr("multiSectionPortPointOptimizer",Ho,t=>{const e=t.portPointPathingSolver;return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e.inputNodes,capacityMeshNodes:t.capacityNodes,capacityMeshEdges:t.capacityEdges,colorMap:t.colorMap,initialConnectionResults:e.connectionsWithResults,initialAssignedPortPoints:e.assignedPortPoints,initialNodeAssignedPortPoints:e.nodeAssignedPortPoints}]}),hr("highDensitySolver",Bi,t=>[{nodePortPoints:t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth,connMap:t.connMap}]),hr("highDensityStitchSolver",nn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensitySolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),hr("traceSimplificationSolver",Mo,t=>[{hdRoutes:t.highDensityStitchSolver?.mergedHdRoutes??t.highDensitySolver?.routes??t.highDensityRouteSolver?.routes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline,defaultViaDiameter:t.viaDiameter,layerCount:t.srj.layerCount,iterations:2}]),hr("traceKeepoutSolver",ir,t=>[{hdRoutes:t.traceSimplificationSolver?.simplifiedHdRoutes??[],obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,srj:t.srj}]),hr("traceWidthSolver",rr,t=>[{hdRoutes:t.traceKeepoutSolver?.redrawnHdRoutes??[],obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,nominalTraceWidth:t.srj.nominalTraceWidth,minTraceWidth:t.minTraceWidth,obstacleMargin:t.srj.defaultObstacleMargin??.15}])];getConstructorParams(){return[this.srj,this.opts]}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 t=this.netToPointPairsSolver?.visualize(),e=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),s=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),i=this.edgeSolver?.visualize(),r=this.deadEndSolver?.visualize(),a=this.availableSegmentPointSolver?.visualize(),c=this.offboardPathFragmentSolver?.visualize(),h=this.portPointPathingSolver?.visualize(),d=this.multiSectionPortPointOptimizer?.visualize(),l=this.highDensityRouteSolver?.visualize(),u=this.highDensitySolver?.visualize(),p=this.simpleHighDensityRouteSolver?.visualize(),m=this.highDensityStitchSolver?.visualize(),f=this.traceSimplificationSolver?.visualize(),y=this.traceKeepoutSolver?.visualize(),x=this.traceWidthSolver?.visualize(),v=this.srj.outline,S=[];if(S.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)"}),v&&v.length>=2){const t=v.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),S.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const P={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:["obstacle",t.offBoardConnectsTo?`offboardConnections: ${t.offBoardConnectsTo?.join(", ")}`:"",t.layers?.join(", ")].filter(Boolean).join("\n")}))],lines:S},b=[P,t,e,n,s,o,i,r,a,c,h,d,l?g(P,l):null,u?g(P,u):null,p?g(P,p):null,m,f,y,x,this.solved?g(P,sn(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...b)}preview(){const t=this.highDensitySolver?.routes??this.simpleHighDensityRouteSolver?.routes??this.highDensityRouteSolver?.routes;if(t){const e=[];for(let n=t.length-1;n>=0;n--){const s=t[n];if(e.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[s.connectionName]}),e.length>200)break}return{lines:e}}if(this.portPointPathingSolver){const t=[];for(const e of this.portPointPathingSolver.connectionsWithResults)e.path&&t.push({points:e.path.map(t=>({x:t.point.x,y:t.point.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.traceWidthSolver?.hdRoutesWithWidths??this.traceKeepoutSolver?.redrawnHdRoutes??this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver?.mergedHdRoutes??this.highDensitySolver?.routes??this.simpleHighDensityRouteSolver?.routes??this.highDensityRouteSolver?.routes}getConnectedOffboardObstacles(){const t={},e=new Set(this.srj.connections.map(t=>t.rootConnectionName??t.name));for(const[n,s]of this.srj.obstacles.entries()){if(!s.offBoardConnectsTo?.length)continue;const o=s.obstacleId??`__obs${n}`;s.obstacleId=o;const i=this.connMap.getNetConnectedToId(o);if(!i)continue;const r=this.connMap.getIdsConnectedToNet(i).find(t=>e.has(t));r&&(t[o]=r)}return t}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver&&!this.simpleHighDensityRouteSolver&&!this.highDensitySolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,o=e.filter(t=>t.connectionName===n.name);for(let e=0;e<o.length;e++){const i=o[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:We(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},lr=class{MAX_ITERATIONS=1e5;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};_setupDone=!1;setup(){this._setupDone||(this._setup(),this._setupDone=!0)}_setup(){}step(){if(this._setupDone||this.setup(),!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,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`,this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}getOutput(){return null}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}},ur=t=>({x:(t.minX+t.maxX)/2,y:(t.minY+t.maxY)/2}),pr={padWidth:.8,padHeight:.5,leftPadCenterX:-1.35,rightPadCenterX:1.35,row1CenterY:1.905,row2CenterY:.635,row3CenterY:-.635,row4CenterY:-1.905},mr=t=>{let e=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,s=Number.POSITIVE_INFINITY,o=Number.NEGATIVE_INFINITY;for(const i of t){const{bounds:t}=i.d;e=Math.min(e,t.minX),n=Math.max(n,t.maxX),s=Math.min(s,t.minY),o=Math.max(o,t.maxY)}return{minX:e,maxX:n,minY:s,maxY:o}};function fr(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}}function gr(t){return void 0===t}function yr(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}function xr(...t){const e=(t,e)=>({a:t.a*e.a+t.c*e.b,c:t.a*e.c+t.c*e.d,e:t.a*e.e+t.c*e.f+t.e,b:t.b*e.a+t.d*e.b,d:t.b*e.c+t.d*e.d,f:t.b*e.e+t.d*e.f+t.f});switch((t=Array.isArray(t[0])?t[0]:t).length){case 0:throw new Error("no matrices provided");case 1:return t[0];case 2:return e(t[0],t[1]);default:{const[n,s,...o]=t;return xr(e(n,s),...o)}}}var{cos:vr,sin:Sr,PI:Pr}=Math;var{tan:br}=Math,Mr=({cols:t,rows:e,marginX:n,marginY:s,innerColChannelPointCount:o=1,innerRowChannelPointCount:i=1,regionsBetweenPads:r=!1,outerPaddingX:a=.5,outerPaddingY:c=.5,outerChannelXPointCount:h,outerChannelYPointCount:d,orientation:l="vertical",center:u,bounds:p,parallelTracesUnderJumperCount:m=4})=>{const f=[],g=[],{padWidth:y,padHeight:x,leftPadCenterX:v,rightPadCenterX:S,row1CenterY:P,row2CenterY:b,row3CenterY:M,row4CenterY:N}=pr,I=y/2,C=x/2,_=S-v+y,T=_+n,E=P-N+x,R=E+s;let w=a,A=c;if(p){const o=t*_+(t-1)*n,i=e*E+(e-1)*s;w=(("horizontal"===l?p.maxY-p.minY:p.maxX-p.minX)-o)/2,A=(("horizontal"===l?p.maxX-p.minX:p.maxY-p.minY)-i)/2}const O=h??Math.max(1,Math.floor(w/.4)),z=d??Math.max(1,Math.floor(A/.4)),D=[],L=[],F=(t,e,n,s)=>({regionId:t,ports:[],d:{bounds:e,center:ur(e),isPad:n,isThroughJumper:s}}),X=(t,e,n)=>{const s=e.d.bounds,o=n.d.bounds;let i,r;Math.abs(s.maxX-o.minX)<.001?(i=s.maxX,r=(Math.max(s.minY,o.minY)+Math.min(s.maxY,o.maxY))/2):Math.abs(s.minX-o.maxX)<.001?(i=s.minX,r=(Math.max(s.minY,o.minY)+Math.min(s.maxY,o.maxY))/2):Math.abs(s.maxY-o.minY)<.001?(i=(Math.max(s.minX,o.minX)+Math.min(s.maxX,o.maxX))/2,r=s.maxY):(i=(Math.max(s.minX,o.minX)+Math.min(s.maxX,o.maxX))/2,r=s.minY);const a={portId:t,region1:e,region2:n,d:{x:i,y:r}};return e.ports.push(a),n.ports.push(a),a},Y=(t,e,n,s)=>{if(s<=0)return[];if(1===s)return[X(t,e,n)];const o=e.d.bounds,i=n.d.bounds,r=[];let a,c,h,d;Math.abs(o.maxX-i.minX)<.001?(a=!0,c=o.maxX,h=Math.max(o.minY,i.minY),d=Math.min(o.maxY,i.maxY)):Math.abs(o.minX-i.maxX)<.001?(a=!0,c=o.minX,h=Math.max(o.minY,i.minY),d=Math.min(o.maxY,i.maxY)):Math.abs(o.maxY-i.minY)<.001?(a=!1,c=o.maxY,h=Math.max(o.minX,i.minX),d=Math.min(o.maxX,i.maxX)):(a=!1,c=o.minY,h=Math.max(o.minX,i.minX),d=Math.min(o.maxX,i.maxX));for(let o=0;o<s;o++){const i=h+(o+.5)/s*(d-h),l={portId:`${t}:${o}`,region1:e,region2:n,d:{x:a?c:i,y:a?i:c}};e.ports.push(l),n.ports.push(l),r.push(l)}return r};for(let n=0;n<e;n++){D[n]=[];for(let a=0;a<t;a++){const c=`cell_${n}_${a}`,h=a*T,d=-n*R,l=h+v,u=d+P,p=h+v,y=d+b,x=h+v,_=d+M,E=h+v,$=d+N,k=h+S,B=d+N,j=h+S,W=d+M,H=h+S,U=d+b,V=h+S,Z=d+P,G=(t,e)=>({minX:t-I,maxX:t+I,minY:e-C,maxY:e+C}),J=G(l,u),q=G(p,y),K=G(x,_),Q=G(E,$),tt=G(k,B),et=G(j,W),nt=G(H,U),st=G(V,Z),ot={minX:J.maxX,maxX:st.minX,minY:Q.minY,maxY:J.maxY},it=.3,rt={minX:l,maxX:V,minY:u-it/2,maxY:u+it/2},at={minX:p,maxX:H,minY:y-it/2,maxY:y+it/2},ct={minX:x,maxX:j,minY:_-it/2,maxY:_+it/2},ht={minX:E,maxX:k,minY:$-it/2,maxY:$+it/2},dt=J.minX,lt=st.maxX,ut=Q.minY,pt=J.maxY,mt=F(`${c}:pad1`,J,!0),ft=F(`${c}:pad2`,q,!0),gt=F(`${c}:pad3`,K,!0),yt=F(`${c}:pad4`,Q,!0),xt=F(`${c}:pad5`,tt,!0),vt=F(`${c}:pad6`,et,!0),St=F(`${c}:pad7`,nt,!0),Pt=F(`${c}:pad8`,st,!0),bt=F(`${c}:underjumper`,ot,!1),Mt=F(`${c}:throughjumper1`,rt,!1,!0),Nt=F(`${c}:throughjumper2`,at,!1,!0),It=F(`${c}:throughjumper3`,ct,!1,!0),Ct=F(`${c}:throughjumper4`,ht,!1,!0);f.push(mt,ft,gt,yt,xt,vt,St,Pt,bt,Mt,Nt,It,Ct);const _t=(l+V)/2,Tt=(u+$)/2;L.push({center:{x:_t,y:Tt},orientation:"vertical",padRegions:[mt,ft,gt,yt,xt,vt,St,Pt]});let Et=null,Rt=null,wt=null,At=null,Ot=null,zt=null;r&&(Et=F(`${c}:L-BP12`,{minX:J.minX,maxX:J.maxX,minY:q.maxY,maxY:J.minY},!1),Rt=F(`${c}:L-BP23`,{minX:q.minX,maxX:q.maxX,minY:K.maxY,maxY:q.minY},!1),wt=F(`${c}:L-BP34`,{minX:K.minX,maxX:K.maxX,minY:Q.maxY,maxY:K.minY},!1),At=F(`${c}:R-BP87`,{minX:st.minX,maxX:st.maxX,minY:nt.maxY,maxY:st.minY},!1),Ot=F(`${c}:R-BP76`,{minX:nt.minX,maxX:nt.maxX,minY:et.maxY,maxY:nt.minY},!1),zt=F(`${c}:R-BP65`,{minX:et.minX,maxX:et.maxX,minY:tt.maxY,maxY:et.minY},!1),f.push(Et,Rt,wt,At,Ot,zt));const Dt=0===a,Lt=n===e-1,Ft=a===t-1;let Xt;if(Ft)Xt=lt+w;else{Xt=(a+1)*T+v-I}let Yt=null;0===n&&(Yt=F(`${c}:T`,{minX:Dt?dt-w:dt,maxX:Xt,minY:pt,maxY:pt+A},!1),f.push(Yt));let $t=null;$t=F(`${c}:B`,{minX:Dt?dt-w:dt,maxX:Xt,minY:ut-(Lt?A:s),maxY:ut},!1),f.push($t);let kt=null;Dt&&(kt=F(`${c}:L`,{minX:dt-w,maxX:dt,minY:ut,maxY:pt},!1),f.push(kt));const Bt=F(`${c}:R`,{minX:lt,maxX:Xt,minY:ut,maxY:pt},!1);if(f.push(Bt),D[n][a]={pad1:mt,pad2:ft,pad3:gt,pad4:yt,pad5:xt,pad6:vt,pad7:St,pad8:Pt,underjumper:bt,throughjumper1:Mt,throughjumper2:Nt,throughjumper3:It,throughjumper4:Ct,top:Yt,bottom:$t,left:kt,right:Bt,leftBP12:Et,leftBP23:Rt,leftBP34:wt,rightBP87:At,rightBP76:Ot,rightBP65:zt},Yt)if(kt&&g.push(...Y(`${c}:T-L`,Yt,kt,O)),g.push(...Y(`${c}:T-R`,Yt,Bt,Ft?O:o)),g.push(X(`${c}:T-P1`,Yt,mt)),g.push(X(`${c}:T-P8`,Yt,Pt)),r){const t=bt.d.bounds,e=(t.maxX-t.minX)/(m+1);for(let n=1;n<=m;n++){const s={portId:`${c}:T-UJ${n}`,region1:Yt,region2:bt,d:{x:t.minX+e*n,y:t.maxY}};Yt.ports.push(s),bt.ports.push(s),g.push(s)}}else g.push(X(`${c}:T-UJ`,Yt,bt));if($t)if(kt&&g.push(...Y(`${c}:B-L`,$t,kt,O)),g.push(...Y(`${c}:B-R`,$t,Bt,Ft?O:o)),g.push(X(`${c}:B-P4`,$t,yt)),g.push(X(`${c}:B-P5`,$t,xt)),r){const t=bt.d.bounds,e=(t.maxX-t.minX)/(m+1);for(let n=1;n<=m;n++){const s={portId:`${c}:B-UJ${n}`,region1:$t,region2:bt,d:{x:t.minX+e*n,y:t.minY}};$t.ports.push(s),bt.ports.push(s),g.push(s)}}else g.push(X(`${c}:B-UJ`,$t,bt));kt&&(g.push(X(`${c}:L-P1`,kt,mt)),g.push(X(`${c}:L-P2`,kt,ft)),g.push(X(`${c}:L-P3`,kt,gt)),g.push(X(`${c}:L-P4`,kt,yt))),g.push(X(`${c}:R-P5`,Bt,xt)),g.push(X(`${c}:R-P6`,Bt,vt)),g.push(X(`${c}:R-P7`,Bt,St)),g.push(X(`${c}:R-P8`,Bt,Pt)),r&&(kt&&(g.push(X(`${c}:L-BP12`,kt,Et)),g.push(X(`${c}:L-BP23`,kt,Rt)),g.push(X(`${c}:L-BP34`,kt,wt))),g.push(X(`${c}:UJ-LBP12`,Et,bt)),g.push(X(`${c}:UJ-LBP23`,Rt,bt)),g.push(X(`${c}:UJ-LBP34`,wt,bt)),g.push(X(`${c}:R-BP87`,Bt,At)),g.push(X(`${c}:R-BP76`,Bt,Ot)),g.push(X(`${c}:R-BP65`,Bt,zt)),g.push(X(`${c}:UJ-RBP87`,At,bt)),g.push(X(`${c}:UJ-RBP76`,Ot,bt)),g.push(X(`${c}:UJ-RBP65`,zt,bt)));const jt={portId:`${c}:TJ1-P1`,region1:Mt,region2:mt,d:{x:l,y:u}};Mt.ports.push(jt),mt.ports.push(jt),g.push(jt);const Wt={portId:`${c}:TJ1-P8`,region1:Mt,region2:Pt,d:{x:V,y:Z}};Mt.ports.push(Wt),Pt.ports.push(Wt),g.push(Wt);const Ht={portId:`${c}:TJ2-P2`,region1:Nt,region2:ft,d:{x:p,y:y}};Nt.ports.push(Ht),ft.ports.push(Ht),g.push(Ht);const Ut={portId:`${c}:TJ2-P7`,region1:Nt,region2:St,d:{x:H,y:U}};Nt.ports.push(Ut),St.ports.push(Ut),g.push(Ut);const Vt={portId:`${c}:TJ3-P3`,region1:It,region2:gt,d:{x:x,y:_}};It.ports.push(Vt),gt.ports.push(Vt),g.push(Vt);const Zt={portId:`${c}:TJ3-P6`,region1:It,region2:vt,d:{x:j,y:W}};It.ports.push(Zt),vt.ports.push(Zt),g.push(Zt);const Gt={portId:`${c}:TJ4-P4`,region1:Ct,region2:yt,d:{x:E,y:$}};Ct.ports.push(Gt),yt.ports.push(Gt),g.push(Gt);const Jt={portId:`${c}:TJ4-P5`,region1:Ct,region2:xt,d:{x:k,y:B}};if(Ct.ports.push(Jt),xt.ports.push(Jt),g.push(Jt),a>0){const t=D[n][a-1];g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-P1`,t.right,mt)),g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-P2`,t.right,ft)),g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-P3`,t.right,gt)),g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-P4`,t.right,yt)),r&&(g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP12`,t.right,Et)),g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP23`,t.right,Rt)),g.push(X(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP34`,t.right,wt))),Yt&&t.top&&g.push(...Y(`cell_${n}_${a-1}->cell_${n}_${a}:T-T`,t.top,Yt,z)),$t&&t.bottom&&g.push(...Y(`cell_${n}_${a-1}->cell_${n}_${a}:B-B`,t.bottom,$t,Lt?z:i))}if(n>0){const t=D[n-1][a];if(kt&&g.push(...Y(`cell_${n-1}_${a}->cell_${n}_${a}:B-L`,t.bottom,kt,O)),g.push(X(`cell_${n-1}_${a}->cell_${n}_${a}:B-P1`,t.bottom,mt)),r){const e=bt.d.bounds,s=(e.maxX-e.minX)/(m+1);for(let o=1;o<=m;o++){const i=e.minX+s*o,r={portId:`cell_${n-1}_${a}->cell_${n}_${a}:B-UJ${o}`,region1:t.bottom,region2:bt,d:{x:i,y:e.maxY}};t.bottom.ports.push(r),bt.ports.push(r),g.push(r)}}else g.push(X(`cell_${n-1}_${a}->cell_${n}_${a}:B-UJ`,t.bottom,bt));g.push(X(`cell_${n-1}_${a}->cell_${n}_${a}:B-P8`,t.bottom,Pt)),g.push(...Y(`cell_${n-1}_${a}->cell_${n}_${a}:B-R`,t.bottom,Bt,Ft?O:o))}}}let $={regions:f,ports:g,jumperLocations:L};const k="horizontal"===l;if(k||void 0!==u||void 0!==p){const t=mr($.regions),e=ur(t),n=[];let s;s=u||(p?ur(p):e),n.push(yr(s.x,s.y)),k&&n.push(function(t,e,n){const s=vr(t),o=Sr(t),i={a:s,c:-o,e:0,b:o,d:s,f:0};return gr(e)||gr(n)?i:xr([yr(e,n),i,yr(-e,-n)])}(-Math.PI/2)),n.push(yr(-e.x,-e.y));const o=function(...t){return xr(...t)}(...n);$=((t,e)=>{const n=t.regions.map(t=>{const{bounds:n,center:s,...o}=t.d,i=[{x:n.minX,y:n.minY},{x:n.maxX,y:n.minY},{x:n.minX,y:n.maxY},{x:n.maxX,y:n.maxY}].map(t=>fr(e,t)),r={minX:Math.min(...i.map(t=>t.x)),maxX:Math.max(...i.map(t=>t.x)),minY:Math.min(...i.map(t=>t.y)),maxY:Math.max(...i.map(t=>t.y))},a=fr(e,s);return{...t,ports:[],d:{...o,bounds:r,center:a}}}),s=new Map;for(let e=0;e<t.regions.length;e++)s.set(t.regions[e],n[e]);const o=t.ports.map(t=>{const n=fr(e,t.d),o=s.get(t.region1),i=s.get(t.region2),r={...t,region1:o,region2:i,d:n};return o.ports.push(r),i.ports.push(r),r}),i=t.jumperLocations?.map(t=>{const n=fr(e,t.center),o=t.padRegions.map(t=>s.get(t)),i=fr(e,{x:1,y:0}),r=fr(e,{x:0,y:0}),a=i.x-r.x,c=i.y-r.y;return{center:n,orientation:Math.abs(c)>Math.abs(a)?"horizontal"===t.orientation?"vertical":"horizontal":t.orientation,padRegions:o}});return{regions:n,ports:o,...i&&{jumperLocations:i}}})($,o)}return $},Nr=(t,e,n,s)=>{const o={portId:t,region1:e,region2:n,d:{x:s.x,y:s.y}};return e.ports.push(o),n.ports.push(o),o},Ir=(t,e,n)=>{const s=.2;return{regionId:t,ports:[],d:{bounds:{minX:e-s,maxX:e+s,minY:n-s,maxY:n+s},center:{x:e,y:n},isPad:!1,isConnectionRegion:!0}}},Cr=(t,e,n,s)=>{for(const s of n){if(s.d.isPad||s.d.isThroughJumper)continue;const n=s.d.bounds;if(Math.abs(t-n.minX)<.01&&e>=n.minY&&e<=n.maxY)return{region:s,portPosition:{x:n.minX,y:e}};if(Math.abs(t-n.maxX)<.01&&e>=n.minY&&e<=n.maxY)return{region:s,portPosition:{x:n.maxX,y:e}};if(Math.abs(e-n.minY)<.01&&t>=n.minX&&t<=n.maxX)return{region:s,portPosition:{x:t,y:n.minY}};if(Math.abs(e-n.maxY)<.01&&t>=n.minX&&t<=n.maxX)return{region:s,portPosition:{x:t,y:n.maxY}}}let o=null,i=Number.POSITIVE_INFINITY,r={x:t,y:e};for(const a of n){if(a.d.isPad||a.d.isThroughJumper)continue;const n=a.d.bounds;if(!(Math.abs(n.minX-s.minX)<.01||Math.abs(n.maxX-s.maxX)<.01||Math.abs(n.minY-s.minY)<.01||Math.abs(n.maxY-s.maxY)<.01))continue;const c=Math.max(n.minX,Math.min(n.maxX,t)),h=Math.max(n.minY,Math.min(n.maxY,e)),d=Math.sqrt((t-c)**2+(e-h)**2);d<i&&(i=d,o=a,r=t<n.minX?{x:n.minX,y:h}:t>n.maxX?{x:n.maxX,y:h}:e<n.minY?{x:c,y:n.minY}:e>n.maxY?{x:c,y:n.maxY}:{x:c,y:h})}return o?{region:o,portPosition:r}:null},_r=class{heap=[];maxSize;constructor(t=[],e=1e4){if(this.maxSize=e,t.length>0){this.heap=[...t].sort((t,e)=>t.f-e.f).slice(0,this.maxSize);for(let t=Math.floor(this.heap.length/2)-1;t>=0;t--)this._siftDown(t)}}get size(){return this.heap.length}isEmpty(){return 0===this.heap.length}peek(){return this.isEmpty()?null:this.heap[0]??null}peekMany(t){return[...this.heap].sort((t,e)=>t.f-e.f).slice(0,t)}dequeue(){if(this.isEmpty())return null;const t=this.heap[0],e=this.heap.pop();return 0===this.heap.length&&void 0!==e||void 0!==e&&(this.heap[0]=e,this._siftDown(0)),t}enqueue(t){this.heap.length>=this.maxSize||(this.heap.push(t),this._siftUp(this.heap.length-1))}_siftUp(t){let e=t;for(;e>0;){const t=this._parentIndex(e);if(this.heap[t].f<=this.heap[e].f)break;this._swap(e,t),e=t}}_siftDown(t){let e=t;const n=this.heap.length;for(;;){const t=this._leftChildIndex(e),s=this._rightChildIndex(e);let o=e;if(t<n&&this.heap[t].f<this.heap[o].f&&(o=t),s<n&&this.heap[s].f<this.heap[o].f&&(o=s),o===e)break;this._swap(e,o),e=o}}_swap(t,e){[this.heap[t],this.heap[e]]=[this.heap[e],this.heap[t]]}_parentIndex(t){return Math.floor((t-1)/2)}_leftChildIndex(t){return 2*t+1}_rightChildIndex(t){return 2*t+2}},Tr=class extends lr{constructor(t){super(),this.input=t,this.graph=(t=>{if(t.ports.length>0&&"region1"in t.ports[0]&&"object"==typeof t.ports[0].region1)return t;const e=new Map,n=new Map;for(const e of t.regions){const{assignments:t,...s}=e;n.set(e.regionId,{...s,ports:[],assignments:void 0})}for(const s of t.ports){const t=n.get(s.region1Id??s.region1?.regionId),o=n.get(s.region2Id??s.region2?.regionId),i={portId:s.portId,region1:t,region2:o,d:s.d};e.set(s.portId,i),t.ports.push(i),o.ports.push(i)}return{ports:Array.from(e.values()),regions:Array.from(n.values())}})(t.inputGraph);for(const t of this.graph.regions)t.assignments=[];this.connections=((t,e)=>{const n=[];for(const s of t)"startRegionId"in s?n.push({connectionId:s.connectionId,mutuallyConnectedNetworkId:s.connectionId,startRegion:e.regions.find(t=>t.regionId===s.startRegionId),endRegion:e.regions.find(t=>t.regionId===s.endRegionId)}):n.push(s);return n})(t.inputConnections,this.graph),void 0!==t.greedyMultiplier&&(this.greedyMultiplier=t.greedyMultiplier),void 0!==t.rippingEnabled&&(this.rippingEnabled=t.rippingEnabled),void 0!==t.ripCost&&(this.ripCost=t.ripCost),this.unprocessedConnections=[...this.connections],this.candidateQueue=new _r,this.beginNewConnection()}graph;connections;candidateQueue;unprocessedConnections;solvedRoutes=[];currentConnection=null;currentEndRegion=null;greedyMultiplier=1;rippingEnabled=!1;ripCost=0;lastCandidate=null;visitedPointsForCurrentConnection=new Map;getConstructorParams(){return{inputGraph:(e=this.graph,{ports:e.ports.map(t=>({portId:t.portId,region1Id:t.region1.regionId,region2Id:t.region2.regionId,d:t.d})),regions:e.regions.map(t=>({regionId:t.regionId,pointIds:t.ports.map(t=>t.portId),d:t.d}))}),inputConnections:(t=this.connections,t.map(t=>({connectionId:t.connectionId,startRegionId:t.startRegion.regionId,endRegionId:t.endRegion.regionId}))),greedyMultiplier:this.greedyMultiplier,rippingEnabled:this.rippingEnabled,ripCost:this.ripCost};var t,e}computeH(t){return this.estimateCostToEnd(t.port)}estimateCostToEnd(t){return 0}getPortUsagePenalty(t){return 0}computeIncreasedRegionCostIfPortsAreUsed(t,e,n){return 0}getRipsRequiredForPortUsage(t,e,n){return[]}computeG(t){return t.parent.g+this.computeIncreasedRegionCostIfPortsAreUsed(t.lastRegion,t.lastPort,t.port)+(t.ripRequired?this.ripCost:0)+this.getPortUsagePenalty(t.port)}selectCandidatesForEnteringRegion(t){return t}getNextCandidates(t){const e=t.nextRegion,n=t.port,s={};for(const o of e.ports){if(o===t.port)continue;const i=o.assignment&&o.assignment.connection.mutuallyConnectedNetworkId!==this.currentConnection.mutuallyConnectedNetworkId,r={port:o,hops:t.hops+1,parent:t,lastRegion:e,nextRegion:o.region1===e?o.region2:o.region1,lastPort:n,ripRequired:i};!this.rippingEnabled&&r.ripRequired||(s[r.nextRegion.regionId]??=[],s[r.nextRegion.regionId].push(r))}const o=[];for(const t in s){const e=s[t];o.push(...this.selectCandidatesForEnteringRegion(e))}for(const t of o)t.g=this.computeG(t),t.h=this.computeH(t),t.f=t.g+t.h*this.greedyMultiplier;return o}processSolvedRoute(t){const e={path:[],connection:this.currentConnection,requiredRip:!1};let n=t,s=!1;for(;n;)s||=!!n.ripRequired,e.path.unshift(n),n=n.parent;const o=new Set;if(s){e.requiredRip=!0;for(const t of e.path)t.port.assignment&&t.port.assignment.connection.mutuallyConnectedNetworkId!==this.currentConnection.mutuallyConnectedNetworkId&&o.add(t.port.assignment.solvedRoute)}for(const t of e.path){if(!t.lastPort||!t.lastRegion)continue;const e=this.getRipsRequiredForPortUsage(t.lastRegion,t.lastPort,t.port);for(const t of e)o.add(t.solvedRoute)}if(o.size>0){e.requiredRip=!0;for(const t of o)this.ripSolvedRoute(t)}for(const t of e.path){if(t.port.assignment={solvedRoute:e,connection:this.currentConnection},!t.lastPort)continue;const n={regionPort1:t.lastPort,regionPort2:t.port,region:t.lastRegion,connection:this.currentConnection,solvedRoute:e};t.lastRegion.assignments?.push(n)}this.solvedRoutes.push(e),this.routeSolvedHook(e)}routeSolvedHook(t){}routeStartedHook(t){}ripSolvedRoute(t){for(const e of t.path.map(t=>t.port))e.ripCount=(e.ripCount??0)+1,e.region1.assignments=e.region1.assignments?.filter(t=>t.regionPort1!==e&&t.regionPort2!==e),e.region2.assignments=e.region2.assignments?.filter(t=>t.regionPort1!==e&&t.regionPort2!==e),e.assignment=void 0;this.solvedRoutes=this.solvedRoutes.filter(e=>e!==t),this.unprocessedConnections.push(t.connection)}beginNewConnection(){this.currentConnection=this.unprocessedConnections.shift(),this.currentEndRegion=this.currentConnection.endRegion,this.candidateQueue=new _r,this.visitedPointsForCurrentConnection.clear(),this.routeStartedHook(this.currentConnection);for(const t of this.currentConnection.startRegion.ports)this.candidateQueue.enqueue({port:t,g:0,h:0,f:0,hops:0,ripRequired:!1,nextRegion:t.region1===this.currentConnection.startRegion?t.region2:t.region1})}_step(){let t=this.candidateQueue.dequeue();if(!t)return this.failed=!0,void(this.error="Ran out of candidates");let e=this.visitedPointsForCurrentConnection.get(t.port.portId);for(;t&&void 0!==e&&!(t.g<e)&&(t=this.candidateQueue.dequeue(),t);)e=this.visitedPointsForCurrentConnection.get(t.port.portId);if(!t)return this.failed=!0,void(this.error="Ran out of candidates");if(this.lastCandidate=t,this.visitedPointsForCurrentConnection.set(t.port.portId,t.g),t.nextRegion===this.currentEndRegion)return this.processSolvedRoute(t),0===this.unprocessedConnections.length?void(this.solved=!0):void this.beginNewConnection();const n=this.getNextCandidates(t);for(const t of n)this.candidateQueue.enqueue(t)}},Er=(t,e=.8)=>{let n=0;for(let e=0;e<t.length;e++)n=17777*t.charCodeAt(e)+((n<<5)-n);return`hsla(${Math.abs(n)%360}, 70%, 50%, ${e})`};function Rr(t,e,n,s,o){const i=n-e,r=o-s,a=1e-6;if(Math.abs(t.y-o)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(o-t.y);if(Math.abs(t.y-s)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-s);const c=Math.abs(t.y-o),h=Math.abs(t.x-n),d=Math.abs(t.y-s),l=Math.abs(t.x-e),u=Math.min(c,h,d,l);return u===c?Math.max(0,Math.min(i,t.x-e)):u===h?i+Math.max(0,Math.min(r,o-t.y)):u===d?i+r+Math.max(0,Math.min(i,n-t.x)):2*i+r+Math.max(0,Math.min(r,t.y-s))}function wr(t,e,n=1e-6){return Math.abs(t-e)<n}function Ar(t,e){const[n,s]=t[0]<t[1]?t:[t[1],t[0]],[o,i]=e[0]<e[1]?e:[e[1],e[0]];return!(wr(n,o)||wr(n,i)||wr(s,o)||wr(s,i))&&(n<o&&o<s&&s<i||o<n&&n<i&&i<s)}var Or=.06393718451067248,zr=.06194817180037216,Dr=6.0761550028071145,Lr=.1315528159128946,Fr=40.00702225250195,Xr=.4316469416682083,Yr=class extends Tr{UNIT_OF_COST="distance";portUsagePenalty=Or;portUsagePenaltySq=zr;crossingPenalty=Dr;crossingPenaltySq=Lr;ripCost=Fr;baseMaxIterations=4e3;additionalMaxIterationsPerConnection=4e3;constructor(t){super({greedyMultiplier:Xr,rippingEnabled:!0,...t}),this.ripCost=t.ripCost??this.ripCost,this.portUsagePenalty=t.portUsagePenalty??this.portUsagePenalty,this.crossingPenalty=t.crossingPenalty??this.crossingPenalty,this.baseMaxIterations=t.baseMaxIterations??this.baseMaxIterations,this.additionalMaxIterationsPerConnection=t.additionalMaxIterationsPerConnection??this.additionalMaxIterationsPerConnection,this.MAX_ITERATIONS=this.baseMaxIterations+t.inputConnections.length*this.additionalMaxIterationsPerConnection,this.populateDistanceToEndMaps()}populateDistanceToEndMaps(){const t=new Set(this.connections.map(t=>t.endRegion));for(const e of t){const t=new Map,n=[];for(t.set(e.regionId,0),n.push({region:e,distance:0});n.length>0;){const{region:e,distance:s}=n.shift();for(const o of e.ports){const i=o.region1===e?o.region2:o.region1;t.has(i.regionId)||(t.set(i.regionId,s+1),n.push({region:i,distance:s+1}))}}for(const n of this.graph.ports){n.distanceToEndMap||(n.distanceToEndMap={});const s=t.get(n.region1.regionId)??1/0,o=t.get(n.region2.regionId)??1/0;n.distanceToEndMap[e.regionId]=Math.min(s,o)}}}estimateCostToEnd(t){const e=this.currentEndRegion.regionId;return t.distanceToEndMap[e]}getPortUsagePenalty(t){const e=t.ripCount??0;return e*this.portUsagePenalty+e*this.portUsagePenaltySq}computeIncreasedRegionCostIfPortsAreUsed(t,e,n){const s=function(t,e,n){const{minX:s,maxX:o,minY:i,maxY:r}=t.d.bounds,a=[Rr(e.d,s,o,i,r),Rr(n.d,s,o,i,r)];let c=0;const h=t.assignments??[];for(const t of h)Ar(a,[Rr(t.regionPort1.d,s,o,i,r),Rr(t.regionPort2.d,s,o,i,r)])&&c++;return c}(t,e,n);return s*this.crossingPenalty+s*this.crossingPenaltySq}getRipsRequiredForPortUsage(t,e,n){const s=function(t,e,n){const{minX:s,maxX:o,minY:i,maxY:r}=t.d.bounds,a=[Rr(e.d,s,o,i,r),Rr(n.d,s,o,i,r)],c=[],h=t.assignments??[];for(const t of h)Ar(a,[Rr(t.regionPort1.d,s,o,i,r),Rr(t.regionPort2.d,s,o,i,r)])&&c.push(t);return c}(t,e,n);return s.filter(t=>t.connection.mutuallyConnectedNetworkId!==this.currentConnection.mutuallyConnectedNetworkId)}routeSolvedHook(t){}routeStartedHook(t){}visualize(){return(t=>{const e=((t,e)=>{const n={arrows:[],circles:[],title:"Jumper Graph",lines:[],points:[],rects:[],texts:[],coordinateSystem:"cartesian"};for(const e of t.regions){const{bounds:t,isPad:s,isThroughJumper:o,isConnectionRegion:i}=e.d,r=(t.minX+t.maxX)/2,a=(t.minY+t.maxY)/2,c=t.maxX-t.minX,h=t.maxY-t.minY;let d;d=i?"rgba(255, 100, 255, 0.6)":o?"rgba(100, 200, 100, 0.5)":s?"rgba(255, 200, 100, 0.5)":"rgba(200, 200, 255, 0.1)",n.rects.push({center:{x:r,y:a},width:c-.1,height:h-.1,fill:d})}if(!e?.hidePortPoints)for(const e of t.ports){const t=e.region1.regionId.split(":").pop()??e.region1.regionId,s=e.region2.regionId.split(":").pop()??e.region2.regionId;n.circles.push({center:{x:e.d.x,y:e.d.y},radius:.05,fill:"rgba(128, 128, 128, 0.5)",label:`${t}-${s}`})}if(!e?.hideRegionPortLines)for(const e of t.ports){const t={x:(e.region1.d.bounds.minX+e.region1.d.bounds.maxX)/2,y:(e.region1.d.bounds.minY+e.region1.d.bounds.maxY)/2},s={x:(e.region2.d.bounds.minX+e.region2.d.bounds.maxX)/2,y:(e.region2.d.bounds.minY+e.region2.d.bounds.maxY)/2};n.lines.push({points:[t,{x:e.d.x,y:e.d.y},s],strokeColor:"rgba(100, 100, 100, 0.3)"})}if(e?.connections&&!e?.hideConnectionLines)for(const t of e.connections){const e=t.startRegion,s=t.endRegion,o={x:(e.d.bounds.minX+e.d.bounds.maxX)/2,y:(e.d.bounds.minY+e.d.bounds.maxY)/2},i={x:(s.d.bounds.minX+s.d.bounds.maxX)/2,y:(s.d.bounds.minY+s.d.bounds.maxY)/2},r=(o.x+i.x)/2,a=(o.y+i.y)/2;n.lines.push({points:[o,i],strokeColor:"rgba(255, 50, 150, 0.8)",strokeDash:"3 3"}),n.points.push({x:r,y:a,color:"rgba(200, 0, 100, 1)",label:t.connectionId})}return n})({regions:t.graph.regions,ports:t.graph.ports},{connections:t.connections,...t.iterations>0?{hideRegionPortLines:!0,hideConnectionLines:!0,hidePortPoints:!0}:{}});if(t.currentConnection&&!t.solved){const n=Er(t.currentConnection.connectionId),s=t.currentConnection.startRegion,o=t.currentConnection.endRegion,i={x:(s.d.bounds.minX+s.d.bounds.maxX)/2,y:(s.d.bounds.minY+s.d.bounds.maxY)/2},r={x:(o.d.bounds.minX+o.d.bounds.maxX)/2,y:(o.d.bounds.minY+o.d.bounds.maxY)/2};e.lines.push({points:[i,r],strokeColor:n,strokeDash:"10 5"}),e.points.push({x:i.x-.1,y:i.y+.1,color:n,label:[t.currentConnection.connectionId,"start"].join("\n")}),e.points.push({x:r.x-.1,y:r.y+.1,color:n,label:[t.currentConnection.connectionId,"end"].join("\n")})}for(const n of t.solvedRoutes){const t=Er(n.connection.connectionId),s=[];for(const t of n.path){const e=t.port;s.push({x:e.d.x,y:e.d.y})}s.length>0&&e.lines.push({points:s,strokeColor:t})}const n=t.candidateQueue.peekMany(10);for(let t=0;t<n.length;t++){const s=n[t],o=s.port,i=0===t;e.points.push({x:o.d.x,y:o.d.y,color:i?"green":"rgba(128, 128, 128, 0.25)",label:[s.port.portId,`g: ${s.g.toFixed(2)}`,`h: ${s.h.toFixed(2)}`,`f: ${s.f.toFixed(2)}`].join("\n")})}const s=n[0];if(!t.solved&&s&&t.currentConnection){const n=Er(t.currentConnection.connectionId),o=[];let i=s;for(;i;){const t=i.port;o.unshift({x:t.d.x,y:t.d.y}),i=i.parent}o.length>1&&e.lines.push({points:o,strokeColor:n})}return e})(this)}},$r=Object.create,kr=Object.defineProperty,Br=Object.getOwnPropertyDescriptor,jr=Object.getOwnPropertyNames,Wr=Object.getPrototypeOf,Hr=Object.prototype.hasOwnProperty,Ur=(t,e)=>function(){return e||(0,t[jr(t)[0]])((e={exports:{}}).exports,e),e.exports},Vr=(t,e,n)=>(n=null!=t?$r(Wr(t)):{},((t,e,n,s)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let o of jr(e))Hr.call(t,o)||o===n||kr(t,o,{get:()=>e[o],enumerable:!(s=Br(e,o))||s.enumerable});return t})(!e&&t&&t.__esModule?n:kr(n,"default",{value:t,enumerable:!0}),t)),Zr=Ur({"node_modules/is-buffer/index.js"(t,e){function n(t){return!!t.constructor&&"function"==typeof t.constructor.isBuffer&&t.constructor.isBuffer(t)}e.exports=function(t){return null!=t&&(n(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&n(t.slice(0,0))}(t)||!!t._isBuffer)}}}),Gr=Ur({"node_modules/kind-of/index.js"(t,e){var n=Zr(),s=Object.prototype.toString;e.exports=function(t){if(void 0===t)return"undefined";if(null===t)return"null";if(!0===t||!1===t||t instanceof Boolean)return"boolean";if("string"==typeof t||t instanceof String)return"string";if("number"==typeof t||t instanceof Number)return"number";if("function"==typeof t||t instanceof Function)return"function";if(void 0!==Array.isArray&&Array.isArray(t))return"array";if(t instanceof RegExp)return"regexp";if(t instanceof Date)return"date";var e=s.call(t);return"[object RegExp]"===e?"regexp":"[object Date]"===e?"date":"[object Arguments]"===e?"arguments":"[object Error]"===e?"error":n(t)?"buffer":"[object Set]"===e?"set":"[object WeakSet]"===e?"weakset":"[object Map]"===e?"map":"[object WeakMap]"===e?"weakmap":"[object Symbol]"===e?"symbol":"[object Int8Array]"===e?"int8array":"[object Uint8Array]"===e?"uint8array":"[object Uint8ClampedArray]"===e?"uint8clampedarray":"[object Int16Array]"===e?"int16array":"[object Uint16Array]"===e?"uint16array":"[object Int32Array]"===e?"int32array":"[object Uint32Array]"===e?"uint32array":"[object Float32Array]"===e?"float32array":"[object Float64Array]"===e?"float64array":"object"}}}),Jr=Ur({"node_modules/rename-keys/index.js"(t,e){!function(){function t(t,e){if("function"!=typeof e)return t;var n={};for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&(n[e(s,t[s])||s]=t[s]);return n}void 0!==e&&e.exports?e.exports=t:"function"==typeof define&&define.amd?define([],function(){return t}):window.rename=t}()}}),qr=Ur({"node_modules/deep-rename-keys/index.js"(t,e){var n=Gr(),s=Jr();e.exports=function t(e,o){var i=n(e);if("object"!==i&&"array"!==i)throw new Error("expected an object");var r=[];for(var a in"object"===i&&(e=s(e,o),r={}),e)if(e.hasOwnProperty(a)){var c=e[a];"object"===n(c)||"array"===n(c)?r[a]=t(c,o):r[a]=c}return r}}}),Kr=Ur({"node_modules/eventemitter3/index.js"(t,e){var n=Object.prototype.hasOwnProperty,s="~";function o(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new o,this._eventsCount=0}Object.create&&(o.prototype=Object.create(null),(new o).__proto__||(s=!1)),r.prototype.eventNames=function(){var t,e,o=[];if(0===this._eventsCount)return o;for(e in t=this._events)n.call(t,e)&&o.push(s?e.slice(1):e);return Object.getOwnPropertySymbols?o.concat(Object.getOwnPropertySymbols(t)):o},r.prototype.listeners=function(t,e){var n=s?s+t:t,o=this._events[n];if(e)return!!o;if(!o)return[];if(o.fn)return[o.fn];for(var i=0,r=o.length,a=new Array(r);i<r;i++)a[i]=o[i].fn;return a},r.prototype.emit=function(t,e,n,o,i,r){var a=s?s+t:t;if(!this._events[a])return!1;var c,h,d=this._events[a],l=arguments.length;if(d.fn){switch(d.once&&this.removeListener(t,d.fn,void 0,!0),l){case 1:return d.fn.call(d.context),!0;case 2:return d.fn.call(d.context,e),!0;case 3:return d.fn.call(d.context,e,n),!0;case 4:return d.fn.call(d.context,e,n,o),!0;case 5:return d.fn.call(d.context,e,n,o,i),!0;case 6:return d.fn.call(d.context,e,n,o,i,r),!0}for(h=1,c=new Array(l-1);h<l;h++)c[h-1]=arguments[h];d.fn.apply(d.context,c)}else{var u,p=d.length;for(h=0;h<p;h++)switch(d[h].once&&this.removeListener(t,d[h].fn,void 0,!0),l){case 1:d[h].fn.call(d[h].context);break;case 2:d[h].fn.call(d[h].context,e);break;case 3:d[h].fn.call(d[h].context,e,n);break;case 4:d[h].fn.call(d[h].context,e,n,o);break;default:if(!c)for(u=1,c=new Array(l-1);u<l;u++)c[u-1]=arguments[u];d[h].fn.apply(d[h].context,c)}}return!0},r.prototype.on=function(t,e,n){var o=new i(e,n||this),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.once=function(t,e,n){var o=new i(e,n||this,!0),r=s?s+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],o]:this._events[r].push(o):(this._events[r]=o,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=s?s+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new o:delete this._events[r],this;var a=this._events[r];if(a.fn)a.fn!==e||i&&!a.once||n&&a.context!==n||(0===--this._eventsCount?this._events=new o:delete this._events[r]);else{for(var c=0,h=[],d=a.length;c<d;c++)(a[c].fn!==e||i&&!a[c].once||n&&a[c].context!==n)&&h.push(a[c]);h.length?this._events[r]=1===h.length?h[0]:h:0===--this._eventsCount?this._events=new o:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=s?s+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new o:delete this._events[e])):(this._events=new o,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=s,r.EventEmitter=r,void 0!==e&&(e.exports=r)}}),Qr=Ur({"node_modules/xml-lexer/dist/lexer.js"(t,e){function n(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var s=Kr(),o=function(){},i={data:"state-data",cdata:"state-cdata",tagBegin:"state-tag-begin",tagName:"state-tag-name",tagEnd:"state-tag-end",attributeNameStart:"state-attribute-name-start",attributeName:"state-attribute-name",attributeNameEnd:"state-attribute-name-end",attributeValueBegin:"state-attribute-value-begin",attributeValue:"state-attribute-value"},r={lt:"action-lt",gt:"action-gt",space:"action-space",equal:"action-equal",quote:"action-quote",slash:"action-slash",char:"action-char",error:"action-error"},a={text:"text",openTag:"open-tag",closeTag:"close-tag",attributeName:"attribute-name",attributeValue:"attribute-value"},c={" ":r.space,"\t":r.space,"\n":r.space,"\r":r.space,"<":r.lt,">":r.gt,'"':r.quote,"'":r.quote,"=":r.equal,"/":r.slash};e.exports={State:i,Action:r,Type:a,create:function(t){var e,h,d,l,u,p,m,f,g,y;t=Object.assign({debug:!1},t);var x=new s,v=i.data,S="",P="",b="",M="",N="",I="",C=function(e,n){if("?"!==P[0]&&"!"!==P[0]){var s={type:e,value:n};t.debug&&console.log("emit:",s),x.emit("data",s)}};x.stateMachine=(n(y={},i.data,(n(e={},r.lt,function(){S.trim()&&C(a.text,S),P="",N=!1,v=i.tagBegin}),n(e,r.char,function(t){S+=t}),e)),n(y,i.cdata,n({},r.char,function(t){"]]>"===(S+=t).substr(-3)&&(C(a.text,S.slice(0,-3)),S="",v=i.data)})),n(y,i.tagBegin,(n(h={},r.space,o),n(h,r.char,function(t){P=t,v=i.tagName}),n(h,r.slash,function(){P="",N=!0}),h)),n(y,i.tagName,(n(d={},r.space,function(){N?v=i.tagEnd:(v=i.attributeNameStart,C(a.openTag,P))}),n(d,r.gt,function(){C(N?a.closeTag:a.openTag,P),S="",v=i.data}),n(d,r.slash,function(){v=i.tagEnd,C(a.openTag,P)}),n(d,r.char,function(t){"![CDATA["===(P+=t)&&(v=i.cdata,S="",P="")}),d)),n(y,i.tagEnd,(n(l={},r.gt,function(){C(a.closeTag,P),S="",v=i.data}),n(l,r.char,o),l)),n(y,i.attributeNameStart,(n(u={},r.char,function(t){b=t,v=i.attributeName}),n(u,r.gt,function(){S="",v=i.data}),n(u,r.space,o),n(u,r.slash,function(){N=!0,v=i.tagEnd}),u)),n(y,i.attributeName,(n(p={},r.space,function(){v=i.attributeNameEnd}),n(p,r.equal,function(){C(a.attributeName,b),v=i.attributeValueBegin}),n(p,r.gt,function(){M="",C(a.attributeName,b),C(a.attributeValue,M),S="",v=i.data}),n(p,r.slash,function(){N=!0,M="",C(a.attributeName,b),C(a.attributeValue,M),v=i.tagEnd}),n(p,r.char,function(t){b+=t}),p)),n(y,i.attributeNameEnd,(n(m={},r.space,o),n(m,r.equal,function(){C(a.attributeName,b),v=i.attributeValueBegin}),n(m,r.gt,function(){M="",C(a.attributeName,b),C(a.attributeValue,M),S="",v=i.data}),n(m,r.char,function(t){M="",C(a.attributeName,b),C(a.attributeValue,M),b=t,v=i.attributeName}),m)),n(y,i.attributeValueBegin,(n(f={},r.space,o),n(f,r.quote,function(t){I=t,M="",v=i.attributeValue}),n(f,r.gt,function(){C(a.attributeValue,M=""),S="",v=i.data}),n(f,r.char,function(t){I="",M=t,v=i.attributeValue}),f)),n(y,i.attributeValue,(n(g={},r.space,function(t){I?M+=t:(C(a.attributeValue,M),v=i.attributeNameStart)}),n(g,r.quote,function(t){I===t?(C(a.attributeValue,M),v=i.attributeNameStart):M+=t}),n(g,r.gt,function(t){I?M+=t:(C(a.attributeValue,M),S="",v=i.data)}),n(g,r.slash,function(t){I?M+=t:(C(a.attributeValue,M),N=!0,v=i.tagEnd)}),n(g,r.char,function(t){M+=t}),g)),y);var _=function(e){t.debug&&console.log(v,e);var n=x.stateMachine[v],s=n[function(t){return c[t]||r.char}(e)]||n[r.error]||n[r.char];s(e)};return x.write=function(t){for(var e=t.length,n=0;n<e;n++)_(t[n])},x}}}}),ta=Ur({"node_modules/xml-reader/dist/reader.js"(t,e){var n=Kr(),s=Qr(),o=s.Type,i={element:"element",text:"text"},r=function(t){return Object.assign({name:"",type:i.element,value:"",parent:null,attributes:{},children:[]},t)},a=function(t){t=Object.assign({stream:!1,parentNodes:!0,doneEvent:"done",tagPrefix:"tag:",emitTopLevelOnly:!1,debug:!1},t);var e=void 0,a=void 0,c=void 0,h=void 0,d=new n,l=function(n){switch(n.type){case o.openTag:if(null===c)(c=a).name=n.value;else{var s=r({name:n.value,parent:c});c.children.push(s),c=s}break;case o.closeTag:var l=c.parent;if(t.parentNodes||(c.parent=null),c.name!==n.value)break;t.stream&&l===a&&(a.children=[],c.parent=null),t.emitTopLevelOnly&&l!==a||(d.emit(t.tagPrefix+c.name,c),d.emit("tag",c.name,c)),c===a&&(e.removeAllListeners("data"),d.emit(t.doneEvent,c),a=null),c=l;break;case o.text:c&&c.children.push(r({type:i.text,value:n.value,parent:t.parentNodes?c:null}));break;case o.attributeName:h=n.value,c.attributes[h]="";break;case o.attributeValue:c.attributes[h]=n.value}};return d.reset=function(){(e=s.create({debug:t.debug})).on("data",l),a=r(),c=null,h="",d.parse=e.write},d.reset(),d};e.exports={parseSync:function(t,e){e=Object.assign({},e,{stream:!1,tagPrefix:":"});var n=a(e),s=void 0;return n.on("done",function(t){s=t}),n.parse(t),s},create:a,NodeType:i}}}),{cos:ea,sin:na,PI:sa}=Math,{tan:oa}=Math,ia=(Vr(qr()),Vr(ta()),class{MAX_ITERATIONS=1e5;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};_setupDone=!1;setup(){this._setupDone||(this._setup(),this._setupDone=!0)}_setup(){}step(){if(this._setupDone||this.setup(),!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.constructor.name} error: ${t}`,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`,this.failed=!0),"computeProgress"in this&&(this.progress=this.computeProgress())}}_step(){}getConstructorParams(){throw new Error("getConstructorParams not implemented")}getOutput(){return null}solve(){const t=Date.now();for(;!this.solved&&!this.failed;)this.step();const e=Date.now();this.timeToSolve=e-t}visualize(){return{lines:[],points:[],rects:[],circles:[]}}tryFinalAcceptance(){}preview(){return{lines:[],points:[],rects:[],circles:[]}}}),ra=t=>t?`hsl(${(t=>{let e=0;for(let n=0;n<t.length;n++)e=779*t.charCodeAt(n)+((e<<5)-e);return e})(t)%360}, 100%, 50%)`:"rgba(0, 0, 0, 0.5)",aa=t=>[[{x:t.minX,y:t.minY},{x:t.maxX,y:t.minY}],[{x:t.maxX,y:t.minY},{x:t.maxX,y:t.maxY}],[{x:t.maxX,y:t.maxY},{x:t.minX,y:t.maxY}],[{x:t.minX,y:t.maxY},{x:t.minX,y:t.minY}]];function ca(t,e){const{minX:n,maxX:s,minY:o,maxY:i}=e,r=s-n,a=i-o,c=1e-6;return Math.abs(t.y-i)<c?t.x-n:Math.abs(t.x-s)<c?r+(i-t.y):Math.abs(t.y-o)<c?r+a+(s-t.x):Math.abs(t.x-n)<c?2*r+a+(t.y-o):0}function ha(t,e){const{minX:n,maxX:s,minY:o,maxY:i}=e,r=1e-6,a=Math.abs(t.y-i)<r,c=Math.abs(t.y-o)<r,h=Math.abs(t.x-s)<r,d=Math.abs(t.x-n)<r;if(a&&h)return{x:-Math.SQRT1_2,y:-Math.SQRT1_2};if(a&&d)return{x:Math.SQRT1_2,y:-Math.SQRT1_2};if(c&&h)return{x:-Math.SQRT1_2,y:Math.SQRT1_2};if(c&&d)return{x:Math.SQRT1_2,y:Math.SQRT1_2};if(a)return{x:0,y:-1};if(c)return{x:0,y:1};if(h)return{x:-1,y:0};if(d)return{x:1,y:0};const l=(o+i)/2,u=(n+s)/2-t.x,p=l-t.y,m=Math.hypot(u,p);return m>0?{x:u/m,y:p/m}:{x:0,y:-1}}function da(t,e,n,s,o,i,r,a,c,h){for(let d=0;d<=h;d++){const l=d/h,u=1-l,p=u*u,m=p*u,f=l*l,g=f*l,y=2*d;c[y]=m*t+3*p*l*n+3*u*f*o+g*r,c[y+1]=m*e+3*p*l*s+3*u*f*i+g*a}}function la(t,e,n,s,o){const i=[];for(let r=0;r<=o;r++){const a=r/o,c=1-a,h=c*c,d=h*c,l=a*a,u=l*a;i.push({x:d*t.x+3*h*a*e.x+3*c*l*n.x+u*s.x,y:d*t.y+3*h*a*e.y+3*c*l*n.y+u*s.y})}return i}function ua(t,e,n,s,o,i){const r=o-n,a=i-s,c=r*r+a*a;if(0===c){const o=t-n,i=e-s;return o*o+i*i}const h=Math.max(0,Math.min(1,((t-n)*r+(e-s)*a)/c)),d=t-(n+h*r),l=e-(s+h*a);return d*d+l*l}function pa(t,e,n,s,o,i,r,a){const c=(r-o)*(e-i)-(a-i)*(t-o),h=(r-o)*(s-i)-(a-i)*(n-o),d=(n-t)*(i-e)-(s-e)*(o-t),l=(n-t)*(a-e)-(s-e)*(r-t);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)?0:Math.min(ua(t,e,o,i,r,a),ua(n,s,o,i,r,a),ua(o,i,t,e,n,s),ua(r,a,t,e,n,s))}function ma(t,e,n,s,o,i,r,a){const c=(r-o)*(e-i)-(a-i)*(t-o),h=(r-o)*(s-i)-(a-i)*(n-o),d=(n-t)*(i-e)-(s-e)*(o-t),l=(n-t)*(a-e)-(s-e)*(r-t);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)}function fa(t,e,n,s,o){const i=t=>(t%o+o)%o,r=i(t),a=i(e),c=i(n),h=i(s),[d,l]=r<a?[r,a]:[a,r];return c>d&&c<l&&h>d&&h<l}function ga(t,e){let n=1/0,s=-1/0,o=1/0,i=-1/0;for(let r=0;r<e;r++){const e=t[2*r],a=t[2*r+1];e<n&&(n=e),e>s&&(s=e),a<o&&(o=a),a>i&&(i=a)}return{minX:n,maxX:s,minY:o,maxY:i}}var ya=class extends ia{constructor(t){super(),this.problem=t;for(const t of this.problem.obstacles)t.outerSegments=aa(t);this.precomputeObstacles()}outputTraces=[];traces=[];optimizationStep=0;maxOptimizationSteps=100;sampledPoints=[];traceBounds=[];obstacleSegments=new Float64Array(0);obstacleNetworkIds=[];numObstacleSegments=0;collisionPairs=[];lastCost=1/0;stagnantSteps=0;effectiveTraceToTraceSpacing=0;getConstructorParams(){return this.problem}precomputeObstacles(){const{obstacles:t}=this.problem;let e=0;for(const n of t)n.outerSegments&&(e+=n.outerSegments.length);this.obstacleSegments=new Float64Array(4*e),this.obstacleNetworkIds=[],this.numObstacleSegments=e;let n=0;for(const e of t)if(e.outerSegments)for(const t of e.outerSegments)this.obstacleSegments[n++]=t[0].x,this.obstacleSegments[n++]=t[0].y,this.obstacleSegments[n++]=t[1].x,this.obstacleSegments[n++]=t[1].y,this.obstacleNetworkIds.push(e.networkId)}initializeTraces(){const{bounds:t,waypointPairs:e}=this.problem,{minX:n,maxX:s,minY:o,maxY:i}=t,r=s-n,a=i-o,c=2*r+2*a,h=function(t){return{x:(t.minX+t.maxX)/2,y:(t.minY+t.maxY)/2}}(t),d=e.map((e,n)=>({pair:e,t1:ca(e.start,t),t2:ca(e.end,t),idx:n})),l=d.map(()=>[]),u=d.map(()=>[]);for(const t of d)for(const e of d)if(t.idx!==e.idx){if(t.pair.networkId&&e.pair.networkId&&t.pair.networkId===e.pair.networkId)continue;fa(e.t1,e.t2,t.t1,t.t2,c)&&(l[t.idx].push(e.idx),u[e.idx].push(t.idx))}const p=l.map(t=>t.length),m=Math.max(...p,1);this.traces=d.map(({pair:e,t1:n,t2:s,idx:o})=>{const i=ha(e.start,t),c=ha(e.end,t),d=Math.hypot(e.end.x-e.start.x,e.end.y-e.start.y),f=p[o]/m,g=(e.start.x+e.end.x)/2,y=(e.start.y+e.end.y)/2,x=d*(.25+.15*(1-Math.hypot(g-h.x,y-h.y)/Math.hypot(r/2,a/2)))*(1-.3*f),v=.05*Math.min(r,a),S=Math.max(v,x),P=Math.max(v,x);return{waypointPair:e,ctrl1:{x:e.start.x+S*i.x,y:e.start.y+S*i.y},ctrl2:{x:e.end.x+P*c.x,y:e.end.y+P*c.y},networkId:e.networkId,t1:n,t2:s,perpDir1:i,perpDir2:c,d1:S,d2:P,containedBy:l[o],contains:u[o]}}),this.sampledPoints=this.traces.map(()=>new Float64Array(12)),this.traceBounds=this.traces.map(()=>({minX:0,maxX:0,minY:0,maxY:0})),this.updateSampledTraces(),this.updateCollisionPairs()}updateSampledTraces(){for(let t=0;t<this.traces.length;t++){const e=this.traces[t];da(e.waypointPair.start.x,e.waypointPair.start.y,e.ctrl1.x,e.ctrl1.y,e.ctrl2.x,e.ctrl2.y,e.waypointPair.end.x,e.waypointPair.end.y,this.sampledPoints[t],5),this.traceBounds[t]=ga(this.sampledPoints[t],6)}}updateSingleTraceSample(t){const e=this.traces[t];da(e.waypointPair.start.x,e.waypointPair.start.y,e.ctrl1.x,e.ctrl1.y,e.ctrl2.x,e.ctrl2.y,e.waypointPair.end.x,e.waypointPair.end.y,this.sampledPoints[t],5),this.traceBounds[t]=ga(this.sampledPoints[t],6)}updateControlPointsFromDistances(t){const e=this.traces[t],{minX:n,maxX:s,minY:o,maxY:i}=this.problem.bounds,r=1e-6;let a=e.waypointPair.start.x+e.d1*e.perpDir1.x,c=e.waypointPair.start.y+e.d1*e.perpDir1.y,h=e.waypointPair.end.x+e.d2*e.perpDir2.x,d=e.waypointPair.end.y+e.d2*e.perpDir2.y;const l=e.waypointPair.start;Math.abs(l.x-n)<r&&(a=Math.max(a,n)),Math.abs(l.x-s)<r&&(a=Math.min(a,s)),Math.abs(l.y-o)<r&&(c=Math.max(c,o)),Math.abs(l.y-i)<r&&(c=Math.min(c,i));const u=e.waypointPair.end;Math.abs(u.x-n)<r&&(h=Math.max(h,n)),Math.abs(u.x-s)<r&&(h=Math.min(h,s)),Math.abs(u.y-o)<r&&(d=Math.max(d,o)),Math.abs(u.y-i)<r&&(d=Math.min(d,i)),a=Math.max(n,Math.min(s,a)),c=Math.max(o,Math.min(i,c)),h=Math.max(n,Math.min(s,h)),d=Math.max(o,Math.min(i,d)),e.ctrl1.x=a,e.ctrl1.y=c,e.ctrl2.x=h,e.ctrl2.y=d}updateCollisionPairs(){const t=this.effectiveTraceToTraceSpacing;this.collisionPairs=[];for(let e=0;e<this.traces.length;e++)for(let n=e+1;n<this.traces.length;n++){const s=this.traces[e],o=this.traces[n];if(s.networkId&&o.networkId&&s.networkId===o.networkId)continue;const i=this.traceBounds[e],r=this.traceBounds[n];i.maxX+t>=r.minX&&r.maxX+t>=i.minX&&i.maxY+t>=r.minY&&r.maxY+t>=i.minY&&this.collisionPairs.push([e,n])}}computeTotalCost(){const{preferredObstacleToTraceSpacing:t}=this.problem,e=this.effectiveTraceToTraceSpacing,n=e**2,s=t**2;let o=0;for(const[t,s]of this.collisionPairs){const i=this.sampledPoints[t],r=this.sampledPoints[s];for(let t=0;t<5;t++){const s=i[2*t],a=i[2*t+1],c=i[2*(t+1)],h=i[2*(t+1)+1];for(let t=0;t<5;t++){const i=pa(s,a,c,h,r[2*t],r[2*t+1],r[2*(t+1)],r[2*(t+1)+1]);if(i<n){o+=(e-Math.sqrt(i))**2,i<1e-18&&(o+=20*n)}}}}for(let e=0;e<this.traces.length;e++){const n=this.traces[e],i=this.sampledPoints[e],r=this.traceBounds[e];for(let e=0;e<this.numObstacleSegments;e++){if(n.networkId&&this.obstacleNetworkIds[e]&&n.networkId===this.obstacleNetworkIds[e])continue;const a=4*e,c=this.obstacleSegments[a],h=this.obstacleSegments[a+1],d=this.obstacleSegments[a+2],l=this.obstacleSegments[a+3],u=Math.min(c,d),p=Math.max(c,d),m=Math.min(h,l),f=Math.max(h,l);if(!(r.maxX+t<u||p+t<r.minX||r.maxY+t<m||f+t<r.minY))for(let e=0;e<5;e++){const n=pa(i[2*e],i[2*e+1],i[2*(e+1)],i[2*(e+1)+1],c,h,d,l);if(n<s){o+=(t-Math.sqrt(n))**2,n<1e-18&&(o+=20*s)}}}}return o}computeCostForTrace(t){const{preferredObstacleToTraceSpacing:e}=this.problem,n=this.effectiveTraceToTraceSpacing,s=n**2,o=e**2,i=this.traces[t],r=this.sampledPoints[t],a=this.traceBounds[t];let c=0;for(let e=0;e<this.traces.length;e++){if(e===t)continue;const o=this.traces[e];if(i.networkId&&o.networkId&&i.networkId===o.networkId)continue;const h=this.traceBounds[e];if(a.maxX+n<h.minX||h.maxX+n<a.minX||a.maxY+n<h.minY||h.maxY+n<a.minY)continue;const d=this.sampledPoints[e];for(let t=0;t<5;t++){const e=r[2*t],o=r[2*t+1],i=r[2*(t+1)],a=r[2*(t+1)+1];for(let t=0;t<5;t++){const r=pa(e,o,i,a,d[2*t],d[2*t+1],d[2*(t+1)],d[2*(t+1)+1]);if(r<s){c+=(n-Math.sqrt(r))**2,r<1e-18&&(c+=20*s)}}}}for(let t=0;t<this.numObstacleSegments;t++){if(i.networkId&&this.obstacleNetworkIds[t]&&i.networkId===this.obstacleNetworkIds[t])continue;const n=4*t,s=this.obstacleSegments[n],h=this.obstacleSegments[n+1],d=this.obstacleSegments[n+2],l=this.obstacleSegments[n+3],u=Math.min(s,d),p=Math.max(s,d),m=Math.min(h,l),f=Math.max(h,l);if(!(a.maxX+e<u||p+e<a.minX||a.maxY+e<m||f+e<a.minY))for(let t=0;t<5;t++){const n=pa(r[2*t],r[2*t+1],r[2*(t+1)],r[2*(t+1)+1],s,h,d,l);if(n<o){c+=(e-Math.sqrt(n))**2,n<1e-18&&(c+=20*o)}}}return c}tracesIntersect(t,e){const n=this.traces[t],s=this.traces[e],o=15,i=new Float64Array(32),r=new Float64Array(32);da(n.waypointPair.start.x,n.waypointPair.start.y,n.ctrl1.x,n.ctrl1.y,n.ctrl2.x,n.ctrl2.y,n.waypointPair.end.x,n.waypointPair.end.y,i,o),da(s.waypointPair.start.x,s.waypointPair.start.y,s.ctrl1.x,s.ctrl1.y,s.ctrl2.x,s.ctrl2.y,s.waypointPair.end.x,s.waypointPair.end.y,r,o);for(let t=0;t<o;t++){const e=i[2*t],n=i[2*t+1],s=i[2*(t+1)],a=i[2*(t+1)+1];for(let t=0;t<o;t++){if(ma(e,n,s,a,r[2*t],r[2*t+1],r[2*(t+1)],r[2*(t+1)+1]))return!0}}return!1}findIntersectingPairs(){const t=[];for(let e=0;e<this.traces.length;e++)for(let n=e+1;n<this.traces.length;n++){const s=this.traces[e],o=this.traces[n];if(s.networkId&&o.networkId&&s.networkId===o.networkId)continue;const i=this.traceBounds[e],r=this.traceBounds[n];i.maxX<r.minX||r.maxX<i.minX||i.maxY<r.minY||r.maxY<i.minY||this.tracesIntersect(e,n)&&t.push([e,n])}return t}resolveIntersections(){const{bounds:t,preferredTraceToTraceSpacing:e}=this.problem,{minX:n,maxX:s,minY:o,maxY:i}=t,r=Math.min(s-n,i-o),a=.02*r,c=1.5*r,h=this.findIntersectingPairs();if(0===h.length)return 0;let d=0;for(const[t,n]of h){const s=this.traces[t],o=this.traces[n];if(!this.tracesIntersect(t,n))continue;let i,r;if(s.containedBy.includes(n))i=n,r=t;else if(o.containedBy.includes(t))i=t,r=n;else{(s.d1+s.d2)/2<(o.d1+o.d2)/2?(i=t,r=n):(i=n,r=t)}const h=this.traces[i],l=this.traces[r],u=h.d1,p=h.d2,m=l.d1,f=l.d2,g=2*e,y=[{innerMult:1,outerMult:0},{innerMult:0,outerMult:1},{innerMult:.5,outerMult:.5},{innerMult:2,outerMult:0},{innerMult:1,outerMult:1},{innerMult:3,outerMult:0},{innerMult:2,outerMult:1},{innerMult:4,outerMult:0}];let x=this.computeTotalCost(),v=null;for(const t of y)if(h.d1=u,h.d2=p,l.d1=m,l.d2=f,l.d1=Math.min(c,m+g*t.innerMult),l.d2=Math.min(c,f+g*t.innerMult),h.d1=Math.max(a,u-g*t.outerMult),h.d2=Math.max(a,p-g*t.outerMult),this.updateControlPointsFromDistances(r),this.updateControlPointsFromDistances(i),this.updateSingleTraceSample(r),this.updateSingleTraceSample(i),!this.tracesIntersect(i,r)){const e=this.computeTotalCost();(null===v||e<x)&&(x=e,v=t)}v?(l.d1=Math.min(c,m+g*v.innerMult),l.d2=Math.min(c,f+g*v.innerMult),h.d1=Math.max(a,u-g*v.outerMult),h.d2=Math.max(a,p-g*v.outerMult),this.updateControlPointsFromDistances(r),this.updateControlPointsFromDistances(i),this.updateSingleTraceSample(r),this.updateSingleTraceSample(i),d++):(h.d1=u,h.d2=p,l.d1=m,l.d2=f,this.updateControlPointsFromDistances(i),this.updateControlPointsFromDistances(r),this.updateSingleTraceSample(i),this.updateSingleTraceSample(r))}return d}optimizeStep(){const{bounds:t}=this.problem,{minX:e,maxX:n,minY:s,maxY:o}=t,i=Math.min(n-e,o-s),r=this.effectiveTraceToTraceSpacing,a=4*(1-this.optimizationStep/this.maxOptimizationSteps)+.5,c=.02*i,h=1.5*i,d=[];for(let t=0;t<this.traces.length;t++)d.push({idx:t,cost:this.computeCostForTrace(t)});d.sort((t,e)=>e.cost-t.cost);for(const{idx:t,cost:e}of d){if(0===e)continue;const n=this.traces[t],s=e>100?2:1,o=[a*s,1.5*a*s,.5*a];for(const s of o){const o=e>100?[s,-s,2*s,2*-s,3*s,3*-s,2*r,2*-r]:[s,-s,2*s,2*-s];let i=this.computeCostForTrace(t),a=n.d1,d=n.d2;const l=n.d1,u=n.d2;for(const e of o){n.d1=Math.max(c,Math.min(h,l+e)),this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t);const s=this.computeCostForTrace(t);s<i&&(i=s,a=n.d1,d=u),n.d1=l,this.updateControlPointsFromDistances(t),n.d2=Math.max(c,Math.min(h,u+e)),this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t);const o=this.computeCostForTrace(t);o<i&&(i=o,a=l,d=n.d2),n.d2=u,this.updateControlPointsFromDistances(t),n.d1=Math.max(c,Math.min(h,l+e)),n.d2=Math.max(c,Math.min(h,u+e)),this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t);const r=this.computeCostForTrace(t);r<i&&(i=r,a=n.d1,d=n.d2),n.d1=l,n.d2=u,this.updateControlPointsFromDistances(t),n.d1=Math.max(c,Math.min(h,l+e)),n.d2=Math.max(c,Math.min(h,u-e)),this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t);const p=this.computeCostForTrace(t);p<i&&(i=p,a=n.d1,d=n.d2),n.d1=l,n.d2=u,this.updateControlPointsFromDistances(t)}if(n.d1=a,n.d2=d,this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t),i<.9*e)break}}this.optimizationStep%10==0&&this.updateCollisionPairs()}buildOutputTraces(){this.outputTraces=this.traces.map(t=>({waypointPair:t.waypointPair,points:la(t.waypointPair.start,t.ctrl1,t.ctrl2,t.waypointPair.end,20),networkId:t.networkId}))}_step(){if(0===this.traces.length&&(this.effectiveTraceToTraceSpacing=3*this.problem.preferredTraceToTraceSpacing,this.initializeTraces(),this.lastCost=this.computeTotalCost(),this.stagnantSteps=0),this.optimizationStep<this.maxOptimizationSteps){const t=3,e=t+(1-t)*(this.optimizationStep/this.maxOptimizationSteps);if(this.effectiveTraceToTraceSpacing=this.problem.preferredTraceToTraceSpacing*e,this.optimizeStep(),this.optimizationStep++,this.optimizationStep%10==0){this.resolveIntersections()>0&&this.updateCollisionPairs()}const n=this.computeTotalCost();if(0===n)this.optimizationStep=this.maxOptimizationSteps;else if(n>=.99*this.lastCost){if(this.stagnantSteps++,this.stagnantSteps>10){this.resolveIntersections()>0?(this.updateCollisionPairs(),this.stagnantSteps=0):this.stagnantSteps>15&&(this.optimizationStep=this.maxOptimizationSteps)}}else this.stagnantSteps=0;this.lastCost=n}this.optimizationStep>=this.maxOptimizationSteps&&(this.resolveIntersections(),this.buildOutputTraces(),this.solved=!0)}visualize(){return this.traces.length>0&&this.buildOutputTraces(),((t,e=[])=>{const n={arrows:[],circles:[],lines:[],rects:[],coordinateSystem:"cartesian",points:[],texts:[],title:"Curvy Trace Problem"};n.lines.push({points:[{x:t.bounds.minX,y:t.bounds.minY},{x:t.bounds.maxX,y:t.bounds.minY},{x:t.bounds.maxX,y:t.bounds.maxY},{x:t.bounds.minX,y:t.bounds.maxY},{x:t.bounds.minX,y:t.bounds.minY}],strokeColor:"rgba(0, 0, 0, 0.1)"});for(const e of t.waypointPairs)n.points.push({...e.start,label:`start ${e.networkId??""}`,color:ra(e.networkId)}),n.points.push({...e.end,label:`end ${e.networkId??""}`,color:ra(e.networkId)});for(const e of t.obstacles)n.rects.push({center:e.center,width:e.maxX-e.minX,height:e.maxY-e.minY,fill:"rgba(128, 128, 128, 0.3)",stroke:"rgba(128, 128, 128, 0.8)",label:`netId: ${e.networkId}`});for(const t of e)n.lines.push({points:t.points,strokeColor:ra(t.networkId)});return n})(this.problem,this.outputTraces)}},xa=class extends y{constructorParams;nodeWithPortPoints;colorMap;traceWidth;hyperParameters;jumperGraphSolver=null;xyConnections=[];graphBounds=null;jumperLocations=[];solvedRoutes=[];jumpers=[];phase="jumperGraph";curvySolvers=[];currentCurvySolverIndex=0;routeInfos=[];regionCurvedPaths=new Map;constructor(t){super(),this.constructorParams=t,this.nodeWithPortPoints=t.nodeWithPortPoints,this.colorMap=t.colorMap??{},this.traceWidth=t.traceWidth??.15,this.hyperParameters=t.hyperParameters??{},this.MAX_ITERATIONS=1e6,0===Object.keys(this.colorMap).length&&(this.colorMap=this._buildColorMap())}getConstructorParams(){return this.constructorParams}_buildColorMap(){const t=["#e6194b","#3cb44b","#ffe119","#4363d8","#f58231","#911eb4","#46f0f0","#f032e6","#bcf60c","#fabebe"],e={},n=new Set;for(const t of this.nodeWithPortPoints.portPoints)n.add(t.connectionName);let s=0;for(const o of Array.from(n))e[o]=t[s%t.length],s++;return e}_getPatternConfig(){return{cols:this.hyperParameters.COLS??1,rows:this.hyperParameters.ROWS??1}}_initializeGraph(){const t=this.nodeWithPortPoints,e=this._getPatternConfig(),n=this.hyperParameters.ORIENTATION??"vertical",s={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};this.graphBounds=s;const o=Mr({cols:e.cols,rows:e.rows,marginX:Math.max(1.2,.3*e.cols),marginY:Math.max(1.2,.3*e.rows),outerPaddingX:.4,outerPaddingY:.4,parallelTracesUnderJumperCount:3,innerColChannelPointCount:3,innerRowChannelPointCount:3,outerChannelXPointCount:3,outerChannelYPointCount:3,regionsBetweenPads:!0,orientation:n,bounds:s});if(o.regions.length>0){let t=1/0,e=-1/0,n=1/0,i=-1/0;for(const s of o.regions){if(!s.d?.isPad)continue;const o=s.d?.bounds;o&&(t=Math.min(t,o.minX),e=Math.max(e,o.maxX),n=Math.min(n,o.minY),i=Math.max(i,o.maxY))}const r=1;if(t-r<s.minX||e+r>s.maxX||n-r<s.minY||i+r>s.maxY)return this.error=`baseGraph bounds (${t.toFixed(2)}, ${n.toFixed(2)}, ${e.toFixed(2)}, ${i.toFixed(2)}) exceed node bounds (${s.minX.toFixed(2)}, ${s.minY.toFixed(2)}, ${s.maxX.toFixed(2)}, ${s.maxY.toFixed(2)})`,this.failed=!0,!1}this.jumperLocations=o.jumperLocations?.map(t=>({center:t.center,orientation:t.orientation,padRegions:t.padRegions}))??[];const i=new Map;for(const e of t.portPoints){const t=i.get(e.connectionName);t?t.points.push(e):i.set(e.connectionName,{points:[e],rootConnectionName:e.rootConnectionName})}this.xyConnections=[];for(const[t,e]of Array.from(i.entries()))e.points.length<2||this.xyConnections.push({start:{x:e.points[0].x,y:e.points[0].y},end:{x:e.points[1].x,y:e.points[1].y},connectionId:t});if(0===this.xyConnections.length)return this.solved=!0,!0;const r=((t,e)=>{const n=[...t.regions],s=[...t.ports],o=[],i=mr(t.regions);for(const r of e){const{start:e,end:a,connectionId:c}=r,h=Ir(`conn:${c}:start`,e.x,e.y);n.push(h);const d=Ir(`conn:${c}:end`,a.x,a.y);n.push(d);const l=Cr(e.x,e.y,t.regions,i);if(l){const t=Nr(`conn:${c}:start-port`,h,l.region,l.portPosition);s.push(t)}const u=Cr(a.x,a.y,t.regions,i);if(u){const t=Nr(`conn:${c}:end-port`,d,u.region,u.portPosition);s.push(t)}const p={connectionId:c,mutuallyConnectedNetworkId:c,startRegion:h,endRegion:d};o.push(p)}return{regions:n,ports:s,connections:o}})(o,this.xyConnections);return this.jumperGraphSolver=new Yr({inputGraph:{regions:r.regions,ports:r.ports},inputConnections:r.connections}),this.jumperGraphSolver.MAX_ITERATIONS*=3,!0}_step(){switch(this.phase){case"jumperGraph":this._stepJumperGraph();break;case"curvyTrace":this._stepCurvyTrace();break;case"done":this.solved=!0}}_stepJumperGraph(){if(!this.jumperGraphSolver){if(this._initializeGraph(),this.solved)return;if(!this.jumperGraphSolver)return void(this.failed=!0)}this.activeSubSolver=this.jumperGraphSolver,this.jumperGraphSolver.step(),this.jumperGraphSolver.solved?(this._initializeCurvyTraceSolvers(),this.curvySolvers.length>0?this.phase="curvyTrace":(this._finalizeCurvyTraceResults(),this.phase="done",this.solved=!0)):this.jumperGraphSolver.failed&&(this.error=this.jumperGraphSolver.error,this.failed=!0)}_stepCurvyTrace(){if(this.currentCurvySolverIndex>=this.curvySolvers.length)return this._finalizeCurvyTraceResults(),this.phase="done",void(this.solved=!0);const t=this.curvySolvers[this.currentCurvySolverIndex],e=t.solver;if(this.activeSubSolver=e,e.step(),e.solved){const n=t.regionId;this.regionCurvedPaths.has(n)||this.regionCurvedPaths.set(n,new Map);for(const t of e.outputTraces){const e=t.networkId??"",s=t.points.map(t=>({x:t.x,y:t.y})),o={path:s,start:s[0]??{x:0,y:0},end:s[s.length-1]??{x:0,y:0}};this.regionCurvedPaths.get(n).has(e)||this.regionCurvedPaths.get(n).set(e,[]),this.regionCurvedPaths.get(n).get(e).push(o)}this.currentCurvySolverIndex++}else e.failed&&this.currentCurvySolverIndex++}_initializeCurvyTraceSolvers(){if(!this.jumperGraphSolver)return;const t=new Set,e=[];for(const t of this.jumperLocations)for(const n of t.padRegions){const t=n.d.bounds,s=n.d.center;e.push({minX:t.minX,minY:t.minY,maxX:t.maxX,maxY:t.maxY,center:{x:s.x,y:s.y},networkIds:[]})}const n=new Map;for(let e=0;e<this.jumperGraphSolver.solvedRoutes.length;e++){const s=this.jumperGraphSolver.solvedRoutes[e],o=s.connection.connectionId,i=this.nodeWithPortPoints.portPoints.find(t=>t.connectionName===o)?.rootConnectionName,r=[],a=[];let c=null,h=null;for(let d=0;d<s.path.length;d++){const l=s.path[d],u=l.port,p=l.lastRegion,m=u.region1,f=u.region2;let g;if(p)m&&m.regionId!==p.regionId?g=m:f&&f.regionId!==p.regionId&&(g=f);else{const t=s.path[d+1],e=t?.lastRegion;if(e&&(m&&m.regionId===e.regionId?g=m:f&&f.regionId===e.regionId&&(g=f)),!g){const t=t=>t?.regionId?.startsWith("conn:");g=!m||t(m)||m.d?.isPad||m.d?.isThroughJumper?!f||t(f)||f.d?.isPad||f.d?.isThroughJumper?!m||m.d?.isPad||m.d?.isThroughJumper?(!f||f.d?.isPad||f.d?.isThroughJumper)&&m||f:m:f:m}}if(g&&(!c||g.regionId!==c.regionId)){if(c&&h){a.push({regionId:c.regionId,region:c,entryPort:h,exitPort:u});const t=c.regionId;n.has(t)||n.set(t,[]),n.get(t).push({regionId:c.regionId,region:c,routeIndex:e,connectionName:o,rootConnectionName:i,entryPort:h,exitPort:u})}c=g,h=u}if(p?.d?.isThroughJumper&&!t.has(p.regionId)){t.add(p.regionId);const e=p.d.bounds,n=p.d.center;e.maxX-e.minX>e.maxY-e.minY?r.push({route_type:"jumper",start:{x:e.minX,y:n.y},end:{x:e.maxX,y:n.y},footprint:"1206x4_pair"}):r.push({route_type:"jumper",start:{x:n.x,y:e.minY},end:{x:n.x,y:e.maxY},footprint:"1206x4_pair"})}}if(c&&h){const t=s.path[s.path.length-1];a.push({regionId:c.regionId,region:c,entryPort:h,exitPort:t?.port||null})}this.routeInfos.push({connectionId:o,rootConnectionName:i,jumpers:r,traversals:a})}for(let t=0;t<this.routeInfos.length;t++){const n=this.routeInfos[t],s=n.rootConnectionName??n.connectionId;for(const t of n.jumpers){const n=[t.start,t.end];for(const t of n)for(const n of e){const e=Math.abs(n.center.x-t.x),o=Math.abs(n.center.y-t.y);e<.1&&o<.1&&(n.networkIds.includes(s)||n.networkIds.push(s))}}}for(const[t,s]of n){if(0===s.length)continue;const n=s[0].region;if(n.d.isPad||n.d.isThroughJumper)continue;const o=n.d.bounds,i=[];for(const t of s)i.push({start:{x:t.entryPort.d.x,y:t.entryPort.d.y},end:{x:t.exitPort.d.x,y:t.exitPort.d.y},networkId:t.rootConnectionName??t.connectionName});const r=.01,a=e.filter(t=>t.minX<=o.maxX+r&&t.maxX>=o.minX-r&&t.minY<=o.maxY+r&&t.maxY>=o.minY-r).map(t=>{const e=s.map(t=>t.rootConnectionName??t.connectionName),n=t.networkIds.find(t=>e.includes(t));return{minX:t.minX,minY:t.minY,maxX:t.maxX,maxY:t.maxY,center:t.center,networkId:n}}),c={bounds:o,waypointPairs:i,obstacles:a,preferredTraceToTraceSpacing:2*this.traceWidth,preferredObstacleToTraceSpacing:2*this.traceWidth},h=new ya(c);this.curvySolvers.push({solver:h,regionId:t,traversals:s.map(t=>({routeIndex:t.routeIndex,connectionName:t.connectionName,rootConnectionName:t.rootConnectionName}))})}}_finalizeCurvyTraceResults(){const t=(t,e)=>Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2);for(let e=0;e<this.routeInfos.length;e++){const n=this.routeInfos[e],s=[];for(const e of n.traversals){const o=e.regionId,i=n.rootConnectionName??n.connectionId,r=this.regionCurvedPaths.get(o)?.get(i);let a=null;if(r&&r.length>0){const n={x:e.entryPort.d.x,y:e.entryPort.d.y},s=e.exitPort?{x:e.exitPort.d.x,y:e.exitPort.d.y}:null;let o=null,i=1/0;for(const e of r){const r=t(e.start,n)+(s?t(e.end,s):0);r<i&&(i=r,o=e)}o&&i<.5&&(a=o.path)}if(a&&a.length>0){for(let t=s.length>0?1:0;t<a.length;t++)s.push({x:a[t].x,y:a[t].y,z:0})}else 0===s.length&&s.push({x:e.entryPort.d.x,y:e.entryPort.d.y,z:0}),e.exitPort&&s.push({x:e.exitPort.d.x,y:e.exitPort.d.y,z:0})}this.solvedRoutes.push({connectionName:n.connectionId,rootConnectionName:n.rootConnectionName,traceThickness:this.traceWidth,route:s,jumpers:n.jumpers})}}getOutput(){return this.solvedRoutes}getOutputJumpers(){if(this.jumpers.length>0)return this.jumpers;const t=new Map;for(const e of this.solvedRoutes)for(const n of e.jumpers){const s=[n.start,n.end];for(const n of s){const s=`${n.x.toFixed(3)},${n.y.toFixed(3)}`,o=t.get(s)??[];e.rootConnectionName&&!o.includes(e.rootConnectionName)&&o.push(e.rootConnectionName),o.includes(e.connectionName)||o.push(e.connectionName),t.set(s,o)}}const e=Ze["1206x4_pair"];for(const n of this.jumperLocations){const s="horizontal"===n.orientation,o=n.padRegions.map(e=>{const n=e.d.bounds,s=e.d.center,o=n.maxX-n.minX,i=n.maxY-n.minY,r=`${s.x.toFixed(3)},${s.y.toFixed(3)}`;return{type:"rect",center:s,width:o,height:i,layers:["top"],connectedTo:[...t.get(r)??[]]}}),i={jumper_footprint:"1206x4",center:n.center,orientation:n.orientation,width:s?e.length:e.width,height:s?e.width:e.length,pads:o};this.jumpers.push(i)}return this.jumpers=this.jumpers.filter(t=>t.pads.some(t=>t.connectedTo.length>0)),this.jumpers}visualize(){if(this.jumperGraphSolver&&!this.solved)return this.jumperGraphSolver.visualize();const t={lines:[],points:[],rects:[],circles:[]},e=this.nodeWithPortPoints,n={minX:e.center.x-e.width/2,maxX:e.center.x+e.width/2,minY:e.center.y-e.height/2,maxY:e.center.y+e.height/2};t.lines.push({points:[{x:n.minX,y:n.minY},{x:n.maxX,y:n.minY},{x:n.maxX,y:n.maxY},{x:n.minX,y:n.maxY},{x:n.minX,y:n.minY}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"});for(const n of e.portPoints)t.points.push({x:n.x,y:n.y,label:n.connectionName,color:this.colorMap[n.connectionName]??"blue"});for(const e of this.solvedRoutes){const n=this.colorMap[e.connectionName]??"blue";for(let s=0;s<e.route.length-1;s++){const o=e.route[s],i=e.route[s+1];t.lines.push({points:[o,i],strokeColor:it(n,.2),strokeWidth:e.traceThickness,layer:"route-layer-0"})}for(const s of e.jumpers)this._drawJumperPads(t,s,it(n,.5))}return t}_drawJumperPads(t,e,n){const s=Ze[e.footprint],o=e.end.x-e.start.x,i=e.end.y-e.start.y,r=Math.abs(o)>Math.abs(i),a=r?s.padLength:s.padWidth,c=r?s.padWidth:s.padLength;t.rects.push({center:{x:e.start.x,y:e.start.y},width:a,height:c,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.rects.push({center:{x:e.end.x,y:e.end.y},width:a,height:c,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*s.padWidth,layer:"jumper-body"})}},va=class extends Zt{constructorParams;nodeWithPortPoints;colorMap;traceWidth;connMap;baseHyperParameters;solvedRoutes=[];jumpers=[];constructor(t){super(),this.constructorParams=t,this.nodeWithPortPoints=t.nodeWithPortPoints,this.colorMap=t.colorMap??{},this.traceWidth=t.traceWidth??.15,this.connMap=t.connMap,this.baseHyperParameters=t.hyperParameters??{},this.MAX_ITERATIONS=1e6,this.GREEDY_MULTIPLIER=1,this.MIN_SUBSTEPS=1e3}getConstructorParams(){return this.constructorParams}getHyperParameterDefs(){return[{name:"cols",possibleValues:[{COLS:1},{COLS:2},{COLS:3},{COLS:4},{COLS:6},{COLS:8}]},{name:"rows",possibleValues:[{ROWS:1},{ROWS:2},{ROWS:3},{ROWS:4}]},{name:"orientation",possibleValues:[{ORIENTATION:"vertical"},{ORIENTATION:"horizontal"}]}]}getCombinationDefs(){return[["cols","rows","orientation"]]}generateSolver(t){return new xa({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,traceWidth:this.traceWidth,hyperParameters:{COLS:t.COLS,ROWS:t.ROWS,ORIENTATION:t.ORIENTATION}})}computeG(t){const e=t.hyperParameters.COLS*t.hyperParameters.ROWS;return t.iterations/1e4+.25*e}computeH(t){return 1-(t.progress||0)}onSolve(t){this.solvedRoutes=t.solver.solvedRoutes,this.jumpers=t.solver.getOutputJumpers()}getOutput(){return this.solvedRoutes}getOutputJumpers(){return this.jumpers}visualize(){return this.winningSolver?this.winningSolver.visualize():super.visualize()}},Sa=class extends y{nodeWithPortPoints;colorMap;traceWidth;viaDiameter;adjacentObstacles;routes=[];curvyTraceSolver;phase="initializing";constructor(t){super(),this.nodeWithPortPoints=t.nodeWithPortPoints,this.colorMap=t.colorMap??{},this.traceWidth=t.traceWidth??.15,this.viaDiameter=t.viaDiameter??.6,this.adjacentObstacles=t.adjacentObstacles??[],this.MAX_ITERATIONS=1e3}_step(){switch(this.phase){case"initializing":this._initializeCurvySolver();break;case"solving":this._stepCurvySolver();break;case"done":this.solved=!0}}_initializeCurvySolver(){const t=this.nodeWithPortPoints,e={minX:t.center.x-t.width/2,minY:t.center.y-t.height/2,maxX:t.center.x+t.width/2,maxY:t.center.y+t.height/2},n=new Map;for(const e of t.portPoints)n.has(e.connectionName)||n.set(e.connectionName,[]),n.get(e.connectionName).push(e);const s=[];for(const[t,e]of n){if(e.length<2)continue;const n=e[0],o=e[e.length-1];s.push({start:{x:n.x,y:n.y},end:{x:o.x,y:o.y},networkId:t})}if(0===s.length)return void(this.phase="done");const o={bounds:e,waypointPairs:s,obstacles:this.adjacentObstacles.map(t=>({minX:t.minX,minY:t.minY,maxX:t.maxX,maxY:t.maxY,center:{x:(t.minX+t.maxX)/2,y:(t.minY+t.maxY)/2},networkId:t.networkId})),preferredTraceToTraceSpacing:2*this.traceWidth,preferredObstacleToTraceSpacing:2*this.traceWidth};this.curvyTraceSolver=new ya(o),this.phase="solving"}_stepCurvySolver(){this.curvyTraceSolver?(this.activeSubSolver=this.curvyTraceSolver,this.curvyTraceSolver.step(),this.curvyTraceSolver.solved?(this._convertOutputTraces(),this.phase="done"):this.curvyTraceSolver.failed&&(this.error=this.curvyTraceSolver.error,this.failed=!0)):this.phase="done"}_convertOutputTraces(){if(!this.curvyTraceSolver)return;const t=this.nodeWithPortPoints,e=new Map;for(const n of t.portPoints){const t=n.connectionName;e.has(t)||e.set(t,{connectionName:n.connectionName,rootConnectionName:n.rootConnectionName,z:n.z})}for(const t of this.curvyTraceSolver.outputTraces){const n=t.networkId??"",s=e.get(n);if(!s)continue;const o={connectionName:s.connectionName,rootConnectionName:s.rootConnectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:t.points.map(t=>({x:t.x,y:t.y,z:s.z})),vias:[]};this.routes.push(o)}}getConstructorParams(){return{nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,traceWidth:this.traceWidth,viaDiameter:this.viaDiameter,adjacentObstacles:this.adjacentObstacles}}visualize(){const t={lines:[],points:[],rects:[],circles:[]},e=this.nodeWithPortPoints;t.rects.push({center:e.center,width:e.width,height:e.height,fill:"rgba(0, 200, 0, 0.1)",stroke:"rgba(0, 200, 0, 0.5)",label:e.capacityMeshNodeId});for(const e of this.adjacentObstacles)t.rects.push({center:{x:(e.minX+e.maxX)/2,y:(e.minY+e.maxY)/2},width:e.maxX-e.minX,height:e.maxY-e.minY,fill:"rgba(255, 0, 0, 0.1)",stroke:"rgba(255, 0, 0, 0.3)",label:`obstacle: ${e.networkId??""}`});if(this.curvyTraceSolver){const e=this.curvyTraceSolver.visualize();e.lines&&t.lines.push(...e.lines),e.points&&t.points.push(...e.points),e.rects&&t.rects.push(...e.rects),e.circles&&t.circles.push(...e.circles)}for(const e of this.routes){const n=this.colorMap[e.connectionName]??"gray";t.lines.push({points:e.route.map(t=>({x:t.x,y:t.y})),strokeColor:n,strokeWidth:this.traceWidth,label:e.connectionName})}for(const n of e.portPoints){const e=this.colorMap[n.connectionName]??"gray";t.points.push({x:n.x,y:n.y,color:e,label:n.connectionName})}return t}};function Pa(t){return{connectionName:t.connectionName,rootConnectionName:t.rootConnectionName,traceThickness:t.traceThickness,viaDiameter:0,route:t.route,vias:[],jumpers:t.jumpers}}var ba=class extends y{allNodes;nodeAnalyses;routes;colorMap;traceWidth;viaDiameter;connMap;hyperParameters;capacityMeshNodes;capacityMeshEdges;capacityMeshNodeMap;nodeAdjacencyMap;nodesWithoutCrossings;nodesWithCrossings;curvyIntraNodeSolvers;currentCurvySolverIndex;jumperSolvers;currentJumperSolverIndex;phase;jumpers=[];constructor({nodePortPoints:t,colorMap:e,traceWidth:n=.15,viaDiameter:s=.6,connMap:o,hyperParameters:i,capacityMeshNodes:r=[],capacityMeshEdges:a=[]}){super(),this.allNodes=[...t],this.colorMap=e??{},this.routes=[],this.traceWidth=n,this.viaDiameter=s,this.connMap=o,this.hyperParameters=i,this.capacityMeshNodes=r,this.capacityMeshEdges=a,this.capacityMeshNodeMap=new Map(r.map(t=>[t.capacityMeshNodeId,t])),this.nodeAdjacencyMap=this._buildNodeAdjacencyMap(),this.nodesWithoutCrossings=[],this.nodesWithCrossings=[],this.nodeAnalyses=[],this.curvyIntraNodeSolvers=[],this.currentCurvySolverIndex=0,this.jumperSolvers=[],this.currentJumperSolverIndex=0,this.phase="analyzing",this._analyzeNodes();const c=1e3*this.nodesWithoutCrossings.length,h=1e5*this.nodesWithCrossings.length;this.MAX_ITERATIONS=c+h+100}_buildNodeAdjacencyMap(){const t=new Map;for(const e of this.capacityMeshEdges){const[n,s]=e.nodeIds;t.has(n)||t.set(n,new Set),t.has(s)||t.set(s,new Set),t.get(n).add(s),t.get(s).add(n)}return t}_analyzeNodes(){for(const t of this.allNodes){const e=Ro(t),n={node:t,hasCrossings:e.numSameLayerCrossings>0,numSameLayerCrossings:e.numSameLayerCrossings};this.nodeAnalyses.push(n),e.numSameLayerCrossings>0?this.nodesWithCrossings.push(t):this.nodesWithoutCrossings.push(t)}this.nodesWithoutCrossings.length>0?(this.phase="curvy",this._initializeCurvySolvers()):this.nodesWithCrossings.length>0?(this.phase="jumpers",this._initializeJumperSolvers()):this.phase="done"}_step(){switch(this.phase){case"analyzing":this.nodesWithoutCrossings.length>0?(this.phase="curvy",this._initializeCurvySolvers()):this.nodesWithCrossings.length>0?(this.phase="jumpers",this._initializeJumperSolvers()):this.phase="done";break;case"curvy":this._stepCurvySolvers();break;case"jumpers":this._stepJumperSolvers();break;case"done":this.solved=!0}}_getAdjacentObstacles(t){const e=[],n=this.nodeAdjacencyMap.get(t.capacityMeshNodeId);if(!n||0===n.size)return e;const s=new Map(this.allNodes.map(t=>[t.capacityMeshNodeId,t]));for(const t of n){const n=this.capacityMeshNodeMap.get(t);if(!n)continue;if(!n._containsObstacle&&!n._containsTarget)continue;const o=n.center.x-n.width/2,i=n.center.y-n.height/2,r=n.center.x+n.width/2,a=n.center.y+n.height/2;let c;if(n._containsTarget)if(n._targetConnectionName)c=n._targetConnectionName;else{const e=s.get(t);e&&e.portPoints.length>0&&(c=e.portPoints[0].rootConnectionName??e.portPoints[0].connectionName)}e.push({minX:o,minY:i,maxX:r,maxY:a,networkId:c})}return e}_initializeCurvySolvers(){for(const t of this.nodesWithoutCrossings){const e=this._getAdjacentObstacles(t),n=new Sa({nodeWithPortPoints:t,colorMap:this.colorMap,traceWidth:this.traceWidth,viaDiameter:this.viaDiameter,adjacentObstacles:e});this.curvyIntraNodeSolvers.push(n)}}_stepCurvySolvers(){if(0===this.curvyIntraNodeSolvers.length)return this.phase=this.nodesWithCrossings.length>0?"jumpers":"done",void("jumpers"===this.phase&&this._initializeJumperSolvers());const t=this.curvyIntraNodeSolvers[this.currentCurvySolverIndex];if(this.activeSubSolver=t,!t)return this.phase=this.nodesWithCrossings.length>0?"jumpers":"done",void("jumpers"===this.phase&&this._initializeJumperSolvers());if(t.step(),t.solved){this.routes.push(...t.routes),this.currentCurvySolverIndex++;for(let t=this.currentCurvySolverIndex;t<this.curvyIntraNodeSolvers.length;t++){this.curvyIntraNodeSolvers[t];const e=this.nodesWithoutCrossings[t],n=this._getAdjacentObstacles(e),s=new Sa({nodeWithPortPoints:e,colorMap:this.colorMap,traceWidth:this.traceWidth,viaDiameter:this.viaDiameter,adjacentObstacles:n});this.curvyIntraNodeSolvers[t]=s}this.currentCurvySolverIndex>=this.curvyIntraNodeSolvers.length&&(this.phase=this.nodesWithCrossings.length>0?"jumpers":"done","jumpers"===this.phase&&this._initializeJumperSolvers())}else t.failed&&(this.error=`CurvyIntraNodeSolver failed for node: ${t.nodeWithPortPoints.capacityMeshNodeId}: ${t.error}`,this.failed=!0)}_initializeJumperSolvers(){for(const t of this.nodesWithCrossings){const e=new va({nodeWithPortPoints:t,colorMap:this.colorMap,traceWidth:this.traceWidth,connMap:this.connMap});this.jumperSolvers.push(e)}}_stepJumperSolvers(){if(0===this.jumperSolvers.length)return this.phase="done",void(this.solved=!0);const t=this.jumperSolvers[this.currentJumperSolverIndex];if(this.activeSubSolver=t,!t)return this.phase="done",void(this.solved=!0);if(t.step(),t.solved){for(const e of t.solvedRoutes)this.routes.push(Pa(e));this.jumpers.push(...t.getOutputJumpers()),this.currentJumperSolverIndex++,this.currentJumperSolverIndex>=this.jumperSolvers.length&&(this.phase="done",this.solved=!0)}else t.failed&&(this.error=`HyperJumperPrepatternSolver2 failed for node: ${t.nodeWithPortPoints.capacityMeshNodeId}: ${t.error}`,this.failed=!0)}computeProgress(){const t=this.allNodes.length;if(0===t)return 1;let e=0;e+=this.currentCurvySolverIndex;const n=this.curvyIntraNodeSolvers[this.currentCurvySolverIndex];n&&(e+=n.progress),e+=this.currentJumperSolverIndex;const s=this.jumperSolvers[this.currentJumperSolverIndex];return s&&(e+=s.progress),e/t}getConstructorParams(){return{nodePortPoints:this.allNodes,colorMap:this.colorMap,traceWidth:this.traceWidth,viaDiameter:this.viaDiameter,connMap:this.connMap,hyperParameters:this.hyperParameters,capacityMeshNodes:this.capacityMeshNodes,capacityMeshEdges:this.capacityMeshEdges}}getOutputJumpers(){return this.jumpers}visualize(){const t={lines:[],points:[],rects:[],circles:[]};if(this.failed&&this.activeSubSolver)return this.activeSubSolver.visualize();if("curvy"===this.phase&&this.curvyIntraNodeSolvers[this.currentCurvySolverIndex])return this.curvyIntraNodeSolvers[this.currentCurvySolverIndex].visualize();if("jumpers"===this.phase&&this.jumperSolvers[this.currentJumperSolverIndex])return this.jumperSolvers[this.currentJumperSolverIndex].visualize();for(const e of this.routes){const n=e.rootConnectionName??e.connectionName,s=De(e.route,e.connectionName,this.colorMap[n]);for(const n of s)t.lines.push({points:n.points,label:n.connectionName,strokeColor:0===n.z?n.color:it(n.color??"gray",.75),layer:`z${n.z}`,strokeWidth:e.traceThickness,strokeDash:0!==n.z?"10, 5":void 0});for(const s of e.vias)t.circles.push({center:s,radius:e.viaDiameter/2,fill:it(this.colorMap[n]??"gray",.5),layer:"via"});if("jumpers"in e&&e.jumpers)for(const s of e.jumpers){const e=this.colorMap[n]??"gray",o=s.footprint??"1206",i=Ze[o],r=s.end.x-s.start.x,a=s.end.y-s.start.y,c=Math.abs(r)>Math.abs(a),h=c?i.padLength:i.padWidth,d=c?i.padWidth:i.padLength;t.rects.push({center:s.start,width:h,height:d,fill:it(e,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.rects.push({center:s.end,width:h,height:d,fill:it(e,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.lines.push({points:[s.start,s.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*i.padWidth,layer:"jumper-body"})}}for(const e of this.nodeAnalyses){const n=e.node;n.center.x,n.width,n.center.x,n.width,n.center.y,n.height,n.center.y,n.height;t.rects.push({center:n.center,width:n.width,height:n.height,fill:e.hasCrossings?"rgba(255, 200, 0, 0.1)":"rgba(0, 200, 0, 0.1)",stroke:e.hasCrossings?"rgba(255, 150, 0, 0.5)":"rgba(0, 150, 0, 0.5)",label:[n.capacityMeshNodeId,e.hasCrossings?`crossings: ${e.numSameLayerCrossings}`:"no crossings"].join("\n")})}return t}},Ma=class extends y{unsolvedRoutes;mergedHdRoutes=[];colorMap={};defaultTraceThickness;defaultViaDiameter;constructor(t){super(),this.colorMap=t.colorMap??{};const e=t.hdRoutes[0];this.defaultTraceThickness=e?.traceThickness??.15,this.defaultViaDiameter=e?.viaDiameter??t.defaultViaDiameter??.6;const n=new Map;for(const e of t.connectionPathResults)n.set(e.connection.name,e);const s=new Map;for(const e of t.hdRoutes){const t=s.get(e.connectionName);t?t.push(e):s.set(e.connectionName,[e])}this.unsolvedRoutes=[];for(const[e,o]of s.entries()){const s=t.connections.find(t=>t.name===e);if(!s)continue;const i=n.get(e);let r=[];i?.path&&(r=i.path.map(t=>t.currentNodeId));const a={...s.pointsToConnect[0],z:Xe(Ue(s.pointsToConnect[0]),t.layerCount)},c={...s.pointsToConnect[1],z:Xe(Ue(s.pointsToConnect[1]),t.layerCount)};this.unsolvedRoutes.push({connectionName:e,hdRoutes:o,nodeOrder:r,start:a,end:c})}this.MAX_ITERATIONS=1e5}_step(){const t=this.unsolvedRoutes.pop();if(!t)return void(this.solved=!0);const e=this.stitchOrderedRoutes(t);this.mergedHdRoutes.push(e)}stitchOrderedRoutes(t){const{connectionName:e,hdRoutes:n,nodeOrder:s,start:o,end:i}=t;if(0===n.length)return{connectionName:e,traceThickness:this.defaultTraceThickness,viaDiameter:this.defaultViaDiameter,route:[o,i],vias:[],jumpers:[]};let r;r=s.length>0?this.orderRoutesByNodePath(n,s,o,e):this.orderRoutesByProximity(n,o);const a=[],c=[],h=[];a.push({x:o.x,y:o.y,z:o.z});for(let t=0;t<r.length;t++){const e=r[t],n=a[a.length-1],s=e.route[0],o=e.route[e.route.length-1],i=St(n,s),d=St(n,o),l=Math.min(i,d);if(t>0&&l>1)continue;let u;u=i<=d?[...e.route]:[...e.route].reverse();const p=.001;u.length>0&&St(n,u[0])<p&&(u=u.slice(1)),a.push(...u),c.push(...e.vias),e.jumpers&&h.push(...e.jumpers)}const d=St(a[a.length-1],i);return d>.001&&d<5&&a.push({x:i.x,y:i.y,z:i.z}),{connectionName:e,rootConnectionName:n[0]?.rootConnectionName,traceThickness:n[0]?.traceThickness??this.defaultTraceThickness,viaDiameter:n[0]?.viaDiameter??this.defaultViaDiameter,route:a,vias:c,jumpers:h}}orderRoutesByNodePath(t,e,n,s){if(0===t.length)return[];const o=new Set(t);let i=null,r=1/0;for(const t of o){const e=t.route[0],s=t.route[t.route.length-1],o=Math.min(St(n,e),St(n,s));o<r&&(r=o,i=t)}if(!i)return[];o.delete(i);const a=i.route[0],c=i.route[i.route.length-1];let h,d;St(n,a)<=St(n,c)?(h=a,d=c):(h=c,d=a);const l=(t,e)=>{let n=0;for(const s of o){if(s===e)continue;const o=s.route[0],i=s.route[s.route.length-1];(St(t,o)<10||St(t,i)<10)&&n++}return n},u=[i];let p=d;for(;o.size>0;){let t=null,e=1/0,n=-1;for(const s of o){const o=s.route[0],i=s.route[s.route.length-1],r=St(p,o),a=St(p,i),c=Math.min(r,a);if(c>=10)continue;const h=l(r<=a?i:o,s),d=0===h,u=0===n,m=c-e;let f=!1;f=null===t||(!!(!d&&u&&m<5)||!(d&&!u&&m>-5)&&c<e),f&&(e=c,t=s,n=h)}if(!t)break;{u.push(t),o.delete(t);const e=t.route[0],n=t.route[t.route.length-1];p=St(p,e)<=St(p,n)?n:e}}const m=[];for(p=h;o.size>0;){let t=null,e=1/0,s=-1;const i=St(p,n);for(const r of o){const o=r.route[0],a=r.route[r.route.length-1],c=St(p,o),h=St(p,a),d=Math.min(c,h);if(d>=10)continue;const u=c<=h?a:o;if(St(u,n)>i+2)continue;const m=l(u,r),f=0===m,g=0===s,y=d-e;let x=!1;x=null===t||(!!(!f&&g&&y<5)||!(f&&!g&&y>-5)&&d<e),x&&(e=d,t=r,s=m)}if(!t)break;{m.unshift(t),o.delete(t);const e=t.route[0],n=t.route[t.route.length-1];p=St(p,e)<=St(p,n)?n:e}}const f=[...m,...u];if(o.size>0){const e=[...o].map(t=>{const e=t.route[0],n=t.route[t.route.length-1];return`start=(${e.x.toFixed(2)},${e.y.toFixed(2)}) end=(${n.x.toFixed(2)},${n.y.toFixed(2)})`});console.warn(`[StitchSolver] Skipped ${o.size} routes for connection ${t[0]?.connectionName??"?"}, skipped routes: ${e.join("; ")}`)}return f}orderRoutesByProximity(t,e){const n=new Set(t),s=[];let o=e;for(;n.size>0;){let t=null,e=1/0,i=!1;for(const s of n){const n=s.route[0],r=s.route[s.route.length-1],a=St(o,n),c=St(o,r);a<e&&(e=a,t=s,i=!1),c<e&&(e=c,t=s,i=!0)}if(!t)break;{s.push(t),n.delete(t);const e=t.route[0],r=t.route[t.route.length-1];o=i?e:r}}return s}visualize(){const t={points:[],lines:[],circles:[],rects:[],title:"Multiple High Density Route Stitch Solver 2"};for(const[e,n]of this.mergedHdRoutes.entries()){const s=this.colorMap[n.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1],r=0!==o.z?it(s,.5):s;t.lines?.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:r,strokeWidth:n.traceThickness})}for(const e of n.route){const n=0!==e.z?it(s,.5):s;t.points?.push({x:e.x,y:e.y,color:n})}for(const e of n.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:n.viaDiameter/2,fill:s});if(n.jumpers&&n.jumpers.length>0){const e=Je(n.jumpers,{color:s,label:n.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}for(const e of this.unsolvedRoutes){const n=this.colorMap[e.connectionName]??"gray";t.points?.push({x:e.start.x,y:e.start.y,color:n,label:`${e.connectionName} Start`},{x:e.end.x,y:e.end.y,color:n,label:`${e.connectionName} End`});for(let s=0;s<e.hdRoutes.length;s++){const o=e.hdRoutes[s];if(o.route.length>1&&t.lines?.push({points:o.route.map(t=>({x:t.x,y:t.y})),strokeColor:it(n,.5),strokeDash:"10 5",label:`segment ${s}`}),o.jumpers&&o.jumpers.length>0){const e=Je(o.jumpers,{color:n,label:o.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}}return t}};function Na(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var Ia=class extends y{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth,this.effort=e.effort??1,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,o=Math.max(n,s),i=e.targetMinCapacity??.5;e.capacityDepth=Be(o,i)}this.connMap=$e(t),this.colorMap=ot(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;traceKeepoutSolver;nodeSolver;nodeTargetMerger;edgeSolver;relateNodesToOffBoardConnections;colorMap;highDensityRouteSolver;simpleHighDensityRouteSolver;highDensitySolver;highDensityStitchSolver;singleLayerNodeMerger;offboardPathFragmentSolver;strawSolver;deadEndSolver;traceSimplificationSolver;traceWidthSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;viaDiameter;minTraceWidth;effort;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[Na("netToPointPairsSolver",fn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ot(t.srjWithPointPairs,this.connMap),t.connMap=$e(t.srjWithPointPairs)}}),Na("nodeSolver",Js,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Na("relateNodesToOffBoardConnections",ar,t=>[{capacityMeshNodes:t.capacityNodes,srj:t.srj}],{onSolved:t=>{t.capacityNodes=t.relateNodesToOffBoardConnections?.getOutput().capacityNodes}}),Na("edgeSolver",cn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Na("availableSegmentPointSolver",Io,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),Na("portPointPathingSolver",Vo,t=>{const e=t.capacityNodes.map(t=>({capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:[],availableZ:t.availableZ,_containsTarget:t._containsTarget,_containsObstacle:t._containsObstacle,_offBoardConnectionId:t._offBoardConnectionId,_offBoardConnectedCapacityMeshNodeIds:t._offBoardConnectedCapacityMeshNodeIds})),n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),s=t.availableSegmentPointSolver;for(const t of s.sharedEdgeSegments)for(const e of t.portPoints){const[s,o]=e.nodeIds,i={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[s,o],distToCentermostPortOnZ:e.distToCentermostPortOnZ,connectsToOffBoardNode:t.nodeIds.some(t=>n.get(t)?._offBoardConnectionId)},r=n.get(s);r&&r.portPoints.push(i)}return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:e,capacityMeshNodes:t.capacityNodes,colorMap:t.colorMap,numShuffleSeeds:10*t.effort,hyperParameters:{JUMPER_PF_FN_ENABLED:!0,NODE_PF_FACTOR:100,MAX_RIPS:100*t.effort,RIPPING_ENABLED:!0,RIPPING_PF_THRESHOLD:.9-.7*(1-1/t.effort),RANDOM_RIP_FRACTION:.05,NODE_PF_MAX_PENALTY:1e3,STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR:0,CENTER_OFFSET_DIST_PENALTY_FACTOR:0,FORCE_CENTER_FIRST:!0}}]},{onSolved:t=>{const e=t.portPointPathingSolver;e&&cr({connMap:t.connMap,connectionsWithResults:e.connectionsWithResults,inputNodes:e.inputNodes,obstacles:t.srj.obstacles})}}),Na("highDensitySolver",ba,t=>[{nodePortPoints:t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth,connMap:t.connMap,capacityMeshNodes:t.capacityNodes??[],capacityMeshEdges:t.capacityEdges??[]}]),Na("highDensityStitchSolver",Ma,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensitySolver.routes,connectionPathResults:t.multiSectionPortPointOptimizer?.connectionResults??t.portPointPathingSolver?.connectionsWithResults??[],colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),Na("traceKeepoutSolver",ir,t=>[{hdRoutes:t.traceSimplificationSolver?.simplifiedHdRoutes??t.highDensityStitchSolver?.mergedHdRoutes??[],obstacles:t.srj.obstacles,jumpers:t.highDensitySolver?.getOutputJumpers()??[],connMap:t.connMap,colorMap:t.colorMap,srj:t.srj}])];getConstructorParams(){return[this.srj,this.opts]}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 t=this.netToPointPairsSolver?.visualize(),e=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),s=this.singleLayerNodeMerger?.visualize(),o=this.strawSolver?.visualize(),i=this.edgeSolver?.visualize(),r=this.traceKeepoutSolver?.visualize(),a=this.deadEndSolver?.visualize(),c=this.availableSegmentPointSolver?.visualize(),h=this.offboardPathFragmentSolver?.visualize(),d=this.portPointPathingSolver?.visualize(),l=this.multiSectionPortPointOptimizer?.visualize(),u=this.highDensityRouteSolver?.visualize(),p=this.highDensitySolver?.visualize(),m=this.simpleHighDensityRouteSolver?.visualize(),f=this.highDensityStitchSolver?.visualize(),y=this.traceSimplificationSolver?.visualize(),x=this.traceWidthSolver?.visualize(),v=this.srj.outline,S=[];if(S.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)"}),v&&v.length>=2){const t=v.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),S.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const P={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:["obstacle",t.offBoardConnectsTo?`offboardConnections: ${t.offBoardConnectsTo?.join(", ")}`:"",t.layers?.join(", ")].filter(Boolean).join("\n")}))],lines:S},b=[P,t,e,n,s,o,i,a,c,h,d,l,u?g(P,u):null,p?g(P,p):null,m?g(P,m):null,f,y,r,x,this.solved?g(P,sn(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...b)}preview(){const t=this.highDensitySolver?.routes??this.simpleHighDensityRouteSolver?.routes??this.highDensityRouteSolver?.routes;if(t){const e=[];for(let n=t.length-1;n>=0;n--){const s=t[n];if(e.push({points:s.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[s.connectionName]}),e.length>200)break}return{lines:e}}if(this.portPointPathingSolver){const t=[];for(const e of this.portPointPathingSolver.connectionsWithResults)e.path&&t.push({points:e.path.map(t=>({x:t.point.x,y:t.point.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.traceWidthSolver?.hdRoutesWithWidths??this.traceKeepoutSolver?.redrawnHdRoutes??this.traceSimplificationSolver?.simplifiedHdRoutes??this.highDensityStitchSolver?.mergedHdRoutes??this.highDensitySolver?.routes??this.simpleHighDensityRouteSolver?.routes??this.highDensityRouteSolver?.routes}getConnectedOffboardObstacles(){const t={},e=new Set(this.srj.connections.map(t=>t.rootConnectionName??t.name));for(const[n,s]of this.srj.obstacles.entries()){if(!s.offBoardConnectsTo?.length)continue;const o=s.obstacleId??`__obs${n}`;s.obstacleId=o;const i=this.connMap.getNetConnectedToId(o);if(!i)continue;const r=this.connMap.getIdsConnectedToNet(i).find(t=>e.has(t));r&&(t[o]=r)}return t}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver&&!this.simpleHighDensityRouteSolver&&!this.highDensitySolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes();for(const n of this.netToPointPairsSolver?.newConnections??[]){const s=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,o=e.filter(t=>t.connectionName===n.name);for(let e=0;e<o.length;e++){const i=o[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:s??n.rootConnectionName??n.name,route:We(i,this.srj.layerCount)};t.push(r)}}return t}getOutputJumpers(){return this.highDensitySolver?this.highDensitySolver.getOutputJumpers():[]}getOutputSimpleRouteJson(){const t=this.getOutputJumpers();return{...this.srj,traces:this.getOutputSimplifiedPcbTraces(),jumpers:t.length>0?t:void 0}}},Ca=class{constructor(t){this.targets=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],s=Math.floor(n.bounds.minX/this.CELL_SIZE)*this.CELL_SIZE,o=Math.floor(n.bounds.minY/this.CELL_SIZE)*this.CELL_SIZE,i=n.bounds.maxX,r=n.bounds.maxY;for(let t=s;t<=i;t+=this.CELL_SIZE)for(let s=o;s<=r;s+=this.CELL_SIZE){const o=this.getBucketKey(t,s),i=this.buckets.get(o);i?i.push([n,e]):this.buckets.set(o,[[n,e]])}}}buckets;CELL_SIZE=5;getBucketKey(t,e){return`${Math.floor(t/this.CELL_SIZE)}x${Math.floor(e/this.CELL_SIZE)}`}getTargetsInArea(t,e,n,s){const o=[],i=new Set,r=Math.floor((t-n/2)/this.CELL_SIZE)*this.CELL_SIZE,a=Math.floor((e-s/2)/this.CELL_SIZE)*this.CELL_SIZE,c=t+n/2,h=e+s/2;for(let t=r;t<=c;t+=this.CELL_SIZE)for(let e=a;e<=h;e+=this.CELL_SIZE){const n=this.getBucketKey(t,e),s=this.buckets.get(n)||[];for(const t of s)i.has(t[1])||(i.add(t[1]),o.push(t[0]))}return o}},_a=class extends y{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.MAX_DEPTH=e?.capacityDepth??this.MAX_DEPTH,this.MAX_ITERATIONS=1e5,this.layerCount=t.layerCount??2,this.outlinePolygon=t.outline&&t.outline.length>=3?t.outline:void 0;for(const e of t.obstacles)if(!e.zLayers){const n=[];for(const s of e.layers)n.push(Xe(s,t.layerCount));e.zLayers=n}const n={x:(t.bounds.minX+t.bounds.maxX)/2,y:(t.bounds.minY+t.bounds.maxY)/2},s={width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},o=Math.max(s.width,s.height);this.unfinishedNodes=[{capacityMeshNodeId:this.getNextNodeId(),center:n,width:o,height:o,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 Qs("flatbush",this.srj.obstacles),this.targets=this.computeTargets(),this.targetTree=new Ca(this.targets)}unfinishedNodes;finishedNodes;nodeToXYOverlappingObstaclesMap;layerCount;outlinePolygon;MAX_DEPTH=4;targets;targetTree;obstacleTree;computeTargets(){const t=[];for(const e of this.srj.connections)for(const n of e.pointsToConnect){const s=Ve(n),o=this.obstacleTree.searchArea(n.x,n.y,.01,.01).filter(t=>t.zLayers.some(t=>s.some(e=>t===Xe(e,this.layerCount))));let i={minX:n.x-.005,minY:n.y-.005,maxX:n.x+.005,maxY:n.y+.005};o.length>0&&(i={minX:Math.min(...o.map(t=>t.center.x-t.width/2)),minY:Math.min(...o.map(t=>t.center.y-t.height/2)),maxX:Math.max(...o.map(t=>t.center.x+t.width/2)),maxY:Math.max(...o.map(t=>t.center.y+t.height/2))});const r={...n,connectionName:e.name,availableZ:s.map(t=>Xe(t,this.layerCount)),bounds:i};t.push(r)}return t}getNodeBounds(t){const e=t.width/2,n=t.height/2;return{minX:t.center.x-e,maxX:t.center.x+e,minY:t.center.y-n,maxY:t.center.y+n}}getNodeRect(t){return{center:{x:t.center.x,y:t.center.y},width:t.width,height:t.height}}_nextNodeCounter=0;getNextNodeId(){return"cn"+this._nextNodeCounter++}getCapacityFromDepth(t){return(this.MAX_DEPTH-t+1)**2}getTargetIfNodeContainsTarget(t){const e=t.width>4*this.targetTree.CELL_SIZE?this.targets:this.targetTree.getTargetsInArea(t.center.x,t.center.y,t.width,t.height);for(const n of e)if(n.bounds.minX<=t.center.x+t.width/2&&n.bounds.maxX>=t.center.x-t.width/2&&n.bounds.minY<=t.center.y+t.height/2&&n.bounds.maxY>=t.center.y-t.height/2&&n.availableZ.some(e=>t.availableZ.includes(e)))return n;return null}getXYOverlappingObstacles(t){const e=this.nodeToXYOverlappingObstaclesMap.get(t.capacityMeshNodeId);if(e)return e;const n=[],s=this.getNodeBounds(t),o=s.minX,i=s.maxX,r=s.minY,a=s.maxY,c=t._parent?this.getXYOverlappingObstacles(t._parent):this.srj.obstacles;for(const t of c){const e=t.center.x-t.width/2,s=t.center.x+t.width/2,c=t.center.y-t.height/2,h=t.center.y+t.height/2;i>=e&&o<=s&&a>=c&&r<=h?n.push(t):(o>=e&&i<=s&&r>=c&&a<=h||e>=o&&s<=i&&c>=r&&h<=a)&&n.push(t)}return this.nodeToXYOverlappingObstaclesMap.set(t.capacityMeshNodeId,n),n}getXYZOverlappingObstacles(t){const e=this.getXYOverlappingObstacles(t),n=[];for(const s of e)t.availableZ.some(t=>s.zLayers.includes(t))&&n.push(s);return n}doesNodeOverlapObstacle(t){if(this.getXYZOverlappingObstacles(t).length>0)return!0;const e=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!Rt(e,this.outlinePolygon))return!0}return e.minX<this.srj.bounds.minX||e.maxX>this.srj.bounds.maxX||e.minY<this.srj.bounds.minY||e.maxY>this.srj.bounds.maxY}isNodeCompletelyInsideObstacle(t){const e=this.getXYZOverlappingObstacles(t),n=this.getNodeBounds(t);if(this.outlinePolygon){const e=this.getNodeRect(t);if(!Et(e,this.outlinePolygon))return!0}for(const t of e){const e=t.center.x-t.width/2,s=t.center.x+t.width/2,o=t.center.y-t.height/2,i=t.center.y+t.height/2;if(n.minX>=e&&n.maxX<=s&&n.minY>=o&&n.maxY<=i)return!0}return!1}getChildNodes(t){if(t._depth===this.MAX_DEPTH)return[];const e=[],n={width:t.width/2,height:t.height/2},s=[{x:t.center.x-n.width/2,y:t.center.y-n.height/2},{x:t.center.x+n.width/2,y:t.center.y-n.height/2},{x:t.center.x-n.width/2,y:t.center.y+n.height/2},{x:t.center.x+n.width/2,y:t.center.y+n.height/2}];for(const o of s){const s={capacityMeshNodeId:this.getNextNodeId(),center:o,width:n.width,height:n.height,layer:t.layer,availableZ:t.availableZ,_depth:(t._depth??0)+1,_parent:t};s._containsObstacle=this.doesNodeOverlapObstacle(s);const i=this.getTargetIfNodeContainsTarget(s);i&&(s._targetConnectionName=i.connectionName,s.availableZ=i.availableZ,s._containsTarget=!0),s._containsObstacle&&(s._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(s)),s._completelyInsideObstacle&&!s._containsTarget||e.push(s)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||!(!t._containsObstacle||t._completelyInsideObstacle))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),n=[],s=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t);e?s.push(t):e||t._containsObstacle?!e&&t._containsTarget&&n.push(t):n.push(t)}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}visualize(){const t={lines:[],points:[],rects:[],circles:[],coordinateSystem:"cartesian",title:"Capacity Mesh Visualization"};if(this.outlinePolygon&&this.outlinePolygon.length>=2){const e=this.outlinePolygon.map(t=>({x:t.x,y:t.y}));e.push({...e[0]}),t.lines.push({points:e,strokeColor:"rgba(0, 136, 255, 0.95)",label:"outline"});for(const e of this.outlinePolygon)t.points.push({x:e.x,y:e.y,color:"rgba(0, 136, 255, 0.95)"})}for(const e of this.srj.obstacles)t.rects.push({center:e.center,width:e.width,height:e.height,fill:1===e.zLayers?.length&&e.zLayers?.includes(1)?"rgba(0,0,255,0.3)":"rgba(255,0,0,0.3)",stroke:"red",label:["obstacle",`z: ${e.zLayers.join(",")}`].join("\n")});const e=[...this.finishedNodes,...this.unfinishedNodes];for(const n of e){const e=Math.min(...n.availableZ),s=this.unfinishedNodes.length>0&&n===this.unfinishedNodes[this.unfinishedNodes.length-1];t.rects.push({center:{x:n.center.x+e*n.width*.05,y:n.center.y-e*n.width*.05},width:Math.max(n.width-2,.8*n.width),height:Math.max(n.height-2,.8*n.height),fill:n._containsObstacle?"rgba(255,0,0,0.1)":{"0,1":"rgba(0,0,0,0.1)",0:"rgba(0,200,200, 0.1)",1:"rgba(0,0,200, 0.1)"}[n.availableZ.join(",")]??"rgba(0,200,200,0.1)",stroke:s?"rgba(255,165,0,0.5)":void 0,label:[n.capacityMeshNodeId,`availableZ: ${n.availableZ.join(",")}`,`target? ${n._containsTarget??!1}`,`obs? ${n._containsObstacle??!1}`,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`capacity: ${ke(n).toFixed(2)}`].join("\n")})}return t.rects.sort((t,e)=>t.center.y-e.center.y),this.srj.connections.forEach((e,n)=>{const s=st[n%st.length];for(const o of e.pointsToConnect){const e=Ve(o);t.points.push({x:o.x,y:o.y,label:`conn-${n} (${e.join(",")})`,color:s})}}),t}},Ta=class extends _a{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e,this.VIA_DIAMETER=t.minViaDiameter??this.VIA_DIAMETER}VIA_DIAMETER=.6;OBSTACLE_MARGIN=.1;OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES=.2;isNodeCompletelyOutsideBounds(t){if(this.outlinePolygon){const e=this.getNodeRect(t);if(!Et(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!!Et(e,this.outlinePolygon)&&!Rt(e,this.outlinePolygon)}return t.center.x-t.width/2<this.srj.bounds.minX||t.center.x+t.width/2>this.srj.bounds.maxX||t.center.y-t.height/2<this.srj.bounds.minY||t.center.y+t.height/2>this.srj.bounds.maxY}getObstacleCoveragePercentage(t){const e=this.getXYZOverlappingObstacles(t);if(0===e.length)return 0;const n=t.center.x-t.width/2,s=t.center.x+t.width/2,o=t.center.y-t.height/2,i=t.center.y+t.height/2,r=t.width*t.height;let a=0;for(const t of e){const e=Math.max(n,t.center.x-t.width/2),r=Math.min(s,t.center.x+t.width/2),c=Math.max(o,t.center.y-t.height/2),h=Math.min(i,t.center.y+t.height/2);if(e<r&&c<h){a+=(r-e)*(h-c)}}return a/r}shouldFilterSingleLayerNodeForObstacle(t){if(1!==t.availableZ.length)return!1;if(!t._containsObstacle)return!1;return this.getObstacleCoveragePercentage(t)>this.OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES}shouldFilterNodeForObstacle(t){return!!t._containsObstacle&&(1!==t.availableZ.length||this.shouldFilterSingleLayerNodeForObstacle(t))}createChildNodeAtPosition(t,e){const n={capacityMeshNodeId:this.getNextNodeId(),center:e.center,width:e.width,height:e.height,layer:t.layer,availableZ:e.availableZ,_depth:e._depth??(t._depth??0)+1,_parent:t},s=this.getXYZOverlappingObstacles(n);n._containsObstacle=s.length>0||this.isNodePartiallyOutsideBounds(n);const o=this.getTargetIfNodeContainsTarget(n);return o&&(n._targetConnectionName=o.connectionName,n._containsTarget=!0),n._containsObstacle&&(n._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(n)),n}getZSubdivisionChildNodes(t){if(1===t.availableZ.length)return[];const e=[],n=t.availableZ.map(t=>[t]);for(const s of n){const n=this.createChildNodeAtPosition(t,{center:{...t.center},width:t.width,height:t.height,availableZ:s,_depth:t._depth});this.isNodeCompletelyOutsideBounds(n)||e.push(n)}return e}getChildNodes(t){if(t._depth>=this.MAX_DEPTH)return[];const e=[],n={width:t.width/2,height:t.height/2},s=[{x:t.center.x-n.width/2,y:t.center.y-n.height/2},{x:t.center.x+n.width/2,y:t.center.y-n.height/2},{x:t.center.x-n.width/2,y:t.center.y+n.height/2},{x:t.center.x+n.width/2,y:t.center.y+n.height/2}];for(const o of s){const s=this.createChildNodeAtPosition(t,{center:o,width:n.width,height:n.height,availableZ:t.availableZ});this.isNodeCompletelyOutsideBounds(s)||e.push(s)}return e}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||(1===t.availableZ.length&&t._depth<=this.MAX_DEPTH||!(!t._containsObstacle||t._completelyInsideObstacle)))}_step(){const t=this.unfinishedNodes.pop();if(!t)return void(this.solved=!0);const e=this.getChildNodes(t),n=[],s=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),o=t.availableZ.length>1&&!e&&(t._containsObstacle||t.width<this.VIA_DIAMETER+this.OBSTACLE_MARGIN);if(e)s.push(t);else if(e||this.shouldFilterNodeForObstacle(t)||o)if(!e&&t._containsTarget)if(o){const e=this.getZSubdivisionChildNodes(t);n.push(...e.filter(t=>t._containsTarget||!this.shouldFilterNodeForObstacle(t)))}else n.push(t);else o&&n.push(...this.getZSubdivisionChildNodes(t).filter(t=>!this.shouldFilterNodeForObstacle(t)));else n.push(t)}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}},Ea=class extends Ta{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e}MAX_SIZE_FOR_SINGLE_LAYER_NODES=2;isObstacleAssignable(t){return Boolean(t?.netIsAssignable)}getOverlappingAssignableObstacles(t){return this.getXYZOverlappingObstacles(t).filter(t=>this.isObstacleAssignable(t))}shouldNodeBeXYSubdivided(t){return!(t._depth>=this.MAX_DEPTH)&&(!!t._containsTarget||(!(!t._containsObstacle||t._completelyInsideObstacle)||1===t.availableZ.length&&(t.width>this.MAX_SIZE_FOR_SINGLE_LAYER_NODES||t.height>this.MAX_SIZE_FOR_SINGLE_LAYER_NODES)))}shouldFilterNodeForObstacle(t){if(!t._containsObstacle)return!1;return!(this.getOverlappingAssignableObstacles(t).length>0)&&(1!==t.availableZ.length||this.shouldFilterSingleLayerNodeForObstacle(t))}insertAssignableObstaclesAsNodes(){const t=this.srj.obstacles.filter(t=>this.isObstacleAssignable(t)),e=new Map;for(const n of t){const t=[];for(const e of this.finishedNodes){this.getXYZOverlappingObstacles(e).some(t=>t===n)&&t.push(e)}e.set(n,t)}const n=new Set;for(const t of e.values())for(const e of t)n.add(e);this.finishedNodes=this.finishedNodes.filter(t=>!n.has(t));for(const n of t){const t=e.get(n)||[],s=n.layers&&n.layers.length>0?Array.from(new Set(n.layers.map(t=>Xe(t,this.srj.layerCount)))).sort((t,e)=>t-e):Array.from({length:this.srj.layerCount},(t,e)=>this.srj.layerCount-e-1);let o=n.center.x-n.width/2,i=n.center.x+n.width/2,r=n.center.y-n.height/2,a=n.center.y+n.height/2;for(const e of t){const t=e.center.x-e.width/2,n=e.center.x+e.width/2,s=e.center.y-e.height/2,c=e.center.y+e.height/2;o=Math.min(o,t),i=Math.max(i,n),r=Math.min(r,s),a=Math.max(a,c)}const c=i-o,h=a-r,d=(o+i)/2,l=(r+a)/2;let u=!1;for(const t of this.srj.connections){for(const e of t.pointsToConnect)if(e.x>=o&&e.x<=i&&e.y>=r&&e.y<=a){u=!0;break}if(u)break}const p={capacityMeshNodeId:`assignable_via_${n.center.x}_${n.center.y}`,center:{x:d,y:l},width:c,height:h,layer:1===s.length?`z${s[0]}`:`z${s.join(",")}`,availableZ:s,_depth:0,_containsTarget:u,_containsObstacle:!1,_completelyInsideObstacle:!1};p._assignedViaObstacle=n,this.finishedNodes.push(p)}}_step(){const t=this.unfinishedNodes.pop();if(!t)return this.insertAssignableObstaclesAsNodes(),void(this.solved=!0);const e=this.getChildNodes(t),n=[],s=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),o=t.availableZ.length>1&&!e;if(e)s.push(t);else{if(o){const e=this.getZSubdivisionChildNodes(t);for(const t of e)!t._containsTarget&&this.shouldFilterNodeForObstacle(t)||(this.shouldNodeBeXYSubdivided(t)?s.push(t):(t._containsObstacle=!1,n.push(t)));continue}this.shouldFilterNodeForObstacle(t)&&!t._containsTarget||n.push(t)}}this.unfinishedNodes.push(...s),this.finishedNodes.push(...n)}},Ra=.005,wa=class extends y{nodeMap;currentBatchNodeIds;absorbedNodeIds;nextBatchNodeIds;batchHadModifications;hasComputedAdjacentNodeIds=!1;newNodes;constructor(t){super(),this.nodeMap=new Map,this.MAX_ITERATIONS=1e5;for(const e of t)this.nodeMap.set(e.capacityMeshNodeId,e);this.newNodes=[],this.absorbedNodeIds=new Set;const e=[];for(const n of t)n._assignedViaObstacle?(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId)):n._containsTarget?n.availableZ.length>1?(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId)):e.push([n,n.width*n.height]):(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId));e.sort((t,e)=>t[1]-e[1]);for(const[t,n]of e){const e={...t,center:{...t.center}};this.nodeMap.set(t.capacityMeshNodeId,e)}this.currentBatchNodeIds=e.map(([t])=>t.capacityMeshNodeId),this.nextBatchNodeIds=[],this.batchHadModifications=!1}computeAdjacentNodeIdsForFirstBatch(t){const e=Math.max(...t.map(t=>Math.max(...t.availableZ))),n=[];for(let s=0;s<=e;s++)n.push(new an(t.filter(t=>t.availableZ[0]===s)));for(const e of t){const t=[],s=n[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const n of s)n._containsTarget&&n._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!n._containsTarget||n._targetConnectionName!==e._targetConnectionName)||n.capacityMeshNodeId!==e.capacityMeshNodeId&&on(e,n)&&t.push(n);e._adjacentNodeIds=t.map(t=>t.capacityMeshNodeId)}}getAdjacentSameLayerUnprocessedNodes(t){const e=[],n=Array.from(new Set((t._adjacentNodeIds??[]).map(t=>this.nodeMap.get(t)))).filter(e=>e&&e.capacityMeshNodeId!==t.capacityMeshNodeId);n.sort((t,e)=>t.width*t.height-e.width*e.height);for(const t of n)this.absorbedNodeIds.has(t.capacityMeshNodeId)||e.push(t);return e}_step(){this.hasComputedAdjacentNodeIds||(this.computeAdjacentNodeIdsForFirstBatch(this.currentBatchNodeIds.map(t=>this.nodeMap.get(t))),this.hasComputedAdjacentNodeIds=!0);let t=this.currentBatchNodeIds.pop();for(;t&&this.absorbedNodeIds.has(t);)t=this.currentBatchNodeIds.pop();if(!t)return this.batchHadModifications?(this.currentBatchNodeIds=this.nextBatchNodeIds.sort((t,e)=>{const n=this.nodeMap.get(t),s=this.nodeMap.get(e);return n.width*n.height-s.width*s.height}),this.nextBatchNodeIds=[],void(this.batchHadModifications=!1)):(this.solved=!0,void this.newNodes.push(...this.nextBatchNodeIds.map(t=>this.nodeMap.get(t))));const e=this.nodeMap.get(t);let n=!1;const s=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===s.length)return void this.nextBatchNodeIds.push(t);const o=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))))},i=s.filter(t=>t.center.x<e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(i.length>0){const{width:t,height:s}=i[0],r=i.every(e=>e.width===t&&e.height===s);Math.abs(i.reduce((t,e)=>t+e.height,0)-e.height)<Ra&&r&&(e.width+=t,e.center.x=e.center.x-t/2,o(i),n=!0)}const r=s.filter(t=>t.center.x>e.center.x&&Math.abs(t.center.y-e.center.y)<e.height/2);if(r.length>0&&!n){const{width:t,height:s}=r[0],i=r.every(e=>e.width===t&&e.height===s);Math.abs(r.reduce((t,e)=>t+e.height,0)-e.height)<Ra&&i&&(e.width+=t,e.center.x=e.center.x+t/2,o(r),n=!0)}const a=s.filter(t=>t.center.y>e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(a.length>0&&!n){const{width:t,height:s}=a[0],i=a.every(e=>e.width===t&&e.height===s);Math.abs(a.reduce((t,e)=>t+e.width,0)-e.width)<Ra&&i&&(e.height+=s,e.center.y=e.center.y+s/2,o(a),n=!0)}const c=s.filter(t=>t.center.y<e.center.y&&Math.abs(t.center.x-e.center.x)<e.width/2);if(c.length>0&&!n){const{width:t,height:s}=c[0],i=c.every(e=>e.width===t&&e.height===s);Math.abs(c.reduce((t,e)=>t+e.width,0)-e.width)<Ra&&i&&(e.height+=s,e.center.y=e.center.y-s/2,o(c),n=!0)}n?(this.batchHadModifications=!0,this.currentBatchNodeIds.push(t)):this.nextBatchNodeIds.unshift(t)}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Single Layer Node Merger (Only Merge Targets)"};for(const e of this.newNodes)t.rects.push(fi(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let n;e&&(n=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const s of this.currentBatchNodeIds){const o=this.nodeMap.get(s);if(!this.absorbedNodeIds.has(s)&&o){const i=fi(o,{rectMargin:.01});s===e?i.stroke="rgba(0, 255, 0, 0.8)":n?.some(t=>t.capacityMeshNodeId===s)?i.stroke="rgba(128, 0, 128, 0.8)":i.stroke="rgba(255, 165, 0, 0.8)",i.layer=`z${o.availableZ.join(",")}`,i.label=`${i.label}\n(unprocessed)`,t.rects.push(i)}}for(const e of this.nextBatchNodeIds){const n=this.nodeMap.get(e);if(!this.absorbedNodeIds.has(e)&&n){const e=fi(n,{rectMargin:.01});e.layer=`z${n.availableZ.join(",")}`,e.stroke="rgba(0, 217, 255, 0.8)",e.label=`${e.label}\nx: ${n.center.x}, y: ${n.center.y}\n${n.width}x${n.height}\n(next batch)`,t.rects.push(e)}}return t}},Aa=class extends y{newNodes;obstacleToNodesMap;obstaclesToProcess;mergedNodeIds;constructor(t){super(),this.MAX_ITERATIONS=1e4,this.newNodes=[],this.obstacleToNodesMap=new Map,this.mergedNodeIds=new Set;for(const e of t){const t=e._assignedViaObstacle;if(t){const n=this.obstacleToNodesMap.get(t)||[];n.push(e),this.obstacleToNodesMap.set(t,n)}else this.newNodes.push(e)}this.obstaclesToProcess=Array.from(this.obstacleToNodesMap.keys())}_step(){const t=this.obstaclesToProcess.pop();if(!t)return void(this.solved=!0);const e=this.obstacleToNodesMap.get(t);if(!e||0===e.length)return;let n=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,o=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;const r=new Set;let a=!1;for(const t of e){const e=t.center.x-t.width/2,c=t.center.x+t.width/2,h=t.center.y-t.height/2,d=t.center.y+t.height/2;n=Math.min(n,e),s=Math.max(s,c),o=Math.min(o,h),i=Math.max(i,d);for(const e of t.availableZ)r.add(e);t._containsTarget&&(a=!0)}const c=s-n,h=i-o,d=(n+s)/2,l=(o+i)/2,u=Array.from(r).sort((t,e)=>t-e),p={capacityMeshNodeId:`merged_via_${t.center.x}_${t.center.y}`,center:{x:d,y:l},width:c,height:h,layer:1===u.length?`z${u[0]}`:`z${u.join(",")}`,availableZ:u,_containsTarget:a,_containsObstacle:!1,_completelyInsideObstacle:!1};p._assignedViaObstacle=t;for(const t of e)this.mergedNodeIds.add(t.capacityMeshNodeId);this.newNodes.push(p)}visualize(){const t={circles:[],lines:[],points:[],rects:[],coordinateSystem:"cartesian",title:"Assignable Via Node Merger"};for(const e of this.newNodes){const n=fi(e);e._assignedViaObstacle&&(n.stroke="rgba(255, 0, 255, 0.8)",n.label=`${n.label||""}\n(merged via)`),t.rects.push(n)}const e=this.obstaclesToProcess[this.obstaclesToProcess.length-1];if(e){const n=this.obstacleToNodesMap.get(e)||[];for(const e of n){const n=fi(e,{rectMargin:.01});n.stroke="rgba(0, 255, 0, 0.8)",n.label=`${n.label||""}\n(to be merged)`,t.rects.push(n)}}return t}},Oa=class extends y{constructor(t){const{simpleRouteJson:e,nodes:n,edges:s,colorMap:o,MAX_ITERATIONS:i=1e6,hyperParameters:r={}}=t;super(),this.inputParams=t,this.hyperParameters=r,this.MAX_ITERATIONS=i,this.simpleRouteJson=e,this.nodes=n,this.edges=s,this.colorMap=o??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=No(this.edges);const a=this.nodes.filter(t=>t._containsTarget);this.unprocessedConnectionPairs=kt(this.simpleRouteJson.connections.map(t=>{const[e,n]=t.pointsToConnect;return{start:a.find(t=>St(t.center,e)<t.width/2),end:a.find(t=>St(t.center,n)<t.width/2),connection:t}}),this.hyperParameters.SHUFFLE_SEED??0),this.viaNodes=this.nodes.filter(t=>t.availableZ.length>1)}GREEDY_MULTIPLIER=1.5;simpleRouteJson;nodes;edges;colorMap;MAX_ITERATIONS;hyperParameters;usedNodeMap=new Map;nodeMap;nodeEdgeMap;unprocessedConnectionPairs;solvedRoutes=[];activeConnectionPair=null;ogUnprocessedSubpaths=null;unprocessedSubpaths=null;solvedSubpaths=null;activeSubpath=null;viaNodes=[];closestViaForConnectionStartMap=new Map;closestViaForConnectionEndMap=new Map;getConstructorParams(){return this.inputParams}lastStepOperation="none";computeClosestViaForAllConnections(){this.closestViaForConnectionStartMap.clear(),this.closestViaForConnectionEndMap.clear();for(const t of this.unprocessedConnectionPairs){const e=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId));if(e.length>0){const n=e.reduce((e,n)=>{const s=this._dist(e,t.start);return this._dist(n,t.start)<s?n:e});this.closestViaForConnectionStartMap.set(t,n);const s=e.reduce((e,n)=>{const s=this._dist(e,t.end);return this._dist(n,t.end)<s?n:e});this.closestViaForConnectionEndMap.set(t,s)}}}_step(){if(!this.activeConnectionPair)return this.activeConnectionPair=this.unprocessedConnectionPairs.shift(),this.activeConnectionPair?(this.computeClosestViaForAllConnections(),void(this.lastStepOperation="dequeueConnectionPair")):void(this.solved=!0);if(this.activeConnectionPair&&!this.unprocessedSubpaths)return this.unprocessedSubpaths=this.breakConnectionPairIntoSubpaths(this.activeConnectionPair),this.ogUnprocessedSubpaths=this.unprocessedSubpaths.slice(),this.solvedSubpaths=[],void(this.lastStepOperation="breakConnectionPairIntoSubpaths");if(this.activeSubpath){if(this.activeSubpath&&(this.stepSolveSubpath(this.activeSubpath),this.activeSubpath.solved))return this.solvedSubpaths.push(this.activeSubpath),this.activeSubpath=null,this.clearCandidateNodes(),void(this.lastStepOperation="finishedSolvingSubpath");this.lastStepOperation="stepSolveSubpath"}else{if(this.activeSubpath=this.unprocessedSubpaths.shift(),!this.activeSubpath){const t=this.activeConnectionPair;return this.activeConnectionPair=null,this.unprocessedSubpaths=null,this.ogUnprocessedSubpaths=null,this.activeSubpath=null,this.solvedRoutes.push(this.createSolvedRoute(this.solvedSubpaths,t)),void(this.lastStepOperation="finishedSolvingConnectionPair")}this.lastStepOperation="dequeueSubpath"}}queuedCandidateNodes=[];visitedNodes=new Set;_dist(t,e){return Math.hypot(t.center.x-e.center.x,t.center.y-e.center.y)}stepSolveSubpath(t){const{start:e,end:n}=t;if(e.capacityMeshNodeId===n.capacityMeshNodeId)return t.path=[e],t.solved=!0,void this.usedNodeMap.set(e.capacityMeshNodeId,!0);if(0===this.queuedCandidateNodes.length&&0===this.visitedNodes.size){const t=this._dist(e,n),s={prevCandidate:null,node:e,g:0,h:t,f:this.GREEDY_MULTIPLIER*t};this.queuedCandidateNodes.push(s)}let s;for(this.queuedCandidateNodes.sort((t,e)=>t.f-e.f);this.queuedCandidateNodes.length&&!s;){const t=this.queuedCandidateNodes.shift();this.visitedNodes.has(t.node.capacityMeshNodeId)||(s=t)}if(!s)return this.failed=!0,void(this.error="No viable candidates left");if(this.visitedNodes.add(s.node.capacityMeshNodeId),s.node.capacityMeshNodeId===n.capacityMeshNodeId){const e=[];let n=s;for(;n;)e.unshift(n.node),this.usedNodeMap.set(n.node.capacityMeshNodeId,!0),n=n.prevCandidate;return t.path=e,void(t.solved=!0)}const o=this.getNeighbors(s.node);for(const t of o){const e=t.capacityMeshNodeId;if(this.visitedNodes.has(e))continue;const o=this.computeG(s,t,n),i=this.computeH(s,t,n),r=o+this.GREEDY_MULTIPLIER*i,a=this.queuedCandidateNodes.findIndex(t=>t.node.capacityMeshNodeId===e);if(a>=0){if(this.queuedCandidateNodes[a].g<=o)continue;this.queuedCandidateNodes.splice(a,1)}this.queuedCandidateNodes.push({prevCandidate:s,node:t,g:o,h:i,f:r})}}getNeighbors(t){const e=new Set,n=this.nodeEdgeMap.get(t.capacityMeshNodeId)??[];for(const s of n){const[n,o]=s.nodeIds,i=n===t.capacityMeshNodeId?o:n,r=this.nodeMap.get(i);r&&e.add(r)}const s=this.activeSubpath?.layer;return Array.from(e).filter(t=>!(t.capacityMeshNodeId!==this.activeSubpath?.end.capacityMeshNodeId)||!t._containsObstacle&&(!t._containsTarget&&(!this.usedNodeMap.has(t.capacityMeshNodeId)&&!(void 0!==s&&!t.availableZ.includes(s)))))}clearCandidateNodes(){this.queuedCandidateNodes=[],this.visitedNodes=new Set}computeG(t,e,n){const s=this._dist(t.node,e);return t.g+s}computeH(t,e,n){return this._dist(e,n)}createSolvedRoute(t,e){const n=[];for(let e=0;e<t.length;e++){const s=t[e];s.path?0===e?n.push(...s.path):n.push(...s.path.slice(1)):(0===e&&n.push(s.start),e===t.length-1&&n.push(s.end))}return{connection:e.connection,path:n}}breakConnectionPairIntoSubpaths(t){var e,n;if(!(e=[this.hyperParameters.DIRECTIVE_SEED??0,this.solvedRoutes.length],n=this.hyperParameters.FORCE_VIA_TRAVEL_CHANCE??0,Yt(e.reduce((t,e)=>t+16807*e%2147483647,0))()<n))return[{start:t.start,end:t.end,solved:!1,layer:t.start.availableZ[0]??0}];const s=this.getClosestVia(t.start),o=this.getFarVia(s,t.end),i=t.start.availableZ[0]??0,r=t.end.availableZ[0]??0,a=[];return a.push({start:t.start,end:s,solved:!1,layer:i}),i===r?(a.push({start:s,end:o,solved:!1,layer:0===i?1:0}),a.push({start:o,end:t.end,solved:!1,layer:r})):a.push({start:s,end:t.end,solved:!1,layer:r}),a}getClosestVia(t){if(0===this.viaNodes.length)return t;const e=new Set;for(const[t,n]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&e.add(n.capacityMeshNodeId);for(const[t,n]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&e.add(n.capacityMeshNodeId);const n=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId)).filter(t=>!e.has(t.capacityMeshNodeId));if(0===n.length){const e=this.viaNodes.filter(t=>!t._completelyInsideObstacle&&!t._containsObstacle).filter(t=>!this.usedNodeMap.has(t.capacityMeshNodeId));return 0===e.length?t:(e.sort((e,n)=>this._dist(e,t)-this._dist(n,t)),e[0])}n.sort((e,n)=>this._dist(e,t)-this._dist(n,t));const s=this.hyperParameters.MAX_CLOSEST_VIA_SKIP??0;if(s>0&&n.length>1){const t=Yt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length),e=Math.floor(t()*(s+1));return n[Math.min(e,n.length-1)]}return n[0]}getFarVia(t,e){if(0===this.viaNodes.length)return t;const n=null!=this.hyperParameters.FAR_VIA_MIN_DISTANCE?this.hyperParameters.FAR_VIA_MIN_DISTANCE:50,s=new Set;for(const[t,e]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&s.add(e.capacityMeshNodeId);for(const[t,e]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&s.add(e.capacityMeshNodeId);const o=this.viaNodes.filter(e=>!this.usedNodeMap.has(e.capacityMeshNodeId)&&e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!s.has(e.capacityMeshNodeId)&&this._dist(e,t)>=n);if(0===o.length){const s=this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)&&this._dist(e,t)>=n).sort((t,n)=>this._dist(t,e)-this._dist(n,e));if(s.length>0)return s[0];return this.viaNodes.filter(e=>e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!this.usedNodeMap.has(e.capacityMeshNodeId)).sort((t,n)=>this._dist(t,e)-this._dist(n,e))[0]??t}o.sort((t,n)=>this._dist(t,e)-this._dist(n,e));const i=this.hyperParameters.MAX_FURTHEST_VIA_SKIP??0;if(i>0&&o.length>1){const t=Yt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length+1e3),e=Math.floor(t()*(i+1));return o[Math.min(e,o.length-1)]}return o[0]}getCapacityPaths(){const t=[];for(const e of this.solvedRoutes){const n=e.path;n&&n.length>0&&t.push({capacityPathId:e.connection.name,connectionName:e.connection.name,nodeIds:n.map(t=>t.capacityMeshNodeId)})}return t}visualize(){const t={lines:[],points:[],rects:[],circles:[]},e=t=>!!t&&"number"==typeof t.x&&"number"==typeof t.y&&!Number.isNaN(t.x)&&!Number.isNaN(t.y)&&Number.isFinite(t.x)&&Number.isFinite(t.y),n=t=>"number"==typeof t&&!Number.isNaN(t)&&Number.isFinite(t);for(const s of this.nodes){const o=this.queuedCandidateNodes.some(t=>t.node.capacityMeshNodeId===s.capacityMeshNodeId),i=this.queuedCandidateNodes.find(t=>t.node.capacityMeshNodeId===s.capacityMeshNodeId);if(e(s.center)&&n(s.width)&&n(s.height)){const e=fi(s,{rectMargin:.025,zOffset:.01});t.rects.push({...e,fill:o?"rgba(255, 128, 255, 0.5)":s._containsTarget?"rgba(0, 150, 255, 0.15)":s._containsObstacle?"rgba(255, 0, 0, 0.1)":"rgba(200, 200, 200, 0.05)",label:[`ID: ${s.capacityMeshNodeId}`,`Size: ${s.width.toFixed(2)}x${s.height.toFixed(2)}`,`Z: ${s.availableZ.join(", ")}`,i?`g: ${i.g.toFixed(2)}`:"",i?`h: ${i.h.toFixed(2)}`:"",i?`f: ${i.f.toFixed(2)}`:"",s._containsTarget?"TARGET":"",s._containsObstacle?"OBSTACLE":""].filter(t=>t).join("\n")})}}for(const n of this.edges){const[s,o]=n.nodeIds,i=this.nodeMap.get(s),r=this.nodeMap.get(o);i?.center&&r?.center&&e(i.center)&&e(r.center)&&t.lines.push({points:[i.center,r.center],strokeColor:"rgba(150, 150, 150, 0.2)"})}for(let n=0;n<this.solvedRoutes.length;n++){const s=this.solvedRoutes[n],o=s.path,i="blue";for(let s=0;s<o.length-1;s++){const r=o[s],a=o[s+1];if(r?.center&&a?.center&&e(r.center)&&e(a.center)){const e=r.availableZ.includes(1)&&a.availableZ.includes(1),s=n%5*.02;t.lines.push({points:[{x:r.center.x+s,y:r.center.y+s},{x:a.center.x+s,y:a.center.y+s}],strokeColor:i,strokeDash:e?"5 5":void 0})}}if(o.length>0){const n=o[0],i=o[o.length-1];n?.center&&e(n.center)&&t.points.push({x:n.center.x,y:n.center.y,label:`START: ${s.connection.name}`}),i?.center&&e(i.center)&&t.points.push({x:i.center.x,y:i.center.y,label:`END: ${s.connection.name}`})}}if(this.solvedSubpaths)for(let n=0;n<this.solvedSubpaths.length;n++){const s=this.solvedSubpaths[n];if(s.path&&s.path.length>1)for(let n=0;n<s.path.length-1;n++){const o=s.path[n],i=s.path[n+1];o?.center&&i?.center&&e(o.center)&&e(i.center)&&t.lines.push({points:[o.center,i.center],strokeColor:"green",strokeDash:1===s.layer?"3 3":void 0})}}if(this.activeSubpath){const n=this.activeSubpath.start?.center,s=this.activeSubpath.end?.center;n&&s&&e(n)&&e(s)&&(t.lines.push({points:[n,s],strokeColor:"orange",strokeDash:"5 5"}),t.points.push({x:n.x,y:n.y,label:"ACTIVE START"}),t.points.push({x:s.x,y:s.y,label:"ACTIVE END"}))}const s=this.queuedCandidateNodes.slice(0,10).sort((t,e)=>t.f-e.f);for(let n=0;n<s.length;n++){const o=.6*(1-n/10),i=[];let r=s[n];for(;r;)i.push(r.node),r=r.prevCandidate;if(i.reverse(),i.length>1){const n=i.map(t=>t.center).filter(t=>e(t));n.length>1&&t.lines.push({points:n,strokeColor:it("purple",1-o),strokeDash:1===this.activeSubpath?.layer?"4 2":void 0})}}if(this.activeConnectionPair){const n=this.activeConnectionPair.start?.center,s=this.activeConnectionPair.end?.center;n&&s&&e(n)&&e(s)&&t.lines.push({points:[n,s],strokeColor:"cyan",strokeDash:"20 5"})}if(this.ogUnprocessedSubpaths&&3===this.ogUnprocessedSubpaths.length){const[,s]=this.ogUnprocessedSubpaths;if(s.start?.center&&e(s.start.center)){const e=Math.max(s.start.width||0,s.start.height||0);n(e)&&e>0&&(t.circles.push({center:s.start.center,radius:e,stroke:"blue"}),t.points.push({x:s.start.center.x,y:s.start.center.y,label:"DIRECTIVE VIA 1"}))}if(s.end?.center&&e(s.end.center)){const e=Math.max(s.end.width||0,s.end.height||0);n(e)&&e>0&&(t.circles.push({center:s.end.center,radius:e,stroke:"purple"}),t.points.push({x:s.end.center.x,y:s.end.center.y,label:"DIRECTIVE VIA 2"}))}}if(this.queuedCandidateNodes.length>0)for(const n of this.queuedCandidateNodes){const s=n.node;s?.center&&e(s.center)&&t.circles.push({center:s.center,radius:.05,fill:"rgba(255, 255, 0, 0.6)",stroke:"yellow"})}if(this.visitedNodes.size>0)for(const n of this.visitedNodes){const s=this.nodeMap.get(n);s?.center&&e(s.center)&&t.circles.push({center:s.center,radius:.08,fill:"rgba(128, 128, 128, 0.5)",stroke:"gray"})}return t}},za=class extends Zt{constructorParams;constructor(t){super(),this.constructorParams=t,this.MAX_ITERATIONS=t.MAX_ITERATIONS??12e4,this.MIN_SUBSTEPS=5,this.GREEDY_MULTIPLIER=1.35}getHyperParameterDefs(){return[{name:"traceOrderingSeed",possibleValues:[{SHUFFLE_SEED:0},{SHUFFLE_SEED:1},{SHUFFLE_SEED:2},{SHUFFLE_SEED:3},{SHUFFLE_SEED:4},{SHUFFLE_SEED:5},{SHUFFLE_SEED:6},{SHUFFLE_SEED:7},{SHUFFLE_SEED:8},{SHUFFLE_SEED:9}]},{name:"forceViaTravelChance",possibleValues:[{FORCE_VIA_TRAVEL_CHANCE:.6},{FORCE_VIA_TRAVEL_CHANCE:.8},{FORCE_VIA_TRAVEL_CHANCE:.9}]}]}computeG(t){const e=t.unprocessedConnectionPairs.length+t.solvedRoutes.length+(t.activeConnectionPair?1:0),n=t.solvedRoutes.length,s=e>0?n/e:0;return t.iterations/t.MAX_ITERATIONS+(1-s)}computeH(t){const e=t.unprocessedConnectionPairs.length+t.solvedRoutes.length+(t.activeConnectionPair?1:0),n=t.solvedRoutes.length;return e>0?1-n/e:0}generateSolver(t){return new Oa({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}};function Da(t){const e=new Map;for(const n of t)e.set(n.capacityMeshNodeId,n);return e}function La(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var Fa=class extends y{capacityNodes;capacityEdges;enhancedEdges=[];animationState="showing_nodes";assignableNodes=[];shownNodes=[];pendingEdges=[];createdEdges=[];nextEdgeId=0;nodeMap=new Map;constructor(t){super(),this.capacityNodes=t.capacityNodes,this.capacityEdges=t.capacityEdges,this.nodeMap=Da(this.capacityNodes),this.enhancedEdges=[...this.capacityEdges],this.initializeAssignableNodes(),this.initializePendingEdges(),this.MAX_ITERATIONS=this.assignableNodes.length+this.pendingEdges.length+10}initializeAssignableNodes(){for(const t of this.capacityNodes){const e=t._assignedViaObstacle;e?.offBoardConnectsTo&&e.offBoardConnectsTo.length>0&&this.assignableNodes.push(t)}}initializePendingEdges(){const t=new Map;for(const e of this.assignableNodes){const n=e._assignedViaObstacle;if(n?.offBoardConnectsTo)for(const s of n.offBoardConnectsTo)t.has(s)||t.set(s,[]),t.get(s).push(e)}this.pendingEdges=[];for(const[e,n]of t)if(n.length>1)for(let t=0;t<n.length;t++)for(let s=t+1;s<n.length;s++)this.pendingEdges.push({node1:n[t],node2:n[s],netName:e})}_step(){switch(this.animationState){case"showing_nodes":if(this.assignableNodes.length>0){const t=this.assignableNodes.shift();this.shownNodes.push(t)}else this.animationState="showing_edges";break;case"showing_edges":if(this.pendingEdges.length>0){const{node1:t,node2:e,netName:n}=this.pendingEdges.shift(),s=this.createOffboardEdge(t,e,n);this.enhancedEdges.push(s),this.createdEdges.push(s)}else this.animationState="done",this.solved=!0;break;case"done":this.solved=!0}}createOffboardEdge(t,e,n){return{capacityMeshEdgeId:"offboard_"+this.nextEdgeId++,nodeIds:[t.capacityMeshNodeId,e.capacityMeshNodeId],isOffboardEdge:!0,offboardNetName:n}}visualize(){const t=[],e=[],n=[],s=new Set(this.shownNodes.map(t=>t.capacityMeshNodeId));for(const e of this.capacityEdges){if(e.isOffboardEdge)continue;if(s.has(e.nodeIds[0])||s.has(e.nodeIds[1])){const n=this.nodeMap.get(e.nodeIds[0]),s=this.nodeMap.get(e.nodeIds[1]);n&&s&&t.push({points:[n.center,s.center],strokeColor:"rgba(0, 200, 0, 0.5)",strokeWidth:.05})}}for(let t=0;t<this.shownNodes.length;t++){const s=this.shownNodes[t],o=s._assignedViaObstacle,i=t===this.shownNodes.length-1&&"showing_nodes"===this.animationState;n.push({center:s.center,width:s.width,height:s.height,fill:i?"rgba(255, 165, 0, 0.5)":"rgba(173, 216, 230, 0.5)",stroke:i?"orange":"blue",strokeWidth:i?.15:.1}),e.push({x:s.center.x,y:s.center.y,color:i?"orange":"blue",label:`${i?"NEW: ":""}${s.capacityMeshNodeId}\n${o?.offBoardConnectsTo?.join(", ")||""}`})}for(let n=0;n<this.createdEdges.length;n++){const s=this.createdEdges[n],o=n===this.createdEdges.length-1&&"showing_edges"===this.animationState,i=this.nodeMap.get(s.nodeIds[0]),r=this.nodeMap.get(s.nodeIds[1]);if(i&&r){t.push({points:[i.center,r.center],strokeColor:o?"red":"orange",strokeWidth:o?.2:.1,strokeDasharray:"0.3,0.15"});const n=La(i.center,r.center);e.push({x:n.x,y:n.y,color:o?"red":"orange",label:`${o?"NEW: ":""}⚡ ${s.offboardNetName}`})}}let o="Offboard Capacity Node Solver";switch(this.animationState){case"showing_nodes":o+=` - Showing nodes (${this.shownNodes.length}/${this.shownNodes.length+this.assignableNodes.length})`;break;case"showing_edges":o+=` - Creating edges (${this.createdEdges.length}/${this.createdEdges.length+this.pendingEdges.length})`;break;case"done":o+=` - Done (${this.shownNodes.length} nodes, ${this.createdEdges.length} edges)`}return{lines:t,points:e,rects:n,title:o}}getVirtualOffboardNodes(){return[]}getOffboardEdges(){return this.enhancedEdges.filter(t=>t.isOffboardEdge)}};function Xa(t,e){return t.x>=e.center.x-e.width/2&&t.x<=e.center.x+e.width/2&&t.y>=e.center.y-e.height/2&&t.y<=e.center.y+e.height/2}var Ya=class extends y{inputPaths;capacityEdges;originalConnections;fragmentedPaths=[];fragmentedConnections=[];fragmentedOriginalConnectionNames=new Set;nextFragmentId=0;animationState="showing_original_path";currentPath=null;currentFragments=[];currentFragmentIndex=0;nodeMap=new Map;constructor({capacityPaths:t,capacityEdges:e,capacityNodes:n,connections:s}){super(),this.inputPaths=[...t],this.capacityEdges=e,this.originalConnections=s,this.nodeMap=Da(n)}_step(){switch(this.animationState){case"showing_original_path":if(0===this.inputPaths.length)return this.animationState="done",void(this.solved=!0);this.currentPath=this.inputPaths.shift(),this.currentFragments=this.splitPath(this.currentPath),this.currentFragmentIndex=0;this.currentFragments.some(t=>t.isFragmentedPath)?this.animationState="showing_fragment":this.fragmentedPaths.push(...this.currentFragments);break;case"showing_fragment":if(this.currentFragmentIndex<this.currentFragments.length){const t=this.currentFragments[this.currentFragmentIndex];this.fragmentedPaths.push(t),this.currentFragmentIndex++}else this.currentPath&&(this.fragmentedOriginalConnectionNames.add(this.currentPath.connectionName),this.createFragmentConnections(this.currentPath,this.currentFragments)),this.currentPath=null,this.currentFragments=[],this.currentFragmentIndex=0,this.animationState="showing_original_path";break;case"done":this.solved=!0}}createFragmentConnections(t,e){const n=this.originalConnections.find(e=>e.name===t.connectionName);if(n)for(let t=0;t<e.length;t++){const s=e[t];if(!s.isFragmentedPath)continue;const o=n.pointsToConnect.filter(t=>{for(const e of s.nodeIds){const n=this.nodeMap.get(e);if(n&&Xa(t,n))return!0}return!1}),i=0===t,r=i?s.nodeIds[s.nodeIds.length-1]:s.nodeIds[0],a=this.nodeMap.get(r);if(o.length>0&&a){const t=o[0],e={x:a.center.x,y:a.center.y,layer:Ue(t)},r=i?[...o,e]:[e,...o];this.fragmentedConnections.push({name:s.connectionName,pointsToConnect:r,netConnectionName:n.netConnectionName,rootConnectionName:n.rootConnectionName})}}}splitPath(t){const{nodeIds:e}=t;if(e.length<2)return[t];const n=[];for(let t=0;t<e.length-1;t++){const s=this.capacityEdges.find(n=>n.nodeIds[0]===e[t]&&n.nodeIds[1]===e[t+1]||n.nodeIds[0]===e[t+1]&&n.nodeIds[1]===e[t]);s&&s.isOffboardEdge&&n.push(t)}if(0===n.length)return[t];const s=[];let o=0,i=0;for(const r of n){const n=e.slice(o,r+1);if(n.length>=1){const e=this.nextFragmentId++;s.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${i++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}o=r+1}if(o<e.length){const n=e.slice(o);if(n.length>=1){const e=this.nextFragmentId++;s.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${i++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}}return s.length>0?s:[t]}getFragmentedPaths(){return this.fragmentedPaths}getFragmentedConnections(){return this.fragmentedConnections}getFragmentedOriginalConnectionNames(){return this.fragmentedOriginalConnectionNames}visualize(){const t=[],e=[],n=[];if("showing_original_path"===this.animationState&&this.currentPath&&this.drawPath({path:this.currentPath,color:"gray",lines:t,points:e,rects:n,labelPrefix:"Original: "}),this.fragmentedPaths.forEach((s,o)=>{if(s.isFragmentedPath){const i=o%2==0?"blue":"red";this.drawPath({path:s,color:i,lines:t,points:e,rects:n,labelPrefix:`Frag ${o}: `})}else this.drawPath({path:s,color:"green",lines:t,points:e,rects:n,labelPrefix:""})}),"showing_fragment"===this.animationState&&this.currentFragmentIndex>0){const s=this.fragmentedPaths.length-1;if(s>=0){const o=this.fragmentedPaths[s];o.isFragmentedPath&&this.drawPath({path:o,color:"orange",lines:t,points:e,rects:n,labelPrefix:"NEW: "})}}for(const e of this.capacityEdges)if(e.isOffboardEdge){const n=this.nodeMap.get(e.nodeIds[0]),s=this.nodeMap.get(e.nodeIds[1]);n&&s&&t.push({points:[n.center,s.center],strokeColor:"orange",strokeWidth:.15,strokeDasharray:"0.3,0.15"})}let s="Offboard Path Fragment Solver";return"showing_original_path"===this.animationState?s+=" - Analyzing path...":"showing_fragment"===this.animationState?s+=` - Fragment ${this.currentFragmentIndex}/${this.currentFragments.length}`:s+=` - Done (${this.fragmentedPaths.filter(t=>t.isFragmentedPath).length} fragments)`,{lines:t,points:e,rects:n,title:s}}drawPath(t){const{path:e,color:n,lines:s,points:o,rects:i,labelPrefix:r}=t,a=[];for(let t=0;t<e.nodeIds.length;t++){const s=e.nodeIds[t],c=this.nodeMap.get(s);c&&(a.push(c.center),i.push({center:c.center,width:.8*c.width,height:.8*c.height,stroke:n,strokeWidth:.05,fill:`${n}33`}),0!==t&&t!==e.nodeIds.length-1||o.push({x:c.center.x,y:c.center.y,color:n,label:`${r}${e.connectionName}\n${s}`}))}a.length>1&&s.push({points:a,strokeColor:n,strokeWidth:.1})}};function $a(t,e,n,s={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:s.onSolved}}var ka=class extends y{constructor(t,e={}){if(super(),this.srj=t,this.opts=e,this.MAX_ITERATIONS=1e8,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,s=t.bounds.maxY-t.bounds.minY,o=Math.max(n,s),i=e.targetMinCapacity??.5;e.capacityDepth=Be(o,i)}this.connMap=$e(t),this.colorMap=ot(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;initialPathingSolver;initialPathingHyperSolver;pathingOptimizer;edgeToPortSegmentSolver;colorMap;segmentToPointSolver;unravelMultiSectionSolver;segmentToPointOptimizer;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;mergeAssignableViaNodes;offboardCapacityNodeSolver;offboardPathFragmentSolver;strawSolver;deadEndSolver;uselessViaRemovalSolver1;uselessViaRemovalSolver2;multiSimplifiedPathSolver1;multiSimplifiedPathSolver2;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;cacheProvider=null;pipelineDef=[$a("netToPointPairsSolver",fn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=ot(t.srjWithPointPairs,this.connMap),t.connMap=$e(t.srjWithPointPairs)}}),$a("nodeSolver",Ea,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),$a("mergeAssignableViaNodes",Aa,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.mergeAssignableViaNodes?.newNodes}}),$a("singleLayerNodeMerger",wa,t=>[t.capacityNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),$a("edgeSolver",cn,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),$a("offboardCapacityNodeSolver",Fa,t=>[{capacityNodes:t.capacityNodes,capacityEdges:t.capacityEdges||[]}],{onSolved:t=>{t.capacityEdges=t.offboardCapacityNodeSolver?.enhancedEdges||t.capacityEdges}}),$a("deadEndSolver",Oi,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges}],{onSolved:t=>{const e=t.deadEndSolver?.removedNodeIds;t.capacityNodes=t.capacityNodes.filter(t=>!e.has(t.capacityMeshNodeId)),t.capacityEdges=t.capacityEdges.filter(t=>t.nodeIds.every(t=>!e.has(t)))}}),$a("initialPathingHyperSolver",za,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}],{onSolved:t=>{const e=t.initialPathingHyperSolver?.winningSolver;e&&(t.initialPathingSolver=e)}}),$a("offboardPathFragmentSolver",Ya,t=>[{capacityPaths:t.initialPathingSolver?.getCapacityPaths()||[],capacityEdges:t.capacityEdges||[],capacityNodes:t.capacityNodes||[],connections:t.srjWithPointPairs?.connections||[]}],{onSolved:t=>{const e=t.offboardPathFragmentSolver;if(!e)return;const n=e.getFragmentedPaths();for(const e of n)if(e.isFragmentedPath&&e.mstPairConnectionName){const n=t.colorMap[e.mstPairConnectionName];n&&!t.colorMap[e.connectionName]&&(t.colorMap[e.connectionName]=n)}const s=e.getFragmentedOriginalConnectionNames(),o=e.getFragmentedConnections();s.size>0&&t.srjWithPointPairs&&(t.srjWithPointPairs={...t.srjWithPointPairs,connections:[...t.srjWithPointPairs.connections.filter(t=>!s.has(t.name)),...o]},t.connMap=$e(t.srjWithPointPairs))}}),$a("edgeToPortSegmentSolver",qo,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.offboardPathFragmentSolver?.getFragmentedPaths()||t.initialPathingSolver?.getCapacityPaths()||[],colorMap:t.colorMap}]),$a("segmentToPointSolver",ni,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),$a("unravelMultiSectionSolver",mi,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),$a("highDensityRouteSolver",Le,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap}]),$a("highDensityStitchSolver",nn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),$a("uselessViaRemovalSolver1",ao,t=>[{unsimplifiedHdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),$a("multiSimplifiedPathSolver1",Po,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver1?.getOptimizedHdRoutes()||t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}]),$a("uselessViaRemovalSolver2",ao,t=>[{unsimplifiedHdRoutes:t.multiSimplifiedPathSolver1.simplifiedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),$a("multiSimplifiedPathSolver2",Po,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver2?.getOptimizedHdRoutes(),obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}])];getConstructorParams(){return[this.srj,this.opts]}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 t=this.netToPointPairsSolver?.visualize(),e=this.nodeSolver?.visualize(),n=this.nodeTargetMerger?.visualize(),s=this.mergeAssignableViaNodes?.visualize(),o=this.singleLayerNodeMerger?.visualize(),i=this.strawSolver?.visualize(),r=this.edgeSolver?.visualize(),a=(this.offboardCapacityNodeSolver?.visualize(),this.deadEndSolver?.visualize()),c=this.initialPathingSolver?.visualize(),h=this.offboardPathFragmentSolver?.visualize(),d=this.pathingOptimizer?.visualize(),l=this.edgeToPortSegmentSolver?.visualize(),u=this.segmentToPointSolver?.visualize(),p=this.unravelMultiSectionSolver?.visualize()??this.segmentToPointOptimizer?.visualize(),m=this.highDensityRouteSolver?.visualize(),f=this.highDensityStitchSolver?.visualize(),y=this.uselessViaRemovalSolver1?.visualize(),x=this.uselessViaRemovalSolver2?.visualize(),v=this.multiSimplifiedPathSolver1?.visualize(),S=this.multiSimplifiedPathSolver2?.visualize(),P=this.srj.outline,b=[];if(b.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),P&&P.length>=2){const t=P.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),b.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const M={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:t.layers?.join(", ")}))],lines:b},N=[M,t,e,n,s,o,i,r,a,c,h,d,l,u,p,m?g(M,m):null,f,y,v,x,S,this.solved?g(M,sn(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...N)}preview(){if(this.highDensityRouteSolver){const t=[];for(let e=this.highDensityRouteSolver.routes.length-1;e>=0;e--){const n=this.highDensityRouteSolver.routes[e];if(t.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[n.connectionName]}),t.length>200)break}return{lines:t}}if(this.pathingOptimizer){const t=[];for(const e of this.pathingOptimizer.connectionsWithNodes)e.path&&t.push({points:e.path.map(t=>({x:t.center.x,y:t.center.y})),strokeColor:this.colorMap[e.connection.name]});return{lines:t}}return this.netToPointPairsSolver?this.netToPointPairsSolver?.visualize():{}}_getOutputHdRoutes(){return this.multiSimplifiedPathSolver2?.simplifiedHdRoutes??this.uselessViaRemovalSolver2?.getOptimizedHdRoutes()??this.multiSimplifiedPathSolver1?.simplifiedHdRoutes??this.uselessViaRemovalSolver1?.getOptimizedHdRoutes()??this.highDensityStitchSolver.mergedHdRoutes}getOutputSimplifiedPcbTraces(){if(!this.solved||!this.highDensityRouteSolver)throw new Error("Cannot get output before solving is complete");const t=[],e=this._getOutputHdRoutes(),n=this.srjWithPointPairs?.connections??[];for(const s of n){const n=s.netConnectionName,o=s.rootConnectionName,i=e.filter(t=>t.connectionName===s.name);for(let e=0;e<i.length;e++){const r=i[e],a={type:"pcb_trace",pcb_trace_id:`${s.name}_${e}`,connection_name:n??o??s.name,route:We(r,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Ba=1.8,ja=.95,Wa=.8,Ha=.95,Ua=class extends y{obstacleRoutes;bounds;boundsSize;boundsCenter;A;B;roundedGoalPosition;straightLineDistance;traceThickness;obstacleMargin;minCellSize=.05;cellStep=.05;GREEDY_MULTIPLER=1.1;numRoutes;JUMPER_PENALTY_FACTOR;FUTURE_CONNECTION_START_END_PENALTY;FUTURE_CONNECTION_START_END_PROXIMITY;FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY;FUTURE_CONNECTION_JUMPER_PAD_PENALTY;JUMPER_JUMPER_PAD_PROXIMITY;JUMPER_JUMPER_PAD_PENALTY;FUTURE_CONNECTION_LINE_PROXIMITY;FUTURE_CONNECTION_LINE_PENALTY;OBSTACLE_PROX_PENALTY_FACTOR;OBSTACLE_PROX_SIGMA;EDGE_PROX_PENALTY_FACTOR;EDGE_PROX_SIGMA;ALLOW_DIAGONAL;MIN_TRAVEL_BEFORE_JUMPER;CELL_SIZE_FACTOR;exploredNodes;candidates;connectionName;rootConnectionName;solvedPath=null;futureConnections;hyperParameters;connMap;debug_exploredNodesOrdered;debug_exploredNodeValues;debug_nodesTooCloseToObstacle;debug_nodePathToParentIntersectsObstacle;debugEnabled=!0;initialNodeGridOffset;existingJumpers;constructor(t){super(),this.bounds=t.bounds,this.connMap=t.connMap,this.hyperParameters=t.hyperParameters??{};const e=Math.sqrt((t.bounds.maxX-t.bounds.minX)**2+(t.bounds.maxY-t.bounds.minY)**2);this.CELL_SIZE_FACTOR=this.hyperParameters.CELL_SIZE_FACTOR??1,this.JUMPER_PENALTY_FACTOR=.2,this.FUTURE_CONNECTION_START_END_PROXIMITY??=8,this.FUTURE_CONNECTION_START_END_PENALTY??=3,this.FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY=this.hyperParameters.FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY??e/4,this.FUTURE_CONNECTION_JUMPER_PAD_PENALTY=this.hyperParameters.FUTURE_CONNECTION_JUMPER_PAD_PENALTY??1e3,this.JUMPER_JUMPER_PAD_PROXIMITY=this.hyperParameters.JUMPER_JUMPER_PAD_PROXIMITY??5,this.JUMPER_JUMPER_PAD_PENALTY=this.hyperParameters.JUMPER_JUMPER_PAD_PENALTY??0,this.FUTURE_CONNECTION_LINE_PROXIMITY=this.hyperParameters.FUTURE_CONNECTION_LINE_PROXIMITY??10,this.FUTURE_CONNECTION_LINE_PENALTY=this.hyperParameters.FUTURE_CONNECTION_LINE_PENALTY??5,this.OBSTACLE_PROX_PENALTY_FACTOR=this.hyperParameters.OBSTACLE_PROX_PENALTY_FACTOR??2,this.OBSTACLE_PROX_SIGMA=this.hyperParameters.OBSTACLE_PROX_SIGMA??2,this.EDGE_PROX_PENALTY_FACTOR=this.hyperParameters.EDGE_PROX_PENALTY_FACTOR??1,this.EDGE_PROX_SIGMA=this.hyperParameters.EDGE_PROX_SIGMA??1,this.ALLOW_DIAGONAL=this.hyperParameters.ALLOW_DIAGONAL??!0,this.MIN_TRAVEL_BEFORE_JUMPER??=3,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.rootConnectionName=t.rootConnectionName,this.obstacleRoutes=t.obstacleRoutes,this.A={...t.A,z:0},this.B={...t.B,z:0},this.traceThickness=t.traceThickness??.15,this.obstacleMargin=t.obstacleMargin??.2,this.exploredNodes=new Set,this.straightLineDistance=St(this.A,this.B),this.futureConnections=t.futureConnections??[],this.MAX_ITERATIONS=1e4,this.debug_exploredNodesOrdered=[],this.debug_exploredNodeValues=new Map,this.debug_nodesTooCloseToObstacle=new Set,this.debug_nodePathToParentIntersectsObstacle=new Set,this.numRoutes=this.obstacleRoutes.length+this.futureConnections.length,this.existingJumpers=[];for(const t of this.obstacleRoutes)t.jumpers&&this.existingJumpers.push(...t.jumpers);const n=Math.ceil(5*(this.numRoutes+1));let s=this.boundsSize.width/this.cellStep,o=this.boundsSize.height/this.cellStep;for(;s*o>n**2&&!(this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,s=this.boundsSize.width/this.cellStep,o=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR;const i=Math.abs(this.A.x-this.bounds.minX)<.001&&Math.abs(this.B.x-this.bounds.minX)<.001||Math.abs(this.A.x-this.bounds.maxX)<.001&&Math.abs(this.B.x-this.bounds.maxX)<.001||Math.abs(this.A.y-this.bounds.minY)<.001&&Math.abs(this.B.y-this.bounds.minY)<.001||Math.abs(this.A.y-this.bounds.maxY)<.001&&Math.abs(this.B.y-this.bounds.maxY)<.001;this.futureConnections&&0===this.futureConnections.length&&0===this.obstacleRoutes.length&&!i&&this.handleSimpleCases();const r={x:t.A.x,y:t.A.y};this.initialNodeGridOffset={x:r.x-Math.round(t.A.x/this.cellStep)*this.cellStep,y:r.y-Math.round(t.A.y/this.cellStep)*this.cellStep},this.roundedGoalPosition={x:Math.round(t.B.x/this.cellStep)*this.cellStep,y:Math.round(t.B.y/this.cellStep)*this.cellStep,z:0};const a={distFromStart:0,weightedMmNearObstacle:0,weightedMmNearEdge:0,weightedMmNearFutureConnectionStartEnd:0,weightedMmNearFutureConnectionLine:0,jumperPenalty:0,jumperPadFutureConnectionPenalty:0,total:0},c={distanceToGoal:0,obstacleProximity:0,edgeProximity:0,futureConnectionStartEndProximityPenalty:0,futureConnectionLine:0,total:0,obstacleProximityRate:0,edgeProximityRate:0,futureConnectionStartEndProximityRate:0,futureConnectionLineRate:0};this.candidates=new zt([{...t.A,...r,z:0,g:0,h:0,f:0,jumperCount:0,gComponents:a,hComponents:c,parent:{...t.A,z:0,g:0,h:0,f:0,gComponents:a,hComponents:c,parent:null}}])}handleSimpleCases(){this.solved=!0;const{A:t,B:e}=this;this.solvedPath={connectionName:this.connectionName,rootConnectionName:this.rootConnectionName,route:[{x:t.x,y:t.y,z:0},{x:e.x,y:e.y,z:0}],traceThickness:this.traceThickness,jumpers:[]}}get jumperPenaltyDistance(){return Ba+this.straightLineDistance*this.JUMPER_PENALTY_FACTOR}isNodeTooCloseToObstacle(t,e){e??=this.obstacleMargin;for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!s){const s=Va(n);for(const n of s)if(vt(t,n.A,n.B)<this.traceThickness+e)return!0}for(const s of n.jumpers||[])if(this.isNodeTooCloseToJumper(t,s,e))return!0}return!1}isNodeTooCloseToJumper(t,e,n){const s=e.end.x-e.start.x,o=e.end.y-e.start.y,i=Math.abs(s)>Math.abs(o),r=(i?Wa:Ha)/2+n,a=(i?Ha:Wa)/2+n;return Math.abs(t.x-e.start.x)<r&&Math.abs(t.y-e.start.y)<a||Math.abs(t.x-e.end.x)<r&&Math.abs(t.y-e.end.y)<a}isNodeTooCloseToEdge(t){const e=t.gComponents?.distFromStart??0<this.obstacleMargin/2?-this.obstacleMargin/2:this.obstacleMargin/2,n=t.x<this.bounds.minX+e||t.x>this.bounds.maxX-e||t.y<this.bounds.minY+e||t.y>this.bounds.maxY-e;return(!n||!(St(t,this.B)<2*e||St(t,this.A)<2*e))&&n}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!s){for(const s of Va(n))if(gt(t,e,s.A,s.B))return!0;for(const s of n.jumpers||[])if(this.doesSegmentIntersectJumperPads(t,e,s))return!0}}return!1}doesSegmentIntersectJumperPads(t,e,n){const s=this.obstacleMargin,o=n.end.x-n.start.x,i=n.end.y-n.start.y,r=Math.abs(o)>Math.abs(i),a=(r?Wa:Ha)/2+s,c=(r?Ha:Wa)/2+s;return!!this.doesSegmentIntersectRect(t,e,n.start,a,c)||!!this.doesSegmentIntersectRect(t,e,n.end,a,c)}doesSegmentIntersectRect(t,e,n,s,o){const i=n.x-s,r=n.x+s,a=n.y-o,c=n.y+o;if(t.x>=i&&t.x<=r&&t.y>=a&&t.y<=c)return!0;if(e.x>=i&&e.x<=r&&e.y>=a&&e.y<=c)return!0;const h=[{A:{x:i,y:a},B:{x:r,y:a}},{A:{x:r,y:a},B:{x:r,y:c}},{A:{x:r,y:c},B:{x:i,y:c}},{A:{x:i,y:c},B:{x:i,y:a}}];for(const n of h)if(gt(t,e,n.A,n.B))return!0;return!1}findObstaclesBetween(t,e){const n=[];for(const s of this.obstacleRoutes){const o=this.connMap?.areIdsConnected?.(this.connectionName,s.connectionName);if(!o)for(const o of Va(s))gt(t,e,o.A,o.B)&&n.push({A:o.A,B:o.B})}return n}computeHComponents(t){const e=St(t,this.roundedGoalPosition),n=this.getObstacleProximityPenalty(t),s=this.getEdgeProximityPenalty(t),o=this.getFutureConnectionStartEndPenalty(t),i=this.getFutureConnectionLinePenalty(t),r=t.parent,a=r?.hComponents,c=r?St(t,r):0,h=(t,n)=>{if(void 0===n||c<1e-9||e<1e-9)return t;const s=(t-n)/c;return(t+Math.max(0,t+s*e))/2},d=h(n,a?.obstacleProximityRate),l=h(s,a?.edgeProximityRate),u=h(o,a?.futureConnectionStartEndProximityRate),p=h(i,a?.futureConnectionLineRate),m=d*e,f=l*e,g=u*e,y=p*e;return{distanceToGoal:e,obstacleProximity:m,edgeProximity:f,futureConnectionStartEndProximityPenalty:g,futureConnectionLine:y,total:e+m+f+g+y,obstacleProximityRate:n,edgeProximityRate:s,futureConnectionStartEndProximityRate:o,futureConnectionLineRate:i}}computeH(t){return this.computeHComponents(t).total}computeGComponents(t){const e=t.parent,n=e?St(t,e):0,s=e?.gComponents??{distFromStart:0,weightedMmNearObstacle:0,weightedMmNearEdge:0,weightedMmNearFutureConnectionStartEnd:0,weightedMmNearFutureConnectionLine:0,jumperPenalty:0,jumperPadFutureConnectionPenalty:0,total:0},o=s.distFromStart+n,i=s.weightedMmNearObstacle+this.getObstacleProximityPenalty(t)*n,r=s.weightedMmNearEdge+this.getEdgeProximityPenalty(t)*n,a=s.weightedMmNearFutureConnectionStartEnd+this.getFutureConnectionStartEndPenalty(t)*n,c=s.weightedMmNearFutureConnectionLine+this.getFutureConnectionLinePenalty(t)*n;let h=s.jumperPenalty,d=s.jumperPadFutureConnectionPenalty;t.isJumperExit&&(h+=this.jumperPenaltyDistance,d+=this.getJumperPadFutureConnectionPenalty(t));return{distFromStart:o,weightedMmNearObstacle:i,weightedMmNearEdge:r,weightedMmNearFutureConnectionStartEnd:a,weightedMmNearFutureConnectionLine:c,jumperPenalty:h,jumperPadFutureConnectionPenalty:d,total:o+i+r+a+c+h+d}}computeG(t){return this.computeGComponents(t).total}computeF(t,e){return t+e*this.GREEDY_MULTIPLER}getClosestFutureConnectionPoint(t){let e=1/0,n=null;for(const s of this.futureConnections)for(const o of s.points){const s=St(t,o);s<e&&(e=s,n=o)}return n}getFutureConnectionStartEndPenalty(t){let e=0;const n=this.getClosestFutureConnectionPoint(t);if(n){const s=St(t,n);if(s>this.FUTURE_CONNECTION_START_END_PROXIMITY)return 0;const o=s/this.FUTURE_CONNECTION_START_END_PROXIMITY;e=this.FUTURE_CONNECTION_START_END_PENALTY*(1-o)**2}return e}getFutureConnectionLinePenalty(t){if(0===this.futureConnections.length)return 0;let e=1/0;const n=Math.min(1,(t.hComponents?.distanceToGoal??0)/this.FUTURE_CONNECTION_LINE_PROXIMITY)**2;for(const n of this.futureConnections){if(n.points.length<2)continue;const s=vt(t,n.points[0],n.points[n.points.length-1]);e=Math.min(e,s)}if(e*=n,e<this.FUTURE_CONNECTION_LINE_PROXIMITY){const t=Math.max(.1,e/this.FUTURE_CONNECTION_LINE_PROXIMITY);return this.FUTURE_CONNECTION_LINE_PENALTY*(1-t)**2}return 0}getJumperPadFutureConnectionPenalty(t){if(!t.isJumperExit||!t.jumperEntry)return 0;const e=t.jumperEntry,n={x:t.x,y:t.y};let s=1/0;for(const t of this.futureConnections)for(const o of t.points){const t=St(e,o),i=St(n,o),r=Math.min(t,i);s=Math.min(s,r)}if(s<this.FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY){const t=s/this.FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY;return this.FUTURE_CONNECTION_JUMPER_PAD_PENALTY*(1-t)}return 0}getClearanceToObstacles(t){let e=1/0;for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!s){for(const s of Va(n))e=Math.min(e,vt(t,s.A,s.B));for(const s of n.jumpers||[])e=Math.min(e,this.distanceToJumperPads(t,s))}}return e}distanceToJumperPads(t,e){const n=e.end.x-e.start.x,s=e.end.y-e.start.y,o=Math.abs(n)>Math.abs(s),i=(o?Wa:Ha)/2,r=(o?Ha:Wa)/2;return Math.min(this.pointToRectDistance(t,e.start,i,r),this.pointToRectDistance(t,e.end,i,r))}pointToRectDistance(t,e,n,s){const o=Math.max(Math.abs(t.x-e.x)-n,0),i=Math.max(Math.abs(t.y-e.y)-s,0);return Math.hypot(o,i)}getClearanceToEdge(t){return Math.min(t.x-this.bounds.minX,this.bounds.maxX-t.x,t.y-this.bounds.minY,this.bounds.maxY-t.y)}getObstacleProximityPenalty(t){const e=this.getClearanceToObstacles(t),n=Math.max(0,e-(this.traceThickness+this.obstacleMargin)),s=this.OBSTACLE_PROX_SIGMA;return this.OBSTACLE_PROX_PENALTY_FACTOR*Math.exp(-n/s)}getEdgeProximityPenalty(t){const e=this.getClearanceToEdge(t),n=this.EDGE_PROX_SIGMA;if(e>2*this.EDGE_PROX_SIGMA)return 0;const s=St(t,this.B),o=Math.min(1,s/(2*this.EDGE_PROX_SIGMA));return this.EDGE_PROX_PENALTY_FACTOR*Math.exp(-e/n)*o}getNodeKey(t){const e=t.isJumperExit?"_j":"";return`${Math.round(t.x/this.cellStep)*this.cellStep},${Math.round(t.y/this.cellStep)*this.cellStep},${t.z}${e}`}getJumperNeighbors(t){const e=[];if((t.gComponents?.distFromStart??0)<this.MIN_TRAVEL_BEFORE_JUMPER)return e;const n=[{dx:1,dy:0},{dx:-1,dy:0},{dx:0,dy:1},{dx:0,dy:-1}];for(const s of n){const n=2*Ba,o=t.x+s.dx*n,i=t.y+s.dy*n,r=this.findObstaclesBetween(t,{x:o,y:i});if(r.length>0)for(const n of r){const o=this.calculateJumperExit(t,n,s);o&&!this.exploredNodes.has(this.getNodeKey(o))&&(this.isNodeTooCloseToObstacle(o)||this.isNodeTooCloseToEdge(o)||!this.isJumperPlacementValid(t,o)||(o.gComponents=this.computeGComponents(o),o.hComponents=this.computeHComponents(o),o.g=o.gComponents.total,o.h=o.hComponents.total,o.f=this.computeF(o.g,o.h),e.push(o)))}}return e}calculateJumperExit(t,e,n){const s=Ba,o=Math.sqrt(n.dx*n.dx+n.dy*n.dy),i=n.dx/o,r=n.dy/o,a=t.x+i*s,c=t.y+r*s;return a<this.bounds.minX||a>this.bounds.maxX||c<this.bounds.minY||c>this.bounds.maxY?null:{x:a,y:c,z:0,parent:t,g:0,h:0,f:0,jumperEntry:{x:t.x,y:t.y},isJumperExit:!0,jumperCount:(t.jumperCount??0)+1}}isJumperTooCloseToTraces(t,e){const n=e.x-t.x,s=e.y-t.y,o=Math.abs(n)>Math.abs(s),i=(o?Wa:Ha)/2,r=(o?Ha:Wa)/2,a=this.obstacleMargin,c=[t,e];for(const t of c){const e=[t,{x:t.x-i,y:t.y-r},{x:t.x+i,y:t.y-r},{x:t.x-i,y:t.y+r},{x:t.x+i,y:t.y+r},{x:t.x-i,y:t.y},{x:t.x+i,y:t.y},{x:t.x,y:t.y-r},{x:t.x,y:t.y+r}];for(const n of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(s)continue;const o=Va(n);for(const n of o){for(const t of e)if(vt(t,n.A,n.B)<this.traceThickness+a)return!0;if(this.doesSegmentIntersectRect(n.A,n.B,t,i+a,r+a))return!0}}}return!1}isJumperPlacementValid(t,e){if(this.isJumperTooCloseToTraces(t,e))return!1;const n={route_type:"jumper",start:{x:t.x,y:t.y},end:{x:e.x,y:e.y},footprint:"0603"};for(const t of this.existingJumpers)if(this.doJumpersOverlap(n,t))return!1;const s=this.getJumpersInPath(t);for(const t of s)if(this.doJumpersOverlap(n,t))return!1;return!0}doJumpersOverlap(t,e){const n=this.obstacleMargin,s=Math.min(t.start.x,t.end.x)-ja/2-n,o=Math.max(t.start.x,t.end.x)+ja/2+n,i=Math.min(t.start.y,t.end.y)-ja/2-n,r=Math.max(t.start.y,t.end.y)+ja/2+n,a=Math.min(e.start.x,e.end.x)-ja/2-n,c=Math.max(e.start.x,e.end.x)+ja/2+n,h=Math.min(e.start.y,e.end.y)-ja/2-n,d=Math.max(e.start.y,e.end.y)+ja/2+n;return!(o<a||s>c||r<h||i>d)}getJumpersInPath(t){const e=[];let n=t;for(;n&&n.parent;)n.isJumperExit&&n.jumperEntry&&e.push({route_type:"jumper",start:n.jumperEntry,end:{x:n.x,y:n.y},footprint:"0603"}),n=n.parent;return e}getNeighbors(t){const e=[],{maxX:n,minX:s,maxY:o,minY:i}=this.bounds;for(let r=-1;r<=1;r++)for(let a=-1;a<=1;a++){if(0===r&&0===a)continue;if(!this.ALLOW_DIAGONAL&&0!==r&&0!==a)continue;const c=t.x+r*this.cellStep,h=t.y+a*this.cellStep,d=Za(c,s,n),l=Za(h,i,o),u={...t,parent:t,x:d,y:l,isJumperExit:!1,jumperEntry:void 0,jumperCount:t.jumperCount??0},p=this.getNodeKey(u);this.exploredNodes.has(p)||(this.isNodeTooCloseToObstacle(u)?(this.debug_nodesTooCloseToObstacle.add(p),this.exploredNodes.add(p)):this.isNodeTooCloseToEdge(u)?this.debug_nodesTooCloseToObstacle.add(p):this.doesPathToParentIntersectObstacle(u)?(this.debug_nodePathToParentIntersectsObstacle.add(p),this.exploredNodes.add(p)):(u.gComponents=this.computeGComponents(u),u.hComponents=this.computeHComponents(u),u.g=u.gComponents.total,u.h=u.hComponents.total,u.f=this.computeF(u.g,u.h),e.push(u)))}const r=this.getJumperNeighbors(t);return e.push(...r),e}getNodePath(t){const e=[];let n=t;for(;n;)e.push(n),n=n.parent;return e}setSolvedPath(t){const e=this.getNodePath(t);e.reverse();const n=[];for(let t=0;t<e.length;t++){const s=e[t];s.isJumperExit&&s.jumperEntry&&n.push({route_type:"jumper",start:s.jumperEntry,end:{x:s.x,y:s.y},footprint:"0603"})}this.solvedPath={connectionName:this.connectionName,rootConnectionName:this.rootConnectionName,traceThickness:this.traceThickness,route:e.map(t=>({x:t.x,y:t.y,z:0})).concat([{x:this.B.x,y:this.B.y,z:0}]),jumpers:n}}computeProgress(t,e){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 this.failed=!0,void(this.error="Ran out of candidate nodes to explore");this.exploredNodes.add(e),this.debug_exploredNodesOrdered.push(e),this.debug_exploredNodeValues.set(e,{g:t.g,h:t.h,f:t.f,gComponents:t.gComponents,hComponents:t.hComponents});const n=St(t,this.roundedGoalPosition);this.progress=this.computeProgress(t,n),n<=this.cellStep*Math.SQRT2&&!this.doesPathToParentIntersectObstacle({...t,parent:t,x:this.B.x,y:this.B.y})&&(this.solved=!0,this.setSolvedPath(t));const s=this.getNeighbors(t);for(const t of s)this.candidates.enqueue(t)}drawJumperPads(t,e,n,s,o){const i=e.end.x-e.start.x,r=e.end.y-e.start.y,a=Wa,c=Ha,h=Math.abs(i)>Math.abs(r),d=h?a:c,l=h?c:a;t.rects.push({center:{x:e.start.x,y:e.start.y},width:d,height:l,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:s??"jumper",step:o}),t.rects.push({center:{x:e.end.x,y:e.end.y},width:d,height:l,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:s??"jumper",step:o}),t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*c,layer:s??"jumper-body",step:o})}visualize(){const t={lines:[],points:[],rects:[],circles:[]};t.points.push({x:this.A.x,y:this.A.y,label:`Input A\nz: ${this.A.z}`,color:"orange"}),t.points.push({x:this.B.x,y:this.B.y,label:`Input B\nz: ${this.B.z}`,color:"orange"}),t.lines.push({points:[this.A,this.B],strokeColor:"rgba(255, 0, 0, 0.5)",label:"Direct Input Connection"});for(let e=0;e<this.obstacleRoutes.length;e++){const n=this.obstacleRoutes[e];for(let s=0;s<n.route.length-1;s++)t.lines.push({points:[n.route[s],n.route[s+1]],strokeColor:"rgba(255, 0, 0, 0.75)",strokeWidth:n.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`});for(const s of n.jumpers||[])this.drawJumperPads(t,s,"rgba(255, 0, 0, 0.5)",`obstacle-jumper-${e}`)}for(let e=0;e<this.futureConnections.length;e++){const n=this.futureConnections[e];if(n.points.length<2)continue;const s=n.points[0],o=n.points[n.points.length-1];t.lines.push({points:[s,o],strokeColor:"rgba(0, 100, 255, 0.6)",strokeWidth:this.traceThickness,label:`Future: ${n.connectionName}`,layer:`future-connection-${e}`})}for(let e=0;e<this.debug_exploredNodesOrdered.length;e++){const n=this.debug_exploredNodesOrdered[e];if(this.debug_nodesTooCloseToObstacle.has(n))continue;if(this.debug_nodePathToParentIntersectsObstacle.has(n))continue;const[s,o]=n.split(",").map(Number),i=n.endsWith("_j"),r=this.debug_exploredNodeValues.get(n),a=r?.gComponents,c=r?.hComponents,h=c?.distanceToGoal??0,d=[i?"Explored (jumper)":"Explored"];d.push(`g.distFromStart: ${a?.distFromStart.toFixed(2)??"?"}`),d.push(`g.nearObstacle: ${a?.weightedMmNearObstacle.toFixed(2)??"?"}`),d.push(`g.nearEdge: ${a?.weightedMmNearEdge.toFixed(2)??"?"}`),d.push(`g.nearFutStrtEnd: ${a?.weightedMmNearFutureConnectionStartEnd.toFixed(2)??"?"}`),d.push(`g.nearFutLine: ${a?.weightedMmNearFutureConnectionLine.toFixed(2)??"?"}`),d.push(`g.jumper: ${a?.jumperPenalty.toFixed(2)??"?"}`),d.push(`g.jumperPadFutPenalty: ${a?.jumperPadFutureConnectionPenalty.toFixed(2)??"?"}`),d.push(`h.goalDist: ${h.toFixed(2)}`),d.push(`h.obstacleProx: ${c?.obstacleProximity.toFixed(2)??"?"} (${h>0?((c?.obstacleProximity??0)/h).toFixed(3):0}/mm)`),d.push(`h.edgeProx: ${c?.edgeProximity.toFixed(2)??"?"} (${h>0?((c?.edgeProximity??0)/h).toFixed(3):0}/mm)`),d.push(`h.futureConnPt: ${c?.futureConnectionStartEndProximityPenalty.toFixed(2)??"?"} (${h>0?((c?.futureConnectionStartEndProximityPenalty??0)/h).toFixed(3):0}/mm)`),d.push(`h.futureConnLine: ${c?.futureConnectionLine.toFixed(2)??"?"} (${h>0?((c?.futureConnectionLine??0)/h).toFixed(3):0}/mm)`),d.push(`g: ${r?.g.toFixed(2)??"?"}`),d.push(`h: ${r?.h.toFixed(2)??"?"}`),d.push(`f: ${r?.f.toFixed(2)??"?"}`);const l=d.join("\n");t.rects.push({center:{x:s+this.initialNodeGridOffset.x,y:o+this.initialNodeGridOffset.y},fill:i?`rgba(0,255,255,${.4-e/this.debug_exploredNodesOrdered.length*.3})`:`rgba(255,0,255,${.3-e/this.debug_exploredNodesOrdered.length*.2})`,width:.9*this.cellStep,height:.9*this.cellStep,label:l})}if(this.candidates.peek()){const e=this.candidates.peek();t.rects.push({center:{x:e.x,y:e.y},fill:"rgba(0, 255, 0, 0.8)",width:.9*this.cellStep,height:.9*this.cellStep,label:"Next"})}const e=this.candidates.getTopN(5);for(let n=0;n<e.length;n++){const s=e[n],o=s.isJumperExit??!1,i=s.gComponents,r=s.hComponents,a=r?.distanceToGoal??0,c=[`Candidate #${n+1}${o?" (jumper)":""}`];c.push(`g.distFromStart: ${i?.distFromStart.toFixed(2)??"?"}`),c.push(`g.nearObstacle: ${i?.weightedMmNearObstacle.toFixed(2)??"?"}`),c.push(`g.nearEdge: ${i?.weightedMmNearEdge.toFixed(2)??"?"}`),c.push(`g.nearFutureConnPt: ${i?.weightedMmNearFutureConnectionStartEnd.toFixed(2)??"?"}`),c.push(`g.nearFutureConnLine: ${i?.weightedMmNearFutureConnectionLine.toFixed(2)??"?"}`),c.push(`g.jumper: ${i?.jumperPenalty.toFixed(2)??"?"}`),c.push(`g.jumperPadFutureConn: ${i?.jumperPadFutureConnectionPenalty.toFixed(2)??"?"}`),c.push(`g: ${s.g.toFixed(2)}`),c.push(`h.goalDist: ${a.toFixed(2)}`),c.push(`h.obstacleProx: ${r?.obstacleProximity.toFixed(2)??"?"} (${a>0?((r?.obstacleProximity??0)/a).toFixed(3):0}/mm)`),c.push(`h.edgeProx: ${r?.edgeProximity.toFixed(2)??"?"} (${a>0?((r?.edgeProximity??0)/a).toFixed(3):0}/mm)`),c.push(`h.futureConnPt: ${r?.futureConnectionStartEndProximityPenalty.toFixed(2)??"?"} (${a>0?((r?.futureConnectionStartEndProximityPenalty??0)/a).toFixed(3):0}/mm)`),c.push(`h.futureConnLine: ${r?.futureConnectionLine.toFixed(2)??"?"} (${a>0?((r?.futureConnectionLine??0)/a).toFixed(3):0}/mm)`),c.push(`h: ${s.h.toFixed(2)}`),c.push(`f: ${s.f.toFixed(2)}`);const h=c.join("\n");t.points.push({x:s.x,y:s.y,color:"gray",label:h})}if(this.solvedPath){t.lines.push({points:this.solvedPath.route,strokeColor:"green",label:"Solved Route",strokeWidth:this.traceThickness});for(const e of this.solvedPath.jumpers)this.drawJumperPads(t,e,"rgba(0, 200, 0, 0.8)","solved-jumper")}const{minX:n,minY:s,maxX:o,maxY:i}=this.bounds;return t.lines.push({points:[{x:n,y:s},{x:o,y:s},{x:o,y:i},{x:n,y:i},{x:n,y:s}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}};function Va(t){const e=[];for(let n=0;n<t.route.length-1;n++)if(t.route[n].z===t.route[n+1].z){const s=t.route[n],o=t.route[n+1],i=t.jumpers?.some(t=>{const e=Math.abs(t.start.x-s.x)<.001&&Math.abs(t.start.y-s.y)<.001&&Math.abs(t.end.x-o.x)<.001&&Math.abs(t.end.y-o.y)<.001,n=Math.abs(t.start.x-o.x)<.001&&Math.abs(t.start.y-o.y)<.001&&Math.abs(t.end.x-s.x)<.001&&Math.abs(t.end.y-s.y)<.001;return e||n});i||e.push({z:s.z,A:s,B:o})}return e}function Za(t,e,n){return Math.max(e,Math.min(t,n))}var Ga=.8,Ja=.95,qa=class extends y{nodeWithPortPoints;colorMap;unsolvedConnections;totalConnections;solvedRoutes;failedSubSolvers;hyperParameters;minDistBetweenEnteringPoints;traceWidth;activeSubSolver=null;lastActiveSubSolver=null;connMap;get failedSolvers(){return this.failedSubSolvers}get activeSolver(){return this.activeSubSolver}constructor(t){const{nodeWithPortPoints:e,colorMap:n}=t;super(),this.nodeWithPortPoints=e,this.colorMap=n??{},this.solvedRoutes=[],this.hyperParameters=t.hyperParameters??{},this.failedSubSolvers=[],this.connMap=t.connMap,this.traceWidth=t.traceWidth??.15;const s=new Map;for(const{connectionName:t,rootConnectionName:n,x:o,y:i}of e.portPoints){const e=s.get(t);s.set(t,{rootConnectionName:e?.rootConnectionName??n,points:[...e?.points??[],{x:o,y:i,z:0}]})}this.unsolvedConnections=Array.from(s.entries().map(([t,{rootConnectionName:e,points:n}])=>({connectionName:t,rootConnectionName:e,points:n}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=kt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},n)=>({...e,points:kt(t,7117*n+(this.hyperParameters.SHUFFLE_SEED??0))}))),this.totalConnections=this.unsolvedConnections.length,this.MAX_ITERATIONS=1e3*this.totalConnections**1.5,this.minDistBetweenEnteringPoints=jt(this.nodeWithPortPoints)}getConstructorParams(){return{nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,hyperParameters:this.hyperParameters,connMap:this.connMap,traceWidth:this.traceWidth}}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.lastActiveSubSolver=this.activeSubSolver,this.activeSubSolver=null):this.activeSubSolver.failed&&(this.failedSubSolvers.push(this.activeSubSolver),this.lastActiveSubSolver=this.activeSubSolver,this.activeSubSolver=null,this.error=this.failedSubSolvers.map(t=>t.error).join("\n"),this.failed=!0));const t=this.unsolvedConnections.pop();if(this.progress=this.computeProgress(),!t)return void(this.solved=0===this.failedSubSolvers.length);if(1===t.points.length)return;if(2===t.points.length){const[e,n]=t.points,s=Math.abs(e.x-n.x)<1e-6,o=Math.abs(e.y-n.y)<1e-6;if(s&&o)return}const{connectionName:e,rootConnectionName:n,points:s}=t;this.activeSubSolver=new Ua({connectionName:e,rootConnectionName:n,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:Bt(this.nodeWithPortPoints),A:{x:s[0].x,y:s[0].y,z:0},B:{x:s[s.length-1].x,y:s[s.length-1].y,z:0},obstacleRoutes:this.solvedRoutes.filter(t=>(!n||t.rootConnectionName!==n)&&!this.connMap?.areIdsConnected(t.connectionName,e)),futureConnections:this.unsolvedConnections,hyperParameters:this.hyperParameters,connMap:this.connMap,traceThickness:this.traceWidth})}drawJumperPads(t,e,n,s){const o=e.end.x-e.start.x,i=e.end.y-e.start.y,r=Ga,a=Ja,c=Math.abs(o)>Math.abs(i),h=c?r:a,d=c?a:r;t.rects.push({center:{x:e.start.x,y:e.start.y},width:h,height:d,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.rects.push({center:{x:e.end.x,y:e.end.y},width:h,height:d,fill:n,stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*a,layer:"jumper-body"})}visualize(){if(this.activeSubSolver&&!this.solved)return this.activeSubSolver.visualize();if(this.failed&&this.lastActiveSubSolver)return this.lastActiveSubSolver.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: 0 (single-layer)"].join("\n"),color:this.colorMap[e.connectionName]??"blue"});for(let e=0;e<this.solvedRoutes.length;e++){const n=this.solvedRoutes[e];if(n.route.length>0){const s=this.colorMap[n.connectionName]??"blue";for(let e=0;e<n.route.length-1;e++){const o=n.route[e],i=n.route[e+1];t.lines.push({points:[o,i],strokeColor:it(s,.2),layer:"route-layer-0",strokeWidth:n.traceThickness})}for(const o of n.jumpers)this.drawJumperPads(t,o,it(s,.5),e)}}const e=Bt(this.nodeWithPortPoints),{minX:n,minY:s,maxX:o,maxY:i}=e;return t.lines.push({points:[{x:n,y:s},{x:o,y:s},{x:o,y:i},{x:n,y:i},{x:n,y:s}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}};export{ka as AssignableAutoroutingPipeline1Solver,dr as AssignableAutoroutingPipeline2,Ia as AssignableAutoroutingPipeline3,Di as AutoroutingPipeline1_OriginalUnravel,Go as AutoroutingPipelineSolver,Jo as CapacityMeshSolver,Sa as CurvyIntraNodeSolver,ba as HighDensitySolver,ct as InMemoryCache,qa as IntraNodeSolverWithJumpers,dt as LocalStorageCache,Ua as SingleHighDensityRouteWithJumpersSolver,Be as calculateOptimalCapacityDepth,sn as convertSrjToGraphicsObject,ut as getGlobalInMemoryCache,lt as getGlobalLocalStorageCache,ke as getTunedTotalCapacity1,pt as setupGlobalCaches};
|
|
2
2
|
/*! Bundled license information:
|
|
3
3
|
|
|
4
4
|
is-buffer/index.js:
|