@tscircuit/capacity-autorouter 0.0.281 → 0.0.283

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- var t=Object.create,e=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,i=Object.prototype.hasOwnProperty,r=(t,e)=>function(){return e||(0,t[o(t)[0]])((e={exports:{}}).exports,e),e.exports},a=(r,a,c)=>(c=null!=r?t(s(r)):{},((t,s,r,a)=>{if(s&&"object"==typeof s||"function"==typeof s)for(let c of o(s))i.call(t,c)||c===r||e(t,c,{get:()=>s[c],enumerable:!(a=n(s,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(),o=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=o.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 o in t)Object.prototype.hasOwnProperty.call(t,o)&&(n[e(o,t[o])||o]=t[o]);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(),o=d();e.exports=function t(e,s){var i=n(e);if("object"!==i&&"array"!==i)throw new Error("expected an object");var r=[];for(var a in"object"===i&&(e=o(e,s),r={}),e)if(e.hasOwnProperty(a)){var c=e[a];"object"===n(c)||"array"===n(c)?r[a]=t(c,s):r[a]=c}return r}}}),u=r({"node_modules/xml-reader/node_modules/eventemitter3/index.js"(t,e){var n=Object.prototype.hasOwnProperty,o="~";function s(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new s,this._eventsCount=0}Object.create&&(s.prototype=Object.create(null),(new s).__proto__||(o=!1)),r.prototype.eventNames=function(){var t,e,s=[];if(0===this._eventsCount)return s;for(e in t=this._events)n.call(t,e)&&s.push(o?e.slice(1):e);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(t)):s},r.prototype.listeners=function(t,e){var n=o?o+t:t,s=this._events[n];if(e)return!!s;if(!s)return[];if(s.fn)return[s.fn];for(var i=0,r=s.length,a=new Array(r);i<r;i++)a[i]=s[i].fn;return a},r.prototype.emit=function(t,e,n,s,i,r){var a=o?o+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,s),!0;case 5:return d.fn.call(d.context,e,n,s,i),!0;case 6:return d.fn.call(d.context,e,n,s,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,s);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 s=new i(e,n||this),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.once=function(t,e,n){var s=new i(e,n||this,!0),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=o?o+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new s: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 s: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 s:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=o?o+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new s:delete this._events[e])):(this._events=new s,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=o,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,o="~";function s(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new s,this._eventsCount=0}Object.create&&(s.prototype=Object.create(null),(new s).__proto__||(o=!1)),r.prototype.eventNames=function(){var t,e,s=[];if(0===this._eventsCount)return s;for(e in t=this._events)n.call(t,e)&&s.push(o?e.slice(1):e);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(t)):s},r.prototype.listeners=function(t,e){var n=o?o+t:t,s=this._events[n];if(e)return!!s;if(!s)return[];if(s.fn)return[s.fn];for(var i=0,r=s.length,a=new Array(r);i<r;i++)a[i]=s[i].fn;return a},r.prototype.emit=function(t,e,n,s,i,r){var a=o?o+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,s),!0;case 5:return d.fn.call(d.context,e,n,s,i),!0;case 6:return d.fn.call(d.context,e,n,s,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,s);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 s=new i(e,n||this),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.once=function(t,e,n){var s=new i(e,n||this,!0),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=o?o+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new s: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 s: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 s:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=o?o+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new s:delete this._events[e])):(this._events=new s,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=o,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 o=p(),s=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 o,v=i.data,P="",S="",M="",b="",N="",I="",C=function(e,n){if("?"!==S[0]&&"!"!==S[0]){var o={type:e,value:n};t.debug&&console.log("emit:",o),x.emit("data",o)}};x.stateMachine=(n(y={},i.data,(n(e={},r.lt,function(){P.trim()&&C(a.text,P),S="",N=!1,v=i.tagBegin}),n(e,r.char,function(t){P+=t}),e)),n(y,i.cdata,n({},r.char,function(t){"]]>"===(P+=t).substr(-3)&&(C(a.text,P.slice(0,-3)),P="",v=i.data)})),n(y,i.tagBegin,(n(h={},r.space,s),n(h,r.char,function(t){S=t,v=i.tagName}),n(h,r.slash,function(){S="",N=!0}),h)),n(y,i.tagName,(n(d={},r.space,function(){N?v=i.tagEnd:(v=i.attributeNameStart,C(a.openTag,S))}),n(d,r.gt,function(){C(N?a.closeTag:a.openTag,S),P="",v=i.data}),n(d,r.slash,function(){v=i.tagEnd,C(a.openTag,S)}),n(d,r.char,function(t){"![CDATA["===(S+=t)&&(v=i.cdata,P="",S="")}),d)),n(y,i.tagEnd,(n(l={},r.gt,function(){C(a.closeTag,S),P="",v=i.data}),n(l,r.char,s),l)),n(y,i.attributeNameStart,(n(u={},r.char,function(t){M=t,v=i.attributeName}),n(u,r.gt,function(){P="",v=i.data}),n(u,r.space,s),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,M),v=i.attributeValueBegin}),n(p,r.gt,function(){b="",C(a.attributeName,M),C(a.attributeValue,b),P="",v=i.data}),n(p,r.slash,function(){N=!0,b="",C(a.attributeName,M),C(a.attributeValue,b),v=i.tagEnd}),n(p,r.char,function(t){M+=t}),p)),n(y,i.attributeNameEnd,(n(m={},r.space,s),n(m,r.equal,function(){C(a.attributeName,M),v=i.attributeValueBegin}),n(m,r.gt,function(){b="",C(a.attributeName,M),C(a.attributeValue,b),P="",v=i.data}),n(m,r.char,function(t){b="",C(a.attributeName,M),C(a.attributeValue,b),M=t,v=i.attributeName}),m)),n(y,i.attributeValueBegin,(n(f={},r.space,s),n(f,r.quote,function(t){I=t,b="",v=i.attributeValue}),n(f,r.gt,function(){C(a.attributeValue,b=""),P="",v=i.data}),n(f,r.char,function(t){I="",b=t,v=i.attributeValue}),f)),n(y,i.attributeValue,(n(g={},r.space,function(t){I?b+=t:(C(a.attributeValue,b),v=i.attributeNameStart)}),n(g,r.quote,function(t){I===t?(C(a.attributeValue,b),v=i.attributeNameStart):b+=t}),n(g,r.gt,function(t){I?b+=t:(C(a.attributeValue,b),P="",v=i.data)}),n(g,r.slash,function(t){I?b+=t:(C(a.attributeValue,b),N=!0,v=i.tagEnd)}),n(g,r.char,function(t){b+=t}),g)),y);var _=function(e){t.debug&&console.log(v,e);var n=x.stateMachine[v],o=n[function(t){return c[t]||r.char}(e)]||n[r.error]||n[r.char];o(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(),o=m(),s=o.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 s.openTag:if(null===c)(c=a).name=n.value;else{var o=r({name:n.value,parent:c});c.children.push(o),c=o}break;case s.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 s.text:c&&c.children.push(r({type:i.text,value:n.value,parent:t.parentNodes?c:null}));break;case s.attributeName:h=n.value,c.attributes[h]="";break;case s.attributeValue:c.attributes[h]=n.value}};return d.reset=function(){(e=o.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),o=void 0;return n.on("done",function(t){o=t}),n.parse(t),o},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;getSolverName(){return this.constructor.name}step(){if(!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.getSolverName()} 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.getSolverName()} 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 o in n)({}).hasOwnProperty.call(n,o)&&(t[o]=n[o])}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 P(t){return(P=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function S(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(S=function(){return!!t})()}function M(t){var e="function"==typeof Map?new Map:void 0;return M=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(S())return Reflect.construct.apply(null,arguments);var o=[null];o.push.apply(o,e);var s=new(t.bind.apply(t,o));return n&&v(s,n.prototype),s}(t,arguments,P(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),v(n,t)},M(t)}var b={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 o,s=e[0],i=[];for(o=1;o<e.length;o+=1)i.push(e[o]);return i.forEach(function(t){s=s.replace(/%[a-z]/,t)}),s}var I=function(t){var e,n;function o(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 o=arguments.length,s=new Array(o>1?o-1:0),i=1;i<o;i++)s[i-1]=arguments[i];n=t.call(this,N.apply(void 0,[b[e]].concat(s)))||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=o).prototype=Object.create(n.prototype),e.prototype.constructor=e,v(e,n),o}(M(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 o=e,s=n;if("string"==typeof e){if(!C(e,"px"))throw new I(69,t,e);o=T(e)}if("string"==typeof n){if(!C(n,"px"))throw new I(70,t,n);s=T(n)}if("string"==typeof o)throw new I(71,e,t);if("string"==typeof s)throw new I(72,n,t);return""+o/s+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,o){if(void 0===o&&(o=w),0===e)return o(n,n,n);var s=(t%360+360)%360/60,i=(1-Math.abs(2*n-1))*e,r=i*(1-Math.abs(s%2-1)),a=0,c=0,h=0;s>=0&&s<1?(a=i,c=r):s>=1&&s<2?(a=r,c=i):s>=2&&s<3?(c=i,h=r):s>=3&&s<4?(c=r,h=i):s>=4&&s<5?(a=r,h=i):s>=5&&s<6&&(a=i,h=r);var d=n-i/2;return o(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,B=/^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 k(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 o=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:o}}var s=X.exec(e);if(s)return{red:parseInt(""+s[1],10),green:parseInt(""+s[2],10),blue:parseInt(""+s[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=B.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,o=t.green/255,s=t.blue/255,i=Math.max(n,o,s),r=Math.min(n,o,s),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=(o-s)/c+(o<s?6:0);break;case o:e=(s-n)/c+2;break;default:e=(n-o)/c+4}return e*=60,void 0!==t.alpha?{hue:e,saturation:h,lightness:a,alpha:t.alpha}:{hue:e,saturation:h,lightness:a}}(k(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,o){if("string"==typeof t&&"number"==typeof e){var s=k(t);return"rgba("+s.red+","+s.green+","+s.blue+","+e+")"}if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof o)return o>=1?G(t,e,n):"rgba("+t+","+e+","+n+","+o+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===o)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,o){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof o)return o>=1?Z(t,e,n):"rgba("+A(t,e,n)+","+o+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===o)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 o=n.concat(Array.prototype.slice.call(arguments));return o.length>=e?t.apply(this,o):K(t,e,o)}}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 o=k(e),s=x({},o,{alpha:"number"==typeof o.alpha?o.alpha:1}),i=k(n),r=x({},i,{alpha:"number"==typeof i.alpha?i.alpha:1}),a=s.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(s.red*h+r.red*d),green:Math.floor(s.green*h+r.green*d),blue:Math.floor(s.blue*h+r.blue*d),alpha:s.alpha*parseFloat(t)+r.alpha*(1-parseFloat(t))})});Q(function(t,e){if("transparent"===e)return e;var n=k(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=k(e);return J(x({},n,{alpha:tt(0,1,+(100*("number"==typeof n.alpha?n.alpha:1)-100*parseFloat(t)).toFixed(2)/100)}))}),ot=["blue","orange","purple","cyan","magenta","yellowgreen","darkgoldenrod","deeppink"],st=(t,e)=>{const n={};for(let o=0;o<t.connections.length;o++){const s=t.connections[o],i=e?.getNetConnectedToId(s.name);i&&!n[i]&&(n[i]=`hsl(${300*o/t.connections.length}, 100%, 50%)`),n[s.name]=(i?n[i]:null)??`hsl(${340*o/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 o=t.split(":")[0];return this.cacheHitsByPrefix[o]=(this.cacheHitsByPrefix[o]||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 o=t.split(":")[0];return void(this.cacheMissesByPrefix[o]=(this.cacheMissesByPrefix[o]||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,o){const s=yt(t,e,n),i=yt(t,e,o),r=yt(n,o,t),a=yt(n,o,e);return s!==i&&r!==a||(!(0!==s||!xt(t,n,e))||(!(0!==i||!xt(t,o,e))||(!(0!==r||!xt(n,t,o))||!(0!==a||!xt(n,e,o)))))}function yt(t,e,n){const o=(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y);return 0===o?0:o>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 o=(n.x-e.x)**2+(n.y-e.y)**2;if(0===o)return Pt(t,e);let s=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/o;s=Math.max(0,Math.min(1,s));return Pt(t,{x:e.x+s*(n.x-e.x),y:e.y+s*(n.y-e.y)})}function Pt(t,e){const n=t.x-e.x,o=t.y-e.y;return Math.sqrt(n*n+o*o)}function St(t,e,n,o){const s=e.x-t.x,i=e.y-t.y,r=o.x-n.x,a=o.y-n.y,c=t.x-n.x,h=t.y-n.y,d=s*a-i*r;if(Math.abs(d)<1e-10)return null;const l=(h*r-c*a)/d,u=(s*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*s,y:t.y+l*i}}return null}function Mt(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var bt=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 o=t[n],s=t[(n+1)%t.length];e.push([o,s])}return e},Ct=(t,e,n)=>{const o=(t.y-e.y)*(n.x-e.x)-(t.x-e.x)*(n.y-e.y);if(Math.abs(o)>1e-9)return!1;const s=(t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y);if(s<0)return!1;return!(s>(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,o]of n)if(Ct(t,e,o))return!0;let o=!1;for(let n=0,s=e.length-1;n<e.length;s=n++){const i=e[n].x,r=e[n].y,a=e[s].x,c=e[s].y;r>t.y!=c>t.y&&t.x<(a-i)*(t.y-r)/(c-r)+i&&(o=!o)}return o},Tt=(t,e)=>{const n=Nt(t),o=[[n[0],n[1]],[n[1],n[2]],[n[2],n[3]],[n[3],n[0]]],s=It(e);for(const[t,e]of s)for(const[n,s]of o)if(gt(t,e,n,s))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))))(bt(t),e),Rt=(t,e)=>((t,e)=>!(e.length<3)&&(!!Nt(t).every(t=>_t(t,e))&&!Tt(t,e)))(bt(t),e);function wt(t,e,n,o){if(t.x===e.x&&t.y===e.y)return vt(t,n,o);if(n.x===o.x&&n.y===o.y)return vt(n,t,e);if(gt(t,e,n,o))return 0;const s=[vt(t,n,o),vt(e,n,o),vt(n,t,e),vt(o,t,e)];return Math.min(...s)}function At(t,e,n){const o=n.width/2,s=n.height/2;return function(t,e,n){const o={x:n.minX,y:n.minY},s={x:n.maxX,y:n.minY},i={x:n.minX,y:n.maxY},r={x:n.maxX,y:n.maxY};if(gt(t,e,o,s)||gt(t,e,s,r)||gt(t,e,r,i)||gt(t,e,i,o))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(o,t,e),vt(s,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),o=ft(t.y,n.minY,n.maxY);a.push(Pt(t,{x:e,y:o}))}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),o=ft(e.y,n.minY,n.maxY);a.push(Pt(e,{x:t,y:o}))}return Math.min(...a)}(t,e,{minX:n.center.x-o,maxX:n.center.x+o,minY:n.center.y-s,maxY:n.center.y+s})}function Ot(t,e,n){const o=n.x-e.x,s=n.y-e.y,i=o*o+s*s;if(0===i)return{x:e.x,y:e.y};let r=((t.x-e.x)*o+(t.y-e.y)*s)/i;r=Math.max(0,Math.min(1,r));return{x:e.x+r*o,y:e.y+r*s}}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{getSolverName(){return"SingleHighDensityRouteSolver"}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=Pt(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,o=this.boundsSize.height/this.cellStep;for(;n*o>e**2&&!(2*this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,n=this.boundsSize.width/this.cellStep,o=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR;const s=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&&!s&&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 o of n)if(Pt(t,o)<this.viaDiameter/2+e)return!0}for(const o of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,o.connectionName);if(!s){const s=Lt(o);for(const o of s)if((n||o.z===t.z)&&vt(t,o.A,o.B)<this.traceThickness+e)return!0}for(const n of o.vias)if(Pt(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,o=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!(o&&!e&&(Pt(t,this.B)<2*n||Pt(t,this.A)<2*n))&&o}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const n of this.obstacleRoutes){const o=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!o)for(const o of Lt(n))if(o.z===t.z&&gt(t,e,o.A,o.B))return!0}return!1}computeH(t){return Pt(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)+Pt(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:o,maxY:s,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,o,n),y:Ft(t.y+a*this.cellStep,i,s)},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 o={...t,parent:t,z:n};this.exploredNodes.has(this.getNodeKey(o))||this.isNodeTooCloseToObstacle(o,this.viaDiameter/2+this.obstacleMargin/2,!0)||this.isNodeTooCloseToEdge(o,!0)||(o.g=this.computeG(o),o.h=this.computeH(o),o.f=this.computeF(o.g,o.h),e.push(o))}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 o=1-e/this.straightLineDistance;return Math.max(this.progress||0,2/Math.PI*Math.atan(.112*o/(1-o)))}_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=Pt(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 o=this.getNeighbors(t);for(const t of o)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 o=0;o<n.route.length-1;o++){const s=n.route[o].z;t.lines.push({points:[n.route[o],n.route[o+1]],strokeColor:0===s?"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],[o,s,i]=n.split(",").map(Number);this.debug_nodesTooCloseToObstacle.has(n)||(this.debug_nodePathToParentIntersectsObstacle.has(n)||t.rects.push({center:{x:o+this.initialNodeGridOffset.x+i*this.cellStep/20,y:s+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 o of this.futureConnections)for(const s of o.points){const o=Pt(t,s)+(t.z!==s.z?this.viaPenaltyDistance:0);o<e&&(e=o,n=s)}return n}diminishCloseToGoal(t){const e=Pt(t,this.B);return 1-Math.exp(-e/this.straightLineDistance*5)}getFutureConnectionPenalty(t,e){let n=0;const o=this.getClosestFutureConnectionPoint(t),s=Pt(t,this.B);if(o){const i=Pt(t,o);if(s<=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=Pt(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),o=Math.sqrt(e**2+n**2),s=t.z%2==0,i=this.FLIP_TRACE_ALIGNMENT_DIRECTION?s?e:n:s?n:e;return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+o+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 o=e;return()=>{let t=n;n=o,t^=t<<23,t^=t>>>17,t^=o,t^=o>>>26,o=t;const e=(n+o)/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 Bt(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),o=t.slice();for(let t=0;t<o.length;t++){const e=Math.floor(n()*o.length),s=Math.floor(n()*(t+1));[o[e],o[s]]=[o[s],o[e]]}return o}function kt(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 o=t+1;o<n.length;o++){const s=n[t],i=n[o];if(s.z!==i.z)continue;if(s.rootConnectionName&&s.rootConnectionName===i.rootConnectionName)continue;const r=Math.sqrt((s.x-i.x)**2+(s.y-i.y)**2);e=Math.min(e,r)}return e===1/0?0:e},Wt=class extends y{getSolverName(){return"IntraNodeRouteSolver"}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 o=new Map;for(const{connectionName:t,x:n,y:s,z:i}of e.portPoints)o.set(t,[...o.get(t)??[],{x:n,y:s,z:i??0}]);this.unsolvedConnections=Array.from(o.entries().map(([t,e])=>({connectionName:t,points:e}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=Bt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},n)=>({...e,points:Bt(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,o=Math.abs(e.x-n.x)<1e-6,s=Math.abs(e.y-n.y)<1e-6;if(o&&s&&e.z===n.z)return;if(o&&s&&e.z!==n.z){const o={x:this.nodeWithPortPoints.center.x,y:this.nodeWithPortPoints.center.y},s=[{x:e.x,y:e.y,z:e.z},{...o,z:e.z},{...o,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:s,vias:[o]})}}const{connectionName:e,points:n}=t;this.activeSubSolver=new Xt({connectionName:e,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:kt(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 o=this.colorMap[n.connectionName]??"blue";for(let s=0;s<n.route.length-1;s++){const i=n.route[s],r=n.route[s+1];t.lines.push({points:[i,r],strokeColor:0===i.z?it(o,.2):it(o,.8),layer:`route-layer-${i.z}`,step:e,strokeWidth:n.traceThickness})}for(const s of n.vias)t.circles.push({center:{x:s.x,y:s.y},radius:n.viaDiameter/2,fill:it(o,.5),layer:"via",step:e})}}const e=kt(this.nodeWithPortPoints),{minX:n,minY:o,maxX:s,maxY:i}=e;return t.lines.push({points:[{x:n,y:o},{x:s,y:o},{x:s,y:i},{x:n,y:i},{x:n,y:o}],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{getSolverName(){return"CachedIntraNodeRouteSolver"}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))),o=this.connMap?this.initialUnsolvedConnections.map(({connectionName:t})=>({connectionName:t,connectedIds:[...new Set(this.connMap.getIdsConnectedToNet(t)??[])].sort()})):void 0,s={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:o},i=`intranode-solver:${at(s)}`,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{getSolverName(){return"HyperParameterSupervisorSolver"}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,...o]=t,s=this.getHyperParameterCombinations(o);return n.possibleValues.forEach(t=>{s.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 o=n.f;o<t&&(t=o,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:o,E:s,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 o=e.x-t.x,s=e.y-t.y,i=Math.sqrt(o*o+s*s),r=o/i,a=s/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=Pt(t,e.start),o=Pt(t,e.end),s=Pt(e.start,e.end);return Math.abs(n+o-s)<1e-4},u=(t,e)=>{const{start:n,end:o}=t,{start:s,end:i}=e;if(l(n,e)||l(o,e)||l(s,t)||l(i,t))return!0;const r=o.x-n.x,a=o.y-n.y,c=i.x-s.x,h=i.y-s.y,d=r*h-a*c;if(Math.abs(d)<1e-4)return!1;const u=s.x-n.x,p=s.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 o=[];for(let t=0;t<e.length-1;t++)o.push({start:e[t],end:e[t+1]});for(const t of n)for(const e of o)if(u(t,e))return!0;return!1},m=t=>{let e=0;for(let n=1;n<t.length;n++){const o=t[n].x-t[n-1].x,s=t[n].y-t[n-1].y;e+=Math.sqrt(o*o+s*s)}return e},f=(t,e)=>{const{start:n,end:o}=t,s=o.x-n.x,i=o.y-n.y,r=s*s+i*i;if(0===r)return{...n,t:0};const a=Math.max(0,Math.min(1,((e.x-n.x)*s+(e.y-n.y)*i)/r));return{x:n.x+a*s,y:n.y+a*i,t:a}},g=(e,n,o)=>{const s=f(e,n);if(Pt(s,n)>=o)return s;const i=s.x-n.x,r=s.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+o*i/a,y:n.y+o*r/a,t:s.t,isSpecial:!0,specialType:n===t?"A":"B"}}return{x:n.x+o*i/a,y:n.y+o*r/a,t:s.t,isSpecial:!0,specialType:n===t?"A":"B"}},y=d(t,e,r),x=d(t,e,r+a),v=(t,e,n,o,s)=>{const i=t.points;if(i.length<2)return i;const a=n+o,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),o=t.x-e.x,s=t.y-e.y,i=Math.sqrt(o*o+s*s);let h=null;if(i>1e-6)h={x:e.x+a*o/i,y:e.y+a*s/i};else{const t=n.end.x-n.start.x,o=n.end.y-n.start.y,s=Math.sqrt(t*t+o*o);s>1e-6&&(h={x:e.x+a*t/s,y:e.y+a*o/s})}h&&Pt(n.start,h)>r/10&&c.push(h)}Pt(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++)Pt(t[t.length-1],c[e])>r/10&&t.push(c[e]);return t}return c},P=(()=>{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,o],[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,o],[o,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],[o,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 o=t[n],s={start:o[0],end:o[1]},i={start:o[o.length-2],end:o[o.length-1]},r={start:o[3],end:o[4]};u(s,i)||u(s,r)||u(i,r)||e.push({index:n+1,path:o,length:m(o)})}if(0===e.length)return{index:0,path:[]};const s=e.sort((t,e)=>t.length-e.length)[0],i=[...s.path],r=i[0],a=Pt(r,i[2]),c=Pt(r,i[3]),d=a<c?2:3;(a<Pt(r,i[1])||c<Pt(r,i[1]))&&i.splice(1,d-1);const l=i[i.length-1],p=Pt(l,i[i.length-3]),f=Pt(l,i[i.length-4]),g=p<f?i.length-3:i.length-4;return(p<Pt(l,i[i.length-2])||f<Pt(l,i[i.length-2]))&&i.splice(g+1,i.length-g-2),{index:s.index,path:i,startsAt:i[0]===n?"C":"D",goesTo:i[i.length-1]===n?"C":"D"}})(),S=c>0?((n,o)=>{if(n.length<2)return n;const s=[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=Pt(c,t),d=Pt(c,e);if((h<=r||d<=r)&&Math.abs(h-d)>1e-4){const n=f(a,t),i=f(a,e),c=Pt(n,t),h=Pt(i,e)<r,d=c<r?g(a,t,r):null,l=h?g(a,e,r):null;let u=[];if(Pt(a.start,a.end)>r/2&&o>0)for(let n=1;n<=o;n++){const s=n/(o+1),i={x:a.start.x+s*(a.end.x-a.start.x),y:a.start.y+s*(a.end.y-a.start.y),t:s,isSpecial:!1},c=Pt(i,t),h=Pt(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],o=u[e];Pt(n,o)>r/10&&t.push(o)}u=t}u.forEach(t=>s.push(t))}s.push(n[i+1])}if(s.length>1){const t=[s[0]];for(let e=1;e<s.length;e++){const n=t[t.length-1],o=s[e];Pt(n,o)>r/10&&t.push(o)}return t}return s})(P.path,c):P.path;let M=(()=>{if(0===P.path.length)return null;const n=(()=>{const n=h(y.A_Right,y.B_Right),o=h(y.B_Left,y.A_Left);return[{startsAt:"E",goesTo:"B",points:[s,e]},{startsAt:"E",goesTo:"A",points:[s,t]},{startsAt:"F",goesTo:"B",points:[i,e]},{startsAt:"F",goesTo:"A",points:[i,t]},{startsAt:"E",goesTo:"B",points:[s,n,e]},{startsAt:"E",goesTo:"A",points:[s,n,t]},{startsAt:"F",goesTo:"B",points:[i,n,e]},{startsAt:"F",goesTo:"A",points:[i,n,t]},{startsAt:"E",goesTo:"B",points:[s,o,e]},{startsAt:"E",goesTo:"A",points:[s,o,t]},{startsAt:"F",goesTo:"B",points:[i,o,e]},{startsAt:"F",goesTo:"A",points:[i,o,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Right,n,e]},{startsAt:"F",goesTo:"B",points:[i,x.B_Right,n,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Left,o,t]},{startsAt:"F",goesTo:"A",points:[i,x.A_Left,o,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Left,o,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Opp,x.B_Left,o,t]},{startsAt:"F",goesTo:"B",points:[i,x.A_Opp,x.A_Left,o,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,o,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Opp,x.A_Left,o,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Opp,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Left,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Right,x.B_Opp,x.B_Left,o,t]},{startsAt:"F",goesTo:"B",points:[i,x.A_Right,x.A_Opp,x.A_Left,o,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,o,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Right,x.A_Opp,x.A_Left,o,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Left,x.B_Opp,x.B_Right,n,t]}].map((t,e)=>({...t,index:e}))})(),o=n.filter(t=>"E"===t.startsAt),r=n.filter(t=>"F"===t.startsAt),a=[],c=[];for(const t of o)if(!p(t.points,P.path)){a.push(t);break}for(const t of r)if(!p(t.points,P.path)){c.push(t);break}return 0===a.length||0===c.length?null:{line1:a[0],line2:c[0]}})();if(M){const n="A"===M.line1.goesTo?e:t,o="A"===M.line2.goesTo?e:t,s=v(M.line1,n,r,a),i=v(M.line2,o,r,a);M={line1:{...M.line1,points:s},line2:{...M.line2,points:i}}}return{jPair:M,optimalPath:{startsAt:P.startsAt,goesTo:P.goesTo,points:S}}}var Jt=class extends y{getSolverName(){return"TwoCrossingRoutesHighDensitySolver"}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,o]of n.entries())2===o.length&&t.push({startPort:{...o[0],z:o[0].z??0},endPort:{...o[1],z:o[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,o=this.bounds.maxY-this.bounds.minY,s=this.bounds.minX,i=this.bounds.minY,r={width:n-2*this.obstacleMargin-this.viaDiameter,height:o-2*this.obstacleMargin-this.viaDiameter,x:s+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)=>Pt(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,o)=>{((t,e)=>{const n=t.x,o=t.y,s=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=s*s-(t-n)**2;if(e<0)return[];if(Math.abs(e)<.001){const e=o;return e>=Math.min(r,c)&&e<=Math.max(r,c)?[{x:t,y:e}]:[]}const a=o+Math.sqrt(e),h=o-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*o-n),p=u*u-4*l*(n*n+(d-o)*(d-o)-s*s);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:o})})})}),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=Pt(g,t.startPort);return Pt(y,t.startPort)<x&&([g,y]=[y,g]),{via1:g,via2:y}}trySolveAOverB(t,e,n=!1){const o=n?this.calculateViaPositions(t,e):this.calculateViaPositions(e,t);if(!o)return!1;this.debugViaPositions.push(o);const{via1:s,via2:i}=this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(o));this.debugViaPositions.push({via1:s,via2:i});const{jPair:r,optimalPath:a}=Gt({A:s,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:[s,i]};return this.solvedRoutes.push(c,h),!0}pushViasFromEndpoints(t){const e={...t.via1},n={...t.via2},o=[this.routes[0].startPort,this.routes[0].endPort,this.routes[1].startPort,this.routes[1].endPort],s=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 o){const o=Pt(e,t);if(o<i){const n=(i-o)*c,s=e.x-t.x,a=e.y-t.y,h=Math.sqrt(s*s+a*a);h>1e-6&&(e.x+=s/h*n,e.y+=a/h*n,r=!0)}const s=Pt(n,t);if(s<i){const e=(i-s)*c,o=n.x-t.x,r=n.y-t.y,h=Math.sqrt(o*o+r*r);h>1e-6&&(n.x+=o/h*e,n.y+=r/h*e,a=!0)}}const h=Pt(e,n);if(h<s){const t=(s-h)/2,o=n.x-e.x,i=n.y-e.y,c=Math.sqrt(o*o+i*i);c>1e-6?(e.x-=o/c*t,e.y-=i/c*t,n.x+=o/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=Pt(e,n);if(r<s){const t=(s-r)/2,o=n.x-e.x,i=n.y-e.y,a=Math.sqrt(o*o+i*i);a>1e-6?(e.x-=o/a*t,e.y-=i/a*t,n.x+=o/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,o=this.getMinDistanceBetweenViaCenters(),s=Pt(e,n);if(s<=o)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,(s-o)/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:[]},o={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,o),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:o}=this.debugViaPositions[e],s=["rgba(255, 165, 0, 0.3)","rgba(128, 0, 128, 0.3)"],i=s[e%s.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:o,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:o,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,o,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],o=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 s=n.route[e],i=n.route[e+1];t.lines.push({points:[s,i],strokeColor:o,strokeDash:1===s.z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${s.z}`}),s._label&&t.points.push({x:s.x,y:s.y,label:s._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,o,s){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>=s.minX&&i.x<=s.maxX&&i.y>=s.minY&&i.y<=s.maxY;return a>=o&&c>=o&&h>=o&&d};if(a(i))return i;const c=(t,e,n)=>{const o=t.x-e.x,s=t.y-e.y,i=Math.sqrt(o*o+s*s);return i<1e-10?{x:e.x+n,y:e.y}:{x:e.x+o/i*n,y:e.y+s/i*n}},h=(t,e,n)=>{const o=e.x-t.x,s=e.y-t.y,i=Math.sqrt(o*o+s*s);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+o*a/i,d=t.y+s*a/i,l={x:h+c*s/i,y:d-c*o/i},u={x:h-c*s/i,y:d+c*o/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,o),c(i,e,o),c(i,n,o),...h(t,e,o),...h(e,n,o),...h(n,t,o)],l=d.filter(a);if(l.length>0){const t=l.filter(t=>!(t=>{const e=1e-6;return Math.abs(t.x-s.minX)<e||Math.abs(t.x-s.maxX)<e||Math.abs(t.y-s.minY)<e||Math.abs(t.y-s.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=s.minX+1;t<s.maxX;t+=5)for(let e=s.minY+1;e<s.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:s.minX+e*(s.maxX-s.minX),y:s.minY}),m.push({x:s.maxX,y:s.minY+e*(s.maxY-s.minY)}),m.push({x:s.maxX-e*(s.maxX-s.minX),y:s.maxY}),m.push({x:s.minX,y:s.maxY-e*(s.maxY-s.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:s.minX,y:s.minY};for(const i of[...d,...m])if(i.x>=s.minX&&i.x<=s.maxX&&i.y>=s.minY&&i.y<=s.maxY){const s=Math.max(0,o-r(i,t))+Math.max(0,o-r(i,e))+Math.max(0,o-r(i,n));s<g&&(g=s,y=i)}return y}function Kt(t,e,n){const o=Qt(e,t,n.center,n.radius),s=Qt(t,e,n.center,n.radius),i=te(o,e),r=te(t,s),a=1e-6;let c;if(i>a&&r>a){c={x:(o.x+s.x)/2,y:(o.y+s.y)/2};const i=te(o,c),r=te(s,c);if(Math.abs(i-r)>.5*Math.min(i,r)){const n=te(t,o),i=te(e,s),r=n+i;if(r>a){const t=i/r,e=n/r;c={x:o.x*t+s.x*e,y:o.y*t+s.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 o={x:(t.x+e.x)/2,y:(t.y+e.y)/2},s=te(o,n.center);if(s<1.1*n.radius){const t={x:(o.x-n.center.x)/s,y:(o.y-n.center.y)/s};c={x:n.center.x+t.x*n.radius*1.2,y:n.center.y+t.y*n.radius*1.2}}else c=o}return{B:o,D:s,E:c}}function Qt(t,e,n,o){const s=[n.x-t.x,n.y-t.y],i=Math.sqrt(s[0]*s[0]+s[1]*s[1]);if(i<=o){if(i<1e-8){const s=[e.x-t.x,e.y-t.y],i=Math.sqrt(s[0]*s[0]+s[1]*s[1]);return i<1e-8?{x:n.x+o,y:n.y}:{x:n.x+s[0]/i*o,y:n.y+s[1]/i*o}}const r=[s[0]/i,s[1]/i];return{x:n.x-r[0]*o,y:n.y-r[1]*o}}const r=[e.x-t.x,e.y-t.y],a=Math.sqrt(i*i-o*o),c=[s[0]/i,s[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=o/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,o=e.y-t.y;return Math.sqrt(n*n+o*o)}var ee=({value:t,min:e,max:n})=>t>=e&&t<=n,ne=({value:t,target:e,epsilon:n})=>Math.abs(t-e)<=n,oe=({point:t,bounds:e,epsilon:n=1e-6})=>{if(![t.x,t.y,e.minX,e.maxX,e.minY,e.maxY].every(t=>(({value:t})=>Number.isFinite(t))({value:t})))return"outside";const o=function(t,e){return t.x>=e.minX&&t.x<=e.maxX&&t.y>=e.minY&&t.y<=e.maxY?0:Pt(t,{x:ft(t.x,e.minX,e.maxX),y:ft(t.y,e.minY,e.maxY)})}(t,e);if(o>n)return"outside";const s=ne({value:t.x,target:e.minX,epsilon:n}),i=ne({value:t.x,target:e.maxX,epsilon:n}),r=ne({value:t.y,target:e.minY,epsilon:n}),a=ne({value:t.y,target:e.maxY,epsilon:n}),c=s||i,h=r||a;if(c&&h)return"on-boundary";const d=ee({value:t.y,min:e.minY,max:e.maxY}),l=ee({value:t.x,min:e.minX,max:e.maxX});return c&&d||h&&l?"on-boundary":"inside"},se=1e-9;function ie(t,e,n,o="cw"){const s=re(t,n),i=re(e,n);return Math.abs(i-s)<se?{left:0,top:0,right:0,bottom:0}:function(t,e,n,o){const s=n.maxX-n.minX,i=n.maxY-n.minY;if(s<se&&i<se)return{left:0,top:0,right:0,bottom:0};const r=2*(s+i);if(r<se)return{left:0,top:0,right:0,bottom:0};const a=s/r*(2*Math.PI),c=(s+i)/r*(2*Math.PI),h=(s+s+i)/r*(2*Math.PI),d=2*Math.PI,l=[{name:"top",start:0,end:a,length:s},{name:"right",start:a,end:c,length:i},{name:"bottom",start:c,end:h,length:s},{name:"left",start:h,end:d,length:i}],u={left:0,top:0,right:0,bottom:0},p=(t,e,n,o,s)=>{const i=e>2*Math.PI-se?2*Math.PI:e;if(i<=t+se)return 0;if(s){const e=Math.max(t,n),s=Math.min(i,2*Math.PI),r=Math.max(0,s-e),a=Math.max(t,0),c=Math.min(i,o);return r+Math.max(0,c-a)}{const e=Math.max(t,n),s=Math.min(i,o);return Math.max(0,s-e)}};for(const n of l){const s=n.end-n.start;if(s<se||n.length<se)continue;let i=0;if("cw"===o){const o=t>e+se;i=p(n.start,n.end,t,e,o)}else{const o=e>t+se;i=p(n.start,n.end,e,t,o)}if(i>se){const t=i/s;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}(s,i,n,o)}function re(t,e){const n=e.maxX-e.minX,o=e.maxY-e.minY;if(n<se&&o<se)return 0;const s=2*(n+o);if(s<se)return 0;let i=0;if(Math.abs(t.y-e.maxY)<se&&t.x>=e.minX-se&&t.x<=e.maxX+se)i=Math.max(0,Math.min(n,t.x-e.minX));else if(Math.abs(t.x-e.maxX)<se&&t.y>=e.minY-se&&t.y<=e.maxY+se)i=n+Math.max(0,Math.min(o,e.maxY-t.y));else if(Math.abs(t.y-e.minY)<se&&t.x>=e.minX-se&&t.x<=e.maxX+se)i=n+o+Math.max(0,Math.min(n,e.maxX-t.x));else{if(!(Math.abs(t.x-e.minX)<se&&t.y>=e.minY-se&&t.y<=e.maxY+se))throw new Error(`Point (${t.x}, ${t.y}) does not lie on the boundary defined by ${JSON.stringify(e)}`);i=n+o+n+Math.max(0,Math.min(o,t.y-e.minY))}return i=Math.max(0,Math.min(s,i)),s>se?i/s*(2*Math.PI):0}function ae(t,e,n,o){return function({angleA:t,angleB:e,angleC:n}){const o=Math.cos(t),s=Math.sin(t),i=Math.cos(e),r=Math.sin(e),a=Math.cos(n);return(i-o)*(Math.sin(n)-s)-(r-s)*(a-o)<0?"ccw":"cw"}({angleA:re(t,o),angleB:re(e,o),angleC:re(n,o)})}var ce=class extends y{getSolverName(){return"SingleTransitionCrossingRouteSolver"}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=this.routes.flatMap(t=>[t.A,t.B]).map(t=>this.getPortPointBoundsPosition(t));if(e.includes("outside"))return this.failed=!0,void(this.error="Invalid route input: SingleTransitionCrossingRouteSolver received port point(s) outside node bounds");if(e.includes("inside"))return void(this.failed=!0);const[n,o]=this.routes,s=n.A.z!==n.B.z,i=o.A.z!==o.B.z;return s&&i||!s&&!i?(this.failed=!0,void(this.error="Exactly one route must have a layer transition")):void 0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e)?.push(t)}for(const[e,o]of n.entries())2===o.length&&t.push({A:{...o[0],z:o[0].z??0},B:{...o[1],z:o[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}}getPortPointBoundsPosition(t,e=1e-6){return oe({point:t,bounds:this.bounds,epsilon:e})}doRoutesCross(t,e){return gt(t.A,t.B,e.A,e.B)}calculateViaPosition(t,e){const n=e.A.z,o=t.A.z!==n?t.A:t.B,s=2*this.obstacleMargin+this.viaDiameter/2+this.traceThickness,i=this.obstacleMargin+this.viaDiameter/2,r=e.A,a=o,c=e.B,h=ae(r,a,c,this.bounds),d=function(t,e,n,o,s){const i=ie(t,e,o,s),r=ie(e,n,o,s),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])<se&&(a[t]=0);return a}(r,a,c,this.bounds,h),l={minX:this.bounds.minX+(d.left>.5?s:i),minY:this.bounds.minY+(d.bottom>.5?s:i),maxX:this.bounds.maxX-(d.right>.5?s:i),maxY:this.bounds.maxY-(d.top>.5?s: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,s,l)}createTransitionRoute(t,e,n,o){return{connectionName:o,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,o,s,i){o.z,t.z;const r=this.viaDiameter/2+this.traceThickness/2+this.obstacleMargin,a=((t,e,n,o)=>{const s=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+s*e,y:t.y+i*e},{x:n.x-s*o,y:n.y-i*o})})(n,this.viaDiameter,o.z!==t.z?o:s,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,o=n?t:e,s=n?e:t,i=this.calculateViaPosition(o,s);if(!i)return!1;this.debugViaPositions.push({via:i});const r=this.createTransitionRoute(o.A,o.B,i,o.connectionName),a=this.createFlatRoute(s.A,s.B,i,o.A,o.B,s.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 o=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:n,radius:o,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],o=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 s=n.route[e],i=n.route[e+1];t.lines.push({points:[s,i],strokeColor:o,strokeDash:s.z!==n.route[0].z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${s.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}},he=class extends y{getSolverName(){return"SingleTransitionIntraNodeSolver"}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,o={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,o,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,o]of n.entries())2===o.length&&t.push({A:{...o[0]},B:{...o[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,o){return{connectionName:o,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],o="rgba(0, 255, 0, 0.75)";for(let e=0;e<n.route.length-1;e++){const s=n.route[e],i=n.route[e+1];t.lines.push({points:[s,i],strokeColor:o,strokeDash:s.z!==n.route[0].z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${s.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}},de=(t,e)=>{const n={};return t.portPoints.forEach((e,o)=>{n[e.connectionName]=`hsl(${360*o/t.portPoints.length}, 100%, 50%)`}),n},le=class extends y{getSolverName(){return"ViaPossibilitiesSolver2"}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:o}){super(),this.MAX_ITERATIONS=1e5,this.colorMap=e??de(t),this.maxViaCount=5,this.bounds=kt(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=o??.6,this.unprocessedConnections=Array.from(this.portPairMap.keys()).sort(),n?.SHUFFLE_SEED&&(this.unprocessedConnections=Bt(this.unprocessedConnections,n.SHUFFLE_SEED));for(const[t,{start:e,end:n}]of this.portPairMap.entries())if(e.z===n.z){const o=Math.abs(e.x-n.x)<1e-9,s=Math.abs(e.y-n.y)<1e-9;o||s?this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),this._padByPlaceholderWallBuffer(n),n]):this.placeholderPaths.set(t,[e,n])}else{const o=(e.x+n.x)/2,s=(e.y+n.y)/2,i=this._padByPlaceholderWallBuffer({x:o,y:s,z:e.z}),r=this._padByPlaceholderWallBuffer({x:o,y:s,z:n.z});this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),i,r,this._padByPlaceholderWallBuffer(n),n])}this.currentConnectionName=this.unprocessedConnections.pop();const s=this.portPairMap.get(this.currentConnectionName).start;this.currentHead=this._padByNewHeadWallBuffer(s),this.currentPath=[s,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,o=null;const s=t=>{for(const s of t.values())for(let t=0;t<s.length-1;t++){const i=[s[t],s[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=St(e[0],e[1],i[0],i[1]);if(r){const t=Pt(this.currentHead,r);if(t<1e-6)continue;(!n||t<n.dist)&&(n={point:r,dist:t},o=i[0].z)}}};s(this.completedPaths),s(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=Mt(this.currentHead,n.point);else{const o=n.point,s=o.x-this.currentHead.x,i=o.y-this.currentHead.y,r=(e-this.VIA_INTERSECTION_BUFFER_DISTANCE)/e;t={x:this.currentHead.x+s*r,y:this.currentHead.y+i*r}}const s=this.availableZ.find(t=>t!==o);if(void 0===s)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:s};this.currentPath.push(i,r),this.currentHead=r}else if(i){let e;const n=Pt(this.currentHead,t);if(n<this.VIA_INTERSECTION_BUFFER_DISTANCE)e=Mt(this.currentHead,t);else{const o=t.x-this.currentHead.x,s=t.y-this.currentHead.y,i=(n-this.VIA_INTERSECTION_BUFFER_DISTANCE)/n;e={x:this.currentHead.x+o*i,y:this.currentHead.y+s*i}}const o=t.z,s={...e,z:this.currentHead.z},i={...e,z:o};this.currentPath.push(s,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:o}]of this.portPairMap.entries()){const s=this.colorMap[e]??"black";t.points.push({x:n.x,y:n.y,color:s,label:`Port: ${e} Start (z${n.z})`}),t.points.push({x:o.x,y:o.y,color:s,label:`Port: ${e} End (z${o.z})`})}const n=(n,o)=>{for(const[s,i]of n.entries()){const n=e[s]??"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:`${o}: ${s} 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:`${o}: ${s} (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 o=this.currentPath[e],s=this.currentPath[e+1];o.x===s.x&&o.y===s.y&&o.z!==s.z?t.circles.push({center:{x:o.x,y:o.y},radius:this.viaDiameter/2,fill:it(n,.5),label:`Current: ${this.currentConnectionName} Via (z${o.z}->z${s.z})`}):t.lines.push({points:[o,s],strokeColor:it(n,.5),strokeWidth:.15,strokeDash:"2,2",label:`Current: ${this.currentConnectionName} (z${o.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}},ue=t=>Math.round(1e4*t),pe=t=>{let e=0,n=[];const o=[];for(const e of t.portPoints){if(n.some(t=>t.connectionName===e.connectionName))continue;if(o.some(t=>t.connectionName===e.connectionName))continue;const s={connectionName:e.connectionName,z:e.z,points:[{x:ue(e.x),y:ue(e.y),z:e.z}]};for(const n of t.portPoints)e.connectionName===n.connectionName&&(e.x===n.x&&e.y===n.y||s.points.push({x:ue(n.x),y:ue(n.y),z:n.z}));s.points.some(t=>t.z!==s.z)?o.push(s):n.push(s)}n=n.filter(t=>t.points.length>1);for(let t=0;t<n.length;t++)for(let o=t+1;o<n.length;o++){const s=n[t],i=n[o];s.z===i.z&&gt(s.points[0],s.points[1],i.points[0],i.points[1])&&e++}let s=0;for(let t=0;t<o.length;t++)for(let e=t+1;e<o.length;e++){const n=o[t],i=o[e];gt(n.points[0],n.points[1],i.points[0],i.points[1])&&s++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:o.length,numTransitionPairCrossings:s}},me=1e-9;function fe(t,e,n=me){return Math.abs(t-e)<n}function ge(t,e,n,o){return t*o-e*n}function ye(t,e,n,o){const s={x:e.x-t.x,y:e.y-t.y},i={x:o.x-n.x,y:o.y-n.y},r=ge(s.x,s.y,i.x,i.y);if(fe(r,0))return null;const a={x:n.x-t.x,y:n.y-t.y},c=ge(a.x,a.y,i.x,i.y)/r,h=ge(a.x,a.y,s.x,s.y)/r;return c<-me||c>1+me||h<-me||h>1+me?null:{x:t.x+c*s.x,y:t.y+c*s.y}}function xe(t){let e=0;for(let n=0,o=t.length;n<o;++n){const s=(n+1)%o;e+=t[n].x*t[s].y-t[s].x*t[n].y}return.5*e}function ve(t){let e=0,n=0,o=0;for(let s=0,i=t.length;s<i;++s){const r=(s+1)%i,a=t[s].x*t[r].y-t[r].x*t[s].y;e+=a,n+=(t[s].x+t[r].x)*a,o+=(t[s].y+t[r].y)*a}return e*=.5,fe(e,0)?null:(n/=6*e,o/=6*e,{x:n,y:o})}var Pe=class{x;y;out;connectionNames;constructor(t,e){this.x=t,this.y=e,this.out=[],this.connectionNames=new Set}},Se=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 Me(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}}]],o=n.map(()=>[]);for(let t=0;t<n.length;++t){const e=n[t];o[t].push(e.start,e.end)}for(let t=0;t<n.length;++t)for(let e=t+1;e<n.length;++e){const s=ye(n[t].start,n[t].end,n[e].start,n[e].end);s&&(o[t].push(s),o[e].push(s))}const s=new Map,i=[];function r(t){const e=function(t,e=me){return`${Math.round(t.x/e)}:${Math.round(t.y/e)}`}(t);if(!s.has(e)){const n=i.length;return s.set(e,n),i.push(new Pe(t.x,t.y)),n}return s.get(e)}const a=[];for(let t=0;t<n.length;++t){const e=n[t],s=o[t].slice();s.sort((t,n)=>{const o=e.end.x-e.start.x,s=e.end.y-e.start.y;return(fe(Math.abs(o),0)?(t.y-e.start.y)/s:(t.x-e.start.x)/o)-(fe(Math.abs(o),0)?(n.y-e.start.y)/s:(n.x-e.start.x)/o)});for(let t=0;t<s.length-1;++t){const n=s[t],o=s[t+1],c=r(n),h=r(o);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 Se(t,e),o=new Se(e,t);n.twin=c.length+1,o.twin=c.length;const s=c.length;c.push(n,o),i[t].out.push(s),i[e].out.push(s+1)}for(let t=0;t<i.length;++t){const e=i[t];e.out.sort((t,n)=>{const o=c[t],s=c[n],r=i[o.dest],a=i[s.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 o=e.out[t],s=e.out[(t-1+n)%n],i=c[o];null!==i.twin&&(c[i.twin].next=s)}}const h=[],d=[];for(let t=0;t<c.length;++t){if(c[t].visited)continue;let e=t;const n=[],o=[];do{if(null===e)break;const t=c[e];t.visited=!0,n.push(i[t.orig]),o.push(e),e=t.next}while(null!==e&&e!==t&&!c[e].visited);if(n.length<3)continue;if(xe(n)>me){const t=ve(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 be(t,e){if(t>e)throw new Error("oneCount cannot be greater than length");if(t<0||e<0)throw new Error("oneCount and length must be non-negative");const n=[];return function t(o,s,i){i!==e?(o[i]=0,t(o,s,i+1),s>0&&(o[i]=1,t(o,s-1,i+1))):0===s&&n.push([...o])}(Array(e).fill(0),t,0),n}var Ne=t=>{if(0===t.length)return[[]];const e=[];for(let n=0;n<t.length;n++){const o=t[n],s=[...t.slice(0,n),...t.slice(n+1)],i=Ne(s);for(const t of i)e.push([o,...t])}return e};var Ie=t=>{const{start:e,end:n,segmentsPerPolyline:o,viaPositions:s,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 o=Math.floor(t/e),s=Math.floor((t-(o*(e-1)+1))/2);for(let t=0;t<e;t++)n[s+t*o]=1}else{const o=t-e,s=Math.floor(t/o),i=Math.floor((t-(s*(o-1)+1))/2);n.fill(1);for(let t=0;t<o;t++)n[i+t*s]=0}return n}(o,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]={...s[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,o=c.length;for(let n=t+1;n<c.length;n++)if(c[n]){e=c[n],o=n;break}const s=o-t,i=e.x-u.x,r=e.y-u.y;for(let e=1/(s+1),n=0;t+n!==o;e+=1/(s+1),n++)c[t+n]={x:u.x+i*e,y:u.y+r*e,z1:u.z2,z2:u.z2}}return c},Ce=1e-9;function _e(t,e){return Math.abs(t-e)<Ce}function Te(t){return`${Math.round(t.x/Ce)}:${Math.round(t.y/Ce)}`}function Ee(t,e,n,o){return t*o-e*n}function Re(t,e,n,o){const s={x:e.x-t.x,y:e.y-t.y},i={x:o.x-n.x,y:o.y-n.y},r=Ee(s.x,s.y,i.x,i.y),a={x:n.x-t.x,y:n.y-t.y};if(_e(r,0))return null;const c=Ee(a.x,a.y,i.x,i.y)/r,h=Ee(a.x,a.y,s.x,s.y)/r;return c>=-1e-9&&c<=1+Ce&&h>=-1e-9&&h<=1+Ce?{x:t.x+c*s.x,y:t.y+c*s.y}:null}function we(t,e,n){return _e(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 Ae(t,e){const n=[],o=new Map;for(const e of t){const t=[e.start,...e.mPoints,e.end];for(let s=0;s<t.length-1;s++){const i=t[s],r=t[s+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=Te(i);o.has(t)||o.set(t,{point:i,connectionName:e.connectionName})}}const s=t[t.length-1];if(s.z1!==s.z2){const t=Te(s);o.has(t)||o.set(t,{point:s,connectionName:e.connectionName})}}const s=[{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(...s);const i=new Map;let r=0;function a(t,e){const n=Te(t);let s=i.get(n);if(!s){const e=o.has(n);s={id:r++,x:t.x,y:t.y,isVia:e,connectionNames:new Set,outgoingEdges:[]},i.set(n,s),e&&o.get(n)&&s.connectionNames.add(o.get(n).connectionName)}return e&&s.connectionNames.add(e),s}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 o=Re(n[t].start,n[t].end,n[e].start,n[e].end);o&&(a(o),we(o,n[t].start,n[t].end)&&c.get(n[t]).push(o),we(o,n[e].start,n[e].end)&&c.get(n[e]).push(o))}const h=[];let d=0;for(const t of n){const e=[t.start,...c.get(t),t.end];e.sort((e,n)=>{const o=t.end.x-t.start.x,s=t.end.y-t.start.y;return Math.abs(o)>Math.abs(s)?(e.x-t.start.x)/o-(n.x-t.start.x)/o:Math.abs(s)<Ce?0:(e.y-t.start.y)/s-(n.y-t.start.y)/s});const n=[];if(e.length>0){n.push(e[0]);for(let t=1;t<e.length;t++)_e(e[t].x,e[t-1].x)&&_e(e[t].y,e[t-1].y)||n.push(e[t])}for(let e=0;e<n.length-1;e++){const o=n[e],s=n[e+1],i=a(o,t.connectionName),r=a(s,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 o=e.twin.origin,s=n.twin.origin;return Math.atan2(o.y-t.y,o.x-t.x)-Math.atan2(s.y-t.y,s.x-t.x)});const e=t.outgoingEdges.length;for(let n=0;n<e;n++){const o=t.outgoingEdges[n],s=t.outgoingEdges[(n-1+e)%e];o.twin&&(o.twin.next=s)}}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 o=[],s=[],i=new Set;let r=0;do{if(!n||n.visited){console.warn("Face traversal encountered visited edge or null, breaking loop.",e.id),o.length=0;break}n.visited=!0,n.face=e,o.push(n),s.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&&o.length>0){if([...i].filter(t=>null!==t).length>1){let t=!1;for(const e of s)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 Oe=class extends y{getSolverName(){return"MultiHeadPolyLineIntraNodeSolver"}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??de(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,o=new Set(this.nodeWithPortPoints.portPoints.map(t=>t.connectionName)).size;this.uniqueConnections=o;const{numSameLayerCrossings:s,numEntryExitLayerChanges:i}=pe(this.nodeWithPortPoints);if(this.minViaCount=2*s+i,this.maxViaCount=Math.min(Math.floor(e/n),Math.ceil(1.5*o)),this.minViaCount>this.SEGMENTS_PER_POLYLINE*(o/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=[],o=[];for(let e=0;e<t.length;e++){const s=t[e],i=[s.start,...s.mPoints,s.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),o.push(i.filter(t=>t.z1!==t.z2))}for(let s=0;s<t.length;s++){const i=n[s],r=o[s];for(let a=s+1;a<t.length;a++){if(this.connMap?.areIdsConnected(t[s].connectionName,t[a].connectionName))continue;const c=n[a],h=o[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,Pt(t,e)-this.viaDiameter)}e.push(d)}}return e}insertCandidate(t){let e=0,n=this.candidates.length-1;for(;e<=n;){const o=Math.floor((e+n)/2);this.candidates[o].f<t.f?e=o+1:n=o-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,o)=>{const s=[];for(const[,n]of t){const t=n.start.z1!==n.end.z1,o=[];for(let n=0;n<=e;n++){const e=n%2!=0;t&&e?o.push(n):t||e||o.push(n)}s.push(o)}if(0===s.length)return[[]];let i=(t=>{if(!t||0===t.length)return[[]];let e=[[]];for(const n of t){const t=[];for(const o of e)for(const e of n)t.push([...o,e]);e=t}return e})(s).filter(t=>{for(let e=0;e<t.length;e++)if(t.reduce((t,e)=>t+e,0)<o)return!1;return!0});return i=i.filter(e=>{for(let n=0;n<t.length;n++){const[,o]=t[n];if(o.start.z1!==o.start.z2&&0===e[n])return!1}return!0}),i=i.filter(e=>{for(let n=0;n<t.length;n++){const[,o]=t[n];if(t[n][1].start.z1===t[n][1].start.z2)for(let s=n+1;s<t.length;s++){if(t[s][1].start.z1!==t[s][1].start.z2)continue;const[,i]=t[s];if(o.start.z1===o.end.z1&&i.start.z1===i.end.z1&&o.start.z1===i.start.z1&&gt(o.start,o.end,i.start,i.end)&&e[n]+e[s]<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),o=(t=>{const{bounds:e,portPairsEntries:n,viaCountVariants:o}=t,{centroids:s}=Me(e,n.map(([t,e])=>e)),i=[];for(const t of o){const n=t.reduce((t,e)=>t+e,0);let o=s;if(s.length<n){o=[];const t=Math.ceil(Math.sqrt(n)),s=t;for(let n=0;n<t;n++)for(let i=0;i<s;i++)o.push({x:e.minX+(i+1)/(s+1)*(e.maxX-e.minX),y:e.minY+(n+1)/(t+1)*(e.maxY-e.minY)})}const r=be(n,o.length);for(const e of r){const n=[];for(let t=0;t<e.length;t++)1===e[t]&&n.push(o[t]);i.push({viaPositions:n,viaCountVariant:t})}}return i})({portPairsEntries:e,viaCountVariants:n,bounds:this.bounds}),s=[];for(const{viaCountVariant:t,viaPositions:e}of o){const n=Ne(e);for(const e of n)s.push({viaCountVariant:t,viaPositions:e})}for(const{viaPositions:t,viaCountVariant:n}of s){const o=[];let s=0;for(let i=0;i<e.length;i++){const[r,a]=e[i],c=n[i],h=t.slice(s,s+c),d=Ie({start:a.start,end:a.end,segmentsPerPolyline:this.SEGMENTS_PER_POLYLINE,viaPositions:h,viaCount:c,availableZ:this.availableZ});s+=c,o.push({connectionName:r,start:a.start,end:a.end,mPoints:d})}if(Ae(o,this.bounds))continue;const i=this.computeMinGapBtwPolyLines(o),r=this.computeH({minGaps:i,forces:[]}),a={polyLines:o,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,o=.02,s=.008,i=1e-6,r=Array.from({length:n},(t,n)=>Array.from({length:e[n].mPoints.length},()=>new Map)),a=(t,n,o,s,i)=>{if(n>0&&n<e[t].mPoints.length+1){const e=n-1,a=r[t][e],c=a.get(o)||{fx:0,fy:0};a.set(o,{fx:c.fx+s,fy:c.fy+i})}};for(let t=0;t<n;t++)for(let s=t+1;s<n;s++){const n=e[t],r=e[s],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 o={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=o.x-r.x,h=o.y-r.y,d=c*c+h*h;if(d>i){const o=Math.sqrt(d),r=(Math.exp(-6*o),`seg:${s}:${n.p1Idx}:${n.p2Idx}`),c=`seg:${t}:${e.p1Idx}:${e.p2Idx}`,h=(t,e,n,o,s,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(o,e,r,f,g),a(s,n.p1Idx,c,-f/2,-g/2),a(s,n.p2Idx,c,-f/2,-g/2)};h(e.p1,e.p1Idx,n,t,s,r,c),h(e.p2,e.p2Idx,n,t,s,r,c),h(n.p1,n.p1Idx,e,s,t,c,r),h(n.p2,n.p2Idx,e,s,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*o*Math.exp(-6*u),m=c/r*p,f=h/r*p,g=`seg:${s}:${n.p1Idx}:${n.p2Idx}`;a(t,e.index,g,m,f);const y=`via:${t}:${e.index}`;a(s,n.p1Idx,y,-m/2,-f/2),a(s,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*o*Math.exp(-6*u),m=c/r*p,f=h/r*p,g=`seg:${t}:${n.p1Idx}:${n.p2Idx}`;a(s,e.index,g,m,f);const y=`via:${s}:${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*o*Math.exp(-6*u),m=r/d*p,f=c/d*p,g=`via:${s}:${n.index}`,y=`via:${t}:${e.index}`;a(t,e.index,g,m,f),a(s,n.index,y,-m,-f)}}}}for(let t=0;t<n;t++){const n=e[t],s=[n.start,...n.mPoints,n.end],r=[];if(s.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 s=r[e],c=r[n],h=s.point.x-c.point.x,d=s.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*o*Math.exp(-6*r),p=h/e*u,m=d/e*u,f=`via:${t}:${c.index}`,g=`via:${t}:${s.index}`;a(t,s.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],o=r[t][e],a={fx:0,fy:0};for(const t of o.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,o=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=s*(Math.exp(p/(2*this.obstacleMargin))-1):m>0&&(e=-.008*(Math.exp(m/(2*this.obstacleMargin))-1)),f>0?o=s*(Math.exp(f/(2*this.obstacleMargin))-1):g>0&&(o=-.008*(Math.exp(g/(2*this.obstacleMargin))-1)),a.fx+=e,a.fy+=o,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,o)=>{const s=this.colorMap[n.connectionName]??"purple",i=[n.start,...n.mPoints,n.end];for(let e=0;e<i.length-1;e++){const o=i[e],r=i[e+1],a=o.z2,c=0===a,h=c?s:it(s,.5);t.lines.push({points:[o,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 s=a-1,i=e.forces?.[o]?.[s];if(i&&i.size>0){const o={fx:0,fy:0};i.forEach((i,a)=>{if(o.fx+=i.fx,o.fy+=i.fy,Math.abs(i.fx)>1e-6||Math.abs(i.fy)>1e-6){const o=a.split(":"),c=o[0],h=parseInt(o[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(o[2],10)}`}else if("seg"===c){m+=` Seg ${parseInt(o[2],10)}-${parseInt(o[3],10)}`}t.lines.push({points:[r,p],strokeColor:l,strokeWidth:.02,strokeDash:"2,2",label:`Force by ${m} on ${n.connectionName} mPoint ${s}`})}}),(Math.abs(o.fx)>1e-6||Math.abs(o.fy)>1e-6)&&(u=`\nNet Force: (${o.fx.toFixed(3)}, ${o.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(s,.5),label:l});else if(d){const e=0===h?s:it(s,.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=[],o=[],s=[e.start,...e.mPoints,e.end];for(let t=0;t<s.length;t++){const e=s[t];n.push({x:e.x,y:e.y,z:e.z1}),e.z1!==e.z2&&(o.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:o})}this.solvedRoutes=t}},ze=class extends Oe{getSolverName(){return"MultiHeadPolyLineIntraNodeSolver2"}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 o=void 0===t.magForceApplied?1:10;for(let s=0;s<o;s++){const o=this.applyForcesToPolyLines(t.polyLines);if(n+=o.magForceApplied,e=o.lastStepMoved,!o.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,o=.02,s=.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,o,s)=>{if(n>0&&n<t[e].mPoints.length+1){const t=n-1;r[e][t].fx+=o,r[e][t].fy+=s}},c=(t,e,n,o,s)=>{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(o,e,p,m),a(s,n.p1Idx,-p/2,-m/2),a(s,n.p2Idx,-p/2,-m/2)};for(let e=0;e<n;e++)for(let s=e+1;s<n;s++){const n=t[e],r=t[s],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,s),c(t.p2,t.p2Idx,n,e,s),c(n.p1,n.p1Idx,t,s,e),c(n.p2,n.p2Idx,t,s,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*o*Math.exp(-6*u),m=c/r*p,f=h/r*p;a(e,t.index,m,f),a(s,n.p1Idx,-m/2,-f/2),a(s,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*o*Math.exp(-6*u),m=c/r*p,f=h/r*p;a(s,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*o*Math.exp(-6*u),m=r/d*p,f=c/d*p;a(e,t.index,m,f),a(s,n.index,-m,-f)}}}}for(let e=0;e<n;e++){const n=t[e],s=[n.start,...n.mPoints,n.end],r=[];if(s.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 s=r[t],c=r[n],h=s.point.x-c.point.x,d=s.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*o*Math.exp(-6*r),p=h/t*u,m=d/t*u;a(e,s.index,p,m),a(e,c.index,-p,-m)}}}let h=!1;for(let o=0;o<n;o++)for(let n=0;n<t[o].mPoints.length;n++){const a=t[o].mPoints[n],c=r[o][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 o=this.viaDiameter/2+this.BOUNDARY_PADDING,i=this.bounds.minX+o,r=this.bounds.maxX-o,c=this.bounds.minY+o,h=this.bounds.maxY-o,d=i+t-a.x,f=a.x-(r-t),g=c+t-a.y,y=a.y-(h-t);d>0?e=s*(Math.exp(d/(2*this.obstacleMargin))-1):f>0&&(e=-.008*(Math.exp(f/(2*this.obstacleMargin))-1)),g>0?n=s*(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}}},De=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 Le=class extends ze{getSolverName(){return"MultiHeadPolyLineIntraNodeSolver3"}constructor(t){super(t),this.MAX_ITERATIONS=1e3}createInitialCandidateFromSeed(t){const e=new le({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 o=0;for(const[t,s]of e.completedPaths.entries()){if(s.length<2){console.warn(`Skipping connection "${t}" due to insufficient points (${s.length}) in ViaPossibilitiesSolver2 path.`);continue}const e=s[0],i=s[s.length-1],r=s.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,o=h,s=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:o,z2:s}),o!==s?(c++,t++,h=s):h=e.z}o+=c;const d=this.SEGMENTS_PER_POLYLINE;let l=a.length+1;for(;l<d;){let n=-1,o=-1,s=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=Pt(e,i);a>n&&(n=a,o=t,s=e,r=i)}if(-1===o||!s||!r){console.warn(`Could not find longest segment for ${t} while trying to reach ${d} segments.`);break}const h=(s.x+r.x)/2,u=(s.y+r.y)/2,p=s.z2,m={x:h,y:u,z1:p,z2:p};a.splice(o,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 s=this.computeMinGapBtwPolyLines(n),i=this.computeH({minGaps:s,forces:[]}),r={polyLines:n,g:0,h:i,f:0+i,viaCount:o,minGaps:s};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 o=De(t.polyLines);e.has(o)||(e.add(o),this.candidates.push(t))}this.candidates.sort((t,e)=>t.f-e.f)}},Fe=class extends Zt{getSolverName(){return"HyperSingleIntraNodeSolver"}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 ce({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.CLOSED_FORM_SINGLE_TRANSITION?new he({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.MULTI_HEAD_POLYLINE_SOLVER?new Le({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 Xe(t,e,n){const o=[];let s=null;for(let i=0;i<t.length;i++){const r=t[i];s?s.z===r.z?s.points.push({x:r.x,y:r.y}):(o.push(s),s={points:[{x:r.x,y:r.y}],z:r.z,connectionName:e,color:n}):s={points:[{x:r.x,y:r.y}],z:r.z,connectionName:e,color:n},i===t.length-1&&s&&o.push(s)}return o}var Ye=class extends y{getSolverName(){return"HighDensitySolver"}unsolvedNodePortPoints;routes;colorMap;defaultViaDiameter=.6;defaultTraceThickness=.15;viaDiameter;traceWidth;failedSolvers;activeSubSolver=null;connMap;constructor({nodePortPoints:t,colorMap:e,connMap:n,viaDiameter:o,traceWidth:s}){super(),this.unsolvedNodePortPoints=t,this.colorMap=e??{},this.connMap=n,this.routes=[],this.failedSolvers=[],this.MAX_ITERATIONS=1e6,this.viaDiameter=o??this.defaultViaDiameter,this.traceWidth=s??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 Fe({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=Xe(e.route,e.connectionName,this.colorMap[e.connectionName]);for(const o of n)t.lines.push({points:o.points,label:o.connectionName,strokeColor:0===o.z?o.color:it(o.color,.75),layer:`z${o.z}`,strokeWidth:e.traceThickness,strokeDash:0!==o.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,o=.1*n.width,s=.1*n.height;t.rects.push({center:{x:n.center.x-o/2,y:n.center.y-s/2},layer:"did_not_connect",width:o,height:s,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 o=n[e],s=n[e+1];t.lines.push({points:[o,s],strokeColor:"red",strokeDash:"10, 5",layer:"did_not_connect"})}}return this.activeSubSolver&&(t=g(t,this.activeSubSolver.visualize())),t}},$e=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 o=this.getNetConnectedToId(e);return!!o&&(n===o||o===t||o===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}},Be=(t,e)=>"top"===t?0:"bottom"===t?e-1:parseInt(t.slice(5)),ke=t=>`${Math.round(100*t.x)},${Math.round(100*t.y)}`,je=t=>{const e=new $e({});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 o of n.pointsToConnect)e.addConnections([[n.name,`${ke(o)}:${"layers"in o?o.layers.map(e=>Be(e,t.layerCount)).sort().join("-"):Be(o.layer,t.layerCount)}`]]),"pcb_port_id"in o&&o.pcb_port_id&&e.addConnections([[n.name,o.pcb_port_id]])}for(const n of t.obstacles){const o=n.offBoardConnectsTo??[],s=Array.from(new Set([n.obstacleId,...n.connectedTo,...o,`${ke(n.center)}:${n.layers.map(e=>Be(e,t.layerCount)).sort().join("-")}`].filter(Boolean)));s.length>0&&e.addConnections([s])}return e},We=(t,e=1,n={})=>{const o=n.viaDiameter??.6,s=n.obstacleMargin??.2,i=(("width"in t?t.width:t)/(o/2+s)/2)**1.1*e;return 1===t.availableZ?.length&&i>1?1:i},He=(t,e=.5,n=16)=>{let o=0,s=t;for(;o<n;){if(We({width:s})<=e)break;s/=2,o++}return Math.max(1,o)},Ue=(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}`},Ve=(t,e)=>{const n=[];if(0===t.route.length)return n;let o=[],s=t.route[0].z;for(let i=0;i<t.route.length;i++){const r=t.route[i];if(r.z!==s){const i=Ue(s,e);for(const e of o)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=Ue(s,e),o=Ue(r.z,e);n.push({route_type:"via",x:r.x,y:r.y,from_layer:t,to_layer:o})}o=[r],s=r.z}else o.push(r)}const i=Ue(s,e);for(const e of o)n.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:i});if(t.jumpers&&t.jumpers.length>0){const o=Ue(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:o})}return n};function Ze(t){return"layers"in t&&Array.isArray(t.layers)}function Ge(t){return Ze(t)?t.layers[0]:t.layer}function Je(t){return Ze(t)?t.layers:[t.layer]}var qe={"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 Ke(t,e={}){const n=[],o=[],s=e.color??"gray",i=e.label,r=qe[t.footprint]??qe["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(s,.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(s,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper",label:i?`${i} (end)`:void 0}),o.push({points:[t.start,t.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*r.padWidth,layer:"jumper-body"}),{rects:n,lines:o}}function Qe(t,e={}){const n={rects:[],lines:[]};for(const o of t){const{rects:t,lines:s}=Ke(o,e);n.rects.push(...t),n.lines.push(...s)}return n}var tn=1e5,en=.001,nn=class extends y{getSolverName(){return"SingleHighDensityRouteStitchSolver"}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],o="start-to-end";for(const s of t.hdRoutes){const i=s.route[0],r=s.route[s.route.length-1],a=Pt(t.start,i),c=Pt(t.start,r),h=Pt(t.end,i),d=Pt(t.end,r),l=Math.min(a,c,h,d);l<e&&(e=l,n=s,o=Math.min(h,d)<Math.min(a,c)?"end-to-start":"start-to-end")}"start-to-end"===o?(this.start=t.start,this.end=t.end):(this.start=t.end,this.end=t.start);const s=n.route[0],i=n.route[n.route.length-1],r=Pt(this.start,s)<=Pt(this.start,i)?s: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&&Pt(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",o=1/0;for(let s=0;s<this.remainingHdRoutes.length;s++){const i=this.remainingHdRoutes[s],r=i.route[0],a=i.route[i.route.length-1],c=Pt(t,r),h=Pt(t,a);let d=1/0;d=t.z===r.z?c<en?c:tn+c:c<en?1e3+c:tn+c,d<o&&(o=d,e=s,n="first");let l=1/0;l=t.z===a.z?h<en?h:tn+h:h<en?1e3+h:tn+h,l<o&&(o=l,e=s,n="last")}if(-1===e)return void(this.remainingHdRoutes=[]);const s=this.remainingHdRoutes[e];let i;this.remainingHdRoutes.splice(e,1),i="first"===n?s.route:[...s.route].reverse(),i.length>0&&Pt(t,i[0])<en&&t.z===i[0].z?this.mergedHdRoute.route.push(...i.slice(1)):this.mergedHdRoute.route.push(...i),this.mergedHdRoute.vias.push(...s.vias),s.jumpers&&this.mergedHdRoute.jumpers.push(...s.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=Qe(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 o=this.colorMap[n.connectionName]??"gray";n.route.length>1&&t.lines?.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:o});for(let s=0;s<n.route.length;s++){const i=n.route[s];t.points?.push({x:i.x+(e%2-.5)/500+(s%8-4)/1e3,y:i.y+(e%2-.5)/500+(s%8-4)/1e3,color:o,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:o});if(n.jumpers&&n.jumpers.length>0){const e=Qe(n.jumpers,{color:o,label:n.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}return t}},on=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],o=this.netMap[e];if(t&&o){t.push(...o),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 o=this.getNetConnectedToId(e);return!!o&&(n===o||o===t||o===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}},sn=t=>`${Math.round(100*t.x)},${Math.round(100*t.y)},${Math.round(100*t.z)}`,rn=class extends y{getSolverName(){return"MultipleHighDensityRouteStitchSolver"}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 on({}),o=[],s=new Map;for(let e=0;e<t.hdRoutes.length;e++){const n=t.hdRoutes[e],s=n.route[0],i=n.route[n.route.length-1];o.push([`route_island_${e}`,`${n.connectionName}:${sn(s)}`,`${n.connectionName}:${sn(i)}`])}n.addConnections(o);for(const t of o)for(const e of t.slice(1))s.set(e,(s.get(e)??0)+1);this.unsolvedRoutes=[];const i=Array.from(new Set(Object.values(n.idToNetMap)));for(const e of i){const o=n.getIdsConnectedToNet(e),i=t.hdRoutes.filter((t,e)=>o.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}:${sn(t)}`;1===s.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:Be(Ge(r.pointsToConnect[0]),t.layerCount)},d={...r.pointsToConnect[1],z:Be(Ge(r.pointsToConnect[1]),t.layerCount)}):(h=c[0],d=c[1],Pt(h,r.pointsToConnect[1])<Pt(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 nn&&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 nn({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 o=this.colorMap[n.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<n.route.length-1;e++){const s=n.route[e],i=n.route[e+1],r=0!==s.z?it(o,.5):o;t.lines?.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:r,strokeWidth:n.traceThickness})}for(const e of n.route){const n=0!==e.z?it(o,.5):o;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:o});if(n.jumpers&&n.jumpers.length>0){const e=Qe(n.jumpers,{color:o,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 o of e.hdRoutes){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"});for(const e of o.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:o.viaDiameter/2,fill:n});if(o.jumpers&&o.jumpers.length>0){const e=Qe(o.jumpers,{color:n,label:o.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}}return t}},an=t=>{const e=[],n=[],o=[],s=[],i=st(t),r=(t.minViaDiameter??.6)/2;if(t.connections)for(const e of t.connections)for(const t of e.pointsToConnect){const n=Je(t);o.push({x:t.x,y:t.y,color:i[e.name],layer:n[0]??("z"in t?Ue(t.z,2):"top"),label:`${e.name} (${n.join(",")})`})}if(t.traces)for(const o of t.traces){let a=t.minTraceWidth;const c=o.route.filter(t=>"jumper"===t.route_type),h=(t,e)=>{const n=.01;for(const o of c){const s=Math.abs(t.x-o.start.x)<n&&Math.abs(t.y-o.start.y)<n&&Math.abs(e.x-o.end.x)<n&&Math.abs(e.y-o.end.y)<n,i=Math.abs(t.x-o.end.x)<n&&Math.abs(t.y-o.end.y)<n&&Math.abs(e.x-o.start.x)<n&&Math.abs(e.y-o.start.y)<n;if(s||i)return!0}return!1};for(let t=0;t<o.route.length-1;t++){const c=o.route[t],d=o.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[o.connection_name]??"rgba(255, 165, 0, 0.8)",n=c.footprint,r=qe["1206x4_pair"===n?"1206x4_pair":"0603"]??qe["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;s.push({center:c.start,width:l,height:u,fill:it(t,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),s.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[o.connection_name],n="top"===c.layer,s=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${Be(c.layer,2)}`,strokeWidth:a,strokeColor:n?s:it(s,.5),...n?{}:{strokeDash:"3 2"}})}}}for(const e of t.obstacles)s.push({center:e.center,width:e.width,height:e.height,fill:"rgba(255,0,0,0.5)",layer:`z${e.layers.map(t=>Be(t,2)).join(",")}`});if(t.jumpers)for(const e of t.jumpers)for(const t of e.pads)s.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:s,circles:n,lines:e,points:o}};function cn(t,e){const n=t.center.x-t.width/2,o=t.center.x+t.width/2,s=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(o-r)<d||Math.abs(n-a)<d)&&Math.min(i,h)-Math.max(s,c)>=d,u=(Math.abs(i-c)<d||Math.abs(s-h)<d)&&Math.min(o,a)-Math.max(n,r)>=d;return l||u}var hn=class extends y{constructor(t){super(),this.nodes=t,this.edges=[]}getSolverName(){return"CapacityMeshEdgeSolver"}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)&&cn(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 o of this.nodes){if(o._containsObstacle)continue;if(o._containsTarget)continue;const s=Pt(e.center,o.center);s<n&&(n=s,t=o)}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]),o=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&o?.center){const t=Math.min(...n.availableZ),s=Math.min(...o.availableZ),i={x:n.center.x+t*n.width*.05,y:n.center.y-t*n.width*.05},r={x:o.center.x+s*o.width*.05,y:o.center.y-s*o.width*.05},a=Array.from(new Set([...n.availableZ,...o.availableZ])).sort();e.lines.push({layer:`z${a.join(",")}`,points:[i,r],strokeDash:n.availableZ.join(",")===o.availableZ.join(",")?void 0:"10 5"})}}return e}},dn=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,o=e.center.x+e.width/2,s=e.center.y+e.height/2;for(let i=t;i<=o;i+=this.CELL_SIZE)for(let t=n;t<=s;t+=this.CELL_SIZE){const n=this.getBucketKey(i,t),o=this.buckets.get(n);o?o.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,o){const s=[],i=new Set,r=e-o/2,a=t+n/2,c=e+o/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),o=this.buckets.get(n)||[];for(const t of o)i.has(t.capacityMeshNodeId)||(i.add(t.capacityMeshNodeId),s.push(t))}return s}},ln=class extends hn{constructor(t){super(t),this.nodes=t,this.MAX_ITERATIONS=1e7,this.nodeTree=new dn(this.nodes),this.currentNodeIndex=0,this.edgeSet=new Set}getSolverName(){return"CapacityMeshEdgeSolver2_NodeTreeOptimization"}nodeTree;currentNodeIndex;edgeSet;_step(){if(this.currentNodeIndex>=this.nodes.length)return this.handleTargetNodes(),void(this.solved=!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(!cn(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++}},un=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),o=this.find(e);n!==o&&(this.parent[o]=n)}getGroup(t){const e=this.find(t),n=[];for(const t in this.parent)this.find(t)===e&&n.push(t);return n}},pn=class{point;left=null;right=null;constructor(t){this.point=t}},mn=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 o=Math.floor(t.length/2),s=new pn(t[o]);return o>0&&(s.left=this.buildTree(t.slice(0,o),e+1)),o<t.length-1&&(s.right=this.buildTree(t.slice(o+1),e+1)),s}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,o,s){if(!t)return o;const i=n%2?"x":"y",r=this.distance(e,t.point);r<s&&(o=t.point,s=r);const a=e[i]-t.point[i],c=a<=0?t.left:t.right,h=a<=0?t.right:t.left;return o=this.nearestNeighborSearch(c,e,n+1,o,s),s=this.distance(e,o),Math.abs(a)<s&&(o=this.nearestNeighborSearch(h,e,n+1,o,s)),o}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,o,s){if(!t)return;const i=n%2?"x":"y",r=this.distance(e,t.point);o.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,o,s);let d=1/0;o.length>=s&&(o.sort((t,e)=>t.distance-e.distance),d=o[s-1]?.distance||1/0),(Math.abs(a)<d||o.length<s)&&this.kNearestNeighborSearch(h,e,n+1,o,s)}distance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}},fn=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 o=e;for(;o!==n;){const t=this.parent.get(o);this.parent.set(o,n),o=t}return n}union(t,e){const n=this.find(t),o=this.find(e);if(n===o)return!1;const s=this.rank.get(n)||0,i=this.rank.get(o)||0;return s<i?this.parent.set(n,o):s>i?this.parent.set(o,n):(this.parent.set(o,n),this.rank.set(n,s+1)),!0}};function gn(t){if(t.length<=1)return[];const e=new mn(t),n=[],o=Math.min(10,t.length-1);for(const s of t){const t=e.findKNearestNeighbors(s,o+1);for(const e of t){if(s.x===e.x&&s.y===e.y)continue;const t=Math.sqrt((s.x-e.x)**2+(s.y-e.y)**2);n.push({from:s,to:e,weight:t})}}n.sort((t,e)=>t.weight-e.weight);const s=new fn(t),i=[];for(const e of n)if(s.union(e.from,e.to)&&(i.push(e),i.length===t.length-1))break;return i}function yn(t){if(t.pointId)return t.pointId;let e="";var n;return"layer"in(n=t)&&"string"==typeof n.layer?e=t.layer:Ze(t)&&t.layers&&(e=t.layers.sort().join("-")),`${t.x.toFixed(4)},${t.y.toFixed(4)},${e}`}var xn=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 un(e),o=new Map;t.forEach((t,e)=>{const n=`conn_${e}`;t.pointsToConnect.forEach(t=>{const e=yn(t);o.has(e)||o.set(e,[]),o.get(e).push(n)})});for(const t of o.values())if(t.length>1){const e=t[0];for(let o=1;o<t.length;o++)n.union(e,t[o])}const s=new Map;t.forEach((t,e)=>{const o=`conn_${e}`,i=n.find(o);s.has(i)||s.set(i,[]),s.get(i).push(t)});const i=[];for(const t of s.values()){if(1===t.length){i.push(t[0]);continue}const e=new Map,n=new Set;let o=!1;const s=[],r=new Set;let a;t.forEach(t=>{t.pointsToConnect.forEach(t=>e.set(yn(t),t)),n.add(t.name),t.isOffBoard&&(o=!0),t.externallyConnectedPointIds&&s.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:o,externallyConnectedPointIds:s.length>0?s:void 0,netConnectionName:r.size>0?Array.from(r).join("__"):void 0,nominalTraceWidth:a};i.push(c)}return i}([...t.connections]),this.newConnections=[]}getSolverName(){return"NetToPointPairsSolver"}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 o=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const o=n.get(t.pointId),s=n.get(e.pointId);return void 0!==o&&o===s};if(2===t.pointsToConnect.length){if(o(t.pointsToConnect[0],t.pointsToConnect[1]))return;return void this.newConnections.push({...t,rootConnectionName:t.name})}const s=gn(t.pointsToConnect);let i=0;for(const e of s)o(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,o=Yt(0),s=new Set;for(let i=0;i<Math.max(n,2*e.pointsToConnect.length);i++){const n=Math.floor(o()*e.pointsToConnect.length),i=Math.floor(o()*e.pointsToConnect.length);s.has(`${n}-${i}`)||(s.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(o=>{t.points.push({x:o.x,y:o.y,color:n,label:e.name})});for(let o=0;o<e.pointsToConnect.length-1;o++)for(let s=o+1;s<e.pointsToConnect.length;s++)t.lines.push({points:[e.pointsToConnect[o],e.pointsToConnect[s]],strokeColor:n})}),t}},vn=class extends xn{constructor(t,e={}){const n=t.connections.flatMap(t=>t.pointsToConnect),o=new Map;for(const t of n)t.pointId&&o.set(t.pointId,t);const s=n.map(t=>t.pointId).filter(t=>!!t),i=new un(s),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=o,this.ogSrj=t}getSolverName(){return"NetToPointPairsSolver2_OffBoardConnection"}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)),o=this.connectionPointDsu.getGroup(e.pointId).map(t=>this.connectionPointMap.get(t));let s=t,i=e,r=1/0;for(const t of n)for(const e of o){const n=Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));n<r&&(r=n,s=t,i=e)}return{pointsToConnect:[s,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 o=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const o=n.get(t.pointId),s=n.get(e.pointId);return void 0!==o&&o===s};if(2===t.pointsToConnect.length){if(o(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 s=gn(t.pointsToConnect);let i=0;for(const e of s){if(o(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 Pn(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 Sn(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}var{cos:Mn,sin:bn,PI:Nn}=Math,{tan:In}=Math;a(l()),a(f());function Cn(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 _n=class{MAX_ITERATIONS=1e5;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};_setupDone=!1;getSolverName(){return this.constructor.name}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.getSolverName()} 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.getSolverName()} 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:[]}}};function Tn(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var En=class extends _n{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,o=this.firstIterationOfStage[e.solverName]||0,s=this.iterations,i=e.solverName===this.getCurrentStageName()?s-o: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&&(Cn(e,0),t=1);let n=null;this.solved&&(n=this.finalVisualize());const o=[e].filter(Boolean).concat(this.pipelineDef.map((e,n)=>{const o=this[e.solverName],s=o?.visualize();return s?(Cn(s,n+t),s):null}).filter(Boolean));return 0===o.length?{points:[],rects:[],lines:[],circles:[],texts:[]}:(this.solved&&n&&(Cn(n,o.length+t+1),o.push(n)),1===o.length?o[0]:{points:o.flatMap(t=>t.points||[]),rects:o.flatMap(t=>t.rects||[]),lines:o.flatMap(t=>t.lines||[]),circles:o.flatMap(t=>t.circles||[]),texts:o.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]}},Rn=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,o=this.values[t];if(e>=o)break;this.ids[n]=this.ids[t],this.values[n]=o,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],o=--this.length;if(o>0){const n=t[o],s=e[o];let i=0;const r=o>>1;for(;i<r;){const n=1+(i<<1),r=n+1,a=n+(+(r<o)&+(e[r]<e[n]));if(e[a]>=s)break;t[i]=t[a],e[i]=e[a],i=a}t[i]=n,e[i]=s}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}},wn=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],An=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[o,s]=new Uint8Array(e,n+0,2);if(251!==o)throw new Error("Data does not appear to be in a Flatbush format.");const i=s>>4;if(3!==i)throw new Error(`Got v${i} data when expected v3.`);const r=wn[15&s];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,o=ArrayBuffer,s,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=wn.indexOf(n),h=4*a*n.BYTES_PER_ELEMENT;if(c<0)throw new Error(`Unexpected typed array class: ${n}.`);if(s)this.data=s,this._boxes=new n(s,i+8,4*a),this._indices=new this.IndexArrayType(s,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 s=this.data=new o(8+h+a*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new n(s,8,4*a),this._indices=new this.IndexArrayType(s,8+h,a),this._pos=0,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,new Uint8Array(s,0,2).set([251,48+c]),new Uint16Array(s,2,1)[0]=e,new Uint32Array(s,4,1)[0]=t}this._queue=new Rn}add(t,e,n=t,o=e){const s=this._pos>>2,i=this._boxes;return this._indices[s]=s,i[this._pos++]=t,i[this._pos++]=e,i[this._pos++]=n,i[this._pos++]=o,t<this.minX&&(this.minX=t),e<this.minY&&(this.minY=e),n>this.maxX&&(this.maxX=n),o>this.maxY&&(this.maxY=o),s}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,o=new Uint32Array(this.numItems);for(let s=0,i=0;s<this.numItems;s++){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);o[s]=Ln(d,l)}zn(o,t,this._indices,0,this.numItems-1,this.nodeSize);for(let e=0,n=0;e<this._levelBounds.length-1;e++){const o=this._levelBounds[e];for(;n<o;){const e=n;let s=t[n++],i=t[n++],r=t[n++],a=t[n++];for(let e=1;e<this.nodeSize&&n<o;e++)s=Math.min(s,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++]=s,t[this._pos++]=i,t[this._pos++]=r,t[this._pos++]=a}}}search(t,e,n,o,s){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,On(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(o<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===s||s(p,c,d,l,u))&&a.push(p)}i=r.pop()}return a}neighbors(t,e,n=1/0,o=1/0,s){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=o*o;t:for(;void 0!==i;){const o=Math.min(i+4*this.nodeSize,On(i,this._levelBounds));for(let n=i;n<o;n+=4){const o=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(o<<1,m):(void 0===s||s(o))&&r.push(1+(o<<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 On(t,e){let n=0,o=e.length-1;for(;n<o;){const s=n+o>>1;e[s]>t?o=s:n=s+1}return e[n]}function zn(t,e,n,o,s,i){if(Math.floor(o/i)>=Math.floor(s/i))return;const r=t[o],a=t[o+s>>1],c=t[s];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=o-1,u=s+1;for(;;){do{l++}while(t[l]<h);do{u--}while(t[u]>h);if(l>=u)break;Dn(t,e,n,l,u)}zn(t,e,n,o,u,i),zn(t,e,n,u+1,s,i)}function Dn(t,e,n,o,s){const i=t[o];t[o]=t[s],t[s]=i;const r=4*o,a=4*s,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[o];n[o]=n[s],n[s]=u}function Ln(t,e){let n=t^e,o=65535^n,s=65535^(t|e),i=t&(65535^e),r=n|o>>1,a=n>>1^n,c=s>>1^o&i>>1^s,h=n&s>>1^i>>1^i;n=r,o=a,s=c,i=h,r=n&n>>2^o&o>>2,a=n&o>>2^o&(n^o)>>2,c^=n&s>>2^o&i>>2,h^=o&s>>2^(n^o)&i>>2,n=r,o=a,s=c,i=h,r=n&n>>4^o&o>>4,a=n&o>>4^o&(n^o)>>4,c^=n&s>>4^o&i>>4,h^=o&s>>4^(n^o)&i>>4,n=r,o=a,s=c,i=h,c^=n&s>>8^o&i>>8,h^=o&s>>8^(n^o)&i>>8,n=c^c>>1,o=h^h>>1;let d=t^e,l=o|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 Fn(t,e,n=0,o=t.length-1,s=Yn){for(;o>n;){if(o-n>600){const i=o-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);Fn(t,e,Math.max(n,Math.floor(e-r*c/i+h)),Math.min(o,Math.floor(e+(i-r)*c/i+h)),s)}const i=t[e];let r=n,a=o;for(Xn(t,n,e),s(t[o],i)>0&&Xn(t,n,o);r<a;){for(Xn(t,r,a),r++,a--;s(t[r],i)<0;)r++;for(;s(t[a],i)>0;)a--}0===s(t[n],i)?Xn(t,n,a):(a++,Xn(t,a,o)),a<=e&&(n=a+1),e<=a&&(o=a-1)}}function Xn(t,e,n){const o=t[e];t[e]=t[n],t[n]=o}function Yn(t,e){return t<e?-1:t>e?1:0}var $n=class{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(.4*this._maxEntries)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const n=[];if(!Kn(t,e))return n;const o=this.toBBox,s=[];for(;e;){for(let i=0;i<e.children.length;i++){const r=e.children[i],a=e.leaf?o(r):r;Kn(t,a)&&(e.leaf?n.push(r):qn(t,a)?this._all(r,n):s.push(r))}e=s.pop()}return n}collides(t){let e=this.data;if(!Kn(t,e))return!1;const n=[];for(;e;){for(let o=0;o<e.children.length;o++){const s=e.children[o],i=e.leaf?this.toBBox(s):s;if(Kn(t,i)){if(e.leaf||qn(t,i))return!0;n.push(s)}}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=Qn([]),this}remove(t,e){if(!t)return this;let n=this.data;const o=this.toBBox(t),s=[],i=[];let r,a,c;for(;n||s.length;){if(n||(n=s.pop(),a=s[s.length-1],r=i.pop(),c=!0),n.leaf){const o=Bn(t,n.children,e);if(-1!==o)return n.children.splice(o,1),s.push(n),this._condense(s),this}c||n.leaf||!qn(n,o)?a?(r++,n=a.children[r],c=!1):n=null:(s.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,o){const s=n-e+1;let i,r=this._maxEntries;if(s<=r)return i=Qn(t.slice(e,n+1)),kn(i,this.toBBox),i;o||(o=Math.ceil(Math.log(s)/Math.log(r)),r=Math.ceil(s/Math.pow(r,o-1))),i=Qn([]),i.leaf=!1,i.height=o;const a=Math.ceil(s/r),c=a*Math.ceil(Math.sqrt(r));to(t,e,n,c,this.compareMinX);for(let s=e;s<=n;s+=c){const e=Math.min(s+c-1,n);to(t,s,e,a,this.compareMinY);for(let n=s;n<=e;n+=a){const s=Math.min(n+a-1,e);i.children.push(this._build(t,n,s,o-1))}}return kn(i,this.toBBox),i}_chooseSubtree(t,e,n,o){for(;o.push(e),!e.leaf&&o.length-1!==n;){let n,o=1/0,s=1/0;for(let i=0;i<e.children.length;i++){const r=e.children[i],a=Vn(r),c=Gn(t,r)-a;c<s?(s=c,o=a<o?a:o,n=r):c===s&&a<o&&(o=a,n=r)}e=n||e.children[0]}return e}_insert(t,e,n){const o=n?t:this.toBBox(t),s=[],i=this._chooseSubtree(o,this.data,e,s);for(i.children.push(t),Wn(i,o);e>=0&&s[e].children.length>this._maxEntries;)this._split(s,e),e--;this._adjustParentBBoxes(o,s,e)}_split(t,e){const n=t[e],o=n.children.length,s=this._minEntries;this._chooseSplitAxis(n,s,o);const i=this._chooseSplitIndex(n,s,o),r=Qn(n.children.splice(i,n.children.length-i));r.height=n.height,r.leaf=n.leaf,kn(n,this.toBBox),kn(r,this.toBBox),e?t[e-1].children.push(r):this._splitRoot(n,r)}_splitRoot(t,e){this.data=Qn([t,e]),this.data.height=t.height+1,this.data.leaf=!1,kn(this.data,this.toBBox)}_chooseSplitIndex(t,e,n){let o,s=1/0,i=1/0;for(let r=e;r<=n-e;r++){const e=jn(t,0,r,this.toBBox),a=jn(t,r,n,this.toBBox),c=Jn(e,a),h=Vn(e)+Vn(a);c<s?(s=c,o=r,i=h<i?h:i):c===s&&h<i&&(i=h,o=r)}return o||n-e}_chooseSplitAxis(t,e,n){const o=t.leaf?this.compareMinX:Hn,s=t.leaf?this.compareMinY:Un;this._allDistMargin(t,e,n,o)<this._allDistMargin(t,e,n,s)&&t.children.sort(o)}_allDistMargin(t,e,n,o){t.children.sort(o);const s=this.toBBox,i=jn(t,0,e,s),r=jn(t,n-e,n,s);let a=Zn(i)+Zn(r);for(let o=e;o<n-e;o++){const e=t.children[o];Wn(i,t.leaf?s(e):e),a+=Zn(i)}for(let o=n-e-1;o>=e;o--){const e=t.children[o];Wn(r,t.leaf?s(e):e),a+=Zn(r)}return a}_adjustParentBBoxes(t,e,n){for(let o=n;o>=0;o--)Wn(e[o],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():kn(t[n],this.toBBox)}};function Bn(t,e,n){if(!n)return e.indexOf(t);for(let o=0;o<e.length;o++)if(n(t,e[o]))return o;return-1}function kn(t,e){jn(t,0,t.children.length,e,t)}function jn(t,e,n,o,s){s||(s=Qn(null)),s.minX=1/0,s.minY=1/0,s.maxX=-1/0,s.maxY=-1/0;for(let i=e;i<n;i++){const e=t.children[i];Wn(s,t.leaf?o(e):e)}return s}function Wn(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 Hn(t,e){return t.minX-e.minX}function Un(t,e){return t.minY-e.minY}function Vn(t){return(t.maxX-t.minX)*(t.maxY-t.minY)}function Zn(t){return t.maxX-t.minX+(t.maxY-t.minY)}function Gn(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 Jn(t,e){const n=Math.max(t.minX,e.minX),o=Math.max(t.minY,e.minY),s=Math.min(t.maxX,e.maxX),i=Math.min(t.maxY,e.maxY);return Math.max(0,s-n)*Math.max(0,i-o)}function qn(t,e){return t.minX<=e.minX&&t.minY<=e.minY&&e.maxX<=t.maxX&&e.maxY<=t.maxY}function Kn(t,e){return e.minX<=t.maxX&&e.minY<=t.maxY&&e.maxX>=t.minX&&e.maxY>=t.minY}function Qn(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function to(t,e,n,o,s){const i=[e,n];for(;i.length;){if((n=i.pop())-(e=i.pop())<=o)continue;const r=e+Math.ceil((n-e)/o/2)*o;Fn(t,r,e,n,s),i.push(e,r,r,n)}}var eo=1e-4;var no=[{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}],oo={"x-":no.find(t=>"x-"===t.facingDirection),"x+":no.find(t=>"x+"===t.facingDirection),"y-":no.find(t=>"y-"===t.facingDirection),"y+":no.find(t=>"y+"===t.facingDirection)},so={"x-":{x:-1,y:0},"x+":{x:1,y:0},"y-":{x:0,y:-1},"y+":{x:0,y:1}},io=(t,e)=>{const{dir:n,amt:o}=e,s=so[n];return t.map(t=>({x:t.x+s.x*o,y:t.y+s.y*o}))},ro=1e-4,ao=class extends _n{constructor(t){super(),this.input=t;for(const t of this.input.meshNodes)for(const e of no){let n={x:t.center.x+t.width*e.startX,y:t.center.y+t.height*e.startY},o={x:t.center.x+t.width*e.endX,y:t.center.y+t.height*e.endY};n.x>o.x&&([n,o]=[o,n]),Math.abs(n.x-o.x)<ro&&n.y>o.y&&([n,o]=[o,n]);for(const s of t.availableZ)this.unprocessedEdges.push({parent:t,start:n,end:o,facingDirection:e.facingDirection,z:s})}this.allEdges=[...this.unprocessedEdges],this.edgeSpatialIndex=new An(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-ro,t.start.y-ro,t.end.x+ro,t.end.y+ro).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)<eo,o=Math.abs(t.start.x-t.end.x)<eo;if(!n&&!o)return[];const s=n?"x":"y",i=n?"y":"x",r=t.start[i],a=t.start[s],c=t.end[s],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)<eo,o=Math.abs(n.start.x-n.end.x)<eo;if("x"===s&&!e)continue;if("y"===s&&!o)continue;if(Math.abs(n.start[i]-r)>eo)continue;const a=Math.min(n.start[s],n.end[s]),c=Math.max(n.start[s],n.end[s]),h=l(a),d=l(c);d-h>eo&&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+eo?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+eo&&m.push({s:f,e:t.s}),f=Math.max(f,t.e),f>=d-eo)break;return d>f+eo&&m.push({s:f,e:d}),0===m.length?[]:m.filter(t=>t.e-t.s>eo).map(e=>{const n="x"===s?{x:e.s,y:r}:{x:r,y:e.s},o="x"===s?{x:e.e,y:r}:{x:r,y:e.e};return{parent:t.parent,facingDirection:t.facingDirection,start:n,end:o,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:io([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:io([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:io([e.start,e.end],{dir:e.facingDirection,amt:-.05}),strokeColor:"green",strokeDash:"2 2"});return t}},co=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))}),ho=1e-4,lo=class extends _n{constructor(t){super(),this.input=t,this.unprocessedSegments=[...this.input.segmentsWithAdjacentEmptySpace],this.rectSpatialIndex=new $n,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}=oo[t.facingDirection],o=t.end.x-t.start.x,s=t.end.y-t.start.y,i=Math.sqrt(o**2+s**2),r=o/i,a=s/i;let c=null,h=1;const d={x:t.start.x+e*ho+r*ho*10,y:t.start.y+n*ho+a*ho*10},l={x:t.end.x+e*ho-r*ho*10,y:t.end.y+n*ho-a*ho*10};for(this.lastSearchCorner1=d,this.lastSearchCorner2=l;(!c||0===c.length)&&h<1e3;){const o=co([d,l,{x:d.x+e*h,y:d.y+n*h},{x:l.x+e*h,y:l.y+n*h}]);this.lastSearchBounds=o,c=this.rectSpatialIndex.search(o).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=co([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<ho||y<ho||(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}},uo=class extends En{findSegmentsWithAdjacentEmptySpaceSolver;expandEdgesToEmptySpaceSolver;pipelineDef=[Tn("findSegmentsWithAdjacentEmptySpaceSolver",ao,t=>[{meshNodes:t.inputProblem.meshNodes}],{onSolved:()=>{}}),Tn("expandEdgesToEmptySpaceSolver",lo,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??[],o=new Set(n.map(t=>t.newNode.capacityMeshNodeId));for(const n of e){const e=o.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}},po=1e-9,mo=(t,e,n)=>Math.max(e,Math.min(n,t)),fo=(t,e)=>t>e+po,go=(t,e)=>t>e-po,yo=(t,e)=>t<e-po,xo=(t,e)=>t<e+po;function vo(t,e){return!(t.x+t.width<=e.x+po||e.x+e.width<=t.x+po||t.y+t.height<=e.y+po||e.y+e.height<=t.y+po)}function Po(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 o=1/0;for(const[e,s,i,r]of n){const n=t.x-e,a=t.y-s,c=i-e,h=r-s,d=c*c+h*h;let l=0!==d?(n*c+a*h)/d:0;l=mo(l,0,1);const u=e+l*c,p=s+l*h;o=Math.min(o,Math.hypot(t.x-u,t.y-p))}return o}function So(t,e){const n=Math.max(t[0],e[0]),o=Math.min(t[1],e[1]);return o>n+po?[n,o]:null}function Mo(t,e){if(!vo(t,e))return[t];const n=So([t.x,t.x+t.width],[e.x,e.x+e.width]),o=So([t.y,t.y+t.height],[e.y,e.y+e.height]);if(!n||!o)return[t];const[s,i]=n,[r,a]=o,c=[];s>t.x+po&&c.push({x:t.x,y:t.y,width:s-t.x,height:t.height}),t.x+t.width>i+po&&c.push({x:i,y:t.y,width:t.x+t.width-i,height:t.height});const h=Math.max(0,i-s);return h>po&&r>t.y+po&&c.push({x:s,y:t.y,width:h,height:r-t.y}),h>po&&t.y+t.height>a+po&&c.push({x:s,y:a,width:h,height:t.y+t.height-a}),c.filter(t=>t.width>po&&t.height>po)}function bo(t,e){let n=!1;for(let o=0,s=e.length-1;o<e.length;s=o++){const i=e[o].x,r=e[o].y,a=e[s].x,c=e[s].y;r>t.y!=c>t.y&&t.x<(a-i)*(t.y-r)/(c-r)+i&&(n=!n)}return n}function No(t,e){if(!e||e.length<3)return[];const n=e.length>100?function(t,e){const n=t=>Math.round(t/e)*e,o=new Set,s=[];for(const e of t){const t=n(e.x),i=n(e.y),r=`${t},${i}`;o.has(r)||(o.add(r),s.push({x:t,y:i}))}return s}(e,Math.max(t.width,t.height)/100):e,o=new Set([t.x,t.x+t.width]),s=new Set([t.y,t.y+t.height]);for(const t of n)o.add(t.x),s.add(t.y);const i=Array.from(o).sort((t,e)=>t-e),r=Array.from(s).sort((t,e)=>t-e),a=[];for(let n=0;n<i.length-1;n++)for(let o=0;o<r.length-1;o++){const s=i[n],c=i[n+1],h=r[o],d=r[o+1],l=(s+c)/2,u=(h+d)/2;l>=t.x&&l<=t.x+t.width&&u>=t.y&&u<=t.y+t.height&&(bo({x:l,y:u},e)||a.push({x:s,y:h,width:c-s,height:d-h}))}const c=[];a.sort((t,e)=>Math.abs(t.y-e.y)>po?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)<po,n=Math.abs(h.height-t.height)<po,o=Math.abs(h.x+h.width-t.x)<po;e&&n&&o?h.width+=t.width:(c.push(h),h=t)}h&&c.push(h),c.sort((t,e)=>Math.abs(t.x-e.x)>po?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)<po,n=Math.abs(h.width-t.width)<po,o=Math.abs(h.y+h.height-t.y)<po;e&&n&&o?h.height+=t.height:(d.push(h),h=t)}return h&&d.push(h),d}function Io(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 Co(t){const e=function(t){return Array.from(new Set(t)).sort((t,e)=>{const n=Io(t),o=Io(e);return n!==o?n-o:t.localeCompare(e)})}((t.obstacles??[]).flatMap(t=>t.layers??[])),n=Math.max(1,t.layerCount||e.length||1),o=Array.from({length:n},(t,e)=>0===e?"top":e===n-1?"bottom":`inner${e}`),s=[],i=new Set,r=t=>{const e=t.toLowerCase();i.has(e)||(i.add(e),s.push(t))};o.forEach(r),e.forEach(r);const a=s.slice(0,n),c=new Map;return a.forEach((t,e)=>c.set(t.toLowerCase(),e)),s.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 _o(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 To(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 Eo=1e-9,Ro=t=>Math.abs(t.rect.x+t.rect.width/2-t.startX)<Eo&&Math.abs(t.rect.y+t.rect.height/2-t.startY)<Eo&&Math.abs(t.rect.width-t.initialW)<Eo&&Math.abs(t.rect.height-t.initialH)<Eo,wo=({rect:t,bounds:e})=>({x:t.x,y:t.y,width:e.x+e.width-t.x,height:t.height}),Ao=({rect:t,bounds:e})=>({x:t.x,y:t.y,width:t.width,height:e.y+e.height-t.y}),Oo=({rect:t,bounds:e})=>({x:e.x,y:t.y,width:t.x-e.x,height:t.height}),zo=({rect:t,bounds:e})=>({x:t.x,y:e.y,width:t.width,height:t.y-e.y});function Do(t){const{r:e,bounds:n,blockers:o,maxAspect:s}=t;let i=n.x+n.width-e.x;for(const t of o){if(e.y+e.height>t.y+po&&t.y+t.height>e.y+po)if(go(t.x,e.x+e.width))i=Math.min(i,t.x-e.x);else if(t.x+t.width>e.x+e.width-po&&t.x<e.x+e.width+po)return 0}let r=Math.max(0,i-e.width);if(r<=0)return 0;if(null!=s){const t=e.width,n=e.height;t>=n&&(r=Math.min(r,s*n-t))}return Math.max(0,r)}function Lo(t){const{r:e,bounds:n,blockers:o,maxAspect:s}=t;let i=n.y+n.height-e.y;for(const t of o){if(e.x+e.width>t.x+po&&t.x+t.width>e.x+po)if(go(t.y,e.y+e.height))i=Math.min(i,t.y-e.y);else if(t.y+t.height>e.y+e.height-po&&t.y<e.y+e.height+po)return 0}let r=Math.max(0,i-e.height);if(r<=0)return 0;if(null!=s){const t=e.width,n=e.height;n>=t&&(r=Math.min(r,s*t-n))}return Math.max(0,r)}function Fo(t){const{r:e,bounds:n,blockers:o,maxAspect:s}=t;let i=n.x;for(const t of o){if(e.y+e.height>t.y+po&&t.y+t.height>e.y+po)if(xo(t.x+t.width,e.x))i=Math.max(i,t.x+t.width);else if(t.x<e.x+po&&t.x+t.width>e.x-po)return 0}let r=Math.max(0,e.x-i);if(r<=0)return 0;if(null!=s){const t=e.width,n=e.height;t>=n&&(r=Math.min(r,s*n-t))}return Math.max(0,r)}function Xo(t){const{r:e,bounds:n,blockers:o,maxAspect:s}=t;let i=n.y;for(const t of o){if(e.x+e.width>t.x+po&&t.x+t.width>e.x+po)if(xo(t.y+t.height,e.y))i=Math.max(i,t.y+t.height);else if(t.y<e.y+po&&t.y+t.height>e.y-po)return 0}let r=Math.max(0,e.y-i);if(r<=0)return 0;if(null!=s){const t=e.width,n=e.height;n>=t&&(r=Math.min(r,s*t-n))}return Math.max(0,r)}var Yo=t=>({x:t.minX,y:t.minY,width:t.maxX-t.minX,height:t.maxY-t.minY}),$o=t=>{const{rect:e,seen:n,blockers:o}=t,s=`${e.x}|${e.y}|${e.width}|${e.height}`;n.has(s)||(n.add(s),o.push(e))};function Bo(t){const{startX:e,startY:n,gridSize:o,bounds:s,obsticalIndexByLayer:i,placedIndexByLayer:r,initialCellRatio:a,maxAspectRatio:c,minReq:h}=t,d=Math.max(1e-9,o*a),l=Math.max(d,h.width),u=Math.max(d,h.height),p=[],m=new Set,f=r.length,g=o=>{const a=(t=>{const{bounds:e,rect:n}=t,o=Math.max(e.x,n.x),s=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<=o+po||r<=s+po?null:{minX:o,minY:s,maxX:i,maxY:r}})({bounds:s,rect:o});if(a)for(const o of t.zLayers){const t=i[o];if(t)for(const e of t.search(a))$o({rect:Yo(e),seen:m,blockers:p});const s=r[o];if(s)for(const t of s.search(a)){if(!(t.zLayers.length>=f))continue;const o=Yo(t);Ro({rect:o,startX:e,startY:n,initialW:l,initialH:u})||$o({rect:o,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 o={x:e+t.ox,y:n+t.oy,width:l,height:u};if(g(o),yo(o.x,s.x)||yo(o.y,s.y)||fo(o.x+o.width,s.x+s.width)||fo(o.y+o.height,s.y+s.height))continue;for(const t of p)if(vo(o,t))continue t;const i=1e-6,r=1e3;let a=!0,d=0;for(;a&&d<r;){d++,a=!1;const t={bounds:s,blockers:p,maxAspect:c};g(wo({rect:o,bounds:s}));const e=Do({...t,r:o});e>i&&(o={...o,width:o.width+e},g(o),a=!0),g(Ao({rect:o,bounds:s}));const n=Lo({...t,r:o});n>i&&(o={...o,height:o.height+n},g(o),a=!0),g(Oo({rect:o,bounds:s}));const r=Fo({...t,r:o});r>i&&(o={x:o.x-r,y:o.y,width:o.width+r,height:o.height},g(o),a=!0),g(zo({rect:o,bounds:s}));const h=Xo({...t,r:o});h>i&&(o={x:o.x,y:o.y-h,width:o.width,height:o.height+h},g(o),a=!0)}if(o.width+po>=h.width&&o.height+po>=h.height){const t=o.width*o.height;t>v&&(x=o,v=t)}}return x}function ko(t){const e=Math.max(t.width,t.height);return[e/8,e/16,e/32]}function jo(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 o=t.obstacleIndexByLayer[n],s=!!o&&o.search(e).length>0,i=t.placedIndexByLayer[n],r=!!i&&i.search(e).length>0;if(!s&&!r)return!1}return!0}function Wo(t){const{x:e,y:n,z:o,layerCount:s,minSpan:i,maxSpan:r,obstacleIndexByLayer:a,additionalBlockersByLayer:c}=t,h=t=>{const o={minX:e,minY:n,maxX:e,maxY:n},s=a[t];if(s&&s.search(o).length>0)return!1;return!(c?.[t]??[]).some(t=>{return(s={x:e,y:n}).x>=(o=t).x-po&&s.x<=o.x+o.width+po&&s.y>=o.y-po&&s.y<=o.y+o.height+po;var o,s})};let d=o,l=o;for(;d-1>=0&&h(d-1);)d--;for(;l+1<s&&h(l+1);)l++;if("number"==typeof r){const t=mo(r,1,s);for(;l-d+1>t;)o-d>l-o?d++:l--}const u=[];for(let t=d;t<=l;t++)u.push(t);return u.length>=i?u:[]}function Ho(t){const{lineStart:e,lineEnd:n,coveringIntervals:o,minSegmentLength:s}=t;if(0===o.length){return[{start:e,end:n,center:(e+n)/2}]}const i=[...o].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+po?a.end=Math.max(a.end,e.end):(r.push(a),a={...e})}r.push(a);const c=[];if(r[0].start>e+po){const t=e,n=r[0].start;n-t>=s&&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>=s&&c.push({start:e,end:n,center:(e+n)/2})}if(r[r.length-1].end<n-po){const t=r[r.length-1].end,e=n;e-t>=s&&c.push({start:t,end:e,center:(t+e)/2})}return c}function Uo(t){const{bounds:e,minSize:n,layerCount:o,obstacleIndexByLayer:s,placedIndexByLayer:i,hardPlacedByLayer:r}=t,a=[],c=Math.max(.15*n,3*po),h=new Set;function d(t){const{x:n,y:c,z:d}=t;if(n<e.x+po||c<e.y+po||n>e.x+e.width-po||c>e.y+e.height-po)return;if(function(t){return jo({layerCount:o,obstacleIndexByLayer:s,placedIndexByLayer:i,point:t})}({x:n,y:c}))return;const l=[...s[d]?.all()??[],...r[d]??[]],u=Math.min(Po({x:n,y:c},e),...l.length?l.map(t=>Po({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=Wo({x:n,y:c,z:d,layerCount:o,minSpan:1,maxSpan:void 0,obstacleIndexByLayer:s,additionalBlockersByLayer:r});a.push({x:n,y:c,z:d,distance:u,zSpanLen:m.length,isEdgeSeed:!0})}for(let t=0;t<o;t++){const o=[...s[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=o.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=Ho({lineStart:e.x+c,lineEnd:e.x+e.width-c,coveringIntervals:h,minSegmentLength:.5*n});for(const e of l){const o=e.end-e.start;o>=n&&(d({x:e.center,y:a,z:t}),o>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=o.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=Ho({lineStart:e.x+c,lineEnd:e.x+e.width-c,coveringIntervals:p,minSegmentLength:.5*n});for(const e of m){const o=e.end-e.start;o>=n&&(d({x:e.center,y:u,z:t}),o>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=o.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=Ho({lineStart:e.y+c,lineEnd:e.y+e.height-c,coveringIntervals:g,minSegmentLength:.5*n});for(const e of y){const o=e.end-e.start;o>=n&&(d({x:f,y:e.center,z:t}),o>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=o.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)})),P=Ho({lineStart:e.y+c,lineEnd:e.y+e.height-c,coveringIntervals:v,minSegmentLength:.5*n});for(const e of P){const o=e.end-e.start;o>=n&&(d({x:x,y:e.center,z:t}),o>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 s of o){const i=s.x-c;if(i>e.x+po&&i<e.x+e.width-po){const e=o.filter(t=>t!==s&&t.x<=i&&t.x+t.width>=i).map(t=>({start:Math.max(s.y,t.y),end:Math.min(s.y+s.height,t.y+t.height)})),r=Ho({lineStart:s.y,lineEnd:s.y+s.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of r)d({x:i,y:e.center,z:t})}const r=s.x+s.width+c;if(r>e.x+po&&r<e.x+e.width-po){const e=o.filter(t=>t!==s&&t.x<=r&&t.x+t.width>=r).map(t=>({start:Math.max(s.y,t.y),end:Math.min(s.y+s.height,t.y+t.height)})),i=Ho({lineStart:s.y,lineEnd:s.y+s.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of i)d({x:r,y:e.center,z:t})}const a=s.y-c;if(a>e.y+po&&a<e.y+e.height-po){const e=o.filter(t=>t!==s&&t.y<=a&&t.y+t.height>=a).map(t=>({start:Math.max(s.x,t.x),end:Math.min(s.x+s.width,t.x+t.width)})),i=Ho({lineStart:s.x,lineEnd:s.x+s.width,coveringIntervals:e,minSegmentLength:.5*n});for(const e of i)d({x:e.center,y:a,z:t})}const h=s.y+s.height+c;if(h>e.y+po&&h<e.y+e.height-po){const e=o.filter(t=>t!==s&&t.y<=h&&t.y+t.height>=h).map(t=>({start:Math.max(s.x,t.x),end:Math.min(s.x+s.width,t.x+t.width)})),i=Ho({lineStart:s.x,lineEnd:s.x+s.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 Vo=(t,e)=>({...t,minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height,zLayers:e.zLayers});function Zo(t,e){const n=t.placed[e],{rect:o,zLayers:s}=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=>s.includes(t));if(0===h.length)continue;if(!vo(c.rect,o))continue;const d=Mo(c.rect,o);r.push(n);const l=c.zLayers.filter(t=>!s.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+po>=u&&t.height+po>=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 o=t.placedIndexByLayer[e];o&&o.remove(Vo(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 o=t.placedIndexByLayer[n];o&&o.insert(Vo(e.rect,{zLayers:e.zLayers.slice()}))}}}var Go=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]},Jo=class extends _n{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:o}=Co(t),s=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??ko(i)};this.srj=t,this.layerNames=n,this.layerCount=s,this.bounds=i,this.options=a,this.boardVoidRects=this.input.boardVoidRects,this.gridIndex=0,this.candidates=[],this.placed=[],this.placedIndexByLayer=Array.from({length:s},()=>new $n),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:o,minMulti:s,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:o,obstacleIndexByLayer:s,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)<po||Math.abs(c-e.y)<po||t>e.x+e.width-n-po||c>e.y+e.height-n-po)continue;if(jo({layerCount:o,obstacleIndexByLayer:s,placedIndexByLayer:i,point:{x:t,y:c}}))continue;let h=[],d=0;for(let e=0;e<o;e++){const n=Wo({x:t,y:c,z:e,layerCount:o,minSpan:1,maxSpan:void 0,obstacleIndexByLayer:s,additionalBlockersByLayer:r});n.length>h.length&&(h=n,d=e)}const l=h.length?h[Math.floor(h.length/2)]:d,u=[...s[l]?.all()??[],...r[l]??[]],p=Math.min(Po({x:t,y:c},e),...u.length?u.map(e=>Po({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(o.width,o.height);return this.candidates=Uo({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=Wo({x:h.x,y:h.y,z:h.z,layerCount:this.layerCount,minSpan:s.minLayers,maxSpan:r,obstacleIndexByLayer:this.input.obstacleIndexByLayer,additionalBlockersByLayer:c}),l=[];d.length>=s.minLayers&&l.push({kind:"multi",layers:d,minReq:{width:s.width,height:s.height}}),l.push({kind:"single",layers:[h.z],minReq:{width:o.width,height:o.height}});const u=i?l:l.reverse();for(const t of u){const o=Bo({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(!o)continue;const s={rect:o,zLayers:[...t.layers]},i=this.placed.push(s)-1;for(const e of t.layers){const t=this.placedIndexByLayer[e];t&&t.insert(Vo(o,{zLayers:s.zLayers}))}return Zo({layerCount:this.layerCount,placed:this.placed,options:this.options,placedIndexByLayer:this.placedIndexByLayer},i),void(this.candidates=this.candidates.filter(t=>!jo({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),o=n?this.consumedSeedsThisGrid/n:1;return Math.min(.999,e+o*(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=[],o=this.srj??this.input.simpleRouteJson,s=o.bounds.minX,i=o.bounds.maxX,r=o.bounds.minY,a=o.bounds.maxY;o.outline&&o.outline.length>1?n.push({points:[...o.outline,o.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):t.push({center:{x:(s+i)/2,y:(r+a)/2},width:i-s,height:a-r,fill:"none",stroke:"#111827",label:"board"});for(const e of o.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(o.outline&&o.outline.length>0){const t=o.outline.map(t=>t.x),n=o.outline.map(t=>t.y),s=Math.min(...t),i=Math.min(...n);e={x:s,y:i,width:Math.max(...t)-s,height:Math.max(...n)-i}}for(const n of this.boardVoidRects)e&&!vo(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=Go(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 qo=(t,e)=>t.minX===e.minX&&t.minY===e.minY&&t.maxX===e.maxX&&t.maxY===e.maxY,Ko=class extends _n{constructor(t){super(),this.input=t}placedIndexByLayer=[];_meshNodes=[];_setup(){this.stats={gridIndex:this.input.gridIndex},this.placedIndexByLayer=Array.from({length:this.input.layerCount},()=>new $n);for(const t of this.input.placed)for(const e of t.zLayers){const n=this.placedIndexByLayer[e];n&&n.insert(Vo(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],o=e.rect,s=Bo({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(s){this.input.placed[t]={rect:s,zLayers:e.zLayers};for(const t of e.zLayers){const n=this.placedIndexByLayer[t];n&&(n.remove(Vo(o,{zLayers:e.zLayers}),qo),n.insert(Vo(s,{zLayers:e.zLayers})))}Zo({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}=Co(t.srj),o=new Map;for(const e of t.srj.obstacles??[]){const t=To(e);if(!t)continue;const s=e.zLayers?.length&&e.zLayers.length>0?e.zLayers:_o(e,n),i=`${t.x}:${t.y}:${t.width}:${t.height}`;let r=o.get(i);r||(r={rect:t,layers:new Set},o.set(i,r)),s.forEach(t=>r.layers.add(t))}for(const{rect:t,layers:n}of o.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 o of t){const t=Math.max(0,o.maxX-o.minX),s=Math.max(0,o.maxY-o.minY);t<=0||s<=0||0===o.zLayers.length||n.push({capacityMeshNodeId:"cmn_"+e++,center:{x:(o.minX+o.maxX)/2,y:(o.minY+o.maxY)/2},width:t,height:s,layer:"top",availableZ:o.zLayers.slice(),_containsObstacle:o.isObstacle,_containsTarget:o.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),o=n?this.input.expansionIndex/n:1;return Math.min(.999,e+o*(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:[]}}},Qo=class extends En{rectDiffSeedingSolver;rectDiffExpansionSolver;obstacleIndexByLayer;constructor(t){super(t);const{obstacleIndexByLayer:e}=(t=>{const{srj:e,boardVoidRects:n}=t,{layerNames:o,zIndexByName:s}=Co(e),i=Math.max(1,o.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 $n)),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=To(t);if(!e)continue;const n=_o(t,s),o=n.filter(t=>t<0||t>=i);if(o.length)throw new Error(`RectDiff: obstacle uses z-layer indices ${o.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=[Tn("rectDiffSeedingSolver",Jo,t=>[{simpleRouteJson:t.inputProblem.simpleRouteJson,gridOptions:t.inputProblem.gridOptions,obstacleIndexByLayer:t.obstacleIndexByLayer,boardVoidRects:t.inputProblem.boardVoidRects}]),Tn("rectDiffExpansionSolver",Ko,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 ts(t,e="RectDiff"){const n=[],o=[],s=t.bounds.minX,i=t.bounds.maxX,r=t.bounds.minY,a=t.bounds.maxY;t.outline&&t.outline.length>1?o.push({points:[...t.outline,t.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):n.push({center:{x:(s+i)/2,y:(r+a)/2},width:i-s,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:o}}var es=class extends En{rectDiffGridSolverPipeline;gapFillSolver;boardVoidRects;pipelineDef=[Tn("rectDiffGridSolverPipeline",Qo,t=>[{simpleRouteJson:t.inputProblem.simpleRouteJson,gridOptions:t.inputProblem.gridOptions,boardVoidRects:t.boardVoidRects}]),Tn("gapFillSolver",uo,t=>[{meshNodes:t.rectDiffGridSolverPipeline?.getOutput().meshNodes??[],boardVoid:{boardVoidRects:t.boardVoidRects||[],layerCount:t.inputProblem.simpleRouteJson.layerCount||0}}])];_setup(){this.inputProblem.simpleRouteJson.outline&&(this.boardVoidRects=No({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=ts(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=ts(this.inputProblem.simpleRouteJson,"RectDiffPipeline - Final"),{meshNodes:e}=this.getOutput(),n=new Set((this.rectDiffGridSolverPipeline?.getOutput().meshNodes??[]).map(t=>t.capacityMeshNodeId));for(const o of e){const e=!n.has(o.capacityMeshNodeId);t.rects.push({center:o.center,width:o.width,height:o.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${o.availableZ.join(",")}`,label:[`${e?"[expanded] ":""}node ${o.capacityMeshNodeId}`,`z:${o.availableZ.join(",")}`].join("\n")})}return t}},ns=class{tree;constructor(t=9){this.tree=new $n(t)}insert(t,e,n,o,s){this.tree.insert({minX:e,minY:n,maxX:o,maxY:s,data:t})}bulkLoad(t){const e=t.map(({item:t,minX:e,minY:n,maxX:o,maxY:s})=>({minX:e,minY:n,maxX:o,maxY:s,data:t}));this.tree.load(e)}search(t,e,n,o){return this.tree.search({minX:t,minY:e,maxX:n,maxY:o}).map(t=>t.data)}clear(){this.tree.clear()}},os=class{index;items=[];currentIndex=0;capacity;constructor(t){this.capacity=Math.max(1,t),this.index=new An(this.capacity)}insert(t,e,n,o,s){if(this.currentIndex>=this.index.numItems)throw new Error("Exceeded initial capacity");this.items[this.currentIndex]=t,this.index.add(e,n,o,s),this.currentIndex++}finish(){this.index.finish()}search(t,e,n,o){return this.index.search(t,e,n,o).map(t=>this.items[t]||null).filter(Boolean)}clear(){this.items=[],this.currentIndex=0,this.index=new An(this.capacity)}},ss=class{idx;storage=[];constructor(t="native",e=[]){"flatbush"===t?0===e.length?(this.idx=new ns,t="rbush"):this.idx=new os(e.length):this.idx="rbush"===t?new ns:new class{shi=new is(e);insert(t){}search(t,e,n,o){const s=(t+n)/2,i=(e+o)/2,r=n-t,a=o-e;return this.shi.getNodesInArea(s,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,o){return this.search({minX:t-n/2,minY:e-o/2,maxX:t+n/2,maxY:e+o/2})}},is=class{constructor(t){this.obstacles=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],o=n.center.x-n.width/2,s=n.center.y-n.height/2,i=n.center.x+n.width/2,r=n.center.y+n.height/2;for(let t=o;t<=i;t+=this.CELL_SIZE)for(let o=s;o<=r;o+=this.CELL_SIZE){const s=this.getBucketKey(t,o),i=this.buckets.get(s);i?i.push([n,e]):this.buckets.set(s,[[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,o){const s=[],i=new Set,r=e-o/2,a=t+n/2,c=e+o/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),o=this.buckets.get(n)||[];for(const t of o)i.has(t[1])||(i.add(t[1]),s.push(t[0]))}return s}},rs=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 as(t,e){const n=t.x-e.x,o=t.y-e.y;return n*n+o*o}function cs(t,e,n){const o=as(e,n);if(0===o)return as(t,e);let s=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/o;s=Math.max(0,Math.min(1,s));return as(t,{x:e.x+s*(n.x-e.x),y:e.y+s*(n.y-e.y)})}function hs(t,e,n,o){if(gt(t,e,n,o))return 0;const s={x:t.x,y:t.y},i={x:e.x,y:e.y},r={x:n.x,y:n.y},a={x:o.x,y:o.y};return Math.min(cs(s,r,a),cs(i,r,a),cs(r,s,i),cs(a,s,i))}var ds=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],o=e.route[t+1];if(n.x===o.x&&n.y===o.y)continue;if(n.insideJumperPad&&o.insideJumperPad)continue;const s=[n,o],i=rs(s),r={segmentId:`${e.connectionName}-seg-${t}`,segment:s,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 o=this.segmentBuckets.get(n);o||(o=[],this.segmentBuckets.set(n,o)),o.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 o={viaId:`${e.connectionName}-via-${t}`,x:n.x,y:n.y,parentRoute:e},s=`${Math.floor(n.x/this.CELL_SIZE)}x${Math.floor(n.y/this.CELL_SIZE)}`;let i=this.viaBuckets.get(s);i||(i=[],this.viaBuckets.set(s,i)),i.push(o)}}else console.warn("Skipping route with missing data:",e)}getConflictingRoutesForSegment(t,e,n){const o=rs([t,e]),s=o.minX-n,i=o.minY-n,r=o.maxX+n,a=o.maxY+n,c=Math.floor(s/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 o=c;o<=h;o++)for(let s=d;s<=l;s++){const i=`${o}x${s}`,r=this.segmentBuckets.get(i);if(r)for(const o of r){if(p.has(o.segmentId))continue;p.add(o.segmentId);const s=o.parentRoute,[i,r]=o.segment,a=n+s.traceThickness/2,c=a*a,h=hs(t,e,i,r);if(h<c){const t=s.connectionName,e=u.get(t);(!e||h<e.minDistSq)&&u.set(t,{route:s,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,o={x:t.x,y:t.y},s=n+e.viaDiameter/2,i=s*s,r=cs(o,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 o=n.filter(e=>e.parentRoute.connectionName!==t);0===o.length?this.segmentBuckets.delete(e):o.length!==n.length&&this.segmentBuckets.set(e,o)}for(const[e,n]of this.viaBuckets){const o=n.filter(e=>e.parentRoute.connectionName!==t);0===o.length?this.viaBuckets.delete(e):o.length!==n.length&&this.viaBuckets.set(e,o)}}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],o=t.route[e+1];if(n.x===o.x&&n.y===o.y)continue;if(n.insideJumperPad&&o.insideJumperPad)continue;const s=[n,o],i=rs(s),r={segmentId:`${t.connectionName}-seg-${e}`,segment:s,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 o=this.segmentBuckets.get(n);o||(o=[],this.segmentBuckets.set(n,o)),o.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 o={viaId:`${t.connectionName}-via-${e}`,x:n.x,y:n.y,parentRoute:t},s=`${Math.floor(n.x/this.CELL_SIZE)}x${Math.floor(n.y/this.CELL_SIZE)}`;let i=this.viaBuckets.get(s);i||(i=[],this.viaBuckets.set(s,i)),i.push(o)}}getConflictingRoutesNearPoint(t,e){const n=t.x-e,o=t.y-e,s=t.x+e,i=t.y+e,r=Math.floor(n/this.CELL_SIZE),a=Math.floor((s+1e-9)/this.CELL_SIZE),c=Math.floor(o/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 o=c;o<=h;o++){const s=`${n}x${o}`,i=this.segmentBuckets.get(s);if(i)for(const n of i){if(l.has(n.segmentId))continue;l.add(n.segmentId);const o=n.segment[0],s=n.segment[1];if(o.z!==s.z||o.z!==t.z)continue;const i=n.parentRoute,r={x:n.segment[0].x,y:n.segment[0].y},a={x:n.segment[1].x,y:n.segment[1].y},c=e+i.traceThickness/2,h=c*c,u=cs(t,r,a);if(u<h){const t=i.connectionName,e=d.get(t);(!e||u<e.minDistSq)&&d.set(t,{route:i,minDistSq:u})}}const r=this.viaBuckets.get(s);if(r)for(const n of r){if(u.has(n.viaId))continue;u.add(n.viaId);const o=n.parentRoute,s={x:n.x,y:n.y},i=e+o.viaDiameter/2,r=i*i,a=as(t,s);if(a<r){const t=o.connectionName,e=d.get(t);(!e||a<e.minDistSq)&&d.set(t,{route:o,minDistSq:a})}}}const p=[];for(const t of d.values())p.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return p}},ls=class extends y{getSolverName(){return"SingleRouteUselessViaRemovalSolver"}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 o={startIndex:0,endIndex:-1,z:n[0].z,points:[n[0]]};for(let t=1;t<n.length;t++)n[t].z===o.z?o.points.push(n[t]):(o.endIndex=t-1,e.push(o),o={startIndex:t,endIndex:-1,z:n[t].z,points:[n[t]]});return o.endIndex=n.length-1,e.push(o),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,o=t.points[0];if(this.canEndpointConnectOnLayer(o.x,o.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,o=t.points[t.points.length-1];this.canEndpointConnectOnLayer(o.x,o.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 o=t.z;if(this.canSectionMoveToLayer({currentSection:e,targetZ:o}))return e.z=o,e.points=e.points.map(t=>({...t,z:o})),void(this.currentSectionIndex+=2);this.currentSectionIndex++}canEndpointConnectOnLayer(t,e,n){const o=this.obstacleSHI.searchArea(t,e,2,2).filter(n=>{if(!n.connectedTo?.includes(this.unsimplifiedRoute.connectionName))return!1;const o=n.width/2+.05,s=n.height/2+.05,i=Math.abs(t-n.center.x)<=o,r=Math.abs(e-n.center.y)<=s;return i&&r});return!(o.length>0)||o.some(t=>t.zLayers?.includes(n))}canSectionMoveToLayer({currentSection:t,targetZ:e}){for(let n=0;n<t.points.length-1;n++){const o={...t.points[n],z:e},s={...t.points[n+1],z:e},i=this.hdRouteSHI.getConflictingRoutesForSegment(o,s,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:(o.x+s.x)/2,centerY:(o.y+s.y)/2,width:Math.abs(o.x-s.x),height:Math.abs(o.y-s.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(o.x-t.center.x)<.01&&Math.abs(o.y-t.center.y)<.01||Math.abs(s.x-t.center.x)<.01&&Math.abs(s.y-t.center.y)<.01)continue}if(At(o,s,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}},us=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 ss("flatbush",t.obstacles),this.hdRouteSHI=new ds(this.unsimplifiedHdRoutes)}getSolverName(){return"UselessViaRemovalSolver"}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 ls({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 o=e.zLayers?.includes(0),s=e.zLayers?.includes(1);o&&s?n="rgba(128, 0, 128, 0.2)":o?n="rgba(255, 0, 0, 0.2)":s&&(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 o=e.route[n],s=e.route[n+1];o.z===s.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:s.x,y:s.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 o=Qe(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...o.rects??[]),t.lines.push(...o.lines??[])}}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},ps=class extends y{getSolverName(){return"SingleSimplifiedPathSolver"}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,o]of e)t.lines.push({points:[n,o]})}return t}};function ms(t,e,n,o){if(gt(t,e,n,o))return 0;const s=fs(t,n,o),i=fs(e,n,o),r=fs(n,t,e),a=fs(o,t,e);return Math.min(s,i,r,a)}function fs(t,e,n){const o={x:n.x-e.x,y:n.y-e.y},s=gs({x:t.x-e.x,y:t.y-e.y},o);if(s<=0)return ys(t,e);const i=gs(o,o);if(i<=s)return ys(t,n);const r=s/i;return ys(t,{x:e.x+r*o.x,y:e.y+r*o.y})}function gs(t,e){return t.x*e.x+t.y*e.y}function ys(t,e){const n=e.x-t.x,o=e.y-t.y;return Math.sqrt(n*n+o*o)}var xs=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)}),vs=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 o=xs(n),s=Math.floor(o.minX/this.CELL_SIZE),i=Math.floor(o.maxX/this.CELL_SIZE),r=Math.floor(o.minY/this.CELL_SIZE),a=Math.floor(o.maxY/this.CELL_SIZE);for(let e=s;e<=i;e++)for(let o=r;o<=a;o++){const s=`${e}x${o}`,i=this.buckets.get(s),r=[n[0],n[1],t];i?i.push(r):this.buckets.set(s,[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=[],o=new Set,s=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(s/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 s=`${t}x${e}`,i=this.buckets.get(s);if(i)for(const t of i){const e=t[2];o.has(e)||(o.add(e),n.push(t))}}return n}},Ps=1e-6,Ss=(t,e,n)=>vt(t,e,n)<=Ps,Ms=(t,e)=>Math.abs(t.x-e.x)<=Ps&&Math.abs(t.y-e.y)<=Ps,bs=(t,e)=>{if(!e||e.length<3)return!1;for(let n=0;n<e.length;n++){const o=e[n],s=e[(n+1)%e.length];if(Ss(t,o,s))return!0}let n=!1;for(let o=0,s=e.length-1;o<e.length;s=o++){const i=e[o],r=e[s];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},Ns=class extends ps{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),o=mt(e),s=Math.max(n.minX-o.maxX,o.minX-n.maxX,0),i=Math.max(n.minY-o.maxY,o.minY-n.maxY,0);return Math.hypot(s,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,o=[];for(let t=0;t<n.length-1;t++){const s=n[t],i=n[t+1],r=Math.min(s.x,i.x),a=Math.max(s.x,i.x),c=Math.min(s.y,i.y),h=Math.max(s.y,i.y);r<=e.maxX&&a>=e.minX&&c<=e.maxY&&h>=e.minY&&o.push([s,i])}return o}),this.segmentTree=new vs(this.filteredObstaclePathSegments),this.filteredVias=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const n=t.vias,o=[];for(const s of n){const n=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2+t.viaDiameter/2,i=s.x-n,r=s.x+n,a=s.y-n,c=s.y+n;i<=e.maxX&&r>=e.minX&&a<=e.maxY&&c>=e.minY&&o.push({...s,diameter:t.viaDiameter})}return o});const o=(t,n)=>{const o=[];for(const s of t){const t=qe[s.footprint]??qe["0603"],i=s.end.x-s.start.x,r=s.end.y-s.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;s.start.x-c/2-d<=e.maxX&&s.start.x+c/2+d>=e.minX&&s.start.y-h/2-d<=e.maxY&&s.start.y+h/2+d>=e.minY&&o.push({center:s.start,width:c,height:h,connectionName:n}),s.end.x-c/2-d<=e.maxX&&s.end.x+c/2+d>=e.minX&&s.end.y-h/2-d<=e.maxY&&s.end.y+h/2+d>=e.minY&&o.push({center:s.end,width:c,height:h,connectionName:n})}return o};if(this.filteredJumperPads=this.otherHdRoutes.flatMap(t=>this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName)?[]:o(t.jumpers??[],t.connectionName)),this.inputRoute.jumpers&&this.inputRoute.jumpers.length>0){this.filteredJumperPads.push(...o(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],o=this.inputRoute.route[e+1],s=Math.sqrt((o.x-n.x)**2+(o.y-n.y)**2)+e/1e4;this.pathSegments.push({start:n,end:o,length:s,startDistance:t,endDistance:t+s}),t+=s}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],o=(n.startDistance+n.endDistance)/2;return t>o?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[o,s,i]of n)if(o.z===t.z&&s.z===t.z){if(ms({x:t.x,y:t.y},{x:e.x,y:e.y},{x:o.x,y:o.y},{x:s.x,y:s.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:o=.2})=>{if(!n||n.length<3)return!1;const s=bs(t,n),i=bs(e,n);if(!s||!i)return!0;for(let s=0;s<n.length;s++){const i=n[s],r=n[(s+1)%n.length],a=Ss(t,i,r),c=Ss(e,i,r);if(a&&c)continue;if(!gt(t,e,i,r)){if(!a&&!c&&ms(t,e,i,r)<o-Ps)return!0;continue}const h=St(t,e,i,r);if(!(h&&(a&&Ms(h,t)||c&&Ms(h,e))||h&&(Ms(h,t)||Ms(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=[],o=Math.abs(e.x-t.x),s=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(o,s),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 o=[];for(const t of this.inputRoute.route)0!==o.length&&this.arePointsEqual(o[o.length-1],t)||o.push(t);return this.newRoute=o,this.newVias=[...this.inputRoute.vias],void(this.solved=!0)}this.moveHead(this.currentStepSize);const n=this.getPointAtDistance(this.tailDistanceAlongPath),o=this.getPointAtDistance(this.headDistanceAlongPath),s=this.getNearestIndexForDistance(this.tailDistanceAlongPath),i=this.getNearestIndexForDistance(this.headDistanceAlongPath);let r=!1,a=-1;for(let t=s;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=s+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 o=this.newRoute[this.newRoute.length-1];o.x===n.x&&o.y===n.y||this.newRoute.push({x:n.x,y:n.y,z:o.z}),this.newVias.push(n),this.newRoute.push({x:n.x,y:n.y,z:e.z}),this.currentStepSize=this.maxStepSize;const s=this.pathSegments.findIndex(t=>t.start===e);if(-1!==s)this.tailDistanceAlongPath=this.pathSegments[s].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,o);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],o=this.inputRoute.route[this.inputRoute.route.length-1];return void(this.arePointsEqual(t,n)||this.arePointsEqual(n,o)||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 o=this.getPointAtDistance(this.headDistanceAlongPath+this.currentStepSize);t.points.push({x:o.x,y:o.y,color:"red",label:["Tentative Head",`z: ${o.z}`].join("\n")});let s=0;for(;s<this.totalPathLength;){const e=this.getPointAtDistance(s);t.circles.push({center:{x:e.x,y:e.y},radius:.05,fill:"rgba(100, 100, 100, 0.5)"}),s+=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}},Is=class extends y{getSolverName(){return"MultiSimplifiedPathSolver"}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 $e({}),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 Ns({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 o=0;o<e.route.length-1;o++)t.lines.push({points:[{x:e.route[o].x,y:e.route[o].y},{x:e.route[o+1].x,y:e.route[o+1].y}],strokeWidth:.15,strokeColor:n,strokeDash:1===e.route[o].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}},Cs=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 ss("flatbush",t.obstacles),this.hdRouteSHI=new ds(this.inputHdRoutes),this.vias=[],this.offendingVias=[],this.connMap=t.connMap,this.viasByNet=new Map,this.rebuildVias()}getSolverName(){return"SameNetViaMergerSolver"}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 o=e.vias[n],s={x:o.x,y:o.y,diameter:e.viaDiameter,net:this.connMap?.idToNetMap[e.connectionName]??"",layers:[...new Set(e.route.map(t=>t.z))],routeIndex:t};this.vias.push(s);const i=this.viasByNet.get(s.net);i?i.push(s):this.viasByNet.set(s.net,[s])}}}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 o=n.indexOf(e);for(let t=o>=0?o+1:0;t<n.length;t++){const o=n[t],s=e.x-o.x,i=e.y-o.y,r=s*s+i*i,a=e.diameter/2+o.diameter/2;if(r<=a*a&&0!==r)return[e,o]}}return null}handleOffendingPair(t,e){const n=t.layers.length<e.layers.length?t:e,o=n===t?e:t,s=this.mergedViaHdRoutes[n.routeIndex].route;for(let t=0;t<n.layers.length;t++)for(let t=s.length-1;t>=1;t--){const e=s[t-1],i=s[t];if(i.x===n.x&&i.y===n.y){s.splice(t,0,{x:o.x,y:o.y,z:i.z}),s.splice(t,0,{x:o.x,y:o.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:o.x,y:o.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 o=e.zLayers?.includes(0),s=e.zLayers?.includes(1);o&&s?n="rgba(128, 0, 128, 0.2)":o?n="rgba(255, 0, 0, 0.2)":s&&(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 o=e.route[n],s=e.route[n+1];o.z===s.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:s.x,y:s.y}],strokeColor:0===o.z?"rgba(255, 0, 0, 0.5)":"rgba(0, 0, 255, 0.5)",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 o=Qe(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...o.rects??[]),t.lines.push(...o.lines??[])}}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},_s=class extends y{constructor(t){super(),this.simplificationConfig=t,this.hdRoutes=[...t.hdRoutes],this.MAX_ITERATIONS=1e8}getSolverName(){return"TraceSimplificationSolver"}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 us({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 Cs({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 Is({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 o=e.zLayers?.includes(0),s=e.zLayers?.includes(1);o&&s?n="rgba(128, 0, 128, 0.2)":o?n="rgba(255, 0, 0, 0.2)":s&&(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 o=e.route[n],s=e.route[n+1];o.z===s.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:s.x,y:s.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 n=Qe(e.jumpers,{color:"orange",label:e.connectionName});t.rects.push(...n.rects??[]),t.lines.push(...n.lines??[])}}return t}};function Ts(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 Es=class extends y{getSolverName(){return"AvailableSegmentPointSolver"}nodes;edges;traceWidth;obstacleMargin;minPortSpacing;nodeMap;nodeEdgeMap;sharedEdgeSegments=[];edgeSegmentMap=new Map;portPointMap=new Map;colorMap;constructor({nodes:t,edges:e,traceWidth:n,obstacleMargin:o,colorMap:s}){super(),this.nodes=t,this.edges=e,this.traceWidth=n,this.obstacleMargin=o??.15,this.minPortSpacing=this.traceWidth+this.obstacleMargin,this.colorMap=s??{},this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ts(e),this.MAX_ITERATIONS=1}_step(){this.computeAllSharedEdgeSegments(),this.solved=!0}computeAllSharedEdgeSegments(){for(const t of this.edges){const[e,n]=t.nodeIds,o=this.nodeMap.get(e),s=this.nodeMap.get(n);if(!o||!s)continue;const i=this.computeSharedEdgeSegment(t,o,s);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 o=this.findOverlappingSegment(e,n);if(!o)return null;const s=e.availableZ.filter(t=>n.availableZ.includes(t));if(0===s.length)return null;const i=Math.sqrt((o.end.x-o.start.x)**2+(o.end.y-o.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=o.end.x-o.start.x,l=o.end.y-o.start.y,u=(o.start.x+o.end.x)/2,p=(o.start.y+o.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=o.start.x+d*e,s=o.start.y+l*e,h=Math.sqrt((n-u)**2+(s-p)**2);m.push({x:n,y:s,distToCenter:h})}const f=m.reduce((t,e)=>e.distToCenter<t.distToCenter?e:t);for(let o=0;o<c;o++){const{x:i,y:r}=m[o],a=Math.sqrt((i-f.x)**2+(r-f.y)**2);for(const c of s){const s={segmentPortPointId:`${t.capacityMeshEdgeId}_pp${o}_z${c}`,x:i,y:r,availableZ:[c],nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],edgeId:t.capacityMeshEdgeId,connectionName:null,distToCentermostPortOnZ:a};h.push(s)}}return{edgeId:t.capacityMeshEdgeId,nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],start:o.start,end:o.end,availableZ:s,portPoints:h}}shouldSkipOffBoardPortPoint(t,e){const n=this.nodeEdgeMap.get(e.capacityMeshNodeId)??[];for(const o of n){const n=o.nodeIds[0]===e.capacityMeshNodeId?o.nodeIds[1]:o.nodeIds[0];if(n===t.capacityMeshNodeId)continue;const s=this.nodeMap.get(n);if(s?._offBoardConnectionId!==t._offBoardConnectionId)continue;if(2!==this.nodes.filter(e=>e._offBoardConnectionId===t._offBoardConnectionId).length)continue;const i={x:(t.center.x+s.center.x)/2,y:(t.center.y+s.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)},o={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)},s=n.end-n.start,i=o.end-o.start;if(s<-1e-4||i<-1e-4)return null;if(s<i){const t=(n.start+n.end)/2;return{start:{x:t,y:o.start},end:{x:t,y:o.end}}}{const t=(o.start+o.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 o=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return o?o.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 o=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return o?.portPoints??[]}assignPortPoint(t,e,n){const o=this.portPointMap.get(t);return!!o&&(null===o.connectionName&&(o.connectionName=e,o.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}},Rs=(t,e,n,o)=>{if(t?._containsTarget)return 0;if(1===(t.availableZ?.length??2)&&(e>0||n>0||o>0))return 1;return((.82*e+.41*n+.2*o)/2)**1.1/We(t)};function ws(t,e,n,o,s){const i=n-e,r=s-o,a=1e-6;if(Math.abs(t.y-s)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(s-t.y);if(Math.abs(t.y-o)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-o);const c=Math.abs(t.y-s),h=Math.abs(t.x-n),d=Math.abs(t.y-o),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,s-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-o))}function As(t,e,n=1e-6){return Math.abs(t-e)<n}function Os(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[o,s]=e[t];for(let i=t+1;i<e.length;i++){const[t,r]=e[i];As(o,t)||As(o,r)||As(s,t)||As(s,r)||(o<t&&t<s&&s<r||t<o&&o<r&&r<s)&&n++}}return n}var zs=t=>{const e=t.center.x-t.width/2,n=t.center.x+t.width/2,o=t.center.y-t.height/2,s=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=ws(t,e,n,o,s),l=ws(i,e,n,o,s);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+=Os(e);return{numSameLayerCrossings:h,numEntryExitLayerChanges:c,numTransitionPairCrossings:Os(a)}},Ds=1.6*3.2,Ls=(t,e)=>{const n=Math.ceil(e/2),o=Math.min(t.width,t.height),s=Math.max(t.width,t.height),i=(Math.floor(o/1.6)+.1)*(Math.floor(s/3.2)+.1)/Ds;return Math.min(1,n/i)};function Fs(t,e,n,o){const s=e.x-n/2,i=e.x+n/2,r=e.y-o/2,a=e.y+o/2,c=Math.abs(t.y-a),h=Math.abs(t.x-i),d=Math.abs(t.y-r),l=Math.abs(t.x-s),u=Math.min(c,h,d,l);return u>.001?"interior":u===c?"top":u===h?"right":u===d?"bottom":"left"}function Xs(t,e,n,o,s){const i=Fs(t,n,o,s),r=Fs(e,n,o,s);return"interior"!==i&&i===r}function Ys(t,e,n,o,s){const i=Fs(t,n,o,s);let r;if("top"===i||"bottom"===i){const n=o;r=Math.abs(e.x-t.x)/n}else{const n=s;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 $s(t){return"computeNodePf"in t&&"function"==typeof t.computeNodePf}function Bs(t){const e={lines:[],points:[],rects:[],circles:[]};for(const n of t.inputNodes){let o=0,s=0,i={numSameLayerCrossings:0,numEntryExitLayerChanges:0,numTransitionPairCrossings:0},r=0;if($s(t)){o=t.computeNodePf(n),s=t.nodeMemoryPfMap.get(n.capacityMeshNodeId)??0;const e=t.buildNodeWithPortPointsForCrossing(n);i=zs(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{o=t.nodePfMap.get(n.capacityMeshNodeId)??0;const e=t.nodeAssignedPortPoints.get(n.capacityMeshNodeId)??[],s={capacityMeshNodeId:n.capacityMeshNodeId,center:n.center,width:n.width,height:n.height,portPoints:e,availableZ:n.availableZ};i=zs(s);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*o)),c=Math.max(0,255-Math.floor(512*o));let h=`rgba(${a}, ${c}, ${c}, ${o<.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: ${o.toFixed(3)}, memPf: ${s.toFixed(3)}\nC#: ${r}\nxSame: ${i.numSameLayerCrossings}, xLC: ${i.numEntryExitLayerChanges}, xTransition: ${i.numTransitionPairCrossings}\nobCmid: ${n._offBoardConnectedCapacityMeshNodeIds?.join(",")}\nobs: ${n._containsObstacle?"yes":"no"}`})}if($s(t))for(const[n,o]of t.portPointMap){const s=t.assignedPortPoints.get(n),i=s?t.colorMap[s.connectionName]??"blue":"rgba(150, 150, 150, 0.5)";e.circles.push({center:{x:o.x,y:o.y},radius:.05,fill:i,layer:`z${o.z}`,label:[n,`conn: ${s?.connectionName}`,`cd: ${o.distToCentermostPortOnZ}`,`connects: ${o.connectionNodeIds.join(",")}`,`rootConn: ${s?.rootConnectionName}`].filter(Boolean).join("\n")})}const n=$s(t)?t.connectionsWithResults:t.connectionResults;for(const o of n){if(!o.path)continue;const n=o.connection,s=t.colorMap[n.name]??"blue",i=[];for(const t of o.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 o=i[n],r=i[n+1],a=o.z===r.z,c=o.z;let h;h=a?0===c?void 0:"10 5":"3 3 10";const d=o.nodeId?t.nodeMap.get(o.nodeId):null;if(d&&Xs(o,r,d.center,d.width,d.height)){const t=Ys(o,r,d.center,d.width,d.height);e.lines.push({points:[{x:o.x,y:o.y},{x:t.x,y:t.y}],strokeColor:s,strokeDash:h}),e.lines.push({points:[{x:t.x,y:t.y},{x:r.x,y:r.y}],strokeColor:s,strokeDash:h})}else e.lines.push({points:[{x:o.x,y:o.y},{x:r.x,y:r.y}],strokeColor:s,strokeDash:h})}}if($s(t)&&!t.solved&&t.candidates&&t.candidates.length>0){const n=t.currentConnection,o=n?t.colorMap[n.connection.name]??"blue":"blue";if(n){const[s,i]=n.nodeIds,r=t.nodeMap.get(s),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,s=h?{x:h.x,y:h.y}:a.center;e.lines.push({points:[t,s],strokeColor:it(o,.5),strokeDash:"5 5"}),e.points.push({x:t.x,y:t.y,color:o,label:[`Start: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.points.push({x:s.x,y:s.y,color:o,label:[`End: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.circles.push({center:s,radius:.08,stroke:o,label:`Goal: ${n.connection.name}`})}}const s=[...t.candidates].sort((t,e)=>t.f-e.f).slice(0,1);for(const i of s){const s=[];let r=i;for(;r;)s.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<s.length-1;n++){const i=s[n],r=s[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&&Xs(i,r,d.center,d.width,d.height)){const t=Ys(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(o,.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(o,.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(o,.25),strokeDash:h})}if(s.length>=1){const r=s[s.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,o={x:i.prevCandidate.point.x,y:i.prevCandidate.point.y,z:i.prevCandidate.z,connectionName:e},s={x:i.portPoint.x,y:i.portPoint.y,z:i.portPoint.z,connectionName:e},r=t.buildNodeWithPortPointsForCrossing(p,[o,s]),m=pe(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?Ls(f,h):Rs(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,P=t.nodeMemoryPfMap.get(i.currentNodeId)??0,S=-Math.log(1-P)*t.MEMORY_PF_FACTOR;e.circles.push({center:r,radius:.03,fill:it(o,.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: ${S.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 ks(t,e){const n=[],o=e.filter(t=>t._containsTarget),s=new Map;for(const i of t.connections){const t=[];for(const n of i.pointsToConnect){let s=e[0],i=Number.MAX_VALUE;for(const t of o){const e=Math.sqrt((t.center.x-n.x)**2+(t.center.y-n.y)**2);e<i&&(i=e,s=t)}t.push(s)}if(t.length<2)throw new Error(`Not enough nodes for connection "${i.name}", only ${t.length} found`);s.set(i.name,t.map(t=>t.capacityMeshNodeId)),n.push({connection:i,nodeIds:[t[0].capacityMeshNodeId,t[t.length-1].capacityMeshNodeId],straightLineDistance:Pt(t[0].center,t[t.length-1].center)})}return{unshuffledConnectionsWithResults:n,connectionNameToGoalNodeIds:s}}function js(t,e){const n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),o=e.map(t=>(t.width+t.height)/2).filter(t=>Number.isFinite(t)&&t>0),s=o.length>0?o.reduce((t,e)=>t+e,0)/o.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}=ks(t,e);return{nodeMap:n,avgNodePitch:s,offBoardNodes:i,portPointMap:r,nodePortPointsMap:a,nodeAssignedPortPoints:c,unshuffledConnectionsWithResults:h,connectionNameToGoalNodeIds:d}}function Ws(t,e,n){let o=0;const s=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=zs(n),r=Math.min(Rs(t,i.numSameLayerCrossings,i.numEntryExitLayerChanges,i.numTransitionPairCrossings),s);o+=Math.log(1-r)}return o}function Hs(t,e){if(e._containsTarget)return 0;const n=zs(t);return Rs(e,n.numSameLayerCrossings,n.numEntryExitLayerChanges,n.numTransitionPairCrossings)}function Us(t,e,n,o,s){const i=n-e,r=s-o,a=1e-6;if(Math.abs(t.y-s)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(s-t.y);if(Math.abs(t.y-o)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-o);const c=Math.abs(t.y-s),h=Math.abs(t.x-n),d=Math.abs(t.y-o),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,s-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-o))}function Vs(t,e,n){let o=0;const s=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=zs(n),r=Math.min(Ls(t,i.numSameLayerCrossings),s);o+=Math.log(1-r)}return o}function Zs(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 Gs=[{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}],Js=class extends y{getSolverName(){return"MultiSectionPortPointOptimizer"}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=Gs;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 o={capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ},s=this.JUMPER_PF_FN_ENABLED&&1===e.availableZ.length?Ls(e,zs(o).numSameLayerCrossings):Hs(o,e);t.set(e.capacityMeshNodeId,s)}return t}computeBoardScore(){const t=this.getNodesWithPortPoints();return this.computeScoreForNodes(t)}computeScoreForNodes(t){return this.JUMPER_PF_FN_ENABLED?Vs(t,this.capacityMeshNodeMap):Ws(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 o={capacityMeshNodeId:e,center:t.center,width:t.width,height:t.height,portPoints:n,availableZ:t.availableZ},s=this.JUMPER_PF_FN_ENABLED&&1===t.availableZ.length?Ls(t,zs(o).numSameLayerCrossings):Hs(o,t);this.nodePfMap.set(e,s)}}getCreatePortPointSectionInput(){return{inputNodes:this.inputNodes,capacityMeshNodes:this.capacityMeshNodes,capacityMeshEdges:this.capacityMeshEdges,nodeMap:this.nodeMap,connectionResults:this.connectionResults}}createSection(t){return function(t,e){const{inputNodes:n,capacityMeshNodes:o,capacityMeshEdges:s,connectionResults:i}=t,{centerOfSectionCapacityNodeId:r,expansionDegrees:a}=e,c=new Map;for(const t of s){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=o.filter(t=>h.has(t.capacityMeshNodeId)),m=[],f=[];for(const t of s){const[e,n]=t.nodeIds,o=h.has(e),s=h.has(n);o&&s?m.push(t):(o||s)&&f.push(t)}const g=u.map(t=>{const e=t.portPoints.filter(t=>{const[e,n]=t.connectionNodeIds,o=h.has(e),s=h.has(n);return o||s});return{...t,portPoints:e}}),y=function(t,e){const n=[];for(const o of t){if(!o.path||0===o.path.length)continue;const t=o.connection.name,s=o.connection.rootConnectionName,i=[];for(let t=0;t<o.path.length;t++){const n=o.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=o.path[0].currentNodeId;(o.nodeIds[0]===t||o.nodeIds[1]===t)&&(c=0)}if(a<o.path.length-1){const t=o.path.length-1,e=o.path[t].currentNodeId;(o.nodeIds[0]===e||o.nodeIds[1]===e)&&(h=t)}const d=o.path.slice(c,h+1),l=c>0,u=h<o.path.length-1;n.push({connectionName:t,rootConnectionName:s,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),o=this.capacityMeshNodeMap.get(n);if(!t||!o)continue;const s=this.nodeAssignedPortPoints.get(n)??[];s.length>0&&e.push({capacityMeshNodeId:n,center:t.center,width:t.width,height:t.height,portPoints:s,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,o]of this.nodePfMap.entries()){o*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_ATTEMPTS_PER_NODE)**2>e&&(e=o,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,o=Zs(n);if(this.FRACTION_TO_REPLACE>=1)return new Set(e);const s=function(t,e){const n=Zs(e),o=[...t];for(let t=o.length-1;t>0;t--){const e=Math.floor(n()*(t+1));[o[t],o[e]]=[o[e],o[t]]}return o}(e,n),i=Math.max(1,Math.ceil(s.length*this.FRACTION_TO_REPLACE)),r=new Set(s.slice(0,i));if(this.ALWAYS_RIP_INTERSECTIONS){const n=function(t){const{section:e,nodePfMap:n,capacityMeshNodeMap:o,nodeAssignedPortPoints:s,acceptablePf:i}=t,r=[];for(const t of e.nodeIds){if((n.get(t)??0)<=i)continue;const e=o.get(t);if(!e)continue;const a=s.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],o=e[1];if(n.z!==o.z)continue;const s=Us(n,c,h,d,l),i=Us(o,c,h,d,l),r=n.z,a=p.get(r)??[];a.push({connectionName:t,t1:s,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:o,b:s}=e[t];for(let i=t+1;i<e.length;i++){const{connectionName:t,a:a,b:c}=e[i];Math.abs(o-a)<m||Math.abs(o-c)<m||Math.abs(s-a)<m||Math.abs(s-c)<m||(o<a&&a<s&&s<c||a<o&&o<c&&c<s)&&r.push([n,t])}}}}return r}({section:t,nodePfMap:this.nodePfMap,capacityMeshNodeMap:this.capacityMeshNodeMap,nodeAssignedPortPoints:this.nodeAssignedPortPoints,acceptablePf:this.ACCEPTABLE_PF});for(const[t,s]of n){if(r.has(t)||r.has(s))continue;const n=e.includes(t),i=e.includes(s);if(n&&i){const e=o()<.5;r.add(e?t:s)}else n?r.add(t):i&&r.add(s)}}return this.stats.lastRipCount=r.size,r}createSectionSimpleRouteJson(t){const e=[];this.currentSectionCutPathInfo.clear(),this.currentSectionKeptPortPoints.clear(),this.currentSectionFixedRoutes=[];const n=[],o=[];for(const e of this.connectionResults){if(!e.path||0===e.path.length)continue;const[s,i]=e.nodeIds,r=t.nodeIds.has(s),a=t.nodeIds.has(i);r&&a&&(o.push(e),n.push(e.connection.name))}const s=[];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&&(s.push({sectionPath:e,originalResult:t}),n.includes(e.connectionName)||n.push(e.connectionName))}const i=this.determineConnectionsToRip(t,n);for(const t of o)i.has(t.connection.name)&&e.push(t.connection);for(const{sectionPath:t,originalResult:n}of s){if(!i.has(t.connectionName))continue;const o=`__cut__${t.connectionName}__${t.originalStartIndex}`;this.colorMap[o]=this.colorMap[t.connectionName];const s=t.points[0],r=t.points[t.points.length-1],a={name:o,rootConnectionName:t.rootConnectionName??t.connectionName,pointsToConnect:[{x:s.x,y:s.y,layers:[`layer${s.z+1}`]},{x:r.x,y:r.y,layers:[`layer${r.z+1}`]}]};e.push(a),this.currentSectionCutPathInfo.set(o,{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 o)r.has(t.connection.name)&&this.currentSectionFixedRoutes.push(t);for(const{sectionPath:t,originalResult:e}of s)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 o=n.points[0].nodeId;e.add(o);const s=n.points[n.points.length-1].nodeId;e.add(s)}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),o=js(e,n);for(const[t,e]of this.currentSectionKeptPortPoints){const n=o.nodeAssignedPortPoints.get(t)??[];o.nodeAssignedPortPoints.set(t,[...n,...e])}return new Ks({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:o,fixedRoutes:this.currentSectionFixedRoutes})}reattachSection(t,e,n,o){const s=[],i=[];for(const t of e)t.connection.name.startsWith("__cut__")?i.push(t):s.push(t);const r=new Set(s.map(t=>t.connection.name));this.connectionResults=this.connectionResults.filter(t=>!r.has(t.connection.name)),this.connectionResults.push(...s);for(const[e,n]of this.nodeAssignedPortPoints.entries()){if(!t.nodeIds.has(e))continue;const o=n.filter(t=>!r.has(t.connectionName));this.nodeAssignedPortPoints.set(e,o)}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:o,originalConnectionResult:s}=n,i=s.path;if(!i)continue;const r=o.connectionName;for(const[e,n]of this.nodeAssignedPortPoints.entries()){const o=n.filter(n=>n.connectionName!==r||!t.nodeIds.has(e));this.nodeAssignedPortPoints.set(e,o)}const a=i.slice(0,o.originalStartIndex),c=i.slice(o.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]}),s.path=[...a,...h,...c],e.portPoints)for(const n of e.portPoints){const e={...n,connectionName:r,rootConnectionName:o.rootConnectionName??r};for(const o of t.inputNodes)for(const t of o.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 o.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("__"),o=n>=0?e.slice(0,n):e;return{...t,connectionName:o}}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),o=this.computeScoreForNodes(n),s=this.computeScoreForNodes(t),i=`attempt${this.sectionAttempts}`;if(this.stats.lastSectionScore=s,s>o){const t=this.stats.currentBoardScore;this.stats.lastBoardScore=t;const e=[...this.connectionResults],n=new Map(this.assignedPortPoints),o=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 s=this.computeBoardScore();this.stats.sectionScores[i]=s,s>t?(this.stats.successfulOptimizations++,this.stats.currentBoardScore=s):(this.connectionResults=e,this.assignedPortPoints=n,this.nodeAssignedPortPoints=o,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?Bs(this):this.activeSubSolver?this.activeSubSolver.visualize():this.currentSection?function(t,e){const n={lines:[],points:[],rects:[],circles:[]};for(const e of t.inputNodes){const o=e.capacityMeshNodeId===t.centerNodeId,s=o?"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:s,label:`${e.capacityMeshNodeId}${o?" (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 o of t.sectionPaths){const t=e?.[o.connectionName]??"blue";for(let e=0;e<o.points.length-1;e++){const s=o.points[e],i=o.points[e+1],r=s.z===i.z,a=s.z;let c;c=r?0===a?"5 5":"10 5":"3 3 10",n.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:t,strokeDash:c})}}return n}(this.currentSection,this.colorMap):Bs(this)}},qs=class extends y{constructor(t){super(),this.input=t;const{simpleRouteJson:e,capacityMeshNodes:n,inputNodes:o,colorMap:s,nodeMemoryPfMap:i,hyperParameters:r,precomputedInitialParams:a,fixedRoutes:c}=t;if(this.input=structuredClone(t),this.MAX_ITERATIONS=1e8,this.simpleRouteJson=e,this.inputNodes=o,this.colorMap=s??{},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,o]of t.nodeAssignedPortPoints)e.set(n,[...o]);return{nodeAssignedPortPoints:e}}(a);this.nodeAssignedPortPoints=t,this.connectionsWithResults=Bt(structuredClone(a.unshuffledConnectionsWithResults),this.hyperParameters.SHUFFLE_SEED??0)}else{this.nodeMap=new Map(o.map(t=>[t.capacityMeshNodeId,t]));const t=o.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=o.filter(t=>t._offBoardConnectionId),this.portPointMap=new Map,this.nodePortPointsMap=new Map;for(const t of o)this.nodePortPointsMap.set(t.capacityMeshNodeId,[]),this.nodeAssignedPortPoints.set(t.capacityMeshNodeId,[]);for(const t of o)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}getSolverName(){return"PortPointPathingSolver"}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(){const t=this.hyperParameters.START_RIPPING_PF_THRESHOLD,e=this.hyperParameters.END_RIPPING_PF_THRESHOLD;if(void 0!==t&&void 0!==e){const n=this.MAX_RIPS;return t+(n>0?this.totalRipCount/n:0)*(e-t)}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 o=this.computeNodePf(n),s=this.pfToFailureCost(o);return this.baseNodeCostCache.set(t,s),s}computeBoardScore(){const t=this.getNodesWithPortPoints();return this.JUMPER_PF_FN_ENABLED?Vs(t,this.capacityMeshNodeMap):Ws(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 o=this.nodeMap.get(t);if(!o)return 0;const s=this.getBaseNodeFailureCost(t),i=this.computeNodePf(o,[e,n]),r=this.pfToFailureCost(i),a=Math.max(0,r-s);return i>=this.NODE_MAX_PF?this.NODE_PF_MAX_PENALTY:a*this.NODE_PF_FACTOR}getConnectionsWithNodes(){const{unshuffledConnectionsWithResults:t,connectionNameToGoalNodeIds:e}=ks(this.simpleRouteJson,this.inputNodes);return{connectionsWithResults:Bt(t,this.hyperParameters.SHUFFLE_SEED??0),connectionNameToGoalNodeIds:e}}buildNodeWithPortPointsForCrossing(t,e){const n=this.nodeAssignedPortPoints.get(t.capacityMeshNodeId)??[],o=e?[...n,...e]:n;return{capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:o,availableZ:t.availableZ}}computeNodePf(t,e){if(t._containsTarget)return 0;const n=this.buildNodeWithPortPointsForCrossing(t,e),o=zs(n);return this.JUMPER_PF_FN_ENABLED&&1===t.availableZ.length?Ls(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),o.numSameLayerCrossings):Rs(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),o.numSameLayerCrossings,o.numEntryExitLayerChanges,o.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,o]=t.connectionNodeIds;return n===e?o:o===e?n:null}computeG(t,e,n,o,s){const i=t.currentNodeId,r=t.point,a={x:r.x,y:r.y,z:t.z,connectionName:o,rootConnectionName:s},c={x:e.x,y:e.y,z:e.z,connectionName:o,rootConnectionName:s},h=this.getNodeDeltaFailureCostForSegment(i,a,c);return t.g+h}computeGToEndTarget(t,e,n,o){const s=t.currentNodeId,i={x:t.point.x,y:t.point.y,z:t.z,connectionName:n,rootConnectionName:o},r={x:e.x,y:e.y,z:t.z,connectionName:n,rootConnectionName:o},a=this.getNodeDeltaFailureCostForSegment(s,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 o=Pt(t,n.center);o<e&&(e=o)}return e}computeH(t,e,n,o,s,i){if(this.RANDOM_WALK_DISTANCE>0&&s<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=Pt(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,o=this.nodePortPointsMap.get(t)??[],s=[];for(const t of o){const o=this.getVisitedPortPointKey(t.portPointId,e);if(this.visitedPortPoints?.has(o))continue;const i=this.assignedPortPoints.get(t.portPointId);i&&i?.rootConnectionName!==n||s.push(t)}return s}getAvailableExitPortPointsWithOmissions(t,e,n){const o=this.nodePortPointsMap.get(t)??[],s=this.currentConnection?.connection.rootConnectionName,i=new Map;for(const e of o){const o=this.getVisitedPortPointKey(e.portPointId,n);if(this.visitedPortPoints?.has(o))continue;const s=this.getOtherNodeId(e,t);if(!s)continue;this.nodeMap.get(s);const r=`${s}|${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),o=n&&n.rootConnectionName===s;if(!n||o){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===s?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 o=this.currentConnection?.connection.rootConnectionName,s=[];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!==o||s.push({...t,throughNodeId:i})}}return s}canTravelThroughObstacle(t,e,n){const o=this.connectionNameToGoalNodeIds.get(e);return o?.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),o=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}),o&&o._offBoardConnectionId&&e.push({prevCandidate:null,portPoint:null,currentNodeId:n.prevCandidate.currentNodeId,point:o.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 o=[];for(let s=0;s<t.length;s++){const i=t[s];if(!i.portPoint){const r=0===s,a=s===t.length-1;if(!r&&!a){const t={x:i.point.x,y:i.point.y,z:i.z,connectionName:e,rootConnectionName:n};o.push(t);const s=this.nodeAssignedPortPoints.get(i.currentNodeId)??[];s.push(t),this.nodeAssignedPortPoints.set(i.currentNodeId,s)}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};o.push(a);for(const t of r.connectionNodeIds){const e=this.nodeAssignedPortPoints.get(t)??[];e.push(a),this.nodeAssignedPortPoints.set(t,e)}}const s=Array.from(new Set(t.map(t=>t.currentNodeId)));for(const t of s){const o=this.nodeMap.get(t);if(o&&o._offBoardConnectionId)for(const t of o?._offBoardConnectedCapacityMeshNodeIds??[]){const o=this.nodePortPointsMap.get(t)??[];for(const t of o)this.assignedPortPoints.set(t.portPointId,{connectionName:e,rootConnectionName:n})}}return o}addTargetPointsToNodes(t,e){const n=t[0],o=t[t.length-1],s=e.pointsToConnect[0],i=e.pointsToConnect[e.pointsToConnect.length-1];if(n&&s){const t=this.nodeAssignedPortPoints.get(n.currentNodeId)??[];t.push({x:s.x,y:s.y,z:n.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(n.currentNodeId,t)}if(o&&i){const t=this.nodeAssignedPortPoints.get(o.currentNodeId)??[];t.push({x:i.x,y:i.y,z:o.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(o.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,totalRipCount:this.totalRipCount},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,o]=t.nodeIds,s=this.nodeMap.get(n),i=this.nodeMap.get(o);if(!s||!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 s.availableZ){const e=c?{x:c.x,y:c.y}:s.center,i=this.computeH({...e,distToCentermostPortOnZ:0},n,o,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,o)){const e=t.connection.pointsToConnect[t.connection.pointsToConnect.length-1],n=e?{x:e.x,y:e.y}:i.center,s=this.computeGToEndTarget(d,n,r,a),c={prevCandidate:d,portPoint:null,currentNodeId:o,point:n,z:d.z,g:s,h:0,f:s,distanceTraveled:d.distanceTraveled+Pt(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,o,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,s=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+Pt(d.point,t),u=d.hasTouchedOffBoardNode||Boolean(i._offBoardConnectionId),p=this.computeH(t,e,o,t.z,h,u),m=c+p*this.GREEDY_MULTIPLIER,f=Boolean(l?._offBoardConnectionId)&&Boolean(s?._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=[],o=new Set;for(const s of this.connectionsWithResults)if(s.path&&s.connection.name!==e&&!o.has(s.connection.name))for(const e of s.path)if(e.currentNodeId===t){n.push(s),o.add(s.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),o={capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:n,availableZ:t.availableZ},s=zs(o),i=s.numSameLayerCrossings+s.numEntryExitLayerChanges+s.numTransitionPairCrossings;return{pf:Rs(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),s.numSameLayerCrossings,s.numEntryExitLayerChanges,s.numTransitionPairCrossings),totalCrossings:i}}computeNodeCrossings(t){if(t._containsTarget)return 0;const e=this.buildNodeWithPortPointsForCrossing(t),n=zs(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 o=n.filter(t=>t.connectionName!==e);this.nodeAssignedPortPoints.set(t,o)}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 o=!1;for(const t of n){if(this.totalRipCount>this.MAX_RIPS)break;const n=this.nodeMap.get(t);if(!n)continue;let s=this.computeNodePf(n);if(s<=this.RIPPING_PF_THRESHOLD)continue;this.testedRipConnections.has(t)||this.testedRipConnections.set(t,new Set);const i=this.testedRipConnections.get(t),r=Bt(this.getConnectionsInNode(t,e),(this.hyperParameters.SHUFFLE_SEED??0)+this.processedConnectionQueue.length);for(const t of r){if(s<=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;s=r,o=!0,this.clearCostCaches()}}o&&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)),o=Bt(e,(this.hyperParameters.SHUFFLE_SEED??0)+this.totalRipCount+this.processedConnectionQueue.length);for(let t=0;t<n&&t<o.length&&!(this.totalRipCount>this.MAX_RIPS);t++){const e=o[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=Bs(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}},Ks=class extends Zt{getSolverName(){return"HyperPortPointPathingSolver"}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??js(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 qs({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()}},Qs=(t,e)=>t<=e?[t,e]:[e,t],ti=t=>`${t[0]}|${t[1]}`,ei=({portPointId:t,currentNodeId:e,inputNodes:n})=>{let o;if(t)for(const e of n){const n=e.portPoints.find(e=>e.portPointId===t);if(n?.connectionNodeIds){o=n.connectionNodeIds;break}}if(!o||2!==o.length)return[e,e];const[s,i]=o;return s&&i?Qs(s,i):[e,e]},ni=1e-6,oi=(t,e)=>Math.abs(t-e)<=ni,si=({nodeAId:t,nodeBId:e,nodeBounds:n})=>{if(t===e)return null;const o=n.get(t),s=n.get(e);if(!o||!s)return null;const i=Qs(t,e),r=ti(i);if(oi(o.maxX,s.minX)||oi(s.maxX,o.minX)){const n=Math.max(o.minY,s.minY),a=Math.min(o.maxY,s.maxY),c=a-n;if(c>ni){const h=oi(o.maxX,s.minX)?o.maxX:o.minX;return{ownerNodeIds:i,ownerPairKey:r,orientation:"vertical",x1:h,y1:n,x2:h,y2:a,center:{x:h,y:(n+a)/2},length:c,nodeSideByOwnerId:oi(o.maxX,s.minX)?{[t]:"right",[e]:"left"}:{[t]:"left",[e]:"right"}}}}if(oi(o.maxY,s.minY)||oi(s.maxY,o.minY)){const n=Math.max(o.minX,s.minX),a=Math.min(o.maxX,s.maxX),c=a-n;if(c>ni){const h=oi(o.maxY,s.minY)?o.maxY:o.minY;return{ownerNodeIds:i,ownerPairKey:r,orientation:"horizontal",x1:n,y1:h,x2:a,y2:h,center:{x:(n+a)/2,y:h},length:c,nodeSideByOwnerId:oi(o.maxY,s.minY)?{[t]:"top",[e]:"bottom"}:{[t]:"bottom",[e]:"top"}}}}return null},ii=({portPoint:t,ownerNodeIds:e,inputNodes:n})=>{for(const o of e){const e=n.find(t=>t.capacityMeshNodeId===o);if(e?._containsTarget)return!0;const s=e?.portPoints.find(e=>e.portPointId===t.portPointId);if(s?.connectionNodeIds?.some(t=>n.find(e=>e.capacityMeshNodeId===t)?._containsTarget))return!0}return!1},ri=1e-6,ai=class extends _n{constructor(t){super(),this.input=t;for(const e of t.nodeWithPortPoints)this.mapOfNodeIdToBounds.set(e.capacityMeshNodeId,kt(e));const e=new Map;for(const n of t.nodeWithPortPoints)for(const o of n.portPoints){if(!o.portPointId)continue;const s=ei({portPointId:o.portPointId,currentNodeId:n.capacityMeshNodeId,inputNodes:t.inputNodesWithPortPoints}),i=ti(s),r=this.mapOfOwnerPairToPortPoints.get(i)??[];r.some(t=>t.portPointId&&t.portPointId===o.portPointId)||r.push({...o,ownerNodeIds:s,ownerPairKey:i}),this.mapOfOwnerPairToPortPoints.set(i,r),e.set(i,s)}this.mapOfOwnerPairToSharedEdge=(({ownerPairs:t,nodeBounds:e})=>{const n=new Map;for(const o of t){const[t,s]=o;if(t===s)continue;const i=si({nodeAId:t,nodeBId:s,nodeBounds:e});i&&n.set(ti(o),i)}return n})({ownerPairs:Array.from(e.values()),nodeBounds:this.mapOfNodeIdToBounds}),this.ownerPairsToProcess=Array.from(this.mapOfOwnerPairToSharedEdge.keys()),this.ownerPairsToProcess.sort((t,e)=>{const n=this.mapOfOwnerPairToSharedEdge.get(t),o=this.mapOfOwnerPairToSharedEdge.get(e);return n.center.x-o.center.x||n.center.y-o.center.y})}getSolverName(){return"UniformPortDistributionSolver"}mapOfNodeIdToBounds=new Map;mapOfOwnerPairToPortPoints=new Map;mapOfOwnerPairToSharedEdge=new Map;ownerPairsToProcess=[];currentOwnerPairBeingProcessed=null;redistributedNodes=[];step(){if(0===this.ownerPairsToProcess.length)return this.rebuildNodes(),void(this.solved=!0);this.currentOwnerPairBeingProcessed=this.ownerPairsToProcess.shift();const t=this.currentOwnerPairBeingProcessed,e=this.mapOfOwnerPairToSharedEdge.get(t);if(!e)return;if((({sharedEdge:t,obstacles:e})=>{for(const n of e){const e=n.center.x-n.width/2,o=n.center.x+n.width/2,s=n.center.y-n.height/2,i=n.center.y+n.height/2;if("vertical"!==t.orientation){if(Math.abs(t.y1-s)<ri||Math.abs(t.y1-i)<ri){const n=Math.max(t.x1,e);if(Math.min(t.x2,o)-n>ri)return!0}}else if(Math.abs(t.x1-e)<ri||Math.abs(t.x1-o)<ri){const e=Math.max(t.y1,s);if(Math.min(t.y2,i)-e>ri)return!0}}return!1})({sharedEdge:e,obstacles:this.input.obstacles}))return;const n=this.mapOfOwnerPairToPortPoints.get(t)??[],o=[];for(const t of n)ii({portPoint:t,ownerNodeIds:t.ownerNodeIds,inputNodes:this.input.inputNodesWithPortPoints})||o.push(t);const s=(({sharedEdge:t,portPoints:e})=>{if(0===e.length)return[];const n=new Map;for(const t of e){const e=t.z??0,o=n.get(e)??[];o.push(t),n.set(e,o)}const o=[],s=Array.from(n.keys()).sort((t,e)=>t-e);for(const e of s){const s=n.get(e),i=s.length;s.sort((e,n)=>"horizontal"===t.orientation?e.x-n.x:e.y-n.y);for(let e=0;e<i;e++){const n=(2*e+1)/(2*i),r="horizontal"===t.orientation?t.x1+t.length*n:t.x1,a="horizontal"===t.orientation?t.y1:t.y1+t.length*n;o.push({...s[e],x:r,y:a})}}return o})({sharedEdge:e,portPoints:o});this.mapOfOwnerPairToPortPoints.set(t,s)}rebuildNodes(){const t=new Map;for(const e of this.mapOfOwnerPairToPortPoints.values())for(const n of e)n.portPointId&&t.set(n.portPointId,{x:n.x,y:n.y});this.redistributedNodes=this.input.nodeWithPortPoints.map(e=>({...e,portPoints:e.portPoints.map(e=>{if(e.portPointId&&t.has(e.portPointId)){const n=t.get(e.portPointId);return{...e,x:n.x,y:n.y}}return e})}))}getOutput=()=>this.redistributedNodes;visualize(){return(({obstacles:t,nodeWithPortPoints:e,mapOfOwnerPairToPortPoints:n,mapOfOwnerPairToSharedEdge:o,ownerPairsToProcess:s,currentOwnerPairBeingProcessed:i,mapOfNodeIdToBounds:r})=>{const a=t.map(t=>({...t,fill:"#ec000070"})),c=[],h=[],d=new Map,l=new Map,u=new Map;for(const t of e)for(const e of t.portPoints)e.portPointId&&(d.set(e.portPointId,{x:e.x,y:e.y}),l.set(e.portPointId,e.z??0));for(const t of n.values())for(const e of t)e.portPointId&&(d.set(e.portPointId,{x:e.x,y:e.y}),l.set(e.portPointId,e.z??0),u.set(e.portPointId,`${e.ownerNodeIds[0]}&${e.ownerNodeIds[1]}`));e.forEach(t=>{const e=r.get(t.capacityMeshNodeId);if(e){const n=(e.minX+e.maxX)/2,o=(e.minY+e.maxY)/2,s=e.maxX-e.minX,i=e.maxY-e.minY;a.push({center:{x:n,y:o},width:s,height:i,fill:"#00000030",label:`${t.capacityMeshNodeId}`})}t.portPoints.forEach(e=>{if(!e.portPointId)return;const n=d.get(e.portPointId),o=l.get(e.portPointId)??0,s=u.get(e.portPointId)??`${t.capacityMeshNodeId}&${t.capacityMeshNodeId}`;c.push({x:n.x,y:n.y,label:`z:${o}\no:${s}`}),t.portPoints.forEach(t=>{if(t.portPointId&&e!==t&&e.connectionName===t.connectionName){const e=d.get(t.portPointId);h.push({points:[n,e],strokeColor:"#fff822c9"})}})})});for(const t of s){const e=o.get(t);e&&h.push({points:[{x:e.x1,y:e.y1},{x:e.x2,y:e.y2}],strokeColor:"orange",strokeWidth:.01})}if(i){const t=o.get(i);t&&(h.push({points:[{x:t.x1,y:t.y1},{x:t.x2,y:t.y2}],strokeColor:"red",strokeWidth:.03}),c.push({x:t.center.x,y:t.center.y,label:t.ownerPairKey}))}for(const t of o.values())h.push({points:[{x:t.x1,y:t.y1},{x:t.x2,y:t.y2}],strokeColor:"#33b5ff80",strokeWidth:.006});return{rects:a,lines:h,points:c}})({obstacles:this.input.obstacles,nodeWithPortPoints:this.input.nodeWithPortPoints,mapOfOwnerPairToPortPoints:this.mapOfOwnerPairToPortPoints,mapOfOwnerPairToSharedEdge:this.mapOfOwnerPairToSharedEdge,ownerPairsToProcess:this.ownerPairsToProcess,currentOwnerPairBeingProcessed:this.currentOwnerPairBeingProcessed,mapOfNodeIdToBounds:this.mapOfNodeIdToBounds})}},ci=class extends y{getSolverName(){return"TraceWidthSolver"}hdRoutes;hdRoutesWithWidths=[];nominalTraceWidth;minTraceWidth;obstacleMargin;TRACE_WIDTH_SCHEDULE;connectionNominalTraceWidthMap;unprocessedRoutes=[];processedRoutes=[];currentTrace=null;cursorPosition=null;currentTraceSegmentIndex=0;currentTraceSegmentT=0;currentScheduleIndex=0;currentTargetWidth=0;hasInsufficientClearance=!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.obstacleMargin=t.obstacleMargin??.15,this.nominalTraceWidth=0,this.TRACE_WIDTH_SCHEDULE=[],this.unprocessedRoutes=[...this.hdRoutes],this.connMap=t.connMap,this.colorMap=t.colorMap,this.obstacles=t.obstacles??[],this.connectionNominalTraceWidthMap=new Map;for(const e of t.connection)void 0!==e.nominalTraceWidth&&this.connectionNominalTraceWidthMap.set(e.name,e.nominalTraceWidth);this.obstacles.length>0&&(this.obstacleSHI=new ss("flatbush",this.obstacles)),this.hdRouteSHI=new ds(this.hdRoutes)}getNominalTraceWidthForRoute(t){const e=this.connectionNominalTraceWidthMap.get(t.connectionName);return void 0!==e?e:t.rootConnectionName?this.connectionNominalTraceWidthMap.get(t.rootConnectionName):void 0}_step(){if(!this.currentTrace){const t=this.unprocessedRoutes.shift();if(!t)return this.hdRoutesWithWidths=this.processedRoutes,void(this.solved=!0);const e=this.getNominalTraceWidthForRoute(t);if(void 0===e)return this.processedRoutes.push({...t}),void(this.currentTrace=null);this.currentTrace=t,this.nominalTraceWidth=e;const n=(this.nominalTraceWidth+this.minTraceWidth)/2;return this.TRACE_WIDTH_SCHEDULE=[this.nominalTraceWidth,n],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())}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],o=t[this.currentTraceSegmentIndex+1];if(n.insideJumperPad&&o.insideJumperPad){this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0;continue}const s=o.x-n.x,i=o.y-n.y,r=Math.sqrt(s*s+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+s*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),o=Math.sqrt((t.center.x-e.end.x)**2+(t.center.y-e.end.y)**2),s=Math.max(t.width,t.height)/2+.01;if(n<s||o<s)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 o=1/0;if(this.lastCollidingObstacles=[],this.lastCollidingRoutes=[],this.obstacleSHI){const s=this.obstacleSHI.searchArea(t.x,t.y,n,n);for(const n of s){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 s=!1;if(this.connMap)for(const t of n.connectedTo)if(this.connMap.areIdsConnected(e,t)){s=!0;break}if(s)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<o&&(o=l)}}const s=this.hdRouteSHI.getConflictingRoutesNearPoint({x:t.x,y:t.y,z:t.z},n);for(const{conflictingRoute:t,distance:n}of s){const s=t.rootConnectionName??t.connectionName;if(s===e)continue;if(this.connMap?.areIdsConnected(e,s))continue;const i=n-(t.traceThickness??.15)/2;i<this.currentTargetWidth/2+this.obstacleMargin&&this.lastCollidingRoutes.push(t),i<o&&(o=i)}return this.lastClearance=o,o}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 o=e.has(n.obstacleId),s=n.zLayers?.includes(0),i=n.zLayers?.includes(1);let r;r=o?"rgba(255, 0, 0, 0.6)":s&&i?"rgba(128, 0, 128, 0.15)":s?"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:o?"red":void 0,label:o?`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,o=e.traceThickness===this.TRACE_WIDTH_SCHEDULE[1],s=n?"green":o?"yellow":"orange";for(let n=0;n<e.route.length-1;n++){const o=e.route[n],i=e.route[n+1];o.insideJumperPad&&i.insideJumperPad||o.z===i.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:s,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=Qe(e.jumpers,{color:s,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],o=this.currentTrace.route[e+1];n.insideJumperPad&&o.insideJumperPad||n.z===o.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:o.x,y:o.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 o=n.has(e.connectionName);for(let n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:o?"rgba(255, 0, 0, 0.8)":"rgba(128, 128, 128, 0.3)",strokeWidth:e.traceThickness??this.minTraceWidth,label:o?`COLLIDING: ${e.connectionName}`:e.connectionName})}}return t}getHdRoutesWithWidths(){return this.hdRoutesWithWidths}};function hi(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.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,this.effort=e.effort??1,void 0===e.capacityDepth){const n=t.bounds.maxX-t.bounds.minX,o=t.bounds.maxY-t.bounds.minY,s=Math.max(n,o),i=e.targetMinCapacity??.5;e.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getSolverName(){return"AutoroutingPipelineSolver2_PortPointPathing"}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;colorMap;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;uniformPortDistributionSolver;traceWidthSolver;viaDiameter;minTraceWidth;effort;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;inputNodeWithPortPoints=[];cacheProvider=null;pipelineDef=[hi("netToPointPairsSolver",vn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),hi("nodeSolver",es,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),hi("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),hi("availableSegmentPointSolver",Es,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),hi("portPointPathingSolver",Ks,t=>{this.inputNodeWithPortPoints=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}));const e=new Map(this.inputNodeWithPortPoints.map(t=>[t.capacityMeshNodeId,t])),n=t.availableSegmentPointSolver;for(const t of n.sharedEdgeSegments)for(const n of t.portPoints){const[t,o]=n.nodeIds,s={portPointId:n.segmentPortPointId,x:n.x,y:n.y,z:n.availableZ[0]??0,connectionNodeIds:[t,o],distToCentermostPortOnZ:n.distToCentermostPortOnZ},i=e.get(t);i&&i.portPoints.push(s)}return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:this.inputNodeWithPortPoints,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}}]}),hi("multiSectionPortPointOptimizer",Js,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}]}),hi("uniformPortDistributionSolver",ai,t=>[{nodeWithPortPoints:t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],inputNodesWithPortPoints:this.inputNodeWithPortPoints,minTraceWidth:t.minTraceWidth,obstacles:t.srj.obstacles,layerCount:t.srj.layerCount}]),hi("highDensityRouteSolver",Ye,t=>[{nodePortPoints:t.uniformPortDistributionSolver?.getOutput()??t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),hi("highDensityStitchSolver",rn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),hi("traceSimplificationSolver",_s,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}]),hi("traceWidthSolver",ci,t=>[{hdRoutes:t.traceSimplificationSolver.simplifiedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,minTraceWidth:t.minTraceWidth,connection:t.srj.connections}])];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(),o=this.singleLayerNodeMerger?.visualize(),s=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.uniformPortDistributionSolver?.visualize(),l=this.highDensityRouteSolver?.visualize(),u=this.highDensityStitchSolver?.visualize(),p=this.traceSimplificationSolver?.visualize(),m=this.srj.outline,f=[];if(f.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),m&&m.length>=2){const t=m.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),f.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const y={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:f},x=[y,t,e,n,o,s,i,r,a,c,h,d,l?g(y,l):null,u,p,this.solved?g(y,an(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...x)}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.traceWidthSolver?.getHdRoutesWithWidths()??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 o=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,s=e.filter(t=>t.connectionName===n.name);for(let e=0;e<s.length;e++){const i=s[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??n.rootConnectionName??n.name,route:Ve(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},li=di,ui=class{constructor(t){this.targets=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],o=Math.floor(n.bounds.minX/this.CELL_SIZE)*this.CELL_SIZE,s=Math.floor(n.bounds.minY/this.CELL_SIZE)*this.CELL_SIZE,i=n.bounds.maxX,r=n.bounds.maxY;for(let t=o;t<=i;t+=this.CELL_SIZE)for(let o=s;o<=r;o+=this.CELL_SIZE){const s=this.getBucketKey(t,o),i=this.buckets.get(s);i?i.push([n,e]):this.buckets.set(s,[[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,o){const s=[],i=new Set,r=Math.floor((t-n/2)/this.CELL_SIZE)*this.CELL_SIZE,a=Math.floor((e-o/2)/this.CELL_SIZE)*this.CELL_SIZE,c=t+n/2,h=e+o/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),o=this.buckets.get(n)||[];for(const t of o)i.has(t[1])||(i.add(t[1]),s.push(t[0]))}return s}},pi=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 o of e.layers)n.push(Be(o,t.layerCount));e.zLayers=n}const n={x:(t.bounds.minX+t.bounds.maxX)/2,y:(t.bounds.minY+t.bounds.maxY)/2},o={width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},s=Math.max(o.width,o.height);this.unfinishedNodes=[{capacityMeshNodeId:this.getNextNodeId(),center:n,width:s,height:s,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 ss("flatbush",this.srj.obstacles),this.targets=this.computeTargets(),this.targetTree=new ui(this.targets)}getSolverName(){return"CapacityMeshNodeSolver"}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 o=Je(n),s=this.obstacleTree.searchArea(n.x,n.y,.01,.01).filter(t=>t.zLayers.some(t=>o.some(e=>t===Be(e,this.layerCount))));let i={minX:n.x-.005,minY:n.y-.005,maxX:n.x+.005,maxY:n.y+.005};s.length>0&&(i={minX:Math.min(...s.map(t=>t.center.x-t.width/2)),minY:Math.min(...s.map(t=>t.center.y-t.height/2)),maxX:Math.max(...s.map(t=>t.center.x+t.width/2)),maxY:Math.max(...s.map(t=>t.center.y+t.height/2))});const r={...n,connectionName:e.name,availableZ:o.map(t=>Be(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=[],o=this.getNodeBounds(t),s=o.minX,i=o.maxX,r=o.minY,a=o.maxY,c=t._parent?this.getXYOverlappingObstacles(t._parent):this.srj.obstacles;for(const t of c){const e=t.center.x-t.width/2,o=t.center.x+t.width/2,c=t.center.y-t.height/2,h=t.center.y+t.height/2;i>=e&&s<=o&&a>=c&&r<=h?n.push(t):(s>=e&&i<=o&&r>=c&&a<=h||e>=s&&o<=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 o of e)t.availableZ.some(t=>o.zLayers.includes(t))&&n.push(o);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,o=t.center.x+t.width/2,s=t.center.y-t.height/2,i=t.center.y+t.height/2;if(n.minX>=e&&n.maxX<=o&&n.minY>=s&&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},o=[{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 s of o){const o={capacityMeshNodeId:this.getNextNodeId(),center:s,width:n.width,height:n.height,layer:t.layer,availableZ:t.availableZ,_depth:(t._depth??0)+1,_parent:t};o._containsObstacle=this.doesNodeOverlapObstacle(o);const i=this.getTargetIfNodeContainsTarget(o);i&&(o._targetConnectionName=i.connectionName,o.availableZ=i.availableZ,o._containsTarget=!0),o._containsObstacle&&(o._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(o)),o._completelyInsideObstacle&&!o._containsTarget||e.push(o)}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=[],o=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t);e?o.push(t):e||t._containsObstacle?!e&&t._containsTarget&&n.push(t):n.push(t)}this.unfinishedNodes.push(...o),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),o=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:o?"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: ${We(n).toFixed(2)}`].join("\n")})}return t.rects.sort((t,e)=>t.center.y-e.center.y),this.srj.connections.forEach((e,n)=>{const o=ot[n%ot.length];for(const s of e.pointsToConnect){const e=Je(s);t.points.push({x:s.x,y:s.y,label:`conn-${n} (${e.join(",")})`,color:o})}}),t}},mi=class extends pi{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e,this.VIA_DIAMETER=t.minViaDiameter??this.VIA_DIAMETER}getSolverName(){return"CapacityMeshNodeSolver2_NodeUnderObstacle"}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,o=t.center.x+t.width/2,s=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(o,t.center.x+t.width/2),c=Math.max(s,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},o=this.getXYZOverlappingObstacles(n);n._containsObstacle=o.length>0||this.isNodePartiallyOutsideBounds(n);const s=this.getTargetIfNodeContainsTarget(n);return s&&(n._targetConnectionName=s.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 o of n){const n=this.createChildNodeAtPosition(t,{center:{...t.center},width:t.width,height:t.height,availableZ:o,_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},o=[{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 s of o){const o=this.createChildNodeAtPosition(t,{center:s,width:n.width,height:n.height,availableZ:t.availableZ});this.isNodeCompletelyOutsideBounds(o)||e.push(o)}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=[],o=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),s=t.availableZ.length>1&&!e&&(t._containsObstacle||t.width<this.VIA_DIAMETER+this.OBSTACLE_MARGIN);if(e)o.push(t);else if(e||this.shouldFilterNodeForObstacle(t)||s)if(!e&&t._containsTarget)if(s){const e=this.getZSubdivisionChildNodes(t);n.push(...e.filter(t=>t._containsTarget||!this.shouldFilterNodeForObstacle(t)))}else n.push(t);else s&&n.push(...this.getZSubdivisionChildNodes(t).filter(t=>!this.shouldFilterNodeForObstacle(t)));else n.push(t)}this.unfinishedNodes.push(...o),this.finishedNodes.push(...n)}},fi=class extends y{getSolverName(){return"CapacityEdgeToPortSegmentSolver"}nodes;edges;capacityPaths;nodeMap;nodeEdgeMap;unprocessedNodeIds;nodePortSegments;colorMap;constructor({nodes:t,edges:e,capacityPaths:n,colorMap:o}){super(),this.nodes=t,this.edges=e,this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ts(e),this.capacityPaths=n,this.colorMap=o??{},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 o=n.nodeIds.indexOf(t);-1!==o&&e.push({path:n,indexOfNodeInPath:o})}const n=this.nodeMap.get(t),o=[];for(const{path:s,indexOfNodeInPath:i}of e){const e=s.nodeIds[i-1],r=s.nodeIds[i+1];for(const i of[e,r]){const e=this.nodeMap.get(i);if(!e)continue;const r=gi(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:[s.connectionName],rootConnectionNames:s.rootConnectionName?[s.rootConnectionName]:void 0,availableZ:a};o.push(c)}}const s=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 o=!1;for(let n=0;n<e.length;n++){const s=e[n],i=xi(s.start,t.start)&&xi(s.end,t.end)||xi(s.start,t.end)&&xi(s.end,t.start),r=vi(s.availableZ,t.availableZ);if(i&&r){const e=new Set(s.connectionNames);t.connectionNames.forEach(t=>e.add(t)),s.connectionNames=Array.from(e);const n=new Set(s.rootConnectionNames||[]);t.rootConnectionNames?.forEach(t=>n.add(t)),s.rootConnectionNames=Array.from(n),o=!0;break}}o||e.push(t)}return e}(o);this.nodePortSegments.set(t,s)}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 o=0;o<e.connectionNames.length;o++){const s={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+s.x,y:i.y+s.y};s.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[o]],.6)})}})}),t}};function gi(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)},o={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<o.end-o.start){const t=(n.start+n.end)/2;return{start:{x:t,y:o.start},end:{x:t,y:o.end}}}{const t=(o.start+o.end)/2;return{start:{x:n.start,y:t},end:{x:n.end,y:t}}}}var yi=1e-9;function xi(t,e){return Math.abs(t.x-e.x)<yi&&Math.abs(t.y-e.y)<yi}function vi(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 Pi=class extends y{getSolverName(){return"CapacitySegmentToPointSolver"}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 o=[...n.connectionNames].sort(),s=n.end.x-n.start.x,i=n.end.y-n.start.y,r=o.length,a=[];for(let t=1;t<=r;t++){const e=t/(r+1);a.push({x:n.start.x+s*e,y:n.start.y+i*e,z:n.availableZ[0]})}n.assignedPoints=o.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,o=this.nodeMap[n];t.has(n)||t.set(n,{capacityMeshNodeId:n,portPoints:[],center:o.center,width:o.width,height:o.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 o=n.assignedPoints[e],s={x:o.point.x,y:o.point.y},i={x:o.point.x+.05*o.point.z,y:o.point.y+.05*o.point.z};0!==o.point.z&&t.lines.push({points:[s,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}-${o.connectionName}`,`z: ${n.availableZ.join(",")}`,`nodePortSegmentId: ${n.nodePortSegmentId}`].join("\n"),color:this.colorMap[o.connectionName],step:4})}}const e=[],n={};for(const t of this.solvedSegments){const e=t.capacityMeshNodeId;n[e]||(n[e]={});for(const o of t.assignedPoints)n[e][o.connectionName]||(n[e][o.connectionName]=[]),n[e][o.connectionName].push({x:o.point.x,y:o.point.y})}for(const t in n)for(const o in n[t]){const s=n[t][o];s.length>1&&e.push({points:s,step:4,strokeDash:"5 5",strokeColor:this.colorMap[o]||"#000"})}return t.lines.push(...e),t}};function Si(t){const{nodeId:e,nodeIdToSegmentIds:n,segmentIdToNodeIds:o,hops:s}=t;if(0===s)return[e];const i=new Set([e]),r=[{nodeId:e,remainingHops:s}];for(;r.length>0;){const{nodeId:t,remainingHops:e}=r.shift();if(0===e)continue;const s=n.get(t)||[];for(const t of s){const n=o.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 Mi=t=>Array.from(t.entries()).map(([t,{x:e,y:n,z:o}])=>`${t}(${e?.toFixed(3)??""},${n?.toFixed(3)??""},${o??""})`).sort().join("&"),bi=(t,e,n,o)=>{const s=Math.min(t,e),i=Math.max(t,e),r=Math.min(n,o);return s<=Math.max(n,o)&&i>=r},Ni=(t,e,n,o)=>{const s=[],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]),o=i.get(t[1]);e.z!==o.z&&s.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(o?.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(!bi(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?s.push({type:"same_layer_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,crossingLine1:a,crossingLine2:c,probabilityOfFailure:0}):h.z===d.z&&l.z!==u.z?s.push({type:"single_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,sameLayerCrossingLine:a,transitionCrossingLine:c,probabilityOfFailure:0}):h.z!==d.z&&l.z===u.z?s.push({type:"single_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,sameLayerCrossingLine:c,transitionCrossingLine:a,probabilityOfFailure:0}):h.z!==d.z&&l.z!==u.z&&s.push({type:"double_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,crossingLine1:a,crossingLine2:c,probabilityOfFailure:0}))}}return s},Ii=(t,e,n)=>{if("change_layer"===e.type)for(const n of e.segmentPointIds){const o=t.get(n)||{};t.set(n,{...o,z:e.newZ})}else if("swap_position_on_segment"===e.type){const[o,s]=e.segmentPointIds,i=n(o),r=n(s),a=t.get(o)||{},c=t.get(s)||{};t.set(o,{...a,x:r.x,y:r.y}),t.set(s,{...c,x:i.x,y:i.y})}else if("combined"===e.type)for(const o of e.operations)Ii(t,o,n)},Ci=(t,e)=>{const n=new Map,o=new Map,s=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)o.set(t,[...o.get(t)??[],c.segmentPointId]);s.set(a.nodePortSegmentId,[...s.get(a.nodePortSegmentId)??[],c.segmentPointId]),i.push(c)}return{segmentPointMap:n,nodeToSegmentPointMap:o,segmentToSegmentPointMap:s}},_i=class extends y{getSolverName(){return"UnravelSectionSolver"}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,We(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}),o=Array.from(new Set(n).difference(new Set(e)));t?.segmentPointMap||(t=Ci(this.dedupedSegments,this.segmentIdToNodeIds));const s=new Map;for(const e of n)s.set(e,t.nodeToSegmentPointMap.get(e));const i=new Map;for(const e of n)for(const n of s.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 s.entries())for(let e=0;e<n.length;e++){const o=t.segmentPointMap.get(n[e]);for(let s=e+1;s<n.length;s++){const e=t.segmentPointMap.get(n[s]);e.segmentPointId!==o.segmentPointId&&(e.segmentId!==o.segmentId&&e.connectionName===o.connectionName&&(e.directlyConnectedSegmentPointIds.includes(o.segmentPointId)||(o.directlyConnectedSegmentPointIds.push(e.segmentPointId),e.directlyConnectedSegmentPointIds.push(o.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 o=c.get(n);if(o)for(const s of e.directlyConnectedSegmentPointIds){const i=t.segmentPointMap.get(s);i.segmentPointId!==e.segmentPointId&&(i.capacityMeshNodeIds.some(t=>t===n)&&(o.some(([t,n])=>t===e.segmentPointId&&n===i.segmentPointId||t===i.segmentPointId&&n===e.segmentPointId)||o.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)),o=this.dedupedSegmentMap.get(t.segmentId),s=o&&o.availableZ.length>1;(n||s)&&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:o,mutableSegmentIds:h,segmentPairsInNode:c,segmentPointMap:i,segmentPointsInNode:s,segmentPointsInSegment:a,originalPointMap:i,mutableSegmentPointIds:d,zLockedSegmentPointIds:l}}createInitialCandidate(){const t=new Map,e=Ni(this.unravelSection,this.nodeMap,t),n=this.computeG({issues:e,originalCandidate:{},operationsPerformed:0,operation:{}});return{pointModifications:t,g:n,h:0,f:n,operationsPerformed:0,candidateHash:Mi(t),issues:Ni(this.unravelSection,this.nodeMap,t)}}get nextCandidate(){return this.candidates[0]??null}getPointInCandidate(t,e){const n=this.unravelSection.segmentPointMap.get(e),o=t.pointModifications.get(e);return{x:o?.x??n.x,y:o?.y??n.y,z:o?.z??n.z,segmentId:n.segmentId}}getConnectionSegmentPointIds(t){const e=[];for(const[n,o]of this.unravelSection.segmentPointMap.entries())o.connectionName===t&&e.push(n);return e}canConnectionUseLayer(t,e){for(const n of t){const t=this.unravelSection.segmentPointMap.get(n),o=this.dedupedSegmentMap.get(t.segmentId);if(!o||!o.availableZ.includes(e))return!1}return!0}getOperationsForIssue(t,e){const n=[];if("transition_via"===e.type){const[o,s]=e.segmentPoints,i=this.getPointInCandidate(t,o),r=this.getPointInCandidate(t,s),a=this.unravelSection.segmentPointMap.get(o),c=(this.unravelSection.segmentPointMap.get(s),this.dedupedSegmentMap.get(i.segmentId).availableZ),h=this.dedupedSegmentMap.get(r.segmentId).availableZ,d=this.unravelSection.zLockedSegmentPointIds.has(o),l=this.unravelSection.zLockedSegmentPointIds.has(s),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(o)&&!d&&c.includes(r.z)&&n.push({type:"change_layer",newZ:r.z,segmentPointIds:[o]}),this.unravelSection.mutableSegmentPointIds.has(s)&&!l&&h.includes(i.z)&&n.push({type:"change_layer",newZ:i.z,segmentPointIds:[s]})}if("same_layer_crossing"===e.type){const[t,o]=e.crossingLine1,[s,i]=e.crossingLine2,r=[],a=this.unravelSection.segmentPointMap.get(t),c=this.unravelSection.segmentPointMap.get(o),h=this.unravelSection.segmentPointMap.get(s),d=this.unravelSection.segmentPointMap.get(i),l=this.unravelSection.mutableSegmentPointIds.has(t),u=this.unravelSection.mutableSegmentPointIds.has(o),p=this.unravelSection.mutableSegmentPointIds.has(s),m=this.unravelSection.mutableSegmentPointIds.has(i),f=this.unravelSection.zLockedSegmentPointIds.has(t),g=this.unravelSection.zLockedSegmentPointIds.has(o),y=this.unravelSection.zLockedSegmentPointIds.has(s),x=this.unravelSection.zLockedSegmentPointIds.has(i);l&&p&&a.segmentId===h.segmentId&&r.push([t,s]),l&&m&&a.segmentId===d.segmentId&&r.push([t,i]),u&&p&&c.segmentId===h.segmentId&&r.push([o,s]),u&&m&&c.segmentId===d.segmentId&&r.push([o,i]);for(const[t,e]of r)n.push({type:"swap_position_on_segment",segmentPointIds:[t,e]});const v=this.getConnectionSegmentPointIds(a.connectionName),P=this.getConnectionSegmentPointIds(h.connectionName),S=new Set;for(const t of this.unravelSection.segmentPointMap.values()){const e=this.dedupedSegmentMap.get(t.segmentId);if(e)for(const t of e.availableZ)S.add(t)}for(const t of S)if(t!==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 S)if(t!==h.z&&this.canConnectionUseLayer(P,t)){const e=P.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 M=this.dedupedSegmentMap.get(a.segmentId),b=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([M,b],e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t,o]})}if(p&&m&&!y&&!x){const t=0===h.z?1:0;C([N,I],t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[s,i]})}if(l&&!f){const e=0===a.z?1:0;M.availableZ.includes(e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t]})}if(u&&!g){const t=0===c.z?1:0;b.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[o]})}if(p&&!y){const t=0===h.z?1:0;N.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[s]})}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:o,operation:s}=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:o}]of i){const s=this.nodeMap.get(t),i=Math.min(Rs(s,n,e,o),.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);Ii(n,e,e=>this.getPointInCandidate(t,e));const o=Mi(n);if(this.queuedOrExploredCandidatePointModificationHashes.has(o))return null;const s=Ni(this.unravelSection,this.nodeMap,n),i=t.operationsPerformed+1,r=this.computeG({issues:s,originalCandidate:t,operationsPerformed:i,operation:e});return{issues:s,g:r,h:0,f:r,pointModifications:n,candidateHash:o,operationsPerformed:i}}getNeighborOperationsForCandidate(t){return t.issues.flatMap(e=>this.getOperationsForIssue(t,e))}getNeighbors(t){const e=[],n=this.getNeighborOperationsForCandidate(t);for(const o of n){const n=this.getUnexploredNeighborByApplyingOperation(t,o);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,o]of this.unravelSection.segmentPointMap){const s={...o},i=e.pointModifications.get(t);i&&(void 0!==i.x&&(s.x=i.x),void 0!==i.y&&(s.y=i.y),void 0!==i.z&&(s.z=i.z)),n.set(t,s)}for(const[e,o]of n)t.points.push({x:o.x,y:o.y,label:`${e}\nSegment: ${o.segmentId} ${this.unravelSection.mutableSegmentIds.has(o.segmentId)?"MUTABLE":"IMMUTABLE"}\nLayer: ${o.z}`,color:this.colorMap[o.connectionName]||"#000"});const o=new Map;for(const t of this.unravelSection.allNodeIds)o.set(t,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0,estPf:0});for(const t of e.issues){const e=o.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"!==t.type&&"single_transition_crossing"!==t.type||e.numEntryExitLayerChanges++}for(const[t,e]of o.entries()){const n=this.nodeMap.get(t);e.estPf=Rs(n,e.numSameLayerCrossings,e.numEntryExitLayerChanges,e.numTransitionCrossings)}for(const e of this.unravelSection.allNodeIds){const n=this.nodeMap.get(e),s=this.unravelSection.mutableNodeIds.includes(e),i=o.get(e),r=[`${e} (${s?"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:s?"green":"red",width:n.width/8,height:n.height/8})}for(const[e,o]of this.unravelSection.segmentPointsInSegment){if(o.length<=1)continue;const s=o.map(t=>n.get(t));for(let n=0;n<s.length-1;n++)t.lines.push({points:[{x:s[n].x,y:s[n].y},{x:s[n+1].x,y:s[n+1].y}],strokeColor:this.colorMap[e]||"#000"})}for(const[e,o]of n)for(const s of o.directlyConnectedSegmentPointIds)if(e<s){const e=n.get(s);if(!e)continue;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]||"#000"})}for(const o of e.issues){const e=this.nodeMap.get(o.capacityMeshNodeId);if("transition_via"===o.type)for(const s of o.segmentPoints){const o=n.get(s);t.circles.push({center:{x:o.x,y:o.y},radius:e.width/16,stroke:"#ff0000",fill:"rgba(255, 0, 0, 0.2)",label:`Via Issue\n${s}\nLayer: ${o.z}`})}else if("same_layer_crossing"===o.type)for(const[s,i]of[o.crossingLine1,o.crossingLine2]){const o=n.get(s),r=n.get(i);t.lines.push({points:[{x:o.x,y:o.y},{x:r.x,y:r.y}],strokeColor:"rgba(255,0,0,0.2)",strokeWidth:e.width/32})}}for(const[o,s]of e.pointModifications){const e=n.get(o),s=this.unravelSection.segmentPointMap.get(o);t.circles.push({center:{x:e.x,y:e.y},radius:.05,stroke:"#0000ff",fill:"rgba(0, 0, 255, 0.2)",label:`${o}\nOriginal: (${s.x.toFixed(2)}, ${s.y.toFixed(2)}, ${s.z})\nNew: (${e.x.toFixed(2)}, ${e.y.toFixed(2)}, ${e.z})`})}return t}};import Ti from"object-hash";var Ei=t=>(Math.round(20*t)/20).toFixed(2),Ri=t=>(Math.round(1e3*t)/1e3).toFixed(3);pt();var wi=class extends _i{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=Sn(-t.center.x,-t.center.y),n=new Map,o=new Map,s=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),o=this.nodeMap.get(e);return n.center.x!==o.center.x?n.center.x-o.center.x:n.center.y-o.center.y});for(const t of l){const e="node_"+c++;n.set(t,e),o.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(!s.has(n)){const t="seg_"+h++;s.set(n,t),i.set(t,n)}}const p={};for(const[t,o]of n.entries()){const n=this.nodeMap.get(t),s=Pn(e,n.center);p[o]={width:n.width,height:n.height,availableZ:n.availableZ,center:{x:Ei(s.x),y:Ei(s.y)}}}const m={};for(const[t,n]of r.entries()){const o=this.unravelSection.segmentPointMap.get(t),s=Pn(e,{x:o.x,y:o.y});m[n]={x:Ei(s.x),y:Ei(s.y),z:o.z}}const f={hyperParameters:this.hyperParameters,normalizedNodes:p,normalizedSegmentPoints:m,mutableHops:this.MUTABLE_HOPS},g=`unravelsec:${Ti(f)}`,y={realToCacheTransform:e,nodeIdMap:n,segmentIdMap:s,segmentPointIdMap:r,reverseNodeIdMap:o,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,o=new Map;for(const[n,s]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!==s.dx){const t=parseFloat(s.dx);Number.isNaN(t)?console.warn(`Failed to parse cached dx coordinate: ${s.dx}`):r.x=i.x+t}if(void 0!==s.dy){const t=parseFloat(s.dy);Number.isNaN(t)?console.warn(`Failed to parse cached dy coordinate: ${s.dy}`):r.y=i.y+t}void 0!==s.dz&&(r.z=i.z+s.dz),Object.keys(r).length>0&&o.set(t,r)}const s=Ni(this.unravelSection,this.nodeMap,o);this.bestCandidate={pointModifications:o,issues:s,f:t.bestCandidateF,g:t.bestCandidateF,h:0,operationsPerformed:-1,candidateHash:Mi(o)},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,o]of this.bestCandidate.pointModifications.entries()){const s=t.get(n);if(!s){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!==o.x){const t=o.x-i.x,e=Ri(t);0!==parseFloat(e)&&(r.dx=e,a=!0)}if(void 0!==o.y){const t=o.y-i.y,e=Ri(t);0!==parseFloat(e)&&(r.dy=e,a=!0)}if(void 0!==o.z){const t=o.z-i.z;0!==t&&(r.dz=t,a=!0)}a&&e.push([s,r])}const n={success:!0,bestCandidatePointModificationsDelta:e,bestCandidateF:this.bestCandidate.f};this.cacheProvider?.setCachedSolutionSync(this.cacheKey,n)}},Ai=class extends y{getSolverName(){return"UnravelMultiSectionSolver"}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:o}){super(),this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.cacheHits=0,this.stats.cacheMisses=0,this.cacheProvider=o??null,this.MAX_ITERATIONS=1e6,this.dedupedSegments=(t=>{const e=[],n=new Map;let o=-1;for(const s of t){const t=`${s.start.x}-${s.start.y}-${s.end.x}-${s.end.y}-${s.availableZ.join(",")}`,i=n.get(t);i?s.nodePortSegmentId=i.nodePortSegmentId:(o++,s.nodePortSegmentId=`SEG${o}`,n.set(t,s),e.push(s))}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,We(e));const{segmentPointMap:s,nodeToSegmentPointMap:i,segmentToSegmentPointMap:r}=Ci(this.dedupedSegments,this.segmentIdToNodeIds);this.segmentPointMap=s,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:o}=(t=>{let e=0,n=0,o=0;const s=new Map;for(const e of t)s.has(e.connectionName)||s.set(e.connectionName,[]),s.get(e.connectionName).push(e);const i=[],r=[];for(const[t,e]of s.entries()){if(e.length<2)continue;const o=e[0];for(let s=1;s<e.length;s++){const a=e[s],c={connectionName:t,z:o.z,points:[o,a]};o.z!==a.z?(n++,r.push({connectionName:t,points:[o,a]})):i.push(c)}}for(let t=0;t<i.length;t++)for(let n=t+1;n<i.length;n++){const o=i[t],s=i[n];o.z===s.z&&gt(o.points[0],o.points[1],s.points[0],s.points[1])&&e++}for(let t=0;t<r.length;t++)for(let e=t+1;e<r.length;e++){const n=r[t],s=r[e];gt(n.points[0],n.points[1],s.points[0],s.points[1])&&o++}for(let t=0;t<r.length;t++)for(let e=0;e<i.length;e++){const n=r[t],s=i[e];gt(n.points[0],n.points[1],s.points[0],s.points[1])&&o++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:n,numTransitionCrossings:o}})((this.nodeToSegmentPointMap.get(t.capacityMeshNodeId)??[]).map(t=>this.segmentPointMap.get(t)));return Rs(t,e,n,o)}_step(){if(this.iterations>=this.MAX_ITERATIONS-1)return void(this.solved=!0);if(!this.activeSubSolver){let t=null,e=0;for(const[n,o]of this.nodePfMap.entries()){o*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_NODE_ATTEMPTS)>e&&(e=o,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 wi({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 o=this.nodePfMap.get(e)||0,s=Math.min(o,1),i=`rgb(${Math.floor(255*s)}, ${Math.floor(255*(1-s))}, 0)`;0===(this.attemptsToFixNode.get(e)??0)&&0===s||t.rects.push({center:n.center,label:[e,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Pf: ${o.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,o]of e.entries()){if(o.length<2)continue;const e=[...o].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y);for(let o=0;o<e.length-1;o++)t.lines.push({points:[{x:e[o].x,y:e[o].y},{x:e[o+1].x,y:e[o+1].y}],strokeColor:this.colorMap[n]||"#000"})}const n=new Set,o=Array.from(this.segmentPointMap.values());for(let e=0;e<o.length;e++){const s=o[e];for(let i=e+1;i<o.length;i++){const e=o[i];if(s.connectionName!==e.connectionName||s.segmentId===e.segmentId)continue;if(s.capacityMeshNodeIds.some(t=>e.capacityMeshNodeIds.includes(t))){const o=`${s.segmentPointId}-${e.segmentPointId}`;if(n.has(o))continue;n.add(o);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]||"#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 o=t.get(n);o&&o.portPoints.push({x:e.x,y:e.y,z:e.z,connectionName:e.connectionName,rootConnectionName:e.rootConnectionName})}return Array.from(t.values())}},Oi=(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")}},zi=class extends y{getSolverName(){return"CapacityPathingSolver"}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:o,MAX_ITERATIONS:s=1e6,hyperParameters:i={}}){super(),this.MAX_ITERATIONS=s,this.simpleRouteJson=t,this.nodes=e,this.edges=n,this.colorMap=o??{};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=Ts(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 o of this.simpleRouteJson.connections){const s=[];for(const t of o.pointsToConnect){let n=this.nodes[0],o=Number.MAX_VALUE;for(const s of e){const e=Math.sqrt((s.center.x-t.x)**2+(s.center.y-t.y)**2);e<o&&(o=e,n=s)}s.push(n)}if(s.length<2)throw new Error(`Not enough nodes for connection "${o.name}", only ${s.length} found`);n.set(o.name,s.map(t=>t.capacityMeshNodeId)),t.push({connection:o,nodes:s,pathFound:!1,straightLineDistance:Pt(s[0].center,s[s.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,o=this.getTotalCapacity(t);if(1===t.availableZ.length&&!t._containsTarget&&n>0)return!1;let s=0;return t.availableZ.length>1&&1===e.availableZ.length&&(s+=.5),n+s<o}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=Pt(e.center,n.center)),this.candidates.sort((t,e)=>t.f-e.f);const o=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),!o)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(o.node,n))return t.path=this.getBacktrackedPath({prevCandidate:o,node:n,f:0,g:0,h:0}),this.reduceCapacityAlongPath(t),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);const s=this.getNeighboringNodes(o.node);for(const t of s){if(this.visitedNodes?.has(t.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(t,o.node))continue;const e=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;if(t._containsObstacle&&!this.canTravelThroughObstacle(t,e))continue;const s=this.computeG(o,t,n),i=this.computeH(o,t,n),r=s+i*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:r,g:s,h:i});const a={prevCandidate:o,node:t,f:r,g:s,h:i};this.candidates.push(a)}this.visitedNodes.add(o.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 o=n.path.map(({center:{x:t,y:n},width:o,availableZ:s})=>({x:t+.005*o*(e%10+e%19),y:n+.005*o*(e%10+e%19),availableZ:s}));t.lines.push({points:o,strokeColor:this.colorMap[n.connection.name]});for(let e=0;e<o.length;e++){const s=o[e];t.points.push({x:s.x,y:s.y,label:[`conn: ${n.connection.name}`,`node: ${n.path[e].capacityMeshNodeId}`,`z: ${s.availableZ.join(",")}`].join("\n")})}}}for(const e of this.nodes){const n=this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,o=this.getTotalCapacity(e),s=this.debug_lastNodeCostMap.get(e.capacityMeshNodeId);t.rects.push({...Oi(e,{rectMargin:.025,zOffset:.01}),label:[`${e.capacityMeshNodeId}`,`${n}/${o}`,`${e.width.toFixed(2)}x${e.height.toFixed(2)}`,`g: ${void 0!==s?.g?s.g.toFixed(2):"?"}`,`h: ${void 0!==s?.h?s.h.toFixed(2):"?"}`,`f: ${void 0!==s?.f?s.f.toFixed(2):"?"}`,`z: ${e.availableZ.join(", ")}`].join("\n"),stroke:n>o+.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,o]=e.connection.pointsToConnect;t.lines.push({points:[{x:n.x,y:n.y},{x:o.x,y:o.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,o)=>{const s=.5*(1-o/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-s)})})}return t}},Di=class extends zi{getSolverName(){return"CapacityPathingSolver5"}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 We(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){const e=t.width+t.height,n=.05,o=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0);if(o>2)return n;return(e-n)*Math.max(1,(2-o)/(e-n))+n}getDistanceBetweenNodes(t,e){const n=t.center.x-e.center.x,o=t.center.y-e.center.y;return Math.sqrt(n**2+o**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)}},Li=class extends Di{getSolverName(){return"CapacityPathingGreedySolver"}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 Fi(t,e,n){const o=e.x-t.x,s=e.y-t.y;if(Math.abs(o)<1e-9&&Math.abs(s)<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(o)>1e-9){const e=(a-t.x)/o,n=(c-t.x)/o;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(s)>1e-9){const e=(h-t.y)/s,n=(d-t.y)/s;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+o*l,y:t.y+s*l}}function Xi(t,e){const n=t.center,o=e.center,s=Fi(n,o,t),i=Fi(o,n,e),r=o.x-n.x,a=o.y-n.y,c=Math.sqrt(r*r+a*a);let h=s,d=i;if(c>1e-9){const n={x:r/c,y:a/c},o=.3*t.width,l=.3*e.width;o+l<Math.sqrt((i.x-s.x)**2+(i.y-s.y)**2)?(h={x:s.x+n.x*o,y:s.y+n.y*o},d={x:i.x-n.x*l,y:i.y-n.y*l}):(h=s,d=i)}return{lineStart:h,lineEnd:d}}var Yi=t=>{const{usedCapacity:e,totalCapacity:n,layerCount:o}=t;if(e<n)return 0;if(n<1&&e<=1)return 0;if(1===o&&e>1)return 1-.01**e;const s=e/n-1;return 1-Math.exp(-2*s)},$i=(t,e,n)=>{if(n._containsTarget)return 0;if(t<=e)return 0;const o=1-Yi({usedCapacity:t,totalCapacity:e,layerCount:n.availableZ.length});return o<=0?-1e9:Math.log(o)},Bi=({totalNodeCapacityMap:t,usedNodeCapacityMap:e,nodeMap:n,sectionNodeIds:o})=>{let s=0;const i=o??new Set(e.keys());for(const o of i){if(!t.has(o))continue;const i=n.get(o);if(!i)continue;const r=t.get(o),a=e.get(o)??0;s+=$i(a,r,i)}return s};function ki({sectionNodes:t,sectionEdges:e,sectionConnectionTerminals:n,completedPaths:o,nodeMap:s,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 o=e.availableZ??[],s=o.includes(0),i=o.includes(1);s&&i?(t=`rgba(128, 0, 128, ${c})`,n=`rgba(128, 0, 128, ${c})`):s?(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({...Oi(e),fill:t,stroke:n,label:`${e.capacityMeshNodeId}\n(Section Node)\nZ: ${o.join(",")}`});const a=l.rects.length-1;if(h&&d){const t=h.get(e.capacityMeshNodeId)??0,n=d.get(e.capacityMeshNodeId)??0,o=n>0?(t/n*100).toFixed(1):"N/A",s=Yi({usedCapacity:t,totalCapacity:n,layerCount:e.availableZ.length});l.rects[a].label+=`\n${t.toFixed(1)} / ${n.toFixed(1)}\n${o}% (Pf: ${(100*s).toFixed(1)}%)`,s>.2&&(l.rects[a].stroke=it("red",.7*(.8+c)))}}for(const t of e){const[e,n]=t.nodeIds,o=s.get(e),i=s.get(n);if(o&&i){const{lineStart:t,lineEnd:e}=Xi(o,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=s.get(t.startNodeId),o=s.get(t.endNodeId),r=i[t.connectionName]??"black",a=n&&u.has(n.capacityMeshNodeId),c=o&&u.has(o.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&&o){const e=.02*Math.min(o.width,o.height);m=e*h,f=e*h,l.points.push({x:o.center.x+m,y:o.center.y+f,color:r,label:`End: ${t.connectionName}\n(${t.endNodeId})`}),l.lines.push({points:[{x:o.center.x,y:o.center.y},{x:o.center.x+m,y:o.center.y+f}],strokeColor:"gray",strokeDash:"2 2"})}a&&c&&n&&o&&l.lines.push({points:[{x:n.center.x+d,y:n.center.y+p},{x:o.center.x+m,y:o.center.y+f}],strokeColor:r,strokeDash:"5 5"})}),o&&o.forEach((t,e)=>{if(t.path&&t.path.length>0){const n=i[t.connectionName]??"gray",o={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+o.x,y:e+o.y})),strokeColor:it(n,.2)})}}),l}var ji=class extends y{getSolverName(){return"CapacityPathingSingleSectionSolver"}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??Ts(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=Bi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:e}),t.hyperParameters?.SHUFFLE_SEED&&(this.sectionConnectionTerminals=Bt(this.sectionConnectionTerminals,t.hyperParameters?.SHUFFLE_SEED))}getTotalCapacity(t){return We(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,o=t.center.y-e.center.y;return Math.sqrt(n**2+o**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 o=this.totalNodeCapacityMap.get(t),s=this.usedNodeCapacityMap.get(t)??0,i=$i(s,o,n);this.currentSectionScore-=i;const r=s+1;this.usedNodeCapacityMap.set(t,r);const a=$i(r,o,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 o=this.candidates;if(0===o.length)return void this._handleCandidatesExhausted(t);o.sort((t,e)=>t.f-e.f);const s=o.shift();if(o.length>this.MAX_CANDIDATES_IN_MEMORY&&o.splice(this.MAX_CANDIDATES_IN_MEMORY,o.length-this.MAX_CANDIDATES_IN_MEMORY),this.visitedNodes.add(s.node.capacityMeshNodeId),s.node.capacityMeshNodeId===n.capacityMeshNodeId)return void this._handleGoalReached(s,t,n);const i=this.getNeighboringNodes(s.node);for(const e of i){if(this.queuedNodes?.has(e.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(e,s.node))continue;if(e._containsObstacle){const n=e.capacityMeshNodeId===t.startNodeId,o=e.capacityMeshNodeId===t.endNodeId;if(!n&&!o)continue}const i=this.computeG(s,e,n),r=this.computeH(s,e,n),a=i+r*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(e.capacityMeshNodeId,{f:a,g:i,h:r});const c={prevCandidate:s,node:e,f:a,g:i,h:r};this.queuedNodes?.add(e.capacityMeshNodeId),o.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=Pt(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 o=this.getBacktrackedPath(t);e.path=o,this.reduceCapacityAlongPath(o),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=ki({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 o=this.debug_lastNodeCostMap.get(t.capacityMeshNodeId),s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,i=this.getTotalCapacity(t),r=`${s.toFixed(1)}/${i.toFixed(1)}`,a=o?`f:${o.f.toFixed(1)} g:${o.g.toFixed(1)} h:${o.h.toFixed(1)}`:"cost:?";e.rects[n].label=[t.capacityMeshNodeId,`Cap: ${r}`,a,`Z: ${t.availableZ.join(",")}`].join("\n"),s>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],o=n?.connectionName??"unknown",s=this.colorMap[o]??"purple";t.forEach((t,n)=>{const o=.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(s,1-o),strokeWidth:.05})})}return e}},Wi=t=>Array.from({length:t},(t,e)=>e),Hi=class extends Zt{getSolverName(){return"HyperCapacityPathingSingleSectionSolver"}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:Wi(2).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings6_for3",possibleValues:Wi(6).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings24_for4",possibleValues:Wi(24).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings30",possibleValues:Wi(30).map(t=>({SHUFFLE_SEED:t}))}]}generateSolver(t){return new ji({...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 Ui from"object-hash";var Vi=t=>Math.floor(10*t)/10,Zi=class extends Hi{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 o=n.pop();if(!o)break;e.push(o.capacityMeshNodeId);const s=this.constructorParams.nodeEdgeMap.get(o.capacityMeshNodeId).flatMap(t=>t.nodeIds).filter(e=>!t.has(e)).filter(t=>this.sectionNodeIdSet.has(t));for(const e of s){t.add(e);const s=this.constructorParams.nodeMap.get(e),i=We(s);n.push({ancestorCapacitySum:o.g,capacity:i,g:o.g+i,capacityMeshNodeId:e})}}return e}computeCacheKeyAndTransform(){const t=this._computeBfsOrderingOfNodesInSection(),e=new Map,n=new Map;t.forEach((t,o)=>{const s=`node${o}`;e.set(t,s),n.set(s,t)});const o={};for(const n of t){const t=e.get(n),s=this.constructorParams.nodeMap.get(n),i=We(s);o[t]=Vi(i).toFixed(1)}const s=new Set,i=[];for(const n of t){const t=e.get(n),o=this.constructorParams.nodeEdgeMap.get(n)??[];for(const r of o){const o=r.nodeIds.find(t=>t!==n);if(this.sectionNodeIdSet.has(o)){const n=[t,e.get(o)].sort(),r=`${n[0]}-${n[1]}`;s.has(r)||(i.push(n),s.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),o=e.get(t.endNodeId),[s,i]=[n,o].sort(),h=`${s}->${i}`,d=c.get(h)??0;c.set(h,d+1);const l=`${s}->${i}::${d}`;r[l]={start:s,end:i},a.set(l,t.connectionName)}const h=`capacitypathing:${Ui({node_capacity_map:o,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[o,s]of Object.entries(t.solutionPaths)){const t=n.get(o);if(!t){console.warn(`Could not find real connection name for ${o}`);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=s.map(n=>{const o=e.get(n);if(!o)throw new Error(`Could not map cache node ID ${n} to real node ID for connection ${t}`);const s=this.constructorParams.nodeMap.get(o);if(!s)throw new Error(`Could not find node with ID ${o} in nodeMap for connection ${t}`);return s});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:o}=this.cacheToSolveSpaceTransform,s=new Map;for(const[t,e]of n)s.set(e,t);const i=new Map;for(const[t,e]of o)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 o=i.get(t);if(!o){console.warn(`Could not find cache space connection ID for ${t} when saving to cache.`);continue}const r=n.map(e=>{const n=s.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[o]=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 ki({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"})}},Gi=class extends y{getSolverName(){return"CapacityPathingMultiSectionSolver"}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=Ts(this.edges),this.colorMap=t.colorMap??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ts(this.edges),this.initialSolver=t.initialPathingSolver||new Li({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,o=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,o),this.nodeOptimizationAttemptCountMap.set(t.capacityMeshNodeId,0)}this.connectionsWithNodes=this.initialSolver.connectionsWithNodes,this.stats.startingScore=Bi({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 o of this.nodes){if(o._containsTarget)continue;const s=this.nodeOptimizationAttemptCountMap.get(o.capacityMeshNodeId),i=this.totalNodeCapacityMap.get(o.capacityMeshNodeId),r=Yi({usedCapacity:this.usedNodeCapacityMap.get(o.capacityMeshNodeId)??0,totalCapacity:i,layerCount:o.availableZ.length}),a=r/(s+1);s<this.currentSchedule.MAX_ATTEMPTS_PER_NODE&&a>t&&r>this.currentSchedule.MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE&&(t=a,e=r,n=o.capacityMeshNodeId)}return n}getOverallScore(){let t=0;for(const e of this.nodes){if(e._containsTarget)continue;const n=this.totalNodeCapacityMap.get(e.capacityMeshNodeId),o=Yi({usedCapacity:this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,totalCapacity:n,layerCount:e.availableZ.length});o>t&&(t=o)}return{highestNodePf:t,score:Bi({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:o,edges:s,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=>o.get(t)),l=s.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 o=t.path[e];if(a.has(o.capacityMeshNodeId)){n=o.capacityMeshNodeId;break}}e&&n&&u.push({connectionName:t.connection.name,startNodeId:e,endNodeId:n})}return{sectionConnectionTerminals:u,sectionNodes:d,sectionEdges:l,centerNodeId:e}})({centerNodeId:t,connectionsWithNodes:this.connectionsWithNodes,nodeMap:this.nodeMap,edges:this.edges,expansionDegrees:this.currentSchedule.MAX_EXPANSION_DEGREES,nodeEdgeMap:this.nodeEdgeMap});this.stats.scheduleScores[this.currentScheduleIndex].sectionAttempts++,this.currentSection=e,this.sectionSolver=new Zi({sectionNodes:this.currentSection.sectionNodes,sectionEdges:this.currentSection.sectionEdges,sectionConnectionTerminals:this.currentSection.sectionConnectionTerminals,colorMap:this.colorMap,centerNodeId:this.currentSection.centerNodeId,nodeEdgeMap:this.nodeEdgeMap,hyperParameters:{EXPANSION_DEGREES:this.currentSchedule.MAX_EXPANSION_DEGREES},cacheProvider:this.cacheProvider}),this.activeSubSolver=this.sectionSolver,this.nodeOptimizationAttemptCountMap.set(t,(this.nodeOptimizationAttemptCountMap.get(t)??0)+1)}if(this.sectionSolver.step(),(this.sectionSolver.failed||this.sectionSolver.solved)&&(this.sectionSolver.cacheHit?this.stats.cacheHits++:this.stats.cacheMisses++),this.sectionSolver.failed)return console.warn(`Section solver failed for node ${this.currentSection.centerNodeId}. Error: ${this.sectionSolver.error}`),this.stats.failedSectionSolvers++,this.stats.failedOptimizations++,this.sectionSolver=null,void(this.activeSubSolver=null);if(this.sectionSolver.solved){const t=this.sectionSolver.sectionConnectionTerminals,e=this.sectionSolver.sectionNodes,n=this.sectionSolver.centerNodeId;if(this.sectionSolver=null,this.activeSubSolver=null,!t)return void console.warn(`Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`);const o=new Set(e.map(t=>t.capacityMeshNodeId)),s=Bi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:o}),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(o.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)o.has(e.capacityMeshNodeId)&&i.set(e.capacityMeshNodeId,(i.get(e.capacityMeshNodeId)??0)+1);Bi({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:i,nodeMap:this.nodeMap,sectionNodeIds:o})>s?(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 o=e.path,s=n.path,i=o.findIndex(t=>t.capacityMeshNodeId===n.startNodeId),r=o.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=o.slice(0,a),d=o.slice(c+1);let l=s;if(s.length>0&&o[a]&&s[0].capacityMeshNodeId!==o[a].capacityMeshNodeId){if(s[s.length-1].capacityMeshNodeId!==o[a].capacityMeshNodeId){console.warn(`New section path for ${n.connectionName} doesn't align with original path boundaries. Skipping merge for this connection.`);continue}l=[...s].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,o=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,o)}}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 ki({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)"})}},Ji=class extends y{getSolverName(){return"StrawSolver"}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 o=n.center.x-n.width/2,s=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,o),c=Math.min(t.maxX,s),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+=We(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:o,topSurroundingCapacity:s,bottomSurroundingCapacity:i}=this.getSurroundingCapacities(t);if(1*(n+o)>s+i){const n=Math.floor(t.height/this.strawSize),o=t.height/n;for(let s=0;s<n;s++){const n=t.center.y-t.height/2+s*o+o/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${s}`,center:{x:t.center.x,y:n},width:t.width,height:o,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}else{const n=Math.floor(t.width/this.strawSize),o=t.width/n;for(let s=0;s<n;s++){const n=t.center.x-t.width/2+s*o+o/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${s}`,center:{x:n,y:t.center.y},width:o,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}},qi=.005,Ki=class extends y{getSolverName(){return"SingleLayerNodeMergerSolver"}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.availableZ.length>1?(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId)):e.push([n,n.width*n.height]);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 o=0;o<=e;o++)n.push(new dn(t.filter(t=>t.availableZ[0]===o)));for(const e of t){const t=[],o=n[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const n of o)n._containsTarget&&n._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!n._containsTarget||n._targetConnectionName!==e._targetConnectionName)||n.capacityMeshNodeId!==e.capacityMeshNodeId&&cn(e,n)&&t.push(n);e._adjacentNodeIds=t.map(t=>t.capacityMeshNodeId)}}getAdjacentSameLayerUnprocessedNodes(t){return this.getAdjacentSameLayerUnprocessedNodes2(t)}getAdjacentSameLayerUnprocessedNodes2(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),o=this.nodeMap.get(e);return n.width*n.height-o.width*o.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 o=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===o.length)return void this.nextBatchNodeIds.push(t);const s=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=o.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:o}=i[0],r=i.every(e=>e.width===t&&e.height===o);Math.abs(i.reduce((t,e)=>t+e.height,0)-e.height)<qi&&r&&(e.width+=t,e.center.x=e.center.x-t/2,s(i),n=!0)}const r=o.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:o}=r[0],i=r.every(e=>e.width===t&&e.height===o);Math.abs(r.reduce((t,e)=>t+e.height,0)-e.height)<qi&&i&&(e.width+=t,e.center.x=e.center.x+t/2,s(r),n=!0)}const a=o.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:o}=a[0],i=a.every(e=>e.width===t&&e.height===o);Math.abs(a.reduce((t,e)=>t+e.width,0)-e.width)<qi&&i&&(e.height+=o,e.center.y=e.center.y+o/2,s(a),n=!0)}const c=o.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:o}=c[0],i=c.every(e=>e.width===t&&e.height===o);Math.abs(c.reduce((t,e)=>t+e.width,0)-e.width)<qi&&i&&(e.height+=o,e.center.y=e.center.y-o/2,s(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:"Same Layer Node Merger"};for(const e of this.newNodes)t.rects.push(Oi(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let n;e&&(n=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const o of this.currentBatchNodeIds){const s=this.nodeMap.get(o);if(!this.absorbedNodeIds.has(o)&&s){const i=Oi(s,{rectMargin:.01});o===e?i.stroke="rgba(0, 255, 0, 0.8)":n?.some(t=>t.capacityMeshNodeId===o)?i.stroke="rgba(128, 0, 128, 0.8)":i.stroke="rgba(255, 165, 0, 0.8)",i.layer=`z${s.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=Oi(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}},Qi=class extends y{getSolverName(){return"DeadEndSolver"}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,o=n?this.adjacencyList.get(n):void 0;if(!n||!o)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));o.delete(t),this.removedNodeIds.add(t),this.adjacencyList.delete(t),1!==o.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]),o=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&o?.center){const s=Math.min(...n.availableZ),i=Math.min(...o.availableZ),r={x:n.center.x+s*n.width*.05,y:n.center.y-s*n.width*.05},a={x:o.center.x+i*o.width*.05,y:o.center.y-i*o.width*.05},c=Array.from(new Set([...n.availableZ,...o.availableZ])).sort();e.lines.push({layer:`z${c.join(",")}`,points:[r,a],strokeDash:n.availableZ.join(",")===o.availableZ.join(",")?void 0:"10 5",strokeColor:t.nodeIds.some(t=>this.removedNodeIds.has(t))?it("black",.9):void 0})}}return e}},tr=class extends rn{getSolverName(){return"NoOffBoardMultipleHighDensityRouteStitchSolver"}constructor(t){super(t),this.unsolvedRoutes=[];const e=new Map;for(const n of t.hdRoutes){const t=e.get(n.connectionName)||[];t.push(n),e.set(n.connectionName,t)}for(const[n,o]of e.entries()){const e=t.connections.find(t=>t.name===n);if(!e)continue;const s={...e.pointsToConnect[0],z:Be(Ge(e.pointsToConnect[0]),t.layerCount)},i={...e.pointsToConnect[1],z:Be(Ge(e.pointsToConnect[1]),t.layerCount)};this.unsolvedRoutes.push({connectionName:n,hdRoutes:o,start:s,end:i})}for(const n of t.connections)e.has(n.name)||this.unsolvedRoutes.push({connectionName:n.name,hdRoutes:[],start:{...n.pointsToConnect[0],z:Be(Ge(n.pointsToConnect[0]),t.layerCount)},end:{...n.pointsToConnect[1],z:Be(Ge(n.pointsToConnect[1]),t.layerCount)}})}};function er(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var nr=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,o=t.bounds.maxY-t.bounds.minY,s=Math.max(n,o),i=e.targetMinCapacity??.5;e.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getSolverName(){return"AutoroutingPipeline1_OriginalUnravel"}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=[er("netToPointPairsSolver",vn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),er("nodeSolver",mi,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),er("singleLayerNodeMerger",Ki,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),er("strawSolver",Ji,t=>[{nodes:t.singleLayerNodeMerger?.newNodes}],{onSolved:t=>{t.capacityNodes=t.strawSolver?.getResultNodes()}}),er("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),er("deadEndSolver",Qi,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)))}}),er("initialPathingSolver",Li,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),er("pathingOptimizer",Gi,t=>[{initialPathingSolver:t.initialPathingSolver,simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,cacheProvider:t.cacheProvider,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),er("edgeToPortSegmentSolver",fi,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.pathingOptimizer?.getCapacityPaths()||[],colorMap:t.colorMap}]),er("segmentToPointSolver",Pi,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),er("unravelMultiSectionSolver",Ai,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),er("highDensityRouteSolver",Ye,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),er("highDensityStitchSolver",tr,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),er("traceSimplificationSolver",_s,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}])];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(),o=this.singleLayerNodeMerger?.visualize(),s=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,o,s,i,r,a,c,h,d,l,u?g(x,u):null,p,m,this.solved?g(x,an(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 o=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,s=e.filter(t=>t.connectionName===n.name);for(let e=0;e<s.length;e++){const i=s[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??n.rootConnectionName??n.name,route:Ve(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},or=.1,sr=.1;function ir(t,e,n,o,s,i){return(s-t)*(o-e)-(i-e)*(n-t)}function rr(t,e,n,o,s,i){return Math.min(t,n)<=s&&s<=Math.max(t,n)&&Math.min(e,o)<=i&&i<=Math.max(e,o)}function ar(t,e,n,o,s,i,r,a){const c=ir(s,i,r,a,t,e),h=ir(s,i,r,a,n,o),d=ir(t,e,n,o,s,i),l=ir(t,e,n,o,r,a);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)||(!(0!==c||!rr(s,i,r,a,t,e))||(!(0!==h||!rr(s,i,r,a,n,o))||(!(0!==d||!rr(t,e,n,o,s,i))||!(0!==l||!rr(t,e,n,o,r,a)))))}function cr(t,e,n,o,s,i){const r=s-n,a=i-o,c=t-n,h=e-o,d=r*r+a*a;if(0===d){return{x:n,y:o,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=o+l*a,m=t-u,f=e-p;return{x:u,y:p,distSq:m*m+f*f}}var hr=class extends y{getSolverName(){return"SimpleHighDensitySolver"}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:o=.6,pushMargin:s=.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=o,this.numMovablePoints=i,this.pushMargin=s,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,o=t.center.y-t.height/2,s=t.center.y+t.height/2;this.currentNodeBounds={minX:e,maxX:n,minY:o,maxY:s};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],o=e[e.length-1],s=n.z,i=o.x-n.x,r=o.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*sr,y:n.y+h*sr,z:s,rootConnectionName:n.rootConnectionName,connectionName:t}),this.numMovablePoints>=2&&d.push({x:o.x-c*sr,y:o.y-h*sr,z:s,rootConnectionName:n.rootConnectionName,connectionName:t}),this.numMovablePoints>=3&&d.push({x:n.x+i/2,y:n.y+r/2,z:s,rootConnectionName:n.rootConnectionName,connectionName:t}),this.routesInProgress.push({connectionName:t,rootConnectionName:n.rootConnectionName,startPoint:{x:n.x,y:n.y,z:s},endPoint:{x:o.x,y:o.y,z:s},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 o=.3+this.pushMargin,s=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}),s.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<o&&(e.fx+=or*(o-r)),a<o&&(e.fx-=or*(o-a)),h<o&&(e.fy+=or*(o-h)),c<o&&(e.fy-=or*(o-c));for(const t of this.routesInProgress){if(t.rootConnectionName===i.rootConnectionName)continue;const r=s.get(t);for(let t=0;t<r.length-1;t++){const s=r[t],a=r[t+1],c=cr(i.x,i.y,s.x,s.y,a.x,a.y),h=Math.sqrt(c.distSq);if(h>0&&h<2*o){const t=i.x-c.x,o=i.y-c.y,r=.002/c.distSq,h=r*t,d=r*o;e.fx+=h,e.fy+=d;const l=s.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=s.get(e);let o=-1;for(let e=0;e<n.length;e++)if(n[e].movablePoint===t){o=e;break}if(-1===o)return!1;const r=[];if(o>0){const e=i(n[o-1]);r.push({ax:e.x,ay:e.y,bx:t.x,by:t.y})}if(o<n.length-1){const e=i(n[o+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=s.get(t);for(let t=0;t<n.length-1;t++){const e=i(n[t]),o=i(n[t+1]);for(const t of r)if(ar(t.ax,t.ay,t.bx,t.by,e.x,e.y,o.x,o.y))return!0}}return!1};for(const o of e){const e=n.get(o);o.forceX=e.fx,o.forceY=e.fy;const s=o.x,i=o.y;o.x+=e.fx,o.y+=e.fy,o.x=Math.max(t.minX,Math.min(t.maxX,o.x)),o.y=Math.max(t.minY,Math.min(t.maxY,o.y)),r(o)&&(o.x=s,o.y=i)}}_finalizeRoutesForCurrentNode(){for(const t of this.routesInProgress){const{connectionName:e,rootConnectionName:n,startPoint:o,endPoint:s,movablePoints:i}=t,r=[{x:o.x,y:o.y,z:o.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:s.x,y:s.y,z:s.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,o]of n)o.length<2||t.lines.push({points:o.map(t=>({x:t.x,y:t.y})),label:e,strokeColor:"gray",strokeWidth:this.traceWidth})}for(const e of this.routes){const n=Xe(e.route,e.connectionName,this.colorMap[e.connectionName]);for(const o of n)t.lines.push({points:o.points,label:o.connectionName,strokeColor:0===o.z?o.color:it(o.color,.75),layer:`z${o.z}`,strokeWidth:e.traceThickness,strokeDash:0!==o.z?"10, 5":void 0});const o=e.route;for(let e=0;e<o.length;e++){const n=o[e],s=0===e,i=e===o.length-1,r=!s&&!i;let a;a=s?"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:o,movablePoints:s,connectionName:i}=e,r=this.colorMap[i]??"gray",a=[{x:n.x,y:n.y}];1===s.length?a.push({x:s[0].x,y:s[0].y}):2===s.length?(a.push({x:s[0].x,y:s[0].y}),a.push({x:s[1].x,y:s[1].y})):3===s.length&&(a.push({x:s[0].x,y:s[0].y}),a.push({x:s[2].x,y:s[2].y}),a.push({x:s[1].x,y:s[1].y})),a.push({x:o.x,y:o.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<s.length;e++){const n=s[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 o=5;t.lines.push({points:[{x:n.x,y:n.y},{x:n.x+n.forceX*o,y:n.y+n.forceY*o}],strokeColor:"red",strokeWidth:.02,label:`F${e+1}`});const s=.05,i=n.x+n.forceX*o,r=n.y+n.forceY*o,a=Math.atan2(n.forceY,n.forceX);t.lines.push({points:[{x:i,y:r},{x:i-s*Math.cos(a-Math.PI/6),y:r-s*Math.sin(a-Math.PI/6)}],strokeColor:"red",strokeWidth:.02}),t.lines.push({points:[{x:i,y:r},{x:i-s*Math.cos(a+Math.PI/6),y:r-s*Math.sin(a+Math.PI/6)}],strokeColor:"purple",strokeWidth:.02})}}}t.points.push({x:o.x,y:o.y,label:"end",color:"blue"})}return t}};function dr(t){const{pos:e,segments:n,dir:o,keepoutRadius:s}=t;let i=1/0;const r=s/4,a={x:e.x-o.x*r,y:e.y-o.y*r},c={x:e.x+o.x*r,y:e.y+o.y*r};for(const t of n){const e=wt(a,c,t.start,t.end);i=Math.min(i,e)}return i}function lr(t,e,n,o){const s=ur(n,o,t),i=ur(n,o,e),r=ur(t,e,n),a=ur(t,e,o);if((s>0&&i<0||s<0&&i>0)&&(r>0&&a<0||r<0&&a>0))return!0;const c=1e-4;return!!(Math.abs(s)<c&&pr(n,o,t))||(!!(Math.abs(i)<c&&pr(n,o,e))||(!!(Math.abs(r)<c&&pr(t,e,n))||!!(Math.abs(a)<c&&pr(t,e,o))))}function ur(t,e,n){return(n.x-t.x)*(e.y-t.y)-(e.x-t.x)*(n.y-t.y)}function pr(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 mr(t,e,n){for(const o of n)if(lr(t,e,o.start,o.end))return!1;return!0}var fr=1e-4;function gr(t){const e=t.width/2,n=t.height/2,o=t.center.x,s=t.center.y,i={x:o-e,y:s+n},r={x:o+e,y:s+n},a={x:o-e,y:s-n},c={x:o+e,y:s-n};return[{start:i,end:r},{start:r,end:c},{start:c,end:a},{start:a,end:i}]}function yr(t,e,n=.1){const o=e.x-t.x,s=e.y-t.y,i=Math.sqrt(o*o+s*s);if(0===i)return[];const r=-(s/i),a=o/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 xr(t,e,n){const o=Math.hypot(t.start.x-e.x,t.start.y-e.y),s=Math.hypot(t.end.x-e.x,t.end.y-e.y);if(o<=n||s<=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 vr(t,e,n){if(!n||0===n.length)return!1;for(const o of n){const n=Math.abs(t.x-o.start.x)<fr&&Math.abs(t.y-o.start.y)<fr&&Math.abs(e.x-o.end.x)<fr&&Math.abs(e.y-o.end.y)<fr,s=Math.abs(t.x-o.end.x)<fr&&Math.abs(t.y-o.end.y)<fr&&Math.abs(e.x-o.start.x)<fr&&Math.abs(e.y-o.start.y)<fr;if(n||s)return!0}return!1}function Pr(t,e,n,o,s){const i=[];for(let r=0;r<t.length-1;r++){const a=t[r],c=t[r+1];vr(a,c,s)||xr({start:a,end:c},n,o+e)&&i.push(...yr(a,c,e))}return i}var Sr=1e-4;function Mr(t,e,n,o){const s=e.x-t.x,i=e.y-t.y,r=o.x-n.x,a=o.y-n.y,c=s*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*s)/c,p=1e-6;return l>p&&l<.999999&&u>p&&u<.999999?{x:t.x+l*s,y:t.y+l*i}:null}function br(t,e){if(!e||0===e.length)return!1;for(const n of e)if(Math.abs(t.x-n.start.x)<Sr&&Math.abs(t.y-n.start.y)<Sr||Math.abs(t.x-n.end.x)<Sr&&Math.abs(t.y-n.end.y)<Sr)return!0;return!1}function Nr(t,e,n,o){if(!o||0===o.length)return!1;for(let s=e;s<=n;s++)if(s>=0&&s<t.length&&br(t[s],o))return!0;return!1}var Ir=1e-4,Cr=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 ss("flatbush",e),this.boardOutlineRoutes=this.createBoardOutlineRoutes(),this.hdRouteSHI=new ds([...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 o=this.obstacleSHI.searchArea(t.x,t.y,.01,.01).filter(e=>e.zLayers?.includes(t.z));if(0===o.length)continue;const s=o[0];this.input.connMap.addConnections([[e,n,...s.offBoardConnectsTo??[],s.obstacleId,...s.connectedTo].filter(Boolean)])}}getSolverName(){return"TraceKeepoutSolver"}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 o of t.jumpers){let t=-1,s=1/0;for(let e=0;e<n.length-1;e++){const i=n[e],r=n[e+1],a=Math.sqrt((i.x-o.start.x)**2+(i.y-o.start.y)**2),c=Math.sqrt((r.x-o.end.x)**2+(r.y-o.end.y)**2),h=a+c,d=Math.sqrt((i.x-o.end.x)**2+(i.y-o.end.y)**2),l=Math.sqrt((r.x-o.start.x)**2+(r.y-o.start.y)**2),u=d+l,p=Math.min(h,u);(h<=u?a:d)<1&&(h<=u?c:l)<1&&p<s&&(s=p,t=e)}t>=0&&e.set(t,o)}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=Bt([...this.processedRoutes],this.currentScheduleIndex),this.smoothedCursorRoutes=[...this.unprocessedRoutes],this.processedRoutes=[],void(this.hdRouteSHI=new ds([...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:o,keepoutRadius:s}=t;if(0===o.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=dr({pos:e,segments:o,dir:h,keepoutRadius:s});if(u>=s)return null;for(let t=1;t<=20;t++){const n=t/20*s,i={x:e.x+d*n,y:e.y+l*n},r=dr({pos:i,segments:o,dir:h,keepoutRadius:s}),a={x:e.x-d*n,y:e.y-l*n},c=dr({pos:a,segments:o,dir:h,keepoutRadius:s}),u=r>=s&&mr(e,i,o),p=c>=s&&mr(e,a,o);if(u&&p)return r>=c?i:a;if(u)return i;if(p)return a}const p=s,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=dr({pos:i,segments:o,dir:h,keepoutRadius:s}),a=mr(e,i,o);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],o=m[t+1];if(n.clearance>=e.clearance&&n.clearance>=o.clearance){x=n;break}}let v=null;for(let t=y-1;t>0;t--){const e=m[t-1],n=m[t],o=m[t+1];if(n.clearance>=e.clearance&&n.clearance>=o.clearance){v=n;break}}let P=null,S=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],o=f[t+1];if(n.clearance>=e.clearance&&n.clearance>=o.clearance){P=n;break}}for(let t=e-1;t>0;t--){const e=f[t-1],n=f[t],o=f[t+1];if(n.clearance>=e.clearance&&n.clearance>=o.clearance){S=n;break}}}const M=[x,v,P,S,m.find(t=>0===t.index)].filter(t=>null!=t),b=new Set,N=M.filter(t=>{const e=`${t.pos.x.toFixed(6)},${t.pos.y.toFixed(6)}`;return!b.has(e)&&(b.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*s){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 o=this.recordedDrawPositions[this.recordedDrawPositions.length-1];if(o&&this.drawPosition){const t={x:o.x,y:o.y,z:o.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>Ir?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],o=t[this.currentTraceSegmentIndex+1],s=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=s<=i?n.start:n.end,a=s<=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:o.z,insideJumperPad:!0}),this.cursorPosition={x:a.x,y:a.y,z:o.z},this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0,"jumper"}const o=t[this.currentTraceSegmentIndex],s=t[this.currentTraceSegmentIndex+1],i=s.x-o.x,r=s.y-o.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:o.x+i*this.currentTraceSegmentT,y:o.y+r*this.currentTraceSegmentT,z:o.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,o=[],s=this.obstacleSHI.searchArea(t.x,t.y,n,n).filter(e=>e.zLayers?.includes(t.z));for(const n of s){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 s=!1;for(const t of n.connectedTo)if(this.input.connMap.areIdsConnected(e,t)){s=!0;break}s||o.push(...gr(n))}const i=this.hdRouteSHI.getConflictingRoutesNearPoint({x:t.x,y:t.y,z:t.z},n);for(const{conflictingRoute:s}of i){const i=s.rootConnectionName??s.connectionName;if(i===e)continue;if(this.input.connMap.areIdsConnected(e,i))continue;const r=s.traceThickness??.15;o.push(...Pr(s.route,r,{x:t.x,y:t.y},n,s.jumpers))}return o}positionHasCollision(t,e=0){const n=this.getCollidingSegments(t);for(const o of n)if(vt(t,o.start,o.end)<=this.currentKeepoutRadius+e)return!0;return!1}segmentIntersectsOtherRoutes(t,e){if(!this.currentTrace)return!1;const n=this.currentTrace.rootConnectionName??this.currentTrace.connectionName,o=[...this.unprocessedRoutes,...this.smoothedCursorRoutes,...this.processedRoutes];for(const s of o){if((s.rootConnectionName??s.connectionName)!==n)for(let n=0;n<s.route.length-1;n++){const o=s.route[n],i=s.route[n+1];if((o.z===t.z||i.z===t.z)&&((!o.insideJumperPad||!i.insideJumperPad)&&gt({x:t.x,y:t.y},{x:e.x,y:e.y},{x:o.x,y:o.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],o=!0;for(;o;){o=!1;for(let t=0;t<n.length-1&&!o;t++){const s=n[t],i=n[t+1];if(s.z===i.z)for(let r=t+2;r<n.length-1&&!o;r++){if(r===t+1)continue;const a=n[r],c=n[r+1];if(a.z!==c.z||s.z!==a.z)continue;const h=Mr(s,i,a,c);if(h){if(Nr(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:s.z});for(let t=r+1;t<n.length;t++)i.push(n[t]);n=i,o=!0}}}}return n}(this.simplifyRoute(this.recordedDrawPositions,this.currentTrace.jumpers),this.currentTrace.jumpers),o={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(o),this.hdRouteSHI.removeRoute(this.currentTrace.connectionName),this.hdRouteSHI.addRoute(o),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)<Ir&&Math.abs(t.y-n.start.y)<Ir||Math.abs(t.x-n.end.x)<Ir&&Math.abs(t.y-n.end.y)<Ir)return!0;return!1}simplifyRoute(t,e){if(t.length<=2)return t;const n=[t[0]];for(let o=1;o<t.length-1;o++){const s=n[n.length-1],i=t[o],r=t[o+1];if(this.isJumperEndpoint(i,e)){n.push(i);continue}if(i.z!==s.z||i.z!==r.z){n.push(i);continue}const a=i.x-s.x,c=i.y-s.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 o;o=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 s=this.input.srj.layerCount??2;for(let e=0;e<o.length;e++){const n=o[e],i=o[(e+1)%o.length];for(let o=0;o<s;o++)t.push({connectionName:`__board_outline___${e}_z${o}`,traceThickness:.01,viaDiameter:0,route:[{x:n.x,y:n.y,z:o},{x:i.x,y:i.y,z:o}],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 o=e.route[n],s=e.route[n+1];o.z===s.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:s.x,y:s.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",o=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:o,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 o=e.zLayers?.includes(0),s=e.zLayers?.includes(1);o&&s?n="rgba(128, 0, 128, 0.2)":o?n="rgba(255, 0, 0, 0.2)":s&&(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 o;o=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<o.length;e++){const n=o[e],s=o[(e+1)%o.length];t.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.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",o=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 s=e.route[n],i=e.route[n+1],r=Math.abs(s.x-t.start.x)<Ir&&Math.abs(s.y-t.start.y)<Ir&&Math.abs(i.x-t.end.x)<Ir&&Math.abs(i.y-t.end.y)<Ir,a=Math.abs(s.x-t.end.x)<Ir&&Math.abs(s.y-t.end.y)<Ir&&Math.abs(i.x-t.start.x)<Ir&&Math.abs(i.y-t.start.y)<Ir;if(r||a){o.add(n);break}}for(let n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];o.has(n)?t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:"rgba(128, 128, 128, 0.6)",strokeDash:"2 2",label:`${e.connectionName} (jumper segment - fixed)`}):s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:0===s.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const o=Qe(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...o.rects??[]),t.lines.push(...o.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],o=this.recordedDrawPositions[e+1];t.lines.push({points:[{x:n.x,y:n.y},{x:o.x,y:o.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,o=Math.sqrt(e*e+n*n),s=o>1e-4?{x:e/o,y:n/o}:{x:1,y:0},i=this.currentKeepoutRadius/4,r={x:this.cursorPosition.x-s.x*i,y:this.cursorPosition.y-s.y*i},a={x:this.cursorPosition.x+s.x*i,y:this.cursorPosition.y+s.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 o=e.route[n],s=e.route[n+1];o.z===s.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:s.x,y:s.y}],strokeColor:"gray"})}return t}getRedrawnHdRoutes(){return this.redrawnHdRoutes}},_r=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=>Be(t,this.input.srj.layerCount))}),this.offBoardConnMap=new on({}),this.offBoardConnMap.addConnections(this.unprocessedObstacles.filter(t=>t.offBoardConnectsTo?.length).map(t=>[t.obstacleId,...t.offBoardConnectsTo??[]])),this.nodeTree=new dn(this.input.capacityMeshNodes)}getSolverName(){return"RelateNodesToOffBoardConnectionsSolver"}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),o=n.map(t=>t.capacityMeshNodeId),s=this.nodesInNet.get(e)??[],i=[...s.map(t=>t.capacityMeshNodeId),...o];for(const t of s)t._offBoardConnectedCapacityMeshNodeIds=i;for(const t of n)t._offBoardConnectedCapacityMeshNodeIds=i,t._offBoardConnectionId=e;this.nodesInNet.set(e,[...s,...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 o of n)t.rects.push({center:o.center,width:o.width,height:o.height,fill:rt(e,.2),label:`OffBoardConn: ${e}`});for(const o of n)for(const s of n)o.capacityMeshNodeId!==s.capacityMeshNodeId&&t.lines.push({points:[o.center,s.center],strokeColor:rt(e,1)})}return t}},Tr=({connMap:t,connectionsWithResults:e,inputNodes:n,obstacles:o})=>{const s=o.filter(t=>t.offBoardConnectsTo?.length);if(0===s.length)return;const i=new $e({});i.addConnections(s.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,o=new Set;for(const t of n.path){const e=r.get(t.currentNodeId);if(e?._offBoardConnectionId&&o.add(e._offBoardConnectionId),t.throughNodeId){const e=r.get(t.throughNodeId);e?._offBoardConnectionId&&o.add(e._offBoardConnectionId)}}for(const n of o){const o=i.getIdsConnectedToNet(n);o?.length&&t.addConnections([[e,...o]])}}};function Er(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var Rr=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,o=t.bounds.maxY-t.bounds.minY,s=Math.max(n,o),i=e.targetMinCapacity??.5;e.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getSolverName(){return"AssignableAutoroutingPipeline2"}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=[Er("netToPointPairsSolver",xn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),Er("nodeSolver",es,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Er("relateNodesToOffBoardConnections",_r,t=>[{capacityMeshNodes:t.capacityNodes,srj:t.srj}],{onSolved:t=>{t.capacityNodes=t.relateNodesToOffBoardConnections?.getOutput().capacityNodes}}),Er("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Er("availableSegmentPointSolver",Es,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),Er("portPointPathingSolver",Ks,t=>{const e=t.capacityNodes.map(t=>({capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:[],availableZ:t.availableZ,_containsTarget:t._containsTarget,_containsObstacle:t._containsObstacle,_offBoardConnectionId:t._offBoardConnectionId,_offBoardConnectedCapacityMeshNodeIds:t._offBoardConnectedCapacityMeshNodeIds})),n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),o=t.availableSegmentPointSolver;for(const t of o.sharedEdgeSegments)for(const e of t.portPoints){const[o,s]=e.nodeIds,i={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[o,s],distToCentermostPortOnZ:e.distToCentermostPortOnZ,connectsToOffBoardNode:t.nodeIds.some(t=>n.get(t)?._offBoardConnectionId)},r=n.get(o);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&&Tr({connMap:t.connMap,connectionsWithResults:e.connectionsWithResults,inputNodes:e.inputNodes,obstacles:t.srj.obstacles})}}),Er("multiSectionPortPointOptimizer",Js,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}]}),Er("highDensitySolver",hr,t=>[{nodePortPoints:t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth,connMap:t.connMap}]),Er("highDensityStitchSolver",rn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensitySolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),Er("traceSimplificationSolver",_s,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}]),Er("traceKeepoutSolver",Cr,t=>[{hdRoutes:t.traceSimplificationSolver?.simplifiedHdRoutes??[],obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,srj:t.srj}]),Er("traceWidthSolver",ci,t=>[{hdRoutes:t.traceKeepoutSolver?.redrawnHdRoutes??[],connection:t.srj.connections,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,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(),o=this.singleLayerNodeMerger?.visualize(),s=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,P=[];if(P.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]}),P.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const S={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:["obstacle",t.offBoardConnectsTo?`offboardConnections: ${t.offBoardConnectsTo?.join(", ")}`:"",t.layers?.join(", ")].filter(Boolean).join("\n")}))],lines:P},M=[S,t,e,n,o,s,i,r,a,c,h,d,l?g(S,l):null,u?g(S,u):null,p?g(S,p):null,m,f,y,x,this.solved?g(S,an(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...M)}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 o=t[n];if(e.push({points:o.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[o.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,o]of this.srj.obstacles.entries()){if(!o.offBoardConnectsTo?.length)continue;const s=o.obstacleId??`__obs${n}`;o.obstacleId=s;const i=this.connMap.getNetConnectedToId(s);if(!i)continue;const r=this.connMap.getIdsConnectedToNet(i).find(t=>e.has(t));r&&(t[s]=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 o=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,s=e.filter(t=>t.connectionName===n.name);for(let e=0;e<s.length;e++){const i=s[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??n.rootConnectionName??n.name,route:Ve(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},wr=t=>({x:(t.minX+t.maxX)/2,y:(t.minY+t.maxY)/2}),Ar={padWidth:.8,outerPadHeight:.5,innerPadHeight:.4,leftPadCenterX:-.9,rightPadCenterX:.9,row1CenterY:-1.2,row2CenterY:-.4,row3CenterY:.4,row4CenterY:1.2},Or=t=>{let e=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,o=Number.POSITIVE_INFINITY,s=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),o=Math.min(o,t.minY),s=Math.max(s,t.maxY)}return{minX:e,maxX:n,minY:o,maxY:s}};function zr(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 Dr(t){return void 0===t}function Lr(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}function Fr(...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,o,...s]=t;return Fr(e(n,o),...s)}}}function Xr(...t){return Fr(...t)}var{cos:Yr,sin:$r,PI:Br}=Math;function kr(t,e,n){const o=Yr(t),s=$r(t),i={a:o,c:-s,e:0,b:s,d:o,f:0};return Dr(e)||Dr(n)?i:Fr([Lr(e,n),i,Lr(-e,-n)])}var{tan:jr}=Math,Wr=(t,e)=>{const n=t.regions.map(t=>{const{bounds:n,center:o,...s}=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=>zr(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=zr(e,o);return{...t,ports:[],d:{...s,bounds:r,center:a}}}),o=new Map;for(let e=0;e<t.regions.length;e++)o.set(t.regions[e],n[e]);const s=t.ports.map(t=>{const n=zr(e,t.d),s=o.get(t.region1),i=o.get(t.region2),r={...t,region1:s,region2:i,d:n};return s.ports.push(r),i.ports.push(r),r}),i=t.jumperLocations?.map(t=>{const n=zr(e,t.center),s=t.padRegions.map(t=>o.get(t)),i=zr(e,{x:1,y:0}),r=zr(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:s}});return{regions:n,ports:s,...i&&{jumperLocations:i}}},Hr={padToPad:1.65,padLength:.8,padWidth:.95},Ur=({cols:t,rows:e,marginX:n,marginY:o,innerColChannelPointCount:s=1,innerRowChannelPointCount:i=1,outerPaddingX:r=.5,outerPaddingY:a=.5,outerChannelXPoints:c,outerChannelYPoints:h,orientation:d="vertical"})=>{const l=c??Math.max(1,Math.floor(r/.4)),u=(h??Math.max(1,Math.floor(a/.4)),[]),p=[],{padToPad:m,padLength:f,padWidth:g}=Hr,y=f/2,x=g/2,v=m+f+n,P=g+o,S=[],M=(t,e,n,o)=>({regionId:t,ports:[],d:{bounds:e,center:wr(e),isPad:n,isThroughJumper:o}}),b=(t,e,n)=>{const o=e.d.bounds,s=n.d.bounds;let i,r;Math.abs(o.maxX-s.minX)<.001?(i=o.maxX,r=(Math.max(o.minY,s.minY)+Math.min(o.maxY,s.maxY))/2):Math.abs(o.minX-s.maxX)<.001?(i=o.minX,r=(Math.max(o.minY,s.minY)+Math.min(o.maxY,s.maxY))/2):Math.abs(o.maxY-s.minY)<.001?(i=(Math.max(o.minX,s.minX)+Math.min(o.maxX,s.maxX))/2,r=o.maxY):(i=(Math.max(o.minX,s.minX)+Math.min(o.maxX,s.maxX))/2,r=o.minY);const a={portId:t,region1:e,region2:n,d:{x:i,y:r}};return e.ports.push(a),n.ports.push(a),a},N=(t,e,n,o)=>{if(o<=0)return[];if(1===o)return[b(t,e,n)];const s=e.d.bounds,i=n.d.bounds,r=[];let a,c,h,d;Math.abs(s.maxX-i.minX)<.001?(a=!0,c=s.maxX,h=Math.max(s.minY,i.minY),d=Math.min(s.maxY,i.maxY)):Math.abs(s.minX-i.maxX)<.001?(a=!0,c=s.minX,h=Math.max(s.minY,i.minY),d=Math.min(s.maxY,i.maxY)):Math.abs(s.maxY-i.minY)<.001?(a=!1,c=s.maxY,h=Math.max(s.minX,i.minX),d=Math.min(s.maxX,i.maxX)):(a=!1,c=s.minY,h=Math.max(s.minX,i.minX),d=Math.min(s.maxX,i.maxX));for(let s=0;s<o;s++){const i=h+(s+.5)/o*(d-h),l={portId:`${t}:${s}`,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++){S[n]=[];for(let c=0;c<t;c++){const h=`cell_${n}_${c}`,d=c*v,f=-n*P,g=d-m/2,I=d+m/2,C={minX:g-y,maxX:g+y,minY:f-x,maxY:f+x},_={minX:I-y,maxX:I+y,minY:f-x,maxY:f+x},T={minX:C.maxX,maxX:_.minX,minY:f-x,maxY:f+x},E=.3,R={minX:g,maxX:I,minY:f-E/2,maxY:f+E/2},w=C.minX,A=_.maxX,O=C.minY,z=C.maxY,D=M(`${h}:leftPad`,C,!0),L=M(`${h}:rightPad`,_,!0),F=M(`${h}:underjumper`,T,!1),X=M(`${h}:throughjumper`,R,!1,!0);u.push(D,L,F,X);const Y=0===c,$=n===e-1,B=c===t-1;let k;if(B)k=A+r;else{k=(c+1)*v-m/2-y}let j=null;0===n&&(j=M(`${h}:T`,{minX:Y?w-r:w,maxX:k,minY:z,maxY:z+a},!1),u.push(j));let W=null;W=M(`${h}:B`,{minX:Y?w-r:w,maxX:k,minY:O-($?a:o),maxY:O},!1),u.push(W);let H=null;Y&&(H=M(`${h}:L`,{minX:w-r,maxX:w,minY:O,maxY:z},!1),u.push(H));const U=M(`${h}:R`,{minX:A,maxX:k,minY:O,maxY:z},!1);u.push(U),S[n][c]={leftPad:D,rightPad:L,underjumper:F,throughjumper:X,top:j,bottom:W,left:H,right:U},j&&(H&&p.push(...N(`${h}:T-L`,j,H,l)),p.push(...N(`${h}:T-R`,j,U,B?l:s)),p.push(b(`${h}:T-UJ`,j,F))),W&&(H&&p.push(...N(`${h}:B-L`,W,H,l)),p.push(...N(`${h}:B-R`,W,U,B?l:s)),p.push(b(`${h}:B-UJ`,W,F))),H&&p.push(b(`${h}:L-LP`,H,D)),p.push(b(`${h}:R-RP`,U,L));const V={portId:`${h}:TJ-LP`,region1:X,region2:D,d:{x:g,y:f}};X.ports.push(V),D.ports.push(V),p.push(V);const Z={portId:`${h}:TJ-RP`,region1:X,region2:L,d:{x:I,y:f}};if(X.ports.push(Z),L.ports.push(Z),p.push(Z),c>0){const t=S[n][c-1];p.push(b(`cell_${n}_${c-1}->cell_${n}_${c}:R-LP`,t.right,D)),j&&t.top&&p.push(...N(`cell_${n}_${c-1}->cell_${n}_${c}:T-T`,t.top,j,i)),W&&t.bottom&&p.push(...N(`cell_${n}_${c-1}->cell_${n}_${c}:B-B`,t.bottom,W,i))}if(n>0){const t=S[n-1][c];H&&p.push(...N(`cell_${n-1}_${c}->cell_${n}_${c}:B-L`,t.bottom,H,l)),p.push(b(`cell_${n-1}_${c}->cell_${n}_${c}:B-UJ`,t.bottom,F)),p.push(...N(`cell_${n-1}_${c}->cell_${n}_${c}:B-R`,t.bottom,U,B?l:s))}}}let I={regions:u,ports:p};if("horizontal"===d){const t=Or(I.regions),e=wr(t),n=Xr(Lr(e.x,e.y),kr(-Math.PI/2),Lr(-e.x,-e.y));I=Wr(I,n)}return I},Vr=(t,e,n,o)=>{const s={portId:t,region1:e,region2:n,d:{x:o.x,y:o.y}};return e.ports.push(s),n.ports.push(s),s},Zr=(t,e,n)=>{const o=.2;return{regionId:t,ports:[],d:{bounds:{minX:e-o,maxX:e+o,minY:n-o,maxY:n+o},center:{x:e,y:n},isPad:!1,isConnectionRegion:!0}}},Gr=(t,e,n,o)=>{for(const o of n){if(o.d.isPad||o.d.isThroughJumper)continue;const n=o.d.bounds;if(Math.abs(t-n.minX)<.01&&e>=n.minY&&e<=n.maxY)return{region:o,portPosition:{x:n.minX,y:e}};if(Math.abs(t-n.maxX)<.01&&e>=n.minY&&e<=n.maxY)return{region:o,portPosition:{x:n.maxX,y:e}};if(Math.abs(e-n.minY)<.01&&t>=n.minX&&t<=n.maxX)return{region:o,portPosition:{x:t,y:n.minY}};if(Math.abs(e-n.maxY)<.01&&t>=n.minX&&t<=n.maxX)return{region:o,portPosition:{x:t,y:n.maxY}}}let s=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-o.minX)<.01||Math.abs(n.maxX-o.maxX)<.01||Math.abs(n.minY-o.minY)<.01||Math.abs(n.maxY-o.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,s=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 s?{region:s,portPosition:r}:null},Jr=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),o=this._rightChildIndex(e);let s=e;if(t<n&&this.heap[t].f<this.heap[s].f&&(s=t),o<n&&this.heap[o].f<this.heap[s].f&&(s=o),s===e)break;this._swap(e,s),e=s}}_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}},qr=class extends _n{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,...o}=e;n.set(e.regionId,{...o,ports:[],assignments:void 0})}for(const o of t.ports){const t=n.get(o.region1Id??o.region1?.regionId),s=n.get(o.region2Id??o.region2?.regionId),i={portId:o.portId,region1:t,region2:s,d:o.d};e.set(o.portId,i),t.ports.push(i),s.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 o of t)"startRegionId"in o?n.push({connectionId:o.connectionId,mutuallyConnectedNetworkId:o.connectionId,startRegion:e.regions.find(t=>t.regionId===o.startRegionId),endRegion:e.regions.find(t=>t.regionId===o.endRegionId)}):n.push(o);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 Jr,this.beginNewConnection()}getSolverName(){return"HyperGraphSolver"}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}computeRoutesToRip(t){const e=this.computeCrossingRoutes(t),n=this.computePortOverlapRoutes(t);return new Set([...e,...n])}computePortOverlapRoutes(t){const e=new Set;for(const n of t.path)n.port.assignment&&n.port.assignment.connection.mutuallyConnectedNetworkId!==t.connection.mutuallyConnectedNetworkId&&e.add(n.port.assignment.solvedRoute);return e}computeCrossingRoutes(t){const e=new Set;for(const n of t.path){if(!n.lastPort||!n.lastRegion)continue;const t=this.getRipsRequiredForPortUsage(n.lastRegion,n.lastPort,n.port);for(const n of t)e.add(n.solvedRoute)}return e}getNextCandidates(t){const e=t.nextRegion,n=t.port,o={};for(const s of e.ports){if(s===t.port)continue;const i=s.assignment&&s.assignment.connection.mutuallyConnectedNetworkId!==this.currentConnection.mutuallyConnectedNetworkId,r={port:s,hops:t.hops+1,parent:t,lastRegion:e,nextRegion:s.region1===e?s.region2:s.region1,lastPort:n,ripRequired:i};!this.rippingEnabled&&r.ripRequired||(o[r.nextRegion.regionId]??=[],o[r.nextRegion.regionId].push(r))}const s=[];for(const t in o){const e=o[t];s.push(...this.selectCandidatesForEnteringRegion(e))}for(const t of s)t.g=this.computeG(t),t.h=this.computeH(t),t.f=t.g+t.h*this.greedyMultiplier;return s}processSolvedRoute(t){const e={path:[],connection:this.currentConnection,requiredRip:!1};let n=t,o=!1;for(;n;)o||=!!n.ripRequired,e.path.unshift(n),n=n.parent;o&&(e.requiredRip=!0);const s=this.computeRoutesToRip(e);if(s.size>0){e.requiredRip=!0;for(const t of s)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 Jr,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)}},Kr=(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 Qr(t,e,n,o,s){const i=n-e,r=s-o,a=1e-6;if(Math.abs(t.y-s)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(s-t.y);if(Math.abs(t.y-o)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-o);const c=Math.abs(t.y-s),h=Math.abs(t.x-n),d=Math.abs(t.y-o),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,s-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-o))}function ta(t,e,n=1e-6){return Math.abs(t-e)<n}function ea(t,e){const[n,o]=t[0]<t[1]?t:[t[1],t[0]],[s,i]=e[0]<e[1]?e:[e[1],e[0]];return!(ta(n,s)||ta(n,i)||ta(o,s)||ta(o,i))&&(n<s&&s<o&&o<i||s<n&&n<i&&i<o)}var na=.034685181009478865,oa=0,sa=4.072520483177124,ia=0,ra=35.38577539020022,aa=.5518001238069296,ca=class extends qr{getSolverName(){return"JumperGraphSolver"}UNIT_OF_COST="hops";portUsagePenalty=na;portUsagePenaltySq=oa;crossingPenalty=sa;crossingPenaltySq=ia;ripCost=ra;baseMaxIterations=4e3;additionalMaxIterationsPerConnection=2e3;additionalMaxIterationsPerCrossing=2e3;constructor(t){super({greedyMultiplier:aa,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;const e=function(t,e){if(e.length<2)return 0;let n=1/0,o=-1/0,s=1/0,i=-1/0;for(const e of t.regions){const t=e;t.d?.bounds?(n=Math.min(n,t.d.bounds.minX),o=Math.max(o,t.d.bounds.maxX),s=Math.min(s,t.d.bounds.minY),i=Math.max(i,t.d.bounds.maxY)):t.d?.center&&(n=Math.min(n,t.d.center.x),o=Math.max(o,t.d.center.x),s=Math.min(s,t.d.center.y),i=Math.max(i,t.d.center.y))}const r=new Map;for(const e of t.regions){const t=e;t.d?.center&&r.set(e.regionId,t.d.center)}const a=[];for(const t of e){let e,c;if("startRegion"in t&&t.startRegion){const n=t.startRegion,o=t.endRegion;e=n.d?.center,c=o.d?.center}else"startRegionId"in t&&(e=r.get(t.startRegionId),c=r.get(t.endRegionId));if(!e||!c)continue;const h=Qr(e,n,o,s,i),d=Qr(c,n,o,s,i);a.push([h,d])}let c=0;for(let t=0;t<a.length;t++)for(let e=t+1;e<a.length;e++)ea(a[t],a[e])&&c++;return c}(this.graph,t.inputConnections);this.MAX_ITERATIONS=this.baseMaxIterations+t.inputConnections.length*this.additionalMaxIterationsPerConnection+e*this.additionalMaxIterationsPerCrossing,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:o}=n.shift();for(const s of e.ports){const i=s.region1===e?s.region2:s.region1;t.has(i.regionId)||(t.set(i.regionId,o+1),n.push({region:i,distance:o+1}))}}for(const n of this.graph.ports){n.distanceToEndMap||(n.distanceToEndMap={});const o=t.get(n.region1.regionId)??1/0,s=t.get(n.region2.regionId)??1/0;n.distanceToEndMap[e.regionId]=Math.min(o,s)}}}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 o=function(t,e,n){const{minX:o,maxX:s,minY:i,maxY:r}=t.d.bounds,a=[Qr(e.d,o,s,i,r),Qr(n.d,o,s,i,r)];let c=0;const h=t.assignments??[];for(const t of h)ea(a,[Qr(t.regionPort1.d,o,s,i,r),Qr(t.regionPort2.d,o,s,i,r)])&&c++;return c}(t,e,n);return o*this.crossingPenalty+o*this.crossingPenaltySq}getRipsRequiredForPortUsage(t,e,n){const o=function(t,e,n){const{minX:o,maxX:s,minY:i,maxY:r}=t.d.bounds,a=[Qr(e.d,o,s,i,r),Qr(n.d,o,s,i,r)],c=[],h=t.assignments??[];for(const t of h)ea(a,[Qr(t.regionPort1.d,o,s,i,r),Qr(t.regionPort2.d,o,s,i,r)])&&c.push(t);return c}(t,e,n);return o.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:[],polygons:[],coordinateSystem:"cartesian"};for(const e of t.regions){const{bounds:t,isPad:o,isThroughJumper:s,isConnectionRegion:i,polygon:r}=e.d,a=(t.minX+t.maxX)/2,c=(t.minY+t.maxY)/2,h=t.maxX-t.minX,d=t.maxY-t.minY;let l;if(l=i?"rgba(255, 100, 255, 0.6)":s?"rgba(100, 200, 100, 0.5)":o?"rgba(255, 200, 100, 0.5)":"rgba(200, 200, 255, 0.1)",r&&r.length>=3){const t=r;n.polygons.push({points:t,fill:l,stroke:"rgba(128, 128, 128, 0.5)",strokeWidth:.03})}else n.rects.push({center:{x:a,y:c},width:h-.1,height:d-.1,fill:l})}if(!e?.hidePortPoints)for(const e of t.ports){const t=e.region1.regionId.split(":").pop()??e.region1.regionId,o=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}-${o}`})}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},o={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},o],strokeColor:"rgba(100, 100, 100, 0.3)"})}if(e?.connections&&!e?.hideConnectionLines)for(const t of e.connections){const e=t.startRegion,o=t.endRegion,s={x:(e.d.bounds.minX+e.d.bounds.maxX)/2,y:(e.d.bounds.minY+e.d.bounds.maxY)/2},i={x:(o.d.bounds.minX+o.d.bounds.maxX)/2,y:(o.d.bounds.minY+o.d.bounds.maxY)/2},r=(s.x+i.x)/2,a=(s.y+i.y)/2;n.lines.push({points:[s,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=Kr(t.currentConnection.connectionId),o=t.currentConnection.startRegion,s=t.currentConnection.endRegion,i={x:(o.d.bounds.minX+o.d.bounds.maxX)/2,y:(o.d.bounds.minY+o.d.bounds.maxY)/2},r={x:(s.d.bounds.minX+s.d.bounds.maxX)/2,y:(s.d.bounds.minY+s.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=Kr(n.connection.connectionId),o=[];for(const t of n.path){const e=t.port;o.push({x:e.d.x,y:e.d.y})}o.length>0&&e.lines.push({points:o,strokeColor:t})}const n=t.candidateQueue.peekMany(10);for(let t=0;t<n.length;t++){const o=n[t],s=o.port,i=0===t;e.points.push({x:s.d.x,y:s.d.y,color:i?"green":"rgba(128, 128, 128, 0.25)",label:[o.port.portId,`g: ${o.g.toFixed(2)}`,`h: ${o.h.toFixed(2)}`,`f: ${o.f.toFixed(2)}`].join("\n")})}const o=n[0];if(!t.solved&&o&&t.currentConnection){const n=Kr(t.currentConnection.connectionId),s=[];let i=o;for(;i;){const t=i.port;s.unshift({x:t.d.x,y:t.d.y}),i=i.parent}s.length>1&&e.lines.push({points:s,strokeColor:n})}return e})(this)}},ha=Object.create,da=Object.defineProperty,la=Object.getOwnPropertyDescriptor,ua=Object.getOwnPropertyNames,pa=Object.getPrototypeOf,ma=Object.prototype.hasOwnProperty,fa=(t,e)=>function(){return e||(0,t[ua(t)[0]])((e={exports:{}}).exports,e),e.exports},ga=(t,e,n)=>(n=null!=t?ha(pa(t)):{},((t,e,n,o)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let s of ua(e))ma.call(t,s)||s===n||da(t,s,{get:()=>e[s],enumerable:!(o=la(e,s))||o.enumerable});return t})(!e&&t&&t.__esModule?n:da(n,"default",{value:t,enumerable:!0}),t)),ya=fa({"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)}}}),xa=fa({"node_modules/kind-of/index.js"(t,e){var n=ya(),o=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=o.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"}}}),va=fa({"node_modules/rename-keys/index.js"(t,e){!function(){function t(t,e){if("function"!=typeof e)return t;var n={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&(n[e(o,t[o])||o]=t[o]);return n}void 0!==e&&e.exports?e.exports=t:"function"==typeof define&&define.amd?define([],function(){return t}):window.rename=t}()}}),Pa=fa({"node_modules/deep-rename-keys/index.js"(t,e){var n=xa(),o=va();e.exports=function t(e,s){var i=n(e);if("object"!==i&&"array"!==i)throw new Error("expected an object");var r=[];for(var a in"object"===i&&(e=o(e,s),r={}),e)if(e.hasOwnProperty(a)){var c=e[a];"object"===n(c)||"array"===n(c)?r[a]=t(c,s):r[a]=c}return r}}}),Sa=fa({"node_modules/eventemitter3/index.js"(t,e){var n=Object.prototype.hasOwnProperty,o="~";function s(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new s,this._eventsCount=0}Object.create&&(s.prototype=Object.create(null),(new s).__proto__||(o=!1)),r.prototype.eventNames=function(){var t,e,s=[];if(0===this._eventsCount)return s;for(e in t=this._events)n.call(t,e)&&s.push(o?e.slice(1):e);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(t)):s},r.prototype.listeners=function(t,e){var n=o?o+t:t,s=this._events[n];if(e)return!!s;if(!s)return[];if(s.fn)return[s.fn];for(var i=0,r=s.length,a=new Array(r);i<r;i++)a[i]=s[i].fn;return a},r.prototype.emit=function(t,e,n,s,i,r){var a=o?o+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,s),!0;case 5:return d.fn.call(d.context,e,n,s,i),!0;case 6:return d.fn.call(d.context,e,n,s,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,s);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 s=new i(e,n||this),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.once=function(t,e,n){var s=new i(e,n||this,!0),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=o?o+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new s: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 s: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 s:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=o?o+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new s:delete this._events[e])):(this._events=new s,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=o,r.EventEmitter=r,void 0!==e&&(e.exports=r)}}),Ma=fa({"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 o=Sa(),s=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 o,v=i.data,P="",S="",M="",b="",N="",I="",C=function(e,n){if("?"!==S[0]&&"!"!==S[0]){var o={type:e,value:n};t.debug&&console.log("emit:",o),x.emit("data",o)}};x.stateMachine=(n(y={},i.data,(n(e={},r.lt,function(){P.trim()&&C(a.text,P),S="",N=!1,v=i.tagBegin}),n(e,r.char,function(t){P+=t}),e)),n(y,i.cdata,n({},r.char,function(t){"]]>"===(P+=t).substr(-3)&&(C(a.text,P.slice(0,-3)),P="",v=i.data)})),n(y,i.tagBegin,(n(h={},r.space,s),n(h,r.char,function(t){S=t,v=i.tagName}),n(h,r.slash,function(){S="",N=!0}),h)),n(y,i.tagName,(n(d={},r.space,function(){N?v=i.tagEnd:(v=i.attributeNameStart,C(a.openTag,S))}),n(d,r.gt,function(){C(N?a.closeTag:a.openTag,S),P="",v=i.data}),n(d,r.slash,function(){v=i.tagEnd,C(a.openTag,S)}),n(d,r.char,function(t){"![CDATA["===(S+=t)&&(v=i.cdata,P="",S="")}),d)),n(y,i.tagEnd,(n(l={},r.gt,function(){C(a.closeTag,S),P="",v=i.data}),n(l,r.char,s),l)),n(y,i.attributeNameStart,(n(u={},r.char,function(t){M=t,v=i.attributeName}),n(u,r.gt,function(){P="",v=i.data}),n(u,r.space,s),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,M),v=i.attributeValueBegin}),n(p,r.gt,function(){b="",C(a.attributeName,M),C(a.attributeValue,b),P="",v=i.data}),n(p,r.slash,function(){N=!0,b="",C(a.attributeName,M),C(a.attributeValue,b),v=i.tagEnd}),n(p,r.char,function(t){M+=t}),p)),n(y,i.attributeNameEnd,(n(m={},r.space,s),n(m,r.equal,function(){C(a.attributeName,M),v=i.attributeValueBegin}),n(m,r.gt,function(){b="",C(a.attributeName,M),C(a.attributeValue,b),P="",v=i.data}),n(m,r.char,function(t){b="",C(a.attributeName,M),C(a.attributeValue,b),M=t,v=i.attributeName}),m)),n(y,i.attributeValueBegin,(n(f={},r.space,s),n(f,r.quote,function(t){I=t,b="",v=i.attributeValue}),n(f,r.gt,function(){C(a.attributeValue,b=""),P="",v=i.data}),n(f,r.char,function(t){I="",b=t,v=i.attributeValue}),f)),n(y,i.attributeValue,(n(g={},r.space,function(t){I?b+=t:(C(a.attributeValue,b),v=i.attributeNameStart)}),n(g,r.quote,function(t){I===t?(C(a.attributeValue,b),v=i.attributeNameStart):b+=t}),n(g,r.gt,function(t){I?b+=t:(C(a.attributeValue,b),P="",v=i.data)}),n(g,r.slash,function(t){I?b+=t:(C(a.attributeValue,b),N=!0,v=i.tagEnd)}),n(g,r.char,function(t){b+=t}),g)),y);var _=function(e){t.debug&&console.log(v,e);var n=x.stateMachine[v],o=n[function(t){return c[t]||r.char}(e)]||n[r.error]||n[r.char];o(e)};return x.write=function(t){for(var e=t.length,n=0;n<e;n++)_(t[n])},x}}}}),ba=fa({"node_modules/xml-reader/dist/reader.js"(t,e){var n=Sa(),o=Ma(),s=o.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 s.openTag:if(null===c)(c=a).name=n.value;else{var o=r({name:n.value,parent:c});c.children.push(o),c=o}break;case s.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 s.text:c&&c.children.push(r({type:i.text,value:n.value,parent:t.parentNodes?c:null}));break;case s.attributeName:h=n.value,c.attributes[h]="";break;case s.attributeValue:c.attributes[h]=n.value}};return d.reset=function(){(e=o.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),o=void 0;return n.on("done",function(t){o=t}),n.parse(t),o},create:a,NodeType:i}}}),{cos:Na,sin:Ia,PI:Ca}=Math,{tan:_a}=Math,Ta=(ga(Pa()),ga(ba()),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:[]}}}),Ea=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)",Ra=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 wa(t,e){const{minX:n,maxX:o,minY:s,maxY:i}=e,r=o-n,a=i-s,c=1e-6;return Math.abs(t.y-i)<c?t.x-n:Math.abs(t.x-o)<c?r+(i-t.y):Math.abs(t.y-s)<c?r+a+(o-t.x):Math.abs(t.x-n)<c?2*r+a+(t.y-s):0}function Aa(t,e){const{minX:n,maxX:o,minY:s,maxY:i}=e,r=1e-6,a=Math.abs(t.y-i)<r,c=Math.abs(t.y-s)<r,h=Math.abs(t.x-o)<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=(s+i)/2,u=(n+o)/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 Oa(t,e,n,o,s,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*s+g*r,c[y+1]=m*e+3*p*l*o+3*u*f*i+g*a}}function za(t,e,n,o,s){const i=[];for(let r=0;r<=s;r++){const a=r/s,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*o.x,y:d*t.y+3*h*a*e.y+3*c*l*n.y+u*o.y})}return i}function Da(t,e,n,o,s,i){const r=s-n,a=i-o,c=r*r+a*a;if(0===c){const s=t-n,i=e-o;return s*s+i*i}const h=Math.max(0,Math.min(1,((t-n)*r+(e-o)*a)/c)),d=t-(n+h*r),l=e-(o+h*a);return d*d+l*l}function La(t,e,n,o,s,i,r,a){const c=(r-s)*(e-i)-(a-i)*(t-s),h=(r-s)*(o-i)-(a-i)*(n-s),d=(n-t)*(i-e)-(o-e)*(s-t),l=(n-t)*(a-e)-(o-e)*(r-t);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)?0:Math.min(Da(t,e,s,i,r,a),Da(n,o,s,i,r,a),Da(s,i,t,e,n,o),Da(r,a,t,e,n,o))}function Fa(t,e,n,o,s,i,r,a){const c=(r-s)*(e-i)-(a-i)*(t-s),h=(r-s)*(o-i)-(a-i)*(n-s),d=(n-t)*(i-e)-(o-e)*(s-t),l=(n-t)*(a-e)-(o-e)*(r-t);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)}function Xa(t,e,n,o,s){const i=t=>(t%s+s)%s,r=i(t),a=i(e),c=i(n),h=i(o),[d,l]=r<a?[r,a]:[a,r];return c>d&&c<l&&h>d&&h<l}function Ya(t,e){let n=1/0,o=-1/0,s=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>o&&(o=e),a<s&&(s=a),a>i&&(i=a)}return{minX:n,maxX:o,minY:s,maxY:i}}var $a=class extends Ta{constructor(t){super(),this.problem=t;for(const t of this.problem.obstacles)t.outerSegments=Ra(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:o,minY:s,maxY:i}=t,r=o-n,a=i-s,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:wa(e.start,t),t2:wa(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;Xa(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:o,idx:s})=>{const i=Aa(e.start,t),c=Aa(e.end,t),d=Math.hypot(e.end.x-e.start.x,e.end.y-e.start.y),f=p[s]/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),P=Math.max(v,x),S=Math.max(v,x);return{waypointPair:e,ctrl1:{x:e.start.x+P*i.x,y:e.start.y+P*i.y},ctrl2:{x:e.end.x+S*c.x,y:e.end.y+S*c.y},networkId:e.networkId,t1:n,t2:o,perpDir1:i,perpDir2:c,d1:P,d2:S,containedBy:l[s],contains:u[s]}}),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];Oa(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]=Ya(this.sampledPoints[t],6)}}updateSingleTraceSample(t){const e=this.traces[t];Oa(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]=Ya(this.sampledPoints[t],6)}updateControlPointsFromDistances(t){const e=this.traces[t],{minX:n,maxX:o,minY:s,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-o)<r&&(a=Math.min(a,o)),Math.abs(l.y-s)<r&&(c=Math.max(c,s)),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-o)<r&&(h=Math.min(h,o)),Math.abs(u.y-s)<r&&(d=Math.max(d,s)),Math.abs(u.y-i)<r&&(d=Math.min(d,i)),a=Math.max(n,Math.min(o,a)),c=Math.max(s,Math.min(i,c)),h=Math.max(n,Math.min(o,h)),d=Math.max(s,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 o=this.traces[e],s=this.traces[n];if(o.networkId&&s.networkId&&o.networkId===s.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,o=t**2;let s=0;for(const[t,o]of this.collisionPairs){const i=this.sampledPoints[t],r=this.sampledPoints[o];for(let t=0;t<5;t++){const o=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=La(o,a,c,h,r[2*t],r[2*t+1],r[2*(t+1)],r[2*(t+1)+1]);if(i<n){s+=(e-Math.sqrt(i))**2,i<1e-18&&(s+=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=La(i[2*e],i[2*e+1],i[2*(e+1)],i[2*(e+1)+1],c,h,d,l);if(n<o){s+=(t-Math.sqrt(n))**2,n<1e-18&&(s+=20*o)}}}}return s}computeCostForTrace(t){const{preferredObstacleToTraceSpacing:e}=this.problem,n=this.effectiveTraceToTraceSpacing,o=n**2,s=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 s=this.traces[e];if(i.networkId&&s.networkId&&i.networkId===s.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],s=r[2*t+1],i=r[2*(t+1)],a=r[2*(t+1)+1];for(let t=0;t<5;t++){const r=La(e,s,i,a,d[2*t],d[2*t+1],d[2*(t+1)],d[2*(t+1)+1]);if(r<o){c+=(n-Math.sqrt(r))**2,r<1e-18&&(c+=20*o)}}}}for(let t=0;t<this.numObstacleSegments;t++){if(i.networkId&&this.obstacleNetworkIds[t]&&i.networkId===this.obstacleNetworkIds[t])continue;const n=4*t,o=this.obstacleSegments[n],h=this.obstacleSegments[n+1],d=this.obstacleSegments[n+2],l=this.obstacleSegments[n+3],u=Math.min(o,d),p=Math.max(o,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=La(r[2*t],r[2*t+1],r[2*(t+1)],r[2*(t+1)+1],o,h,d,l);if(n<s){c+=(e-Math.sqrt(n))**2,n<1e-18&&(c+=20*s)}}}return c}tracesIntersect(t,e){const n=this.traces[t],o=this.traces[e],s=15,i=new Float64Array(32),r=new Float64Array(32);Oa(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,s),Oa(o.waypointPair.start.x,o.waypointPair.start.y,o.ctrl1.x,o.ctrl1.y,o.ctrl2.x,o.ctrl2.y,o.waypointPair.end.x,o.waypointPair.end.y,r,s);for(let t=0;t<s;t++){const e=i[2*t],n=i[2*t+1],o=i[2*(t+1)],a=i[2*(t+1)+1];for(let t=0;t<s;t++){if(Fa(e,n,o,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 o=this.traces[e],s=this.traces[n];if(o.networkId&&s.networkId&&o.networkId===s.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:o,minY:s,maxY:i}=t,r=Math.min(o-n,i-s),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 o=this.traces[t],s=this.traces[n];if(!this.tracesIntersect(t,n))continue;let i,r;if(o.containedBy.includes(n))i=n,r=t;else if(s.containedBy.includes(t))i=t,r=n;else{(o.d1+o.d2)/2<(s.d1+s.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:o,maxY:s}=t,i=Math.min(n-e,s-o),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],o=e>100?2:1,s=[a*o,1.5*a*o,.5*a];for(const o of s){const s=e>100?[o,-o,2*o,2*-o,3*o,3*-o,2*r,2*-r]:[o,-o,2*o,2*-o];let i=this.computeCostForTrace(t),a=n.d1,d=n.d2;const l=n.d1,u=n.d2;for(const e of s){n.d1=Math.max(c,Math.min(h,l+e)),this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t);const o=this.computeCostForTrace(t);o<i&&(i=o,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 s=this.computeCostForTrace(t);s<i&&(i=s,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:za(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:Ea(e.networkId)}),n.points.push({...e.end,label:`end ${e.networkId??""}`,color:Ea(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:Ea(t.networkId)});return n})(this.problem,this.outputTraces)}},Ba=class extends y{getSolverName(){return"JumperPrepatternSolver2_HyperGraph"}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 o=0;for(const s of Array.from(n))e[s]=t[o%t.length],o++;return e}_getPatternConfig(){return{cols:this.hyperParameters.COLS??1,rows:this.hyperParameters.ROWS??1}}_generate0603Grid(t,e,n){const o="horizontal"===e?t.rows:t.cols,s="horizontal"===e?t.cols:t.rows,i=n.maxX-n.minX,r=n.maxY-n.minY,a=.5,c=Ur({cols:o,rows:s,marginX:a,marginY:a,innerColChannelPointCount:2,innerRowChannelPointCount:2,outerPaddingX:.1,outerPaddingY:.1,outerChannelXPoints:3,outerChannelYPoints:3}),h=Or(c.regions),d=h.maxX-h.minX,l=h.maxY-h.minY,u=Math.max(.3,(i-d)/2+.1),p=Math.max(.3,(r-l)/2+.1),m=Math.max(3,Math.ceil(u/.5)),f=Math.max(3,Math.ceil(p/.5)),g=Ur({cols:o,rows:s,marginX:a,marginY:a,innerColChannelPointCount:2,innerRowChannelPointCount:2,outerPaddingX:u,outerPaddingY:p,outerChannelXPoints:m,outerChannelYPoints:f}),y={regions:g.regions,ports:g.ports,jumperLocations:[]},x=Or(y.regions),v=(x.minX+x.maxX)/2,P=(x.minY+x.maxY)/2,S=Sn((n.minX+n.maxX)/2-v,(n.minY+n.maxY)/2-P),M=Wr(y,S),b=[];for(const t of M.regions)t.d?.isPad&&b.push({center:t.d.center,orientation:e,padRegions:[t]});return M.jumperLocations=b,M}_initializeGraph(){const t=this.nodeWithPortPoints,e=this._getPatternConfig(),n=this.hyperParameters.ORIENTATION??"vertical",o=this.hyperParameters.JUMPER_TYPE??"1206x4",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};let i;if(this.graphBounds=s,"0603"===o){const t=this._generate0603Grid(e,n,s);if(!t)return this.error=`0603 grid (${e.cols}x${e.rows}) is too large to fit in node bounds`,this.failed=!0,!1;i=t}else i=(({cols:t,rows:e,marginX:n,marginY:o,innerColChannelPointCount:s=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=2})=>{const f=[],g=[],{padWidth:y,outerPadHeight:x,innerPadHeight:v,leftPadCenterX:P,rightPadCenterX:S,row1CenterY:M,row2CenterY:b,row3CenterY:N,row4CenterY:I}=Ar,C=y/2,_=x/2,T=v/2,E=S-P+y,R=E+n,w=I-M+x,A=w+o;let O=a,z=c;if(p){const s=t*E+(t-1)*n,i=e*w+(e-1)*o;O=(("horizontal"===l?p.maxY-p.minY:p.maxX-p.minX)-s)/2,z=(("horizontal"===l?p.maxX-p.minX:p.maxY-p.minY)-i)/2}const D=h??Math.max(1,Math.floor(O/.4)),L=d??Math.max(1,Math.floor(z/.4)),F=[],X=[],Y=(t,e,n,o)=>({regionId:t,ports:[],d:{bounds:e,center:wr(e),isPad:n,isThroughJumper:o}}),$=(t,e,n)=>{const o=e.d.bounds,s=n.d.bounds;let i,r;Math.abs(o.maxX-s.minX)<.001?(i=o.maxX,r=(Math.max(o.minY,s.minY)+Math.min(o.maxY,s.maxY))/2):Math.abs(o.minX-s.maxX)<.001?(i=o.minX,r=(Math.max(o.minY,s.minY)+Math.min(o.maxY,s.maxY))/2):Math.abs(o.maxY-s.minY)<.001?(i=(Math.max(o.minX,s.minX)+Math.min(o.maxX,s.maxX))/2,r=o.maxY):(i=(Math.max(o.minX,s.minX)+Math.min(o.maxX,s.maxX))/2,r=o.minY);const a={portId:t,region1:e,region2:n,d:{x:i,y:r}};return e.ports.push(a),n.ports.push(a),a},B=(t,e,n,o)=>{if(o<=0)return[];if(1===o)return[$(t,e,n)];const s=e.d.bounds,i=n.d.bounds,r=[];let a,c,h,d;Math.abs(s.maxX-i.minX)<.001?(a=!0,c=s.maxX,h=Math.max(s.minY,i.minY),d=Math.min(s.maxY,i.maxY)):Math.abs(s.minX-i.maxX)<.001?(a=!0,c=s.minX,h=Math.max(s.minY,i.minY),d=Math.min(s.maxY,i.maxY)):Math.abs(s.maxY-i.minY)<.001?(a=!1,c=s.maxY,h=Math.max(s.minX,i.minX),d=Math.min(s.maxX,i.maxX)):(a=!1,c=s.minY,h=Math.max(s.minX,i.minX),d=Math.min(s.maxX,i.maxX));for(let s=0;s<o;s++){const i=h+(s+.5)/o*(d-h),l={portId:`${t}:${s}`,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++){F[n]=[];for(let a=0;a<t;a++){const c=`cell_${n}_${a}`,h=a*R,d=-n*A,l=h+P,u=d+M,p=h+P,y=d+b,x=h+P,v=d+N,E=h+P,w=d+I,k=h+S,j=d+I,W=h+S,H=d+N,U=h+S,V=d+b,Z=h+S,G=d+M,J=(t,e,n)=>({minX:t-C,maxX:t+C,minY:e-n,maxY:e+n}),q=J(l,u,_),K=J(p,y,T),Q=J(x,v,T),tt=J(E,w,_),et=J(k,j,_),nt=J(W,H,T),ot=J(U,V,T),st=J(Z,G,_),it={minX:q.maxX,maxX:st.minX,minY:q.minY,maxY:tt.maxY},rt=.3,at={minX:l,maxX:Z,minY:u-rt/2,maxY:u+rt/2},ct={minX:p,maxX:U,minY:y-rt/2,maxY:y+rt/2},ht={minX:x,maxX:W,minY:v-rt/2,maxY:v+rt/2},dt={minX:E,maxX:k,minY:w-rt/2,maxY:w+rt/2},lt=q.minX,ut=st.maxX,pt=q.minY,mt=tt.maxY,ft=Y(`${c}:pad1`,q,!0),gt=Y(`${c}:pad2`,K,!0),yt=Y(`${c}:pad3`,Q,!0),xt=Y(`${c}:pad4`,tt,!0),vt=Y(`${c}:pad5`,et,!0),Pt=Y(`${c}:pad6`,nt,!0),St=Y(`${c}:pad7`,ot,!0),Mt=Y(`${c}:pad8`,st,!0),bt=Y(`${c}:underjumper`,it,!1),Nt=Y(`${c}:throughjumper1`,at,!1,!0),It=Y(`${c}:throughjumper2`,ct,!1,!0),Ct=Y(`${c}:throughjumper3`,ht,!1,!0),_t=Y(`${c}:throughjumper4`,dt,!1,!0);f.push(ft,gt,yt,xt,vt,Pt,St,Mt,bt,Nt,It,Ct,_t);const Tt=(l+Z)/2,Et=(u+w)/2;X.push({center:{x:Tt,y:Et},orientation:"vertical",padRegions:[ft,gt,yt,xt,vt,Pt,St,Mt]});let Rt=null,wt=null,At=null,Ot=null,zt=null,Dt=null;r&&(Rt=Y(`${c}:L-BP12`,{minX:q.minX,maxX:q.maxX,minY:q.maxY,maxY:K.minY},!1),wt=Y(`${c}:L-BP23`,{minX:K.minX,maxX:K.maxX,minY:K.maxY,maxY:Q.minY},!1),At=Y(`${c}:L-BP34`,{minX:Q.minX,maxX:Q.maxX,minY:Q.maxY,maxY:tt.minY},!1),Ot=Y(`${c}:R-BP87`,{minX:st.minX,maxX:st.maxX,minY:st.maxY,maxY:ot.minY},!1),zt=Y(`${c}:R-BP76`,{minX:ot.minX,maxX:ot.maxX,minY:ot.maxY,maxY:nt.minY},!1),Dt=Y(`${c}:R-BP65`,{minX:nt.minX,maxX:nt.maxX,minY:nt.maxY,maxY:et.minY},!1),f.push(Rt,wt,At,Ot,zt,Dt));const Lt=0===a,Ft=n===e-1,Xt=a===t-1;let Yt;Yt=Xt?ut+O:(a+1)*R+P-C;let $t=null;0===n&&($t=Y(`${c}:T`,{minX:Lt?lt-O:lt,maxX:Yt,minY:mt,maxY:mt+z},!1),f.push($t));let Bt=null;Bt=Y(`${c}:B`,{minX:Lt?lt-O:lt,maxX:Yt,minY:pt-(Ft?z:o),maxY:pt},!1),f.push(Bt);let kt=null;Lt&&(kt=Y(`${c}:L`,{minX:lt-O,maxX:lt,minY:pt,maxY:mt},!1),f.push(kt));const jt=Y(`${c}:R`,{minX:ut,maxX:Yt,minY:pt,maxY:mt},!1);if(f.push(jt),F[n][a]={pad1:ft,pad2:gt,pad3:yt,pad4:xt,pad5:vt,pad6:Pt,pad7:St,pad8:Mt,underjumper:bt,throughjumper1:Nt,throughjumper2:It,throughjumper3:Ct,throughjumper4:_t,top:$t,bottom:Bt,left:kt,right:jt,leftBP12:Rt,leftBP23:wt,leftBP34:At,rightBP87:Ot,rightBP76:zt,rightBP65:Dt},$t)if(kt&&g.push(...B(`${c}:T-L`,$t,kt,D)),g.push(...B(`${c}:T-R`,$t,jt,Xt?D:s)),g.push($(`${c}:T-P4`,$t,xt)),g.push($(`${c}:T-P5`,$t,vt)),r){const t=bt.d.bounds,e=(t.maxX-t.minX)/(m+1);for(let n=1;n<=m;n++){const o={portId:`${c}:T-UJ${n}`,region1:$t,region2:bt,d:{x:t.minX+e*n,y:t.maxY}};$t.ports.push(o),bt.ports.push(o),g.push(o)}}else g.push($(`${c}:T-UJ`,$t,bt));if(Bt)if(kt&&g.push(...B(`${c}:B-L`,Bt,kt,D)),g.push(...B(`${c}:B-R`,Bt,jt,Xt?D:s)),g.push($(`${c}:B-P1`,Bt,ft)),g.push($(`${c}:B-P8`,Bt,Mt)),r){const t=bt.d.bounds,e=(t.maxX-t.minX)/(m+1);for(let n=1;n<=m;n++){const o={portId:`${c}:B-UJ${n}`,region1:Bt,region2:bt,d:{x:t.minX+e*n,y:t.minY}};Bt.ports.push(o),bt.ports.push(o),g.push(o)}}else g.push($(`${c}:B-UJ`,Bt,bt));kt&&(g.push($(`${c}:L-P1`,kt,ft)),g.push($(`${c}:L-P2`,kt,gt)),g.push($(`${c}:L-P3`,kt,yt)),g.push($(`${c}:L-P4`,kt,xt))),g.push($(`${c}:R-P5`,jt,vt)),g.push($(`${c}:R-P6`,jt,Pt)),g.push($(`${c}:R-P7`,jt,St)),g.push($(`${c}:R-P8`,jt,Mt)),r&&(kt&&(g.push($(`${c}:L-BP12`,kt,Rt)),g.push($(`${c}:L-BP23`,kt,wt)),g.push($(`${c}:L-BP34`,kt,At))),g.push($(`${c}:UJ-LBP12`,Rt,bt)),g.push($(`${c}:UJ-LBP23`,wt,bt)),g.push($(`${c}:UJ-LBP34`,At,bt)),g.push($(`${c}:R-BP87`,jt,Ot)),g.push($(`${c}:R-BP76`,jt,zt)),g.push($(`${c}:R-BP65`,jt,Dt)),g.push($(`${c}:UJ-RBP87`,Ot,bt)),g.push($(`${c}:UJ-RBP76`,zt,bt)),g.push($(`${c}:UJ-RBP65`,Dt,bt)));const Wt={portId:`${c}:TJ1-P1`,region1:Nt,region2:ft,d:{x:l,y:u}};Nt.ports.push(Wt),ft.ports.push(Wt),g.push(Wt);const Ht={portId:`${c}:TJ1-P8`,region1:Nt,region2:Mt,d:{x:Z,y:G}};Nt.ports.push(Ht),Mt.ports.push(Ht),g.push(Ht);const Ut={portId:`${c}:TJ2-P2`,region1:It,region2:gt,d:{x:p,y:y}};It.ports.push(Ut),gt.ports.push(Ut),g.push(Ut);const Vt={portId:`${c}:TJ2-P7`,region1:It,region2:St,d:{x:U,y:V}};It.ports.push(Vt),St.ports.push(Vt),g.push(Vt);const Zt={portId:`${c}:TJ3-P3`,region1:Ct,region2:yt,d:{x:x,y:v}};Ct.ports.push(Zt),yt.ports.push(Zt),g.push(Zt);const Gt={portId:`${c}:TJ3-P6`,region1:Ct,region2:Pt,d:{x:W,y:H}};Ct.ports.push(Gt),Pt.ports.push(Gt),g.push(Gt);const Jt={portId:`${c}:TJ4-P4`,region1:_t,region2:xt,d:{x:E,y:w}};_t.ports.push(Jt),xt.ports.push(Jt),g.push(Jt);const qt={portId:`${c}:TJ4-P5`,region1:_t,region2:vt,d:{x:k,y:j}};if(_t.ports.push(qt),vt.ports.push(qt),g.push(qt),a>0){const t=F[n][a-1];g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-P1`,t.right,ft)),g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-P2`,t.right,gt)),g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-P3`,t.right,yt)),g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-P4`,t.right,xt)),r&&(g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP12`,t.right,Rt)),g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP23`,t.right,wt)),g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP34`,t.right,At))),$t&&t.top&&g.push(...B(`cell_${n}_${a-1}->cell_${n}_${a}:T-T`,t.top,$t,L)),Bt&&t.bottom&&g.push(...B(`cell_${n}_${a-1}->cell_${n}_${a}:B-B`,t.bottom,Bt,Ft?L:i))}if(n>0){const t=F[n-1][a];if(kt&&g.push(...B(`cell_${n-1}_${a}->cell_${n}_${a}:B-L`,t.bottom,kt,D)),g.push($(`cell_${n-1}_${a}->cell_${n}_${a}:B-P4`,t.bottom,xt)),r){const e=bt.d.bounds,o=(e.maxX-e.minX)/(m+1);for(let s=1;s<=m;s++){const i=e.minX+o*s,r={portId:`cell_${n-1}_${a}->cell_${n}_${a}:B-UJ${s}`,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($(`cell_${n-1}_${a}->cell_${n}_${a}:B-UJ`,t.bottom,bt));g.push($(`cell_${n-1}_${a}->cell_${n}_${a}:B-P5`,t.bottom,vt)),g.push(...B(`cell_${n-1}_${a}->cell_${n}_${a}:B-R`,t.bottom,jt,Xt?D:s))}}}let k={regions:f,ports:g,jumperLocations:X};const j="horizontal"===l;if(j||void 0!==u||void 0!==p){const t=Or(k.regions),e=wr(t),n=[];let o;o=u||(p?wr(p):e),n.push(Lr(o.x,o.y)),j&&n.push(kr(-Math.PI/2)),n.push(Lr(-e.x,-e.y));const s=Xr(...n);k=Wr(k,s)}return k})({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:2,innerColChannelPointCount:3,innerRowChannelPointCount:3,outerChannelXPointCount:3,outerChannelYPointCount:3,regionsBetweenPads:!0,orientation:n,bounds:s});if(i.regions.length>0){let t=1/0,e=-1/0,n=1/0,r=-1/0;for(const o of i.regions){if(!o.d?.isPad)continue;const s=o.d?.bounds;s&&(t=Math.min(t,s.minX),e=Math.max(e,s.maxX),n=Math.min(n,s.minY),r=Math.max(r,s.maxY))}const a="0603"===o?.5:1;if(t-a<s.minX||e+a>s.maxX||n-a<s.minY||r+a>s.maxY)return this.error=`baseGraph bounds (${t.toFixed(2)}, ${n.toFixed(2)}, ${e.toFixed(2)}, ${r.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=i.jumperLocations?.map(t=>({center:t.center,orientation:t.orientation,padRegions:t.padRegions}))??[];const r=new Map;for(const e of t.portPoints){const t=r.get(e.connectionName);t?t.points.push(e):r.set(e.connectionName,{points:[e],rootConnectionName:e.rootConnectionName})}this.xyConnections=[];for(const[t,e]of Array.from(r.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 a=((t,e)=>{const n=[...t.regions],o=[...t.ports],s=[],i=Or(t.regions);for(const r of e){const{start:e,end:a,connectionId:c}=r,h=Zr(`conn:${c}:start`,e.x,e.y);n.push(h);const d=Zr(`conn:${c}:end`,a.x,a.y);n.push(d);const l=Gr(e.x,e.y,t.regions,i);if(l){const t=Vr(`conn:${c}:start-port`,h,l.region,l.portPosition);o.push(t)}const u=Gr(a.x,a.y,t.regions,i);if(u){const t=Vr(`conn:${c}:end-port`,d,u.region,u.portPosition);o.push(t)}const p={connectionId:c,mutuallyConnectedNetworkId:c,startRegion:h,endRegion:d};s.push(p)}return{regions:n,ports:o,connections:s}})(i,this.xyConnections);return this.jumperGraphSolver=new ca({inputGraph:{regions:a.regions,ports:a.ports},inputConnections:a.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??"",o=t.points.map(t=>({x:t.x,y:t.y})),s={path:o,start:o[0]??{x:0,y:0},end:o[o.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(s)}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,o=n.d.center;e.push({minX:t.minX,minY:t.minY,maxX:t.maxX,maxY:t.maxY,center:{x:o.x,y:o.y},networkIds:[]})}const n=new Map;for(let e=0;e<this.jumperGraphSolver.solvedRoutes.length;e++){const o=this.jumperGraphSolver.solvedRoutes[e],s=o.connection.connectionId,i=this.nodeWithPortPoints.portPoints.find(t=>t.connectionName===s)?.rootConnectionName,r=[],a=[];let c=null,h=null;for(let d=0;d<o.path.length;d++){const l=o.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=o.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:s,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,o=e.maxX-e.minX>e.maxY-e.minY,s="0603"===(this.hyperParameters.JUMPER_TYPE??"1206x4")?"0603":"1206x4_pair";o?r.push({route_type:"jumper",start:{x:e.minX,y:n.y},end:{x:e.maxX,y:n.y},footprint:s}):r.push({route_type:"jumper",start:{x:n.x,y:e.minY},end:{x:n.x,y:e.maxY},footprint:s})}}if(c&&h){const t=o.path[o.path.length-1];a.push({regionId:c.regionId,region:c,entryPort:h,exitPort:t?.port||null})}this.routeInfos.push({connectionId:s,rootConnectionName:i,jumpers:r,traversals:a})}for(let t=0;t<this.routeInfos.length;t++){const n=this.routeInfos[t],o=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),s=Math.abs(n.center.y-t.y);e<.1&&s<.1&&(n.networkIds.includes(o)||n.networkIds.push(o))}}}for(const[t,o]of n){if(0===o.length)continue;const n=o[0].region;if(n.d.isPad||n.d.isThroughJumper)continue;const s=n.d.bounds,i=[];for(const t of o)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<=s.maxX+r&&t.maxX>=s.minX-r&&t.minY<=s.maxY+r&&t.maxY>=s.minY-r).map(t=>{const e=o.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:s,waypointPairs:i,obstacles:a,preferredTraceToTraceSpacing:2*this.traceWidth,preferredObstacleToTraceSpacing:2*this.traceWidth},h=new $a(c);this.curvySolvers.push({solver:h,regionId:t,traversals:o.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],o=[];for(const e of n.traversals){const s=e.regionId,i=n.rootConnectionName??n.connectionId,r=this.regionCurvedPaths.get(s)?.get(i);let a=null;if(r&&r.length>0){const n={x:e.entryPort.d.x,y:e.entryPort.d.y},o=e.exitPort?{x:e.exitPort.d.x,y:e.exitPort.d.y}:null;let s=null,i=1/0;for(const e of r){const r=t(e.start,n)+(o?t(e.end,o):0);r<i&&(i=r,s=e)}s&&i<.5&&(a=s.path)}if(a&&a.length>0){for(let t=o.length>0?1:0;t<a.length;t++)o.push({x:a[t].x,y:a[t].y,z:0})}else 0===o.length&&o.push({x:e.entryPort.d.x,y:e.entryPort.d.y,z:0}),e.exitPort&&o.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:o,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 o=[n.start,n.end];for(const n of o){const o=`${n.x.toFixed(3)},${n.y.toFixed(3)}`,s=t.get(o)??[];e.rootConnectionName&&!s.includes(e.rootConnectionName)&&s.push(e.rootConnectionName),s.includes(e.connectionName)||s.push(e.connectionName),t.set(o,s)}}const e=this.hyperParameters.JUMPER_TYPE??"1206x4",n=qe["0603"===e?"0603":"1206x4_pair"];for(const o of this.jumperLocations){const s="horizontal"===o.orientation,i=o.padRegions.map(e=>{const n=e.d.bounds,o=e.d.center,s=n.maxX-n.minX,i=n.maxY-n.minY,r=`${o.x.toFixed(3)},${o.y.toFixed(3)}`;return{type:"rect",center:o,width:s,height:i,layers:["top"],connectedTo:[...t.get(r)??[]]}}),r={jumper_footprint:e,center:o.center,orientation:o.orientation,width:s?n.length:n.width,height:s?n.width:n.length,pads:i};this.jumpers.push(r)}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 o=0;o<e.route.length-1;o++){const s=e.route[o],i=e.route[o+1];t.lines.push({points:[s,i],strokeColor:it(n,.2),strokeWidth:e.traceThickness,layer:"route-layer-0"})}for(const o of e.jumpers)this._drawJumperPads(t,o,it(n,.5))}return t}_drawJumperPads(t,e,n){const o=qe[e.footprint],s=e.end.x-e.start.x,i=e.end.y-e.start.y,r=Math.abs(s)>Math.abs(i),a=r?o.padLength:o.padWidth,c=r?o.padWidth:o.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*o.padWidth,layer:"jumper-body"})}};function ka(t,e,n,o=.5){const s=t-2*o,i=e-2*o,r=Math.max(1,Math.floor(1+(s-2.45)/2.95)),a=Math.max(1,Math.floor(i/1.42));return"vertical"===n?{cols:r,rows:a}:{cols:a,rows:r}}var ja=class extends Zt{constructorParams;nodeWithPortPoints;colorMap;traceWidth;connMap;baseHyperParameters;availableJumperTypes;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.availableJumperTypes=t.availableJumperTypes??["0603"],this.MAX_ITERATIONS=1e6,this.GREEDY_MULTIPLIER=1,this.MIN_SUBSTEPS=1e3}getConstructorParams(){return this.constructorParams}getHyperParameterDefs(){const t=[],e=this.nodeWithPortPoints,n=ka(e.width,e.height,"vertical");t.push({name:"0603_max_rows_and_cols_vert",possibleValues:[{JUMPER_TYPE:"0603",COLS:n.cols,ROWS:n.rows,ORIENTATION:"vertical"}]});const o=ka(e.width,e.height,"horizontal");t.push({name:"0603_max_rows_and_cols_horz",possibleValues:[{JUMPER_TYPE:"0603",COLS:o.cols,ROWS:o.rows,ORIENTATION:"horizontal"}]}),t.push({name:"1206x4",possibleValues:[{JUMPER_TYPE:"1206x4"}]});return t.push({name:"1206x4_cols",possibleValues:[1,2,3,4,6,8,10].map(t=>({COLS:t}))}),t.push({name:"1206x4_rows",possibleValues:[1,2,3,4,8].map(t=>({ROWS:t}))}),t.push({name:"orientation",possibleValues:[{ORIENTATION:"vertical"},{ORIENTATION:"horizontal"}]}),t}isValidCombination(t){const{JUMPER_TYPE:e,COLS:n,ROWS:o}=t,s=[1,2,4,6,8],i=[1,2,3,4,6,8,10],r=[1,2,3,4,8];return"0603"===e?s.includes(n)&&s.includes(o):"1206x4"===e&&(i.includes(n)&&r.includes(o))}getCombinationDefs(){return[["0603_max_rows_and_cols_vert"],["0603_max_rows_and_cols_horz"],["1206x4","1206x4_cols","1206x4_rows","orientation"]]}initializeSolvers(){const t=this.getHyperParameterDefs(),e=this.getCombinationDefs();this.supervisedSolvers=[];for(const n of e){const e=n.includes("0603_max_rows_and_cols_vert")||n.includes("0603_max_rows_and_cols_horz"),o=n.includes("1206x4");if(e&&!this.availableJumperTypes.includes("0603"))continue;if(o&&!this.availableJumperTypes.includes("1206x4"))continue;const s=this.getHyperParameterCombinations(t.filter(t=>n.includes(t.name)));for(const t of s){const e=this.generateSolver(t),n=this.computeG(e);this.supervisedSolvers.push({hyperParameters:t,solver:e,h:0,g:n,f:n})}}}generateSolver(t){return new Ba({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,traceWidth:this.traceWidth,hyperParameters:{COLS:t.COLS,ROWS:t.ROWS,ORIENTATION:t.ORIENTATION,JUMPER_TYPE:t.JUMPER_TYPE}})}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()}},Wa=class extends y{getSolverName(){return"CurvyIntraNodeSolver"}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 o=[];for(const[t,e]of n){if(e.length<2)continue;const n=e[0],s=e[e.length-1];o.push({start:{x:n.x,y:n.y},end:{x:s.x,y:s.y},networkId:t})}if(0===o.length)return void(this.phase="done");const s={bounds:e,waypointPairs:o,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 $a(s),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??"",o=e.get(n);if(!o)continue;const s={connectionName:o.connectionName,rootConnectionName:o.rootConnectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:t.points.map(t=>({x:t.x,y:t.y,z:o.z})),vias:[]};this.routes.push(s)}}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 Ha(t){return{connectionName:t.connectionName,rootConnectionName:t.rootConnectionName,traceThickness:t.traceThickness,viaDiameter:0,route:t.route,vias:[],jumpers:t.jumpers}}var Ua=class extends y{getSolverName(){return"JumperHighDensitySolver"}allNodes;nodeAnalyses;routes;colorMap;traceWidth;viaDiameter;connMap;hyperParameters;availableJumperTypes;capacityMeshNodes;capacityMeshEdges;capacityMeshNodeMap;nodeAdjacencyMap;nodesWithoutCrossings;nodesWithCrossings;curvyIntraNodeSolvers;currentCurvySolverIndex;jumperSolvers;currentJumperSolverIndex;phase;jumpers=[];constructor({nodePortPoints:t,colorMap:e,traceWidth:n=.15,viaDiameter:o=.6,connMap:s,hyperParameters:i,capacityMeshNodes:r=[],capacityMeshEdges:a=[],availableJumperTypes:c}){super(),this.allNodes=[...t],this.colorMap=e??{},this.routes=[],this.traceWidth=n,this.viaDiameter=o,this.connMap=s,this.hyperParameters=i,this.capacityMeshNodes=r,this.capacityMeshEdges=a,this.availableJumperTypes=c??["0603"],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 h=1e3*this.nodesWithoutCrossings.length,d=1e5*this.nodesWithCrossings.length;this.MAX_ITERATIONS=h+d+100}_buildNodeAdjacencyMap(){const t=new Map;for(const e of this.capacityMeshEdges){const[n,o]=e.nodeIds;t.has(n)||t.set(n,new Set),t.has(o)||t.set(o,new Set),t.get(n).add(o),t.get(o).add(n)}return t}_analyzeNodes(){for(const t of this.allNodes){const e=zs(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 o=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 s=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=o.get(t);e&&e.portPoints.length>0&&(c=e.portPoints[0].rootConnectionName??e.portPoints[0].connectionName)}e.push({minX:s,minY:i,maxX:r,maxY:a,networkId:c})}return e}_initializeCurvySolvers(){for(const t of this.nodesWithoutCrossings){const e=this._getAdjacentObstacles(t),n=new Wa({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),o=new Wa({nodeWithPortPoints:e,colorMap:this.colorMap,traceWidth:this.traceWidth,viaDiameter:this.viaDiameter,adjacentObstacles:n});this.curvyIntraNodeSolvers[t]=o}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 ja({nodeWithPortPoints:t,colorMap:this.colorMap,traceWidth:this.traceWidth,connMap:this.connMap,availableJumperTypes:this.availableJumperTypes});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(Ha(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 o=this.jumperSolvers[this.currentJumperSolverIndex];return o&&(e+=o.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,availableJumperTypes:this.availableJumperTypes}}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,o=Xe(e.route,e.connectionName,this.colorMap[n]);for(const n of o)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 o of e.vias)t.circles.push({center:o,radius:e.viaDiameter/2,fill:it(this.colorMap[n]??"gray",.5),layer:"via"});if("jumpers"in e&&e.jumpers)for(const o of e.jumpers){const e=this.colorMap[n]??"gray",s=o.footprint??"1206",i=qe[s],r=o.end.x-o.start.x,a=o.end.y-o.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:o.start,width:h,height:d,fill:it(e,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.rects.push({center:o.end,width:h,height:d,fill:it(e,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.lines.push({points:[o.start,o.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}},Va=class extends y{getSolverName(){return"MultipleHighDensityRouteStitchSolver2"}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 o=new Map;for(const e of t.hdRoutes){const t=o.get(e.connectionName);t?t.push(e):o.set(e.connectionName,[e])}this.unsolvedRoutes=[];for(const[e,s]of o.entries()){const o=t.connections.find(t=>t.name===e);if(!o)continue;const i=n.get(e);let r=[];i?.path&&(r=i.path.map(t=>t.currentNodeId));const a={...o.pointsToConnect[0],z:Be(Ge(o.pointsToConnect[0]),t.layerCount)},c={...o.pointsToConnect[1],z:Be(Ge(o.pointsToConnect[1]),t.layerCount)};this.unsolvedRoutes.push({connectionName:e,hdRoutes:s,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:o,start:s,end:i}=t;if(0===n.length)return{connectionName:e,traceThickness:this.defaultTraceThickness,viaDiameter:this.defaultViaDiameter,route:[s,i],vias:[],jumpers:[]};let r;r=o.length>0?this.orderRoutesByNodePath(n,o,s,e):this.orderRoutesByProximity(n,s);const a=[],c=[],h=[];a.push({x:s.x,y:s.y,z:s.z});for(let t=0;t<r.length;t++){const e=r[t],n=a[a.length-1],o=e.route[0],s=e.route[e.route.length-1],i=Pt(n,o),d=Pt(n,s),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&&Pt(n,u[0])<p&&(u=u.slice(1)),a.push(...u),c.push(...e.vias),e.jumpers&&h.push(...e.jumpers)}const d=Pt(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,o){if(0===t.length)return[];const s=new Set(t);let i=null,r=1/0;for(const t of s){const e=t.route[0],o=t.route[t.route.length-1],s=Math.min(Pt(n,e),Pt(n,o));s<r&&(r=s,i=t)}if(!i)return[];s.delete(i);const a=i.route[0],c=i.route[i.route.length-1];let h,d;Pt(n,a)<=Pt(n,c)?(h=a,d=c):(h=c,d=a);const l=(t,e)=>{let n=0;for(const o of s){if(o===e)continue;const s=o.route[0],i=o.route[o.route.length-1];(Pt(t,s)<10||Pt(t,i)<10)&&n++}return n},u=[i];let p=d;for(;s.size>0;){let t=null,e=1/0,n=-1;for(const o of s){const s=o.route[0],i=o.route[o.route.length-1],r=Pt(p,s),a=Pt(p,i),c=Math.min(r,a);if(c>=10)continue;const h=l(r<=a?i:s,o),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=o,n=h)}if(!t)break;{u.push(t),s.delete(t);const e=t.route[0],n=t.route[t.route.length-1];p=Pt(p,e)<=Pt(p,n)?n:e}}const m=[];for(p=h;s.size>0;){let t=null,e=1/0,o=-1;const i=Pt(p,n);for(const r of s){const s=r.route[0],a=r.route[r.route.length-1],c=Pt(p,s),h=Pt(p,a),d=Math.min(c,h);if(d>=10)continue;const u=c<=h?a:s;if(Pt(u,n)>i+2)continue;const m=l(u,r),f=0===m,g=0===o,y=d-e;let x=!1;x=null===t||(!!(!f&&g&&y<5)||!(f&&!g&&y>-5)&&d<e),x&&(e=d,t=r,o=m)}if(!t)break;{m.unshift(t),s.delete(t);const e=t.route[0],n=t.route[t.route.length-1];p=Pt(p,e)<=Pt(p,n)?n:e}}const f=[...m,...u];if(s.size>0){const e=[...s].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 ${s.size} routes for connection ${t[0]?.connectionName??"?"}, skipped routes: ${e.join("; ")}`)}return f}orderRoutesByProximity(t,e){const n=new Set(t),o=[];let s=e;for(;n.size>0;){let t=null,e=1/0,i=!1;for(const o of n){const n=o.route[0],r=o.route[o.route.length-1],a=Pt(s,n),c=Pt(s,r);a<e&&(e=a,t=o,i=!1),c<e&&(e=c,t=o,i=!0)}if(!t)break;{o.push(t),n.delete(t);const e=t.route[0],r=t.route[t.route.length-1];s=i?e:r}}return o}visualize(){const t={points:[],lines:[],circles:[],rects:[],title:"Multiple High Density Route Stitch Solver 2"};for(const[e,n]of this.mergedHdRoutes.entries()){const o=this.colorMap[n.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<n.route.length-1;e++){const s=n.route[e],i=n.route[e+1],r=0!==s.z?it(o,.5):o;t.lines?.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:r,strokeWidth:n.traceThickness})}for(const e of n.route){const n=0!==e.z?it(o,.5):o;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:o});if(n.jumpers&&n.jumpers.length>0){const e=Qe(n.jumpers,{color:o,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 o=0;o<e.hdRoutes.length;o++){const s=e.hdRoutes[o];if(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",label:`segment ${o}`}),s.jumpers&&s.jumpers.length>0){const e=Qe(s.jumpers,{color:n,label:s.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}}return t}};function Za(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var Ga=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,o=t.bounds.maxY-t.bounds.minY,s=Math.max(n,o),i=e.targetMinCapacity??.5;e.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getSolverName(){return"AssignableAutoroutingPipeline3"}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=[Za("netToPointPairsSolver",xn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),Za("nodeSolver",es,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Za("relateNodesToOffBoardConnections",_r,t=>[{capacityMeshNodes:t.capacityNodes,srj:t.srj}],{onSolved:t=>{t.capacityNodes=t.relateNodesToOffBoardConnections?.getOutput().capacityNodes}}),Za("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Za("availableSegmentPointSolver",Es,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),Za("portPointPathingSolver",Ks,t=>{const e=t.capacityNodes.map(t=>({capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:[],availableZ:t.availableZ,_containsTarget:t._containsTarget,_containsObstacle:t._containsObstacle,_offBoardConnectionId:t._offBoardConnectionId,_offBoardConnectedCapacityMeshNodeIds:t._offBoardConnectedCapacityMeshNodeIds})),n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),o=t.availableSegmentPointSolver;for(const t of o.sharedEdgeSegments)for(const e of t.portPoints){const[o,s]=e.nodeIds,i={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[o,s],distToCentermostPortOnZ:e.distToCentermostPortOnZ,connectsToOffBoardNode:t.nodeIds.some(t=>n.get(t)?._offBoardConnectionId)},r=n.get(o);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,MAX_RIPPING_PF_THRESHOLD:.9,MIN_RIPPING_PF_THRESHOLD:.1,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&&Tr({connMap:t.connMap,connectionsWithResults:e.connectionsWithResults,inputNodes:e.inputNodes,obstacles:t.srj.obstacles})}}),Za("highDensitySolver",Ua,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??[],availableJumperTypes:t.srj.availableJumperTypes}]),Za("highDensityStitchSolver",Va,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}]),Za("traceKeepoutSolver",Cr,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(),o=this.singleLayerNodeMerger?.visualize(),s=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,P=[];if(P.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]}),P.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const S={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:["obstacle",t.offBoardConnectsTo?`offboardConnections: ${t.offBoardConnectsTo?.join(", ")}`:"",t.layers?.join(", ")].filter(Boolean).join("\n")}))],lines:P},M=[S,t,e,n,o,s,i,a,c,h,d,l,u?g(S,u):null,p?g(S,p):null,m?g(S,m):null,f,y,r,x,this.solved?g(S,an(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...M)}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 o=t[n];if(e.push({points:o.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[o.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,o]of this.srj.obstacles.entries()){if(!o.offBoardConnectsTo?.length)continue;const s=o.obstacleId??`__obs${n}`;o.obstacleId=s;const i=this.connMap.getNetConnectedToId(s);if(!i)continue;const r=this.connMap.getIdsConnectedToNet(i).find(t=>e.has(t));r&&(t[s]=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 o=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,s=e.filter(t=>t.connectionName===n.name);for(let e=0;e<s.length;e++){const i=s[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??n.rootConnectionName??n.name,route:Ve(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}}};function Ja({path:t,connection:e,assignedPortPoints:n,nodeAssignedPortPoints:o}){const s=[];for(const i of t){if(!i.portPoint)continue;const t=i.portPoint;n.set(t.portPointId,{connectionName:e.name,rootConnectionName:e.rootConnectionName});const r={portPointId:t.portPointId,x:t.x,y:t.y,z:t.z,connectionName:e.name,rootConnectionName:e.rootConnectionName};s.push(r);for(const e of t.connectionNodeIds){const t=o.get(e)??[];t.push(r),o.set(e,t)}}return s}function qa(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}function Ka({connectionPoint:t,node:e}){const n=Je(t);if(0===n.length)return console.error("[addConnectionEndpointsToNodeAssignments] endpoint has no declared layers; falling back to candidate z"),[];const o=n.map(t=>function({layerName:t,node:e}){const n=Math.max(...e.availableZ,0)+1,o=Be(t,n);if(Number.isFinite(o))return o;const s=t.match(/^layer(\d+)$/);return s?Number.parseInt(s[1],10)-1:void 0}({layerName:t,node:e})).filter(t=>void 0!==t);return 0===o.length&&console.error(`[addConnectionEndpointsToNodeAssignments] endpoint has unparseable layer names: ${n.join(", ")}; falling back to candidate z`),o}function Qa({connectionPoint:t,candidate:e,node:n,endpointName:o,connection:s}){if(!n)return console.error(`[addConnectionEndpointsToNodeAssignments] ${o} endpoint for "${s.name}" missing node; using raw endpoint/candidate values`),{x:t.x,y:t.y,z:e.z};const i=function({connectionPoint:t,candidate:e,node:n,endpointName:o,connection:s}){const i=Ka({connectionPoint:t,node:n});if(0===i.length)return e.z;if(i.includes(e.z))return e.z;const r=i.reduce((t,n)=>Math.abs(n-e.z)<Math.abs(t-e.z)?n:t);return console.assert(!1,`[addConnectionEndpointsToNodeAssignments] ${o} endpoint for "${s.name}" is on z=${e.z} but endpoint allows z in [${i.join(", ")}]; using fallback z=${r}`),console.error(`[addConnectionEndpointsToNodeAssignments] ${o} endpoint for "${s.name}" layer mismatch; using fallback z=${r}`),r}({connectionPoint:t,candidate:e,node:n,endpointName:o,connection:s}),r=function({point:t,node:e}){return qa(t,e)}({point:t,node:n});if(!r){const e=function({point:t,node:e}){const n=e.center.x-e.width/2,o=e.center.x+e.width/2,s=e.center.y-e.height/2,i=e.center.y+e.height/2;return{x:Math.min(Math.max(t.x,n),o),y:Math.min(Math.max(t.y,s),i)}}({point:t,node:n});return console.assert(r,`[addConnectionEndpointsToNodeAssignments] ${o} endpoint for "${s.name}" connectionPoint outside obstacle/node bounds; original=(${t.x}, ${t.y}) clamped=(${e.x}, ${e.y})`),{x:e.x,y:e.y,z:i}}return{x:t.x,y:t.y,z:i}}function tc({path:t,connection:e,inputNodeMap:n,nodeAssignedPortPoints:o}){if(0===t.length)return;const s=t[0],i=t[t.length-1],r=e.pointsToConnect[0],a=e.pointsToConnect[e.pointsToConnect.length-1];if(r){const t=Qa({connectionPoint:r,candidate:s,node:n.get(s.currentNodeId),endpointName:"start",connection:e}),i=o.get(s.currentNodeId)??[];i.push({x:t.x,y:t.y,z:t.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),o.set(s.currentNodeId,i)}if(a){const t=Qa({connectionPoint:a,candidate:i,node:n.get(i.currentNodeId),endpointName:"end",connection:e}),s=o.get(i.currentNodeId)??[];s.push({x:t.x,y:t.y,z:t.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),o.set(i.currentNodeId,s)}}function ec({candidate:t}){return t.nextRegion?.regionId?t.nextRegion.regionId:t.port.region2?.regionId?t.port.region2.regionId:t.port.region1.regionId}function nc({point:t}){if(t)return"layers"in t&&Array.isArray(t.layers)?t.layers[0]:t.layer}function oc({layer:t,defaultZ:e}){if(!t)return e;const n=t.match(/\d+/);if(!n)return e;const o=Number.parseInt(n[0],10)-1;return Number.isFinite(o)&&o>=0?o:e}function sc({solvedRoute:t,connectionResult:e}){const n=[],o=e.connection,s=o.pointsToConnect[0],i=o.pointsToConnect[o.pointsToConnect.length-1],r=oc({layer:nc({point:s}),defaultZ:0}),a=oc({layer:nc({point:i}),defaultZ:0}),c={prevCandidate:null,portPoint:null,currentNodeId:e.nodeIds[0],point:{x:s?.x??0,y:s?.y??0},z:r,f:0,g:0,h:0,distanceTraveled:0};n.push(c);for(const e of t.path){const t=n[n.length-1],o=e.port.d,s={prevCandidate:t,portPoint:o,currentNodeId:ec({candidate:e}),point:{x:o.x,y:o.y},z:o.z,f:0,g:0,h:0,distanceTraveled:t.distanceTraveled+Pt(t.point,o)};n.push(s)}const h=n[n.length-1],d={prevCandidate:h,portPoint:null,currentNodeId:e.nodeIds[1],point:{x:i?.x??h.point.x,y:i?.y??h.point.y},z:a,f:0,g:0,h:0,distanceTraveled:h.distanceTraveled+Pt(h.point,i??h.point)};return n.push(d),n}function ic({solvedRoutes:t,connectionResults:e,inputNodes:n}){const o=new Map(e.map(t=>[t.connection.name,t])),s=new Map,i=new Map,r=new Map(n.map(t=>[t.capacityMeshNodeId,t]));for(const t of n)i.set(t.capacityMeshNodeId,[]);for(const e of t){const t=e.connection.connectionId,n=o.get(t);if(!n)continue;const a=sc({solvedRoute:e,connectionResult:n});n.path=a,n.portPoints=Ja({path:a,connection:n.connection,assignedPortPoints:s,nodeAssignedPortPoints:i}),tc({path:a,connection:n.connection,inputNodeMap:r,nodeAssignedPortPoints:i})}return{connectionsWithResults:e,assignedPortPoints:s,nodeAssignedPortPoints:i}}var rc=t=>{const e=function({solver:t}){const e=[],n=[],o=[],s=[];for(const e of t.inputNodes){const n=t.computeNodePf(e),o=Math.min(255,Math.floor(512*n)),i=Math.max(0,255-Math.floor(512*n));let r=`rgba(${o}, ${i}, ${i}, ${n<.001?"0.1":"0.3"})`;e._containsObstacle&&(r="rgba(255, 0, 0, 0.3)"),e._offBoardConnectedCapacityMeshNodeIds?.length&&(r="rgba(255, 165, 0, 0.3)"),s.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(80, 80, 120, 0.15)",fill:r,label:`${e.capacityMeshNodeId}\npf: ${n.toFixed(3)}`})}for(const e of t.portPointMap.values())n.push({center:{x:e.x,y:e.y},radius:.035,fill:"rgba(120, 120, 120, 0.3)"});for(const n of t.graph.ports){const t=n.region1.d.center,o=n.region2.d.center;e.push({points:[t,{x:n.d.x,y:n.d.y},o],strokeColor:"rgba(100, 100, 100, 0.1)",strokeWidth:.03})}for(const n of t.connections){const t=n.startRegion.d.center,s=n.endRegion.d.center,i=(t.x+s.x)/2,r=(t.y+s.y)/2;e.push({points:[t,s],strokeColor:"rgba(255, 50, 150, 0.2)",strokeWidth:.05}),o.push({x:i,y:r,color:"rgba(200, 0, 100, 0.9)",label:n.connectionId})}return{lines:e,circles:n,points:o,rects:s}}({solver:t});if(t.currentConnection&&!t.solved){const n=rt(t.currentConnection.connectionId,.8),o=t.currentConnection.startRegion,s=t.currentConnection.endRegion,i=o.d.center,r=s.d.center;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=rt(n.connection.connectionId,.8),o=[];for(const t of n.path){const e=t.port;o.push({x:e.d.x,y:e.d.y})}const s=n.connection.startRegion.d.center,i=n.connection.endRegion.d.center;o.unshift(s),o.push(i),o.length>0&&e.lines.push({points:o,strokeColor:t})}const n=t.candidateQueue.peekMany(10);for(let t=0;t<n.length;t++){const o=n[t],s=o.port,i=0===t;e.points.push({x:s.d.x,y:s.d.y,color:i?"green":"rgba(128, 128, 128, 0.55)",label:[o.port.portId,`g: ${o.g.toFixed(2)}`,`h: ${o.h.toFixed(2)}`,`f: ${o.f.toFixed(2)}`].join("\n")})}const o=n[0];if(!t.solved&&o&&t.currentConnection){const n=rt(t.currentConnection.connectionId,.8),s=[];let i=o;for(;i;){const t=i.port;s.unshift({x:t.d.x,y:t.d.y}),i=i.parent}const r=t.currentConnection.startRegion.d.center;s.unshift(r),s.length>1&&e.lines.push({points:s,strokeColor:n})}return e},ac=class extends qr{inputNodes;regionNodeMap;regionById;portPointMap;connectionsWithResults=[];assignedPortPoints=new Map;nodeAssignedPortPoints=new Map;assignmentsBuilt=!1;portUsagePenalty;regionTransitionPenalty;ripRegionPfThresholdStart;maxRegionRips;memoryPfFactor;centerOffsetDistPenaltyFactor;forceCenterFirst;straightLineDeviationPenaltyFactor;connectionResultByName;regionRipCountMap=new Map;regionMemoryPfMap=new Map;totalRipCount=0;randomRipFraction;maxRips;MIN_ALLOWED_BOARD_SCORE;constructor({inputGraph:t,inputConnections:e,connectionsWithResults:n,inputNodes:o,portPointMap:s,regionMemoryPfMap:i,rippingEnabled:r,weights:a,forceCenterFirst:c}){const{GREEDY_MULTIPLIER:h,MAX_REGION_RIPS:d,MEMORY_PF_FACTOR:l,CENTER_OFFSET_DIST_PENALTY_FACTOR:u,PORT_USAGE_PENALTY:p,REGION_TRANSITION_PENALTY:m,STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR:f,RIP_COST:g,RIP_REGION_PF_THRESHOLD_START:y,RANDOM_RIP_FRACTION:x,MAX_RIPS:v,MIN_ALLOWED_BOARD_SCORE:P}=a;super({inputGraph:t,inputConnections:e,greedyMultiplier:h,rippingEnabled:r??!0,ripCost:g}),this.inputNodes=o,this.regionNodeMap=new Map(o.map(t=>[t.capacityMeshNodeId,t])),this.regionById=new Map(this.graph.regions.map(t=>[t.regionId,t])),this.portPointMap=s,this.connectionsWithResults=n,this.portUsagePenalty=p,this.regionTransitionPenalty=m,this.ripRegionPfThresholdStart=y,this.maxRegionRips=d,this.memoryPfFactor=l,this.centerOffsetDistPenaltyFactor=u,this.forceCenterFirst=c,this.straightLineDeviationPenaltyFactor=f,this.regionMemoryPfMap=i,this.randomRipFraction=x,this.maxRips=v,this.MIN_ALLOWED_BOARD_SCORE=P,this.MAX_ITERATIONS=2e5,this.connectionResultByName=new Map(n.map(t=>[t.connection.name,t]))}clampPf(t){return Number.isFinite(t)?Math.max(0,Math.min(.9999,t)):0}pfToFailureCost(t){return-Math.log(1-this.clampPf(t))}recordRegionMemoryPf(t,e){const n=this.clampPf(e),o=this.regionMemoryPfMap.get(t)??0,s=Math.max(n,.98*o);this.regionMemoryPfMap.set(t,s)}estimateCostToEnd(t){const e=this.currentEndRegion?.d?.center;return e?Pt({x:t.d.x,y:t.d.y},e):0}computeH(t){const e=this.estimateCostToEnd(t.port),n=t.port.d.distToCentermostPortOnZ??0,o=t.nextRegion?.regionId??t.lastRegion?.regionId,s=o?this.regionMemoryPfMap.get(o)??0:0,i=this.pfToFailureCost(s)*this.memoryPfFactor,r=this.getStraightLineDeviationPenalty(t);return e+n*this.centerOffsetDistPenaltyFactor+i+r}getStraightLineDeviationPenalty(t){if(this.straightLineDeviationPenaltyFactor<=0)return 0;const e=this.currentConnection?.connectionId;if(!e)return 0;const n=this.connectionResultByName.get(e),o=n?.connection.pointsToConnect;if(!o||o.length<2)return 0;const s=o[0],i=o[1],r=vt({x:t.port.d.x,y:t.port.d.y},s,i);return this.straightLineDeviationPenaltyFactor*r}computeIncreasedRegionCostIfPortsAreUsed(t,e,n){const o=Pt({x:e.d.x,y:e.d.y},{x:n.d.x,y:n.d.y}),s=.01*Math.max(t.d.width,t.d.height);return o*this.regionTransitionPenalty+s}getPortUsagePenalty(t){return(t.ripCount??0)*this.portUsagePenalty}getRipsRequiredForPortUsage(t,e,n){const o=t.assignments??[];if(0===o.length)return[];const s={x:e.d.x,y:e.d.y},i={x:n.d.x,y:n.d.y};return o.filter(t=>{if(t.connection.mutuallyConnectedNetworkId===this.currentConnection?.mutuallyConnectedNetworkId)return!1;const o=t.regionPort1,r=t.regionPort2;if(o===e||o===n)return!1;if(r===e||r===n)return!1;const a={x:o.d.x,y:o.d.y},c={x:r.d.x,y:r.d.y};return gt(s,i,a,c)})}isPortAvailableForCurrentNet(t){const e=t.assignment;if(!e)return!0;const n=this.currentConnection?.mutuallyConnectedNetworkId;return e.connection.mutuallyConnectedNetworkId===n}getCenterFirstEnteringRegionCandidates(t){const e=new Map;for(const n of t){const t=n.port.d.z??0,o=e.get(t)??[];o.push(n),e.set(t,o)}const n=[];for(const t of e.values()){const e=t.slice().sort((t,e)=>t.port.d.distToCentermostPortOnZ-e.port.d.distToCentermostPortOnZ)[0];if(!e)continue;if(this.isPortAvailableForCurrentNet(e.port)){n.push(e);continue}const o=t.slice().sort((t,e)=>t.port.d.x!==e.port.d.x?t.port.d.x-e.port.d.x:t.port.d.y-e.port.d.y),s=[];let i=[];for(const t of o)this.isPortAvailableForCurrentNet(t.port)?i.push(t):i.length>0&&(s.push(i),i=[]);i.length>0&&s.push(i);for(const t of s)n.push(t[Math.floor(t.length/2)])}return n}selectCandidatesForEnteringRegion(t){const e=this.currentConnection?.startRegion,n=this.currentConnection?.endRegion,o=t.filter(t=>{const o=t.nextRegion;return!o?.d._containsObstacle||(o===e||o===n)}),s=this.forceCenterFirst?this.getCenterFirstEnteringRegionCandidates(o):o;return s.length<=2?s:s.slice().sort((t,e)=>t.g+t.h-(e.g+e.h)).slice(0,2)}routeSolvedHook(t){const e=new Set;for(const n of t.path){const t=n.lastRegion;t&&e.add(t)}for(const t of e){const e=this.computeRegionPfFromAssignments(t);this.recordRegionMemoryPf(t.regionId,e)}if(!t.requiredRip)return;if(this.unprocessedConnections.length<2)return;const[n,...o]=this.unprocessedConnections;this.unprocessedConnections=[...o,n]}_step(){super._step(),this.enforceBoardScoreGuardrail()||this.buildAssignmentsIfSolved()}enforceBoardScoreGuardrail(){if(!this.solved||this.failed)return!1;const t=this.computeBoardScore();return this.stats={...this.stats,boardScore:t,totalRipCount:this.totalRipCount},!(t>=this.MIN_ALLOWED_BOARD_SCORE)&&(this.error=`Board score ${t.toFixed(2)} is less than MIN_ALLOWED_BOARD_SCORE ${this.MIN_ALLOWED_BOARD_SCORE.toFixed(2)}`,this.failed=!0,this.solved=!1,!0)}buildAssignmentsIfSolved(){if(!this.solved||this.assignmentsBuilt)return;const t=ic({solvedRoutes:this.solvedRoutes,connectionResults:this.connectionsWithResults,inputNodes:this.inputNodes});this.connectionsWithResults=t.connectionsWithResults,this.assignedPortPoints=t.assignedPortPoints,this.nodeAssignedPortPoints=t.nodeAssignedPortPoints,this.assignmentsBuilt=!0}getRegionRippingPfThreshold(t){const e=this.regionRipCountMap.get(t)??0,n=Math.min(1,e/this.maxRegionRips);return this.ripRegionPfThresholdStart*(1-n)+1*n}getPortPointsFromRegionAssignments(t){return t.flatMap(t=>{const e=t.regionPort1,n=t.regionPort2,o=t.connection.connectionId,s=t.connection.mutuallyConnectedNetworkId;return[{x:e.d.x,y:e.d.y,z:e.d.z,connectionName:o,rootConnectionName:s},{x:n.d.x,y:n.d.y,z:n.d.z,connectionName:o,rootConnectionName:s}]})}getPortPointsFromNewlySolvedRouteInRegion(t,e){return t.path.flatMap(n=>{if(!n.lastPort||n.lastRegion!==e)return[];const o=n.lastPort,s=n.port;return[{x:o.d.x,y:o.d.y,z:o.d.z,connectionName:t.connection.connectionId,rootConnectionName:t.connection.mutuallyConnectedNetworkId},{x:s.d.x,y:s.d.y,z:s.d.z,connectionName:t.connection.connectionId,rootConnectionName:t.connection.mutuallyConnectedNetworkId}]})}computeRegionPf({region:t,newlySolvedRoute:e,routesToRip:n}){const o=this.regionNodeMap.get(t.regionId);if(!o||o._containsTarget)return 0;const s=(t.assignments??[]).filter(t=>!n.has(t.solvedRoute)),i=[...this.getPortPointsFromRegionAssignments(s),...this.getPortPointsFromNewlySolvedRouteInRegion(e,t)],r={capacityMeshNodeId:o.capacityMeshNodeId,center:o.center,width:o.width,height:o.height,portPoints:i,availableZ:o.availableZ},a=zs(r),c=this.getDerivedCapacityMeshNode(o);return Rs(c,a.numSameLayerCrossings,a.numEntryExitLayerChanges,a.numTransitionPairCrossings)}computeRegionPfFromAssignments(t){const e=this.regionNodeMap.get(t.regionId);if(!e||e._containsTarget)return 0;const n=t.assignments??[],o=this.getPortPointsFromRegionAssignments(n),s={capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:o,availableZ:e.availableZ},i=zs(s),r=this.getDerivedCapacityMeshNode(e);return Rs(r,i.numSameLayerCrossings,i.numEntryExitLayerChanges,i.numTransitionPairCrossings)}getDerivedCapacityMeshNode(t){return{capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,availableZ:t.availableZ,layer:`z${t.availableZ.join(",")}`,_containsObstacle:t._containsObstacle,_containsTarget:t._containsTarget,_offBoardConnectionId:t._offBoardConnectionId,_offBoardConnectedCapacityMeshNodeIds:t._offBoardConnectedCapacityMeshNodeIds}}getCrossingRoutesByRegionForRoute(t){const e=new Map;for(const n of t.path){if(!n.lastPort||!n.lastRegion)continue;const t=n.lastRegion,o=t.regionId,s=this.getRipsRequiredForPortUsage(t,n.lastPort,n.port);if(0===s.length)continue;const i=e.get(o)??new Set;for(const t of s)i.add(t.solvedRoute);e.set(o,i)}return e}getRoutesInRegionForRipping({regionId:t,routesToRip:e,newlySolvedRoute:n}){const o=this.regionById.get(t);if(!o?.assignments?.length)return[];const s=new Map;for(const t of o.assignments){const o=t.solvedRoute,i=o.connection.connectionId;i!==n.connection.connectionId&&(e.has(o)||s.set(i,o))}return[...s.values()]}getTraversedRegionIds(t){const e=new Set;for(const n of t.path){const t=n.lastRegion;t&&e.add(t.regionId)}return[...e]}processRandomRips({routesToRip:t,newlySolvedRoute:e,randomSeed:n}){if(this.randomRipFraction<=0)return;if(this.totalRipCount>=this.maxRips)return;const o=this.solvedRoutes.filter(n=>!t.has(n)&&n.connection.connectionId!==e.connection.connectionId);if(0===o.length)return;const s=Math.max(1,Math.floor(this.randomRipFraction*o.length)),i=Bt(o,n);let r=0;for(const e of i){if(r>=s)break;if(this.totalRipCount>=this.maxRips)break;t.has(e)||(t.add(e),r++,this.totalRipCount++)}}processRippingForRoute(t){const e=super.computePortOverlapRoutes(t),n=new Set(e),o=this.getCrossingRoutesByRegionForRoute(t),s=this.iterations+this.solvedRoutes.length+this.totalRipCount,i=this.getTraversedRegionIds(t),r=Bt(Array.from(new Set([...i,...o.keys()])),s);for(const e of r){if(this.totalRipCount>=this.maxRips)break;const o=this.regionById.get(e);if(!o)continue;const i=this.getRegionRippingPfThreshold(e);let r=this.computeRegionPf({region:o,newlySolvedRoute:t,routesToRip:n});if(this.recordRegionMemoryPf(e,r),r<=i)continue;const a=new Set;let c=0;for(;r>i&&!(this.totalRipCount>=this.maxRips);){const i=this.getRoutesInRegionForRipping({regionId:e,routesToRip:n,newlySolvedRoute:t}).filter(t=>!a.has(t.connection.connectionId)&&!n.has(t));if(0===i.length)break;const h=Bt(i,s+c+a.size)[0];if(!h)break;a.add(h.connection.connectionId),n.add(h),this.totalRipCount++,c++,this.regionRipCountMap.set(e,(this.regionRipCountMap.get(e)??0)+1),r=this.computeRegionPf({region:o,newlySolvedRoute:t,routesToRip:n}),this.recordRegionMemoryPf(e,r)}}return n.size>e.size&&this.processRandomRips({routesToRip:n,newlySolvedRoute:t,randomSeed:s+1e4}),n}computeRoutesToRip(t){return this.processRippingForRoute(t)}getNodesWithPortPoints(){const t=[];for(const e of this.inputNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];0!==n.length&&t.push({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ})}return t}computeBoardScore(){let t=this.nodeAssignedPortPoints;if(!this.assignmentsBuilt){t=ic({solvedRoutes:this.solvedRoutes,connectionResults:this.connectionsWithResults,inputNodes:this.inputNodes}).nodeAssignedPortPoints}const e=[];for(const n of this.inputNodes){const o=t.get(n.capacityMeshNodeId)??[];0!==o.length&&e.push({capacityMeshNodeId:n.capacityMeshNodeId,center:n.center,width:n.width,height:n.height,portPoints:o,availableZ:n.availableZ})}return Ws(e,new Map(this.inputNodes.map(t=>[t.capacityMeshNodeId,this.getDerivedCapacityMeshNode(t)])))}computeNodePf(t){const e=this.nodeAssignedPortPoints.get(t.capacityMeshNodeId);if(!e||0===e.length)return 0;const n={capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:e,availableZ:t.availableZ},o=zs(n),s=this.getDerivedCapacityMeshNode(t);return Rs(s,o.numSameLayerCrossings,o.numEntryExitLayerChanges,o.numTransitionPairCrossings)}visualize(){return rc(this)}};function cc(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var hc=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,o=t.bounds.maxY-t.bounds.minY,s=Math.max(n,o),i=e.targetMinCapacity??.5;e.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(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;uniformPortDistributionSolver;traceWidthSolver;viaDiameter;minTraceWidth;effort;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;inputNodeWithPortPoints=[];cacheProvider=null;pipelineDef=[cc("netToPointPairsSolver",vn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),cc("nodeSolver",es,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),cc("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),cc("availableSegmentPointSolver",Es,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),cc("portPointPathingSolver",ac,t=>{this.inputNodeWithPortPoints=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}));const e=new Map(this.inputNodeWithPortPoints.map(t=>[t.capacityMeshNodeId,t])),n=t.availableSegmentPointSolver;for(const t of n.sharedEdgeSegments)for(const n of t.portPoints){const[t,o]=n.nodeIds,s={portPointId:n.segmentPortPointId,x:n.x,y:n.y,z:n.availableZ[0]??0,connectionNodeIds:[t,o],distToCentermostPortOnZ:n.distToCentermostPortOnZ},i=e.get(t);i&&i.portPoints.push(s)}const{graph:o,regionMap:s,portPointMap:i}=function({inputNodes:t}){const e=new Map,n=new Map,o=[],s=[];for(const n of t){const t={regionId:n.capacityMeshNodeId,ports:[],assignments:[],d:n};o.push(t),e.set(n.capacityMeshNodeId,t)}for(const o of t)for(const t of o.portPoints){if(n.has(t.portPointId))continue;n.set(t.portPointId,t);const[o,i]=t.connectionNodeIds,r=e.get(o),a=e.get(i);if(!r||!a)continue;const c={portId:t.portPointId,region1:r,region2:a,d:t};s.push(c),r.ports.push(c),a.ports.push(c)}return{graph:{regions:o,ports:s},regionMap:e,portPointMap:n}}({inputNodes:this.inputNodeWithPortPoints}),{connections:r,connectionsWithResults:a}=function({simpleRouteJson:t,inputNodes:e,regionMap:n}){const{unshuffledConnectionsWithResults:o}=ks(t,e),s=[];for(const t of o){const e=n.get(t.nodeIds[0]),o=n.get(t.nodeIds[1]);if(!e||!o)throw new Error(`Missing region for connection "${t.connection.name}"`);s.push({connectionId:t.connection.name,mutuallyConnectedNetworkId:t.connection.rootConnectionName??t.connection.name,startRegion:e,endRegion:o})}return{connections:s,connectionsWithResults:o}}({simpleRouteJson:t.srjWithPointPairs,inputNodes:this.inputNodeWithPortPoints,regionMap:s});return[{inputGraph:o,inputConnections:r,connectionsWithResults:a,inputNodes:this.inputNodeWithPortPoints,portPointMap:i,rippingEnabled:!0,weights:{PORT_USAGE_PENALTY:.15,REGION_TRANSITION_PENALTY:.6,MEMORY_PF_FACTOR:4,CENTER_OFFSET_DIST_PENALTY_FACTOR:.05,STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR:4,RIP_COST:8.5,GREEDY_MULTIPLIER:.7,RIP_REGION_PF_THRESHOLD_START:.3,MAX_REGION_RIPS:100,MAX_RIPS:1e3,RANDOM_RIP_FRACTION:.3,MIN_ALLOWED_BOARD_SCORE:-1e4},forceCenterFirst:!0,regionMemoryPfMap:new Map}]}),cc("uniformPortDistributionSolver",ai,t=>[{nodeWithPortPoints:t.portPointPathingSolver?.getNodesWithPortPoints()??[],inputNodesWithPortPoints:this.inputNodeWithPortPoints,minTraceWidth:t.minTraceWidth,obstacles:t.srj.obstacles,layerCount:t.srj.layerCount}]),cc("highDensityRouteSolver",Ye,t=>[{nodePortPoints:t.uniformPortDistributionSolver?.getOutput()??t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),cc("highDensityStitchSolver",rn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),cc("traceSimplificationSolver",_s,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}]),cc("traceWidthSolver",ci,t=>[{hdRoutes:t.traceSimplificationSolver.simplifiedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,minTraceWidth:t.minTraceWidth,connection:t.srj.connections}])];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(),o=this.singleLayerNodeMerger?.visualize(),s=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.uniformPortDistributionSolver?.visualize(),l=this.highDensityRouteSolver?.visualize(),u=this.highDensityStitchSolver?.visualize(),p=this.traceSimplificationSolver?.visualize(),m=this.srj.outline,f=[];if(f.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),m&&m.length>=2){const t=m.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),f.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const y={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:f},x=[y,t,e,n,o,s,i,r,a,c,h,d,l?g(y,l):null,u,p,this.solved?g(y,an(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...x)}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.traceWidthSolver?.getHdRoutesWithWidths()??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 o=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,s=e.filter(t=>t.connectionName===n.name);for(let e=0;e<s.length;e++){const i=s[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??n.rootConnectionName??n.name,route:Ve(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},dc=class extends mi{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)||[],o=n.layers&&n.layers.length>0?Array.from(new Set(n.layers.map(t=>Be(t,this.srj.layerCount)))).sort((t,e)=>t-e):Array.from({length:this.srj.layerCount},(t,e)=>this.srj.layerCount-e-1);let s=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,o=e.center.y-e.height/2,c=e.center.y+e.height/2;s=Math.min(s,t),i=Math.max(i,n),r=Math.min(r,o),a=Math.max(a,c)}const c=i-s,h=a-r,d=(s+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>=s&&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===o.length?`z${o[0]}`:`z${o.join(",")}`,availableZ:o,_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=[],o=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),s=t.availableZ.length>1&&!e;if(e)o.push(t);else{if(s){const e=this.getZSubdivisionChildNodes(t);for(const t of e)!t._containsTarget&&this.shouldFilterNodeForObstacle(t)||(this.shouldNodeBeXYSubdivided(t)?o.push(t):(t._containsObstacle=!1,n.push(t)));continue}this.shouldFilterNodeForObstacle(t)&&!t._containsTarget||n.push(t)}}this.unfinishedNodes.push(...o),this.finishedNodes.push(...n)}},lc=.005,uc=class extends y{getSolverName(){return"SingleLayerNodeMergerSolver_OnlyMergeTargets"}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 o=0;o<=e;o++)n.push(new dn(t.filter(t=>t.availableZ[0]===o)));for(const e of t){const t=[],o=n[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const n of o)n._containsTarget&&n._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!n._containsTarget||n._targetConnectionName!==e._targetConnectionName)||n.capacityMeshNodeId!==e.capacityMeshNodeId&&cn(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),o=this.nodeMap.get(e);return n.width*n.height-o.width*o.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 o=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===o.length)return void this.nextBatchNodeIds.push(t);const s=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=o.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:o}=i[0],r=i.every(e=>e.width===t&&e.height===o);Math.abs(i.reduce((t,e)=>t+e.height,0)-e.height)<lc&&r&&(e.width+=t,e.center.x=e.center.x-t/2,s(i),n=!0)}const r=o.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:o}=r[0],i=r.every(e=>e.width===t&&e.height===o);Math.abs(r.reduce((t,e)=>t+e.height,0)-e.height)<lc&&i&&(e.width+=t,e.center.x=e.center.x+t/2,s(r),n=!0)}const a=o.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:o}=a[0],i=a.every(e=>e.width===t&&e.height===o);Math.abs(a.reduce((t,e)=>t+e.width,0)-e.width)<lc&&i&&(e.height+=o,e.center.y=e.center.y+o/2,s(a),n=!0)}const c=o.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:o}=c[0],i=c.every(e=>e.width===t&&e.height===o);Math.abs(c.reduce((t,e)=>t+e.width,0)-e.width)<lc&&i&&(e.height+=o,e.center.y=e.center.y-o/2,s(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(Oi(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let n;e&&(n=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const o of this.currentBatchNodeIds){const s=this.nodeMap.get(o);if(!this.absorbedNodeIds.has(o)&&s){const i=Oi(s,{rectMargin:.01});o===e?i.stroke="rgba(0, 255, 0, 0.8)":n?.some(t=>t.capacityMeshNodeId===o)?i.stroke="rgba(128, 0, 128, 0.8)":i.stroke="rgba(255, 165, 0, 0.8)",i.layer=`z${s.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=Oi(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}},pc=class extends y{getSolverName(){return"AssignableViaNodeMergerSolver"}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,o=Number.NEGATIVE_INFINITY,s=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),o=Math.max(o,c),s=Math.min(s,h),i=Math.max(i,d);for(const e of t.availableZ)r.add(e);t._containsTarget&&(a=!0)}const c=o-n,h=i-s,d=(n+o)/2,l=(s+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=Oi(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=Oi(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}},mc=class extends y{constructor(t){const{simpleRouteJson:e,nodes:n,edges:o,colorMap:s,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=o,this.colorMap=s??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Ts(this.edges);const a=this.nodes.filter(t=>t._containsTarget);this.unprocessedConnectionPairs=Bt(this.simpleRouteJson.connections.map(t=>{const[e,n]=t.pointsToConnect;return{start:a.find(t=>Pt(t.center,e)<t.width/2),end:a.find(t=>Pt(t.center,n)<t.width/2),connection:t}}),this.hyperParameters.SHUFFLE_SEED??0),this.viaNodes=this.nodes.filter(t=>t.availableZ.length>1)}getSolverName(){return"AssignableViaCapacityPathingSolver_DirectiveSubOptimal"}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 o=this._dist(e,t.start);return this._dist(n,t.start)<o?n:e});this.closestViaForConnectionStartMap.set(t,n);const o=e.reduce((e,n)=>{const o=this._dist(e,t.end);return this._dist(n,t.end)<o?n:e});this.closestViaForConnectionEndMap.set(t,o)}}}_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),o={prevCandidate:null,node:e,g:0,h:t,f:this.GREEDY_MULTIPLIER*t};this.queuedCandidateNodes.push(o)}let o;for(this.queuedCandidateNodes.sort((t,e)=>t.f-e.f);this.queuedCandidateNodes.length&&!o;){const t=this.queuedCandidateNodes.shift();this.visitedNodes.has(t.node.capacityMeshNodeId)||(o=t)}if(!o)return this.failed=!0,void(this.error="No viable candidates left");if(this.visitedNodes.add(o.node.capacityMeshNodeId),o.node.capacityMeshNodeId===n.capacityMeshNodeId){const e=[];let n=o;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 s=this.getNeighbors(o.node);for(const t of s){const e=t.capacityMeshNodeId;if(this.visitedNodes.has(e))continue;const s=this.computeG(o,t,n),i=this.computeH(o,t,n),r=s+this.GREEDY_MULTIPLIER*i,a=this.queuedCandidateNodes.findIndex(t=>t.node.capacityMeshNodeId===e);if(a>=0){if(this.queuedCandidateNodes[a].g<=s)continue;this.queuedCandidateNodes.splice(a,1)}this.queuedCandidateNodes.push({prevCandidate:o,node:t,g:s,h:i,f:r})}}getNeighbors(t){const e=new Set,n=this.nodeEdgeMap.get(t.capacityMeshNodeId)??[];for(const o of n){const[n,s]=o.nodeIds,i=n===t.capacityMeshNodeId?s:n,r=this.nodeMap.get(i);r&&e.add(r)}const o=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!==o&&!t.availableZ.includes(o)))))}clearCandidateNodes(){this.queuedCandidateNodes=[],this.visitedNodes=new Set}computeG(t,e,n){const o=this._dist(t.node,e);return t.g+o}computeH(t,e,n){return this._dist(e,n)}createSolvedRoute(t,e){const n=[];for(let e=0;e<t.length;e++){const o=t[e];o.path?0===e?n.push(...o.path):n.push(...o.path.slice(1)):(0===e&&n.push(o.start),e===t.length-1&&n.push(o.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 o=this.getClosestVia(t.start),s=this.getFarVia(o,t.end),i=t.start.availableZ[0]??0,r=t.end.availableZ[0]??0,a=[];return a.push({start:t.start,end:o,solved:!1,layer:i}),i===r?(a.push({start:o,end:s,solved:!1,layer:0===i?1:0}),a.push({start:s,end:t.end,solved:!1,layer:r})):a.push({start:o,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 o=this.hyperParameters.MAX_CLOSEST_VIA_SKIP??0;if(o>0&&n.length>1){const t=Yt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length),e=Math.floor(t()*(o+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,o=new Set;for(const[t,e]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&o.add(e.capacityMeshNodeId);for(const[t,e]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&o.add(e.capacityMeshNodeId);const s=this.viaNodes.filter(e=>!this.usedNodeMap.has(e.capacityMeshNodeId)&&e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!o.has(e.capacityMeshNodeId)&&this._dist(e,t)>=n);if(0===s.length){const o=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(o.length>0)return o[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}s.sort((t,n)=>this._dist(t,e)-this._dist(n,e));const i=this.hyperParameters.MAX_FURTHEST_VIA_SKIP??0;if(i>0&&s.length>1){const t=Yt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length+1e3),e=Math.floor(t()*(i+1));return s[Math.min(e,s.length-1)]}return s[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 o of this.nodes){const s=this.queuedCandidateNodes.some(t=>t.node.capacityMeshNodeId===o.capacityMeshNodeId),i=this.queuedCandidateNodes.find(t=>t.node.capacityMeshNodeId===o.capacityMeshNodeId);if(e(o.center)&&n(o.width)&&n(o.height)){const e=Oi(o,{rectMargin:.025,zOffset:.01});t.rects.push({...e,fill:s?"rgba(255, 128, 255, 0.5)":o._containsTarget?"rgba(0, 150, 255, 0.15)":o._containsObstacle?"rgba(255, 0, 0, 0.1)":"rgba(200, 200, 200, 0.05)",label:[`ID: ${o.capacityMeshNodeId}`,`Size: ${o.width.toFixed(2)}x${o.height.toFixed(2)}`,`Z: ${o.availableZ.join(", ")}`,i?`g: ${i.g.toFixed(2)}`:"",i?`h: ${i.h.toFixed(2)}`:"",i?`f: ${i.f.toFixed(2)}`:"",o._containsTarget?"TARGET":"",o._containsObstacle?"OBSTACLE":""].filter(t=>t).join("\n")})}}for(const n of this.edges){const[o,s]=n.nodeIds,i=this.nodeMap.get(o),r=this.nodeMap.get(s);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 o=this.solvedRoutes[n],s=o.path,i="blue";for(let o=0;o<s.length-1;o++){const r=s[o],a=s[o+1];if(r?.center&&a?.center&&e(r.center)&&e(a.center)){const e=r.availableZ.includes(1)&&a.availableZ.includes(1),o=n%5*.02;t.lines.push({points:[{x:r.center.x+o,y:r.center.y+o},{x:a.center.x+o,y:a.center.y+o}],strokeColor:i,strokeDash:e?"5 5":void 0})}}if(s.length>0){const n=s[0],i=s[s.length-1];n?.center&&e(n.center)&&t.points.push({x:n.center.x,y:n.center.y,label:`START: ${o.connection.name}`}),i?.center&&e(i.center)&&t.points.push({x:i.center.x,y:i.center.y,label:`END: ${o.connection.name}`})}}if(this.solvedSubpaths)for(let n=0;n<this.solvedSubpaths.length;n++){const o=this.solvedSubpaths[n];if(o.path&&o.path.length>1)for(let n=0;n<o.path.length-1;n++){const s=o.path[n],i=o.path[n+1];s?.center&&i?.center&&e(s.center)&&e(i.center)&&t.lines.push({points:[s.center,i.center],strokeColor:"green",strokeDash:1===o.layer?"3 3":void 0})}}if(this.activeSubpath){const n=this.activeSubpath.start?.center,o=this.activeSubpath.end?.center;n&&o&&e(n)&&e(o)&&(t.lines.push({points:[n,o],strokeColor:"orange",strokeDash:"5 5"}),t.points.push({x:n.x,y:n.y,label:"ACTIVE START"}),t.points.push({x:o.x,y:o.y,label:"ACTIVE END"}))}const o=this.queuedCandidateNodes.slice(0,10).sort((t,e)=>t.f-e.f);for(let n=0;n<o.length;n++){const s=.6*(1-n/10),i=[];let r=o[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-s),strokeDash:1===this.activeSubpath?.layer?"4 2":void 0})}}if(this.activeConnectionPair){const n=this.activeConnectionPair.start?.center,o=this.activeConnectionPair.end?.center;n&&o&&e(n)&&e(o)&&t.lines.push({points:[n,o],strokeColor:"cyan",strokeDash:"20 5"})}if(this.ogUnprocessedSubpaths&&3===this.ogUnprocessedSubpaths.length){const[,o]=this.ogUnprocessedSubpaths;if(o.start?.center&&e(o.start.center)){const e=Math.max(o.start.width||0,o.start.height||0);n(e)&&e>0&&(t.circles.push({center:o.start.center,radius:e,stroke:"blue"}),t.points.push({x:o.start.center.x,y:o.start.center.y,label:"DIRECTIVE VIA 1"}))}if(o.end?.center&&e(o.end.center)){const e=Math.max(o.end.width||0,o.end.height||0);n(e)&&e>0&&(t.circles.push({center:o.end.center,radius:e,stroke:"purple"}),t.points.push({x:o.end.center.x,y:o.end.center.y,label:"DIRECTIVE VIA 2"}))}}if(this.queuedCandidateNodes.length>0)for(const n of this.queuedCandidateNodes){const o=n.node;o?.center&&e(o.center)&&t.circles.push({center:o.center,radius:.05,fill:"rgba(255, 255, 0, 0.6)",stroke:"yellow"})}if(this.visitedNodes.size>0)for(const n of this.visitedNodes){const o=this.nodeMap.get(n);o?.center&&e(o.center)&&t.circles.push({center:o.center,radius:.08,fill:"rgba(128, 128, 128, 0.5)",stroke:"gray"})}return t}},fc=class extends Zt{getSolverName(){return"HyperAssignableViaCapacityPathingSolver"}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,o=e>0?n/e:0;return t.iterations/t.MAX_ITERATIONS+(1-o)}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 mc({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}};function gc(t){const e=new Map;for(const n of t)e.set(n.capacityMeshNodeId,n);return e}function yc(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var xc=class extends y{getSolverName(){return"OffboardCapacityNodeSolver"}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=gc(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 o of n.offBoardConnectsTo)t.has(o)||t.set(o,[]),t.get(o).push(e)}this.pendingEdges=[];for(const[e,n]of t)if(n.length>1)for(let t=0;t<n.length;t++)for(let o=t+1;o<n.length;o++)this.pendingEdges.push({node1:n[t],node2:n[o],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(),o=this.createOffboardEdge(t,e,n);this.enhancedEdges.push(o),this.createdEdges.push(o)}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=[],o=new Set(this.shownNodes.map(t=>t.capacityMeshNodeId));for(const e of this.capacityEdges){if(e.isOffboardEdge)continue;if(o.has(e.nodeIds[0])||o.has(e.nodeIds[1])){const n=this.nodeMap.get(e.nodeIds[0]),o=this.nodeMap.get(e.nodeIds[1]);n&&o&&t.push({points:[n.center,o.center],strokeColor:"rgba(0, 200, 0, 0.5)",strokeWidth:.05})}}for(let t=0;t<this.shownNodes.length;t++){const o=this.shownNodes[t],s=o._assignedViaObstacle,i=t===this.shownNodes.length-1&&"showing_nodes"===this.animationState;n.push({center:o.center,width:o.width,height:o.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:o.center.x,y:o.center.y,color:i?"orange":"blue",label:`${i?"NEW: ":""}${o.capacityMeshNodeId}\n${s?.offBoardConnectsTo?.join(", ")||""}`})}for(let n=0;n<this.createdEdges.length;n++){const o=this.createdEdges[n],s=n===this.createdEdges.length-1&&"showing_edges"===this.animationState,i=this.nodeMap.get(o.nodeIds[0]),r=this.nodeMap.get(o.nodeIds[1]);if(i&&r){t.push({points:[i.center,r.center],strokeColor:s?"red":"orange",strokeWidth:s?.2:.1,strokeDasharray:"0.3,0.15"});const n=yc(i.center,r.center);e.push({x:n.x,y:n.y,color:s?"red":"orange",label:`${s?"NEW: ":""}⚡ ${o.offboardNetName}`})}}let s="Offboard Capacity Node Solver";switch(this.animationState){case"showing_nodes":s+=` - Showing nodes (${this.shownNodes.length}/${this.shownNodes.length+this.assignableNodes.length})`;break;case"showing_edges":s+=` - Creating edges (${this.createdEdges.length}/${this.createdEdges.length+this.pendingEdges.length})`;break;case"done":s+=` - Done (${this.shownNodes.length} nodes, ${this.createdEdges.length} edges)`}return{lines:t,points:e,rects:n,title:s}}getVirtualOffboardNodes(){return[]}getOffboardEdges(){return this.enhancedEdges.filter(t=>t.isOffboardEdge)}},vc=class extends y{getSolverName(){return"OffboardPathFragmentSolver"}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:o}){super(),this.inputPaths=[...t],this.capacityEdges=e,this.originalConnections=o,this.nodeMap=gc(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 o=e[t];if(!o.isFragmentedPath)continue;const s=n.pointsToConnect.filter(t=>{for(const e of o.nodeIds){const n=this.nodeMap.get(e);if(n&&qa(t,n))return!0}return!1}),i=0===t,r=i?o.nodeIds[o.nodeIds.length-1]:o.nodeIds[0],a=this.nodeMap.get(r);if(s.length>0&&a){const t=s[0],e={x:a.center.x,y:a.center.y,layer:Ge(t)},r=i?[...s,e]:[e,...s];this.fragmentedConnections.push({name:o.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 o=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]);o&&o.isOffboardEdge&&n.push(t)}if(0===n.length)return[t];const o=[];let s=0,i=0;for(const r of n){const n=e.slice(s,r+1);if(n.length>=1){const e=this.nextFragmentId++;o.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${i++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}s=r+1}if(s<e.length){const n=e.slice(s);if(n.length>=1){const e=this.nextFragmentId++;o.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${i++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}}return o.length>0?o:[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((o,s)=>{if(o.isFragmentedPath){const i=s%2==0?"blue":"red";this.drawPath({path:o,color:i,lines:t,points:e,rects:n,labelPrefix:`Frag ${s}: `})}else this.drawPath({path:o,color:"green",lines:t,points:e,rects:n,labelPrefix:""})}),"showing_fragment"===this.animationState&&this.currentFragmentIndex>0){const o=this.fragmentedPaths.length-1;if(o>=0){const s=this.fragmentedPaths[o];s.isFragmentedPath&&this.drawPath({path:s,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]),o=this.nodeMap.get(e.nodeIds[1]);n&&o&&t.push({points:[n.center,o.center],strokeColor:"orange",strokeWidth:.15,strokeDasharray:"0.3,0.15"})}let o="Offboard Path Fragment Solver";return"showing_original_path"===this.animationState?o+=" - Analyzing path...":"showing_fragment"===this.animationState?o+=` - Fragment ${this.currentFragmentIndex}/${this.currentFragments.length}`:o+=` - Done (${this.fragmentedPaths.filter(t=>t.isFragmentedPath).length} fragments)`,{lines:t,points:e,rects:n,title:o}}drawPath(t){const{path:e,color:n,lines:o,points:s,rects:i,labelPrefix:r}=t,a=[];for(let t=0;t<e.nodeIds.length;t++){const o=e.nodeIds[t],c=this.nodeMap.get(o);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||s.push({x:c.center.x,y:c.center.y,color:n,label:`${r}${e.connectionName}\n${o}`}))}a.length>1&&o.push({points:a,strokeColor:n,strokeWidth:.1})}};function Pc(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var Sc=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,o=t.bounds.maxY-t.bounds.minY,s=Math.max(n,o),i=e.targetMinCapacity??.5;e.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===e.cacheProvider?ut():null===e.cacheProvider?null:e.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getSolverName(){return"AssignableAutoroutingPipeline1Solver"}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=[Pc("netToPointPairsSolver",xn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),Pc("nodeSolver",dc,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),Pc("mergeAssignableViaNodes",pc,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.mergeAssignableViaNodes?.newNodes}}),Pc("singleLayerNodeMerger",uc,t=>[t.capacityNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),Pc("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Pc("offboardCapacityNodeSolver",xc,t=>[{capacityNodes:t.capacityNodes,capacityEdges:t.capacityEdges||[]}],{onSolved:t=>{t.capacityEdges=t.offboardCapacityNodeSolver?.enhancedEdges||t.capacityEdges}}),Pc("deadEndSolver",Qi,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)))}}),Pc("initialPathingHyperSolver",fc,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)}}),Pc("offboardPathFragmentSolver",vc,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 o=e.getFragmentedOriginalConnectionNames(),s=e.getFragmentedConnections();o.size>0&&t.srjWithPointPairs&&(t.srjWithPointPairs={...t.srjWithPointPairs,connections:[...t.srjWithPointPairs.connections.filter(t=>!o.has(t.name)),...s]},t.connMap=je(t.srjWithPointPairs))}}),Pc("edgeToPortSegmentSolver",fi,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.offboardPathFragmentSolver?.getFragmentedPaths()||t.initialPathingSolver?.getCapacityPaths()||[],colorMap:t.colorMap}]),Pc("segmentToPointSolver",Pi,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),Pc("unravelMultiSectionSolver",Ai,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),Pc("highDensityRouteSolver",Ye,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap}]),Pc("highDensityStitchSolver",rn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Pc("uselessViaRemovalSolver1",us,t=>[{unsimplifiedHdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Pc("multiSimplifiedPathSolver1",Is,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver1?.getOptimizedHdRoutes()||t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}]),Pc("uselessViaRemovalSolver2",us,t=>[{unsimplifiedHdRoutes:t.multiSimplifiedPathSolver1.simplifiedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Pc("multiSimplifiedPathSolver2",Is,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(),o=this.mergeAssignableViaNodes?.visualize(),s=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(),P=this.multiSimplifiedPathSolver2?.visualize(),S=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)"}),S&&S.length>=2){const t=S.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),M.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const b={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:t.layers?.join(", ")}))],lines:M},N=[b,t,e,n,o,s,i,r,a,c,h,d,l,u,p,m?g(b,m):null,f,y,v,x,P,this.solved?g(b,an(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 o of n){const n=o.netConnectionName,s=o.rootConnectionName,i=e.filter(t=>t.connectionName===o.name);for(let e=0;e<i.length;e++){const r=i[e],a={type:"pcb_trace",pcb_trace_id:`${o.name}_${e}`,connection_name:n??s??o.name,route:Ve(r,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Mc=1.8,bc=.95,Nc=.8,Ic=.95,Cc=class extends y{getSolverName(){return"SingleHighDensityRouteWithJumpersSolver"}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=Pt(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 o=this.boundsSize.width/this.cellStep,s=this.boundsSize.height/this.cellStep;for(;o*s>n**2&&!(this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,o=this.boundsSize.width/this.cellStep,s=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR;const i=Math.abs(this.A.x-this.bounds.minX)<.001&&Math.abs(this.B.x-this.bounds.minX)<.001||Math.abs(this.A.x-this.bounds.maxX)<.001&&Math.abs(this.B.x-this.bounds.maxX)<.001||Math.abs(this.A.y-this.bounds.minY)<.001&&Math.abs(this.B.y-this.bounds.minY)<.001||Math.abs(this.A.y-this.bounds.maxY)<.001&&Math.abs(this.B.y-this.bounds.maxY)<.001;this.futureConnections&&0===this.futureConnections.length&&0===this.obstacleRoutes.length&&!i&&this.handleSimpleCases();const 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 Mc+this.straightLineDistance*this.JUMPER_PENALTY_FACTOR}isNodeTooCloseToObstacle(t,e){e??=this.obstacleMargin;for(const n of this.obstacleRoutes){const o=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!o){const o=_c(n);for(const n of o)if(vt(t,n.A,n.B)<this.traceThickness+e)return!0}for(const o of n.jumpers||[])if(this.isNodeTooCloseToJumper(t,o,e))return!0}return!1}isNodeTooCloseToJumper(t,e,n){const o=e.end.x-e.start.x,s=e.end.y-e.start.y,i=Math.abs(o)>Math.abs(s),r=(i?Nc:Ic)/2+n,a=(i?Ic:Nc)/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||!(Pt(t,this.B)<2*e||Pt(t,this.A)<2*e))&&n}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const n of this.obstacleRoutes){const o=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!o){for(const o of _c(n))if(gt(t,e,o.A,o.B))return!0;for(const o of n.jumpers||[])if(this.doesSegmentIntersectJumperPads(t,e,o))return!0}}return!1}doesSegmentIntersectJumperPads(t,e,n){const o=this.obstacleMargin,s=n.end.x-n.start.x,i=n.end.y-n.start.y,r=Math.abs(s)>Math.abs(i),a=(r?Nc:Ic)/2+o,c=(r?Ic:Nc)/2+o;return!!this.doesSegmentIntersectRect(t,e,n.start,a,c)||!!this.doesSegmentIntersectRect(t,e,n.end,a,c)}doesSegmentIntersectRect(t,e,n,o,s){const i=n.x-o,r=n.x+o,a=n.y-s,c=n.y+s;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 o of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,o.connectionName);if(!s)for(const s of _c(o))gt(t,e,s.A,s.B)&&n.push({A:s.A,B:s.B})}return n}computeHComponents(t){const e=Pt(t,this.roundedGoalPosition),n=this.getObstacleProximityPenalty(t),o=this.getEdgeProximityPenalty(t),s=this.getFutureConnectionStartEndPenalty(t),i=this.getFutureConnectionLinePenalty(t),r=t.parent,a=r?.hComponents,c=r?Pt(t,r):0,h=(t,n)=>{if(void 0===n||c<1e-9||e<1e-9)return t;const o=(t-n)/c;return(t+Math.max(0,t+o*e))/2},d=h(n,a?.obstacleProximityRate),l=h(o,a?.edgeProximityRate),u=h(s,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:o,futureConnectionStartEndProximityRate:s,futureConnectionLineRate:i}}computeH(t){return this.computeHComponents(t).total}computeGComponents(t){const e=t.parent,n=e?Pt(t,e):0,o=e?.gComponents??{distFromStart:0,weightedMmNearObstacle:0,weightedMmNearEdge:0,weightedMmNearFutureConnectionStartEnd:0,weightedMmNearFutureConnectionLine:0,jumperPenalty:0,jumperPadFutureConnectionPenalty:0,total:0},s=o.distFromStart+n,i=o.weightedMmNearObstacle+this.getObstacleProximityPenalty(t)*n,r=o.weightedMmNearEdge+this.getEdgeProximityPenalty(t)*n,a=o.weightedMmNearFutureConnectionStartEnd+this.getFutureConnectionStartEndPenalty(t)*n,c=o.weightedMmNearFutureConnectionLine+this.getFutureConnectionLinePenalty(t)*n;let h=o.jumperPenalty,d=o.jumperPadFutureConnectionPenalty;t.isJumperExit&&(h+=this.jumperPenaltyDistance,d+=this.getJumperPadFutureConnectionPenalty(t));return{distFromStart:s,weightedMmNearObstacle:i,weightedMmNearEdge:r,weightedMmNearFutureConnectionStartEnd:a,weightedMmNearFutureConnectionLine:c,jumperPenalty:h,jumperPadFutureConnectionPenalty:d,total:s+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 o of this.futureConnections)for(const s of o.points){const o=Pt(t,s);o<e&&(e=o,n=s)}return n}getFutureConnectionStartEndPenalty(t){let e=0;const n=this.getClosestFutureConnectionPoint(t);if(n){const o=Pt(t,n);if(o>this.FUTURE_CONNECTION_START_END_PROXIMITY)return 0;const s=o/this.FUTURE_CONNECTION_START_END_PROXIMITY;e=this.FUTURE_CONNECTION_START_END_PENALTY*(1-s)**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 o=vt(t,n.points[0],n.points[n.points.length-1]);e=Math.min(e,o)}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 o=1/0;for(const t of this.futureConnections)for(const s of t.points){const t=Pt(e,s),i=Pt(n,s),r=Math.min(t,i);o=Math.min(o,r)}if(o<this.FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY){const t=o/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 o=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!o){for(const o of _c(n))e=Math.min(e,vt(t,o.A,o.B));for(const o of n.jumpers||[])e=Math.min(e,this.distanceToJumperPads(t,o))}}return e}distanceToJumperPads(t,e){const n=e.end.x-e.start.x,o=e.end.y-e.start.y,s=Math.abs(n)>Math.abs(o),i=(s?Nc:Ic)/2,r=(s?Ic:Nc)/2;return Math.min(this.pointToRectDistance(t,e.start,i,r),this.pointToRectDistance(t,e.end,i,r))}pointToRectDistance(t,e,n,o){const s=Math.max(Math.abs(t.x-e.x)-n,0),i=Math.max(Math.abs(t.y-e.y)-o,0);return Math.hypot(s,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)),o=this.OBSTACLE_PROX_SIGMA;return this.OBSTACLE_PROX_PENALTY_FACTOR*Math.exp(-n/o)}getEdgeProximityPenalty(t){const e=this.getClearanceToEdge(t),n=this.EDGE_PROX_SIGMA;if(e>2*this.EDGE_PROX_SIGMA)return 0;const o=Pt(t,this.B),s=Math.min(1,o/(2*this.EDGE_PROX_SIGMA));return this.EDGE_PROX_PENALTY_FACTOR*Math.exp(-e/n)*s}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 o of n){const n=2*Mc,s=t.x+o.dx*n,i=t.y+o.dy*n,r=this.findObstaclesBetween(t,{x:s,y:i});if(r.length>0)for(const n of r){const s=this.calculateJumperExit(t,n,o);s&&!this.exploredNodes.has(this.getNodeKey(s))&&(this.isNodeTooCloseToObstacle(s)||this.isNodeTooCloseToEdge(s)||!this.isJumperPlacementValid(t,s)||(s.gComponents=this.computeGComponents(s),s.hComponents=this.computeHComponents(s),s.g=s.gComponents.total,s.h=s.hComponents.total,s.f=this.computeF(s.g,s.h),e.push(s)))}}return e}calculateJumperExit(t,e,n){const o=Mc,s=Math.sqrt(n.dx*n.dx+n.dy*n.dy),i=n.dx/s,r=n.dy/s,a=t.x+i*o,c=t.y+r*o;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,o=e.y-t.y,s=Math.abs(n)>Math.abs(o),i=(s?Nc:Ic)/2,r=(s?Ic:Nc)/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 o=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(o)continue;const s=_c(n);for(const n of s){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 o=this.getJumpersInPath(t);for(const t of o)if(this.doJumpersOverlap(n,t))return!1;return!0}doJumpersOverlap(t,e){const n=this.obstacleMargin,o=Math.min(t.start.x,t.end.x)-bc/2-n,s=Math.max(t.start.x,t.end.x)+bc/2+n,i=Math.min(t.start.y,t.end.y)-bc/2-n,r=Math.max(t.start.y,t.end.y)+bc/2+n,a=Math.min(e.start.x,e.end.x)-bc/2-n,c=Math.max(e.start.x,e.end.x)+bc/2+n,h=Math.min(e.start.y,e.end.y)-bc/2-n,d=Math.max(e.start.y,e.end.y)+bc/2+n;return!(s<a||o>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:o,maxY:s,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=Tc(c,o,n),l=Tc(h,i,s),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 o=e[t];o.isJumperExit&&o.jumperEntry&&n.push({route_type:"jumper",start:o.jumperEntry,end:{x:o.x,y:o.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=Pt(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 o=this.getNeighbors(t);for(const t of o)this.candidates.enqueue(t)}drawJumperPads(t,e,n,o,s){const i=e.end.x-e.start.x,r=e.end.y-e.start.y,a=Nc,c=Ic,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:o??"jumper",step:s}),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:o??"jumper",step:s}),t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*c,layer:o??"jumper-body",step:s})}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 o=0;o<n.route.length-1;o++)t.lines.push({points:[n.route[o],n.route[o+1]],strokeColor:"rgba(255, 0, 0, 0.75)",strokeWidth:n.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`});for(const o of n.jumpers||[])this.drawJumperPads(t,o,"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 o=n.points[0],s=n.points[n.points.length-1];t.lines.push({points:[o,s],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[o,s]=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:o+this.initialNodeGridOffset.x,y:s+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 o=e[n],s=o.isJumperExit??!1,i=o.gComponents,r=o.hComponents,a=r?.distanceToGoal??0,c=[`Candidate #${n+1}${s?" (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: ${o.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: ${o.h.toFixed(2)}`),c.push(`f: ${o.f.toFixed(2)}`);const h=c.join("\n");t.points.push({x:o.x,y:o.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:o,maxX:s,maxY:i}=this.bounds;return t.lines.push({points:[{x:n,y:o},{x:s,y:o},{x:s,y:i},{x:n,y:i},{x:n,y:o}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}};function _c(t){const e=[];for(let n=0;n<t.route.length-1;n++)if(t.route[n].z===t.route[n+1].z){const o=t.route[n],s=t.route[n+1],i=t.jumpers?.some(t=>{const e=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,n=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;return e||n});i||e.push({z:o.z,A:o,B:s})}return e}function Tc(t,e,n){return Math.max(e,Math.min(t,n))}var Ec=.8,Rc=.95,wc=class extends y{getSolverName(){return"IntraNodeSolverWithJumpers"}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 o=new Map;for(const{connectionName:t,rootConnectionName:n,x:s,y:i}of e.portPoints){const e=o.get(t);o.set(t,{rootConnectionName:e?.rootConnectionName??n,points:[...e?.points??[],{x:s,y:i,z:0}]})}this.unsolvedConnections=Array.from(o.entries().map(([t,{rootConnectionName:e,points:n}])=>({connectionName:t,rootConnectionName:e,points:n}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=Bt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},n)=>({...e,points:Bt(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,o=Math.abs(e.x-n.x)<1e-6,s=Math.abs(e.y-n.y)<1e-6;if(o&&s)return}const{connectionName:e,rootConnectionName:n,points:o}=t;this.activeSubSolver=new Cc({connectionName:e,rootConnectionName:n,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:kt(this.nodeWithPortPoints),A:{x:o[0].x,y:o[0].y,z:0},B:{x:o[o.length-1].x,y:o[o.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,o){const s=e.end.x-e.start.x,i=e.end.y-e.start.y,r=Ec,a=Rc,c=Math.abs(s)>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 o=this.colorMap[n.connectionName]??"blue";for(let e=0;e<n.route.length-1;e++){const s=n.route[e],i=n.route[e+1];t.lines.push({points:[s,i],strokeColor:it(o,.2),layer:"route-layer-0",strokeWidth:n.traceThickness})}for(const s of n.jumpers)this.drawJumperPads(t,s,it(o,.5),e)}}const e=kt(this.nodeWithPortPoints),{minX:n,minY:o,maxX:s,maxY:i}=e;return t.lines.push({points:[{x:n,y:o},{x:s,y:o},{x:s,y:i},{x:n,y:i},{x:n,y:o}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}};export{Sc as AssignableAutoroutingPipeline1Solver,Rr as AssignableAutoroutingPipeline2,Ga as AssignableAutoroutingPipeline3,nr as AutoroutingPipeline1_OriginalUnravel,di as AutoroutingPipelineSolver,hc as AutoroutingPipelineSolver3_HgPortPointPathing,li as CapacityMeshSolver,Wa as CurvyIntraNodeSolver,Ua as HighDensitySolver,ct as InMemoryCache,wc as IntraNodeSolverWithJumpers,dt as LocalStorageCache,Cc as SingleHighDensityRouteWithJumpersSolver,He as calculateOptimalCapacityDepth,an as convertSrjToGraphicsObject,ut as getGlobalInMemoryCache,lt as getGlobalLocalStorageCache,We as getTunedTotalCapacity1,pt as setupGlobalCaches};
1
+ var t=Object.create,e=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,i=Object.prototype.hasOwnProperty,r=(t,e)=>function(){return e||(0,t[o(t)[0]])((e={exports:{}}).exports,e),e.exports},a=(r,a,c)=>(c=null!=r?t(s(r)):{},((t,s,r,a)=>{if(s&&"object"==typeof s||"function"==typeof s)for(let c of o(s))i.call(t,c)||c===r||e(t,c,{get:()=>s[c],enumerable:!(a=n(s,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(),o=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=o.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 o in t)Object.prototype.hasOwnProperty.call(t,o)&&(n[e(o,t[o])||o]=t[o]);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(),o=d();e.exports=function t(e,s){var i=n(e);if("object"!==i&&"array"!==i)throw new Error("expected an object");var r=[];for(var a in"object"===i&&(e=o(e,s),r={}),e)if(e.hasOwnProperty(a)){var c=e[a];"object"===n(c)||"array"===n(c)?r[a]=t(c,s):r[a]=c}return r}}}),u=r({"node_modules/xml-reader/node_modules/eventemitter3/index.js"(t,e){var n=Object.prototype.hasOwnProperty,o="~";function s(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new s,this._eventsCount=0}Object.create&&(s.prototype=Object.create(null),(new s).__proto__||(o=!1)),r.prototype.eventNames=function(){var t,e,s=[];if(0===this._eventsCount)return s;for(e in t=this._events)n.call(t,e)&&s.push(o?e.slice(1):e);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(t)):s},r.prototype.listeners=function(t,e){var n=o?o+t:t,s=this._events[n];if(e)return!!s;if(!s)return[];if(s.fn)return[s.fn];for(var i=0,r=s.length,a=new Array(r);i<r;i++)a[i]=s[i].fn;return a},r.prototype.emit=function(t,e,n,s,i,r){var a=o?o+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,s),!0;case 5:return d.fn.call(d.context,e,n,s,i),!0;case 6:return d.fn.call(d.context,e,n,s,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,s);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 s=new i(e,n||this),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.once=function(t,e,n){var s=new i(e,n||this,!0),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=o?o+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new s: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 s: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 s:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=o?o+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new s:delete this._events[e])):(this._events=new s,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=o,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,o="~";function s(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new s,this._eventsCount=0}Object.create&&(s.prototype=Object.create(null),(new s).__proto__||(o=!1)),r.prototype.eventNames=function(){var t,e,s=[];if(0===this._eventsCount)return s;for(e in t=this._events)n.call(t,e)&&s.push(o?e.slice(1):e);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(t)):s},r.prototype.listeners=function(t,e){var n=o?o+t:t,s=this._events[n];if(e)return!!s;if(!s)return[];if(s.fn)return[s.fn];for(var i=0,r=s.length,a=new Array(r);i<r;i++)a[i]=s[i].fn;return a},r.prototype.emit=function(t,e,n,s,i,r){var a=o?o+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,s),!0;case 5:return d.fn.call(d.context,e,n,s,i),!0;case 6:return d.fn.call(d.context,e,n,s,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,s);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 s=new i(e,n||this),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.once=function(t,e,n){var s=new i(e,n||this,!0),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=o?o+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new s: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 s: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 s:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=o?o+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new s:delete this._events[e])):(this._events=new s,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=o,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 o=p(),s=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 o,v=i.data,P="",S="",M="",b="",N="",I="",C=function(e,n){if("?"!==S[0]&&"!"!==S[0]){var o={type:e,value:n};t.debug&&console.log("emit:",o),x.emit("data",o)}};x.stateMachine=(n(y={},i.data,(n(e={},r.lt,function(){P.trim()&&C(a.text,P),S="",N=!1,v=i.tagBegin}),n(e,r.char,function(t){P+=t}),e)),n(y,i.cdata,n({},r.char,function(t){"]]>"===(P+=t).substr(-3)&&(C(a.text,P.slice(0,-3)),P="",v=i.data)})),n(y,i.tagBegin,(n(h={},r.space,s),n(h,r.char,function(t){S=t,v=i.tagName}),n(h,r.slash,function(){S="",N=!0}),h)),n(y,i.tagName,(n(d={},r.space,function(){N?v=i.tagEnd:(v=i.attributeNameStart,C(a.openTag,S))}),n(d,r.gt,function(){C(N?a.closeTag:a.openTag,S),P="",v=i.data}),n(d,r.slash,function(){v=i.tagEnd,C(a.openTag,S)}),n(d,r.char,function(t){"![CDATA["===(S+=t)&&(v=i.cdata,P="",S="")}),d)),n(y,i.tagEnd,(n(l={},r.gt,function(){C(a.closeTag,S),P="",v=i.data}),n(l,r.char,s),l)),n(y,i.attributeNameStart,(n(u={},r.char,function(t){M=t,v=i.attributeName}),n(u,r.gt,function(){P="",v=i.data}),n(u,r.space,s),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,M),v=i.attributeValueBegin}),n(p,r.gt,function(){b="",C(a.attributeName,M),C(a.attributeValue,b),P="",v=i.data}),n(p,r.slash,function(){N=!0,b="",C(a.attributeName,M),C(a.attributeValue,b),v=i.tagEnd}),n(p,r.char,function(t){M+=t}),p)),n(y,i.attributeNameEnd,(n(m={},r.space,s),n(m,r.equal,function(){C(a.attributeName,M),v=i.attributeValueBegin}),n(m,r.gt,function(){b="",C(a.attributeName,M),C(a.attributeValue,b),P="",v=i.data}),n(m,r.char,function(t){b="",C(a.attributeName,M),C(a.attributeValue,b),M=t,v=i.attributeName}),m)),n(y,i.attributeValueBegin,(n(f={},r.space,s),n(f,r.quote,function(t){I=t,b="",v=i.attributeValue}),n(f,r.gt,function(){C(a.attributeValue,b=""),P="",v=i.data}),n(f,r.char,function(t){I="",b=t,v=i.attributeValue}),f)),n(y,i.attributeValue,(n(g={},r.space,function(t){I?b+=t:(C(a.attributeValue,b),v=i.attributeNameStart)}),n(g,r.quote,function(t){I===t?(C(a.attributeValue,b),v=i.attributeNameStart):b+=t}),n(g,r.gt,function(t){I?b+=t:(C(a.attributeValue,b),P="",v=i.data)}),n(g,r.slash,function(t){I?b+=t:(C(a.attributeValue,b),N=!0,v=i.tagEnd)}),n(g,r.char,function(t){b+=t}),g)),y);var _=function(e){t.debug&&console.log(v,e);var n=x.stateMachine[v],o=n[function(t){return c[t]||r.char}(e)]||n[r.error]||n[r.char];o(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(),o=m(),s=o.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 s.openTag:if(null===c)(c=a).name=n.value;else{var o=r({name:n.value,parent:c});c.children.push(o),c=o}break;case s.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 s.text:c&&c.children.push(r({type:i.text,value:n.value,parent:t.parentNodes?c:null}));break;case s.attributeName:h=n.value,c.attributes[h]="";break;case s.attributeValue:c.attributes[h]=n.value}};return d.reset=function(){(e=o.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),o=void 0;return n.on("done",function(t){o=t}),n.parse(t),o},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;getSolverName(){return this.constructor.name}step(){if(!this.solved&&!this.failed){this.iterations++;try{this._step()}catch(t){throw this.error=`${this.getSolverName()} 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.getSolverName()} 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 o in n)({}).hasOwnProperty.call(n,o)&&(t[o]=n[o])}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 P(t){return(P=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function S(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(t){}return(S=function(){return!!t})()}function M(t){var e="function"==typeof Map?new Map:void 0;return M=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(S())return Reflect.construct.apply(null,arguments);var o=[null];o.push.apply(o,e);var s=new(t.bind.apply(t,o));return n&&v(s,n.prototype),s}(t,arguments,P(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),v(n,t)},M(t)}var b={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 o,s=e[0],i=[];for(o=1;o<e.length;o+=1)i.push(e[o]);return i.forEach(function(t){s=s.replace(/%[a-z]/,t)}),s}var I=function(t){var e,n;function o(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 o=arguments.length,s=new Array(o>1?o-1:0),i=1;i<o;i++)s[i-1]=arguments[i];n=t.call(this,N.apply(void 0,[b[e]].concat(s)))||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=o).prototype=Object.create(n.prototype),e.prototype.constructor=e,v(e,n),o}(M(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 o=e,s=n;if("string"==typeof e){if(!C(e,"px"))throw new I(69,t,e);o=T(e)}if("string"==typeof n){if(!C(n,"px"))throw new I(70,t,n);s=T(n)}if("string"==typeof o)throw new I(71,e,t);if("string"==typeof s)throw new I(72,n,t);return""+o/s+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,o){if(void 0===o&&(o=w),0===e)return o(n,n,n);var s=(t%360+360)%360/60,i=(1-Math.abs(2*n-1))*e,r=i*(1-Math.abs(s%2-1)),a=0,c=0,h=0;s>=0&&s<1?(a=i,c=r):s>=1&&s<2?(a=r,c=i):s>=2&&s<3?(c=i,h=r):s>=3&&s<4?(c=r,h=i):s>=4&&s<5?(a=r,h=i):s>=5&&s<6&&(a=i,h=r);var d=n-i/2;return o(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,B=/^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 k(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 o=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:o}}var s=X.exec(e);if(s)return{red:parseInt(""+s[1],10),green:parseInt(""+s[2],10),blue:parseInt(""+s[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=B.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,o=t.green/255,s=t.blue/255,i=Math.max(n,o,s),r=Math.min(n,o,s),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=(o-s)/c+(o<s?6:0);break;case o:e=(s-n)/c+2;break;default:e=(n-o)/c+4}return e*=60,void 0!==t.alpha?{hue:e,saturation:h,lightness:a,alpha:t.alpha}:{hue:e,saturation:h,lightness:a}}(k(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,o){if("string"==typeof t&&"number"==typeof e){var s=k(t);return"rgba("+s.red+","+s.green+","+s.blue+","+e+")"}if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof o)return o>=1?G(t,e,n):"rgba("+t+","+e+","+n+","+o+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===o)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,o){if("number"==typeof t&&"number"==typeof e&&"number"==typeof n&&"number"==typeof o)return o>=1?Z(t,e,n):"rgba("+A(t,e,n)+","+o+")";if("object"==typeof t&&void 0===e&&void 0===n&&void 0===o)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 o=n.concat(Array.prototype.slice.call(arguments));return o.length>=e?t.apply(this,o):K(t,e,o)}}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 o=k(e),s=x({},o,{alpha:"number"==typeof o.alpha?o.alpha:1}),i=k(n),r=x({},i,{alpha:"number"==typeof i.alpha?i.alpha:1}),a=s.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(s.red*h+r.red*d),green:Math.floor(s.green*h+r.green*d),blue:Math.floor(s.blue*h+r.blue*d),alpha:s.alpha*parseFloat(t)+r.alpha*(1-parseFloat(t))})});Q(function(t,e){if("transparent"===e)return e;var n=k(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=k(e);return J(x({},n,{alpha:tt(0,1,+(100*("number"==typeof n.alpha?n.alpha:1)-100*parseFloat(t)).toFixed(2)/100)}))}),ot=["blue","orange","purple","cyan","magenta","yellowgreen","darkgoldenrod","deeppink"],st=(t,e)=>{const n={};for(let o=0;o<t.connections.length;o++){const s=t.connections[o],i=e?.getNetConnectedToId(s.name);i&&!n[i]&&(n[i]=`hsl(${300*o/t.connections.length}, 100%, 50%)`),n[s.name]=(i?n[i]:null)??`hsl(${340*o/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 o=t.split(":")[0];return this.cacheHitsByPrefix[o]=(this.cacheHitsByPrefix[o]||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 o=t.split(":")[0];return void(this.cacheMissesByPrefix[o]=(this.cacheMissesByPrefix[o]||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,o){const s=yt(t,e,n),i=yt(t,e,o),r=yt(n,o,t),a=yt(n,o,e);return s!==i&&r!==a||(!(0!==s||!xt(t,n,e))||(!(0!==i||!xt(t,o,e))||(!(0!==r||!xt(n,t,o))||!(0!==a||!xt(n,e,o)))))}function yt(t,e,n){const o=(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y);return 0===o?0:o>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 o=(n.x-e.x)**2+(n.y-e.y)**2;if(0===o)return Pt(t,e);let s=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/o;s=Math.max(0,Math.min(1,s));return Pt(t,{x:e.x+s*(n.x-e.x),y:e.y+s*(n.y-e.y)})}function Pt(t,e){const n=t.x-e.x,o=t.y-e.y;return Math.sqrt(n*n+o*o)}function St(t,e,n,o){const s=e.x-t.x,i=e.y-t.y,r=o.x-n.x,a=o.y-n.y,c=t.x-n.x,h=t.y-n.y,d=s*a-i*r;if(Math.abs(d)<1e-10)return null;const l=(h*r-c*a)/d,u=(s*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*s,y:t.y+l*i}}return null}function Mt(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var bt=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 o=t[n],s=t[(n+1)%t.length];e.push([o,s])}return e},Ct=(t,e,n)=>{const o=(t.y-e.y)*(n.x-e.x)-(t.x-e.x)*(n.y-e.y);if(Math.abs(o)>1e-9)return!1;const s=(t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y);if(s<0)return!1;return!(s>(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,o]of n)if(Ct(t,e,o))return!0;let o=!1;for(let n=0,s=e.length-1;n<e.length;s=n++){const i=e[n].x,r=e[n].y,a=e[s].x,c=e[s].y;r>t.y!=c>t.y&&t.x<(a-i)*(t.y-r)/(c-r)+i&&(o=!o)}return o},Tt=(t,e)=>{const n=Nt(t),o=[[n[0],n[1]],[n[1],n[2]],[n[2],n[3]],[n[3],n[0]]],s=It(e);for(const[t,e]of s)for(const[n,s]of o)if(gt(t,e,n,s))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))))(bt(t),e),Rt=(t,e)=>((t,e)=>!(e.length<3)&&(!!Nt(t).every(t=>_t(t,e))&&!Tt(t,e)))(bt(t),e);function wt(t,e,n,o){if(t.x===e.x&&t.y===e.y)return vt(t,n,o);if(n.x===o.x&&n.y===o.y)return vt(n,t,e);if(gt(t,e,n,o))return 0;const s=[vt(t,n,o),vt(e,n,o),vt(n,t,e),vt(o,t,e)];return Math.min(...s)}function At(t,e,n){const o=n.width/2,s=n.height/2;return function(t,e,n){const o={x:n.minX,y:n.minY},s={x:n.maxX,y:n.minY},i={x:n.minX,y:n.maxY},r={x:n.maxX,y:n.maxY};if(gt(t,e,o,s)||gt(t,e,s,r)||gt(t,e,r,i)||gt(t,e,i,o))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(o,t,e),vt(s,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),o=ft(t.y,n.minY,n.maxY);a.push(Pt(t,{x:e,y:o}))}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),o=ft(e.y,n.minY,n.maxY);a.push(Pt(e,{x:t,y:o}))}return Math.min(...a)}(t,e,{minX:n.center.x-o,maxX:n.center.x+o,minY:n.center.y-s,maxY:n.center.y+s})}function Ot(t,e,n){const o=n.x-e.x,s=n.y-e.y,i=o*o+s*s;if(0===i)return{x:e.x,y:e.y};let r=((t.x-e.x)*o+(t.y-e.y)*s)/i;r=Math.max(0,Math.min(1,r));return{x:e.x+r*o,y:e.y+r*s}}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{getSolverName(){return"SingleHighDensityRouteSolver"}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=Pt(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,o=this.boundsSize.height/this.cellStep;for(;n*o>e**2&&!(2*this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,n=this.boundsSize.width/this.cellStep,o=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR;const s=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&&!s&&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 o of n)if(Pt(t,o)<this.viaDiameter/2+e)return!0}for(const o of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,o.connectionName);if(!s){const s=Lt(o);for(const o of s)if((n||o.z===t.z)&&vt(t,o.A,o.B)<this.traceThickness+e)return!0}for(const n of o.vias)if(Pt(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,o=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!(o&&!e&&(Pt(t,this.B)<2*n||Pt(t,this.A)<2*n))&&o}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const n of this.obstacleRoutes){const o=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!o)for(const o of Lt(n))if(o.z===t.z&&gt(t,e,o.A,o.B))return!0}return!1}computeH(t){return Pt(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)+Pt(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:o,maxY:s,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,o,n),y:Ft(t.y+a*this.cellStep,i,s)},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 o={...t,parent:t,z:n};this.exploredNodes.has(this.getNodeKey(o))||this.isNodeTooCloseToObstacle(o,this.viaDiameter/2+this.obstacleMargin/2,!0)||this.isNodeTooCloseToEdge(o,!0)||(o.g=this.computeG(o),o.h=this.computeH(o),o.f=this.computeF(o.g,o.h),e.push(o))}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 o=1-e/this.straightLineDistance;return Math.max(this.progress||0,2/Math.PI*Math.atan(.112*o/(1-o)))}_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=Pt(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 o=this.getNeighbors(t);for(const t of o)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 o=0;o<n.route.length-1;o++){const s=n.route[o].z;t.lines.push({points:[n.route[o],n.route[o+1]],strokeColor:0===s?"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],[o,s,i]=n.split(",").map(Number);this.debug_nodesTooCloseToObstacle.has(n)||(this.debug_nodePathToParentIntersectsObstacle.has(n)||t.rects.push({center:{x:o+this.initialNodeGridOffset.x+i*this.cellStep/20,y:s+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 o of this.futureConnections)for(const s of o.points){const o=Pt(t,s)+(t.z!==s.z?this.viaPenaltyDistance:0);o<e&&(e=o,n=s)}return n}diminishCloseToGoal(t){const e=Pt(t,this.B);return 1-Math.exp(-e/this.straightLineDistance*5)}getFutureConnectionPenalty(t,e){let n=0;const o=this.getClosestFutureConnectionPoint(t),s=Pt(t,this.B);if(o){const i=Pt(t,o);if(s<=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=Pt(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),o=Math.sqrt(e**2+n**2),s=t.z%2==0,i=this.FLIP_TRACE_ALIGNMENT_DIRECTION?s?e:n:s?n:e;return(t.parent?.g??0)+(t.z===t.parent?.z?0:this.viaPenaltyDistance)+o+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 o=e;return()=>{let t=n;n=o,t^=t<<23,t^=t>>>17,t^=o,t^=o>>>26,o=t;const e=(n+o)/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 Bt(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),o=t.slice();for(let t=0;t<o.length;t++){const e=Math.floor(n()*o.length),s=Math.floor(n()*(t+1));[o[e],o[s]]=[o[s],o[e]]}return o}function kt(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 o=t+1;o<n.length;o++){const s=n[t],i=n[o];if(s.z!==i.z)continue;if(s.rootConnectionName&&s.rootConnectionName===i.rootConnectionName)continue;const r=Math.sqrt((s.x-i.x)**2+(s.y-i.y)**2);e=Math.min(e,r)}return e===1/0?0:e},Wt=class extends y{getSolverName(){return"IntraNodeRouteSolver"}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 o=new Map;for(const{connectionName:t,x:n,y:s,z:i}of e.portPoints)o.set(t,[...o.get(t)??[],{x:n,y:s,z:i??0}]);this.unsolvedConnections=Array.from(o.entries().map(([t,e])=>({connectionName:t,points:e}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=Bt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},n)=>({...e,points:Bt(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,o=Math.abs(e.x-n.x)<1e-6,s=Math.abs(e.y-n.y)<1e-6;if(o&&s&&e.z===n.z)return;if(o&&s&&e.z!==n.z){const o={x:this.nodeWithPortPoints.center.x,y:this.nodeWithPortPoints.center.y},s=[{x:e.x,y:e.y,z:e.z},{...o,z:e.z},{...o,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:s,vias:[o]})}}const{connectionName:e,points:n}=t;this.activeSubSolver=new Xt({connectionName:e,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:kt(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 o=this.colorMap[n.connectionName]??"blue";for(let s=0;s<n.route.length-1;s++){const i=n.route[s],r=n.route[s+1];t.lines.push({points:[i,r],strokeColor:0===i.z?it(o,.2):it(o,.8),layer:`route-layer-${i.z}`,step:e,strokeWidth:n.traceThickness})}for(const s of n.vias)t.circles.push({center:{x:s.x,y:s.y},radius:n.viaDiameter/2,fill:it(o,.5),layer:"via",step:e})}}const e=kt(this.nodeWithPortPoints),{minX:n,minY:o,maxX:s,maxY:i}=e;return t.lines.push({points:[{x:n,y:o},{x:s,y:o},{x:s,y:i},{x:n,y:i},{x:n,y:o}],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{getSolverName(){return"CachedIntraNodeRouteSolver"}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))),o=this.connMap?this.initialUnsolvedConnections.map(({connectionName:t})=>({connectionName:t,connectedIds:[...new Set(this.connMap.getIdsConnectedToNet(t)??[])].sort()})):void 0,s={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:o},i=`intranode-solver:${at(s)}`,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{getSolverName(){return"HyperParameterSupervisorSolver"}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,...o]=t,s=this.getHyperParameterCombinations(o);return n.possibleValues.forEach(t=>{s.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 o=n.f;o<t&&(t=o,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:o,E:s,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 o=e.x-t.x,s=e.y-t.y,i=Math.sqrt(o*o+s*s),r=o/i,a=s/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=Pt(t,e.start),o=Pt(t,e.end),s=Pt(e.start,e.end);return Math.abs(n+o-s)<1e-4},u=(t,e)=>{const{start:n,end:o}=t,{start:s,end:i}=e;if(l(n,e)||l(o,e)||l(s,t)||l(i,t))return!0;const r=o.x-n.x,a=o.y-n.y,c=i.x-s.x,h=i.y-s.y,d=r*h-a*c;if(Math.abs(d)<1e-4)return!1;const u=s.x-n.x,p=s.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 o=[];for(let t=0;t<e.length-1;t++)o.push({start:e[t],end:e[t+1]});for(const t of n)for(const e of o)if(u(t,e))return!0;return!1},m=t=>{let e=0;for(let n=1;n<t.length;n++){const o=t[n].x-t[n-1].x,s=t[n].y-t[n-1].y;e+=Math.sqrt(o*o+s*s)}return e},f=(t,e)=>{const{start:n,end:o}=t,s=o.x-n.x,i=o.y-n.y,r=s*s+i*i;if(0===r)return{...n,t:0};const a=Math.max(0,Math.min(1,((e.x-n.x)*s+(e.y-n.y)*i)/r));return{x:n.x+a*s,y:n.y+a*i,t:a}},g=(e,n,o)=>{const s=f(e,n);if(Pt(s,n)>=o)return s;const i=s.x-n.x,r=s.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+o*i/a,y:n.y+o*r/a,t:s.t,isSpecial:!0,specialType:n===t?"A":"B"}}return{x:n.x+o*i/a,y:n.y+o*r/a,t:s.t,isSpecial:!0,specialType:n===t?"A":"B"}},y=d(t,e,r),x=d(t,e,r+a),v=(t,e,n,o,s)=>{const i=t.points;if(i.length<2)return i;const a=n+o,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),o=t.x-e.x,s=t.y-e.y,i=Math.sqrt(o*o+s*s);let h=null;if(i>1e-6)h={x:e.x+a*o/i,y:e.y+a*s/i};else{const t=n.end.x-n.start.x,o=n.end.y-n.start.y,s=Math.sqrt(t*t+o*o);s>1e-6&&(h={x:e.x+a*t/s,y:e.y+a*o/s})}h&&Pt(n.start,h)>r/10&&c.push(h)}Pt(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++)Pt(t[t.length-1],c[e])>r/10&&t.push(c[e]);return t}return c},P=(()=>{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,o],[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,o],[o,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],[o,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 o=t[n],s={start:o[0],end:o[1]},i={start:o[o.length-2],end:o[o.length-1]},r={start:o[3],end:o[4]};u(s,i)||u(s,r)||u(i,r)||e.push({index:n+1,path:o,length:m(o)})}if(0===e.length)return{index:0,path:[]};const s=e.sort((t,e)=>t.length-e.length)[0],i=[...s.path],r=i[0],a=Pt(r,i[2]),c=Pt(r,i[3]),d=a<c?2:3;(a<Pt(r,i[1])||c<Pt(r,i[1]))&&i.splice(1,d-1);const l=i[i.length-1],p=Pt(l,i[i.length-3]),f=Pt(l,i[i.length-4]),g=p<f?i.length-3:i.length-4;return(p<Pt(l,i[i.length-2])||f<Pt(l,i[i.length-2]))&&i.splice(g+1,i.length-g-2),{index:s.index,path:i,startsAt:i[0]===n?"C":"D",goesTo:i[i.length-1]===n?"C":"D"}})(),S=c>0?((n,o)=>{if(n.length<2)return n;const s=[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=Pt(c,t),d=Pt(c,e);if((h<=r||d<=r)&&Math.abs(h-d)>1e-4){const n=f(a,t),i=f(a,e),c=Pt(n,t),h=Pt(i,e)<r,d=c<r?g(a,t,r):null,l=h?g(a,e,r):null;let u=[];if(Pt(a.start,a.end)>r/2&&o>0)for(let n=1;n<=o;n++){const s=n/(o+1),i={x:a.start.x+s*(a.end.x-a.start.x),y:a.start.y+s*(a.end.y-a.start.y),t:s,isSpecial:!1},c=Pt(i,t),h=Pt(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],o=u[e];Pt(n,o)>r/10&&t.push(o)}u=t}u.forEach(t=>s.push(t))}s.push(n[i+1])}if(s.length>1){const t=[s[0]];for(let e=1;e<s.length;e++){const n=t[t.length-1],o=s[e];Pt(n,o)>r/10&&t.push(o)}return t}return s})(P.path,c):P.path;let M=(()=>{if(0===P.path.length)return null;const n=(()=>{const n=h(y.A_Right,y.B_Right),o=h(y.B_Left,y.A_Left);return[{startsAt:"E",goesTo:"B",points:[s,e]},{startsAt:"E",goesTo:"A",points:[s,t]},{startsAt:"F",goesTo:"B",points:[i,e]},{startsAt:"F",goesTo:"A",points:[i,t]},{startsAt:"E",goesTo:"B",points:[s,n,e]},{startsAt:"E",goesTo:"A",points:[s,n,t]},{startsAt:"F",goesTo:"B",points:[i,n,e]},{startsAt:"F",goesTo:"A",points:[i,n,t]},{startsAt:"E",goesTo:"B",points:[s,o,e]},{startsAt:"E",goesTo:"A",points:[s,o,t]},{startsAt:"F",goesTo:"B",points:[i,o,e]},{startsAt:"F",goesTo:"A",points:[i,o,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Right,n,e]},{startsAt:"F",goesTo:"B",points:[i,x.B_Right,n,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Left,o,t]},{startsAt:"F",goesTo:"A",points:[i,x.A_Left,o,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Left,o,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Opp,x.B_Left,o,t]},{startsAt:"F",goesTo:"B",points:[i,x.A_Opp,x.A_Left,o,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,o,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Opp,x.A_Left,o,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Opp,x.B_Right,n,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Left,x.A_Opp,x.A_Right,n,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Right,x.B_Opp,x.B_Left,o,t]},{startsAt:"F",goesTo:"B",points:[i,x.A_Right,x.A_Opp,x.A_Left,o,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,o,t]},{startsAt:"E",goesTo:"B",points:[s,x.A_Right,x.A_Opp,x.A_Left,o,e]},{startsAt:"E",goesTo:"A",points:[s,x.B_Left,x.B_Opp,x.B_Right,n,t]}].map((t,e)=>({...t,index:e}))})(),o=n.filter(t=>"E"===t.startsAt),r=n.filter(t=>"F"===t.startsAt),a=[],c=[];for(const t of o)if(!p(t.points,P.path)){a.push(t);break}for(const t of r)if(!p(t.points,P.path)){c.push(t);break}return 0===a.length||0===c.length?null:{line1:a[0],line2:c[0]}})();if(M){const n="A"===M.line1.goesTo?e:t,o="A"===M.line2.goesTo?e:t,s=v(M.line1,n,r,a),i=v(M.line2,o,r,a);M={line1:{...M.line1,points:s},line2:{...M.line2,points:i}}}return{jPair:M,optimalPath:{startsAt:P.startsAt,goesTo:P.goesTo,points:S}}}var Jt=class extends y{getSolverName(){return"TwoCrossingRoutesHighDensitySolver"}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,o]of n.entries())2===o.length&&t.push({startPort:{...o[0],z:o[0].z??0},endPort:{...o[1],z:o[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,o=this.bounds.maxY-this.bounds.minY,s=this.bounds.minX,i=this.bounds.minY,r={width:n-2*this.obstacleMargin-this.viaDiameter,height:o-2*this.obstacleMargin-this.viaDiameter,x:s+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)=>Pt(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,o)=>{((t,e)=>{const n=t.x,o=t.y,s=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=s*s-(t-n)**2;if(e<0)return[];if(Math.abs(e)<.001){const e=o;return e>=Math.min(r,c)&&e<=Math.max(r,c)?[{x:t,y:e}]:[]}const a=o+Math.sqrt(e),h=o-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*o-n),p=u*u-4*l*(n*n+(d-o)*(d-o)-s*s);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:o})})})}),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=Pt(g,t.startPort);return Pt(y,t.startPort)<x&&([g,y]=[y,g]),{via1:g,via2:y}}trySolveAOverB(t,e,n=!1){const o=n?this.calculateViaPositions(t,e):this.calculateViaPositions(e,t);if(!o)return!1;this.debugViaPositions.push(o);const{via1:s,via2:i}=this.pushViasFromEndpoints(this.moveViasAsCloseAsPossible(o));this.debugViaPositions.push({via1:s,via2:i});const{jPair:r,optimalPath:a}=Gt({A:s,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:[s,i]};return this.solvedRoutes.push(c,h),!0}pushViasFromEndpoints(t){const e={...t.via1},n={...t.via2},o=[this.routes[0].startPort,this.routes[0].endPort,this.routes[1].startPort,this.routes[1].endPort],s=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 o){const o=Pt(e,t);if(o<i){const n=(i-o)*c,s=e.x-t.x,a=e.y-t.y,h=Math.sqrt(s*s+a*a);h>1e-6&&(e.x+=s/h*n,e.y+=a/h*n,r=!0)}const s=Pt(n,t);if(s<i){const e=(i-s)*c,o=n.x-t.x,r=n.y-t.y,h=Math.sqrt(o*o+r*r);h>1e-6&&(n.x+=o/h*e,n.y+=r/h*e,a=!0)}}const h=Pt(e,n);if(h<s){const t=(s-h)/2,o=n.x-e.x,i=n.y-e.y,c=Math.sqrt(o*o+i*i);c>1e-6?(e.x-=o/c*t,e.y-=i/c*t,n.x+=o/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=Pt(e,n);if(r<s){const t=(s-r)/2,o=n.x-e.x,i=n.y-e.y,a=Math.sqrt(o*o+i*i);a>1e-6?(e.x-=o/a*t,e.y-=i/a*t,n.x+=o/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,o=this.getMinDistanceBetweenViaCenters(),s=Pt(e,n);if(s<=o)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,(s-o)/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:[]},o={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,o),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:o}=this.debugViaPositions[e],s=["rgba(255, 165, 0, 0.3)","rgba(128, 0, 128, 0.3)"],i=s[e%s.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:o,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:o,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,o,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],o=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 s=n.route[e],i=n.route[e+1];t.lines.push({points:[s,i],strokeColor:o,strokeDash:1===s.z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${s.z}`}),s._label&&t.points.push({x:s.x,y:s.y,label:s._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,o,s){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>=s.minX&&i.x<=s.maxX&&i.y>=s.minY&&i.y<=s.maxY;return a>=o&&c>=o&&h>=o&&d};if(a(i))return i;const c=(t,e,n)=>{const o=t.x-e.x,s=t.y-e.y,i=Math.sqrt(o*o+s*s);return i<1e-10?{x:e.x+n,y:e.y}:{x:e.x+o/i*n,y:e.y+s/i*n}},h=(t,e,n)=>{const o=e.x-t.x,s=e.y-t.y,i=Math.sqrt(o*o+s*s);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+o*a/i,d=t.y+s*a/i,l={x:h+c*s/i,y:d-c*o/i},u={x:h-c*s/i,y:d+c*o/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,o),c(i,e,o),c(i,n,o),...h(t,e,o),...h(e,n,o),...h(n,t,o)],l=d.filter(a);if(l.length>0){const t=l.filter(t=>!(t=>{const e=1e-6;return Math.abs(t.x-s.minX)<e||Math.abs(t.x-s.maxX)<e||Math.abs(t.y-s.minY)<e||Math.abs(t.y-s.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=s.minX+1;t<s.maxX;t+=5)for(let e=s.minY+1;e<s.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:s.minX+e*(s.maxX-s.minX),y:s.minY}),m.push({x:s.maxX,y:s.minY+e*(s.maxY-s.minY)}),m.push({x:s.maxX-e*(s.maxX-s.minX),y:s.maxY}),m.push({x:s.minX,y:s.maxY-e*(s.maxY-s.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:s.minX,y:s.minY};for(const i of[...d,...m])if(i.x>=s.minX&&i.x<=s.maxX&&i.y>=s.minY&&i.y<=s.maxY){const s=Math.max(0,o-r(i,t))+Math.max(0,o-r(i,e))+Math.max(0,o-r(i,n));s<g&&(g=s,y=i)}return y}function Kt(t,e,n){const o=Qt(e,t,n.center,n.radius),s=Qt(t,e,n.center,n.radius),i=te(o,e),r=te(t,s),a=1e-6;let c;if(i>a&&r>a){c={x:(o.x+s.x)/2,y:(o.y+s.y)/2};const i=te(o,c),r=te(s,c);if(Math.abs(i-r)>.5*Math.min(i,r)){const n=te(t,o),i=te(e,s),r=n+i;if(r>a){const t=i/r,e=n/r;c={x:o.x*t+s.x*e,y:o.y*t+s.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 o={x:(t.x+e.x)/2,y:(t.y+e.y)/2},s=te(o,n.center);if(s<1.1*n.radius){const t={x:(o.x-n.center.x)/s,y:(o.y-n.center.y)/s};c={x:n.center.x+t.x*n.radius*1.2,y:n.center.y+t.y*n.radius*1.2}}else c=o}return{B:o,D:s,E:c}}function Qt(t,e,n,o){const s=[n.x-t.x,n.y-t.y],i=Math.sqrt(s[0]*s[0]+s[1]*s[1]);if(i<=o){if(i<1e-8){const s=[e.x-t.x,e.y-t.y],i=Math.sqrt(s[0]*s[0]+s[1]*s[1]);return i<1e-8?{x:n.x+o,y:n.y}:{x:n.x+s[0]/i*o,y:n.y+s[1]/i*o}}const r=[s[0]/i,s[1]/i];return{x:n.x-r[0]*o,y:n.y-r[1]*o}}const r=[e.x-t.x,e.y-t.y],a=Math.sqrt(i*i-o*o),c=[s[0]/i,s[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=o/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,o=e.y-t.y;return Math.sqrt(n*n+o*o)}var ee=({value:t,min:e,max:n})=>t>=e&&t<=n,ne=({value:t,target:e,epsilon:n})=>Math.abs(t-e)<=n,oe=({point:t,bounds:e,epsilon:n=1e-6})=>{if(![t.x,t.y,e.minX,e.maxX,e.minY,e.maxY].every(t=>(({value:t})=>Number.isFinite(t))({value:t})))return"outside";const o=function(t,e){return t.x>=e.minX&&t.x<=e.maxX&&t.y>=e.minY&&t.y<=e.maxY?0:Pt(t,{x:ft(t.x,e.minX,e.maxX),y:ft(t.y,e.minY,e.maxY)})}(t,e);if(o>n)return"outside";const s=ne({value:t.x,target:e.minX,epsilon:n}),i=ne({value:t.x,target:e.maxX,epsilon:n}),r=ne({value:t.y,target:e.minY,epsilon:n}),a=ne({value:t.y,target:e.maxY,epsilon:n}),c=s||i,h=r||a;if(c&&h)return"on-boundary";const d=ee({value:t.y,min:e.minY,max:e.maxY}),l=ee({value:t.x,min:e.minX,max:e.maxX});return c&&d||h&&l?"on-boundary":"inside"},se=1e-9;function ie(t,e,n,o="cw"){const s=re(t,n),i=re(e,n);return Math.abs(i-s)<se?{left:0,top:0,right:0,bottom:0}:function(t,e,n,o){const s=n.maxX-n.minX,i=n.maxY-n.minY;if(s<se&&i<se)return{left:0,top:0,right:0,bottom:0};const r=2*(s+i);if(r<se)return{left:0,top:0,right:0,bottom:0};const a=s/r*(2*Math.PI),c=(s+i)/r*(2*Math.PI),h=(s+s+i)/r*(2*Math.PI),d=2*Math.PI,l=[{name:"top",start:0,end:a,length:s},{name:"right",start:a,end:c,length:i},{name:"bottom",start:c,end:h,length:s},{name:"left",start:h,end:d,length:i}],u={left:0,top:0,right:0,bottom:0},p=(t,e,n,o,s)=>{const i=e>2*Math.PI-se?2*Math.PI:e;if(i<=t+se)return 0;if(s){const e=Math.max(t,n),s=Math.min(i,2*Math.PI),r=Math.max(0,s-e),a=Math.max(t,0),c=Math.min(i,o);return r+Math.max(0,c-a)}{const e=Math.max(t,n),s=Math.min(i,o);return Math.max(0,s-e)}};for(const n of l){const s=n.end-n.start;if(s<se||n.length<se)continue;let i=0;if("cw"===o){const o=t>e+se;i=p(n.start,n.end,t,e,o)}else{const o=e>t+se;i=p(n.start,n.end,e,t,o)}if(i>se){const t=i/s;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}(s,i,n,o)}function re(t,e){const n=e.maxX-e.minX,o=e.maxY-e.minY;if(n<se&&o<se)return 0;const s=2*(n+o);if(s<se)return 0;let i=0;if(Math.abs(t.y-e.maxY)<se&&t.x>=e.minX-se&&t.x<=e.maxX+se)i=Math.max(0,Math.min(n,t.x-e.minX));else if(Math.abs(t.x-e.maxX)<se&&t.y>=e.minY-se&&t.y<=e.maxY+se)i=n+Math.max(0,Math.min(o,e.maxY-t.y));else if(Math.abs(t.y-e.minY)<se&&t.x>=e.minX-se&&t.x<=e.maxX+se)i=n+o+Math.max(0,Math.min(n,e.maxX-t.x));else{if(!(Math.abs(t.x-e.minX)<se&&t.y>=e.minY-se&&t.y<=e.maxY+se))throw new Error(`Point (${t.x}, ${t.y}) does not lie on the boundary defined by ${JSON.stringify(e)}`);i=n+o+n+Math.max(0,Math.min(o,t.y-e.minY))}return i=Math.max(0,Math.min(s,i)),s>se?i/s*(2*Math.PI):0}function ae(t,e,n,o){return function({angleA:t,angleB:e,angleC:n}){const o=Math.cos(t),s=Math.sin(t),i=Math.cos(e),r=Math.sin(e),a=Math.cos(n);return(i-o)*(Math.sin(n)-s)-(r-s)*(a-o)<0?"ccw":"cw"}({angleA:re(t,o),angleB:re(e,o),angleC:re(n,o)})}var ce=class extends y{getSolverName(){return"SingleTransitionCrossingRouteSolver"}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=this.routes.flatMap(t=>[t.A,t.B]).map(t=>this.getPortPointBoundsPosition(t));if(e.includes("outside"))return this.failed=!0,void(this.error="Invalid route input: SingleTransitionCrossingRouteSolver received port point(s) outside node bounds");if(e.includes("inside"))return void(this.failed=!0);const[n,o]=this.routes,s=n.A.z!==n.B.z,i=o.A.z!==o.B.z;return s&&i||!s&&!i?(this.failed=!0,void(this.error="Exactly one route must have a layer transition")):void 0}extractRoutesFromNode(){const t=[],e=this.nodeWithPortPoints.portPoints,n=new Map;for(const t of e){const{connectionName:e}=t;n.has(e)||n.set(e,[]),n.get(e)?.push(t)}for(const[e,o]of n.entries())2===o.length&&t.push({A:{...o[0],z:o[0].z??0},B:{...o[1],z:o[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}}getPortPointBoundsPosition(t,e=1e-6){return oe({point:t,bounds:this.bounds,epsilon:e})}doRoutesCross(t,e){return gt(t.A,t.B,e.A,e.B)}calculateViaPosition(t,e){const n=e.A.z,o=t.A.z!==n?t.A:t.B,s=2*this.obstacleMargin+this.viaDiameter/2+this.traceThickness,i=this.obstacleMargin+this.viaDiameter/2,r=e.A,a=o,c=e.B,h=ae(r,a,c,this.bounds),d=function(t,e,n,o,s){const i=ie(t,e,o,s),r=ie(e,n,o,s),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])<se&&(a[t]=0);return a}(r,a,c,this.bounds,h),l={minX:this.bounds.minX+(d.left>.5?s:i),minY:this.bounds.minY+(d.bottom>.5?s:i),maxX:this.bounds.maxX-(d.right>.5?s:i),maxY:this.bounds.maxY-(d.top>.5?s: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,s,l)}createTransitionRoute(t,e,n,o){return{connectionName:o,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,o,s,i){o.z,t.z;const r=this.viaDiameter/2+this.traceThickness/2+this.obstacleMargin,a=((t,e,n,o)=>{const s=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+s*e,y:t.y+i*e},{x:n.x-s*o,y:n.y-i*o})})(n,this.viaDiameter,o.z!==t.z?o:s,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,o=n?t:e,s=n?e:t,i=this.calculateViaPosition(o,s);if(!i)return!1;this.debugViaPositions.push({via:i});const r=this.createTransitionRoute(o.A,o.B,i,o.connectionName),a=this.createFlatRoute(s.A,s.B,i,o.A,o.B,s.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 o=this.viaDiameter/2+this.obstacleMargin;t.circles.push({center:n,radius:o,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],o=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 s=n.route[e],i=n.route[e+1];t.lines.push({points:[s,i],strokeColor:o,strokeDash:s.z!==n.route[0].z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${s.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}},he=class extends y{getSolverName(){return"SingleTransitionIntraNodeSolver"}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,o={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,o,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,o]of n.entries())2===o.length&&t.push({A:{...o[0]},B:{...o[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,o){return{connectionName:o,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],o="rgba(0, 255, 0, 0.75)";for(let e=0;e<n.route.length-1;e++){const s=n.route[e],i=n.route[e+1];t.lines.push({points:[s,i],strokeColor:o,strokeDash:s.z!==n.route[0].z?[.2,.2]:void 0,strokeWidth:n.traceThickness,label:`${n.connectionName} z=${s.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}},de=(t,e)=>{const n={};return t.portPoints.forEach((e,o)=>{n[e.connectionName]=`hsl(${360*o/t.portPoints.length}, 100%, 50%)`}),n},le=class extends y{getSolverName(){return"ViaPossibilitiesSolver2"}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:o}){super(),this.MAX_ITERATIONS=1e5,this.colorMap=e??de(t),this.maxViaCount=5,this.bounds=kt(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=o??.6,this.unprocessedConnections=Array.from(this.portPairMap.keys()).sort(),n?.SHUFFLE_SEED&&(this.unprocessedConnections=Bt(this.unprocessedConnections,n.SHUFFLE_SEED));for(const[t,{start:e,end:n}]of this.portPairMap.entries())if(e.z===n.z){const o=Math.abs(e.x-n.x)<1e-9,s=Math.abs(e.y-n.y)<1e-9;o||s?this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),this._padByPlaceholderWallBuffer(n),n]):this.placeholderPaths.set(t,[e,n])}else{const o=(e.x+n.x)/2,s=(e.y+n.y)/2,i=this._padByPlaceholderWallBuffer({x:o,y:s,z:e.z}),r=this._padByPlaceholderWallBuffer({x:o,y:s,z:n.z});this.placeholderPaths.set(t,[e,this._padByPlaceholderWallBuffer(e),i,r,this._padByPlaceholderWallBuffer(n),n])}this.currentConnectionName=this.unprocessedConnections.pop();const s=this.portPairMap.get(this.currentConnectionName).start;this.currentHead=this._padByNewHeadWallBuffer(s),this.currentPath=[s,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,o=null;const s=t=>{for(const s of t.values())for(let t=0;t<s.length-1;t++){const i=[s[t],s[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=St(e[0],e[1],i[0],i[1]);if(r){const t=Pt(this.currentHead,r);if(t<1e-6)continue;(!n||t<n.dist)&&(n={point:r,dist:t},o=i[0].z)}}};s(this.completedPaths),s(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=Mt(this.currentHead,n.point);else{const o=n.point,s=o.x-this.currentHead.x,i=o.y-this.currentHead.y,r=(e-this.VIA_INTERSECTION_BUFFER_DISTANCE)/e;t={x:this.currentHead.x+s*r,y:this.currentHead.y+i*r}}const s=this.availableZ.find(t=>t!==o);if(void 0===s)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:s};this.currentPath.push(i,r),this.currentHead=r}else if(i){let e;const n=Pt(this.currentHead,t);if(n<this.VIA_INTERSECTION_BUFFER_DISTANCE)e=Mt(this.currentHead,t);else{const o=t.x-this.currentHead.x,s=t.y-this.currentHead.y,i=(n-this.VIA_INTERSECTION_BUFFER_DISTANCE)/n;e={x:this.currentHead.x+o*i,y:this.currentHead.y+s*i}}const o=t.z,s={...e,z:this.currentHead.z},i={...e,z:o};this.currentPath.push(s,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:o}]of this.portPairMap.entries()){const s=this.colorMap[e]??"black";t.points.push({x:n.x,y:n.y,color:s,label:`Port: ${e} Start (z${n.z})`}),t.points.push({x:o.x,y:o.y,color:s,label:`Port: ${e} End (z${o.z})`})}const n=(n,o)=>{for(const[s,i]of n.entries()){const n=e[s]??"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:`${o}: ${s} 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:`${o}: ${s} (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 o=this.currentPath[e],s=this.currentPath[e+1];o.x===s.x&&o.y===s.y&&o.z!==s.z?t.circles.push({center:{x:o.x,y:o.y},radius:this.viaDiameter/2,fill:it(n,.5),label:`Current: ${this.currentConnectionName} Via (z${o.z}->z${s.z})`}):t.lines.push({points:[o,s],strokeColor:it(n,.5),strokeWidth:.15,strokeDash:"2,2",label:`Current: ${this.currentConnectionName} (z${o.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}},ue=t=>Math.round(1e4*t),pe=t=>{let e=0,n=[];const o=[];for(const e of t.portPoints){if(n.some(t=>t.connectionName===e.connectionName))continue;if(o.some(t=>t.connectionName===e.connectionName))continue;const s={connectionName:e.connectionName,z:e.z,points:[{x:ue(e.x),y:ue(e.y),z:e.z}]};for(const n of t.portPoints)e.connectionName===n.connectionName&&(e.x===n.x&&e.y===n.y||s.points.push({x:ue(n.x),y:ue(n.y),z:n.z}));s.points.some(t=>t.z!==s.z)?o.push(s):n.push(s)}n=n.filter(t=>t.points.length>1);for(let t=0;t<n.length;t++)for(let o=t+1;o<n.length;o++){const s=n[t],i=n[o];s.z===i.z&&gt(s.points[0],s.points[1],i.points[0],i.points[1])&&e++}let s=0;for(let t=0;t<o.length;t++)for(let e=t+1;e<o.length;e++){const n=o[t],i=o[e];gt(n.points[0],n.points[1],i.points[0],i.points[1])&&s++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:o.length,numTransitionPairCrossings:s}},me=1e-9;function fe(t,e,n=me){return Math.abs(t-e)<n}function ge(t,e,n,o){return t*o-e*n}function ye(t,e,n,o){const s={x:e.x-t.x,y:e.y-t.y},i={x:o.x-n.x,y:o.y-n.y},r=ge(s.x,s.y,i.x,i.y);if(fe(r,0))return null;const a={x:n.x-t.x,y:n.y-t.y},c=ge(a.x,a.y,i.x,i.y)/r,h=ge(a.x,a.y,s.x,s.y)/r;return c<-me||c>1+me||h<-me||h>1+me?null:{x:t.x+c*s.x,y:t.y+c*s.y}}function xe(t){let e=0;for(let n=0,o=t.length;n<o;++n){const s=(n+1)%o;e+=t[n].x*t[s].y-t[s].x*t[n].y}return.5*e}function ve(t){let e=0,n=0,o=0;for(let s=0,i=t.length;s<i;++s){const r=(s+1)%i,a=t[s].x*t[r].y-t[r].x*t[s].y;e+=a,n+=(t[s].x+t[r].x)*a,o+=(t[s].y+t[r].y)*a}return e*=.5,fe(e,0)?null:(n/=6*e,o/=6*e,{x:n,y:o})}var Pe=class{x;y;out;connectionNames;constructor(t,e){this.x=t,this.y=e,this.out=[],this.connectionNames=new Set}},Se=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 Me(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}}]],o=n.map(()=>[]);for(let t=0;t<n.length;++t){const e=n[t];o[t].push(e.start,e.end)}for(let t=0;t<n.length;++t)for(let e=t+1;e<n.length;++e){const s=ye(n[t].start,n[t].end,n[e].start,n[e].end);s&&(o[t].push(s),o[e].push(s))}const s=new Map,i=[];function r(t){const e=function(t,e=me){return`${Math.round(t.x/e)}:${Math.round(t.y/e)}`}(t);if(!s.has(e)){const n=i.length;return s.set(e,n),i.push(new Pe(t.x,t.y)),n}return s.get(e)}const a=[];for(let t=0;t<n.length;++t){const e=n[t],s=o[t].slice();s.sort((t,n)=>{const o=e.end.x-e.start.x,s=e.end.y-e.start.y;return(fe(Math.abs(o),0)?(t.y-e.start.y)/s:(t.x-e.start.x)/o)-(fe(Math.abs(o),0)?(n.y-e.start.y)/s:(n.x-e.start.x)/o)});for(let t=0;t<s.length-1;++t){const n=s[t],o=s[t+1],c=r(n),h=r(o);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 Se(t,e),o=new Se(e,t);n.twin=c.length+1,o.twin=c.length;const s=c.length;c.push(n,o),i[t].out.push(s),i[e].out.push(s+1)}for(let t=0;t<i.length;++t){const e=i[t];e.out.sort((t,n)=>{const o=c[t],s=c[n],r=i[o.dest],a=i[s.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 o=e.out[t],s=e.out[(t-1+n)%n],i=c[o];null!==i.twin&&(c[i.twin].next=s)}}const h=[],d=[];for(let t=0;t<c.length;++t){if(c[t].visited)continue;let e=t;const n=[],o=[];do{if(null===e)break;const t=c[e];t.visited=!0,n.push(i[t.orig]),o.push(e),e=t.next}while(null!==e&&e!==t&&!c[e].visited);if(n.length<3)continue;if(xe(n)>me){const t=ve(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 be(t,e){if(t>e)throw new Error("oneCount cannot be greater than length");if(t<0||e<0)throw new Error("oneCount and length must be non-negative");const n=[];return function t(o,s,i){i!==e?(o[i]=0,t(o,s,i+1),s>0&&(o[i]=1,t(o,s-1,i+1))):0===s&&n.push([...o])}(Array(e).fill(0),t,0),n}var Ne=t=>{if(0===t.length)return[[]];const e=[];for(let n=0;n<t.length;n++){const o=t[n],s=[...t.slice(0,n),...t.slice(n+1)],i=Ne(s);for(const t of i)e.push([o,...t])}return e};var Ie=t=>{const{start:e,end:n,segmentsPerPolyline:o,viaPositions:s,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 o=Math.floor(t/e),s=Math.floor((t-(o*(e-1)+1))/2);for(let t=0;t<e;t++)n[s+t*o]=1}else{const o=t-e,s=Math.floor(t/o),i=Math.floor((t-(s*(o-1)+1))/2);n.fill(1);for(let t=0;t<o;t++)n[i+t*s]=0}return n}(o,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]={...s[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,o=c.length;for(let n=t+1;n<c.length;n++)if(c[n]){e=c[n],o=n;break}const s=o-t,i=e.x-u.x,r=e.y-u.y;for(let e=1/(s+1),n=0;t+n!==o;e+=1/(s+1),n++)c[t+n]={x:u.x+i*e,y:u.y+r*e,z1:u.z2,z2:u.z2}}return c},Ce=1e-9;function _e(t,e){return Math.abs(t-e)<Ce}function Te(t){return`${Math.round(t.x/Ce)}:${Math.round(t.y/Ce)}`}function Ee(t,e,n,o){return t*o-e*n}function Re(t,e,n,o){const s={x:e.x-t.x,y:e.y-t.y},i={x:o.x-n.x,y:o.y-n.y},r=Ee(s.x,s.y,i.x,i.y),a={x:n.x-t.x,y:n.y-t.y};if(_e(r,0))return null;const c=Ee(a.x,a.y,i.x,i.y)/r,h=Ee(a.x,a.y,s.x,s.y)/r;return c>=-1e-9&&c<=1+Ce&&h>=-1e-9&&h<=1+Ce?{x:t.x+c*s.x,y:t.y+c*s.y}:null}function we(t,e,n){return _e(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 Ae(t,e){const n=[],o=new Map;for(const e of t){const t=[e.start,...e.mPoints,e.end];for(let s=0;s<t.length-1;s++){const i=t[s],r=t[s+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=Te(i);o.has(t)||o.set(t,{point:i,connectionName:e.connectionName})}}const s=t[t.length-1];if(s.z1!==s.z2){const t=Te(s);o.has(t)||o.set(t,{point:s,connectionName:e.connectionName})}}const s=[{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(...s);const i=new Map;let r=0;function a(t,e){const n=Te(t);let s=i.get(n);if(!s){const e=o.has(n);s={id:r++,x:t.x,y:t.y,isVia:e,connectionNames:new Set,outgoingEdges:[]},i.set(n,s),e&&o.get(n)&&s.connectionNames.add(o.get(n).connectionName)}return e&&s.connectionNames.add(e),s}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 o=Re(n[t].start,n[t].end,n[e].start,n[e].end);o&&(a(o),we(o,n[t].start,n[t].end)&&c.get(n[t]).push(o),we(o,n[e].start,n[e].end)&&c.get(n[e]).push(o))}const h=[];let d=0;for(const t of n){const e=[t.start,...c.get(t),t.end];e.sort((e,n)=>{const o=t.end.x-t.start.x,s=t.end.y-t.start.y;return Math.abs(o)>Math.abs(s)?(e.x-t.start.x)/o-(n.x-t.start.x)/o:Math.abs(s)<Ce?0:(e.y-t.start.y)/s-(n.y-t.start.y)/s});const n=[];if(e.length>0){n.push(e[0]);for(let t=1;t<e.length;t++)_e(e[t].x,e[t-1].x)&&_e(e[t].y,e[t-1].y)||n.push(e[t])}for(let e=0;e<n.length-1;e++){const o=n[e],s=n[e+1],i=a(o,t.connectionName),r=a(s,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 o=e.twin.origin,s=n.twin.origin;return Math.atan2(o.y-t.y,o.x-t.x)-Math.atan2(s.y-t.y,s.x-t.x)});const e=t.outgoingEdges.length;for(let n=0;n<e;n++){const o=t.outgoingEdges[n],s=t.outgoingEdges[(n-1+e)%e];o.twin&&(o.twin.next=s)}}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 o=[],s=[],i=new Set;let r=0;do{if(!n||n.visited){console.warn("Face traversal encountered visited edge or null, breaking loop.",e.id),o.length=0;break}n.visited=!0,n.face=e,o.push(n),s.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&&o.length>0){if([...i].filter(t=>null!==t).length>1){let t=!1;for(const e of s)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 Oe=class extends y{getSolverName(){return"MultiHeadPolyLineIntraNodeSolver"}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??de(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,o=new Set(this.nodeWithPortPoints.portPoints.map(t=>t.connectionName)).size;this.uniqueConnections=o;const{numSameLayerCrossings:s,numEntryExitLayerChanges:i}=pe(this.nodeWithPortPoints);if(this.minViaCount=2*s+i,this.maxViaCount=Math.min(Math.floor(e/n),Math.ceil(1.5*o)),this.minViaCount>this.SEGMENTS_PER_POLYLINE*(o/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=[],o=[];for(let e=0;e<t.length;e++){const s=t[e],i=[s.start,...s.mPoints,s.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),o.push(i.filter(t=>t.z1!==t.z2))}for(let s=0;s<t.length;s++){const i=n[s],r=o[s];for(let a=s+1;a<t.length;a++){if(this.connMap?.areIdsConnected(t[s].connectionName,t[a].connectionName))continue;const c=n[a],h=o[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,Pt(t,e)-this.viaDiameter)}e.push(d)}}return e}insertCandidate(t){let e=0,n=this.candidates.length-1;for(;e<=n;){const o=Math.floor((e+n)/2);this.candidates[o].f<t.f?e=o+1:n=o-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,o)=>{const s=[];for(const[,n]of t){const t=n.start.z1!==n.end.z1,o=[];for(let n=0;n<=e;n++){const e=n%2!=0;t&&e?o.push(n):t||e||o.push(n)}s.push(o)}if(0===s.length)return[[]];let i=(t=>{if(!t||0===t.length)return[[]];let e=[[]];for(const n of t){const t=[];for(const o of e)for(const e of n)t.push([...o,e]);e=t}return e})(s).filter(t=>{for(let e=0;e<t.length;e++)if(t.reduce((t,e)=>t+e,0)<o)return!1;return!0});return i=i.filter(e=>{for(let n=0;n<t.length;n++){const[,o]=t[n];if(o.start.z1!==o.start.z2&&0===e[n])return!1}return!0}),i=i.filter(e=>{for(let n=0;n<t.length;n++){const[,o]=t[n];if(t[n][1].start.z1===t[n][1].start.z2)for(let s=n+1;s<t.length;s++){if(t[s][1].start.z1!==t[s][1].start.z2)continue;const[,i]=t[s];if(o.start.z1===o.end.z1&&i.start.z1===i.end.z1&&o.start.z1===i.start.z1&&gt(o.start,o.end,i.start,i.end)&&e[n]+e[s]<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),o=(t=>{const{bounds:e,portPairsEntries:n,viaCountVariants:o}=t,{centroids:s}=Me(e,n.map(([t,e])=>e)),i=[];for(const t of o){const n=t.reduce((t,e)=>t+e,0);let o=s;if(s.length<n){o=[];const t=Math.ceil(Math.sqrt(n)),s=t;for(let n=0;n<t;n++)for(let i=0;i<s;i++)o.push({x:e.minX+(i+1)/(s+1)*(e.maxX-e.minX),y:e.minY+(n+1)/(t+1)*(e.maxY-e.minY)})}const r=be(n,o.length);for(const e of r){const n=[];for(let t=0;t<e.length;t++)1===e[t]&&n.push(o[t]);i.push({viaPositions:n,viaCountVariant:t})}}return i})({portPairsEntries:e,viaCountVariants:n,bounds:this.bounds}),s=[];for(const{viaCountVariant:t,viaPositions:e}of o){const n=Ne(e);for(const e of n)s.push({viaCountVariant:t,viaPositions:e})}for(const{viaPositions:t,viaCountVariant:n}of s){const o=[];let s=0;for(let i=0;i<e.length;i++){const[r,a]=e[i],c=n[i],h=t.slice(s,s+c),d=Ie({start:a.start,end:a.end,segmentsPerPolyline:this.SEGMENTS_PER_POLYLINE,viaPositions:h,viaCount:c,availableZ:this.availableZ});s+=c,o.push({connectionName:r,start:a.start,end:a.end,mPoints:d})}if(Ae(o,this.bounds))continue;const i=this.computeMinGapBtwPolyLines(o),r=this.computeH({minGaps:i,forces:[]}),a={polyLines:o,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,o=.02,s=.008,i=1e-6,r=Array.from({length:n},(t,n)=>Array.from({length:e[n].mPoints.length},()=>new Map)),a=(t,n,o,s,i)=>{if(n>0&&n<e[t].mPoints.length+1){const e=n-1,a=r[t][e],c=a.get(o)||{fx:0,fy:0};a.set(o,{fx:c.fx+s,fy:c.fy+i})}};for(let t=0;t<n;t++)for(let s=t+1;s<n;s++){const n=e[t],r=e[s],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 o={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=o.x-r.x,h=o.y-r.y,d=c*c+h*h;if(d>i){const o=Math.sqrt(d),r=(Math.exp(-6*o),`seg:${s}:${n.p1Idx}:${n.p2Idx}`),c=`seg:${t}:${e.p1Idx}:${e.p2Idx}`,h=(t,e,n,o,s,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(o,e,r,f,g),a(s,n.p1Idx,c,-f/2,-g/2),a(s,n.p2Idx,c,-f/2,-g/2)};h(e.p1,e.p1Idx,n,t,s,r,c),h(e.p2,e.p2Idx,n,t,s,r,c),h(n.p1,n.p1Idx,e,s,t,c,r),h(n.p2,n.p2Idx,e,s,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*o*Math.exp(-6*u),m=c/r*p,f=h/r*p,g=`seg:${s}:${n.p1Idx}:${n.p2Idx}`;a(t,e.index,g,m,f);const y=`via:${t}:${e.index}`;a(s,n.p1Idx,y,-m/2,-f/2),a(s,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*o*Math.exp(-6*u),m=c/r*p,f=h/r*p,g=`seg:${t}:${n.p1Idx}:${n.p2Idx}`;a(s,e.index,g,m,f);const y=`via:${s}:${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*o*Math.exp(-6*u),m=r/d*p,f=c/d*p,g=`via:${s}:${n.index}`,y=`via:${t}:${e.index}`;a(t,e.index,g,m,f),a(s,n.index,y,-m,-f)}}}}for(let t=0;t<n;t++){const n=e[t],s=[n.start,...n.mPoints,n.end],r=[];if(s.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 s=r[e],c=r[n],h=s.point.x-c.point.x,d=s.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*o*Math.exp(-6*r),p=h/e*u,m=d/e*u,f=`via:${t}:${c.index}`,g=`via:${t}:${s.index}`;a(t,s.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],o=r[t][e],a={fx:0,fy:0};for(const t of o.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,o=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=s*(Math.exp(p/(2*this.obstacleMargin))-1):m>0&&(e=-.008*(Math.exp(m/(2*this.obstacleMargin))-1)),f>0?o=s*(Math.exp(f/(2*this.obstacleMargin))-1):g>0&&(o=-.008*(Math.exp(g/(2*this.obstacleMargin))-1)),a.fx+=e,a.fy+=o,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,o)=>{const s=this.colorMap[n.connectionName]??"purple",i=[n.start,...n.mPoints,n.end];for(let e=0;e<i.length-1;e++){const o=i[e],r=i[e+1],a=o.z2,c=0===a,h=c?s:it(s,.5);t.lines.push({points:[o,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 s=a-1,i=e.forces?.[o]?.[s];if(i&&i.size>0){const o={fx:0,fy:0};i.forEach((i,a)=>{if(o.fx+=i.fx,o.fy+=i.fy,Math.abs(i.fx)>1e-6||Math.abs(i.fy)>1e-6){const o=a.split(":"),c=o[0],h=parseInt(o[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(o[2],10)}`}else if("seg"===c){m+=` Seg ${parseInt(o[2],10)}-${parseInt(o[3],10)}`}t.lines.push({points:[r,p],strokeColor:l,strokeWidth:.02,strokeDash:"2,2",label:`Force by ${m} on ${n.connectionName} mPoint ${s}`})}}),(Math.abs(o.fx)>1e-6||Math.abs(o.fy)>1e-6)&&(u=`\nNet Force: (${o.fx.toFixed(3)}, ${o.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(s,.5),label:l});else if(d){const e=0===h?s:it(s,.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=[],o=[],s=[e.start,...e.mPoints,e.end];for(let t=0;t<s.length;t++){const e=s[t];n.push({x:e.x,y:e.y,z:e.z1}),e.z1!==e.z2&&(o.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:o})}this.solvedRoutes=t}},ze=class extends Oe{getSolverName(){return"MultiHeadPolyLineIntraNodeSolver2"}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 o=void 0===t.magForceApplied?1:10;for(let s=0;s<o;s++){const o=this.applyForcesToPolyLines(t.polyLines);if(n+=o.magForceApplied,e=o.lastStepMoved,!o.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,o=.02,s=.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,o,s)=>{if(n>0&&n<t[e].mPoints.length+1){const t=n-1;r[e][t].fx+=o,r[e][t].fy+=s}},c=(t,e,n,o,s)=>{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(o,e,p,m),a(s,n.p1Idx,-p/2,-m/2),a(s,n.p2Idx,-p/2,-m/2)};for(let e=0;e<n;e++)for(let s=e+1;s<n;s++){const n=t[e],r=t[s],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,s),c(t.p2,t.p2Idx,n,e,s),c(n.p1,n.p1Idx,t,s,e),c(n.p2,n.p2Idx,t,s,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*o*Math.exp(-6*u),m=c/r*p,f=h/r*p;a(e,t.index,m,f),a(s,n.p1Idx,-m/2,-f/2),a(s,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*o*Math.exp(-6*u),m=c/r*p,f=h/r*p;a(s,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*o*Math.exp(-6*u),m=r/d*p,f=c/d*p;a(e,t.index,m,f),a(s,n.index,-m,-f)}}}}for(let e=0;e<n;e++){const n=t[e],s=[n.start,...n.mPoints,n.end],r=[];if(s.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 s=r[t],c=r[n],h=s.point.x-c.point.x,d=s.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*o*Math.exp(-6*r),p=h/t*u,m=d/t*u;a(e,s.index,p,m),a(e,c.index,-p,-m)}}}let h=!1;for(let o=0;o<n;o++)for(let n=0;n<t[o].mPoints.length;n++){const a=t[o].mPoints[n],c=r[o][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 o=this.viaDiameter/2+this.BOUNDARY_PADDING,i=this.bounds.minX+o,r=this.bounds.maxX-o,c=this.bounds.minY+o,h=this.bounds.maxY-o,d=i+t-a.x,f=a.x-(r-t),g=c+t-a.y,y=a.y-(h-t);d>0?e=s*(Math.exp(d/(2*this.obstacleMargin))-1):f>0&&(e=-.008*(Math.exp(f/(2*this.obstacleMargin))-1)),g>0?n=s*(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}}},De=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 Le=class extends ze{getSolverName(){return"MultiHeadPolyLineIntraNodeSolver3"}constructor(t){super(t),this.MAX_ITERATIONS=1e3}createInitialCandidateFromSeed(t){const e=new le({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 o=0;for(const[t,s]of e.completedPaths.entries()){if(s.length<2){console.warn(`Skipping connection "${t}" due to insufficient points (${s.length}) in ViaPossibilitiesSolver2 path.`);continue}const e=s[0],i=s[s.length-1],r=s.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,o=h,s=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:o,z2:s}),o!==s?(c++,t++,h=s):h=e.z}o+=c;const d=this.SEGMENTS_PER_POLYLINE;let l=a.length+1;for(;l<d;){let n=-1,o=-1,s=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=Pt(e,i);a>n&&(n=a,o=t,s=e,r=i)}if(-1===o||!s||!r){console.warn(`Could not find longest segment for ${t} while trying to reach ${d} segments.`);break}const h=(s.x+r.x)/2,u=(s.y+r.y)/2,p=s.z2,m={x:h,y:u,z1:p,z2:p};a.splice(o,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 s=this.computeMinGapBtwPolyLines(n),i=this.computeH({minGaps:s,forces:[]}),r={polyLines:n,g:0,h:i,f:0+i,viaCount:o,minGaps:s};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 o=De(t.polyLines);e.has(o)||(e.add(o),this.candidates.push(t))}this.candidates.sort((t,e)=>t.f-e.f)}},Fe=class extends Zt{getSolverName(){return"HyperSingleIntraNodeSolver"}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 ce({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.CLOSED_FORM_SINGLE_TRANSITION?new he({nodeWithPortPoints:this.nodeWithPortPoints,viaDiameter:this.constructorParams.viaDiameter}):t.MULTI_HEAD_POLYLINE_SOLVER?new Le({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 Xe(t,e,n){const o=[];let s=null;for(let i=0;i<t.length;i++){const r=t[i];s?s.z===r.z?s.points.push({x:r.x,y:r.y}):(o.push(s),s={points:[{x:r.x,y:r.y}],z:r.z,connectionName:e,color:n}):s={points:[{x:r.x,y:r.y}],z:r.z,connectionName:e,color:n},i===t.length-1&&s&&o.push(s)}return o}var Ye=class extends y{getSolverName(){return"HighDensitySolver"}unsolvedNodePortPoints;routes;colorMap;defaultViaDiameter=.6;defaultTraceThickness=.15;viaDiameter;traceWidth;failedSolvers;activeSubSolver=null;connMap;constructor({nodePortPoints:t,colorMap:e,connMap:n,viaDiameter:o,traceWidth:s}){super(),this.unsolvedNodePortPoints=t,this.colorMap=e??{},this.connMap=n,this.routes=[],this.failedSolvers=[],this.MAX_ITERATIONS=1e6,this.viaDiameter=o??this.defaultViaDiameter,this.traceWidth=s??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 Fe({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=Xe(e.route,e.connectionName,this.colorMap[e.connectionName]);for(const o of n)t.lines.push({points:o.points,label:o.connectionName,strokeColor:0===o.z?o.color:it(o.color,.75),layer:`z${o.z}`,strokeWidth:e.traceThickness,strokeDash:0!==o.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,o=.1*n.width,s=.1*n.height;t.rects.push({center:{x:n.center.x-o/2,y:n.center.y-s/2},layer:"did_not_connect",width:o,height:s,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 o=n[e],s=n[e+1];t.lines.push({points:[o,s],strokeColor:"red",strokeDash:"10, 5",layer:"did_not_connect"})}}return this.activeSubSolver&&(t=g(t,this.activeSubSolver.visualize())),t}},$e=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 o=this.getNetConnectedToId(e);return!!o&&(n===o||o===t||o===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}},Be=(t,e)=>"top"===t?0:"bottom"===t?e-1:parseInt(t.slice(5)),ke=t=>`${Math.round(100*t.x)},${Math.round(100*t.y)}`,je=t=>{const e=new $e({});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 o of n.pointsToConnect)e.addConnections([[n.name,`${ke(o)}:${"layers"in o?o.layers.map(e=>Be(e,t.layerCount)).sort().join("-"):Be(o.layer,t.layerCount)}`]]),"pcb_port_id"in o&&o.pcb_port_id&&e.addConnections([[n.name,o.pcb_port_id]])}for(const n of t.obstacles){const o=n.offBoardConnectsTo??[],s=Array.from(new Set([n.obstacleId,...n.connectedTo,...o,`${ke(n.center)}:${n.layers.map(e=>Be(e,t.layerCount)).sort().join("-")}`].filter(Boolean)));s.length>0&&e.addConnections([s])}return e},We=(t,e=1,n={})=>{const o=n.viaDiameter??.6,s=n.obstacleMargin??.2,i=(("width"in t?t.width:t)/(o/2+s)/2)**1.1*e;return 1===t.availableZ?.length&&i>1?1:i},He=(t,e=.5,n=16)=>{let o=0,s=t;for(;o<n;){if(We({width:s})<=e)break;s/=2,o++}return Math.max(1,o)},Ue=(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}`},Ve=(t,e)=>{const n=[];if(0===t.route.length)return n;let o=[],s=t.route[0].z;for(let i=0;i<t.route.length;i++){const r=t.route[i];if(r.z!==s){const i=Ue(s,e);for(const e of o)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=Ue(s,e),o=Ue(r.z,e);n.push({route_type:"via",x:r.x,y:r.y,from_layer:t,to_layer:o})}o=[r],s=r.z}else o.push(r)}const i=Ue(s,e);for(const e of o)n.push({route_type:"wire",x:e.x,y:e.y,width:t.traceThickness,layer:i});if(t.jumpers&&t.jumpers.length>0){const o=Ue(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:o})}return n};function Ze(t){return"layers"in t&&Array.isArray(t.layers)}function Ge(t){return Ze(t)?t.layers[0]:t.layer}function Je(t){return Ze(t)?t.layers:[t.layer]}var qe={"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 Ke(t,e={}){const n=[],o=[],s=e.color??"gray",i=e.label,r=qe[t.footprint]??qe["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(s,.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(s,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper",label:i?`${i} (end)`:void 0}),o.push({points:[t.start,t.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*r.padWidth,layer:"jumper-body"}),{rects:n,lines:o}}function Qe(t,e={}){const n={rects:[],lines:[]};for(const o of t){const{rects:t,lines:s}=Ke(o,e);n.rects.push(...t),n.lines.push(...s)}return n}var tn=1e5,en=.001,nn=class extends y{getSolverName(){return"SingleHighDensityRouteStitchSolver"}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],o="start-to-end";for(const s of t.hdRoutes){const i=s.route[0],r=s.route[s.route.length-1],a=Pt(t.start,i),c=Pt(t.start,r),h=Pt(t.end,i),d=Pt(t.end,r),l=Math.min(a,c,h,d);l<e&&(e=l,n=s,o=Math.min(h,d)<Math.min(a,c)?"end-to-start":"start-to-end")}"start-to-end"===o?(this.start=t.start,this.end=t.end):(this.start=t.end,this.end=t.start);const s=n.route[0],i=n.route[n.route.length-1],r=Pt(this.start,s)<=Pt(this.start,i)?s: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&&Pt(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",o=1/0;for(let s=0;s<this.remainingHdRoutes.length;s++){const i=this.remainingHdRoutes[s],r=i.route[0],a=i.route[i.route.length-1],c=Pt(t,r),h=Pt(t,a);let d=1/0;d=t.z===r.z?c<en?c:tn+c:c<en?1e3+c:tn+c,d<o&&(o=d,e=s,n="first");let l=1/0;l=t.z===a.z?h<en?h:tn+h:h<en?1e3+h:tn+h,l<o&&(o=l,e=s,n="last")}if(-1===e)return void(this.remainingHdRoutes=[]);const s=this.remainingHdRoutes[e];let i;this.remainingHdRoutes.splice(e,1),i="first"===n?s.route:[...s.route].reverse(),i.length>0&&Pt(t,i[0])<en&&t.z===i[0].z?this.mergedHdRoute.route.push(...i.slice(1)):this.mergedHdRoute.route.push(...i),this.mergedHdRoute.vias.push(...s.vias),s.jumpers&&this.mergedHdRoute.jumpers.push(...s.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=Qe(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 o=this.colorMap[n.connectionName]??"gray";n.route.length>1&&t.lines?.push({points:n.route.map(t=>({x:t.x,y:t.y})),strokeColor:o});for(let s=0;s<n.route.length;s++){const i=n.route[s];t.points?.push({x:i.x+(e%2-.5)/500+(s%8-4)/1e3,y:i.y+(e%2-.5)/500+(s%8-4)/1e3,color:o,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:o});if(n.jumpers&&n.jumpers.length>0){const e=Qe(n.jumpers,{color:o,label:n.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}return t}},on=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],o=this.netMap[e];if(t&&o){t.push(...o),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 o=this.getNetConnectedToId(e);return!!o&&(n===o||o===t||o===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}},sn=t=>`${Math.round(100*t.x)},${Math.round(100*t.y)},${Math.round(100*t.z)}`,rn=class extends y{getSolverName(){return"MultipleHighDensityRouteStitchSolver"}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 on({}),o=[],s=new Map;for(let e=0;e<t.hdRoutes.length;e++){const n=t.hdRoutes[e],s=n.route[0],i=n.route[n.route.length-1];o.push([`route_island_${e}`,`${n.connectionName}:${sn(s)}`,`${n.connectionName}:${sn(i)}`])}n.addConnections(o);for(const t of o)for(const e of t.slice(1))s.set(e,(s.get(e)??0)+1);this.unsolvedRoutes=[];const i=Array.from(new Set(Object.values(n.idToNetMap)));for(const e of i){const o=n.getIdsConnectedToNet(e),i=t.hdRoutes.filter((t,e)=>o.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}:${sn(t)}`;1===s.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:Be(Ge(r.pointsToConnect[0]),t.layerCount)},d={...r.pointsToConnect[1],z:Be(Ge(r.pointsToConnect[1]),t.layerCount)}):(h=c[0],d=c[1],Pt(h,r.pointsToConnect[1])<Pt(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 nn&&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 nn({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 o=this.colorMap[n.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<n.route.length-1;e++){const s=n.route[e],i=n.route[e+1],r=0!==s.z?it(o,.5):o;t.lines?.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:r,strokeWidth:n.traceThickness})}for(const e of n.route){const n=0!==e.z?it(o,.5):o;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:o});if(n.jumpers&&n.jumpers.length>0){const e=Qe(n.jumpers,{color:o,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 o of e.hdRoutes){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"});for(const e of o.vias)t.circles?.push({center:{x:e.x,y:e.y},radius:o.viaDiameter/2,fill:n});if(o.jumpers&&o.jumpers.length>0){const e=Qe(o.jumpers,{color:n,label:o.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}}return t}},an=t=>{const e=[],n=[],o=[],s=[],i=st(t),r=(t.minViaDiameter??.6)/2;if(t.connections)for(const e of t.connections)for(const t of e.pointsToConnect){const n=Je(t);o.push({x:t.x,y:t.y,color:i[e.name],layer:n[0]??("z"in t?Ue(t.z,2):"top"),label:`${e.name} (${n.join(",")})`})}if(t.traces)for(const o of t.traces){let a=t.minTraceWidth;const c=o.route.filter(t=>"jumper"===t.route_type),h=(t,e)=>{const n=.01;for(const o of c){const s=Math.abs(t.x-o.start.x)<n&&Math.abs(t.y-o.start.y)<n&&Math.abs(e.x-o.end.x)<n&&Math.abs(e.y-o.end.y)<n,i=Math.abs(t.x-o.end.x)<n&&Math.abs(t.y-o.end.y)<n&&Math.abs(e.x-o.start.x)<n&&Math.abs(e.y-o.start.y)<n;if(s||i)return!0}return!1};for(let t=0;t<o.route.length-1;t++){const c=o.route[t],d=o.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[o.connection_name]??"rgba(255, 165, 0, 0.8)",n=c.footprint,r=qe["1206x4_pair"===n?"1206x4_pair":"0603"]??qe["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;s.push({center:c.start,width:l,height:u,fill:it(t,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),s.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[o.connection_name],n="top"===c.layer,s=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${Be(c.layer,2)}`,strokeWidth:a,strokeColor:n?s:it(s,.5),...n?{}:{strokeDash:"3 2"}})}}}for(const e of t.obstacles)s.push({center:e.center,width:e.width,height:e.height,fill:"rgba(255,0,0,0.5)",layer:`z${e.layers.map(t=>Be(t,2)).join(",")}`});if(t.jumpers)for(const e of t.jumpers)for(const t of e.pads)s.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:s,circles:n,lines:e,points:o}};function cn(t,e){const n=t.center.x-t.width/2,o=t.center.x+t.width/2,s=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(o-r)<d||Math.abs(n-a)<d)&&Math.min(i,h)-Math.max(s,c)>=d,u=(Math.abs(i-c)<d||Math.abs(s-h)<d)&&Math.min(o,a)-Math.max(n,r)>=d;return l||u}var hn=class extends y{constructor(t){super(),this.nodes=t,this.edges=[]}getSolverName(){return"CapacityMeshEdgeSolver"}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)&&cn(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 o of this.nodes){if(o._containsObstacle)continue;if(o._containsTarget)continue;const s=Pt(e.center,o.center);s<n&&(n=s,t=o)}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]),o=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&o?.center){const t=Math.min(...n.availableZ),s=Math.min(...o.availableZ),i={x:n.center.x+t*n.width*.05,y:n.center.y-t*n.width*.05},r={x:o.center.x+s*o.width*.05,y:o.center.y-s*o.width*.05},a=Array.from(new Set([...n.availableZ,...o.availableZ])).sort();e.lines.push({layer:`z${a.join(",")}`,points:[i,r],strokeDash:n.availableZ.join(",")===o.availableZ.join(",")?void 0:"10 5"})}}return e}},dn=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,o=e.center.x+e.width/2,s=e.center.y+e.height/2;for(let i=t;i<=o;i+=this.CELL_SIZE)for(let t=n;t<=s;t+=this.CELL_SIZE){const n=this.getBucketKey(i,t),o=this.buckets.get(n);o?o.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,o){const s=[],i=new Set,r=e-o/2,a=t+n/2,c=e+o/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),o=this.buckets.get(n)||[];for(const t of o)i.has(t.capacityMeshNodeId)||(i.add(t.capacityMeshNodeId),s.push(t))}return s}},ln=class extends hn{constructor(t){super(t),this.nodes=t,this.MAX_ITERATIONS=1e7,this.nodeTree=new dn(this.nodes),this.currentNodeIndex=0,this.edgeSet=new Set}getSolverName(){return"CapacityMeshEdgeSolver2_NodeTreeOptimization"}nodeTree;currentNodeIndex;edgeSet;_step(){if(this.currentNodeIndex>=this.nodes.length)return this.handleTargetNodes(),void(this.solved=!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(!cn(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++}},un=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),o=this.find(e);n!==o&&(this.parent[o]=n)}getGroup(t){const e=this.find(t),n=[];for(const t in this.parent)this.find(t)===e&&n.push(t);return n}},pn=class{point;left=null;right=null;constructor(t){this.point=t}},mn=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 o=Math.floor(t.length/2),s=new pn(t[o]);return o>0&&(s.left=this.buildTree(t.slice(0,o),e+1)),o<t.length-1&&(s.right=this.buildTree(t.slice(o+1),e+1)),s}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,o,s){if(!t)return o;const i=n%2?"x":"y",r=this.distance(e,t.point);r<s&&(o=t.point,s=r);const a=e[i]-t.point[i],c=a<=0?t.left:t.right,h=a<=0?t.right:t.left;return o=this.nearestNeighborSearch(c,e,n+1,o,s),s=this.distance(e,o),Math.abs(a)<s&&(o=this.nearestNeighborSearch(h,e,n+1,o,s)),o}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,o,s){if(!t)return;const i=n%2?"x":"y",r=this.distance(e,t.point);o.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,o,s);let d=1/0;o.length>=s&&(o.sort((t,e)=>t.distance-e.distance),d=o[s-1]?.distance||1/0),(Math.abs(a)<d||o.length<s)&&this.kNearestNeighborSearch(h,e,n+1,o,s)}distance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}},fn=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 o=e;for(;o!==n;){const t=this.parent.get(o);this.parent.set(o,n),o=t}return n}union(t,e){const n=this.find(t),o=this.find(e);if(n===o)return!1;const s=this.rank.get(n)||0,i=this.rank.get(o)||0;return s<i?this.parent.set(n,o):s>i?this.parent.set(o,n):(this.parent.set(o,n),this.rank.set(n,s+1)),!0}};function gn(t){if(t.length<=1)return[];const e=[...t],n=new mn(e),o=[],s=Math.min(10,t.length-1);for(const t of e){const e=n.findKNearestNeighbors(t,s+1);for(const n of e){if(t.x===n.x&&t.y===n.y)continue;const e=Math.sqrt((t.x-n.x)**2+(t.y-n.y)**2);o.push({from:t,to:n,weight:e})}}o.sort((t,e)=>t.weight-e.weight);const i=new fn(e),r=[];for(const t of o)if(i.union(t.from,t.to)&&(r.push(t),r.length===e.length-1))break;return r}function yn(t){if(t.pointId)return t.pointId;let e="";var n;return"layer"in(n=t)&&"string"==typeof n.layer?e=t.layer:Ze(t)&&t.layers&&(e=t.layers.sort().join("-")),`${t.x.toFixed(4)},${t.y.toFixed(4)},${e}`}var xn=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 un(e),o=new Map;t.forEach((t,e)=>{const n=`conn_${e}`;t.pointsToConnect.forEach(t=>{const e=yn(t);o.has(e)||o.set(e,[]),o.get(e).push(n)})});for(const t of o.values())if(t.length>1){const e=t[0];for(let o=1;o<t.length;o++)n.union(e,t[o])}const s=new Map;t.forEach((t,e)=>{const o=`conn_${e}`,i=n.find(o);s.has(i)||s.set(i,[]),s.get(i).push(t)});const i=[];for(const t of s.values()){if(1===t.length){i.push(t[0]);continue}const e=new Map,n=new Set;let o=!1;const s=[],r=new Set;let a;t.forEach(t=>{t.pointsToConnect.forEach(t=>e.set(yn(t),t)),n.add(t.name),t.isOffBoard&&(o=!0),t.externallyConnectedPointIds&&s.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:o,externallyConnectedPointIds:s.length>0?s:void 0,netConnectionName:r.size>0?Array.from(r).join("__"):void 0,nominalTraceWidth:a};i.push(c)}return i}([...t.connections]),this.newConnections=[]}getSolverName(){return"NetToPointPairsSolver"}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 o=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const o=n.get(t.pointId),s=n.get(e.pointId);return void 0!==o&&o===s};if(2===t.pointsToConnect.length){if(o(t.pointsToConnect[0],t.pointsToConnect[1]))return;return void this.newConnections.push({...t,rootConnectionName:t.name})}const s=gn(t.pointsToConnect);let i=0;for(const e of s)o(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{...structuredClone(this.ogSrj),connections:structuredClone(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,o=Yt(0),s=new Set;for(let i=0;i<Math.max(n,2*e.pointsToConnect.length);i++){const n=Math.floor(o()*e.pointsToConnect.length),i=Math.floor(o()*e.pointsToConnect.length);s.has(`${n}-${i}`)||(s.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(o=>{t.points.push({x:o.x,y:o.y,color:n,label:e.name})});for(let o=0;o<e.pointsToConnect.length-1;o++)for(let s=o+1;s<e.pointsToConnect.length;s++)t.lines.push({points:[e.pointsToConnect[o],e.pointsToConnect[s]],strokeColor:n})}),t}},vn=class extends xn{constructor(t,e={}){const n=t.connections.flatMap(t=>t.pointsToConnect),o=new Map;for(const t of n)t.pointId&&o.set(t.pointId,t);const s=n.map(t=>t.pointId).filter(t=>!!t),i=new un(s),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=o,this.ogSrj=t}getSolverName(){return"NetToPointPairsSolver2_OffBoardConnection"}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)),o=this.connectionPointDsu.getGroup(e.pointId).map(t=>this.connectionPointMap.get(t));let s=t,i=e,r=1/0;for(const t of n)for(const e of o){const n=Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));n<r&&(r=n,s=t,i=e)}return{pointsToConnect:[s,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 o=(t,e)=>{if(!t.pointId||!e.pointId)return!1;const o=n.get(t.pointId),s=n.get(e.pointId);return void 0!==o&&o===s};if(2===t.pointsToConnect.length){if(o(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 s=gn(t.pointsToConnect);let i=0;for(const e of s){if(o(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 Pn(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 Sn(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}var{cos:Mn,sin:bn,PI:Nn}=Math,{tan:In}=Math;a(l()),a(f());function Cn(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 _n=class{MAX_ITERATIONS=1e5;solved=!1;failed=!1;iterations=0;progress=0;error=null;activeSubSolver;failedSubSolvers;timeToSolve;stats={};_setupDone=!1;getSolverName(){return this.constructor.name}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.getSolverName()} 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.getSolverName()} 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:[]}}};function Tn(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var En=class extends _n{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,o=this.firstIterationOfStage[e.solverName]||0,s=this.iterations,i=e.solverName===this.getCurrentStageName()?s-o: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&&(Cn(e,0),t=1);let n=null;this.solved&&(n=this.finalVisualize());const o=[e].filter(Boolean).concat(this.pipelineDef.map((e,n)=>{const o=this[e.solverName],s=o?.visualize();return s?(Cn(s,n+t),s):null}).filter(Boolean));return 0===o.length?{points:[],rects:[],lines:[],circles:[],texts:[]}:(this.solved&&n&&(Cn(n,o.length+t+1),o.push(n)),1===o.length?o[0]:{points:o.flatMap(t=>t.points||[]),rects:o.flatMap(t=>t.rects||[]),lines:o.flatMap(t=>t.lines||[]),circles:o.flatMap(t=>t.circles||[]),texts:o.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]}},Rn=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,o=this.values[t];if(e>=o)break;this.ids[n]=this.ids[t],this.values[n]=o,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],o=--this.length;if(o>0){const n=t[o],s=e[o];let i=0;const r=o>>1;for(;i<r;){const n=1+(i<<1),r=n+1,a=n+(+(r<o)&+(e[r]<e[n]));if(e[a]>=s)break;t[i]=t[a],e[i]=e[a],i=a}t[i]=n,e[i]=s}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}},wn=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],An=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[o,s]=new Uint8Array(e,n+0,2);if(251!==o)throw new Error("Data does not appear to be in a Flatbush format.");const i=s>>4;if(3!==i)throw new Error(`Got v${i} data when expected v3.`);const r=wn[15&s];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,o=ArrayBuffer,s,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=wn.indexOf(n),h=4*a*n.BYTES_PER_ELEMENT;if(c<0)throw new Error(`Unexpected typed array class: ${n}.`);if(s)this.data=s,this._boxes=new n(s,i+8,4*a),this._indices=new this.IndexArrayType(s,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 s=this.data=new o(8+h+a*this.IndexArrayType.BYTES_PER_ELEMENT);this._boxes=new n(s,8,4*a),this._indices=new this.IndexArrayType(s,8+h,a),this._pos=0,this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,new Uint8Array(s,0,2).set([251,48+c]),new Uint16Array(s,2,1)[0]=e,new Uint32Array(s,4,1)[0]=t}this._queue=new Rn}add(t,e,n=t,o=e){const s=this._pos>>2,i=this._boxes;return this._indices[s]=s,i[this._pos++]=t,i[this._pos++]=e,i[this._pos++]=n,i[this._pos++]=o,t<this.minX&&(this.minX=t),e<this.minY&&(this.minY=e),n>this.maxX&&(this.maxX=n),o>this.maxY&&(this.maxY=o),s}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,o=new Uint32Array(this.numItems);for(let s=0,i=0;s<this.numItems;s++){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);o[s]=Ln(d,l)}zn(o,t,this._indices,0,this.numItems-1,this.nodeSize);for(let e=0,n=0;e<this._levelBounds.length-1;e++){const o=this._levelBounds[e];for(;n<o;){const e=n;let s=t[n++],i=t[n++],r=t[n++],a=t[n++];for(let e=1;e<this.nodeSize&&n<o;e++)s=Math.min(s,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++]=s,t[this._pos++]=i,t[this._pos++]=r,t[this._pos++]=a}}}search(t,e,n,o,s){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,On(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(o<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===s||s(p,c,d,l,u))&&a.push(p)}i=r.pop()}return a}neighbors(t,e,n=1/0,o=1/0,s){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=o*o;t:for(;void 0!==i;){const o=Math.min(i+4*this.nodeSize,On(i,this._levelBounds));for(let n=i;n<o;n+=4){const o=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(o<<1,m):(void 0===s||s(o))&&r.push(1+(o<<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 On(t,e){let n=0,o=e.length-1;for(;n<o;){const s=n+o>>1;e[s]>t?o=s:n=s+1}return e[n]}function zn(t,e,n,o,s,i){if(Math.floor(o/i)>=Math.floor(s/i))return;const r=t[o],a=t[o+s>>1],c=t[s];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=o-1,u=s+1;for(;;){do{l++}while(t[l]<h);do{u--}while(t[u]>h);if(l>=u)break;Dn(t,e,n,l,u)}zn(t,e,n,o,u,i),zn(t,e,n,u+1,s,i)}function Dn(t,e,n,o,s){const i=t[o];t[o]=t[s],t[s]=i;const r=4*o,a=4*s,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[o];n[o]=n[s],n[s]=u}function Ln(t,e){let n=t^e,o=65535^n,s=65535^(t|e),i=t&(65535^e),r=n|o>>1,a=n>>1^n,c=s>>1^o&i>>1^s,h=n&s>>1^i>>1^i;n=r,o=a,s=c,i=h,r=n&n>>2^o&o>>2,a=n&o>>2^o&(n^o)>>2,c^=n&s>>2^o&i>>2,h^=o&s>>2^(n^o)&i>>2,n=r,o=a,s=c,i=h,r=n&n>>4^o&o>>4,a=n&o>>4^o&(n^o)>>4,c^=n&s>>4^o&i>>4,h^=o&s>>4^(n^o)&i>>4,n=r,o=a,s=c,i=h,c^=n&s>>8^o&i>>8,h^=o&s>>8^(n^o)&i>>8,n=c^c>>1,o=h^h>>1;let d=t^e,l=o|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 Fn(t,e,n=0,o=t.length-1,s=Yn){for(;o>n;){if(o-n>600){const i=o-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);Fn(t,e,Math.max(n,Math.floor(e-r*c/i+h)),Math.min(o,Math.floor(e+(i-r)*c/i+h)),s)}const i=t[e];let r=n,a=o;for(Xn(t,n,e),s(t[o],i)>0&&Xn(t,n,o);r<a;){for(Xn(t,r,a),r++,a--;s(t[r],i)<0;)r++;for(;s(t[a],i)>0;)a--}0===s(t[n],i)?Xn(t,n,a):(a++,Xn(t,a,o)),a<=e&&(n=a+1),e<=a&&(o=a-1)}}function Xn(t,e,n){const o=t[e];t[e]=t[n],t[n]=o}function Yn(t,e){return t<e?-1:t>e?1:0}var $n=class{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(.4*this._maxEntries)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const n=[];if(!Kn(t,e))return n;const o=this.toBBox,s=[];for(;e;){for(let i=0;i<e.children.length;i++){const r=e.children[i],a=e.leaf?o(r):r;Kn(t,a)&&(e.leaf?n.push(r):qn(t,a)?this._all(r,n):s.push(r))}e=s.pop()}return n}collides(t){let e=this.data;if(!Kn(t,e))return!1;const n=[];for(;e;){for(let o=0;o<e.children.length;o++){const s=e.children[o],i=e.leaf?this.toBBox(s):s;if(Kn(t,i)){if(e.leaf||qn(t,i))return!0;n.push(s)}}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=Qn([]),this}remove(t,e){if(!t)return this;let n=this.data;const o=this.toBBox(t),s=[],i=[];let r,a,c;for(;n||s.length;){if(n||(n=s.pop(),a=s[s.length-1],r=i.pop(),c=!0),n.leaf){const o=Bn(t,n.children,e);if(-1!==o)return n.children.splice(o,1),s.push(n),this._condense(s),this}c||n.leaf||!qn(n,o)?a?(r++,n=a.children[r],c=!1):n=null:(s.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,o){const s=n-e+1;let i,r=this._maxEntries;if(s<=r)return i=Qn(t.slice(e,n+1)),kn(i,this.toBBox),i;o||(o=Math.ceil(Math.log(s)/Math.log(r)),r=Math.ceil(s/Math.pow(r,o-1))),i=Qn([]),i.leaf=!1,i.height=o;const a=Math.ceil(s/r),c=a*Math.ceil(Math.sqrt(r));to(t,e,n,c,this.compareMinX);for(let s=e;s<=n;s+=c){const e=Math.min(s+c-1,n);to(t,s,e,a,this.compareMinY);for(let n=s;n<=e;n+=a){const s=Math.min(n+a-1,e);i.children.push(this._build(t,n,s,o-1))}}return kn(i,this.toBBox),i}_chooseSubtree(t,e,n,o){for(;o.push(e),!e.leaf&&o.length-1!==n;){let n,o=1/0,s=1/0;for(let i=0;i<e.children.length;i++){const r=e.children[i],a=Vn(r),c=Gn(t,r)-a;c<s?(s=c,o=a<o?a:o,n=r):c===s&&a<o&&(o=a,n=r)}e=n||e.children[0]}return e}_insert(t,e,n){const o=n?t:this.toBBox(t),s=[],i=this._chooseSubtree(o,this.data,e,s);for(i.children.push(t),Wn(i,o);e>=0&&s[e].children.length>this._maxEntries;)this._split(s,e),e--;this._adjustParentBBoxes(o,s,e)}_split(t,e){const n=t[e],o=n.children.length,s=this._minEntries;this._chooseSplitAxis(n,s,o);const i=this._chooseSplitIndex(n,s,o),r=Qn(n.children.splice(i,n.children.length-i));r.height=n.height,r.leaf=n.leaf,kn(n,this.toBBox),kn(r,this.toBBox),e?t[e-1].children.push(r):this._splitRoot(n,r)}_splitRoot(t,e){this.data=Qn([t,e]),this.data.height=t.height+1,this.data.leaf=!1,kn(this.data,this.toBBox)}_chooseSplitIndex(t,e,n){let o,s=1/0,i=1/0;for(let r=e;r<=n-e;r++){const e=jn(t,0,r,this.toBBox),a=jn(t,r,n,this.toBBox),c=Jn(e,a),h=Vn(e)+Vn(a);c<s?(s=c,o=r,i=h<i?h:i):c===s&&h<i&&(i=h,o=r)}return o||n-e}_chooseSplitAxis(t,e,n){const o=t.leaf?this.compareMinX:Hn,s=t.leaf?this.compareMinY:Un;this._allDistMargin(t,e,n,o)<this._allDistMargin(t,e,n,s)&&t.children.sort(o)}_allDistMargin(t,e,n,o){t.children.sort(o);const s=this.toBBox,i=jn(t,0,e,s),r=jn(t,n-e,n,s);let a=Zn(i)+Zn(r);for(let o=e;o<n-e;o++){const e=t.children[o];Wn(i,t.leaf?s(e):e),a+=Zn(i)}for(let o=n-e-1;o>=e;o--){const e=t.children[o];Wn(r,t.leaf?s(e):e),a+=Zn(r)}return a}_adjustParentBBoxes(t,e,n){for(let o=n;o>=0;o--)Wn(e[o],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():kn(t[n],this.toBBox)}};function Bn(t,e,n){if(!n)return e.indexOf(t);for(let o=0;o<e.length;o++)if(n(t,e[o]))return o;return-1}function kn(t,e){jn(t,0,t.children.length,e,t)}function jn(t,e,n,o,s){s||(s=Qn(null)),s.minX=1/0,s.minY=1/0,s.maxX=-1/0,s.maxY=-1/0;for(let i=e;i<n;i++){const e=t.children[i];Wn(s,t.leaf?o(e):e)}return s}function Wn(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 Hn(t,e){return t.minX-e.minX}function Un(t,e){return t.minY-e.minY}function Vn(t){return(t.maxX-t.minX)*(t.maxY-t.minY)}function Zn(t){return t.maxX-t.minX+(t.maxY-t.minY)}function Gn(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 Jn(t,e){const n=Math.max(t.minX,e.minX),o=Math.max(t.minY,e.minY),s=Math.min(t.maxX,e.maxX),i=Math.min(t.maxY,e.maxY);return Math.max(0,s-n)*Math.max(0,i-o)}function qn(t,e){return t.minX<=e.minX&&t.minY<=e.minY&&e.maxX<=t.maxX&&e.maxY<=t.maxY}function Kn(t,e){return e.minX<=t.maxX&&e.minY<=t.maxY&&e.maxX>=t.minX&&e.maxY>=t.minY}function Qn(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function to(t,e,n,o,s){const i=[e,n];for(;i.length;){if((n=i.pop())-(e=i.pop())<=o)continue;const r=e+Math.ceil((n-e)/o/2)*o;Fn(t,r,e,n,s),i.push(e,r,r,n)}}var eo=1e-4;var no=[{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}],oo={"x-":no.find(t=>"x-"===t.facingDirection),"x+":no.find(t=>"x+"===t.facingDirection),"y-":no.find(t=>"y-"===t.facingDirection),"y+":no.find(t=>"y+"===t.facingDirection)},so={"x-":{x:-1,y:0},"x+":{x:1,y:0},"y-":{x:0,y:-1},"y+":{x:0,y:1}},io=(t,e)=>{const{dir:n,amt:o}=e,s=so[n];return t.map(t=>({x:t.x+s.x*o,y:t.y+s.y*o}))},ro=1e-4,ao=class extends _n{constructor(t){super(),this.input=t;for(const t of this.input.meshNodes)for(const e of no){let n={x:t.center.x+t.width*e.startX,y:t.center.y+t.height*e.startY},o={x:t.center.x+t.width*e.endX,y:t.center.y+t.height*e.endY};n.x>o.x&&([n,o]=[o,n]),Math.abs(n.x-o.x)<ro&&n.y>o.y&&([n,o]=[o,n]);for(const s of t.availableZ)this.unprocessedEdges.push({parent:t,start:n,end:o,facingDirection:e.facingDirection,z:s})}this.allEdges=[...this.unprocessedEdges],this.edgeSpatialIndex=new An(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-ro,t.start.y-ro,t.end.x+ro,t.end.y+ro).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)<eo,o=Math.abs(t.start.x-t.end.x)<eo;if(!n&&!o)return[];const s=n?"x":"y",i=n?"y":"x",r=t.start[i],a=t.start[s],c=t.end[s],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)<eo,o=Math.abs(n.start.x-n.end.x)<eo;if("x"===s&&!e)continue;if("y"===s&&!o)continue;if(Math.abs(n.start[i]-r)>eo)continue;const a=Math.min(n.start[s],n.end[s]),c=Math.max(n.start[s],n.end[s]),h=l(a),d=l(c);d-h>eo&&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+eo?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+eo&&m.push({s:f,e:t.s}),f=Math.max(f,t.e),f>=d-eo)break;return d>f+eo&&m.push({s:f,e:d}),0===m.length?[]:m.filter(t=>t.e-t.s>eo).map(e=>{const n="x"===s?{x:e.s,y:r}:{x:r,y:e.s},o="x"===s?{x:e.e,y:r}:{x:r,y:e.e};return{parent:t.parent,facingDirection:t.facingDirection,start:n,end:o,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:io([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:io([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:io([e.start,e.end],{dir:e.facingDirection,amt:-.05}),strokeColor:"green",strokeDash:"2 2"});return t}},co=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))}),ho=1e-4,lo=class extends _n{constructor(t){super(),this.input=t,this.unprocessedSegments=[...this.input.segmentsWithAdjacentEmptySpace],this.rectSpatialIndex=new $n,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}=oo[t.facingDirection],o=t.end.x-t.start.x,s=t.end.y-t.start.y,i=Math.sqrt(o**2+s**2),r=o/i,a=s/i;let c=null,h=1;const d={x:t.start.x+e*ho+r*ho*10,y:t.start.y+n*ho+a*ho*10},l={x:t.end.x+e*ho-r*ho*10,y:t.end.y+n*ho-a*ho*10};for(this.lastSearchCorner1=d,this.lastSearchCorner2=l;(!c||0===c.length)&&h<1e3;){const o=co([d,l,{x:d.x+e*h,y:d.y+n*h},{x:l.x+e*h,y:l.y+n*h}]);this.lastSearchBounds=o,c=this.rectSpatialIndex.search(o).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=co([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<ho||y<ho||(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}},uo=class extends En{findSegmentsWithAdjacentEmptySpaceSolver;expandEdgesToEmptySpaceSolver;pipelineDef=[Tn("findSegmentsWithAdjacentEmptySpaceSolver",ao,t=>[{meshNodes:t.inputProblem.meshNodes}],{onSolved:()=>{}}),Tn("expandEdgesToEmptySpaceSolver",lo,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??[],o=new Set(n.map(t=>t.newNode.capacityMeshNodeId));for(const n of e){const e=o.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}},po=1e-9,mo=(t,e,n)=>Math.max(e,Math.min(n,t)),fo=(t,e)=>t>e+po,go=(t,e)=>t>e-po,yo=(t,e)=>t<e-po,xo=(t,e)=>t<e+po;function vo(t,e){return!(t.x+t.width<=e.x+po||e.x+e.width<=t.x+po||t.y+t.height<=e.y+po||e.y+e.height<=t.y+po)}function Po(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 o=1/0;for(const[e,s,i,r]of n){const n=t.x-e,a=t.y-s,c=i-e,h=r-s,d=c*c+h*h;let l=0!==d?(n*c+a*h)/d:0;l=mo(l,0,1);const u=e+l*c,p=s+l*h;o=Math.min(o,Math.hypot(t.x-u,t.y-p))}return o}function So(t,e){const n=Math.max(t[0],e[0]),o=Math.min(t[1],e[1]);return o>n+po?[n,o]:null}function Mo(t,e){if(!vo(t,e))return[t];const n=So([t.x,t.x+t.width],[e.x,e.x+e.width]),o=So([t.y,t.y+t.height],[e.y,e.y+e.height]);if(!n||!o)return[t];const[s,i]=n,[r,a]=o,c=[];s>t.x+po&&c.push({x:t.x,y:t.y,width:s-t.x,height:t.height}),t.x+t.width>i+po&&c.push({x:i,y:t.y,width:t.x+t.width-i,height:t.height});const h=Math.max(0,i-s);return h>po&&r>t.y+po&&c.push({x:s,y:t.y,width:h,height:r-t.y}),h>po&&t.y+t.height>a+po&&c.push({x:s,y:a,width:h,height:t.y+t.height-a}),c.filter(t=>t.width>po&&t.height>po)}function bo(t,e){let n=!1;for(let o=0,s=e.length-1;o<e.length;s=o++){const i=e[o].x,r=e[o].y,a=e[s].x,c=e[s].y;r>t.y!=c>t.y&&t.x<(a-i)*(t.y-r)/(c-r)+i&&(n=!n)}return n}function No(t,e){if(!e||e.length<3)return[];const n=e.length>100?function(t,e){const n=t=>Math.round(t/e)*e,o=new Set,s=[];for(const e of t){const t=n(e.x),i=n(e.y),r=`${t},${i}`;o.has(r)||(o.add(r),s.push({x:t,y:i}))}return s}(e,Math.max(t.width,t.height)/100):e,o=new Set([t.x,t.x+t.width]),s=new Set([t.y,t.y+t.height]);for(const t of n)o.add(t.x),s.add(t.y);const i=Array.from(o).sort((t,e)=>t-e),r=Array.from(s).sort((t,e)=>t-e),a=[];for(let n=0;n<i.length-1;n++)for(let o=0;o<r.length-1;o++){const s=i[n],c=i[n+1],h=r[o],d=r[o+1],l=(s+c)/2,u=(h+d)/2;l>=t.x&&l<=t.x+t.width&&u>=t.y&&u<=t.y+t.height&&(bo({x:l,y:u},e)||a.push({x:s,y:h,width:c-s,height:d-h}))}const c=[];a.sort((t,e)=>Math.abs(t.y-e.y)>po?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)<po,n=Math.abs(h.height-t.height)<po,o=Math.abs(h.x+h.width-t.x)<po;e&&n&&o?h.width+=t.width:(c.push(h),h=t)}h&&c.push(h),c.sort((t,e)=>Math.abs(t.x-e.x)>po?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)<po,n=Math.abs(h.width-t.width)<po,o=Math.abs(h.y+h.height-t.y)<po;e&&n&&o?h.height+=t.height:(d.push(h),h=t)}return h&&d.push(h),d}function Io(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 Co(t){const e=function(t){return Array.from(new Set(t)).sort((t,e)=>{const n=Io(t),o=Io(e);return n!==o?n-o:t.localeCompare(e)})}((t.obstacles??[]).flatMap(t=>t.layers??[])),n=Math.max(1,t.layerCount||e.length||1),o=Array.from({length:n},(t,e)=>0===e?"top":e===n-1?"bottom":`inner${e}`),s=[],i=new Set,r=t=>{const e=t.toLowerCase();i.has(e)||(i.add(e),s.push(t))};o.forEach(r),e.forEach(r);const a=s.slice(0,n),c=new Map;return a.forEach((t,e)=>c.set(t.toLowerCase(),e)),s.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 _o(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 To(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 Eo=1e-9,Ro=t=>Math.abs(t.rect.x+t.rect.width/2-t.startX)<Eo&&Math.abs(t.rect.y+t.rect.height/2-t.startY)<Eo&&Math.abs(t.rect.width-t.initialW)<Eo&&Math.abs(t.rect.height-t.initialH)<Eo,wo=({rect:t,bounds:e})=>({x:t.x,y:t.y,width:e.x+e.width-t.x,height:t.height}),Ao=({rect:t,bounds:e})=>({x:t.x,y:t.y,width:t.width,height:e.y+e.height-t.y}),Oo=({rect:t,bounds:e})=>({x:e.x,y:t.y,width:t.x-e.x,height:t.height}),zo=({rect:t,bounds:e})=>({x:t.x,y:e.y,width:t.width,height:t.y-e.y});function Do(t){const{r:e,bounds:n,blockers:o,maxAspect:s}=t;let i=n.x+n.width-e.x;for(const t of o){if(e.y+e.height>t.y+po&&t.y+t.height>e.y+po)if(go(t.x,e.x+e.width))i=Math.min(i,t.x-e.x);else if(t.x+t.width>e.x+e.width-po&&t.x<e.x+e.width+po)return 0}let r=Math.max(0,i-e.width);if(r<=0)return 0;if(null!=s){const t=e.width,n=e.height;t>=n&&(r=Math.min(r,s*n-t))}return Math.max(0,r)}function Lo(t){const{r:e,bounds:n,blockers:o,maxAspect:s}=t;let i=n.y+n.height-e.y;for(const t of o){if(e.x+e.width>t.x+po&&t.x+t.width>e.x+po)if(go(t.y,e.y+e.height))i=Math.min(i,t.y-e.y);else if(t.y+t.height>e.y+e.height-po&&t.y<e.y+e.height+po)return 0}let r=Math.max(0,i-e.height);if(r<=0)return 0;if(null!=s){const t=e.width,n=e.height;n>=t&&(r=Math.min(r,s*t-n))}return Math.max(0,r)}function Fo(t){const{r:e,bounds:n,blockers:o,maxAspect:s}=t;let i=n.x;for(const t of o){if(e.y+e.height>t.y+po&&t.y+t.height>e.y+po)if(xo(t.x+t.width,e.x))i=Math.max(i,t.x+t.width);else if(t.x<e.x+po&&t.x+t.width>e.x-po)return 0}let r=Math.max(0,e.x-i);if(r<=0)return 0;if(null!=s){const t=e.width,n=e.height;t>=n&&(r=Math.min(r,s*n-t))}return Math.max(0,r)}function Xo(t){const{r:e,bounds:n,blockers:o,maxAspect:s}=t;let i=n.y;for(const t of o){if(e.x+e.width>t.x+po&&t.x+t.width>e.x+po)if(xo(t.y+t.height,e.y))i=Math.max(i,t.y+t.height);else if(t.y<e.y+po&&t.y+t.height>e.y-po)return 0}let r=Math.max(0,e.y-i);if(r<=0)return 0;if(null!=s){const t=e.width,n=e.height;n>=t&&(r=Math.min(r,s*t-n))}return Math.max(0,r)}var Yo=t=>({x:t.minX,y:t.minY,width:t.maxX-t.minX,height:t.maxY-t.minY}),$o=t=>{const{rect:e,seen:n,blockers:o}=t,s=`${e.x}|${e.y}|${e.width}|${e.height}`;n.has(s)||(n.add(s),o.push(e))};function Bo(t){const{startX:e,startY:n,gridSize:o,bounds:s,obsticalIndexByLayer:i,placedIndexByLayer:r,initialCellRatio:a,maxAspectRatio:c,minReq:h}=t,d=Math.max(1e-9,o*a),l=Math.max(d,h.width),u=Math.max(d,h.height),p=[],m=new Set,f=r.length,g=o=>{const a=(t=>{const{bounds:e,rect:n}=t,o=Math.max(e.x,n.x),s=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<=o+po||r<=s+po?null:{minX:o,minY:s,maxX:i,maxY:r}})({bounds:s,rect:o});if(a)for(const o of t.zLayers){const t=i[o];if(t)for(const e of t.search(a))$o({rect:Yo(e),seen:m,blockers:p});const s=r[o];if(s)for(const t of s.search(a)){if(!(t.zLayers.length>=f))continue;const o=Yo(t);Ro({rect:o,startX:e,startY:n,initialW:l,initialH:u})||$o({rect:o,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 o={x:e+t.ox,y:n+t.oy,width:l,height:u};if(g(o),yo(o.x,s.x)||yo(o.y,s.y)||fo(o.x+o.width,s.x+s.width)||fo(o.y+o.height,s.y+s.height))continue;for(const t of p)if(vo(o,t))continue t;const i=1e-6,r=1e3;let a=!0,d=0;for(;a&&d<r;){d++,a=!1;const t={bounds:s,blockers:p,maxAspect:c};g(wo({rect:o,bounds:s}));const e=Do({...t,r:o});e>i&&(o={...o,width:o.width+e},g(o),a=!0),g(Ao({rect:o,bounds:s}));const n=Lo({...t,r:o});n>i&&(o={...o,height:o.height+n},g(o),a=!0),g(Oo({rect:o,bounds:s}));const r=Fo({...t,r:o});r>i&&(o={x:o.x-r,y:o.y,width:o.width+r,height:o.height},g(o),a=!0),g(zo({rect:o,bounds:s}));const h=Xo({...t,r:o});h>i&&(o={x:o.x,y:o.y-h,width:o.width,height:o.height+h},g(o),a=!0)}if(o.width+po>=h.width&&o.height+po>=h.height){const t=o.width*o.height;t>v&&(x=o,v=t)}}return x}function ko(t){const e=Math.max(t.width,t.height);return[e/8,e/16,e/32]}function jo(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 o=t.obstacleIndexByLayer[n],s=!!o&&o.search(e).length>0,i=t.placedIndexByLayer[n],r=!!i&&i.search(e).length>0;if(!s&&!r)return!1}return!0}function Wo(t){const{x:e,y:n,z:o,layerCount:s,minSpan:i,maxSpan:r,obstacleIndexByLayer:a,additionalBlockersByLayer:c}=t,h=t=>{const o={minX:e,minY:n,maxX:e,maxY:n},s=a[t];if(s&&s.search(o).length>0)return!1;return!(c?.[t]??[]).some(t=>{return(s={x:e,y:n}).x>=(o=t).x-po&&s.x<=o.x+o.width+po&&s.y>=o.y-po&&s.y<=o.y+o.height+po;var o,s})};let d=o,l=o;for(;d-1>=0&&h(d-1);)d--;for(;l+1<s&&h(l+1);)l++;if("number"==typeof r){const t=mo(r,1,s);for(;l-d+1>t;)o-d>l-o?d++:l--}const u=[];for(let t=d;t<=l;t++)u.push(t);return u.length>=i?u:[]}function Ho(t){const{lineStart:e,lineEnd:n,coveringIntervals:o,minSegmentLength:s}=t;if(0===o.length){return[{start:e,end:n,center:(e+n)/2}]}const i=[...o].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+po?a.end=Math.max(a.end,e.end):(r.push(a),a={...e})}r.push(a);const c=[];if(r[0].start>e+po){const t=e,n=r[0].start;n-t>=s&&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>=s&&c.push({start:e,end:n,center:(e+n)/2})}if(r[r.length-1].end<n-po){const t=r[r.length-1].end,e=n;e-t>=s&&c.push({start:t,end:e,center:(t+e)/2})}return c}function Uo(t){const{bounds:e,minSize:n,layerCount:o,obstacleIndexByLayer:s,placedIndexByLayer:i,hardPlacedByLayer:r}=t,a=[],c=Math.max(.15*n,3*po),h=new Set;function d(t){const{x:n,y:c,z:d}=t;if(n<e.x+po||c<e.y+po||n>e.x+e.width-po||c>e.y+e.height-po)return;if(function(t){return jo({layerCount:o,obstacleIndexByLayer:s,placedIndexByLayer:i,point:t})}({x:n,y:c}))return;const l=[...s[d]?.all()??[],...r[d]??[]],u=Math.min(Po({x:n,y:c},e),...l.length?l.map(t=>Po({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=Wo({x:n,y:c,z:d,layerCount:o,minSpan:1,maxSpan:void 0,obstacleIndexByLayer:s,additionalBlockersByLayer:r});a.push({x:n,y:c,z:d,distance:u,zSpanLen:m.length,isEdgeSeed:!0})}for(let t=0;t<o;t++){const o=[...s[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=o.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=Ho({lineStart:e.x+c,lineEnd:e.x+e.width-c,coveringIntervals:h,minSegmentLength:.5*n});for(const e of l){const o=e.end-e.start;o>=n&&(d({x:e.center,y:a,z:t}),o>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=o.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=Ho({lineStart:e.x+c,lineEnd:e.x+e.width-c,coveringIntervals:p,minSegmentLength:.5*n});for(const e of m){const o=e.end-e.start;o>=n&&(d({x:e.center,y:u,z:t}),o>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=o.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=Ho({lineStart:e.y+c,lineEnd:e.y+e.height-c,coveringIntervals:g,minSegmentLength:.5*n});for(const e of y){const o=e.end-e.start;o>=n&&(d({x:f,y:e.center,z:t}),o>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=o.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)})),P=Ho({lineStart:e.y+c,lineEnd:e.y+e.height-c,coveringIntervals:v,minSegmentLength:.5*n});for(const e of P){const o=e.end-e.start;o>=n&&(d({x:x,y:e.center,z:t}),o>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 s of o){const i=s.x-c;if(i>e.x+po&&i<e.x+e.width-po){const e=o.filter(t=>t!==s&&t.x<=i&&t.x+t.width>=i).map(t=>({start:Math.max(s.y,t.y),end:Math.min(s.y+s.height,t.y+t.height)})),r=Ho({lineStart:s.y,lineEnd:s.y+s.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of r)d({x:i,y:e.center,z:t})}const r=s.x+s.width+c;if(r>e.x+po&&r<e.x+e.width-po){const e=o.filter(t=>t!==s&&t.x<=r&&t.x+t.width>=r).map(t=>({start:Math.max(s.y,t.y),end:Math.min(s.y+s.height,t.y+t.height)})),i=Ho({lineStart:s.y,lineEnd:s.y+s.height,coveringIntervals:e,minSegmentLength:.5*n});for(const e of i)d({x:r,y:e.center,z:t})}const a=s.y-c;if(a>e.y+po&&a<e.y+e.height-po){const e=o.filter(t=>t!==s&&t.y<=a&&t.y+t.height>=a).map(t=>({start:Math.max(s.x,t.x),end:Math.min(s.x+s.width,t.x+t.width)})),i=Ho({lineStart:s.x,lineEnd:s.x+s.width,coveringIntervals:e,minSegmentLength:.5*n});for(const e of i)d({x:e.center,y:a,z:t})}const h=s.y+s.height+c;if(h>e.y+po&&h<e.y+e.height-po){const e=o.filter(t=>t!==s&&t.y<=h&&t.y+t.height>=h).map(t=>({start:Math.max(s.x,t.x),end:Math.min(s.x+s.width,t.x+t.width)})),i=Ho({lineStart:s.x,lineEnd:s.x+s.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 Vo=(t,e)=>({...t,minX:t.x,minY:t.y,maxX:t.x+t.width,maxY:t.y+t.height,zLayers:e.zLayers});function Zo(t,e){const n=t.placed[e],{rect:o,zLayers:s}=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=>s.includes(t));if(0===h.length)continue;if(!vo(c.rect,o))continue;const d=Mo(c.rect,o);r.push(n);const l=c.zLayers.filter(t=>!s.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+po>=u&&t.height+po>=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 o=t.placedIndexByLayer[e];o&&o.remove(Vo(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 o=t.placedIndexByLayer[n];o&&o.insert(Vo(e.rect,{zLayers:e.zLayers.slice()}))}}}var Go=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]},Jo=class extends _n{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:o}=Co(t),s=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??ko(i)};this.srj=t,this.layerNames=n,this.layerCount=s,this.bounds=i,this.options=a,this.boardVoidRects=this.input.boardVoidRects,this.gridIndex=0,this.candidates=[],this.placed=[],this.placedIndexByLayer=Array.from({length:s},()=>new $n),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:o,minMulti:s,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:o,obstacleIndexByLayer:s,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)<po||Math.abs(c-e.y)<po||t>e.x+e.width-n-po||c>e.y+e.height-n-po)continue;if(jo({layerCount:o,obstacleIndexByLayer:s,placedIndexByLayer:i,point:{x:t,y:c}}))continue;let h=[],d=0;for(let e=0;e<o;e++){const n=Wo({x:t,y:c,z:e,layerCount:o,minSpan:1,maxSpan:void 0,obstacleIndexByLayer:s,additionalBlockersByLayer:r});n.length>h.length&&(h=n,d=e)}const l=h.length?h[Math.floor(h.length/2)]:d,u=[...s[l]?.all()??[],...r[l]??[]],p=Math.min(Po({x:t,y:c},e),...u.length?u.map(e=>Po({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(o.width,o.height);return this.candidates=Uo({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=Wo({x:h.x,y:h.y,z:h.z,layerCount:this.layerCount,minSpan:s.minLayers,maxSpan:r,obstacleIndexByLayer:this.input.obstacleIndexByLayer,additionalBlockersByLayer:c}),l=[];d.length>=s.minLayers&&l.push({kind:"multi",layers:d,minReq:{width:s.width,height:s.height}}),l.push({kind:"single",layers:[h.z],minReq:{width:o.width,height:o.height}});const u=i?l:l.reverse();for(const t of u){const o=Bo({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(!o)continue;const s={rect:o,zLayers:[...t.layers]},i=this.placed.push(s)-1;for(const e of t.layers){const t=this.placedIndexByLayer[e];t&&t.insert(Vo(o,{zLayers:s.zLayers}))}return Zo({layerCount:this.layerCount,placed:this.placed,options:this.options,placedIndexByLayer:this.placedIndexByLayer},i),void(this.candidates=this.candidates.filter(t=>!jo({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),o=n?this.consumedSeedsThisGrid/n:1;return Math.min(.999,e+o*(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=[],o=this.srj??this.input.simpleRouteJson,s=o.bounds.minX,i=o.bounds.maxX,r=o.bounds.minY,a=o.bounds.maxY;o.outline&&o.outline.length>1?n.push({points:[...o.outline,o.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):t.push({center:{x:(s+i)/2,y:(r+a)/2},width:i-s,height:a-r,fill:"none",stroke:"#111827",label:"board"});for(const e of o.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(o.outline&&o.outline.length>0){const t=o.outline.map(t=>t.x),n=o.outline.map(t=>t.y),s=Math.min(...t),i=Math.min(...n);e={x:s,y:i,width:Math.max(...t)-s,height:Math.max(...n)-i}}for(const n of this.boardVoidRects)e&&!vo(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=Go(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 qo=(t,e)=>t.minX===e.minX&&t.minY===e.minY&&t.maxX===e.maxX&&t.maxY===e.maxY,Ko=class extends _n{constructor(t){super(),this.input=t}placedIndexByLayer=[];_meshNodes=[];_setup(){this.stats={gridIndex:this.input.gridIndex},this.placedIndexByLayer=Array.from({length:this.input.layerCount},()=>new $n);for(const t of this.input.placed)for(const e of t.zLayers){const n=this.placedIndexByLayer[e];n&&n.insert(Vo(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],o=e.rect,s=Bo({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(s){this.input.placed[t]={rect:s,zLayers:e.zLayers};for(const t of e.zLayers){const n=this.placedIndexByLayer[t];n&&(n.remove(Vo(o,{zLayers:e.zLayers}),qo),n.insert(Vo(s,{zLayers:e.zLayers})))}Zo({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}=Co(t.srj),o=new Map;for(const e of t.srj.obstacles??[]){const t=To(e);if(!t)continue;const s=e.zLayers?.length&&e.zLayers.length>0?e.zLayers:_o(e,n),i=`${t.x}:${t.y}:${t.width}:${t.height}`;let r=o.get(i);r||(r={rect:t,layers:new Set},o.set(i,r)),s.forEach(t=>r.layers.add(t))}for(const{rect:t,layers:n}of o.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 o of t){const t=Math.max(0,o.maxX-o.minX),s=Math.max(0,o.maxY-o.minY);t<=0||s<=0||0===o.zLayers.length||n.push({capacityMeshNodeId:"cmn_"+e++,center:{x:(o.minX+o.maxX)/2,y:(o.minY+o.maxY)/2},width:t,height:s,layer:"top",availableZ:o.zLayers.slice(),_containsObstacle:o.isObstacle,_containsTarget:o.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),o=n?this.input.expansionIndex/n:1;return Math.min(.999,e+o*(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:[]}}},Qo=class extends En{rectDiffSeedingSolver;rectDiffExpansionSolver;obstacleIndexByLayer;constructor(t){super(t);const{obstacleIndexByLayer:e}=(t=>{const{srj:e,boardVoidRects:n}=t,{layerNames:o,zIndexByName:s}=Co(e),i=Math.max(1,o.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 $n)),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=To(t);if(!e)continue;const n=_o(t,s),o=n.filter(t=>t<0||t>=i);if(o.length)throw new Error(`RectDiff: obstacle uses z-layer indices ${o.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=[Tn("rectDiffSeedingSolver",Jo,t=>[{simpleRouteJson:t.inputProblem.simpleRouteJson,gridOptions:t.inputProblem.gridOptions,obstacleIndexByLayer:t.obstacleIndexByLayer,boardVoidRects:t.inputProblem.boardVoidRects}]),Tn("rectDiffExpansionSolver",Ko,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 ts(t,e="RectDiff"){const n=[],o=[],s=t.bounds.minX,i=t.bounds.maxX,r=t.bounds.minY,a=t.bounds.maxY;t.outline&&t.outline.length>1?o.push({points:[...t.outline,t.outline[0]],strokeColor:"#111827",strokeWidth:.01,label:"outline"}):n.push({center:{x:(s+i)/2,y:(r+a)/2},width:i-s,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:o}}var es=class extends En{rectDiffGridSolverPipeline;gapFillSolver;boardVoidRects;pipelineDef=[Tn("rectDiffGridSolverPipeline",Qo,t=>[{simpleRouteJson:t.inputProblem.simpleRouteJson,gridOptions:t.inputProblem.gridOptions,boardVoidRects:t.boardVoidRects}]),Tn("gapFillSolver",uo,t=>[{meshNodes:t.rectDiffGridSolverPipeline?.getOutput().meshNodes??[],boardVoid:{boardVoidRects:t.boardVoidRects||[],layerCount:t.inputProblem.simpleRouteJson.layerCount||0}}])];_setup(){this.inputProblem.simpleRouteJson.outline&&(this.boardVoidRects=No({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=ts(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=ts(this.inputProblem.simpleRouteJson,"RectDiffPipeline - Final"),{meshNodes:e}=this.getOutput(),n=new Set((this.rectDiffGridSolverPipeline?.getOutput().meshNodes??[]).map(t=>t.capacityMeshNodeId));for(const o of e){const e=!n.has(o.capacityMeshNodeId);t.rects.push({center:o.center,width:o.width,height:o.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${o.availableZ.join(",")}`,label:[`${e?"[expanded] ":""}node ${o.capacityMeshNodeId}`,`z:${o.availableZ.join(",")}`].join("\n")})}return t}},ns=class{tree;constructor(t=9){this.tree=new $n(t)}insert(t,e,n,o,s){this.tree.insert({minX:e,minY:n,maxX:o,maxY:s,data:t})}bulkLoad(t){const e=t.map(({item:t,minX:e,minY:n,maxX:o,maxY:s})=>({minX:e,minY:n,maxX:o,maxY:s,data:t}));this.tree.load(e)}search(t,e,n,o){return this.tree.search({minX:t,minY:e,maxX:n,maxY:o}).map(t=>t.data)}clear(){this.tree.clear()}},os=class{index;items=[];currentIndex=0;capacity;constructor(t){this.capacity=Math.max(1,t),this.index=new An(this.capacity)}insert(t,e,n,o,s){if(this.currentIndex>=this.index.numItems)throw new Error("Exceeded initial capacity");this.items[this.currentIndex]=t,this.index.add(e,n,o,s),this.currentIndex++}finish(){this.index.finish()}search(t,e,n,o){return this.index.search(t,e,n,o).map(t=>this.items[t]||null).filter(Boolean)}clear(){this.items=[],this.currentIndex=0,this.index=new An(this.capacity)}},ss=class{idx;storage=[];constructor(t="native",e=[]){"flatbush"===t?0===e.length?(this.idx=new ns,t="rbush"):this.idx=new os(e.length):this.idx="rbush"===t?new ns:new class{shi=new is(e);insert(t){}search(t,e,n,o){const s=(t+n)/2,i=(e+o)/2,r=n-t,a=o-e;return this.shi.getNodesInArea(s,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,o){return this.search({minX:t-n/2,minY:e-o/2,maxX:t+n/2,maxY:e+o/2})}},is=class{constructor(t){this.obstacles=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],o=n.center.x-n.width/2,s=n.center.y-n.height/2,i=n.center.x+n.width/2,r=n.center.y+n.height/2;for(let t=o;t<=i;t+=this.CELL_SIZE)for(let o=s;o<=r;o+=this.CELL_SIZE){const s=this.getBucketKey(t,o),i=this.buckets.get(s);i?i.push([n,e]):this.buckets.set(s,[[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,o){const s=[],i=new Set,r=e-o/2,a=t+n/2,c=e+o/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),o=this.buckets.get(n)||[];for(const t of o)i.has(t[1])||(i.add(t[1]),s.push(t[0]))}return s}},rs=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 as(t,e){const n=t.x-e.x,o=t.y-e.y;return n*n+o*o}function cs(t,e,n){const o=as(e,n);if(0===o)return as(t,e);let s=((t.x-e.x)*(n.x-e.x)+(t.y-e.y)*(n.y-e.y))/o;s=Math.max(0,Math.min(1,s));return as(t,{x:e.x+s*(n.x-e.x),y:e.y+s*(n.y-e.y)})}function hs(t,e,n,o){if(gt(t,e,n,o))return 0;const s={x:t.x,y:t.y},i={x:e.x,y:e.y},r={x:n.x,y:n.y},a={x:o.x,y:o.y};return Math.min(cs(s,r,a),cs(i,r,a),cs(r,s,i),cs(a,s,i))}var ds=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],o=e.route[t+1];if(n.x===o.x&&n.y===o.y)continue;if(n.insideJumperPad&&o.insideJumperPad)continue;const s=[n,o],i=rs(s),r={segmentId:`${e.connectionName}-seg-${t}`,segment:s,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 o=this.segmentBuckets.get(n);o||(o=[],this.segmentBuckets.set(n,o)),o.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 o={viaId:`${e.connectionName}-via-${t}`,x:n.x,y:n.y,parentRoute:e},s=`${Math.floor(n.x/this.CELL_SIZE)}x${Math.floor(n.y/this.CELL_SIZE)}`;let i=this.viaBuckets.get(s);i||(i=[],this.viaBuckets.set(s,i)),i.push(o)}}else console.warn("Skipping route with missing data:",e)}getConflictingRoutesForSegment(t,e,n){const o=rs([t,e]),s=o.minX-n,i=o.minY-n,r=o.maxX+n,a=o.maxY+n,c=Math.floor(s/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 o=c;o<=h;o++)for(let s=d;s<=l;s++){const i=`${o}x${s}`,r=this.segmentBuckets.get(i);if(r)for(const o of r){if(p.has(o.segmentId))continue;p.add(o.segmentId);const s=o.parentRoute,[i,r]=o.segment,a=n+s.traceThickness/2,c=a*a,h=hs(t,e,i,r);if(h<c){const t=s.connectionName,e=u.get(t);(!e||h<e.minDistSq)&&u.set(t,{route:s,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,o={x:t.x,y:t.y},s=n+e.viaDiameter/2,i=s*s,r=cs(o,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 o=n.filter(e=>e.parentRoute.connectionName!==t);0===o.length?this.segmentBuckets.delete(e):o.length!==n.length&&this.segmentBuckets.set(e,o)}for(const[e,n]of this.viaBuckets){const o=n.filter(e=>e.parentRoute.connectionName!==t);0===o.length?this.viaBuckets.delete(e):o.length!==n.length&&this.viaBuckets.set(e,o)}}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],o=t.route[e+1];if(n.x===o.x&&n.y===o.y)continue;if(n.insideJumperPad&&o.insideJumperPad)continue;const s=[n,o],i=rs(s),r={segmentId:`${t.connectionName}-seg-${e}`,segment:s,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 o=this.segmentBuckets.get(n);o||(o=[],this.segmentBuckets.set(n,o)),o.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 o={viaId:`${t.connectionName}-via-${e}`,x:n.x,y:n.y,parentRoute:t},s=`${Math.floor(n.x/this.CELL_SIZE)}x${Math.floor(n.y/this.CELL_SIZE)}`;let i=this.viaBuckets.get(s);i||(i=[],this.viaBuckets.set(s,i)),i.push(o)}}getConflictingRoutesNearPoint(t,e){const n=t.x-e,o=t.y-e,s=t.x+e,i=t.y+e,r=Math.floor(n/this.CELL_SIZE),a=Math.floor((s+1e-9)/this.CELL_SIZE),c=Math.floor(o/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 o=c;o<=h;o++){const s=`${n}x${o}`,i=this.segmentBuckets.get(s);if(i)for(const n of i){if(l.has(n.segmentId))continue;l.add(n.segmentId);const o=n.segment[0],s=n.segment[1];if(o.z!==s.z||o.z!==t.z)continue;const i=n.parentRoute,r={x:n.segment[0].x,y:n.segment[0].y},a={x:n.segment[1].x,y:n.segment[1].y},c=e+i.traceThickness/2,h=c*c,u=cs(t,r,a);if(u<h){const t=i.connectionName,e=d.get(t);(!e||u<e.minDistSq)&&d.set(t,{route:i,minDistSq:u})}}const r=this.viaBuckets.get(s);if(r)for(const n of r){if(u.has(n.viaId))continue;u.add(n.viaId);const o=n.parentRoute,s={x:n.x,y:n.y},i=e+o.viaDiameter/2,r=i*i,a=as(t,s);if(a<r){const t=o.connectionName,e=d.get(t);(!e||a<e.minDistSq)&&d.set(t,{route:o,minDistSq:a})}}}const p=[];for(const t of d.values())p.push({conflictingRoute:t.route,distance:Math.sqrt(t.minDistSq)});return p}},ls=class extends y{getSolverName(){return"SingleRouteUselessViaRemovalSolver"}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 o={startIndex:0,endIndex:-1,z:n[0].z,points:[n[0]]};for(let t=1;t<n.length;t++)n[t].z===o.z?o.points.push(n[t]):(o.endIndex=t-1,e.push(o),o={startIndex:t,endIndex:-1,z:n[t].z,points:[n[t]]});return o.endIndex=n.length-1,e.push(o),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,o=t.points[0];if(this.canEndpointConnectOnLayer(o.x,o.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,o=t.points[t.points.length-1];this.canEndpointConnectOnLayer(o.x,o.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 o=t.z;if(this.canSectionMoveToLayer({currentSection:e,targetZ:o}))return e.z=o,e.points=e.points.map(t=>({...t,z:o})),void(this.currentSectionIndex+=2);this.currentSectionIndex++}canEndpointConnectOnLayer(t,e,n){const o=this.obstacleSHI.searchArea(t,e,2,2).filter(n=>{if(!n.connectedTo?.includes(this.unsimplifiedRoute.connectionName))return!1;const o=n.width/2+.05,s=n.height/2+.05,i=Math.abs(t-n.center.x)<=o,r=Math.abs(e-n.center.y)<=s;return i&&r});return!(o.length>0)||o.some(t=>t.zLayers?.includes(n))}canSectionMoveToLayer({currentSection:t,targetZ:e}){for(let n=0;n<t.points.length-1;n++){const o={...t.points[n],z:e},s={...t.points[n+1],z:e},i=this.hdRouteSHI.getConflictingRoutesForSegment(o,s,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:(o.x+s.x)/2,centerY:(o.y+s.y)/2,width:Math.abs(o.x-s.x),height:Math.abs(o.y-s.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(o.x-t.center.x)<.01&&Math.abs(o.y-t.center.y)<.01||Math.abs(s.x-t.center.x)<.01&&Math.abs(s.y-t.center.y)<.01)continue}if(At(o,s,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}},us=(t,e=2)=>{const n=Array.from({length:e},(t,e)=>e);return t.map(t=>{const o=t.zLayers??t.layers?.map(t=>Be(t,e))??n,s=Array.from(new Set(o.filter(t=>t>=0&&t<e)));return{...t,zLayers:s.length>0?s:n}})},ps=class extends y{constructor(t){super(),this.input=t,this.input={...t,obstacles:us(t.obstacles,t.layerCount)},this.MAX_ITERATIONS=1e6,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes,this.optimizedHdRoutes=[],this.unprocessedRoutes=[...t.unsimplifiedHdRoutes],this.obstacleSHI=new ss("flatbush",this.input.obstacles),this.hdRouteSHI=new ds(this.unsimplifiedHdRoutes)}getSolverName(){return"UselessViaRemovalSolver"}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 ls({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 o=e.zLayers?.includes(0),s=e.zLayers?.includes(1);o&&s?n="rgba(128, 0, 128, 0.2)":o?n="rgba(255, 0, 0, 0.2)":s&&(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 o=e.route[n],s=e.route[n+1];o.z===s.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:s.x,y:s.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 o=Qe(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...o.rects??[]),t.lines.push(...o.lines??[])}}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},ms=class extends y{getSolverName(){return"SingleSimplifiedPathSolver"}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,o]of e)t.lines.push({points:[n,o]})}return t}};function fs(t,e,n,o){if(gt(t,e,n,o))return 0;const s=gs(t,n,o),i=gs(e,n,o),r=gs(n,t,e),a=gs(o,t,e);return Math.min(s,i,r,a)}function gs(t,e,n){const o={x:n.x-e.x,y:n.y-e.y},s=ys({x:t.x-e.x,y:t.y-e.y},o);if(s<=0)return xs(t,e);const i=ys(o,o);if(i<=s)return xs(t,n);const r=s/i;return xs(t,{x:e.x+r*o.x,y:e.y+r*o.y})}function ys(t,e){return t.x*e.x+t.y*e.y}function xs(t,e){const n=e.x-t.x,o=e.y-t.y;return Math.sqrt(n*n+o*o)}var vs=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)}),Ps=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 o=vs(n),s=Math.floor(o.minX/this.CELL_SIZE),i=Math.floor(o.maxX/this.CELL_SIZE),r=Math.floor(o.minY/this.CELL_SIZE),a=Math.floor(o.maxY/this.CELL_SIZE);for(let e=s;e<=i;e++)for(let o=r;o<=a;o++){const s=`${e}x${o}`,i=this.buckets.get(s),r=[n[0],n[1],t];i?i.push(r):this.buckets.set(s,[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=[],o=new Set,s=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(s/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 s=`${t}x${e}`,i=this.buckets.get(s);if(i)for(const t of i){const e=t[2];o.has(e)||(o.add(e),n.push(t))}}return n}},Ss=1e-6,Ms=(t,e,n)=>vt(t,e,n)<=Ss,bs=(t,e)=>Math.abs(t.x-e.x)<=Ss&&Math.abs(t.y-e.y)<=Ss,Ns=(t,e)=>{if(!e||e.length<3)return!1;for(let n=0;n<e.length;n++){const o=e[n],s=e[(n+1)%e.length];if(Ms(t,o,s))return!0}let n=!1;for(let o=0,s=e.length-1;o<e.length;s=o++){const i=e[o],r=e[s];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},Is=class extends ms{pathSegments=[];totalPathLength=0;headDistanceAlongPath=0;tailDistanceAlongPath=0;minStepSize=.25;lastValidPath=null;lastValidPathHeadDistance=0;STEP_SIZE_REDUCTION_FACTOR=.25;maxStepSize=4;currentStepSize=this.maxStepSize;lastHeadMoveDistance=0;cachedValidPathSegments;filteredObstacles=[];filteredObstaclePathSegments=[];filteredVias=[];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),o=mt(e),s=Math.max(n.minX-o.maxX,o.minX-n.maxX,0),i=Math.max(n.minY-o.maxY,o.minY-n.maxY,0);return Math.hypot(s,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,o=[];for(let t=0;t<n.length-1;t++){const s=n[t],i=n[t+1],r=Math.min(s.x,i.x),a=Math.max(s.x,i.x),c=Math.min(s.y,i.y),h=Math.max(s.y,i.y);r<=e.maxX&&a>=e.minX&&c<=e.maxY&&h>=e.minY&&o.push([s,i])}return o}),this.segmentTree=new Ps(this.filteredObstaclePathSegments),this.filteredVias=this.otherHdRoutes.flatMap(t=>{if(this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName))return[];const n=t.vias,o=[];for(const s of n){const n=this.OBSTACLE_MARGIN+this.TRACE_THICKNESS/2+t.viaDiameter/2,i=s.x-n,r=s.x+n,a=s.y-n,c=s.y+n;i<=e.maxX&&r>=e.minX&&a<=e.maxY&&c>=e.minY&&o.push({...s,diameter:t.viaDiameter})}return o});const o=(t,n)=>{const o=[];for(const s of t){const t=qe[s.footprint]??qe["0603"],i=s.end.x-s.start.x,r=s.end.y-s.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;s.start.x-c/2-d<=e.maxX&&s.start.x+c/2+d>=e.minX&&s.start.y-h/2-d<=e.maxY&&s.start.y+h/2+d>=e.minY&&o.push({center:s.start,width:c,height:h,connectionName:n}),s.end.x-c/2-d<=e.maxX&&s.end.x+c/2+d>=e.minX&&s.end.y-h/2-d<=e.maxY&&s.end.y+h/2+d>=e.minY&&o.push({center:s.end,width:c,height:h,connectionName:n})}return o};if(this.filteredJumperPads=this.otherHdRoutes.flatMap(t=>this.connMap.areIdsConnected(this.inputRoute.connectionName,t.connectionName)?[]:o(t.jumpers??[],t.connectionName)),this.inputRoute.jumpers&&this.inputRoute.jumpers.length>0){this.filteredJumperPads.push(...o(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],o=this.inputRoute.route[e+1],s=Math.sqrt((o.x-n.x)**2+(o.y-n.y)**2)+e/1e4;this.pathSegments.push({start:n,end:o,length:s,startDistance:t,endDistance:t+s}),t+=s}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],o=(n.startDistance+n.endDistance)/2;return t>o?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[o,s,i]of n)if(o.z===t.z&&s.z===t.z){if(fs({x:t.x,y:t.y},{x:e.x,y:e.y},{x:o.x,y:o.y},{x:s.x,y:s.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:o=.2})=>{if(!n||n.length<3)return!1;const s=Ns(t,n),i=Ns(e,n);if(!s||!i)return!0;for(let s=0;s<n.length;s++){const i=n[s],r=n[(s+1)%n.length],a=Ms(t,i,r),c=Ms(e,i,r);if(a&&c)continue;if(!gt(t,e,i,r)){if(!a&&!c&&fs(t,e,i,r)<o-Ss)return!0;continue}const h=St(t,e,i,r);if(!(h&&(a&&bs(h,t)||c&&bs(h,e))||h&&(bs(h,t)||bs(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=[],o=Math.abs(e.x-t.x),s=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(o,s),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 o=[];for(const t of this.inputRoute.route)0!==o.length&&this.arePointsEqual(o[o.length-1],t)||o.push(t);return this.newRoute=o,this.newVias=[...this.inputRoute.vias],void(this.solved=!0)}this.moveHead(this.currentStepSize);const n=this.getPointAtDistance(this.tailDistanceAlongPath),o=this.getPointAtDistance(this.headDistanceAlongPath),s=this.getNearestIndexForDistance(this.tailDistanceAlongPath),i=this.getNearestIndexForDistance(this.headDistanceAlongPath);let r=!1,a=-1;for(let t=s;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=s+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 o=this.newRoute[this.newRoute.length-1];o.x===n.x&&o.y===n.y||this.newRoute.push({x:n.x,y:n.y,z:o.z}),this.newVias.push(n),this.newRoute.push({x:n.x,y:n.y,z:e.z}),this.currentStepSize=this.maxStepSize;const s=this.pathSegments.findIndex(t=>t.start===e);if(-1!==s)this.tailDistanceAlongPath=this.pathSegments[s].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,o);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],o=this.inputRoute.route[this.inputRoute.route.length-1];return void(this.arePointsEqual(t,n)||this.arePointsEqual(n,o)||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 o=this.getPointAtDistance(this.headDistanceAlongPath+this.currentStepSize);t.points.push({x:o.x,y:o.y,color:"red",label:["Tentative Head",`z: ${o.z}`].join("\n")});let s=0;for(;s<this.totalPathLength;){const e=this.getPointAtDistance(s);t.circles.push({center:{x:e.x,y:e.y},radius:.05,fill:"rgba(100, 100, 100, 0.5)"}),s+=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}},Cs=class extends y{getSolverName(){return"MultiSimplifiedPathSolver"}simplifiedHdRoutes;currentUnsimplifiedHdRouteIndex=0;activeSubSolver=null;unsimplifiedHdRoutes;obstacles;connMap;colorMap;outline;defaultViaDiameter;constructor(t){super(),this.MAX_ITERATIONS=1e8,this.unsimplifiedHdRoutes=t.unsimplifiedHdRoutes;const e=Math.max(2,...t.unsimplifiedHdRoutes.flatMap(t=>t.route.map(t=>t.z+1)))||2;this.obstacles=us(t.obstacles,e),this.connMap=t.connMap||new $e({}),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 Is({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 o=0;o<e.route.length-1;o++)t.lines.push({points:[{x:e.route[o].x,y:e.route[o].y},{x:e.route[o+1].x,y:e.route[o+1].y}],strokeWidth:.15,strokeColor:n,strokeDash:1===e.route[o].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}},_s=class extends y{constructor(t){super(),this.input=t,this.input={...t,obstacles:us(t.obstacles,t.layerCount)},this.MAX_ITERATIONS=1e6,this.inputHdRoutes=this.input.inputHdRoutes,this.mergedViaHdRoutes=structuredClone(this.inputHdRoutes),this.unprocessedRoutes=[...this.input.inputHdRoutes],this.colorMap=this.input.colorMap,this.outline=this.input.outline,this.obstacles=this.input.obstacles,this.obstacleSHI=new ss("flatbush",this.input.obstacles),this.hdRouteSHI=new ds(this.inputHdRoutes),this.vias=[],this.offendingVias=[],this.connMap=t.connMap,this.viasByNet=new Map,this.rebuildVias()}getSolverName(){return"SameNetViaMergerSolver"}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 o=e.vias[n],s={x:o.x,y:o.y,diameter:e.viaDiameter,net:this.connMap?.idToNetMap[e.connectionName]??"",layers:[...new Set(e.route.map(t=>t.z))],routeIndex:t};this.vias.push(s);const i=this.viasByNet.get(s.net);i?i.push(s):this.viasByNet.set(s.net,[s])}}}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 o=n.indexOf(e);for(let t=o>=0?o+1:0;t<n.length;t++){const o=n[t],s=e.x-o.x,i=e.y-o.y,r=s*s+i*i,a=e.diameter/2+o.diameter/2;if(r<=a*a&&0!==r)return[e,o]}}return null}handleOffendingPair(t,e){const n=t.layers.length<e.layers.length?t:e,o=n===t?e:t,s=this.mergedViaHdRoutes[n.routeIndex].route;for(let t=0;t<n.layers.length;t++)for(let t=s.length-1;t>=1;t--){const e=s[t-1],i=s[t];if(i.x===n.x&&i.y===n.y){s.splice(t,0,{x:o.x,y:o.y,z:i.z}),s.splice(t,0,{x:o.x,y:o.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:o.x,y:o.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 o=e.zLayers?.includes(0),s=e.zLayers?.includes(1);o&&s?n="rgba(128, 0, 128, 0.2)":o?n="rgba(255, 0, 0, 0.2)":s&&(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 o=e.route[n],s=e.route[n+1];o.z===s.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:s.x,y:s.y}],strokeColor:0===o.z?"rgba(255, 0, 0, 0.5)":"rgba(0, 0, 255, 0.5)",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 o=Qe(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...o.rects??[]),t.lines.push(...o.lines??[])}}return this.activeSubSolver&&t.lines.push(...this.activeSubSolver.visualize().lines??[]),t}},Ts=class extends y{constructor(t){super(),this.simplificationConfig=t,this.simplificationConfig={...t,obstacles:us(t.obstacles,t.layerCount)},this.hdRoutes=[...t.hdRoutes],this.MAX_ITERATIONS=1e8}getSolverName(){return"TraceSimplificationSolver"}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 ps({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 _s({inputHdRoutes:this.hdRoutes,obstacles:[...this.simplificationConfig.obstacles],colorMap:{...this.simplificationConfig.colorMap},layerCount:this.simplificationConfig.layerCount,connMap:this.simplificationConfig.connMap,outline:this.simplificationConfig.outline?[...this.simplificationConfig.outline]:void 0}),this.extractResult=t=>t.getMergedViaHdRoutes()??[];break;case"path_simplification":this.activeSubSolver=new Cs({unsimplifiedHdRoutes:this.hdRoutes,obstacles:[...this.simplificationConfig.obstacles],connMap:this.simplificationConfig.connMap,colorMap:{...this.simplificationConfig.colorMap},outline:this.simplificationConfig.outline?[...this.simplificationConfig.outline]:void 0,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 o=e.zLayers?.includes(0),s=e.zLayers?.includes(1);o&&s?n="rgba(128, 0, 128, 0.2)":o?n="rgba(255, 0, 0, 0.2)":s&&(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 o=e.route[n],s=e.route[n+1];o.z===s.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:s.x,y:s.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 n=Qe(e.jumpers,{color:"orange",label:e.connectionName});t.rects.push(...n.rects??[]),t.lines.push(...n.lines??[])}}return t}};function Es(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 Rs=class extends y{getSolverName(){return"AvailableSegmentPointSolver"}nodes;edges;traceWidth;obstacleMargin;minPortSpacing;nodeMap;nodeEdgeMap;sharedEdgeSegments=[];edgeSegmentMap=new Map;portPointMap=new Map;colorMap;constructor({nodes:t,edges:e,traceWidth:n,obstacleMargin:o,colorMap:s}){super(),this.nodes=t,this.edges=e,this.traceWidth=n,this.obstacleMargin=o??.15,this.minPortSpacing=this.traceWidth+this.obstacleMargin,this.colorMap=s??{},this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Es(e),this.MAX_ITERATIONS=1}_step(){this.computeAllSharedEdgeSegments(),this.solved=!0}computeAllSharedEdgeSegments(){for(const t of this.edges){const[e,n]=t.nodeIds,o=this.nodeMap.get(e),s=this.nodeMap.get(n);if(!o||!s)continue;const i=this.computeSharedEdgeSegment(t,o,s);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 o=this.findOverlappingSegment(e,n);if(!o)return null;const s=e.availableZ.filter(t=>n.availableZ.includes(t));if(0===s.length)return null;const i=Math.sqrt((o.end.x-o.start.x)**2+(o.end.y-o.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=o.end.x-o.start.x,l=o.end.y-o.start.y,u=(o.start.x+o.end.x)/2,p=(o.start.y+o.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=o.start.x+d*e,s=o.start.y+l*e,h=Math.sqrt((n-u)**2+(s-p)**2);m.push({x:n,y:s,distToCenter:h})}const f=m.reduce((t,e)=>e.distToCenter<t.distToCenter?e:t);for(let o=0;o<c;o++){const{x:i,y:r}=m[o],a=Math.sqrt((i-f.x)**2+(r-f.y)**2);for(const c of s){const s={segmentPortPointId:`${t.capacityMeshEdgeId}_pp${o}_z${c}`,x:i,y:r,availableZ:[c],nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],edgeId:t.capacityMeshEdgeId,connectionName:null,distToCentermostPortOnZ:a};h.push(s)}}return{edgeId:t.capacityMeshEdgeId,nodeIds:[e.capacityMeshNodeId,n.capacityMeshNodeId],start:o.start,end:o.end,availableZ:s,portPoints:h}}shouldSkipOffBoardPortPoint(t,e){const n=this.nodeEdgeMap.get(e.capacityMeshNodeId)??[];for(const o of n){const n=o.nodeIds[0]===e.capacityMeshNodeId?o.nodeIds[1]:o.nodeIds[0];if(n===t.capacityMeshNodeId)continue;const s=this.nodeMap.get(n);if(s?._offBoardConnectionId!==t._offBoardConnectionId)continue;if(2!==this.nodes.filter(e=>e._offBoardConnectionId===t._offBoardConnectionId).length)continue;const i={x:(t.center.x+s.center.x)/2,y:(t.center.y+s.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)},o={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)},s=n.end-n.start,i=o.end-o.start;if(s<-1e-4||i<-1e-4)return null;if(s<i){const t=(n.start+n.end)/2;return{start:{x:t,y:o.start},end:{x:t,y:o.end}}}{const t=(o.start+o.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 o=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return o?o.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 o=this.edgeSegmentMap.get(n.capacityMeshEdgeId);return o?.portPoints??[]}assignPortPoint(t,e,n){const o=this.portPointMap.get(t);return!!o&&(null===o.connectionName&&(o.connectionName=e,o.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}},ws=(t,e,n,o)=>{if(t?._containsTarget)return 0;if(1===(t.availableZ?.length??2)&&(e>0||n>0||o>0))return 1;return((.82*e+.41*n+.2*o)/2)**1.1/We(t)};function As(t,e,n,o,s){const i=n-e,r=s-o,a=1e-6;if(Math.abs(t.y-s)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(s-t.y);if(Math.abs(t.y-o)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-o);const c=Math.abs(t.y-s),h=Math.abs(t.x-n),d=Math.abs(t.y-o),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,s-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-o))}function Os(t,e,n=1e-6){return Math.abs(t-e)<n}function zs(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[o,s]=e[t];for(let i=t+1;i<e.length;i++){const[t,r]=e[i];Os(o,t)||Os(o,r)||Os(s,t)||Os(s,r)||(o<t&&t<s&&s<r||t<o&&o<r&&r<s)&&n++}}return n}var Ds=t=>{const e=t.center.x-t.width/2,n=t.center.x+t.width/2,o=t.center.y-t.height/2,s=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=As(t,e,n,o,s),l=As(i,e,n,o,s);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+=zs(e);return{numSameLayerCrossings:h,numEntryExitLayerChanges:c,numTransitionPairCrossings:zs(a)}},Ls=1.6*3.2,Fs=(t,e)=>{const n=Math.ceil(e/2),o=Math.min(t.width,t.height),s=Math.max(t.width,t.height),i=(Math.floor(o/1.6)+.1)*(Math.floor(s/3.2)+.1)/Ls;return Math.min(1,n/i)};function Xs(t,e,n,o){const s=e.x-n/2,i=e.x+n/2,r=e.y-o/2,a=e.y+o/2,c=Math.abs(t.y-a),h=Math.abs(t.x-i),d=Math.abs(t.y-r),l=Math.abs(t.x-s),u=Math.min(c,h,d,l);return u>.001?"interior":u===c?"top":u===h?"right":u===d?"bottom":"left"}function Ys(t,e,n,o,s){const i=Xs(t,n,o,s),r=Xs(e,n,o,s);return"interior"!==i&&i===r}function $s(t,e,n,o,s){const i=Xs(t,n,o,s);let r;if("top"===i||"bottom"===i){const n=o;r=Math.abs(e.x-t.x)/n}else{const n=s;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 Bs(t){return"computeNodePf"in t&&"function"==typeof t.computeNodePf}function ks(t){const e={lines:[],points:[],rects:[],circles:[]};for(const n of t.inputNodes){let o=0,s=0,i={numSameLayerCrossings:0,numEntryExitLayerChanges:0,numTransitionPairCrossings:0},r=0;if(Bs(t)){o=t.computeNodePf(n),s=t.nodeMemoryPfMap.get(n.capacityMeshNodeId)??0;const e=t.buildNodeWithPortPointsForCrossing(n);i=Ds(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{o=t.nodePfMap.get(n.capacityMeshNodeId)??0;const e=t.nodeAssignedPortPoints.get(n.capacityMeshNodeId)??[],s={capacityMeshNodeId:n.capacityMeshNodeId,center:n.center,width:n.width,height:n.height,portPoints:e,availableZ:n.availableZ};i=Ds(s);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*o)),c=Math.max(0,255-Math.floor(512*o));let h=`rgba(${a}, ${c}, ${c}, ${o<.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: ${o.toFixed(3)}, memPf: ${s.toFixed(3)}\nC#: ${r}\nxSame: ${i.numSameLayerCrossings}, xLC: ${i.numEntryExitLayerChanges}, xTransition: ${i.numTransitionPairCrossings}\nobCmid: ${n._offBoardConnectedCapacityMeshNodeIds?.join(",")}\nobs: ${n._containsObstacle?"yes":"no"}`})}if(Bs(t))for(const[n,o]of t.portPointMap){const s=t.assignedPortPoints.get(n),i=s?t.colorMap[s.connectionName]??"blue":"rgba(150, 150, 150, 0.5)";e.circles.push({center:{x:o.x,y:o.y},radius:.05,fill:i,layer:`z${o.z}`,label:[n,`conn: ${s?.connectionName}`,`cd: ${o.distToCentermostPortOnZ}`,`connects: ${o.connectionNodeIds.join(",")}`,`rootConn: ${s?.rootConnectionName}`].filter(Boolean).join("\n")})}const n=Bs(t)?t.connectionsWithResults:t.connectionResults;for(const o of n){if(!o.path)continue;const n=o.connection,s=t.colorMap[n.name]??"blue",i=[];for(const t of o.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 o=i[n],r=i[n+1],a=o.z===r.z,c=o.z;let h;h=a?0===c?void 0:"10 5":"3 3 10";const d=o.nodeId?t.nodeMap.get(o.nodeId):null;if(d&&Ys(o,r,d.center,d.width,d.height)){const t=$s(o,r,d.center,d.width,d.height);e.lines.push({points:[{x:o.x,y:o.y},{x:t.x,y:t.y}],strokeColor:s,strokeDash:h}),e.lines.push({points:[{x:t.x,y:t.y},{x:r.x,y:r.y}],strokeColor:s,strokeDash:h})}else e.lines.push({points:[{x:o.x,y:o.y},{x:r.x,y:r.y}],strokeColor:s,strokeDash:h})}}if(Bs(t)&&!t.solved&&t.candidates&&t.candidates.length>0){const n=t.currentConnection,o=n?t.colorMap[n.connection.name]??"blue":"blue";if(n){const[s,i]=n.nodeIds,r=t.nodeMap.get(s),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,s=h?{x:h.x,y:h.y}:a.center;e.lines.push({points:[t,s],strokeColor:it(o,.5),strokeDash:"5 5"}),e.points.push({x:t.x,y:t.y,color:o,label:[`Start: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.points.push({x:s.x,y:s.y,color:o,label:[`End: ${n.connection.name}`,`${n.connection.rootConnectionName}`].join("\n")}),e.circles.push({center:s,radius:.08,stroke:o,label:`Goal: ${n.connection.name}`})}}const s=[...t.candidates].sort((t,e)=>t.f-e.f).slice(0,1);for(const i of s){const s=[];let r=i;for(;r;)s.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<s.length-1;n++){const i=s[n],r=s[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&&Ys(i,r,d.center,d.width,d.height)){const t=$s(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(o,.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(o,.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(o,.25),strokeDash:h})}if(s.length>=1){const r=s[s.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,o={x:i.prevCandidate.point.x,y:i.prevCandidate.point.y,z:i.prevCandidate.z,connectionName:e},s={x:i.portPoint.x,y:i.portPoint.y,z:i.portPoint.z,connectionName:e},r=t.buildNodeWithPortPointsForCrossing(p,[o,s]),m=pe(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?Fs(f,h):ws(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,P=t.nodeMemoryPfMap.get(i.currentNodeId)??0,S=-Math.log(1-P)*t.MEMORY_PF_FACTOR;e.circles.push({center:r,radius:.03,fill:it(o,.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: ${S.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 js(t,e){const n=[],o=e.filter(t=>t._containsTarget),s=new Map;for(const i of t.connections){const t=[];for(const n of i.pointsToConnect){let s=e[0],i=Number.MAX_VALUE;for(const t of o){const e=Math.sqrt((t.center.x-n.x)**2+(t.center.y-n.y)**2);e<i&&(i=e,s=t)}t.push(s)}if(t.length<2)throw new Error(`Not enough nodes for connection "${i.name}", only ${t.length} found`);s.set(i.name,t.map(t=>t.capacityMeshNodeId)),n.push({connection:i,nodeIds:[t[0].capacityMeshNodeId,t[t.length-1].capacityMeshNodeId],straightLineDistance:Pt(t[0].center,t[t.length-1].center)})}return{unshuffledConnectionsWithResults:n,connectionNameToGoalNodeIds:s}}function Ws(t,e){const n=new Map(e.map(t=>[t.capacityMeshNodeId,t])),o=e.map(t=>(t.width+t.height)/2).filter(t=>Number.isFinite(t)&&t>0),s=o.length>0?o.reduce((t,e)=>t+e,0)/o.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}=js(t,e);return{nodeMap:n,avgNodePitch:s,offBoardNodes:i,portPointMap:r,nodePortPointsMap:a,nodeAssignedPortPoints:c,unshuffledConnectionsWithResults:h,connectionNameToGoalNodeIds:d}}function Hs(t,e,n){let o=0;const s=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=Ds(n),r=Math.min(ws(t,i.numSameLayerCrossings,i.numEntryExitLayerChanges,i.numTransitionPairCrossings),s);o+=Math.log(1-r)}return o}function Us(t,e){if(e._containsTarget)return 0;const n=Ds(t);return ws(e,n.numSameLayerCrossings,n.numEntryExitLayerChanges,n.numTransitionPairCrossings)}function Vs(t,e,n,o,s){const i=n-e,r=s-o,a=1e-6;if(Math.abs(t.y-s)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(s-t.y);if(Math.abs(t.y-o)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-o);const c=Math.abs(t.y-s),h=Math.abs(t.x-n),d=Math.abs(t.y-o),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,s-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-o))}function Zs(t,e,n){let o=0;const s=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=Ds(n),r=Math.min(Fs(t,i.numSameLayerCrossings),s);o+=Math.log(1-r)}return o}function Gs(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 Js=[{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}],qs=class extends y{getSolverName(){return"MultiSectionPortPointOptimizer"}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=Js;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 o={capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ},s=this.JUMPER_PF_FN_ENABLED&&1===e.availableZ.length?Fs(e,Ds(o).numSameLayerCrossings):Us(o,e);t.set(e.capacityMeshNodeId,s)}return t}computeBoardScore(){const t=this.getNodesWithPortPoints();return this.computeScoreForNodes(t)}computeScoreForNodes(t){return this.JUMPER_PF_FN_ENABLED?Zs(t,this.capacityMeshNodeMap):Hs(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 o={capacityMeshNodeId:e,center:t.center,width:t.width,height:t.height,portPoints:n,availableZ:t.availableZ},s=this.JUMPER_PF_FN_ENABLED&&1===t.availableZ.length?Fs(t,Ds(o).numSameLayerCrossings):Us(o,t);this.nodePfMap.set(e,s)}}getCreatePortPointSectionInput(){return{inputNodes:this.inputNodes,capacityMeshNodes:this.capacityMeshNodes,capacityMeshEdges:this.capacityMeshEdges,nodeMap:this.nodeMap,connectionResults:this.connectionResults}}createSection(t){return function(t,e){const{inputNodes:n,capacityMeshNodes:o,capacityMeshEdges:s,connectionResults:i}=t,{centerOfSectionCapacityNodeId:r,expansionDegrees:a}=e,c=new Map;for(const t of s){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=o.filter(t=>h.has(t.capacityMeshNodeId)),m=[],f=[];for(const t of s){const[e,n]=t.nodeIds,o=h.has(e),s=h.has(n);o&&s?m.push(t):(o||s)&&f.push(t)}const g=u.map(t=>{const e=t.portPoints.filter(t=>{const[e,n]=t.connectionNodeIds,o=h.has(e),s=h.has(n);return o||s});return{...t,portPoints:e}}),y=function(t,e){const n=[];for(const o of t){if(!o.path||0===o.path.length)continue;const t=o.connection.name,s=o.connection.rootConnectionName,i=[];for(let t=0;t<o.path.length;t++){const n=o.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=o.path[0].currentNodeId;(o.nodeIds[0]===t||o.nodeIds[1]===t)&&(c=0)}if(a<o.path.length-1){const t=o.path.length-1,e=o.path[t].currentNodeId;(o.nodeIds[0]===e||o.nodeIds[1]===e)&&(h=t)}const d=o.path.slice(c,h+1),l=c>0,u=h<o.path.length-1;n.push({connectionName:t,rootConnectionName:s,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),o=this.capacityMeshNodeMap.get(n);if(!t||!o)continue;const s=this.nodeAssignedPortPoints.get(n)??[];s.length>0&&e.push({capacityMeshNodeId:n,center:t.center,width:t.width,height:t.height,portPoints:s,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,o]of this.nodePfMap.entries()){o*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_ATTEMPTS_PER_NODE)**2>e&&(e=o,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,o=Gs(n);if(this.FRACTION_TO_REPLACE>=1)return new Set(e);const s=function(t,e){const n=Gs(e),o=[...t];for(let t=o.length-1;t>0;t--){const e=Math.floor(n()*(t+1));[o[t],o[e]]=[o[e],o[t]]}return o}(e,n),i=Math.max(1,Math.ceil(s.length*this.FRACTION_TO_REPLACE)),r=new Set(s.slice(0,i));if(this.ALWAYS_RIP_INTERSECTIONS){const n=function(t){const{section:e,nodePfMap:n,capacityMeshNodeMap:o,nodeAssignedPortPoints:s,acceptablePf:i}=t,r=[];for(const t of e.nodeIds){if((n.get(t)??0)<=i)continue;const e=o.get(t);if(!e)continue;const a=s.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],o=e[1];if(n.z!==o.z)continue;const s=Vs(n,c,h,d,l),i=Vs(o,c,h,d,l),r=n.z,a=p.get(r)??[];a.push({connectionName:t,t1:s,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:o,b:s}=e[t];for(let i=t+1;i<e.length;i++){const{connectionName:t,a:a,b:c}=e[i];Math.abs(o-a)<m||Math.abs(o-c)<m||Math.abs(s-a)<m||Math.abs(s-c)<m||(o<a&&a<s&&s<c||a<o&&o<c&&c<s)&&r.push([n,t])}}}}return r}({section:t,nodePfMap:this.nodePfMap,capacityMeshNodeMap:this.capacityMeshNodeMap,nodeAssignedPortPoints:this.nodeAssignedPortPoints,acceptablePf:this.ACCEPTABLE_PF});for(const[t,s]of n){if(r.has(t)||r.has(s))continue;const n=e.includes(t),i=e.includes(s);if(n&&i){const e=o()<.5;r.add(e?t:s)}else n?r.add(t):i&&r.add(s)}}return this.stats.lastRipCount=r.size,r}createSectionSimpleRouteJson(t){const e=[];this.currentSectionCutPathInfo.clear(),this.currentSectionKeptPortPoints.clear(),this.currentSectionFixedRoutes=[];const n=[],o=[];for(const e of this.connectionResults){if(!e.path||0===e.path.length)continue;const[s,i]=e.nodeIds,r=t.nodeIds.has(s),a=t.nodeIds.has(i);r&&a&&(o.push(e),n.push(e.connection.name))}const s=[];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&&(s.push({sectionPath:e,originalResult:t}),n.includes(e.connectionName)||n.push(e.connectionName))}const i=this.determineConnectionsToRip(t,n);for(const t of o)i.has(t.connection.name)&&e.push(t.connection);for(const{sectionPath:t,originalResult:n}of s){if(!i.has(t.connectionName))continue;const o=`__cut__${t.connectionName}__${t.originalStartIndex}`;this.colorMap[o]=this.colorMap[t.connectionName];const s=t.points[0],r=t.points[t.points.length-1],a={name:o,rootConnectionName:t.rootConnectionName??t.connectionName,pointsToConnect:[{x:s.x,y:s.y,layers:[`layer${s.z+1}`]},{x:r.x,y:r.y,layers:[`layer${r.z+1}`]}]};e.push(a),this.currentSectionCutPathInfo.set(o,{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 o)r.has(t.connection.name)&&this.currentSectionFixedRoutes.push(t);for(const{sectionPath:t,originalResult:e}of s)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 o=n.points[0].nodeId;e.add(o);const s=n.points[n.points.length-1].nodeId;e.add(s)}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),o=Ws(e,n);for(const[t,e]of this.currentSectionKeptPortPoints){const n=o.nodeAssignedPortPoints.get(t)??[];o.nodeAssignedPortPoints.set(t,[...n,...e])}return new Qs({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:o,fixedRoutes:this.currentSectionFixedRoutes})}reattachSection(t,e,n,o){const s=[],i=[];for(const t of e)t.connection.name.startsWith("__cut__")?i.push(t):s.push(t);const r=new Set(s.map(t=>t.connection.name));this.connectionResults=this.connectionResults.filter(t=>!r.has(t.connection.name)),this.connectionResults.push(...s);for(const[e,n]of this.nodeAssignedPortPoints.entries()){if(!t.nodeIds.has(e))continue;const o=n.filter(t=>!r.has(t.connectionName));this.nodeAssignedPortPoints.set(e,o)}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:o,originalConnectionResult:s}=n,i=s.path;if(!i)continue;const r=o.connectionName;for(const[e,n]of this.nodeAssignedPortPoints.entries()){const o=n.filter(n=>n.connectionName!==r||!t.nodeIds.has(e));this.nodeAssignedPortPoints.set(e,o)}const a=i.slice(0,o.originalStartIndex),c=i.slice(o.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]}),s.path=[...a,...h,...c],e.portPoints)for(const n of e.portPoints){const e={...n,connectionName:r,rootConnectionName:o.rootConnectionName??r};for(const o of t.inputNodes)for(const t of o.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 o.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("__"),o=n>=0?e.slice(0,n):e;return{...t,connectionName:o}}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),o=this.computeScoreForNodes(n),s=this.computeScoreForNodes(t),i=`attempt${this.sectionAttempts}`;if(this.stats.lastSectionScore=s,s>o){const t=this.stats.currentBoardScore;this.stats.lastBoardScore=t;const e=[...this.connectionResults],n=new Map(this.assignedPortPoints),o=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 s=this.computeBoardScore();this.stats.sectionScores[i]=s,s>t?(this.stats.successfulOptimizations++,this.stats.currentBoardScore=s):(this.connectionResults=e,this.assignedPortPoints=n,this.nodeAssignedPortPoints=o,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?ks(this):this.activeSubSolver?this.activeSubSolver.visualize():this.currentSection?function(t,e){const n={lines:[],points:[],rects:[],circles:[]};for(const e of t.inputNodes){const o=e.capacityMeshNodeId===t.centerNodeId,s=o?"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:s,label:`${e.capacityMeshNodeId}${o?" (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 o of t.sectionPaths){const t=e?.[o.connectionName]??"blue";for(let e=0;e<o.points.length-1;e++){const s=o.points[e],i=o.points[e+1],r=s.z===i.z,a=s.z;let c;c=r?0===a?"5 5":"10 5":"3 3 10",n.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:t,strokeDash:c})}}return n}(this.currentSection,this.colorMap):ks(this)}},Ks=class extends y{constructor(t){super(),this.input=t;const{simpleRouteJson:e,capacityMeshNodes:n,inputNodes:o,colorMap:s,nodeMemoryPfMap:i,hyperParameters:r,precomputedInitialParams:a,fixedRoutes:c}=t;if(this.input=structuredClone(t),this.MAX_ITERATIONS=1e8,this.simpleRouteJson=e,this.inputNodes=o,this.colorMap=s??{},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,o]of t.nodeAssignedPortPoints)e.set(n,[...o]);return{nodeAssignedPortPoints:e}}(a);this.nodeAssignedPortPoints=t,this.connectionsWithResults=Bt(structuredClone(a.unshuffledConnectionsWithResults),this.hyperParameters.SHUFFLE_SEED??0)}else{this.nodeMap=new Map(o.map(t=>[t.capacityMeshNodeId,t]));const t=o.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=o.filter(t=>t._offBoardConnectionId),this.portPointMap=new Map,this.nodePortPointsMap=new Map;for(const t of o)this.nodePortPointsMap.set(t.capacityMeshNodeId,[]),this.nodeAssignedPortPoints.set(t.capacityMeshNodeId,[]);for(const t of o)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}getSolverName(){return"PortPointPathingSolver"}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(){const t=this.hyperParameters.START_RIPPING_PF_THRESHOLD,e=this.hyperParameters.END_RIPPING_PF_THRESHOLD;if(void 0!==t&&void 0!==e){const n=this.MAX_RIPS;return t+(n>0?this.totalRipCount/n:0)*(e-t)}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 o=this.computeNodePf(n),s=this.pfToFailureCost(o);return this.baseNodeCostCache.set(t,s),s}computeBoardScore(){const t=this.getNodesWithPortPoints();return this.JUMPER_PF_FN_ENABLED?Zs(t,this.capacityMeshNodeMap):Hs(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 o=this.nodeMap.get(t);if(!o)return 0;const s=this.getBaseNodeFailureCost(t),i=this.computeNodePf(o,[e,n]),r=this.pfToFailureCost(i),a=Math.max(0,r-s);return i>=this.NODE_MAX_PF?this.NODE_PF_MAX_PENALTY:a*this.NODE_PF_FACTOR}getConnectionsWithNodes(){const{unshuffledConnectionsWithResults:t,connectionNameToGoalNodeIds:e}=js(this.simpleRouteJson,this.inputNodes);return{connectionsWithResults:Bt(t,this.hyperParameters.SHUFFLE_SEED??0),connectionNameToGoalNodeIds:e}}buildNodeWithPortPointsForCrossing(t,e){const n=this.nodeAssignedPortPoints.get(t.capacityMeshNodeId)??[],o=e?[...n,...e]:n;return{capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:o,availableZ:t.availableZ}}computeNodePf(t,e){if(t._containsTarget)return 0;const n=this.buildNodeWithPortPointsForCrossing(t,e),o=Ds(n);return this.JUMPER_PF_FN_ENABLED&&1===t.availableZ.length?Fs(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),o.numSameLayerCrossings):ws(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),o.numSameLayerCrossings,o.numEntryExitLayerChanges,o.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,o]=t.connectionNodeIds;return n===e?o:o===e?n:null}computeG(t,e,n,o,s){const i=t.currentNodeId,r=t.point,a={x:r.x,y:r.y,z:t.z,connectionName:o,rootConnectionName:s},c={x:e.x,y:e.y,z:e.z,connectionName:o,rootConnectionName:s},h=this.getNodeDeltaFailureCostForSegment(i,a,c);return t.g+h}computeGToEndTarget(t,e,n,o){const s=t.currentNodeId,i={x:t.point.x,y:t.point.y,z:t.z,connectionName:n,rootConnectionName:o},r={x:e.x,y:e.y,z:t.z,connectionName:n,rootConnectionName:o},a=this.getNodeDeltaFailureCostForSegment(s,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 o=Pt(t,n.center);o<e&&(e=o)}return e}computeH(t,e,n,o,s,i){if(this.RANDOM_WALK_DISTANCE>0&&s<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=Pt(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,o=this.nodePortPointsMap.get(t)??[],s=[];for(const t of o){const o=this.getVisitedPortPointKey(t.portPointId,e);if(this.visitedPortPoints?.has(o))continue;const i=this.assignedPortPoints.get(t.portPointId);i&&i?.rootConnectionName!==n||s.push(t)}return s}getAvailableExitPortPointsWithOmissions(t,e,n){const o=this.nodePortPointsMap.get(t)??[],s=this.currentConnection?.connection.rootConnectionName,i=new Map;for(const e of o){const o=this.getVisitedPortPointKey(e.portPointId,n);if(this.visitedPortPoints?.has(o))continue;const s=this.getOtherNodeId(e,t);if(!s)continue;this.nodeMap.get(s);const r=`${s}|${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),o=n&&n.rootConnectionName===s;if(!n||o){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===s?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 o=this.currentConnection?.connection.rootConnectionName,s=[];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!==o||s.push({...t,throughNodeId:i})}}return s}canTravelThroughObstacle(t,e,n){const o=this.connectionNameToGoalNodeIds.get(e);return o?.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),o=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}),o&&o._offBoardConnectionId&&e.push({prevCandidate:null,portPoint:null,currentNodeId:n.prevCandidate.currentNodeId,point:o.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 o=[];for(let s=0;s<t.length;s++){const i=t[s];if(!i.portPoint){const r=0===s,a=s===t.length-1;if(!r&&!a){const t={x:i.point.x,y:i.point.y,z:i.z,connectionName:e,rootConnectionName:n};o.push(t);const s=this.nodeAssignedPortPoints.get(i.currentNodeId)??[];s.push(t),this.nodeAssignedPortPoints.set(i.currentNodeId,s)}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};o.push(a);for(const t of r.connectionNodeIds){const e=this.nodeAssignedPortPoints.get(t)??[];e.push(a),this.nodeAssignedPortPoints.set(t,e)}}const s=Array.from(new Set(t.map(t=>t.currentNodeId)));for(const t of s){const o=this.nodeMap.get(t);if(o&&o._offBoardConnectionId)for(const t of o?._offBoardConnectedCapacityMeshNodeIds??[]){const o=this.nodePortPointsMap.get(t)??[];for(const t of o)this.assignedPortPoints.set(t.portPointId,{connectionName:e,rootConnectionName:n})}}return o}addTargetPointsToNodes(t,e){const n=t[0],o=t[t.length-1],s=e.pointsToConnect[0],i=e.pointsToConnect[e.pointsToConnect.length-1];if(n&&s){const t=this.nodeAssignedPortPoints.get(n.currentNodeId)??[];t.push({x:s.x,y:s.y,z:n.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(n.currentNodeId,t)}if(o&&i){const t=this.nodeAssignedPortPoints.get(o.currentNodeId)??[];t.push({x:i.x,y:i.y,z:o.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),this.nodeAssignedPortPoints.set(o.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,totalRipCount:this.totalRipCount},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,o]=t.nodeIds,s=this.nodeMap.get(n),i=this.nodeMap.get(o);if(!s||!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 s.availableZ){const e=c?{x:c.x,y:c.y}:s.center,i=this.computeH({...e,distToCentermostPortOnZ:0},n,o,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,o)){const e=t.connection.pointsToConnect[t.connection.pointsToConnect.length-1],n=e?{x:e.x,y:e.y}:i.center,s=this.computeGToEndTarget(d,n,r,a),c={prevCandidate:d,portPoint:null,currentNodeId:o,point:n,z:d.z,g:s,h:0,f:s,distanceTraveled:d.distanceTraveled+Pt(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,o,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,s=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+Pt(d.point,t),u=d.hasTouchedOffBoardNode||Boolean(i._offBoardConnectionId),p=this.computeH(t,e,o,t.z,h,u),m=c+p*this.GREEDY_MULTIPLIER,f=Boolean(l?._offBoardConnectionId)&&Boolean(s?._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=[],o=new Set;for(const s of this.connectionsWithResults)if(s.path&&s.connection.name!==e&&!o.has(s.connection.name))for(const e of s.path)if(e.currentNodeId===t){n.push(s),o.add(s.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),o={capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:n,availableZ:t.availableZ},s=Ds(o),i=s.numSameLayerCrossings+s.numEntryExitLayerChanges+s.numTransitionPairCrossings;return{pf:ws(this.capacityMeshNodeMap.get(t.capacityMeshNodeId),s.numSameLayerCrossings,s.numEntryExitLayerChanges,s.numTransitionPairCrossings),totalCrossings:i}}computeNodeCrossings(t){if(t._containsTarget)return 0;const e=this.buildNodeWithPortPointsForCrossing(t),n=Ds(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 o=n.filter(t=>t.connectionName!==e);this.nodeAssignedPortPoints.set(t,o)}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 o=!1;for(const t of n){if(this.totalRipCount>this.MAX_RIPS)break;const n=this.nodeMap.get(t);if(!n)continue;let s=this.computeNodePf(n);if(s<=this.RIPPING_PF_THRESHOLD)continue;this.testedRipConnections.has(t)||this.testedRipConnections.set(t,new Set);const i=this.testedRipConnections.get(t),r=Bt(this.getConnectionsInNode(t,e),(this.hyperParameters.SHUFFLE_SEED??0)+this.processedConnectionQueue.length);for(const t of r){if(s<=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;s=r,o=!0,this.clearCostCaches()}}o&&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)),o=Bt(e,(this.hyperParameters.SHUFFLE_SEED??0)+this.totalRipCount+this.processedConnectionQueue.length);for(let t=0;t<n&&t<o.length&&!(this.totalRipCount>this.MAX_RIPS);t++){const e=o[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=ks(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}},Qs=class extends Zt{getSolverName(){return"HyperPortPointPathingSolver"}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??Ws(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 Ks({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()}},ti=(t,e)=>t<=e?[t,e]:[e,t],ei=t=>`${t[0]}|${t[1]}`,ni=({portPointId:t,currentNodeId:e,inputNodes:n})=>{let o;if(t)for(const e of n){const n=e.portPoints.find(e=>e.portPointId===t);if(n?.connectionNodeIds){o=n.connectionNodeIds;break}}if(!o||2!==o.length)return[e,e];const[s,i]=o;return s&&i?ti(s,i):[e,e]},oi=1e-6,si=(t,e)=>Math.abs(t-e)<=oi,ii=({nodeAId:t,nodeBId:e,nodeBounds:n})=>{if(t===e)return null;const o=n.get(t),s=n.get(e);if(!o||!s)return null;const i=ti(t,e),r=ei(i);if(si(o.maxX,s.minX)||si(s.maxX,o.minX)){const n=Math.max(o.minY,s.minY),a=Math.min(o.maxY,s.maxY),c=a-n;if(c>oi){const h=si(o.maxX,s.minX)?o.maxX:o.minX;return{ownerNodeIds:i,ownerPairKey:r,orientation:"vertical",x1:h,y1:n,x2:h,y2:a,center:{x:h,y:(n+a)/2},length:c,nodeSideByOwnerId:si(o.maxX,s.minX)?{[t]:"right",[e]:"left"}:{[t]:"left",[e]:"right"}}}}if(si(o.maxY,s.minY)||si(s.maxY,o.minY)){const n=Math.max(o.minX,s.minX),a=Math.min(o.maxX,s.maxX),c=a-n;if(c>oi){const h=si(o.maxY,s.minY)?o.maxY:o.minY;return{ownerNodeIds:i,ownerPairKey:r,orientation:"horizontal",x1:n,y1:h,x2:a,y2:h,center:{x:(n+a)/2,y:h},length:c,nodeSideByOwnerId:si(o.maxY,s.minY)?{[t]:"top",[e]:"bottom"}:{[t]:"bottom",[e]:"top"}}}}return null},ri=({portPoint:t,ownerNodeIds:e,inputNodes:n})=>{for(const o of e){const e=n.find(t=>t.capacityMeshNodeId===o);if(e?._containsTarget)return!0;const s=e?.portPoints.find(e=>e.portPointId===t.portPointId);if(s?.connectionNodeIds?.some(t=>n.find(e=>e.capacityMeshNodeId===t)?._containsTarget))return!0}return!1},ai=1e-6,ci=class extends _n{constructor(t){super(),this.input=t;for(const e of t.nodeWithPortPoints)this.mapOfNodeIdToBounds.set(e.capacityMeshNodeId,kt(e));const e=new Map;for(const n of t.nodeWithPortPoints)for(const o of n.portPoints){if(!o.portPointId)continue;const s=ni({portPointId:o.portPointId,currentNodeId:n.capacityMeshNodeId,inputNodes:t.inputNodesWithPortPoints}),i=ei(s),r=this.mapOfOwnerPairToPortPoints.get(i)??[];r.some(t=>t.portPointId&&t.portPointId===o.portPointId)||r.push({...o,ownerNodeIds:s,ownerPairKey:i}),this.mapOfOwnerPairToPortPoints.set(i,r),e.set(i,s)}this.mapOfOwnerPairToSharedEdge=(({ownerPairs:t,nodeBounds:e})=>{const n=new Map;for(const o of t){const[t,s]=o;if(t===s)continue;const i=ii({nodeAId:t,nodeBId:s,nodeBounds:e});i&&n.set(ei(o),i)}return n})({ownerPairs:Array.from(e.values()),nodeBounds:this.mapOfNodeIdToBounds}),this.ownerPairsToProcess=Array.from(this.mapOfOwnerPairToSharedEdge.keys()),this.ownerPairsToProcess.sort((t,e)=>{const n=this.mapOfOwnerPairToSharedEdge.get(t),o=this.mapOfOwnerPairToSharedEdge.get(e);return n.center.x-o.center.x||n.center.y-o.center.y})}getSolverName(){return"UniformPortDistributionSolver"}mapOfNodeIdToBounds=new Map;mapOfOwnerPairToPortPoints=new Map;mapOfOwnerPairToSharedEdge=new Map;ownerPairsToProcess=[];currentOwnerPairBeingProcessed=null;redistributedNodes=[];step(){if(0===this.ownerPairsToProcess.length)return this.rebuildNodes(),void(this.solved=!0);this.currentOwnerPairBeingProcessed=this.ownerPairsToProcess.shift();const t=this.currentOwnerPairBeingProcessed,e=this.mapOfOwnerPairToSharedEdge.get(t);if(!e)return;if((({sharedEdge:t,obstacles:e})=>{for(const n of e){const e=n.center.x-n.width/2,o=n.center.x+n.width/2,s=n.center.y-n.height/2,i=n.center.y+n.height/2;if("vertical"!==t.orientation){if(Math.abs(t.y1-s)<ai||Math.abs(t.y1-i)<ai){const n=Math.max(t.x1,e);if(Math.min(t.x2,o)-n>ai)return!0}}else if(Math.abs(t.x1-e)<ai||Math.abs(t.x1-o)<ai){const e=Math.max(t.y1,s);if(Math.min(t.y2,i)-e>ai)return!0}}return!1})({sharedEdge:e,obstacles:this.input.obstacles}))return;const n=this.mapOfOwnerPairToPortPoints.get(t)??[],o=[];for(const t of n)ri({portPoint:t,ownerNodeIds:t.ownerNodeIds,inputNodes:this.input.inputNodesWithPortPoints})||o.push(t);const s=(({sharedEdge:t,portPoints:e})=>{if(0===e.length)return[];const n=new Map;for(const t of e){const e=t.z??0,o=n.get(e)??[];o.push(t),n.set(e,o)}const o=[],s=Array.from(n.keys()).sort((t,e)=>t-e);for(const e of s){const s=n.get(e),i=s.length;s.sort((e,n)=>"horizontal"===t.orientation?e.x-n.x:e.y-n.y);for(let e=0;e<i;e++){const n=(2*e+1)/(2*i),r="horizontal"===t.orientation?t.x1+t.length*n:t.x1,a="horizontal"===t.orientation?t.y1:t.y1+t.length*n;o.push({...s[e],x:r,y:a})}}return o})({sharedEdge:e,portPoints:o});this.mapOfOwnerPairToPortPoints.set(t,s)}rebuildNodes(){const t=new Map;for(const e of this.mapOfOwnerPairToPortPoints.values())for(const n of e)n.portPointId&&t.set(n.portPointId,{x:n.x,y:n.y});this.redistributedNodes=this.input.nodeWithPortPoints.map(e=>({...e,portPoints:e.portPoints.map(e=>{if(e.portPointId&&t.has(e.portPointId)){const n=t.get(e.portPointId);return{...e,x:n.x,y:n.y}}return e})}))}getOutput=()=>this.redistributedNodes;visualize(){return(({obstacles:t,nodeWithPortPoints:e,mapOfOwnerPairToPortPoints:n,mapOfOwnerPairToSharedEdge:o,ownerPairsToProcess:s,currentOwnerPairBeingProcessed:i,mapOfNodeIdToBounds:r})=>{const a=t.map(t=>({...t,fill:"#ec000070"})),c=[],h=[],d=new Map,l=new Map,u=new Map;for(const t of e)for(const e of t.portPoints)e.portPointId&&(d.set(e.portPointId,{x:e.x,y:e.y}),l.set(e.portPointId,e.z??0));for(const t of n.values())for(const e of t)e.portPointId&&(d.set(e.portPointId,{x:e.x,y:e.y}),l.set(e.portPointId,e.z??0),u.set(e.portPointId,`${e.ownerNodeIds[0]}&${e.ownerNodeIds[1]}`));e.forEach(t=>{const e=r.get(t.capacityMeshNodeId);if(e){const n=(e.minX+e.maxX)/2,o=(e.minY+e.maxY)/2,s=e.maxX-e.minX,i=e.maxY-e.minY;a.push({center:{x:n,y:o},width:s,height:i,fill:"#00000030",label:`${t.capacityMeshNodeId}`})}t.portPoints.forEach(e=>{if(!e.portPointId)return;const n=d.get(e.portPointId),o=l.get(e.portPointId)??0,s=u.get(e.portPointId)??`${t.capacityMeshNodeId}&${t.capacityMeshNodeId}`;c.push({x:n.x,y:n.y,label:`z:${o}\no:${s}`}),t.portPoints.forEach(t=>{if(t.portPointId&&e!==t&&e.connectionName===t.connectionName){const e=d.get(t.portPointId);h.push({points:[n,e],strokeColor:"#fff822c9"})}})})});for(const t of s){const e=o.get(t);e&&h.push({points:[{x:e.x1,y:e.y1},{x:e.x2,y:e.y2}],strokeColor:"orange",strokeWidth:.01})}if(i){const t=o.get(i);t&&(h.push({points:[{x:t.x1,y:t.y1},{x:t.x2,y:t.y2}],strokeColor:"red",strokeWidth:.03}),c.push({x:t.center.x,y:t.center.y,label:t.ownerPairKey}))}for(const t of o.values())h.push({points:[{x:t.x1,y:t.y1},{x:t.x2,y:t.y2}],strokeColor:"#33b5ff80",strokeWidth:.006});return{rects:a,lines:h,points:c}})({obstacles:this.input.obstacles,nodeWithPortPoints:this.input.nodeWithPortPoints,mapOfOwnerPairToPortPoints:this.mapOfOwnerPairToPortPoints,mapOfOwnerPairToSharedEdge:this.mapOfOwnerPairToSharedEdge,ownerPairsToProcess:this.ownerPairsToProcess,currentOwnerPairBeingProcessed:this.currentOwnerPairBeingProcessed,mapOfNodeIdToBounds:this.mapOfNodeIdToBounds})}},hi=class extends y{getSolverName(){return"TraceWidthSolver"}hdRoutes;hdRoutesWithWidths=[];nominalTraceWidth;minTraceWidth;obstacleMargin;TRACE_WIDTH_SCHEDULE;connectionNominalTraceWidthMap;unprocessedRoutes=[];processedRoutes=[];currentTrace=null;cursorPosition=null;currentTraceSegmentIndex=0;currentTraceSegmentT=0;currentScheduleIndex=0;currentTargetWidth=0;hasInsufficientClearance=!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.obstacleMargin=t.obstacleMargin??.15,this.nominalTraceWidth=0,this.TRACE_WIDTH_SCHEDULE=[],this.unprocessedRoutes=[...this.hdRoutes],this.connMap=t.connMap,this.colorMap=t.colorMap;const e=t.layerCount;this.obstacles=us(t.obstacles??[],e),this.connectionNominalTraceWidthMap=new Map;for(const e of t.connection)void 0!==e.nominalTraceWidth&&this.connectionNominalTraceWidthMap.set(e.name,e.nominalTraceWidth);this.obstacles.length>0&&(this.obstacleSHI=new ss("flatbush",this.obstacles)),this.hdRouteSHI=new ds(this.hdRoutes)}getNominalTraceWidthForRoute(t){const e=this.connectionNominalTraceWidthMap.get(t.connectionName);return void 0!==e?e:t.rootConnectionName?this.connectionNominalTraceWidthMap.get(t.rootConnectionName):void 0}_step(){if(!this.currentTrace){const t=this.unprocessedRoutes.shift();if(!t)return this.hdRoutesWithWidths=this.processedRoutes,void(this.solved=!0);const e=this.getNominalTraceWidthForRoute(t);if(void 0===e)return this.processedRoutes.push({...t}),void(this.currentTrace=null);this.currentTrace=t,this.nominalTraceWidth=e;const n=(this.nominalTraceWidth+this.minTraceWidth)/2;return this.TRACE_WIDTH_SCHEDULE=[this.nominalTraceWidth,n],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())}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],o=t[this.currentTraceSegmentIndex+1];if(n.insideJumperPad&&o.insideJumperPad){this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0;continue}const s=o.x-n.x,i=o.y-n.y,r=Math.sqrt(s*s+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+s*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),o=Math.sqrt((t.center.x-e.end.x)**2+(t.center.y-e.end.y)**2),s=Math.max(t.width,t.height)/2+.01;if(n<s||o<s)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 o=1/0;if(this.lastCollidingObstacles=[],this.lastCollidingRoutes=[],this.obstacleSHI){const s=this.obstacleSHI.searchArea(t.x,t.y,n,n);for(const n of s){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 s=!1;if(this.connMap)for(const t of n.connectedTo)if(this.connMap.areIdsConnected(e,t)){s=!0;break}if(s)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<o&&(o=l)}}const s=this.hdRouteSHI.getConflictingRoutesNearPoint({x:t.x,y:t.y,z:t.z},n);for(const{conflictingRoute:t,distance:n}of s){const s=t.rootConnectionName??t.connectionName;if(s===e)continue;if(this.connMap?.areIdsConnected(e,s))continue;const i=n-(t.traceThickness??.15)/2;i<this.currentTargetWidth/2+this.obstacleMargin&&this.lastCollidingRoutes.push(t),i<o&&(o=i)}return this.lastClearance=o,o}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 o=e.has(n.obstacleId),s=n.zLayers?.includes(0),i=n.zLayers?.includes(1);let r;r=o?"rgba(255, 0, 0, 0.6)":s&&i?"rgba(128, 0, 128, 0.15)":s?"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:o?"red":void 0,label:o?`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,o=e.traceThickness===this.TRACE_WIDTH_SCHEDULE[1],s=n?"green":o?"yellow":"orange";for(let n=0;n<e.route.length-1;n++){const o=e.route[n],i=e.route[n+1];o.insideJumperPad&&i.insideJumperPad||o.z===i.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:i.x,y:i.y}],strokeColor:s,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=Qe(e.jumpers,{color:s,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],o=this.currentTrace.route[e+1];n.insideJumperPad&&o.insideJumperPad||n.z===o.z&&t.lines.push({points:[{x:n.x,y:n.y},{x:o.x,y:o.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 o=n.has(e.connectionName);for(let n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:o?"rgba(255, 0, 0, 0.8)":"rgba(128, 128, 128, 0.3)",strokeWidth:e.traceThickness??this.minTraceWidth,label:o?`COLLIDING: ${e.connectionName}`:e.connectionName})}}return t}getHdRoutesWithWidths(){return this.hdRoutesWithWidths}};function di(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var li=class extends y{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.srj=t,this.opts={...e},this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth;const n=this.opts;if(this.effort=n.effort??1,void 0===n.capacityDepth){const e=t.bounds.maxX-t.bounds.minX,o=t.bounds.maxY-t.bounds.minY,s=Math.max(e,o),i=n.targetMinCapacity??.5;n.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===n.cacheProvider?ut():null===n.cacheProvider?null:n.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getSolverName(){return"AutoroutingPipelineSolver2_PortPointPathing"}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;colorMap;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;uniformPortDistributionSolver;traceWidthSolver;viaDiameter;minTraceWidth;effort;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;inputNodeWithPortPoints=[];cacheProvider=null;pipelineDef=[di("netToPointPairsSolver",vn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),di("nodeSolver",es,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),di("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),di("availableSegmentPointSolver",Rs,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),di("portPointPathingSolver",Qs,t=>{this.inputNodeWithPortPoints=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}));const e=new Map(this.inputNodeWithPortPoints.map(t=>[t.capacityMeshNodeId,t])),n=t.availableSegmentPointSolver;for(const t of n.sharedEdgeSegments)for(const n of t.portPoints){const[t,o]=n.nodeIds,s={portPointId:n.segmentPortPointId,x:n.x,y:n.y,z:n.availableZ[0]??0,connectionNodeIds:[t,o],distToCentermostPortOnZ:n.distToCentermostPortOnZ},i=e.get(t);i&&i.portPoints.push(s)}return[{simpleRouteJson:t.srjWithPointPairs,inputNodes:this.inputNodeWithPortPoints,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}}]}),di("multiSectionPortPointOptimizer",qs,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}]}),di("uniformPortDistributionSolver",ci,t=>[{nodeWithPortPoints:t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],inputNodesWithPortPoints:this.inputNodeWithPortPoints,minTraceWidth:t.minTraceWidth,obstacles:t.srj.obstacles,layerCount:t.srj.layerCount}]),di("highDensityRouteSolver",Ye,t=>[{nodePortPoints:t.uniformPortDistributionSolver?.getOutput()??t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),di("highDensityStitchSolver",rn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),di("traceSimplificationSolver",Ts,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}]),di("traceWidthSolver",hi,t=>[{hdRoutes:t.traceSimplificationSolver.simplifiedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,minTraceWidth:t.minTraceWidth,connection:t.srj.connections,layerCount:t.srj.layerCount}])];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(),o=this.singleLayerNodeMerger?.visualize(),s=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.uniformPortDistributionSolver?.visualize(),l=this.highDensityRouteSolver?.visualize(),u=this.highDensityStitchSolver?.visualize(),p=this.traceSimplificationSolver?.visualize(),m=this.srj.outline,f=[];if(f.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),m&&m.length>=2){const t=m.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),f.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const y={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:f},x=[y,t,e,n,o,s,i,r,a,c,h,d,l?g(y,l):null,u,p,this.solved?g(y,an(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...x)}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.traceWidthSolver?.getHdRoutesWithWidths()??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 o=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,s=e.filter(t=>t.connectionName===n.name);for(let e=0;e<s.length;e++){const i=s[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??n.rootConnectionName??n.name,route:Ve(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},ui=li,pi=class{constructor(t){this.targets=t,this.buckets=new Map;for(let e=0;e<t.length;e++){const n=t[e],o=Math.floor(n.bounds.minX/this.CELL_SIZE)*this.CELL_SIZE,s=Math.floor(n.bounds.minY/this.CELL_SIZE)*this.CELL_SIZE,i=n.bounds.maxX,r=n.bounds.maxY;for(let t=o;t<=i;t+=this.CELL_SIZE)for(let o=s;o<=r;o+=this.CELL_SIZE){const s=this.getBucketKey(t,o),i=this.buckets.get(s);i?i.push([n,e]):this.buckets.set(s,[[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,o){const s=[],i=new Set,r=Math.floor((t-n/2)/this.CELL_SIZE)*this.CELL_SIZE,a=Math.floor((e-o/2)/this.CELL_SIZE)*this.CELL_SIZE,c=t+n/2,h=e+o/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),o=this.buckets.get(n)||[];for(const t of o)i.has(t[1])||(i.add(t[1]),s.push(t[0]))}return s}},mi=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;const n={x:(t.bounds.minX+t.bounds.maxX)/2,y:(t.bounds.minY+t.bounds.maxY)/2},o={width:t.bounds.maxX-t.bounds.minX,height:t.bounds.maxY-t.bounds.minY},s=Math.max(o.width,o.height);this.unfinishedNodes=[{capacityMeshNodeId:this.getNextNodeId(),center:n,width:s,height:s,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.obstacleZLayersByObstacle=new WeakMap;const i=us(this.srj.obstacles,this.layerCount);for(const[t,e]of this.srj.obstacles.entries())this.obstacleZLayersByObstacle.set(e,i[t].zLayers);this.obstacleTree=new ss("flatbush",this.srj.obstacles),this.targets=this.computeTargets(),this.targetTree=new pi(this.targets)}getSolverName(){return"CapacityMeshNodeSolver"}unfinishedNodes;finishedNodes;nodeToXYOverlappingObstaclesMap;layerCount;outlinePolygon;MAX_DEPTH=4;targets;targetTree;obstacleTree;obstacleZLayersByObstacle;computeTargets(){const t=[];for(const e of this.srj.connections)for(const n of e.pointsToConnect){const o=Je(n),s=this.obstacleTree.searchArea(n.x,n.y,.01,.01).filter(t=>{const e=this.getObstacleZLayers(t);return!(!e||0===e.length)&&e.some(t=>o.some(e=>t===Be(e,this.layerCount)))});let i={minX:n.x-.005,minY:n.y-.005,maxX:n.x+.005,maxY:n.y+.005};s.length>0&&(i={minX:Math.min(...s.map(t=>t.center.x-t.width/2)),minY:Math.min(...s.map(t=>t.center.y-t.height/2)),maxX:Math.max(...s.map(t=>t.center.x+t.width/2)),maxY:Math.max(...s.map(t=>t.center.y+t.height/2))});const r={...n,connectionName:e.name,availableZ:o.map(t=>Be(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=[],o=this.getNodeBounds(t),s=o.minX,i=o.maxX,r=o.minY,a=o.maxY,c=t._parent?this.getXYOverlappingObstacles(t._parent):this.srj.obstacles;for(const t of c){const e=t.center.x-t.width/2,o=t.center.x+t.width/2,c=t.center.y-t.height/2,h=t.center.y+t.height/2;i>=e&&s<=o&&a>=c&&r<=h?n.push(t):(s>=e&&i<=o&&r>=c&&a<=h||e>=s&&o<=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 o of e)t.availableZ.some(t=>this.getObstacleZLayers(o).includes(t))&&n.push(o);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,o=t.center.x+t.width/2,s=t.center.y-t.height/2,i=t.center.y+t.height/2;if(n.minX>=e&&n.maxX<=o&&n.minY>=s&&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},o=[{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 s of o){const o={capacityMeshNodeId:this.getNextNodeId(),center:s,width:n.width,height:n.height,layer:t.layer,availableZ:t.availableZ,_depth:(t._depth??0)+1,_parent:t};o._containsObstacle=this.doesNodeOverlapObstacle(o);const i=this.getTargetIfNodeContainsTarget(o);i&&(o._targetConnectionName=i.connectionName,o.availableZ=i.availableZ,o._containsTarget=!0),o._containsObstacle&&(o._completelyInsideObstacle=this.isNodeCompletelyInsideObstacle(o)),o._completelyInsideObstacle&&!o._containsTarget||e.push(o)}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=[],o=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t);e?o.push(t):e||t._containsObstacle?!e&&t._containsTarget&&n.push(t):n.push(t)}this.unfinishedNodes.push(...o),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){const n=this.getObstacleZLayers(e);t.rects.push({center:e.center,width:e.width,height:e.height,fill:1===n.length&&n.includes(1)?"rgba(0,0,255,0.3)":"rgba(255,0,0,0.3)",stroke:"red",label:["obstacle",`z: ${n.join(",")}`].join("\n")})}const e=[...this.finishedNodes,...this.unfinishedNodes];for(const n of e){const e=Math.min(...n.availableZ),o=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:o?"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: ${We(n).toFixed(2)}`].join("\n")})}return t.rects.sort((t,e)=>t.center.y-e.center.y),this.srj.connections.forEach((e,n)=>{const o=ot[n%ot.length];for(const s of e.pointsToConnect){const e=Je(s);t.points.push({x:s.x,y:s.y,label:`conn-${n} (${e.join(",")})`,color:o})}}),t}getObstacleZLayers(t){return this.obstacleZLayersByObstacle.get(t)??[]}},fi=class extends mi{constructor(t,e={}){super(t,e),this.srj=t,this.opts=e,this.VIA_DIAMETER=t.minViaDiameter??this.VIA_DIAMETER}getSolverName(){return"CapacityMeshNodeSolver2_NodeUnderObstacle"}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,o=t.center.x+t.width/2,s=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(o,t.center.x+t.width/2),c=Math.max(s,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},o=this.getXYZOverlappingObstacles(n);n._containsObstacle=o.length>0||this.isNodePartiallyOutsideBounds(n);const s=this.getTargetIfNodeContainsTarget(n);return s&&(n._targetConnectionName=s.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 o of n){const n=this.createChildNodeAtPosition(t,{center:{...t.center},width:t.width,height:t.height,availableZ:o,_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},o=[{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 s of o){const o=this.createChildNodeAtPosition(t,{center:s,width:n.width,height:n.height,availableZ:t.availableZ});this.isNodeCompletelyOutsideBounds(o)||e.push(o)}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=[],o=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),s=t.availableZ.length>1&&!e&&(t._containsObstacle||t.width<this.VIA_DIAMETER+this.OBSTACLE_MARGIN);if(e)o.push(t);else if(e||this.shouldFilterNodeForObstacle(t)||s)if(!e&&t._containsTarget)if(s){const e=this.getZSubdivisionChildNodes(t);n.push(...e.filter(t=>t._containsTarget||!this.shouldFilterNodeForObstacle(t)))}else n.push(t);else s&&n.push(...this.getZSubdivisionChildNodes(t).filter(t=>!this.shouldFilterNodeForObstacle(t)));else n.push(t)}this.unfinishedNodes.push(...o),this.finishedNodes.push(...n)}},gi=class extends y{getSolverName(){return"CapacityEdgeToPortSegmentSolver"}nodes;edges;capacityPaths;nodeMap;nodeEdgeMap;unprocessedNodeIds;nodePortSegments;colorMap;constructor({nodes:t,edges:e,capacityPaths:n,colorMap:o}){super(),this.nodes=t,this.edges=e,this.nodeMap=new Map(t.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Es(e),this.capacityPaths=n,this.colorMap=o??{},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 o=n.nodeIds.indexOf(t);-1!==o&&e.push({path:n,indexOfNodeInPath:o})}const n=this.nodeMap.get(t),o=[];for(const{path:s,indexOfNodeInPath:i}of e){const e=s.nodeIds[i-1],r=s.nodeIds[i+1];for(const i of[e,r]){const e=this.nodeMap.get(i);if(!e)continue;const r=yi(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:[s.connectionName],rootConnectionNames:s.rootConnectionName?[s.rootConnectionName]:void 0,availableZ:a};o.push(c)}}const s=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 o=!1;for(let n=0;n<e.length;n++){const s=e[n],i=vi(s.start,t.start)&&vi(s.end,t.end)||vi(s.start,t.end)&&vi(s.end,t.start),r=Pi(s.availableZ,t.availableZ);if(i&&r){const e=new Set(s.connectionNames);t.connectionNames.forEach(t=>e.add(t)),s.connectionNames=Array.from(e);const n=new Set(s.rootConnectionNames||[]);t.rootConnectionNames?.forEach(t=>n.add(t)),s.rootConnectionNames=Array.from(n),o=!0;break}}o||e.push(t)}return e}(o);this.nodePortSegments.set(t,s)}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 o=0;o<e.connectionNames.length;o++){const s={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+s.x,y:i.y+s.y};s.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[o]],.6)})}})}),t}};function yi(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)},o={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<o.end-o.start){const t=(n.start+n.end)/2;return{start:{x:t,y:o.start},end:{x:t,y:o.end}}}{const t=(o.start+o.end)/2;return{start:{x:n.start,y:t},end:{x:n.end,y:t}}}}var xi=1e-9;function vi(t,e){return Math.abs(t.x-e.x)<xi&&Math.abs(t.y-e.y)<xi}function Pi(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 Si=class extends y{getSolverName(){return"CapacitySegmentToPointSolver"}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 o=[...n.connectionNames].sort(),s=n.end.x-n.start.x,i=n.end.y-n.start.y,r=o.length,a=[];for(let t=1;t<=r;t++){const e=t/(r+1);a.push({x:n.start.x+s*e,y:n.start.y+i*e,z:n.availableZ[0]})}n.assignedPoints=o.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,o=this.nodeMap[n];t.has(n)||t.set(n,{capacityMeshNodeId:n,portPoints:[],center:o.center,width:o.width,height:o.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 o=n.assignedPoints[e],s={x:o.point.x,y:o.point.y},i={x:o.point.x+.05*o.point.z,y:o.point.y+.05*o.point.z};0!==o.point.z&&t.lines.push({points:[s,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}-${o.connectionName}`,`z: ${n.availableZ.join(",")}`,`nodePortSegmentId: ${n.nodePortSegmentId}`].join("\n"),color:this.colorMap[o.connectionName],step:4})}}const e=[],n={};for(const t of this.solvedSegments){const e=t.capacityMeshNodeId;n[e]||(n[e]={});for(const o of t.assignedPoints)n[e][o.connectionName]||(n[e][o.connectionName]=[]),n[e][o.connectionName].push({x:o.point.x,y:o.point.y})}for(const t in n)for(const o in n[t]){const s=n[t][o];s.length>1&&e.push({points:s,step:4,strokeDash:"5 5",strokeColor:this.colorMap[o]||"#000"})}return t.lines.push(...e),t}};function Mi(t){const{nodeId:e,nodeIdToSegmentIds:n,segmentIdToNodeIds:o,hops:s}=t;if(0===s)return[e];const i=new Set([e]),r=[{nodeId:e,remainingHops:s}];for(;r.length>0;){const{nodeId:t,remainingHops:e}=r.shift();if(0===e)continue;const s=n.get(t)||[];for(const t of s){const n=o.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 bi=t=>Array.from(t.entries()).map(([t,{x:e,y:n,z:o}])=>`${t}(${e?.toFixed(3)??""},${n?.toFixed(3)??""},${o??""})`).sort().join("&"),Ni=(t,e,n,o)=>{const s=Math.min(t,e),i=Math.max(t,e),r=Math.min(n,o);return s<=Math.max(n,o)&&i>=r},Ii=(t,e,n,o)=>{const s=[],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]),o=i.get(t[1]);e.z!==o.z&&s.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(o?.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(!Ni(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?s.push({type:"same_layer_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,crossingLine1:a,crossingLine2:c,probabilityOfFailure:0}):h.z===d.z&&l.z!==u.z?s.push({type:"single_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,sameLayerCrossingLine:a,transitionCrossingLine:c,probabilityOfFailure:0}):h.z!==d.z&&l.z===u.z?s.push({type:"single_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,sameLayerCrossingLine:c,transitionCrossingLine:a,probabilityOfFailure:0}):h.z!==d.z&&l.z!==u.z&&s.push({type:"double_transition_crossing",segmentPoints:[a,c],capacityMeshNodeId:n,crossingLine1:a,crossingLine2:c,probabilityOfFailure:0}))}}return s},Ci=(t,e,n)=>{if("change_layer"===e.type)for(const n of e.segmentPointIds){const o=t.get(n)||{};t.set(n,{...o,z:e.newZ})}else if("swap_position_on_segment"===e.type){const[o,s]=e.segmentPointIds,i=n(o),r=n(s),a=t.get(o)||{},c=t.get(s)||{};t.set(o,{...a,x:r.x,y:r.y}),t.set(s,{...c,x:i.x,y:i.y})}else if("combined"===e.type)for(const o of e.operations)Ci(t,o,n)},_i=(t,e)=>{const n=new Map,o=new Map,s=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)o.set(t,[...o.get(t)??[],c.segmentPointId]);s.set(a.nodePortSegmentId,[...s.get(a.nodePortSegmentId)??[],c.segmentPointId]),i.push(c)}return{segmentPointMap:n,nodeToSegmentPointMap:o,segmentToSegmentPointMap:s}},Ti=class extends y{getSolverName(){return"UnravelSectionSolver"}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,We(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=Mi({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS}),n=Mi({nodeId:this.rootNodeId,nodeIdToSegmentIds:this.nodeIdToSegmentIds,segmentIdToNodeIds:this.segmentIdToNodeIds,hops:this.MUTABLE_HOPS+1}),o=Array.from(new Set(n).difference(new Set(e)));t?.segmentPointMap||(t=_i(this.dedupedSegments,this.segmentIdToNodeIds));const s=new Map;for(const e of n)s.set(e,t.nodeToSegmentPointMap.get(e));const i=new Map;for(const e of n)for(const n of s.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 s.entries())for(let e=0;e<n.length;e++){const o=t.segmentPointMap.get(n[e]);for(let s=e+1;s<n.length;s++){const e=t.segmentPointMap.get(n[s]);e.segmentPointId!==o.segmentPointId&&(e.segmentId!==o.segmentId&&e.connectionName===o.connectionName&&(e.directlyConnectedSegmentPointIds.includes(o.segmentPointId)||(o.directlyConnectedSegmentPointIds.push(e.segmentPointId),e.directlyConnectedSegmentPointIds.push(o.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 o=c.get(n);if(o)for(const s of e.directlyConnectedSegmentPointIds){const i=t.segmentPointMap.get(s);i.segmentPointId!==e.segmentPointId&&(i.capacityMeshNodeIds.some(t=>t===n)&&(o.some(([t,n])=>t===e.segmentPointId&&n===i.segmentPointId||t===i.segmentPointId&&n===e.segmentPointId)||o.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)),o=this.dedupedSegmentMap.get(t.segmentId),s=o&&o.availableZ.length>1;(n||s)&&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:o,mutableSegmentIds:h,segmentPairsInNode:c,segmentPointMap:i,segmentPointsInNode:s,segmentPointsInSegment:a,originalPointMap:i,mutableSegmentPointIds:d,zLockedSegmentPointIds:l}}createInitialCandidate(){const t=new Map,e=Ii(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:bi(t),issues:Ii(this.unravelSection,this.nodeMap,t)}}get nextCandidate(){return this.candidates[0]??null}getPointInCandidate(t,e){const n=this.unravelSection.segmentPointMap.get(e),o=t.pointModifications.get(e);return{x:o?.x??n.x,y:o?.y??n.y,z:o?.z??n.z,segmentId:n.segmentId}}getConnectionSegmentPointIds(t){const e=[];for(const[n,o]of this.unravelSection.segmentPointMap.entries())o.connectionName===t&&e.push(n);return e}canConnectionUseLayer(t,e){for(const n of t){const t=this.unravelSection.segmentPointMap.get(n),o=this.dedupedSegmentMap.get(t.segmentId);if(!o||!o.availableZ.includes(e))return!1}return!0}getOperationsForIssue(t,e){const n=[];if("transition_via"===e.type){const[o,s]=e.segmentPoints,i=this.getPointInCandidate(t,o),r=this.getPointInCandidate(t,s),a=this.unravelSection.segmentPointMap.get(o),c=(this.unravelSection.segmentPointMap.get(s),this.dedupedSegmentMap.get(i.segmentId).availableZ),h=this.dedupedSegmentMap.get(r.segmentId).availableZ,d=this.unravelSection.zLockedSegmentPointIds.has(o),l=this.unravelSection.zLockedSegmentPointIds.has(s),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(o)&&!d&&c.includes(r.z)&&n.push({type:"change_layer",newZ:r.z,segmentPointIds:[o]}),this.unravelSection.mutableSegmentPointIds.has(s)&&!l&&h.includes(i.z)&&n.push({type:"change_layer",newZ:i.z,segmentPointIds:[s]})}if("same_layer_crossing"===e.type){const[t,o]=e.crossingLine1,[s,i]=e.crossingLine2,r=[],a=this.unravelSection.segmentPointMap.get(t),c=this.unravelSection.segmentPointMap.get(o),h=this.unravelSection.segmentPointMap.get(s),d=this.unravelSection.segmentPointMap.get(i),l=this.unravelSection.mutableSegmentPointIds.has(t),u=this.unravelSection.mutableSegmentPointIds.has(o),p=this.unravelSection.mutableSegmentPointIds.has(s),m=this.unravelSection.mutableSegmentPointIds.has(i),f=this.unravelSection.zLockedSegmentPointIds.has(t),g=this.unravelSection.zLockedSegmentPointIds.has(o),y=this.unravelSection.zLockedSegmentPointIds.has(s),x=this.unravelSection.zLockedSegmentPointIds.has(i);l&&p&&a.segmentId===h.segmentId&&r.push([t,s]),l&&m&&a.segmentId===d.segmentId&&r.push([t,i]),u&&p&&c.segmentId===h.segmentId&&r.push([o,s]),u&&m&&c.segmentId===d.segmentId&&r.push([o,i]);for(const[t,e]of r)n.push({type:"swap_position_on_segment",segmentPointIds:[t,e]});const v=this.getConnectionSegmentPointIds(a.connectionName),P=this.getConnectionSegmentPointIds(h.connectionName),S=new Set;for(const t of this.unravelSection.segmentPointMap.values()){const e=this.dedupedSegmentMap.get(t.segmentId);if(e)for(const t of e.availableZ)S.add(t)}for(const t of S)if(t!==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 S)if(t!==h.z&&this.canConnectionUseLayer(P,t)){const e=P.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 M=this.dedupedSegmentMap.get(a.segmentId),b=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([M,b],e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t,o]})}if(p&&m&&!y&&!x){const t=0===h.z?1:0;C([N,I],t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[s,i]})}if(l&&!f){const e=0===a.z?1:0;M.availableZ.includes(e)&&n.push({type:"change_layer",newZ:e,segmentPointIds:[t]})}if(u&&!g){const t=0===c.z?1:0;b.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[o]})}if(p&&!y){const t=0===h.z?1:0;N.availableZ.includes(t)&&n.push({type:"change_layer",newZ:t,segmentPointIds:[s]})}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:o,operation:s}=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:o}]of i){const s=this.nodeMap.get(t),i=Math.min(ws(s,n,e,o),.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);Ci(n,e,e=>this.getPointInCandidate(t,e));const o=bi(n);if(this.queuedOrExploredCandidatePointModificationHashes.has(o))return null;const s=Ii(this.unravelSection,this.nodeMap,n),i=t.operationsPerformed+1,r=this.computeG({issues:s,originalCandidate:t,operationsPerformed:i,operation:e});return{issues:s,g:r,h:0,f:r,pointModifications:n,candidateHash:o,operationsPerformed:i}}getNeighborOperationsForCandidate(t){return t.issues.flatMap(e=>this.getOperationsForIssue(t,e))}getNeighbors(t){const e=[],n=this.getNeighborOperationsForCandidate(t);for(const o of n){const n=this.getUnexploredNeighborByApplyingOperation(t,o);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,o]of this.unravelSection.segmentPointMap){const s={...o},i=e.pointModifications.get(t);i&&(void 0!==i.x&&(s.x=i.x),void 0!==i.y&&(s.y=i.y),void 0!==i.z&&(s.z=i.z)),n.set(t,s)}for(const[e,o]of n)t.points.push({x:o.x,y:o.y,label:`${e}\nSegment: ${o.segmentId} ${this.unravelSection.mutableSegmentIds.has(o.segmentId)?"MUTABLE":"IMMUTABLE"}\nLayer: ${o.z}`,color:this.colorMap[o.connectionName]||"#000"});const o=new Map;for(const t of this.unravelSection.allNodeIds)o.set(t,{numTransitionCrossings:0,numSameLayerCrossings:0,numEntryExitLayerChanges:0,estPf:0});for(const t of e.issues){const e=o.get(t.capacityMeshNodeId);"transition_via"===t.type?e.numTransitionCrossings++:"same_layer_crossing"===t.type?e.numSameLayerCrossings++:"double_transition_crossing"!==t.type&&"single_transition_crossing"!==t.type||e.numEntryExitLayerChanges++}for(const[t,e]of o.entries()){const n=this.nodeMap.get(t);e.estPf=ws(n,e.numSameLayerCrossings,e.numEntryExitLayerChanges,e.numTransitionCrossings)}for(const e of this.unravelSection.allNodeIds){const n=this.nodeMap.get(e),s=this.unravelSection.mutableNodeIds.includes(e),i=o.get(e),r=[`${e} (${s?"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:s?"green":"red",width:n.width/8,height:n.height/8})}for(const[e,o]of this.unravelSection.segmentPointsInSegment){if(o.length<=1)continue;const s=o.map(t=>n.get(t));for(let n=0;n<s.length-1;n++)t.lines.push({points:[{x:s[n].x,y:s[n].y},{x:s[n+1].x,y:s[n+1].y}],strokeColor:this.colorMap[e]||"#000"})}for(const[e,o]of n)for(const s of o.directlyConnectedSegmentPointIds)if(e<s){const e=n.get(s);if(!e)continue;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]||"#000"})}for(const o of e.issues){const e=this.nodeMap.get(o.capacityMeshNodeId);if("transition_via"===o.type)for(const s of o.segmentPoints){const o=n.get(s);t.circles.push({center:{x:o.x,y:o.y},radius:e.width/16,stroke:"#ff0000",fill:"rgba(255, 0, 0, 0.2)",label:`Via Issue\n${s}\nLayer: ${o.z}`})}else if("same_layer_crossing"===o.type)for(const[s,i]of[o.crossingLine1,o.crossingLine2]){const o=n.get(s),r=n.get(i);t.lines.push({points:[{x:o.x,y:o.y},{x:r.x,y:r.y}],strokeColor:"rgba(255,0,0,0.2)",strokeWidth:e.width/32})}}for(const[o,s]of e.pointModifications){const e=n.get(o),s=this.unravelSection.segmentPointMap.get(o);t.circles.push({center:{x:e.x,y:e.y},radius:.05,stroke:"#0000ff",fill:"rgba(0, 0, 255, 0.2)",label:`${o}\nOriginal: (${s.x.toFixed(2)}, ${s.y.toFixed(2)}, ${s.z})\nNew: (${e.x.toFixed(2)}, ${e.y.toFixed(2)}, ${e.z})`})}return t}};import Ei from"object-hash";var Ri=t=>(Math.round(20*t)/20).toFixed(2),wi=t=>(Math.round(1e3*t)/1e3).toFixed(3);pt();var Ai=class extends Ti{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=Sn(-t.center.x,-t.center.y),n=new Map,o=new Map,s=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),o=this.nodeMap.get(e);return n.center.x!==o.center.x?n.center.x-o.center.x:n.center.y-o.center.y});for(const t of l){const e="node_"+c++;n.set(t,e),o.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(!s.has(n)){const t="seg_"+h++;s.set(n,t),i.set(t,n)}}const p={};for(const[t,o]of n.entries()){const n=this.nodeMap.get(t),s=Pn(e,n.center);p[o]={width:n.width,height:n.height,availableZ:n.availableZ,center:{x:Ri(s.x),y:Ri(s.y)}}}const m={};for(const[t,n]of r.entries()){const o=this.unravelSection.segmentPointMap.get(t),s=Pn(e,{x:o.x,y:o.y});m[n]={x:Ri(s.x),y:Ri(s.y),z:o.z}}const f={hyperParameters:this.hyperParameters,normalizedNodes:p,normalizedSegmentPoints:m,mutableHops:this.MUTABLE_HOPS},g=`unravelsec:${Ei(f)}`,y={realToCacheTransform:e,nodeIdMap:n,segmentIdMap:s,segmentPointIdMap:r,reverseNodeIdMap:o,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,o=new Map;for(const[n,s]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!==s.dx){const t=parseFloat(s.dx);Number.isNaN(t)?console.warn(`Failed to parse cached dx coordinate: ${s.dx}`):r.x=i.x+t}if(void 0!==s.dy){const t=parseFloat(s.dy);Number.isNaN(t)?console.warn(`Failed to parse cached dy coordinate: ${s.dy}`):r.y=i.y+t}void 0!==s.dz&&(r.z=i.z+s.dz),Object.keys(r).length>0&&o.set(t,r)}const s=Ii(this.unravelSection,this.nodeMap,o);this.bestCandidate={pointModifications:o,issues:s,f:t.bestCandidateF,g:t.bestCandidateF,h:0,operationsPerformed:-1,candidateHash:bi(o)},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,o]of this.bestCandidate.pointModifications.entries()){const s=t.get(n);if(!s){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!==o.x){const t=o.x-i.x,e=wi(t);0!==parseFloat(e)&&(r.dx=e,a=!0)}if(void 0!==o.y){const t=o.y-i.y,e=wi(t);0!==parseFloat(e)&&(r.dy=e,a=!0)}if(void 0!==o.z){const t=o.z-i.z;0!==t&&(r.dz=t,a=!0)}a&&e.push([s,r])}const n={success:!0,bestCandidatePointModificationsDelta:e,bestCandidateF:this.bestCandidate.f};this.cacheProvider?.setCachedSolutionSync(this.cacheKey,n)}},Oi=class extends y{getSolverName(){return"UnravelMultiSectionSolver"}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:o}){super(),this.stats.successfulOptimizations=0,this.stats.failedOptimizations=0,this.stats.cacheHits=0,this.stats.cacheMisses=0,this.cacheProvider=o??null,this.MAX_ITERATIONS=1e6,this.dedupedSegments=(t=>{const e=[],n=new Map;let o=-1;for(const s of t){const t=`${s.start.x}-${s.start.y}-${s.end.x}-${s.end.y}-${s.availableZ.join(",")}`,i=n.get(t);i?s.nodePortSegmentId=i.nodePortSegmentId:(o++,s.nodePortSegmentId=`SEG${o}`,n.set(t,s),e.push(s))}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,We(e));const{segmentPointMap:s,nodeToSegmentPointMap:i,segmentToSegmentPointMap:r}=_i(this.dedupedSegments,this.segmentIdToNodeIds);this.segmentPointMap=s,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:o}=(t=>{let e=0,n=0,o=0;const s=new Map;for(const e of t)s.has(e.connectionName)||s.set(e.connectionName,[]),s.get(e.connectionName).push(e);const i=[],r=[];for(const[t,e]of s.entries()){if(e.length<2)continue;const o=e[0];for(let s=1;s<e.length;s++){const a=e[s],c={connectionName:t,z:o.z,points:[o,a]};o.z!==a.z?(n++,r.push({connectionName:t,points:[o,a]})):i.push(c)}}for(let t=0;t<i.length;t++)for(let n=t+1;n<i.length;n++){const o=i[t],s=i[n];o.z===s.z&&gt(o.points[0],o.points[1],s.points[0],s.points[1])&&e++}for(let t=0;t<r.length;t++)for(let e=t+1;e<r.length;e++){const n=r[t],s=r[e];gt(n.points[0],n.points[1],s.points[0],s.points[1])&&o++}for(let t=0;t<r.length;t++)for(let e=0;e<i.length;e++){const n=r[t],s=i[e];gt(n.points[0],n.points[1],s.points[0],s.points[1])&&o++}return{numSameLayerCrossings:e,numEntryExitLayerChanges:n,numTransitionCrossings:o}})((this.nodeToSegmentPointMap.get(t.capacityMeshNodeId)??[]).map(t=>this.segmentPointMap.get(t)));return ws(t,e,n,o)}_step(){if(this.iterations>=this.MAX_ITERATIONS-1)return void(this.solved=!0);if(!this.activeSubSolver){let t=null,e=0;for(const[n,o]of this.nodePfMap.entries()){o*(1-(this.attemptsToFixNode.get(n)??0)/this.MAX_NODE_ATTEMPTS)>e&&(e=o,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 Ai({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 o=this.nodePfMap.get(e)||0,s=Math.min(o,1),i=`rgb(${Math.floor(255*s)}, ${Math.floor(255*(1-s))}, 0)`;0===(this.attemptsToFixNode.get(e)??0)&&0===s||t.rects.push({center:n.center,label:[e,`${n.width.toFixed(2)}x${n.height.toFixed(2)}`,`Pf: ${o.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,o]of e.entries()){if(o.length<2)continue;const e=[...o].sort((t,e)=>t.x!==e.x?t.x-e.x:t.y-e.y);for(let o=0;o<e.length-1;o++)t.lines.push({points:[{x:e[o].x,y:e[o].y},{x:e[o+1].x,y:e[o+1].y}],strokeColor:this.colorMap[n]||"#000"})}const n=new Set,o=Array.from(this.segmentPointMap.values());for(let e=0;e<o.length;e++){const s=o[e];for(let i=e+1;i<o.length;i++){const e=o[i];if(s.connectionName!==e.connectionName||s.segmentId===e.segmentId)continue;if(s.capacityMeshNodeIds.some(t=>e.capacityMeshNodeIds.includes(t))){const o=`${s.segmentPointId}-${e.segmentPointId}`;if(n.has(o))continue;n.add(o);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]||"#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 o=t.get(n);o&&o.portPoints.push({x:e.x,y:e.y,z:e.z,connectionName:e.connectionName,rootConnectionName:e.rootConnectionName})}return Array.from(t.values())}},zi=(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")}},Di=class extends y{getSolverName(){return"CapacityPathingSolver"}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:o,MAX_ITERATIONS:s=1e6,hyperParameters:i={}}){super(),this.MAX_ITERATIONS=s,this.simpleRouteJson=t,this.nodes=e,this.edges=n,this.colorMap=o??{};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=Es(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 o of this.simpleRouteJson.connections){const s=[];for(const t of o.pointsToConnect){let n=this.nodes[0],o=Number.MAX_VALUE;for(const s of e){const e=Math.sqrt((s.center.x-t.x)**2+(s.center.y-t.y)**2);e<o&&(o=e,n=s)}s.push(n)}if(s.length<2)throw new Error(`Not enough nodes for connection "${o.name}", only ${s.length} found`);n.set(o.name,s.map(t=>t.capacityMeshNodeId)),t.push({connection:o,nodes:s,pathFound:!1,straightLineDistance:Pt(s[0].center,s[s.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,o=this.getTotalCapacity(t);if(1===t.availableZ.length&&!t._containsTarget&&n>0)return!1;let s=0;return t.availableZ.length>1&&1===e.availableZ.length&&(s+=.5),n+s<o}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=Pt(e.center,n.center)),this.candidates.sort((t,e)=>t.f-e.f);const o=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),!o)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(o.node,n))return t.path=this.getBacktrackedPath({prevCandidate:o,node:n,f:0,g:0,h:0}),this.reduceCapacityAlongPath(t),this.currentConnectionIndex++,this.candidates=null,void(this.visitedNodes=null);const s=this.getNeighboringNodes(o.node);for(const t of s){if(this.visitedNodes?.has(t.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(t,o.node))continue;const e=this.connectionsWithNodes[this.currentConnectionIndex].connection.name;if(t._containsObstacle&&!this.canTravelThroughObstacle(t,e))continue;const s=this.computeG(o,t,n),i=this.computeH(o,t,n),r=s+i*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(t.capacityMeshNodeId,{f:r,g:s,h:i});const a={prevCandidate:o,node:t,f:r,g:s,h:i};this.candidates.push(a)}this.visitedNodes.add(o.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 o=n.path.map(({center:{x:t,y:n},width:o,availableZ:s})=>({x:t+.005*o*(e%10+e%19),y:n+.005*o*(e%10+e%19),availableZ:s}));t.lines.push({points:o,strokeColor:this.colorMap[n.connection.name]});for(let e=0;e<o.length;e++){const s=o[e];t.points.push({x:s.x,y:s.y,label:[`conn: ${n.connection.name}`,`node: ${n.path[e].capacityMeshNodeId}`,`z: ${s.availableZ.join(",")}`].join("\n")})}}}for(const e of this.nodes){const n=this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,o=this.getTotalCapacity(e),s=this.debug_lastNodeCostMap.get(e.capacityMeshNodeId);t.rects.push({...zi(e,{rectMargin:.025,zOffset:.01}),label:[`${e.capacityMeshNodeId}`,`${n}/${o}`,`${e.width.toFixed(2)}x${e.height.toFixed(2)}`,`g: ${void 0!==s?.g?s.g.toFixed(2):"?"}`,`h: ${void 0!==s?.h?s.h.toFixed(2):"?"}`,`f: ${void 0!==s?.f?s.f.toFixed(2):"?"}`,`z: ${e.availableZ.join(", ")}`].join("\n"),stroke:n>o+.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,o]=e.connection.pointsToConnect;t.lines.push({points:[{x:n.x,y:n.y},{x:o.x,y:o.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,o)=>{const s=.5*(1-o/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-s)})})}return t}},Li=class extends Di{getSolverName(){return"CapacityPathingSolver5"}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 We(t,this.maxCapacityFactor)}getNodeCapacityPenalty(t){const e=t.width+t.height,n=.05,o=this.getTotalCapacity(t)-(this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0);if(o>2)return n;return(e-n)*Math.max(1,(2-o)/(e-n))+n}getDistanceBetweenNodes(t,e){const n=t.center.x-e.center.x,o=t.center.y-e.center.y;return Math.sqrt(n**2+o**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)}},Fi=class extends Li{getSolverName(){return"CapacityPathingGreedySolver"}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 Xi(t,e,n){const o=e.x-t.x,s=e.y-t.y;if(Math.abs(o)<1e-9&&Math.abs(s)<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(o)>1e-9){const e=(a-t.x)/o,n=(c-t.x)/o;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(s)>1e-9){const e=(h-t.y)/s,n=(d-t.y)/s;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+o*l,y:t.y+s*l}}function Yi(t,e){const n=t.center,o=e.center,s=Xi(n,o,t),i=Xi(o,n,e),r=o.x-n.x,a=o.y-n.y,c=Math.sqrt(r*r+a*a);let h=s,d=i;if(c>1e-9){const n={x:r/c,y:a/c},o=.3*t.width,l=.3*e.width;o+l<Math.sqrt((i.x-s.x)**2+(i.y-s.y)**2)?(h={x:s.x+n.x*o,y:s.y+n.y*o},d={x:i.x-n.x*l,y:i.y-n.y*l}):(h=s,d=i)}return{lineStart:h,lineEnd:d}}var $i=t=>{const{usedCapacity:e,totalCapacity:n,layerCount:o}=t;if(e<n)return 0;if(n<1&&e<=1)return 0;if(1===o&&e>1)return 1-.01**e;const s=e/n-1;return 1-Math.exp(-2*s)},Bi=(t,e,n)=>{if(n._containsTarget)return 0;if(t<=e)return 0;const o=1-$i({usedCapacity:t,totalCapacity:e,layerCount:n.availableZ.length});return o<=0?-1e9:Math.log(o)},ki=({totalNodeCapacityMap:t,usedNodeCapacityMap:e,nodeMap:n,sectionNodeIds:o})=>{let s=0;const i=o??new Set(e.keys());for(const o of i){if(!t.has(o))continue;const i=n.get(o);if(!i)continue;const r=t.get(o),a=e.get(o)??0;s+=Bi(a,r,i)}return s};function ji({sectionNodes:t,sectionEdges:e,sectionConnectionTerminals:n,completedPaths:o,nodeMap:s,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 o=e.availableZ??[],s=o.includes(0),i=o.includes(1);s&&i?(t=`rgba(128, 0, 128, ${c})`,n=`rgba(128, 0, 128, ${c})`):s?(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({...zi(e),fill:t,stroke:n,label:`${e.capacityMeshNodeId}\n(Section Node)\nZ: ${o.join(",")}`});const a=l.rects.length-1;if(h&&d){const t=h.get(e.capacityMeshNodeId)??0,n=d.get(e.capacityMeshNodeId)??0,o=n>0?(t/n*100).toFixed(1):"N/A",s=$i({usedCapacity:t,totalCapacity:n,layerCount:e.availableZ.length});l.rects[a].label+=`\n${t.toFixed(1)} / ${n.toFixed(1)}\n${o}% (Pf: ${(100*s).toFixed(1)}%)`,s>.2&&(l.rects[a].stroke=it("red",.7*(.8+c)))}}for(const t of e){const[e,n]=t.nodeIds,o=s.get(e),i=s.get(n);if(o&&i){const{lineStart:t,lineEnd:e}=Yi(o,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=s.get(t.startNodeId),o=s.get(t.endNodeId),r=i[t.connectionName]??"black",a=n&&u.has(n.capacityMeshNodeId),c=o&&u.has(o.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&&o){const e=.02*Math.min(o.width,o.height);m=e*h,f=e*h,l.points.push({x:o.center.x+m,y:o.center.y+f,color:r,label:`End: ${t.connectionName}\n(${t.endNodeId})`}),l.lines.push({points:[{x:o.center.x,y:o.center.y},{x:o.center.x+m,y:o.center.y+f}],strokeColor:"gray",strokeDash:"2 2"})}a&&c&&n&&o&&l.lines.push({points:[{x:n.center.x+d,y:n.center.y+p},{x:o.center.x+m,y:o.center.y+f}],strokeColor:r,strokeDash:"5 5"})}),o&&o.forEach((t,e)=>{if(t.path&&t.path.length>0){const n=i[t.connectionName]??"gray",o={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+o.x,y:e+o.y})),strokeColor:it(n,.2)})}}),l}var Wi=class extends y{getSolverName(){return"CapacityPathingSingleSectionSolver"}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??Es(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=ki({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:e}),t.hyperParameters?.SHUFFLE_SEED&&(this.sectionConnectionTerminals=Bt(this.sectionConnectionTerminals,t.hyperParameters?.SHUFFLE_SEED))}getTotalCapacity(t){return We(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,o=t.center.y-e.center.y;return Math.sqrt(n**2+o**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 o=this.totalNodeCapacityMap.get(t),s=this.usedNodeCapacityMap.get(t)??0,i=Bi(s,o,n);this.currentSectionScore-=i;const r=s+1;this.usedNodeCapacityMap.set(t,r);const a=Bi(r,o,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 o=this.candidates;if(0===o.length)return void this._handleCandidatesExhausted(t);o.sort((t,e)=>t.f-e.f);const s=o.shift();if(o.length>this.MAX_CANDIDATES_IN_MEMORY&&o.splice(this.MAX_CANDIDATES_IN_MEMORY,o.length-this.MAX_CANDIDATES_IN_MEMORY),this.visitedNodes.add(s.node.capacityMeshNodeId),s.node.capacityMeshNodeId===n.capacityMeshNodeId)return void this._handleGoalReached(s,t,n);const i=this.getNeighboringNodes(s.node);for(const e of i){if(this.queuedNodes?.has(e.capacityMeshNodeId))continue;if(!this.doesNodeHaveCapacityForTrace(e,s.node))continue;if(e._containsObstacle){const n=e.capacityMeshNodeId===t.startNodeId,o=e.capacityMeshNodeId===t.endNodeId;if(!n&&!o)continue}const i=this.computeG(s,e,n),r=this.computeH(s,e,n),a=i+r*this.GREEDY_MULTIPLIER;this.debug_lastNodeCostMap.set(e.capacityMeshNodeId,{f:a,g:i,h:r});const c={prevCandidate:s,node:e,f:a,g:i,h:r};this.queuedNodes?.add(e.capacityMeshNodeId),o.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=Pt(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 o=this.getBacktrackedPath(t);e.path=o,this.reduceCapacityAlongPath(o),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=ji({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 o=this.debug_lastNodeCostMap.get(t.capacityMeshNodeId),s=this.usedNodeCapacityMap.get(t.capacityMeshNodeId)??0,i=this.getTotalCapacity(t),r=`${s.toFixed(1)}/${i.toFixed(1)}`,a=o?`f:${o.f.toFixed(1)} g:${o.g.toFixed(1)} h:${o.h.toFixed(1)}`:"cost:?";e.rects[n].label=[t.capacityMeshNodeId,`Cap: ${r}`,a,`Z: ${t.availableZ.join(",")}`].join("\n"),s>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],o=n?.connectionName??"unknown",s=this.colorMap[o]??"purple";t.forEach((t,n)=>{const o=.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(s,1-o),strokeWidth:.05})})}return e}},Hi=t=>Array.from({length:t},(t,e)=>e),Ui=class extends Zt{getSolverName(){return"HyperCapacityPathingSingleSectionSolver"}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:Hi(2).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings6_for3",possibleValues:Hi(6).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings24_for4",possibleValues:Hi(24).map(t=>({SHUFFLE_SEED:t}))},{name:"orderings30",possibleValues:Hi(30).map(t=>({SHUFFLE_SEED:t}))}]}generateSolver(t){return new Wi({...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 Vi from"object-hash";var Zi=t=>Math.floor(10*t)/10,Gi=class extends Ui{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 o=n.pop();if(!o)break;e.push(o.capacityMeshNodeId);const s=this.constructorParams.nodeEdgeMap.get(o.capacityMeshNodeId).flatMap(t=>t.nodeIds).filter(e=>!t.has(e)).filter(t=>this.sectionNodeIdSet.has(t));for(const e of s){t.add(e);const s=this.constructorParams.nodeMap.get(e),i=We(s);n.push({ancestorCapacitySum:o.g,capacity:i,g:o.g+i,capacityMeshNodeId:e})}}return e}computeCacheKeyAndTransform(){const t=this._computeBfsOrderingOfNodesInSection(),e=new Map,n=new Map;t.forEach((t,o)=>{const s=`node${o}`;e.set(t,s),n.set(s,t)});const o={};for(const n of t){const t=e.get(n),s=this.constructorParams.nodeMap.get(n),i=We(s);o[t]=Zi(i).toFixed(1)}const s=new Set,i=[];for(const n of t){const t=e.get(n),o=this.constructorParams.nodeEdgeMap.get(n)??[];for(const r of o){const o=r.nodeIds.find(t=>t!==n);if(this.sectionNodeIdSet.has(o)){const n=[t,e.get(o)].sort(),r=`${n[0]}-${n[1]}`;s.has(r)||(i.push(n),s.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),o=e.get(t.endNodeId),[s,i]=[n,o].sort(),h=`${s}->${i}`,d=c.get(h)??0;c.set(h,d+1);const l=`${s}->${i}::${d}`;r[l]={start:s,end:i},a.set(l,t.connectionName)}const h=`capacitypathing:${Vi({node_capacity_map:o,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[o,s]of Object.entries(t.solutionPaths)){const t=n.get(o);if(!t){console.warn(`Could not find real connection name for ${o}`);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=s.map(n=>{const o=e.get(n);if(!o)throw new Error(`Could not map cache node ID ${n} to real node ID for connection ${t}`);const s=this.constructorParams.nodeMap.get(o);if(!s)throw new Error(`Could not find node with ID ${o} in nodeMap for connection ${t}`);return s});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:o}=this.cacheToSolveSpaceTransform,s=new Map;for(const[t,e]of n)s.set(e,t);const i=new Map;for(const[t,e]of o)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 o=i.get(t);if(!o){console.warn(`Could not find cache space connection ID for ${t} when saving to cache.`);continue}const r=n.map(e=>{const n=s.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[o]=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 ji({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"})}},Ji=class extends y{getSolverName(){return"CapacityPathingMultiSectionSolver"}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=Es(this.edges),this.colorMap=t.colorMap??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Es(this.edges),this.initialSolver=t.initialPathingSolver||new Fi({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,o=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,o),this.nodeOptimizationAttemptCountMap.set(t.capacityMeshNodeId,0)}this.connectionsWithNodes=this.initialSolver.connectionsWithNodes,this.stats.startingScore=ki({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 o of this.nodes){if(o._containsTarget)continue;const s=this.nodeOptimizationAttemptCountMap.get(o.capacityMeshNodeId),i=this.totalNodeCapacityMap.get(o.capacityMeshNodeId),r=$i({usedCapacity:this.usedNodeCapacityMap.get(o.capacityMeshNodeId)??0,totalCapacity:i,layerCount:o.availableZ.length}),a=r/(s+1);s<this.currentSchedule.MAX_ATTEMPTS_PER_NODE&&a>t&&r>this.currentSchedule.MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE&&(t=a,e=r,n=o.capacityMeshNodeId)}return n}getOverallScore(){let t=0;for(const e of this.nodes){if(e._containsTarget)continue;const n=this.totalNodeCapacityMap.get(e.capacityMeshNodeId),o=$i({usedCapacity:this.usedNodeCapacityMap.get(e.capacityMeshNodeId)??0,totalCapacity:n,layerCount:e.availableZ.length});o>t&&(t=o)}return{highestNodePf:t,score:ki({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:o,edges:s,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=>o.get(t)),l=s.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 o=t.path[e];if(a.has(o.capacityMeshNodeId)){n=o.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 Gi({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 o=new Set(e.map(t=>t.capacityMeshNodeId)),s=ki({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:this.usedNodeCapacityMap,nodeMap:this.nodeMap,sectionNodeIds:o}),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(o.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)o.has(e.capacityMeshNodeId)&&i.set(e.capacityMeshNodeId,(i.get(e.capacityMeshNodeId)??0)+1);ki({totalNodeCapacityMap:this.totalNodeCapacityMap,usedNodeCapacityMap:i,nodeMap:this.nodeMap,sectionNodeIds:o})>s?(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 o=e.path,s=n.path,i=o.findIndex(t=>t.capacityMeshNodeId===n.startNodeId),r=o.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=o.slice(0,a),d=o.slice(c+1);let l=s;if(s.length>0&&o[a]&&s[0].capacityMeshNodeId!==o[a].capacityMeshNodeId){if(s[s.length-1].capacityMeshNodeId!==o[a].capacityMeshNodeId){console.warn(`New section path for ${n.connectionName} doesn't align with original path boundaries. Skipping merge for this connection.`);continue}l=[...s].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,o=e>0?n/e:0;this.nodeCapacityPercentMap.set(t.capacityMeshNodeId,o)}}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 ji({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)"})}},qi=class extends y{getSolverName(){return"StrawSolver"}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 o=n.center.x-n.width/2,s=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,o),c=Math.min(t.maxX,s),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+=We(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:o,topSurroundingCapacity:s,bottomSurroundingCapacity:i}=this.getSurroundingCapacities(t);if(1*(n+o)>s+i){const n=Math.floor(t.height/this.strawSize),o=t.height/n;for(let s=0;s<n;s++){const n=t.center.y-t.height/2+s*o+o/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${s}`,center:{x:t.center.x,y:n},width:t.width,height:o,layer:t.layer,availableZ:[...t.availableZ],_depth:t._depth,_strawNode:!0,_strawParentCapacityMeshNodeId:t.capacityMeshNodeId})}}else{const n=Math.floor(t.width/this.strawSize),o=t.width/n;for(let s=0;s<n;s++){const n=t.center.x-t.width/2+s*o+o/2;e.push({capacityMeshNodeId:`${t.capacityMeshNodeId}_straw${s}`,center:{x:n,y:t.center.y},width:o,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}},Ki=.005,Qi=class extends y{getSolverName(){return"SingleLayerNodeMergerSolver"}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.availableZ.length>1?(this.newNodes.push(n),this.absorbedNodeIds.add(n.capacityMeshNodeId)):e.push([n,n.width*n.height]);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 o=0;o<=e;o++)n.push(new dn(t.filter(t=>t.availableZ[0]===o)));for(const e of t){const t=[],o=n[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const n of o)n._containsTarget&&n._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!n._containsTarget||n._targetConnectionName!==e._targetConnectionName)||n.capacityMeshNodeId!==e.capacityMeshNodeId&&cn(e,n)&&t.push(n);e._adjacentNodeIds=t.map(t=>t.capacityMeshNodeId)}}getAdjacentSameLayerUnprocessedNodes(t){return this.getAdjacentSameLayerUnprocessedNodes2(t)}getAdjacentSameLayerUnprocessedNodes2(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),o=this.nodeMap.get(e);return n.width*n.height-o.width*o.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 o=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===o.length)return void this.nextBatchNodeIds.push(t);const s=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=o.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:o}=i[0],r=i.every(e=>e.width===t&&e.height===o);Math.abs(i.reduce((t,e)=>t+e.height,0)-e.height)<Ki&&r&&(e.width+=t,e.center.x=e.center.x-t/2,s(i),n=!0)}const r=o.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:o}=r[0],i=r.every(e=>e.width===t&&e.height===o);Math.abs(r.reduce((t,e)=>t+e.height,0)-e.height)<Ki&&i&&(e.width+=t,e.center.x=e.center.x+t/2,s(r),n=!0)}const a=o.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:o}=a[0],i=a.every(e=>e.width===t&&e.height===o);Math.abs(a.reduce((t,e)=>t+e.width,0)-e.width)<Ki&&i&&(e.height+=o,e.center.y=e.center.y+o/2,s(a),n=!0)}const c=o.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:o}=c[0],i=c.every(e=>e.width===t&&e.height===o);Math.abs(c.reduce((t,e)=>t+e.width,0)-e.width)<Ki&&i&&(e.height+=o,e.center.y=e.center.y-o/2,s(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:"Same Layer Node Merger"};for(const e of this.newNodes)t.rects.push(zi(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let n;e&&(n=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const o of this.currentBatchNodeIds){const s=this.nodeMap.get(o);if(!this.absorbedNodeIds.has(o)&&s){const i=zi(s,{rectMargin:.01});o===e?i.stroke="rgba(0, 255, 0, 0.8)":n?.some(t=>t.capacityMeshNodeId===o)?i.stroke="rgba(128, 0, 128, 0.8)":i.stroke="rgba(255, 165, 0, 0.8)",i.layer=`z${s.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=zi(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}},tr=class extends y{getSolverName(){return"DeadEndSolver"}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,o=n?this.adjacencyList.get(n):void 0;if(!n||!o)return this.removedNodeIds.add(t),this.adjacencyList.delete(t),this.leavesIndex+=1,void(this.leavesIndex===this.leaves.length&&(this.solved=!0));o.delete(t),this.removedNodeIds.add(t),this.adjacencyList.delete(t),1!==o.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]),o=this.nodeMap.get(t.nodeIds[1]);if(n?.center&&o?.center){const s=Math.min(...n.availableZ),i=Math.min(...o.availableZ),r={x:n.center.x+s*n.width*.05,y:n.center.y-s*n.width*.05},a={x:o.center.x+i*o.width*.05,y:o.center.y-i*o.width*.05},c=Array.from(new Set([...n.availableZ,...o.availableZ])).sort();e.lines.push({layer:`z${c.join(",")}`,points:[r,a],strokeDash:n.availableZ.join(",")===o.availableZ.join(",")?void 0:"10 5",strokeColor:t.nodeIds.some(t=>this.removedNodeIds.has(t))?it("black",.9):void 0})}}return e}},er=class extends rn{getSolverName(){return"NoOffBoardMultipleHighDensityRouteStitchSolver"}constructor(t){super(t),this.unsolvedRoutes=[];const e=new Map;for(const n of t.hdRoutes){const t=e.get(n.connectionName)||[];t.push(n),e.set(n.connectionName,t)}for(const[n,o]of e.entries()){const e=t.connections.find(t=>t.name===n);if(!e)continue;const s={...e.pointsToConnect[0],z:Be(Ge(e.pointsToConnect[0]),t.layerCount)},i={...e.pointsToConnect[1],z:Be(Ge(e.pointsToConnect[1]),t.layerCount)};this.unsolvedRoutes.push({connectionName:n,hdRoutes:o,start:s,end:i})}for(const n of t.connections)e.has(n.name)||this.unsolvedRoutes.push({connectionName:n.name,hdRoutes:[],start:{...n.pointsToConnect[0],z:Be(Ge(n.pointsToConnect[0]),t.layerCount)},end:{...n.pointsToConnect[1],z:Be(Ge(n.pointsToConnect[1]),t.layerCount)}})}};function nr(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var or=class extends y{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.srj=t,this.opts={...e},this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth;const n=this.opts;if(void 0===n.capacityDepth){const e=t.bounds.maxX-t.bounds.minX,o=t.bounds.maxY-t.bounds.minY,s=Math.max(e,o),i=n.targetMinCapacity??.5;n.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===n.cacheProvider?ut():null===n.cacheProvider?null:n.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getSolverName(){return"AutoroutingPipeline1_OriginalUnravel"}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=[nr("netToPointPairsSolver",vn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),nr("nodeSolver",fi,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),nr("singleLayerNodeMerger",Qi,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),nr("strawSolver",qi,t=>[{nodes:t.singleLayerNodeMerger?.newNodes}],{onSolved:t=>{t.capacityNodes=t.strawSolver?.getResultNodes()}}),nr("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),nr("deadEndSolver",tr,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)))}}),nr("initialPathingSolver",Fi,t=>[{simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),nr("pathingOptimizer",Ji,t=>[{initialPathingSolver:t.initialPathingSolver,simpleRouteJson:t.srjWithPointPairs,nodes:t.capacityNodes,edges:t.capacityEdges||[],colorMap:t.colorMap,cacheProvider:t.cacheProvider,hyperParameters:{MAX_CAPACITY_FACTOR:1}}]),nr("edgeToPortSegmentSolver",gi,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.pathingOptimizer?.getCapacityPaths()||[],colorMap:t.colorMap}]),nr("segmentToPointSolver",Si,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),nr("unravelMultiSectionSolver",Oi,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),nr("highDensityRouteSolver",Ye,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),nr("highDensityStitchSolver",er,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),nr("traceSimplificationSolver",Ts,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}])];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(),o=this.singleLayerNodeMerger?.visualize(),s=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,o,s,i,r,a,c,h,d,l,u?g(x,u):null,p,m,this.solved?g(x,an(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 o=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,s=e.filter(t=>t.connectionName===n.name);for(let e=0;e<s.length;e++){const i=s[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??n.rootConnectionName??n.name,route:Ve(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},sr=.1,ir=.1;function rr(t,e,n,o,s,i){return(s-t)*(o-e)-(i-e)*(n-t)}function ar(t,e,n,o,s,i){return Math.min(t,n)<=s&&s<=Math.max(t,n)&&Math.min(e,o)<=i&&i<=Math.max(e,o)}function cr(t,e,n,o,s,i,r,a){const c=rr(s,i,r,a,t,e),h=rr(s,i,r,a,n,o),d=rr(t,e,n,o,s,i),l=rr(t,e,n,o,r,a);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)||(!(0!==c||!ar(s,i,r,a,t,e))||(!(0!==h||!ar(s,i,r,a,n,o))||(!(0!==d||!ar(t,e,n,o,s,i))||!(0!==l||!ar(t,e,n,o,r,a)))))}function hr(t,e,n,o,s,i){const r=s-n,a=i-o,c=t-n,h=e-o,d=r*r+a*a;if(0===d){return{x:n,y:o,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=o+l*a,m=t-u,f=e-p;return{x:u,y:p,distSq:m*m+f*f}}var dr=class extends y{getSolverName(){return"SimpleHighDensitySolver"}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:o=.6,pushMargin:s=.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=o,this.numMovablePoints=i,this.pushMargin=s,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,o=t.center.y-t.height/2,s=t.center.y+t.height/2;this.currentNodeBounds={minX:e,maxX:n,minY:o,maxY:s};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],o=e[e.length-1],s=n.z,i=o.x-n.x,r=o.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*ir,y:n.y+h*ir,z:s,rootConnectionName:n.rootConnectionName,connectionName:t}),this.numMovablePoints>=2&&d.push({x:o.x-c*ir,y:o.y-h*ir,z:s,rootConnectionName:n.rootConnectionName,connectionName:t}),this.numMovablePoints>=3&&d.push({x:n.x+i/2,y:n.y+r/2,z:s,rootConnectionName:n.rootConnectionName,connectionName:t}),this.routesInProgress.push({connectionName:t,rootConnectionName:n.rootConnectionName,startPoint:{x:n.x,y:n.y,z:s},endPoint:{x:o.x,y:o.y,z:s},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 o=.3+this.pushMargin,s=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}),s.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<o&&(e.fx+=sr*(o-r)),a<o&&(e.fx-=sr*(o-a)),h<o&&(e.fy+=sr*(o-h)),c<o&&(e.fy-=sr*(o-c));for(const t of this.routesInProgress){if(t.rootConnectionName===i.rootConnectionName)continue;const r=s.get(t);for(let t=0;t<r.length-1;t++){const s=r[t],a=r[t+1],c=hr(i.x,i.y,s.x,s.y,a.x,a.y),h=Math.sqrt(c.distSq);if(h>0&&h<2*o){const t=i.x-c.x,o=i.y-c.y,r=.002/c.distSq,h=r*t,d=r*o;e.fx+=h,e.fy+=d;const l=s.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=s.get(e);let o=-1;for(let e=0;e<n.length;e++)if(n[e].movablePoint===t){o=e;break}if(-1===o)return!1;const r=[];if(o>0){const e=i(n[o-1]);r.push({ax:e.x,ay:e.y,bx:t.x,by:t.y})}if(o<n.length-1){const e=i(n[o+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=s.get(t);for(let t=0;t<n.length-1;t++){const e=i(n[t]),o=i(n[t+1]);for(const t of r)if(cr(t.ax,t.ay,t.bx,t.by,e.x,e.y,o.x,o.y))return!0}}return!1};for(const o of e){const e=n.get(o);o.forceX=e.fx,o.forceY=e.fy;const s=o.x,i=o.y;o.x+=e.fx,o.y+=e.fy,o.x=Math.max(t.minX,Math.min(t.maxX,o.x)),o.y=Math.max(t.minY,Math.min(t.maxY,o.y)),r(o)&&(o.x=s,o.y=i)}}_finalizeRoutesForCurrentNode(){for(const t of this.routesInProgress){const{connectionName:e,rootConnectionName:n,startPoint:o,endPoint:s,movablePoints:i}=t,r=[{x:o.x,y:o.y,z:o.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:s.x,y:s.y,z:s.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,o]of n)o.length<2||t.lines.push({points:o.map(t=>({x:t.x,y:t.y})),label:e,strokeColor:"gray",strokeWidth:this.traceWidth})}for(const e of this.routes){const n=Xe(e.route,e.connectionName,this.colorMap[e.connectionName]);for(const o of n)t.lines.push({points:o.points,label:o.connectionName,strokeColor:0===o.z?o.color:it(o.color,.75),layer:`z${o.z}`,strokeWidth:e.traceThickness,strokeDash:0!==o.z?"10, 5":void 0});const o=e.route;for(let e=0;e<o.length;e++){const n=o[e],s=0===e,i=e===o.length-1,r=!s&&!i;let a;a=s?"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:o,movablePoints:s,connectionName:i}=e,r=this.colorMap[i]??"gray",a=[{x:n.x,y:n.y}];1===s.length?a.push({x:s[0].x,y:s[0].y}):2===s.length?(a.push({x:s[0].x,y:s[0].y}),a.push({x:s[1].x,y:s[1].y})):3===s.length&&(a.push({x:s[0].x,y:s[0].y}),a.push({x:s[2].x,y:s[2].y}),a.push({x:s[1].x,y:s[1].y})),a.push({x:o.x,y:o.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<s.length;e++){const n=s[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 o=5;t.lines.push({points:[{x:n.x,y:n.y},{x:n.x+n.forceX*o,y:n.y+n.forceY*o}],strokeColor:"red",strokeWidth:.02,label:`F${e+1}`});const s=.05,i=n.x+n.forceX*o,r=n.y+n.forceY*o,a=Math.atan2(n.forceY,n.forceX);t.lines.push({points:[{x:i,y:r},{x:i-s*Math.cos(a-Math.PI/6),y:r-s*Math.sin(a-Math.PI/6)}],strokeColor:"red",strokeWidth:.02}),t.lines.push({points:[{x:i,y:r},{x:i-s*Math.cos(a+Math.PI/6),y:r-s*Math.sin(a+Math.PI/6)}],strokeColor:"purple",strokeWidth:.02})}}}t.points.push({x:o.x,y:o.y,label:"end",color:"blue"})}return t}};function lr(t){const{pos:e,segments:n,dir:o,keepoutRadius:s}=t;let i=1/0;const r=s/4,a={x:e.x-o.x*r,y:e.y-o.y*r},c={x:e.x+o.x*r,y:e.y+o.y*r};for(const t of n){const e=wt(a,c,t.start,t.end);i=Math.min(i,e)}return i}function ur(t,e,n,o){const s=pr(n,o,t),i=pr(n,o,e),r=pr(t,e,n),a=pr(t,e,o);if((s>0&&i<0||s<0&&i>0)&&(r>0&&a<0||r<0&&a>0))return!0;const c=1e-4;return!!(Math.abs(s)<c&&mr(n,o,t))||(!!(Math.abs(i)<c&&mr(n,o,e))||(!!(Math.abs(r)<c&&mr(t,e,n))||!!(Math.abs(a)<c&&mr(t,e,o))))}function pr(t,e,n){return(n.x-t.x)*(e.y-t.y)-(e.x-t.x)*(n.y-t.y)}function mr(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 fr(t,e,n){for(const o of n)if(ur(t,e,o.start,o.end))return!1;return!0}var gr=1e-4;function yr(t){const e=t.width/2,n=t.height/2,o=t.center.x,s=t.center.y,i={x:o-e,y:s+n},r={x:o+e,y:s+n},a={x:o-e,y:s-n},c={x:o+e,y:s-n};return[{start:i,end:r},{start:r,end:c},{start:c,end:a},{start:a,end:i}]}function xr(t,e,n=.1){const o=e.x-t.x,s=e.y-t.y,i=Math.sqrt(o*o+s*s);if(0===i)return[];const r=-(s/i),a=o/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 vr(t,e,n){const o=Math.hypot(t.start.x-e.x,t.start.y-e.y),s=Math.hypot(t.end.x-e.x,t.end.y-e.y);if(o<=n||s<=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 Pr(t,e,n){if(!n||0===n.length)return!1;for(const o of n){const n=Math.abs(t.x-o.start.x)<gr&&Math.abs(t.y-o.start.y)<gr&&Math.abs(e.x-o.end.x)<gr&&Math.abs(e.y-o.end.y)<gr,s=Math.abs(t.x-o.end.x)<gr&&Math.abs(t.y-o.end.y)<gr&&Math.abs(e.x-o.start.x)<gr&&Math.abs(e.y-o.start.y)<gr;if(n||s)return!0}return!1}function Sr(t,e,n,o,s){const i=[];for(let r=0;r<t.length-1;r++){const a=t[r],c=t[r+1];Pr(a,c,s)||vr({start:a,end:c},n,o+e)&&i.push(...xr(a,c,e))}return i}var Mr=1e-4;function br(t,e,n,o){const s=e.x-t.x,i=e.y-t.y,r=o.x-n.x,a=o.y-n.y,c=s*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*s)/c,p=1e-6;return l>p&&l<.999999&&u>p&&u<.999999?{x:t.x+l*s,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)<Mr&&Math.abs(t.y-n.start.y)<Mr||Math.abs(t.x-n.end.x)<Mr&&Math.abs(t.y-n.end.y)<Mr)return!0;return!1}function Ir(t,e,n,o){if(!o||0===o.length)return!1;for(let s=e;s<=n;s++)if(s>=0&&s<t.length&&Nr(t[s],o))return!0;return!1}var Cr=1e-4,_r=class extends y{constructor(t){super(),this.input=t;const e=t.srj?.layerCount??2;this.input={...t,obstacles:us(t.obstacles,e)},this.MAX_ITERATIONS=1e6,this.originalHdRoutes=[...this.input.hdRoutes],this.hdRoutes=this.input.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 n=[...this.input.obstacles,...this.getJumperPadObstacles()];this.obstacleSHI=new ss("flatbush",n),this.boardOutlineRoutes=this.createBoardOutlineRoutes(),this.hdRouteSHI=new ds([...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 o=this.obstacleSHI.searchArea(t.x,t.y,.01,.01).filter(e=>e.zLayers?.includes(t.z));if(0===o.length)continue;const s=o[0];this.input.connMap.addConnections([[e,n,...s.offBoardConnectsTo??[],s.obstacleId,...s.connectedTo].filter(Boolean)])}}getSolverName(){return"TraceKeepoutSolver"}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 o of t.jumpers){let t=-1,s=1/0;for(let e=0;e<n.length-1;e++){const i=n[e],r=n[e+1],a=Math.sqrt((i.x-o.start.x)**2+(i.y-o.start.y)**2),c=Math.sqrt((r.x-o.end.x)**2+(r.y-o.end.y)**2),h=a+c,d=Math.sqrt((i.x-o.end.x)**2+(i.y-o.end.y)**2),l=Math.sqrt((r.x-o.start.x)**2+(r.y-o.start.y)**2),u=d+l,p=Math.min(h,u);(h<=u?a:d)<1&&(h<=u?c:l)<1&&p<s&&(s=p,t=e)}t>=0&&e.set(t,o)}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=Bt([...this.processedRoutes],this.currentScheduleIndex),this.smoothedCursorRoutes=[...this.unprocessedRoutes],this.processedRoutes=[],void(this.hdRouteSHI=new ds([...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:o,keepoutRadius:s}=t;if(0===o.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=lr({pos:e,segments:o,dir:h,keepoutRadius:s});if(u>=s)return null;for(let t=1;t<=20;t++){const n=t/20*s,i={x:e.x+d*n,y:e.y+l*n},r=lr({pos:i,segments:o,dir:h,keepoutRadius:s}),a={x:e.x-d*n,y:e.y-l*n},c=lr({pos:a,segments:o,dir:h,keepoutRadius:s}),u=r>=s&&fr(e,i,o),p=c>=s&&fr(e,a,o);if(u&&p)return r>=c?i:a;if(u)return i;if(p)return a}const p=s,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=lr({pos:i,segments:o,dir:h,keepoutRadius:s}),a=fr(e,i,o);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],o=m[t+1];if(n.clearance>=e.clearance&&n.clearance>=o.clearance){x=n;break}}let v=null;for(let t=y-1;t>0;t--){const e=m[t-1],n=m[t],o=m[t+1];if(n.clearance>=e.clearance&&n.clearance>=o.clearance){v=n;break}}let P=null,S=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],o=f[t+1];if(n.clearance>=e.clearance&&n.clearance>=o.clearance){P=n;break}}for(let t=e-1;t>0;t--){const e=f[t-1],n=f[t],o=f[t+1];if(n.clearance>=e.clearance&&n.clearance>=o.clearance){S=n;break}}}const M=[x,v,P,S,m.find(t=>0===t.index)].filter(t=>null!=t),b=new Set,N=M.filter(t=>{const e=`${t.pos.x.toFixed(6)},${t.pos.y.toFixed(6)}`;return!b.has(e)&&(b.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*s){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 o=this.recordedDrawPositions[this.recordedDrawPositions.length-1];if(o&&this.drawPosition){const t={x:o.x,y:o.y,z:o.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>Cr?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],o=t[this.currentTraceSegmentIndex+1],s=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=s<=i?n.start:n.end,a=s<=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:o.z,insideJumperPad:!0}),this.cursorPosition={x:a.x,y:a.y,z:o.z},this.currentTraceSegmentIndex++,this.currentTraceSegmentT=0,"jumper"}const o=t[this.currentTraceSegmentIndex],s=t[this.currentTraceSegmentIndex+1],i=s.x-o.x,r=s.y-o.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:o.x+i*this.currentTraceSegmentT,y:o.y+r*this.currentTraceSegmentT,z:o.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,o=[],s=this.obstacleSHI.searchArea(t.x,t.y,n,n).filter(e=>e.zLayers?.includes(t.z));for(const n of s){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 s=!1;for(const t of n.connectedTo)if(this.input.connMap.areIdsConnected(e,t)){s=!0;break}s||o.push(...yr(n))}const i=this.hdRouteSHI.getConflictingRoutesNearPoint({x:t.x,y:t.y,z:t.z},n);for(const{conflictingRoute:s}of i){const i=s.rootConnectionName??s.connectionName;if(i===e)continue;if(this.input.connMap.areIdsConnected(e,i))continue;const r=s.traceThickness??.15;o.push(...Sr(s.route,r,{x:t.x,y:t.y},n,s.jumpers))}return o}positionHasCollision(t,e=0){const n=this.getCollidingSegments(t);for(const o of n)if(vt(t,o.start,o.end)<=this.currentKeepoutRadius+e)return!0;return!1}segmentIntersectsOtherRoutes(t,e){if(!this.currentTrace)return!1;const n=this.currentTrace.rootConnectionName??this.currentTrace.connectionName,o=[...this.unprocessedRoutes,...this.smoothedCursorRoutes,...this.processedRoutes];for(const s of o){if((s.rootConnectionName??s.connectionName)!==n)for(let n=0;n<s.route.length-1;n++){const o=s.route[n],i=s.route[n+1];if((o.z===t.z||i.z===t.z)&&((!o.insideJumperPad||!i.insideJumperPad)&&gt({x:t.x,y:t.y},{x:e.x,y:e.y},{x:o.x,y:o.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],o=!0;for(;o;){o=!1;for(let t=0;t<n.length-1&&!o;t++){const s=n[t],i=n[t+1];if(s.z===i.z)for(let r=t+2;r<n.length-1&&!o;r++){if(r===t+1)continue;const a=n[r],c=n[r+1];if(a.z!==c.z||s.z!==a.z)continue;const h=br(s,i,a,c);if(h){if(Ir(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:s.z});for(let t=r+1;t<n.length;t++)i.push(n[t]);n=i,o=!0}}}}return n}(this.simplifyRoute(this.recordedDrawPositions,this.currentTrace.jumpers),this.currentTrace.jumpers),o={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(o),this.hdRouteSHI.removeRoute(this.currentTrace.connectionName),this.hdRouteSHI.addRoute(o),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)<Cr&&Math.abs(t.y-n.start.y)<Cr||Math.abs(t.x-n.end.x)<Cr&&Math.abs(t.y-n.end.y)<Cr)return!0;return!1}simplifyRoute(t,e){if(t.length<=2)return t;const n=[t[0]];for(let o=1;o<t.length-1;o++){const s=n[n.length-1],i=t[o],r=t[o+1];if(this.isJumperEndpoint(i,e)){n.push(i);continue}if(i.z!==s.z||i.z!==r.z){n.push(i);continue}const a=i.x-s.x,c=i.y-s.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 o;o=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 s=this.input.srj.layerCount??2;for(let e=0;e<o.length;e++){const n=o[e],i=o[(e+1)%o.length];for(let o=0;o<s;o++)t.push({connectionName:`__board_outline___${e}_z${o}`,traceThickness:.01,viaDiameter:0,route:[{x:n.x,y:n.y,z:o},{x:i.x,y:i.y,z:o}],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 o=e.route[n],s=e.route[n+1];o.z===s.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:s.x,y:s.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",o=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:o,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 o=e.zLayers?.includes(0),s=e.zLayers?.includes(1);o&&s?n="rgba(128, 0, 128, 0.2)":o?n="rgba(255, 0, 0, 0.2)":s&&(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 o;o=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<o.length;e++){const n=o[e],s=o[(e+1)%o.length];t.lines.push({points:[{x:n.x,y:n.y},{x:s.x,y:s.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",o=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 s=e.route[n],i=e.route[n+1],r=Math.abs(s.x-t.start.x)<Cr&&Math.abs(s.y-t.start.y)<Cr&&Math.abs(i.x-t.end.x)<Cr&&Math.abs(i.y-t.end.y)<Cr,a=Math.abs(s.x-t.end.x)<Cr&&Math.abs(s.y-t.end.y)<Cr&&Math.abs(i.x-t.start.x)<Cr&&Math.abs(i.y-t.start.y)<Cr;if(r||a){o.add(n);break}}for(let n=0;n<e.route.length-1;n++){const s=e.route[n],i=e.route[n+1];o.has(n)?t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:"rgba(128, 128, 128, 0.6)",strokeDash:"2 2",label:`${e.connectionName} (jumper segment - fixed)`}):s.z===i.z&&t.lines.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:0===s.z?"red":"blue",strokeWidth:e.traceThickness,label:`${e.connectionName} (z=${s.z})`})}for(const n of e.vias)t.circles.push({center:{x:n.x,y:n.y},radius:e.viaDiameter/2,fill:"rgba(255, 0, 255, 0.5)",label:`${e.connectionName} via`});if(e.jumpers&&e.jumpers.length>0){const o=Qe(e.jumpers,{color:n,label:e.connectionName});t.rects.push(...o.rects??[]),t.lines.push(...o.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],o=this.recordedDrawPositions[e+1];t.lines.push({points:[{x:n.x,y:n.y},{x:o.x,y:o.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,o=Math.sqrt(e*e+n*n),s=o>1e-4?{x:e/o,y:n/o}:{x:1,y:0},i=this.currentKeepoutRadius/4,r={x:this.cursorPosition.x-s.x*i,y:this.cursorPosition.y-s.y*i},a={x:this.cursorPosition.x+s.x*i,y:this.cursorPosition.y+s.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 o=e.route[n],s=e.route[n+1];o.z===s.z&&t.lines.push({points:[{x:o.x,y:o.y},{x:s.x,y:s.y}],strokeColor:"gray"})}return t}getRedrawnHdRoutes(){return this.redrawnHdRoutes}},Tr=class extends y{constructor(t){super(),this.input=t,this.unprocessedObstacles=us(this.input.srj.obstacles,this.input.srj.layerCount).filter(t=>t.offBoardConnectsTo&&t.offBoardConnectsTo.length>0),this.unprocessedObstacles.forEach((t,e)=>{t.obstacleId=t.obstacleId??`__obs${e}`}),this.offBoardConnMap=new on({}),this.offBoardConnMap.addConnections(this.unprocessedObstacles.filter(t=>t.offBoardConnectsTo?.length).map(t=>[t.obstacleId,...t.offBoardConnectsTo??[]])),this.nodeTree=new dn(this.input.capacityMeshNodes)}getSolverName(){return"RelateNodesToOffBoardConnectionsSolver"}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),o=n.map(t=>t.capacityMeshNodeId),s=this.nodesInNet.get(e)??[],i=[...s.map(t=>t.capacityMeshNodeId),...o];for(const t of s)t._offBoardConnectedCapacityMeshNodeIds=i;for(const t of n)t._offBoardConnectedCapacityMeshNodeIds=i,t._offBoardConnectionId=e;this.nodesInNet.set(e,[...s,...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 o of n)t.rects.push({center:o.center,width:o.width,height:o.height,fill:rt(e,.2),label:`OffBoardConn: ${e}`});for(const o of n)for(const s of n)o.capacityMeshNodeId!==s.capacityMeshNodeId&&t.lines.push({points:[o.center,s.center],strokeColor:rt(e,1)})}return t}},Er=({connMap:t,connectionsWithResults:e,inputNodes:n,obstacles:o})=>{const s=o.filter(t=>t.offBoardConnectsTo?.length);if(0===s.length)return;const i=new $e({});i.addConnections(s.map((t,e)=>[t.obstacleId??`__obs${e}`,...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,o=new Set;for(const t of n.path){const e=r.get(t.currentNodeId);if(e?._offBoardConnectionId&&o.add(e._offBoardConnectionId),t.throughNodeId){const e=r.get(t.throughNodeId);e?._offBoardConnectionId&&o.add(e._offBoardConnectionId)}}for(const n of o){const o=i.getIdsConnectedToNet(n);o?.length&&t.addConnections([[e,...o]])}}};function Rr(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var wr=class extends y{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.srj=t,this.opts={...e},this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth;const n=this.opts;if(this.effort=n.effort??1,void 0===n.capacityDepth){const e=t.bounds.maxX-t.bounds.minX,o=t.bounds.maxY-t.bounds.minY,s=Math.max(e,o),i=n.targetMinCapacity??.5;n.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===n.cacheProvider?ut():null===n.cacheProvider?null:n.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getSolverName(){return"AssignableAutoroutingPipeline2"}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=[Rr("netToPointPairsSolver",xn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),Rr("nodeSolver",es,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Rr("relateNodesToOffBoardConnections",Tr,t=>[{capacityMeshNodes:t.capacityNodes,srj:t.srj}],{onSolved:t=>{t.capacityNodes=t.relateNodesToOffBoardConnections?.getOutput().capacityNodes}}),Rr("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Rr("availableSegmentPointSolver",Rs,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),Rr("portPointPathingSolver",Qs,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])),o=t.availableSegmentPointSolver;for(const t of o.sharedEdgeSegments)for(const e of t.portPoints){const[o,s]=e.nodeIds,i={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[o,s],distToCentermostPortOnZ:e.distToCentermostPortOnZ,connectsToOffBoardNode:t.nodeIds.some(t=>n.get(t)?._offBoardConnectionId)},r=n.get(o);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&&Er({connMap:t.connMap,connectionsWithResults:e.connectionsWithResults,inputNodes:e.inputNodes,obstacles:t.srj.obstacles})}}),Rr("multiSectionPortPointOptimizer",qs,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}]}),Rr("highDensitySolver",dr,t=>[{nodePortPoints:t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth,connMap:t.connMap}]),Rr("highDensityStitchSolver",rn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensitySolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),Rr("traceSimplificationSolver",Ts,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}]),Rr("traceKeepoutSolver",_r,t=>[{hdRoutes:t.traceSimplificationSolver?.simplifiedHdRoutes??[],obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,srj:t.srj}]),Rr("traceWidthSolver",hi,t=>[{hdRoutes:t.traceKeepoutSolver?.redrawnHdRoutes??[],connection:t.srj.connections,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,minTraceWidth:t.minTraceWidth,obstacleMargin:t.srj.defaultObstacleMargin??.15,layerCount:t.srj.layerCount}])];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(),o=this.singleLayerNodeMerger?.visualize(),s=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,P=[];if(P.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]}),P.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const S={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:["obstacle",t.offBoardConnectsTo?`offboardConnections: ${t.offBoardConnectsTo?.join(", ")}`:"",t.layers?.join(", ")].filter(Boolean).join("\n")}))],lines:P},M=[S,t,e,n,o,s,i,r,a,c,h,d,l?g(S,l):null,u?g(S,u):null,p?g(S,p):null,m,f,y,x,this.solved?g(S,an(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...M)}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 o=t[n];if(e.push({points:o.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[o.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,o]of this.srj.obstacles.entries()){if(!o.offBoardConnectsTo?.length)continue;const s=o.obstacleId??`__obs${n}`,i=this.connMap.getNetConnectedToId(s);if(!i)continue;const r=this.connMap.getIdsConnectedToNet(i).find(t=>e.has(t));r&&(t[s]=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 o=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,s=e.filter(t=>t.connectionName===n.name);for(let e=0;e<s.length;e++){const i=s[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??n.rootConnectionName??n.name,route:Ve(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},Ar=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),o=this._rightChildIndex(e);let s=e;if(t<n&&this.heap[t].f<this.heap[s].f&&(s=t),o<n&&this.heap[o].f<this.heap[s].f&&(s=o),s===e)break;this._swap(e,s),e=s}}_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}},Or=class extends _n{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,...o}=e;n.set(e.regionId,{...o,ports:[],assignments:void 0})}for(const o of t.ports){const t=n.get(o.region1Id??o.region1?.regionId),s=n.get(o.region2Id??o.region2?.regionId),i={portId:o.portId,region1:t,region2:s,d:o.d};e.set(o.portId,i),t.ports.push(i),s.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 o of t)"startRegionId"in o?n.push({connectionId:o.connectionId,mutuallyConnectedNetworkId:o.connectionId,startRegion:e.regions.find(t=>t.regionId===o.startRegionId),endRegion:e.regions.find(t=>t.regionId===o.endRegionId)}):n.push(o);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 Ar,this.beginNewConnection()}getSolverName(){return"HyperGraphSolver"}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}computeRoutesToRip(t){const e=this.computeCrossingRoutes(t),n=this.computePortOverlapRoutes(t);return new Set([...e,...n])}computePortOverlapRoutes(t){const e=new Set;for(const n of t.path)n.port.assignment&&n.port.assignment.connection.mutuallyConnectedNetworkId!==t.connection.mutuallyConnectedNetworkId&&e.add(n.port.assignment.solvedRoute);return e}computeCrossingRoutes(t){const e=new Set;for(const n of t.path){if(!n.lastPort||!n.lastRegion)continue;const t=this.getRipsRequiredForPortUsage(n.lastRegion,n.lastPort,n.port);for(const n of t)e.add(n.solvedRoute)}return e}getNextCandidates(t){const e=t.nextRegion,n=t.port,o={};for(const s of e.ports){if(s===t.port)continue;const i=s.assignment&&s.assignment.connection.mutuallyConnectedNetworkId!==this.currentConnection.mutuallyConnectedNetworkId,r={port:s,hops:t.hops+1,parent:t,lastRegion:e,nextRegion:s.region1===e?s.region2:s.region1,lastPort:n,ripRequired:i};!this.rippingEnabled&&r.ripRequired||(o[r.nextRegion.regionId]??=[],o[r.nextRegion.regionId].push(r))}const s=[];for(const t in o){const e=o[t];s.push(...this.selectCandidatesForEnteringRegion(e))}for(const t of s)t.g=this.computeG(t),t.h=this.computeH(t),t.f=t.g+t.h*this.greedyMultiplier;return s}processSolvedRoute(t){const e={path:[],connection:this.currentConnection,requiredRip:!1};let n=t,o=!1;for(;n;)o||=!!n.ripRequired,e.path.unshift(n),n=n.parent;o&&(e.requiredRip=!0);const s=this.computeRoutesToRip(e);if(s.size>0){e.requiredRip=!0;for(const t of s)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 Ar,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)}};function zr(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 Dr(t){return void 0===t}function Lr(t,e=0){return{a:1,c:0,e:t,b:0,d:1,f:e}}function Fr(...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,o,...s]=t;return Fr(e(n,o),...s)}}}function Xr(...t){return Fr(...t)}var{cos:Yr,sin:$r,PI:Br}=Math;function kr(t,e,n){const o=Yr(t),s=$r(t),i={a:o,c:-s,e:0,b:s,d:o,f:0};return Dr(e)||Dr(n)?i:Fr([Lr(e,n),i,Lr(-e,-n)])}var{tan:jr}=Math,Wr=t=>{let e=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,o=Number.POSITIVE_INFINITY,s=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),o=Math.min(o,t.minY),s=Math.max(s,t.maxY)}return{minX:e,maxX:n,minY:o,maxY:s}},Hr=t=>({x:(t.minX+t.maxX)/2,y:(t.minY+t.maxY)/2}),Ur=(t,e)=>{const n=t.regions.map(t=>{const{bounds:n,center:o,...s}=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=>zr(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=zr(e,o);return{...t,ports:[],d:{...s,bounds:r,center:a}}}),o=new Map;for(let e=0;e<t.regions.length;e++)o.set(t.regions[e],n[e]);const s=t.ports.map(t=>{const n=zr(e,t.d),s=o.get(t.region1),i=o.get(t.region2),r={...t,region1:s,region2:i,d:n};return s.ports.push(r),i.ports.push(r),r}),i=t.jumperLocations?.map(t=>{const n=zr(e,t.center),s=t.padRegions.map(t=>o.get(t)),i=zr(e,{x:1,y:0}),r=zr(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:s}});return{regions:n,ports:s,...i&&{jumperLocations:i}}},Vr=(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 Zr(t,e,n,o,s){const i=n-e,r=s-o,a=1e-6;if(Math.abs(t.y-s)<a)return t.x-e;if(Math.abs(t.x-n)<a)return i+(s-t.y);if(Math.abs(t.y-o)<a)return i+r+(n-t.x);if(Math.abs(t.x-e)<a)return 2*i+r+(t.y-o);const c=Math.abs(t.y-s),h=Math.abs(t.x-n),d=Math.abs(t.y-o),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,s-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-o))}function Gr(t,e,n=1e-6){return Math.abs(t-e)<n}function Jr(t,e){const[n,o]=t[0]<t[1]?t:[t[1],t[0]],[s,i]=e[0]<e[1]?e:[e[1],e[0]];return!(Gr(n,s)||Gr(n,i)||Gr(o,s)||Gr(o,i))&&(n<s&&s<o&&o<i||s<n&&n<i&&i<o)}var qr=.034685181009478865,Kr=0,Qr=4.072520483177124,ta=0,ea=35.38577539020022,na=.5518001238069296,oa=class extends Or{getSolverName(){return"JumperGraphSolver"}UNIT_OF_COST="hops";portUsagePenalty=qr;portUsagePenaltySq=Kr;crossingPenalty=Qr;crossingPenaltySq=ta;ripCost=ea;baseMaxIterations=4e3;additionalMaxIterationsPerConnection=2e3;additionalMaxIterationsPerCrossing=2e3;constructor(t){super({greedyMultiplier:na,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;const e=function(t,e){if(e.length<2)return 0;let n=1/0,o=-1/0,s=1/0,i=-1/0;for(const e of t.regions){const t=e;t.d?.bounds?(n=Math.min(n,t.d.bounds.minX),o=Math.max(o,t.d.bounds.maxX),s=Math.min(s,t.d.bounds.minY),i=Math.max(i,t.d.bounds.maxY)):t.d?.center&&(n=Math.min(n,t.d.center.x),o=Math.max(o,t.d.center.x),s=Math.min(s,t.d.center.y),i=Math.max(i,t.d.center.y))}const r=new Map;for(const e of t.regions){const t=e;t.d?.center&&r.set(e.regionId,t.d.center)}const a=[];for(const t of e){let e,c;if("startRegion"in t&&t.startRegion){const n=t.startRegion,o=t.endRegion;e=n.d?.center,c=o.d?.center}else"startRegionId"in t&&(e=r.get(t.startRegionId),c=r.get(t.endRegionId));if(!e||!c)continue;const h=Zr(e,n,o,s,i),d=Zr(c,n,o,s,i);a.push([h,d])}let c=0;for(let t=0;t<a.length;t++)for(let e=t+1;e<a.length;e++)Jr(a[t],a[e])&&c++;return c}(this.graph,t.inputConnections);this.MAX_ITERATIONS=this.baseMaxIterations+t.inputConnections.length*this.additionalMaxIterationsPerConnection+e*this.additionalMaxIterationsPerCrossing,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:o}=n.shift();for(const s of e.ports){const i=s.region1===e?s.region2:s.region1;t.has(i.regionId)||(t.set(i.regionId,o+1),n.push({region:i,distance:o+1}))}}for(const n of this.graph.ports){n.distanceToEndMap||(n.distanceToEndMap={});const o=t.get(n.region1.regionId)??1/0,s=t.get(n.region2.regionId)??1/0;n.distanceToEndMap[e.regionId]=Math.min(o,s)}}}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 o=function(t,e,n){const{minX:o,maxX:s,minY:i,maxY:r}=t.d.bounds,a=[Zr(e.d,o,s,i,r),Zr(n.d,o,s,i,r)];let c=0;const h=t.assignments??[];for(const t of h)Jr(a,[Zr(t.regionPort1.d,o,s,i,r),Zr(t.regionPort2.d,o,s,i,r)])&&c++;return c}(t,e,n);return o*this.crossingPenalty+o*this.crossingPenaltySq}getRipsRequiredForPortUsage(t,e,n){const o=function(t,e,n){const{minX:o,maxX:s,minY:i,maxY:r}=t.d.bounds,a=[Zr(e.d,o,s,i,r),Zr(n.d,o,s,i,r)],c=[],h=t.assignments??[];for(const t of h)Jr(a,[Zr(t.regionPort1.d,o,s,i,r),Zr(t.regionPort2.d,o,s,i,r)])&&c.push(t);return c}(t,e,n);return o.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:[],polygons:[],coordinateSystem:"cartesian"};for(const e of t.regions){const{bounds:t,isPad:o,isThroughJumper:s,isConnectionRegion:i,polygon:r}=e.d,a=(t.minX+t.maxX)/2,c=(t.minY+t.maxY)/2,h=t.maxX-t.minX,d=t.maxY-t.minY;let l;if(l=i?"rgba(255, 100, 255, 0.6)":s?"rgba(100, 200, 100, 0.5)":o?"rgba(255, 200, 100, 0.5)":"rgba(200, 200, 255, 0.1)",r&&r.length>=3){const t=r;n.polygons.push({points:t,fill:l,stroke:"rgba(128, 128, 128, 0.5)",strokeWidth:.03})}else n.rects.push({center:{x:a,y:c},width:h-.1,height:d-.1,fill:l})}if(!e?.hidePortPoints)for(const e of t.ports){const t=e.region1.regionId.split(":").pop()??e.region1.regionId,o=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}-${o}`})}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},o={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},o],strokeColor:"rgba(100, 100, 100, 0.3)"})}if(e?.connections&&!e?.hideConnectionLines)for(const t of e.connections){const e=t.startRegion,o=t.endRegion,s={x:(e.d.bounds.minX+e.d.bounds.maxX)/2,y:(e.d.bounds.minY+e.d.bounds.maxY)/2},i={x:(o.d.bounds.minX+o.d.bounds.maxX)/2,y:(o.d.bounds.minY+o.d.bounds.maxY)/2},r=(s.x+i.x)/2,a=(s.y+i.y)/2;n.lines.push({points:[s,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=Vr(t.currentConnection.connectionId),o=t.currentConnection.startRegion,s=t.currentConnection.endRegion,i={x:(o.d.bounds.minX+o.d.bounds.maxX)/2,y:(o.d.bounds.minY+o.d.bounds.maxY)/2},r={x:(s.d.bounds.minX+s.d.bounds.maxX)/2,y:(s.d.bounds.minY+s.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=Vr(n.connection.connectionId),o=[];for(const t of n.path){const e=t.port;o.push({x:e.d.x,y:e.d.y})}o.length>0&&e.lines.push({points:o,strokeColor:t})}const n=t.candidateQueue.peekMany(10);for(let t=0;t<n.length;t++){const o=n[t],s=o.port,i=0===t;e.points.push({x:s.d.x,y:s.d.y,color:i?"green":"rgba(128, 128, 128, 0.25)",label:[o.port.portId,`g: ${o.g.toFixed(2)}`,`h: ${o.h.toFixed(2)}`,`f: ${o.f.toFixed(2)}`].join("\n")})}const o=n[0];if(!t.solved&&o&&t.currentConnection){const n=Vr(t.currentConnection.connectionId),s=[];let i=o;for(;i;){const t=i.port;s.unshift({x:t.d.x,y:t.d.y}),i=i.parent}s.length>1&&e.lines.push({points:s,strokeColor:n})}return e})(this)}},sa=(t,e,n,o)=>{const s={portId:t,region1:e,region2:n,d:{x:o.x,y:o.y}};return e.ports.push(s),n.ports.push(s),s},ia=(t,e,n)=>{const o=.2;return{regionId:t,ports:[],d:{bounds:{minX:e-o,maxX:e+o,minY:n-o,maxY:n+o},center:{x:e,y:n},isPad:!1,isConnectionRegion:!0}}},ra=(t,e,n,o)=>{for(const o of n){if(o.d.isPad||o.d.isThroughJumper)continue;const n=o.d.bounds;if(Math.abs(t-n.minX)<.01&&e>=n.minY&&e<=n.maxY)return{region:o,portPosition:{x:n.minX,y:e}};if(Math.abs(t-n.maxX)<.01&&e>=n.minY&&e<=n.maxY)return{region:o,portPosition:{x:n.maxX,y:e}};if(Math.abs(e-n.minY)<.01&&t>=n.minX&&t<=n.maxX)return{region:o,portPosition:{x:t,y:n.minY}};if(Math.abs(e-n.maxY)<.01&&t>=n.minX&&t<=n.maxX)return{region:o,portPosition:{x:t,y:n.maxY}}}let s=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-o.minX)<.01||Math.abs(n.maxX-o.maxX)<.01||Math.abs(n.minY-o.minY)<.01||Math.abs(n.maxY-o.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,s=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 s?{region:s,portPosition:r}:null},aa={padToPad:1.65,padLength:.8,padWidth:.95},ca=({cols:t,rows:e,marginX:n,marginY:o,innerColChannelPointCount:s=1,innerRowChannelPointCount:i=1,outerPaddingX:r=.5,outerPaddingY:a=.5,outerChannelXPoints:c,outerChannelYPoints:h,orientation:d="vertical"})=>{const l=c??Math.max(1,Math.floor(r/.4)),u=(h??Math.max(1,Math.floor(a/.4)),[]),p=[],{padToPad:m,padLength:f,padWidth:g}=aa,y=f/2,x=g/2,v=m+f+n,P=g+o,S=[],M=(t,e,n,o)=>({regionId:t,ports:[],d:{bounds:e,center:Hr(e),isPad:n,isThroughJumper:o}}),b=(t,e,n)=>{const o=e.d.bounds,s=n.d.bounds;let i,r;Math.abs(o.maxX-s.minX)<.001?(i=o.maxX,r=(Math.max(o.minY,s.minY)+Math.min(o.maxY,s.maxY))/2):Math.abs(o.minX-s.maxX)<.001?(i=o.minX,r=(Math.max(o.minY,s.minY)+Math.min(o.maxY,s.maxY))/2):Math.abs(o.maxY-s.minY)<.001?(i=(Math.max(o.minX,s.minX)+Math.min(o.maxX,s.maxX))/2,r=o.maxY):(i=(Math.max(o.minX,s.minX)+Math.min(o.maxX,s.maxX))/2,r=o.minY);const a={portId:t,region1:e,region2:n,d:{x:i,y:r}};return e.ports.push(a),n.ports.push(a),a},N=(t,e,n,o)=>{if(o<=0)return[];if(1===o)return[b(t,e,n)];const s=e.d.bounds,i=n.d.bounds,r=[];let a,c,h,d;Math.abs(s.maxX-i.minX)<.001?(a=!0,c=s.maxX,h=Math.max(s.minY,i.minY),d=Math.min(s.maxY,i.maxY)):Math.abs(s.minX-i.maxX)<.001?(a=!0,c=s.minX,h=Math.max(s.minY,i.minY),d=Math.min(s.maxY,i.maxY)):Math.abs(s.maxY-i.minY)<.001?(a=!1,c=s.maxY,h=Math.max(s.minX,i.minX),d=Math.min(s.maxX,i.maxX)):(a=!1,c=s.minY,h=Math.max(s.minX,i.minX),d=Math.min(s.maxX,i.maxX));for(let s=0;s<o;s++){const i=h+(s+.5)/o*(d-h),l={portId:`${t}:${s}`,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++){S[n]=[];for(let c=0;c<t;c++){const h=`cell_${n}_${c}`,d=c*v,f=-n*P,g=d-m/2,I=d+m/2,C={minX:g-y,maxX:g+y,minY:f-x,maxY:f+x},_={minX:I-y,maxX:I+y,minY:f-x,maxY:f+x},T={minX:C.maxX,maxX:_.minX,minY:f-x,maxY:f+x},E=.3,R={minX:g,maxX:I,minY:f-E/2,maxY:f+E/2},w=C.minX,A=_.maxX,O=C.minY,z=C.maxY,D=M(`${h}:leftPad`,C,!0),L=M(`${h}:rightPad`,_,!0),F=M(`${h}:underjumper`,T,!1),X=M(`${h}:throughjumper`,R,!1,!0);u.push(D,L,F,X);const Y=0===c,$=n===e-1,B=c===t-1;let k;if(B)k=A+r;else{k=(c+1)*v-m/2-y}let j=null;0===n&&(j=M(`${h}:T`,{minX:Y?w-r:w,maxX:k,minY:z,maxY:z+a},!1),u.push(j));let W=null;W=M(`${h}:B`,{minX:Y?w-r:w,maxX:k,minY:O-($?a:o),maxY:O},!1),u.push(W);let H=null;Y&&(H=M(`${h}:L`,{minX:w-r,maxX:w,minY:O,maxY:z},!1),u.push(H));const U=M(`${h}:R`,{minX:A,maxX:k,minY:O,maxY:z},!1);u.push(U),S[n][c]={leftPad:D,rightPad:L,underjumper:F,throughjumper:X,top:j,bottom:W,left:H,right:U},j&&(H&&p.push(...N(`${h}:T-L`,j,H,l)),p.push(...N(`${h}:T-R`,j,U,B?l:s)),p.push(b(`${h}:T-UJ`,j,F))),W&&(H&&p.push(...N(`${h}:B-L`,W,H,l)),p.push(...N(`${h}:B-R`,W,U,B?l:s)),p.push(b(`${h}:B-UJ`,W,F))),H&&p.push(b(`${h}:L-LP`,H,D)),p.push(b(`${h}:R-RP`,U,L));const V={portId:`${h}:TJ-LP`,region1:X,region2:D,d:{x:g,y:f}};X.ports.push(V),D.ports.push(V),p.push(V);const Z={portId:`${h}:TJ-RP`,region1:X,region2:L,d:{x:I,y:f}};if(X.ports.push(Z),L.ports.push(Z),p.push(Z),c>0){const t=S[n][c-1];p.push(b(`cell_${n}_${c-1}->cell_${n}_${c}:R-LP`,t.right,D)),j&&t.top&&p.push(...N(`cell_${n}_${c-1}->cell_${n}_${c}:T-T`,t.top,j,i)),W&&t.bottom&&p.push(...N(`cell_${n}_${c-1}->cell_${n}_${c}:B-B`,t.bottom,W,i))}if(n>0){const t=S[n-1][c];H&&p.push(...N(`cell_${n-1}_${c}->cell_${n}_${c}:B-L`,t.bottom,H,l)),p.push(b(`cell_${n-1}_${c}->cell_${n}_${c}:B-UJ`,t.bottom,F)),p.push(...N(`cell_${n-1}_${c}->cell_${n}_${c}:B-R`,t.bottom,U,B?l:s))}}}let I={regions:u,ports:p};if("horizontal"===d){const t=Wr(I.regions),e=Hr(t),n=Xr(Lr(e.x,e.y),kr(-Math.PI/2),Lr(-e.x,-e.y));I=Ur(I,n)}return I},ha={padWidth:.8,outerPadHeight:.5,innerPadHeight:.4,leftPadCenterX:-.9,rightPadCenterX:.9,row1CenterY:-1.2,row2CenterY:-.4,row3CenterY:.4,row4CenterY:1.2},da=Object.create,la=Object.defineProperty,ua=Object.getOwnPropertyDescriptor,pa=Object.getOwnPropertyNames,ma=Object.getPrototypeOf,fa=Object.prototype.hasOwnProperty,ga=(t,e)=>function(){return e||(0,t[pa(t)[0]])((e={exports:{}}).exports,e),e.exports},ya=(t,e,n)=>(n=null!=t?da(ma(t)):{},((t,e,n,o)=>{if(e&&"object"==typeof e||"function"==typeof e)for(let s of pa(e))fa.call(t,s)||s===n||la(t,s,{get:()=>e[s],enumerable:!(o=ua(e,s))||o.enumerable});return t})(!e&&t&&t.__esModule?n:la(n,"default",{value:t,enumerable:!0}),t)),xa=ga({"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)}}}),va=ga({"node_modules/kind-of/index.js"(t,e){var n=xa(),o=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=o.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"}}}),Pa=ga({"node_modules/rename-keys/index.js"(t,e){!function(){function t(t,e){if("function"!=typeof e)return t;var n={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&(n[e(o,t[o])||o]=t[o]);return n}void 0!==e&&e.exports?e.exports=t:"function"==typeof define&&define.amd?define([],function(){return t}):window.rename=t}()}}),Sa=ga({"node_modules/deep-rename-keys/index.js"(t,e){var n=va(),o=Pa();e.exports=function t(e,s){var i=n(e);if("object"!==i&&"array"!==i)throw new Error("expected an object");var r=[];for(var a in"object"===i&&(e=o(e,s),r={}),e)if(e.hasOwnProperty(a)){var c=e[a];"object"===n(c)||"array"===n(c)?r[a]=t(c,s):r[a]=c}return r}}}),Ma=ga({"node_modules/eventemitter3/index.js"(t,e){var n=Object.prototype.hasOwnProperty,o="~";function s(){}function i(t,e,n){this.fn=t,this.context=e,this.once=n||!1}function r(){this._events=new s,this._eventsCount=0}Object.create&&(s.prototype=Object.create(null),(new s).__proto__||(o=!1)),r.prototype.eventNames=function(){var t,e,s=[];if(0===this._eventsCount)return s;for(e in t=this._events)n.call(t,e)&&s.push(o?e.slice(1):e);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(t)):s},r.prototype.listeners=function(t,e){var n=o?o+t:t,s=this._events[n];if(e)return!!s;if(!s)return[];if(s.fn)return[s.fn];for(var i=0,r=s.length,a=new Array(r);i<r;i++)a[i]=s[i].fn;return a},r.prototype.emit=function(t,e,n,s,i,r){var a=o?o+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,s),!0;case 5:return d.fn.call(d.context,e,n,s,i),!0;case 6:return d.fn.call(d.context,e,n,s,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,s);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 s=new i(e,n||this),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.once=function(t,e,n){var s=new i(e,n||this,!0),r=o?o+t:t;return this._events[r]?this._events[r].fn?this._events[r]=[this._events[r],s]:this._events[r].push(s):(this._events[r]=s,this._eventsCount++),this},r.prototype.removeListener=function(t,e,n,i){var r=o?o+t:t;if(!this._events[r])return this;if(!e)return 0===--this._eventsCount?this._events=new s: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 s: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 s:delete this._events[r]}return this},r.prototype.removeAllListeners=function(t){var e;return t?(e=o?o+t:t,this._events[e]&&(0===--this._eventsCount?this._events=new s:delete this._events[e])):(this._events=new s,this._eventsCount=0),this},r.prototype.off=r.prototype.removeListener,r.prototype.addListener=r.prototype.on,r.prototype.setMaxListeners=function(){return this},r.prefixed=o,r.EventEmitter=r,void 0!==e&&(e.exports=r)}}),ba=ga({"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 o=Ma(),s=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 o,v=i.data,P="",S="",M="",b="",N="",I="",C=function(e,n){if("?"!==S[0]&&"!"!==S[0]){var o={type:e,value:n};t.debug&&console.log("emit:",o),x.emit("data",o)}};x.stateMachine=(n(y={},i.data,(n(e={},r.lt,function(){P.trim()&&C(a.text,P),S="",N=!1,v=i.tagBegin}),n(e,r.char,function(t){P+=t}),e)),n(y,i.cdata,n({},r.char,function(t){"]]>"===(P+=t).substr(-3)&&(C(a.text,P.slice(0,-3)),P="",v=i.data)})),n(y,i.tagBegin,(n(h={},r.space,s),n(h,r.char,function(t){S=t,v=i.tagName}),n(h,r.slash,function(){S="",N=!0}),h)),n(y,i.tagName,(n(d={},r.space,function(){N?v=i.tagEnd:(v=i.attributeNameStart,C(a.openTag,S))}),n(d,r.gt,function(){C(N?a.closeTag:a.openTag,S),P="",v=i.data}),n(d,r.slash,function(){v=i.tagEnd,C(a.openTag,S)}),n(d,r.char,function(t){"![CDATA["===(S+=t)&&(v=i.cdata,P="",S="")}),d)),n(y,i.tagEnd,(n(l={},r.gt,function(){C(a.closeTag,S),P="",v=i.data}),n(l,r.char,s),l)),n(y,i.attributeNameStart,(n(u={},r.char,function(t){M=t,v=i.attributeName}),n(u,r.gt,function(){P="",v=i.data}),n(u,r.space,s),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,M),v=i.attributeValueBegin}),n(p,r.gt,function(){b="",C(a.attributeName,M),C(a.attributeValue,b),P="",v=i.data}),n(p,r.slash,function(){N=!0,b="",C(a.attributeName,M),C(a.attributeValue,b),v=i.tagEnd}),n(p,r.char,function(t){M+=t}),p)),n(y,i.attributeNameEnd,(n(m={},r.space,s),n(m,r.equal,function(){C(a.attributeName,M),v=i.attributeValueBegin}),n(m,r.gt,function(){b="",C(a.attributeName,M),C(a.attributeValue,b),P="",v=i.data}),n(m,r.char,function(t){b="",C(a.attributeName,M),C(a.attributeValue,b),M=t,v=i.attributeName}),m)),n(y,i.attributeValueBegin,(n(f={},r.space,s),n(f,r.quote,function(t){I=t,b="",v=i.attributeValue}),n(f,r.gt,function(){C(a.attributeValue,b=""),P="",v=i.data}),n(f,r.char,function(t){I="",b=t,v=i.attributeValue}),f)),n(y,i.attributeValue,(n(g={},r.space,function(t){I?b+=t:(C(a.attributeValue,b),v=i.attributeNameStart)}),n(g,r.quote,function(t){I===t?(C(a.attributeValue,b),v=i.attributeNameStart):b+=t}),n(g,r.gt,function(t){I?b+=t:(C(a.attributeValue,b),P="",v=i.data)}),n(g,r.slash,function(t){I?b+=t:(C(a.attributeValue,b),N=!0,v=i.tagEnd)}),n(g,r.char,function(t){b+=t}),g)),y);var _=function(e){t.debug&&console.log(v,e);var n=x.stateMachine[v],o=n[function(t){return c[t]||r.char}(e)]||n[r.error]||n[r.char];o(e)};return x.write=function(t){for(var e=t.length,n=0;n<e;n++)_(t[n])},x}}}}),Na=ga({"node_modules/xml-reader/dist/reader.js"(t,e){var n=Ma(),o=ba(),s=o.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 s.openTag:if(null===c)(c=a).name=n.value;else{var o=r({name:n.value,parent:c});c.children.push(o),c=o}break;case s.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 s.text:c&&c.children.push(r({type:i.text,value:n.value,parent:t.parentNodes?c:null}));break;case s.attributeName:h=n.value,c.attributes[h]="";break;case s.attributeValue:c.attributes[h]=n.value}};return d.reset=function(){(e=o.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),o=void 0;return n.on("done",function(t){o=t}),n.parse(t),o},create:a,NodeType:i}}}),{cos:Ia,sin:Ca,PI:_a}=Math,{tan:Ta}=Math,Ea=(ya(Sa()),ya(Na()),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)",wa=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 Aa(t,e){const{minX:n,maxX:o,minY:s,maxY:i}=e,r=o-n,a=i-s,c=1e-6;return Math.abs(t.y-i)<c?t.x-n:Math.abs(t.x-o)<c?r+(i-t.y):Math.abs(t.y-s)<c?r+a+(o-t.x):Math.abs(t.x-n)<c?2*r+a+(t.y-s):0}function Oa(t,e){const{minX:n,maxX:o,minY:s,maxY:i}=e,r=1e-6,a=Math.abs(t.y-i)<r,c=Math.abs(t.y-s)<r,h=Math.abs(t.x-o)<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=(s+i)/2,u=(n+o)/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 za(t,e,n,o,s,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*s+g*r,c[y+1]=m*e+3*p*l*o+3*u*f*i+g*a}}function Da(t,e,n,o,s){const i=[];for(let r=0;r<=s;r++){const a=r/s,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*o.x,y:d*t.y+3*h*a*e.y+3*c*l*n.y+u*o.y})}return i}function La(t,e,n,o,s,i){const r=s-n,a=i-o,c=r*r+a*a;if(0===c){const s=t-n,i=e-o;return s*s+i*i}const h=Math.max(0,Math.min(1,((t-n)*r+(e-o)*a)/c)),d=t-(n+h*r),l=e-(o+h*a);return d*d+l*l}function Fa(t,e,n,o,s,i,r,a){const c=(r-s)*(e-i)-(a-i)*(t-s),h=(r-s)*(o-i)-(a-i)*(n-s),d=(n-t)*(i-e)-(o-e)*(s-t),l=(n-t)*(a-e)-(o-e)*(r-t);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)?0:Math.min(La(t,e,s,i,r,a),La(n,o,s,i,r,a),La(s,i,t,e,n,o),La(r,a,t,e,n,o))}function Xa(t,e,n,o,s,i,r,a){const c=(r-s)*(e-i)-(a-i)*(t-s),h=(r-s)*(o-i)-(a-i)*(n-s),d=(n-t)*(i-e)-(o-e)*(s-t),l=(n-t)*(a-e)-(o-e)*(r-t);return(c>0&&h<0||c<0&&h>0)&&(d>0&&l<0||d<0&&l>0)}function Ya(t,e,n,o,s){const i=t=>(t%s+s)%s,r=i(t),a=i(e),c=i(n),h=i(o),[d,l]=r<a?[r,a]:[a,r];return c>d&&c<l&&h>d&&h<l}function $a(t,e){let n=1/0,o=-1/0,s=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>o&&(o=e),a<s&&(s=a),a>i&&(i=a)}return{minX:n,maxX:o,minY:s,maxY:i}}var Ba=class extends Ea{constructor(t){super(),this.problem=t;for(const t of this.problem.obstacles)t.outerSegments=wa(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:o,minY:s,maxY:i}=t,r=o-n,a=i-s,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:Aa(e.start,t),t2:Aa(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;Ya(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:o,idx:s})=>{const i=Oa(e.start,t),c=Oa(e.end,t),d=Math.hypot(e.end.x-e.start.x,e.end.y-e.start.y),f=p[s]/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),P=Math.max(v,x),S=Math.max(v,x);return{waypointPair:e,ctrl1:{x:e.start.x+P*i.x,y:e.start.y+P*i.y},ctrl2:{x:e.end.x+S*c.x,y:e.end.y+S*c.y},networkId:e.networkId,t1:n,t2:o,perpDir1:i,perpDir2:c,d1:P,d2:S,containedBy:l[s],contains:u[s]}}),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];za(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]=$a(this.sampledPoints[t],6)}}updateSingleTraceSample(t){const e=this.traces[t];za(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]=$a(this.sampledPoints[t],6)}updateControlPointsFromDistances(t){const e=this.traces[t],{minX:n,maxX:o,minY:s,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-o)<r&&(a=Math.min(a,o)),Math.abs(l.y-s)<r&&(c=Math.max(c,s)),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-o)<r&&(h=Math.min(h,o)),Math.abs(u.y-s)<r&&(d=Math.max(d,s)),Math.abs(u.y-i)<r&&(d=Math.min(d,i)),a=Math.max(n,Math.min(o,a)),c=Math.max(s,Math.min(i,c)),h=Math.max(n,Math.min(o,h)),d=Math.max(s,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 o=this.traces[e],s=this.traces[n];if(o.networkId&&s.networkId&&o.networkId===s.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,o=t**2;let s=0;for(const[t,o]of this.collisionPairs){const i=this.sampledPoints[t],r=this.sampledPoints[o];for(let t=0;t<5;t++){const o=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=Fa(o,a,c,h,r[2*t],r[2*t+1],r[2*(t+1)],r[2*(t+1)+1]);if(i<n){s+=(e-Math.sqrt(i))**2,i<1e-18&&(s+=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=Fa(i[2*e],i[2*e+1],i[2*(e+1)],i[2*(e+1)+1],c,h,d,l);if(n<o){s+=(t-Math.sqrt(n))**2,n<1e-18&&(s+=20*o)}}}}return s}computeCostForTrace(t){const{preferredObstacleToTraceSpacing:e}=this.problem,n=this.effectiveTraceToTraceSpacing,o=n**2,s=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 s=this.traces[e];if(i.networkId&&s.networkId&&i.networkId===s.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],s=r[2*t+1],i=r[2*(t+1)],a=r[2*(t+1)+1];for(let t=0;t<5;t++){const r=Fa(e,s,i,a,d[2*t],d[2*t+1],d[2*(t+1)],d[2*(t+1)+1]);if(r<o){c+=(n-Math.sqrt(r))**2,r<1e-18&&(c+=20*o)}}}}for(let t=0;t<this.numObstacleSegments;t++){if(i.networkId&&this.obstacleNetworkIds[t]&&i.networkId===this.obstacleNetworkIds[t])continue;const n=4*t,o=this.obstacleSegments[n],h=this.obstacleSegments[n+1],d=this.obstacleSegments[n+2],l=this.obstacleSegments[n+3],u=Math.min(o,d),p=Math.max(o,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=Fa(r[2*t],r[2*t+1],r[2*(t+1)],r[2*(t+1)+1],o,h,d,l);if(n<s){c+=(e-Math.sqrt(n))**2,n<1e-18&&(c+=20*s)}}}return c}tracesIntersect(t,e){const n=this.traces[t],o=this.traces[e],s=15,i=new Float64Array(32),r=new Float64Array(32);za(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,s),za(o.waypointPair.start.x,o.waypointPair.start.y,o.ctrl1.x,o.ctrl1.y,o.ctrl2.x,o.ctrl2.y,o.waypointPair.end.x,o.waypointPair.end.y,r,s);for(let t=0;t<s;t++){const e=i[2*t],n=i[2*t+1],o=i[2*(t+1)],a=i[2*(t+1)+1];for(let t=0;t<s;t++){if(Xa(e,n,o,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 o=this.traces[e],s=this.traces[n];if(o.networkId&&s.networkId&&o.networkId===s.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:o,minY:s,maxY:i}=t,r=Math.min(o-n,i-s),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 o=this.traces[t],s=this.traces[n];if(!this.tracesIntersect(t,n))continue;let i,r;if(o.containedBy.includes(n))i=n,r=t;else if(s.containedBy.includes(t))i=t,r=n;else{(o.d1+o.d2)/2<(s.d1+s.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:o,maxY:s}=t,i=Math.min(n-e,s-o),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],o=e>100?2:1,s=[a*o,1.5*a*o,.5*a];for(const o of s){const s=e>100?[o,-o,2*o,2*-o,3*o,3*-o,2*r,2*-r]:[o,-o,2*o,2*-o];let i=this.computeCostForTrace(t),a=n.d1,d=n.d2;const l=n.d1,u=n.d2;for(const e of s){n.d1=Math.max(c,Math.min(h,l+e)),this.updateControlPointsFromDistances(t),this.updateSingleTraceSample(t);const o=this.computeCostForTrace(t);o<i&&(i=o,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 s=this.computeCostForTrace(t);s<i&&(i=s,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:Da(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)}},ka=class extends y{getSolverName(){return"JumperPrepatternSolver2_HyperGraph"}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 o=0;for(const s of Array.from(n))e[s]=t[o%t.length],o++;return e}_getPatternConfig(){return{cols:this.hyperParameters.COLS??1,rows:this.hyperParameters.ROWS??1}}_generate0603Grid(t,e,n){const o="horizontal"===e?t.rows:t.cols,s="horizontal"===e?t.cols:t.rows,i=n.maxX-n.minX,r=n.maxY-n.minY,a=.5,c=ca({cols:o,rows:s,marginX:a,marginY:a,innerColChannelPointCount:2,innerRowChannelPointCount:2,outerPaddingX:.1,outerPaddingY:.1,outerChannelXPoints:3,outerChannelYPoints:3}),h=Wr(c.regions),d=h.maxX-h.minX,l=h.maxY-h.minY,u=Math.max(.3,(i-d)/2+.1),p=Math.max(.3,(r-l)/2+.1),m=Math.max(3,Math.ceil(u/.5)),f=Math.max(3,Math.ceil(p/.5)),g=ca({cols:o,rows:s,marginX:a,marginY:a,innerColChannelPointCount:2,innerRowChannelPointCount:2,outerPaddingX:u,outerPaddingY:p,outerChannelXPoints:m,outerChannelYPoints:f}),y={regions:g.regions,ports:g.ports,jumperLocations:[]},x=Wr(y.regions),v=(x.minX+x.maxX)/2,P=(x.minY+x.maxY)/2,S=Sn((n.minX+n.maxX)/2-v,(n.minY+n.maxY)/2-P),M=Ur(y,S),b=[];for(const t of M.regions)t.d?.isPad&&b.push({center:t.d.center,orientation:e,padRegions:[t]});return M.jumperLocations=b,M}_initializeGraph(){const t=this.nodeWithPortPoints,e=this._getPatternConfig(),n=this.hyperParameters.ORIENTATION??"vertical",o=this.hyperParameters.JUMPER_TYPE??"1206x4",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};let i;if(this.graphBounds=s,"0603"===o){const t=this._generate0603Grid(e,n,s);if(!t)return this.error=`0603 grid (${e.cols}x${e.rows}) is too large to fit in node bounds`,this.failed=!0,!1;i=t}else i=(({cols:t,rows:e,marginX:n,marginY:o,innerColChannelPointCount:s=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=2})=>{const f=[],g=[],{padWidth:y,outerPadHeight:x,innerPadHeight:v,leftPadCenterX:P,rightPadCenterX:S,row1CenterY:M,row2CenterY:b,row3CenterY:N,row4CenterY:I}=ha,C=y/2,_=x/2,T=v/2,E=S-P+y,R=E+n,w=I-M+x,A=w+o;let O=a,z=c;if(p){const s=t*E+(t-1)*n,i=e*w+(e-1)*o;O=(("horizontal"===l?p.maxY-p.minY:p.maxX-p.minX)-s)/2,z=(("horizontal"===l?p.maxX-p.minX:p.maxY-p.minY)-i)/2}const D=h??Math.max(1,Math.floor(O/.4)),L=d??Math.max(1,Math.floor(z/.4)),F=[],X=[],Y=(t,e,n,o)=>({regionId:t,ports:[],d:{bounds:e,center:Hr(e),isPad:n,isThroughJumper:o}}),$=(t,e,n)=>{const o=e.d.bounds,s=n.d.bounds;let i,r;Math.abs(o.maxX-s.minX)<.001?(i=o.maxX,r=(Math.max(o.minY,s.minY)+Math.min(o.maxY,s.maxY))/2):Math.abs(o.minX-s.maxX)<.001?(i=o.minX,r=(Math.max(o.minY,s.minY)+Math.min(o.maxY,s.maxY))/2):Math.abs(o.maxY-s.minY)<.001?(i=(Math.max(o.minX,s.minX)+Math.min(o.maxX,s.maxX))/2,r=o.maxY):(i=(Math.max(o.minX,s.minX)+Math.min(o.maxX,s.maxX))/2,r=o.minY);const a={portId:t,region1:e,region2:n,d:{x:i,y:r}};return e.ports.push(a),n.ports.push(a),a},B=(t,e,n,o)=>{if(o<=0)return[];if(1===o)return[$(t,e,n)];const s=e.d.bounds,i=n.d.bounds,r=[];let a,c,h,d;Math.abs(s.maxX-i.minX)<.001?(a=!0,c=s.maxX,h=Math.max(s.minY,i.minY),d=Math.min(s.maxY,i.maxY)):Math.abs(s.minX-i.maxX)<.001?(a=!0,c=s.minX,h=Math.max(s.minY,i.minY),d=Math.min(s.maxY,i.maxY)):Math.abs(s.maxY-i.minY)<.001?(a=!1,c=s.maxY,h=Math.max(s.minX,i.minX),d=Math.min(s.maxX,i.maxX)):(a=!1,c=s.minY,h=Math.max(s.minX,i.minX),d=Math.min(s.maxX,i.maxX));for(let s=0;s<o;s++){const i=h+(s+.5)/o*(d-h),l={portId:`${t}:${s}`,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++){F[n]=[];for(let a=0;a<t;a++){const c=`cell_${n}_${a}`,h=a*R,d=-n*A,l=h+P,u=d+M,p=h+P,y=d+b,x=h+P,v=d+N,E=h+P,w=d+I,k=h+S,j=d+I,W=h+S,H=d+N,U=h+S,V=d+b,Z=h+S,G=d+M,J=(t,e,n)=>({minX:t-C,maxX:t+C,minY:e-n,maxY:e+n}),q=J(l,u,_),K=J(p,y,T),Q=J(x,v,T),tt=J(E,w,_),et=J(k,j,_),nt=J(W,H,T),ot=J(U,V,T),st=J(Z,G,_),it={minX:q.maxX,maxX:st.minX,minY:q.minY,maxY:tt.maxY},rt=.3,at={minX:l,maxX:Z,minY:u-rt/2,maxY:u+rt/2},ct={minX:p,maxX:U,minY:y-rt/2,maxY:y+rt/2},ht={minX:x,maxX:W,minY:v-rt/2,maxY:v+rt/2},dt={minX:E,maxX:k,minY:w-rt/2,maxY:w+rt/2},lt=q.minX,ut=st.maxX,pt=q.minY,mt=tt.maxY,ft=Y(`${c}:pad1`,q,!0),gt=Y(`${c}:pad2`,K,!0),yt=Y(`${c}:pad3`,Q,!0),xt=Y(`${c}:pad4`,tt,!0),vt=Y(`${c}:pad5`,et,!0),Pt=Y(`${c}:pad6`,nt,!0),St=Y(`${c}:pad7`,ot,!0),Mt=Y(`${c}:pad8`,st,!0),bt=Y(`${c}:underjumper`,it,!1),Nt=Y(`${c}:throughjumper1`,at,!1,!0),It=Y(`${c}:throughjumper2`,ct,!1,!0),Ct=Y(`${c}:throughjumper3`,ht,!1,!0),_t=Y(`${c}:throughjumper4`,dt,!1,!0);f.push(ft,gt,yt,xt,vt,Pt,St,Mt,bt,Nt,It,Ct,_t);const Tt=(l+Z)/2,Et=(u+w)/2;X.push({center:{x:Tt,y:Et},orientation:"vertical",padRegions:[ft,gt,yt,xt,vt,Pt,St,Mt]});let Rt=null,wt=null,At=null,Ot=null,zt=null,Dt=null;r&&(Rt=Y(`${c}:L-BP12`,{minX:q.minX,maxX:q.maxX,minY:q.maxY,maxY:K.minY},!1),wt=Y(`${c}:L-BP23`,{minX:K.minX,maxX:K.maxX,minY:K.maxY,maxY:Q.minY},!1),At=Y(`${c}:L-BP34`,{minX:Q.minX,maxX:Q.maxX,minY:Q.maxY,maxY:tt.minY},!1),Ot=Y(`${c}:R-BP87`,{minX:st.minX,maxX:st.maxX,minY:st.maxY,maxY:ot.minY},!1),zt=Y(`${c}:R-BP76`,{minX:ot.minX,maxX:ot.maxX,minY:ot.maxY,maxY:nt.minY},!1),Dt=Y(`${c}:R-BP65`,{minX:nt.minX,maxX:nt.maxX,minY:nt.maxY,maxY:et.minY},!1),f.push(Rt,wt,At,Ot,zt,Dt));const Lt=0===a,Ft=n===e-1,Xt=a===t-1;let Yt;Yt=Xt?ut+O:(a+1)*R+P-C;let $t=null;0===n&&($t=Y(`${c}:T`,{minX:Lt?lt-O:lt,maxX:Yt,minY:mt,maxY:mt+z},!1),f.push($t));let Bt=null;Bt=Y(`${c}:B`,{minX:Lt?lt-O:lt,maxX:Yt,minY:pt-(Ft?z:o),maxY:pt},!1),f.push(Bt);let kt=null;Lt&&(kt=Y(`${c}:L`,{minX:lt-O,maxX:lt,minY:pt,maxY:mt},!1),f.push(kt));const jt=Y(`${c}:R`,{minX:ut,maxX:Yt,minY:pt,maxY:mt},!1);if(f.push(jt),F[n][a]={pad1:ft,pad2:gt,pad3:yt,pad4:xt,pad5:vt,pad6:Pt,pad7:St,pad8:Mt,underjumper:bt,throughjumper1:Nt,throughjumper2:It,throughjumper3:Ct,throughjumper4:_t,top:$t,bottom:Bt,left:kt,right:jt,leftBP12:Rt,leftBP23:wt,leftBP34:At,rightBP87:Ot,rightBP76:zt,rightBP65:Dt},$t)if(kt&&g.push(...B(`${c}:T-L`,$t,kt,D)),g.push(...B(`${c}:T-R`,$t,jt,Xt?D:s)),g.push($(`${c}:T-P4`,$t,xt)),g.push($(`${c}:T-P5`,$t,vt)),r){const t=bt.d.bounds,e=(t.maxX-t.minX)/(m+1);for(let n=1;n<=m;n++){const o={portId:`${c}:T-UJ${n}`,region1:$t,region2:bt,d:{x:t.minX+e*n,y:t.maxY}};$t.ports.push(o),bt.ports.push(o),g.push(o)}}else g.push($(`${c}:T-UJ`,$t,bt));if(Bt)if(kt&&g.push(...B(`${c}:B-L`,Bt,kt,D)),g.push(...B(`${c}:B-R`,Bt,jt,Xt?D:s)),g.push($(`${c}:B-P1`,Bt,ft)),g.push($(`${c}:B-P8`,Bt,Mt)),r){const t=bt.d.bounds,e=(t.maxX-t.minX)/(m+1);for(let n=1;n<=m;n++){const o={portId:`${c}:B-UJ${n}`,region1:Bt,region2:bt,d:{x:t.minX+e*n,y:t.minY}};Bt.ports.push(o),bt.ports.push(o),g.push(o)}}else g.push($(`${c}:B-UJ`,Bt,bt));kt&&(g.push($(`${c}:L-P1`,kt,ft)),g.push($(`${c}:L-P2`,kt,gt)),g.push($(`${c}:L-P3`,kt,yt)),g.push($(`${c}:L-P4`,kt,xt))),g.push($(`${c}:R-P5`,jt,vt)),g.push($(`${c}:R-P6`,jt,Pt)),g.push($(`${c}:R-P7`,jt,St)),g.push($(`${c}:R-P8`,jt,Mt)),r&&(kt&&(g.push($(`${c}:L-BP12`,kt,Rt)),g.push($(`${c}:L-BP23`,kt,wt)),g.push($(`${c}:L-BP34`,kt,At))),g.push($(`${c}:UJ-LBP12`,Rt,bt)),g.push($(`${c}:UJ-LBP23`,wt,bt)),g.push($(`${c}:UJ-LBP34`,At,bt)),g.push($(`${c}:R-BP87`,jt,Ot)),g.push($(`${c}:R-BP76`,jt,zt)),g.push($(`${c}:R-BP65`,jt,Dt)),g.push($(`${c}:UJ-RBP87`,Ot,bt)),g.push($(`${c}:UJ-RBP76`,zt,bt)),g.push($(`${c}:UJ-RBP65`,Dt,bt)));const Wt={portId:`${c}:TJ1-P1`,region1:Nt,region2:ft,d:{x:l,y:u}};Nt.ports.push(Wt),ft.ports.push(Wt),g.push(Wt);const Ht={portId:`${c}:TJ1-P8`,region1:Nt,region2:Mt,d:{x:Z,y:G}};Nt.ports.push(Ht),Mt.ports.push(Ht),g.push(Ht);const Ut={portId:`${c}:TJ2-P2`,region1:It,region2:gt,d:{x:p,y:y}};It.ports.push(Ut),gt.ports.push(Ut),g.push(Ut);const Vt={portId:`${c}:TJ2-P7`,region1:It,region2:St,d:{x:U,y:V}};It.ports.push(Vt),St.ports.push(Vt),g.push(Vt);const Zt={portId:`${c}:TJ3-P3`,region1:Ct,region2:yt,d:{x:x,y:v}};Ct.ports.push(Zt),yt.ports.push(Zt),g.push(Zt);const Gt={portId:`${c}:TJ3-P6`,region1:Ct,region2:Pt,d:{x:W,y:H}};Ct.ports.push(Gt),Pt.ports.push(Gt),g.push(Gt);const Jt={portId:`${c}:TJ4-P4`,region1:_t,region2:xt,d:{x:E,y:w}};_t.ports.push(Jt),xt.ports.push(Jt),g.push(Jt);const qt={portId:`${c}:TJ4-P5`,region1:_t,region2:vt,d:{x:k,y:j}};if(_t.ports.push(qt),vt.ports.push(qt),g.push(qt),a>0){const t=F[n][a-1];g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-P1`,t.right,ft)),g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-P2`,t.right,gt)),g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-P3`,t.right,yt)),g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-P4`,t.right,xt)),r&&(g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP12`,t.right,Rt)),g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP23`,t.right,wt)),g.push($(`cell_${n}_${a-1}->cell_${n}_${a}:R-LBP34`,t.right,At))),$t&&t.top&&g.push(...B(`cell_${n}_${a-1}->cell_${n}_${a}:T-T`,t.top,$t,L)),Bt&&t.bottom&&g.push(...B(`cell_${n}_${a-1}->cell_${n}_${a}:B-B`,t.bottom,Bt,Ft?L:i))}if(n>0){const t=F[n-1][a];if(kt&&g.push(...B(`cell_${n-1}_${a}->cell_${n}_${a}:B-L`,t.bottom,kt,D)),g.push($(`cell_${n-1}_${a}->cell_${n}_${a}:B-P4`,t.bottom,xt)),r){const e=bt.d.bounds,o=(e.maxX-e.minX)/(m+1);for(let s=1;s<=m;s++){const i=e.minX+o*s,r={portId:`cell_${n-1}_${a}->cell_${n}_${a}:B-UJ${s}`,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($(`cell_${n-1}_${a}->cell_${n}_${a}:B-UJ`,t.bottom,bt));g.push($(`cell_${n-1}_${a}->cell_${n}_${a}:B-P5`,t.bottom,vt)),g.push(...B(`cell_${n-1}_${a}->cell_${n}_${a}:B-R`,t.bottom,jt,Xt?D:s))}}}let k={regions:f,ports:g,jumperLocations:X};const j="horizontal"===l;if(j||void 0!==u||void 0!==p){const t=Wr(k.regions),e=Hr(t),n=[];let o;o=u||(p?Hr(p):e),n.push(Lr(o.x,o.y)),j&&n.push(kr(-Math.PI/2)),n.push(Lr(-e.x,-e.y));const s=Xr(...n);k=Ur(k,s)}return k})({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:2,innerColChannelPointCount:3,innerRowChannelPointCount:3,outerChannelXPointCount:3,outerChannelYPointCount:3,regionsBetweenPads:!0,orientation:n,bounds:s});if(i.regions.length>0){let t=1/0,e=-1/0,n=1/0,r=-1/0;for(const o of i.regions){if(!o.d?.isPad)continue;const s=o.d?.bounds;s&&(t=Math.min(t,s.minX),e=Math.max(e,s.maxX),n=Math.min(n,s.minY),r=Math.max(r,s.maxY))}const a="0603"===o?.5:1;if(t-a<s.minX||e+a>s.maxX||n-a<s.minY||r+a>s.maxY)return this.error=`baseGraph bounds (${t.toFixed(2)}, ${n.toFixed(2)}, ${e.toFixed(2)}, ${r.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=i.jumperLocations?.map(t=>({center:t.center,orientation:t.orientation,padRegions:t.padRegions}))??[];const r=new Map;for(const e of t.portPoints){const t=r.get(e.connectionName);t?t.points.push(e):r.set(e.connectionName,{points:[e],rootConnectionName:e.rootConnectionName})}this.xyConnections=[];for(const[t,e]of Array.from(r.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 a=((t,e)=>{const n=[...t.regions],o=[...t.ports],s=[],i=Wr(t.regions);for(const r of e){const{start:e,end:a,connectionId:c}=r,h=ia(`conn:${c}:start`,e.x,e.y);n.push(h);const d=ia(`conn:${c}:end`,a.x,a.y);n.push(d);const l=ra(e.x,e.y,t.regions,i);if(l){const t=sa(`conn:${c}:start-port`,h,l.region,l.portPosition);o.push(t)}const u=ra(a.x,a.y,t.regions,i);if(u){const t=sa(`conn:${c}:end-port`,d,u.region,u.portPosition);o.push(t)}const p={connectionId:c,mutuallyConnectedNetworkId:c,startRegion:h,endRegion:d};s.push(p)}return{regions:n,ports:o,connections:s}})(i,this.xyConnections);return this.jumperGraphSolver=new oa({inputGraph:{regions:a.regions,ports:a.ports},inputConnections:a.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??"",o=t.points.map(t=>({x:t.x,y:t.y})),s={path:o,start:o[0]??{x:0,y:0},end:o[o.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(s)}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,o=n.d.center;e.push({minX:t.minX,minY:t.minY,maxX:t.maxX,maxY:t.maxY,center:{x:o.x,y:o.y},networkIds:[]})}const n=new Map;for(let e=0;e<this.jumperGraphSolver.solvedRoutes.length;e++){const o=this.jumperGraphSolver.solvedRoutes[e],s=o.connection.connectionId,i=this.nodeWithPortPoints.portPoints.find(t=>t.connectionName===s)?.rootConnectionName,r=[],a=[];let c=null,h=null;for(let d=0;d<o.path.length;d++){const l=o.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=o.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:s,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,o=e.maxX-e.minX>e.maxY-e.minY,s="0603"===(this.hyperParameters.JUMPER_TYPE??"1206x4")?"0603":"1206x4_pair";o?r.push({route_type:"jumper",start:{x:e.minX,y:n.y},end:{x:e.maxX,y:n.y},footprint:s}):r.push({route_type:"jumper",start:{x:n.x,y:e.minY},end:{x:n.x,y:e.maxY},footprint:s})}}if(c&&h){const t=o.path[o.path.length-1];a.push({regionId:c.regionId,region:c,entryPort:h,exitPort:t?.port||null})}this.routeInfos.push({connectionId:s,rootConnectionName:i,jumpers:r,traversals:a})}for(let t=0;t<this.routeInfos.length;t++){const n=this.routeInfos[t],o=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),s=Math.abs(n.center.y-t.y);e<.1&&s<.1&&(n.networkIds.includes(o)||n.networkIds.push(o))}}}for(const[t,o]of n){if(0===o.length)continue;const n=o[0].region;if(n.d.isPad||n.d.isThroughJumper)continue;const s=n.d.bounds,i=[];for(const t of o)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<=s.maxX+r&&t.maxX>=s.minX-r&&t.minY<=s.maxY+r&&t.maxY>=s.minY-r).map(t=>{const e=o.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:s,waypointPairs:i,obstacles:a,preferredTraceToTraceSpacing:2*this.traceWidth,preferredObstacleToTraceSpacing:2*this.traceWidth},h=new Ba(c);this.curvySolvers.push({solver:h,regionId:t,traversals:o.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],o=[];for(const e of n.traversals){const s=e.regionId,i=n.rootConnectionName??n.connectionId,r=this.regionCurvedPaths.get(s)?.get(i);let a=null;if(r&&r.length>0){const n={x:e.entryPort.d.x,y:e.entryPort.d.y},o=e.exitPort?{x:e.exitPort.d.x,y:e.exitPort.d.y}:null;let s=null,i=1/0;for(const e of r){const r=t(e.start,n)+(o?t(e.end,o):0);r<i&&(i=r,s=e)}s&&i<.5&&(a=s.path)}if(a&&a.length>0){for(let t=o.length>0?1:0;t<a.length;t++)o.push({x:a[t].x,y:a[t].y,z:0})}else 0===o.length&&o.push({x:e.entryPort.d.x,y:e.entryPort.d.y,z:0}),e.exitPort&&o.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:o,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 o=[n.start,n.end];for(const n of o){const o=`${n.x.toFixed(3)},${n.y.toFixed(3)}`,s=t.get(o)??[];e.rootConnectionName&&!s.includes(e.rootConnectionName)&&s.push(e.rootConnectionName),s.includes(e.connectionName)||s.push(e.connectionName),t.set(o,s)}}const e=this.hyperParameters.JUMPER_TYPE??"1206x4",n=qe["0603"===e?"0603":"1206x4_pair"];for(const o of this.jumperLocations){const s="horizontal"===o.orientation,i=o.padRegions.map(e=>{const n=e.d.bounds,o=e.d.center,s=n.maxX-n.minX,i=n.maxY-n.minY,r=`${o.x.toFixed(3)},${o.y.toFixed(3)}`;return{type:"rect",center:o,width:s,height:i,layers:["top"],connectedTo:[...t.get(r)??[]]}}),r={jumper_footprint:e,center:o.center,orientation:o.orientation,width:s?n.length:n.width,height:s?n.width:n.length,pads:i};this.jumpers.push(r)}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 o=0;o<e.route.length-1;o++){const s=e.route[o],i=e.route[o+1];t.lines.push({points:[s,i],strokeColor:it(n,.2),strokeWidth:e.traceThickness,layer:"route-layer-0"})}for(const o of e.jumpers)this._drawJumperPads(t,o,it(n,.5))}return t}_drawJumperPads(t,e,n){const o=qe[e.footprint],s=e.end.x-e.start.x,i=e.end.y-e.start.y,r=Math.abs(s)>Math.abs(i),a=r?o.padLength:o.padWidth,c=r?o.padWidth:o.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*o.padWidth,layer:"jumper-body"})}};function ja(t,e,n,o=.5){const s=t-2*o,i=e-2*o,r=Math.max(1,Math.floor(1+(s-2.45)/2.95)),a=Math.max(1,Math.floor(i/1.42));return"vertical"===n?{cols:r,rows:a}:{cols:a,rows:r}}var Wa=class extends Zt{constructorParams;nodeWithPortPoints;colorMap;traceWidth;connMap;baseHyperParameters;availableJumperTypes;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.availableJumperTypes=t.availableJumperTypes??["0603"],this.MAX_ITERATIONS=1e6,this.GREEDY_MULTIPLIER=1,this.MIN_SUBSTEPS=1e3}getConstructorParams(){return this.constructorParams}getHyperParameterDefs(){const t=[],e=this.nodeWithPortPoints,n=ja(e.width,e.height,"vertical");t.push({name:"0603_max_rows_and_cols_vert",possibleValues:[{JUMPER_TYPE:"0603",COLS:n.cols,ROWS:n.rows,ORIENTATION:"vertical"}]});const o=ja(e.width,e.height,"horizontal");t.push({name:"0603_max_rows_and_cols_horz",possibleValues:[{JUMPER_TYPE:"0603",COLS:o.cols,ROWS:o.rows,ORIENTATION:"horizontal"}]}),t.push({name:"1206x4",possibleValues:[{JUMPER_TYPE:"1206x4"}]});return t.push({name:"1206x4_cols",possibleValues:[1,2,3,4,6,8,10].map(t=>({COLS:t}))}),t.push({name:"1206x4_rows",possibleValues:[1,2,3,4,8].map(t=>({ROWS:t}))}),t.push({name:"orientation",possibleValues:[{ORIENTATION:"vertical"},{ORIENTATION:"horizontal"}]}),t}isValidCombination(t){const{JUMPER_TYPE:e,COLS:n,ROWS:o}=t,s=[1,2,4,6,8],i=[1,2,3,4,6,8,10],r=[1,2,3,4,8];return"0603"===e?s.includes(n)&&s.includes(o):"1206x4"===e&&(i.includes(n)&&r.includes(o))}getCombinationDefs(){return[["0603_max_rows_and_cols_vert"],["0603_max_rows_and_cols_horz"],["1206x4","1206x4_cols","1206x4_rows","orientation"]]}initializeSolvers(){const t=this.getHyperParameterDefs(),e=this.getCombinationDefs();this.supervisedSolvers=[];for(const n of e){const e=n.includes("0603_max_rows_and_cols_vert")||n.includes("0603_max_rows_and_cols_horz"),o=n.includes("1206x4");if(e&&!this.availableJumperTypes.includes("0603"))continue;if(o&&!this.availableJumperTypes.includes("1206x4"))continue;const s=this.getHyperParameterCombinations(t.filter(t=>n.includes(t.name)));for(const t of s){const e=this.generateSolver(t),n=this.computeG(e);this.supervisedSolvers.push({hyperParameters:t,solver:e,h:0,g:n,f:n})}}}generateSolver(t){return new ka({nodeWithPortPoints:this.nodeWithPortPoints,colorMap:this.colorMap,traceWidth:this.traceWidth,hyperParameters:{COLS:t.COLS,ROWS:t.ROWS,ORIENTATION:t.ORIENTATION,JUMPER_TYPE:t.JUMPER_TYPE}})}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()}},Ha=class extends y{getSolverName(){return"CurvyIntraNodeSolver"}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 o=[];for(const[t,e]of n){if(e.length<2)continue;const n=e[0],s=e[e.length-1];o.push({start:{x:n.x,y:n.y},end:{x:s.x,y:s.y},networkId:t})}if(0===o.length)return void(this.phase="done");const s={bounds:e,waypointPairs:o,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 Ba(s),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??"",o=e.get(n);if(!o)continue;const s={connectionName:o.connectionName,rootConnectionName:o.rootConnectionName,traceThickness:this.traceWidth,viaDiameter:this.viaDiameter,route:t.points.map(t=>({x:t.x,y:t.y,z:o.z})),vias:[]};this.routes.push(s)}}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 Ua(t){return{connectionName:t.connectionName,rootConnectionName:t.rootConnectionName,traceThickness:t.traceThickness,viaDiameter:0,route:t.route,vias:[],jumpers:t.jumpers}}var Va=class extends y{getSolverName(){return"JumperHighDensitySolver"}allNodes;nodeAnalyses;routes;colorMap;traceWidth;viaDiameter;connMap;hyperParameters;availableJumperTypes;capacityMeshNodes;capacityMeshEdges;capacityMeshNodeMap;nodeAdjacencyMap;nodesWithoutCrossings;nodesWithCrossings;curvyIntraNodeSolvers;currentCurvySolverIndex;jumperSolvers;currentJumperSolverIndex;phase;jumpers=[];constructor({nodePortPoints:t,colorMap:e,traceWidth:n=.15,viaDiameter:o=.6,connMap:s,hyperParameters:i,capacityMeshNodes:r=[],capacityMeshEdges:a=[],availableJumperTypes:c}){super(),this.allNodes=[...t],this.colorMap=e??{},this.routes=[],this.traceWidth=n,this.viaDiameter=o,this.connMap=s,this.hyperParameters=i,this.capacityMeshNodes=r,this.capacityMeshEdges=a,this.availableJumperTypes=c??["0603"],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 h=1e3*this.nodesWithoutCrossings.length,d=1e5*this.nodesWithCrossings.length;this.MAX_ITERATIONS=h+d+100}_buildNodeAdjacencyMap(){const t=new Map;for(const e of this.capacityMeshEdges){const[n,o]=e.nodeIds;t.has(n)||t.set(n,new Set),t.has(o)||t.set(o,new Set),t.get(n).add(o),t.get(o).add(n)}return t}_analyzeNodes(){for(const t of this.allNodes){const e=Ds(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 o=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 s=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=o.get(t);e&&e.portPoints.length>0&&(c=e.portPoints[0].rootConnectionName??e.portPoints[0].connectionName)}e.push({minX:s,minY:i,maxX:r,maxY:a,networkId:c})}return e}_initializeCurvySolvers(){for(const t of this.nodesWithoutCrossings){const e=this._getAdjacentObstacles(t),n=new Ha({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),o=new Ha({nodeWithPortPoints:e,colorMap:this.colorMap,traceWidth:this.traceWidth,viaDiameter:this.viaDiameter,adjacentObstacles:n});this.curvyIntraNodeSolvers[t]=o}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 Wa({nodeWithPortPoints:t,colorMap:this.colorMap,traceWidth:this.traceWidth,connMap:this.connMap,availableJumperTypes:this.availableJumperTypes});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(Ua(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 o=this.jumperSolvers[this.currentJumperSolverIndex];return o&&(e+=o.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,availableJumperTypes:this.availableJumperTypes}}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,o=Xe(e.route,e.connectionName,this.colorMap[n]);for(const n of o)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 o of e.vias)t.circles.push({center:o,radius:e.viaDiameter/2,fill:it(this.colorMap[n]??"gray",.5),layer:"via"});if("jumpers"in e&&e.jumpers)for(const o of e.jumpers){const e=this.colorMap[n]??"gray",s=o.footprint??"1206",i=qe[s],r=o.end.x-o.start.x,a=o.end.y-o.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:o.start,width:h,height:d,fill:it(e,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.rects.push({center:o.end,width:h,height:d,fill:it(e,.5),stroke:"rgba(0, 0, 0, 0.5)",layer:"jumper"}),t.lines.push({points:[o.start,o.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}},Za=class extends y{getSolverName(){return"MultipleHighDensityRouteStitchSolver2"}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 o=new Map;for(const e of t.hdRoutes){const t=o.get(e.connectionName);t?t.push(e):o.set(e.connectionName,[e])}this.unsolvedRoutes=[];for(const[e,s]of o.entries()){const o=t.connections.find(t=>t.name===e);if(!o)continue;const i=n.get(e);let r=[];i?.path&&(r=i.path.map(t=>t.currentNodeId));const a={...o.pointsToConnect[0],z:Be(Ge(o.pointsToConnect[0]),t.layerCount)},c={...o.pointsToConnect[1],z:Be(Ge(o.pointsToConnect[1]),t.layerCount)};this.unsolvedRoutes.push({connectionName:e,hdRoutes:s,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:o,start:s,end:i}=t;if(0===n.length)return{connectionName:e,traceThickness:this.defaultTraceThickness,viaDiameter:this.defaultViaDiameter,route:[s,i],vias:[],jumpers:[]};let r;r=o.length>0?this.orderRoutesByNodePath(n,o,s,e):this.orderRoutesByProximity(n,s);const a=[],c=[],h=[];a.push({x:s.x,y:s.y,z:s.z});for(let t=0;t<r.length;t++){const e=r[t],n=a[a.length-1],o=e.route[0],s=e.route[e.route.length-1],i=Pt(n,o),d=Pt(n,s),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&&Pt(n,u[0])<p&&(u=u.slice(1)),a.push(...u),c.push(...e.vias),e.jumpers&&h.push(...e.jumpers)}const d=Pt(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,o){if(0===t.length)return[];const s=new Set(t);let i=null,r=1/0;for(const t of s){const e=t.route[0],o=t.route[t.route.length-1],s=Math.min(Pt(n,e),Pt(n,o));s<r&&(r=s,i=t)}if(!i)return[];s.delete(i);const a=i.route[0],c=i.route[i.route.length-1];let h,d;Pt(n,a)<=Pt(n,c)?(h=a,d=c):(h=c,d=a);const l=(t,e)=>{let n=0;for(const o of s){if(o===e)continue;const s=o.route[0],i=o.route[o.route.length-1];(Pt(t,s)<10||Pt(t,i)<10)&&n++}return n},u=[i];let p=d;for(;s.size>0;){let t=null,e=1/0,n=-1;for(const o of s){const s=o.route[0],i=o.route[o.route.length-1],r=Pt(p,s),a=Pt(p,i),c=Math.min(r,a);if(c>=10)continue;const h=l(r<=a?i:s,o),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=o,n=h)}if(!t)break;{u.push(t),s.delete(t);const e=t.route[0],n=t.route[t.route.length-1];p=Pt(p,e)<=Pt(p,n)?n:e}}const m=[];for(p=h;s.size>0;){let t=null,e=1/0,o=-1;const i=Pt(p,n);for(const r of s){const s=r.route[0],a=r.route[r.route.length-1],c=Pt(p,s),h=Pt(p,a),d=Math.min(c,h);if(d>=10)continue;const u=c<=h?a:s;if(Pt(u,n)>i+2)continue;const m=l(u,r),f=0===m,g=0===o,y=d-e;let x=!1;x=null===t||(!!(!f&&g&&y<5)||!(f&&!g&&y>-5)&&d<e),x&&(e=d,t=r,o=m)}if(!t)break;{m.unshift(t),s.delete(t);const e=t.route[0],n=t.route[t.route.length-1];p=Pt(p,e)<=Pt(p,n)?n:e}}const f=[...m,...u];if(s.size>0){const e=[...s].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 ${s.size} routes for connection ${t[0]?.connectionName??"?"}, skipped routes: ${e.join("; ")}`)}return f}orderRoutesByProximity(t,e){const n=new Set(t),o=[];let s=e;for(;n.size>0;){let t=null,e=1/0,i=!1;for(const o of n){const n=o.route[0],r=o.route[o.route.length-1],a=Pt(s,n),c=Pt(s,r);a<e&&(e=a,t=o,i=!1),c<e&&(e=c,t=o,i=!0)}if(!t)break;{o.push(t),n.delete(t);const e=t.route[0],r=t.route[t.route.length-1];s=i?e:r}}return o}visualize(){const t={points:[],lines:[],circles:[],rects:[],title:"Multiple High Density Route Stitch Solver 2"};for(const[e,n]of this.mergedHdRoutes.entries()){const o=this.colorMap[n.connectionName]??`hsl(120, 100%, ${40+10*e%40}%)`;for(let e=0;e<n.route.length-1;e++){const s=n.route[e],i=n.route[e+1],r=0!==s.z?it(o,.5):o;t.lines?.push({points:[{x:s.x,y:s.y},{x:i.x,y:i.y}],strokeColor:r,strokeWidth:n.traceThickness})}for(const e of n.route){const n=0!==e.z?it(o,.5):o;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:o});if(n.jumpers&&n.jumpers.length>0){const e=Qe(n.jumpers,{color:o,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 o=0;o<e.hdRoutes.length;o++){const s=e.hdRoutes[o];if(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",label:`segment ${o}`}),s.jumpers&&s.jumpers.length>0){const e=Qe(s.jumpers,{color:n,label:s.connectionName});t.rects.push(...e.rects??[]),t.lines.push(...e.lines??[])}}}return t}};function Ga(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var Ja=class extends y{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.srj=t,this.opts={...e},this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth;const n=this.opts;if(this.effort=n.effort??1,void 0===n.capacityDepth){const e=t.bounds.maxX-t.bounds.minX,o=t.bounds.maxY-t.bounds.minY,s=Math.max(e,o),i=n.targetMinCapacity??.5;n.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===n.cacheProvider?ut():null===n.cacheProvider?null:n.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getSolverName(){return"AssignableAutoroutingPipeline3"}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=[Ga("netToPointPairsSolver",xn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),Ga("nodeSolver",es,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),Ga("relateNodesToOffBoardConnections",Tr,t=>[{capacityMeshNodes:t.capacityNodes,srj:t.srj}],{onSolved:t=>{t.capacityNodes=t.relateNodesToOffBoardConnections?.getOutput().capacityNodes}}),Ga("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Ga("availableSegmentPointSolver",Rs,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),Ga("portPointPathingSolver",Qs,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])),o=t.availableSegmentPointSolver;for(const t of o.sharedEdgeSegments)for(const e of t.portPoints){const[o,s]=e.nodeIds,i={portPointId:e.segmentPortPointId,x:e.x,y:e.y,z:e.availableZ[0]??0,connectionNodeIds:[o,s],distToCentermostPortOnZ:e.distToCentermostPortOnZ,connectsToOffBoardNode:t.nodeIds.some(t=>n.get(t)?._offBoardConnectionId)},r=n.get(o);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,MAX_RIPPING_PF_THRESHOLD:.9,MIN_RIPPING_PF_THRESHOLD:.1,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&&Er({connMap:t.connMap,connectionsWithResults:e.connectionsWithResults,inputNodes:e.inputNodes,obstacles:t.srj.obstacles})}}),Ga("highDensitySolver",Va,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??[],availableJumperTypes:t.srj.availableJumperTypes}]),Ga("highDensityStitchSolver",Za,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}]),Ga("traceKeepoutSolver",_r,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(),o=this.singleLayerNodeMerger?.visualize(),s=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,P=[];if(P.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]}),P.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const S={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:["obstacle",t.offBoardConnectsTo?`offboardConnections: ${t.offBoardConnectsTo?.join(", ")}`:"",t.layers?.join(", ")].filter(Boolean).join("\n")}))],lines:P},M=[S,t,e,n,o,s,i,a,c,h,d,l,u?g(S,u):null,p?g(S,p):null,m?g(S,m):null,f,y,r,x,this.solved?g(S,an(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...M)}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 o=t[n];if(e.push({points:o.route.map(t=>({x:t.x,y:t.y})),strokeColor:this.colorMap[o.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,o]of this.srj.obstacles.entries()){if(!o.offBoardConnectsTo?.length)continue;const s=o.obstacleId??`__obs${n}`;o.obstacleId=s;const i=this.connMap.getNetConnectedToId(s);if(!i)continue;const r=this.connMap.getIdsConnectedToNet(i).find(t=>e.has(t));r&&(t[s]=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 o=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,s=e.filter(t=>t.connectionName===n.name);for(let e=0;e<s.length;e++){const i=s[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??n.rootConnectionName??n.name,route:Ve(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}}};function qa({path:t,connection:e,assignedPortPoints:n,nodeAssignedPortPoints:o}){const s=[];for(const i of t){if(!i.portPoint)continue;const t=i.portPoint;n.set(t.portPointId,{connectionName:e.name,rootConnectionName:e.rootConnectionName});const r={portPointId:t.portPointId,x:t.x,y:t.y,z:t.z,connectionName:e.name,rootConnectionName:e.rootConnectionName};s.push(r);for(const e of t.connectionNodeIds){const t=o.get(e)??[];t.push(r),o.set(e,t)}}return s}function Ka(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}function Qa({connectionPoint:t,node:e}){const n=Je(t);if(0===n.length)return console.error("[addConnectionEndpointsToNodeAssignments] endpoint has no declared layers; falling back to candidate z"),[];const o=n.map(t=>function({layerName:t,node:e}){const n=Math.max(...e.availableZ,0)+1,o=Be(t,n);if(Number.isFinite(o))return o;const s=t.match(/^layer(\d+)$/);return s?Number.parseInt(s[1],10)-1:void 0}({layerName:t,node:e})).filter(t=>void 0!==t);return 0===o.length&&console.error(`[addConnectionEndpointsToNodeAssignments] endpoint has unparseable layer names: ${n.join(", ")}; falling back to candidate z`),o}function tc({connectionPoint:t,candidate:e,node:n,endpointName:o,connection:s}){if(!n)return console.error(`[addConnectionEndpointsToNodeAssignments] ${o} endpoint for "${s.name}" missing node; using raw endpoint/candidate values`),{x:t.x,y:t.y,z:e.z};const i=function({connectionPoint:t,candidate:e,node:n,endpointName:o,connection:s}){const i=Qa({connectionPoint:t,node:n});if(0===i.length)return e.z;if(i.includes(e.z))return e.z;const r=i.reduce((t,n)=>Math.abs(n-e.z)<Math.abs(t-e.z)?n:t);return console.assert(!1,`[addConnectionEndpointsToNodeAssignments] ${o} endpoint for "${s.name}" is on z=${e.z} but endpoint allows z in [${i.join(", ")}]; using fallback z=${r}`),console.error(`[addConnectionEndpointsToNodeAssignments] ${o} endpoint for "${s.name}" layer mismatch; using fallback z=${r}`),r}({connectionPoint:t,candidate:e,node:n,endpointName:o,connection:s}),r=function({point:t,node:e}){return Ka(t,e)}({point:t,node:n});if(!r){const e=function({point:t,node:e}){const n=e.center.x-e.width/2,o=e.center.x+e.width/2,s=e.center.y-e.height/2,i=e.center.y+e.height/2;return{x:Math.min(Math.max(t.x,n),o),y:Math.min(Math.max(t.y,s),i)}}({point:t,node:n});return console.assert(r,`[addConnectionEndpointsToNodeAssignments] ${o} endpoint for "${s.name}" connectionPoint outside obstacle/node bounds; original=(${t.x}, ${t.y}) clamped=(${e.x}, ${e.y})`),{x:e.x,y:e.y,z:i}}return{x:t.x,y:t.y,z:i}}function ec({path:t,connection:e,inputNodeMap:n,nodeAssignedPortPoints:o}){if(0===t.length)return;const s=t[0],i=t[t.length-1],r=e.pointsToConnect[0],a=e.pointsToConnect[e.pointsToConnect.length-1];if(r){const t=tc({connectionPoint:r,candidate:s,node:n.get(s.currentNodeId),endpointName:"start",connection:e}),i=o.get(s.currentNodeId)??[];i.push({x:t.x,y:t.y,z:t.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),o.set(s.currentNodeId,i)}if(a){const t=tc({connectionPoint:a,candidate:i,node:n.get(i.currentNodeId),endpointName:"end",connection:e}),s=o.get(i.currentNodeId)??[];s.push({x:t.x,y:t.y,z:t.z,connectionName:e.name,rootConnectionName:e.rootConnectionName}),o.set(i.currentNodeId,s)}}function nc({candidate:t}){return t.nextRegion?.regionId?t.nextRegion.regionId:t.port.region2?.regionId?t.port.region2.regionId:t.port.region1.regionId}function oc({point:t}){if(t)return"layers"in t&&Array.isArray(t.layers)?t.layers[0]:t.layer}function sc({layer:t,defaultZ:e}){if(!t)return e;const n=t.match(/\d+/);if(!n)return e;const o=Number.parseInt(n[0],10)-1;return Number.isFinite(o)&&o>=0?o:e}function ic({solvedRoute:t,connectionResult:e}){const n=[],o=e.connection,s=o.pointsToConnect[0],i=o.pointsToConnect[o.pointsToConnect.length-1],r=sc({layer:oc({point:s}),defaultZ:0}),a=sc({layer:oc({point:i}),defaultZ:0}),c={prevCandidate:null,portPoint:null,currentNodeId:e.nodeIds[0],point:{x:s?.x??0,y:s?.y??0},z:r,f:0,g:0,h:0,distanceTraveled:0};n.push(c);for(const e of t.path){const t=n[n.length-1],o=e.port.d,s={prevCandidate:t,portPoint:o,currentNodeId:nc({candidate:e}),point:{x:o.x,y:o.y},z:o.z,f:0,g:0,h:0,distanceTraveled:t.distanceTraveled+Pt(t.point,o)};n.push(s)}const h=n[n.length-1],d={prevCandidate:h,portPoint:null,currentNodeId:e.nodeIds[1],point:{x:i?.x??h.point.x,y:i?.y??h.point.y},z:a,f:0,g:0,h:0,distanceTraveled:h.distanceTraveled+Pt(h.point,i??h.point)};return n.push(d),n}function rc({solvedRoutes:t,connectionResults:e,inputNodes:n}){const o=new Map(e.map(t=>[t.connection.name,t])),s=new Map,i=new Map,r=new Map(n.map(t=>[t.capacityMeshNodeId,t]));for(const t of n)i.set(t.capacityMeshNodeId,[]);for(const e of t){const t=e.connection.connectionId,n=o.get(t);if(!n)continue;const a=ic({solvedRoute:e,connectionResult:n});n.path=a,n.portPoints=qa({path:a,connection:n.connection,assignedPortPoints:s,nodeAssignedPortPoints:i}),ec({path:a,connection:n.connection,inputNodeMap:r,nodeAssignedPortPoints:i})}return{connectionsWithResults:e,assignedPortPoints:s,nodeAssignedPortPoints:i}}var ac=t=>{const e=function({solver:t}){const e=[],n=[],o=[],s=[];for(const e of t.inputNodes){const n=t.computeNodePf(e),o=Math.min(255,Math.floor(512*n)),i=Math.max(0,255-Math.floor(512*n));let r=`rgba(${o}, ${i}, ${i}, ${n<.001?"0.1":"0.3"})`;e._containsObstacle&&(r="rgba(255, 0, 0, 0.3)"),e._offBoardConnectedCapacityMeshNodeIds?.length&&(r="rgba(255, 165, 0, 0.3)"),s.push({center:e.center,width:e.width,height:e.height,stroke:"rgba(80, 80, 120, 0.15)",fill:r,label:`${e.capacityMeshNodeId}\npf: ${n.toFixed(3)}`})}for(const e of t.portPointMap.values())n.push({center:{x:e.x,y:e.y},radius:.035,fill:"rgba(120, 120, 120, 0.3)"});for(const n of t.graph.ports){const t=n.region1.d.center,o=n.region2.d.center;e.push({points:[t,{x:n.d.x,y:n.d.y},o],strokeColor:"rgba(100, 100, 100, 0.1)",strokeWidth:.03})}for(const n of t.connections){const t=n.startRegion.d.center,s=n.endRegion.d.center,i=(t.x+s.x)/2,r=(t.y+s.y)/2;e.push({points:[t,s],strokeColor:"rgba(255, 50, 150, 0.2)",strokeWidth:.05}),o.push({x:i,y:r,color:"rgba(200, 0, 100, 0.9)",label:n.connectionId})}return{lines:e,circles:n,points:o,rects:s}}({solver:t});if(t.currentConnection&&!t.solved){const n=rt(t.currentConnection.connectionId,.8),o=t.currentConnection.startRegion,s=t.currentConnection.endRegion,i=o.d.center,r=s.d.center;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=rt(n.connection.connectionId,.8),o=[];for(const t of n.path){const e=t.port;o.push({x:e.d.x,y:e.d.y})}const s=n.connection.startRegion.d.center,i=n.connection.endRegion.d.center;o.unshift(s),o.push(i),o.length>0&&e.lines.push({points:o,strokeColor:t})}const n=t.candidateQueue.peekMany(10);for(let t=0;t<n.length;t++){const o=n[t],s=o.port,i=0===t;e.points.push({x:s.d.x,y:s.d.y,color:i?"green":"rgba(128, 128, 128, 0.55)",label:[o.port.portId,`g: ${o.g.toFixed(2)}`,`h: ${o.h.toFixed(2)}`,`f: ${o.f.toFixed(2)}`].join("\n")})}const o=n[0];if(!t.solved&&o&&t.currentConnection){const n=rt(t.currentConnection.connectionId,.8),s=[];let i=o;for(;i;){const t=i.port;s.unshift({x:t.d.x,y:t.d.y}),i=i.parent}const r=t.currentConnection.startRegion.d.center;s.unshift(r),s.length>1&&e.lines.push({points:s,strokeColor:n})}return e},cc=class extends Or{inputNodes;regionNodeMap;regionById;portPointMap;connectionsWithResults=[];assignedPortPoints=new Map;nodeAssignedPortPoints=new Map;assignmentsBuilt=!1;portUsagePenalty;regionTransitionPenalty;ripRegionPfThresholdStart;maxRegionRips;memoryPfFactor;centerOffsetDistPenaltyFactor;forceCenterFirst;straightLineDeviationPenaltyFactor;connectionResultByName;regionRipCountMap=new Map;regionMemoryPfMap=new Map;totalRipCount=0;randomRipFraction;maxRips;MIN_ALLOWED_BOARD_SCORE;constructor({inputGraph:t,inputConnections:e,connectionsWithResults:n,inputNodes:o,portPointMap:s,regionMemoryPfMap:i,rippingEnabled:r,weights:a,forceCenterFirst:c}){const{GREEDY_MULTIPLIER:h,MAX_REGION_RIPS:d,MEMORY_PF_FACTOR:l,CENTER_OFFSET_DIST_PENALTY_FACTOR:u,PORT_USAGE_PENALTY:p,REGION_TRANSITION_PENALTY:m,STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR:f,RIP_COST:g,RIP_REGION_PF_THRESHOLD_START:y,RANDOM_RIP_FRACTION:x,MAX_RIPS:v,MIN_ALLOWED_BOARD_SCORE:P}=a;super({inputGraph:t,inputConnections:e,greedyMultiplier:h,rippingEnabled:r??!0,ripCost:g}),this.inputNodes=o,this.regionNodeMap=new Map(o.map(t=>[t.capacityMeshNodeId,t])),this.regionById=new Map(this.graph.regions.map(t=>[t.regionId,t])),this.portPointMap=s,this.connectionsWithResults=n,this.portUsagePenalty=p,this.regionTransitionPenalty=m,this.ripRegionPfThresholdStart=y,this.maxRegionRips=d,this.memoryPfFactor=l,this.centerOffsetDistPenaltyFactor=u,this.forceCenterFirst=c,this.straightLineDeviationPenaltyFactor=f,this.regionMemoryPfMap=i,this.randomRipFraction=x,this.maxRips=v,this.MIN_ALLOWED_BOARD_SCORE=P,this.MAX_ITERATIONS=2e5,this.connectionResultByName=new Map(n.map(t=>[t.connection.name,t]))}clampPf(t){return Number.isFinite(t)?Math.max(0,Math.min(.9999,t)):0}pfToFailureCost(t){return-Math.log(1-this.clampPf(t))}recordRegionMemoryPf(t,e){const n=this.clampPf(e),o=this.regionMemoryPfMap.get(t)??0,s=Math.max(n,.98*o);this.regionMemoryPfMap.set(t,s)}estimateCostToEnd(t){const e=this.currentEndRegion?.d?.center;return e?Pt({x:t.d.x,y:t.d.y},e):0}computeH(t){const e=this.estimateCostToEnd(t.port),n=t.port.d.distToCentermostPortOnZ??0,o=t.nextRegion?.regionId??t.lastRegion?.regionId,s=o?this.regionMemoryPfMap.get(o)??0:0,i=this.pfToFailureCost(s)*this.memoryPfFactor,r=this.getStraightLineDeviationPenalty(t);return e+n*this.centerOffsetDistPenaltyFactor+i+r}getStraightLineDeviationPenalty(t){if(this.straightLineDeviationPenaltyFactor<=0)return 0;const e=this.currentConnection?.connectionId;if(!e)return 0;const n=this.connectionResultByName.get(e),o=n?.connection.pointsToConnect;if(!o||o.length<2)return 0;const s=o[0],i=o[1],r=vt({x:t.port.d.x,y:t.port.d.y},s,i);return this.straightLineDeviationPenaltyFactor*r}computeIncreasedRegionCostIfPortsAreUsed(t,e,n){const o=Pt({x:e.d.x,y:e.d.y},{x:n.d.x,y:n.d.y}),s=.01*Math.max(t.d.width,t.d.height);return o*this.regionTransitionPenalty+s}getPortUsagePenalty(t){return(t.ripCount??0)*this.portUsagePenalty}getRipsRequiredForPortUsage(t,e,n){const o=t.assignments??[];if(0===o.length)return[];const s={x:e.d.x,y:e.d.y},i={x:n.d.x,y:n.d.y};return o.filter(t=>{if(t.connection.mutuallyConnectedNetworkId===this.currentConnection?.mutuallyConnectedNetworkId)return!1;const o=t.regionPort1,r=t.regionPort2;if(o===e||o===n)return!1;if(r===e||r===n)return!1;const a={x:o.d.x,y:o.d.y},c={x:r.d.x,y:r.d.y};return gt(s,i,a,c)})}isPortAvailableForCurrentNet(t){const e=t.assignment;if(!e)return!0;const n=this.currentConnection?.mutuallyConnectedNetworkId;return e.connection.mutuallyConnectedNetworkId===n}getCenterFirstEnteringRegionCandidates(t){const e=new Map;for(const n of t){const t=n.port.d.z??0,o=e.get(t)??[];o.push(n),e.set(t,o)}const n=[];for(const t of e.values()){const e=t.slice().sort((t,e)=>t.port.d.distToCentermostPortOnZ-e.port.d.distToCentermostPortOnZ)[0];if(!e)continue;if(this.isPortAvailableForCurrentNet(e.port)){n.push(e);continue}const o=t.slice().sort((t,e)=>t.port.d.x!==e.port.d.x?t.port.d.x-e.port.d.x:t.port.d.y-e.port.d.y),s=[];let i=[];for(const t of o)this.isPortAvailableForCurrentNet(t.port)?i.push(t):i.length>0&&(s.push(i),i=[]);i.length>0&&s.push(i);for(const t of s)n.push(t[Math.floor(t.length/2)])}return n}selectCandidatesForEnteringRegion(t){const e=this.currentConnection?.startRegion,n=this.currentConnection?.endRegion,o=t.filter(t=>{const o=t.nextRegion;return!o?.d._containsObstacle||(o===e||o===n)}),s=this.forceCenterFirst?this.getCenterFirstEnteringRegionCandidates(o):o;return s.length<=2?s:s.slice().sort((t,e)=>t.g+t.h-(e.g+e.h)).slice(0,2)}routeSolvedHook(t){const e=new Set;for(const n of t.path){const t=n.lastRegion;t&&e.add(t)}for(const t of e){const e=this.computeRegionPfFromAssignments(t);this.recordRegionMemoryPf(t.regionId,e)}if(!t.requiredRip)return;if(this.unprocessedConnections.length<2)return;const[n,...o]=this.unprocessedConnections;this.unprocessedConnections=[...o,n]}_step(){super._step(),this.enforceBoardScoreGuardrail()||this.buildAssignmentsIfSolved()}enforceBoardScoreGuardrail(){if(!this.solved||this.failed)return!1;const t=this.computeBoardScore();return this.stats={...this.stats,boardScore:t,totalRipCount:this.totalRipCount},!(t>=this.MIN_ALLOWED_BOARD_SCORE)&&(this.error=`Board score ${t.toFixed(2)} is less than MIN_ALLOWED_BOARD_SCORE ${this.MIN_ALLOWED_BOARD_SCORE.toFixed(2)}`,this.failed=!0,this.solved=!1,!0)}buildAssignmentsIfSolved(){if(!this.solved||this.assignmentsBuilt)return;const t=rc({solvedRoutes:this.solvedRoutes,connectionResults:this.connectionsWithResults,inputNodes:this.inputNodes});this.connectionsWithResults=t.connectionsWithResults,this.assignedPortPoints=t.assignedPortPoints,this.nodeAssignedPortPoints=t.nodeAssignedPortPoints,this.assignmentsBuilt=!0}getRegionRippingPfThreshold(t){const e=this.regionRipCountMap.get(t)??0,n=Math.min(1,e/this.maxRegionRips);return this.ripRegionPfThresholdStart*(1-n)+1*n}getPortPointsFromRegionAssignments(t){return t.flatMap(t=>{const e=t.regionPort1,n=t.regionPort2,o=t.connection.connectionId,s=t.connection.mutuallyConnectedNetworkId;return[{x:e.d.x,y:e.d.y,z:e.d.z,connectionName:o,rootConnectionName:s},{x:n.d.x,y:n.d.y,z:n.d.z,connectionName:o,rootConnectionName:s}]})}getPortPointsFromNewlySolvedRouteInRegion(t,e){return t.path.flatMap(n=>{if(!n.lastPort||n.lastRegion!==e)return[];const o=n.lastPort,s=n.port;return[{x:o.d.x,y:o.d.y,z:o.d.z,connectionName:t.connection.connectionId,rootConnectionName:t.connection.mutuallyConnectedNetworkId},{x:s.d.x,y:s.d.y,z:s.d.z,connectionName:t.connection.connectionId,rootConnectionName:t.connection.mutuallyConnectedNetworkId}]})}computeRegionPf({region:t,newlySolvedRoute:e,routesToRip:n}){const o=this.regionNodeMap.get(t.regionId);if(!o||o._containsTarget)return 0;const s=(t.assignments??[]).filter(t=>!n.has(t.solvedRoute)),i=[...this.getPortPointsFromRegionAssignments(s),...this.getPortPointsFromNewlySolvedRouteInRegion(e,t)],r={capacityMeshNodeId:o.capacityMeshNodeId,center:o.center,width:o.width,height:o.height,portPoints:i,availableZ:o.availableZ},a=Ds(r),c=this.getDerivedCapacityMeshNode(o);return ws(c,a.numSameLayerCrossings,a.numEntryExitLayerChanges,a.numTransitionPairCrossings)}computeRegionPfFromAssignments(t){const e=this.regionNodeMap.get(t.regionId);if(!e||e._containsTarget)return 0;const n=t.assignments??[],o=this.getPortPointsFromRegionAssignments(n),s={capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:o,availableZ:e.availableZ},i=Ds(s),r=this.getDerivedCapacityMeshNode(e);return ws(r,i.numSameLayerCrossings,i.numEntryExitLayerChanges,i.numTransitionPairCrossings)}getDerivedCapacityMeshNode(t){return{capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,availableZ:t.availableZ,layer:`z${t.availableZ.join(",")}`,_containsObstacle:t._containsObstacle,_containsTarget:t._containsTarget,_offBoardConnectionId:t._offBoardConnectionId,_offBoardConnectedCapacityMeshNodeIds:t._offBoardConnectedCapacityMeshNodeIds}}getCrossingRoutesByRegionForRoute(t){const e=new Map;for(const n of t.path){if(!n.lastPort||!n.lastRegion)continue;const t=n.lastRegion,o=t.regionId,s=this.getRipsRequiredForPortUsage(t,n.lastPort,n.port);if(0===s.length)continue;const i=e.get(o)??new Set;for(const t of s)i.add(t.solvedRoute);e.set(o,i)}return e}getRoutesInRegionForRipping({regionId:t,routesToRip:e,newlySolvedRoute:n}){const o=this.regionById.get(t);if(!o?.assignments?.length)return[];const s=new Map;for(const t of o.assignments){const o=t.solvedRoute,i=o.connection.connectionId;i!==n.connection.connectionId&&(e.has(o)||s.set(i,o))}return[...s.values()]}getTraversedRegionIds(t){const e=new Set;for(const n of t.path){const t=n.lastRegion;t&&e.add(t.regionId)}return[...e]}processRandomRips({routesToRip:t,newlySolvedRoute:e,randomSeed:n}){if(this.randomRipFraction<=0)return;if(this.totalRipCount>=this.maxRips)return;const o=this.solvedRoutes.filter(n=>!t.has(n)&&n.connection.connectionId!==e.connection.connectionId);if(0===o.length)return;const s=Math.max(1,Math.floor(this.randomRipFraction*o.length)),i=Bt(o,n);let r=0;for(const e of i){if(r>=s)break;if(this.totalRipCount>=this.maxRips)break;t.has(e)||(t.add(e),r++,this.totalRipCount++)}}processRippingForRoute(t){const e=super.computePortOverlapRoutes(t),n=new Set(e),o=this.getCrossingRoutesByRegionForRoute(t),s=this.iterations+this.solvedRoutes.length+this.totalRipCount,i=this.getTraversedRegionIds(t),r=Bt(Array.from(new Set([...i,...o.keys()])),s);for(const e of r){if(this.totalRipCount>=this.maxRips)break;const o=this.regionById.get(e);if(!o)continue;const i=this.getRegionRippingPfThreshold(e);let r=this.computeRegionPf({region:o,newlySolvedRoute:t,routesToRip:n});if(this.recordRegionMemoryPf(e,r),r<=i)continue;const a=new Set;let c=0;for(;r>i&&!(this.totalRipCount>=this.maxRips);){const i=this.getRoutesInRegionForRipping({regionId:e,routesToRip:n,newlySolvedRoute:t}).filter(t=>!a.has(t.connection.connectionId)&&!n.has(t));if(0===i.length)break;const h=Bt(i,s+c+a.size)[0];if(!h)break;a.add(h.connection.connectionId),n.add(h),this.totalRipCount++,c++,this.regionRipCountMap.set(e,(this.regionRipCountMap.get(e)??0)+1),r=this.computeRegionPf({region:o,newlySolvedRoute:t,routesToRip:n}),this.recordRegionMemoryPf(e,r)}}return n.size>e.size&&this.processRandomRips({routesToRip:n,newlySolvedRoute:t,randomSeed:s+1e4}),n}computeRoutesToRip(t){return this.processRippingForRoute(t)}getNodesWithPortPoints(){const t=[];for(const e of this.inputNodes){const n=this.nodeAssignedPortPoints.get(e.capacityMeshNodeId)??[];0!==n.length&&t.push({capacityMeshNodeId:e.capacityMeshNodeId,center:e.center,width:e.width,height:e.height,portPoints:n,availableZ:e.availableZ})}return t}computeBoardScore(){let t=this.nodeAssignedPortPoints;if(!this.assignmentsBuilt){t=rc({solvedRoutes:this.solvedRoutes,connectionResults:this.connectionsWithResults,inputNodes:this.inputNodes}).nodeAssignedPortPoints}const e=[];for(const n of this.inputNodes){const o=t.get(n.capacityMeshNodeId)??[];0!==o.length&&e.push({capacityMeshNodeId:n.capacityMeshNodeId,center:n.center,width:n.width,height:n.height,portPoints:o,availableZ:n.availableZ})}return Hs(e,new Map(this.inputNodes.map(t=>[t.capacityMeshNodeId,this.getDerivedCapacityMeshNode(t)])))}computeNodePf(t){const e=this.nodeAssignedPortPoints.get(t.capacityMeshNodeId);if(!e||0===e.length)return 0;const n={capacityMeshNodeId:t.capacityMeshNodeId,center:t.center,width:t.width,height:t.height,portPoints:e,availableZ:t.availableZ},o=Ds(n),s=this.getDerivedCapacityMeshNode(t);return ws(s,o.numSameLayerCrossings,o.numEntryExitLayerChanges,o.numTransitionPairCrossings)}visualize(){return ac(this)}};function hc(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var dc=class extends y{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.srj=t,this.opts={...e},this.MAX_ITERATIONS=1e8,this.viaDiameter=t.minViaDiameter??.6,this.minTraceWidth=t.minTraceWidth;const n=this.opts;if(this.effort=n.effort??1,void 0===n.capacityDepth){const e=t.bounds.maxX-t.bounds.minX,o=t.bounds.maxY-t.bounds.minY,s=Math.max(e,o),i=n.targetMinCapacity??.5;n.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===n.cacheProvider?ut():null===n.cacheProvider?null:n.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}netToPointPairsSolver;nodeSolver;nodeTargetMerger;edgeSolver;colorMap;highDensityRouteSolver;highDensityStitchSolver;singleLayerNodeMerger;strawSolver;deadEndSolver;traceSimplificationSolver;availableSegmentPointSolver;portPointPathingSolver;multiSectionPortPointOptimizer;uniformPortDistributionSolver;traceWidthSolver;viaDiameter;minTraceWidth;effort;startTimeOfPhase;endTimeOfPhase;timeSpentOnPhase;activeSubSolver=null;connMap;srjWithPointPairs;capacityNodes=null;capacityEdges=null;inputNodeWithPortPoints=[];cacheProvider=null;pipelineDef=[hc("netToPointPairsSolver",vn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),hc("nodeSolver",es,t=>[{simpleRouteJson:t.srjWithPointPairs}],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.getOutput().meshNodes??[]}}),hc("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),hc("availableSegmentPointSolver",Rs,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],traceWidth:t.minTraceWidth,colorMap:t.colorMap}]),hc("portPointPathingSolver",cc,t=>{this.inputNodeWithPortPoints=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}));const e=new Map(this.inputNodeWithPortPoints.map(t=>[t.capacityMeshNodeId,t])),n=t.availableSegmentPointSolver;for(const t of n.sharedEdgeSegments)for(const n of t.portPoints){const[t,o]=n.nodeIds,s={portPointId:n.segmentPortPointId,x:n.x,y:n.y,z:n.availableZ[0]??0,connectionNodeIds:[t,o],distToCentermostPortOnZ:n.distToCentermostPortOnZ},i=e.get(t);i&&i.portPoints.push(s)}const{graph:o,regionMap:s,portPointMap:i}=function({inputNodes:t}){const e=new Map,n=new Map,o=[],s=[];for(const n of t){const t={regionId:n.capacityMeshNodeId,ports:[],assignments:[],d:n};o.push(t),e.set(n.capacityMeshNodeId,t)}for(const o of t)for(const t of o.portPoints){if(n.has(t.portPointId))continue;n.set(t.portPointId,t);const[o,i]=t.connectionNodeIds,r=e.get(o),a=e.get(i);if(!r||!a)continue;const c={portId:t.portPointId,region1:r,region2:a,d:t};s.push(c),r.ports.push(c),a.ports.push(c)}return{graph:{regions:o,ports:s},regionMap:e,portPointMap:n}}({inputNodes:this.inputNodeWithPortPoints}),{connections:r,connectionsWithResults:a}=function({simpleRouteJson:t,inputNodes:e,regionMap:n}){const{unshuffledConnectionsWithResults:o}=js(t,e),s=[];for(const t of o){const e=n.get(t.nodeIds[0]),o=n.get(t.nodeIds[1]);if(!e||!o)throw new Error(`Missing region for connection "${t.connection.name}"`);s.push({connectionId:t.connection.name,mutuallyConnectedNetworkId:t.connection.rootConnectionName??t.connection.name,startRegion:e,endRegion:o})}return{connections:s,connectionsWithResults:o}}({simpleRouteJson:t.srjWithPointPairs,inputNodes:this.inputNodeWithPortPoints,regionMap:s});return[{inputGraph:o,inputConnections:r,connectionsWithResults:a,inputNodes:this.inputNodeWithPortPoints,portPointMap:i,rippingEnabled:!0,weights:{PORT_USAGE_PENALTY:.15,REGION_TRANSITION_PENALTY:.6,MEMORY_PF_FACTOR:4,CENTER_OFFSET_DIST_PENALTY_FACTOR:.05,STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR:4,RIP_COST:8.5,GREEDY_MULTIPLIER:.7,RIP_REGION_PF_THRESHOLD_START:.3,MAX_REGION_RIPS:100,MAX_RIPS:1e3,RANDOM_RIP_FRACTION:.3,MIN_ALLOWED_BOARD_SCORE:-1e4},forceCenterFirst:!0,regionMemoryPfMap:new Map}]}),hc("uniformPortDistributionSolver",ci,t=>[{nodeWithPortPoints:t.portPointPathingSolver?.getNodesWithPortPoints()??[],inputNodesWithPortPoints:this.inputNodeWithPortPoints,minTraceWidth:t.minTraceWidth,obstacles:t.srj.obstacles,layerCount:t.srj.layerCount}]),hc("highDensityRouteSolver",Ye,t=>[{nodePortPoints:t.uniformPortDistributionSolver?.getOutput()??t.multiSectionPortPointOptimizer?.getNodesWithPortPoints()??t.portPointPathingSolver?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap,viaDiameter:t.viaDiameter,traceWidth:t.minTraceWidth}]),hc("highDensityStitchSolver",rn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount,defaultViaDiameter:t.viaDiameter}]),hc("traceSimplificationSolver",Ts,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}]),hc("traceWidthSolver",hi,t=>[{hdRoutes:t.traceSimplificationSolver.simplifiedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,minTraceWidth:t.minTraceWidth,connection:t.srj.connections,layerCount:t.srj.layerCount}])];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(),o=this.singleLayerNodeMerger?.visualize(),s=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.uniformPortDistributionSolver?.visualize(),l=this.highDensityRouteSolver?.visualize(),u=this.highDensityStitchSolver?.visualize(),p=this.traceSimplificationSolver?.visualize(),m=this.srj.outline,f=[];if(f.push({points:[{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.minY??-50},{x:this.srj.bounds?.maxX??50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.maxY??50},{x:this.srj.bounds?.minX??-50,y:this.srj.bounds?.minY??-50}],strokeColor:"rgba(255,0,0,0.25)"}),m&&m.length>=2){const t=m.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),f.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const y={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:f},x=[y,t,e,n,o,s,i,r,a,c,h,d,l?g(y,l):null,u,p,this.solved?g(y,an(this.getOutputSimpleRouteJson())):null].filter(Boolean);return g(...x)}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.traceWidthSolver?.getHdRoutesWithWidths()??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 o=n.netConnectionName??this.srj.connections.find(t=>t.name===n.name)?.netConnectionName,s=e.filter(t=>t.connectionName===n.name);for(let e=0;e<s.length;e++){const i=s[e],r={type:"pcb_trace",pcb_trace_id:`${n.name}_${e}`,connection_name:o??n.rootConnectionName??n.name,route:Ve(i,this.srj.layerCount)};t.push(r)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},lc=class extends fi{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)||[],o=n.layers&&n.layers.length>0?Array.from(new Set(n.layers.map(t=>Be(t,this.srj.layerCount)))).sort((t,e)=>t-e):Array.from({length:this.srj.layerCount},(t,e)=>this.srj.layerCount-e-1);let s=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,o=e.center.y-e.height/2,c=e.center.y+e.height/2;s=Math.min(s,t),i=Math.max(i,n),r=Math.min(r,o),a=Math.max(a,c)}const c=i-s,h=a-r,d=(s+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>=s&&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===o.length?`z${o[0]}`:`z${o.join(",")}`,availableZ:o,_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=[],o=[];for(const t of e){const e=this.shouldNodeBeXYSubdivided(t),s=t.availableZ.length>1&&!e;if(e)o.push(t);else{if(s){const e=this.getZSubdivisionChildNodes(t);for(const t of e)!t._containsTarget&&this.shouldFilterNodeForObstacle(t)||(this.shouldNodeBeXYSubdivided(t)?o.push(t):(t._containsObstacle=!1,n.push(t)));continue}this.shouldFilterNodeForObstacle(t)&&!t._containsTarget||n.push(t)}}this.unfinishedNodes.push(...o),this.finishedNodes.push(...n)}},uc=.005,pc=class extends y{getSolverName(){return"SingleLayerNodeMergerSolver_OnlyMergeTargets"}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 o=0;o<=e;o++)n.push(new dn(t.filter(t=>t.availableZ[0]===o)));for(const e of t){const t=[],o=n[e.availableZ[0]].getNodesInArea(e.center.x,e.center.y,4*e.width,4*e.height);for(const n of o)n._containsTarget&&n._targetConnectionName!==e._targetConnectionName||e._containsTarget&&(!n._containsTarget||n._targetConnectionName!==e._targetConnectionName)||n.capacityMeshNodeId!==e.capacityMeshNodeId&&cn(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),o=this.nodeMap.get(e);return n.width*n.height-o.width*o.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 o=this.getAdjacentSameLayerUnprocessedNodes(e);if(0===o.length)return void this.nextBatchNodeIds.push(t);const s=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=o.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:o}=i[0],r=i.every(e=>e.width===t&&e.height===o);Math.abs(i.reduce((t,e)=>t+e.height,0)-e.height)<uc&&r&&(e.width+=t,e.center.x=e.center.x-t/2,s(i),n=!0)}const r=o.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:o}=r[0],i=r.every(e=>e.width===t&&e.height===o);Math.abs(r.reduce((t,e)=>t+e.height,0)-e.height)<uc&&i&&(e.width+=t,e.center.x=e.center.x+t/2,s(r),n=!0)}const a=o.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:o}=a[0],i=a.every(e=>e.width===t&&e.height===o);Math.abs(a.reduce((t,e)=>t+e.width,0)-e.width)<uc&&i&&(e.height+=o,e.center.y=e.center.y+o/2,s(a),n=!0)}const c=o.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:o}=c[0],i=c.every(e=>e.width===t&&e.height===o);Math.abs(c.reduce((t,e)=>t+e.width,0)-e.width)<uc&&i&&(e.height+=o,e.center.y=e.center.y-o/2,s(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(zi(e));const e=this.currentBatchNodeIds[this.currentBatchNodeIds.length-1];let n;e&&(n=this.getAdjacentSameLayerUnprocessedNodes(this.nodeMap.get(e)));for(const o of this.currentBatchNodeIds){const s=this.nodeMap.get(o);if(!this.absorbedNodeIds.has(o)&&s){const i=zi(s,{rectMargin:.01});o===e?i.stroke="rgba(0, 255, 0, 0.8)":n?.some(t=>t.capacityMeshNodeId===o)?i.stroke="rgba(128, 0, 128, 0.8)":i.stroke="rgba(255, 165, 0, 0.8)",i.layer=`z${s.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=zi(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}},mc=class extends y{getSolverName(){return"AssignableViaNodeMergerSolver"}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,o=Number.NEGATIVE_INFINITY,s=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),o=Math.max(o,c),s=Math.min(s,h),i=Math.max(i,d);for(const e of t.availableZ)r.add(e);t._containsTarget&&(a=!0)}const c=o-n,h=i-s,d=(n+o)/2,l=(s+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=zi(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=zi(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}},fc=class extends y{constructor(t){const{simpleRouteJson:e,nodes:n,edges:o,colorMap:s,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=o,this.colorMap=s??{},this.nodeMap=new Map(this.nodes.map(t=>[t.capacityMeshNodeId,t])),this.nodeEdgeMap=Es(this.edges);const a=this.nodes.filter(t=>t._containsTarget);this.unprocessedConnectionPairs=Bt(this.simpleRouteJson.connections.map(t=>{const[e,n]=t.pointsToConnect;return{start:a.find(t=>Pt(t.center,e)<t.width/2),end:a.find(t=>Pt(t.center,n)<t.width/2),connection:t}}),this.hyperParameters.SHUFFLE_SEED??0),this.viaNodes=this.nodes.filter(t=>t.availableZ.length>1)}getSolverName(){return"AssignableViaCapacityPathingSolver_DirectiveSubOptimal"}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 o=this._dist(e,t.start);return this._dist(n,t.start)<o?n:e});this.closestViaForConnectionStartMap.set(t,n);const o=e.reduce((e,n)=>{const o=this._dist(e,t.end);return this._dist(n,t.end)<o?n:e});this.closestViaForConnectionEndMap.set(t,o)}}}_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),o={prevCandidate:null,node:e,g:0,h:t,f:this.GREEDY_MULTIPLIER*t};this.queuedCandidateNodes.push(o)}let o;for(this.queuedCandidateNodes.sort((t,e)=>t.f-e.f);this.queuedCandidateNodes.length&&!o;){const t=this.queuedCandidateNodes.shift();this.visitedNodes.has(t.node.capacityMeshNodeId)||(o=t)}if(!o)return this.failed=!0,void(this.error="No viable candidates left");if(this.visitedNodes.add(o.node.capacityMeshNodeId),o.node.capacityMeshNodeId===n.capacityMeshNodeId){const e=[];let n=o;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 s=this.getNeighbors(o.node);for(const t of s){const e=t.capacityMeshNodeId;if(this.visitedNodes.has(e))continue;const s=this.computeG(o,t,n),i=this.computeH(o,t,n),r=s+this.GREEDY_MULTIPLIER*i,a=this.queuedCandidateNodes.findIndex(t=>t.node.capacityMeshNodeId===e);if(a>=0){if(this.queuedCandidateNodes[a].g<=s)continue;this.queuedCandidateNodes.splice(a,1)}this.queuedCandidateNodes.push({prevCandidate:o,node:t,g:s,h:i,f:r})}}getNeighbors(t){const e=new Set,n=this.nodeEdgeMap.get(t.capacityMeshNodeId)??[];for(const o of n){const[n,s]=o.nodeIds,i=n===t.capacityMeshNodeId?s:n,r=this.nodeMap.get(i);r&&e.add(r)}const o=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!==o&&!t.availableZ.includes(o)))))}clearCandidateNodes(){this.queuedCandidateNodes=[],this.visitedNodes=new Set}computeG(t,e,n){const o=this._dist(t.node,e);return t.g+o}computeH(t,e,n){return this._dist(e,n)}createSolvedRoute(t,e){const n=[];for(let e=0;e<t.length;e++){const o=t[e];o.path?0===e?n.push(...o.path):n.push(...o.path.slice(1)):(0===e&&n.push(o.start),e===t.length-1&&n.push(o.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 o=this.getClosestVia(t.start),s=this.getFarVia(o,t.end),i=t.start.availableZ[0]??0,r=t.end.availableZ[0]??0,a=[];return a.push({start:t.start,end:o,solved:!1,layer:i}),i===r?(a.push({start:o,end:s,solved:!1,layer:0===i?1:0}),a.push({start:s,end:t.end,solved:!1,layer:r})):a.push({start:o,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 o=this.hyperParameters.MAX_CLOSEST_VIA_SKIP??0;if(o>0&&n.length>1){const t=Yt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length),e=Math.floor(t()*(o+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,o=new Set;for(const[t,e]of this.closestViaForConnectionStartMap)t!==this.activeConnectionPair&&o.add(e.capacityMeshNodeId);for(const[t,e]of this.closestViaForConnectionEndMap)t!==this.activeConnectionPair&&o.add(e.capacityMeshNodeId);const s=this.viaNodes.filter(e=>!this.usedNodeMap.has(e.capacityMeshNodeId)&&e.capacityMeshNodeId!==t.capacityMeshNodeId&&!e._completelyInsideObstacle&&!e._containsObstacle&&!o.has(e.capacityMeshNodeId)&&this._dist(e,t)>=n);if(0===s.length){const o=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(o.length>0)return o[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}s.sort((t,n)=>this._dist(t,e)-this._dist(n,e));const i=this.hyperParameters.MAX_FURTHEST_VIA_SKIP??0;if(i>0&&s.length>1){const t=Yt((this.hyperParameters.DIRECTIVE_SEED??0)+this.solvedRoutes.length+1e3),e=Math.floor(t()*(i+1));return s[Math.min(e,s.length-1)]}return s[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 o of this.nodes){const s=this.queuedCandidateNodes.some(t=>t.node.capacityMeshNodeId===o.capacityMeshNodeId),i=this.queuedCandidateNodes.find(t=>t.node.capacityMeshNodeId===o.capacityMeshNodeId);if(e(o.center)&&n(o.width)&&n(o.height)){const e=zi(o,{rectMargin:.025,zOffset:.01});t.rects.push({...e,fill:s?"rgba(255, 128, 255, 0.5)":o._containsTarget?"rgba(0, 150, 255, 0.15)":o._containsObstacle?"rgba(255, 0, 0, 0.1)":"rgba(200, 200, 200, 0.05)",label:[`ID: ${o.capacityMeshNodeId}`,`Size: ${o.width.toFixed(2)}x${o.height.toFixed(2)}`,`Z: ${o.availableZ.join(", ")}`,i?`g: ${i.g.toFixed(2)}`:"",i?`h: ${i.h.toFixed(2)}`:"",i?`f: ${i.f.toFixed(2)}`:"",o._containsTarget?"TARGET":"",o._containsObstacle?"OBSTACLE":""].filter(t=>t).join("\n")})}}for(const n of this.edges){const[o,s]=n.nodeIds,i=this.nodeMap.get(o),r=this.nodeMap.get(s);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 o=this.solvedRoutes[n],s=o.path,i="blue";for(let o=0;o<s.length-1;o++){const r=s[o],a=s[o+1];if(r?.center&&a?.center&&e(r.center)&&e(a.center)){const e=r.availableZ.includes(1)&&a.availableZ.includes(1),o=n%5*.02;t.lines.push({points:[{x:r.center.x+o,y:r.center.y+o},{x:a.center.x+o,y:a.center.y+o}],strokeColor:i,strokeDash:e?"5 5":void 0})}}if(s.length>0){const n=s[0],i=s[s.length-1];n?.center&&e(n.center)&&t.points.push({x:n.center.x,y:n.center.y,label:`START: ${o.connection.name}`}),i?.center&&e(i.center)&&t.points.push({x:i.center.x,y:i.center.y,label:`END: ${o.connection.name}`})}}if(this.solvedSubpaths)for(let n=0;n<this.solvedSubpaths.length;n++){const o=this.solvedSubpaths[n];if(o.path&&o.path.length>1)for(let n=0;n<o.path.length-1;n++){const s=o.path[n],i=o.path[n+1];s?.center&&i?.center&&e(s.center)&&e(i.center)&&t.lines.push({points:[s.center,i.center],strokeColor:"green",strokeDash:1===o.layer?"3 3":void 0})}}if(this.activeSubpath){const n=this.activeSubpath.start?.center,o=this.activeSubpath.end?.center;n&&o&&e(n)&&e(o)&&(t.lines.push({points:[n,o],strokeColor:"orange",strokeDash:"5 5"}),t.points.push({x:n.x,y:n.y,label:"ACTIVE START"}),t.points.push({x:o.x,y:o.y,label:"ACTIVE END"}))}const o=this.queuedCandidateNodes.slice(0,10).sort((t,e)=>t.f-e.f);for(let n=0;n<o.length;n++){const s=.6*(1-n/10),i=[];let r=o[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-s),strokeDash:1===this.activeSubpath?.layer?"4 2":void 0})}}if(this.activeConnectionPair){const n=this.activeConnectionPair.start?.center,o=this.activeConnectionPair.end?.center;n&&o&&e(n)&&e(o)&&t.lines.push({points:[n,o],strokeColor:"cyan",strokeDash:"20 5"})}if(this.ogUnprocessedSubpaths&&3===this.ogUnprocessedSubpaths.length){const[,o]=this.ogUnprocessedSubpaths;if(o.start?.center&&e(o.start.center)){const e=Math.max(o.start.width||0,o.start.height||0);n(e)&&e>0&&(t.circles.push({center:o.start.center,radius:e,stroke:"blue"}),t.points.push({x:o.start.center.x,y:o.start.center.y,label:"DIRECTIVE VIA 1"}))}if(o.end?.center&&e(o.end.center)){const e=Math.max(o.end.width||0,o.end.height||0);n(e)&&e>0&&(t.circles.push({center:o.end.center,radius:e,stroke:"purple"}),t.points.push({x:o.end.center.x,y:o.end.center.y,label:"DIRECTIVE VIA 2"}))}}if(this.queuedCandidateNodes.length>0)for(const n of this.queuedCandidateNodes){const o=n.node;o?.center&&e(o.center)&&t.circles.push({center:o.center,radius:.05,fill:"rgba(255, 255, 0, 0.6)",stroke:"yellow"})}if(this.visitedNodes.size>0)for(const n of this.visitedNodes){const o=this.nodeMap.get(n);o?.center&&e(o.center)&&t.circles.push({center:o.center,radius:.08,fill:"rgba(128, 128, 128, 0.5)",stroke:"gray"})}return t}},gc=class extends Zt{getSolverName(){return"HyperAssignableViaCapacityPathingSolver"}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,o=e>0?n/e:0;return t.iterations/t.MAX_ITERATIONS+(1-o)}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 fc({...this.constructorParams,hyperParameters:{...this.constructorParams.hyperParameters,...t}})}};function yc(t){const e=new Map;for(const n of t)e.set(n.capacityMeshNodeId,n);return e}function xc(t,e){return{x:(t.x+e.x)/2,y:(t.y+e.y)/2}}var vc=class extends y{getSolverName(){return"OffboardCapacityNodeSolver"}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=yc(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 o of n.offBoardConnectsTo)t.has(o)||t.set(o,[]),t.get(o).push(e)}this.pendingEdges=[];for(const[e,n]of t)if(n.length>1)for(let t=0;t<n.length;t++)for(let o=t+1;o<n.length;o++)this.pendingEdges.push({node1:n[t],node2:n[o],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(),o=this.createOffboardEdge(t,e,n);this.enhancedEdges.push(o),this.createdEdges.push(o)}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=[],o=new Set(this.shownNodes.map(t=>t.capacityMeshNodeId));for(const e of this.capacityEdges){if(e.isOffboardEdge)continue;if(o.has(e.nodeIds[0])||o.has(e.nodeIds[1])){const n=this.nodeMap.get(e.nodeIds[0]),o=this.nodeMap.get(e.nodeIds[1]);n&&o&&t.push({points:[n.center,o.center],strokeColor:"rgba(0, 200, 0, 0.5)",strokeWidth:.05})}}for(let t=0;t<this.shownNodes.length;t++){const o=this.shownNodes[t],s=o._assignedViaObstacle,i=t===this.shownNodes.length-1&&"showing_nodes"===this.animationState;n.push({center:o.center,width:o.width,height:o.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:o.center.x,y:o.center.y,color:i?"orange":"blue",label:`${i?"NEW: ":""}${o.capacityMeshNodeId}\n${s?.offBoardConnectsTo?.join(", ")||""}`})}for(let n=0;n<this.createdEdges.length;n++){const o=this.createdEdges[n],s=n===this.createdEdges.length-1&&"showing_edges"===this.animationState,i=this.nodeMap.get(o.nodeIds[0]),r=this.nodeMap.get(o.nodeIds[1]);if(i&&r){t.push({points:[i.center,r.center],strokeColor:s?"red":"orange",strokeWidth:s?.2:.1,strokeDasharray:"0.3,0.15"});const n=xc(i.center,r.center);e.push({x:n.x,y:n.y,color:s?"red":"orange",label:`${s?"NEW: ":""}⚡ ${o.offboardNetName}`})}}let s="Offboard Capacity Node Solver";switch(this.animationState){case"showing_nodes":s+=` - Showing nodes (${this.shownNodes.length}/${this.shownNodes.length+this.assignableNodes.length})`;break;case"showing_edges":s+=` - Creating edges (${this.createdEdges.length}/${this.createdEdges.length+this.pendingEdges.length})`;break;case"done":s+=` - Done (${this.shownNodes.length} nodes, ${this.createdEdges.length} edges)`}return{lines:t,points:e,rects:n,title:s}}getVirtualOffboardNodes(){return[]}getOffboardEdges(){return this.enhancedEdges.filter(t=>t.isOffboardEdge)}},Pc=class extends y{getSolverName(){return"OffboardPathFragmentSolver"}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:o}){super(),this.inputPaths=[...t],this.capacityEdges=e,this.originalConnections=o,this.nodeMap=yc(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 o=e[t];if(!o.isFragmentedPath)continue;const s=n.pointsToConnect.filter(t=>{for(const e of o.nodeIds){const n=this.nodeMap.get(e);if(n&&Ka(t,n))return!0}return!1}),i=0===t,r=i?o.nodeIds[o.nodeIds.length-1]:o.nodeIds[0],a=this.nodeMap.get(r);if(s.length>0&&a){const t=s[0],e={x:a.center.x,y:a.center.y,layer:Ge(t)},r=i?[...s,e]:[e,...s];this.fragmentedConnections.push({name:o.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 o=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]);o&&o.isOffboardEdge&&n.push(t)}if(0===n.length)return[t];const o=[];let s=0,i=0;for(const r of n){const n=e.slice(s,r+1);if(n.length>=1){const e=this.nextFragmentId++;o.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${i++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}s=r+1}if(s<e.length){const n=e.slice(s);if(n.length>=1){const e=this.nextFragmentId++;o.push({capacityPathId:`${t.capacityPathId}_frag_${e}`,connectionName:`${t.connectionName}_frag_${i++}`,rootConnectionName:t.rootConnectionName,nodeIds:n,isFragmentedPath:!0,mstPairConnectionName:t.connectionName})}}return o.length>0?o:[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((o,s)=>{if(o.isFragmentedPath){const i=s%2==0?"blue":"red";this.drawPath({path:o,color:i,lines:t,points:e,rects:n,labelPrefix:`Frag ${s}: `})}else this.drawPath({path:o,color:"green",lines:t,points:e,rects:n,labelPrefix:""})}),"showing_fragment"===this.animationState&&this.currentFragmentIndex>0){const o=this.fragmentedPaths.length-1;if(o>=0){const s=this.fragmentedPaths[o];s.isFragmentedPath&&this.drawPath({path:s,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]),o=this.nodeMap.get(e.nodeIds[1]);n&&o&&t.push({points:[n.center,o.center],strokeColor:"orange",strokeWidth:.15,strokeDasharray:"0.3,0.15"})}let o="Offboard Path Fragment Solver";return"showing_original_path"===this.animationState?o+=" - Analyzing path...":"showing_fragment"===this.animationState?o+=` - Fragment ${this.currentFragmentIndex}/${this.currentFragments.length}`:o+=` - Done (${this.fragmentedPaths.filter(t=>t.isFragmentedPath).length} fragments)`,{lines:t,points:e,rects:n,title:o}}drawPath(t){const{path:e,color:n,lines:o,points:s,rects:i,labelPrefix:r}=t,a=[];for(let t=0;t<e.nodeIds.length;t++){const o=e.nodeIds[t],c=this.nodeMap.get(o);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||s.push({x:c.center.x,y:c.center.y,color:n,label:`${r}${e.connectionName}\n${o}`}))}a.length>1&&o.push({points:a,strokeColor:n,strokeWidth:.1})}};function Sc(t,e,n,o={}){return{solverName:t,solverClass:e,getConstructorParams:n,onSolved:o.onSolved}}var Mc=class extends y{constructor(t,e={}){super(),this.srj=t,this.opts=e,this.srj=t,this.opts={...e},this.MAX_ITERATIONS=1e8;const n=this.opts;if(void 0===n.capacityDepth){const e=t.bounds.maxX-t.bounds.minX,o=t.bounds.maxY-t.bounds.minY,s=Math.max(e,o),i=n.targetMinCapacity??.5;n.capacityDepth=He(s,i)}this.connMap=je(t),this.colorMap=st(t,this.connMap),this.cacheProvider=void 0===n.cacheProvider?ut():null===n.cacheProvider?null:n.cacheProvider,this.startTimeOfPhase={},this.endTimeOfPhase={},this.timeSpentOnPhase={}}getSolverName(){return"AssignableAutoroutingPipeline1Solver"}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=[Sc("netToPointPairsSolver",xn,t=>[t.srj,t.colorMap],{onSolved:t=>{t.srjWithPointPairs=t.netToPointPairsSolver?.getNewSimpleRouteJson(),t.colorMap=st(t.srjWithPointPairs,this.connMap),t.connMap=je(t.srjWithPointPairs)}}),Sc("nodeSolver",lc,t=>[t.netToPointPairsSolver?.getNewSimpleRouteJson()||t.srj,t.opts],{onSolved:t=>{t.capacityNodes=t.nodeSolver?.finishedNodes}}),Sc("mergeAssignableViaNodes",mc,t=>[t.nodeSolver?.finishedNodes],{onSolved:t=>{t.capacityNodes=t.mergeAssignableViaNodes?.newNodes}}),Sc("singleLayerNodeMerger",pc,t=>[t.capacityNodes],{onSolved:t=>{t.capacityNodes=t.singleLayerNodeMerger?.newNodes}}),Sc("edgeSolver",ln,t=>[t.capacityNodes],{onSolved:t=>{t.capacityEdges=t.edgeSolver?.edges}}),Sc("offboardCapacityNodeSolver",vc,t=>[{capacityNodes:t.capacityNodes,capacityEdges:t.capacityEdges||[]}],{onSolved:t=>{t.capacityEdges=t.offboardCapacityNodeSolver?.enhancedEdges||t.capacityEdges}}),Sc("deadEndSolver",tr,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)))}}),Sc("initialPathingHyperSolver",gc,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)}}),Sc("offboardPathFragmentSolver",Pc,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 o=e.getFragmentedOriginalConnectionNames(),s=e.getFragmentedConnections();o.size>0&&t.srjWithPointPairs&&(t.srjWithPointPairs={...t.srjWithPointPairs,connections:[...t.srjWithPointPairs.connections.filter(t=>!o.has(t.name)),...s]},t.connMap=je(t.srjWithPointPairs))}}),Sc("edgeToPortSegmentSolver",gi,t=>[{nodes:t.capacityNodes,edges:t.capacityEdges||[],capacityPaths:t.offboardPathFragmentSolver?.getFragmentedPaths()||t.initialPathingSolver?.getCapacityPaths()||[],colorMap:t.colorMap}]),Sc("segmentToPointSolver",Si,t=>{const e=[];return t.edgeToPortSegmentSolver?.nodePortSegments&&t.edgeToPortSegmentSolver.nodePortSegments.forEach(t=>{e.push(...t)}),[{segments:e,colorMap:t.colorMap,nodes:t.capacityNodes}]}),Sc("unravelMultiSectionSolver",Oi,t=>[{assignedSegments:t.segmentToPointSolver?.solvedSegments||[],colorMap:t.colorMap,nodes:t.capacityNodes,cacheProvider:this.cacheProvider}]),Sc("highDensityRouteSolver",Ye,t=>[{nodePortPoints:t.unravelMultiSectionSolver?.getNodesWithPortPoints()??t.segmentToPointOptimizer?.getNodesWithPortPoints()??[],colorMap:t.colorMap,connMap:t.connMap}]),Sc("highDensityStitchSolver",rn,t=>[{connections:t.srjWithPointPairs.connections,hdRoutes:t.highDensityRouteSolver.routes,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Sc("uselessViaRemovalSolver1",ps,t=>[{unsimplifiedHdRoutes:t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Sc("multiSimplifiedPathSolver1",Cs,t=>[{unsimplifiedHdRoutes:t.uselessViaRemovalSolver1?.getOptimizedHdRoutes()||t.highDensityStitchSolver.mergedHdRoutes,obstacles:t.srj.obstacles,connMap:t.connMap,colorMap:t.colorMap,outline:t.srj.outline}]),Sc("uselessViaRemovalSolver2",ps,t=>[{unsimplifiedHdRoutes:t.multiSimplifiedPathSolver1.simplifiedHdRoutes,obstacles:t.srj.obstacles,colorMap:t.colorMap,layerCount:t.srj.layerCount}]),Sc("multiSimplifiedPathSolver2",Cs,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(),o=this.mergeAssignableViaNodes?.visualize(),s=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(),P=this.multiSimplifiedPathSolver2?.visualize(),S=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)"}),S&&S.length>=2){const t=S.map(t=>({x:t.x,y:t.y}));t.push({...t[0]}),M.push({points:t,strokeColor:"rgba(0, 136, 255, 0.95)"})}const b={points:[...this.srj.connections.flatMap(t=>t.pointsToConnect.map(e=>({...e,label:`${t.name} ${e.pcb_port_id??""}`})))],rects:[...(this.srj.obstacles??[]).map(t=>({...t,fill:t.layers?.includes("top")?"rgba(255,0,0,0.25)":t.layers?.includes("bottom")?"rgba(0,0,255,0.25)":"rgba(255,0,0,0.25)",label:t.layers?.join(", ")}))],lines:M},N=[b,t,e,n,o,s,i,r,a,c,h,d,l,u,p,m?g(b,m):null,f,y,v,x,P,this.solved?g(b,an(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 o of n){const n=o.netConnectionName,s=o.rootConnectionName,i=e.filter(t=>t.connectionName===o.name);for(let e=0;e<i.length;e++){const r=i[e],a={type:"pcb_trace",pcb_trace_id:`${o.name}_${e}`,connection_name:n??s??o.name,route:Ve(r,this.srj.layerCount)};t.push(a)}}return t}getOutputSimpleRouteJson(){return{...this.srj,traces:this.getOutputSimplifiedPcbTraces()}}},bc=1.8,Nc=.95,Ic=.8,Cc=.95,_c=class extends y{getSolverName(){return"SingleHighDensityRouteWithJumpersSolver"}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=Pt(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 o=this.boundsSize.width/this.cellStep,s=this.boundsSize.height/this.cellStep;for(;o*s>n**2&&!(this.cellStep>t.minDistBetweenEnteringPoints);)this.cellStep*=2,o=this.boundsSize.width/this.cellStep,s=this.boundsSize.height/this.cellStep;this.cellStep*=this.CELL_SIZE_FACTOR;const i=Math.abs(this.A.x-this.bounds.minX)<.001&&Math.abs(this.B.x-this.bounds.minX)<.001||Math.abs(this.A.x-this.bounds.maxX)<.001&&Math.abs(this.B.x-this.bounds.maxX)<.001||Math.abs(this.A.y-this.bounds.minY)<.001&&Math.abs(this.B.y-this.bounds.minY)<.001||Math.abs(this.A.y-this.bounds.maxY)<.001&&Math.abs(this.B.y-this.bounds.maxY)<.001;this.futureConnections&&0===this.futureConnections.length&&0===this.obstacleRoutes.length&&!i&&this.handleSimpleCases();const 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 bc+this.straightLineDistance*this.JUMPER_PENALTY_FACTOR}isNodeTooCloseToObstacle(t,e){e??=this.obstacleMargin;for(const n of this.obstacleRoutes){const o=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!o){const o=Tc(n);for(const n of o)if(vt(t,n.A,n.B)<this.traceThickness+e)return!0}for(const o of n.jumpers||[])if(this.isNodeTooCloseToJumper(t,o,e))return!0}return!1}isNodeTooCloseToJumper(t,e,n){const o=e.end.x-e.start.x,s=e.end.y-e.start.y,i=Math.abs(o)>Math.abs(s),r=(i?Ic:Cc)/2+n,a=(i?Cc:Ic)/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||!(Pt(t,this.B)<2*e||Pt(t,this.A)<2*e))&&n}doesPathToParentIntersectObstacle(t){const e=t.parent;if(!e)return!1;for(const n of this.obstacleRoutes){const o=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!o){for(const o of Tc(n))if(gt(t,e,o.A,o.B))return!0;for(const o of n.jumpers||[])if(this.doesSegmentIntersectJumperPads(t,e,o))return!0}}return!1}doesSegmentIntersectJumperPads(t,e,n){const o=this.obstacleMargin,s=n.end.x-n.start.x,i=n.end.y-n.start.y,r=Math.abs(s)>Math.abs(i),a=(r?Ic:Cc)/2+o,c=(r?Cc:Ic)/2+o;return!!this.doesSegmentIntersectRect(t,e,n.start,a,c)||!!this.doesSegmentIntersectRect(t,e,n.end,a,c)}doesSegmentIntersectRect(t,e,n,o,s){const i=n.x-o,r=n.x+o,a=n.y-s,c=n.y+s;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 o of this.obstacleRoutes){const s=this.connMap?.areIdsConnected?.(this.connectionName,o.connectionName);if(!s)for(const s of Tc(o))gt(t,e,s.A,s.B)&&n.push({A:s.A,B:s.B})}return n}computeHComponents(t){const e=Pt(t,this.roundedGoalPosition),n=this.getObstacleProximityPenalty(t),o=this.getEdgeProximityPenalty(t),s=this.getFutureConnectionStartEndPenalty(t),i=this.getFutureConnectionLinePenalty(t),r=t.parent,a=r?.hComponents,c=r?Pt(t,r):0,h=(t,n)=>{if(void 0===n||c<1e-9||e<1e-9)return t;const o=(t-n)/c;return(t+Math.max(0,t+o*e))/2},d=h(n,a?.obstacleProximityRate),l=h(o,a?.edgeProximityRate),u=h(s,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:o,futureConnectionStartEndProximityRate:s,futureConnectionLineRate:i}}computeH(t){return this.computeHComponents(t).total}computeGComponents(t){const e=t.parent,n=e?Pt(t,e):0,o=e?.gComponents??{distFromStart:0,weightedMmNearObstacle:0,weightedMmNearEdge:0,weightedMmNearFutureConnectionStartEnd:0,weightedMmNearFutureConnectionLine:0,jumperPenalty:0,jumperPadFutureConnectionPenalty:0,total:0},s=o.distFromStart+n,i=o.weightedMmNearObstacle+this.getObstacleProximityPenalty(t)*n,r=o.weightedMmNearEdge+this.getEdgeProximityPenalty(t)*n,a=o.weightedMmNearFutureConnectionStartEnd+this.getFutureConnectionStartEndPenalty(t)*n,c=o.weightedMmNearFutureConnectionLine+this.getFutureConnectionLinePenalty(t)*n;let h=o.jumperPenalty,d=o.jumperPadFutureConnectionPenalty;t.isJumperExit&&(h+=this.jumperPenaltyDistance,d+=this.getJumperPadFutureConnectionPenalty(t));return{distFromStart:s,weightedMmNearObstacle:i,weightedMmNearEdge:r,weightedMmNearFutureConnectionStartEnd:a,weightedMmNearFutureConnectionLine:c,jumperPenalty:h,jumperPadFutureConnectionPenalty:d,total:s+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 o of this.futureConnections)for(const s of o.points){const o=Pt(t,s);o<e&&(e=o,n=s)}return n}getFutureConnectionStartEndPenalty(t){let e=0;const n=this.getClosestFutureConnectionPoint(t);if(n){const o=Pt(t,n);if(o>this.FUTURE_CONNECTION_START_END_PROXIMITY)return 0;const s=o/this.FUTURE_CONNECTION_START_END_PROXIMITY;e=this.FUTURE_CONNECTION_START_END_PENALTY*(1-s)**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 o=vt(t,n.points[0],n.points[n.points.length-1]);e=Math.min(e,o)}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 o=1/0;for(const t of this.futureConnections)for(const s of t.points){const t=Pt(e,s),i=Pt(n,s),r=Math.min(t,i);o=Math.min(o,r)}if(o<this.FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY){const t=o/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 o=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(!o){for(const o of Tc(n))e=Math.min(e,vt(t,o.A,o.B));for(const o of n.jumpers||[])e=Math.min(e,this.distanceToJumperPads(t,o))}}return e}distanceToJumperPads(t,e){const n=e.end.x-e.start.x,o=e.end.y-e.start.y,s=Math.abs(n)>Math.abs(o),i=(s?Ic:Cc)/2,r=(s?Cc:Ic)/2;return Math.min(this.pointToRectDistance(t,e.start,i,r),this.pointToRectDistance(t,e.end,i,r))}pointToRectDistance(t,e,n,o){const s=Math.max(Math.abs(t.x-e.x)-n,0),i=Math.max(Math.abs(t.y-e.y)-o,0);return Math.hypot(s,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)),o=this.OBSTACLE_PROX_SIGMA;return this.OBSTACLE_PROX_PENALTY_FACTOR*Math.exp(-n/o)}getEdgeProximityPenalty(t){const e=this.getClearanceToEdge(t),n=this.EDGE_PROX_SIGMA;if(e>2*this.EDGE_PROX_SIGMA)return 0;const o=Pt(t,this.B),s=Math.min(1,o/(2*this.EDGE_PROX_SIGMA));return this.EDGE_PROX_PENALTY_FACTOR*Math.exp(-e/n)*s}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 o of n){const n=2*bc,s=t.x+o.dx*n,i=t.y+o.dy*n,r=this.findObstaclesBetween(t,{x:s,y:i});if(r.length>0)for(const n of r){const s=this.calculateJumperExit(t,n,o);s&&!this.exploredNodes.has(this.getNodeKey(s))&&(this.isNodeTooCloseToObstacle(s)||this.isNodeTooCloseToEdge(s)||!this.isJumperPlacementValid(t,s)||(s.gComponents=this.computeGComponents(s),s.hComponents=this.computeHComponents(s),s.g=s.gComponents.total,s.h=s.hComponents.total,s.f=this.computeF(s.g,s.h),e.push(s)))}}return e}calculateJumperExit(t,e,n){const o=bc,s=Math.sqrt(n.dx*n.dx+n.dy*n.dy),i=n.dx/s,r=n.dy/s,a=t.x+i*o,c=t.y+r*o;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,o=e.y-t.y,s=Math.abs(n)>Math.abs(o),i=(s?Ic:Cc)/2,r=(s?Cc:Ic)/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 o=this.connMap?.areIdsConnected?.(this.connectionName,n.connectionName);if(o)continue;const s=Tc(n);for(const n of s){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 o=this.getJumpersInPath(t);for(const t of o)if(this.doJumpersOverlap(n,t))return!1;return!0}doJumpersOverlap(t,e){const n=this.obstacleMargin,o=Math.min(t.start.x,t.end.x)-Nc/2-n,s=Math.max(t.start.x,t.end.x)+Nc/2+n,i=Math.min(t.start.y,t.end.y)-Nc/2-n,r=Math.max(t.start.y,t.end.y)+Nc/2+n,a=Math.min(e.start.x,e.end.x)-Nc/2-n,c=Math.max(e.start.x,e.end.x)+Nc/2+n,h=Math.min(e.start.y,e.end.y)-Nc/2-n,d=Math.max(e.start.y,e.end.y)+Nc/2+n;return!(s<a||o>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:o,maxY:s,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=Ec(c,o,n),l=Ec(h,i,s),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 o=e[t];o.isJumperExit&&o.jumperEntry&&n.push({route_type:"jumper",start:o.jumperEntry,end:{x:o.x,y:o.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=Pt(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 o=this.getNeighbors(t);for(const t of o)this.candidates.enqueue(t)}drawJumperPads(t,e,n,o,s){const i=e.end.x-e.start.x,r=e.end.y-e.start.y,a=Ic,c=Cc,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:o??"jumper",step:s}),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:o??"jumper",step:s}),t.lines.push({points:[e.start,e.end],strokeColor:"rgba(100, 100, 100, 0.8)",strokeWidth:.3*c,layer:o??"jumper-body",step:s})}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 o=0;o<n.route.length-1;o++)t.lines.push({points:[n.route[o],n.route[o+1]],strokeColor:"rgba(255, 0, 0, 0.75)",strokeWidth:n.traceThickness,label:"Obstacle Route",layer:`obstacle${e.toString()}`});for(const o of n.jumpers||[])this.drawJumperPads(t,o,"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 o=n.points[0],s=n.points[n.points.length-1];t.lines.push({points:[o,s],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[o,s]=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:o+this.initialNodeGridOffset.x,y:s+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 o=e[n],s=o.isJumperExit??!1,i=o.gComponents,r=o.hComponents,a=r?.distanceToGoal??0,c=[`Candidate #${n+1}${s?" (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: ${o.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: ${o.h.toFixed(2)}`),c.push(`f: ${o.f.toFixed(2)}`);const h=c.join("\n");t.points.push({x:o.x,y:o.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:o,maxX:s,maxY:i}=this.bounds;return t.lines.push({points:[{x:n,y:o},{x:s,y:o},{x:s,y:i},{x:n,y:i},{x:n,y:o}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}};function Tc(t){const e=[];for(let n=0;n<t.route.length-1;n++)if(t.route[n].z===t.route[n+1].z){const o=t.route[n],s=t.route[n+1],i=t.jumpers?.some(t=>{const e=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,n=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;return e||n});i||e.push({z:o.z,A:o,B:s})}return e}function Ec(t,e,n){return Math.max(e,Math.min(t,n))}var Rc=.8,wc=.95,Ac=class extends y{getSolverName(){return"IntraNodeSolverWithJumpers"}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 o=new Map;for(const{connectionName:t,rootConnectionName:n,x:s,y:i}of e.portPoints){const e=o.get(t);o.set(t,{rootConnectionName:e?.rootConnectionName??n,points:[...e?.points??[],{x:s,y:i,z:0}]})}this.unsolvedConnections=Array.from(o.entries().map(([t,{rootConnectionName:e,points:n}])=>({connectionName:t,rootConnectionName:e,points:n}))),this.hyperParameters.SHUFFLE_SEED&&(this.unsolvedConnections=Bt(this.unsolvedConnections,this.hyperParameters.SHUFFLE_SEED??0),this.unsolvedConnections=this.unsolvedConnections.map(({points:t,...e},n)=>({...e,points:Bt(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,o=Math.abs(e.x-n.x)<1e-6,s=Math.abs(e.y-n.y)<1e-6;if(o&&s)return}const{connectionName:e,rootConnectionName:n,points:o}=t;this.activeSubSolver=new _c({connectionName:e,rootConnectionName:n,minDistBetweenEnteringPoints:this.minDistBetweenEnteringPoints,bounds:kt(this.nodeWithPortPoints),A:{x:o[0].x,y:o[0].y,z:0},B:{x:o[o.length-1].x,y:o[o.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,o){const s=e.end.x-e.start.x,i=e.end.y-e.start.y,r=Rc,a=wc,c=Math.abs(s)>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 o=this.colorMap[n.connectionName]??"blue";for(let e=0;e<n.route.length-1;e++){const s=n.route[e],i=n.route[e+1];t.lines.push({points:[s,i],strokeColor:it(o,.2),layer:"route-layer-0",strokeWidth:n.traceThickness})}for(const s of n.jumpers)this.drawJumperPads(t,s,it(o,.5),e)}}const e=kt(this.nodeWithPortPoints),{minX:n,minY:o,maxX:s,maxY:i}=e;return t.lines.push({points:[{x:n,y:o},{x:s,y:o},{x:s,y:i},{x:n,y:i},{x:n,y:o}],strokeColor:"rgba(255, 0, 0, 0.25)",strokeDash:"4 4",layer:"border"}),t}};export{Mc as AssignableAutoroutingPipeline1Solver,wr as AssignableAutoroutingPipeline2,Ja as AssignableAutoroutingPipeline3,or as AutoroutingPipeline1_OriginalUnravel,li as AutoroutingPipelineSolver,dc as AutoroutingPipelineSolver3_HgPortPointPathing,ui as CapacityMeshSolver,Ha as CurvyIntraNodeSolver,Va as HighDensitySolver,ct as InMemoryCache,Ac as IntraNodeSolverWithJumpers,dt as LocalStorageCache,_c as SingleHighDensityRouteWithJumpersSolver,He as calculateOptimalCapacityDepth,an as convertSrjToGraphicsObject,ut as getGlobalInMemoryCache,lt as getGlobalLocalStorageCache,We as getTunedTotalCapacity1,pt as setupGlobalCaches};
2
2
  /*! Bundled license information:
3
3
 
4
4
  is-buffer/index.js: