@tscircuit/capacity-autorouter 0.0.49 → 0.0.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +150 -39
- package/dist/index.js +575 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../lib/utils/combineVisualizations.ts","../lib/solvers/BaseSolver.ts","../node_modules/@babel/runtime/helpers/esm/extends.js","../node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js","../node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","../node_modules/@babel/runtime/helpers/esm/inheritsLoose.js","../node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js","../node_modules/@babel/runtime/helpers/esm/isNativeFunction.js","../node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js","../node_modules/@babel/runtime/helpers/esm/construct.js","../node_modules/@babel/runtime/helpers/esm/wrapNativeSuper.js","../node_modules/polished/dist/polished.esm.js","../lib/solvers/colors.ts","../lib/utils/mapLayerNameToZ.ts","../lib/utils/getTunedTotalCapacity1.ts","../lib/data-structures/ObstacleTree.ts","../lib/data-structures/TargetTree.ts","../lib/solvers/CapacityMeshSolver/CapacityMeshNodeSolver1.ts","../lib/solvers/CapacityMeshSolver/CapacityMeshNodeSolver2_NodesUnderObstacles.ts","../lib/solvers/CapacityMeshSolver/getNodeEdgeMap.ts","../lib/solvers/CapacityMeshSolver/CapacityEdgeToPortSegmentSolver.ts","../lib/solvers/CapacityMeshSolver/CapacitySegmentToPointSolver.ts","../node_modules/@tscircuit/math-utils/src/line-intersections.ts","../node_modules/@tscircuit/math-utils/src/nearest-box.ts","../node_modules/@tscircuit/math-utils/src/segment-distance.ts","../lib/data-structures/SingleRouteCandidatePriorityQueue.ts","../lib/solvers/HighDensitySolver/SingleHighDensityRouteSolver.ts","../lib/solvers/HighDensitySolver/SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost.ts","../lib/utils/cloneAndShuffleArray.ts","../lib/utils/getBoundsFromNodeWithPortPoints.ts","../lib/utils/getMinDistBetweenEnteringPoints.ts","../lib/solvers/HighDensitySolver/IntraNodeSolver.ts","../lib/solvers/HyperParameterSupervisorSolver.ts","../lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/findCircleLineIntersections.ts","../lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/TwoCrossingRoutesHighDensitySolver.ts","../lib/utils/findClosestPointToABCWithinBounds.ts","../lib/utils/findPointToGetAroundCircle.ts","../lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/calculateSideTraversal.ts","../lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/SingleTransitionCrossingRouteSolver.ts","../lib/solvers/HyperHighDensitySolver/HyperSingleIntraNodeSolver.ts","../lib/utils/mergeRouteSegments.ts","../lib/solvers/HighDensitySolver/HighDensitySolver.ts","../node_modules/circuit-json-to-connectivity-map/src/findConnectedNetworks.ts","../node_modules/circuit-json-to-connectivity-map/src/ConnectivityMap.ts","../node_modules/circuit-json-to-connectivity-map/src/getSourcePortConnectivityMapFromCircuitJson.ts","../node_modules/circuit-json-to-connectivity-map/src/getFullConnectivityMapFromCircuitJson.ts","../node_modules/circuit-json-to-connectivity-map/src/PcbConnectivityMap.ts","../lib/utils/getConnectivityMapFromSimpleRouteJson.ts","../lib/solvers/NetToPointPairsSolver/buildMinimumSpanningTree.ts","../lib/solvers/NetToPointPairsSolver/NetToPointPairsSolver.ts","../lib/utils/mapZToLayerName.ts","../lib/utils/convertHdRouteToSimplifiedRoute.ts","../lib/solvers/RouteStitchingSolver/SingleHighDensityRouteStitchSolver.ts","../lib/solvers/RouteStitchingSolver/MultipleHighDensityRouteStitchSolver.ts","../tests/fixtures/convertSrjToGraphicsObject.ts","../lib/solvers/UnravelSolver/getNodesNearNode.ts","../lib/solvers/UnravelSolver/createPointModificationsHash.ts","../lib/solvers/UnravelSolver/hasZRangeOverlap.ts","../lib/solvers/UnravelSolver/getIssuesInSection.ts","../lib/solvers/UnravelSolver/getLogProbability.ts","../lib/solvers/UnravelSolver/applyOperationToPointModifications.ts","../lib/solvers/UnravelSolver/createSegmentPointMap.ts","../lib/solvers/UnravelSolver/UnravelSectionSolver.ts","../lib/solvers/UnravelSolver/getDedupedSegments.ts","../lib/solvers/UnravelSolver/calculateCrossingProbabilityOfFailure.ts","../lib/utils/getIntraNodeCrossingsFromSegmentPoints.ts","../lib/solvers/UnravelSolver/UnravelMultiSectionSolver.ts","../lib/utils/createRectFromCapacityNode.ts","../lib/solvers/CapacityPathingSolver/CapacityPathingSolver.ts","../lib/solvers/CapacityPathingSolver/CapacityPathingSolver5.ts","../lib/solvers/StrawSolver/StrawSolver.ts","../lib/utils/areNodesBordering.ts","../lib/data-structures/CapacityNodeTree.ts","../lib/solvers/SingleLayerNodeMerger/SingleLayerNodeMergerSolver.ts","../lib/solvers/SimplifiedPathSolver/SingleSimplifiedPathSolver.ts","../lib/utils/calculate45DegreePaths.ts","../lib/utils/minimumDistanceBetweenSegments.ts","../lib/data-structures/SegmentTree.ts","../lib/solvers/SimplifiedPathSolver/SingleSimplifiedPathSolver5_Deg45.ts","../lib/solvers/SimplifiedPathSolver/MultiSimplifiedPathSolver.ts","../lib/solvers/CapacityMeshSolver/CapacityMeshEdgeSolver.ts","../lib/solvers/CapacityMeshSolver/CapacityMeshEdgeSolver2_NodeTreeOptimization.ts","../lib/solvers/AutoroutingPipelineSolver.ts"],"sourcesContent":["import type { GraphicsObject } from \"graphics-debug\"\n\nexport const combineVisualizations = (\n ...visualizations: GraphicsObject[]\n): GraphicsObject => {\n const combined: GraphicsObject = {\n points: [],\n lines: [],\n circles: [],\n rects: [],\n }\n\n visualizations.forEach((viz, i) => {\n if (!viz) return\n if (viz.lines) {\n combined.lines = [\n ...(combined.lines || []),\n ...viz.lines.map((l) => ({ ...l, step: i })),\n ]\n }\n if (viz.points) {\n combined.points = [\n ...(combined.points || []),\n ...viz.points.map((p) => ({ ...p, step: i })),\n ]\n }\n if (viz.circles) {\n combined.circles = [\n ...(combined.circles || []),\n ...viz.circles.map((c) => ({ ...c, step: i })),\n ]\n }\n if (viz.rects) {\n combined.rects = [\n ...(combined.rects || []),\n ...viz.rects.map((r) => ({ ...r, step: i })),\n ]\n }\n })\n\n return combined\n}\n","import type { GraphicsObject } from \"graphics-debug\"\n\nexport class BaseSolver {\n MAX_ITERATIONS = 1000\n solved = false\n failed = false\n iterations = 0\n progress = 0\n error: string | null = null\n activeSubSolver?: BaseSolver | null\n failedSubSolvers?: BaseSolver[]\n timeToSolve?: number\n\n /** DO NOT OVERRIDE! Override _step() instead */\n step() {\n if (this.solved) return\n if (this.failed) return\n this.iterations++\n try {\n this._step()\n } catch (e) {\n this.error = `${this.constructor.name} error: ${e}`\n console.error(this.error)\n this.failed = true\n throw e\n }\n if (!this.solved && this.iterations > this.MAX_ITERATIONS) {\n this.error = `${this.constructor.name} did not converge`\n console.error(this.error)\n this.failed = true\n }\n }\n\n _step() {}\n\n getConstructorParams() {\n throw new Error(\"getConstructorParams not implemented\")\n }\n\n solve() {\n const startTime = Date.now()\n while (!this.solved && !this.failed) {\n this.step()\n }\n const endTime = Date.now()\n this.timeToSolve = endTime - startTime\n }\n\n visualize(): GraphicsObject {\n return {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n }\n\n /**\n * A lightweight version of the visualize method that can be used to stream\n * progress\n */\n preview(): GraphicsObject {\n return {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n }\n}\n","function _extends() {\n return _extends = Object.assign ? Object.assign.bind() : function (n) {\n for (var e = 1; e < arguments.length; e++) {\n var t = arguments[e];\n for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);\n }\n return n;\n }, _extends.apply(null, arguments);\n}\nexport { _extends as default };","function _assertThisInitialized(e) {\n if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n return e;\n}\nexport { _assertThisInitialized as default };","function _setPrototypeOf(t, e) {\n return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {\n return t.__proto__ = e, t;\n }, _setPrototypeOf(t, e);\n}\nexport { _setPrototypeOf as default };","import setPrototypeOf from \"./setPrototypeOf.js\";\nfunction _inheritsLoose(t, o) {\n t.prototype = Object.create(o.prototype), t.prototype.constructor = t, setPrototypeOf(t, o);\n}\nexport { _inheritsLoose as default };","function _getPrototypeOf(t) {\n return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {\n return t.__proto__ || Object.getPrototypeOf(t);\n }, _getPrototypeOf(t);\n}\nexport { _getPrototypeOf as default };","function _isNativeFunction(t) {\n try {\n return -1 !== Function.toString.call(t).indexOf(\"[native code]\");\n } catch (n) {\n return \"function\" == typeof t;\n }\n}\nexport { _isNativeFunction as default };","function _isNativeReflectConstruct() {\n try {\n var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));\n } catch (t) {}\n return (_isNativeReflectConstruct = function _isNativeReflectConstruct() {\n return !!t;\n })();\n}\nexport { _isNativeReflectConstruct as default };","import isNativeReflectConstruct from \"./isNativeReflectConstruct.js\";\nimport setPrototypeOf from \"./setPrototypeOf.js\";\nfunction _construct(t, e, r) {\n if (isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);\n var o = [null];\n o.push.apply(o, e);\n var p = new (t.bind.apply(t, o))();\n return r && setPrototypeOf(p, r.prototype), p;\n}\nexport { _construct as default };","import getPrototypeOf from \"./getPrototypeOf.js\";\nimport setPrototypeOf from \"./setPrototypeOf.js\";\nimport isNativeFunction from \"./isNativeFunction.js\";\nimport construct from \"./construct.js\";\nfunction _wrapNativeSuper(t) {\n var r = \"function\" == typeof Map ? new Map() : void 0;\n return _wrapNativeSuper = function _wrapNativeSuper(t) {\n if (null === t || !isNativeFunction(t)) return t;\n if (\"function\" != typeof t) throw new TypeError(\"Super expression must either be null or a function\");\n if (void 0 !== r) {\n if (r.has(t)) return r.get(t);\n r.set(t, Wrapper);\n }\n function Wrapper() {\n return construct(t, arguments, getPrototypeOf(this).constructor);\n }\n return Wrapper.prototype = Object.create(t.prototype, {\n constructor: {\n value: Wrapper,\n enumerable: !1,\n writable: !0,\n configurable: !0\n }\n }), setPrototypeOf(Wrapper, t);\n }, _wrapNativeSuper(t);\n}\nexport { _wrapNativeSuper as default };","import _extends from '@babel/runtime/helpers/esm/extends';\nimport _assertThisInitialized from '@babel/runtime/helpers/esm/assertThisInitialized';\nimport _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose';\nimport _wrapNativeSuper from '@babel/runtime/helpers/esm/wrapNativeSuper';\nimport _taggedTemplateLiteralLoose from '@babel/runtime/helpers/esm/taggedTemplateLiteralLoose';\n\nfunction last() {\n var _ref;\n return _ref = arguments.length - 1, _ref < 0 || arguments.length <= _ref ? undefined : arguments[_ref];\n}\nfunction negation(a) {\n return -a;\n}\nfunction addition(a, b) {\n return a + b;\n}\nfunction subtraction(a, b) {\n return a - b;\n}\nfunction multiplication(a, b) {\n return a * b;\n}\nfunction division(a, b) {\n return a / b;\n}\nfunction max() {\n return Math.max.apply(Math, arguments);\n}\nfunction min() {\n return Math.min.apply(Math, arguments);\n}\nfunction comma() {\n return Array.of.apply(Array, arguments);\n}\nvar defaultSymbols = {\n symbols: {\n '*': {\n infix: {\n symbol: '*',\n f: multiplication,\n notation: 'infix',\n precedence: 4,\n rightToLeft: 0,\n argCount: 2\n },\n symbol: '*',\n regSymbol: '\\\\*'\n },\n '/': {\n infix: {\n symbol: '/',\n f: division,\n notation: 'infix',\n precedence: 4,\n rightToLeft: 0,\n argCount: 2\n },\n symbol: '/',\n regSymbol: '/'\n },\n '+': {\n infix: {\n symbol: '+',\n f: addition,\n notation: 'infix',\n precedence: 2,\n rightToLeft: 0,\n argCount: 2\n },\n prefix: {\n symbol: '+',\n f: last,\n notation: 'prefix',\n precedence: 3,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: '+',\n regSymbol: '\\\\+'\n },\n '-': {\n infix: {\n symbol: '-',\n f: subtraction,\n notation: 'infix',\n precedence: 2,\n rightToLeft: 0,\n argCount: 2\n },\n prefix: {\n symbol: '-',\n f: negation,\n notation: 'prefix',\n precedence: 3,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: '-',\n regSymbol: '-'\n },\n ',': {\n infix: {\n symbol: ',',\n f: comma,\n notation: 'infix',\n precedence: 1,\n rightToLeft: 0,\n argCount: 2\n },\n symbol: ',',\n regSymbol: ','\n },\n '(': {\n prefix: {\n symbol: '(',\n f: last,\n notation: 'prefix',\n precedence: 0,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: '(',\n regSymbol: '\\\\('\n },\n ')': {\n postfix: {\n symbol: ')',\n f: undefined,\n notation: 'postfix',\n precedence: 0,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: ')',\n regSymbol: '\\\\)'\n },\n min: {\n func: {\n symbol: 'min',\n f: min,\n notation: 'func',\n precedence: 0,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: 'min',\n regSymbol: 'min\\\\b'\n },\n max: {\n func: {\n symbol: 'max',\n f: max,\n notation: 'func',\n precedence: 0,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: 'max',\n regSymbol: 'max\\\\b'\n }\n }\n};\nvar defaultSymbolMap = defaultSymbols;\n\n// based on https://github.com/styled-components/styled-components/blob/fcf6f3804c57a14dd7984dfab7bc06ee2edca044/src/utils/error.js\n/**\n * Parse errors.md and turn it into a simple hash of code: message\n * @private\n */\nvar ERRORS = {\n \"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\",\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\",\n \"3\": \"Passed an incorrect argument to a color function, please pass a string representation of a color.\\n\\n\",\n \"4\": \"Couldn't generate valid rgb string from %s, it returned %s.\\n\\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\",\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\",\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\",\n \"8\": \"Passed invalid argument to toColorString, please pass a RgbColor, RgbaColor, HslColor or HslaColor object.\\n\\n\",\n \"9\": \"Please provide a number of steps to the modularScale helper.\\n\\n\",\n \"10\": \"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\\n\\n\",\n \"11\": \"Invalid value passed as base to modularScale, expected number or em string but got \\\"%s\\\"\\n\\n\",\n \"12\": \"Expected a string ending in \\\"px\\\" or a number passed as the first argument to %s(), got \\\"%s\\\" instead.\\n\\n\",\n \"13\": \"Expected a string ending in \\\"px\\\" or a number passed as the second argument to %s(), got \\\"%s\\\" instead.\\n\\n\",\n \"14\": \"Passed invalid pixel value (\\\"%s\\\") to %s(), please pass a value like \\\"12px\\\" or 12.\\n\\n\",\n \"15\": \"Passed invalid base value (\\\"%s\\\") to %s(), please pass a value like \\\"12px\\\" or 12.\\n\\n\",\n \"16\": \"You must provide a template to this method.\\n\\n\",\n \"17\": \"You passed an unsupported selector state to this method.\\n\\n\",\n \"18\": \"minScreen and maxScreen must be provided as stringified numbers with the same units.\\n\\n\",\n \"19\": \"fromSize and toSize must be provided as stringified numbers with the same units.\\n\\n\",\n \"20\": \"expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\\n\\n\",\n \"21\": \"expects the objects in the first argument array to have the properties `prop`, `fromSize`, and `toSize`.\\n\\n\",\n \"22\": \"expects the first argument object to have the properties `prop`, `fromSize`, and `toSize`.\\n\\n\",\n \"23\": \"fontFace expects a name of a font-family.\\n\\n\",\n \"24\": \"fontFace expects either the path to the font file(s) or a name of a local copy.\\n\\n\",\n \"25\": \"fontFace expects localFonts to be an array.\\n\\n\",\n \"26\": \"fontFace expects fileFormats to be an array.\\n\\n\",\n \"27\": \"radialGradient requries at least 2 color-stops to properly render.\\n\\n\",\n \"28\": \"Please supply a filename to retinaImage() as the first argument.\\n\\n\",\n \"29\": \"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\\n\\n\",\n \"30\": \"Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\\n\\n\",\n \"31\": \"The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation\\n\\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\",\n \"33\": \"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation\\n\\n\",\n \"34\": \"borderRadius expects a radius value as a string or number as the second argument.\\n\\n\",\n \"35\": \"borderRadius expects one of \\\"top\\\", \\\"bottom\\\", \\\"left\\\" or \\\"right\\\" as the first argument.\\n\\n\",\n \"36\": \"Property must be a string value.\\n\\n\",\n \"37\": \"Syntax Error at %s.\\n\\n\",\n \"38\": \"Formula contains a function that needs parentheses at %s.\\n\\n\",\n \"39\": \"Formula is missing closing parenthesis at %s.\\n\\n\",\n \"40\": \"Formula has too many closing parentheses at %s.\\n\\n\",\n \"41\": \"All values in a formula must have the same unit or be unitless.\\n\\n\",\n \"42\": \"Please provide a number of steps to the modularScale helper.\\n\\n\",\n \"43\": \"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\\n\\n\",\n \"44\": \"Invalid value passed as base to modularScale, expected number or em/rem string but got %s.\\n\\n\",\n \"45\": \"Passed invalid argument to hslToColorString, please pass a HslColor or HslaColor object.\\n\\n\",\n \"46\": \"Passed invalid argument to rgbToColorString, please pass a RgbColor or RgbaColor object.\\n\\n\",\n \"47\": \"minScreen and maxScreen must be provided as stringified numbers with the same units.\\n\\n\",\n \"48\": \"fromSize and toSize must be provided as stringified numbers with the same units.\\n\\n\",\n \"49\": \"Expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\\n\\n\",\n \"50\": \"Expects the objects in the first argument array to have the properties prop, fromSize, and toSize.\\n\\n\",\n \"51\": \"Expects the first argument object to have the properties prop, fromSize, and toSize.\\n\\n\",\n \"52\": \"fontFace expects either the path to the font file(s) or a name of a local copy.\\n\\n\",\n \"53\": \"fontFace expects localFonts to be an array.\\n\\n\",\n \"54\": \"fontFace expects fileFormats to be an array.\\n\\n\",\n \"55\": \"fontFace expects a name of a font-family.\\n\\n\",\n \"56\": \"linearGradient requries at least 2 color-stops to properly render.\\n\\n\",\n \"57\": \"radialGradient requries at least 2 color-stops to properly render.\\n\\n\",\n \"58\": \"Please supply a filename to retinaImage() as the first argument.\\n\\n\",\n \"59\": \"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\\n\\n\",\n \"60\": \"Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\\n\\n\",\n \"61\": \"Property must be a string value.\\n\\n\",\n \"62\": \"borderRadius expects a radius value as a string or number as the second argument.\\n\\n\",\n \"63\": \"borderRadius expects one of \\\"top\\\", \\\"bottom\\\", \\\"left\\\" or \\\"right\\\" as the first argument.\\n\\n\",\n \"64\": \"The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation.\\n\\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\",\n \"66\": \"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation.\\n\\n\",\n \"67\": \"You must provide a template to this method.\\n\\n\",\n \"68\": \"You passed an unsupported selector state to this method.\\n\\n\",\n \"69\": \"Expected a string ending in \\\"px\\\" or a number passed as the first argument to %s(), got %s instead.\\n\\n\",\n \"70\": \"Expected a string ending in \\\"px\\\" or a number passed as the second argument to %s(), got %s instead.\\n\\n\",\n \"71\": \"Passed invalid pixel value %s to %s(), please pass a value like \\\"12px\\\" or 12.\\n\\n\",\n \"72\": \"Passed invalid base value %s to %s(), please pass a value like \\\"12px\\\" or 12.\\n\\n\",\n \"73\": \"Please provide a valid CSS variable.\\n\\n\",\n \"74\": \"CSS variable not found and no default was provided.\\n\\n\",\n \"75\": \"important requires a valid style object, got a %s instead.\\n\\n\",\n \"76\": \"fromSize and toSize must be provided as stringified numbers with the same units as minScreen and maxScreen.\\n\\n\",\n \"77\": \"remToPx expects a value in \\\"rem\\\" but you provided it in \\\"%s\\\".\\n\\n\",\n \"78\": \"base must be set in \\\"px\\\" or \\\"%\\\" but you set it in \\\"%s\\\".\\n\"\n};\n\n/**\n * super basic version of sprintf\n * @private\n */\nfunction format() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n var a = args[0];\n var b = [];\n var c;\n for (c = 1; c < args.length; c += 1) {\n b.push(args[c]);\n }\n b.forEach(function (d) {\n a = a.replace(/%[a-z]/, d);\n });\n return a;\n}\n\n/**\n * Create an error file out of errors.md for development and a simple web link to the full errors\n * in production mode.\n * @private\n */\nvar PolishedError = /*#__PURE__*/function (_Error) {\n _inheritsLoose(PolishedError, _Error);\n function PolishedError(code) {\n var _this;\n if (process.env.NODE_ENV === 'production') {\n _this = _Error.call(this, \"An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#\" + code + \" for more information.\") || this;\n } else {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n _this = _Error.call(this, format.apply(void 0, [ERRORS[code]].concat(args))) || this;\n }\n return _assertThisInitialized(_this);\n }\n return PolishedError;\n}( /*#__PURE__*/_wrapNativeSuper(Error));\n\nvar unitRegExp = /((?!\\w)a|na|hc|mc|dg|me[r]?|xe|ni(?![a-zA-Z])|mm|cp|tp|xp|q(?!s)|hv|xamv|nimv|wv|sm|s(?!\\D|$)|ged|darg?|nrut)/g;\n\n// Merges additional math functionality into the defaults.\nfunction mergeSymbolMaps(additionalSymbols) {\n var symbolMap = {};\n symbolMap.symbols = additionalSymbols ? _extends({}, defaultSymbolMap.symbols, additionalSymbols.symbols) : _extends({}, defaultSymbolMap.symbols);\n return symbolMap;\n}\nfunction exec(operators, values) {\n var _ref;\n var op = operators.pop();\n values.push(op.f.apply(op, (_ref = []).concat.apply(_ref, values.splice(-op.argCount))));\n return op.precedence;\n}\nfunction calculate(expression, additionalSymbols) {\n var symbolMap = mergeSymbolMaps(additionalSymbols);\n var match;\n var operators = [symbolMap.symbols['('].prefix];\n var values = [];\n var pattern = new RegExp( // Pattern for numbers\n \"\\\\d+(?:\\\\.\\\\d+)?|\" +\n // ...and patterns for individual operators/function names\n Object.keys(symbolMap.symbols).map(function (key) {\n return symbolMap.symbols[key];\n })\n // longer symbols should be listed first\n // $FlowFixMe\n .sort(function (a, b) {\n return b.symbol.length - a.symbol.length;\n })\n // $FlowFixMe\n .map(function (val) {\n return val.regSymbol;\n }).join('|') + \"|(\\\\S)\", 'g');\n pattern.lastIndex = 0; // Reset regular expression object\n\n var afterValue = false;\n do {\n match = pattern.exec(expression);\n var _ref2 = match || [')', undefined],\n token = _ref2[0],\n bad = _ref2[1];\n var notNumber = symbolMap.symbols[token];\n var notNewValue = notNumber && !notNumber.prefix && !notNumber.func;\n var notAfterValue = !notNumber || !notNumber.postfix && !notNumber.infix;\n\n // Check for syntax errors:\n if (bad || (afterValue ? notAfterValue : notNewValue)) {\n throw new PolishedError(37, match ? match.index : expression.length, expression);\n }\n if (afterValue) {\n // We either have an infix or postfix operator (they should be mutually exclusive)\n var curr = notNumber.postfix || notNumber.infix;\n do {\n var prev = operators[operators.length - 1];\n if ((curr.precedence - prev.precedence || prev.rightToLeft) > 0) break;\n // Apply previous operator, since it has precedence over current one\n } while (exec(operators, values)); // Exit loop after executing an opening parenthesis or function\n afterValue = curr.notation === 'postfix';\n if (curr.symbol !== ')') {\n operators.push(curr);\n // Postfix always has precedence over any operator that follows after it\n if (afterValue) exec(operators, values);\n }\n } else if (notNumber) {\n // prefix operator or function\n operators.push(notNumber.prefix || notNumber.func);\n if (notNumber.func) {\n // Require an opening parenthesis\n match = pattern.exec(expression);\n if (!match || match[0] !== '(') {\n throw new PolishedError(38, match ? match.index : expression.length, expression);\n }\n }\n } else {\n // number\n values.push(+token);\n afterValue = true;\n }\n } while (match && operators.length);\n if (operators.length) {\n throw new PolishedError(39, match ? match.index : expression.length, expression);\n } else if (match) {\n throw new PolishedError(40, match ? match.index : expression.length, expression);\n } else {\n return values.pop();\n }\n}\nfunction reverseString(str) {\n return str.split('').reverse().join('');\n}\n\n/**\n * Helper for doing math with CSS Units. Accepts a formula as a string. All values in the formula must have the same unit (or be unitless). Supports complex formulas utliziing addition, subtraction, multiplication, division, square root, powers, factorial, min, max, as well as parentheses for order of operation.\n *\n *In cases where you need to do calculations with mixed units where one unit is a [relative length unit](https://developer.mozilla.org/en-US/docs/Web/CSS/length#Relative_length_units), you will want to use [CSS Calc](https://developer.mozilla.org/en-US/docs/Web/CSS/calc).\n *\n * *warning* While we've done everything possible to ensure math safely evalutes formulas expressed as strings, you should always use extreme caution when passing `math` user provided values.\n * @example\n * // Styles as object usage\n * const styles = {\n * fontSize: math('12rem + 8rem'),\n * fontSize: math('(12px + 2px) * 3'),\n * fontSize: math('3px^2 + sqrt(4)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * fontSize: ${math('12rem + 8rem')};\n * fontSize: ${math('(12px + 2px) * 3')};\n * fontSize: ${math('3px^2 + sqrt(4)')};\n * `\n *\n * // CSS as JS Output\n *\n * div: {\n * fontSize: '20rem',\n * fontSize: '42px',\n * fontSize: '11px',\n * }\n */\nfunction math(formula, additionalSymbols) {\n var reversedFormula = reverseString(formula);\n var formulaMatch = reversedFormula.match(unitRegExp);\n\n // Check that all units are the same\n if (formulaMatch && !formulaMatch.every(function (unit) {\n return unit === formulaMatch[0];\n })) {\n throw new PolishedError(41);\n }\n var cleanFormula = reverseString(reversedFormula.replace(unitRegExp, ''));\n return \"\" + calculate(cleanFormula, additionalSymbols) + (formulaMatch ? reverseString(formulaMatch[0]) : '');\n}\n\nvar cssVariableRegex = /--[\\S]*/g;\n\n/**\n * Fetches the value of a passed CSS Variable in the :root scope, or otherwise returns a defaultValue if provided.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'background': cssVar('--background-color'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${cssVar('--background-color')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * 'background': 'red'\n * }\n */\nfunction cssVar(cssVariable, defaultValue) {\n if (!cssVariable || !cssVariable.match(cssVariableRegex)) {\n throw new PolishedError(73);\n }\n var variableValue;\n\n /* eslint-disable */\n /* istanbul ignore next */\n if (typeof document !== 'undefined' && document.documentElement !== null) {\n variableValue = getComputedStyle(document.documentElement).getPropertyValue(cssVariable);\n }\n /* eslint-enable */\n\n if (variableValue) {\n return variableValue.trim();\n } else if (defaultValue) {\n return defaultValue;\n }\n throw new PolishedError(74);\n}\n\n// @private\nfunction capitalizeString(string) {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nvar positionMap$1 = ['Top', 'Right', 'Bottom', 'Left'];\nfunction generateProperty(property, position) {\n if (!property) return position.toLowerCase();\n var splitProperty = property.split('-');\n if (splitProperty.length > 1) {\n splitProperty.splice(1, 0, position);\n return splitProperty.reduce(function (acc, val) {\n return \"\" + acc + capitalizeString(val);\n });\n }\n var joinedProperty = property.replace(/([a-z])([A-Z])/g, \"$1\" + position + \"$2\");\n return property === joinedProperty ? \"\" + property + position : joinedProperty;\n}\nfunction generateStyles(property, valuesWithDefaults) {\n var styles = {};\n for (var i = 0; i < valuesWithDefaults.length; i += 1) {\n if (valuesWithDefaults[i] || valuesWithDefaults[i] === 0) {\n styles[generateProperty(property, positionMap$1[i])] = valuesWithDefaults[i];\n }\n }\n return styles;\n}\n\n/**\n * Enables shorthand for direction-based properties. It accepts a property (hyphenated or camelCased) and up to four values that map to top, right, bottom, and left, respectively. You can optionally pass an empty string to get only the directional values as properties. You can also optionally pass a null argument for a directional value to ignore it.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...directionalProperty('padding', '12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${directionalProperty('padding', '12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'paddingTop': '12px',\n * 'paddingRight': '24px',\n * 'paddingBottom': '36px',\n * 'paddingLeft': '48px'\n * }\n */\nfunction directionalProperty(property) {\n for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n values[_key - 1] = arguments[_key];\n }\n // prettier-ignore\n var firstValue = values[0],\n _values$ = values[1],\n secondValue = _values$ === void 0 ? firstValue : _values$,\n _values$2 = values[2],\n thirdValue = _values$2 === void 0 ? firstValue : _values$2,\n _values$3 = values[3],\n fourthValue = _values$3 === void 0 ? secondValue : _values$3;\n var valuesWithDefaults = [firstValue, secondValue, thirdValue, fourthValue];\n return generateStyles(property, valuesWithDefaults);\n}\n\n/**\n * Check if a string ends with something\n * @private\n */\nfunction endsWith(string, suffix) {\n return string.substr(-suffix.length) === suffix;\n}\n\nvar cssRegex$1 = /^([+-]?(?:\\d+|\\d*\\.\\d+))([a-z]*|%)$/;\n\n/**\n * Returns a given CSS value minus its unit of measure.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * '--dimension': stripUnit('100px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * --dimension: ${stripUnit('100px')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * '--dimension': 100\n * }\n */\nfunction stripUnit(value) {\n if (typeof value !== 'string') return value;\n var matchedValue = value.match(cssRegex$1);\n return matchedValue ? parseFloat(value) : value;\n}\n\n/**\n * Factory function that creates pixel-to-x converters\n * @private\n */\nvar pxtoFactory = function pxtoFactory(to) {\n return function (pxval, base) {\n if (base === void 0) {\n base = '16px';\n }\n var newPxval = pxval;\n var newBase = base;\n if (typeof pxval === 'string') {\n if (!endsWith(pxval, 'px')) {\n throw new PolishedError(69, to, pxval);\n }\n newPxval = stripUnit(pxval);\n }\n if (typeof base === 'string') {\n if (!endsWith(base, 'px')) {\n throw new PolishedError(70, to, base);\n }\n newBase = stripUnit(base);\n }\n if (typeof newPxval === 'string') {\n throw new PolishedError(71, pxval, to);\n }\n if (typeof newBase === 'string') {\n throw new PolishedError(72, base, to);\n }\n return \"\" + newPxval / newBase + to;\n };\n};\nvar pixelsto = pxtoFactory;\n\n/**\n * Convert pixel value to ems. The default base value is 16px, but can be changed by passing a\n * second argument to the function.\n * @function\n * @param {string|number} pxval\n * @param {string|number} [base='16px']\n * @example\n * // Styles as object usage\n * const styles = {\n * 'height': em('16px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * height: ${em('16px')}\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * 'height': '1em'\n * }\n */\nvar em = pixelsto('em');\nvar em$1 = em;\n\nvar cssRegex = /^([+-]?(?:\\d+|\\d*\\.\\d+))([a-z]*|%)$/;\n\n/**\n * Returns a given CSS value and its unit as elements of an array.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * '--dimension': getValueAndUnit('100px')[0],\n * '--unit': getValueAndUnit('100px')[1],\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * --dimension: ${getValueAndUnit('100px')[0]};\n * --unit: ${getValueAndUnit('100px')[1]};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * '--dimension': 100,\n * '--unit': 'px',\n * }\n */\nfunction getValueAndUnit(value) {\n if (typeof value !== 'string') return [value, ''];\n var matchedValue = value.match(cssRegex);\n if (matchedValue) return [parseFloat(value), matchedValue[2]];\n return [value, undefined];\n}\n\n/**\n * Helper for targeting rules in a style block generated by polished modules that need !important-level specificity. Can optionally specify a rule (or rules) to target specific rules.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...important(cover())\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${important(cover())}\n * `\n *\n * // CSS as JS Output\n *\n * div: {\n * 'position': 'absolute !important',\n * 'top': '0 !important',\n * 'right: '0 !important',\n * 'bottom': '0 !important',\n * 'left: '0 !important'\n * }\n */\nfunction important(styleBlock, rules) {\n if (typeof styleBlock !== 'object' || styleBlock === null) {\n throw new PolishedError(75, typeof styleBlock);\n }\n var newStyleBlock = {};\n Object.keys(styleBlock).forEach(function (key) {\n if (typeof styleBlock[key] === 'object' && styleBlock[key] !== null) {\n newStyleBlock[key] = important(styleBlock[key], rules);\n } else if (!rules || rules && (rules === key || rules.indexOf(key) >= 0)) {\n newStyleBlock[key] = styleBlock[key] + \" !important\";\n } else {\n newStyleBlock[key] = styleBlock[key];\n }\n });\n return newStyleBlock;\n}\n\nvar ratioNames = {\n minorSecond: 1.067,\n majorSecond: 1.125,\n minorThird: 1.2,\n majorThird: 1.25,\n perfectFourth: 1.333,\n augFourth: 1.414,\n perfectFifth: 1.5,\n minorSixth: 1.6,\n goldenSection: 1.618,\n majorSixth: 1.667,\n minorSeventh: 1.778,\n majorSeventh: 1.875,\n octave: 2,\n majorTenth: 2.5,\n majorEleventh: 2.667,\n majorTwelfth: 3,\n doubleOctave: 4\n};\nfunction getRatio(ratioName) {\n return ratioNames[ratioName];\n}\n\n/**\n * Establish consistent measurements and spacial relationships throughout your projects by incrementing an em or rem value up or down a defined scale. We provide a list of commonly used scales as pre-defined variables.\n * @example\n * // Styles as object usage\n * const styles = {\n * // Increment two steps up the default scale\n * 'fontSize': modularScale(2)\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * // Increment two steps up the default scale\n * fontSize: ${modularScale(2)}\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * 'fontSize': '1.77689em'\n * }\n */\nfunction modularScale(steps, base, ratio) {\n if (base === void 0) {\n base = '1em';\n }\n if (ratio === void 0) {\n ratio = 1.333;\n }\n if (typeof steps !== 'number') {\n throw new PolishedError(42);\n }\n if (typeof ratio === 'string' && !ratioNames[ratio]) {\n throw new PolishedError(43);\n }\n var _ref = typeof base === 'string' ? getValueAndUnit(base) : [base, ''],\n realBase = _ref[0],\n unit = _ref[1];\n var realRatio = typeof ratio === 'string' ? getRatio(ratio) : ratio;\n if (typeof realBase === 'string') {\n throw new PolishedError(44, base);\n }\n return \"\" + realBase * Math.pow(realRatio, steps) + (unit || '');\n}\n\n/**\n * Convert pixel value to rems. The default base value is 16px, but can be changed by passing a\n * second argument to the function.\n * @function\n * @param {string|number} pxval\n * @param {string|number} [base='16px']\n * @example\n * // Styles as object usage\n * const styles = {\n * 'height': rem('16px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * height: ${rem('16px')}\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * 'height': '1rem'\n * }\n */\nvar rem = pixelsto('rem');\nvar rem$1 = rem;\n\nvar defaultFontSize = 16;\nfunction convertBase(base) {\n var deconstructedValue = getValueAndUnit(base);\n if (deconstructedValue[1] === 'px') {\n return parseFloat(base);\n }\n if (deconstructedValue[1] === '%') {\n return parseFloat(base) / 100 * defaultFontSize;\n }\n throw new PolishedError(78, deconstructedValue[1]);\n}\nfunction getBaseFromDoc() {\n /* eslint-disable */\n /* istanbul ignore next */\n if (typeof document !== 'undefined' && document.documentElement !== null) {\n var rootFontSize = getComputedStyle(document.documentElement).fontSize;\n return rootFontSize ? convertBase(rootFontSize) : defaultFontSize;\n }\n /* eslint-enable */\n /* istanbul ignore next */\n return defaultFontSize;\n}\n\n/**\n * Convert rem values to px. By default, the base value is pulled from the font-size property on the root element (if it is set in % or px). It defaults to 16px if not found on the root. You can also override the base value by providing your own base in % or px.\n * @example\n * // Styles as object usage\n * const styles = {\n * 'height': remToPx('1.6rem')\n * 'height': remToPx('1.6rem', '10px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * height: ${remToPx('1.6rem')}\n * height: ${remToPx('1.6rem', '10px')}\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * 'height': '25.6px',\n * 'height': '16px',\n * }\n */\nfunction remToPx(value, base) {\n var deconstructedValue = getValueAndUnit(value);\n if (deconstructedValue[1] !== 'rem' && deconstructedValue[1] !== '') {\n throw new PolishedError(77, deconstructedValue[1]);\n }\n var newBase = base ? convertBase(base) : getBaseFromDoc();\n return deconstructedValue[0] * newBase + \"px\";\n}\n\nvar functionsMap$3 = {\n back: 'cubic-bezier(0.600, -0.280, 0.735, 0.045)',\n circ: 'cubic-bezier(0.600, 0.040, 0.980, 0.335)',\n cubic: 'cubic-bezier(0.550, 0.055, 0.675, 0.190)',\n expo: 'cubic-bezier(0.950, 0.050, 0.795, 0.035)',\n quad: 'cubic-bezier(0.550, 0.085, 0.680, 0.530)',\n quart: 'cubic-bezier(0.895, 0.030, 0.685, 0.220)',\n quint: 'cubic-bezier(0.755, 0.050, 0.855, 0.060)',\n sine: 'cubic-bezier(0.470, 0.000, 0.745, 0.715)'\n};\n\n/**\n * String to represent common easing functions as demonstrated here: (github.com/jaukia/easie).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'transitionTimingFunction': easeIn('quad')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * transitionTimingFunction: ${easeIn('quad')};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'transitionTimingFunction': 'cubic-bezier(0.550, 0.085, 0.680, 0.530)',\n * }\n */\nfunction easeIn(functionName) {\n return functionsMap$3[functionName.toLowerCase().trim()];\n}\n\nvar functionsMap$2 = {\n back: 'cubic-bezier(0.680, -0.550, 0.265, 1.550)',\n circ: 'cubic-bezier(0.785, 0.135, 0.150, 0.860)',\n cubic: 'cubic-bezier(0.645, 0.045, 0.355, 1.000)',\n expo: 'cubic-bezier(1.000, 0.000, 0.000, 1.000)',\n quad: 'cubic-bezier(0.455, 0.030, 0.515, 0.955)',\n quart: 'cubic-bezier(0.770, 0.000, 0.175, 1.000)',\n quint: 'cubic-bezier(0.860, 0.000, 0.070, 1.000)',\n sine: 'cubic-bezier(0.445, 0.050, 0.550, 0.950)'\n};\n\n/**\n * String to represent common easing functions as demonstrated here: (github.com/jaukia/easie).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'transitionTimingFunction': easeInOut('quad')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * transitionTimingFunction: ${easeInOut('quad')};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'transitionTimingFunction': 'cubic-bezier(0.455, 0.030, 0.515, 0.955)',\n * }\n */\nfunction easeInOut(functionName) {\n return functionsMap$2[functionName.toLowerCase().trim()];\n}\n\nvar functionsMap$1 = {\n back: 'cubic-bezier(0.175, 0.885, 0.320, 1.275)',\n cubic: 'cubic-bezier(0.215, 0.610, 0.355, 1.000)',\n circ: 'cubic-bezier(0.075, 0.820, 0.165, 1.000)',\n expo: 'cubic-bezier(0.190, 1.000, 0.220, 1.000)',\n quad: 'cubic-bezier(0.250, 0.460, 0.450, 0.940)',\n quart: 'cubic-bezier(0.165, 0.840, 0.440, 1.000)',\n quint: 'cubic-bezier(0.230, 1.000, 0.320, 1.000)',\n sine: 'cubic-bezier(0.390, 0.575, 0.565, 1.000)'\n};\n\n/**\n * String to represent common easing functions as demonstrated here: (github.com/jaukia/easie).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'transitionTimingFunction': easeOut('quad')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * transitionTimingFunction: ${easeOut('quad')};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'transitionTimingFunction': 'cubic-bezier(0.250, 0.460, 0.450, 0.940)',\n * }\n */\nfunction easeOut(functionName) {\n return functionsMap$1[functionName.toLowerCase().trim()];\n}\n\n/**\n * Returns a CSS calc formula for linear interpolation of a property between two values. Accepts optional minScreen (defaults to '320px') and maxScreen (defaults to '1200px').\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * fontSize: between('20px', '100px', '400px', '1000px'),\n * fontSize: between('20px', '100px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * fontSize: ${between('20px', '100px', '400px', '1000px')};\n * fontSize: ${between('20px', '100px')}\n * `\n *\n * // CSS as JS Output\n *\n * h1: {\n * 'fontSize': 'calc(-33.33333333333334px + 13.333333333333334vw)',\n * 'fontSize': 'calc(-9.090909090909093px + 9.090909090909092vw)'\n * }\n */\nfunction between(fromSize, toSize, minScreen, maxScreen) {\n if (minScreen === void 0) {\n minScreen = '320px';\n }\n if (maxScreen === void 0) {\n maxScreen = '1200px';\n }\n var _getValueAndUnit = getValueAndUnit(fromSize),\n unitlessFromSize = _getValueAndUnit[0],\n fromSizeUnit = _getValueAndUnit[1];\n var _getValueAndUnit2 = getValueAndUnit(toSize),\n unitlessToSize = _getValueAndUnit2[0],\n toSizeUnit = _getValueAndUnit2[1];\n var _getValueAndUnit3 = getValueAndUnit(minScreen),\n unitlessMinScreen = _getValueAndUnit3[0],\n minScreenUnit = _getValueAndUnit3[1];\n var _getValueAndUnit4 = getValueAndUnit(maxScreen),\n unitlessMaxScreen = _getValueAndUnit4[0],\n maxScreenUnit = _getValueAndUnit4[1];\n if (typeof unitlessMinScreen !== 'number' || typeof unitlessMaxScreen !== 'number' || !minScreenUnit || !maxScreenUnit || minScreenUnit !== maxScreenUnit) {\n throw new PolishedError(47);\n }\n if (typeof unitlessFromSize !== 'number' || typeof unitlessToSize !== 'number' || fromSizeUnit !== toSizeUnit) {\n throw new PolishedError(48);\n }\n if (fromSizeUnit !== minScreenUnit || toSizeUnit !== maxScreenUnit) {\n throw new PolishedError(76);\n }\n var slope = (unitlessFromSize - unitlessToSize) / (unitlessMinScreen - unitlessMaxScreen);\n var base = unitlessToSize - slope * unitlessMaxScreen;\n return \"calc(\" + base.toFixed(2) + (fromSizeUnit || '') + \" + \" + (100 * slope).toFixed(2) + \"vw)\";\n}\n\n/**\n * CSS to contain a float (credit to CSSMojo).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...clearFix(),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${clearFix()}\n * `\n *\n * // CSS as JS Output\n *\n * '&::after': {\n * 'clear': 'both',\n * 'content': '\"\"',\n * 'display': 'table'\n * }\n */\nfunction clearFix(parent) {\n var _ref;\n if (parent === void 0) {\n parent = '&';\n }\n var pseudoSelector = parent + \"::after\";\n return _ref = {}, _ref[pseudoSelector] = {\n clear: 'both',\n content: '\"\"',\n display: 'table'\n }, _ref;\n}\n\n/**\n * CSS to fully cover an area. Can optionally be passed an offset to act as a \"padding\".\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...cover()\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${cover()}\n * `\n *\n * // CSS as JS Output\n *\n * div: {\n * 'position': 'absolute',\n * 'top': '0',\n * 'right: '0',\n * 'bottom': '0',\n * 'left: '0'\n * }\n */\nfunction cover(offset) {\n if (offset === void 0) {\n offset = 0;\n }\n return {\n position: 'absolute',\n top: offset,\n right: offset,\n bottom: offset,\n left: offset\n };\n}\n\n/**\n * CSS to represent truncated text with an ellipsis. You can optionally pass a max-width and number of lines before truncating.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...ellipsis('250px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${ellipsis('250px')}\n * `\n *\n * // CSS as JS Output\n *\n * div: {\n * 'display': 'inline-block',\n * 'maxWidth': '250px',\n * 'overflow': 'hidden',\n * 'textOverflow': 'ellipsis',\n * 'whiteSpace': 'nowrap',\n * 'wordWrap': 'normal'\n * }\n */\nfunction ellipsis(width, lines) {\n if (lines === void 0) {\n lines = 1;\n }\n var styles = {\n display: 'inline-block',\n maxWidth: width || '100%',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n wordWrap: 'normal'\n };\n return lines > 1 ? _extends({}, styles, {\n WebkitBoxOrient: 'vertical',\n WebkitLineClamp: lines,\n display: '-webkit-box',\n whiteSpace: 'normal'\n }) : styles;\n}\n\nfunction _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== \"undefined\" && o[Symbol.iterator] || o[\"@@iterator\"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }\n/**\n * Returns a set of media queries that resizes a property (or set of properties) between a provided fromSize and toSize. Accepts optional minScreen (defaults to '320px') and maxScreen (defaults to '1200px') to constrain the interpolation.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...fluidRange(\n * {\n * prop: 'padding',\n * fromSize: '20px',\n * toSize: '100px',\n * },\n * '400px',\n * '1000px',\n * )\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${fluidRange(\n * {\n * prop: 'padding',\n * fromSize: '20px',\n * toSize: '100px',\n * },\n * '400px',\n * '1000px',\n * )}\n * `\n *\n * // CSS as JS Output\n *\n * div: {\n * \"@media (min-width: 1000px)\": Object {\n * \"padding\": \"100px\",\n * },\n * \"@media (min-width: 400px)\": Object {\n * \"padding\": \"calc(-33.33333333333334px + 13.333333333333334vw)\",\n * },\n * \"padding\": \"20px\",\n * }\n */\nfunction fluidRange(cssProp, minScreen, maxScreen) {\n if (minScreen === void 0) {\n minScreen = '320px';\n }\n if (maxScreen === void 0) {\n maxScreen = '1200px';\n }\n if (!Array.isArray(cssProp) && typeof cssProp !== 'object' || cssProp === null) {\n throw new PolishedError(49);\n }\n if (Array.isArray(cssProp)) {\n var mediaQueries = {};\n var fallbacks = {};\n for (var _iterator = _createForOfIteratorHelperLoose(cssProp), _step; !(_step = _iterator()).done;) {\n var _extends2, _extends3;\n var obj = _step.value;\n if (!obj.prop || !obj.fromSize || !obj.toSize) {\n throw new PolishedError(50);\n }\n fallbacks[obj.prop] = obj.fromSize;\n mediaQueries[\"@media (min-width: \" + minScreen + \")\"] = _extends({}, mediaQueries[\"@media (min-width: \" + minScreen + \")\"], (_extends2 = {}, _extends2[obj.prop] = between(obj.fromSize, obj.toSize, minScreen, maxScreen), _extends2));\n mediaQueries[\"@media (min-width: \" + maxScreen + \")\"] = _extends({}, mediaQueries[\"@media (min-width: \" + maxScreen + \")\"], (_extends3 = {}, _extends3[obj.prop] = obj.toSize, _extends3));\n }\n return _extends({}, fallbacks, mediaQueries);\n } else {\n var _ref, _ref2, _ref3;\n if (!cssProp.prop || !cssProp.fromSize || !cssProp.toSize) {\n throw new PolishedError(51);\n }\n return _ref3 = {}, _ref3[cssProp.prop] = cssProp.fromSize, _ref3[\"@media (min-width: \" + minScreen + \")\"] = (_ref = {}, _ref[cssProp.prop] = between(cssProp.fromSize, cssProp.toSize, minScreen, maxScreen), _ref), _ref3[\"@media (min-width: \" + maxScreen + \")\"] = (_ref2 = {}, _ref2[cssProp.prop] = cssProp.toSize, _ref2), _ref3;\n }\n}\n\nvar dataURIRegex = /^\\s*data:([a-z]+\\/[a-z-]+(;[a-z-]+=[a-z-]+)?)?(;charset=[a-z0-9-]+)?(;base64)?,[a-z0-9!$&',()*+,;=\\-._~:@/?%\\s]*\\s*$/i;\nvar formatHintMap = {\n woff: 'woff',\n woff2: 'woff2',\n ttf: 'truetype',\n otf: 'opentype',\n eot: 'embedded-opentype',\n svg: 'svg',\n svgz: 'svg'\n};\nfunction generateFormatHint(format, formatHint) {\n if (!formatHint) return '';\n return \" format(\\\"\" + formatHintMap[format] + \"\\\")\";\n}\nfunction isDataURI(fontFilePath) {\n return !!fontFilePath.replace(/\\s+/g, ' ').match(dataURIRegex);\n}\nfunction generateFileReferences(fontFilePath, fileFormats, formatHint) {\n if (isDataURI(fontFilePath)) {\n return \"url(\\\"\" + fontFilePath + \"\\\")\" + generateFormatHint(fileFormats[0], formatHint);\n }\n var fileFontReferences = fileFormats.map(function (format) {\n return \"url(\\\"\" + fontFilePath + \".\" + format + \"\\\")\" + generateFormatHint(format, formatHint);\n });\n return fileFontReferences.join(', ');\n}\nfunction generateLocalReferences(localFonts) {\n var localFontReferences = localFonts.map(function (font) {\n return \"local(\\\"\" + font + \"\\\")\";\n });\n return localFontReferences.join(', ');\n}\nfunction generateSources(fontFilePath, localFonts, fileFormats, formatHint) {\n var fontReferences = [];\n if (localFonts) fontReferences.push(generateLocalReferences(localFonts));\n if (fontFilePath) {\n fontReferences.push(generateFileReferences(fontFilePath, fileFormats, formatHint));\n }\n return fontReferences.join(', ');\n}\n\n/**\n * CSS for a @font-face declaration. Defaults to check for local copies of the font on the user's machine. You can disable this by passing `null` to localFonts.\n *\n * @example\n * // Styles as object basic usage\n * const styles = {\n * ...fontFace({\n * 'fontFamily': 'Sans-Pro',\n * 'fontFilePath': 'path/to/file'\n * })\n * }\n *\n * // styled-components basic usage\n * const GlobalStyle = createGlobalStyle`${\n * fontFace({\n * 'fontFamily': 'Sans-Pro',\n * 'fontFilePath': 'path/to/file'\n * }\n * )}`\n *\n * // CSS as JS Output\n *\n * '@font-face': {\n * 'fontFamily': 'Sans-Pro',\n * 'src': 'url(\"path/to/file.eot\"), url(\"path/to/file.woff2\"), url(\"path/to/file.woff\"), url(\"path/to/file.ttf\"), url(\"path/to/file.svg\")',\n * }\n */\n\nfunction fontFace(_ref) {\n var fontFamily = _ref.fontFamily,\n fontFilePath = _ref.fontFilePath,\n fontStretch = _ref.fontStretch,\n fontStyle = _ref.fontStyle,\n fontVariant = _ref.fontVariant,\n fontWeight = _ref.fontWeight,\n _ref$fileFormats = _ref.fileFormats,\n fileFormats = _ref$fileFormats === void 0 ? ['eot', 'woff2', 'woff', 'ttf', 'svg'] : _ref$fileFormats,\n _ref$formatHint = _ref.formatHint,\n formatHint = _ref$formatHint === void 0 ? false : _ref$formatHint,\n _ref$localFonts = _ref.localFonts,\n localFonts = _ref$localFonts === void 0 ? [fontFamily] : _ref$localFonts,\n unicodeRange = _ref.unicodeRange,\n fontDisplay = _ref.fontDisplay,\n fontVariationSettings = _ref.fontVariationSettings,\n fontFeatureSettings = _ref.fontFeatureSettings;\n // Error Handling\n if (!fontFamily) throw new PolishedError(55);\n if (!fontFilePath && !localFonts) {\n throw new PolishedError(52);\n }\n if (localFonts && !Array.isArray(localFonts)) {\n throw new PolishedError(53);\n }\n if (!Array.isArray(fileFormats)) {\n throw new PolishedError(54);\n }\n var fontFaceDeclaration = {\n '@font-face': {\n fontFamily: fontFamily,\n src: generateSources(fontFilePath, localFonts, fileFormats, formatHint),\n unicodeRange: unicodeRange,\n fontStretch: fontStretch,\n fontStyle: fontStyle,\n fontVariant: fontVariant,\n fontWeight: fontWeight,\n fontDisplay: fontDisplay,\n fontVariationSettings: fontVariationSettings,\n fontFeatureSettings: fontFeatureSettings\n }\n };\n\n // Removes undefined fields for cleaner css object.\n return JSON.parse(JSON.stringify(fontFaceDeclaration));\n}\n\n/**\n * CSS to hide text to show a background image in a SEO-friendly way.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'backgroundImage': 'url(logo.png)',\n * ...hideText(),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * backgroundImage: url(logo.png);\n * ${hideText()};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'backgroundImage': 'url(logo.png)',\n * 'textIndent': '101%',\n * 'overflow': 'hidden',\n * 'whiteSpace': 'nowrap',\n * }\n */\nfunction hideText() {\n return {\n textIndent: '101%',\n overflow: 'hidden',\n whiteSpace: 'nowrap'\n };\n}\n\n/**\n * CSS to hide content visually but remain accessible to screen readers.\n * from [HTML5 Boilerplate](https://github.com/h5bp/html5-boilerplate/blob/9a176f57af1cfe8ec70300da4621fb9b07e5fa31/src/css/main.css#L121)\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...hideVisually(),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${hideVisually()};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'border': '0',\n * 'clip': 'rect(0 0 0 0)',\n * 'height': '1px',\n * 'margin': '-1px',\n * 'overflow': 'hidden',\n * 'padding': '0',\n * 'position': 'absolute',\n * 'whiteSpace': 'nowrap',\n * 'width': '1px',\n * }\n */\nfunction hideVisually() {\n return {\n border: '0',\n clip: 'rect(0 0 0 0)',\n height: '1px',\n margin: '-1px',\n overflow: 'hidden',\n padding: '0',\n position: 'absolute',\n whiteSpace: 'nowrap',\n width: '1px'\n };\n}\n\n/**\n * Generates a media query to target HiDPI devices.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * [hiDPI(1.5)]: {\n * width: 200px;\n * }\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${hiDPI(1.5)} {\n * width: 200px;\n * }\n * `\n *\n * // CSS as JS Output\n *\n * '@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n * only screen and (min--moz-device-pixel-ratio: 1.5),\n * only screen and (-o-min-device-pixel-ratio: 1.5/1),\n * only screen and (min-resolution: 144dpi),\n * only screen and (min-resolution: 1.5dppx)': {\n * 'width': '200px',\n * }\n */\nfunction hiDPI(ratio) {\n if (ratio === void 0) {\n ratio = 1.3;\n }\n return \"\\n @media only screen and (-webkit-min-device-pixel-ratio: \" + ratio + \"),\\n only screen and (min--moz-device-pixel-ratio: \" + ratio + \"),\\n only screen and (-o-min-device-pixel-ratio: \" + ratio + \"/1),\\n only screen and (min-resolution: \" + Math.round(ratio * 96) + \"dpi),\\n only screen and (min-resolution: \" + ratio + \"dppx)\\n \";\n}\n\nfunction constructGradientValue(literals) {\n var template = '';\n for (var _len = arguments.length, substitutions = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n substitutions[_key - 1] = arguments[_key];\n }\n for (var i = 0; i < literals.length; i += 1) {\n template += literals[i];\n if (i === substitutions.length - 1 && substitutions[i]) {\n var definedValues = substitutions.filter(function (substitute) {\n return !!substitute;\n });\n // Adds leading coma if properties preceed color-stops\n if (definedValues.length > 1) {\n template = template.slice(0, -1);\n template += \", \" + substitutions[i];\n // No trailing space if color-stops is the only param provided\n } else if (definedValues.length === 1) {\n template += \"\" + substitutions[i];\n }\n } else if (substitutions[i]) {\n template += substitutions[i] + \" \";\n }\n }\n return template.trim();\n}\n\nvar _templateObject$1;\n/**\n * CSS for declaring a linear gradient, including a fallback background-color. The fallback is either the first color-stop or an explicitly passed fallback color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...linearGradient({\n colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],\n toDirection: 'to top right',\n fallback: '#FFF',\n })\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${linearGradient({\n colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],\n toDirection: 'to top right',\n fallback: '#FFF',\n })}\n *`\n *\n * // CSS as JS Output\n *\n * div: {\n * 'backgroundColor': '#FFF',\n * 'backgroundImage': 'linear-gradient(to top right, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%)',\n * }\n */\nfunction linearGradient(_ref) {\n var colorStops = _ref.colorStops,\n fallback = _ref.fallback,\n _ref$toDirection = _ref.toDirection,\n toDirection = _ref$toDirection === void 0 ? '' : _ref$toDirection;\n if (!colorStops || colorStops.length < 2) {\n throw new PolishedError(56);\n }\n return {\n backgroundColor: fallback || colorStops[0].replace(/,\\s+/g, ',').split(' ')[0].replace(/,(?=\\S)/g, ', '),\n backgroundImage: constructGradientValue(_templateObject$1 || (_templateObject$1 = _taggedTemplateLiteralLoose([\"linear-gradient(\", \"\", \")\"])), toDirection, colorStops.join(', ').replace(/,(?=\\S)/g, ', '))\n };\n}\n\n/**\n * CSS to normalize abnormalities across browsers (normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css)\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...normalize(),\n * }\n *\n * // styled-components usage\n * const GlobalStyle = createGlobalStyle`${normalize()}`\n *\n * // CSS as JS Output\n *\n * html {\n * lineHeight: 1.15,\n * textSizeAdjust: 100%,\n * } ...\n */\nfunction normalize() {\n var _ref;\n return [(_ref = {\n html: {\n lineHeight: '1.15',\n textSizeAdjust: '100%'\n },\n body: {\n margin: '0'\n },\n main: {\n display: 'block'\n },\n h1: {\n fontSize: '2em',\n margin: '0.67em 0'\n },\n hr: {\n boxSizing: 'content-box',\n height: '0',\n overflow: 'visible'\n },\n pre: {\n fontFamily: 'monospace, monospace',\n fontSize: '1em'\n },\n a: {\n backgroundColor: 'transparent'\n },\n 'abbr[title]': {\n borderBottom: 'none',\n textDecoration: 'underline'\n }\n }, _ref[\"b,\\n strong\"] = {\n fontWeight: 'bolder'\n }, _ref[\"code,\\n kbd,\\n samp\"] = {\n fontFamily: 'monospace, monospace',\n fontSize: '1em'\n }, _ref.small = {\n fontSize: '80%'\n }, _ref[\"sub,\\n sup\"] = {\n fontSize: '75%',\n lineHeight: '0',\n position: 'relative',\n verticalAlign: 'baseline'\n }, _ref.sub = {\n bottom: '-0.25em'\n }, _ref.sup = {\n top: '-0.5em'\n }, _ref.img = {\n borderStyle: 'none'\n }, _ref[\"button,\\n input,\\n optgroup,\\n select,\\n textarea\"] = {\n fontFamily: 'inherit',\n fontSize: '100%',\n lineHeight: '1.15',\n margin: '0'\n }, _ref[\"button,\\n input\"] = {\n overflow: 'visible'\n }, _ref[\"button,\\n select\"] = {\n textTransform: 'none'\n }, _ref[\"button,\\n html [type=\\\"button\\\"],\\n [type=\\\"reset\\\"],\\n [type=\\\"submit\\\"]\"] = {\n WebkitAppearance: 'button'\n }, _ref[\"button::-moz-focus-inner,\\n [type=\\\"button\\\"]::-moz-focus-inner,\\n [type=\\\"reset\\\"]::-moz-focus-inner,\\n [type=\\\"submit\\\"]::-moz-focus-inner\"] = {\n borderStyle: 'none',\n padding: '0'\n }, _ref[\"button:-moz-focusring,\\n [type=\\\"button\\\"]:-moz-focusring,\\n [type=\\\"reset\\\"]:-moz-focusring,\\n [type=\\\"submit\\\"]:-moz-focusring\"] = {\n outline: '1px dotted ButtonText'\n }, _ref.fieldset = {\n padding: '0.35em 0.625em 0.75em'\n }, _ref.legend = {\n boxSizing: 'border-box',\n color: 'inherit',\n display: 'table',\n maxWidth: '100%',\n padding: '0',\n whiteSpace: 'normal'\n }, _ref.progress = {\n verticalAlign: 'baseline'\n }, _ref.textarea = {\n overflow: 'auto'\n }, _ref[\"[type=\\\"checkbox\\\"],\\n [type=\\\"radio\\\"]\"] = {\n boxSizing: 'border-box',\n padding: '0'\n }, _ref[\"[type=\\\"number\\\"]::-webkit-inner-spin-button,\\n [type=\\\"number\\\"]::-webkit-outer-spin-button\"] = {\n height: 'auto'\n }, _ref['[type=\"search\"]'] = {\n WebkitAppearance: 'textfield',\n outlineOffset: '-2px'\n }, _ref['[type=\"search\"]::-webkit-search-decoration'] = {\n WebkitAppearance: 'none'\n }, _ref['::-webkit-file-upload-button'] = {\n WebkitAppearance: 'button',\n font: 'inherit'\n }, _ref.details = {\n display: 'block'\n }, _ref.summary = {\n display: 'list-item'\n }, _ref.template = {\n display: 'none'\n }, _ref['[hidden]'] = {\n display: 'none'\n }, _ref), {\n 'abbr[title]': {\n textDecoration: 'underline dotted'\n }\n }];\n}\n\nvar _templateObject;\n/**\n * CSS for declaring a radial gradient, including a fallback background-color. The fallback is either the first color-stop or an explicitly passed fallback color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...radialGradient({\n * colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],\n * extent: 'farthest-corner at 45px 45px',\n * position: 'center',\n * shape: 'ellipse',\n * })\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${radialGradient({\n * colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],\n * extent: 'farthest-corner at 45px 45px',\n * position: 'center',\n * shape: 'ellipse',\n * })}\n *`\n *\n * // CSS as JS Output\n *\n * div: {\n * 'backgroundColor': '#00FFFF',\n * 'backgroundImage': 'radial-gradient(center ellipse farthest-corner at 45px 45px, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%)',\n * }\n */\nfunction radialGradient(_ref) {\n var colorStops = _ref.colorStops,\n _ref$extent = _ref.extent,\n extent = _ref$extent === void 0 ? '' : _ref$extent,\n fallback = _ref.fallback,\n _ref$position = _ref.position,\n position = _ref$position === void 0 ? '' : _ref$position,\n _ref$shape = _ref.shape,\n shape = _ref$shape === void 0 ? '' : _ref$shape;\n if (!colorStops || colorStops.length < 2) {\n throw new PolishedError(57);\n }\n return {\n backgroundColor: fallback || colorStops[0].split(' ')[0],\n backgroundImage: constructGradientValue(_templateObject || (_templateObject = _taggedTemplateLiteralLoose([\"radial-gradient(\", \"\", \"\", \"\", \")\"])), position, shape, extent, colorStops.join(', '))\n };\n}\n\n/**\n * A helper to generate a retina background image and non-retina\n * background image. The retina background image will output to a HiDPI media query. The mixin uses\n * a _2x.png filename suffix by default.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...retinaImage('my-img')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${retinaImage('my-img')}\n * `\n *\n * // CSS as JS Output\n * div {\n * backgroundImage: 'url(my-img.png)',\n * '@media only screen and (-webkit-min-device-pixel-ratio: 1.3),\n * only screen and (min--moz-device-pixel-ratio: 1.3),\n * only screen and (-o-min-device-pixel-ratio: 1.3/1),\n * only screen and (min-resolution: 144dpi),\n * only screen and (min-resolution: 1.5dppx)': {\n * backgroundImage: 'url(my-img_2x.png)',\n * }\n * }\n */\nfunction retinaImage(filename, backgroundSize, extension, retinaFilename, retinaSuffix) {\n var _ref;\n if (extension === void 0) {\n extension = 'png';\n }\n if (retinaSuffix === void 0) {\n retinaSuffix = '_2x';\n }\n if (!filename) {\n throw new PolishedError(58);\n }\n // Replace the dot at the beginning of the passed extension if one exists\n var ext = extension.replace(/^\\./, '');\n var rFilename = retinaFilename ? retinaFilename + \".\" + ext : \"\" + filename + retinaSuffix + \".\" + ext;\n return _ref = {\n backgroundImage: \"url(\" + filename + \".\" + ext + \")\"\n }, _ref[hiDPI()] = _extends({\n backgroundImage: \"url(\" + rFilename + \")\"\n }, backgroundSize ? {\n backgroundSize: backgroundSize\n } : {}), _ref;\n}\n\n/* eslint-disable key-spacing */\nvar functionsMap = {\n easeInBack: 'cubic-bezier(0.600, -0.280, 0.735, 0.045)',\n easeInCirc: 'cubic-bezier(0.600, 0.040, 0.980, 0.335)',\n easeInCubic: 'cubic-bezier(0.550, 0.055, 0.675, 0.190)',\n easeInExpo: 'cubic-bezier(0.950, 0.050, 0.795, 0.035)',\n easeInQuad: 'cubic-bezier(0.550, 0.085, 0.680, 0.530)',\n easeInQuart: 'cubic-bezier(0.895, 0.030, 0.685, 0.220)',\n easeInQuint: 'cubic-bezier(0.755, 0.050, 0.855, 0.060)',\n easeInSine: 'cubic-bezier(0.470, 0.000, 0.745, 0.715)',\n easeOutBack: 'cubic-bezier(0.175, 0.885, 0.320, 1.275)',\n easeOutCubic: 'cubic-bezier(0.215, 0.610, 0.355, 1.000)',\n easeOutCirc: 'cubic-bezier(0.075, 0.820, 0.165, 1.000)',\n easeOutExpo: 'cubic-bezier(0.190, 1.000, 0.220, 1.000)',\n easeOutQuad: 'cubic-bezier(0.250, 0.460, 0.450, 0.940)',\n easeOutQuart: 'cubic-bezier(0.165, 0.840, 0.440, 1.000)',\n easeOutQuint: 'cubic-bezier(0.230, 1.000, 0.320, 1.000)',\n easeOutSine: 'cubic-bezier(0.390, 0.575, 0.565, 1.000)',\n easeInOutBack: 'cubic-bezier(0.680, -0.550, 0.265, 1.550)',\n easeInOutCirc: 'cubic-bezier(0.785, 0.135, 0.150, 0.860)',\n easeInOutCubic: 'cubic-bezier(0.645, 0.045, 0.355, 1.000)',\n easeInOutExpo: 'cubic-bezier(1.000, 0.000, 0.000, 1.000)',\n easeInOutQuad: 'cubic-bezier(0.455, 0.030, 0.515, 0.955)',\n easeInOutQuart: 'cubic-bezier(0.770, 0.000, 0.175, 1.000)',\n easeInOutQuint: 'cubic-bezier(0.860, 0.000, 0.070, 1.000)',\n easeInOutSine: 'cubic-bezier(0.445, 0.050, 0.550, 0.950)'\n};\n/* eslint-enable key-spacing */\n\nfunction getTimingFunction(functionName) {\n return functionsMap[functionName];\n}\n\n/**\n * String to represent common easing functions as demonstrated here: (github.com/jaukia/easie).\n *\n * @deprecated - This will be deprecated in v5 in favor of `easeIn`, `easeOut`, `easeInOut`.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'transitionTimingFunction': timingFunctions('easeInQuad')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * transitionTimingFunction: ${timingFunctions('easeInQuad')};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'transitionTimingFunction': 'cubic-bezier(0.550, 0.085, 0.680, 0.530)',\n * }\n */\n\nfunction timingFunctions(timingFunction) {\n return getTimingFunction(timingFunction);\n}\n\nvar getBorderWidth = function getBorderWidth(pointingDirection, height, width) {\n var fullWidth = \"\" + width[0] + (width[1] || '');\n var halfWidth = \"\" + width[0] / 2 + (width[1] || '');\n var fullHeight = \"\" + height[0] + (height[1] || '');\n var halfHeight = \"\" + height[0] / 2 + (height[1] || '');\n switch (pointingDirection) {\n case 'top':\n return \"0 \" + halfWidth + \" \" + fullHeight + \" \" + halfWidth;\n case 'topLeft':\n return fullWidth + \" \" + fullHeight + \" 0 0\";\n case 'left':\n return halfHeight + \" \" + fullWidth + \" \" + halfHeight + \" 0\";\n case 'bottomLeft':\n return fullWidth + \" 0 0 \" + fullHeight;\n case 'bottom':\n return fullHeight + \" \" + halfWidth + \" 0 \" + halfWidth;\n case 'bottomRight':\n return \"0 0 \" + fullWidth + \" \" + fullHeight;\n case 'right':\n return halfHeight + \" 0 \" + halfHeight + \" \" + fullWidth;\n case 'topRight':\n default:\n return \"0 \" + fullWidth + \" \" + fullHeight + \" 0\";\n }\n};\nvar getBorderColor = function getBorderColor(pointingDirection, foregroundColor) {\n switch (pointingDirection) {\n case 'top':\n case 'bottomRight':\n return {\n borderBottomColor: foregroundColor\n };\n case 'right':\n case 'bottomLeft':\n return {\n borderLeftColor: foregroundColor\n };\n case 'bottom':\n case 'topLeft':\n return {\n borderTopColor: foregroundColor\n };\n case 'left':\n case 'topRight':\n return {\n borderRightColor: foregroundColor\n };\n default:\n throw new PolishedError(59);\n }\n};\n\n/**\n * CSS to represent triangle with any pointing direction with an optional background color.\n *\n * @example\n * // Styles as object usage\n *\n * const styles = {\n * ...triangle({ pointingDirection: 'right', width: '100px', height: '100px', foregroundColor: 'red' })\n * }\n *\n *\n * // styled-components usage\n * const div = styled.div`\n * ${triangle({ pointingDirection: 'right', width: '100px', height: '100px', foregroundColor: 'red' })}\n *\n *\n * // CSS as JS Output\n *\n * div: {\n * 'borderColor': 'transparent transparent transparent red',\n * 'borderStyle': 'solid',\n * 'borderWidth': '50px 0 50px 100px',\n * 'height': '0',\n * 'width': '0',\n * }\n */\nfunction triangle(_ref) {\n var pointingDirection = _ref.pointingDirection,\n height = _ref.height,\n width = _ref.width,\n foregroundColor = _ref.foregroundColor,\n _ref$backgroundColor = _ref.backgroundColor,\n backgroundColor = _ref$backgroundColor === void 0 ? 'transparent' : _ref$backgroundColor;\n var widthAndUnit = getValueAndUnit(width);\n var heightAndUnit = getValueAndUnit(height);\n if (isNaN(heightAndUnit[0]) || isNaN(widthAndUnit[0])) {\n throw new PolishedError(60);\n }\n return _extends({\n width: '0',\n height: '0',\n borderColor: backgroundColor\n }, getBorderColor(pointingDirection, foregroundColor), {\n borderStyle: 'solid',\n borderWidth: getBorderWidth(pointingDirection, heightAndUnit, widthAndUnit)\n });\n}\n\n/**\n * Provides an easy way to change the `wordWrap` property.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...wordWrap('break-word')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${wordWrap('break-word')}\n * `\n *\n * // CSS as JS Output\n *\n * const styles = {\n * overflowWrap: 'break-word',\n * wordWrap: 'break-word',\n * wordBreak: 'break-all',\n * }\n */\nfunction wordWrap(wrap) {\n if (wrap === void 0) {\n wrap = 'break-word';\n }\n var wordBreak = wrap === 'break-word' ? 'break-all' : wrap;\n return {\n overflowWrap: wrap,\n wordWrap: wrap,\n wordBreak: wordBreak\n };\n}\n\nfunction colorToInt(color) {\n return Math.round(color * 255);\n}\nfunction convertToInt(red, green, blue) {\n return colorToInt(red) + \",\" + colorToInt(green) + \",\" + colorToInt(blue);\n}\nfunction hslToRgb(hue, saturation, lightness, convert) {\n if (convert === void 0) {\n convert = convertToInt;\n }\n if (saturation === 0) {\n // achromatic\n return convert(lightness, lightness, lightness);\n }\n\n // formulae from https://en.wikipedia.org/wiki/HSL_and_HSV\n var huePrime = (hue % 360 + 360) % 360 / 60;\n var chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;\n var secondComponent = chroma * (1 - Math.abs(huePrime % 2 - 1));\n var red = 0;\n var green = 0;\n var blue = 0;\n if (huePrime >= 0 && huePrime < 1) {\n red = chroma;\n green = secondComponent;\n } else if (huePrime >= 1 && huePrime < 2) {\n red = secondComponent;\n green = chroma;\n } else if (huePrime >= 2 && huePrime < 3) {\n green = chroma;\n blue = secondComponent;\n } else if (huePrime >= 3 && huePrime < 4) {\n green = secondComponent;\n blue = chroma;\n } else if (huePrime >= 4 && huePrime < 5) {\n red = secondComponent;\n blue = chroma;\n } else if (huePrime >= 5 && huePrime < 6) {\n red = chroma;\n blue = secondComponent;\n }\n var lightnessModification = lightness - chroma / 2;\n var finalRed = red + lightnessModification;\n var finalGreen = green + lightnessModification;\n var finalBlue = blue + lightnessModification;\n return convert(finalRed, finalGreen, finalBlue);\n}\n\nvar namedColorMap = {\n aliceblue: 'f0f8ff',\n antiquewhite: 'faebd7',\n aqua: '00ffff',\n aquamarine: '7fffd4',\n azure: 'f0ffff',\n beige: 'f5f5dc',\n bisque: 'ffe4c4',\n black: '000',\n blanchedalmond: 'ffebcd',\n blue: '0000ff',\n blueviolet: '8a2be2',\n brown: 'a52a2a',\n burlywood: 'deb887',\n cadetblue: '5f9ea0',\n chartreuse: '7fff00',\n chocolate: 'd2691e',\n coral: 'ff7f50',\n cornflowerblue: '6495ed',\n cornsilk: 'fff8dc',\n crimson: 'dc143c',\n cyan: '00ffff',\n darkblue: '00008b',\n darkcyan: '008b8b',\n darkgoldenrod: 'b8860b',\n darkgray: 'a9a9a9',\n darkgreen: '006400',\n darkgrey: 'a9a9a9',\n darkkhaki: 'bdb76b',\n darkmagenta: '8b008b',\n darkolivegreen: '556b2f',\n darkorange: 'ff8c00',\n darkorchid: '9932cc',\n darkred: '8b0000',\n darksalmon: 'e9967a',\n darkseagreen: '8fbc8f',\n darkslateblue: '483d8b',\n darkslategray: '2f4f4f',\n darkslategrey: '2f4f4f',\n darkturquoise: '00ced1',\n darkviolet: '9400d3',\n deeppink: 'ff1493',\n deepskyblue: '00bfff',\n dimgray: '696969',\n dimgrey: '696969',\n dodgerblue: '1e90ff',\n firebrick: 'b22222',\n floralwhite: 'fffaf0',\n forestgreen: '228b22',\n fuchsia: 'ff00ff',\n gainsboro: 'dcdcdc',\n ghostwhite: 'f8f8ff',\n gold: 'ffd700',\n goldenrod: 'daa520',\n gray: '808080',\n green: '008000',\n greenyellow: 'adff2f',\n grey: '808080',\n honeydew: 'f0fff0',\n hotpink: 'ff69b4',\n indianred: 'cd5c5c',\n indigo: '4b0082',\n ivory: 'fffff0',\n khaki: 'f0e68c',\n lavender: 'e6e6fa',\n lavenderblush: 'fff0f5',\n lawngreen: '7cfc00',\n lemonchiffon: 'fffacd',\n lightblue: 'add8e6',\n lightcoral: 'f08080',\n lightcyan: 'e0ffff',\n lightgoldenrodyellow: 'fafad2',\n lightgray: 'd3d3d3',\n lightgreen: '90ee90',\n lightgrey: 'd3d3d3',\n lightpink: 'ffb6c1',\n lightsalmon: 'ffa07a',\n lightseagreen: '20b2aa',\n lightskyblue: '87cefa',\n lightslategray: '789',\n lightslategrey: '789',\n lightsteelblue: 'b0c4de',\n lightyellow: 'ffffe0',\n lime: '0f0',\n limegreen: '32cd32',\n linen: 'faf0e6',\n magenta: 'f0f',\n maroon: '800000',\n mediumaquamarine: '66cdaa',\n mediumblue: '0000cd',\n mediumorchid: 'ba55d3',\n mediumpurple: '9370db',\n mediumseagreen: '3cb371',\n mediumslateblue: '7b68ee',\n mediumspringgreen: '00fa9a',\n mediumturquoise: '48d1cc',\n mediumvioletred: 'c71585',\n midnightblue: '191970',\n mintcream: 'f5fffa',\n mistyrose: 'ffe4e1',\n moccasin: 'ffe4b5',\n navajowhite: 'ffdead',\n navy: '000080',\n oldlace: 'fdf5e6',\n olive: '808000',\n olivedrab: '6b8e23',\n orange: 'ffa500',\n orangered: 'ff4500',\n orchid: 'da70d6',\n palegoldenrod: 'eee8aa',\n palegreen: '98fb98',\n paleturquoise: 'afeeee',\n palevioletred: 'db7093',\n papayawhip: 'ffefd5',\n peachpuff: 'ffdab9',\n peru: 'cd853f',\n pink: 'ffc0cb',\n plum: 'dda0dd',\n powderblue: 'b0e0e6',\n purple: '800080',\n rebeccapurple: '639',\n red: 'f00',\n rosybrown: 'bc8f8f',\n royalblue: '4169e1',\n saddlebrown: '8b4513',\n salmon: 'fa8072',\n sandybrown: 'f4a460',\n seagreen: '2e8b57',\n seashell: 'fff5ee',\n sienna: 'a0522d',\n silver: 'c0c0c0',\n skyblue: '87ceeb',\n slateblue: '6a5acd',\n slategray: '708090',\n slategrey: '708090',\n snow: 'fffafa',\n springgreen: '00ff7f',\n steelblue: '4682b4',\n tan: 'd2b48c',\n teal: '008080',\n thistle: 'd8bfd8',\n tomato: 'ff6347',\n turquoise: '40e0d0',\n violet: 'ee82ee',\n wheat: 'f5deb3',\n white: 'fff',\n whitesmoke: 'f5f5f5',\n yellow: 'ff0',\n yellowgreen: '9acd32'\n};\n\n/**\n * Checks if a string is a CSS named color and returns its equivalent hex value, otherwise returns the original color.\n * @private\n */\nfunction nameToHex(color) {\n if (typeof color !== 'string') return color;\n var normalizedColorName = color.toLowerCase();\n return namedColorMap[normalizedColorName] ? \"#\" + namedColorMap[normalizedColorName] : color;\n}\n\nvar hexRegex = /^#[a-fA-F0-9]{6}$/;\nvar hexRgbaRegex = /^#[a-fA-F0-9]{8}$/;\nvar reducedHexRegex = /^#[a-fA-F0-9]{3}$/;\nvar reducedRgbaHexRegex = /^#[a-fA-F0-9]{4}$/;\nvar rgbRegex = /^rgb\\(\\s*(\\d{1,3})\\s*(?:,)?\\s*(\\d{1,3})\\s*(?:,)?\\s*(\\d{1,3})\\s*\\)$/i;\nvar rgbaRegex = /^rgb(?:a)?\\(\\s*(\\d{1,3})\\s*(?:,)?\\s*(\\d{1,3})\\s*(?:,)?\\s*(\\d{1,3})\\s*(?:,|\\/)\\s*([-+]?\\d*[.]?\\d+[%]?)\\s*\\)$/i;\nvar hslRegex = /^hsl\\(\\s*(\\d{0,3}[.]?[0-9]+(?:deg)?)\\s*(?:,)?\\s*(\\d{1,3}[.]?[0-9]?)%\\s*(?:,)?\\s*(\\d{1,3}[.]?[0-9]?)%\\s*\\)$/i;\nvar hslaRegex = /^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;\n\n/**\n * Returns an RgbColor or RgbaColor object. This utility function is only useful\n * if want to extract a color component. With the color util `toColorString` you\n * can convert a RgbColor or RgbaColor object back to a string.\n *\n * @example\n * // Assigns `{ red: 255, green: 0, blue: 0 }` to color1\n * const color1 = parseToRgb('rgb(255, 0, 0)');\n * // Assigns `{ red: 92, green: 102, blue: 112, alpha: 0.75 }` to color2\n * const color2 = parseToRgb('hsla(210, 10%, 40%, 0.75)');\n */\nfunction parseToRgb(color) {\n if (typeof color !== 'string') {\n throw new PolishedError(3);\n }\n var normalizedColor = nameToHex(color);\n if (normalizedColor.match(hexRegex)) {\n return {\n red: parseInt(\"\" + normalizedColor[1] + normalizedColor[2], 16),\n green: parseInt(\"\" + normalizedColor[3] + normalizedColor[4], 16),\n blue: parseInt(\"\" + normalizedColor[5] + normalizedColor[6], 16)\n };\n }\n if (normalizedColor.match(hexRgbaRegex)) {\n var alpha = parseFloat((parseInt(\"\" + normalizedColor[7] + normalizedColor[8], 16) / 255).toFixed(2));\n return {\n red: parseInt(\"\" + normalizedColor[1] + normalizedColor[2], 16),\n green: parseInt(\"\" + normalizedColor[3] + normalizedColor[4], 16),\n blue: parseInt(\"\" + normalizedColor[5] + normalizedColor[6], 16),\n alpha: alpha\n };\n }\n if (normalizedColor.match(reducedHexRegex)) {\n return {\n red: parseInt(\"\" + normalizedColor[1] + normalizedColor[1], 16),\n green: parseInt(\"\" + normalizedColor[2] + normalizedColor[2], 16),\n blue: parseInt(\"\" + normalizedColor[3] + normalizedColor[3], 16)\n };\n }\n if (normalizedColor.match(reducedRgbaHexRegex)) {\n var _alpha = parseFloat((parseInt(\"\" + normalizedColor[4] + normalizedColor[4], 16) / 255).toFixed(2));\n return {\n red: parseInt(\"\" + normalizedColor[1] + normalizedColor[1], 16),\n green: parseInt(\"\" + normalizedColor[2] + normalizedColor[2], 16),\n blue: parseInt(\"\" + normalizedColor[3] + normalizedColor[3], 16),\n alpha: _alpha\n };\n }\n var rgbMatched = rgbRegex.exec(normalizedColor);\n if (rgbMatched) {\n return {\n red: parseInt(\"\" + rgbMatched[1], 10),\n green: parseInt(\"\" + rgbMatched[2], 10),\n blue: parseInt(\"\" + rgbMatched[3], 10)\n };\n }\n var rgbaMatched = rgbaRegex.exec(normalizedColor.substring(0, 50));\n if (rgbaMatched) {\n return {\n red: parseInt(\"\" + rgbaMatched[1], 10),\n green: parseInt(\"\" + rgbaMatched[2], 10),\n blue: parseInt(\"\" + rgbaMatched[3], 10),\n alpha: parseFloat(\"\" + rgbaMatched[4]) > 1 ? parseFloat(\"\" + rgbaMatched[4]) / 100 : parseFloat(\"\" + rgbaMatched[4])\n };\n }\n var hslMatched = hslRegex.exec(normalizedColor);\n if (hslMatched) {\n var hue = parseInt(\"\" + hslMatched[1], 10);\n var saturation = parseInt(\"\" + hslMatched[2], 10) / 100;\n var lightness = parseInt(\"\" + hslMatched[3], 10) / 100;\n var rgbColorString = \"rgb(\" + hslToRgb(hue, saturation, lightness) + \")\";\n var hslRgbMatched = rgbRegex.exec(rgbColorString);\n if (!hslRgbMatched) {\n throw new PolishedError(4, normalizedColor, rgbColorString);\n }\n return {\n red: parseInt(\"\" + hslRgbMatched[1], 10),\n green: parseInt(\"\" + hslRgbMatched[2], 10),\n blue: parseInt(\"\" + hslRgbMatched[3], 10)\n };\n }\n var hslaMatched = hslaRegex.exec(normalizedColor.substring(0, 50));\n if (hslaMatched) {\n var _hue = parseInt(\"\" + hslaMatched[1], 10);\n var _saturation = parseInt(\"\" + hslaMatched[2], 10) / 100;\n var _lightness = parseInt(\"\" + hslaMatched[3], 10) / 100;\n var _rgbColorString = \"rgb(\" + hslToRgb(_hue, _saturation, _lightness) + \")\";\n var _hslRgbMatched = rgbRegex.exec(_rgbColorString);\n if (!_hslRgbMatched) {\n throw new PolishedError(4, normalizedColor, _rgbColorString);\n }\n return {\n red: parseInt(\"\" + _hslRgbMatched[1], 10),\n green: parseInt(\"\" + _hslRgbMatched[2], 10),\n blue: parseInt(\"\" + _hslRgbMatched[3], 10),\n alpha: parseFloat(\"\" + hslaMatched[4]) > 1 ? parseFloat(\"\" + hslaMatched[4]) / 100 : parseFloat(\"\" + hslaMatched[4])\n };\n }\n throw new PolishedError(5);\n}\n\nfunction rgbToHsl(color) {\n // make sure rgb are contained in a set of [0, 255]\n var red = color.red / 255;\n var green = color.green / 255;\n var blue = color.blue / 255;\n var max = Math.max(red, green, blue);\n var min = Math.min(red, green, blue);\n var lightness = (max + min) / 2;\n if (max === min) {\n // achromatic\n if (color.alpha !== undefined) {\n return {\n hue: 0,\n saturation: 0,\n lightness: lightness,\n alpha: color.alpha\n };\n } else {\n return {\n hue: 0,\n saturation: 0,\n lightness: lightness\n };\n }\n }\n var hue;\n var delta = max - min;\n var saturation = lightness > 0.5 ? delta / (2 - max - min) : delta / (max + min);\n switch (max) {\n case red:\n hue = (green - blue) / delta + (green < blue ? 6 : 0);\n break;\n case green:\n hue = (blue - red) / delta + 2;\n break;\n default:\n // blue case\n hue = (red - green) / delta + 4;\n break;\n }\n hue *= 60;\n if (color.alpha !== undefined) {\n return {\n hue: hue,\n saturation: saturation,\n lightness: lightness,\n alpha: color.alpha\n };\n }\n return {\n hue: hue,\n saturation: saturation,\n lightness: lightness\n };\n}\n\n/**\n * Returns an HslColor or HslaColor object. This utility function is only useful\n * if want to extract a color component. With the color util `toColorString` you\n * can convert a HslColor or HslaColor object back to a string.\n *\n * @example\n * // Assigns `{ hue: 0, saturation: 1, lightness: 0.5 }` to color1\n * const color1 = parseToHsl('rgb(255, 0, 0)');\n * // Assigns `{ hue: 128, saturation: 1, lightness: 0.5, alpha: 0.75 }` to color2\n * const color2 = parseToHsl('hsla(128, 100%, 50%, 0.75)');\n */\nfunction parseToHsl(color) {\n // Note: At a later stage we can optimize this function as right now a hsl\n // color would be parsed converted to rgb values and converted back to hsl.\n return rgbToHsl(parseToRgb(color));\n}\n\n/**\n * Reduces hex values if possible e.g. #ff8866 to #f86\n * @private\n */\nvar reduceHexValue = function reduceHexValue(value) {\n if (value.length === 7 && value[1] === value[2] && value[3] === value[4] && value[5] === value[6]) {\n return \"#\" + value[1] + value[3] + value[5];\n }\n return value;\n};\nvar reduceHexValue$1 = reduceHexValue;\n\nfunction numberToHex(value) {\n var hex = value.toString(16);\n return hex.length === 1 ? \"0\" + hex : hex;\n}\n\nfunction colorToHex(color) {\n return numberToHex(Math.round(color * 255));\n}\nfunction convertToHex(red, green, blue) {\n return reduceHexValue$1(\"#\" + colorToHex(red) + colorToHex(green) + colorToHex(blue));\n}\nfunction hslToHex(hue, saturation, lightness) {\n return hslToRgb(hue, saturation, lightness, convertToHex);\n}\n\n/**\n * Returns a string value for the color. The returned result is the smallest possible hex notation.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: hsl(359, 0.75, 0.4),\n * background: hsl({ hue: 360, saturation: 0.75, lightness: 0.4 }),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${hsl(359, 0.75, 0.4)};\n * background: ${hsl({ hue: 360, saturation: 0.75, lightness: 0.4 })};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#b3191c\";\n * background: \"#b3191c\";\n * }\n */\nfunction hsl(value, saturation, lightness) {\n if (typeof value === 'number' && typeof saturation === 'number' && typeof lightness === 'number') {\n return hslToHex(value, saturation, lightness);\n } else if (typeof value === 'object' && saturation === undefined && lightness === undefined) {\n return hslToHex(value.hue, value.saturation, value.lightness);\n }\n throw new PolishedError(1);\n}\n\n/**\n * Returns a string value for the color. The returned result is the smallest possible rgba or hex notation.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: hsla(359, 0.75, 0.4, 0.7),\n * background: hsla({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0,7 }),\n * background: hsla(359, 0.75, 0.4, 1),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${hsla(359, 0.75, 0.4, 0.7)};\n * background: ${hsla({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0,7 })};\n * background: ${hsla(359, 0.75, 0.4, 1)};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"rgba(179,25,28,0.7)\";\n * background: \"rgba(179,25,28,0.7)\";\n * background: \"#b3191c\";\n * }\n */\nfunction hsla(value, saturation, lightness, alpha) {\n if (typeof value === 'number' && typeof saturation === 'number' && typeof lightness === 'number' && typeof alpha === 'number') {\n return alpha >= 1 ? hslToHex(value, saturation, lightness) : \"rgba(\" + hslToRgb(value, saturation, lightness) + \",\" + alpha + \")\";\n } else if (typeof value === 'object' && saturation === undefined && lightness === undefined && alpha === undefined) {\n return value.alpha >= 1 ? hslToHex(value.hue, value.saturation, value.lightness) : \"rgba(\" + hslToRgb(value.hue, value.saturation, value.lightness) + \",\" + value.alpha + \")\";\n }\n throw new PolishedError(2);\n}\n\n/**\n * Returns a string value for the color. The returned result is the smallest possible hex notation.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: rgb(255, 205, 100),\n * background: rgb({ red: 255, green: 205, blue: 100 }),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${rgb(255, 205, 100)};\n * background: ${rgb({ red: 255, green: 205, blue: 100 })};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#ffcd64\";\n * background: \"#ffcd64\";\n * }\n */\nfunction rgb(value, green, blue) {\n if (typeof value === 'number' && typeof green === 'number' && typeof blue === 'number') {\n return reduceHexValue$1(\"#\" + numberToHex(value) + numberToHex(green) + numberToHex(blue));\n } else if (typeof value === 'object' && green === undefined && blue === undefined) {\n return reduceHexValue$1(\"#\" + numberToHex(value.red) + numberToHex(value.green) + numberToHex(value.blue));\n }\n throw new PolishedError(6);\n}\n\n/**\n * Returns a string value for the color. The returned result is the smallest possible rgba or hex notation.\n *\n * Can also be used to fade a color by passing a hex value or named CSS color along with an alpha value.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: rgba(255, 205, 100, 0.7),\n * background: rgba({ red: 255, green: 205, blue: 100, alpha: 0.7 }),\n * background: rgba(255, 205, 100, 1),\n * background: rgba('#ffffff', 0.4),\n * background: rgba('black', 0.7),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${rgba(255, 205, 100, 0.7)};\n * background: ${rgba({ red: 255, green: 205, blue: 100, alpha: 0.7 })};\n * background: ${rgba(255, 205, 100, 1)};\n * background: ${rgba('#ffffff', 0.4)};\n * background: ${rgba('black', 0.7)};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"rgba(255,205,100,0.7)\";\n * background: \"rgba(255,205,100,0.7)\";\n * background: \"#ffcd64\";\n * background: \"rgba(255,255,255,0.4)\";\n * background: \"rgba(0,0,0,0.7)\";\n * }\n */\nfunction rgba(firstValue, secondValue, thirdValue, fourthValue) {\n if (typeof firstValue === 'string' && typeof secondValue === 'number') {\n var rgbValue = parseToRgb(firstValue);\n return \"rgba(\" + rgbValue.red + \",\" + rgbValue.green + \",\" + rgbValue.blue + \",\" + secondValue + \")\";\n } else if (typeof firstValue === 'number' && typeof secondValue === 'number' && typeof thirdValue === 'number' && typeof fourthValue === 'number') {\n return fourthValue >= 1 ? rgb(firstValue, secondValue, thirdValue) : \"rgba(\" + firstValue + \",\" + secondValue + \",\" + thirdValue + \",\" + fourthValue + \")\";\n } else if (typeof firstValue === 'object' && secondValue === undefined && thirdValue === undefined && fourthValue === undefined) {\n return firstValue.alpha >= 1 ? rgb(firstValue.red, firstValue.green, firstValue.blue) : \"rgba(\" + firstValue.red + \",\" + firstValue.green + \",\" + firstValue.blue + \",\" + firstValue.alpha + \")\";\n }\n throw new PolishedError(7);\n}\n\nvar isRgb = function isRgb(color) {\n return typeof color.red === 'number' && typeof color.green === 'number' && typeof color.blue === 'number' && (typeof color.alpha !== 'number' || typeof color.alpha === 'undefined');\n};\nvar isRgba = function isRgba(color) {\n return typeof color.red === 'number' && typeof color.green === 'number' && typeof color.blue === 'number' && typeof color.alpha === 'number';\n};\nvar isHsl = function isHsl(color) {\n return typeof color.hue === 'number' && typeof color.saturation === 'number' && typeof color.lightness === 'number' && (typeof color.alpha !== 'number' || typeof color.alpha === 'undefined');\n};\nvar isHsla = function isHsla(color) {\n return typeof color.hue === 'number' && typeof color.saturation === 'number' && typeof color.lightness === 'number' && typeof color.alpha === 'number';\n};\n\n/**\n * Converts a RgbColor, RgbaColor, HslColor or HslaColor object to a color string.\n * This util is useful in case you only know on runtime which color object is\n * used. Otherwise we recommend to rely on `rgb`, `rgba`, `hsl` or `hsla`.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: toColorString({ red: 255, green: 205, blue: 100 }),\n * background: toColorString({ red: 255, green: 205, blue: 100, alpha: 0.72 }),\n * background: toColorString({ hue: 240, saturation: 1, lightness: 0.5 }),\n * background: toColorString({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0.72 }),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${toColorString({ red: 255, green: 205, blue: 100 })};\n * background: ${toColorString({ red: 255, green: 205, blue: 100, alpha: 0.72 })};\n * background: ${toColorString({ hue: 240, saturation: 1, lightness: 0.5 })};\n * background: ${toColorString({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0.72 })};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#ffcd64\";\n * background: \"rgba(255,205,100,0.72)\";\n * background: \"#00f\";\n * background: \"rgba(179,25,25,0.72)\";\n * }\n */\n\nfunction toColorString(color) {\n if (typeof color !== 'object') throw new PolishedError(8);\n if (isRgba(color)) return rgba(color);\n if (isRgb(color)) return rgb(color);\n if (isHsla(color)) return hsla(color);\n if (isHsl(color)) return hsl(color);\n throw new PolishedError(8);\n}\n\n// Type definitions taken from https://github.com/gcanti/flow-static-land/blob/master/src/Fun.js\n// eslint-disable-next-line no-unused-vars\n// eslint-disable-next-line no-unused-vars\n// eslint-disable-next-line no-redeclare\nfunction curried(f, length, acc) {\n return function fn() {\n // eslint-disable-next-line prefer-rest-params\n var combined = acc.concat(Array.prototype.slice.call(arguments));\n return combined.length >= length ? f.apply(this, combined) : curried(f, length, combined);\n };\n}\n\n// eslint-disable-next-line no-redeclare\nfunction curry(f) {\n // eslint-disable-line no-redeclare\n return curried(f, f.length, []);\n}\n\n/**\n * Changes the hue of the color. Hue is a number between 0 to 360. The first\n * argument for adjustHue is the amount of degrees the color is rotated around\n * the color wheel, always producing a positive hue value.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: adjustHue(180, '#448'),\n * background: adjustHue('180', 'rgba(101,100,205,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${adjustHue(180, '#448')};\n * background: ${adjustHue('180', 'rgba(101,100,205,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#888844\";\n * background: \"rgba(136,136,68,0.7)\";\n * }\n */\nfunction adjustHue(degree, color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n hue: hslColor.hue + parseFloat(degree)\n }));\n}\n\n// prettier-ignore\nvar curriedAdjustHue = curry /* ::<number | string, string, string> */(adjustHue);\nvar curriedAdjustHue$1 = curriedAdjustHue;\n\n/**\n * Returns the complement of the provided color. This is identical to adjustHue(180, <color>).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: complement('#448'),\n * background: complement('rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${complement('#448')};\n * background: ${complement('rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#884\";\n * background: \"rgba(153,153,153,0.7)\";\n * }\n */\nfunction complement(color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n hue: (hslColor.hue + 180) % 360\n }));\n}\n\nfunction guard(lowerBoundary, upperBoundary, value) {\n return Math.max(lowerBoundary, Math.min(upperBoundary, value));\n}\n\n/**\n * Returns a string value for the darkened color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: darken(0.2, '#FFCD64'),\n * background: darken('0.2', 'rgba(255,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${darken(0.2, '#FFCD64')};\n * background: ${darken('0.2', 'rgba(255,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#ffbd31\";\n * background: \"rgba(255,189,49,0.7)\";\n * }\n */\nfunction darken(amount, color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n lightness: guard(0, 1, hslColor.lightness - parseFloat(amount))\n }));\n}\n\n// prettier-ignore\nvar curriedDarken = curry /* ::<number | string, string, string> */(darken);\nvar curriedDarken$1 = curriedDarken;\n\n/**\n * Decreases the intensity of a color. Its range is between 0 to 1. The first\n * argument of the desaturate function is the amount by how much the color\n * intensity should be decreased.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: desaturate(0.2, '#CCCD64'),\n * background: desaturate('0.2', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${desaturate(0.2, '#CCCD64')};\n * background: ${desaturate('0.2', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#b8b979\";\n * background: \"rgba(184,185,121,0.7)\";\n * }\n */\nfunction desaturate(amount, color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n saturation: guard(0, 1, hslColor.saturation - parseFloat(amount))\n }));\n}\n\n// prettier-ignore\nvar curriedDesaturate = curry /* ::<number | string, string, string> */(desaturate);\nvar curriedDesaturate$1 = curriedDesaturate;\n\n/**\n * Returns a number (float) representing the luminance of a color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: getLuminance('#CCCD64') >= getLuminance('#0000ff') ? '#CCCD64' : '#0000ff',\n * background: getLuminance('rgba(58, 133, 255, 1)') >= getLuminance('rgba(255, 57, 149, 1)') ?\n * 'rgba(58, 133, 255, 1)' :\n * 'rgba(255, 57, 149, 1)',\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${getLuminance('#CCCD64') >= getLuminance('#0000ff') ? '#CCCD64' : '#0000ff'};\n * background: ${getLuminance('rgba(58, 133, 255, 1)') >= getLuminance('rgba(255, 57, 149, 1)') ?\n * 'rgba(58, 133, 255, 1)' :\n * 'rgba(255, 57, 149, 1)'};\n *\n * // CSS in JS Output\n *\n * div {\n * background: \"#CCCD64\";\n * background: \"rgba(58, 133, 255, 1)\";\n * }\n */\nfunction getLuminance(color) {\n if (color === 'transparent') return 0;\n var rgbColor = parseToRgb(color);\n var _Object$keys$map = Object.keys(rgbColor).map(function (key) {\n var channel = rgbColor[key] / 255;\n return channel <= 0.03928 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);\n }),\n r = _Object$keys$map[0],\n g = _Object$keys$map[1],\n b = _Object$keys$map[2];\n return parseFloat((0.2126 * r + 0.7152 * g + 0.0722 * b).toFixed(3));\n}\n\n/**\n * Returns the contrast ratio between two colors based on\n * [W3's recommended equation for calculating contrast](http://www.w3.org/TR/WCAG20/#contrast-ratiodef).\n *\n * @example\n * const contrastRatio = getContrast('#444', '#fff');\n */\nfunction getContrast(color1, color2) {\n var luminance1 = getLuminance(color1);\n var luminance2 = getLuminance(color2);\n return parseFloat((luminance1 > luminance2 ? (luminance1 + 0.05) / (luminance2 + 0.05) : (luminance2 + 0.05) / (luminance1 + 0.05)).toFixed(2));\n}\n\n/**\n * Converts the color to a grayscale, by reducing its saturation to 0.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: grayscale('#CCCD64'),\n * background: grayscale('rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${grayscale('#CCCD64')};\n * background: ${grayscale('rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#999\";\n * background: \"rgba(153,153,153,0.7)\";\n * }\n */\nfunction grayscale(color) {\n if (color === 'transparent') return color;\n return toColorString(_extends({}, parseToHsl(color), {\n saturation: 0\n }));\n}\n\n/**\n * Converts a HslColor or HslaColor object to a color string.\n * This util is useful in case you only know on runtime which color object is\n * used. Otherwise we recommend to rely on `hsl` or `hsla`.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: hslToColorString({ hue: 240, saturation: 1, lightness: 0.5 }),\n * background: hslToColorString({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0.72 }),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${hslToColorString({ hue: 240, saturation: 1, lightness: 0.5 })};\n * background: ${hslToColorString({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0.72 })};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#00f\";\n * background: \"rgba(179,25,25,0.72)\";\n * }\n */\nfunction hslToColorString(color) {\n if (typeof color === 'object' && typeof color.hue === 'number' && typeof color.saturation === 'number' && typeof color.lightness === 'number') {\n if (color.alpha && typeof color.alpha === 'number') {\n return hsla({\n hue: color.hue,\n saturation: color.saturation,\n lightness: color.lightness,\n alpha: color.alpha\n });\n }\n return hsl({\n hue: color.hue,\n saturation: color.saturation,\n lightness: color.lightness\n });\n }\n throw new PolishedError(45);\n}\n\n/**\n * Inverts the red, green and blue values of a color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: invert('#CCCD64'),\n * background: invert('rgba(101,100,205,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${invert('#CCCD64')};\n * background: ${invert('rgba(101,100,205,0.7)')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#33329b\";\n * background: \"rgba(154,155,50,0.7)\";\n * }\n */\nfunction invert(color) {\n if (color === 'transparent') return color;\n // parse color string to rgb\n var value = parseToRgb(color);\n return toColorString(_extends({}, value, {\n red: 255 - value.red,\n green: 255 - value.green,\n blue: 255 - value.blue\n }));\n}\n\n/**\n * Returns a string value for the lightened color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: lighten(0.2, '#CCCD64'),\n * background: lighten('0.2', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${lighten(0.2, '#FFCD64')};\n * background: ${lighten('0.2', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#e5e6b1\";\n * background: \"rgba(229,230,177,0.7)\";\n * }\n */\nfunction lighten(amount, color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n lightness: guard(0, 1, hslColor.lightness + parseFloat(amount))\n }));\n}\n\n// prettier-ignore\nvar curriedLighten = curry /* ::<number | string, string, string> */(lighten);\nvar curriedLighten$1 = curriedLighten;\n\n/**\n * Determines which contrast guidelines have been met for two colors.\n * Based on the [contrast calculations recommended by W3](https://www.w3.org/WAI/WCAG21/Understanding/contrast-enhanced.html).\n *\n * @example\n * const scores = meetsContrastGuidelines('#444', '#fff');\n */\nfunction meetsContrastGuidelines(color1, color2) {\n var contrastRatio = getContrast(color1, color2);\n return {\n AA: contrastRatio >= 4.5,\n AALarge: contrastRatio >= 3,\n AAA: contrastRatio >= 7,\n AAALarge: contrastRatio >= 4.5\n };\n}\n\n/**\n * Mixes the two provided colors together by calculating the average of each of the RGB components weighted to the first color by the provided weight.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: mix(0.5, '#f00', '#00f')\n * background: mix(0.25, '#f00', '#00f')\n * background: mix('0.5', 'rgba(255, 0, 0, 0.5)', '#00f')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${mix(0.5, '#f00', '#00f')};\n * background: ${mix(0.25, '#f00', '#00f')};\n * background: ${mix('0.5', 'rgba(255, 0, 0, 0.5)', '#00f')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#7f007f\";\n * background: \"#3f00bf\";\n * background: \"rgba(63, 0, 191, 0.75)\";\n * }\n */\nfunction mix(weight, color, otherColor) {\n if (color === 'transparent') return otherColor;\n if (otherColor === 'transparent') return color;\n if (weight === 0) return otherColor;\n var parsedColor1 = parseToRgb(color);\n var color1 = _extends({}, parsedColor1, {\n alpha: typeof parsedColor1.alpha === 'number' ? parsedColor1.alpha : 1\n });\n var parsedColor2 = parseToRgb(otherColor);\n var color2 = _extends({}, parsedColor2, {\n alpha: typeof parsedColor2.alpha === 'number' ? parsedColor2.alpha : 1\n });\n\n // The formula is copied from the original Sass implementation:\n // http://sass-lang.com/documentation/Sass/Script/Functions.html#mix-instance_method\n var alphaDelta = color1.alpha - color2.alpha;\n var x = parseFloat(weight) * 2 - 1;\n var y = x * alphaDelta === -1 ? x : x + alphaDelta;\n var z = 1 + x * alphaDelta;\n var weight1 = (y / z + 1) / 2.0;\n var weight2 = 1 - weight1;\n var mixedColor = {\n red: Math.floor(color1.red * weight1 + color2.red * weight2),\n green: Math.floor(color1.green * weight1 + color2.green * weight2),\n blue: Math.floor(color1.blue * weight1 + color2.blue * weight2),\n alpha: color1.alpha * parseFloat(weight) + color2.alpha * (1 - parseFloat(weight))\n };\n return rgba(mixedColor);\n}\n\n// prettier-ignore\nvar curriedMix = curry /* ::<number | string, string, string, string> */(mix);\nvar mix$1 = curriedMix;\n\n/**\n * Increases the opacity of a color. Its range for the amount is between 0 to 1.\n *\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: opacify(0.1, 'rgba(255, 255, 255, 0.9)');\n * background: opacify(0.2, 'hsla(0, 0%, 100%, 0.5)'),\n * background: opacify('0.5', 'rgba(255, 0, 0, 0.2)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${opacify(0.1, 'rgba(255, 255, 255, 0.9)')};\n * background: ${opacify(0.2, 'hsla(0, 0%, 100%, 0.5)')},\n * background: ${opacify('0.5', 'rgba(255, 0, 0, 0.2)')},\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#fff\";\n * background: \"rgba(255,255,255,0.7)\";\n * background: \"rgba(255,0,0,0.7)\";\n * }\n */\nfunction opacify(amount, color) {\n if (color === 'transparent') return color;\n var parsedColor = parseToRgb(color);\n var alpha = typeof parsedColor.alpha === 'number' ? parsedColor.alpha : 1;\n var colorWithAlpha = _extends({}, parsedColor, {\n alpha: guard(0, 1, (alpha * 100 + parseFloat(amount) * 100) / 100)\n });\n return rgba(colorWithAlpha);\n}\n\n// prettier-ignore\nvar curriedOpacify = curry /* ::<number | string, string, string> */(opacify);\nvar curriedOpacify$1 = curriedOpacify;\n\nvar defaultReturnIfLightColor = '#000';\nvar defaultReturnIfDarkColor = '#fff';\n\n/**\n * Returns black or white (or optional passed colors) for best\n * contrast depending on the luminosity of the given color.\n * When passing custom return colors, strict mode ensures that the\n * return color always meets or exceeds WCAG level AA or greater. If this test\n * fails, the default return color (black or white) is returned in place of the\n * custom return color. You can optionally turn off strict mode.\n *\n * Follows [W3C specs for readability](https://www.w3.org/TR/WCAG20-TECHS/G18.html).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * color: readableColor('#000'),\n * color: readableColor('black', '#001', '#ff8'),\n * color: readableColor('white', '#001', '#ff8'),\n * color: readableColor('red', '#333', '#ddd', true)\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * color: ${readableColor('#000')};\n * color: ${readableColor('black', '#001', '#ff8')};\n * color: ${readableColor('white', '#001', '#ff8')};\n * color: ${readableColor('red', '#333', '#ddd', true)};\n * `\n *\n * // CSS in JS Output\n * element {\n * color: \"#fff\";\n * color: \"#ff8\";\n * color: \"#001\";\n * color: \"#000\";\n * }\n */\nfunction readableColor(color, returnIfLightColor, returnIfDarkColor, strict) {\n if (returnIfLightColor === void 0) {\n returnIfLightColor = defaultReturnIfLightColor;\n }\n if (returnIfDarkColor === void 0) {\n returnIfDarkColor = defaultReturnIfDarkColor;\n }\n if (strict === void 0) {\n strict = true;\n }\n var isColorLight = getLuminance(color) > 0.179;\n var preferredReturnColor = isColorLight ? returnIfLightColor : returnIfDarkColor;\n if (!strict || getContrast(color, preferredReturnColor) >= 4.5) {\n return preferredReturnColor;\n }\n return isColorLight ? defaultReturnIfLightColor : defaultReturnIfDarkColor;\n}\n\n/**\n * Converts a RgbColor or RgbaColor object to a color string.\n * This util is useful in case you only know on runtime which color object is\n * used. Otherwise we recommend to rely on `rgb` or `rgba`.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: rgbToColorString({ red: 255, green: 205, blue: 100 }),\n * background: rgbToColorString({ red: 255, green: 205, blue: 100, alpha: 0.72 }),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${rgbToColorString({ red: 255, green: 205, blue: 100 })};\n * background: ${rgbToColorString({ red: 255, green: 205, blue: 100, alpha: 0.72 })};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#ffcd64\";\n * background: \"rgba(255,205,100,0.72)\";\n * }\n */\nfunction rgbToColorString(color) {\n if (typeof color === 'object' && typeof color.red === 'number' && typeof color.green === 'number' && typeof color.blue === 'number') {\n if (typeof color.alpha === 'number') {\n return rgba({\n red: color.red,\n green: color.green,\n blue: color.blue,\n alpha: color.alpha\n });\n }\n return rgb({\n red: color.red,\n green: color.green,\n blue: color.blue\n });\n }\n throw new PolishedError(46);\n}\n\n/**\n * Increases the intensity of a color. Its range is between 0 to 1. The first\n * argument of the saturate function is the amount by how much the color\n * intensity should be increased.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: saturate(0.2, '#CCCD64'),\n * background: saturate('0.2', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${saturate(0.2, '#FFCD64')};\n * background: ${saturate('0.2', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#e0e250\";\n * background: \"rgba(224,226,80,0.7)\";\n * }\n */\nfunction saturate(amount, color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n saturation: guard(0, 1, hslColor.saturation + parseFloat(amount))\n }));\n}\n\n// prettier-ignore\nvar curriedSaturate = curry /* ::<number | string, string, string> */(saturate);\nvar curriedSaturate$1 = curriedSaturate;\n\n/**\n * Sets the hue of a color to the provided value. The hue range can be\n * from 0 and 359.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: setHue(42, '#CCCD64'),\n * background: setHue('244', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${setHue(42, '#CCCD64')};\n * background: ${setHue('244', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#cdae64\";\n * background: \"rgba(107,100,205,0.7)\";\n * }\n */\nfunction setHue(hue, color) {\n if (color === 'transparent') return color;\n return toColorString(_extends({}, parseToHsl(color), {\n hue: parseFloat(hue)\n }));\n}\n\n// prettier-ignore\nvar curriedSetHue = curry /* ::<number | string, string, string> */(setHue);\nvar curriedSetHue$1 = curriedSetHue;\n\n/**\n * Sets the lightness of a color to the provided value. The lightness range can be\n * from 0 and 1.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: setLightness(0.2, '#CCCD64'),\n * background: setLightness('0.75', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${setLightness(0.2, '#CCCD64')};\n * background: ${setLightness('0.75', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#4d4d19\";\n * background: \"rgba(223,224,159,0.7)\";\n * }\n */\nfunction setLightness(lightness, color) {\n if (color === 'transparent') return color;\n return toColorString(_extends({}, parseToHsl(color), {\n lightness: parseFloat(lightness)\n }));\n}\n\n// prettier-ignore\nvar curriedSetLightness = curry /* ::<number | string, string, string> */(setLightness);\nvar curriedSetLightness$1 = curriedSetLightness;\n\n/**\n * Sets the saturation of a color to the provided value. The saturation range can be\n * from 0 and 1.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: setSaturation(0.2, '#CCCD64'),\n * background: setSaturation('0.75', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${setSaturation(0.2, '#CCCD64')};\n * background: ${setSaturation('0.75', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#adad84\";\n * background: \"rgba(228,229,76,0.7)\";\n * }\n */\nfunction setSaturation(saturation, color) {\n if (color === 'transparent') return color;\n return toColorString(_extends({}, parseToHsl(color), {\n saturation: parseFloat(saturation)\n }));\n}\n\n// prettier-ignore\nvar curriedSetSaturation = curry /* ::<number | string, string, string> */(setSaturation);\nvar curriedSetSaturation$1 = curriedSetSaturation;\n\n/**\n * Shades a color by mixing it with black. `shade` can produce\n * hue shifts, where as `darken` manipulates the luminance channel and therefore\n * doesn't produce hue shifts.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: shade(0.25, '#00f')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${shade(0.25, '#00f')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#00003f\";\n * }\n */\n\nfunction shade(percentage, color) {\n if (color === 'transparent') return color;\n return mix$1(parseFloat(percentage), 'rgb(0, 0, 0)', color);\n}\n\n// prettier-ignore\nvar curriedShade = curry /* ::<number | string, string, string> */(shade);\nvar curriedShade$1 = curriedShade;\n\n/**\n * Tints a color by mixing it with white. `tint` can produce\n * hue shifts, where as `lighten` manipulates the luminance channel and therefore\n * doesn't produce hue shifts.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: tint(0.25, '#00f')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${tint(0.25, '#00f')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#bfbfff\";\n * }\n */\n\nfunction tint(percentage, color) {\n if (color === 'transparent') return color;\n return mix$1(parseFloat(percentage), 'rgb(255, 255, 255)', color);\n}\n\n// prettier-ignore\nvar curriedTint = curry /* ::<number | string, string, string> */(tint);\nvar curriedTint$1 = curriedTint;\n\n/**\n * Decreases the opacity of a color. Its range for the amount is between 0 to 1.\n *\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: transparentize(0.1, '#fff'),\n * background: transparentize(0.2, 'hsl(0, 0%, 100%)'),\n * background: transparentize('0.5', 'rgba(255, 0, 0, 0.8)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${transparentize(0.1, '#fff')};\n * background: ${transparentize(0.2, 'hsl(0, 0%, 100%)')};\n * background: ${transparentize('0.5', 'rgba(255, 0, 0, 0.8)')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"rgba(255,255,255,0.9)\";\n * background: \"rgba(255,255,255,0.8)\";\n * background: \"rgba(255,0,0,0.3)\";\n * }\n */\nfunction transparentize(amount, color) {\n if (color === 'transparent') return color;\n var parsedColor = parseToRgb(color);\n var alpha = typeof parsedColor.alpha === 'number' ? parsedColor.alpha : 1;\n var colorWithAlpha = _extends({}, parsedColor, {\n alpha: guard(0, 1, +(alpha * 100 - parseFloat(amount) * 100).toFixed(2) / 100)\n });\n return rgba(colorWithAlpha);\n}\n\n// prettier-ignore\nvar curriedTransparentize = curry /* ::<number | string, string, string> */(transparentize);\nvar curriedTransparentize$1 = curriedTransparentize;\n\n/**\n * Shorthand for easily setting the animation property. Allows either multiple arrays with animations\n * or a single animation spread over the arguments.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...animation(['rotate', '1s', 'ease-in-out'], ['colorchange', '2s'])\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${animation(['rotate', '1s', 'ease-in-out'], ['colorchange', '2s'])}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'animation': 'rotate 1s ease-in-out, colorchange 2s'\n * }\n * @example\n * // Styles as object usage\n * const styles = {\n * ...animation('rotate', '1s', 'ease-in-out')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${animation('rotate', '1s', 'ease-in-out')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'animation': 'rotate 1s ease-in-out'\n * }\n */\nfunction animation() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n // Allow single or multiple animations passed\n var multiMode = Array.isArray(args[0]);\n if (!multiMode && args.length > 8) {\n throw new PolishedError(64);\n }\n var code = args.map(function (arg) {\n if (multiMode && !Array.isArray(arg) || !multiMode && Array.isArray(arg)) {\n throw new PolishedError(65);\n }\n if (Array.isArray(arg) && arg.length > 8) {\n throw new PolishedError(66);\n }\n return Array.isArray(arg) ? arg.join(' ') : arg;\n }).join(', ');\n return {\n animation: code\n };\n}\n\n/**\n * Shorthand that accepts any number of backgroundImage values as parameters for creating a single background statement.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...backgroundImages('url(\"/image/background.jpg\")', 'linear-gradient(red, green)')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${backgroundImages('url(\"/image/background.jpg\")', 'linear-gradient(red, green)')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'backgroundImage': 'url(\"/image/background.jpg\"), linear-gradient(red, green)'\n * }\n */\nfunction backgroundImages() {\n for (var _len = arguments.length, properties = new Array(_len), _key = 0; _key < _len; _key++) {\n properties[_key] = arguments[_key];\n }\n return {\n backgroundImage: properties.join(', ')\n };\n}\n\n/**\n * Shorthand that accepts any number of background values as parameters for creating a single background statement.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...backgrounds('url(\"/image/background.jpg\")', 'linear-gradient(red, green)', 'center no-repeat')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${backgrounds('url(\"/image/background.jpg\")', 'linear-gradient(red, green)', 'center no-repeat')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'background': 'url(\"/image/background.jpg\"), linear-gradient(red, green), center no-repeat'\n * }\n */\nfunction backgrounds() {\n for (var _len = arguments.length, properties = new Array(_len), _key = 0; _key < _len; _key++) {\n properties[_key] = arguments[_key];\n }\n return {\n background: properties.join(', ')\n };\n}\n\nvar sideMap = ['top', 'right', 'bottom', 'left'];\n\n/**\n * Shorthand for the border property that splits out individual properties for use with tools like Fela and Styletron. A side keyword can optionally be passed to target only one side's border properties.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...border('1px', 'solid', 'red')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${border('1px', 'solid', 'red')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderColor': 'red',\n * 'borderStyle': 'solid',\n * 'borderWidth': `1px`,\n * }\n *\n * // Styles as object usage\n * const styles = {\n * ...border('top', '1px', 'solid', 'red')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${border('top', '1px', 'solid', 'red')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderTopColor': 'red',\n * 'borderTopStyle': 'solid',\n * 'borderTopWidth': `1px`,\n * }\n */\n\nfunction border(sideKeyword) {\n for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n values[_key - 1] = arguments[_key];\n }\n if (typeof sideKeyword === 'string' && sideMap.indexOf(sideKeyword) >= 0) {\n var _ref;\n return _ref = {}, _ref[\"border\" + capitalizeString(sideKeyword) + \"Width\"] = values[0], _ref[\"border\" + capitalizeString(sideKeyword) + \"Style\"] = values[1], _ref[\"border\" + capitalizeString(sideKeyword) + \"Color\"] = values[2], _ref;\n } else {\n values.unshift(sideKeyword);\n return {\n borderWidth: values[0],\n borderStyle: values[1],\n borderColor: values[2]\n };\n }\n}\n\n/**\n * Shorthand that accepts up to four values, including null to skip a value, and maps them to their respective directions.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...borderColor('red', 'green', 'blue', 'yellow')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${borderColor('red', 'green', 'blue', 'yellow')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderTopColor': 'red',\n * 'borderRightColor': 'green',\n * 'borderBottomColor': 'blue',\n * 'borderLeftColor': 'yellow'\n * }\n */\nfunction borderColor() {\n for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {\n values[_key] = arguments[_key];\n }\n return directionalProperty.apply(void 0, ['borderColor'].concat(values));\n}\n\n/**\n * Shorthand that accepts a value for side and a value for radius and applies the radius value to both corners of the side.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...borderRadius('top', '5px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${borderRadius('top', '5px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderTopRightRadius': '5px',\n * 'borderTopLeftRadius': '5px',\n * }\n */\nfunction borderRadius(side, radius) {\n var uppercaseSide = capitalizeString(side);\n if (!radius && radius !== 0) {\n throw new PolishedError(62);\n }\n if (uppercaseSide === 'Top' || uppercaseSide === 'Bottom') {\n var _ref;\n return _ref = {}, _ref[\"border\" + uppercaseSide + \"RightRadius\"] = radius, _ref[\"border\" + uppercaseSide + \"LeftRadius\"] = radius, _ref;\n }\n if (uppercaseSide === 'Left' || uppercaseSide === 'Right') {\n var _ref2;\n return _ref2 = {}, _ref2[\"borderTop\" + uppercaseSide + \"Radius\"] = radius, _ref2[\"borderBottom\" + uppercaseSide + \"Radius\"] = radius, _ref2;\n }\n throw new PolishedError(63);\n}\n\n/**\n * Shorthand that accepts up to four values, including null to skip a value, and maps them to their respective directions.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...borderStyle('solid', 'dashed', 'dotted', 'double')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${borderStyle('solid', 'dashed', 'dotted', 'double')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderTopStyle': 'solid',\n * 'borderRightStyle': 'dashed',\n * 'borderBottomStyle': 'dotted',\n * 'borderLeftStyle': 'double'\n * }\n */\nfunction borderStyle() {\n for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {\n values[_key] = arguments[_key];\n }\n return directionalProperty.apply(void 0, ['borderStyle'].concat(values));\n}\n\n/**\n * Shorthand that accepts up to four values, including null to skip a value, and maps them to their respective directions.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...borderWidth('12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${borderWidth('12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderTopWidth': '12px',\n * 'borderRightWidth': '24px',\n * 'borderBottomWidth': '36px',\n * 'borderLeftWidth': '48px'\n * }\n */\nfunction borderWidth() {\n for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {\n values[_key] = arguments[_key];\n }\n return directionalProperty.apply(void 0, ['borderWidth'].concat(values));\n}\n\nfunction generateSelectors(template, state) {\n var stateSuffix = state ? \":\" + state : '';\n return template(stateSuffix);\n}\n\n/**\n * Function helper that adds an array of states to a template of selectors. Used in textInputs and buttons.\n * @private\n */\nfunction statefulSelectors(states, template, stateMap) {\n if (!template) throw new PolishedError(67);\n if (states.length === 0) return generateSelectors(template, null);\n var selectors = [];\n for (var i = 0; i < states.length; i += 1) {\n if (stateMap && stateMap.indexOf(states[i]) < 0) {\n throw new PolishedError(68);\n }\n selectors.push(generateSelectors(template, states[i]));\n }\n selectors = selectors.join(',');\n return selectors;\n}\n\nvar stateMap$1 = [undefined, null, 'active', 'focus', 'hover'];\nfunction template$1(state) {\n return \"button\" + state + \",\\n input[type=\\\"button\\\"]\" + state + \",\\n input[type=\\\"reset\\\"]\" + state + \",\\n input[type=\\\"submit\\\"]\" + state;\n}\n\n/**\n * Populates selectors that target all buttons. You can pass optional states to append to the selectors.\n * @example\n * // Styles as object usage\n * const styles = {\n * [buttons('active')]: {\n * 'border': 'none'\n * }\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * > ${buttons('active')} {\n * border: none;\n * }\n * `\n *\n * // CSS in JS Output\n *\n * 'button:active,\n * 'input[type=\"button\"]:active,\n * 'input[type=\\\"reset\\\"]:active,\n * 'input[type=\\\"submit\\\"]:active: {\n * 'border': 'none'\n * }\n */\nfunction buttons() {\n for (var _len = arguments.length, states = new Array(_len), _key = 0; _key < _len; _key++) {\n states[_key] = arguments[_key];\n }\n return statefulSelectors(states, template$1, stateMap$1);\n}\n\n/**\n * Shorthand that accepts up to four values, including null to skip a value, and maps them to their respective directions.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...margin('12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${margin('12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'marginTop': '12px',\n * 'marginRight': '24px',\n * 'marginBottom': '36px',\n * 'marginLeft': '48px'\n * }\n */\nfunction margin() {\n for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {\n values[_key] = arguments[_key];\n }\n return directionalProperty.apply(void 0, ['margin'].concat(values));\n}\n\n/**\n * Shorthand that accepts up to four values, including null to skip a value, and maps them to their respective directions.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...padding('12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${padding('12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'paddingTop': '12px',\n * 'paddingRight': '24px',\n * 'paddingBottom': '36px',\n * 'paddingLeft': '48px'\n * }\n */\nfunction padding() {\n for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {\n values[_key] = arguments[_key];\n }\n return directionalProperty.apply(void 0, ['padding'].concat(values));\n}\n\nvar positionMap = ['absolute', 'fixed', 'relative', 'static', 'sticky'];\n\n/**\n * Shorthand accepts up to five values, including null to skip a value, and maps them to their respective directions. The first value can optionally be a position keyword.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...position('12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${position('12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'top': '12px',\n * 'right': '24px',\n * 'bottom': '36px',\n * 'left': '48px'\n * }\n *\n * // Styles as object usage\n * const styles = {\n * ...position('absolute', '12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${position('absolute', '12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'position': 'absolute',\n * 'top': '12px',\n * 'right': '24px',\n * 'bottom': '36px',\n * 'left': '48px'\n * }\n */\nfunction position(firstValue) {\n for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n values[_key - 1] = arguments[_key];\n }\n if (positionMap.indexOf(firstValue) >= 0 && firstValue) {\n return _extends({}, directionalProperty.apply(void 0, [''].concat(values)), {\n position: firstValue\n });\n } else {\n return directionalProperty.apply(void 0, ['', firstValue].concat(values));\n }\n}\n\n/**\n * Shorthand to set the height and width properties in a single statement.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...size('300px', '250px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${size('300px', '250px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'height': '300px',\n * 'width': '250px',\n * }\n */\nfunction size(height, width) {\n if (width === void 0) {\n width = height;\n }\n return {\n height: height,\n width: width\n };\n}\n\nvar stateMap = [undefined, null, 'active', 'focus', 'hover'];\nfunction template(state) {\n return \"input[type=\\\"color\\\"]\" + state + \",\\n input[type=\\\"date\\\"]\" + state + \",\\n input[type=\\\"datetime\\\"]\" + state + \",\\n input[type=\\\"datetime-local\\\"]\" + state + \",\\n input[type=\\\"email\\\"]\" + state + \",\\n input[type=\\\"month\\\"]\" + state + \",\\n input[type=\\\"number\\\"]\" + state + \",\\n input[type=\\\"password\\\"]\" + state + \",\\n input[type=\\\"search\\\"]\" + state + \",\\n input[type=\\\"tel\\\"]\" + state + \",\\n input[type=\\\"text\\\"]\" + state + \",\\n input[type=\\\"time\\\"]\" + state + \",\\n input[type=\\\"url\\\"]\" + state + \",\\n input[type=\\\"week\\\"]\" + state + \",\\n input:not([type])\" + state + \",\\n textarea\" + state;\n}\n\n/**\n * Populates selectors that target all text inputs. You can pass optional states to append to the selectors.\n * @example\n * // Styles as object usage\n * const styles = {\n * [textInputs('active')]: {\n * 'border': 'none'\n * }\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * > ${textInputs('active')} {\n * border: none;\n * }\n * `\n *\n * // CSS in JS Output\n *\n * 'input[type=\"color\"]:active,\n * input[type=\"date\"]:active,\n * input[type=\"datetime\"]:active,\n * input[type=\"datetime-local\"]:active,\n * input[type=\"email\"]:active,\n * input[type=\"month\"]:active,\n * input[type=\"number\"]:active,\n * input[type=\"password\"]:active,\n * input[type=\"search\"]:active,\n * input[type=\"tel\"]:active,\n * input[type=\"text\"]:active,\n * input[type=\"time\"]:active,\n * input[type=\"url\"]:active,\n * input[type=\"week\"]:active,\n * input:not([type]):active,\n * textarea:active': {\n * 'border': 'none'\n * }\n */\nfunction textInputs() {\n for (var _len = arguments.length, states = new Array(_len), _key = 0; _key < _len; _key++) {\n states[_key] = arguments[_key];\n }\n return statefulSelectors(states, template, stateMap);\n}\n\n/**\n * Accepts any number of transition values as parameters for creating a single transition statement. You may also pass an array of properties as the first parameter that you would like to apply the same transition values to (second parameter).\n * @example\n * // Styles as object usage\n * const styles = {\n * ...transitions('opacity 1.0s ease-in 0s', 'width 2.0s ease-in 2s'),\n * ...transitions(['color', 'background-color'], '2.0s ease-in 2s')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${transitions('opacity 1.0s ease-in 0s', 'width 2.0s ease-in 2s')};\n * ${transitions(['color', 'background-color'], '2.0s ease-in 2s'),};\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'transition': 'opacity 1.0s ease-in 0s, width 2.0s ease-in 2s'\n * 'transition': 'color 2.0s ease-in 2s, background-color 2.0s ease-in 2s',\n * }\n */\nfunction transitions() {\n for (var _len = arguments.length, properties = new Array(_len), _key = 0; _key < _len; _key++) {\n properties[_key] = arguments[_key];\n }\n if (Array.isArray(properties[0]) && properties.length === 2) {\n var value = properties[1];\n if (typeof value !== 'string') {\n throw new PolishedError(61);\n }\n var transitionsString = properties[0].map(function (property) {\n return property + \" \" + value;\n }).join(', ');\n return {\n transition: transitionsString\n };\n } else {\n return {\n transition: properties.join(', ')\n };\n }\n}\n\nexport { curriedAdjustHue$1 as adjustHue, animation, backgroundImages, backgrounds, between, border, borderColor, borderRadius, borderStyle, borderWidth, buttons, clearFix, complement, cover, cssVar, curriedDarken$1 as darken, curriedDesaturate$1 as desaturate, directionalProperty, easeIn, easeInOut, easeOut, ellipsis, em$1 as em, fluidRange, fontFace, getContrast, getLuminance, getValueAndUnit, grayscale, hiDPI, hideText, hideVisually, hsl, hslToColorString, hsla, important, invert, curriedLighten$1 as lighten, linearGradient, margin, math, meetsContrastGuidelines, mix$1 as mix, modularScale, normalize, curriedOpacify$1 as opacify, padding, parseToHsl, parseToRgb, position, radialGradient, readableColor, rem$1 as rem, remToPx, retinaImage, rgb, rgbToColorString, rgba, curriedSaturate$1 as saturate, curriedSetHue$1 as setHue, curriedSetLightness$1 as setLightness, curriedSetSaturation$1 as setSaturation, curriedShade$1 as shade, size, stripUnit, textInputs, timingFunctions, curriedTint$1 as tint, toColorString, transitions, curriedTransparentize$1 as transparentize, triangle, wordWrap };\n","import { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport type { SimpleRouteJson } from \"../types\"\nimport { transparentize } from \"polished\"\n\nexport const COLORS = [\n \"blue\",\n \"orange\",\n \"purple\",\n \"cyan\",\n \"magenta\",\n \"yellowgreen\",\n \"darkgoldenrod\",\n \"deeppink\",\n]\n\nexport const getColorMap = (\n srj: SimpleRouteJson,\n connMap?: ConnectivityMap,\n) => {\n const colorMap: Record<string, string> = {}\n for (let i = 0; i < srj.connections.length; i++) {\n const connection = srj.connections[i]\n const netName = connMap?.getNetConnectedToId(connection.name)\n\n if (netName && !colorMap[netName]) {\n colorMap[netName] =\n `hsl(${(i * 300) / srj.connections.length}, 100%, 50%)`\n }\n\n colorMap[connection.name] =\n (netName ? colorMap[netName] : null) ??\n `hsl(${(i * 340) / srj.connections.length}, 100%, 50%)`\n }\n return colorMap\n}\n\nexport const safeTransparentize = (color: string, amount: number) => {\n try {\n return transparentize(amount, color)\n } catch (e) {\n console.error(e)\n return color\n }\n}\n\nexport const createColorMapFromStrings = (strings: string[]) => {\n const colorMap: Record<string, string> = {}\n for (let i = 0; i < strings.length; i++) {\n colorMap[strings[i]] = `hsl(${(i * 300) / strings.length}, 100%, 50%)`\n }\n return colorMap\n}\n","export const mapLayerNameToZ = (layerName: string, layerCount: number) => {\n if (layerName === \"top\") return 0\n if (layerName === \"bottom\") return layerCount - 1\n return parseInt(layerName.slice(5))\n}\n","import { CapacityMeshNode } from \"lib/types/capacity-mesh-types\"\n\n/**\n * Calculate the capacity of a node based on its width\n *\n * This capacity corresponds to how many vias the node can fit, tuned for two\n * layers.\n *\n * @param nodeOrWidth The node or width to calculate capacity for\n * @param maxCapacityFactor Optional multiplier to adjust capacity\n * @returns The calculated capacity\n */\nexport const getTunedTotalCapacity1 = (\n nodeOrWidth: CapacityMeshNode | { width: number },\n maxCapacityFactor = 1,\n) => {\n const VIA_DIAMETER = 0.6\n const TRACE_WIDTH = 0.15\n const obstacleMargin = 0.2\n\n const width = \"width\" in nodeOrWidth ? nodeOrWidth.width : nodeOrWidth\n const viaLengthAcross = width / (VIA_DIAMETER / 2 + obstacleMargin)\n\n return (viaLengthAcross / 2) ** 1.1 * maxCapacityFactor\n}\n\n/**\n * Calculate the optimal subdivision depth to reach a target minimum capacity\n * @param initialWidth The initial width of the top-level node\n * @param targetMinCapacity The minimum capacity target (default 0.5)\n * @param maxDepth Maximum allowed depth (default 10)\n * @returns The optimal capacity depth\n */\nexport const calculateOptimalCapacityDepth = (\n initialWidth: number,\n targetMinCapacity = 0.5,\n maxDepth = 16,\n): number => {\n let depth = 0\n let width = initialWidth\n\n // Calculate capacity at each subdivision level until we reach target or max depth\n while (depth < maxDepth) {\n const capacity = getTunedTotalCapacity1({ width })\n\n // If capacity is below target, we've gone far enough\n if (capacity <= targetMinCapacity) {\n break\n }\n\n // Move to next subdivision level (each level divides width by 2)\n width /= 2\n depth++\n }\n\n // Return depth + 1 to account for the fact that we want to subdivide\n // until the smallest nodes have capacity <= targetMinCapacity\n return Math.max(1, depth)\n}\n","import { Obstacle } from \"lib/types\"\n\nexport type BucketCoordinate = `${number}x${number}`\n\nexport class ObstacleTree {\n buckets: Map<BucketCoordinate, [Obstacle, number][]>\n CELL_SIZE = 0.4\n\n constructor(public obstacles: Obstacle[]) {\n this.buckets = new Map()\n // for (const obstacle of obstacles) {\n for (let i = 0; i < obstacles.length; i++) {\n const obstacle = obstacles[i]\n const nodeMinX = obstacle.center.x - obstacle.width / 2\n const nodeMinY = obstacle.center.y - obstacle.height / 2\n const nodeMaxX = obstacle.center.x + obstacle.width / 2\n const nodeMaxY = obstacle.center.y + obstacle.height / 2\n for (let x = nodeMinX; x <= nodeMaxX; x += this.CELL_SIZE) {\n for (let y = nodeMinY; y <= nodeMaxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey)\n if (!bucket) {\n this.buckets.set(bucketKey, [[obstacle, i]])\n } else {\n bucket.push([obstacle, i])\n }\n }\n }\n }\n }\n\n getBucketKey(x: number, y: number): BucketCoordinate {\n return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`\n }\n\n getNodesInArea(\n centerX: number,\n centerY: number,\n width: number,\n height: number,\n ): Obstacle[] {\n const obstacles: Obstacle[] = []\n const alreadyAddedObstacles = new Set<number>()\n const minX = centerX - width / 2\n const minY = centerY - height / 2\n const maxX = centerX + width / 2\n const maxY = centerY + height / 2\n for (let x = minX; x <= maxX; x += this.CELL_SIZE) {\n for (let y = minY; y <= maxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey) || []\n for (const obstacleWithIndex of bucket) {\n if (alreadyAddedObstacles.has(obstacleWithIndex[1])) continue\n alreadyAddedObstacles.add(obstacleWithIndex[1])\n obstacles.push(obstacleWithIndex[0])\n }\n }\n }\n return obstacles\n }\n}\n","interface Target {\n x: number\n y: number\n bounds: {\n minX: number\n minY: number\n maxX: number\n maxY: number\n }\n connectionName: string\n availableZ: number[]\n}\n\nexport type BucketCoordinate = `${number}x${number}`\n\nexport class TargetTree {\n buckets: Map<BucketCoordinate, [Target, number][]>\n CELL_SIZE = 5\n\n constructor(public targets: Target[]) {\n this.buckets = new Map()\n for (let i = 0; i < targets.length; i++) {\n const target = targets[i]\n const targetBucketMinX =\n Math.floor(target.bounds.minX / this.CELL_SIZE) * this.CELL_SIZE\n const targetBucketMinY =\n Math.floor(target.bounds.minY / this.CELL_SIZE) * this.CELL_SIZE\n const targetMaxX = target.bounds.maxX\n const targetMaxY = target.bounds.maxY\n for (let x = targetBucketMinX; x <= targetMaxX; x += this.CELL_SIZE) {\n for (let y = targetBucketMinY; y <= targetMaxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey)\n if (!bucket) {\n this.buckets.set(bucketKey, [[target, i]])\n } else {\n bucket.push([target, i])\n }\n }\n }\n }\n }\n\n getBucketKey(x: number, y: number): BucketCoordinate {\n return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`\n }\n\n getTargetsInArea(\n centerX: number,\n centerY: number,\n width: number,\n height: number,\n ): Target[] {\n const targets: Target[] = []\n const alreadyAddedTargets = new Set<number>()\n const minX =\n Math.floor((centerX - width / 2) / this.CELL_SIZE) * this.CELL_SIZE\n const minY =\n Math.floor((centerY - height / 2) / this.CELL_SIZE) * this.CELL_SIZE\n const maxX = centerX + width / 2\n const maxY = centerY + height / 2\n for (let x = minX; x <= maxX; x += this.CELL_SIZE) {\n for (let y = minY; y <= maxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey) || []\n for (const targetWithIndex of bucket) {\n if (alreadyAddedTargets.has(targetWithIndex[1])) continue\n alreadyAddedTargets.add(targetWithIndex[1])\n targets.push(targetWithIndex[0])\n }\n }\n }\n return targets\n }\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n CapacityMeshNodeId,\n Obstacle,\n SimpleRouteJson,\n} from \"../../types\"\nimport { COLORS } from \"../colors\"\nimport { isPointInRect } from \"lib/utils/isPointInRect\"\nimport { doRectsOverlap } from \"lib/utils/doRectsOverlap\"\nimport { mapLayerNameToZ } from \"lib/utils/mapLayerNameToZ\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\nimport { ObstacleTree } from \"lib/data-structures/ObstacleTree\"\nimport { TargetTree } from \"lib/data-structures/TargetTree\"\n\ninterface CapacityMeshNodeSolverOptions {\n capacityDepth?: number\n}\n\ninterface Target {\n x: number\n y: number\n bounds: {\n minX: number\n minY: number\n maxX: number\n maxY: number\n }\n connectionName: string\n availableZ: number[]\n}\n\nexport class CapacityMeshNodeSolver extends BaseSolver {\n unfinishedNodes: CapacityMeshNode[]\n finishedNodes: CapacityMeshNode[]\n\n nodeToXYOverlappingObstaclesMap: Map<CapacityMeshNodeId, Obstacle[]>\n layerCount: number\n\n // targetObstacleMap: Record<string, { obstacle: Obstacle, node: CapacityMeshNode }>\n\n MAX_DEPTH = 4\n\n targets: Target[]\n targetTree: TargetTree\n obstacleTree: ObstacleTree\n\n constructor(\n public srj: SimpleRouteJson,\n public opts: CapacityMeshNodeSolverOptions = {},\n ) {\n super()\n this.MAX_DEPTH = opts?.capacityDepth ?? this.MAX_DEPTH\n this.MAX_ITERATIONS = 100_000\n this.layerCount = srj.layerCount ?? 2\n\n for (const obstacle of srj.obstacles) {\n if (!obstacle.zLayers) {\n const zLayers: number[] = []\n for (const layer of obstacle.layers) {\n zLayers.push(mapLayerNameToZ(layer, srj.layerCount))\n }\n obstacle.zLayers = zLayers\n }\n }\n\n const boundsCenter = {\n x: (srj.bounds.minX + srj.bounds.maxX) / 2,\n y: (srj.bounds.minY + srj.bounds.maxY) / 2,\n }\n const boundsSize = {\n width: srj.bounds.maxX - srj.bounds.minX,\n height: srj.bounds.maxY - srj.bounds.minY,\n }\n const maxWidthHeight = Math.max(boundsSize.width, boundsSize.height)\n this.unfinishedNodes = [\n {\n capacityMeshNodeId: this.getNextNodeId(),\n center: boundsCenter,\n width: maxWidthHeight,\n height: maxWidthHeight,\n layer: \"top\",\n availableZ: [0, 1],\n _depth: 0,\n _containsTarget: true,\n _containsObstacle: true,\n _completelyInsideObstacle: false,\n },\n ]\n this.finishedNodes = []\n this.nodeToXYOverlappingObstaclesMap = new Map()\n this.obstacleTree = new ObstacleTree(this.srj.obstacles)\n this.targets = this.computeTargets()\n this.targetTree = new TargetTree(this.targets)\n }\n\n computeTargets(): Target[] {\n const targets: Target[] = []\n for (const conn of this.srj.connections) {\n for (const ptc of conn.pointsToConnect) {\n const obstacles = this.obstacleTree\n .getNodesInArea(ptc.x, ptc.y, 0.01, 0.01)\n .filter((o) =>\n o.zLayers!.some((z) => (ptc.layer === \"top\" ? z === 0 : z === 1)),\n )\n\n let bounds: {\n minX: number\n minY: number\n maxX: number\n maxY: number\n } = {\n minX: ptc.x - 0.005,\n minY: ptc.y - 0.005,\n maxX: ptc.x + 0.005,\n maxY: ptc.y + 0.005,\n }\n if (obstacles.length > 0) {\n bounds = {\n minX: Math.min(...obstacles.map((o) => o.center.x - o.width / 2)),\n minY: Math.min(...obstacles.map((o) => o.center.y - o.height / 2)),\n maxX: Math.max(...obstacles.map((o) => o.center.x + o.width / 2)),\n maxY: Math.max(...obstacles.map((o) => o.center.y + o.height / 2)),\n }\n }\n const target = {\n ...ptc,\n connectionName: conn.name,\n availableZ: ptc.layer === \"top\" ? [0] : [1],\n bounds,\n }\n targets.push(target)\n }\n }\n return targets\n }\n\n _nextNodeCounter = 0\n getNextNodeId(): string {\n return `cn${this._nextNodeCounter++}`\n }\n\n getCapacityFromDepth(depth: number): number {\n return (this.MAX_DEPTH - depth + 1) ** 2\n }\n\n getTargetIfNodeContainsTarget(node: CapacityMeshNode): Target | null {\n const nearbyTargets =\n node.width > this.targetTree.CELL_SIZE * 4\n ? this.targets\n : this.targetTree.getTargetsInArea(\n node.center.x,\n node.center.y,\n node.width,\n node.height,\n )\n for (const target of nearbyTargets) {\n if (\n // Check if the node and target bounds overlap\n target.bounds.minX <= node.center.x + node.width / 2 &&\n target.bounds.maxX >= node.center.x - node.width / 2 &&\n target.bounds.minY <= node.center.y + node.height / 2 &&\n target.bounds.maxY >= node.center.y - node.height / 2 &&\n target.availableZ.some((z) => node.availableZ.includes(z))\n ) {\n return target\n }\n }\n return null\n }\n\n getXYOverlappingObstacles(node: CapacityMeshNode): Obstacle[] {\n const cachedObstacles = this.nodeToXYOverlappingObstaclesMap.get(\n node.capacityMeshNodeId,\n )\n if (cachedObstacles) {\n return cachedObstacles\n }\n const overlappingObstacles: Obstacle[] = []\n\n // Compute node bounds\n const nodeLeft = node.center.x - node.width / 2\n const nodeRight = node.center.x + node.width / 2\n const nodeTop = node.center.y - node.height / 2\n const nodeBottom = node.center.y + node.height / 2\n\n const obstacles = node._parent\n ? this.getXYOverlappingObstacles(node._parent)\n : this.srj.obstacles\n for (const obstacle of obstacles) {\n const obsLeft = obstacle.center.x - obstacle.width / 2\n const obsRight = obstacle.center.x + obstacle.width / 2\n const obsTop = obstacle.center.y - obstacle.height / 2\n const obsBottom = obstacle.center.y + obstacle.height / 2\n\n // Check for intersection.\n if (\n nodeRight >= obsLeft &&\n nodeLeft <= obsRight &&\n nodeBottom >= obsTop &&\n nodeTop <= obsBottom\n ) {\n overlappingObstacles.push(obstacle)\n continue\n }\n\n // Check if the node is completely within the obstacle\n if (\n nodeLeft >= obsLeft &&\n nodeRight <= obsRight &&\n nodeTop >= obsTop &&\n nodeBottom <= obsBottom\n ) {\n // Node is completely inside the obstacle\n overlappingObstacles.push(obstacle)\n continue\n }\n\n // Check if obstacle is completely within node\n if (\n obsLeft >= nodeLeft &&\n obsRight <= nodeRight &&\n obsTop >= nodeTop &&\n obsBottom <= nodeBottom\n ) {\n overlappingObstacles.push(obstacle)\n }\n }\n\n this.nodeToXYOverlappingObstaclesMap.set(\n node.capacityMeshNodeId,\n overlappingObstacles,\n )\n\n return overlappingObstacles\n }\n\n getXYZOverlappingObstacles(node: CapacityMeshNode): Obstacle[] {\n const xyOverlappingObstacles = this.getXYOverlappingObstacles(node)\n\n // For each obstacle, check if it has any overlap in the z-axis\n const xyzOverlappingObstacles: Obstacle[] = []\n for (const obstacle of xyOverlappingObstacles) {\n if (node.availableZ.some((z) => obstacle.zLayers!.includes(z))) {\n xyzOverlappingObstacles.push(obstacle)\n }\n }\n\n return xyzOverlappingObstacles\n }\n\n /**\n * Checks if the given mesh node overlaps with any obstacle.\n * We treat both obstacles and nodes as axis‐aligned rectangles.\n */\n doesNodeOverlapObstacle(node: CapacityMeshNode): boolean {\n const overlappingObstacles = this.getXYZOverlappingObstacles(node)\n\n if (overlappingObstacles.length > 0) {\n return true\n }\n\n // Compute node bounds\n const nodeLeft = node.center.x - node.width / 2\n const nodeRight = node.center.x + node.width / 2\n const nodeTop = node.center.y - node.height / 2\n const nodeBottom = node.center.y + node.height / 2\n\n // If node is outside the bounds, we consider it to contain an obstacle\n if (\n nodeLeft < this.srj.bounds.minX ||\n nodeRight > this.srj.bounds.maxX ||\n nodeTop < this.srj.bounds.minY ||\n nodeBottom > this.srj.bounds.maxY\n ) {\n return true\n }\n return false\n }\n\n /**\n * Checks if the entire node is contained within any obstacle.\n */\n isNodeCompletelyInsideObstacle(node: CapacityMeshNode): boolean {\n const overlappingObstacles = this.getXYZOverlappingObstacles(node)\n\n // Compute node bounds\n const nodeLeft = node.center.x - node.width / 2\n const nodeRight = node.center.x + node.width / 2\n const nodeTop = node.center.y - node.height / 2\n const nodeBottom = node.center.y + node.height / 2\n\n for (const obstacle of overlappingObstacles) {\n const obsLeft = obstacle.center.x - obstacle.width / 2\n const obsRight = obstacle.center.x + obstacle.width / 2\n const obsTop = obstacle.center.y - obstacle.height / 2\n const obsBottom = obstacle.center.y + obstacle.height / 2\n\n // Check if the node's bounds are completely inside the obstacle's bounds.\n if (\n nodeLeft >= obsLeft &&\n nodeRight <= obsRight &&\n nodeTop >= obsTop &&\n nodeBottom <= obsBottom\n ) {\n return true\n }\n }\n\n // if (\n // nodeRight < this.srj.bounds.minX ||\n // nodeLeft > this.srj.bounds.maxX ||\n // nodeBottom < this.srj.bounds.minY ||\n // nodeTop > this.srj.bounds.maxY\n // ) {\n // return true\n // }\n\n return false\n }\n\n getChildNodes(parent: CapacityMeshNode): CapacityMeshNode[] {\n if (parent._depth === this.MAX_DEPTH) return []\n const childNodes: CapacityMeshNode[] = []\n\n const childNodeSize = { width: parent.width / 2, height: parent.height / 2 }\n\n const childNodePositions = [\n {\n x: parent.center.x - childNodeSize.width / 2,\n y: parent.center.y - childNodeSize.height / 2,\n },\n {\n x: parent.center.x + childNodeSize.width / 2,\n y: parent.center.y - childNodeSize.height / 2,\n },\n {\n x: parent.center.x - childNodeSize.width / 2,\n y: parent.center.y + childNodeSize.height / 2,\n },\n {\n x: parent.center.x + childNodeSize.width / 2,\n y: parent.center.y + childNodeSize.height / 2,\n },\n ]\n\n for (const position of childNodePositions) {\n const childNode: CapacityMeshNode = {\n capacityMeshNodeId: this.getNextNodeId(),\n center: position,\n width: childNodeSize.width,\n height: childNodeSize.height,\n layer: parent.layer,\n availableZ: [0, 1],\n _depth: (parent._depth ?? 0) + 1,\n _parent: parent,\n }\n childNode._containsObstacle = this.doesNodeOverlapObstacle(childNode)\n\n const target = this.getTargetIfNodeContainsTarget(childNode)\n\n if (target) {\n childNode._targetConnectionName = target.connectionName\n childNode.availableZ = target.availableZ\n childNode._containsTarget = true\n }\n\n if (childNode._containsObstacle) {\n childNode._completelyInsideObstacle =\n this.isNodeCompletelyInsideObstacle(childNode)\n }\n if (childNode._completelyInsideObstacle && !childNode._containsTarget)\n continue\n childNodes.push(childNode)\n }\n\n return childNodes\n }\n\n shouldNodeBeXYSubdivided(node: CapacityMeshNode) {\n if (node._depth! >= this.MAX_DEPTH) return false\n if (node._containsTarget) return true\n if (node._containsObstacle && !node._completelyInsideObstacle) return true\n return false\n }\n\n _step() {\n const nextNode = this.unfinishedNodes.pop()\n if (!nextNode) {\n this.solved = true\n return\n }\n\n const newNodes = this.getChildNodes(nextNode)\n\n const finishedNewNodes: CapacityMeshNode[] = []\n const unfinishedNewNodes: CapacityMeshNode[] = []\n\n for (const newNode of newNodes) {\n const shouldBeSubdivided = this.shouldNodeBeXYSubdivided(newNode)\n if (shouldBeSubdivided) {\n unfinishedNewNodes.push(newNode)\n } else if (!shouldBeSubdivided && !newNode._containsObstacle) {\n finishedNewNodes.push(newNode)\n } else if (!shouldBeSubdivided && newNode._containsTarget) {\n finishedNewNodes.push(newNode)\n }\n }\n\n this.unfinishedNodes.push(...unfinishedNewNodes)\n this.finishedNodes.push(...finishedNewNodes)\n }\n\n /**\n * Creates a GraphicsObject to visualize the mesh, its nodes, obstacles, and connection points.\n *\n * - Mesh nodes are rendered as rectangles.\n * - Nodes that have an obstacle intersection are outlined in red.\n * - Other nodes are outlined in green.\n * - Lines are drawn from a node to its parent.\n * - Obstacles are drawn as semi-transparent red rectangles.\n * - Points for each connection’s pointsToConnect are drawn in a unique color.\n */\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Capacity Mesh Visualization\",\n }\n\n // Draw obstacles\n for (const obstacle of this.srj.obstacles) {\n graphics.rects!.push({\n center: obstacle.center,\n width: obstacle.width,\n height: obstacle.height,\n fill:\n obstacle.zLayers?.length === 1 && obstacle.zLayers?.includes(1)\n ? \"rgba(0,0,255,0.3)\"\n : \"rgba(255,0,0,0.3)\",\n stroke: \"red\",\n label: [\"obstacle\", `z: ${obstacle.zLayers!.join(\",\")}`].join(\"\\n\"),\n })\n }\n\n // Draw mesh nodes (both finished and unfinished)\n const allNodes = [...this.finishedNodes, ...this.unfinishedNodes]\n for (const node of allNodes) {\n const lowestZ = Math.min(...node.availableZ)\n const isNextToBeProcessed =\n this.unfinishedNodes.length > 0 &&\n node === this.unfinishedNodes[this.unfinishedNodes.length - 1]\n\n graphics.rects!.push({\n center: {\n x: node.center.x + lowestZ * node.width * 0.05,\n y: node.center.y - lowestZ * node.width * 0.05,\n },\n width: Math.max(node.width - 2, node.width * 0.8),\n height: Math.max(node.height - 2, node.height * 0.8),\n fill: node._containsObstacle\n ? \"rgba(255,0,0,0.1)\"\n : ({\n \"0,1\": \"rgba(0,0,0,0.1)\",\n \"0\": \"rgba(0,200,200, 0.1)\",\n \"1\": \"rgba(0,0,200, 0.1)\",\n }[node.availableZ.join(\",\")] ?? \"rgba(0,200,200,0.1)\"),\n stroke: isNextToBeProcessed ? \"rgba(255,165,0,0.5)\" : undefined,\n label: [\n node.capacityMeshNodeId,\n `availableZ: ${node.availableZ.join(\",\")}`,\n `target? ${node._containsTarget ?? false}`,\n `obs? ${node._containsObstacle ?? false}`,\n `${node.width.toFixed(2)}x${node.height.toFixed(2)}`,\n `capacity: ${getTunedTotalCapacity1(node).toFixed(2)}`,\n ].join(\"\\n\"),\n })\n }\n graphics.rects!.sort((a, b) => a.center.y - b.center.y)\n\n // Draw connection points (each connection gets a unique color).\n this.srj.connections.forEach((connection, index) => {\n const color = COLORS[index % COLORS.length]\n for (const pt of connection.pointsToConnect) {\n graphics.points!.push({\n x: pt.x,\n y: pt.y,\n label: `conn-${index} (${pt.layer})`,\n color,\n })\n }\n })\n\n return graphics\n }\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n CapacityMeshNodeId,\n Obstacle,\n SimpleRouteJson,\n} from \"../../types\"\nimport { COLORS } from \"../colors\"\nimport { isPointInRect } from \"lib/utils/isPointInRect\"\nimport { doRectsOverlap } from \"lib/utils/doRectsOverlap\"\nimport { CapacityMeshNodeSolver } from \"./CapacityMeshNodeSolver1\"\nimport { mapLayerNameToZ } from \"lib/utils/mapLayerNameToZ\"\n\ninterface CapacityMeshNodeSolverOptions {\n capacityDepth?: number\n}\n\ninterface Target {\n x: number\n y: number\n connectionName: string\n availableZ: number[]\n}\n\nexport class CapacityMeshNodeSolver2_NodeUnderObstacle extends CapacityMeshNodeSolver {\n VIA_DIAMETER = 0.6\n OBSTACLE_MARGIN = 0.1\n\n constructor(\n public srj: SimpleRouteJson,\n public opts: CapacityMeshNodeSolverOptions = {},\n ) {\n super(srj, opts)\n }\n\n isNodeCompletelyOutsideBounds(node: CapacityMeshNode): boolean {\n return (\n node.center.x + node.width / 2 < this.srj.bounds.minX ||\n node.center.x - node.width / 2 > this.srj.bounds.maxX ||\n node.center.y + node.height / 2 < this.srj.bounds.minY ||\n node.center.y - node.height / 2 > this.srj.bounds.maxY\n )\n }\n\n isNodePartiallyOutsideBounds(node: CapacityMeshNode): boolean {\n return (\n node.center.x - node.width / 2 < this.srj.bounds.minX ||\n node.center.x + node.width / 2 > this.srj.bounds.maxX ||\n node.center.y - node.height / 2 < this.srj.bounds.minY ||\n node.center.y + node.height / 2 > this.srj.bounds.maxY\n )\n }\n createChildNodeAtPosition(\n parent: CapacityMeshNode,\n opts: {\n center: { x: number; y: number }\n width: number\n height: number\n availableZ: number[]\n _depth?: number\n },\n ): CapacityMeshNode {\n const childNode: CapacityMeshNode = {\n capacityMeshNodeId: this.getNextNodeId(),\n center: opts.center,\n width: opts.width,\n height: opts.height,\n layer: parent.layer,\n availableZ: opts.availableZ,\n _depth: opts._depth ?? (parent._depth ?? 0) + 1,\n _parent: parent,\n }\n\n const overlappingObstacles = this.getXYZOverlappingObstacles(childNode)\n\n childNode._containsObstacle =\n overlappingObstacles.length > 0 ||\n this.isNodePartiallyOutsideBounds(childNode)\n\n const target = this.getTargetIfNodeContainsTarget(childNode)\n\n if (target) {\n childNode._targetConnectionName = target.connectionName\n childNode._containsTarget = true\n }\n\n if (childNode._containsObstacle) {\n childNode._completelyInsideObstacle =\n this.isNodeCompletelyInsideObstacle(childNode)\n }\n // childNode._shouldBeInGraph =\n // (!isOutsideBounds && !childNode._completelyInsideObstacle) || childNode._\n\n return childNode\n }\n\n getZSubdivisionChildNodes(node: CapacityMeshNode): CapacityMeshNode[] {\n if (node.availableZ.length === 1) return []\n\n const childNodes: CapacityMeshNode[] = []\n\n // TODO when we have more than 2 layers, we need to handle other\n // variations, you always want to prioritize having larger contiguous\n // z-blocks\n const otherZBlocks = [[0], [1]]\n\n for (const zBlock of otherZBlocks) {\n const childNode = this.createChildNodeAtPosition(node, {\n center: { ...node.center },\n width: node.width,\n height: node.height,\n availableZ: zBlock,\n // z-subdivision doesn't count towards depth, should be same as parent\n _depth: node._depth!,\n })\n\n if (this.isNodeCompletelyOutsideBounds(childNode)) {\n continue\n }\n\n childNodes.push(childNode)\n }\n\n return childNodes\n }\n\n getChildNodes(parent: CapacityMeshNode): CapacityMeshNode[] {\n if (parent._depth! >= this.MAX_DEPTH) return []\n const childNodes: CapacityMeshNode[] = []\n\n const childNodeSize = { width: parent.width / 2, height: parent.height / 2 }\n\n const childNodePositions = [\n {\n x: parent.center.x - childNodeSize.width / 2,\n y: parent.center.y - childNodeSize.height / 2,\n },\n {\n x: parent.center.x + childNodeSize.width / 2,\n y: parent.center.y - childNodeSize.height / 2,\n },\n {\n x: parent.center.x - childNodeSize.width / 2,\n y: parent.center.y + childNodeSize.height / 2,\n },\n {\n x: parent.center.x + childNodeSize.width / 2,\n y: parent.center.y + childNodeSize.height / 2,\n },\n ]\n\n for (const position of childNodePositions) {\n const childNode = this.createChildNodeAtPosition(parent, {\n center: position,\n width: childNodeSize.width,\n height: childNodeSize.height,\n availableZ: parent.availableZ,\n })\n if (this.isNodeCompletelyOutsideBounds(childNode)) {\n continue\n }\n childNodes.push(childNode)\n }\n\n return childNodes\n }\n\n shouldNodeBeXYSubdivided(node: CapacityMeshNode) {\n if (node._depth! >= this.MAX_DEPTH) return false\n if (node._containsTarget) return true\n if (node.availableZ.length === 1 && node._depth! <= this.MAX_DEPTH)\n return true\n if (node._containsObstacle && !node._completelyInsideObstacle) return true\n return false\n }\n\n _step() {\n const nextNode = this.unfinishedNodes.pop()\n if (!nextNode) {\n this.solved = true\n return\n }\n\n const childNodes = this.getChildNodes(nextNode)\n\n const finishedNewNodes: CapacityMeshNode[] = []\n const unfinishedNewNodes: CapacityMeshNode[] = []\n\n for (const childNode of childNodes) {\n const shouldBeXYSubdivided = this.shouldNodeBeXYSubdivided(childNode)\n const shouldBeZSubdivided =\n childNode.availableZ.length > 1 &&\n !shouldBeXYSubdivided &&\n (childNode._containsObstacle ||\n childNode.width < this.VIA_DIAMETER + this.OBSTACLE_MARGIN)\n if (shouldBeXYSubdivided) {\n unfinishedNewNodes.push(childNode)\n } else if (\n !shouldBeXYSubdivided &&\n !childNode._containsObstacle &&\n !shouldBeZSubdivided\n ) {\n finishedNewNodes.push(childNode)\n } else if (!shouldBeXYSubdivided && childNode._containsTarget) {\n if (shouldBeZSubdivided) {\n const zSubNodes = this.getZSubdivisionChildNodes(childNode)\n finishedNewNodes.push(\n ...zSubNodes.filter(\n (n) => n._containsTarget || !n._containsObstacle,\n ),\n )\n } else {\n finishedNewNodes.push(childNode)\n }\n } else if (shouldBeZSubdivided) {\n finishedNewNodes.push(\n ...this.getZSubdivisionChildNodes(childNode).filter(\n (zSubNode) => !zSubNode._containsObstacle,\n ),\n )\n }\n }\n\n this.unfinishedNodes.push(...unfinishedNewNodes)\n this.finishedNodes.push(...finishedNewNodes)\n }\n}\n","import type { CapacityMeshEdge, CapacityMeshNodeId } from \"../../types\"\n\nexport function getNodeEdgeMap(\n edges: CapacityMeshEdge[],\n): Map<CapacityMeshNodeId, CapacityMeshEdge[]> {\n const nodeEdgeMap = new Map<CapacityMeshNodeId, CapacityMeshEdge[]>()\n\n for (const edge of edges) {\n for (const nodeId of edge.nodeIds) {\n nodeEdgeMap.set(nodeId, [...(nodeEdgeMap.get(nodeId) ?? []), edge])\n }\n }\n\n return nodeEdgeMap\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n CapacityMeshNodeId,\n CapacityPath,\n} from \"../../types\"\nimport type { NodePortSegment } from \"../../types/capacity-edges-to-port-segments-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { getNodeEdgeMap } from \"./getNodeEdgeMap\"\nimport { safeTransparentize } from \"../colors\"\n\n/**\n * Each Node is a square. The capacity paths indicate the nodes the trace will\n * travel through. We want to find the \"Port Segment\" that each capacity path\n * will take for each node.\n */\nexport class CapacityEdgeToPortSegmentSolver extends BaseSolver {\n nodes: CapacityMeshNode[]\n edges: CapacityMeshEdge[]\n capacityPaths: CapacityPath[]\n\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n nodeEdgeMap: Map<CapacityMeshNodeId, CapacityMeshEdge[]>\n\n unprocessedNodeIds: CapacityMeshNodeId[]\n\n nodePortSegments: Map<CapacityMeshNodeId, NodePortSegment[]>\n colorMap: Record<string, string>\n\n constructor({\n nodes,\n edges,\n capacityPaths,\n colorMap,\n }: {\n nodes: CapacityMeshNode[]\n edges: CapacityMeshEdge[]\n capacityPaths: CapacityPath[]\n colorMap?: Record<string, string>\n }) {\n super()\n this.nodes = nodes\n this.edges = edges\n this.nodeMap = new Map(nodes.map((node) => [node.capacityMeshNodeId, node]))\n this.nodeEdgeMap = getNodeEdgeMap(edges)\n this.capacityPaths = capacityPaths\n this.colorMap = colorMap ?? {}\n\n // We will be evaluating capacity paths\n this.unprocessedNodeIds = [\n ...new Set(capacityPaths.flatMap((path) => path.nodeIds)),\n ]\n this.nodePortSegments = new Map()\n }\n\n step() {\n const nodeId = this.unprocessedNodeIds.pop()\n if (!nodeId) {\n this.solved = true\n return\n }\n\n const pathsGoingThroughNode: Array<{\n path: CapacityPath\n indexOfNodeInPath: number\n }> = []\n for (const path of this.capacityPaths) {\n const indexOfNodeInPath = path.nodeIds.indexOf(nodeId)\n if (indexOfNodeInPath !== -1) {\n pathsGoingThroughNode.push({ path, indexOfNodeInPath })\n }\n }\n\n const node = this.nodeMap.get(nodeId)!\n const nodePortSegments: NodePortSegment[] = []\n\n for (const { path, indexOfNodeInPath } of pathsGoingThroughNode) {\n const entryNodeId = path.nodeIds[indexOfNodeInPath - 1]\n const exitNodeId = path.nodeIds[indexOfNodeInPath + 1]\n\n for (const adjNodeId of [entryNodeId, exitNodeId]) {\n const adjNode = this.nodeMap.get(adjNodeId)!\n if (!adjNode) continue\n const segment = findOverlappingSegment(node, adjNode)\n\n const mutuallyAvailableZ = adjNode.availableZ.filter((z) =>\n node.availableZ.includes(z),\n )\n\n if (mutuallyAvailableZ.length === 0) continue\n\n const portSegment: NodePortSegment = {\n capacityMeshNodeId: nodeId,\n start: segment.start,\n end: segment.end,\n connectionNames: [path.connectionName],\n availableZ: mutuallyAvailableZ,\n }\n\n nodePortSegments.push(portSegment)\n }\n }\n\n // Combine overlapping or adjacent segments on the same edge.\n const combinedSegments = combineSegments(nodePortSegments)\n this.nodePortSegments.set(nodeId, combinedSegments)\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n this.nodePortSegments.forEach((segments, nodeId) => {\n const node = this.nodeMap.get(nodeId)!\n segments.forEach((segment) => {\n const isVertical = segment.start.x === segment.end.x\n const THICKNESS = 0.05\n for (let i = 0; i < segment.connectionNames.length; i++) {\n const offset = {\n x: 0.05 * Math.max(...segment.availableZ),\n y: 0.05 * Math.max(...segment.availableZ),\n }\n const trueSegmentCenter = {\n x: (segment.start.x + segment.end.x) / 2,\n y: (segment.start.y + segment.end.y) / 2,\n }\n const segmentCenter = {\n x: trueSegmentCenter.x + offset.x,\n y: trueSegmentCenter.y + offset.y,\n }\n if (offset.x > 0) {\n // small dashed line to show the true center\n graphics.lines!.push({\n points: [trueSegmentCenter, segmentCenter],\n strokeColor: \"rgba(0, 0, 0, 0.25)\",\n strokeDash: \"5 5\",\n })\n }\n graphics.points!.push({\n x: segmentCenter.x,\n y: segmentCenter.y,\n label: `${nodeId}: ${segment.connectionNames.join(\", \")}\\navailableZ: ${segment.availableZ.join(\",\")}\\nnodePortSegmentId: ${segment.nodePortSegmentId!}`,\n })\n graphics.lines!.push({\n points: [segment.start, segment.end],\n strokeColor: safeTransparentize(\n this.colorMap[segment.connectionNames[i]],\n 0.6,\n ),\n })\n }\n })\n })\n return graphics\n }\n}\n\nfunction findOverlappingSegment(\n node: CapacityMeshNode,\n adjNode: CapacityMeshNode,\n): { start: { x: number; y: number }; end: { x: number; y: number } } {\n // Find overlapping ranges in x and y dimensions\n const xOverlap = {\n start: Math.max(\n node.center.x - node.width / 2,\n adjNode.center.x - adjNode.width / 2,\n ),\n end: Math.min(\n node.center.x + node.width / 2,\n adjNode.center.x + adjNode.width / 2,\n ),\n }\n\n const yOverlap = {\n start: Math.max(\n node.center.y - node.height / 2,\n adjNode.center.y - adjNode.height / 2,\n ),\n end: Math.min(\n node.center.y + node.height / 2,\n adjNode.center.y + adjNode.height / 2,\n ),\n }\n\n const xRange = xOverlap.end - xOverlap.start\n const yRange = yOverlap.end - yOverlap.start\n\n // If the x-range is smaller then the nodes touch vertically (common vertical edge).\n if (xRange < yRange) {\n // They are horizontally adjacent: shared vertical edge.\n const x = (xOverlap.start + xOverlap.end) / 2\n return {\n start: { x, y: yOverlap.start },\n end: { x, y: yOverlap.end },\n }\n } else {\n // Otherwise, they are vertically adjacent: shared horizontal edge.\n const y = (yOverlap.start + yOverlap.end) / 2\n return {\n start: { x: xOverlap.start, y },\n end: { x: xOverlap.end, y },\n }\n }\n}\n\nconst EPSILON = 1e-9 // Adjust threshold as needed\n\nfunction coordsAreEqual(\n p1: { x: number; y: number },\n p2: { x: number; y: number },\n): boolean {\n return Math.abs(p1.x - p2.x) < EPSILON && Math.abs(p1.y - p2.y) < EPSILON\n}\n\n// Helper to compare availableZ arrays (order matters for equality check here)\nfunction availableZAreEqual(zA1: number[], zA2: number[]): boolean {\n if (zA1.length !== zA2.length) {\n return false\n }\n // Assuming they are sorted or order matters for distinction\n for (let i = 0; i < zA1.length; i++) {\n if (zA1[i] !== zA2[i]) {\n return false\n }\n }\n return true\n}\n\n/**\n * Given a list of segments on a node, merge segments that are geometrically\n * identical (same start/end points, potentially swapped) AND share the exact\n * same availableZ list. Combines only their connection names.\n */\nfunction combineSegments(segments: NodePortSegment[]): NodePortSegment[] {\n const mergedSegments: NodePortSegment[] = []\n // Create copies to avoid modifying the original array during iteration\n // Sort availableZ consistently within each segment copy first\n const remainingSegments = segments.map((s) => ({\n ...s,\n connectionNames: [...s.connectionNames],\n availableZ: [...s.availableZ].sort((a, b) => a - b), // Ensure Z is sorted for comparison\n }))\n\n while (remainingSegments.length > 0) {\n const segmentUnderTest = remainingSegments.pop()!\n let foundMatch = false\n\n for (let i = 0; i < mergedSegments.length; i++) {\n const mergedSegment = mergedSegments[i]\n\n // Check 1: Geometric match (allowing for start/end swap)\n const geometryMatch =\n (coordsAreEqual(mergedSegment.start, segmentUnderTest.start) &&\n coordsAreEqual(mergedSegment.end, segmentUnderTest.end)) ||\n (coordsAreEqual(mergedSegment.start, segmentUnderTest.end) &&\n coordsAreEqual(mergedSegment.end, segmentUnderTest.start))\n\n // Check 2: availableZ match\n const zMatch = availableZAreEqual(\n mergedSegment.availableZ,\n segmentUnderTest.availableZ,\n )\n\n if (geometryMatch && zMatch) {\n // --- Merge Logic ---\n // Combine connection names (ensuring uniqueness)\n const currentConnections = new Set(mergedSegment.connectionNames)\n segmentUnderTest.connectionNames.forEach((cn) =>\n currentConnections.add(cn),\n )\n mergedSegment.connectionNames = Array.from(currentConnections)\n\n // DO NOT merge availableZ - they must be identical to reach here.\n\n foundMatch = true\n break // Found a match for segmentUnderTest, move to next remaining\n }\n }\n\n if (!foundMatch) {\n // If no suitable match was found (different geometry OR different availableZ),\n // add the segmentUnderTest as a new distinct merged segment.\n mergedSegments.push(segmentUnderTest)\n }\n }\n return mergedSegments\n}\n","import { BaseSolver } from \"../BaseSolver\"\nimport type { NodePortSegment } from \"../../types/capacity-edges-to-port-segments-types\"\nimport type { GraphicsObject, Line } from \"graphics-debug\"\nimport type { NodeWithPortPoints } from \"../../types/high-density-types\"\nimport type { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\n\nexport interface SegmentWithAssignedPoints extends NodePortSegment {\n assignedPoints?: {\n connectionName: string\n point: { x: number; y: number; z: number }\n }[]\n}\n\n/**\n * CapacitySegmentToPointSolver:\n *\n * In each step, the solver iterates over all unsolved segments (segments\n * without points assigned for each connection). For each segment:\n *\n * - If there is only one connection, it assigns the center as the point.\n * - If there are two connections, it attempts to determine the ordering using\n * other segments within the node. If no ordering can be determined, it does nothing.\n *\n * If an iteration produces no new assignments, the solver picks the segment with\n * the fewest connections and assigns points evenly spaced along the segment,\n * ordering them alphabetically.\n */\nexport class CapacitySegmentToPointSolver extends BaseSolver {\n unsolvedSegments: SegmentWithAssignedPoints[]\n solvedSegments: (NodePortSegment & {\n assignedPoints: {\n connectionName: string\n point: { x: number; y: number; z: number }\n }[]\n })[]\n nodeMap: Record<string, CapacityMeshNode>\n colorMap: Record<string, string>\n\n // We use an extra property on segments to remember assigned points.\n // Each segment will get an added property \"assignedPoints\" which is an array of:\n // { connectionName: string, point: {x: number, y: number } }\n // This is a temporary extension used by the solver.\n constructor({\n segments,\n colorMap,\n nodes,\n }: {\n segments: NodePortSegment[]\n colorMap?: Record<string, string>\n /**\n * This isn't used by the algorithm, but allows associating metadata\n * for the result datatype (the center, width, height of the node)\n */\n nodes: CapacityMeshNode[]\n }) {\n super()\n this.MAX_ITERATIONS = 100_000\n this.unsolvedSegments = segments\n this.solvedSegments = []\n this.colorMap = colorMap ?? {}\n this.nodeMap = Object.fromEntries(\n nodes.map((node) => [node.capacityMeshNodeId, node]),\n )\n }\n\n /**\n * Perform one iteration step.\n */\n _step() {\n let updated = false\n // unsolved segments: segments without complete assignments.\n const unsolved = [...this.unsolvedSegments]\n\n // Iterate over unsolved segments.\n for (const seg of unsolved) {\n const n = seg.connectionNames.length\n // Already processed? Skip if assignedPoints exists for all connections.\n if (\"assignedPoints\" in seg && seg.assignedPoints?.length === n) continue\n\n if (n === 1) {\n // For a single connection, assign the center of the segment.\n const center = {\n x: (seg.start.x + seg.end.x) / 2,\n y: (seg.start.y + seg.end.y) / 2,\n z: seg.availableZ[0],\n }\n ;(seg as any).assignedPoints = [\n { connectionName: seg.connectionNames[0], point: center },\n ]\n // Move seg from unsolvedSegments to solvedSegments.\n this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(seg), 1)\n this.solvedSegments.push(seg as any)\n updated = true\n }\n }\n\n // If no segments were updated in this iteration, perform a fallback.\n if (!updated && unsolved.length > 0) {\n // Choose the unsolved segment with the fewest connections.\n let candidate = unsolved[0]\n for (const seg of unsolved) {\n if (seg.connectionNames.length < candidate.connectionNames.length) {\n candidate = seg\n }\n }\n // Fallback: assign points evenly spaced along the segment,\n // after sorting connection names alphabetically.\n const sortedConnections = [...candidate.connectionNames].sort()\n const dx = candidate.end.x - candidate.start.x\n const dy = candidate.end.y - candidate.start.y\n const n = sortedConnections.length\n const points: { x: number; y: number; z: number }[] = []\n // Evenly space positions using fractions of the segment distance.\n for (let i = 1; i <= n; i++) {\n const fraction = i / (n + 1)\n points.push({\n x: candidate.start.x + dx * fraction,\n y: candidate.start.y + dy * fraction,\n z: candidate.availableZ[0],\n })\n }\n ;(candidate as any).assignedPoints = sortedConnections.map(\n (conn, idx) => ({\n connectionName: conn,\n point: points[idx],\n }),\n )\n // Move candidate from unsolvedSegments to solvedSegments.\n this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(candidate), 1)\n this.solvedSegments.push(candidate as any)\n updated = true\n }\n\n // If all segments have been assigned points, mark solved.\n if (this.unsolvedSegments.length === 0) {\n this.solved = true\n }\n }\n\n /**\n * Return the assigned points for each segment.\n */\n getNodesWithPortPoints(): NodeWithPortPoints[] {\n if (!this.solved) {\n throw new Error(\n \"CapacitySegmentToPointSolver not solved, can't give port points yet\",\n )\n }\n const map = new Map<string, NodeWithPortPoints>()\n for (const seg of this.solvedSegments) {\n const nodeId = seg.capacityMeshNodeId\n const node = this.nodeMap[nodeId]\n if (!map.has(nodeId)) {\n map.set(nodeId, {\n capacityMeshNodeId: nodeId,\n portPoints: [],\n center: node.center,\n width: node.width,\n height: node.height,\n })\n }\n map.get(nodeId)!.portPoints.push(\n ...seg.assignedPoints.map((ap) => ({\n ...ap.point,\n connectionName: ap.connectionName,\n })),\n )\n }\n return Array.from(map.values())\n }\n\n /**\n * Return a GraphicsObject that visualizes the segments with assigned points.\n */\n visualize(): GraphicsObject {\n const graphics: Required<GraphicsObject> = {\n points: [],\n lines: this.solvedSegments.map((seg) => ({\n points: [seg.start, seg.end],\n step: 4,\n })),\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Capacity Segment to Point Solver\",\n }\n\n // Add points for each assigned point on solved segments\n for (let i = 0; i < this.solvedSegments.length; i++) {\n const seg = this.solvedSegments[i]\n for (let j = 0; j < seg.assignedPoints.length; j++) {\n const ap = seg.assignedPoints[j]\n\n // Calculate the true position and the offset position (if z != 0)\n const truePoint = {\n x: ap.point.x,\n y: ap.point.y,\n }\n\n const offsetPoint = {\n x: ap.point.x + ap.point.z * 0.05,\n y: ap.point.y + ap.point.z * 0.05,\n }\n\n // Add a dashed line to show the true position if there's an offset\n if (ap.point.z !== 0) {\n graphics.lines.push({\n points: [truePoint, offsetPoint],\n strokeColor: \"rgba(0, 0, 0, 0.25)\",\n strokeDash: \"5 5\",\n step: 4,\n })\n }\n\n // Add the point with label\n graphics.points.push({\n x: offsetPoint.x,\n y: offsetPoint.y,\n label: [\n `${seg.capacityMeshNodeId}-${ap.connectionName}`,\n `z: ${seg.availableZ.join(\",\")}`,\n `nodePortSegmentId: ${seg.nodePortSegmentId}`,\n ].join(\"\\n\"),\n color: this.colorMap[ap.connectionName],\n step: 4,\n })\n }\n }\n\n // Add a dashed line connecting the assignment points with the same\n // connection name within the same node\n const dashedLines: Line[] = []\n const nodeConnections: Record<\n CapacityMeshNodeId,\n Record<string, { x: number; y: number }[]>\n > = {}\n for (const seg of this.solvedSegments) {\n const nodeId = seg.capacityMeshNodeId\n if (!nodeConnections[nodeId]) {\n nodeConnections[nodeId] = {}\n }\n for (const ap of seg.assignedPoints) {\n if (!nodeConnections[nodeId][ap.connectionName]) {\n nodeConnections[nodeId][ap.connectionName] = []\n }\n nodeConnections[nodeId][ap.connectionName].push({\n x: ap.point.x,\n y: ap.point.y,\n })\n }\n }\n for (const nodeId in nodeConnections) {\n for (const conn in nodeConnections[nodeId]) {\n const points = nodeConnections[nodeId][conn]\n if (points.length > 1) {\n dashedLines.push({\n points,\n step: 4,\n strokeDash: \"5 5\",\n strokeColor: this.colorMap[conn] || \"#000\",\n } as Line)\n }\n }\n }\n graphics.lines.push(...(dashedLines as any))\n\n return graphics\n }\n}\n","import type { Point } from \"./common\"\n\n/**\n * Returns true if the two lines intersect.\n */\nexport function doesLineIntersectLine(\n [a1, a2]: [Point, Point],\n [b1, b2]: [Point, Point],\n {\n lineThickness = 0,\n }: {\n lineThickness?: number\n } = {},\n): boolean {\n if (lineThickness === 0) {\n return doSegmentsIntersect(a1, a2, b1, b2)\n }\n const minDist = segmentsDistance(a1, a2, b1, b2)\n return minDist <= lineThickness\n}\n\n/**\n * Returns true if the two segments intersect.\n */\nexport function doSegmentsIntersect(\n p1: Point,\n q1: Point,\n p2: Point,\n q2: Point,\n): boolean {\n const o1 = orientation(p1, q1, p2)\n const o2 = orientation(p1, q1, q2)\n const o3 = orientation(p2, q2, p1)\n const o4 = orientation(p2, q2, q1)\n\n // General case\n if (o1 !== o2 && o3 !== o4) {\n return true\n }\n\n // Special Cases\n if (o1 === 0 && onSegment(p1, p2, q1)) return true\n if (o2 === 0 && onSegment(p1, q2, q1)) return true\n if (o3 === 0 && onSegment(p2, p1, q2)) return true\n if (o4 === 0 && onSegment(p2, q1, q2)) return true\n\n return false\n}\n\n/**\n * Returns 0 if the points are colinear, 1 if they are clockwise, and 2 if they are counterclockwise.\n */\nexport function orientation(p: Point, q: Point, r: Point): number {\n const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)\n if (val === 0) return 0 // colinear\n return val > 0 ? 1 : 2 // clock or counterclock wise\n}\n\n/**\n * Returns true if q is on the segment p->r.\n */\nexport function onSegment(p: Point, q: Point, r: Point): boolean {\n return (\n q.x <= Math.max(p.x, r.x) &&\n q.x >= Math.min(p.x, r.x) &&\n q.y <= Math.max(p.y, r.y) &&\n q.y >= Math.min(p.y, r.y)\n )\n}\n\n/**\n * Returns the minimum distance between two segments.\n */\nfunction segmentsDistance(a1: Point, a2: Point, b1: Point, b2: Point): number {\n // Handle degenerate cases: segments of zero length\n if (a1.x === a2.x && a1.y === a2.y) {\n return pointToSegmentDistance(a1, b1, b2)\n }\n if (b1.x === b2.x && b1.y === b2.y) {\n return pointToSegmentDistance(b1, a1, a2)\n }\n\n // Check if segments intersect\n if (doSegmentsIntersect(a1, a2, b1, b2)) {\n return 0\n }\n\n // Compute the minimum distance between the segments\n const distances = [\n pointToSegmentDistance(a1, b1, b2),\n pointToSegmentDistance(a2, b1, b2),\n pointToSegmentDistance(b1, a1, a2),\n pointToSegmentDistance(b2, a1, a2),\n ]\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance between a point and a segment.\n */\nexport function pointToSegmentDistance(p: Point, v: Point, w: Point): number {\n const l2 = (w.x - v.x) ** 2 + (w.y - v.y) ** 2\n if (l2 === 0) return distance(p, v)\n\n let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2\n t = Math.max(0, Math.min(1, t))\n\n const projection = {\n x: v.x + t * (w.x - v.x),\n y: v.y + t * (w.y - v.y),\n }\n\n return distance(p, projection)\n}\n\n/**\n * Returns the distance between two points.\n */\nexport function distance(p1: Point, p2: Point): number {\n const dx = p1.x - p2.x\n const dy = p1.y - p2.y\n return Math.sqrt(dx * dx + dy * dy)\n}\n","import type { Point } from \"./common\"\n\nexport type Box = { center: Point; width: number; height: number }\nexport type BoxSet = Box[]\n\nexport type GridCell = { boxes: Box[] }\n\nexport function getBoundingBox(box: Box) {\n const halfWidth = box.width / 2\n const halfHeight = box.height / 2\n return {\n minX: box.center.x - halfWidth,\n maxX: box.center.x + halfWidth,\n minY: box.center.y - halfHeight,\n maxY: box.center.y + halfHeight,\n }\n}\n\nexport function computeDistanceBetweenBoxes(\n boxA: Box,\n boxB: Box,\n): { distance: number; pointA: Point; pointB: Point } {\n const a = getBoundingBox(boxA)\n const b = getBoundingBox(boxB)\n\n const dx = Math.max(a.minX - b.maxX, b.minX - a.maxX, 0)\n const dy = Math.max(a.minY - b.maxY, b.minY - a.maxY, 0)\n\n const pointA: Point = { x: 0, y: 0 }\n const pointB: Point = { x: 0, y: 0 }\n\n if (dx === 0 && dy === 0) {\n // Boxes overlap\n return { distance: 0, pointA: boxA.center, pointB: boxB.center }\n }\n\n // Compute the closest points on the edges\n pointA.x = clamp(boxA.center.x, b.minX, b.maxX)\n pointA.y = clamp(boxA.center.y, b.minY, b.maxY)\n\n pointB.x = clamp(boxB.center.x, a.minX, a.maxX)\n pointB.y = clamp(boxB.center.y, a.minY, a.maxY)\n\n const distance = Math.hypot(pointA.x - pointB.x, pointA.y - pointB.y)\n return { distance, pointA, pointB }\n}\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value))\n}\n\nexport function findNearestPointsBetweenBoxSets(\n boxSetA: BoxSet,\n boxSetB: BoxSet,\n): { pointA: Point; pointB: Point; distance: number } {\n let minDistance = Number.POSITIVE_INFINITY\n let nearestPointA: Point = { x: 0, y: 0 }\n let nearestPointB: Point = { x: 0, y: 0 }\n\n for (const boxA of boxSetA) {\n for (const boxB of boxSetB) {\n const { distance, pointA, pointB } = computeDistanceBetweenBoxes(\n boxA,\n boxB,\n )\n if (distance < minDistance) {\n minDistance = distance\n nearestPointA = pointA\n nearestPointB = pointB\n }\n }\n }\n\n return {\n pointA: nearestPointA,\n pointB: nearestPointB,\n distance: minDistance,\n }\n}\n","import type { Point } from \"./common\"\nimport {\n distance,\n doSegmentsIntersect,\n pointToSegmentDistance,\n} from \"./line-intersections\"\nimport { clamp } from \"./nearest-box\"\n\n/**\n * Returns the minimum distance between two line segments.\n */\nexport function segmentToSegmentMinDistance(\n a: Point,\n b: Point,\n u: Point,\n v: Point,\n): number {\n // Handle degenerate cases: segments of zero length\n if (a.x === b.x && a.y === b.y) {\n return pointToSegmentDistance(a, u, v)\n }\n if (u.x === v.x && u.y === v.y) {\n return pointToSegmentDistance(u, a, b)\n }\n\n // Check if segments intersect\n if (doSegmentsIntersect(a, b, u, v)) {\n return 0\n }\n\n // Compute the minimum distance between the segments\n const distances = [\n pointToSegmentDistance(a, u, v),\n pointToSegmentDistance(b, u, v),\n pointToSegmentDistance(u, a, b),\n pointToSegmentDistance(v, a, b),\n ]\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance from a line segment to a bounding box.\n */\nexport function segmentToBoundsMinDistance(\n a: Point,\n b: Point,\n bounds: { minX: number; minY: number; maxX: number; maxY: number },\n): number {\n // Check if segment intersects with the bounds\n // Create the four edges of the bounds\n const topLeft = { x: bounds.minX, y: bounds.minY }\n const topRight = { x: bounds.maxX, y: bounds.minY }\n const bottomLeft = { x: bounds.minX, y: bounds.maxY }\n const bottomRight = { x: bounds.maxX, y: bounds.maxY }\n\n // Check if segment intersects with any of the bounds edges\n if (\n doSegmentsIntersect(a, b, topLeft, topRight) ||\n doSegmentsIntersect(a, b, topRight, bottomRight) ||\n doSegmentsIntersect(a, b, bottomRight, bottomLeft) ||\n doSegmentsIntersect(a, b, bottomLeft, topLeft)\n ) {\n return 0\n }\n\n // Check if segment is entirely inside the bounds\n if (\n a.x >= bounds.minX &&\n a.x <= bounds.maxX &&\n a.y >= bounds.minY &&\n a.y <= bounds.maxY &&\n b.x >= bounds.minX &&\n b.x <= bounds.maxX &&\n b.y >= bounds.minY &&\n b.y <= bounds.maxY\n ) {\n return 0\n }\n\n // If not intersecting, calculate the minimum distance\n const distances = [\n pointToSegmentDistance(topLeft, a, b),\n pointToSegmentDistance(topRight, a, b),\n pointToSegmentDistance(bottomLeft, a, b),\n pointToSegmentDistance(bottomRight, a, b),\n ]\n\n // If one of the segment endpoints is inside the bounds, we need to consider its distance to the bounds as 0\n if (\n a.x >= bounds.minX &&\n a.x <= bounds.maxX &&\n a.y >= bounds.minY &&\n a.y <= bounds.maxY\n ) {\n return 0\n }\n\n if (\n b.x >= bounds.minX &&\n b.x <= bounds.maxX &&\n b.y >= bounds.minY &&\n b.y <= bounds.maxY\n ) {\n return 0\n }\n\n // Calculate distances from segment endpoints to bounds if outside\n if (\n a.x < bounds.minX ||\n a.x > bounds.maxX ||\n a.y < bounds.minY ||\n a.y > bounds.maxY\n ) {\n const closestX = clamp(a.x, bounds.minX, bounds.maxX)\n const closestY = clamp(a.y, bounds.minY, bounds.maxY)\n distances.push(distance(a, { x: closestX, y: closestY }))\n }\n\n if (\n b.x < bounds.minX ||\n b.x > bounds.maxX ||\n b.y < bounds.minY ||\n b.y > bounds.maxY\n ) {\n const closestX = clamp(b.x, bounds.minX, bounds.maxX)\n const closestY = clamp(b.y, bounds.minY, bounds.maxY)\n distances.push(distance(b, { x: closestX, y: closestY }))\n }\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance from a line segment to a box.\n */\nexport function segmentToBoxMinDistance(\n a: Point,\n b: Point,\n box: { center: Point; width: number; height: number },\n): number {\n const halfWidth = box.width / 2\n const halfHeight = box.height / 2\n const bounds = {\n minX: box.center.x - halfWidth,\n maxX: box.center.x + halfWidth,\n minY: box.center.y - halfHeight,\n maxY: box.center.y + halfHeight,\n }\n\n return segmentToBoundsMinDistance(a, b, bounds)\n}\n\n/**\n * Returns the minimum distance from a line segment to a circle.\n */\nexport function segmentToCircleMinDistance(\n a: Point,\n b: Point,\n circle: { x: number; y: number; radius: number },\n): number {\n // Calculate the distance from the circle center to the line segment\n const circleCenter = { x: circle.x, y: circle.y }\n\n // Handle degenerate case: segment of zero length (point to circle)\n if (a.x === b.x && a.y === b.y) {\n return Math.max(0, distance(a, circleCenter) - circle.radius)\n }\n\n // Vector from a to b\n const ab = { x: b.x - a.x, y: b.y - a.y }\n // Vector from a to circle center\n const ac = { x: circleCenter.x - a.x, y: circleCenter.y - a.y }\n\n // Length of segment ab squared\n const abLengthSq = ab.x * ab.x + ab.y * ab.y\n\n // Calculate projection of ac onto ab, normalized by the length of ab\n const t = Math.max(0, Math.min(1, (ab.x * ac.x + ab.y * ac.y) / abLengthSq))\n\n // Find the closest point on the segment to the circle center\n const closestPoint = {\n x: a.x + t * ab.x,\n y: a.y + t * ab.y,\n }\n\n // Calculate distance from closest point to circle center\n const distToCenter = distance(closestPoint, circleCenter)\n\n // Return the distance to the circle (subtract radius from distance to center)\n return Math.max(0, distToCenter - circle.radius)\n}\n","export type Node = {\n x: number\n y: number\n z: number\n\n g: number\n h: number\n f: number\n\n parent: Node | null\n}\n\nexport class SingleRouteCandidatePriorityQueue {\n private heap: Node[] = []\n\n constructor(nodes: Node[]) {\n this.heap = []\n\n for (const node of nodes) {\n this.enqueue(node)\n }\n }\n\n private getLeftChildIndex(parentIndex: number): number {\n return 2 * parentIndex + 1\n }\n\n private getRightChildIndex(parentIndex: number): number {\n return 2 * parentIndex + 2\n }\n\n private getParentIndex(childIndex: number) {\n return Math.floor((childIndex - 1) / 2)\n }\n\n private hasLeftChild(index: number): boolean {\n return this.getLeftChildIndex(index) < this.heap.length\n }\n\n private hasRightChild(index: number): boolean {\n return this.getRightChildIndex(index) < this.heap.length\n }\n\n private hasParent(index: number): boolean {\n return this.getParentIndex(index) >= 0\n }\n\n private leftChild(index: number): Node {\n return this.heap[this.getLeftChildIndex(index)]\n }\n\n private rightChild(index: number): Node {\n return this.heap[this.getRightChildIndex(index)]\n }\n\n private parent(index: number): Node {\n return this.heap[this.getParentIndex(index)]\n }\n\n private swap(i: number, j: number) {\n const temp = this.heap[i]\n this.heap[i] = this.heap[j]\n this.heap[j] = temp\n }\n\n // Removing an element will remove the\n // top element with highest priority then\n // heapifyDown will be called\n dequeue(): Node | null {\n if (this.heap.length === 0) {\n return null\n }\n const item = this.heap[0]\n this.heap[0] = this.heap[this.heap.length - 1]\n this.heap.pop()\n this.heapifyDown()\n return item\n }\n\n peek(): Node | null {\n if (this.heap.length === 0) {\n return null\n }\n return this.heap[0]\n }\n\n enqueue(item: Node) {\n this.heap.push(item)\n this.heapifyUp()\n }\n\n heapifyUp() {\n let index = this.heap.length - 1\n while (this.hasParent(index) && this.parent(index).f > this.heap[index].f) {\n this.swap(this.getParentIndex(index), index)\n index = this.getParentIndex(index)\n }\n }\n\n heapifyDown() {\n let index = 0\n while (this.hasLeftChild(index)) {\n let smallerChildIndex = this.getLeftChildIndex(index)\n if (\n this.hasRightChild(index) &&\n this.rightChild(index).f < this.leftChild(index).f\n ) {\n smallerChildIndex = this.getRightChildIndex(index)\n }\n if (this.heap[index].f < this.heap[smallerChildIndex].f) {\n break\n } else {\n this.swap(index, smallerChildIndex)\n }\n index = smallerChildIndex\n }\n }\n}\n","import { BaseSolver } from \"../BaseSolver\"\nimport type { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport {\n distance,\n pointToSegmentDistance,\n doSegmentsIntersect,\n} from \"@tscircuit/math-utils\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { HighDensityHyperParameters } from \"./HighDensityHyperParameters\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport {\n Node,\n SingleRouteCandidatePriorityQueue,\n} from \"lib/data-structures/SingleRouteCandidatePriorityQueue\"\n\nexport type FutureConnection = {\n connectionName: string\n points: { x: number; y: number; z: number }[]\n}\n\nexport class SingleHighDensityRouteSolver extends BaseSolver {\n obstacleRoutes: HighDensityIntraNodeRoute[]\n bounds: { minX: number; maxX: number; minY: number; maxY: number }\n boundsSize: { width: number; height: number }\n boundsCenter: { x: number; y: number }\n A: { x: number; y: number; z: number }\n B: { x: number; y: number; z: number }\n straightLineDistance: number\n\n viaDiameter: number\n traceThickness: number\n obstacleMargin: number\n layerCount: number\n minCellSize = 0.05\n cellStep = 0.05\n GREEDY_MULTIPLER = 1.1\n numRoutes: number\n\n VIA_PENALTY_FACTOR = 0.3\n CELL_SIZE_FACTOR: number\n\n exploredNodes: Set<string>\n\n candidates: SingleRouteCandidatePriorityQueue\n\n connectionName: string\n solvedPath: HighDensityIntraNodeRoute | null = null\n\n futureConnections: FutureConnection[]\n hyperParameters: Partial<HighDensityHyperParameters>\n\n connMap?: ConnectivityMap\n\n /** For debugging/animating the exploration */\n debug_exploredNodesOrdered: string[]\n debug_nodesTooCloseToObstacle: Set<string>\n debug_nodePathToParentIntersectsObstacle: Set<string>\n\n debugEnabled = true\n\n constructor(opts: {\n connectionName: string\n obstacleRoutes: HighDensityIntraNodeRoute[]\n minDistBetweenEnteringPoints: number\n bounds: { minX: number; maxX: number; minY: number; maxY: number }\n A: { x: number; y: number; z: number }\n B: { x: number; y: number; z: number }\n viaDiameter?: number\n traceThickness?: number\n obstacleMargin?: number\n layerCount?: number\n futureConnections?: FutureConnection[]\n hyperParameters?: Partial<HighDensityHyperParameters>\n connMap?: ConnectivityMap\n }) {\n super()\n this.bounds = opts.bounds\n this.connMap = opts.connMap\n this.hyperParameters = opts.hyperParameters ?? {}\n this.CELL_SIZE_FACTOR = this.hyperParameters.CELL_SIZE_FACTOR ?? 1\n this.boundsSize = {\n width: this.bounds.maxX - this.bounds.minX,\n height: this.bounds.maxY - this.bounds.minY,\n }\n this.boundsCenter = {\n x: (this.bounds.minX + this.bounds.maxX) / 2,\n y: (this.bounds.minY + this.bounds.maxY) / 2,\n }\n this.connectionName = opts.connectionName\n this.obstacleRoutes = opts.obstacleRoutes\n this.A = opts.A\n this.B = opts.B\n this.viaDiameter = opts.viaDiameter ?? 0.6\n this.traceThickness = opts.traceThickness ?? 0.15\n this.obstacleMargin = opts.obstacleMargin ?? 0.2\n this.layerCount = opts.layerCount ?? 2\n this.exploredNodes = new Set()\n this.straightLineDistance = distance(this.A, this.B)\n this.futureConnections = opts.futureConnections ?? []\n this.MAX_ITERATIONS = 5000\n\n this.debug_exploredNodesOrdered = []\n this.debug_nodesTooCloseToObstacle = new Set()\n this.debug_nodePathToParentIntersectsObstacle = new Set()\n this.numRoutes = this.obstacleRoutes.length + this.futureConnections.length\n const bestRowOrColumnCount = Math.ceil(5 * (this.numRoutes + 1))\n let numXCells = this.boundsSize.width / this.cellStep\n let numYCells = this.boundsSize.height / this.cellStep\n\n while (numXCells * numYCells > bestRowOrColumnCount ** 2) {\n if (this.cellStep * 2 > opts.minDistBetweenEnteringPoints) {\n break\n }\n this.cellStep *= 2\n numXCells = this.boundsSize.width / this.cellStep\n numYCells = this.boundsSize.height / this.cellStep\n }\n\n this.cellStep *= this.CELL_SIZE_FACTOR\n\n if (\n this.futureConnections &&\n this.futureConnections.length === 0 &&\n this.obstacleRoutes.length === 0\n ) {\n this.handleSimpleCases()\n }\n\n this.candidates = new SingleRouteCandidatePriorityQueue([\n {\n ...opts.A,\n x: Math.floor(opts.A.x / this.cellStep) * this.cellStep,\n y: Math.floor(opts.A.y / this.cellStep) * this.cellStep,\n z: opts.A.z ?? 0,\n g: 0,\n h: 0,\n f: 0,\n parent: {\n ...opts.A,\n z: opts.A.z ?? 0,\n g: 0,\n h: 0,\n f: 0,\n parent: null,\n },\n },\n ])\n }\n\n handleSimpleCases() {\n this.solved = true\n const { A, B } = this\n const route =\n A.z === B.z\n ? [A, B]\n : [\n A,\n { ...this.boundsCenter, z: this.A.z },\n {\n ...this.boundsCenter,\n z: B.z,\n },\n B,\n ]\n this.solvedPath = {\n connectionName: this.connectionName,\n route,\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: this.A.z === this.B.z ? [] : [this.boundsCenter],\n }\n }\n\n get viaPenaltyDistance() {\n return this.cellStep + this.straightLineDistance * this.VIA_PENALTY_FACTOR\n }\n\n isNodeTooCloseToObstacle(node: Node, margin?: number, isVia?: boolean) {\n margin ??= this.obstacleMargin\n\n if (isVia && node.parent) {\n const viasInMyRoute = this.getViasInNodePath(node.parent)\n for (const via of viasInMyRoute) {\n if (distance(node, via) < this.viaDiameter / 2 + margin) {\n return true\n }\n }\n }\n\n for (const route of this.obstacleRoutes) {\n const connectedToObstacle = this.connMap?.areIdsConnected?.(\n this.connectionName,\n route.connectionName,\n )\n\n if (!connectedToObstacle) {\n const pointPairs = getSameLayerPointPairs(route)\n for (const pointPair of pointPairs) {\n if (\n (isVia || pointPair.z === node.z) &&\n pointToSegmentDistance(node, pointPair.A, pointPair.B) <\n this.traceThickness + margin\n ) {\n return true\n }\n }\n }\n for (const via of route.vias) {\n if (distance(node, via) < this.viaDiameter / 2 + margin) {\n return true\n }\n }\n }\n\n return false\n }\n\n isNodeTooCloseToEdge(node: Node, isVia?: boolean) {\n const margin = isVia\n ? this.viaDiameter / 2 + this.obstacleMargin / 2\n : this.obstacleMargin / 2\n const tooClose =\n node.x < this.bounds.minX + margin ||\n node.x > this.bounds.maxX - margin ||\n node.y < this.bounds.minY + margin ||\n node.y > this.bounds.maxY - margin\n if (tooClose && !isVia) {\n // If it's close to B or A it's an exception\n if (\n distance(node, this.B) < margin * 2 ||\n distance(node, this.A) < margin * 2\n ) {\n return false\n }\n }\n return tooClose\n }\n\n doesPathToParentIntersectObstacle(node: Node) {\n const parent = node.parent\n if (!parent) return false\n for (const route of this.obstacleRoutes) {\n const obstacleIsConnectedToNewPath = this.connMap?.areIdsConnected?.(\n this.connectionName,\n route.connectionName,\n )\n if (obstacleIsConnectedToNewPath) continue\n for (const pointPair of getSameLayerPointPairs(route)) {\n if (pointPair.z !== node.z) continue\n if (doSegmentsIntersect(node, parent, pointPair.A, pointPair.B)) {\n return true\n }\n }\n }\n return false\n }\n\n computeH(node: Node) {\n return (\n distance(node, this.B) +\n // via penalty\n Math.abs(node.z - this.B.z) * this.viaPenaltyDistance\n )\n }\n\n computeG(node: Node) {\n return (\n (node.parent?.g ?? 0) +\n (node.z === 0 ? 0 : this.viaPenaltyDistance) +\n distance(node, node.parent!)\n )\n }\n\n computeF(g: number, h: number) {\n return g + h * this.GREEDY_MULTIPLER\n }\n\n getNodeKey(node: Node) {\n return `${Math.round(node.x / this.cellStep) * this.cellStep},${Math.round(node.y / this.cellStep) * this.cellStep},${node.z}`\n }\n\n getNeighbors(node: Node) {\n const neighbors: Node[] = []\n\n const { maxX, minX, maxY, minY } = this.bounds\n\n for (let x = -1; x <= 1; x++) {\n for (let y = -1; y <= 1; y++) {\n if (x === 0 && y === 0) continue\n\n const neighbor = {\n ...node,\n parent: node,\n x: clamp(node.x + x * this.cellStep, minX, maxX),\n y: clamp(node.y + y * this.cellStep, minY, maxY),\n }\n\n const neighborKey = this.getNodeKey(neighbor)\n\n if (this.exploredNodes.has(neighborKey)) {\n continue\n }\n\n if (this.isNodeTooCloseToObstacle(neighbor)) {\n this.debug_nodesTooCloseToObstacle.add(neighborKey)\n this.exploredNodes.add(neighborKey)\n continue\n }\n\n if (this.isNodeTooCloseToEdge(neighbor, false)) {\n this.exploredNodes.add(neighborKey)\n continue\n }\n\n if (this.doesPathToParentIntersectObstacle(neighbor)) {\n this.debug_nodePathToParentIntersectsObstacle.add(neighborKey)\n this.exploredNodes.add(neighborKey)\n continue\n }\n\n neighbor.g = this.computeG(neighbor)\n neighbor.h = this.computeH(neighbor)\n neighbor.f = this.computeF(neighbor.g, neighbor.h)\n\n neighbors.push(neighbor)\n }\n }\n\n const viaNeighbor = {\n ...node,\n parent: node,\n z: node.z === 0 ? this.layerCount - 1 : 0,\n }\n\n if (\n !this.exploredNodes.has(this.getNodeKey(viaNeighbor)) &&\n !this.isNodeTooCloseToObstacle(\n viaNeighbor,\n this.viaDiameter / 2 + this.obstacleMargin / 2,\n true,\n ) &&\n !this.isNodeTooCloseToEdge(viaNeighbor, true)\n ) {\n viaNeighbor.g = this.computeG(viaNeighbor)\n viaNeighbor.h = this.computeH(viaNeighbor)\n viaNeighbor.f = this.computeF(viaNeighbor.g, viaNeighbor.h)\n\n neighbors.push(viaNeighbor)\n }\n\n return neighbors\n }\n\n getNodePath(node: Node) {\n const path: Node[] = []\n while (node) {\n path.push(node)\n node = node.parent!\n }\n return path\n }\n\n getViasInNodePath(node: Node) {\n const path = this.getNodePath(node)\n const vias: { x: number; y: number }[] = []\n for (let i = 0; i < path.length - 1; i++) {\n if (path[i].z !== path[i + 1].z) {\n vias.push({ x: path[i].x, y: path[i].y })\n }\n }\n return vias\n }\n\n setSolvedPath(node: Node) {\n const path = this.getNodePath(node)\n path.reverse()\n\n const vias: { x: number; y: number }[] = []\n for (let i = 0; i < path.length - 1; i++) {\n if (path[i].z !== path[i + 1].z) {\n vias.push({ x: path[i].x, y: path[i].y })\n }\n }\n\n this.solvedPath = {\n connectionName: this.connectionName,\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n route: path\n .map((node) => ({ x: node.x, y: node.y, z: node.z }))\n .concat([this.B]),\n vias,\n }\n }\n\n computeProgress(currentNode: Node, goalDist: number, isOnLayer: boolean) {\n if (!isOnLayer) goalDist += this.viaPenaltyDistance\n const goalDistPercent = 1 - goalDist / this.straightLineDistance\n\n // This is a perfectly acceptable progress metric\n // return Math.max(this.progress || 0, goalDistPercent)\n\n // Linearize because it typically gets harder towards the end\n return Math.max(\n this.progress || 0,\n // 0.112 = ~90% -> 50%\n // ~25% -> 2%\n // ~99% -> 94%\n // ~95% -> 72%\n (2 / Math.PI) *\n Math.atan((0.112 * goalDistPercent) / (1 - goalDistPercent)),\n )\n }\n\n _step() {\n let currentNode = this.candidates.dequeue()\n let currentNodeKey = currentNode ? this.getNodeKey(currentNode) : undefined\n\n while (\n currentNode &&\n currentNodeKey &&\n this.exploredNodes.has(currentNodeKey)\n ) {\n currentNode = this.candidates.dequeue()\n currentNodeKey = currentNode ? this.getNodeKey(currentNode) : undefined\n }\n\n if (!currentNode || !currentNodeKey) {\n this.failed = true\n return\n }\n this.exploredNodes.add(currentNodeKey)\n this.debug_exploredNodesOrdered.push(currentNodeKey)\n\n const goalDist = distance(currentNode, this.B)\n\n this.progress = this.computeProgress(\n currentNode,\n goalDist,\n currentNode.z === this.B.z,\n )\n\n if (goalDist <= this.cellStep * Math.SQRT2 && currentNode.z === this.B.z) {\n this.solved = true\n this.setSolvedPath(currentNode)\n }\n\n const neighbors = this.getNeighbors(currentNode)\n for (const neighbor of neighbors) {\n this.candidates.enqueue(neighbor)\n }\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n\n // Display the input port points (from nodeWithPortPoints via A and B)\n graphics.points!.push({\n x: this.A.x,\n y: this.A.y,\n label: `Input A\\nz: ${this.A.z}`,\n color: \"orange\",\n })\n graphics.points!.push({\n x: this.B.x,\n y: this.B.y,\n label: `Input B\\nz: ${this.B.z}`,\n color: \"orange\",\n })\n\n // Draw circles at future connection points\n // if (\"FUTURE_CONNECTION_PROXIMITY_VD\" in this) {\n // for (const futureConnection of this.futureConnections) {\n // for (const point of futureConnection.points) {\n // graphics.circles!.push({\n // center: point,\n // radius:\n // (this.viaDiameter *\n // (this.FUTURE_CONNECTION_PROXIMITY_VD as number)) /\n // 2,\n // // strokeColor: \"rgba(0, 255, 0, 0.3)\",\n // stroke: \"rgba(0,255,0,0.1)\",\n // label: `Future Connection: ${futureConnection.connectionName}`,\n // })\n // }\n // }\n // // Draw circles around obstacle route points\n // for (const route of this.obstacleRoutes) {\n // for (const point of [\n // route.route[0],\n // route.route[route.route.length - 1],\n // ]) {\n // graphics.circles!.push({\n // center: point,\n // radius:\n // (this.viaDiameter *\n // (this.FUTURE_CONNECTION_PROXIMITY_VD as number)) /\n // 2,\n // stroke: \"rgba(255,0,0,0.1)\",\n // label: \"Obstacle Route Point\",\n // })\n // }\n // }\n // }\n\n // Draw a line representing the direct connection between the input port points\n graphics.lines!.push({\n points: [this.A, this.B],\n strokeColor: \"rgba(255, 0, 0, 0.5)\",\n label: \"Direct Input Connection\",\n })\n\n // Show any obstacle routes as background references\n for (\n let routeIndex = 0;\n routeIndex < this.obstacleRoutes.length;\n routeIndex++\n ) {\n const route = this.obstacleRoutes[routeIndex]\n for (let i = 0; i < route.route.length - 1; i++) {\n const z = route.route[i].z\n graphics.lines!.push({\n points: [route.route[i], route.route[i + 1]],\n strokeColor:\n z === 0 ? \"rgba(255, 0, 0, 0.75)\" : \"rgba(255, 128, 0, 0.25)\",\n strokeWidth: route.traceThickness,\n label: \"Obstacle Route\",\n layer: `obstacle${routeIndex.toString()}`,\n })\n }\n }\n\n // Optionally, visualize explored nodes for debugging purposes\n for (let i = 0; i < this.debug_exploredNodesOrdered.length; i++) {\n const nodeKey = this.debug_exploredNodesOrdered[i]\n const [x, y, z] = nodeKey.split(\",\").map(Number)\n if (this.debug_nodesTooCloseToObstacle.has(nodeKey)) continue\n if (this.debug_nodePathToParentIntersectsObstacle.has(nodeKey)) continue\n graphics.rects!.push({\n center: {\n x: x + (z * this.cellStep) / 20,\n y: y + (z * this.cellStep) / 20,\n },\n fill:\n z === 0\n ? `rgba(255,0,255,${0.3 - (i / this.debug_exploredNodesOrdered.length) * 0.2})`\n : `rgba(0,0,255,${0.3 - (i / this.debug_exploredNodesOrdered.length) * 0.2})`,\n width: this.cellStep * 0.9,\n height: this.cellStep * 0.9,\n label: `Explored (z=${z})`,\n })\n }\n\n // Visualize the next node to be explored\n if (this.candidates.peek()) {\n const nextNode = this.candidates.peek()!\n graphics.rects!.push({\n center: {\n x: nextNode.x + (nextNode.z * this.cellStep) / 20,\n y: nextNode.y + (nextNode.z * this.cellStep) / 20,\n },\n fill: \"rgba(0, 255, 0, 0.8)\",\n width: this.cellStep * 0.9,\n height: this.cellStep * 0.9,\n label: `Next (z=${nextNode.z})`,\n })\n }\n\n // Visualize vias from obstacle routes\n for (const route of this.obstacleRoutes) {\n for (const via of route.vias) {\n graphics.circles!.push({\n center: {\n x: via.x,\n y: via.y,\n },\n radius: this.viaDiameter / 2,\n fill: \"rgba(255, 0, 0, 0.5)\",\n label: \"Via\",\n })\n }\n }\n // If a solved route exists, display it along with via markers\n if (this.solvedPath) {\n graphics.lines!.push({\n points: this.solvedPath.route,\n strokeColor: \"green\",\n label: \"Solved Route\",\n })\n for (const via of this.solvedPath.vias) {\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2,\n fill: \"green\",\n label: \"Via\",\n })\n }\n }\n\n return graphics\n }\n}\n\nfunction getSameLayerPointPairs(route: HighDensityIntraNodeRoute) {\n const pointPairs: {\n z: number\n A: { x: number; y: number; z: number }\n B: { x: number; y: number; z: number }\n }[] = []\n\n for (let i = 0; i < route.route.length - 1; i++) {\n if (route.route[i].z === route.route[i + 1].z) {\n pointPairs.push({\n z: route.route[i].z,\n A: route.route[i],\n B: route.route[i + 1],\n })\n }\n }\n\n return pointPairs\n}\n\nfunction clamp(value: number, min: number, max: number) {\n return Math.max(min, Math.min(value, max))\n}\n","import { distance } from \"@tscircuit/math-utils\"\nimport { SingleHighDensityRouteSolver } from \"./SingleHighDensityRouteSolver\"\nimport { Node } from \"lib/data-structures/SingleRouteCandidatePriorityQueue\"\n\nexport class SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost extends SingleHighDensityRouteSolver {\n FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR = 2\n FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR = 1\n FUTURE_CONNECTION_PROXIMITY_VD = 10\n MISALIGNED_DIST_PENALTY_FACTOR = 5\n VIA_PENALTY_FACTOR_2 = 1\n FLIP_TRACE_ALIGNMENT_DIRECTION = false\n\n constructor(\n opts: ConstructorParameters<typeof SingleHighDensityRouteSolver>[0],\n ) {\n super(opts)\n for (const key in opts.hyperParameters) {\n // @ts-ignore\n this[key] = opts.hyperParameters[key]\n }\n\n // Ratio of available space determines via penalty\n const viasThatCanFitHorz = this.boundsSize.width / this.viaDiameter\n this.VIA_PENALTY_FACTOR =\n 0.3 * (viasThatCanFitHorz / this.numRoutes) * this.VIA_PENALTY_FACTOR_2\n }\n\n getClosestFutureConnectionPoint(node: Node) {\n let minDist = Infinity\n let closestPoint = null\n\n for (const futureConnection of this.futureConnections) {\n for (const point of futureConnection.points) {\n const dist =\n distance(node, point) +\n (node.z !== point.z ? this.viaPenaltyDistance : 0)\n if (dist < minDist) {\n minDist = dist\n closestPoint = point\n }\n }\n }\n\n return closestPoint\n }\n\n /**\n * Rapidly approaches 0 as the goal distance approaches 0\n */\n diminishCloseToGoal(node: Node) {\n const goalDist = distance(node, this.B)\n return 1 - Math.exp((-goalDist / this.straightLineDistance) * 5)\n }\n\n getFutureConnectionPenalty(node: Node, isVia: boolean) {\n let futureConnectionPenalty = 0\n const closestFuturePoint = this.getClosestFutureConnectionPoint(node)\n const goalDist = distance(node, this.B)\n if (closestFuturePoint) {\n const distToFuturePoint = distance(node, closestFuturePoint)\n if (goalDist <= distToFuturePoint) return 0\n const maxDist = this.viaDiameter * this.FUTURE_CONNECTION_PROXIMITY_VD\n const distRatio = distToFuturePoint / maxDist\n const maxPenalty = isVia\n ? this.straightLineDistance *\n this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR\n : this.straightLineDistance *\n this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR\n futureConnectionPenalty = maxPenalty * Math.exp(-distRatio * 5)\n }\n return futureConnectionPenalty\n }\n\n computeH(node: Node) {\n const goalDist = distance(node, this.B) ** 1.6\n const goalDistRatio = goalDist / this.straightLineDistance\n\n // Base cost from original function\n const baseCost =\n goalDist + (node.z !== this.B.z ? this.viaPenaltyDistance : 0)\n\n return (\n baseCost +\n this.getFutureConnectionPenalty(node, node.z !== node.parent?.z)\n )\n }\n\n computeG(node: Node) {\n const dx = Math.abs(node.x - node.parent!.x)\n const dy = Math.abs(node.y - node.parent!.y)\n const dist = Math.sqrt(dx ** 2 + dy ** 2)\n\n const misalignedDist = !this.FLIP_TRACE_ALIGNMENT_DIRECTION\n ? node.z === 0\n ? dy\n : dx\n : node.z === 0\n ? dx\n : dy\n\n // Base cost from original function\n const baseCost =\n (node.parent?.g ?? 0) +\n (node.z === node.parent?.z ? 0 : this.viaPenaltyDistance) +\n dist +\n misalignedDist * this.MISALIGNED_DIST_PENALTY_FACTOR\n\n return (\n baseCost +\n this.getFutureConnectionPenalty(node, node.z !== node.parent?.z)\n )\n }\n}\n","export function seededRandom(seed: number) {\n // Use a simple hash to initialize both state variables\n let s = seed\n for (let i = 0; i < 10; i++) {\n s = (s * 16807) % 2147483647\n }\n let state0 = s\n\n // Use a different hash for the second state\n s = (seed * 69069 + 1) % 2147483647\n for (let i = 0; i < 10; i++) {\n s = (s * 48271) % 2147483647\n }\n let state1 = s\n\n // Return the function that generates random numbers\n return () => {\n // xorshift128+ algorithm produces much better randomness than LCG\n let s1 = state0\n const s0 = state1\n\n state0 = s0\n s1 ^= s1 << 23\n s1 ^= s1 >>> 17\n s1 ^= s0\n s1 ^= s0 >>> 26\n state1 = s1\n\n // Generate a number between 0 and 1\n const result = (state0 + state1) / 4294967296\n return result - Math.floor(result)\n }\n}\n\nexport function cloneAndShuffleArray<T>(arr: T[], seed: number): T[] {\n if (seed === 0) return arr\n const random = seededRandom(seed)\n // if (arr.length === 2) {\n // console.log(random(), seed)\n // if (random() > 0.5) return arr.slice()\n // return [arr[1], arr[0]]\n // }\n const shuffled = arr.slice() // Copy the array\n for (let i = 0; i < shuffled.length; i++) {\n const i1 = Math.floor(random() * shuffled.length)\n const i2 = Math.floor(random() * (i + 1))\n ;[shuffled[i1], shuffled[i2]] = [shuffled[i2], shuffled[i1]]\n }\n return shuffled\n}\n","import { NodeWithPortPoints } from \"lib/types/high-density-types\"\n\nexport function getBoundsFromNodeWithPortPoints(\n nodeWithPortPoints: NodeWithPortPoints,\n): { minX: number; maxX: number; minY: number; maxY: number } {\n const bounds = {\n minX: nodeWithPortPoints.center.x - nodeWithPortPoints.width / 2,\n maxX: nodeWithPortPoints.center.x + nodeWithPortPoints.width / 2,\n minY: nodeWithPortPoints.center.y - nodeWithPortPoints.height / 2,\n maxY: nodeWithPortPoints.center.y + nodeWithPortPoints.height / 2,\n }\n\n // Sometimes port points may be outside the node- this happens when there's\n // a \"leap\" to the final target or at the end or beginning of a trace when\n // we're wrapping up\n for (const pt of nodeWithPortPoints.portPoints) {\n if (pt.x < bounds.minX) {\n bounds.minX = pt.x\n }\n if (pt.x > bounds.maxX) {\n bounds.maxX = pt.x\n }\n if (pt.y < bounds.minY) {\n bounds.minY = pt.y\n }\n if (pt.y > bounds.maxY) {\n bounds.maxY = pt.y\n }\n }\n\n return bounds\n}\n","import { NodeWithPortPoints } from \"lib/types/high-density-types\"\n\nexport const getMinDistBetweenEnteringPoints = (node: NodeWithPortPoints) => {\n let minDist = Infinity\n const points = node.portPoints\n\n // Compare each point with every other point\n for (let i = 0; i < points.length; i++) {\n for (let j = i + 1; j < points.length; j++) {\n if (points[i].z !== points[j].z) {\n continue\n }\n const p1 = points[i]\n const p2 = points[j]\n\n // Calculate Euclidean distance between points\n const dist = Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2)\n\n minDist = Math.min(minDist, dist)\n }\n }\n\n return minDist === Infinity ? 0 : minDist\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport type {\n HighDensityIntraNodeRoute,\n NodeWithPortPoints,\n} from \"../../types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { SingleHighDensityRouteSolver } from \"./SingleHighDensityRouteSolver\"\nimport { safeTransparentize } from \"../colors\"\nimport { SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost } from \"./SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost\"\nimport { HighDensityHyperParameters } from \"./HighDensityHyperParameters\"\nimport { cloneAndShuffleArray } from \"lib/utils/cloneAndShuffleArray\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport { getBoundsFromNodeWithPortPoints } from \"lib/utils/getBoundsFromNodeWithPortPoints\"\nimport { getMinDistBetweenEnteringPoints } from \"lib/utils/getMinDistBetweenEnteringPoints\"\n\nexport class IntraNodeRouteSolver extends BaseSolver {\n nodeWithPortPoints: NodeWithPortPoints\n colorMap: Record<string, string>\n unsolvedConnections: {\n connectionName: string\n points: { x: number; y: number; z: number }[]\n }[]\n\n totalConnections: number\n solvedRoutes: HighDensityIntraNodeRoute[]\n failedSubSolvers: SingleHighDensityRouteSolver[]\n hyperParameters: Partial<HighDensityHyperParameters>\n minDistBetweenEnteringPoints: number\n\n activeSubSolver: SingleHighDensityRouteSolver | null = null\n connMap?: ConnectivityMap\n\n // Legacy compat\n get failedSolvers() {\n return this.failedSubSolvers\n }\n\n // Legacy compat\n get activeSolver() {\n return this.activeSubSolver\n }\n\n constructor(params: {\n nodeWithPortPoints: NodeWithPortPoints\n colorMap?: Record<string, string>\n hyperParameters?: Partial<HighDensityHyperParameters>\n connMap?: ConnectivityMap\n }) {\n const { nodeWithPortPoints, colorMap } = params\n super()\n this.nodeWithPortPoints = nodeWithPortPoints\n this.colorMap = colorMap ?? {}\n this.solvedRoutes = []\n this.hyperParameters = params.hyperParameters ?? {}\n this.failedSubSolvers = []\n this.connMap = params.connMap\n const unsolvedConnectionsMap: Map<\n string,\n { x: number; y: number; z: number }[]\n > = new Map()\n for (const { connectionName, x, y, z } of nodeWithPortPoints.portPoints) {\n unsolvedConnectionsMap.set(connectionName, [\n ...(unsolvedConnectionsMap.get(connectionName) ?? []),\n { x, y, z: z ?? 0 },\n ])\n }\n this.unsolvedConnections = Array.from(\n unsolvedConnectionsMap.entries().map(([connectionName, points]) => ({\n connectionName,\n points,\n })),\n )\n\n if (this.hyperParameters.SHUFFLE_SEED) {\n this.unsolvedConnections = cloneAndShuffleArray(\n this.unsolvedConnections,\n this.hyperParameters.SHUFFLE_SEED ?? 0,\n )\n\n // Shuffle the starting and ending points of each connection (some\n // algorithms are biased towards the start or end of a trace)\n this.unsolvedConnections = this.unsolvedConnections.map(\n ({ points, ...rest }, i) => ({\n ...rest,\n points: cloneAndShuffleArray(\n points,\n i * 7117 + (this.hyperParameters.SHUFFLE_SEED ?? 0),\n ),\n }),\n )\n }\n\n this.totalConnections = this.unsolvedConnections.length\n this.MAX_ITERATIONS = 1_000 * this.totalConnections ** 1.5\n\n this.minDistBetweenEnteringPoints = getMinDistBetweenEnteringPoints(\n this.nodeWithPortPoints,\n )\n\n // const {\n // numEntryExitLayerChanges,\n // numSameLayerCrossings,\n // numTransitionPairCrossings,\n // numTransitions,\n // } = getIntraNodeCrossings(this.nodeWithPortPoints)\n\n // if (this.nodeWithPortPoints.portPoints.length === 4) {\n\n // }\n\n // if (\n // numSameLayerCrossings === 0 &&\n // numTransitions === 0 &&\n // numEntryExitLayerChanges === 0\n // ) {\n // this.handleSimpleNoCrossingsCase()\n // }\n }\n\n // handleSimpleNoCrossingsCase() {\n // // TODO check to make sure there are no crossings due to trace width\n // this.solved = true\n // this.solvedRoutes = this.unsolvedConnections.map(\n // ({ connectionName, points }) => ({\n // connectionName,\n // route: points,\n // traceThickness: 0.1, // TODO load from hyperParameters\n // viaDiameter: 0.6,\n // vias: [],\n // }),\n // )\n // this.unsolvedConnections = []\n // }\n\n computeProgress() {\n return (\n (this.solvedRoutes.length + (this.activeSubSolver?.progress || 0)) /\n this.totalConnections\n )\n }\n\n _step() {\n if (this.activeSubSolver) {\n this.activeSubSolver.step()\n this.progress = this.computeProgress()\n if (this.activeSubSolver.solved) {\n this.solvedRoutes.push(this.activeSubSolver.solvedPath!)\n this.activeSubSolver = null\n } else if (this.activeSubSolver.failed) {\n this.failedSubSolvers.push(this.activeSubSolver)\n this.activeSubSolver = null\n this.error = this.failedSubSolvers.map((s) => s.error).join(\"\\n\")\n this.failed = true\n }\n return\n }\n\n const unsolvedConnection = this.unsolvedConnections.pop()\n this.progress = this.computeProgress()\n if (!unsolvedConnection) {\n this.solved = this.failedSubSolvers.length === 0\n return\n }\n if (unsolvedConnection.points.length === 1) {\n return\n }\n if (unsolvedConnection.points.length === 2) {\n const [A, B] = unsolvedConnection.points\n if (A.x === B.x && A.y === B.y && A.z === B.z) {\n return\n }\n }\n const { connectionName, points } = unsolvedConnection\n this.activeSubSolver =\n new SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost({\n connectionName,\n minDistBetweenEnteringPoints: this.minDistBetweenEnteringPoints,\n bounds: getBoundsFromNodeWithPortPoints(this.nodeWithPortPoints),\n A: { x: points[0].x, y: points[0].y, z: points[0].z },\n B: {\n x: points[points.length - 1].x,\n y: points[points.length - 1].y,\n z: points[points.length - 1].z,\n },\n obstacleRoutes: this.solvedRoutes,\n futureConnections: this.unsolvedConnections,\n layerCount: 2,\n hyperParameters: this.hyperParameters,\n connMap: this.connMap,\n })\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n\n // Draw node bounds\n // graphics.rects!.push({\n // center: {\n // x: this.nodeWithPortPoints.center.x,\n // y: this.nodeWithPortPoints.center.y,\n // },\n // width: this.nodeWithPortPoints.width,\n // height: this.nodeWithPortPoints.height,\n // stroke: \"gray\",\n // fill: \"transparent\",\n // })\n\n // Visualize input nodeWithPortPoints\n for (const pt of this.nodeWithPortPoints.portPoints) {\n graphics.points!.push({\n x: pt.x,\n y: pt.y,\n label: [pt.connectionName, `layer: ${pt.z}`].join(\"\\n\"),\n color: this.colorMap[pt.connectionName] ?? \"blue\",\n })\n }\n\n // Visualize solvedRoutes\n for (\n let routeIndex = 0;\n routeIndex < this.solvedRoutes.length;\n routeIndex++\n ) {\n const route = this.solvedRoutes[routeIndex]\n if (route.route.length > 0) {\n const routeColor = this.colorMap[route.connectionName] ?? \"blue\"\n\n // Draw route segments between points\n for (let i = 0; i < route.route.length - 1; i++) {\n const p1 = route.route[i]\n const p2 = route.route[i + 1]\n\n graphics.lines!.push({\n points: [p1, p2],\n strokeColor:\n p1.z === 0\n ? safeTransparentize(routeColor, 0.2)\n : safeTransparentize(routeColor, 0.8),\n layer: `route-layer-${p1.z}`,\n step: routeIndex,\n strokeWidth: route.traceThickness,\n })\n }\n\n // Draw vias\n for (const via of route.vias) {\n graphics.circles!.push({\n center: { x: via.x, y: via.y },\n radius: route.viaDiameter / 2,\n fill: safeTransparentize(routeColor, 0.5),\n layer: \"via\",\n step: routeIndex,\n })\n }\n }\n }\n\n // Draw border around the node\n const bounds = getBoundsFromNodeWithPortPoints(this.nodeWithPortPoints)\n const { minX, minY, maxX, maxY } = bounds\n\n // Draw the four sides of the border with thin red lines\n graphics.lines!.push({\n points: [\n { x: minX, y: minY },\n { x: maxX, y: minY },\n { x: maxX, y: maxY },\n { x: minX, y: maxY },\n { x: minX, y: minY },\n ],\n strokeColor: \"rgba(255, 0, 0, 0.25)\",\n strokeDash: \"4 4\",\n layer: \"border\",\n })\n\n return graphics\n }\n}\n","import { GraphicsObject } from \"graphics-debug\"\nimport { BaseSolver } from \"./BaseSolver\"\n\nexport type SupervisedSolver<T extends BaseSolver> = {\n hyperParameters: any\n solver: T\n h: number\n g: number\n f: number\n}\n\nexport type HyperParameterDef = {\n name: string\n possibleValues: Array<any>\n}\n\n/**\n * The HyperParameterSupervisorSolver is a solver that solves a problem by\n * running competing solvers with different hyperparameters.\n *\n * As solvers make progress, the supervisor will allow the best solvers to run\n * for more iterations, prioritizing the solvers that are working the best.\n */\nexport class HyperParameterSupervisorSolver<\n T extends BaseSolver,\n> extends BaseSolver {\n GREEDY_MULTIPLIER = 1.2\n MIN_SUBSTEPS = 1\n\n supervisedSolvers?: Array<SupervisedSolver<T>>\n\n getHyperParameterDefs(): Array<HyperParameterDef> {\n throw new Error(\"Not implemented\")\n }\n\n getCombinationDefs(): Array<Array<string>> | null {\n return null\n }\n\n getHyperParameterCombinations(\n hyperParameterDefs?: Array<HyperParameterDef>,\n ): Array<Record<string, any>> {\n if (!hyperParameterDefs) {\n hyperParameterDefs = this.getHyperParameterDefs()\n }\n const combinations: Array<Record<string, any>> = []\n // Base case - no more hyperparameters to combine\n if (hyperParameterDefs.length === 0) {\n return [{}]\n }\n\n // Take first hyperparameter definition\n const [currentDef, ...remainingDefs] = hyperParameterDefs\n\n // Get combinations for remaining hyperparameters\n const subCombinations = this.getHyperParameterCombinations(remainingDefs)\n\n // For each possible value of current hyperparameter,\n // combine with all sub-combinations\n currentDef.possibleValues.forEach((value) => {\n subCombinations.forEach((subCombo) => {\n combinations.push({\n ...subCombo,\n ...value,\n })\n })\n })\n\n return combinations\n }\n\n initializeSolvers() {\n const hyperParameterDefs = this.getHyperParameterDefs()\n\n const combinationDefs = this.getCombinationDefs() ?? [\n hyperParameterDefs.map((def) => def.name),\n ]\n\n this.supervisedSolvers = []\n for (const combinationDef of combinationDefs) {\n const hyperParameterCombinations = this.getHyperParameterCombinations(\n hyperParameterDefs.filter((hpd) => combinationDef.includes(hpd.name)),\n )\n\n for (const hyperParameters of hyperParameterCombinations) {\n const solver = this.generateSolver(hyperParameters)\n this.supervisedSolvers.push({\n hyperParameters,\n solver,\n h: 0,\n g: 0,\n f: 0,\n })\n }\n }\n }\n\n generateSolver(hyperParameters: any): T {\n throw new Error(\"Not implemented\")\n }\n\n computeG(solver: T) {\n return solver.iterations / solver.MAX_ITERATIONS\n }\n\n computeH(solver: T) {\n return 1 - (solver.progress || 0)\n }\n\n computeF(g: number, h: number) {\n return g + h * this.GREEDY_MULTIPLIER\n }\n\n getSupervisedSolverWithBestFitness(): SupervisedSolver<T> | null {\n let bestFitness = Infinity\n let bestSolver: SupervisedSolver<T> | null = null\n for (const supervisedSolver of this.supervisedSolvers ?? []) {\n if (supervisedSolver.solver.solved) {\n return supervisedSolver\n }\n if (supervisedSolver.solver.failed) {\n continue\n }\n const fitness = supervisedSolver.f\n if (fitness < bestFitness) {\n bestFitness = fitness\n bestSolver = supervisedSolver\n }\n }\n return bestSolver\n }\n\n _step() {\n if (!this.supervisedSolvers) this.initializeSolvers()\n\n const supervisedSolver = this.getSupervisedSolverWithBestFitness()\n\n if (!supervisedSolver) {\n this.failed = true\n this.error = \"All solvers failed\"\n return\n }\n\n for (let i = 0; i < this.MIN_SUBSTEPS; i++) {\n supervisedSolver.solver.step()\n }\n\n supervisedSolver.g = this.computeG(supervisedSolver.solver)\n supervisedSolver.h = this.computeH(supervisedSolver.solver)\n supervisedSolver.f = this.computeF(supervisedSolver.g, supervisedSolver.h)\n\n if (supervisedSolver.solver.solved) {\n this.solved = true\n this.onSolve?.(supervisedSolver)\n }\n }\n\n onSolve(solver: SupervisedSolver<T>) {}\n\n visualize(): GraphicsObject {\n const bestSupervisedSolver = this.getSupervisedSolverWithBestFitness()\n let graphics: GraphicsObject = {\n lines: [],\n circles: [],\n points: [],\n rects: [],\n }\n\n if (bestSupervisedSolver) {\n graphics = bestSupervisedSolver.solver.visualize()\n }\n return graphics\n }\n}\n","interface Point {\n x: number\n y: number\n}\n\nexport const findCircleLineIntersections = (\n circle: Point & { r: number },\n line: { p1: Point; p2: Point },\n) => {\n const cx = circle.x\n const cy = circle.y\n const r = circle.r\n\n const x1 = line.p1.x\n const y1 = line.p1.y\n const x2 = line.p2.x\n const y2 = line.p2.y\n\n // Check if line is vertical\n if (Math.abs(x2 - x1) < 0.001) {\n const x = x1\n\n // Calculate discriminant\n const a = r * r - (x - cx) ** 2\n\n if (a < 0) return [] // No intersection\n\n if (Math.abs(a) < 0.001) {\n // One intersection\n const y = cy\n // Check if this point is within the line segment\n if (y >= Math.min(y1, y2) && y <= Math.max(y1, y2)) {\n return [{ x, y }]\n }\n return []\n }\n\n // Two intersections\n const y_1 = cy + Math.sqrt(a)\n const y_2 = cy - Math.sqrt(a)\n\n const points: Point[] = []\n if (y_1 >= Math.min(y1, y2) && y_1 <= Math.max(y1, y2)) {\n points.push({ x, y: y_1 })\n }\n if (y_2 >= Math.min(y1, y2) && y_2 <= Math.max(y1, y2)) {\n points.push({ x, y: y_2 })\n }\n\n return points\n }\n\n // Line is not vertical\n const m = (y2 - y1) / (x2 - x1)\n const b = y1 - m * x1\n\n // Substitute line equation into circle equation\n const A = 1 + m * m\n const B = 2 * (m * b - m * cy - cx)\n const C = cx * cx + (b - cy) * (b - cy) - r * r\n\n // Calculate discriminant\n const discriminant = B * B - 4 * A * C\n\n if (discriminant < 0) return [] // No intersection\n\n if (Math.abs(discriminant) < 0.001) {\n // One intersection\n const x = -B / (2 * A)\n const y = m * x + b\n\n // Check if this point is within the line segment\n if (\n x >= Math.min(x1, x2) &&\n x <= Math.max(x1, x2) &&\n y >= Math.min(y1, y2) &&\n y <= Math.max(y1, y2)\n ) {\n return [{ x, y }]\n }\n return []\n }\n\n // Two intersections\n const x_1 = (-B + Math.sqrt(discriminant)) / (2 * A)\n const x_2 = (-B - Math.sqrt(discriminant)) / (2 * A)\n const y_1 = m * x_1 + b\n const y_2 = m * x_2 + b\n\n const points: Point[] = []\n if (\n x_1 >= Math.min(x1, x2) &&\n x_1 <= Math.max(x1, x2) &&\n y_1 >= Math.min(y1, y2) &&\n y_1 <= Math.max(y1, y2)\n ) {\n points.push({ x: x_1, y: y_1 })\n }\n if (\n x_2 >= Math.min(x1, x2) &&\n x_2 <= Math.max(x1, x2) &&\n y_2 >= Math.min(y1, y2) &&\n y_2 <= Math.max(y1, y2)\n ) {\n points.push({ x: x_2, y: y_2 })\n }\n\n return points\n}\n","import { BaseSolver } from \"lib/solvers/BaseSolver\"\nimport {\n NodeWithPortPoints,\n HighDensityIntraNodeRoute,\n} from \"lib/types/high-density-types\"\nimport {\n distance,\n pointToSegmentDistance,\n doSegmentsIntersect,\n} from \"@tscircuit/math-utils\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { getIntraNodeCrossings } from \"lib/utils/getIntraNodeCrossings\"\nimport { findCircleLineIntersections } from \"./findCircleLineIntersections\"\n\ntype Point = { x: number; y: number; z?: number }\ntype Route = {\n startPort: Point\n endPort: Point\n connectionName: string\n}\n\nexport class TwoCrossingRoutesHighDensitySolver extends BaseSolver {\n // Input parameters\n nodeWithPortPoints: NodeWithPortPoints\n routes: Route[]\n\n // Configuration parameters\n viaDiameter: number\n traceThickness: number\n obstacleMargin: number\n layerCount: number = 2\n\n debugViaPositions: {\n via1: Point\n via2: Point\n }[]\n\n // Solution state\n solvedRoutes: HighDensityIntraNodeRoute[] = []\n\n // Bounds\n bounds: { minX: number; maxX: number; minY: number; maxY: number }\n\n constructor(params: {\n nodeWithPortPoints: NodeWithPortPoints\n viaDiameter?: number\n traceThickness?: number\n obstacleMargin?: number\n layerCount?: number\n }) {\n super()\n\n this.nodeWithPortPoints = params.nodeWithPortPoints\n this.viaDiameter = params?.viaDiameter ?? 0.6\n this.traceThickness = params?.traceThickness ?? 0.15\n this.obstacleMargin = params?.obstacleMargin ?? 0.1\n this.layerCount = params?.layerCount ?? 2\n this.debugViaPositions = []\n\n // Extract routes from the node data\n this.routes = this.extractRoutesFromNode()\n\n // Calculate bounds\n this.bounds = this.calculateBounds()\n\n if (this.routes.length !== 2) {\n this.failed = true\n return\n }\n\n const [routeA, routeB] = this.routes\n const routeAStartsAndEndsOnSameLayer =\n routeA.startPort.z === routeA.endPort.z\n if (!routeAStartsAndEndsOnSameLayer) {\n this.failed = true\n return\n }\n\n const routeBStartsAndEndsOnSameLayer =\n routeB.startPort.z === routeB.endPort.z\n if (!routeBStartsAndEndsOnSameLayer) {\n this.failed = true\n return\n }\n\n const routesAreSameLayer = routeA.startPort.z === routeB.startPort.z\n if (!routesAreSameLayer) {\n this.failed = true\n return\n }\n\n // TODO check to make sure the lines cross\n }\n\n /**\n * Extract routes that need to be connected from the node data\n */\n private extractRoutesFromNode(): Route[] {\n const routes: Route[] = []\n const connectedPorts = this.nodeWithPortPoints.portPoints!\n\n // Group ports by connection name\n const connectionGroups = new Map<string, Point[]>()\n\n for (const connectedPort of connectedPorts) {\n const { connectionName } = connectedPort\n if (!connectionGroups.has(connectionName)) {\n connectionGroups.set(connectionName, [])\n }\n connectionGroups.get(connectionName)?.push(connectedPort)\n }\n\n // Create routes for each connection (assuming each connection has exactly 2 points)\n for (const [connectionName, points] of connectionGroups.entries()) {\n if (points.length === 2) {\n routes.push({\n startPort: { ...points[0], z: points[0].z ?? 0 },\n endPort: { ...points[1], z: points[1].z ?? 0 },\n connectionName,\n })\n }\n }\n\n return routes\n }\n\n /**\n * Calculate the bounding box of the node\n */\n private calculateBounds() {\n return {\n minX:\n this.nodeWithPortPoints.center.x - this.nodeWithPortPoints.width / 2,\n maxX:\n this.nodeWithPortPoints.center.x + this.nodeWithPortPoints.width / 2,\n minY:\n this.nodeWithPortPoints.center.y - this.nodeWithPortPoints.height / 2,\n maxY:\n this.nodeWithPortPoints.center.y + this.nodeWithPortPoints.height / 2,\n }\n }\n\n /**\n * Check if two routes are crossing\n */\n private doRoutesCross(routeA: Route, routeB: Route): boolean {\n return doSegmentsIntersect(\n routeA.startPort,\n routeA.endPort,\n routeB.startPort,\n routeB.endPort,\n )\n }\n\n private calculateViaPositions(\n routeA: Route,\n routeB: Route,\n ): {\n via1: Point\n via2: Point\n } | null {\n // Define outer box as the bounds where all points lie\n const outerBox = {\n width: this.bounds.maxX - this.bounds.minX,\n height: this.bounds.maxY - this.bounds.minY,\n x: this.bounds.minX,\n y: this.bounds.minY,\n }\n\n // Define inner box with padding of obstacleMargin\n const innerBox = {\n width: outerBox.width - 2 * this.obstacleMargin - this.viaDiameter,\n height: outerBox.height - 2 * this.obstacleMargin - this.viaDiameter,\n x: outerBox.x + this.obstacleMargin + this.viaDiameter / 2,\n y: outerBox.y + this.obstacleMargin + this.viaDiameter / 2,\n }\n\n // Define the K1 parameter (minimum distance from A/B to C/D)\n // We'll use viaDiameter + obstacleMargin as the minimum distance\n const K1 = this.viaDiameter + this.obstacleMargin\n\n // Get points A and B from the routeB\n const pointA = routeB.startPort\n const pointB = routeB.endPort\n\n // Get the inner box corners\n const corners = [\n { x: innerBox.x, y: innerBox.y }, // Top-left (0)\n { x: innerBox.x + innerBox.width, y: innerBox.y }, // Top-right (1)\n { x: innerBox.x + innerBox.width, y: innerBox.y + innerBox.height }, // Bottom-right (2)\n { x: innerBox.x, y: innerBox.y + innerBox.height }, // Bottom-left (3)\n ]\n\n // Calculate distance between two points\n const distanceBetween = (p1: Point, p2: Point): number => {\n return distance(p1, p2)\n }\n\n // Find all valid candidate points\n const candidatePoints: Array<\n Point & { type: string; index?: number; circle?: number; edge?: number }\n > = []\n\n // 1. First check which corners are valid (outside both K1 circles)\n corners.forEach((corner, index) => {\n if (\n distanceBetween(corner, pointA) >= K1 &&\n distanceBetween(corner, pointB) >= K1\n ) {\n candidatePoints.push({ ...corner, type: \"corner\", index })\n }\n })\n\n // 2. Find intersections of K1 circles with the inner box edges\n // Define the 4 edges of the inner box\n const edges = [\n { p1: corners[0], p2: corners[1] }, // top\n { p1: corners[1], p2: corners[2] }, // right\n { p1: corners[2], p2: corners[3] }, // bottom\n { p1: corners[3], p2: corners[0] }, // left\n ]\n\n // Find intersections for both circles with all edges\n ;[pointA, pointB].forEach((circleCenter, circleIndex) => {\n edges.forEach((edge, edgeIndex) => {\n const intersections = findCircleLineIntersections(\n { ...circleCenter, r: K1 },\n edge,\n )\n\n // For each intersection, check if it's also outside the other circle\n intersections.forEach((point) => {\n const otherCircle = circleIndex === 0 ? pointB : pointA\n if (distanceBetween(point, otherCircle) >= K1) {\n candidatePoints.push({\n ...point,\n type: \"intersection\",\n circle: circleIndex,\n edge: edgeIndex,\n })\n }\n })\n })\n })\n\n // If we have fewer than 2 candidate points, relax the constraints\n if (candidatePoints.length < 2) {\n // Try with smaller K1\n const relaxedK1 = K1 * 0.8 // Reduce by 20%\n corners.forEach((corner, index) => {\n if (\n distanceBetween(corner, pointA) >= relaxedK1 &&\n distanceBetween(corner, pointB) >= relaxedK1 &&\n !candidatePoints.some((p) => p.x === corner.x && p.y === corner.y)\n ) {\n candidatePoints.push({ ...corner, type: \"relaxed_corner\", index })\n }\n })\n\n // If still not enough, add corners sorted by distance\n if (candidatePoints.length < 2) {\n // Sort corners by their distance from A and B\n const sortedCorners = [...corners].sort((a, b) => {\n const aMinDist = Math.min(\n distanceBetween(a, pointA),\n distanceBetween(a, pointB),\n )\n const bMinDist = Math.min(\n distanceBetween(b, pointA),\n distanceBetween(b, pointB),\n )\n return bMinDist - aMinDist // Larger distances first\n })\n\n // Add corners not already in candidatePoints\n for (const corner of sortedCorners) {\n if (\n !candidatePoints.some((p) => p.x === corner.x && p.y === corner.y)\n ) {\n candidatePoints.push({ ...corner, type: \"forced_corner\" })\n if (candidatePoints.length >= 2) break\n }\n }\n }\n }\n\n // If still fewer than 2 candidates, return null\n if (candidatePoints.length < 2) {\n return null\n }\n\n // Find the pair of points with maximum distance between them\n let maxDist = 0\n let optimalPair = [\n candidatePoints[0],\n candidatePoints[candidatePoints.length > 1 ? 1 : 0],\n ]\n\n for (let i = 0; i < candidatePoints.length; i++) {\n for (let j = i + 1; j < candidatePoints.length; j++) {\n const dist = distanceBetween(candidatePoints[i], candidatePoints[j])\n if (dist > maxDist) {\n maxDist = dist\n optimalPair = [candidatePoints[i], candidatePoints[j]]\n }\n }\n }\n\n let via1 = { x: optimalPair[0].x, y: optimalPair[0].y }\n let via2 = { x: optimalPair[1].x, y: optimalPair[1].y }\n\n const via1DistToStart = distance(via1, routeA.startPort)\n const via2DistToStart = distance(via2, routeA.startPort)\n\n if (via2DistToStart < via1DistToStart) {\n ;[via1, via2] = [via2, via1]\n }\n\n return {\n via1,\n via2,\n }\n }\n\n /**\n * Create a route with properly placed vias\n */\n private createRoute(\n start: Point,\n end: Point,\n via1: Point,\n via2: Point,\n connectionName: string,\n ): HighDensityIntraNodeRoute {\n const middleZ = start.z === 0 ? 1 : 0\n\n // Create the route path with layer transitions\n const route = [\n { x: start.x, y: start.y, z: start.z ?? 0 },\n { x: via1.x, y: via1.y, z: start.z ?? 0 },\n { x: via1.x, y: via1.y, z: middleZ }, // Via transition to layer 1\n { x: via2.x, y: via2.y, z: middleZ }, // Stay on layer 1\n { x: via2.x, y: via2.y, z: end.z ?? 0 }, // Via transition back\n { x: end.x, y: end.y, z: end.z ?? 0 },\n ]\n\n return {\n connectionName,\n route,\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [via1, via2],\n }\n }\n\n /**\n * Try to solve with routeA going over and routeB staying on layer 0\n */\n private trySolveAOverB(routeA: Route, routeB: Route): boolean {\n const viaPositions = this.calculateViaPositions(routeA, routeB)\n if (viaPositions) {\n this.debugViaPositions.push(viaPositions)\n } else {\n return false\n }\n\n const { via1, via2 } = this.optimizeViaPositions(viaPositions)\n\n // if (\n // distance(via1, via2) <\n // this.viaDiameter + this.traceThickness + this.obstacleMargin * 2\n // ) {\n // return false\n // }\n\n // Create route for A that goes over B using vias\n const routeASolution = this.createRoute(\n routeA.startPort,\n routeA.endPort,\n via1,\n via2,\n routeA.connectionName,\n )\n\n // Calculate orthogonal line through the middle segment of route A\n const midSegmentStart = { x: via1.x, y: via1.y, z: 1 }\n const midSegmentEnd = { x: via2.x, y: via2.y, z: 1 }\n\n // Calculate the orthogonal points for route B\n const orthogonalPoints =\n this.calculateShortestOrthogonalRoutePoints(\n routeB.startPort,\n routeB.endPort,\n midSegmentStart,\n midSegmentEnd,\n routeA.startPort,\n routeA.endPort,\n ) ??\n this.calculateConservativeOrthogonalRoutePoints(\n routeB.startPort,\n routeB.endPort,\n midSegmentStart,\n midSegmentEnd,\n routeA.startPort,\n routeA.endPort,\n )\n\n // Create route for B that navigates around the vias\n const routeBSolution: HighDensityIntraNodeRoute = {\n connectionName: routeB.connectionName,\n route: orthogonalPoints as any,\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [],\n }\n\n this.solvedRoutes.push(routeASolution, routeBSolution)\n return true\n }\n\n private optimizeViaPositions(viaPositions: { via1: Point; via2: Point }): {\n via1: Point\n via2: Point\n } {\n const { via1, via2 } = viaPositions\n\n // Calculate the minimum required distance between vias\n const minRequiredDistance =\n (this.viaDiameter + this.traceThickness + this.obstacleMargin) * 2\n\n // Calculate current distance between vias\n const currentDistance = distance(via1, via2)\n\n // If vias are already closer than or equal to the minimum required distance, return as is\n if (currentDistance <= minRequiredDistance) {\n return viaPositions\n }\n\n // Calculate the direction vector from viaA to viaB\n const dirX = via2.x - via1.x\n const dirY = via2.y - via1.y\n\n // Normalize the direction vector\n const dirLength = Math.sqrt(dirX * dirX + dirY * dirY)\n const normDirX = dirX / dirLength\n const normDirY = dirY / dirLength\n\n // Calculate the midpoint of the current vias\n const midpointX = (via1.x + via2.x) / 2\n const midpointY = (via1.y + via2.y) / 2\n\n // Calculate new positions that are minRequiredDistance apart\n // Move each via half the distance towards the midpoint\n const moveDistance = (currentDistance - minRequiredDistance) / 2\n\n const newVia1 = {\n x: via1.x + normDirX * moveDistance,\n y: via1.y + normDirY * moveDistance,\n }\n\n const newVia2 = {\n x: via2.x - normDirX * moveDistance,\n y: via2.y - normDirY * moveDistance,\n }\n\n return {\n via1: newVia1,\n via2: newVia2,\n }\n }\n\n /**\n * Calculate the orthogonal route points for the second route\n */\n private calculateConservativeOrthogonalRoutePoints(\n start: Point,\n end: Point,\n via1: Point,\n via2: Point,\n otherRouteStart: Point,\n otherRouteEnd: Point,\n ): Point[] | null {\n // Define the inner edge box which is obstacleMargin away from outer box\n const outerBox = {\n width: this.bounds.maxX - this.bounds.minX,\n height: this.bounds.maxY - this.bounds.minY,\n x: this.bounds.minX,\n y: this.bounds.minY,\n }\n\n const innerEdgeBox = {\n width: outerBox.width - 2 * this.obstacleMargin - this.traceThickness,\n height: outerBox.height - 2 * this.obstacleMargin - this.traceThickness,\n x: outerBox.x + this.obstacleMargin + this.traceThickness / 2,\n y: outerBox.y + this.obstacleMargin + this.traceThickness / 2,\n }\n\n // Calculate the orthogonal line to the mid segment\n // First get the direction vector of mid segment\n const midSegmentDX = via2.x - via1.x\n const midSegmentDY = via2.y - via1.y\n\n // Calculate orthogonal vector (rotate by 90 degrees)\n const orthDX = -midSegmentDY\n const orthDY = midSegmentDX\n\n // Normalize the orthogonal vector\n const orthLength = Math.sqrt(orthDX * orthDX + orthDY * orthDY)\n const normOrthDX = orthDX / orthLength\n const normOrthDY = orthDY / orthLength\n\n // Calculate the midpoint of the mid segment\n const midpointX = (via1.x + via2.x) / 2\n const midpointY = (via1.y + via2.y) / 2\n\n // Calculate the orthogonal line that passes through the midpoint\n // Line equation: (x, y) = (midpointX, midpointY) + t * (normOrthDX, normOrthDY)\n\n // Function to calculate intersections with the innerEdgeBox\n const calculateIntersections = (): Point[] => {\n const intersections: Point[] = []\n\n // Check intersection with left edge\n const leftT = (innerEdgeBox.x - midpointX) / normOrthDX\n const leftY = midpointY + leftT * normOrthDY\n if (\n leftY >= innerEdgeBox.y &&\n leftY <= innerEdgeBox.y + innerEdgeBox.height\n ) {\n intersections.push({ x: innerEdgeBox.x, y: leftY })\n }\n\n // Check intersection with right edge\n const rightT =\n (innerEdgeBox.x + innerEdgeBox.width - midpointX) / normOrthDX\n const rightY = midpointY + rightT * normOrthDY\n if (\n rightY >= innerEdgeBox.y &&\n rightY <= innerEdgeBox.y + innerEdgeBox.height\n ) {\n intersections.push({\n x: innerEdgeBox.x + innerEdgeBox.width,\n y: rightY,\n })\n }\n\n // Check intersection with top edge\n const topT = (innerEdgeBox.y - midpointY) / normOrthDY\n const topX = midpointX + topT * normOrthDX\n if (\n topX >= innerEdgeBox.x &&\n topX <= innerEdgeBox.x + innerEdgeBox.width\n ) {\n intersections.push({ x: topX, y: innerEdgeBox.y })\n }\n\n // Check intersection with bottom edge\n const bottomT =\n (innerEdgeBox.y + innerEdgeBox.height - midpointY) / normOrthDY\n const bottomX = midpointX + bottomT * normOrthDX\n if (\n bottomX >= innerEdgeBox.x &&\n bottomX <= innerEdgeBox.x + innerEdgeBox.width\n ) {\n intersections.push({\n x: bottomX,\n y: innerEdgeBox.y + innerEdgeBox.height,\n })\n }\n\n return intersections\n }\n\n const intersections = calculateIntersections()\n\n // If we don't have at least 2 intersections, return direct route\n if (intersections.length < 2) {\n return [\n { x: start.x, y: start.y, z: start.z ?? 0 },\n { x: end.x, y: end.y, z: end.z ?? 0 },\n ]\n }\n\n // Sort intersections by distance from start point\n const sortedIntersections = [...intersections].sort((a, b) => {\n const distA = distance(a, start)\n const distB = distance(b, start)\n return distA - distB\n })\n\n // Choose the closest intersection to the start and the closest to the end\n let middlePoint1 = sortedIntersections[0]\n let middlePoint2 = sortedIntersections[intersections.length - 1]\n\n if (\n doSegmentsIntersect(start, middlePoint1, otherRouteStart, via1) ||\n doSegmentsIntersect(end, middlePoint2, otherRouteEnd, via2)\n ) {\n ;[middlePoint1, middlePoint2] = [middlePoint2, middlePoint1]\n }\n\n // Create the route with 4 points\n return [\n { x: start.x, y: start.y, z: start.z ?? 0 },\n { x: middlePoint1.x, y: middlePoint1.y, z: start.z ?? 0 },\n { x: middlePoint2.x, y: middlePoint2.y, z: start.z ?? 0 },\n { x: end.x, y: end.y, z: end.z ?? 0 },\n ]\n }\n\n private calculateShortestOrthogonalRoutePoints(\n start: Point,\n end: Point,\n via1: Point,\n via2: Point,\n otherRouteStart: Point,\n otherRouteEnd: Point,\n ): Point[] | null {\n const midSegmentCenter = {\n x: (via1.x + via2.x) / 2,\n y: (via1.y + via2.y) / 2,\n }\n\n const midSegmentDirection = {\n x: via2.x - via1.x,\n y: via2.y - via1.y,\n }\n\n const midSegmentLength = distance(via1, via2)\n const normOrthDX = midSegmentDirection.y / midSegmentLength\n const normOrthDY = midSegmentDirection.x / midSegmentLength\n\n // Travel orthogonal to the mid segment by the length of the mid segment to\n // get two points\n let orthogonalPoint1 = {\n x: midSegmentCenter.x + (midSegmentLength / 2) * normOrthDY,\n y: midSegmentCenter.y - (midSegmentLength / 2) * normOrthDX,\n }\n\n let orthogonalPoint2 = {\n x: midSegmentCenter.x - (midSegmentLength / 2) * normOrthDY,\n y: midSegmentCenter.y + (midSegmentLength / 2) * normOrthDX,\n }\n\n if (distance(orthogonalPoint2, start) < distance(orthogonalPoint1, start)) {\n ;[orthogonalPoint1, orthogonalPoint2] = [\n orthogonalPoint2,\n orthogonalPoint1,\n ]\n }\n\n // Make sure we're not too close to the other route, or the mid segment\n // start or end (which has vias)\n // TODO - i haven't done this because we need a good test case/fixture -seve\n\n if (\n doSegmentsIntersect(start, orthogonalPoint1, otherRouteStart, via1) ||\n doSegmentsIntersect(end, orthogonalPoint2, otherRouteEnd, via2)\n ) {\n ;[orthogonalPoint1, orthogonalPoint2] = [\n orthogonalPoint2,\n orthogonalPoint1,\n ]\n }\n\n if (\n doSegmentsIntersect(start, orthogonalPoint2, otherRouteStart, via1) ||\n doSegmentsIntersect(end, orthogonalPoint1, otherRouteEnd, via2)\n ) {\n return null\n }\n\n return [\n { x: start.x, y: start.y, z: start.z ?? 0 },\n { x: orthogonalPoint1.x, y: orthogonalPoint1.y, z: start.z ?? 0 },\n { x: orthogonalPoint2.x, y: orthogonalPoint2.y, z: start.z ?? 0 },\n { x: end.x, y: end.y, z: end.z ?? 0 },\n ]\n }\n\n /**\n * Main step method that attempts to solve the two crossing routes\n */\n _step() {\n // Check if we have exactly two routes\n if (this.routes.length !== 2) {\n this.failed = true\n return\n }\n\n const [routeA, routeB] = this.routes\n\n // Check if routes are actually crossing\n if (!this.doRoutesCross(routeA, routeB)) {\n // Routes don't cross, create simple direct connections\n const routeASolution: HighDensityIntraNodeRoute = {\n connectionName: routeA.connectionName,\n route: [\n {\n x: routeA.startPort.x,\n y: routeA.startPort.y,\n z: routeA.startPort.z ?? 0,\n },\n {\n x: routeA.endPort.x,\n y: routeA.endPort.y,\n z: routeA.endPort.z ?? 0,\n },\n ],\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [],\n }\n\n const routeBSolution: HighDensityIntraNodeRoute = {\n connectionName: routeB.connectionName,\n route: [\n {\n x: routeB.startPort.x,\n y: routeB.startPort.y,\n z: routeB.startPort.z ?? 0,\n },\n {\n x: routeB.endPort.x,\n y: routeB.endPort.y,\n z: routeB.endPort.z ?? 0,\n },\n ],\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [],\n }\n\n this.solvedRoutes.push(routeASolution, routeBSolution)\n this.solved = true\n return\n }\n\n // Try having route A go over route B\n if (this.trySolveAOverB(routeA, routeB)) {\n this.solved = true\n return\n }\n\n // If that fails, try having route B go over route A\n if (this.trySolveAOverB(routeB, routeA)) {\n this.solved = true\n return\n }\n\n // If both approaches fail, mark as failed\n this.failed = true\n }\n\n /**\n * Visualization for debugging\n */\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n\n // Draw PCB bounds\n graphics.rects!.push({\n center: {\n x: (this.bounds.minX + this.bounds.maxX) / 2,\n y: (this.bounds.minY + this.bounds.maxY) / 2,\n },\n width: this.bounds.maxX - this.bounds.minX,\n height: this.bounds.maxY - this.bounds.minY,\n stroke: \"rgba(0, 0, 0, 0.5)\",\n fill: \"rgba(240, 240, 240, 0.1)\",\n label: \"PCB Bounds\",\n })\n\n // Draw original routes\n for (const route of this.routes) {\n // Draw endpoints\n graphics.points!.push({\n x: route.startPort.x,\n y: route.startPort.y,\n label: `${route.connectionName} start`,\n color: \"orange\",\n })\n\n graphics.points!.push({\n x: route.endPort.x,\n y: route.endPort.y,\n label: `${route.connectionName} end`,\n color: \"orange\",\n })\n\n // Draw direct connection line\n graphics.lines!.push({\n points: [route.startPort, route.endPort],\n strokeColor: \"rgba(255, 0, 0, 0.5)\",\n label: `${route.connectionName} direct`,\n })\n }\n\n // Draw debug via positions (even if solution failed)\n for (let i = 0; i < this.debugViaPositions.length; i++) {\n const { via1, via2 } = this.debugViaPositions[i]\n\n // Draw computed vias (using different colors for different attempts)\n const colors = [\"rgba(255, 165, 0, 0.7)\", \"rgba(128, 0, 128, 0.7)\"] // orange, purple\n const color = colors[i % colors.length]\n\n graphics.circles!.push({\n center: via1,\n radius: this.viaDiameter / 2,\n fill: color,\n stroke: \"rgba(0, 0, 0, 0.5)\",\n label: `Computed Via A (attempt ${i + 1})`,\n })\n\n graphics.circles!.push({\n center: via2,\n radius: this.viaDiameter / 2,\n fill: color,\n stroke: \"rgba(0, 0, 0, 0.5)\",\n label: `Computed Via B (attempt ${i + 1})`,\n })\n\n // Draw safety margins around vias\n const safetyMargin = this.viaDiameter / 2 + this.obstacleMargin\n graphics.circles!.push({\n center: via1,\n radius: safetyMargin,\n stroke: color,\n fill: \"rgba(0, 0, 0, 0)\",\n label: \"Safety Margin\",\n })\n\n graphics.circles!.push({\n center: via2,\n radius: safetyMargin,\n stroke: color,\n fill: \"rgba(0, 0, 0, 0)\",\n label: \"Safety Margin\",\n })\n\n // Draw potential route through vias\n graphics.lines!.push({\n points: [\n this.routes[i % 2].startPort,\n via1,\n via2,\n this.routes[i % 2].endPort,\n ],\n strokeColor: `${color.substring(0, color.lastIndexOf(\",\"))}, 0.3)`,\n strokeDash: [5, 5],\n label: `Potential Route (attempt ${i + 1})`,\n })\n }\n\n // Draw solved routes if available\n for (let si = 0; si < this.solvedRoutes.length; si++) {\n const route = this.solvedRoutes[si]\n const routeColor =\n si % 2 === 0 ? \"rgba(0, 255, 0, 0.75)\" : \"rgba(255, 0, 255, 0.75)\"\n for (let i = 0; i < route.route.length - 1; i++) {\n const pointA = route.route[i]\n const pointB = route.route[i + 1]\n\n graphics.lines!.push({\n points: [pointA, pointB],\n strokeColor: routeColor,\n strokeDash: pointA.z === 1 ? [0.2, 0.2] : undefined,\n strokeWidth: route.traceThickness,\n label: `${route.connectionName} z=${pointA.z}`,\n })\n }\n\n // Draw vias in solved routes\n for (const via of route.vias) {\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2,\n fill: \"rgba(0, 0, 255, 0.8)\",\n stroke: \"black\",\n label: \"Solved Via\",\n })\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2 + this.obstacleMargin,\n fill: \"rgba(0, 0, 255, 0.3)\",\n stroke: \"black\",\n label: \"Via Margin\",\n })\n }\n }\n\n return graphics\n }\n\n /**\n * Get the solved routes\n */\n getSolvedRoutes(): HighDensityIntraNodeRoute[] {\n return this.solvedRoutes\n }\n}\n","interface Point {\n x: number\n y: number\n}\n\n/**\n * Finds the optimal position that is closest to the average of points A, B, and C,\n * while maintaining a minimum distance of radius from each point and staying within bounds.\n *\n * https://claude.ai/artifacts/b61d2619-0d39-45e7-b02b-ebdcb645f07e\n */\nexport function findClosestPointToABCWithinBounds(\n A: Point,\n B: Point,\n C: Point,\n radius: number,\n bounds: { minX: number; minY: number; maxX: number; maxY: number },\n) {\n // Calculate the average point (center of mass)\n const avgPoint = {\n x: (A.x + B.x + C.x) / 3,\n y: (A.y + B.y + C.y) / 3,\n }\n\n // Function to calculate distance between two points\n const distance = (p1: Point, p2: Point) => {\n return Math.sqrt((p2.x - p1.x) ** 2 + (p2.y - p1.y) ** 2)\n }\n\n // Function to check if a point satisfies all constraints\n const isValidPoint = (point: Point) => {\n // Check distance constraints\n const distToA = distance(point, A)\n const distToB = distance(point, B)\n const distToC = distance(point, C)\n\n // Check bounds constraints\n const withinBounds =\n point.x >= bounds.minX &&\n point.x <= bounds.maxX &&\n point.y >= bounds.minY &&\n point.y <= bounds.maxY\n\n return (\n distToA >= radius &&\n distToB >= radius &&\n distToC >= radius &&\n withinBounds\n )\n }\n\n // Function to check if a point is on the boundary\n const isOnBoundary = (point: Point) => {\n const epsilon = 1e-6\n return (\n Math.abs(point.x - bounds.minX) < epsilon ||\n Math.abs(point.x - bounds.maxX) < epsilon ||\n Math.abs(point.y - bounds.minY) < epsilon ||\n Math.abs(point.y - bounds.maxY) < epsilon\n )\n }\n\n // First check if average point satisfies all constraints\n if (isValidPoint(avgPoint)) {\n return avgPoint\n }\n\n // Next, check all the standard candidates based on circles and intersections\n const pointOnCircle = (center: Point, constraint: Point, r: number) => {\n const vx = center.x - constraint.x\n const vy = center.y - constraint.y\n const dist = Math.sqrt(vx * vx + vy * vy)\n\n if (dist < 1e-10) {\n return { x: constraint.x + r, y: constraint.y }\n }\n\n return {\n x: constraint.x + (vx / dist) * r,\n y: constraint.y + (vy / dist) * r,\n }\n }\n\n const findCircleIntersections = (c1: Point, c2: Point, r: number) => {\n const dx = c2.x - c1.x\n const dy = c2.y - c1.y\n const dist = Math.sqrt(dx * dx + dy * dy)\n\n if (dist > 2 * r - 1e-10 || dist < 1e-10) {\n return []\n }\n\n const a = (dist * dist) / (2 * dist)\n const h = Math.sqrt(Math.max(0, r * r - a * a))\n\n const midX = c1.x + (dx * a) / dist\n const midY = c1.y + (dy * a) / dist\n\n const intersection1 = {\n x: midX + (h * dy) / dist,\n y: midY - (h * dx) / dist,\n }\n\n const intersection2 = {\n x: midX - (h * dy) / dist,\n y: midY + (h * dx) / dist,\n }\n\n const result = []\n const epsilon = 1e-6\n\n if (\n Math.abs(distance(intersection1, c1) - r) < epsilon &&\n Math.abs(distance(intersection1, c2) - r) < epsilon\n ) {\n result.push(intersection1)\n }\n\n if (\n Math.abs(distance(intersection2, c1) - r) < epsilon &&\n Math.abs(distance(intersection2, c2) - r) < epsilon\n ) {\n result.push(intersection2)\n }\n\n return result\n }\n\n // Get all standard candidates\n const candidateA = pointOnCircle(avgPoint, A, radius)\n const candidateB = pointOnCircle(avgPoint, B, radius)\n const candidateC = pointOnCircle(avgPoint, C, radius)\n\n const intersectionsAB = findCircleIntersections(A, B, radius)\n const intersectionsBC = findCircleIntersections(B, C, radius)\n const intersectionsCA = findCircleIntersections(C, A, radius)\n\n const allCandidates = [\n candidateA,\n candidateB,\n candidateC,\n ...intersectionsAB,\n ...intersectionsBC,\n ...intersectionsCA,\n ]\n\n // Filter to valid candidates\n const validCandidates = allCandidates.filter(isValidPoint)\n\n // If we have valid interior candidates, use them\n if (validCandidates.length > 0) {\n // Separate interior and boundary points\n const interiorCandidates = validCandidates.filter((p) => !isOnBoundary(p))\n\n if (interiorCandidates.length > 0) {\n // Sort by distance to average\n interiorCandidates.sort(\n (a, b) => distance(a, avgPoint) - distance(b, avgPoint),\n )\n return interiorCandidates[0]\n }\n }\n\n // No valid interior candidates from standard points, now do a grid search\n // We'll do a systematic grid search to find interior points\n const gridStep = 5 // 5px grid\n let bestPoint = null\n let bestDistance = Infinity\n\n for (let x = bounds.minX + 1; x < bounds.maxX; x += gridStep) {\n for (let y = bounds.minY + 1; y < bounds.maxY; y += gridStep) {\n const point = { x, y }\n if (isValidPoint(point)) {\n const dist = distance(point, avgPoint)\n if (dist < bestDistance) {\n bestDistance = dist\n bestPoint = point\n }\n }\n }\n }\n\n // If we found a valid interior point in the grid search, return it\n if (bestPoint !== null) {\n return bestPoint\n }\n\n // If all interior methods failed, check boundary points\n // Sample points along the boundary\n const numSamples = 100 // More samples for better accuracy\n const boundaryPoints = []\n\n for (let i = 0; i <= numSamples; i++) {\n const t = i / numSamples\n\n // Top edge\n boundaryPoints.push({\n x: bounds.minX + t * (bounds.maxX - bounds.minX),\n y: bounds.minY,\n })\n\n // Right edge\n boundaryPoints.push({\n x: bounds.maxX,\n y: bounds.minY + t * (bounds.maxY - bounds.minY),\n })\n\n // Bottom edge\n boundaryPoints.push({\n x: bounds.maxX - t * (bounds.maxX - bounds.minX),\n y: bounds.maxY,\n })\n\n // Left edge\n boundaryPoints.push({\n x: bounds.minX,\n y: bounds.maxY - t * (bounds.maxY - bounds.minY),\n })\n }\n\n // Find valid boundary points\n const validBoundaryPoints = boundaryPoints.filter(isValidPoint)\n\n if (validBoundaryPoints.length > 0) {\n // Sort by distance to average\n validBoundaryPoints.sort(\n (a, b) => distance(a, avgPoint) - distance(b, avgPoint),\n )\n return validBoundaryPoints[0]\n }\n\n // If we get here, no valid point exists that satisfies all constraints\n // Find the point that minimizes constraint violations\n let minViolation = Infinity\n let leastBadPoint = { x: bounds.minX, y: bounds.minY }\n\n for (const point of [...allCandidates, ...boundaryPoints]) {\n // Only consider points within bounds\n if (\n point.x >= bounds.minX &&\n point.x <= bounds.maxX &&\n point.y >= bounds.minY &&\n point.y <= bounds.maxY\n ) {\n const violationA = Math.max(0, radius - distance(point, A))\n const violationB = Math.max(0, radius - distance(point, B))\n const violationC = Math.max(0, radius - distance(point, C))\n\n const totalViolation = violationA + violationB + violationC\n\n if (totalViolation < minViolation) {\n minViolation = totalViolation\n leastBadPoint = point\n }\n }\n }\n\n return leastBadPoint\n}\n","interface Point {\n x: number\n y: number\n}\n\ninterface Circle {\n center: Point\n radius: number\n}\n\n/**\n * Finds the tangent points and their intersection for the shortest path from C to A\n * that touches the circle Q at points B and D.\n *\n * E is the point where you're guaranteed to be able to get around the circle\n * without intersecting it if you travel from A to E to C\n *\n * @param A First observation point\n * @param C Second observation point\n * @param Q Circle definition with center and radius\n * @returns Object containing points B, D, and E\n */\nexport function findPointToGetAroundCircle(\n A: Point,\n C: Point,\n Q: Circle,\n): { B: Point; D: Point; E: Point } {\n // Compute point B (tangent from C to circle Q)\n const B = computeTangentPoint(C, A, Q.center, Q.radius)\n\n // Compute point D (tangent from A to circle Q)\n const D = computeTangentPoint(A, C, Q.center, Q.radius)\n\n // Check if B and D are valid (not too close to C and A respectively)\n const distBC = distance(B, C)\n const distAD = distance(A, D)\n const minDistThreshold = 1e-6\n\n const BIsValid = distBC > minDistThreshold\n const DIsValid = distAD > minDistThreshold\n\n // Compute point E using a robust approach\n let E: Point\n\n if (!BIsValid || !DIsValid) {\n // Fallback: Use the midpoint between A and C but ensure it's outside the circle\n const midAC = {\n x: (A.x + C.x) / 2,\n y: (A.y + C.y) / 2,\n }\n\n const distFromCenter = distance(midAC, Q.center)\n if (distFromCenter < Q.radius * 1.1) {\n // Too close to circle, move away from center\n const dirFromCenter = {\n x: (midAC.x - Q.center.x) / distFromCenter,\n y: (midAC.y - Q.center.y) / distFromCenter,\n }\n\n E = {\n x: Q.center.x + dirFromCenter.x * Q.radius * 1.2,\n y: Q.center.y + dirFromCenter.y * Q.radius * 1.2,\n }\n } else {\n // Midpoint is far enough from circle\n E = midAC\n }\n } else {\n // B and D are valid, use midpoint between B and D as a robust solution\n E = {\n x: (B.x + D.x) / 2,\n y: (B.y + D.y) / 2,\n }\n\n // Check if the midpoint is a reasonable solution\n const distBE = distance(B, E)\n const distDE = distance(D, E)\n\n if (Math.abs(distBE - distDE) > Math.min(distBE, distDE) * 0.5) {\n // The midpoint is significantly closer to one point than the other\n // Use a weighted average instead\n const distAB = distance(A, B)\n const distCD = distance(C, D)\n const totalDist = distAB + distCD\n\n if (totalDist > minDistThreshold) {\n // Weight based on distances from A to B and C to D\n const weightB = distCD / totalDist\n const weightD = distAB / totalDist\n\n E = {\n x: B.x * weightB + D.x * weightD,\n y: B.y * weightB + D.y * weightD,\n }\n }\n }\n\n // Final safety check: make sure E is outside the circle\n const distEToCenter = distance(E, Q.center)\n if (distEToCenter < Q.radius * 1.05) {\n // E is too close to the circle, adjust it\n const dirFromCenter = {\n x: (E.x - Q.center.x) / distEToCenter,\n y: (E.y - Q.center.y) / distEToCenter,\n }\n\n E = {\n x: Q.center.x + dirFromCenter.x * Q.radius * 1.2,\n y: Q.center.y + dirFromCenter.y * Q.radius * 1.2,\n }\n }\n }\n\n return { B, D, E }\n}\n\n/**\n * Computes the tangent point from an observation point to a circle\n *\n * @param observationPoint The point from which the tangent is drawn\n * @param referencePoint A reference point that helps determine which side of the circle to choose\n * @param circleCenter The center of the circle\n * @param radius The radius of the circle\n * @returns The tangent point on the circle\n */\nfunction computeTangentPoint(\n observationPoint: Point,\n referencePoint: Point,\n circleCenter: Point,\n radius: number,\n): Point {\n // Vector from observation point to circle center\n const CQ = [\n circleCenter.x - observationPoint.x,\n circleCenter.y - observationPoint.y,\n ]\n const CQLength = Math.sqrt(CQ[0] * CQ[0] + CQ[1] * CQ[1])\n\n // Check if tangent is possible (point is inside or on the circle)\n if (CQLength <= radius) {\n // Instead of returning the observation point, find a point on the circle\n // in the direction away from the circle center\n if (CQLength < 1e-8) {\n // If observation point is at circle center, move in direction of reference point\n const refVec = [\n referencePoint.x - observationPoint.x,\n referencePoint.y - observationPoint.y,\n ]\n const refLength = Math.sqrt(refVec[0] * refVec[0] + refVec[1] * refVec[1])\n\n if (refLength < 1e-8) {\n // If reference point is also at circle center, use arbitrary direction\n return {\n x: circleCenter.x + radius,\n y: circleCenter.y,\n }\n }\n\n return {\n x: circleCenter.x + (refVec[0] / refLength) * radius,\n y: circleCenter.y + (refVec[1] / refLength) * radius,\n }\n }\n\n // Move away from circle center along the same line\n const CQUnit = [CQ[0] / CQLength, CQ[1] / CQLength]\n return {\n x: circleCenter.x - CQUnit[0] * radius,\n y: circleCenter.y - CQUnit[1] * radius,\n }\n }\n\n // Vector from observation point to reference point (to determine which side of the circle)\n const CR = [\n referencePoint.x - observationPoint.x,\n referencePoint.y - observationPoint.y,\n ]\n\n // Calculate the distance from observation point to the tangent point\n const d = Math.sqrt(CQLength * CQLength - radius * radius)\n\n // Normalize CQ to get the unit vector in that direction\n const CQUnit = [CQ[0] / CQLength, CQ[1] / CQLength]\n\n // Calculate two possible perpendicular unit vectors\n const perp1 = [-CQUnit[1], CQUnit[0]]\n const perp2 = [CQUnit[1], -CQUnit[0]]\n\n // Choose the perpendicular that forms an angle closer to CR\n const dot1 = CR[0] * perp1[0] + CR[1] * perp1[1]\n const dot2 = CR[0] * perp2[0] + CR[1] * perp2[1]\n const perp = dot1 > dot2 ? perp1 : perp2\n\n // Calculate the sine and cosine of the angle from CQ to the tangent line\n const sinTheta = radius / CQLength\n const cosTheta = d / CQLength\n\n // Unit vector in the direction of the tangent point\n const unitToTangent = [\n CQUnit[0] * cosTheta + perp[0] * sinTheta,\n CQUnit[1] * cosTheta + perp[1] * sinTheta,\n ]\n\n // Calculate the tangent point\n return {\n x: observationPoint.x + d * unitToTangent[0],\n y: observationPoint.y + d * unitToTangent[1],\n }\n}\n\n/**\n * Helper function to calculate the Euclidean distance between two points\n */\nfunction distance(p1: Point, p2: Point): number {\n const dx = p2.x - p1.x\n const dy = p2.y - p1.y\n return Math.sqrt(dx * dx + dy * dy)\n}\n","interface Point {\n x: number\n y: number\n}\n\ninterface Bounds {\n minX: number\n maxX: number\n minY: number\n maxY: number\n}\n\ninterface SidePercentages {\n left: number\n top: number\n right: number\n bottom: number\n}\n\n// Keep a small epsilon for floating point comparisons\nconst EPSILON = 1e-9 // Using a slightly smaller epsilon can sometimes help precision\n\n/**\n * Calculates the percentage of each side traversed when going from point A to point B\n * along the rectangle boundary.\n * Assumes traversal is always in the 'forward' direction along the perimeter (clockwise conceptually).\n */\nfunction calculateSegmentTraversal(\n startPoint: Point,\n endPoint: Point,\n bounds: Bounds,\n): SidePercentages {\n const startAngle = pointToAngle(startPoint, bounds)\n let endAngle = pointToAngle(endPoint, bounds)\n\n // Handle angle wrap-around (e.g., traversing past the 2π point)\n // If the end angle is less than the start angle, it means we crossed the 0/2π boundary\n if (endAngle < startAngle) {\n endAngle += 2 * Math.PI\n }\n\n // Use the existing helper, which calculates percentages based on a start and end angle\n // Ensure the end angle is strictly greater for non-zero traversal\n if (Math.abs(endAngle - startAngle) < EPSILON) {\n return { left: 0, top: 0, right: 0, bottom: 0 } // No movement\n }\n\n return calculateSidePercentages(startAngle, endAngle, bounds)\n}\n\n/**\n * Calculates the total percentage of each side traversed when going sequentially\n * from A to B, and then from B to C along a rectangle boundary.\n */\nexport function calculateTraversalPercentages(\n A: Point,\n B: Point,\n C: Point,\n bounds: Bounds,\n): SidePercentages {\n // Calculate traversal percentages for the segment A -> B\n const percentagesAB = calculateSegmentTraversal(A, B, bounds)\n\n // Calculate traversal percentages for the segment B -> C\n const percentagesBC = calculateSegmentTraversal(B, C, bounds)\n\n // Sum the percentages from both segments\n // Use Math.min to cap at 1.0 in case of tiny floating point overflows\n const totalPercentages: SidePercentages = {\n left: Math.min(1.0, percentagesAB.left + percentagesBC.left),\n top: Math.min(1.0, percentagesAB.top + percentagesBC.top),\n right: Math.min(1.0, percentagesAB.right + percentagesBC.right),\n bottom: Math.min(1.0, percentagesAB.bottom + percentagesBC.bottom),\n }\n\n // Optional: Clean up near-zero values resulting from floating point inaccuracies\n for (const key in totalPercentages) {\n if (Math.abs(totalPercentages[key as keyof SidePercentages]) < EPSILON) {\n totalPercentages[key as keyof SidePercentages] = 0\n }\n }\n\n return totalPercentages\n}\n\n/**\n * Converts a point on the rectangle boundary to an angle (0 to 2π, clockwise from top-left).\n * Updated to be slightly more robust with epsilon checks.\n */\nfunction pointToAngle(point: Point, bounds: Bounds): number {\n const width = bounds.maxX - bounds.minX\n const height = bounds.maxY - bounds.minY\n // Avoid division by zero if width or height is zero\n if (width < EPSILON && height < EPSILON) return 0\n const perimeter = 2 * (width + height)\n if (perimeter < EPSILON) return 0 // Avoid division by zero for degenerate rectangles\n\n let distance = 0\n\n // Check sides using epsilon comparisons\n if (\n Math.abs(point.y - bounds.maxY) < EPSILON &&\n point.x >= bounds.minX - EPSILON &&\n point.x <= bounds.maxX + EPSILON\n ) {\n // Top side (y is maxY)\n // Ensure x is clamped within bounds for distance calculation robustness\n distance = Math.max(0, Math.min(width, point.x - bounds.minX))\n } else if (\n Math.abs(point.x - bounds.maxX) < EPSILON &&\n point.y >= bounds.minY - EPSILON &&\n point.y <= bounds.maxY + EPSILON\n ) {\n // Right side (x is maxX)\n // Ensure y is clamped within bounds\n distance = width + Math.max(0, Math.min(height, bounds.maxY - point.y))\n } else if (\n Math.abs(point.y - bounds.minY) < EPSILON &&\n point.x >= bounds.minX - EPSILON &&\n point.x <= bounds.maxX + EPSILON\n ) {\n // Bottom side (y is minY)\n // Ensure x is clamped within bounds\n distance =\n width + height + Math.max(0, Math.min(width, bounds.maxX - point.x))\n } else if (\n Math.abs(point.x - bounds.minX) < EPSILON &&\n point.y >= bounds.minY - EPSILON &&\n point.y <= bounds.maxY + EPSILON\n ) {\n // Left side (x is minX)\n // Ensure y is clamped within bounds\n distance =\n width +\n height +\n width +\n Math.max(0, Math.min(height, point.y - bounds.minY))\n } else {\n // Point might be slightly off boundary due to precision, try snapping it?\n // Or throw error as before. For now, let's log a warning and try snapping.\n // console.warn(\n // \"Point does not lie exactly on the boundary, attempting to snap.\",\n // { point, bounds },\n // )\n // Simple snap: Find closest side point (more complex logic could be added here)\n // For simplicity, we'll re-call with snapped points if needed, or just throw.\n // Let's stick to the original error for now if it's significantly off.\n throw new Error(\n `Point (${point.x}, ${point.y}) does not lie on the boundary defined by ${JSON.stringify(bounds)}`,\n )\n // Alternative: Add logic here to find the closest point on the boundary and use that.\n }\n\n // Ensure distance doesn't exceed perimeter due to float issues\n distance = Math.max(0, Math.min(perimeter, distance))\n\n // Convert distance to angle (0 to 2π)\n // Handle perimeter being zero\n return perimeter > EPSILON ? (distance / perimeter) * (2 * Math.PI) : 0\n}\n\n/**\n * Calculate percentages of each side traversed based on start and end angles (endAngle >= startAngle).\n * This function remains largely the same but benefits from corrected inputs.\n */\nfunction calculateSidePercentages(\n startAngle: number,\n endAngle: number,\n bounds: Bounds,\n): SidePercentages {\n const width = bounds.maxX - bounds.minX\n const height = bounds.maxY - bounds.minY\n // Avoid division by zero if width or height is zero\n if (width < EPSILON && height < EPSILON)\n return { left: 0, top: 0, right: 0, bottom: 0 }\n const perimeter = 2 * (width + height)\n if (perimeter < EPSILON) return { left: 0, top: 0, right: 0, bottom: 0 }\n\n // Define angle ranges for each side (clockwise from top-left = 0)\n // Ensure denominator is non-zero\n const angleTopEnd = (width / perimeter) * (2 * Math.PI)\n const angleRightEnd = ((width + height) / perimeter) * (2 * Math.PI)\n const angleBottomEnd = ((width + width + height) / perimeter) * (2 * Math.PI)\n const angleLeftEnd = 2 * Math.PI // Full circle\n\n const sides = [\n { name: \"top\", start: 0, end: angleTopEnd, length: width },\n { name: \"right\", start: angleTopEnd, end: angleRightEnd, length: height },\n {\n name: \"bottom\",\n start: angleRightEnd,\n end: angleBottomEnd,\n length: width,\n },\n { name: \"left\", start: angleBottomEnd, end: angleLeftEnd, length: height }, // Ends at 2PI\n ]\n\n const result: SidePercentages = { left: 0, top: 0, right: 0, bottom: 0 }\n const totalAngleTraversal = endAngle - startAngle\n\n if (totalAngleTraversal < EPSILON) return result // No traversal\n\n for (const side of sides) {\n const sideAngleRange = side.end - side.start\n\n // Skip calculation if side length (and thus angle range) is effectively zero\n if (sideAngleRange < EPSILON || side.length < EPSILON) continue\n\n // Calculate overlap\n const overlapStart = Math.max(startAngle, side.start)\n const overlapEnd = Math.min(endAngle, side.end)\n\n if (overlapStart < overlapEnd - EPSILON) {\n // Check overlap is significant\n const traversedAngleOnSide = overlapEnd - overlapStart\n\n // Percentage calculation: (traversed angle on side) / (total angle range of side)\n // This gives the fraction *of the side* that was covered by this segment traversal.\n const percentage = traversedAngleOnSide / sideAngleRange\n\n // Add percentage, ensuring it's non-negative\n result[side.name as keyof SidePercentages] += Math.max(0, percentage)\n }\n }\n\n // Normalize results slightly in case of FP inaccuracies summing up\n for (const key in result) {\n result[key as keyof SidePercentages] = Math.max(\n 0,\n Math.min(1.0, result[key as keyof SidePercentages]),\n )\n }\n\n return result\n}\n","import { BaseSolver } from \"lib/solvers/BaseSolver\"\nimport {\n NodeWithPortPoints,\n HighDensityIntraNodeRoute,\n} from \"lib/types/high-density-types\"\nimport {\n distance,\n pointToSegmentDistance,\n doSegmentsIntersect,\n clamp,\n} from \"@tscircuit/math-utils\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { getIntraNodeCrossings } from \"lib/utils/getIntraNodeCrossings\"\nimport { findCircleLineIntersections } from \"./findCircleLineIntersections\"\nimport { findClosestPointToABCWithinBounds } from \"lib/utils/findClosestPointToABCWithinBounds\"\nimport { calculatePerpendicularPointsAtDistance } from \"lib/utils/calculatePointsAtDistance\"\nimport { snapToNearestBound } from \"lib/utils/snapToNearestBound\"\nimport { findPointToGetAroundCircle } from \"lib/utils/findPointToGetAroundCircle\"\nimport { calculateTraversalPercentages } from \"./calculateSideTraversal\"\n\ntype Point = { x: number; y: number; z?: number }\ntype Route = {\n A: Point\n B: Point\n connectionName: string\n}\n\nexport class SingleTransitionCrossingRouteSolver extends BaseSolver {\n // Input parameters\n nodeWithPortPoints: NodeWithPortPoints\n routes: Route[]\n\n // Configuration parameters\n viaDiameter: number\n traceThickness: number\n obstacleMargin: number\n layerCount: number = 2\n\n debugViaPositions: {\n via: Point\n }[]\n\n // Solution state\n solvedRoutes: HighDensityIntraNodeRoute[] = []\n\n // Bounds\n bounds: { minX: number; maxX: number; minY: number; maxY: number }\n\n constructor(params: {\n nodeWithPortPoints: NodeWithPortPoints\n viaDiameter?: number\n traceThickness?: number\n obstacleMargin?: number\n layerCount?: number\n }) {\n super()\n\n this.nodeWithPortPoints = params.nodeWithPortPoints\n this.viaDiameter = params?.viaDiameter ?? 0.6\n this.traceThickness = params?.traceThickness ?? 0.15\n this.obstacleMargin = params?.obstacleMargin ?? 0.1\n this.layerCount = params?.layerCount ?? 2\n this.debugViaPositions = []\n\n // Extract routes from the node data\n this.routes = this.extractRoutesFromNode()\n\n // Calculate bounds\n this.bounds = this.calculateBounds()\n\n if (this.routes.length !== 2) {\n this.failed = true\n return\n }\n\n const [routeA, routeB] = this.routes\n\n // Check if one route has a layer transition and the other doesn't\n const routeAHasTransition = routeA.A.z !== routeA.B.z\n const routeBHasTransition = routeB.A.z !== routeB.B.z\n\n // We need exactly one route with a transition\n if (\n (routeAHasTransition && routeBHasTransition) ||\n (!routeAHasTransition && !routeBHasTransition)\n ) {\n this.failed = true\n return\n }\n }\n\n /**\n * Extract routes that need to be connected from the node data\n */\n private extractRoutesFromNode(): Route[] {\n const routes: Route[] = []\n const connectedPorts = this.nodeWithPortPoints.portPoints!\n\n // Group ports by connection name\n const connectionGroups = new Map<string, Point[]>()\n\n for (const connectedPort of connectedPorts) {\n const { connectionName } = connectedPort\n if (!connectionGroups.has(connectionName)) {\n connectionGroups.set(connectionName, [])\n }\n connectionGroups.get(connectionName)?.push(connectedPort)\n }\n\n // Create routes for each connection (assuming each connection has exactly 2 points)\n for (const [connectionName, points] of connectionGroups.entries()) {\n if (points.length === 2) {\n routes.push({\n A: { ...points[0], z: points[0].z ?? 0 },\n B: { ...points[1], z: points[1].z ?? 0 },\n connectionName,\n })\n }\n }\n\n return routes\n }\n\n /**\n * Calculate the bounding box of the node\n */\n private calculateBounds() {\n return {\n minX:\n this.nodeWithPortPoints.center.x - this.nodeWithPortPoints.width / 2,\n maxX:\n this.nodeWithPortPoints.center.x + this.nodeWithPortPoints.width / 2,\n minY:\n this.nodeWithPortPoints.center.y - this.nodeWithPortPoints.height / 2,\n maxY:\n this.nodeWithPortPoints.center.y + this.nodeWithPortPoints.height / 2,\n }\n }\n\n /**\n * Check if two routes are crossing\n */\n private doRoutesCross(routeA: Route, routeB: Route): boolean {\n // For this specific solver, we want to check if the 2D projections intersect\n // (ignoring z values)\n return doSegmentsIntersect(routeA.A, routeA.B, routeB.A, routeB.B)\n }\n\n private calculateViaPosition(\n transitionRoute: Route,\n flatRoute: Route,\n ): Point | null {\n const flatRouteZ = flatRoute.A.z\n const ntrP1 =\n transitionRoute.A.z !== flatRouteZ ? transitionRoute.A : transitionRoute.B\n\n // ntrP1 is always on the opposite layer as the flat route, the trace must always\n // weave between ntrP1 and the via\n // The via must also be far enough from the flat route\n const marginFromBorderWithTrace =\n this.obstacleMargin * 2 + this.viaDiameter / 2 + this.traceThickness\n const marginFromBorderWithoutTrace =\n this.obstacleMargin + this.viaDiameter / 2\n\n const A = flatRoute.A\n const B = ntrP1\n const C = flatRoute.B\n\n const sideTraversal = calculateTraversalPercentages(A, B, C, this.bounds)\n\n const viaBounds = {\n minX:\n this.bounds.minX +\n (sideTraversal.left > 0.5\n ? marginFromBorderWithTrace\n : marginFromBorderWithoutTrace),\n minY:\n this.bounds.minY +\n (sideTraversal.bottom > 0.5\n ? marginFromBorderWithTrace\n : marginFromBorderWithoutTrace),\n maxX:\n this.bounds.maxX -\n (sideTraversal.right > 0.5\n ? marginFromBorderWithTrace\n : marginFromBorderWithoutTrace),\n maxY:\n this.bounds.maxY -\n (sideTraversal.top > 0.5\n ? marginFromBorderWithTrace\n : marginFromBorderWithoutTrace),\n }\n\n if (viaBounds.maxY < viaBounds.minY) {\n viaBounds.minY = (viaBounds.minY + viaBounds.maxY) / 2\n viaBounds.maxY = viaBounds.minY\n }\n\n if (viaBounds.maxX < viaBounds.minX) {\n viaBounds.minX = (viaBounds.minX + viaBounds.maxX) / 2\n viaBounds.maxX = viaBounds.minX\n }\n\n return findClosestPointToABCWithinBounds(\n A,\n B,\n C,\n marginFromBorderWithTrace,\n viaBounds,\n )\n }\n /**\n * Create a single transition route with properly placed via\n */\n private createTransitionRoute(\n start: Point,\n end: Point,\n via: Point,\n connectionName: string,\n ): HighDensityIntraNodeRoute {\n // Create the route path with layer transition at the via\n const route = [\n { x: start.x, y: start.y, z: start.z ?? 0 },\n { x: via.x, y: via.y, z: start.z ?? 0 },\n { x: via.x, y: via.y, z: end.z ?? 0 },\n { x: end.x, y: end.y, z: end.z ?? 0 },\n ]\n\n return {\n connectionName,\n route,\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [via],\n }\n }\n\n /**\n * Create the non-transition route\n */\n private createFlatRoute(\n flatStart: Point,\n flatEnd: Point,\n via: Point,\n otherRouteStart: Point,\n otherRouteEnd: Point,\n flatRouteConnectionName: string,\n ): HighDensityIntraNodeRoute {\n const ntrP1 =\n otherRouteStart.z !== flatStart.z ? otherRouteStart : otherRouteEnd\n // We need to navigate around the via\n\n const middle = (a: Point, b: Point) => {\n return {\n x: (a.x + b.x) / 2,\n y: (a.y + b.y) / 2,\n }\n }\n\n const middleWithMargin = (\n a: Point,\n aMargin: number,\n b: Point,\n bMargin: number,\n ) => {\n const dx = b.x - a.x\n const dy = b.y - a.y\n\n const effectiveA = {\n x: a.x + dx * aMargin,\n y: a.y + dy * aMargin,\n }\n\n const effectiveB = {\n x: b.x - dx * bMargin,\n y: b.y - dy * bMargin,\n }\n\n return middle(effectiveA, effectiveB)\n }\n\n const traceBounds = {\n maxX: this.bounds.maxX - this.obstacleMargin - this.traceThickness / 2,\n maxY: this.bounds.maxY - this.obstacleMargin - this.traceThickness / 2,\n minX: this.bounds.minX + this.obstacleMargin + this.traceThickness / 2,\n minY: this.bounds.minY + this.obstacleMargin + this.traceThickness / 2,\n }\n\n const minDistFromViaToTrace =\n this.viaDiameter / 2 + this.traceThickness / 2 + this.obstacleMargin\n const p2 = middleWithMargin(\n via,\n this.viaDiameter,\n otherRouteStart.z !== flatStart.z ? otherRouteStart : otherRouteEnd,\n this.traceThickness,\n )\n const p1 = findPointToGetAroundCircle(flatStart, p2, {\n center: { x: via.x, y: via.y },\n radius: minDistFromViaToTrace,\n }).E\n const p3 = findPointToGetAroundCircle(p2, flatEnd, {\n center: { x: via.x, y: via.y },\n radius: minDistFromViaToTrace,\n }).E\n\n // Determine if we need p1 or if we can just go from flatStart to p2 without\n // intersecting the via\n const p1IsNeeded =\n pointToSegmentDistance(via, flatStart, p2) < minDistFromViaToTrace\n const p3IsNeeded =\n pointToSegmentDistance(via, p2, flatEnd) < minDistFromViaToTrace\n\n // We need to navigate around the via\n return {\n connectionName: flatRouteConnectionName,\n route: [\n { x: flatStart.x, y: flatStart.y, z: flatStart.z ?? 0 },\n ...(p1IsNeeded ? [{ x: p1.x, y: p1.y, z: flatStart.z ?? 0 }] : []),\n { x: p2.x, y: p2.y, z: flatStart.z ?? 0 },\n ...(p3IsNeeded ? [{ x: p3.x, y: p3.y, z: flatStart.z ?? 0 }] : []),\n { x: flatEnd.x, y: flatEnd.y, z: flatEnd.z ?? 0 },\n ],\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [],\n }\n }\n\n /**\n * Try to solve with one route having a transition and the other staying flat\n */\n private trySolve(): boolean {\n const [routeA, routeB] = this.routes\n\n // Determine which route has the transition\n const routeAHasTransition = routeA.A.z !== routeA.B.z\n\n const transitionRoute = routeAHasTransition ? routeA : routeB\n const flatRoute = routeAHasTransition ? routeB : routeA\n\n const viaPosition = this.calculateViaPosition(transitionRoute, flatRoute)\n if (viaPosition) {\n this.debugViaPositions.push({ via: viaPosition })\n } else {\n return false\n }\n\n // Create transition route with via\n const transitionRouteSolution = this.createTransitionRoute(\n transitionRoute.A,\n transitionRoute.B,\n viaPosition,\n transitionRoute.connectionName,\n )\n\n // Create flat route\n const flatRouteSolution = this.createFlatRoute(\n flatRoute.A,\n flatRoute.B,\n viaPosition,\n transitionRoute.A,\n transitionRoute.B,\n flatRoute.connectionName,\n )\n\n this.solvedRoutes.push(transitionRouteSolution, flatRouteSolution)\n return true\n }\n\n /**\n * Main step method that attempts to solve the routes\n */\n _step() {\n // Check if routes are actually crossing\n if (!this.doRoutesCross(this.routes[0], this.routes[1])) {\n this.failed = true\n this.error =\n \"Can only solve routes that have a single transition crossing\"\n return\n }\n\n // Try to solve\n if (this.trySolve()) {\n this.solved = true\n return\n }\n\n // If approach fails, mark as failed\n this.failed = true\n }\n\n /**\n * Visualization for debugging\n */\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n\n // Draw PCB bounds\n graphics.rects!.push({\n center: {\n x: (this.bounds.minX + this.bounds.maxX) / 2,\n y: (this.bounds.minY + this.bounds.maxY) / 2,\n },\n width: this.bounds.maxX - this.bounds.minX,\n height: this.bounds.maxY - this.bounds.minY,\n stroke: \"rgba(0, 0, 0, 0.5)\",\n fill: \"rgba(240, 240, 240, 0.1)\",\n label: \"PCB Bounds\",\n })\n\n // Draw original routes\n for (const route of this.routes) {\n // Draw endpoints\n graphics.points!.push({\n x: route.A.x,\n y: route.A.y,\n label: `${route.connectionName} start (z=${route.A.z})`,\n color: \"orange\",\n })\n\n graphics.points!.push({\n x: route.B.x,\n y: route.B.y,\n label: `${route.connectionName} end (z=${route.B.z})`,\n color: \"orange\",\n })\n\n // Draw direct connection line\n graphics.lines!.push({\n points: [route.A, route.B],\n strokeColor: \"rgba(255, 0, 0, 0.5)\",\n label: `${route.connectionName} direct`,\n })\n }\n\n // Draw debug via positions (even if solution failed)\n for (let i = 0; i < this.debugViaPositions.length; i++) {\n const { via } = this.debugViaPositions[i]\n\n // Draw computed via\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2,\n fill: \"rgba(255, 165, 0, 0.7)\",\n stroke: \"rgba(0, 0, 0, 0.5)\",\n label: `Computed Via (attempt ${i + 1})`,\n })\n\n // Draw safety margin around via\n const safetyMargin = this.viaDiameter / 2 + this.obstacleMargin\n graphics.circles!.push({\n center: via,\n radius: safetyMargin,\n stroke: \"rgba(255, 165, 0, 0.7)\",\n fill: \"rgba(0, 0, 0, 0)\",\n label: \"Safety Margin\",\n })\n }\n\n // Draw solved routes if available\n for (let si = 0; si < this.solvedRoutes.length; si++) {\n const route = this.solvedRoutes[si]\n const routeColor =\n si % 2 === 0 ? \"rgba(0, 255, 0, 0.75)\" : \"rgba(255, 0, 255, 0.75)\"\n for (let i = 0; i < route.route.length - 1; i++) {\n const pointA = route.route[i]\n const pointB = route.route[i + 1]\n\n graphics.lines!.push({\n points: [pointA, pointB],\n strokeColor: routeColor,\n strokeDash: pointA.z !== route.route[0].z ? [0.2, 0.2] : undefined,\n strokeWidth: route.traceThickness,\n label: `${route.connectionName} z=${pointA.z}`,\n })\n }\n\n // Draw vias in solved routes\n for (const via of route.vias) {\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2,\n fill: \"rgba(0, 0, 255, 0.8)\",\n stroke: \"black\",\n label: \"Solved Via\",\n })\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2 + this.obstacleMargin,\n fill: \"rgba(0, 0, 255, 0.3)\",\n stroke: \"black\",\n label: \"Via Margin\",\n })\n }\n }\n\n return graphics\n }\n\n /**\n * Get the solved routes\n */\n getSolvedRoutes(): HighDensityIntraNodeRoute[] {\n return this.solvedRoutes\n }\n}\n","import {\n HighDensityIntraNodeRoute,\n NodeWithPortPoints,\n} from \"lib/types/high-density-types\"\nimport { IntraNodeRouteSolver } from \"../HighDensitySolver/IntraNodeSolver\"\nimport {\n HyperParameterSupervisorSolver,\n SupervisedSolver,\n} from \"../HyperParameterSupervisorSolver\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport { TwoCrossingRoutesHighDensitySolver } from \"../HighDensitySolver/TwoRouteHighDensitySolver/TwoCrossingRoutesHighDensitySolver\"\nimport { SingleTransitionCrossingRouteSolver } from \"../HighDensitySolver/TwoRouteHighDensitySolver/SingleTransitionCrossingRouteSolver\"\n\nexport class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver<\n IntraNodeRouteSolver | TwoCrossingRoutesHighDensitySolver\n> {\n constructorParams: ConstructorParameters<typeof IntraNodeRouteSolver>[0]\n solvedRoutes: HighDensityIntraNodeRoute[] = []\n nodeWithPortPoints: NodeWithPortPoints\n\n constructor(opts: ConstructorParameters<typeof IntraNodeRouteSolver>[0]) {\n super()\n this.nodeWithPortPoints = opts.nodeWithPortPoints\n this.constructorParams = opts\n this.MAX_ITERATIONS = 250_000\n this.GREEDY_MULTIPLIER = 5\n this.MIN_SUBSTEPS = 100\n }\n\n getCombinationDefs() {\n return [\n [\"closedFormTwoTrace\"],\n [\"majorCombinations\", \"orderings6\", \"cellSizeFactor\"],\n [\"noVias\"],\n [\"orderings50\"],\n [\"flipTraceAlignmentDirection\", \"orderings6\"],\n ]\n }\n\n getHyperParameterDefs() {\n return [\n {\n name: \"majorCombinations\",\n possibleValues: [\n {\n FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: 2,\n FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: 1,\n FUTURE_CONNECTION_PROXIMITY_VD: 10,\n MISALIGNED_DIST_PENALTY_FACTOR: 5,\n },\n {\n FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: 1,\n FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: 0.5,\n FUTURE_CONNECTION_PROXIMITY_VD: 5,\n MISALIGNED_DIST_PENALTY_FACTOR: 2,\n },\n {\n FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: 10,\n FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: 1,\n FUTURE_CONNECTION_PROXIMITY_VD: 5,\n MISALIGNED_DIST_PENALTY_FACTOR: 10,\n VIA_PENALTY_FACTOR_2: 1,\n },\n ],\n },\n {\n name: \"orderings6\",\n possibleValues: [\n {\n SHUFFLE_SEED: 0,\n },\n {\n SHUFFLE_SEED: 1,\n },\n {\n SHUFFLE_SEED: 2,\n },\n {\n SHUFFLE_SEED: 3,\n },\n {\n SHUFFLE_SEED: 4,\n },\n {\n SHUFFLE_SEED: 5,\n },\n ],\n },\n {\n name: \"cellSizeFactor\",\n possibleValues: [\n {\n CELL_SIZE_FACTOR: 0.5,\n },\n {\n CELL_SIZE_FACTOR: 1,\n },\n ],\n },\n {\n name: \"flipTraceAlignmentDirection\",\n possibleValues: [\n {\n FLIP_TRACE_ALIGNMENT_DIRECTION: true,\n },\n ],\n },\n {\n name: \"noVias\",\n possibleValues: [\n {\n CELL_SIZE_FACTOR: 2,\n VIA_PENALTY_FACTOR_2: 10,\n },\n ],\n },\n {\n name: \"orderings50\",\n possibleValues: Array.from({ length: 50 }, (_, i) => ({\n SHUFFLE_SEED: 100 + i,\n })),\n },\n {\n name: \"closedFormTwoTrace\",\n possibleValues: [\n {\n CLOSED_FORM_TWO_TRACE_SAME_LAYER: true,\n },\n {\n CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING: true,\n },\n ],\n },\n ]\n }\n\n computeG(solver: IntraNodeRouteSolver) {\n return (\n solver.iterations / 10_000 // + solver.hyperParameters.SHUFFLE_SEED! * 0.05\n )\n }\n\n computeH(solver: IntraNodeRouteSolver) {\n return 1 - (solver.progress || 0)\n }\n\n generateSolver(hyperParameters: any): IntraNodeRouteSolver {\n if (hyperParameters.CLOSED_FORM_TWO_TRACE_SAME_LAYER) {\n return new TwoCrossingRoutesHighDensitySolver({\n nodeWithPortPoints: this.nodeWithPortPoints,\n }) as any\n }\n if (hyperParameters.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING) {\n return new SingleTransitionCrossingRouteSolver({\n nodeWithPortPoints: this.nodeWithPortPoints,\n }) as any\n }\n return new IntraNodeRouteSolver({\n ...this.constructorParams,\n hyperParameters,\n })\n }\n\n onSolve(solver: SupervisedSolver<IntraNodeRouteSolver>) {\n this.solvedRoutes = solver.solver.solvedRoutes\n }\n}\n","interface RoutePoint {\n x: number\n y: number\n z: number\n}\n\ninterface MergedSegment {\n points: { x: number; y: number }[]\n z: number\n connectionName: string\n color: string\n}\n\n/**\n * Merges consecutive route points with the same z-coordinate into segments\n * @param route Array of route points\n * @param connectionName Name of the connection\n * @param color Color for the segment\n * @returns Array of merged segments\n */\nexport function mergeRouteSegments(\n route: RoutePoint[],\n connectionName: string,\n color: string,\n): MergedSegment[] {\n const segments: MergedSegment[] = []\n let currentSegment: MergedSegment | null = null\n\n for (let i = 0; i < route.length; i++) {\n const point = route[i]\n\n if (!currentSegment) {\n currentSegment = {\n points: [{ x: point.x, y: point.y }],\n z: point.z,\n connectionName,\n color,\n }\n } else if (currentSegment.z === point.z) {\n currentSegment.points.push({ x: point.x, y: point.y })\n } else {\n segments.push(currentSegment)\n currentSegment = {\n points: [{ x: point.x, y: point.y }],\n z: point.z,\n connectionName,\n color,\n }\n }\n\n // Add final segment if we're at the last point\n if (i === route.length - 1 && currentSegment) {\n segments.push(currentSegment)\n }\n }\n\n return segments\n}\n","import type {\n HighDensityIntraNodeRoute,\n NodeWithPortPoints,\n} from \"../../types/high-density-types\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { safeTransparentize } from \"../colors\"\nimport { IntraNodeRouteSolver } from \"./IntraNodeSolver\"\nimport { HyperSingleIntraNodeSolver } from \"../HyperHighDensitySolver/HyperSingleIntraNodeSolver\"\nimport { combineVisualizations } from \"lib/utils/combineVisualizations\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport { mergeRouteSegments } from \"lib/utils/mergeRouteSegments\"\n\nexport class HighDensitySolver extends BaseSolver {\n unsolvedNodePortPoints: NodeWithPortPoints[]\n routes: HighDensityIntraNodeRoute[]\n colorMap: Record<string, string>\n\n // Defaults as specified: viaDiameter of 0.6 and traceThickness of 0.15\n readonly defaultViaDiameter = 0.6\n readonly defaultTraceThickness = 0.15\n\n failedSolvers: (IntraNodeRouteSolver | HyperSingleIntraNodeSolver)[]\n activeSubSolver: IntraNodeRouteSolver | HyperSingleIntraNodeSolver | null =\n null\n connMap?: ConnectivityMap\n\n constructor({\n nodePortPoints,\n colorMap,\n connMap,\n }: {\n nodePortPoints: NodeWithPortPoints[]\n colorMap?: Record<string, string>\n connMap?: ConnectivityMap\n }) {\n super()\n this.unsolvedNodePortPoints = nodePortPoints\n this.colorMap = colorMap ?? {}\n this.connMap = connMap\n this.routes = []\n this.failedSolvers = []\n this.MAX_ITERATIONS = 1e6\n }\n\n /**\n * Each iteration, pop an unsolved node and attempt to find the routes inside\n * of it.\n */\n _step() {\n if (this.activeSubSolver) {\n this.activeSubSolver.step()\n if (this.activeSubSolver.solved) {\n this.routes.push(...this.activeSubSolver.solvedRoutes)\n this.activeSubSolver = null\n } else if (this.activeSubSolver.failed) {\n this.failedSolvers.push(this.activeSubSolver)\n this.activeSubSolver = null\n }\n return\n }\n if (this.unsolvedNodePortPoints.length === 0) {\n this.solved = true\n return\n }\n const node = this.unsolvedNodePortPoints.pop()!\n\n this.activeSubSolver = new HyperSingleIntraNodeSolver({\n nodeWithPortPoints: node,\n colorMap: this.colorMap,\n connMap: this.connMap,\n })\n }\n\n visualize(): GraphicsObject {\n let graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n for (const route of this.routes) {\n // Merge segments based on z-coordinate\n const mergedSegments = mergeRouteSegments(\n route.route,\n route.connectionName,\n this.colorMap[route.connectionName],\n )\n\n // Add merged segments to graphics\n for (const segment of mergedSegments) {\n graphics.lines!.push({\n points: segment.points,\n label: segment.connectionName,\n strokeColor:\n segment.z === 0\n ? segment.color\n : safeTransparentize(segment.color, 0.75),\n strokeWidth: route.traceThickness,\n strokeDash: segment.z !== 0 ? \"10, 5\" : undefined,\n })\n }\n for (const via of route.vias) {\n graphics.circles!.push({\n center: via,\n radius: route.viaDiameter / 2,\n fill: this.colorMap[route.connectionName],\n label: `${route.connectionName} via`,\n })\n }\n }\n for (const solver of this.failedSolvers) {\n const node = solver.nodeWithPortPoints\n // Group port points by connectionName\n const connectionGroups: Record<\n string,\n { x: number; y: number; z: number }[]\n > = {}\n for (const pt of node.portPoints) {\n if (!connectionGroups[pt.connectionName]) {\n connectionGroups[pt.connectionName] = []\n }\n connectionGroups[pt.connectionName].push({ x: pt.x, y: pt.y, z: pt.z })\n }\n\n for (const [connectionName, points] of Object.entries(connectionGroups)) {\n for (let i = 0; i < points.length - 1; i++) {\n const start = points[i]\n const end = points[i + 1]\n graphics.lines!.push({\n points: [start, end],\n strokeColor: \"red\",\n strokeDash: \"10, 5\",\n })\n }\n }\n }\n if (this.activeSubSolver) {\n graphics = combineVisualizations(\n graphics,\n this.activeSubSolver.visualize(),\n )\n }\n return graphics\n }\n}\n","type NodeId = string\n\nexport function findConnectedNetworks(\n connections: Array<NodeId[]>,\n): Record<string, string[]> {\n const networks: Map<string, Set<string>> = new Map()\n let netCounter = 0\n\n function getOrCreateNetwork(nodeId: string): Set<string> {\n for (const [, network] of networks) {\n if (network.has(nodeId)) {\n return network\n }\n }\n const newNetwork = new Set<string>()\n networks.set(`connectivity_net${netCounter++}`, newNetwork)\n return newNetwork\n }\n\n for (const connection of connections) {\n let network: Set<string> | null = null\n\n for (const nodeId of connection) {\n if (!network) {\n network = getOrCreateNetwork(nodeId)\n } else if (!network.has(nodeId)) {\n const existingNetwork = getOrCreateNetwork(nodeId)\n if (existingNetwork !== network) {\n // Merge networks\n for (const node of existingNetwork) {\n network.add(node)\n }\n networks.delete(\n Array.from(networks.entries()).find(\n ([, net]) => net === existingNetwork,\n )![0],\n )\n }\n }\n network.add(nodeId)\n }\n }\n\n return Object.fromEntries(\n Array.from(networks.entries()).map(([netId, connectedNodes]) => [\n netId,\n Array.from(connectedNodes),\n ]),\n )\n}\n","export class ConnectivityMap {\n netMap: Record<string, string[]>\n\n idToNetMap: Record<string, string>\n\n constructor(netMap: Record<string, string[]>) {\n this.netMap = netMap\n this.idToNetMap = {}\n for (const [netId, ids] of Object.entries(netMap)) {\n for (const id of ids) {\n this.idToNetMap[id] = netId\n }\n }\n }\n\n addConnections(connections: string[][]) {\n for (const connection of connections) {\n const existingNets = new Set<string>()\n\n // Find all existing nets for the connection\n for (const id of connection) {\n const existingNetId = this.idToNetMap[id]\n if (existingNetId) {\n existingNets.add(existingNetId)\n }\n }\n\n let targetNetId: string\n\n if (existingNets.size === 0) {\n // If no existing nets found, create a new one\n targetNetId = `connectivity_net${Object.keys(this.netMap).length}`\n this.netMap[targetNetId] = []\n } else if (existingNets.size === 1) {\n // If only one existing net found, use it\n targetNetId =\n existingNets.values().next().value ??\n `connectivity_net${Object.keys(this.netMap).length}`\n } else {\n // If multiple nets found, merge them\n targetNetId =\n existingNets.values().next().value ??\n `connectivity_net${Object.keys(this.netMap).length}`\n for (const netId of existingNets) {\n if (netId !== targetNetId) {\n this.netMap[targetNetId].push(...this.netMap[netId])\n\n // we could delete the net, but setting it to reference the other net\n // will make sure any usage of the old netId will still work\n this.netMap[netId] = this.netMap[targetNetId]\n for (const id of this.netMap[targetNetId]) {\n this.idToNetMap[id] = targetNetId\n }\n }\n }\n }\n\n // Add all ids to the target net\n for (const id of connection) {\n if (!this.netMap[targetNetId].includes(id)) {\n this.netMap[targetNetId].push(id)\n }\n this.idToNetMap[id] = targetNetId\n }\n }\n }\n\n getIdsConnectedToNet(netId: string): string[] {\n return this.netMap[netId] || []\n }\n\n getNetConnectedToId(id: string): string | undefined {\n return this.idToNetMap[id]\n }\n\n areIdsConnected(id1: string, id2: string): boolean {\n if (id1 === id2) return true\n const netId1 = this.getNetConnectedToId(id1)\n if (!netId1) return false\n const netId2 = this.getNetConnectedToId(id2)\n if (!netId2) return false\n return netId1 === netId2 || netId2 === id1 || netId2 === id1\n }\n\n areAllIdsConnected(ids: string[]): boolean {\n const netId = this.getNetConnectedToId(ids[0])\n for (const id of ids) {\n const nextNetId = this.getNetConnectedToId(id)\n if (nextNetId === undefined) {\n return false\n }\n if (nextNetId !== netId) {\n return false\n }\n }\n return true\n }\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getSourcePortConnectivityMapFromCircuitJson = (\n circuitJson: AnyCircuitElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push([\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ])\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getFullConnectivityMapFromCircuitJson = (\n circuitJson: AnyCircuitElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push(\n [\n element.source_trace_id,\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ].filter(Boolean),\n )\n } else if (element.type === \"pcb_port\") {\n const { pcb_port_id, source_port_id } = element\n if (source_port_id && pcb_port_id) {\n connections.push([source_port_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_smtpad\") {\n const { pcb_smtpad_id, pcb_port_id } = element\n if (pcb_port_id && pcb_smtpad_id) {\n connections.push([pcb_smtpad_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_plated_hole\") {\n const { pcb_plated_hole_id, pcb_port_id } = element\n if (pcb_port_id && pcb_plated_hole_id) {\n connections.push([pcb_plated_hole_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_trace\") {\n const { pcb_trace_id, source_trace_id } = element\n if (source_trace_id && pcb_trace_id) {\n connections.push([pcb_trace_id, source_trace_id])\n }\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnyCircuitElement, PCBPort, PCBTrace } from \"circuit-json\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\nimport { doesLineIntersectLine } from \"@tscircuit/math-utils\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\n\n/**\n * A PCB Connectivity Map is a connectivity map that has analyzed what traces and ports are actually connected on the\n * PCB.\n *\n * This is useful for determining how to route a trace on the PCB. For example, you may want to determine where the\n * nearest connected net point is to connect an unrouted pin.\n */\nexport class PcbConnectivityMap {\n circuitJson: AnyCircuitElement[]\n traceIdToElm: Map<string, PCBTrace>\n portIdToElm: Map<string, PCBPort>\n connMap: ConnectivityMap\n\n constructor(circuitJson?: AnyCircuitElement[]) {\n this.circuitJson = circuitJson || []\n this.traceIdToElm = new Map()\n this.portIdToElm = new Map()\n if (circuitJson) {\n this._buildTraceMap()\n this._buildPortMap()\n this.connMap = this._buildTraceConnectivityMap()\n } else {\n this.connMap = new ConnectivityMap({})\n }\n }\n\n private _buildPortMap() {\n for (const element of this.circuitJson) {\n if (element.type === \"pcb_port\") {\n this.portIdToElm.set(element.pcb_port_id, element as PCBPort)\n }\n }\n }\n\n private _buildTraceMap() {\n for (const element of this.circuitJson) {\n if (element.type === \"pcb_trace\") {\n this.traceIdToElm.set(element.pcb_trace_id, element as PCBTrace)\n }\n }\n }\n\n private _buildTraceConnectivityMap(): ConnectivityMap {\n const connections: string[][] = []\n const traceIds = Array.from(this.traceIdToElm.keys())\n\n for (let i = 0; i < traceIds.length; i++) {\n for (let j = i + 1; j < traceIds.length; j++) {\n const trace1 = this.traceIdToElm.get(traceIds[i])!\n const trace2 = this.traceIdToElm.get(traceIds[j])!\n if (this._arePcbTracesConnected(trace1, trace2)) {\n connections.push([traceIds[i], traceIds[j]])\n }\n }\n }\n\n for (const port of this.portIdToElm.values()) {\n for (const trace of this.traceIdToElm.values()) {\n for (const rp of trace.route) {\n if (rp.route_type === \"wire\") {\n if (rp.start_pcb_port_id === port.pcb_port_id) {\n connections.push([port.pcb_port_id, trace.pcb_trace_id])\n } else if (rp.end_pcb_port_id === port.pcb_port_id) {\n connections.push([trace.pcb_trace_id, port.pcb_port_id])\n }\n }\n }\n }\n }\n\n return new ConnectivityMap(findConnectedNetworks(connections))\n }\n\n addTrace(trace: PCBTrace) {\n this.traceIdToElm.set(trace.pcb_trace_id, trace)\n const connections: string[][] = []\n for (const rp of trace.route) {\n if (rp.route_type === \"wire\") {\n if (rp.start_pcb_port_id) {\n connections.push([rp.start_pcb_port_id, trace.pcb_trace_id])\n }\n if (rp.end_pcb_port_id) {\n connections.push([rp.end_pcb_port_id, trace.pcb_trace_id])\n }\n }\n }\n\n this.connMap.addConnections(connections)\n }\n\n _arePcbTracesConnected(trace1: PCBTrace, trace2: PCBTrace): boolean {\n for (let i = 0; i < trace1.route.length - 1; i++) {\n const segment1A = trace1.route[i]\n const segment1B = trace1.route[i + 1]\n if (segment1A.route_type !== \"wire\") continue\n if (segment1B.route_type !== \"wire\") continue\n for (let j = 0; j < trace2.route.length - 1; j++) {\n const segment2A = trace2.route[j]\n const segment2B = trace2.route[j + 1]\n\n if (segment2A.route_type !== \"wire\") continue\n if (segment2B.route_type !== \"wire\") continue\n\n // Check if lines are overlapping\n const isOverlapping = doesLineIntersectLine(\n [segment1A, segment1B],\n [segment2A, segment2B],\n {\n lineThickness: (segment1A.width + segment2A.width) / 2,\n },\n )\n if (isOverlapping) {\n return true\n }\n }\n }\n return false\n }\n\n areTracesConnected(traceId1: string, traceId2: string): boolean {\n return this.connMap.areIdsConnected(traceId1, traceId2)\n }\n\n getAllTracesConnectedToTrace(traceId: string): PCBTrace[] {\n const netId = this.connMap.getNetConnectedToId(traceId)\n return netId\n ? this.connMap\n .getIdsConnectedToNet(netId)\n .filter((id) => this.traceIdToElm.has(id))\n .map((id) => this.traceIdToElm.get(id) as PCBTrace)\n : []\n }\n\n getAllTracesConnectedToPort(portId: string): PCBTrace[] {\n const netId = this.connMap.getNetConnectedToId(portId)\n return netId\n ? this.connMap\n .getIdsConnectedToNet(netId)\n .filter((id) => this.traceIdToElm.has(id))\n .map((id) => this.traceIdToElm.get(id) as PCBTrace)\n : []\n }\n}\n","import { SimpleRouteJson } from \"lib/types\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\n\nexport const getConnectivityMapFromSimpleRouteJson = (srj: SimpleRouteJson) => {\n const connMap = new ConnectivityMap({})\n for (const connection of srj.connections) {\n for (const point of connection.pointsToConnect) {\n if (\"pcb_port_id\" in point && point.pcb_port_id) {\n connMap.addConnections([[connection.name, point.pcb_port_id as string]])\n }\n }\n }\n for (const obstacle of srj.obstacles) {\n connMap.addConnections([obstacle.connectedTo])\n }\n return connMap\n}\n","type Point = { x: number; y: number }\n\nexport class KDNode {\n point: Point\n left: KDNode | null = null\n right: KDNode | null = null\n\n constructor(point: Point) {\n this.point = point\n }\n}\n\nclass KDTree {\n root: KDNode | null = null\n\n constructor(points: Point[]) {\n if (points.length > 0) {\n this.root = this.buildTree(points, 0)\n }\n }\n\n private buildTree(points: Point[], depth: number): KDNode {\n const axis = depth % 2 === 0 ? \"x\" : \"y\"\n\n // Sort points by the current axis\n points.sort((a, b) => a[axis] - b[axis])\n\n // Choose median as the pivot element\n const medianIndex = Math.floor(points.length / 2)\n const node = new KDNode(points[medianIndex])\n\n // Recursively build left and right subtrees\n if (medianIndex > 0) {\n node.left = this.buildTree(points.slice(0, medianIndex), depth + 1)\n }\n\n if (medianIndex < points.length - 1) {\n node.right = this.buildTree(points.slice(medianIndex + 1), depth + 1)\n }\n\n return node\n }\n\n // Find the nearest neighbor to a query point\n findNearestNeighbor(queryPoint: Point): Point {\n if (!this.root) {\n throw new Error(\"Tree is empty\")\n }\n\n const best: Point = this.root.point\n const bestDistance = this.distance(queryPoint, best)\n\n this.nearestNeighborSearch(this.root, queryPoint, 0, best, bestDistance)\n\n return best\n }\n\n private nearestNeighborSearch(\n node: KDNode | null,\n queryPoint: Point,\n depth: number,\n best: Point,\n bestDistance: number,\n ): Point {\n if (!node) {\n return best\n }\n\n const axis = depth % 2 ? \"x\" : \"y\"\n const currentDistance = this.distance(queryPoint, node.point)\n\n if (currentDistance < bestDistance) {\n best = node.point\n bestDistance = currentDistance\n }\n\n // Determine which subtree to search first\n const axisDiff = queryPoint[axis] - node.point[axis]\n const firstBranch = axisDiff <= 0 ? node.left : node.right\n const secondBranch = axisDiff <= 0 ? node.right : node.left\n\n // Recursively search the first branch\n best = this.nearestNeighborSearch(\n firstBranch,\n queryPoint,\n depth + 1,\n best,\n bestDistance,\n )\n bestDistance = this.distance(queryPoint, best)\n\n // Check if we need to search the second branch\n if (Math.abs(axisDiff) < bestDistance) {\n best = this.nearestNeighborSearch(\n secondBranch,\n queryPoint,\n depth + 1,\n best,\n bestDistance,\n )\n }\n\n return best\n }\n\n // Find k nearest neighbors\n findKNearestNeighbors(queryPoint: Point, k: number): Point[] {\n if (!this.root) {\n return []\n }\n\n const neighbors: Array<{ point: Point; distance: number }> = []\n\n this.kNearestNeighborSearch(this.root, queryPoint, 0, neighbors, k)\n\n return neighbors\n .sort((a, b) => a.distance - b.distance)\n .slice(0, k)\n .map((n) => n.point)\n }\n\n private kNearestNeighborSearch(\n node: KDNode | null,\n queryPoint: Point,\n depth: number,\n neighbors: Array<{ point: Point; distance: number }>,\n k: number,\n ): void {\n if (!node) {\n return\n }\n\n const axis = depth % 2 ? \"x\" : \"y\"\n const currentDistance = this.distance(queryPoint, node.point)\n\n // Add current node to neighbors\n neighbors.push({ point: node.point, distance: currentDistance })\n\n // Determine which subtree to search first\n const axisDiff = queryPoint[axis] - node.point[axis]\n const firstBranch = axisDiff <= 0 ? node.left : node.right\n const secondBranch = axisDiff <= 0 ? node.right : node.left\n\n // Recursively search the first branch\n this.kNearestNeighborSearch(\n firstBranch,\n queryPoint,\n depth + 1,\n neighbors,\n k,\n )\n\n // Get the kth distance if we have k neighbors\n let kthDistance = Infinity\n if (neighbors.length >= k) {\n neighbors.sort((a, b) => a.distance - b.distance)\n kthDistance = neighbors[k - 1]?.distance || Infinity\n }\n\n // Search the other branch if necessary\n if (Math.abs(axisDiff) < kthDistance || neighbors.length < k) {\n this.kNearestNeighborSearch(\n secondBranch,\n queryPoint,\n depth + 1,\n neighbors,\n k,\n )\n }\n }\n\n // Calculate Euclidean distance between two points\n private distance(a: Point, b: Point): number {\n return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2)\n }\n}\n\n// Disjoint Set (Union-Find) data structure for Kruskal's algorithm\nexport class DisjointSet {\n private parent: Map<string, string> = new Map()\n private rank: Map<string, number> = new Map()\n\n constructor(points: Point[]) {\n // Initialize each point as a separate set\n for (const point of points) {\n const key = this.pointToKey(point)\n this.parent.set(key, key)\n this.rank.set(key, 0)\n }\n }\n\n private pointToKey(point: Point): string {\n return `${point.x},${point.y}`\n }\n\n find(point: Point): string {\n const key = this.pointToKey(point)\n if (!this.parent.has(key)) {\n throw new Error(`Point ${key} not found in DisjointSet`)\n }\n\n let root = key\n while (root !== this.parent.get(root)) {\n root = this.parent.get(root)!\n }\n\n // Path compression\n let current = key\n while (current !== root) {\n const next = this.parent.get(current)!\n this.parent.set(current, root)\n current = next\n }\n\n return root\n }\n\n union(pointA: Point, pointB: Point): boolean {\n const rootA = this.find(pointA)\n const rootB = this.find(pointB)\n\n if (rootA === rootB) {\n return false // Already in the same set\n }\n\n // Union by rank\n const rankA = this.rank.get(rootA) || 0\n const rankB = this.rank.get(rootB) || 0\n\n if (rankA < rankB) {\n this.parent.set(rootA, rootB)\n } else if (rankA > rankB) {\n this.parent.set(rootB, rootA)\n } else {\n this.parent.set(rootB, rootA)\n this.rank.set(rootA, rankA + 1)\n }\n\n return true\n }\n}\n\n// Edge representation for Kruskal's algorithm\ninterface Edge<T extends Point> {\n from: T\n to: T\n weight: number\n}\n\n// Main function to build a minimum spanning tree using Kruskal's algorithm\nexport function buildMinimumSpanningTree<T extends Point>(\n points: T[],\n): Edge<T>[] {\n if (points.length <= 1) {\n return []\n }\n\n // Build KD-Tree for efficient nearest neighbor search\n const kdTree = new KDTree(points)\n\n // Generate edges with k-nearest neighbors for each point\n // This is an optimization to avoid generating all possible n(n-1)/2 edges\n const edges: Edge<T>[] = []\n const k = Math.min(10, points.length - 1) // Consider k nearest neighbors\n\n for (const point of points) {\n const neighbors = kdTree.findKNearestNeighbors(point, k + 1) // +1 because it includes the point itself\n\n for (const neighbor of neighbors) {\n // Skip self\n if (point.x === neighbor.x && point.y === neighbor.y) {\n continue\n }\n\n const distance = Math.sqrt(\n (point.x - neighbor.x) ** 2 + (point.y - neighbor.y) ** 2,\n )\n\n edges.push({\n from: point,\n to: neighbor as T,\n weight: distance,\n })\n }\n }\n\n // Sort edges by weight (distance)\n edges.sort((a, b) => a.weight - b.weight)\n\n // Apply Kruskal's algorithm\n const disjointSet = new DisjointSet(points)\n const mstEdges: Edge<T>[] = []\n\n for (const edge of edges) {\n if (disjointSet.union(edge.from, edge.to)) {\n mstEdges.push(edge)\n\n // MST has n-1 edges for n points\n if (mstEdges.length === points.length - 1) {\n break\n }\n }\n }\n\n return mstEdges\n}\n","import { SimpleRouteConnection, SimpleRouteJson } from \"lib/types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { buildMinimumSpanningTree } from \"./buildMinimumSpanningTree\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { seededRandom } from \"lib/utils/cloneAndShuffleArray\"\n\n/**\n * Converts a net containing many points to connect into an array of point pair\n * connections.\n *\n * For example, a connection with 3 pointsToConnect could be turned into 2\n * connections of 2 points each.\n *\n * Where we create the minimum number of pairs, we're using a minimum spanning\n * tree (MST).\n *\n * Sometimes it can be used to add additional traces to help make sure we\n * distribute load effectively. In this version we don't do that!\n */\nexport class NetToPointPairsSolver extends BaseSolver {\n unprocessedConnections: Array<SimpleRouteConnection>\n newConnections: Array<SimpleRouteConnection>\n\n constructor(\n public ogSrj: SimpleRouteJson,\n public colorMap: Record<string, string> = {},\n ) {\n super()\n this.unprocessedConnections = [...ogSrj.connections]\n this.newConnections = []\n }\n\n _step() {\n if (this.unprocessedConnections.length === 0) {\n this.solved = true\n return\n }\n const connection = this.unprocessedConnections.pop()!\n if (connection.pointsToConnect.length === 2) {\n this.newConnections.push(connection)\n return\n }\n\n const edges = buildMinimumSpanningTree(connection.pointsToConnect)\n\n for (let i = 0; i < edges.length; i++) {\n const edge = edges[i]\n this.newConnections.push({\n pointsToConnect: [edge.from, edge.to],\n name: `${connection.name}_mst${i}`,\n })\n }\n }\n\n getNewSimpleRouteJson(): SimpleRouteJson {\n return {\n ...this.ogSrj,\n connections: this.newConnections,\n }\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Net To Point Pairs Visualization\",\n }\n\n // Draw unprocessed connections in red\n this.unprocessedConnections.forEach((connection) => {\n // Draw points\n connection.pointsToConnect.forEach((point) => {\n graphics.points!.push({\n x: point.x,\n y: point.y,\n color: \"red\",\n label: connection.name,\n })\n })\n\n // Draw lines connecting all points in the connection\n const fullyConnectedEdgeCount = connection.pointsToConnect.length ** 2\n const random = seededRandom(0)\n const alreadyPlacedEdges = new Set<string>()\n for (\n let i = 0;\n i <\n Math.max(\n fullyConnectedEdgeCount,\n connection.pointsToConnect.length * 2,\n );\n i++\n ) {\n const a = Math.floor(random() * connection.pointsToConnect.length)\n const b = Math.floor(random() * connection.pointsToConnect.length)\n if (alreadyPlacedEdges.has(`${a}-${b}`)) continue\n alreadyPlacedEdges.add(`${a}-${b}`)\n graphics.lines!.push({\n points: [\n connection.pointsToConnect[a],\n connection.pointsToConnect[b],\n ],\n strokeColor: \"rgba(255,0,0,0.25)\",\n })\n }\n })\n\n // Draw processed connections with appropriate colors\n this.newConnections.forEach((connection) => {\n const color = this.colorMap?.[connection.name] || \"blue\"\n\n // Draw points\n connection.pointsToConnect.forEach((point) => {\n graphics.points!.push({\n x: point.x,\n y: point.y,\n color: color,\n label: connection.name,\n })\n })\n\n // Draw lines connecting all points in the connection\n for (let i = 0; i < connection.pointsToConnect.length - 1; i++) {\n for (let j = i + 1; j < connection.pointsToConnect.length; j++) {\n graphics.lines!.push({\n points: [\n connection.pointsToConnect[i],\n connection.pointsToConnect[j],\n ],\n strokeColor: color,\n })\n }\n }\n })\n\n return graphics\n }\n}\n","export type LayerName =\n | \"top\"\n | \"bottom\"\n | \"inner1\"\n | \"inner2\"\n | \"inner3\"\n | \"inner4\"\n | \"inner5\"\n | \"inner6\"\n\nexport const mapZToLayerName = (z: number, layerCount: number): LayerName => {\n if (z < 0 || z >= layerCount) {\n throw new Error(`Invalid z \"${z}\" for layer count: ${layerCount}`)\n }\n\n if (z === 0) return \"top\"\n if (z === layerCount - 1) return \"bottom\"\n return `inner${z}` as any\n}\n","import { SimplifiedPcbTraces } from \"lib/types\"\nimport { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { mapZToLayerName } from \"./mapZToLayerName\"\n\ntype Point = { x: number; y: number; z: number }\n\nexport const convertHdRouteToSimplifiedRoute = (\n hdRoute: HighDensityIntraNodeRoute,\n layerCount: number,\n): SimplifiedPcbTraces[number][\"route\"] => {\n const result: SimplifiedPcbTraces[number][\"route\"] = []\n if (hdRoute.route.length === 0) return result\n\n let currentLayerPoints: Point[] = []\n let currentZ = hdRoute.route[0].z\n\n // Add all points to their respective layer segments\n for (let i = 0; i < hdRoute.route.length; i++) {\n const point = hdRoute.route[i]\n\n // If we're changing layers, process the current layer's points\n // and add a via if one exists at this position\n if (point.z !== currentZ) {\n // Add all wire segments for the current layer\n const layerName = mapZToLayerName(currentZ, layerCount)\n for (const layerPoint of currentLayerPoints) {\n result.push({\n route_type: \"wire\",\n x: layerPoint.x,\n y: layerPoint.y,\n width: hdRoute.traceThickness,\n layer: layerName,\n })\n }\n\n // Check if a via exists at this position\n const viaExists = hdRoute.vias.some(\n (via) =>\n Math.abs(via.x - point.x) < 0.001 &&\n Math.abs(via.y - point.y) < 0.001,\n )\n\n // Add a via if one exists\n if (viaExists) {\n const fromLayer = mapZToLayerName(currentZ, layerCount)\n const toLayer = mapZToLayerName(point.z, layerCount)\n\n result.push({\n route_type: \"via\",\n x: point.x,\n y: point.y,\n from_layer: fromLayer,\n to_layer: toLayer,\n })\n }\n\n // Start a new layer\n currentLayerPoints = [point]\n currentZ = point.z\n } else {\n // Continue on the same layer\n currentLayerPoints.push(point)\n }\n }\n\n // Add the final layer's wire segments\n const layerName = mapZToLayerName(currentZ, layerCount)\n for (const layerPoint of currentLayerPoints) {\n result.push({\n route_type: \"wire\",\n x: layerPoint.x,\n y: layerPoint.y,\n width: hdRoute.traceThickness,\n layer: layerName,\n })\n }\n\n return result\n}\n","import { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { distance } from \"@tscircuit/math-utils\"\n\nexport class SingleHighDensityRouteStitchSolver extends BaseSolver {\n mergedHdRoute: HighDensityIntraNodeRoute\n remainingHdRoutes: HighDensityIntraNodeRoute[]\n start: { x: number; y: number; z: number }\n end: { x: number; y: number; z: number }\n\n constructor(opts: {\n connectionName?: string\n hdRoutes: HighDensityIntraNodeRoute[]\n start: { x: number; y: number; z: number }\n end: { x: number; y: number; z: number }\n }) {\n super()\n this.remainingHdRoutes = [...opts.hdRoutes]\n this.mergedHdRoute = {\n connectionName: opts.connectionName ?? opts.hdRoutes[0].connectionName,\n route: [\n {\n x: opts.start.x,\n y: opts.start.y,\n z: opts.start.z,\n },\n ],\n vias: [],\n viaDiameter: opts.hdRoutes?.[0]?.viaDiameter ?? 0.6,\n traceThickness: opts.hdRoutes?.[0]?.traceThickness ?? 0.15,\n }\n this.start = opts.start\n this.end = opts.end\n }\n\n _step() {\n if (this.remainingHdRoutes.length === 0) {\n // Add the end point to the merged route\n this.mergedHdRoute.route.push({\n x: this.end.x,\n y: this.end.y,\n z: this.end.z,\n })\n this.solved = true\n return\n }\n\n const lastMergedPoint =\n this.mergedHdRoute.route[this.mergedHdRoute.route.length - 1]\n\n // Find the next logical route to merge\n // 1. We need to check both the first and last points of the remaining routes\n // 2. If the last point is closest, we need to reverse the hd route before merging\n // 3. After merging, we remove it from the remaining routes\n\n let closestRouteIndex = 0\n let matchedOn: \"first\" | \"last\" = \"first\"\n let closestDistance = Infinity\n for (let i = 0; i < this.remainingHdRoutes.length; i++) {\n const hdRoute = this.remainingHdRoutes[i]\n const lastPointInCandidate = hdRoute.route[hdRoute.route.length - 1]\n const firstPointInCandidate = hdRoute.route[0]\n const distToFirst = distance(lastMergedPoint, firstPointInCandidate)\n const distToLast = distance(lastMergedPoint, lastPointInCandidate)\n if (distToFirst < closestDistance) {\n closestDistance = distToFirst\n closestRouteIndex = i\n matchedOn = \"first\"\n }\n if (distToLast < closestDistance) {\n closestDistance = distToLast\n closestRouteIndex = i\n matchedOn = \"last\"\n }\n }\n\n const hdRouteToMerge = this.remainingHdRoutes[closestRouteIndex]\n this.remainingHdRoutes.splice(closestRouteIndex, 1)\n\n if (matchedOn === \"first\") {\n this.mergedHdRoute.route.push(...hdRouteToMerge.route)\n } else {\n this.mergedHdRoute.route.push(...[...hdRouteToMerge.route].reverse())\n }\n\n this.mergedHdRoute.vias.push(...hdRouteToMerge.vias)\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n points: [],\n lines: [],\n circles: [],\n title: \"Single High Density Route Stitch Solver\",\n }\n\n // Visualize start and end points\n graphics.points?.push(\n {\n x: this.start.x,\n y: this.start.y,\n color: \"green\",\n label: \"Start\",\n },\n {\n x: this.end.x,\n y: this.end.y,\n color: \"red\",\n label: \"End\",\n },\n )\n\n // Visualize the merged HD route in green\n if (this.mergedHdRoute && this.mergedHdRoute.route.length > 1) {\n graphics.lines?.push({\n points: this.mergedHdRoute.route.map((point) => ({\n x: point.x,\n y: point.y,\n })),\n strokeColor: \"green\",\n })\n\n // Add points for the merged route\n for (const point of this.mergedHdRoute.route) {\n graphics.points?.push({\n x: point.x,\n y: point.y,\n color: \"green\",\n })\n }\n\n // Visualize vias in the merged route\n for (const via of this.mergedHdRoute.vias) {\n graphics.circles?.push({\n center: { x: via.x, y: via.y },\n radius: this.mergedHdRoute.viaDiameter / 2,\n fill: \"green\",\n })\n }\n }\n\n // Visualize all remaining HD routes\n const colorList = Array.from(\n { length: this.remainingHdRoutes.length },\n (_, i) => `hsl(${(i * 360) / this.remainingHdRoutes.length}, 100%, 50%)`,\n )\n for (const [i, hdRoute] of this.remainingHdRoutes.entries()) {\n if (hdRoute.route.length > 1) {\n // Create a line for the route\n graphics.lines?.push({\n points: hdRoute.route.map((point) => ({ x: point.x, y: point.y })),\n strokeColor: colorList[i],\n })\n }\n\n // Add points for each route node\n for (let pi = 0; pi < hdRoute.route.length; pi++) {\n const point = hdRoute.route[pi]\n graphics.points?.push({\n x: point.x + ((i % 2) - 0.5) / 500 + ((pi % 8) - 4) / 1000,\n y: point.y + ((i % 2) - 0.5) / 500 + ((pi % 8) - 4) / 1000,\n color: colorList[i],\n label: `Route ${i} ${point === hdRoute.route[0] ? \"First\" : point === hdRoute.route[hdRoute.route.length - 1] ? \"Last\" : \"\"}`,\n })\n }\n\n // Visualize vias\n for (const via of hdRoute.vias) {\n graphics.circles?.push({\n center: { x: via.x, y: via.y },\n radius: hdRoute.viaDiameter / 2,\n fill: colorList[i],\n })\n }\n }\n\n return graphics\n }\n}\n","import { SimpleRouteConnection } from \"lib/types\"\nimport { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { mapLayerNameToZ } from \"lib/utils/mapLayerNameToZ\"\nimport { SingleHighDensityRouteStitchSolver } from \"./SingleHighDensityRouteStitchSolver\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { safeTransparentize } from \"../colors\"\n\nexport type UnsolvedRoute = {\n connectionName: string\n hdRoutes: HighDensityIntraNodeRoute[]\n start: { x: number; y: number; z: number }\n end: { x: number; y: number; z: number }\n}\n\nexport class MultipleHighDensityRouteStitchSolver extends BaseSolver {\n unsolvedRoutes: UnsolvedRoute[]\n activeSolver: SingleHighDensityRouteStitchSolver | null = null\n mergedHdRoutes: HighDensityIntraNodeRoute[] = []\n\n constructor(opts: {\n connections: SimpleRouteConnection[]\n hdRoutes: HighDensityIntraNodeRoute[]\n layerCount: number\n }) {\n super()\n this.unsolvedRoutes = opts.connections.map((c) => ({\n connectionName: c.name,\n hdRoutes: opts.hdRoutes.filter((r) => r.connectionName === c.name),\n start: {\n ...c.pointsToConnect[0],\n z: mapLayerNameToZ(c.pointsToConnect[0].layer, opts.layerCount),\n },\n end: {\n ...c.pointsToConnect[1],\n z: mapLayerNameToZ(c.pointsToConnect[1].layer, opts.layerCount),\n },\n }))\n this.MAX_ITERATIONS = 100e3\n }\n\n _step() {\n if (this.activeSolver) {\n this.activeSolver.step()\n if (this.activeSolver.solved) {\n this.mergedHdRoutes.push(this.activeSolver.mergedHdRoute)\n this.activeSolver = null\n } else if (this.activeSolver.failed) {\n this.failed = true\n this.error = this.activeSolver.error\n }\n return\n }\n\n const unsolvedRoute = this.unsolvedRoutes.pop()\n\n if (!unsolvedRoute) {\n this.solved = true\n return\n }\n\n this.activeSolver = new SingleHighDensityRouteStitchSolver({\n connectionName: unsolvedRoute.connectionName,\n hdRoutes: unsolvedRoute.hdRoutes,\n start: unsolvedRoute.start,\n end: unsolvedRoute.end,\n })\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n points: [],\n lines: [],\n circles: [],\n title: \"Multiple High Density Route Stitch Solver\",\n }\n\n // Visualize the active solver if one exists\n if (this.activeSolver) {\n // Combine visualizations from the active solver\n const activeSolverGraphics = this.activeSolver.visualize()\n\n // Merge points\n if (activeSolverGraphics.points?.length) {\n graphics.points?.push(...activeSolverGraphics.points)\n }\n\n // Merge lines\n if (activeSolverGraphics.lines?.length) {\n graphics.lines?.push(...activeSolverGraphics.lines)\n }\n\n // Merge circles\n if (activeSolverGraphics.circles?.length) {\n graphics.circles?.push(...activeSolverGraphics.circles)\n }\n\n // Merge rects if they exist\n if (activeSolverGraphics.rects?.length) {\n graphics.rects = activeSolverGraphics.rects\n }\n }\n\n // Visualize all merged HD routes that have been solved\n for (const [i, mergedRoute] of this.mergedHdRoutes.entries()) {\n const solvedColor = `hsl(120, 100%, ${40 + ((i * 10) % 40)}%)` // Different shades of green\n\n // Visualize the route path\n if (mergedRoute.route.length > 1) {\n graphics.lines?.push({\n points: mergedRoute.route.map((point) => ({\n x: point.x,\n y: point.y,\n })),\n strokeColor: solvedColor,\n strokeWidth: mergedRoute.traceThickness,\n })\n }\n\n // Visualize route points\n for (const point of mergedRoute.route) {\n graphics.points?.push({\n x: point.x,\n y: point.y,\n color: solvedColor,\n })\n }\n\n // Visualize vias in the merged route\n for (const via of mergedRoute.vias) {\n graphics.circles?.push({\n center: { x: via.x, y: via.y },\n radius: mergedRoute.viaDiameter / 2,\n fill: solvedColor,\n })\n }\n }\n\n // Visualize all remaining unsolved routes - start/end points only\n const colorList = Array.from(\n { length: this.unsolvedRoutes.length },\n (_, i) => `hsl(${(i * 360) / this.unsolvedRoutes.length}, 100%, 50%)`,\n )\n for (const [i, unsolvedRoute] of this.unsolvedRoutes.entries()) {\n // Add start and end points for unsolved connections\n graphics.points?.push(\n {\n x: unsolvedRoute.start.x,\n y: unsolvedRoute.start.y,\n color: colorList[i],\n label: `${unsolvedRoute.connectionName} Start`,\n },\n {\n x: unsolvedRoute.end.x,\n y: unsolvedRoute.end.y,\n color: colorList[i],\n label: `${unsolvedRoute.connectionName} End`,\n },\n )\n\n // Add a light dashed line between start and end to show pending connections\n graphics.lines?.push({\n points: [\n { x: unsolvedRoute.start.x, y: unsolvedRoute.start.y },\n { x: unsolvedRoute.end.x, y: unsolvedRoute.end.y },\n ],\n strokeColor: colorList[i],\n strokeDash: \"2 2\",\n })\n\n // Visualize HD routes associated with unsolved routes (faded)\n for (const hdRoute of unsolvedRoute.hdRoutes) {\n if (hdRoute.route.length > 1) {\n graphics.lines?.push({\n points: hdRoute.route.map((point) => ({ x: point.x, y: point.y })),\n strokeColor: safeTransparentize(colorList[i], 0.5),\n strokeDash: \"10 5\",\n })\n }\n\n // Visualize vias\n for (const via of hdRoute.vias) {\n graphics.circles?.push({\n center: { x: via.x, y: via.y },\n radius: hdRoute.viaDiameter / 2,\n fill: colorList[i],\n })\n }\n }\n }\n\n return graphics\n }\n}\n","import { Rect, Line, Circle, Point } from \"graphics-debug\"\nimport { SimpleRouteJson } from \"../../lib/types/srj-types\"\nimport { getColorMap, safeTransparentize } from \"lib/solvers/colors\"\nimport { mapZToLayerName } from \"lib/utils/mapZToLayerName\"\nimport { mapLayerNameToZ } from \"lib/utils/mapLayerNameToZ\"\n\nexport const convertSrjToGraphicsObject = (srj: SimpleRouteJson) => {\n const lines: Line[] = []\n const circles: Circle[] = []\n const points: Point[] = []\n\n const colorMap: Record<string, string> = getColorMap(srj)\n const layerCount = 2\n\n // Add points for each connection's pointsToConnect\n if (srj.connections) {\n for (const connection of srj.connections) {\n for (const point of connection.pointsToConnect) {\n points.push({\n x: point.x,\n y: point.y,\n color: colorMap[connection.name]!,\n layer:\n point.layer ??\n (\"z\" in point\n ? mapZToLayerName(point.z as number, layerCount)\n : \"top\"),\n label: `${connection.name} (${point.layer})`,\n })\n }\n }\n }\n\n // Process each trace\n if (srj.traces) {\n for (const trace of srj.traces) {\n for (let j = 0; j < trace.route.length - 1; j++) {\n const routePoint = trace.route[j]\n const nextRoutePoint = trace.route[j + 1]\n\n if (routePoint.route_type === \"via\") {\n // Add a circle for the via\n circles.push({\n center: { x: routePoint.x, y: routePoint.y },\n radius: 0.3, // 0.6 via diameter\n fill: \"blue\",\n stroke: \"none\",\n layer: \"z0,1\",\n })\n } else if (\n routePoint.route_type === \"wire\" &&\n nextRoutePoint.route_type === \"wire\" &&\n nextRoutePoint.layer === routePoint.layer\n ) {\n // Create a line between consecutive wire segments on the same layer\n lines.push({\n points: [\n { x: routePoint.x, y: routePoint.y },\n { x: nextRoutePoint.x, y: nextRoutePoint.y },\n ],\n layer: `z${mapLayerNameToZ(routePoint.layer, layerCount)}`,\n strokeWidth: 0.15,\n strokeColor: safeTransparentize(\n {\n top: \"red\",\n bottom: \"blue\",\n inner1: \"green\",\n inner2: \"yellow\",\n }[routePoint.layer]!,\n 0.5,\n ),\n // For some reason this is too small, likely a graphics-debug bug\n // strokeWidth: 0.15,\n })\n }\n }\n }\n }\n\n return {\n rects: srj.obstacles.map(\n (o) =>\n ({\n center: o.center,\n width: o.width,\n height: o.height,\n fill: \"rgba(255,0,0,0.5)\",\n layer: `z${o.layers.map(mapLayerNameToZ).join(\",\")}`,\n }) as Rect,\n ),\n circles,\n lines,\n points,\n }\n}\n","import { CapacityMeshNodeId } from \"lib/types\"\n\nexport function getNodesNearNode(params: {\n nodeId: CapacityMeshNodeId\n nodeIdToSegmentIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n segmentIdToNodeIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n hops: number\n}): CapacityMeshNodeId[] {\n const { nodeId, nodeIdToSegmentIds, segmentIdToNodeIds, hops } = params\n\n if (hops === 0) return [nodeId]\n\n const visitedNodes = new Set<CapacityMeshNodeId>([nodeId])\n const exploreQueue: Array<{\n nodeId: CapacityMeshNodeId\n remainingHops: number\n }> = [{ nodeId: nodeId, remainingHops: hops }]\n\n while (exploreQueue.length > 0) {\n const { nodeId: node, remainingHops } = exploreQueue.shift()!\n\n if (remainingHops === 0) continue\n\n const segments = nodeIdToSegmentIds.get(node) || []\n for (const segmentId of segments) {\n const adjacentNodeIds = segmentIdToNodeIds.get(segmentId) || []\n for (const adjacentNodeId of adjacentNodeIds) {\n if (!visitedNodes.has(adjacentNodeId)) {\n visitedNodes.add(adjacentNodeId)\n exploreQueue.push({\n nodeId: adjacentNodeId,\n remainingHops: remainingHops - 1,\n })\n }\n }\n }\n }\n\n return Array.from(visitedNodes)\n}\n","import { SegmentPointId } from \"./types\"\n\nexport const createPointModificationsHash = (\n pointModifications: Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >,\n) => {\n return Array.from(pointModifications.entries())\n .map(\n ([id, { x, y, z }]) =>\n `${id}(${x?.toFixed(3) ?? \"\"},${y?.toFixed(3) ?? \"\"},${z ?? \"\"})`,\n )\n .sort()\n .join(\"&\")\n}\n\nexport const createFullPointModificationsHash = (\n originalPoints: Map<SegmentPointId, { x: number; y: number; z: number }>,\n pointModifications: Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >,\n) => {\n return Array.from(originalPoints.entries())\n .map(([id, originalPoint]) => {\n const mods = pointModifications.get(id)\n const finalPoint = {\n x: mods?.x !== undefined ? mods.x : originalPoint.x,\n y: mods?.y !== undefined ? mods.y : originalPoint.y,\n z: mods?.z !== undefined ? mods.z : originalPoint.z,\n }\n return `${id}(${finalPoint.x.toFixed(3)},${finalPoint.y.toFixed(3)},${finalPoint.z})`\n })\n .sort()\n .join(\"&\")\n}\n","export const hasZRangeOverlap = (\n A_z1: number,\n A_z2: number,\n B_z1: number,\n B_z2: number,\n) => {\n const Amin = Math.min(A_z1, A_z2)\n const Amax = Math.max(A_z1, A_z2)\n const Bmin = Math.min(B_z1, B_z2)\n const Bmax = Math.max(B_z1, B_z2)\n return Amin <= Bmax && Amax >= Bmin\n}\n","import { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\nimport {\n UnravelSection,\n UnravelIssue,\n UnravelTransitionViaIssue,\n SegmentPoint,\n SegmentPointId,\n UnravelSameLayerCrossingIssue,\n UnravelSingleTransitionCrossingIssue,\n UnravelDoubleTransitionCrossingIssue,\n} from \"./types\"\nimport { getIntraNodeCrossingsFromSegments } from \"lib/utils/getIntraNodeCrossingsFromSegments\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\nimport { getLogProbability } from \"./getLogProbability\"\nimport { doSegmentsIntersect } from \"@tscircuit/math-utils\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport { hasZRangeOverlap } from \"./hasZRangeOverlap\"\n\nexport const getIssuesInSection = (\n section: UnravelSection,\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>,\n pointModifications: Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >,\n connMap?: ConnectivityMap,\n): UnravelIssue[] => {\n const issues: UnravelIssue[] = []\n\n const points: Map<SegmentPointId, { x: number; y: number; z: number }> =\n new Map(section.originalPointMap)\n for (const [segmentPointId, modPoint] of pointModifications.entries()) {\n const ogPoint = points.get(segmentPointId)!\n points.set(segmentPointId, {\n x: modPoint.x ?? ogPoint.x,\n y: modPoint.y ?? ogPoint.y,\n z: modPoint.z ?? ogPoint.z,\n })\n }\n\n for (const nodeId of section.allNodeIds) {\n const node = nodeMap.get(nodeId)\n if (!node) continue\n\n const nodeSegmentPairs = section.segmentPairsInNode.get(nodeId)!\n\n // If there's a Z transition within the pair, there's a transition_via issue\n for (const pair of nodeSegmentPairs) {\n const A = points.get(pair[0])!\n const B = points.get(pair[1])!\n if (A.z !== B.z) {\n issues.push({\n type: \"transition_via\",\n segmentPoints: pair,\n capacityMeshNodeId: nodeId,\n probabilityOfFailure: 0,\n })\n }\n }\n\n // Find crossing issues\n for (let i = 0; i < nodeSegmentPairs.length; i++) {\n for (let j = i + 1; j < nodeSegmentPairs.length; j++) {\n if (\n connMap?.areIdsConnected(\n nodeSegmentPairs[i][0],\n nodeSegmentPairs[i][1],\n )\n ) {\n continue\n }\n\n const pair1 = nodeSegmentPairs[i]\n const pair2 = nodeSegmentPairs[j]\n\n const A = points.get(pair1[0])!\n const B = points.get(pair1[1])!\n const C = points.get(pair2[0])!\n const D = points.get(pair2[1])!\n\n // Are the lines ever on the same layer? Is there any risk of overlap?\n if (!hasZRangeOverlap(A.z, B.z, C.z, D.z)) continue\n\n const areCrossing = doSegmentsIntersect(A, B, C, D)\n const isSameLayer = A.z === B.z && C.z === D.z && A.z === C.z\n if (areCrossing) {\n if (isSameLayer) {\n issues.push({\n type: \"same_layer_crossing\",\n segmentPoints: [pair1, pair2],\n capacityMeshNodeId: nodeId,\n crossingLine1: pair1,\n crossingLine2: pair2,\n probabilityOfFailure: 0,\n } as UnravelSameLayerCrossingIssue)\n } else if (A.z === B.z && C.z !== D.z) {\n issues.push({\n type: \"single_transition_crossing\",\n segmentPoints: [pair1, pair2],\n capacityMeshNodeId: nodeId,\n sameLayerCrossingLine: pair1,\n transitionCrossingLine: pair2,\n probabilityOfFailure: 0,\n } as UnravelSingleTransitionCrossingIssue)\n } else if (A.z !== B.z && C.z === D.z) {\n issues.push({\n type: \"single_transition_crossing\",\n segmentPoints: [pair1, pair2],\n capacityMeshNodeId: nodeId,\n sameLayerCrossingLine: pair2,\n transitionCrossingLine: pair1,\n probabilityOfFailure: 0,\n } as UnravelSingleTransitionCrossingIssue)\n } else if (A.z !== B.z && C.z !== D.z) {\n issues.push({\n type: \"double_transition_crossing\",\n segmentPoints: [pair1, pair2],\n capacityMeshNodeId: nodeId,\n crossingLine1: pair1,\n crossingLine2: pair2,\n probabilityOfFailure: 0,\n } as UnravelDoubleTransitionCrossingIssue)\n }\n }\n }\n }\n }\n\n return issues\n}\n","export const getLogProbability = (probability: number) => {\n const K = -2.3\n return 1 - Math.exp(probability * K)\n}\n","import { SegmentPointId, UnravelOperation } from \"./types\"\n\n/**\n * Applies an operation to the point modifications map\n * @param pointModifications The current point modifications map\n * @param operation The operation to apply\n * @param getPointInCandidate Function to get the current point values (with any existing modifications)\n * @returns The modified point modifications map\n */\nexport const applyOperationToPointModifications = (\n pointModifications: Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >,\n operation: UnravelOperation,\n getPointInCandidate: (segmentPointId: SegmentPointId) => {\n x: number\n y: number\n z: number\n segmentId: string\n },\n) => {\n if (operation.type === \"change_layer\") {\n for (const segmentPointId of operation.segmentPointIds) {\n const existingMods = pointModifications.get(segmentPointId) || {}\n pointModifications.set(segmentPointId, {\n ...existingMods,\n z: operation.newZ,\n })\n }\n } else if (operation.type === \"swap_position_on_segment\") {\n const [ASpId, BSpId] = operation.segmentPointIds\n const A = getPointInCandidate(ASpId)\n const B = getPointInCandidate(BSpId)\n\n const existingModsA = pointModifications.get(ASpId) || {}\n const existingModsB = pointModifications.get(BSpId) || {}\n\n pointModifications.set(ASpId, {\n ...existingModsA,\n x: B.x,\n y: B.y,\n })\n\n pointModifications.set(BSpId, {\n ...existingModsB,\n x: A.x,\n y: A.y,\n })\n } else if (operation.type === \"combined\") {\n // For combined operations, recursively apply each operation\n for (const subOperation of operation.operations) {\n // Apply each sub-operation directly to the modifications\n applyOperationToPointModifications(\n pointModifications,\n subOperation,\n getPointInCandidate,\n )\n }\n }\n}\n","import { CapacityMeshNodeId } from \"lib/types\"\nimport { SegmentWithAssignedPoints } from \"../CapacityMeshSolver/CapacitySegmentToPointSolver\"\nimport {\n SegmentId,\n SegmentPoint,\n SegmentPointId,\n SegmentPointMap,\n} from \"./types\"\n\nexport type SegmentPointMapAndReverseMaps = {\n segmentPointMap: SegmentPointMap\n nodeToSegmentPointMap: Map<CapacityMeshNodeId, SegmentPointId[]>\n segmentToSegmentPointMap: Map<SegmentId, SegmentPointId[]>\n}\n\nexport const createSegmentPointMap = (\n dedupedSegments: SegmentWithAssignedPoints[],\n segmentIdToNodeIds: Map<SegmentId, CapacityMeshNodeId[]>,\n): SegmentPointMapAndReverseMaps => {\n const segmentPointMap: SegmentPointMap = new Map()\n const nodeToSegmentPointMap: Map<CapacityMeshNodeId, SegmentPointId[]> =\n new Map()\n const segmentToSegmentPointMap: Map<SegmentId, SegmentPointId[]> = new Map()\n\n const segmentPoints: SegmentPoint[] = []\n let highestSegmentPointId = 0\n for (const segment of dedupedSegments) {\n for (const point of segment.assignedPoints!) {\n const sp = {\n segmentPointId: `SP${highestSegmentPointId++}`,\n segmentId: segment.nodePortSegmentId!,\n capacityMeshNodeIds: segmentIdToNodeIds.get(\n segment.nodePortSegmentId!,\n )!,\n connectionName: point.connectionName,\n x: point.point.x,\n y: point.point.y,\n z: point.point.z,\n directlyConnectedSegmentPointIds: [],\n }\n\n segmentPointMap.set(sp.segmentPointId, sp)\n for (const nodeId of sp.capacityMeshNodeIds) {\n nodeToSegmentPointMap.set(nodeId, [\n ...(nodeToSegmentPointMap.get(nodeId) ?? []),\n sp.segmentPointId,\n ])\n }\n\n segmentToSegmentPointMap.set(segment.nodePortSegmentId!, [\n ...(segmentToSegmentPointMap.get(segment.nodePortSegmentId!) ?? []),\n sp.segmentPointId,\n ])\n\n segmentPoints.push(sp)\n }\n }\n\n return {\n segmentPointMap,\n nodeToSegmentPointMap,\n segmentToSegmentPointMap,\n }\n}\n","import { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { SegmentWithAssignedPoints } from \"../CapacityMeshSolver/CapacitySegmentToPointSolver\"\nimport {\n UnravelSection,\n UnravelCandidate,\n SegmentPoint,\n SegmentPointId,\n SegmentId,\n UnravelOperation,\n UnravelIssue,\n SegmentPointMap,\n} from \"./types\"\nimport { getNodesNearNode } from \"./getNodesNearNode\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport {\n createFullPointModificationsHash,\n createPointModificationsHash,\n} from \"./createPointModificationsHash\"\nimport { getIssuesInSection } from \"./getIssuesInSection\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\nimport { getLogProbability } from \"./getLogProbability\"\nimport { applyOperationToPointModifications } from \"./applyOperationToPointModifications\"\nimport {\n createSegmentPointMap,\n SegmentPointMapAndReverseMaps,\n} from \"./createSegmentPointMap\"\n\n/**\n * The UntangleSectionSolver optimizes a section of connected capacity nodes\n * with their deduplicated segments.\n *\n * The section always has a \"root\" node. From the root node, MUTABLE_HOPS are\n * taken to reach other nodes that are mutable. One additional hop is taken to\n * have all the impacted nodes in section. So a section is composed of mutable\n * and immutable nodes.\n *\n * The goal of the solver is to perform operations on the mutable nodes of the\n * section to lower the overall cost of the section.\n *\n * The untangle phase will perform \"operations\" on segments based on \"issues\"\n *\n * An \"issue\" is anything that increases the cost of the node:\n * - Anything that causes a via (e.g. layer transition)\n * - Any time two traces cross on the same layer\n *\n * An operation is a change to a segment. There are two main operations:\n * - Change layer\n * - Change point order on segment\n *\n * This solver works by exploring different paths of operations. When an\n * operation is performed, new issues are created. Each path has a cost, and\n * a set of neighbors representing next operations to perform.\n *\n */\nexport class UnravelSectionSolver extends BaseSolver {\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n dedupedSegments: SegmentWithAssignedPoints[]\n dedupedSegmentMap: Map<SegmentId, SegmentWithAssignedPoints>\n\n MUTABLE_HOPS = 1\n\n unravelSection: UnravelSection\n\n candidates: UnravelCandidate[] = []\n\n lastProcessedCandidate: UnravelCandidate | null = null\n bestCandidate: UnravelCandidate | null = null\n originalCandidate: UnravelCandidate\n\n rootNodeId: CapacityMeshNodeId\n nodeIdToSegmentIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n segmentIdToNodeIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n colorMap: Record<string, string>\n tunedNodeCapacityMap: Map<CapacityMeshNodeId, number>\n MAX_CANDIDATES = 500\n\n selectedCandidateIndex: number | \"best\" | \"original\" | null = null\n\n queuedOrExploredCandidatePointModificationHashes: Set<string> = new Set()\n\n constructor(params: {\n rootNodeId: CapacityMeshNodeId\n colorMap?: Record<string, string>\n MUTABLE_HOPS?: number\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n dedupedSegments: SegmentWithAssignedPoints[]\n dedupedSegmentMap?: Map<SegmentId, SegmentWithAssignedPoints>\n nodeIdToSegmentIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n segmentIdToNodeIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n segmentPointMap?: SegmentPointMap\n nodeToSegmentPointMap?: Map<CapacityMeshNodeId, SegmentPointId[]>\n segmentToSegmentPointMap?: Map<SegmentId, SegmentPointId[]>\n }) {\n super()\n\n this.MUTABLE_HOPS = params.MUTABLE_HOPS ?? this.MUTABLE_HOPS\n\n this.nodeMap = params.nodeMap\n this.dedupedSegments = params.dedupedSegments\n if (params.dedupedSegmentMap) {\n this.dedupedSegmentMap = params.dedupedSegmentMap\n } else {\n this.dedupedSegmentMap = new Map()\n for (const segment of this.dedupedSegments) {\n this.dedupedSegmentMap.set(segment.nodePortSegmentId!, segment)\n }\n }\n this.nodeIdToSegmentIds = params.nodeIdToSegmentIds\n this.segmentIdToNodeIds = params.segmentIdToNodeIds\n this.rootNodeId = params.rootNodeId\n this.colorMap = params.colorMap ?? {}\n this.unravelSection = this.createUnravelSection({\n segmentPointMap: params.segmentPointMap!,\n nodeToSegmentPointMap: params.nodeToSegmentPointMap!,\n segmentToSegmentPointMap: params.segmentToSegmentPointMap!,\n })\n this.tunedNodeCapacityMap = new Map()\n for (const nodeId of this.unravelSection.allNodeIds) {\n this.tunedNodeCapacityMap.set(\n nodeId,\n getTunedTotalCapacity1(this.nodeMap.get(nodeId)!),\n )\n }\n this.originalCandidate = this.createInitialCandidate()\n this.candidates = [this.originalCandidate]\n }\n\n createUnravelSection(\n largeSpMaps?: SegmentPointMapAndReverseMaps,\n ): UnravelSection {\n const mutableNodeIds = getNodesNearNode({\n nodeId: this.rootNodeId,\n nodeIdToSegmentIds: this.nodeIdToSegmentIds,\n segmentIdToNodeIds: this.segmentIdToNodeIds,\n hops: this.MUTABLE_HOPS,\n })\n const allSectionNodeIds = getNodesNearNode({\n nodeId: this.rootNodeId,\n nodeIdToSegmentIds: this.nodeIdToSegmentIds,\n segmentIdToNodeIds: this.segmentIdToNodeIds,\n hops: this.MUTABLE_HOPS + 1,\n })\n const immutableNodeIds = Array.from(\n new Set(allSectionNodeIds).difference(new Set(mutableNodeIds)),\n )\n\n if (!largeSpMaps?.segmentPointMap) {\n largeSpMaps = createSegmentPointMap(\n this.dedupedSegments,\n this.segmentIdToNodeIds,\n )\n }\n\n const segmentPointsInNode = new Map<CapacityMeshNodeId, SegmentPointId[]>()\n for (const nodeId of allSectionNodeIds) {\n segmentPointsInNode.set(\n nodeId,\n largeSpMaps.nodeToSegmentPointMap.get(nodeId)!,\n )\n }\n\n const sectionPointMap = new Map<SegmentPointId, SegmentPoint>()\n for (const nodeId of allSectionNodeIds) {\n for (const segmentPointId of segmentPointsInNode.get(nodeId)!) {\n const point = largeSpMaps.segmentPointMap.get(segmentPointId)!\n sectionPointMap.set(segmentPointId, point)\n }\n }\n\n const segmentPoints = Array.from(sectionPointMap.values())\n\n const segmentPointsInSegment = new Map<SegmentId, SegmentPointId[]>()\n for (const segmentPoint of segmentPoints) {\n segmentPointsInSegment.set(segmentPoint.segmentId, [\n ...(segmentPointsInSegment.get(segmentPoint.segmentId) ?? []),\n segmentPoint.segmentPointId,\n ])\n }\n\n // Second pass: set neighboring segment point ids\n for (const [nodeId, segmentPoints] of segmentPointsInNode.entries()) {\n for (let i = 0; i < segmentPoints.length; i++) {\n const A = largeSpMaps.segmentPointMap.get(segmentPoints[i])!\n for (let j = i + 1; j < segmentPoints.length; j++) {\n const B = largeSpMaps.segmentPointMap.get(segmentPoints[j])!\n\n if (B.segmentPointId === A.segmentPointId) continue\n if (B.segmentId === A.segmentId) continue\n if (B.connectionName !== A.connectionName) continue\n if (B.directlyConnectedSegmentPointIds.includes(A.segmentPointId))\n continue\n\n A.directlyConnectedSegmentPointIds.push(B.segmentPointId)\n B.directlyConnectedSegmentPointIds.push(A.segmentPointId)\n }\n }\n }\n\n const segmentPairsInNode = new Map<\n CapacityMeshNodeId,\n Array<[SegmentPointId, SegmentPointId]>\n >()\n for (const nodeId of allSectionNodeIds) {\n segmentPairsInNode.set(nodeId, [])\n }\n\n for (const A of segmentPoints) {\n for (const nodeId of A.capacityMeshNodeIds) {\n const segmentPairs = segmentPairsInNode.get(nodeId)\n if (!segmentPairs) continue\n for (const BId of A.directlyConnectedSegmentPointIds) {\n const B = largeSpMaps.segmentPointMap.get(BId)!\n if (B.segmentPointId === A.segmentPointId) continue\n if (!B.capacityMeshNodeIds.some((nId) => nId === nodeId)) continue\n if (\n !segmentPairs.some(\n ([a, b]) =>\n (a === A.segmentPointId && b === B.segmentPointId) ||\n (a === B.segmentPointId && b === A.segmentPointId),\n )\n ) {\n segmentPairs.push([A.segmentPointId, B.segmentPointId])\n }\n }\n }\n }\n\n const mutableSegmentIds = new Set<string>()\n for (const nodeId of mutableNodeIds) {\n for (const segmentId of this.nodeIdToSegmentIds.get(nodeId)!) {\n const allNodeIdsWithSegment = this.segmentIdToNodeIds.get(segmentId)!\n if (\n allNodeIdsWithSegment.every(\n (nodeId) => !this.nodeMap.get(nodeId)!._containsTarget,\n )\n ) {\n mutableSegmentIds.add(segmentId)\n }\n }\n }\n\n return {\n allNodeIds: allSectionNodeIds,\n mutableNodeIds,\n immutableNodeIds,\n mutableSegmentIds,\n segmentPairsInNode,\n segmentPointMap: sectionPointMap,\n segmentPointsInNode,\n segmentPointsInSegment,\n originalPointMap: sectionPointMap,\n }\n }\n\n createInitialCandidate(): UnravelCandidate {\n const pointModifications = new Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >()\n const issues = getIssuesInSection(\n this.unravelSection,\n this.nodeMap,\n pointModifications,\n )\n const g = this.computeG({\n issues,\n originalCandidate: {} as any,\n operationsPerformed: 0,\n operation: {} as any,\n })\n return {\n pointModifications,\n issues,\n g,\n h: 0,\n f: g,\n operationsPerformed: 0,\n candidateHash: createPointModificationsHash(pointModifications),\n // candidateFullHash: createFullPointModificationsHash(\n // this.unravelSection.segmentPointMap,\n // pointModifications,\n // ),\n }\n }\n\n get nextCandidate(): UnravelCandidate | null {\n return this.candidates[0] ?? null\n }\n\n getPointInCandidate(\n candidate: UnravelCandidate,\n segmentPointId: SegmentPointId,\n ): { x: number; y: number; z: number; segmentId: string } {\n const originalPoint =\n this.unravelSection.segmentPointMap.get(segmentPointId)!\n const modifications = candidate.pointModifications.get(segmentPointId)\n\n return {\n x: modifications?.x ?? originalPoint.x,\n y: modifications?.y ?? originalPoint.y,\n z: modifications?.z ?? originalPoint.z,\n segmentId: originalPoint.segmentId,\n }\n }\n\n getOperationsForIssue(\n candidate: UnravelCandidate,\n issue: UnravelIssue,\n ): UnravelOperation[] {\n const operations: UnravelOperation[] = []\n\n if (issue.type === \"transition_via\") {\n // When there's a transition via, we attempt to change the layer of either\n // end to match the other end\n const [APointId, BPointId] = issue.segmentPoints\n const pointA = this.getPointInCandidate(candidate, APointId)\n const pointB = this.getPointInCandidate(candidate, BPointId)\n\n const aAvailableZ = this.dedupedSegmentMap.get(\n pointA.segmentId,\n )!.availableZ\n const bAvailableZ = this.dedupedSegmentMap.get(\n pointB.segmentId,\n )!.availableZ\n\n if (\n this.unravelSection.mutableSegmentIds.has(pointA.segmentId) &&\n aAvailableZ.includes(pointB.z)\n ) {\n operations.push({\n type: \"change_layer\",\n newZ: pointB.z,\n segmentPointIds: [APointId],\n })\n }\n if (\n this.unravelSection.mutableSegmentIds.has(pointB.segmentId) &&\n bAvailableZ.includes(pointA.z)\n ) {\n operations.push({\n type: \"change_layer\",\n newZ: pointA.z,\n segmentPointIds: [BPointId],\n })\n }\n }\n\n if (issue.type === \"same_layer_crossing\") {\n // For a same-layer crossing, we should try all the following:\n // 1. Swap the points on each segment (for each shared segment, if any)\n // 2. Change the layer of each segment entirely to remove the crossing\n // 3. Change the layer of each point individually to make it a transition\n // crossing\n\n // 1. SWAP POINTS\n const [APointId, BPointId] = issue.crossingLine1\n const [CPointId, DPointId] = issue.crossingLine2\n\n const sharedSegments: Array<[SegmentPointId, SegmentPointId]> = []\n const A = this.unravelSection.segmentPointMap.get(APointId)!\n const B = this.unravelSection.segmentPointMap.get(BPointId)!\n const C = this.unravelSection.segmentPointMap.get(CPointId)!\n const D = this.unravelSection.segmentPointMap.get(DPointId)!\n\n if (A.segmentId === C.segmentId) {\n sharedSegments.push([APointId, CPointId])\n }\n if (A.segmentId === D.segmentId) {\n sharedSegments.push([APointId, DPointId])\n }\n if (B.segmentId === C.segmentId) {\n sharedSegments.push([BPointId, CPointId])\n }\n if (B.segmentId === D.segmentId) {\n sharedSegments.push([BPointId, DPointId])\n }\n\n for (const [EPointId, FPointId] of sharedSegments) {\n operations.push({\n type: \"swap_position_on_segment\",\n segmentPointIds: [EPointId, FPointId],\n })\n }\n\n // 2. CHANGE LAYER OF EACH SEGMENT ENTIRELY TO REMOVE CROSSING\n const Amutable = this.unravelSection.mutableSegmentIds.has(A.segmentId)\n const Bmutable = this.unravelSection.mutableSegmentIds.has(B.segmentId)\n const Cmutable = this.unravelSection.mutableSegmentIds.has(C.segmentId)\n const Dmutable = this.unravelSection.mutableSegmentIds.has(D.segmentId)\n\n // Get availableZ for each segment\n const aSegment = this.dedupedSegmentMap.get(A.segmentId)!\n const bSegment = this.dedupedSegmentMap.get(B.segmentId)!\n const cSegment = this.dedupedSegmentMap.get(C.segmentId)!\n const dSegment = this.dedupedSegmentMap.get(D.segmentId)!\n\n // Function to check if a new Z level is available for all segments\n const isNewZAvailableForAll = (segmentObjects: any[], newZ: number) => {\n return segmentObjects.every((seg) => seg.availableZ.includes(newZ))\n }\n\n // Only propose layer changes if both segments can use the target layer\n if (Amutable && Bmutable) {\n const newZ = A.z === 0 ? 1 : 0\n if (isNewZAvailableForAll([aSegment, bSegment], newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [APointId, BPointId],\n })\n }\n }\n\n if (Cmutable && Dmutable) {\n const newZ = C.z === 0 ? 1 : 0\n if (isNewZAvailableForAll([cSegment, dSegment], newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [CPointId, DPointId],\n })\n }\n }\n\n // 3. CHANGE LAYER OF EACH POINT INDIVIDUALLY TO MAKE TRANSITION CROSSING\n if (Amutable) {\n const newZ = A.z === 0 ? 1 : 0\n if (aSegment.availableZ.includes(newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [APointId],\n })\n }\n }\n\n if (Bmutable) {\n const newZ = B.z === 0 ? 1 : 0\n if (bSegment.availableZ.includes(newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [BPointId],\n })\n }\n }\n\n if (Cmutable) {\n const newZ = C.z === 0 ? 1 : 0\n if (cSegment.availableZ.includes(newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [CPointId],\n })\n }\n }\n\n if (Dmutable) {\n const newZ = D.z === 0 ? 1 : 0\n if (dSegment.availableZ.includes(newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [DPointId],\n })\n }\n }\n }\n\n // TODO single_transition_crossing\n // TODO double_transition_crossing\n // TODO same_layer_trace_imbalance_with_low_capacity\n\n return operations\n }\n\n computeG(params: {\n issues: UnravelIssue[]\n originalCandidate: UnravelCandidate\n operationsPerformed: number\n operation: UnravelOperation\n }): number {\n const { issues, originalCandidate, operationsPerformed, operation } = params\n\n const nodeProblemCounts = new Map<\n CapacityMeshNodeId,\n {\n numTransitionCrossings: number\n numSameLayerCrossings: number\n numEntryExitLayerChanges: number\n }\n >()\n\n for (const issue of issues) {\n if (!nodeProblemCounts.has(issue.capacityMeshNodeId)) {\n nodeProblemCounts.set(issue.capacityMeshNodeId, {\n numTransitionCrossings: 0,\n numSameLayerCrossings: 0,\n numEntryExitLayerChanges: 0,\n })\n }\n\n const nodeProblemCount = nodeProblemCounts.get(issue.capacityMeshNodeId)!\n\n if (issue.type === \"transition_via\") {\n nodeProblemCount.numTransitionCrossings++\n } else if (issue.type === \"same_layer_crossing\") {\n nodeProblemCount.numSameLayerCrossings++\n } else if (\n issue.type === \"double_transition_crossing\" ||\n issue.type === \"single_transition_crossing\"\n ) {\n nodeProblemCount.numEntryExitLayerChanges++\n } else if (\n issue.type === \"same_layer_trace_imbalance_with_low_capacity\"\n ) {\n // TODO\n }\n }\n\n let cost = 0\n\n for (const [\n nodeId,\n {\n numEntryExitLayerChanges,\n numSameLayerCrossings,\n numTransitionCrossings,\n },\n ] of nodeProblemCounts) {\n const estNumVias =\n numSameLayerCrossings * 0.82 +\n numEntryExitLayerChanges * 0.41 +\n numTransitionCrossings * 0.2\n\n const estUsedCapacity = (estNumVias / 2) ** 1.1\n\n const totalCapacity = this.tunedNodeCapacityMap.get(nodeId)!\n\n const estPf = estUsedCapacity / totalCapacity\n\n cost += getLogProbability(estPf)\n }\n\n return cost\n }\n\n getUnexploredNeighborByApplyingOperation(\n currentCandidate: UnravelCandidate,\n operation: UnravelOperation,\n ): UnravelCandidate | null {\n const pointModifications = new Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >(currentCandidate.pointModifications)\n\n applyOperationToPointModifications(\n pointModifications,\n operation,\n (segmentPointId) =>\n this.getPointInCandidate(currentCandidate, segmentPointId),\n )\n\n const candidateHash = createPointModificationsHash(pointModifications)\n\n if (\n this.queuedOrExploredCandidatePointModificationHashes.has(candidateHash)\n ) {\n return null\n }\n\n const issues: UnravelIssue[] = getIssuesInSection(\n this.unravelSection,\n this.nodeMap,\n pointModifications,\n )\n\n const operationsPerformed = currentCandidate.operationsPerformed + 1\n\n const g = this.computeG({\n issues,\n originalCandidate: currentCandidate,\n operationsPerformed,\n operation,\n })\n\n return {\n issues,\n g,\n h: 0,\n f: g,\n pointModifications,\n candidateHash,\n\n // TODO PERFORMANCE allow disabling this\n // candidateFullHash: createFullPointModificationsHash(\n // this.unravelSection.segmentPointMap,\n // pointModifications,\n // ),\n\n operationsPerformed,\n }\n }\n\n getNeighborOperationsForCandidate(\n candidate: UnravelCandidate,\n ): UnravelOperation[] {\n return candidate.issues.flatMap((issue) =>\n this.getOperationsForIssue(candidate, issue),\n )\n }\n\n getNeighbors(candidate: UnravelCandidate): UnravelCandidate[] {\n const neighbors: UnravelCandidate[] = []\n\n const operations = this.getNeighborOperationsForCandidate(candidate)\n for (const operation of operations) {\n const neighbor = this.getUnexploredNeighborByApplyingOperation(\n candidate,\n operation,\n )\n if (!neighbor) continue\n neighbors.push(neighbor)\n }\n\n return neighbors\n }\n\n _step() {\n const candidate = this.candidates.shift()\n if (!candidate) {\n this.solved = true\n return\n }\n this.lastProcessedCandidate = candidate\n\n if (candidate.f < (this.bestCandidate?.f ?? Infinity)) {\n this.bestCandidate = candidate\n // TODO, only works if we start computing f\n // if (candidate.f <= 0.00001) {\n // this.solved = true\n // return\n // }\n }\n\n this.getNeighbors(candidate).forEach((neighbor) => {\n const isPartialHashExplored =\n this.queuedOrExploredCandidatePointModificationHashes.has(\n neighbor.candidateHash,\n )\n // const isFullHashExplored =\n // neighbor.candidateFullHash &&\n // this.queuedOrExploredCandidatePointModificationHashes.has(\n // neighbor.candidateFullHash,\n // )\n\n // if (isPartialHashExplored || isFullHashExplored) return\n if (isPartialHashExplored) return\n this.queuedOrExploredCandidatePointModificationHashes.add(\n neighbor.candidateHash,\n )\n // if (neighbor.candidateFullHash) {\n // this.queuedOrExploredCandidatePointModificationHashes.add(\n // neighbor.candidateFullHash,\n // )\n // }\n this.candidates.push(neighbor)\n })\n this.candidates.sort((a, b) => a.f - b.f)\n this.candidates.length = Math.min(\n this.candidates.length,\n this.MAX_CANDIDATES,\n )\n }\n\n visualize(): GraphicsObject {\n const graphics: Required<GraphicsObject> = {\n points: [],\n lines: [],\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Unravel Section Solver\",\n }\n\n // Get the candidate to visualize\n let candidate: UnravelCandidate | null = null\n if (this.selectedCandidateIndex !== null) {\n if (this.selectedCandidateIndex === \"best\") {\n candidate = this.bestCandidate\n } else if (this.selectedCandidateIndex === \"original\") {\n candidate = this.originalCandidate\n } else {\n candidate = this.candidates[this.selectedCandidateIndex]\n }\n } else {\n candidate = this.lastProcessedCandidate || this.candidates[0]\n }\n if (!candidate) return graphics\n\n // Create a map of segment points with modifications applied\n const modifiedSegmentPoints = new Map<string, SegmentPoint>()\n for (const [segmentPointId, segmentPoint] of this.unravelSection\n .segmentPointMap) {\n // Create a copy of the original point\n const modifiedPoint = { ...segmentPoint }\n\n // Apply any modifications from the candidate\n const modification = candidate.pointModifications.get(segmentPointId)\n if (modification) {\n if (modification.x !== undefined) modifiedPoint.x = modification.x\n if (modification.y !== undefined) modifiedPoint.y = modification.y\n if (modification.z !== undefined) modifiedPoint.z = modification.z\n }\n\n modifiedSegmentPoints.set(segmentPointId, modifiedPoint)\n }\n\n // Visualize all segment points with modifications applied\n for (const [segmentPointId, segmentPoint] of modifiedSegmentPoints) {\n graphics.points.push({\n x: segmentPoint.x,\n y: segmentPoint.y,\n label: `${segmentPointId}\\nSegment: ${segmentPoint.segmentId} ${this.unravelSection.mutableSegmentIds.has(segmentPoint.segmentId) ? \"MUTABLE\" : \"IMMUTABLE\"}\\nLayer: ${segmentPoint.z}`,\n color: this.colorMap[segmentPoint.connectionName] || \"#000\",\n })\n }\n\n // Visualize nodes\n for (const nodeId of this.unravelSection.allNodeIds) {\n const node = this.nodeMap.get(nodeId)!\n const isMutable = this.unravelSection.mutableNodeIds.includes(nodeId)\n\n graphics.rects.push({\n center: node.center,\n label: `${nodeId}\\n${node.width.toFixed(2)}x${node.height.toFixed(2)}\\n${isMutable ? \"MUTABLE\" : \"IMMUTABLE\"}`,\n color: isMutable ? \"green\" : \"red\",\n width: node.width / 8,\n height: node.height / 8,\n })\n }\n\n // Connect segment points that belong to the same segment\n for (const [segmentId, segmentPointIds] of this.unravelSection\n .segmentPointsInSegment) {\n if (segmentPointIds.length <= 1) continue\n\n const points = segmentPointIds.map(\n (spId) => modifiedSegmentPoints.get(spId)!,\n )\n\n // Connect points in order\n for (let i = 0; i < points.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: points[i].x, y: points[i].y },\n { x: points[i + 1].x, y: points[i + 1].y },\n ],\n strokeColor: this.colorMap[segmentId] || \"#000\",\n })\n }\n }\n\n // Connect directly connected segment points (points with the same connection name)\n for (const [segmentPointId, segmentPoint] of modifiedSegmentPoints) {\n for (const connectedPointId of segmentPoint.directlyConnectedSegmentPointIds) {\n // Only process each connection once (when the current point's ID is less than the connected point's ID)\n if (segmentPointId < connectedPointId) {\n const connectedPoint = modifiedSegmentPoints.get(connectedPointId)!\n if (!connectedPoint) continue\n\n // Determine line style based on layer (z) values\n const sameLayer = segmentPoint.z === connectedPoint.z\n const commonLayer = segmentPoint.z\n\n let strokeDash: string | undefined\n if (sameLayer) {\n strokeDash = commonLayer === 0 ? undefined : \"10 5\" // top layer: solid, bottom layer: long dash\n } else {\n strokeDash = \"3 3 10\" // transition between layers: mixed dash pattern\n }\n\n graphics.lines.push({\n points: [\n { x: segmentPoint.x, y: segmentPoint.y },\n { x: connectedPoint.x, y: connectedPoint.y },\n ],\n strokeDash,\n strokeColor: this.colorMap[segmentPoint.connectionName] || \"#000\",\n })\n }\n }\n }\n\n // Visualize issues\n for (const issue of candidate.issues) {\n const node = this.nodeMap.get(issue.capacityMeshNodeId)!\n\n if (issue.type === \"transition_via\") {\n // Highlight via issues\n for (const segmentPointId of issue.segmentPoints) {\n const segmentPoint = modifiedSegmentPoints.get(segmentPointId)!\n graphics.circles.push({\n center: { x: segmentPoint.x, y: segmentPoint.y },\n radius: node.width / 16,\n stroke: \"#ff0000\",\n fill: \"rgba(255, 0, 0, 0.2)\",\n label: `Via Issue\\n${segmentPointId}\\nLayer: ${segmentPoint.z}`,\n })\n }\n } else if (issue.type === \"same_layer_crossing\") {\n // Highlight crossing issues\n for (const [sp1Id, sp2Id] of [\n issue.crossingLine1,\n issue.crossingLine2,\n ]) {\n const sp1 = modifiedSegmentPoints.get(sp1Id)!\n const sp2 = modifiedSegmentPoints.get(sp2Id)!\n\n graphics.lines.push({\n points: [\n { x: sp1.x, y: sp1.y },\n { x: sp2.x, y: sp2.y },\n ],\n strokeColor: \"rgba(255,0,0,0.2)\",\n strokeWidth: node.width / 32,\n })\n }\n }\n }\n\n // Highlight modified points\n for (const [segmentPointId, modification] of candidate.pointModifications) {\n const modifiedPoint = modifiedSegmentPoints.get(segmentPointId)!\n const originalPoint =\n this.unravelSection.segmentPointMap.get(segmentPointId)!\n\n graphics.circles.push({\n center: { x: modifiedPoint.x, y: modifiedPoint.y },\n radius: 0.05,\n stroke: \"#0000ff\",\n fill: \"rgba(0, 0, 255, 0.2)\",\n label: `${segmentPointId}\\nOriginal: (${originalPoint.x.toFixed(2)}, ${originalPoint.y.toFixed(2)}, ${originalPoint.z})\\nNew: (${modifiedPoint.x.toFixed(2)}, ${modifiedPoint.y.toFixed(2)}, ${modifiedPoint.z})`,\n })\n }\n\n return graphics\n }\n}\n","import { NodePortSegment } from \"lib/types/capacity-edges-to-port-segments-types\"\nimport { SegmentWithAssignedPoints } from \"../CapacityMeshSolver/CapacitySegmentToPointSolver\"\n\n/**\n * Deduplicates segments with the same start and end points.\n * Assigns a unique ID to each unique segment and ensures all segments with the same\n * start/end points share the same ID.\n * @param assignedSegments The segments to deduplicate\n * @returns Deduplicated segments with unique IDs\n */\nexport const getDedupedSegments = (\n assignedSegments: NodePortSegment[],\n): SegmentWithAssignedPoints[] => {\n const dedupedSegments: SegmentWithAssignedPoints[] = []\n type SegKey = `${number}-${number}-${number}-${number}-${string}`\n const dedupedSegPointMap: Map<SegKey, NodePortSegment> = new Map()\n let highestSegmentId = -1\n\n for (const seg of assignedSegments) {\n // Check if there's another segment with the same start and end and availableZ\n const segKey: SegKey = `${seg.start.x}-${seg.start.y}-${seg.end.x}-${seg.end.y}-${seg.availableZ.join(\",\")}`\n const existingSeg = dedupedSegPointMap.get(segKey)\n\n if (!existingSeg) {\n highestSegmentId++\n seg.nodePortSegmentId = `SEG${highestSegmentId}`\n dedupedSegPointMap.set(segKey, seg)\n dedupedSegments.push(seg)\n continue\n }\n\n seg.nodePortSegmentId = existingSeg.nodePortSegmentId\n }\n\n return dedupedSegments\n}\n","import { CapacityMeshNode } from \"lib/types\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\n\nexport const calculateNodeProbabilityOfFailure = (\n node: CapacityMeshNode,\n numSameLayerCrossings: number,\n numEntryExitLayerChanges: number,\n numTransitionCrossings: number,\n): number => {\n if (node?._containsTarget) return 0\n\n // Number of traces through the node\n const totalCapacity = getTunedTotalCapacity1(node)\n\n // Estimated number of vias based on crossings\n const estNumVias =\n numSameLayerCrossings * 0.82 +\n numEntryExitLayerChanges * 0.41 +\n numTransitionCrossings * 0.2\n\n const estUsedCapacity = (estNumVias / 2) ** 1.1\n\n // We could refine this with actual trace capacity\n const approxProb = estUsedCapacity / totalCapacity\n\n // Bounded probability calculation\n return approxProb\n}\n","import { doSegmentsIntersect } from \"@tscircuit/math-utils\"\nimport { SegmentPoint } from \"lib/solvers/UnravelSolver/types\"\n\nexport const getIntraNodeCrossingsFromSegmentPoints = (\n segmentPoints: SegmentPoint[],\n) => {\n // Count the number of crossings\n let numSameLayerCrossings = 0\n let numEntryExitLayerChanges = 0\n let numTransitionCrossings = 0\n\n // Group segment points by connection name\n const connectionGroups = new Map<string, SegmentPoint[]>()\n\n for (const point of segmentPoints) {\n if (!connectionGroups.has(point.connectionName)) {\n connectionGroups.set(point.connectionName, [])\n }\n connectionGroups.get(point.connectionName)!.push(point)\n }\n\n const pointPairs: {\n points: { x: number; y: number; z: number }[]\n z: number\n connectionName: string\n }[] = []\n\n const transitionPairPoints: {\n points: { x: number; y: number; z: number }[]\n connectionName: string\n }[] = []\n\n // Process each connection group\n for (const [connectionName, points] of connectionGroups.entries()) {\n if (points.length < 2) continue\n\n // For simplicity, we'll just connect the first point to all others in the group\n // This assumes a simple connection pattern\n const firstPoint = points[0]\n\n for (let i = 1; i < points.length; i++) {\n const secondPoint = points[i]\n\n const pointPair = {\n connectionName,\n z: firstPoint.z,\n points: [firstPoint, secondPoint],\n }\n\n if (firstPoint.z !== secondPoint.z) {\n numEntryExitLayerChanges++\n transitionPairPoints.push({\n connectionName,\n points: [firstPoint, secondPoint],\n })\n } else {\n pointPairs.push(pointPair)\n }\n }\n }\n\n // Check for same layer crossings\n for (let i = 0; i < pointPairs.length; i++) {\n for (let j = i + 1; j < pointPairs.length; j++) {\n const pair1 = pointPairs[i]\n const pair2 = pointPairs[j]\n\n if (\n pair1.z === pair2.z &&\n doSegmentsIntersect(\n pair1.points[0],\n pair1.points[1],\n pair2.points[0],\n pair2.points[1],\n )\n ) {\n numSameLayerCrossings++\n }\n }\n }\n\n // Check for transition crossings\n for (let i = 0; i < transitionPairPoints.length; i++) {\n for (let j = i + 1; j < transitionPairPoints.length; j++) {\n const pair1 = transitionPairPoints[i]\n const pair2 = transitionPairPoints[j]\n\n if (\n doSegmentsIntersect(\n pair1.points[0],\n pair1.points[1],\n pair2.points[0],\n pair2.points[1],\n )\n ) {\n numTransitionCrossings++\n }\n }\n }\n\n // Check for crossings between transition pairs and regular pairs\n for (let i = 0; i < transitionPairPoints.length; i++) {\n for (let j = 0; j < pointPairs.length; j++) {\n const pair1 = transitionPairPoints[i]\n const pair2 = pointPairs[j]\n\n if (\n doSegmentsIntersect(\n pair1.points[0],\n pair1.points[1],\n pair2.points[0],\n pair2.points[1],\n )\n ) {\n numTransitionCrossings++\n }\n }\n }\n\n return {\n numSameLayerCrossings,\n numEntryExitLayerChanges,\n numTransitionCrossings,\n }\n}\n","import { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\nimport { SegmentWithAssignedPoints } from \"../CapacityMeshSolver/CapacitySegmentToPointSolver\"\nimport { UnravelSectionSolver } from \"./UnravelSectionSolver\"\nimport { getIntraNodeCrossings } from \"lib/utils/getIntraNodeCrossings\"\nimport { NodePortSegment } from \"lib/types/capacity-edges-to-port-segments-types\"\nimport { getDedupedSegments } from \"./getDedupedSegments\"\nimport { getIntraNodeCrossingsFromSegments } from \"lib/utils/getIntraNodeCrossingsFromSegments\"\nimport { calculateNodeProbabilityOfFailure } from \"./calculateCrossingProbabilityOfFailure\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { NodeWithPortPoints } from \"lib/types/high-density-types\"\nimport {\n PointModificationsMap,\n SegmentId,\n SegmentPoint,\n SegmentPointId,\n SegmentPointMap,\n} from \"./types\"\nimport { createSegmentPointMap } from \"./createSegmentPointMap\"\nimport { getIntraNodeCrossingsFromSegmentPoints } from \"lib/utils/getIntraNodeCrossingsFromSegmentPoints\"\nimport { getNodesNearNode } from \"./getNodesNearNode\"\n\nexport class UnravelMultiSectionSolver extends BaseSolver {\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n dedupedSegmentMap: Map<SegmentId, SegmentWithAssignedPoints>\n dedupedSegments: SegmentWithAssignedPoints[]\n nodeIdToSegmentIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n segmentIdToNodeIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n nodeToSegmentPointMap: Map<CapacityMeshNodeId, SegmentPointId[]>\n segmentToSegmentPointMap: Map<SegmentId, SegmentPointId[]>\n colorMap: Record<string, string>\n tunedNodeCapacityMap: Map<CapacityMeshNodeId, number>\n\n MAX_NODE_ATTEMPTS = 2\n\n MUTABLE_HOPS = 1\n\n ACCEPTABLE_PF = 0.05\n\n /**\n * Probability of failure for each node\n */\n nodePfMap: Map<CapacityMeshNodeId, number>\n\n attemptsToFixNode: Map<CapacityMeshNodeId, number>\n\n activeSolver: UnravelSectionSolver | null = null\n\n segmentPointMap: SegmentPointMap\n\n constructor({\n assignedSegments,\n colorMap,\n nodes,\n }: {\n assignedSegments: NodePortSegment[]\n colorMap?: Record<string, string>\n /**\n * This isn't used by the algorithm, but allows associating metadata\n * for the result datatype (the center, width, height of the node)\n */\n nodes: CapacityMeshNode[]\n }) {\n super()\n\n this.MAX_ITERATIONS = 100_000\n\n this.dedupedSegments = getDedupedSegments(assignedSegments)\n this.dedupedSegmentMap = new Map()\n for (const segment of this.dedupedSegments) {\n this.dedupedSegmentMap.set(segment.nodePortSegmentId!, segment)\n }\n this.nodeMap = new Map()\n for (const node of nodes) {\n this.nodeMap.set(node.capacityMeshNodeId, node)\n }\n\n this.nodeIdToSegmentIds = new Map()\n this.segmentIdToNodeIds = new Map()\n this.attemptsToFixNode = new Map()\n\n for (const segment of assignedSegments) {\n this.segmentIdToNodeIds.set(segment.nodePortSegmentId!, [\n ...(this.segmentIdToNodeIds.get(segment.nodePortSegmentId!) ?? []),\n segment.capacityMeshNodeId,\n ])\n this.nodeIdToSegmentIds.set(segment.capacityMeshNodeId, [\n ...(this.nodeIdToSegmentIds.get(segment.capacityMeshNodeId) ?? []),\n segment.nodePortSegmentId!,\n ])\n }\n\n this.colorMap = colorMap ?? {}\n\n // Compute tuned capacity for each node\n this.tunedNodeCapacityMap = new Map()\n for (const [nodeId, node] of this.nodeMap) {\n this.tunedNodeCapacityMap.set(nodeId, getTunedTotalCapacity1(node))\n }\n\n const { segmentPointMap, nodeToSegmentPointMap, segmentToSegmentPointMap } =\n createSegmentPointMap(this.dedupedSegments, this.segmentIdToNodeIds)\n\n this.segmentPointMap = segmentPointMap\n this.nodeToSegmentPointMap = nodeToSegmentPointMap\n this.segmentToSegmentPointMap = segmentToSegmentPointMap\n\n this.nodePfMap = this.computeInitialPfMap()\n }\n\n computeInitialPfMap() {\n const pfMap = new Map<CapacityMeshNodeId, number>()\n\n for (const [nodeId, node] of this.nodeMap.entries()) {\n pfMap.set(nodeId, this.computeNodePf(node))\n }\n\n return pfMap\n }\n\n computeNodePf(node: CapacityMeshNode) {\n const {\n numSameLayerCrossings,\n numEntryExitLayerChanges,\n numTransitionCrossings,\n } = getIntraNodeCrossingsFromSegmentPoints(\n (this.nodeToSegmentPointMap.get(node.capacityMeshNodeId) ?? []).map(\n (segPointId) => this.segmentPointMap.get(segPointId)!,\n ),\n )\n\n const probabilityOfFailure = calculateNodeProbabilityOfFailure(\n node,\n numSameLayerCrossings,\n numEntryExitLayerChanges,\n numTransitionCrossings,\n )\n\n return probabilityOfFailure\n }\n\n _step() {\n if (this.iterations >= this.MAX_ITERATIONS - 1) {\n this.solved = true\n return\n }\n if (!this.activeSolver) {\n // Find the node with the highest probability of failure\n let highestPfNodeId = null\n let highestPf = 0\n for (const [nodeId, pf] of this.nodePfMap.entries()) {\n const pfReduced =\n pf *\n (1 -\n (this.attemptsToFixNode.get(nodeId) ?? 0) / this.MAX_NODE_ATTEMPTS)\n if (pfReduced > highestPf) {\n highestPf = pf\n highestPfNodeId = nodeId\n }\n }\n\n if (!highestPfNodeId || highestPf < this.ACCEPTABLE_PF) {\n this.solved = true\n return\n }\n\n this.attemptsToFixNode.set(\n highestPfNodeId,\n (this.attemptsToFixNode.get(highestPfNodeId) ?? 0) + 1,\n )\n this.activeSolver = new UnravelSectionSolver({\n dedupedSegments: this.dedupedSegments,\n dedupedSegmentMap: this.dedupedSegmentMap,\n nodeMap: this.nodeMap,\n nodeIdToSegmentIds: this.nodeIdToSegmentIds,\n segmentIdToNodeIds: this.segmentIdToNodeIds,\n colorMap: this.colorMap,\n rootNodeId: highestPfNodeId,\n MUTABLE_HOPS: this.MUTABLE_HOPS,\n segmentPointMap: this.segmentPointMap,\n nodeToSegmentPointMap: this.nodeToSegmentPointMap,\n segmentToSegmentPointMap: this.segmentToSegmentPointMap,\n })\n }\n\n this.activeSolver.step()\n\n const { bestCandidate, originalCandidate, lastProcessedCandidate } =\n this.activeSolver\n\n const giveUpFactor =\n 1 + 4 * (1 - Math.min(1, this.activeSolver.iterations / 40))\n const shouldEarlyStop =\n lastProcessedCandidate &&\n lastProcessedCandidate!.g > bestCandidate!.g * giveUpFactor\n\n if (this.activeSolver.solved || shouldEarlyStop) {\n // Incorporate the changes from the active solver\n\n const foundBetterSolution =\n bestCandidate && bestCandidate.g < originalCandidate!.g\n\n if (foundBetterSolution) {\n // Modify the points using the pointModifications of the candidate\n for (const [\n segmentPointId,\n pointModification,\n ] of bestCandidate.pointModifications.entries()) {\n const segmentPoint = this.segmentPointMap.get(segmentPointId)!\n segmentPoint.x = pointModification.x ?? segmentPoint.x\n segmentPoint.y = pointModification.y ?? segmentPoint.y\n segmentPoint.z = pointModification.z ?? segmentPoint.z\n }\n\n // HACK: This is time consuming but there is a bug where sometimes the\n // UnravelSectionSolver accidentally mutates immutable nodes, so we\n // need to go to even more neighbors to be sure we have the updated\n // Pf values. If that bug gets fixed, you can use this.activeSolver.section.allNodeIds\n const possiblyImpactedNodeIds = getNodesNearNode({\n hops: this.activeSolver.MUTABLE_HOPS + 2,\n nodeId: this.activeSolver.rootNodeId,\n nodeIdToSegmentIds: this.nodeIdToSegmentIds,\n segmentIdToNodeIds: this.segmentIdToNodeIds,\n })\n\n // Update node failure probabilities\n for (const nodeId of possiblyImpactedNodeIds) {\n // for (const nodeId of this.nodeMap.keys()) {\n this.nodePfMap.set(\n nodeId,\n this.computeNodePf(this.nodeMap.get(nodeId)!),\n )\n }\n }\n\n this.activeSolver = null\n }\n }\n\n visualize(): GraphicsObject {\n if (this.activeSolver) {\n return this.activeSolver.visualize()\n }\n\n const graphics: Required<GraphicsObject> = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Unravel Multi Section Solver\",\n }\n\n // Visualize nodes\n for (const [nodeId, node] of this.nodeMap.entries()) {\n const probabilityOfFailure = this.nodePfMap.get(nodeId) || 0\n // Color based on probability of failure - red for high, gradient to green for low\n const pf = Math.min(probabilityOfFailure, 1) // Cap at 1\n const red = Math.floor(255 * pf)\n const green = Math.floor(255 * (1 - pf))\n const color = `rgb(${red}, ${green}, 0)`\n\n if ((this.attemptsToFixNode.get(nodeId) ?? 0) === 0 && pf === 0) {\n continue\n }\n\n graphics.rects.push({\n center: node.center,\n label: [\n nodeId,\n `${node.width.toFixed(2)}x${node.height.toFixed(2)}`,\n `Pf: ${probabilityOfFailure.toFixed(3)}`,\n ].join(\"\\n\"),\n color,\n width: node.width / 8,\n height: node.height / 8,\n })\n }\n\n // Visualize segment points\n for (const segmentPoint of this.segmentPointMap.values()) {\n const segment = this.dedupedSegmentMap.get(segmentPoint.segmentId)\n graphics.points.push({\n x: segmentPoint.x,\n y: segmentPoint.y,\n label: [\n segmentPoint.segmentPointId,\n segmentPoint.segmentId,\n `z: ${segmentPoint.z}`,\n `segment.availableZ: ${segment?.availableZ.join(\",\")}`,\n ].join(\"\\n\"),\n color: this.colorMap[segmentPoint.connectionName] || \"#000\",\n })\n }\n\n // Connect segment points that belong to the same segment\n // Group points by segment ID\n const pointsBySegment = new Map<string, SegmentPoint[]>()\n for (const point of this.segmentPointMap.values()) {\n if (!pointsBySegment.has(point.segmentId)) {\n pointsBySegment.set(point.segmentId, [])\n }\n pointsBySegment.get(point.segmentId)!.push(point)\n }\n\n // Connect points in each segment\n for (const [segmentId, points] of pointsBySegment.entries()) {\n if (points.length < 2) continue\n\n // Sort points by some logical order (this approximates the correct ordering)\n const sortedPoints = [...points].sort((a, b) =>\n a.x !== b.x ? a.x - b.x : a.y - b.y,\n )\n\n // Connect adjacent points in the sorted order\n for (let i = 0; i < sortedPoints.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: sortedPoints[i].x, y: sortedPoints[i].y },\n { x: sortedPoints[i + 1].x, y: sortedPoints[i + 1].y },\n ],\n strokeColor: this.colorMap[segmentId] || \"#000\",\n })\n }\n }\n\n // Connect points with the same connection name that share a node\n const processedConnections = new Set<string>()\n const allPoints = Array.from(this.segmentPointMap.values())\n\n for (let i = 0; i < allPoints.length; i++) {\n const point1 = allPoints[i]\n for (let j = i + 1; j < allPoints.length; j++) {\n const point2 = allPoints[j]\n\n // Skip if they have different connection names or are in the same segment\n if (\n point1.connectionName !== point2.connectionName ||\n point1.segmentId === point2.segmentId\n ) {\n continue\n }\n\n // Check if they share a node\n const hasSharedNode = point1.capacityMeshNodeIds.some((nodeId) =>\n point2.capacityMeshNodeIds.includes(nodeId),\n )\n\n if (hasSharedNode) {\n const connectionKey = `${point1.segmentPointId}-${point2.segmentPointId}`\n if (processedConnections.has(connectionKey)) continue\n processedConnections.add(connectionKey)\n\n // Determine line style based on layer (z) values\n const sameLayer = point1.z === point2.z\n const layer = point1.z\n\n let strokeDash: string | undefined\n if (sameLayer) {\n strokeDash = layer === 0 ? undefined : \"10 5\" // Solid for layer 0, long dash for other layers\n } else {\n strokeDash = \"3 3 10\" // Mixed dash for transitions between layers\n }\n\n graphics.lines.push({\n points: [\n { x: point1.x, y: point1.y },\n { x: point2.x, y: point2.y },\n ],\n strokeDash,\n strokeColor: this.colorMap[point1.connectionName] || \"#666\",\n })\n }\n }\n }\n return graphics\n }\n\n getNodesWithPortPoints(): NodeWithPortPoints[] {\n if (!this.solved) {\n throw new Error(\n \"CapacitySegmentToPointSolver not solved, can't give port points yet\",\n )\n }\n const nodeWithPortPointsMap = new Map<string, NodeWithPortPoints>()\n for (const segment of this.dedupedSegments) {\n const segId = segment.nodePortSegmentId!\n for (const nodeId of this.segmentIdToNodeIds.get(segId)!) {\n const node = this.nodeMap.get(nodeId)!\n if (!nodeWithPortPointsMap.has(nodeId)) {\n nodeWithPortPointsMap.set(nodeId, {\n capacityMeshNodeId: nodeId,\n portPoints: [],\n center: node.center,\n width: node.width,\n height: node.height,\n })\n }\n }\n }\n\n for (const segmentPoint of this.segmentPointMap.values()) {\n for (const nodeId of segmentPoint.capacityMeshNodeIds) {\n const nodeWithPortPoints = nodeWithPortPointsMap.get(nodeId)\n if (nodeWithPortPoints) {\n nodeWithPortPoints.portPoints.push({\n x: segmentPoint.x,\n y: segmentPoint.y,\n z: segmentPoint.z,\n connectionName: segmentPoint.connectionName,\n })\n }\n }\n }\n\n return Array.from(nodeWithPortPointsMap.values())\n }\n}\n","import { Rect } from \"graphics-debug\"\nimport { CapacityMeshNode } from \"lib/types\"\n\nexport const createRectFromCapacityNode = (\n node: CapacityMeshNode,\n opts: {\n rectMargin?: number\n zOffset?: number\n } = {},\n): Rect => {\n const lowestZ = Math.min(...node.availableZ)\n return {\n center:\n !opts.rectMargin || opts.zOffset\n ? {\n x: node.center.x + lowestZ * node.width * (opts.zOffset ?? 0.05),\n y: node.center.y - lowestZ * node.width * (opts.zOffset ?? 0.05),\n }\n : node.center,\n width: opts.rectMargin\n ? node.width - opts.rectMargin * 2\n : Math.max(node.width - 0.5, node.width * 0.8),\n height: opts.rectMargin\n ? node.height - opts.rectMargin * 2\n : Math.max(node.height - 0.5, node.height * 0.8),\n fill: node._containsObstacle\n ? \"rgba(255,0,0,0.1)\"\n : ({\n \"0,1\": \"rgba(0,0,0,0.1)\",\n \"0\": \"rgba(0,200,200, 0.1)\",\n \"1\": \"rgba(0,0,200, 0.1)\",\n }[node.availableZ.join(\",\")] ?? \"rgba(0,200,200,0.1)\"),\n layer: `z${node.availableZ.join(\",\")}`,\n label: [\n node.capacityMeshNodeId,\n `availableZ: ${node.availableZ.join(\",\")}`,\n `${node._containsTarget ? \"containsTarget\" : \"\"}`,\n `${node._containsObstacle ? \"containsObstacle\" : \"\"}`,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n }\n}\n","import { BaseSolver } from \"../BaseSolver\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n CapacityMeshNodeId,\n CapacityPath,\n SimpleRouteConnection,\n SimpleRouteJson,\n} from \"../../types\"\nimport { getNodeEdgeMap } from \"../CapacityMeshSolver/getNodeEdgeMap\"\nimport { distance } from \"@tscircuit/math-utils\"\nimport { CapacityHyperParameters } from \"../CapacityHyperParameters\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { safeTransparentize } from \"../colors\"\nimport { createRectFromCapacityNode } from \"lib/utils/createRectFromCapacityNode\"\n\nexport type Candidate = {\n prevCandidate: Candidate | null\n node: CapacityMeshNode\n f: number\n g: number\n h: number\n}\n\nexport class CapacityPathingSolver extends BaseSolver {\n connectionsWithNodes: Array<{\n connection: SimpleRouteConnection\n nodes: CapacityMeshNode[]\n path?: CapacityMeshNode[]\n straightLineDistance: number\n }>\n\n usedNodeCapacityMap: Map<CapacityMeshNodeId, number>\n\n simpleRouteJson: SimpleRouteJson\n nodes: CapacityMeshNode[]\n edges: CapacityMeshEdge[]\n GREEDY_MULTIPLIER = 1.1\n\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n nodeEdgeMap: Map<CapacityMeshNodeId, CapacityMeshEdge[]>\n connectionNameToGoalNodeIds: Map<string, CapacityMeshNodeId[]>\n colorMap: Record<string, string>\n maxDepthOfNodes: number\n\n activeCandidateStraightLineDistance?: number\n\n debug_lastNodeCostMap: Map<\n CapacityMeshNodeId,\n {\n g: number\n h: number\n f: number\n }\n >\n\n hyperParameters: Partial<CapacityHyperParameters>\n\n constructor({\n simpleRouteJson,\n nodes,\n edges,\n colorMap,\n MAX_ITERATIONS = 1e6,\n hyperParameters = {},\n }: {\n simpleRouteJson: SimpleRouteJson\n nodes: CapacityMeshNode[]\n edges: CapacityMeshEdge[]\n colorMap?: Record<string, string>\n MAX_ITERATIONS?: number\n hyperParameters?: Partial<CapacityHyperParameters>\n }) {\n super()\n this.MAX_ITERATIONS = MAX_ITERATIONS\n this.simpleRouteJson = simpleRouteJson\n this.nodes = nodes\n this.edges = edges\n this.colorMap = colorMap ?? {}\n const { connectionsWithNodes, connectionNameToGoalNodeIds } =\n this.getConnectionsWithNodes()\n this.connectionsWithNodes = connectionsWithNodes\n this.connectionNameToGoalNodeIds = connectionNameToGoalNodeIds\n this.hyperParameters = hyperParameters\n this.usedNodeCapacityMap = new Map(\n this.nodes.map((node) => [node.capacityMeshNodeId, 0]),\n )\n this.nodeMap = new Map(\n this.nodes.map((node) => [node.capacityMeshNodeId, node]),\n )\n this.nodeEdgeMap = getNodeEdgeMap(this.edges)\n this.maxDepthOfNodes = Math.max(\n ...this.nodes.map((node) => node._depth ?? 0),\n )\n this.debug_lastNodeCostMap = new Map()\n }\n\n getTotalCapacity(node: CapacityMeshNode): number {\n const depth = node._depth ?? 0\n return (this.maxDepthOfNodes - depth + 1) ** 2\n }\n\n getConnectionsWithNodes() {\n const connectionsWithNodes: Array<{\n connection: SimpleRouteConnection\n nodes: CapacityMeshNode[]\n pathFound: boolean\n straightLineDistance: number\n }> = []\n const nodesWithTargets = this.nodes.filter((node) => node._containsTarget)\n const connectionNameToGoalNodeIds = new Map<string, CapacityMeshNodeId[]>()\n\n for (const connection of this.simpleRouteJson.connections) {\n const nodesForConnection: CapacityMeshNode[] = []\n for (const point of connection.pointsToConnect) {\n let closestNode = this.nodes[0]\n let minDistance = Number.MAX_VALUE\n\n for (const node of nodesWithTargets) {\n const distance = Math.sqrt(\n (node.center.x - point.x) ** 2 + (node.center.y - point.y) ** 2,\n )\n if (distance < minDistance) {\n minDistance = distance\n closestNode = node\n }\n }\n nodesForConnection.push(closestNode)\n }\n if (nodesForConnection.length < 2) {\n throw new Error(\n `Not enough nodes for connection \"${connection.name}\", only ${nodesForConnection.length} found`,\n )\n }\n connectionNameToGoalNodeIds.set(\n connection.name,\n nodesForConnection.map((n) => n.capacityMeshNodeId),\n )\n connectionsWithNodes.push({\n connection,\n nodes: nodesForConnection,\n pathFound: false,\n straightLineDistance: distance(\n nodesForConnection[0].center,\n nodesForConnection[nodesForConnection.length - 1].center,\n ),\n })\n }\n\n connectionsWithNodes.sort(\n (a, b) => a.straightLineDistance - b.straightLineDistance,\n )\n return { connectionsWithNodes, connectionNameToGoalNodeIds }\n }\n\n currentConnectionIndex = 0\n\n candidates?: Array<Candidate> | null\n visitedNodes?: Set<CapacityMeshNodeId> | null\n\n computeG(\n prevCandidate: Candidate,\n node: CapacityMeshNode,\n endGoal: CapacityMeshNode,\n ) {\n return (\n prevCandidate.g + this.getDistanceBetweenNodes(prevCandidate.node, node)\n )\n }\n\n computeH(\n prevCandidate: Candidate,\n node: CapacityMeshNode,\n endGoal: CapacityMeshNode,\n ) {\n return this.getDistanceBetweenNodes(node, endGoal)\n }\n\n getBacktrackedPath(candidate: Candidate) {\n const path: CapacityMeshNode[] = []\n let currentCandidate = candidate\n while (currentCandidate) {\n path.push(currentCandidate.node)\n currentCandidate = currentCandidate.prevCandidate!\n }\n return path\n }\n\n getNeighboringNodes(node: CapacityMeshNode) {\n return this.nodeEdgeMap\n .get(node.capacityMeshNodeId)!\n .flatMap((edge): CapacityMeshNodeId[] =>\n edge.nodeIds.filter((n) => n !== node.capacityMeshNodeId),\n )\n .map((n) => this.nodeMap.get(n)!)\n }\n\n getCapacityPaths() {\n const capacityPaths: CapacityPath[] = []\n for (const connection of this.connectionsWithNodes) {\n const path = connection.path\n if (path) {\n capacityPaths.push({\n capacityPathId: connection.connection.name,\n connectionName: connection.connection.name,\n nodeIds: path.map((node) => node.capacityMeshNodeId),\n })\n }\n }\n return capacityPaths\n }\n\n doesNodeHaveCapacityForTrace(\n node: CapacityMeshNode,\n prevNode: CapacityMeshNode,\n ) {\n const usedCapacity =\n this.usedNodeCapacityMap.get(node.capacityMeshNodeId) ?? 0\n const totalCapacity = this.getTotalCapacity(node)\n\n // Single layer nodes can't safely have multiple traces because there's no\n // way to cross over two traces without a via\n if (\n node.availableZ.length === 1 &&\n !node._containsTarget &&\n usedCapacity > 0\n )\n return false\n\n let additionalCapacityRequirement = 0\n if (node.availableZ.length > 1 && prevNode.availableZ.length === 1) {\n additionalCapacityRequirement += 0.5\n }\n\n return usedCapacity + additionalCapacityRequirement < totalCapacity\n }\n\n canTravelThroughObstacle(node: CapacityMeshNode, connectionName: string) {\n const goalNodeIds = this.connectionNameToGoalNodeIds.get(connectionName)\n\n return goalNodeIds?.includes(node.capacityMeshNodeId) ?? false\n }\n\n getDistanceBetweenNodes(A: CapacityMeshNode, B: CapacityMeshNode) {\n return Math.sqrt(\n (A.center.x - B.center.x) ** 2 + (A.center.y - B.center.y) ** 2,\n )\n }\n\n reduceCapacityAlongPath(nextConnection: {\n path?: CapacityMeshNode[]\n }) {\n for (const node of nextConnection.path ?? []) {\n this.usedNodeCapacityMap.set(\n node.capacityMeshNodeId,\n this.usedNodeCapacityMap.get(node.capacityMeshNodeId)! + 1,\n )\n }\n }\n\n isConnectedToEndGoal(node: CapacityMeshNode, endGoal: CapacityMeshNode) {\n return this.nodeEdgeMap\n .get(node.capacityMeshNodeId)!\n .some((edge) => edge.nodeIds.includes(endGoal.capacityMeshNodeId))\n }\n\n _step() {\n const nextConnection =\n this.connectionsWithNodes[this.currentConnectionIndex]\n if (!nextConnection) {\n this.solved = true\n return\n }\n const [start, end] = nextConnection.nodes\n if (!this.candidates) {\n this.candidates = [{ prevCandidate: null, node: start, f: 0, g: 0, h: 0 }]\n this.debug_lastNodeCostMap = new Map()\n this.visitedNodes = new Set([start.capacityMeshNodeId])\n this.activeCandidateStraightLineDistance = distance(\n start.center,\n end.center,\n )\n }\n\n this.candidates.sort((a, b) => a.f - b.f)\n const currentCandidate = this.candidates.shift()\n if (!currentCandidate) {\n // TODO Track failed paths, make sure solver doesn't think it solved\n console.error(\n `Ran out of candidates on connection ${nextConnection.connection.name}`,\n )\n this.currentConnectionIndex++\n this.candidates = null\n this.visitedNodes = null\n this.failed = true\n return\n }\n if (this.isConnectedToEndGoal(currentCandidate.node, end)) {\n nextConnection.path = this.getBacktrackedPath({\n prevCandidate: currentCandidate,\n node: end,\n f: 0,\n g: 0,\n h: 0,\n })\n\n this.reduceCapacityAlongPath(nextConnection)\n\n this.currentConnectionIndex++\n this.candidates = null\n this.visitedNodes = null\n return\n }\n\n const neighborNodes = this.getNeighboringNodes(currentCandidate.node)\n for (const neighborNode of neighborNodes) {\n if (this.visitedNodes?.has(neighborNode.capacityMeshNodeId)) {\n continue\n }\n if (\n !this.doesNodeHaveCapacityForTrace(neighborNode, currentCandidate.node)\n ) {\n continue\n }\n const connectionName =\n this.connectionsWithNodes[this.currentConnectionIndex].connection.name\n if (\n neighborNode._containsObstacle &&\n !this.canTravelThroughObstacle(neighborNode, connectionName)\n ) {\n continue\n }\n const g = this.computeG(currentCandidate, neighborNode, end)\n const h = this.computeH(currentCandidate, neighborNode, end)\n const f = g + h * this.GREEDY_MULTIPLIER\n\n this.debug_lastNodeCostMap.set(neighborNode.capacityMeshNodeId, {\n f,\n g,\n h,\n })\n\n const newCandidate = {\n prevCandidate: currentCandidate,\n node: neighborNode,\n f,\n g,\n h,\n }\n this.candidates.push(newCandidate)\n }\n this.visitedNodes!.add(currentCandidate.node.capacityMeshNodeId)\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n\n // Visualize each solved connection path (draw a line through each node's center)\n if (this.connectionsWithNodes) {\n for (let i = 0; i < this.connectionsWithNodes.length; i++) {\n const conn = this.connectionsWithNodes[i]\n if (conn.path && conn.path.length > 0) {\n const pathPoints = conn.path.map(\n ({ center: { x, y }, width, availableZ }) => ({\n // slight offset to allow viewing overlapping paths\n x: x + ((i % 10) + (i % 19)) * (0.005 * width),\n y: y + ((i % 10) + (i % 19)) * (0.005 * width),\n availableZ,\n }),\n )\n graphics.lines!.push({\n points: pathPoints,\n strokeColor: this.colorMap[conn.connection.name],\n })\n for (let u = 0; u < pathPoints.length; u++) {\n const point = pathPoints[u]\n graphics.points!.push({\n x: point.x,\n y: point.y,\n label: [\n `conn: ${conn.connection.name}`,\n `node: ${conn.path[u].capacityMeshNodeId}`,\n `z: ${point.availableZ.join(\",\")}`,\n ].join(\"\\n\"),\n })\n }\n }\n }\n }\n\n for (const node of this.nodes) {\n const nodeCosts = this.debug_lastNodeCostMap.get(node.capacityMeshNodeId)\n graphics.rects!.push({\n ...createRectFromCapacityNode(node, {\n rectMargin: 0.025,\n zOffset: 0.01,\n }),\n label: [\n `${node.capacityMeshNodeId}`,\n `${this.usedNodeCapacityMap.get(node.capacityMeshNodeId)}/${this.getTotalCapacity(node).toFixed(2)}`,\n `${node.width.toFixed(2)}x${node.height.toFixed(2)}`,\n `g: ${nodeCosts?.g !== undefined ? nodeCosts.g.toFixed(2) : \"?\"}`,\n `h: ${nodeCosts?.h !== undefined ? nodeCosts.h.toFixed(2) : \"?\"}`,\n `f: ${nodeCosts?.f !== undefined ? nodeCosts.f.toFixed(2) : \"?\"}`,\n `z: ${node.availableZ.join(\", \")}`,\n ].join(\"\\n\"),\n })\n }\n\n // Visualize connection points from each connection as circles\n if (this.connectionsWithNodes) {\n for (const conn of this.connectionsWithNodes) {\n if (conn.connection?.pointsToConnect) {\n for (const point of conn.connection.pointsToConnect) {\n graphics.points!.push({\n x: point.x,\n y: point.y,\n label: [`pointsToConnect ${conn.connection.name}`].join(\"\\n\"),\n })\n }\n }\n }\n }\n\n // Draw a dashed line from the start node to the end node\n const nextConnection =\n this.connectionsWithNodes[this.currentConnectionIndex]\n if (nextConnection) {\n const [start, end] = nextConnection.connection.pointsToConnect\n graphics.lines!.push({\n points: [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ],\n strokeColor: \"red\",\n strokeDash: \"10 5\",\n })\n }\n\n // Visualize backtracked path of highest ranked candidate\n if (this.candidates) {\n // Get top 10 candidates\n const topCandidates = this.candidates.slice(0, 5)\n const connectionName =\n this.connectionsWithNodes[this.currentConnectionIndex].connection.name\n\n // Add paths for each candidate with decreasing opacity\n topCandidates.forEach((candidate, index) => {\n const opacity = 0.5 * (1 - index / 5) // Opacity decreases from 0.5 to 0.05\n const backtrackedPath = this.getBacktrackedPath(candidate)\n graphics.lines!.push({\n points: backtrackedPath.map(({ center: { x, y } }) => ({ x, y })),\n strokeColor: safeTransparentize(\n this.colorMap[connectionName] ?? \"red\",\n 1 - opacity,\n ),\n })\n })\n }\n\n return graphics\n }\n}\n","import type { CapacityMeshNode } from \"lib/types\"\nimport { CapacityPathingSolver, type Candidate } from \"./CapacityPathingSolver\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\n\nexport class CapacityPathingSolver5 extends CapacityPathingSolver {\n NEGATIVE_CAPACITY_PENALTY_FACTOR = 1\n REDUCED_CAPACITY_PENALTY_FACTOR = 1\n\n constructor(...args: ConstructorParameters<typeof CapacityPathingSolver>) {\n super(...args)\n this.GREEDY_MULTIPLIER = 2.5\n }\n\n get maxCapacityFactor() {\n return this.hyperParameters.MAX_CAPACITY_FACTOR ?? 1\n }\n\n getTotalCapacity(node: CapacityMeshNode): number {\n return getTunedTotalCapacity1(node, this.maxCapacityFactor)\n }\n\n /**\n * Penalty you pay for using this node\n */\n getNodeCapacityPenalty(node: CapacityMeshNode): number {\n // return 0.05\n\n const MAX_PENALTY = node.width + node.height\n const MIN_PENALTY = 0.05\n\n const START_PENALIZING_CAPACITY_WHEN_IT_DROPS_BELOW = 2\n\n const totalCapacity = this.getTotalCapacity(node)\n const usedCapacity =\n this.usedNodeCapacityMap.get(node.capacityMeshNodeId) ?? 0\n const remainingCapacity = totalCapacity - usedCapacity\n\n if (remainingCapacity > START_PENALIZING_CAPACITY_WHEN_IT_DROPS_BELOW) {\n return MIN_PENALTY\n }\n\n const penalty =\n (MAX_PENALTY - MIN_PENALTY) *\n Math.max(\n 1,\n (START_PENALIZING_CAPACITY_WHEN_IT_DROPS_BELOW - remainingCapacity) /\n (MAX_PENALTY - MIN_PENALTY),\n ) +\n MIN_PENALTY\n\n return penalty\n // const penalty =\n // (MAX_PENALTY - MIN_PENALTY) *\n // (remainingCapacity / START_PENALIZING_CAPACITY_WHEN_IT_DROPS_BELOW)\n\n // return penalty\n // if (node.availableZ.length === 1) {\n // return 0\n // }\n\n // const dist = this.activeCandidateStraightLineDistance!\n\n // if (remainingCapacity <= 0) {\n // // | Total Cap | Remaining Cap | Remaining Cap Ratio | PenaltySLD |\n // // | 1 | 0 | (-( 0) + 1) / 1 | 1^2 = 1 |\n // // | 1 | -1 | (-(-1) + 1) / 1 | 2^2 = 4 |\n // // | 1 | -2 | (-(-2) + 1) / 1 | 3^2 = 9 |\n // // | 2 | 0 | (-( 0) + 1) / 2 | 0.5^2 = 0.25 |\n // // | 2 | -1 | (-(-1) + 1) / 2 | 1^2 = 1 |\n // // | 2 | -2 | (-(-2) + 1) / 2 | 2^2 = 4 |\n // // | 2 | -3 | (-(-3) + 1) / 2 | 3^2 = 9 |\n // // | 3 | 0 | (-( 0) + 1) / 3 | 0.333^2= 0.111|\n // // | 3 | -1 | (-(-1) + 1) / 3 | 0.666^2= 0.444|\n // // | 3 | -2 | (-(-2) + 1) / 3 | 1^2 = 1 |\n // // | 3 | -3 | (-(-3) + 1) / 3 | 2^2 = 4 |\n // const penalty =\n // ((-remainingCapacity + 1) / totalCapacity) *\n // dist *\n // (this.NEGATIVE_CAPACITY_PENALTY_FACTOR / 4)\n\n // return penalty ** 2\n // }\n\n // This node still has capacity, but penalize as we reduce the capacity\n // return (\n // ((1 / remainingCapacity) * dist * this.REDUCED_CAPACITY_PENALTY_FACTOR) /\n // 8\n // )\n }\n\n /**\n * We're rewarding travel into big nodes.\n *\n * To minimize shortest path, you'd want to comment this out.\n */\n getDistanceBetweenNodes(A: CapacityMeshNode, B: CapacityMeshNode) {\n const dx = A.center.x - B.center.x\n const dy = A.center.y - B.center.y\n\n return Math.sqrt(dx ** 2 + dy ** 2)\n\n // REWARD BIG NODE TRAVEL\n // const szx = Math.max(A.width, B.width)\n // const szy = Math.max(A.height, B.height)\n\n // const dist = Math.sqrt(dx ** 2 + dy ** 2) / (szx * szy)\n\n // return dist\n }\n\n computeG(\n prevCandidate: Candidate,\n node: CapacityMeshNode,\n endGoal: CapacityMeshNode,\n ) {\n return (\n prevCandidate.g +\n this.getDistanceBetweenNodes(prevCandidate.node, node) +\n this.getNodeCapacityPenalty(node)\n )\n }\n\n computeH(\n prevCandidate: Candidate,\n node: CapacityMeshNode,\n endGoal: CapacityMeshNode,\n ) {\n return (\n this.getDistanceBetweenNodes(node, endGoal) +\n this.getNodeCapacityPenalty(node)\n )\n }\n}\n","import { CapacityMeshNode } from \"lib/types/capacity-mesh-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\n\nexport class StrawSolver extends BaseSolver {\n multiLayerNodes: CapacityMeshNode[]\n\n strawNodes: CapacityMeshNode[]\n skippedNodes: CapacityMeshNode[]\n\n unprocessedNodes: CapacityMeshNode[]\n strawSize: number\n\n nodeIdCounter: number\n\n constructor(params: {\n nodes: CapacityMeshNode[]\n strawSize?: number\n }) {\n super()\n this.MAX_ITERATIONS = 100e3\n this.strawSize = params.strawSize ?? 0.5\n this.multiLayerNodes = []\n this.strawNodes = []\n this.skippedNodes = []\n this.nodeIdCounter = 0\n this.unprocessedNodes = []\n for (const node of params.nodes) {\n if (node.availableZ.length === 1) {\n this.unprocessedNodes.push(node)\n } else {\n this.multiLayerNodes.push(node)\n }\n }\n }\n\n getCapacityOfMultiLayerNodesWithinBounds(bounds: {\n minX: number\n maxX: number\n minY: number\n maxY: number\n }): number {\n let totalCapacity = 0\n\n for (const node of this.multiLayerNodes) {\n // Calculate node bounds\n const nodeMinX = node.center.x - node.width / 2\n const nodeMaxX = node.center.x + node.width / 2\n const nodeMinY = node.center.y - node.height / 2\n const nodeMaxY = node.center.y + node.height / 2\n\n // Calculate overlap area\n const overlapMinX = Math.max(bounds.minX, nodeMinX)\n const overlapMaxX = Math.min(bounds.maxX, nodeMaxX)\n const overlapMinY = Math.max(bounds.minY, nodeMinY)\n const overlapMaxY = Math.min(bounds.maxY, nodeMaxY)\n\n // If there's an overlap\n if (overlapMinX < overlapMaxX && overlapMinY < overlapMaxY) {\n const overlapWidth = overlapMaxX - overlapMinX\n const overlapHeight = overlapMaxY - overlapMinY\n const overlapArea = overlapWidth * overlapHeight\n const nodeArea = node.width * node.height\n\n // Calculate proportion of node that overlaps\n const proportion = overlapArea / nodeArea\n\n // Add proportional capacity to total\n totalCapacity += getTunedTotalCapacity1(node) * proportion\n }\n }\n\n return totalCapacity\n }\n\n getSurroundingCapacities(node: CapacityMeshNode): {\n leftSurroundingCapacity: number\n rightSurroundingCapacity: number\n topSurroundingCapacity: number\n bottomSurroundingCapacity: number\n } {\n const searchDistance = Math.min(node.width, node.height)\n\n const leftSurroundingCapacity =\n this.getCapacityOfMultiLayerNodesWithinBounds({\n minX: node.center.x - node.width / 2 - searchDistance,\n maxX: node.center.x - node.width / 2,\n minY: node.center.y - node.height / 2,\n maxY: node.center.y + node.height / 2,\n })\n\n const rightSurroundingCapacity =\n this.getCapacityOfMultiLayerNodesWithinBounds({\n minX: node.center.x + node.width / 2,\n maxX: node.center.x + node.width / 2 + searchDistance,\n minY: node.center.y - node.height / 2,\n maxY: node.center.y + node.height / 2,\n })\n\n const topSurroundingCapacity =\n this.getCapacityOfMultiLayerNodesWithinBounds({\n minX: node.center.x - node.width / 2,\n maxX: node.center.x + node.width / 2,\n minY: node.center.y - node.height / 2 - searchDistance,\n maxY: node.center.y - node.height / 2,\n })\n\n const bottomSurroundingCapacity =\n this.getCapacityOfMultiLayerNodesWithinBounds({\n minX: node.center.x - node.width / 2,\n maxX: node.center.x + node.width / 2,\n minY: node.center.y + node.height / 2,\n maxY: node.center.y + node.height / 2 + searchDistance,\n })\n\n return {\n leftSurroundingCapacity,\n rightSurroundingCapacity,\n topSurroundingCapacity,\n bottomSurroundingCapacity,\n }\n }\n /**\n * Creates straw nodes from a single-layer node based on surrounding capacities\n */\n createStrawsForNode(node: CapacityMeshNode): CapacityMeshNode[] {\n const result: CapacityMeshNode[] = []\n const {\n leftSurroundingCapacity,\n rightSurroundingCapacity,\n topSurroundingCapacity,\n bottomSurroundingCapacity,\n } = this.getSurroundingCapacities(node)\n\n // Decide whether to create horizontal or vertical straws\n const horizontalCapacity =\n leftSurroundingCapacity + rightSurroundingCapacity\n const verticalCapacity = topSurroundingCapacity + bottomSurroundingCapacity\n\n // Layer-specific preferred direction\n // Layer 0 (top) prefers horizontal traces, Layer 1 (bottom) prefers vertical\n const layerPrefersFactor = 1 // node.availableZ[0] === 0 ? 1.3 : 0.7\n\n const effectiveHorizontalCapacity = horizontalCapacity * layerPrefersFactor\n\n // Create straws based on dimensions and surrounding capacity\n if (effectiveHorizontalCapacity > verticalCapacity) {\n // Create horizontal straws\n const numStraws = Math.floor(node.height / this.strawSize)\n const strawHeight = node.height / numStraws\n\n for (let i = 0; i < numStraws; i++) {\n const strawCenterY =\n node.center.y - node.height / 2 + i * strawHeight + strawHeight / 2\n\n result.push({\n capacityMeshNodeId: `${node.capacityMeshNodeId}_straw${i}`,\n center: { x: node.center.x, y: strawCenterY },\n width: node.width,\n height: strawHeight,\n layer: node.layer,\n availableZ: [...node.availableZ],\n _depth: node._depth,\n _strawNode: true,\n _strawParentCapacityMeshNodeId: node.capacityMeshNodeId,\n })\n }\n } else {\n // Create vertical straws\n const numStraws = Math.floor(node.width / this.strawSize)\n const strawWidth = node.width / numStraws\n\n for (let i = 0; i < numStraws; i++) {\n const strawCenterX =\n node.center.x - node.width / 2 + i * strawWidth + strawWidth / 2\n\n result.push({\n capacityMeshNodeId: `${node.capacityMeshNodeId}_straw${i}`,\n center: { x: strawCenterX, y: node.center.y },\n width: strawWidth,\n height: node.height,\n layer: node.layer,\n availableZ: [...node.availableZ],\n _depth: node._depth,\n _strawNode: true,\n _strawParentCapacityMeshNodeId: node.capacityMeshNodeId,\n })\n }\n }\n\n return result\n }\n\n getResultNodes(): CapacityMeshNode[] {\n return [...this.multiLayerNodes, ...this.strawNodes, ...this.skippedNodes]\n }\n\n _step() {\n const rootNode = this.unprocessedNodes.pop()\n\n if (!rootNode) {\n this.solved = true\n return\n }\n\n // Skip nodes that are too small to subdivide\n if (rootNode.width < this.strawSize && rootNode.height < this.strawSize) {\n this.skippedNodes.push(rootNode)\n return\n }\n\n // Skip target nodes (keep them intact)\n if (rootNode._containsTarget) {\n this.skippedNodes.push(rootNode)\n return\n }\n\n // Create straws for this node\n const strawNodes = this.createStrawsForNode(rootNode)\n this.strawNodes.push(...strawNodes)\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n rects: [],\n lines: [],\n points: [],\n circles: [],\n title: \"Straw Solver\",\n }\n\n // Draw unprocessed nodes\n for (const node of this.unprocessedNodes) {\n graphics.rects!.push({\n center: node.center,\n width: node.width,\n height: node.height,\n fill: \"rgba(200, 200, 200, 0.5)\",\n stroke: \"rgba(0, 0, 0, 0.5)\",\n label: `${node.capacityMeshNodeId}\\nUnprocessed\\n${node.width}x${node.height}`,\n })\n }\n\n // Draw straw nodes with different colors based on layer\n for (const node of this.strawNodes) {\n const color =\n node.availableZ[0] === 0\n ? \"rgba(0, 150, 255, 0.5)\"\n : \"rgba(255, 100, 0, 0.5)\"\n\n graphics.rects!.push({\n center: node.center,\n width: node.width,\n height: node.height,\n fill: color,\n stroke: \"rgba(0, 0, 0, 0.5)\",\n label: `${node.capacityMeshNodeId}\\nLayer: ${node.availableZ[0]}\\n${node.width}x${node.height}`,\n layer: `z${node.availableZ.join(\",\")}`,\n })\n }\n\n // Draw multi-layer nodes\n for (const node of this.multiLayerNodes) {\n graphics.rects!.push({\n center: node.center,\n width: node.width * 0.9,\n height: node.height * 0.9,\n fill: \"rgba(100, 255, 100, 0.5)\",\n stroke: \"rgba(0, 0, 0, 0.5)\",\n layer: `z${node.availableZ.join(\",\")}`,\n label: `${node.capacityMeshNodeId}\\nLayers: ${node.availableZ.join(\",\")}\\n${node.width}x${node.height}`,\n })\n }\n\n return graphics\n }\n}\n","import { CapacityMeshNode } from \"../types\"\n\nexport function areNodesBordering(\n node1: CapacityMeshNode,\n node2: CapacityMeshNode,\n): boolean {\n const n1Left = node1.center.x - node1.width / 2\n const n1Right = node1.center.x + node1.width / 2\n const n1Top = node1.center.y - node1.height / 2\n const n1Bottom = node1.center.y + node1.height / 2\n\n const n2Left = node2.center.x - node2.width / 2\n const n2Right = node2.center.x + node2.width / 2\n const n2Top = node2.center.y - node2.height / 2\n const n2Bottom = node2.center.y + node2.height / 2\n\n const epsilon = 0.001\n\n const shareVerticalBorder =\n (Math.abs(n1Right - n2Left) < epsilon ||\n Math.abs(n1Left - n2Right) < epsilon) &&\n Math.min(n1Bottom, n2Bottom) - Math.max(n1Top, n2Top) >= epsilon\n\n const shareHorizontalBorder =\n (Math.abs(n1Bottom - n2Top) < epsilon ||\n Math.abs(n1Top - n2Bottom) < epsilon) &&\n Math.min(n1Right, n2Right) - Math.max(n1Left, n2Left) >= epsilon\n\n return shareVerticalBorder || shareHorizontalBorder\n}\n","import { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\n\nexport type BucketCoordinate = `${number}x${number}`\n\nexport class CapacityNodeTree {\n buckets: Map<BucketCoordinate, CapacityMeshNode[]>\n CELL_SIZE = 0.4\n\n constructor(public nodes: CapacityMeshNode[]) {\n this.buckets = new Map()\n for (const node of nodes) {\n const nodeMinX = node.center.x - node.width / 2\n const nodeMinY = node.center.y - node.height / 2\n const nodeMaxX = node.center.x + node.width / 2\n const nodeMaxY = node.center.y + node.height / 2\n for (let x = nodeMinX; x <= nodeMaxX; x += this.CELL_SIZE) {\n for (let y = nodeMinY; y <= nodeMaxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey)\n if (!bucket) {\n this.buckets.set(bucketKey, [node])\n } else {\n bucket.push(node)\n }\n }\n }\n }\n }\n\n getBucketKey(x: number, y: number): BucketCoordinate {\n return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`\n }\n\n getNodesInArea(\n centerX: number,\n centerY: number,\n width: number,\n height: number,\n ) {\n const nodes: CapacityMeshNode[] = []\n const alreadyAddedNodes = new Set<CapacityMeshNodeId>()\n const minX = centerX - width / 2\n const minY = centerY - height / 2\n const maxX = centerX + width / 2\n const maxY = centerY + height / 2\n for (let x = minX; x <= maxX; x += this.CELL_SIZE) {\n for (let y = minY; y <= maxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey) || []\n for (const node of bucket) {\n if (alreadyAddedNodes.has(node.capacityMeshNodeId)) continue\n alreadyAddedNodes.add(node.capacityMeshNodeId)\n nodes.push(node)\n }\n }\n }\n return nodes\n }\n}\n","import { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { areNodesBordering } from \"lib/utils/areNodesBordering\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { createRectFromCapacityNode } from \"lib/utils/createRectFromCapacityNode\"\nimport { CapacityNodeTree } from \"lib/data-structures/CapacityNodeTree\"\n\nconst EPSILON = 0.005\n\n/**\n * Merges same layer nodes into larger nodes. Pre-processing stage necessary\n * for \"strawing\".\n */\nexport class SingleLayerNodeMergerSolver extends BaseSolver {\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n currentBatchNodeIds: CapacityMeshNodeId[]\n\n absorbedNodeIds: Set<CapacityMeshNodeId>\n\n nextBatchNodeIds: CapacityMeshNodeId[]\n batchHadModifications: boolean\n\n hasComputedAdjacentNodeIds: boolean = false\n\n newNodes: CapacityMeshNode[]\n constructor(nodes: CapacityMeshNode[]) {\n super()\n this.nodeMap = new Map()\n this.MAX_ITERATIONS = 100_000\n // TODO we probably don't need this map because we only care about\n // nodes that need to be absorbed or processed\n for (const node of nodes) {\n this.nodeMap.set(node.capacityMeshNodeId, node)\n }\n this.newNodes = []\n this.absorbedNodeIds = new Set()\n const unprocessedNodesWithArea: Array<[CapacityMeshNode, number]> = []\n for (const node of nodes) {\n if (node.availableZ.length > 1) {\n this.newNodes.push(node)\n this.absorbedNodeIds.add(node.capacityMeshNodeId)\n } else {\n unprocessedNodesWithArea.push([node, node.width * node.height])\n }\n }\n unprocessedNodesWithArea.sort((a, b) => a[1] - b[1])\n for (const [node, area] of unprocessedNodesWithArea) {\n const unprocessedNode = {\n ...node,\n center: { ...node.center },\n }\n this.nodeMap.set(node.capacityMeshNodeId, unprocessedNode)\n }\n this.currentBatchNodeIds = unprocessedNodesWithArea.map(\n ([node]) => node.capacityMeshNodeId,\n )\n this.nextBatchNodeIds = []\n this.batchHadModifications = false\n }\n\n computeAdjacentNodeIdsForFirstBatch(nodes: CapacityMeshNode[]) {\n const nodeTrees = [\n new CapacityNodeTree(nodes.filter((n) => n.availableZ[0] === 0)),\n new CapacityNodeTree(nodes.filter((n) => n.availableZ[0] === 1)),\n ]\n for (const node of nodes) {\n const adjacentNodes: CapacityMeshNode[] = []\n const z = node.availableZ[0]\n\n const nodesInArea = nodeTrees[z].getNodesInArea(\n node.center.x,\n node.center.y,\n node.width * 4,\n node.height * 4,\n )\n\n for (const unprocessedNode of nodesInArea) {\n if (\n unprocessedNode._containsTarget &&\n unprocessedNode._targetConnectionName !== node._targetConnectionName\n )\n continue\n // if (this.absorbedNodeIds.has(unprocessedNode.capacityMeshNodeId))\n // continue\n if (unprocessedNode.capacityMeshNodeId === node.capacityMeshNodeId)\n continue\n if (!areNodesBordering(node, unprocessedNode)) continue\n\n adjacentNodes.push(unprocessedNode)\n }\n\n node._adjacentNodeIds = adjacentNodes.map((n) => n.capacityMeshNodeId)\n }\n }\n\n // getAdjacentSameLayerUnprocessedNodes1(rootNode: CapacityMeshNode) {\n // const adjacentNodes: CapacityMeshNode[] = []\n // for (const unprocessedNodeId of this.currentBatchNodeIds) {\n // const unprocessedNode = this.nodeMap.get(unprocessedNodeId)!\n // if (!areNodesBordering(rootNode, unprocessedNode)) continue\n // if (unprocessedNode.availableZ[0] !== rootNode.availableZ[0]) continue\n // if (\n // unprocessedNode._containsTarget &&\n // unprocessedNode._targetConnectionName !== rootNode._targetConnectionName\n // )\n // continue\n // if (this.absorbedNodeIds.has(unprocessedNodeId)) continue\n // adjacentNodes.push(unprocessedNode)\n // }\n // return adjacentNodes\n // }\n\n getAdjacentSameLayerUnprocessedNodes(rootNode: CapacityMeshNode) {\n return this.getAdjacentSameLayerUnprocessedNodes2(rootNode)\n }\n\n getAdjacentSameLayerUnprocessedNodes2(rootNode: CapacityMeshNode) {\n const adjacentNodes: CapacityMeshNode[] = []\n const unprocessedAdjNodes: CapacityMeshNode[] = Array.from(\n new Set(\n (rootNode._adjacentNodeIds ?? []).map((a) => this.nodeMap.get(a)!),\n ),\n )\n\n unprocessedAdjNodes.sort((a, b) => a.width * a.height - b.width * b.height)\n\n for (const unprocessedNode of unprocessedAdjNodes) {\n if (this.absorbedNodeIds.has(unprocessedNode.capacityMeshNodeId)) continue\n adjacentNodes.push(unprocessedNode)\n }\n\n return adjacentNodes\n }\n\n _step() {\n if (!this.hasComputedAdjacentNodeIds) {\n this.computeAdjacentNodeIdsForFirstBatch(\n this.currentBatchNodeIds.map((id) => this.nodeMap.get(id)!),\n )\n this.hasComputedAdjacentNodeIds = true\n }\n let rootNodeId = this.currentBatchNodeIds.pop()\n while (rootNodeId && this.absorbedNodeIds.has(rootNodeId)) {\n rootNodeId = this.currentBatchNodeIds.pop()\n }\n\n if (!rootNodeId) {\n if (this.batchHadModifications) {\n this.currentBatchNodeIds = this.nextBatchNodeIds.sort((a, b) => {\n const A = this.nodeMap.get(a)!\n const B = this.nodeMap.get(b)!\n return A.width * A.height - B.width * B.height\n })\n this.nextBatchNodeIds = []\n this.batchHadModifications = false\n return\n }\n\n this.solved = true\n this.newNodes.push(\n ...this.nextBatchNodeIds.map((id) => this.nodeMap.get(id)!),\n )\n return\n }\n\n const rootNode = this.nodeMap.get(rootNodeId)!\n let rootNodeHasGrown = false\n\n const adjacentNodes = this.getAdjacentSameLayerUnprocessedNodes(rootNode)\n\n if (adjacentNodes.length === 0) {\n this.nextBatchNodeIds.push(rootNodeId)\n return\n }\n\n const absorbAdjacentNodeIds = (nodesToAbsorb: CapacityMeshNode[]) => {\n for (const adjNode of nodesToAbsorb) {\n this.absorbedNodeIds.add(adjNode.capacityMeshNodeId)\n }\n\n rootNode._adjacentNodeIds = Array.from(\n new Set(\n [\n ...(rootNode._adjacentNodeIds ?? []),\n ...nodesToAbsorb.flatMap((n) => n._adjacentNodeIds ?? []),\n ].filter((id) => !this.absorbedNodeIds.has(id)),\n ),\n )\n }\n\n // Handle adjacent nodes to the LEFT\n const adjacentNodesToLeft = adjacentNodes.filter(\n (adjNode) =>\n adjNode.center.x < rootNode.center.x &&\n Math.abs(adjNode.center.y - rootNode.center.y) < rootNode.height / 2,\n )\n\n if (adjacentNodesToLeft.length > 0) {\n const { width: leftAdjNodeWidth, height: leftAdjNodeHeight } =\n adjacentNodesToLeft[0]\n const leftAdjNodesAreAllSameSize = adjacentNodesToLeft.every(\n (adjNode) =>\n adjNode.width === leftAdjNodeWidth &&\n adjNode.height === leftAdjNodeHeight,\n )\n\n const leftAdjNodesTakeUpEntireHeight =\n Math.abs(\n adjacentNodesToLeft.reduce((acc, adjNode) => {\n return acc + adjNode.height\n }, 0) - rootNode.height,\n ) < EPSILON\n\n if (leftAdjNodesTakeUpEntireHeight && leftAdjNodesAreAllSameSize) {\n rootNode.width += leftAdjNodeWidth\n rootNode.center.x = rootNode.center.x - leftAdjNodeWidth / 2\n\n absorbAdjacentNodeIds(adjacentNodesToLeft)\n\n rootNodeHasGrown = true\n }\n }\n\n // Handle adjacent nodes to the RIGHT\n const adjacentNodesToRight = adjacentNodes.filter(\n (adjNode) =>\n adjNode.center.x > rootNode.center.x &&\n Math.abs(adjNode.center.y - rootNode.center.y) < rootNode.height / 2,\n )\n\n if (adjacentNodesToRight.length > 0 && !rootNodeHasGrown) {\n const { width: rightAdjNodeWidth, height: rightAdjNodeHeight } =\n adjacentNodesToRight[0]\n const rightAdjNodesAreAllSameSize = adjacentNodesToRight.every(\n (adjNode) =>\n adjNode.width === rightAdjNodeWidth &&\n adjNode.height === rightAdjNodeHeight,\n )\n\n const rightAdjNodesTakeUpEntireHeight =\n Math.abs(\n adjacentNodesToRight.reduce((acc, adjNode) => {\n return acc + adjNode.height\n }, 0) - rootNode.height,\n ) < EPSILON\n\n if (rightAdjNodesTakeUpEntireHeight && rightAdjNodesAreAllSameSize) {\n rootNode.width += rightAdjNodeWidth\n rootNode.center.x = rootNode.center.x + rightAdjNodeWidth / 2\n\n absorbAdjacentNodeIds(adjacentNodesToRight)\n\n rootNodeHasGrown = true\n }\n }\n\n // Handle adjacent nodes to the TOP\n const adjacentNodesToTop = adjacentNodes.filter(\n (adjNode) =>\n adjNode.center.y > rootNode.center.y &&\n Math.abs(adjNode.center.x - rootNode.center.x) < rootNode.width / 2,\n )\n\n if (adjacentNodesToTop.length > 0 && !rootNodeHasGrown) {\n const { width: topAdjNodeWidth, height: topAdjNodeHeight } =\n adjacentNodesToTop[0]\n const topAdjNodesAreAllSameSize = adjacentNodesToTop.every(\n (adjNode) =>\n adjNode.width === topAdjNodeWidth &&\n adjNode.height === topAdjNodeHeight,\n )\n\n const topAdjNodesTakeUpEntireWidth =\n Math.abs(\n adjacentNodesToTop.reduce((acc, adjNode) => {\n return acc + adjNode.width\n }, 0) - rootNode.width,\n ) < EPSILON\n\n if (topAdjNodesTakeUpEntireWidth && topAdjNodesAreAllSameSize) {\n rootNode.height += topAdjNodeHeight\n rootNode.center.y = rootNode.center.y + topAdjNodeHeight / 2\n\n absorbAdjacentNodeIds(adjacentNodesToTop)\n\n rootNodeHasGrown = true\n }\n }\n\n // Handle adjacent nodes to the BOTTOM\n const adjacentNodesToBottom = adjacentNodes.filter(\n (adjNode) =>\n adjNode.center.y < rootNode.center.y &&\n Math.abs(adjNode.center.x - rootNode.center.x) < rootNode.width / 2,\n )\n\n if (adjacentNodesToBottom.length > 0 && !rootNodeHasGrown) {\n const { width: bottomAdjNodeWidth, height: bottomAdjNodeHeight } =\n adjacentNodesToBottom[0]\n const bottomAdjNodesAreAllSameSize = adjacentNodesToBottom.every(\n (adjNode) =>\n adjNode.width === bottomAdjNodeWidth &&\n adjNode.height === bottomAdjNodeHeight,\n )\n\n const bottomAdjNodesTakeUpEntireWidth =\n Math.abs(\n adjacentNodesToBottom.reduce((acc, adjNode) => {\n return acc + adjNode.width\n }, 0) - rootNode.width,\n ) < EPSILON\n\n if (bottomAdjNodesTakeUpEntireWidth && bottomAdjNodesAreAllSameSize) {\n rootNode.height += bottomAdjNodeHeight\n rootNode.center.y = rootNode.center.y - bottomAdjNodeHeight / 2\n\n absorbAdjacentNodeIds(adjacentNodesToBottom)\n\n rootNodeHasGrown = true\n }\n }\n\n if (rootNodeHasGrown) {\n this.batchHadModifications = true\n this.currentBatchNodeIds.push(rootNodeId)\n } else {\n this.nextBatchNodeIds.unshift(rootNodeId)\n // this.processedNodeIds.add(rootNodeId)\n // this.newNodes.push(rootNode)\n }\n }\n\n visualize(): GraphicsObject {\n const graphics = {\n circles: [],\n lines: [],\n points: [],\n rects: [],\n coordinateSystem: \"cartesian\",\n title: \"Same Layer Node Merger\",\n } as Required<GraphicsObject>\n\n for (const node of this.newNodes) {\n graphics.rects.push(createRectFromCapacityNode(node))\n }\n\n const nextNodeIdInBatch =\n this.currentBatchNodeIds[this.currentBatchNodeIds.length - 1]\n let adjacentNodes: CapacityMeshNode[] | undefined\n if (nextNodeIdInBatch) {\n adjacentNodes = this.getAdjacentSameLayerUnprocessedNodes(\n this.nodeMap.get(nextNodeIdInBatch)!,\n )\n }\n\n // Visualize unprocessed nodes with a different style\n for (const nodeId of this.currentBatchNodeIds) {\n const node = this.nodeMap.get(nodeId)\n if (this.absorbedNodeIds.has(nodeId)) continue\n if (node) {\n const rect = createRectFromCapacityNode(node, {\n rectMargin: 0.01,\n })\n if (nodeId === nextNodeIdInBatch) {\n rect.stroke = \"rgba(0, 255, 0, 0.8)\" // Green for next node in batch\n } else if (\n adjacentNodes?.some(\n (adjNode) => adjNode.capacityMeshNodeId === nodeId,\n )\n ) {\n rect.stroke = \"rgba(128, 0, 128, 0.8)\" // Purple for adjacent nodes\n } else {\n rect.stroke = \"rgba(255, 165, 0, 0.8)\" // Orange border for other nodes\n }\n rect.layer = `z${node.availableZ.join(\",\")}`\n rect.label = `${rect.label}\\n(unprocessed)`\n graphics.rects.push(rect)\n }\n }\n\n // Visualize next batch nodes with a different style\n for (const nodeId of this.nextBatchNodeIds) {\n const node = this.nodeMap.get(nodeId)\n if (this.absorbedNodeIds.has(nodeId)) continue\n if (node) {\n const rect = createRectFromCapacityNode(node, {\n rectMargin: 0.01,\n })\n rect.layer = `z${node.availableZ.join(\",\")}`\n rect.stroke = \"rgba(0, 217, 255, 0.8)\" // Green border\n rect.label = `${rect.label}\\nx: ${node.center.x}, y: ${node.center.y}\\n${node.width}x${node.height}\\n(next batch)`\n graphics.rects.push(rect)\n }\n }\n\n return graphics\n }\n}\n","import { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { Obstacle } from \"lib/types\"\nimport { calculate45DegreePaths } from \"lib/utils/calculate45DegreePaths\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\n\ninterface Point {\n x: number\n y: number\n z: number\n}\n\nexport class SingleSimplifiedPathSolver extends BaseSolver {\n newRoute: HighDensityIntraNodeRoute[\"route\"]\n newVias: HighDensityIntraNodeRoute[\"vias\"]\n\n headIndex = 0\n tailIndex = 0\n\n inputRoute: HighDensityIntraNodeRoute\n otherHdRoutes: HighDensityIntraNodeRoute[]\n obstacles: Obstacle[]\n connMap: ConnectivityMap\n colorMap: Record<string, string>\n\n constructor(params: {\n inputRoute: HighDensityIntraNodeRoute\n otherHdRoutes: HighDensityIntraNodeRoute[]\n obstacles: Obstacle[]\n connMap: ConnectivityMap\n colorMap: Record<string, string>\n }) {\n super()\n\n this.inputRoute = params.inputRoute\n this.otherHdRoutes = params.otherHdRoutes\n this.obstacles = params.obstacles\n this.connMap = params.connMap\n this.colorMap = params.colorMap\n\n this.newRoute = [this.inputRoute.route[0]]\n this.newVias = []\n }\n\n getConstructorParams() {\n return {\n inputRoute: this.inputRoute,\n otherHdRoutes: this.otherHdRoutes,\n obstacles: this.obstacles,\n connMap: this.connMap.netMap,\n colorMap: this.colorMap,\n }\n }\n\n get simplifiedRoute(): HighDensityIntraNodeRoute {\n return {\n connectionName: this.inputRoute.connectionName,\n traceThickness: this.inputRoute.traceThickness,\n viaDiameter: this.inputRoute.viaDiameter,\n route: this.newRoute,\n vias: this.newVias,\n }\n }\n\n isValidPath(pointsInRoute: Point[]): boolean {\n // check that the segments don't intersect with any obstacles or other\n // routes or vias\n throw new Error(\"Not implemented\")\n }\n\n _step() {\n // Each iteration, we're going to increase the head and make sure that\n // there's a compatible simplified path from the tail to the head\n // If there isn't a compatible simplified path, we add a segment to the new\n // route from [tail, tail + (head - tail) / 2] then start our next iteration\n // at tail = tail + Math.ceil((head - tail) / 2)\n // If there is a Z change between the tail and the head, we stop the\n // simplification for that segment (add to newRoute and newVias, set tail to\n // head)\n throw new Error(\"Not implemented\")\n }\n\n getVisualsForNewRouteAndObstacles() {\n const graphics: Required<GraphicsObject> = {\n lines: [],\n points: [],\n circles: [],\n rects: [],\n coordinateSystem: \"cartesian\",\n title: \"Simplified Path Solver\",\n }\n\n // Visualize the original route in red\n for (let i = 0; i < this.inputRoute.route.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: this.inputRoute.route[i].x, y: this.inputRoute.route[i].y },\n {\n x: this.inputRoute.route[i + 1].x,\n y: this.inputRoute.route[i + 1].y,\n },\n ],\n strokeColor: \"rgba(255, 0, 0, 0.8)\",\n strokeDash: this.inputRoute.route[i].z === 1 ? \"5, 5\" : undefined,\n layer: `z${this.inputRoute.route[i].z.toString()}`,\n })\n }\n\n // Visualize the simplified route in green\n for (let i = 0; i < this.newRoute.length; i++) {\n if (i < this.newRoute.length - 1) {\n graphics.lines.push({\n points: [\n { x: this.newRoute[i].x, y: this.newRoute[i].y },\n { x: this.newRoute[i + 1].x, y: this.newRoute[i + 1].y },\n ],\n strokeWidth: 0.15,\n strokeColor: \"rgba(0, 255, 0, 0.8)\",\n strokeDash: this.newRoute[i].z === 1 ? [0.4, 0.4] : undefined,\n layer: `z${this.newRoute[i].z.toString()}`,\n })\n }\n graphics.points.push({\n x: this.newRoute[i].x,\n y: this.newRoute[i].y,\n color: \"rgba(0, 255, 0, 0.8)\",\n label: `z: ${this.newRoute[i].z}`,\n layer: `z${this.newRoute[i].z.toString()}`,\n })\n }\n\n // // Visualize vias\n for (const via of this.newVias) {\n graphics.circles.push({\n center: via,\n radius: this.inputRoute.viaDiameter / 2,\n fill: \"rgba(0, 0, 255, 0.5)\",\n })\n }\n\n // Visualize obstacles\n for (const obstacle of this.obstacles) {\n graphics.rects.push({\n center: obstacle.center,\n width: obstacle.width,\n height: obstacle.height,\n fill: obstacle.layers?.includes(\"top\")\n ? \"rgba(255, 0, 0, 0.3)\"\n : obstacle.layers?.includes(\"bottom\")\n ? \"rgba(0, 0, 255, 0.3)\"\n : \"rgba(128, 128, 128, 0.3)\",\n })\n }\n\n // Visualize other routes as obstacles (in purple)\n for (const route of this.otherHdRoutes) {\n for (let i = 0; i < route.route.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: route.route[i].x, y: route.route[i].y },\n { x: route.route[i + 1].x, y: route.route[i + 1].y },\n ],\n strokeWidth: 0.15,\n strokeColor:\n route.route[i].z === 0\n ? \"rgba(255, 0, 255, 0.5)\" // top layer (purple)\n : route.route[i].z === 1\n ? \"rgba(128, 0, 128, 0.5)\" // inner layer (darker purple)\n : \"rgba(0, 0, 255, 0.5)\", // bottom layer (blue)\n layer: `z${route.route[i].z.toString()}`,\n })\n }\n }\n\n if (\"filteredObstaclePathSegments\" in this) {\n const filteredObstaclePathSegments = this\n .filteredObstaclePathSegments as Array<[Point, Point]>\n for (const [start, end] of filteredObstaclePathSegments) {\n graphics.lines.push({\n points: [start, end],\n })\n }\n }\n\n return graphics\n }\n}\n","interface Point {\n x: number\n y: number\n}\n\nexport const calculate45DegreePaths = (\n pointA: Point,\n pointB: Point,\n): Array<Array<Point>> => {\n const result: Array<Array<Point>> = []\n const dx = Math.abs(pointB.x - pointA.x)\n const dy = Math.abs(pointB.y - pointA.y)\n const signX = pointB.x > pointA.x ? 1 : -1\n const signY = pointB.y > pointA.y ? 1 : -1\n\n // Path 1: Horizontal then 45 degrees\n const midPoint1: Point = {\n x: pointB.x - signX * Math.abs(pointB.y - pointA.y),\n y: pointA.y,\n }\n // Check if midpoint is within bounds\n if (\n (midPoint1.x - pointA.x) * signX >= 0 &&\n (midPoint1.x - pointB.x) * signX <= 0\n ) {\n result.push([pointA, midPoint1, pointB])\n }\n\n // Path 2: Vertical then 45 degrees\n const midPoint2: Point = {\n x: pointA.x,\n y: pointB.y - signY * Math.abs(pointB.x - pointA.x),\n }\n // Check if midpoint is within bounds\n if (\n (midPoint2.y - pointA.y) * signY >= 0 &&\n (midPoint2.y - pointB.y) * signY <= 0\n ) {\n result.push([pointA, midPoint2, pointB])\n }\n\n // // Calculate 45-degree points\n const minDist = Math.min(dx, dy)\n\n // // Path 3: 45 degrees then horizontal\n const midPoint3: Point = {\n x: pointA.x + signX * minDist,\n y: pointA.y + signY * minDist,\n }\n // Check if midpoint is within bounds\n if (\n (midPoint3.x - pointA.x) * signX >= 0 &&\n (midPoint3.x - pointB.x) * signX <= 0 &&\n (midPoint3.y - pointA.y) * signY >= 0 &&\n (midPoint3.y - pointB.y) * signY <= 0\n ) {\n result.push([pointA, midPoint3, pointB])\n }\n\n return result\n}\n","interface Point {\n x: number\n y: number\n}\n\n/**\n * Calculates the minimum distance between two line segments.\n * @param A1 First point of the first line segment\n * @param A2 Second point of the first line segment\n * @param B1 First point of the second line segment\n * @param B2 Second point of the second line segment\n * @returns The minimum distance between the two line segments\n */\nexport function minimumDistanceBetweenSegments(\n A1: Point,\n A2: Point,\n B1: Point,\n B2: Point,\n): number {\n // Check if segments intersect\n if (segmentsIntersect(A1, A2, B1, B2)) {\n return 0\n }\n\n // Calculate distances from each endpoint to the other segment\n const distA1 = pointToSegmentDistance(A1, B1, B2)\n const distA2 = pointToSegmentDistance(A2, B1, B2)\n const distB1 = pointToSegmentDistance(B1, A1, A2)\n const distB2 = pointToSegmentDistance(B2, A1, A2)\n\n // Return the minimum of the four distances\n return Math.min(distA1, distA2, distB1, distB2)\n}\n\n/**\n * Calculates the distance from a point to a line segment.\n * @param P The point\n * @param Q1 First point of the line segment\n * @param Q2 Second point of the line segment\n * @returns The minimum distance from point P to the line segment Q1Q2\n */\nfunction pointToSegmentDistance(P: Point, Q1: Point, Q2: Point): number {\n const v = { x: Q2.x - Q1.x, y: Q2.y - Q1.y }\n const w = { x: P.x - Q1.x, y: P.y - Q1.y }\n\n // Calculate squared length of the segment\n const c1 = dotProduct(w, v)\n if (c1 <= 0) {\n // Point is behind Q1\n return distance(P, Q1)\n }\n\n const c2 = dotProduct(v, v)\n if (c2 <= c1) {\n // Point is beyond Q2\n return distance(P, Q2)\n }\n\n // Point projects onto the segment\n const b = c1 / c2\n const Pb = {\n x: Q1.x + b * v.x,\n y: Q1.y + b * v.y,\n }\n return distance(P, Pb)\n}\n\n/**\n * Calculates the dot product of two vectors.\n */\nfunction dotProduct(\n v1: { x: number; y: number },\n v2: { x: number; y: number },\n): number {\n return v1.x * v2.x + v1.y * v2.y\n}\n\n/**\n * Calculates the Euclidean distance between two points.\n */\nfunction distance(p1: Point, p2: Point): number {\n const dx = p2.x - p1.x\n const dy = p2.y - p1.y\n return Math.sqrt(dx * dx + dy * dy)\n}\n\n/**\n * Determines the orientation of triplet (p, q, r).\n * @returns 0 if collinear, 1 if clockwise, 2 if counterclockwise\n */\nfunction orientation(p: Point, q: Point, r: Point): number {\n const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)\n if (val === 0) return 0 // collinear\n return val > 0 ? 1 : 2 // clockwise or counterclockwise\n}\n\n/**\n * Checks if point q lies on segment pr.\n */\nfunction onSegment(p: Point, q: Point, r: Point): boolean {\n return (\n q.x <= Math.max(p.x, r.x) &&\n q.x >= Math.min(p.x, r.x) &&\n q.y <= Math.max(p.y, r.y) &&\n q.y >= Math.min(p.y, r.y)\n )\n}\n\n/**\n * Checks if two line segments intersect.\n */\nfunction segmentsIntersect(\n A1: Point,\n A2: Point,\n B1: Point,\n B2: Point,\n): boolean {\n // Find the four orientations needed for general case\n const o1 = orientation(A1, A2, B1)\n const o2 = orientation(A1, A2, B2)\n const o3 = orientation(B1, B2, A1)\n const o4 = orientation(B1, B2, A2)\n\n // General case\n if (o1 !== o2 && o3 !== o4) return true\n\n // Special Cases\n // A1, A2 and B1 are collinear and B1 lies on segment A1A2\n if (o1 === 0 && onSegment(A1, B1, A2)) return true\n\n // A1, A2 and B2 are collinear and B2 lies on segment A1A2\n if (o2 === 0 && onSegment(A1, B2, A2)) return true\n\n // B1, B2 and A1 are collinear and A1 lies on segment B1B2\n if (o3 === 0 && onSegment(B1, A1, B2)) return true\n\n // B1, B2 and A2 are collinear and A2 lies on segment B1B2\n if (o4 === 0 && onSegment(B1, A2, B2)) return true\n\n return false // Doesn't fall in any of the above cases\n}\n","interface Point {\n x: number\n y: number\n z: number\n}\n\ntype Segment = [Point, Point]\n\ntype SegmentWithId = [Point, Point, string]\n\nconst getSegmentBounds = (segment: Segment) => {\n return {\n minX: Math.min(segment[0].x, segment[1].x),\n maxX: Math.max(segment[0].x, segment[1].x),\n minY: Math.min(segment[0].y, segment[1].y),\n maxY: Math.max(segment[0].y, segment[1].y),\n }\n}\nexport type BucketCoordinate = `${number}x${number}`\n\nexport class SegmentTree {\n buckets: Map<BucketCoordinate, SegmentWithId[]>\n CELL_SIZE = 0.4\n SEGMENT_MARGIN = 0.4 // traceThickness + obstacleMargin\n\n constructor(public segments: Segment[]) {\n this.buckets = new Map()\n const segmentsById = new Map<string, Segment>() // Avoid adding duplicates if input has them\n\n for (const segment of segments) {\n const segmentKey = this.getSegmentKey(segment)\n if (segmentsById.has(segmentKey)) continue // Skip duplicates in input\n segmentsById.set(segmentKey, segment)\n\n const bounds = getSegmentBounds(segment)\n\n // Calculate min/max integer indices covered by the segment's bounds\n const minIndexX = Math.floor(bounds.minX / this.CELL_SIZE)\n const maxIndexX = Math.floor(bounds.maxX / this.CELL_SIZE)\n const minIndexY = Math.floor(bounds.minY / this.CELL_SIZE)\n const maxIndexY = Math.floor(bounds.maxY / this.CELL_SIZE)\n\n // Iterate through the integer indices\n for (let ix = minIndexX; ix <= maxIndexX; ix++) {\n for (let iy = minIndexY; iy <= maxIndexY; iy++) {\n const bucketKey = `${ix}x${iy}` as BucketCoordinate // Construct key from indices\n const bucket = this.buckets.get(bucketKey)\n const segmentWithId: SegmentWithId = [\n segment[0],\n segment[1],\n segmentKey,\n ]\n\n if (!bucket) {\n this.buckets.set(bucketKey, [segmentWithId])\n } else {\n // Optional: Check if segment already in this specific bucket if constructor might be called multiple times\n // or if input segments could be complex overlaps. Usually not needed if input is processed once.\n bucket.push(segmentWithId)\n }\n }\n }\n }\n }\n\n getBucketKey(x: number, y: number): BucketCoordinate {\n return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`\n }\n\n getSegmentKey(segment: Segment): string {\n return `${segment[0].x}-${segment[0].y}-${segment[0].z}-${segment[1].x}-${segment[1].y}-${segment[1].z}`\n }\n\n getSegmentsThatCouldIntersect(A: Point, B: Point): SegmentWithId[] {\n const segments: SegmentWithId[] = []\n const alreadyAddedSegments = new Set<string>()\n\n // Calculate the margined bounding box of the query segment\n const minX = Math.min(A.x, B.x) - this.SEGMENT_MARGIN\n const minY = Math.min(A.y, B.y) - this.SEGMENT_MARGIN\n const maxX = Math.max(A.x, B.x) + this.SEGMENT_MARGIN\n const maxY = Math.max(A.y, B.y) + this.SEGMENT_MARGIN\n\n // Calculate min/max integer indices covered by the margined query bounds\n const minIndexX = Math.floor(minX / this.CELL_SIZE)\n const maxIndexX = Math.floor(maxX / this.CELL_SIZE)\n const minIndexY = Math.floor(minY / this.CELL_SIZE)\n const maxIndexY = Math.floor(maxY / this.CELL_SIZE)\n\n // Iterate through the integer indices\n for (let ix = minIndexX; ix <= maxIndexX; ix++) {\n for (let iy = minIndexY; iy <= maxIndexY; iy++) {\n const bucketKey = `${ix}x${iy}` as BucketCoordinate // Construct key from indices\n const bucket = this.buckets.get(bucketKey)\n\n if (bucket) {\n // Check if bucket exists\n for (const segment of bucket) {\n const key = segment[2] // The segment key is stored at index 2\n if (!alreadyAddedSegments.has(key)) {\n alreadyAddedSegments.add(key)\n segments.push(segment)\n }\n }\n }\n }\n }\n return segments\n }\n}\n","import {\n doSegmentsIntersect,\n pointToSegmentDistance,\n} from \"@tscircuit/math-utils\"\nimport { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { Obstacle } from \"lib/types\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { SingleSimplifiedPathSolver } from \"./SingleSimplifiedPathSolver\"\nimport { calculate45DegreePaths } from \"lib/utils/calculate45DegreePaths\"\nimport { minimumDistanceBetweenSegments } from \"lib/utils/minimumDistanceBetweenSegments\"\nimport { SegmentTree } from \"lib/data-structures/SegmentTree\"\nimport {\n segmentToBoxMinDistance,\n computeDistanceBetweenBoxes,\n segmentToBoundsMinDistance,\n} from \"@tscircuit/math-utils\"\n\ninterface Point {\n x: number\n y: number\n z: number\n}\n\ninterface PathSegment {\n start: Point\n end: Point\n length: number\n startDistance: number\n endDistance: number\n}\n\nexport class SingleSimplifiedPathSolver5 extends SingleSimplifiedPathSolver {\n private pathSegments: PathSegment[] = []\n private totalPathLength: number = 0\n private headDistanceAlongPath: number = 0\n private tailDistanceAlongPath: number = 0\n private minStepSize: number = 0.25 // Default step size, can be adjusted\n private lastValidPath: Point[] | null = null // Store the current valid path\n private lastValidPathHeadDistance: number = 0\n\n /** Amount the step size is reduced when the step isn't possible */\n STEP_SIZE_REDUCTION_FACTOR = 0.25\n maxStepSize = 4\n currentStepSize = this.maxStepSize\n lastHeadMoveDistance = 0\n\n cachedValidPathSegments: Set<string>\n\n filteredObstacles: Obstacle[] = []\n filteredObstaclePathSegments: Array<[Point, Point]> = []\n filteredVias: Array<{ x: number; y: number; diameter: number }> = []\n\n segmentTree!: SegmentTree\n\n OBSTACLE_MARGIN = 0.1\n TRACE_THICKNESS = 0.15\n\n TAIL_JUMP_RATIO: number = 0.8\n\n constructor(\n params: ConstructorParameters<typeof SingleSimplifiedPathSolver>[0],\n ) {\n super(params)\n\n this.cachedValidPathSegments = new Set()\n\n // Handle empty or single-point routes\n if (this.inputRoute.route.length <= 1) {\n this.newRoute = [...this.inputRoute.route]\n this.solved = true\n return\n }\n\n const bounds = this.inputRoute.route.reduce(\n (acc, point) => {\n acc.minX = Math.min(acc.minX, point.x)\n acc.maxX = Math.max(acc.maxX, point.x)\n acc.minY = Math.min(acc.minY, point.y)\n acc.maxY = Math.max(acc.maxY, point.y)\n return acc\n },\n { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity },\n )\n const boundsBox = {\n center: {\n x: (bounds.minX + bounds.maxX) / 2,\n y: (bounds.minY + bounds.maxY) / 2,\n },\n width: bounds.maxX - bounds.minX,\n height: bounds.maxY - bounds.minY,\n }\n\n this.filteredObstacles = this.obstacles\n .filter(\n (obstacle) =>\n !obstacle.connectedTo.some((id) =>\n this.connMap.areIdsConnected(this.inputRoute.connectionName, id),\n ),\n )\n .filter((obstacle) => {\n if (\n obstacle.connectedTo.some((obsId) =>\n this.connMap.areIdsConnected(this.inputRoute.connectionName, obsId),\n )\n ) {\n return false\n }\n\n const { distance } = computeDistanceBetweenBoxes(boundsBox, obstacle)\n\n if (distance < this.OBSTACLE_MARGIN + 0.5) {\n return true\n }\n\n return false\n })\n\n this.filteredObstaclePathSegments = this.otherHdRoutes.flatMap(\n (hdRoute) => {\n if (\n this.connMap.areIdsConnected(\n this.inputRoute.connectionName,\n hdRoute.connectionName,\n )\n ) {\n return []\n }\n\n const route = hdRoute.route\n const segments: Array<[Point, Point]> = []\n for (let i = 0; i < route.length - 1; i++) {\n const start = route[i]\n const end = route[i + 1]\n\n const minX = Math.min(start.x, end.x)\n const maxX = Math.max(start.x, end.x)\n const minY = Math.min(start.y, end.y)\n const maxY = Math.max(start.y, end.y)\n\n if (\n minX <= bounds.maxX &&\n maxX >= bounds.minX &&\n minY <= bounds.maxY &&\n maxY >= bounds.minY\n ) {\n segments.push([start, end])\n }\n }\n\n return segments\n },\n )\n this.segmentTree = new SegmentTree(this.filteredObstaclePathSegments)\n\n this.filteredVias = this.otherHdRoutes.flatMap((hdRoute) => {\n if (\n this.connMap.areIdsConnected(\n this.inputRoute.connectionName,\n hdRoute.connectionName,\n )\n ) {\n return []\n }\n\n const vias = hdRoute.vias\n const filteredVias: Array<{ x: number; y: number; diameter: number }> = []\n for (const via of vias) {\n const margin =\n this.OBSTACLE_MARGIN +\n this.TRACE_THICKNESS / 2 +\n hdRoute.viaDiameter / 2\n const minX = via.x - margin\n const maxX = via.x + margin\n const minY = via.y - margin\n const maxY = via.y + margin\n\n if (\n minX <= bounds.maxX &&\n maxX >= bounds.minX &&\n minY <= bounds.maxY &&\n maxY >= bounds.minY\n ) {\n filteredVias.push({ ...via, diameter: hdRoute.viaDiameter })\n }\n }\n return filteredVias\n })\n\n // Compute path segments and total length\n this.computePathSegments()\n }\n\n // Compute the path segments and their distances\n private computePathSegments() {\n let cumulativeDistance = 0\n\n for (let i = 0; i < this.inputRoute.route.length - 1; i++) {\n const start = this.inputRoute.route[i]\n const end = this.inputRoute.route[i + 1]\n\n // Calculate segment length using Euclidean distance\n const length =\n Math.sqrt((end.x - start.x) ** 2 + (end.y - start.y) ** 2) + i / 10000\n\n this.pathSegments.push({\n start,\n end,\n length,\n startDistance: cumulativeDistance,\n endDistance: cumulativeDistance + length,\n })\n\n cumulativeDistance += length\n }\n\n this.totalPathLength = cumulativeDistance\n }\n\n // Helper to check if two points are the same\n private arePointsEqual(p1: Point, p2: Point): boolean {\n return p1.x === p2.x && p1.y === p2.y && p1.z === p2.z\n }\n\n // Get point at a specific distance along the path\n private getPointAtDistance(distance: number): Point {\n // Ensure distance is within bounds\n distance = Math.max(0, Math.min(distance, this.totalPathLength))\n\n // Find the segment that contains this distance\n const segment = this.pathSegments.find(\n (seg) => distance >= seg.startDistance && distance <= seg.endDistance,\n )\n\n if (!segment) {\n // Fallback to last point if segment not found\n return this.inputRoute.route[this.inputRoute.route.length - 1]\n }\n\n // Calculate interpolation factor (between 0 and 1)\n const factor = (distance - segment.startDistance) / segment.length\n\n // Interpolate the point\n return {\n x: segment.start.x + factor * (segment.end.x - segment.start.x),\n y: segment.start.y + factor * (segment.end.y - segment.start.y),\n z: factor < 0.5 ? segment.start.z : segment.end.z, // Z doesn't interpolate - use the segment's start z value\n }\n }\n\n // Find nearest index in the original route for a given distance\n private getNearestIndexForDistance(distance: number): number {\n if (distance <= 0) return 0\n if (distance >= this.totalPathLength)\n return this.inputRoute.route.length - 1\n\n // Find the segment that contains this distance\n const segmentIndex = this.pathSegments.findIndex(\n (seg) => distance >= seg.startDistance && distance <= seg.endDistance,\n )\n\n if (segmentIndex === -1) return 0\n\n // If closer to the end of the segment, return the next index\n const segment = this.pathSegments[segmentIndex]\n const midDistance = (segment.startDistance + segment.endDistance) / 2\n\n return distance > midDistance ? segmentIndex + 1 : segmentIndex\n }\n\n // Check if a path segment is valid\n isValidPathSegment(start: Point, end: Point): boolean {\n // Check if the segment intersects with any obstacle\n for (const obstacle of this.filteredObstacles) {\n if (!obstacle.zLayers?.includes(start.z)) {\n continue\n }\n\n const distToObstacle = segmentToBoxMinDistance(start, end, obstacle)\n\n // Check if the line might intersect with this obstacle's borders\n if (distToObstacle < this.OBSTACLE_MARGIN + this.TRACE_THICKNESS / 2) {\n return false\n }\n }\n\n // Check if the segment intersects with any other route\n const segmentsThatCouldIntersect =\n this.segmentTree.getSegmentsThatCouldIntersect(start, end)\n for (const [otherSegA, otherSegB, segId] of segmentsThatCouldIntersect) {\n // Only check intersection if we're on the same layer\n if (otherSegA.z === start.z && otherSegB.z === start.z) {\n const distBetweenSegments = minimumDistanceBetweenSegments(\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n { x: otherSegA.x, y: otherSegA.y },\n { x: otherSegB.x, y: otherSegB.y },\n )\n if (distBetweenSegments < this.OBSTACLE_MARGIN + this.TRACE_THICKNESS) {\n return false\n }\n }\n }\n\n for (const via of this.filteredVias) {\n if (\n pointToSegmentDistance(via, start, end) <\n this.OBSTACLE_MARGIN + via.diameter / 2 + this.TRACE_THICKNESS / 2\n ) {\n return false\n }\n }\n\n return true\n }\n\n // Check if a path with multiple points is valid\n isValidPath(pointsInRoute: Point[]): boolean {\n if (pointsInRoute.length < 2) return true\n\n // Check for layer changes - we don't allow simplifying across layer changes\n for (let i = 0; i < pointsInRoute.length - 1; i++) {\n if (pointsInRoute[i].z !== pointsInRoute[i + 1].z) {\n return false\n }\n }\n\n // Check each segment of the path\n for (let i = 0; i < pointsInRoute.length - 1; i++) {\n if (!this.isValidPathSegment(pointsInRoute[i], pointsInRoute[i + 1])) {\n return false\n }\n }\n\n return true\n }\n\n // Find a valid 45-degree path between two points\n private find45DegreePath(start: Point, end: Point): Point[] | null {\n // Skip if points are the same\n if (this.arePointsEqual(start, end)) {\n return [start]\n }\n\n // Skip 45-degree check if we're on different layers\n if (start.z !== end.z) {\n return null\n }\n\n // Calculate potential 45-degree paths\n const possiblePaths = calculate45DegreePaths(\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n )\n\n // Check each path for validity\n for (const path of possiblePaths) {\n // Convert the 2D points to 3D points with the correct z value\n const fullPath = path.map((p) => ({ x: p.x, y: p.y, z: start.z }))\n\n // Check if this path is valid\n if (this.isValidPath(fullPath)) {\n return fullPath\n }\n }\n\n // No valid 45-degree path found\n return null\n }\n\n // Add a path to the result, skipping the first point if it's already added\n private addPathToResult(path: Point[]) {\n if (path.length === 0) return\n\n for (let i = 0; i < path.length; i++) {\n // Skip the first point if it's already added\n if (\n i === 0 &&\n this.newRoute.length > 0 &&\n this.arePointsEqual(this.newRoute[this.newRoute.length - 1], path[i])\n ) {\n continue\n }\n this.newRoute.push(path[i])\n }\n this.currentStepSize = this.maxStepSize\n }\n\n moveHead(distance: number) {\n this.lastHeadMoveDistance = distance\n this.headDistanceAlongPath = Math.min(\n this.headDistanceAlongPath + distance,\n this.totalPathLength,\n )\n }\n\n stepBackAndReduceStepSize() {\n this.headDistanceAlongPath = Math.max(\n this.tailDistanceAlongPath,\n this.headDistanceAlongPath - this.lastHeadMoveDistance,\n )\n this.currentStepSize = Math.max(\n this.minStepSize,\n this.currentStepSize * this.STEP_SIZE_REDUCTION_FACTOR,\n )\n }\n\n _step() {\n const tailHasReachedEnd = this.tailDistanceAlongPath >= this.totalPathLength\n const headHasReachedEnd = this.headDistanceAlongPath >= this.totalPathLength\n\n if (tailHasReachedEnd) {\n // Make sure to add the last point if needed\n const lastPoint = this.inputRoute.route[this.inputRoute.route.length - 1]\n if (\n this.newRoute.length === 0 ||\n !this.arePointsEqual(this.newRoute[this.newRoute.length - 1], lastPoint)\n ) {\n // TODO find path from tail to end w/ 45 degree paths\n this.newRoute.push(lastPoint)\n }\n this.solved = true\n return\n }\n\n if (headHasReachedEnd) {\n const tailPoint = this.getPointAtDistance(this.tailDistanceAlongPath)\n const endPoint = this.inputRoute.route[this.inputRoute.route.length - 1]\n\n // Try to find a valid 45-degree path\n const path45 = this.find45DegreePath(tailPoint, endPoint)\n\n if (path45) {\n // Add the path to the result\n this.addPathToResult(path45)\n this.solved = true\n return\n } else {\n // No valid 45-degree path to the end,\n // add the current path if any and continue with normal advance\n if (this.lastValidPath) {\n this.addPathToResult(this.lastValidPath)\n this.lastValidPath = null\n this.tailDistanceAlongPath = this.lastValidPathHeadDistance\n } else {\n this.newRoute.push(endPoint)\n this.solved = true\n }\n }\n }\n\n // Increment head distance but don't go past the end of the path\n this.moveHead(this.currentStepSize)\n\n // Get the points between tail and head distances\n const tailPoint = this.getPointAtDistance(this.tailDistanceAlongPath)\n const headPoint = this.getPointAtDistance(this.headDistanceAlongPath)\n\n // Check for layer changes between tail and head\n const tailIndex = this.getNearestIndexForDistance(\n this.tailDistanceAlongPath,\n )\n const headIndex = this.getNearestIndexForDistance(\n this.headDistanceAlongPath,\n )\n\n // If there's a potential layer change in this segment\n let layerChangeBtwHeadAndTail = false\n let layerChangeAtDistance = -1\n\n for (let i = tailIndex; i < headIndex; i++) {\n if (\n i + 1 < this.inputRoute.route.length &&\n this.inputRoute.route[i].z !== this.inputRoute.route[i + 1].z\n ) {\n layerChangeBtwHeadAndTail = true\n // Find the segment with the layer change\n const changeSegmentIndex = i\n layerChangeAtDistance =\n this.pathSegments[changeSegmentIndex].startDistance\n break\n }\n }\n\n if (\n layerChangeBtwHeadAndTail &&\n this.lastHeadMoveDistance > this.minStepSize\n ) {\n this.stepBackAndReduceStepSize()\n return\n }\n\n // If there's a layer change, handle it\n // Inside the _step method, within the layer change handling block:\n if (layerChangeBtwHeadAndTail && layerChangeAtDistance > 0) {\n // Get the point *after* the layer change from the original route.\n // This point's XY coordinates define the via location.\n const indexAfterLayerChange =\n this.getNearestIndexForDistance(layerChangeAtDistance) + 1\n const pointAfterChange = this.inputRoute.route[indexAfterLayerChange]\n const viaLocation = { x: pointAfterChange.x, y: pointAfterChange.y }\n\n // 1. Add the last valid path found *before* the layer change.\n if (this.lastValidPath) {\n this.addPathToResult(this.lastValidPath)\n this.lastValidPath = null // Clear it after adding\n }\n\n // 2. Ensure the route connects *exactly* to the via location on the *previous* layer.\n const lastPointInNewRoute = this.newRoute[this.newRoute.length - 1]\n if (\n lastPointInNewRoute.x !== viaLocation.x ||\n lastPointInNewRoute.y !== viaLocation.y\n ) {\n // Add a point explicitly connecting to the via XY on the layer we are *leaving*.\n this.newRoute.push({\n x: viaLocation.x,\n y: viaLocation.y,\n z: lastPointInNewRoute.z, // Use the Z of the layer we are leaving\n })\n }\n // If the last point was already at the via location, its Z is correct, so we don't need an else.\n\n // 3. Add the via itself.\n this.newVias.push(viaLocation)\n\n // 4. Add the point *after* the layer change, starting the segment on the *new* layer.\n // Ensure this point also uses the precise via location and the *new* Z coordinate.\n this.newRoute.push({\n x: viaLocation.x,\n y: viaLocation.y,\n z: pointAfterChange.z, // Use the Z of the layer we are entering\n })\n\n // 5. Reset state for the next segment.\n this.currentStepSize = this.maxStepSize\n\n // Update tail to the start of the segment *after* the layer change point\n const segmentIndexAfterChange = this.pathSegments.findIndex(\n (seg) => seg.start === pointAfterChange,\n )\n\n if (segmentIndexAfterChange !== -1) {\n this.tailDistanceAlongPath =\n this.pathSegments[segmentIndexAfterChange].startDistance\n this.headDistanceAlongPath = this.tailDistanceAlongPath // Reset head to tail\n this.lastValidPath = null // Ensure lastValidPath is clear\n this.lastValidPathHeadDistance = this.tailDistanceAlongPath\n } else if (indexAfterLayerChange < this.inputRoute.route.length) {\n // Fallback if the exact segment wasn't found but index is valid\n // This might happen due to floating point comparisons if getPointAtDistance was used previously\n console.warn(\n \"Fallback used for tailDistanceAlongPath after layer change\",\n )\n const segment = this.pathSegments.find(\n (seg) => seg.start === this.inputRoute.route[indexAfterLayerChange],\n )\n if (segment) {\n this.tailDistanceAlongPath = segment.startDistance\n this.headDistanceAlongPath = this.tailDistanceAlongPath\n this.lastValidPath = null\n this.lastValidPathHeadDistance = this.tailDistanceAlongPath\n } else {\n console.error(\n \"Could not find segment start after layer change, path might be incomplete.\",\n )\n this.solved = true // Prevent infinite loop\n }\n } else {\n // Layer change occurred at the very last point/segment.\n console.warn(\"Layer change occurred at the end of the path.\")\n // The last point on the new layer is already added. We are done.\n this.solved = true\n }\n\n return // End the step after handling the layer change\n }\n\n // Try to find a valid 45-degree path from tail to head\n const path45 = this.find45DegreePath(tailPoint, headPoint)\n\n if (!path45 && this.lastHeadMoveDistance > this.minStepSize) {\n this.stepBackAndReduceStepSize()\n return\n }\n\n if (!path45 && !this.lastValidPath) {\n const oldTailPoint = this.getPointAtDistance(this.tailDistanceAlongPath)\n\n // Move tail and head forward by stepSize\n this.tailDistanceAlongPath += this.minStepSize\n this.moveHead(this.minStepSize)\n\n const newTailIndex = this.getNearestIndexForDistance(\n this.tailDistanceAlongPath,\n )\n const newTailPoint = this.inputRoute.route[newTailIndex]\n const lastRoutePoint =\n this.inputRoute.route[this.inputRoute.route.length - 1]\n\n // Add the segment from old tail to new tail\n if (\n !this.arePointsEqual(oldTailPoint, newTailPoint) &&\n !this.arePointsEqual(newTailPoint, lastRoutePoint)\n ) {\n this.newRoute.push(newTailPoint)\n }\n\n return\n }\n\n if (path45) {\n // Valid 45-degree path found, store it and continue expanding\n this.lastValidPath = path45\n this.lastValidPathHeadDistance = this.headDistanceAlongPath\n return\n }\n\n // No valid path found, use the last valid path and reset\n if (this.lastValidPath) {\n this.addPathToResult(this.lastValidPath)\n this.lastValidPath = null\n this.tailDistanceAlongPath = this.lastValidPathHeadDistance\n this.moveHead(this.minStepSize)\n }\n }\n\n visualize(): GraphicsObject {\n const graphics = this.getVisualsForNewRouteAndObstacles()\n\n // Highlight current head and tail positions\n const tailPoint = this.getPointAtDistance(this.tailDistanceAlongPath)\n const headPoint = this.getPointAtDistance(this.headDistanceAlongPath)\n\n graphics.points.push({\n x: tailPoint.x,\n y: tailPoint.y,\n color: \"yellow\",\n label: [\"Tail\", `z: ${tailPoint.z}`].join(\"\\n\"),\n })\n\n graphics.points.push({\n x: headPoint.x,\n y: headPoint.y,\n color: \"orange\",\n label: [\"Head\", `z: ${headPoint.z}`].join(\"\\n\"),\n })\n\n const tentativeHead = this.getPointAtDistance(\n this.headDistanceAlongPath + this.currentStepSize,\n )\n graphics.points.push({\n x: tentativeHead.x,\n y: tentativeHead.y,\n color: \"red\",\n label: [\"Tentative Head\", `z: ${tentativeHead.z}`].join(\"\\n\"),\n })\n\n // Add visualization of the path segments\n let distance = 0\n while (distance < this.totalPathLength) {\n const point = this.getPointAtDistance(distance)\n graphics.circles.push({\n center: {\n x: point.x,\n y: point.y,\n },\n radius: 0.05,\n fill: \"rgba(100, 100, 100, 0.5)\",\n })\n distance += this.totalPathLength / 20 // Show 20 markers along the path\n }\n\n // Visualize the current prospective 45-degree path from tail to head\n if (this.lastValidPath && this.lastValidPath.length > 1) {\n // Draw the path in a bright cyan color to make it stand out\n for (let i = 0; i < this.lastValidPath.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: this.lastValidPath[i].x, y: this.lastValidPath[i].y },\n {\n x: this.lastValidPath[i + 1].x,\n y: this.lastValidPath[i + 1].y,\n },\n ],\n strokeColor: \"rgba(0, 255, 255, 0.9)\", // Bright cyan\n strokeDash: \"3, 3\", // Dashed line to indicate it's a prospective path\n })\n }\n }\n\n return graphics\n }\n}\n","import { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { Obstacle } from \"lib/types\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { combineVisualizations } from \"lib/utils/combineVisualizations\"\nimport { SingleSimplifiedPathSolver5 } from \"./SingleSimplifiedPathSolver5_Deg45\"\nimport { SingleSimplifiedPathSolver } from \"./SingleSimplifiedPathSolver\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\n\nexport class MultiSimplifiedPathSolver extends BaseSolver {\n simplifiedHdRoutes: HighDensityIntraNodeRoute[]\n\n currentUnsimplifiedHdRouteIndex = 0\n\n activeSubSolver: SingleSimplifiedPathSolver | null = null\n\n unsimplifiedHdRoutes: HighDensityIntraNodeRoute[]\n obstacles: Obstacle[]\n connMap: ConnectivityMap\n colorMap: Record<string, string>\n\n constructor(params: {\n unsimplifiedHdRoutes: HighDensityIntraNodeRoute[]\n obstacles: Obstacle[]\n connMap?: ConnectivityMap\n colorMap?: Record<string, string>\n }) {\n super()\n this.MAX_ITERATIONS = 100e6\n\n this.unsimplifiedHdRoutes = params.unsimplifiedHdRoutes\n this.obstacles = params.obstacles\n this.connMap = params.connMap || new ConnectivityMap({})\n this.colorMap = params.colorMap || {}\n\n this.simplifiedHdRoutes = []\n }\n\n _step() {\n const hdRoute =\n this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex]\n if (!this.activeSubSolver) {\n if (!hdRoute) {\n this.solved = true\n return\n }\n\n this.activeSubSolver = new SingleSimplifiedPathSolver5({\n inputRoute: hdRoute,\n otherHdRoutes: this.unsimplifiedHdRoutes\n .slice(this.currentUnsimplifiedHdRouteIndex + 1)\n .concat(this.simplifiedHdRoutes),\n obstacles: this.obstacles,\n connMap: this.connMap,\n colorMap: this.colorMap,\n })\n this.currentUnsimplifiedHdRouteIndex++\n return\n }\n\n this.activeSubSolver.step()\n if (this.activeSubSolver.solved) {\n this.simplifiedHdRoutes.push(this.activeSubSolver.simplifiedRoute)\n this.activeSubSolver = null\n }\n }\n\n visualize(): GraphicsObject {\n if (this.activeSubSolver) {\n return this.activeSubSolver.visualize()\n }\n\n const graphics: Required<GraphicsObject> = {\n lines: [],\n points: [],\n circles: [],\n rects: [],\n coordinateSystem: \"cartesian\",\n title: \"Multi Simplified Path Solver\",\n }\n\n // Visualize the original unsimplified routes in red with transparency\n for (const route of this.unsimplifiedHdRoutes) {\n if (\n this.simplifiedHdRoutes.some(\n (r) => r.connectionName === route.connectionName,\n )\n ) {\n continue\n }\n\n for (let i = 0; i < route.route.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: route.route[i].x, y: route.route[i].y },\n { x: route.route[i + 1].x, y: route.route[i + 1].y },\n ],\n strokeColor:\n route.route[i].z === 1\n ? \"rgba(0, 0, 255, 0.4)\"\n : \"rgba(255, 0, 0, 0.4)\",\n strokeWidth: 0.15,\n strokeDash: route.route[i].z === 1 ? [0.5, 0.5] : undefined,\n })\n }\n\n // Draw vias for unsimplified routes\n for (const via of route.vias || []) {\n graphics.circles.push({\n center: via,\n radius: route.viaDiameter / 2 || 0.3, // Default radius if viaDiameter not specified\n fill: \"rgba(0, 0, 255, 0.4)\",\n })\n }\n }\n\n // Visualize the simplified routes with colors from colorMap or gray if not found\n for (const route of this.simplifiedHdRoutes) {\n const routeColor =\n this.colorMap?.[route.connectionName] || \"rgba(128, 128, 128, 0.8)\"\n\n // Draw the route lines\n for (let i = 0; i < route.route.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: route.route[i].x, y: route.route[i].y },\n { x: route.route[i + 1].x, y: route.route[i + 1].y },\n ],\n strokeWidth: 0.15,\n strokeColor: routeColor,\n strokeDash: route.route[i].z === 1 ? [0.5, 0.5] : undefined,\n step: 1,\n })\n }\n\n // Visualize vias\n for (const via of route.vias || []) {\n graphics.circles.push({\n center: via,\n radius: route.viaDiameter / 2,\n fill: \"rgba(0, 0, 255, 0.5)\",\n step: 1,\n })\n }\n }\n\n // Visualize the original unsimplified routes in red\n for (const route of this.unsimplifiedHdRoutes) {\n // Draw the route lines\n for (let i = 0; i < route.route.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: route.route[i].x, y: route.route[i].y },\n { x: route.route[i + 1].x, y: route.route[i + 1].y },\n ],\n strokeWidth: 0.15,\n strokeColor: \"rgba(255, 0, 0, 0.2)\",\n strokeDash: [0.5, 0.5],\n step: 0,\n layer: `z${route.route[i].z.toString()}`,\n })\n }\n\n // Add small circles at each point of the original route\n for (const point of route.vias) {\n graphics.circles.push({\n center: { x: point.x, y: point.y },\n radius: route.viaDiameter / 2,\n fill: \"rgba(255, 0, 0, 0.2)\",\n step: 0,\n })\n }\n }\n\n // Visualize obstacles\n for (const obstacle of this.obstacles) {\n graphics.rects.push({\n center: obstacle.center,\n width: obstacle.width,\n height: obstacle.height,\n fill: obstacle.layers?.includes(\"top\")\n ? \"rgba(255, 0, 0, 0.3)\"\n : obstacle.layers?.includes(\"bottom\")\n ? \"rgba(0, 0, 255, 0.3)\"\n : \"rgba(128, 128, 128, 0.3)\",\n })\n }\n\n // Highlight the current route being processed\n if (\n this.currentUnsimplifiedHdRouteIndex < this.unsimplifiedHdRoutes.length\n ) {\n const currentRoute =\n this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex]\n\n // Add a label to the first point of the current route\n if (currentRoute.route.length > 0) {\n graphics.circles.push({\n center: {\n x: currentRoute.route[0].x,\n y: currentRoute.route[0].y,\n },\n radius: 0.2,\n fill: \"yellow\",\n label: \"Current\",\n })\n }\n }\n\n return graphics\n }\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n} from \"../../types/capacity-mesh-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { distance } from \"@tscircuit/math-utils\"\nimport { areNodesBordering } from \"lib/utils/areNodesBordering\"\n\nexport class CapacityMeshEdgeSolver extends BaseSolver {\n public edges: Array<CapacityMeshEdge>\n\n constructor(public nodes: CapacityMeshNode[]) {\n super()\n this.edges = []\n }\n\n getNextCapacityMeshEdgeId() {\n return `ce${this.edges.length}`\n }\n\n step() {\n this.edges = []\n for (let i = 0; i < this.nodes.length; i++) {\n for (let j = i + 1; j < this.nodes.length; j++) {\n const strawNodesWithSameParent =\n this.nodes[i]._strawNode &&\n this.nodes[j]._strawNode &&\n this.nodes[i]._strawParentCapacityMeshNodeId ===\n this.nodes[j]._strawParentCapacityMeshNodeId\n if (\n !strawNodesWithSameParent &&\n areNodesBordering(this.nodes[i], this.nodes[j]) &&\n this.doNodesHaveSharedLayer(this.nodes[i], this.nodes[j])\n ) {\n this.edges.push({\n capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),\n nodeIds: [\n this.nodes[i].capacityMeshNodeId,\n this.nodes[j].capacityMeshNodeId,\n ],\n })\n }\n }\n }\n\n this.handleTargetNodes()\n\n this.solved = true\n }\n\n handleTargetNodes() {\n // If a target node is not connected to any other node, then it is \"inside\n // an obstacle\" (this is the case almost 100% of the time when we place\n // targets inside of PCB pads)\n // To fix this we connect it to the nearest nodes without obstacles\n const targetNodes = this.nodes.filter((node) => node._containsTarget)\n for (const targetNode of targetNodes) {\n const hasEdge = this.edges.some((edge) =>\n edge.nodeIds.includes(targetNode.capacityMeshNodeId),\n )\n if (hasEdge) continue\n\n let nearestNode: CapacityMeshNode | null = null\n let nearestDistance = Infinity\n for (const node of this.nodes) {\n if (node._containsObstacle) continue\n if (node._containsTarget) continue\n const dist = distance(targetNode.center, node.center)\n if (dist < nearestDistance) {\n nearestDistance = dist\n nearestNode = node\n }\n }\n if (nearestNode) {\n this.edges.push({\n capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),\n nodeIds: [\n targetNode.capacityMeshNodeId,\n nearestNode.capacityMeshNodeId,\n ],\n })\n }\n }\n }\n\n doNodesHaveSharedLayer(\n node1: CapacityMeshNode,\n node2: CapacityMeshNode,\n ): boolean {\n return node1.availableZ.some((z) => node2.availableZ.includes(z))\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: this.nodes.map((node) => {\n const lowestZ = Math.min(...node.availableZ)\n return {\n width: Math.max(node.width - 2, node.width * 0.8),\n height: Math.max(node.height - 2, node.height * 0.8),\n center: {\n x: node.center.x + lowestZ * node.width * 0.05,\n y: node.center.y - lowestZ * node.width * 0.05,\n },\n fill: node._containsObstacle\n ? \"rgba(255,0,0,0.1)\"\n : ({\n \"0,1\": \"rgba(0,0,0,0.1)\",\n \"0\": \"rgba(0,200,200, 0.1)\",\n \"1\": \"rgba(0,0,200, 0.1)\",\n }[node.availableZ.join(\",\")] ?? \"rgba(0,200,200,0.1)\"),\n label: [\n node.capacityMeshNodeId,\n `availableZ: ${node.availableZ.join(\",\")}`,\n `target? ${node._containsTarget ?? false}`,\n `obs? ${node._containsObstacle ?? false}`,\n ].join(\"\\n\"),\n }\n }),\n circles: [],\n }\n for (const edge of this.edges) {\n const node1 = this.nodes.find(\n (node) => node.capacityMeshNodeId === edge.nodeIds[0],\n )\n const node2 = this.nodes.find(\n (node) => node.capacityMeshNodeId === edge.nodeIds[1],\n )\n if (node1?.center && node2?.center) {\n const lowestZ1 = Math.min(...node1.availableZ)\n const lowestZ2 = Math.min(...node2.availableZ)\n const nodeCenter1Adj = {\n x: node1.center.x + lowestZ1 * node1.width * 0.05,\n y: node1.center.y - lowestZ1 * node1.width * 0.05,\n }\n const nodeCenter2Adj = {\n x: node2.center.x + lowestZ2 * node2.width * 0.05,\n y: node2.center.y - lowestZ2 * node2.width * 0.05,\n }\n graphics.lines!.push({\n points: [nodeCenter1Adj, nodeCenter2Adj],\n strokeDash:\n node1.availableZ.join(\",\") === node2.availableZ.join(\",\")\n ? undefined\n : \"10 5\",\n })\n }\n }\n return graphics\n }\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n} from \"../../types/capacity-mesh-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { distance } from \"@tscircuit/math-utils\"\nimport { areNodesBordering } from \"lib/utils/areNodesBordering\"\nimport { CapacityMeshEdgeSolver } from \"./CapacityMeshEdgeSolver\"\nimport { CapacityNodeTree } from \"lib/data-structures/CapacityNodeTree\"\n\nexport class CapacityMeshEdgeSolver2_NodeTreeOptimization extends CapacityMeshEdgeSolver {\n step() {\n this.edges = []\n const edgeSet = new Set<string>()\n\n const nodeTree = new CapacityNodeTree(this.nodes)\n\n for (let i = 0; i < this.nodes.length; i++) {\n const A = this.nodes[i]\n const maybeAdjNodes = nodeTree.getNodesInArea(\n A.center.x,\n A.center.y,\n A.width * 2,\n A.height * 2,\n )\n\n for (const B of maybeAdjNodes) {\n const areBordering = areNodesBordering(A, B)\n if (!areBordering) continue\n const strawNodesWithSameParent =\n A._strawNode &&\n B._strawNode &&\n A._strawParentCapacityMeshNodeId === B._strawParentCapacityMeshNodeId\n if (\n !strawNodesWithSameParent &&\n this.doNodesHaveSharedLayer(A, B) &&\n !edgeSet.has(`${A.capacityMeshNodeId}-${B.capacityMeshNodeId}`)\n ) {\n edgeSet.add(`${A.capacityMeshNodeId}-${B.capacityMeshNodeId}`)\n edgeSet.add(`${B.capacityMeshNodeId}-${A.capacityMeshNodeId}`)\n this.edges.push({\n capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),\n nodeIds: [A.capacityMeshNodeId, B.capacityMeshNodeId],\n })\n }\n }\n }\n\n this.handleTargetNodes()\n\n this.solved = true\n }\n}\n","import type { GraphicsObject, Line } from \"graphics-debug\"\nimport { combineVisualizations } from \"../utils/combineVisualizations\"\nimport type {\n CapacityMeshNode,\n SimpleRouteJson,\n SimplifiedPcbTrace,\n SimplifiedPcbTraces,\n TraceId,\n} from \"../types\"\nimport { BaseSolver } from \"./BaseSolver\"\nimport { CapacityMeshEdgeSolver } from \"./CapacityMeshSolver/CapacityMeshEdgeSolver\"\nimport { CapacityMeshNodeSolver } from \"./CapacityMeshSolver/CapacityMeshNodeSolver1\"\nimport { CapacityMeshNodeSolver2_NodeUnderObstacle } from \"./CapacityMeshSolver/CapacityMeshNodeSolver2_NodesUnderObstacles\"\nimport { CapacityPathingSolver } from \"./CapacityPathingSolver/CapacityPathingSolver\"\nimport { CapacityEdgeToPortSegmentSolver } from \"./CapacityMeshSolver/CapacityEdgeToPortSegmentSolver\"\nimport { getColorMap } from \"./colors\"\nimport { CapacitySegmentToPointSolver } from \"./CapacityMeshSolver/CapacitySegmentToPointSolver\"\nimport { HighDensitySolver } from \"./HighDensitySolver/HighDensitySolver\"\nimport type { NodePortSegment } from \"../types/capacity-edges-to-port-segments-types\"\nimport { CapacityPathingSolver2_AvoidLowCapacity } from \"./CapacityPathingSolver/CapacityPathingSolver2_AvoidLowCapacity\"\nimport { CapacityPathingSolver3_FlexibleNegativeCapacity_AvoidLowCapacity } from \"./CapacityPathingSolver/CapacityPathingSolver3_FlexibleNegativeCapacity_AvoidLowCapacity\"\nimport { CapacityPathingSolver4_FlexibleNegativeCapacity } from \"./CapacityPathingSolver/CapacityPathingSolver4_FlexibleNegativeCapacity_AvoidLowCapacity_FixedDistanceCost\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport { getConnectivityMapFromSimpleRouteJson } from \"lib/utils/getConnectivityMapFromSimpleRouteJson\"\nimport { CapacityNodeTargetMerger } from \"./CapacityNodeTargetMerger/CapacityNodeTargetMerger\"\nimport { CapacitySegmentPointOptimizer } from \"./CapacitySegmentPointOptimizer/CapacitySegmentPointOptimizer\"\nimport { calculateOptimalCapacityDepth } from \"../utils/getTunedTotalCapacity1\"\nimport { NetToPointPairsSolver } from \"./NetToPointPairsSolver/NetToPointPairsSolver\"\nimport { convertHdRouteToSimplifiedRoute } from \"lib/utils/convertHdRouteToSimplifiedRoute\"\nimport { mergeRouteSegments } from \"lib/utils/mergeRouteSegments\"\nimport { mapLayerNameToZ } from \"lib/utils/mapLayerNameToZ\"\nimport { MultipleHighDensityRouteStitchSolver } from \"./RouteStitchingSolver/MultipleHighDensityRouteStitchSolver\"\nimport { convertSrjToGraphicsObject } from \"tests/fixtures/convertSrjToGraphicsObject\"\nimport { UnravelMultiSectionSolver } from \"./UnravelSolver/UnravelMultiSectionSolver\"\nimport { CapacityPathingSolver5 } from \"./CapacityPathingSolver/CapacityPathingSolver5\"\nimport { StrawSolver } from \"./StrawSolver/StrawSolver\"\nimport { SingleLayerNodeMergerSolver } from \"./SingleLayerNodeMerger/SingleLayerNodeMergerSolver\"\nimport { CapacityNodeTargetMerger2 } from \"./CapacityNodeTargetMerger/CapacityNodeTargetMerger2\"\nimport { SingleSimplifiedPathSolver } from \"./SimplifiedPathSolver/SingleSimplifiedPathSolver\"\nimport { MultiSimplifiedPathSolver } from \"./SimplifiedPathSolver/MultiSimplifiedPathSolver\"\nimport {\n HighDensityIntraNodeRoute,\n HighDensityRoute,\n} from \"lib/types/high-density-types\"\nimport { CapacityMeshEdgeSolver2_NodeTreeOptimization } from \"./CapacityMeshSolver/CapacityMeshEdgeSolver2_NodeTreeOptimization\"\n\ninterface CapacityMeshSolverOptions {\n capacityDepth?: number\n targetMinCapacity?: number\n}\n\ntype PipelineStep<T extends new (...args: any[]) => BaseSolver> = {\n solverName: string\n solverClass: T\n getConstructorParams: (\n instance: AutoroutingPipelineSolver,\n ) => ConstructorParameters<T>\n onSolved?: (instance: AutoroutingPipelineSolver) => void\n}\n\nfunction definePipelineStep<\n T extends new (\n ...args: any[]\n ) => BaseSolver,\n const P extends ConstructorParameters<T>,\n>(\n solverName: keyof AutoroutingPipelineSolver,\n solverClass: T,\n getConstructorParams: (instance: AutoroutingPipelineSolver) => P,\n opts: {\n onSolved?: (instance: AutoroutingPipelineSolver) => void\n } = {},\n): PipelineStep<T> {\n return {\n solverName,\n solverClass,\n getConstructorParams,\n onSolved: opts.onSolved,\n }\n}\n\nexport class AutoroutingPipelineSolver extends BaseSolver {\n netToPointPairsSolver?: NetToPointPairsSolver\n nodeSolver?: CapacityMeshNodeSolver\n nodeTargetMerger?: CapacityNodeTargetMerger\n edgeSolver?: CapacityMeshEdgeSolver\n pathingSolver?: CapacityPathingSolver\n edgeToPortSegmentSolver?: CapacityEdgeToPortSegmentSolver\n colorMap: Record<string, string>\n segmentToPointSolver?: CapacitySegmentToPointSolver\n unravelMultiSectionSolver?: UnravelMultiSectionSolver\n segmentToPointOptimizer?: CapacitySegmentPointOptimizer\n highDensityRouteSolver?: HighDensitySolver\n highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver\n singleLayerNodeMerger?: SingleLayerNodeMergerSolver\n strawSolver?: StrawSolver\n multiSimplifiedPathSolver?: MultiSimplifiedPathSolver\n\n startTimeOfPhase: Record<string, number>\n endTimeOfPhase: Record<string, number>\n timeSpentOnPhase: Record<string, number>\n\n activeSubSolver?: BaseSolver | null = null\n connMap: ConnectivityMap\n srjWithPointPairs?: SimpleRouteJson\n capacityNodes: CapacityMeshNode[] | null = null\n\n pipelineDef = [\n definePipelineStep(\n \"netToPointPairsSolver\",\n NetToPointPairsSolver,\n (cms) => [cms.srj, cms.colorMap],\n {\n onSolved: (cms) => {\n cms.srjWithPointPairs =\n cms.netToPointPairsSolver?.getNewSimpleRouteJson()\n cms.colorMap = getColorMap(cms.srjWithPointPairs!, this.connMap)\n cms.connMap = getConnectivityMapFromSimpleRouteJson(\n cms.srjWithPointPairs!,\n )\n },\n },\n ),\n definePipelineStep(\n \"nodeSolver\",\n CapacityMeshNodeSolver2_NodeUnderObstacle,\n (cms) => [\n cms.netToPointPairsSolver?.getNewSimpleRouteJson() || cms.srj,\n cms.opts,\n ],\n {\n onSolved: (cms) => {\n cms.capacityNodes = cms.nodeSolver?.finishedNodes!\n },\n },\n ),\n // definePipelineStep(\"nodeTargetMerger\", CapacityNodeTargetMerger, (cms) => [\n // cms.nodeSolver?.finishedNodes || [],\n // cms.srj.obstacles,\n // cms.connMap,\n // ]),\n // definePipelineStep(\"nodeTargetMerger\", CapacityNodeTargetMerger2, (cms) => [\n // cms.nodeSolver?.finishedNodes || [],\n // cms.srj.obstacles,\n // cms.connMap,\n // cms.colorMap,\n // cms.srj.connections,\n // ]),\n definePipelineStep(\n \"singleLayerNodeMerger\",\n SingleLayerNodeMergerSolver,\n (cms) => [cms.nodeSolver?.finishedNodes!],\n {\n onSolved: (cms) => {\n cms.capacityNodes = cms.singleLayerNodeMerger?.newNodes!\n },\n },\n ),\n definePipelineStep(\n \"strawSolver\",\n StrawSolver,\n (cms) => [{ nodes: cms.singleLayerNodeMerger?.newNodes! }],\n {\n onSolved: (cms) => {\n cms.capacityNodes = cms.strawSolver?.getResultNodes()!\n },\n },\n ),\n definePipelineStep(\n \"edgeSolver\",\n CapacityMeshEdgeSolver2_NodeTreeOptimization,\n (cms) => [cms.capacityNodes!],\n ),\n definePipelineStep(\"pathingSolver\", CapacityPathingSolver5, (cms) => [\n {\n simpleRouteJson: cms.srjWithPointPairs!,\n nodes: cms.capacityNodes!,\n edges: cms.edgeSolver?.edges || [],\n colorMap: cms.colorMap,\n hyperParameters: {\n MAX_CAPACITY_FACTOR: 1,\n },\n },\n ]),\n definePipelineStep(\n \"edgeToPortSegmentSolver\",\n CapacityEdgeToPortSegmentSolver,\n (cms) => [\n {\n nodes: cms.capacityNodes!,\n edges: cms.edgeSolver?.edges || [],\n capacityPaths: cms.pathingSolver?.getCapacityPaths() || [],\n colorMap: cms.colorMap,\n },\n ],\n ),\n definePipelineStep(\n \"segmentToPointSolver\",\n CapacitySegmentToPointSolver,\n (cms) => {\n const allSegments: NodePortSegment[] = []\n if (cms.edgeToPortSegmentSolver?.nodePortSegments) {\n cms.edgeToPortSegmentSolver.nodePortSegments.forEach((segs) => {\n allSegments.push(...segs)\n })\n }\n return [\n {\n segments: allSegments,\n colorMap: cms.colorMap,\n nodes: cms.capacityNodes!,\n },\n ]\n },\n ),\n // definePipelineStep(\n // \"segmentToPointOptimizer\",\n // CapacitySegmentPointOptimizer,\n // (cms) => [\n // {\n // assignedSegments: cms.segmentToPointSolver?.solvedSegments || [],\n // colorMap: cms.colorMap,\n // nodes: cms.nodeTargetMerger?.newNodes || [],\n // },\n // ],\n // ),\n definePipelineStep(\n \"unravelMultiSectionSolver\",\n UnravelMultiSectionSolver,\n (cms) => [\n {\n assignedSegments: cms.segmentToPointSolver?.solvedSegments || [],\n colorMap: cms.colorMap,\n nodes: cms.capacityNodes!,\n },\n ],\n ),\n definePipelineStep(\"highDensityRouteSolver\", HighDensitySolver, (cms) => [\n {\n nodePortPoints:\n cms.unravelMultiSectionSolver?.getNodesWithPortPoints() ??\n cms.segmentToPointOptimizer?.getNodesWithPortPoints() ??\n [],\n colorMap: cms.colorMap,\n connMap: cms.connMap,\n },\n ]),\n definePipelineStep(\n \"highDensityStitchSolver\",\n MultipleHighDensityRouteStitchSolver,\n (cms) => [\n {\n connections: cms.srjWithPointPairs!.connections,\n hdRoutes: cms.highDensityRouteSolver!.routes,\n layerCount: cms.srj.layerCount,\n },\n ],\n ),\n definePipelineStep(\n \"multiSimplifiedPathSolver\",\n MultiSimplifiedPathSolver,\n (cms) => [\n {\n unsimplifiedHdRoutes: cms.highDensityStitchSolver!.mergedHdRoutes,\n obstacles: cms.srj.obstacles,\n connMap: cms.connMap,\n colorMap: cms.colorMap,\n },\n ],\n ),\n ]\n\n constructor(\n public srj: SimpleRouteJson,\n public opts: CapacityMeshSolverOptions = {},\n ) {\n super()\n this.MAX_ITERATIONS = 1e6\n\n // If capacityDepth is not provided, calculate it automatically\n if (opts.capacityDepth === undefined) {\n // Calculate max width/height from bounds for initial node size\n const boundsWidth = srj.bounds.maxX - srj.bounds.minX\n const boundsHeight = srj.bounds.maxY - srj.bounds.minY\n const maxWidthHeight = Math.max(boundsWidth, boundsHeight)\n\n // Use the calculateOptimalCapacityDepth function to determine the right depth\n const targetMinCapacity = opts.targetMinCapacity ?? 0.5\n opts.capacityDepth = calculateOptimalCapacityDepth(\n maxWidthHeight,\n targetMinCapacity,\n )\n }\n\n this.connMap = getConnectivityMapFromSimpleRouteJson(srj)\n this.colorMap = getColorMap(srj, this.connMap)\n this.startTimeOfPhase = {}\n this.endTimeOfPhase = {}\n this.timeSpentOnPhase = {}\n }\n\n currentPipelineStepIndex = 0\n _step() {\n const pipelineStepDef = this.pipelineDef[this.currentPipelineStepIndex]\n if (!pipelineStepDef) {\n this.solved = true\n return\n }\n\n if (this.activeSubSolver) {\n this.activeSubSolver.step()\n if (this.activeSubSolver.solved) {\n this.endTimeOfPhase[pipelineStepDef.solverName] = performance.now()\n this.timeSpentOnPhase[pipelineStepDef.solverName] =\n this.endTimeOfPhase[pipelineStepDef.solverName] -\n this.startTimeOfPhase[pipelineStepDef.solverName]\n pipelineStepDef.onSolved?.(this)\n this.activeSubSolver = null\n this.currentPipelineStepIndex++\n } else if (this.activeSubSolver.failed) {\n this.error = this.activeSubSolver?.error\n this.failed = true\n this.activeSubSolver = null\n }\n return\n }\n\n const constructorParams = pipelineStepDef.getConstructorParams(this)\n // @ts-ignore\n this.activeSubSolver = new pipelineStepDef.solverClass(...constructorParams)\n ;(this as any)[pipelineStepDef.solverName] = this.activeSubSolver\n this.timeSpentOnPhase[pipelineStepDef.solverName] = 0\n this.startTimeOfPhase[pipelineStepDef.solverName] = performance.now()\n }\n\n solveUntilPhase(phase: string) {\n while (this.getCurrentPhase() !== phase) {\n this.step()\n }\n }\n\n getCurrentPhase(): string {\n return this.pipelineDef[this.currentPipelineStepIndex]?.solverName ?? \"none\"\n }\n\n visualize(): GraphicsObject {\n if (!this.solved && this.activeSubSolver)\n return this.activeSubSolver.visualize()\n const netToPPSolver = this.netToPointPairsSolver?.visualize()\n const nodeViz = this.nodeSolver?.visualize()\n const nodeTargetMergerViz = this.nodeTargetMerger?.visualize()\n const singleLayerNodeMergerViz = this.singleLayerNodeMerger?.visualize()\n const strawSolverViz = this.strawSolver?.visualize()\n const edgeViz = this.edgeSolver?.visualize()\n const pathingViz = this.pathingSolver?.visualize()\n const edgeToPortSegmentViz = this.edgeToPortSegmentSolver?.visualize()\n const segmentToPointViz = this.segmentToPointSolver?.visualize()\n const segmentOptimizationViz =\n this.unravelMultiSectionSolver?.visualize() ??\n this.segmentToPointOptimizer?.visualize()\n const highDensityViz = this.highDensityRouteSolver?.visualize()\n const highDensityStitchViz = this.highDensityStitchSolver?.visualize()\n const simplifiedPathSolverViz = this.multiSimplifiedPathSolver?.visualize()\n const problemViz = {\n points: [\n ...this.srj.connections.flatMap((c) =>\n c.pointsToConnect.map((p) => ({\n ...p,\n label: `${c.name} ${p.pcb_port_id ?? \"\"}`,\n })),\n ),\n ],\n rects: [\n ...(this.srj.obstacles ?? []).map((o) => ({\n ...o,\n fill: o.layers?.includes(\"top\")\n ? \"rgba(255,0,0,0.25)\"\n : o.layers?.includes(\"bottom\")\n ? \"rgba(0,0,255,0.25)\"\n : \"rgba(255,0,0,0.25)\",\n label: o.layers?.join(\", \"),\n })),\n ],\n lines: [\n {\n points: [\n // Add five points representing the bounds of the PCB\n {\n x: this.srj.bounds?.minX ?? -50,\n y: this.srj.bounds?.minY ?? -50,\n },\n { x: this.srj.bounds?.maxX ?? 50, y: this.srj.bounds?.minY ?? -50 },\n { x: this.srj.bounds?.maxX ?? 50, y: this.srj.bounds?.maxY ?? 50 },\n { x: this.srj.bounds?.minX ?? -50, y: this.srj.bounds?.maxY ?? 50 },\n {\n x: this.srj.bounds?.minX ?? -50,\n y: this.srj.bounds?.minY ?? -50,\n }, // Close the rectangle\n ],\n strokeColor: \"rgba(255,0,0,0.25)\",\n },\n ],\n } as GraphicsObject\n const visualizations = [\n problemViz,\n netToPPSolver,\n nodeViz,\n nodeTargetMergerViz,\n singleLayerNodeMergerViz,\n strawSolverViz,\n edgeViz,\n pathingViz,\n edgeToPortSegmentViz,\n segmentToPointViz,\n segmentOptimizationViz,\n highDensityViz ? combineVisualizations(problemViz, highDensityViz) : null,\n highDensityStitchViz,\n simplifiedPathSolverViz,\n this.solved\n ? combineVisualizations(\n problemViz,\n convertSrjToGraphicsObject(this.getOutputSimpleRouteJson()),\n )\n : null,\n ].filter(Boolean) as GraphicsObject[]\n // return visualizations[visualizations.length - 1]\n return combineVisualizations(...visualizations)\n }\n\n /**\n * A lightweight version of the visualize method that can be used to stream\n * progress\n *\n * We return the most relevant graphic for the stage:\n * 1. netToPointPairs output\n * 2. Capacity Planning Output\n * 3. High Density Route Solver Output, max 200 lines\n */\n preview(): GraphicsObject {\n if (this.highDensityRouteSolver) {\n const lines: Line[] = []\n for (let i = this.highDensityRouteSolver.routes.length - 1; i >= 0; i--) {\n const route = this.highDensityRouteSolver.routes[i]\n lines.push({\n points: route.route.map((n) => ({\n x: n.x,\n y: n.y,\n })),\n strokeColor: this.colorMap[route.connectionName],\n })\n if (lines.length > 200) break\n }\n return { lines }\n }\n\n if (this.pathingSolver) {\n const lines: Line[] = []\n for (const connection of this.pathingSolver.connectionsWithNodes) {\n if (!connection.path) continue\n lines.push({\n points: connection.path.map((n) => ({\n x: n.center.x,\n y: n.center.y,\n })),\n strokeColor: this.colorMap[connection.connection.name],\n })\n }\n return { lines }\n }\n\n // This output is good as-is\n if (this.netToPointPairsSolver) {\n return this.netToPointPairsSolver?.visualize()\n }\n\n return {}\n }\n\n /**\n * Get original connection name from connection name with MST suffix\n * @param mstConnectionName The MST-suffixed connection name (e.g. \"connection1_mst0\")\n * @returns The original connection name (e.g. \"connection1\")\n */\n private getOriginalConnectionName(mstConnectionName: string): string {\n // MST connections are named like \"connection_mst0\", so extract the original name\n const match = mstConnectionName.match(/^(.+?)_mst\\d+$/)\n return match ? match[1] : mstConnectionName\n }\n\n _getOutputHdRoutes(): HighDensityRoute[] {\n return (\n this.multiSimplifiedPathSolver?.simplifiedHdRoutes ??\n this.highDensityStitchSolver!.mergedHdRoutes\n )\n }\n\n /**\n * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces\n */\n getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces {\n if (!this.solved || !this.highDensityRouteSolver) {\n throw new Error(\"Cannot get output before solving is complete\")\n }\n\n const traces: SimplifiedPcbTraces = []\n const allHdRoutes = this._getOutputHdRoutes()\n\n for (const connection of this.netToPointPairsSolver?.newConnections ?? []) {\n const netConnection = this.srj.connections.find(\n (c) => c.name === connection.netConnectionName,\n )\n\n // Find all the hdRoutes that correspond to this connection\n const hdRoutes = allHdRoutes.filter(\n (r) => r.connectionName === connection.name,\n )\n\n for (let i = 0; i < hdRoutes.length; i++) {\n const hdRoute = hdRoutes[i]\n const simplifiedPcbTrace: SimplifiedPcbTrace = {\n type: \"pcb_trace\",\n pcb_trace_id: `${connection.name}_${i}`,\n connection_name: this.getOriginalConnectionName(connection.name),\n route: convertHdRouteToSimplifiedRoute(hdRoute, this.srj.layerCount),\n }\n\n traces.push(simplifiedPcbTrace)\n }\n }\n\n return traces\n }\n\n getOutputSimpleRouteJson(): SimpleRouteJson {\n return {\n ...this.srj,\n traces: this.getOutputSimplifiedPcbTraces(),\n }\n }\n}\n\n/** @deprecated Use AutoroutingPipelineSolver instead */\nexport const CapacityMeshSolver = AutoroutingPipelineSolver\nexport type CapacityMeshSolver = AutoroutingPipelineSolver\n"],"mappings":"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","names":["t","e","t","t","_isNativeReflectConstruct","_wrapNativeSuper","t","PolishedError","pxtoFactory","reduceHexValue","isRgb","isRgba","isHsl","isHsla","distance","clamp","node","y_1","y_2","points","intersections","distance","distance","CQUnit","EPSILON","distance","distance","layerName","segmentPoints","nodeId","distance","EPSILON","pointToSegmentDistance","distance","orientation","onSegment","distance","tailPoint","path45"]}
|
|
1
|
+
{"version":3,"sources":["../lib/utils/combineVisualizations.ts","../lib/solvers/BaseSolver.ts","../node_modules/@babel/runtime/helpers/esm/extends.js","../node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js","../node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","../node_modules/@babel/runtime/helpers/esm/inheritsLoose.js","../node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js","../node_modules/@babel/runtime/helpers/esm/isNativeFunction.js","../node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js","../node_modules/@babel/runtime/helpers/esm/construct.js","../node_modules/@babel/runtime/helpers/esm/wrapNativeSuper.js","../node_modules/polished/dist/polished.esm.js","../lib/solvers/colors.ts","../lib/utils/mapLayerNameToZ.ts","../lib/utils/getTunedTotalCapacity1.ts","../lib/data-structures/ObstacleTree.ts","../lib/data-structures/TargetTree.ts","../lib/solvers/CapacityMeshSolver/CapacityMeshNodeSolver1.ts","../lib/solvers/CapacityMeshSolver/CapacityMeshNodeSolver2_NodesUnderObstacles.ts","../lib/solvers/CapacityMeshSolver/getNodeEdgeMap.ts","../lib/solvers/CapacityMeshSolver/CapacityEdgeToPortSegmentSolver.ts","../lib/solvers/CapacityMeshSolver/CapacitySegmentToPointSolver.ts","../node_modules/@tscircuit/math-utils/src/line-intersections.ts","../node_modules/@tscircuit/math-utils/src/nearest-box.ts","../node_modules/@tscircuit/math-utils/src/segment-distance.ts","../lib/data-structures/SingleRouteCandidatePriorityQueue.ts","../lib/solvers/HighDensitySolver/SingleHighDensityRouteSolver.ts","../lib/solvers/HighDensitySolver/SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost.ts","../lib/utils/cloneAndShuffleArray.ts","../lib/utils/getBoundsFromNodeWithPortPoints.ts","../lib/utils/getMinDistBetweenEnteringPoints.ts","../lib/solvers/HighDensitySolver/IntraNodeSolver.ts","../lib/solvers/HyperParameterSupervisorSolver.ts","../lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/findCircleLineIntersections.ts","../lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/TwoCrossingRoutesHighDensitySolver.ts","../lib/utils/findClosestPointToABCWithinBounds.ts","../lib/utils/findPointToGetAroundCircle.ts","../lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/calculateSideTraversal.ts","../lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/SingleTransitionCrossingRouteSolver.ts","../lib/solvers/HyperHighDensitySolver/HyperSingleIntraNodeSolver.ts","../lib/utils/mergeRouteSegments.ts","../lib/solvers/HighDensitySolver/HighDensitySolver.ts","../node_modules/circuit-json-to-connectivity-map/src/findConnectedNetworks.ts","../node_modules/circuit-json-to-connectivity-map/src/ConnectivityMap.ts","../node_modules/circuit-json-to-connectivity-map/src/getSourcePortConnectivityMapFromCircuitJson.ts","../node_modules/circuit-json-to-connectivity-map/src/getFullConnectivityMapFromCircuitJson.ts","../node_modules/circuit-json-to-connectivity-map/src/PcbConnectivityMap.ts","../lib/utils/getConnectivityMapFromSimpleRouteJson.ts","../lib/solvers/NetToPointPairsSolver/buildMinimumSpanningTree.ts","../lib/solvers/NetToPointPairsSolver/NetToPointPairsSolver.ts","../lib/utils/mapZToLayerName.ts","../lib/utils/convertHdRouteToSimplifiedRoute.ts","../lib/solvers/RouteStitchingSolver/SingleHighDensityRouteStitchSolver.ts","../lib/solvers/RouteStitchingSolver/MultipleHighDensityRouteStitchSolver.ts","../tests/fixtures/convertSrjToGraphicsObject.ts","../lib/solvers/UnravelSolver/getNodesNearNode.ts","../lib/solvers/UnravelSolver/createPointModificationsHash.ts","../lib/solvers/UnravelSolver/hasZRangeOverlap.ts","../lib/solvers/UnravelSolver/getIssuesInSection.ts","../lib/solvers/UnravelSolver/getLogProbability.ts","../lib/solvers/UnravelSolver/applyOperationToPointModifications.ts","../lib/solvers/UnravelSolver/createSegmentPointMap.ts","../lib/solvers/UnravelSolver/UnravelSectionSolver.ts","../lib/solvers/UnravelSolver/getDedupedSegments.ts","../lib/solvers/UnravelSolver/calculateCrossingProbabilityOfFailure.ts","../lib/utils/getIntraNodeCrossingsFromSegmentPoints.ts","../lib/solvers/UnravelSolver/UnravelMultiSectionSolver.ts","../lib/utils/createRectFromCapacityNode.ts","../lib/solvers/CapacityPathingSolver/CapacityPathingSolver.ts","../lib/solvers/CapacityPathingSolver/CapacityPathingSolver5.ts","../lib/solvers/StrawSolver/StrawSolver.ts","../lib/utils/areNodesBordering.ts","../lib/data-structures/CapacityNodeTree.ts","../lib/solvers/SingleLayerNodeMerger/SingleLayerNodeMergerSolver.ts","../lib/solvers/SimplifiedPathSolver/SingleSimplifiedPathSolver.ts","../lib/utils/calculate45DegreePaths.ts","../lib/utils/minimumDistanceBetweenSegments.ts","../lib/data-structures/SegmentTree.ts","../lib/solvers/SimplifiedPathSolver/SingleSimplifiedPathSolver5_Deg45.ts","../lib/solvers/SimplifiedPathSolver/MultiSimplifiedPathSolver.ts","../lib/solvers/CapacityMeshSolver/CapacityMeshEdgeSolver.ts","../lib/solvers/CapacityMeshSolver/CapacityMeshEdgeSolver2_NodeTreeOptimization.ts","../lib/data-structures/HighDensityRouteSpatialIndex.ts","../lib/solvers/UselessViaRemovalSolver/SingleRouteUselessViaRemovalSolver.ts","../lib/solvers/UselessViaRemovalSolver/UselessViaRemovalSolver.ts","../lib/solvers/AutoroutingPipelineSolver.ts"],"sourcesContent":["import type { GraphicsObject } from \"graphics-debug\"\n\nexport const combineVisualizations = (\n ...visualizations: GraphicsObject[]\n): GraphicsObject => {\n const combined: GraphicsObject = {\n points: [],\n lines: [],\n circles: [],\n rects: [],\n }\n\n visualizations.forEach((viz, i) => {\n if (!viz) return\n if (viz.lines) {\n combined.lines = [\n ...(combined.lines || []),\n ...viz.lines.map((l) => ({ ...l, step: i })),\n ]\n }\n if (viz.points) {\n combined.points = [\n ...(combined.points || []),\n ...viz.points.map((p) => ({ ...p, step: i })),\n ]\n }\n if (viz.circles) {\n combined.circles = [\n ...(combined.circles || []),\n ...viz.circles.map((c) => ({ ...c, step: i })),\n ]\n }\n if (viz.rects) {\n combined.rects = [\n ...(combined.rects || []),\n ...viz.rects.map((r) => ({ ...r, step: i })),\n ]\n }\n })\n\n return combined\n}\n","import type { GraphicsObject } from \"graphics-debug\"\n\nexport class BaseSolver {\n MAX_ITERATIONS = 1000\n solved = false\n failed = false\n iterations = 0\n progress = 0\n error: string | null = null\n activeSubSolver?: BaseSolver | null\n failedSubSolvers?: BaseSolver[]\n timeToSolve?: number\n\n /** DO NOT OVERRIDE! Override _step() instead */\n step() {\n if (this.solved) return\n if (this.failed) return\n this.iterations++\n try {\n this._step()\n } catch (e) {\n this.error = `${this.constructor.name} error: ${e}`\n console.error(this.error)\n this.failed = true\n throw e\n }\n if (!this.solved && this.iterations > this.MAX_ITERATIONS) {\n this.error = `${this.constructor.name} did not converge`\n console.error(this.error)\n this.failed = true\n }\n }\n\n _step() {}\n\n getConstructorParams() {\n throw new Error(\"getConstructorParams not implemented\")\n }\n\n solve() {\n const startTime = Date.now()\n while (!this.solved && !this.failed) {\n this.step()\n }\n const endTime = Date.now()\n this.timeToSolve = endTime - startTime\n }\n\n visualize(): GraphicsObject {\n return {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n }\n\n /**\n * A lightweight version of the visualize method that can be used to stream\n * progress\n */\n preview(): GraphicsObject {\n return {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n }\n}\n","function _extends() {\n return _extends = Object.assign ? Object.assign.bind() : function (n) {\n for (var e = 1; e < arguments.length; e++) {\n var t = arguments[e];\n for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);\n }\n return n;\n }, _extends.apply(null, arguments);\n}\nexport { _extends as default };","function _assertThisInitialized(e) {\n if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n return e;\n}\nexport { _assertThisInitialized as default };","function _setPrototypeOf(t, e) {\n return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {\n return t.__proto__ = e, t;\n }, _setPrototypeOf(t, e);\n}\nexport { _setPrototypeOf as default };","import setPrototypeOf from \"./setPrototypeOf.js\";\nfunction _inheritsLoose(t, o) {\n t.prototype = Object.create(o.prototype), t.prototype.constructor = t, setPrototypeOf(t, o);\n}\nexport { _inheritsLoose as default };","function _getPrototypeOf(t) {\n return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {\n return t.__proto__ || Object.getPrototypeOf(t);\n }, _getPrototypeOf(t);\n}\nexport { _getPrototypeOf as default };","function _isNativeFunction(t) {\n try {\n return -1 !== Function.toString.call(t).indexOf(\"[native code]\");\n } catch (n) {\n return \"function\" == typeof t;\n }\n}\nexport { _isNativeFunction as default };","function _isNativeReflectConstruct() {\n try {\n var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));\n } catch (t) {}\n return (_isNativeReflectConstruct = function _isNativeReflectConstruct() {\n return !!t;\n })();\n}\nexport { _isNativeReflectConstruct as default };","import isNativeReflectConstruct from \"./isNativeReflectConstruct.js\";\nimport setPrototypeOf from \"./setPrototypeOf.js\";\nfunction _construct(t, e, r) {\n if (isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);\n var o = [null];\n o.push.apply(o, e);\n var p = new (t.bind.apply(t, o))();\n return r && setPrototypeOf(p, r.prototype), p;\n}\nexport { _construct as default };","import getPrototypeOf from \"./getPrototypeOf.js\";\nimport setPrototypeOf from \"./setPrototypeOf.js\";\nimport isNativeFunction from \"./isNativeFunction.js\";\nimport construct from \"./construct.js\";\nfunction _wrapNativeSuper(t) {\n var r = \"function\" == typeof Map ? new Map() : void 0;\n return _wrapNativeSuper = function _wrapNativeSuper(t) {\n if (null === t || !isNativeFunction(t)) return t;\n if (\"function\" != typeof t) throw new TypeError(\"Super expression must either be null or a function\");\n if (void 0 !== r) {\n if (r.has(t)) return r.get(t);\n r.set(t, Wrapper);\n }\n function Wrapper() {\n return construct(t, arguments, getPrototypeOf(this).constructor);\n }\n return Wrapper.prototype = Object.create(t.prototype, {\n constructor: {\n value: Wrapper,\n enumerable: !1,\n writable: !0,\n configurable: !0\n }\n }), setPrototypeOf(Wrapper, t);\n }, _wrapNativeSuper(t);\n}\nexport { _wrapNativeSuper as default };","import _extends from '@babel/runtime/helpers/esm/extends';\nimport _assertThisInitialized from '@babel/runtime/helpers/esm/assertThisInitialized';\nimport _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose';\nimport _wrapNativeSuper from '@babel/runtime/helpers/esm/wrapNativeSuper';\nimport _taggedTemplateLiteralLoose from '@babel/runtime/helpers/esm/taggedTemplateLiteralLoose';\n\nfunction last() {\n var _ref;\n return _ref = arguments.length - 1, _ref < 0 || arguments.length <= _ref ? undefined : arguments[_ref];\n}\nfunction negation(a) {\n return -a;\n}\nfunction addition(a, b) {\n return a + b;\n}\nfunction subtraction(a, b) {\n return a - b;\n}\nfunction multiplication(a, b) {\n return a * b;\n}\nfunction division(a, b) {\n return a / b;\n}\nfunction max() {\n return Math.max.apply(Math, arguments);\n}\nfunction min() {\n return Math.min.apply(Math, arguments);\n}\nfunction comma() {\n return Array.of.apply(Array, arguments);\n}\nvar defaultSymbols = {\n symbols: {\n '*': {\n infix: {\n symbol: '*',\n f: multiplication,\n notation: 'infix',\n precedence: 4,\n rightToLeft: 0,\n argCount: 2\n },\n symbol: '*',\n regSymbol: '\\\\*'\n },\n '/': {\n infix: {\n symbol: '/',\n f: division,\n notation: 'infix',\n precedence: 4,\n rightToLeft: 0,\n argCount: 2\n },\n symbol: '/',\n regSymbol: '/'\n },\n '+': {\n infix: {\n symbol: '+',\n f: addition,\n notation: 'infix',\n precedence: 2,\n rightToLeft: 0,\n argCount: 2\n },\n prefix: {\n symbol: '+',\n f: last,\n notation: 'prefix',\n precedence: 3,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: '+',\n regSymbol: '\\\\+'\n },\n '-': {\n infix: {\n symbol: '-',\n f: subtraction,\n notation: 'infix',\n precedence: 2,\n rightToLeft: 0,\n argCount: 2\n },\n prefix: {\n symbol: '-',\n f: negation,\n notation: 'prefix',\n precedence: 3,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: '-',\n regSymbol: '-'\n },\n ',': {\n infix: {\n symbol: ',',\n f: comma,\n notation: 'infix',\n precedence: 1,\n rightToLeft: 0,\n argCount: 2\n },\n symbol: ',',\n regSymbol: ','\n },\n '(': {\n prefix: {\n symbol: '(',\n f: last,\n notation: 'prefix',\n precedence: 0,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: '(',\n regSymbol: '\\\\('\n },\n ')': {\n postfix: {\n symbol: ')',\n f: undefined,\n notation: 'postfix',\n precedence: 0,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: ')',\n regSymbol: '\\\\)'\n },\n min: {\n func: {\n symbol: 'min',\n f: min,\n notation: 'func',\n precedence: 0,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: 'min',\n regSymbol: 'min\\\\b'\n },\n max: {\n func: {\n symbol: 'max',\n f: max,\n notation: 'func',\n precedence: 0,\n rightToLeft: 0,\n argCount: 1\n },\n symbol: 'max',\n regSymbol: 'max\\\\b'\n }\n }\n};\nvar defaultSymbolMap = defaultSymbols;\n\n// based on https://github.com/styled-components/styled-components/blob/fcf6f3804c57a14dd7984dfab7bc06ee2edca044/src/utils/error.js\n/**\n * Parse errors.md and turn it into a simple hash of code: message\n * @private\n */\nvar ERRORS = {\n \"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\",\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\",\n \"3\": \"Passed an incorrect argument to a color function, please pass a string representation of a color.\\n\\n\",\n \"4\": \"Couldn't generate valid rgb string from %s, it returned %s.\\n\\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\",\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\",\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\",\n \"8\": \"Passed invalid argument to toColorString, please pass a RgbColor, RgbaColor, HslColor or HslaColor object.\\n\\n\",\n \"9\": \"Please provide a number of steps to the modularScale helper.\\n\\n\",\n \"10\": \"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\\n\\n\",\n \"11\": \"Invalid value passed as base to modularScale, expected number or em string but got \\\"%s\\\"\\n\\n\",\n \"12\": \"Expected a string ending in \\\"px\\\" or a number passed as the first argument to %s(), got \\\"%s\\\" instead.\\n\\n\",\n \"13\": \"Expected a string ending in \\\"px\\\" or a number passed as the second argument to %s(), got \\\"%s\\\" instead.\\n\\n\",\n \"14\": \"Passed invalid pixel value (\\\"%s\\\") to %s(), please pass a value like \\\"12px\\\" or 12.\\n\\n\",\n \"15\": \"Passed invalid base value (\\\"%s\\\") to %s(), please pass a value like \\\"12px\\\" or 12.\\n\\n\",\n \"16\": \"You must provide a template to this method.\\n\\n\",\n \"17\": \"You passed an unsupported selector state to this method.\\n\\n\",\n \"18\": \"minScreen and maxScreen must be provided as stringified numbers with the same units.\\n\\n\",\n \"19\": \"fromSize and toSize must be provided as stringified numbers with the same units.\\n\\n\",\n \"20\": \"expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\\n\\n\",\n \"21\": \"expects the objects in the first argument array to have the properties `prop`, `fromSize`, and `toSize`.\\n\\n\",\n \"22\": \"expects the first argument object to have the properties `prop`, `fromSize`, and `toSize`.\\n\\n\",\n \"23\": \"fontFace expects a name of a font-family.\\n\\n\",\n \"24\": \"fontFace expects either the path to the font file(s) or a name of a local copy.\\n\\n\",\n \"25\": \"fontFace expects localFonts to be an array.\\n\\n\",\n \"26\": \"fontFace expects fileFormats to be an array.\\n\\n\",\n \"27\": \"radialGradient requries at least 2 color-stops to properly render.\\n\\n\",\n \"28\": \"Please supply a filename to retinaImage() as the first argument.\\n\\n\",\n \"29\": \"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\\n\\n\",\n \"30\": \"Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\\n\\n\",\n \"31\": \"The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation\\n\\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\",\n \"33\": \"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation\\n\\n\",\n \"34\": \"borderRadius expects a radius value as a string or number as the second argument.\\n\\n\",\n \"35\": \"borderRadius expects one of \\\"top\\\", \\\"bottom\\\", \\\"left\\\" or \\\"right\\\" as the first argument.\\n\\n\",\n \"36\": \"Property must be a string value.\\n\\n\",\n \"37\": \"Syntax Error at %s.\\n\\n\",\n \"38\": \"Formula contains a function that needs parentheses at %s.\\n\\n\",\n \"39\": \"Formula is missing closing parenthesis at %s.\\n\\n\",\n \"40\": \"Formula has too many closing parentheses at %s.\\n\\n\",\n \"41\": \"All values in a formula must have the same unit or be unitless.\\n\\n\",\n \"42\": \"Please provide a number of steps to the modularScale helper.\\n\\n\",\n \"43\": \"Please pass a number or one of the predefined scales to the modularScale helper as the ratio.\\n\\n\",\n \"44\": \"Invalid value passed as base to modularScale, expected number or em/rem string but got %s.\\n\\n\",\n \"45\": \"Passed invalid argument to hslToColorString, please pass a HslColor or HslaColor object.\\n\\n\",\n \"46\": \"Passed invalid argument to rgbToColorString, please pass a RgbColor or RgbaColor object.\\n\\n\",\n \"47\": \"minScreen and maxScreen must be provided as stringified numbers with the same units.\\n\\n\",\n \"48\": \"fromSize and toSize must be provided as stringified numbers with the same units.\\n\\n\",\n \"49\": \"Expects either an array of objects or a single object with the properties prop, fromSize, and toSize.\\n\\n\",\n \"50\": \"Expects the objects in the first argument array to have the properties prop, fromSize, and toSize.\\n\\n\",\n \"51\": \"Expects the first argument object to have the properties prop, fromSize, and toSize.\\n\\n\",\n \"52\": \"fontFace expects either the path to the font file(s) or a name of a local copy.\\n\\n\",\n \"53\": \"fontFace expects localFonts to be an array.\\n\\n\",\n \"54\": \"fontFace expects fileFormats to be an array.\\n\\n\",\n \"55\": \"fontFace expects a name of a font-family.\\n\\n\",\n \"56\": \"linearGradient requries at least 2 color-stops to properly render.\\n\\n\",\n \"57\": \"radialGradient requries at least 2 color-stops to properly render.\\n\\n\",\n \"58\": \"Please supply a filename to retinaImage() as the first argument.\\n\\n\",\n \"59\": \"Passed invalid argument to triangle, please pass correct pointingDirection e.g. 'right'.\\n\\n\",\n \"60\": \"Passed an invalid value to `height` or `width`. Please provide a pixel based unit.\\n\\n\",\n \"61\": \"Property must be a string value.\\n\\n\",\n \"62\": \"borderRadius expects a radius value as a string or number as the second argument.\\n\\n\",\n \"63\": \"borderRadius expects one of \\\"top\\\", \\\"bottom\\\", \\\"left\\\" or \\\"right\\\" as the first argument.\\n\\n\",\n \"64\": \"The animation shorthand only takes 8 arguments. See the specification for more information: http://mdn.io/animation.\\n\\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\",\n \"66\": \"The animation shorthand arrays can only have 8 elements. See the specification for more information: http://mdn.io/animation.\\n\\n\",\n \"67\": \"You must provide a template to this method.\\n\\n\",\n \"68\": \"You passed an unsupported selector state to this method.\\n\\n\",\n \"69\": \"Expected a string ending in \\\"px\\\" or a number passed as the first argument to %s(), got %s instead.\\n\\n\",\n \"70\": \"Expected a string ending in \\\"px\\\" or a number passed as the second argument to %s(), got %s instead.\\n\\n\",\n \"71\": \"Passed invalid pixel value %s to %s(), please pass a value like \\\"12px\\\" or 12.\\n\\n\",\n \"72\": \"Passed invalid base value %s to %s(), please pass a value like \\\"12px\\\" or 12.\\n\\n\",\n \"73\": \"Please provide a valid CSS variable.\\n\\n\",\n \"74\": \"CSS variable not found and no default was provided.\\n\\n\",\n \"75\": \"important requires a valid style object, got a %s instead.\\n\\n\",\n \"76\": \"fromSize and toSize must be provided as stringified numbers with the same units as minScreen and maxScreen.\\n\\n\",\n \"77\": \"remToPx expects a value in \\\"rem\\\" but you provided it in \\\"%s\\\".\\n\\n\",\n \"78\": \"base must be set in \\\"px\\\" or \\\"%\\\" but you set it in \\\"%s\\\".\\n\"\n};\n\n/**\n * super basic version of sprintf\n * @private\n */\nfunction format() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n var a = args[0];\n var b = [];\n var c;\n for (c = 1; c < args.length; c += 1) {\n b.push(args[c]);\n }\n b.forEach(function (d) {\n a = a.replace(/%[a-z]/, d);\n });\n return a;\n}\n\n/**\n * Create an error file out of errors.md for development and a simple web link to the full errors\n * in production mode.\n * @private\n */\nvar PolishedError = /*#__PURE__*/function (_Error) {\n _inheritsLoose(PolishedError, _Error);\n function PolishedError(code) {\n var _this;\n if (process.env.NODE_ENV === 'production') {\n _this = _Error.call(this, \"An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#\" + code + \" for more information.\") || this;\n } else {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n _this = _Error.call(this, format.apply(void 0, [ERRORS[code]].concat(args))) || this;\n }\n return _assertThisInitialized(_this);\n }\n return PolishedError;\n}( /*#__PURE__*/_wrapNativeSuper(Error));\n\nvar unitRegExp = /((?!\\w)a|na|hc|mc|dg|me[r]?|xe|ni(?![a-zA-Z])|mm|cp|tp|xp|q(?!s)|hv|xamv|nimv|wv|sm|s(?!\\D|$)|ged|darg?|nrut)/g;\n\n// Merges additional math functionality into the defaults.\nfunction mergeSymbolMaps(additionalSymbols) {\n var symbolMap = {};\n symbolMap.symbols = additionalSymbols ? _extends({}, defaultSymbolMap.symbols, additionalSymbols.symbols) : _extends({}, defaultSymbolMap.symbols);\n return symbolMap;\n}\nfunction exec(operators, values) {\n var _ref;\n var op = operators.pop();\n values.push(op.f.apply(op, (_ref = []).concat.apply(_ref, values.splice(-op.argCount))));\n return op.precedence;\n}\nfunction calculate(expression, additionalSymbols) {\n var symbolMap = mergeSymbolMaps(additionalSymbols);\n var match;\n var operators = [symbolMap.symbols['('].prefix];\n var values = [];\n var pattern = new RegExp( // Pattern for numbers\n \"\\\\d+(?:\\\\.\\\\d+)?|\" +\n // ...and patterns for individual operators/function names\n Object.keys(symbolMap.symbols).map(function (key) {\n return symbolMap.symbols[key];\n })\n // longer symbols should be listed first\n // $FlowFixMe\n .sort(function (a, b) {\n return b.symbol.length - a.symbol.length;\n })\n // $FlowFixMe\n .map(function (val) {\n return val.regSymbol;\n }).join('|') + \"|(\\\\S)\", 'g');\n pattern.lastIndex = 0; // Reset regular expression object\n\n var afterValue = false;\n do {\n match = pattern.exec(expression);\n var _ref2 = match || [')', undefined],\n token = _ref2[0],\n bad = _ref2[1];\n var notNumber = symbolMap.symbols[token];\n var notNewValue = notNumber && !notNumber.prefix && !notNumber.func;\n var notAfterValue = !notNumber || !notNumber.postfix && !notNumber.infix;\n\n // Check for syntax errors:\n if (bad || (afterValue ? notAfterValue : notNewValue)) {\n throw new PolishedError(37, match ? match.index : expression.length, expression);\n }\n if (afterValue) {\n // We either have an infix or postfix operator (they should be mutually exclusive)\n var curr = notNumber.postfix || notNumber.infix;\n do {\n var prev = operators[operators.length - 1];\n if ((curr.precedence - prev.precedence || prev.rightToLeft) > 0) break;\n // Apply previous operator, since it has precedence over current one\n } while (exec(operators, values)); // Exit loop after executing an opening parenthesis or function\n afterValue = curr.notation === 'postfix';\n if (curr.symbol !== ')') {\n operators.push(curr);\n // Postfix always has precedence over any operator that follows after it\n if (afterValue) exec(operators, values);\n }\n } else if (notNumber) {\n // prefix operator or function\n operators.push(notNumber.prefix || notNumber.func);\n if (notNumber.func) {\n // Require an opening parenthesis\n match = pattern.exec(expression);\n if (!match || match[0] !== '(') {\n throw new PolishedError(38, match ? match.index : expression.length, expression);\n }\n }\n } else {\n // number\n values.push(+token);\n afterValue = true;\n }\n } while (match && operators.length);\n if (operators.length) {\n throw new PolishedError(39, match ? match.index : expression.length, expression);\n } else if (match) {\n throw new PolishedError(40, match ? match.index : expression.length, expression);\n } else {\n return values.pop();\n }\n}\nfunction reverseString(str) {\n return str.split('').reverse().join('');\n}\n\n/**\n * Helper for doing math with CSS Units. Accepts a formula as a string. All values in the formula must have the same unit (or be unitless). Supports complex formulas utliziing addition, subtraction, multiplication, division, square root, powers, factorial, min, max, as well as parentheses for order of operation.\n *\n *In cases where you need to do calculations with mixed units where one unit is a [relative length unit](https://developer.mozilla.org/en-US/docs/Web/CSS/length#Relative_length_units), you will want to use [CSS Calc](https://developer.mozilla.org/en-US/docs/Web/CSS/calc).\n *\n * *warning* While we've done everything possible to ensure math safely evalutes formulas expressed as strings, you should always use extreme caution when passing `math` user provided values.\n * @example\n * // Styles as object usage\n * const styles = {\n * fontSize: math('12rem + 8rem'),\n * fontSize: math('(12px + 2px) * 3'),\n * fontSize: math('3px^2 + sqrt(4)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * fontSize: ${math('12rem + 8rem')};\n * fontSize: ${math('(12px + 2px) * 3')};\n * fontSize: ${math('3px^2 + sqrt(4)')};\n * `\n *\n * // CSS as JS Output\n *\n * div: {\n * fontSize: '20rem',\n * fontSize: '42px',\n * fontSize: '11px',\n * }\n */\nfunction math(formula, additionalSymbols) {\n var reversedFormula = reverseString(formula);\n var formulaMatch = reversedFormula.match(unitRegExp);\n\n // Check that all units are the same\n if (formulaMatch && !formulaMatch.every(function (unit) {\n return unit === formulaMatch[0];\n })) {\n throw new PolishedError(41);\n }\n var cleanFormula = reverseString(reversedFormula.replace(unitRegExp, ''));\n return \"\" + calculate(cleanFormula, additionalSymbols) + (formulaMatch ? reverseString(formulaMatch[0]) : '');\n}\n\nvar cssVariableRegex = /--[\\S]*/g;\n\n/**\n * Fetches the value of a passed CSS Variable in the :root scope, or otherwise returns a defaultValue if provided.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'background': cssVar('--background-color'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${cssVar('--background-color')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * 'background': 'red'\n * }\n */\nfunction cssVar(cssVariable, defaultValue) {\n if (!cssVariable || !cssVariable.match(cssVariableRegex)) {\n throw new PolishedError(73);\n }\n var variableValue;\n\n /* eslint-disable */\n /* istanbul ignore next */\n if (typeof document !== 'undefined' && document.documentElement !== null) {\n variableValue = getComputedStyle(document.documentElement).getPropertyValue(cssVariable);\n }\n /* eslint-enable */\n\n if (variableValue) {\n return variableValue.trim();\n } else if (defaultValue) {\n return defaultValue;\n }\n throw new PolishedError(74);\n}\n\n// @private\nfunction capitalizeString(string) {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nvar positionMap$1 = ['Top', 'Right', 'Bottom', 'Left'];\nfunction generateProperty(property, position) {\n if (!property) return position.toLowerCase();\n var splitProperty = property.split('-');\n if (splitProperty.length > 1) {\n splitProperty.splice(1, 0, position);\n return splitProperty.reduce(function (acc, val) {\n return \"\" + acc + capitalizeString(val);\n });\n }\n var joinedProperty = property.replace(/([a-z])([A-Z])/g, \"$1\" + position + \"$2\");\n return property === joinedProperty ? \"\" + property + position : joinedProperty;\n}\nfunction generateStyles(property, valuesWithDefaults) {\n var styles = {};\n for (var i = 0; i < valuesWithDefaults.length; i += 1) {\n if (valuesWithDefaults[i] || valuesWithDefaults[i] === 0) {\n styles[generateProperty(property, positionMap$1[i])] = valuesWithDefaults[i];\n }\n }\n return styles;\n}\n\n/**\n * Enables shorthand for direction-based properties. It accepts a property (hyphenated or camelCased) and up to four values that map to top, right, bottom, and left, respectively. You can optionally pass an empty string to get only the directional values as properties. You can also optionally pass a null argument for a directional value to ignore it.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...directionalProperty('padding', '12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${directionalProperty('padding', '12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'paddingTop': '12px',\n * 'paddingRight': '24px',\n * 'paddingBottom': '36px',\n * 'paddingLeft': '48px'\n * }\n */\nfunction directionalProperty(property) {\n for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n values[_key - 1] = arguments[_key];\n }\n // prettier-ignore\n var firstValue = values[0],\n _values$ = values[1],\n secondValue = _values$ === void 0 ? firstValue : _values$,\n _values$2 = values[2],\n thirdValue = _values$2 === void 0 ? firstValue : _values$2,\n _values$3 = values[3],\n fourthValue = _values$3 === void 0 ? secondValue : _values$3;\n var valuesWithDefaults = [firstValue, secondValue, thirdValue, fourthValue];\n return generateStyles(property, valuesWithDefaults);\n}\n\n/**\n * Check if a string ends with something\n * @private\n */\nfunction endsWith(string, suffix) {\n return string.substr(-suffix.length) === suffix;\n}\n\nvar cssRegex$1 = /^([+-]?(?:\\d+|\\d*\\.\\d+))([a-z]*|%)$/;\n\n/**\n * Returns a given CSS value minus its unit of measure.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * '--dimension': stripUnit('100px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * --dimension: ${stripUnit('100px')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * '--dimension': 100\n * }\n */\nfunction stripUnit(value) {\n if (typeof value !== 'string') return value;\n var matchedValue = value.match(cssRegex$1);\n return matchedValue ? parseFloat(value) : value;\n}\n\n/**\n * Factory function that creates pixel-to-x converters\n * @private\n */\nvar pxtoFactory = function pxtoFactory(to) {\n return function (pxval, base) {\n if (base === void 0) {\n base = '16px';\n }\n var newPxval = pxval;\n var newBase = base;\n if (typeof pxval === 'string') {\n if (!endsWith(pxval, 'px')) {\n throw new PolishedError(69, to, pxval);\n }\n newPxval = stripUnit(pxval);\n }\n if (typeof base === 'string') {\n if (!endsWith(base, 'px')) {\n throw new PolishedError(70, to, base);\n }\n newBase = stripUnit(base);\n }\n if (typeof newPxval === 'string') {\n throw new PolishedError(71, pxval, to);\n }\n if (typeof newBase === 'string') {\n throw new PolishedError(72, base, to);\n }\n return \"\" + newPxval / newBase + to;\n };\n};\nvar pixelsto = pxtoFactory;\n\n/**\n * Convert pixel value to ems. The default base value is 16px, but can be changed by passing a\n * second argument to the function.\n * @function\n * @param {string|number} pxval\n * @param {string|number} [base='16px']\n * @example\n * // Styles as object usage\n * const styles = {\n * 'height': em('16px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * height: ${em('16px')}\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * 'height': '1em'\n * }\n */\nvar em = pixelsto('em');\nvar em$1 = em;\n\nvar cssRegex = /^([+-]?(?:\\d+|\\d*\\.\\d+))([a-z]*|%)$/;\n\n/**\n * Returns a given CSS value and its unit as elements of an array.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * '--dimension': getValueAndUnit('100px')[0],\n * '--unit': getValueAndUnit('100px')[1],\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * --dimension: ${getValueAndUnit('100px')[0]};\n * --unit: ${getValueAndUnit('100px')[1]};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * '--dimension': 100,\n * '--unit': 'px',\n * }\n */\nfunction getValueAndUnit(value) {\n if (typeof value !== 'string') return [value, ''];\n var matchedValue = value.match(cssRegex);\n if (matchedValue) return [parseFloat(value), matchedValue[2]];\n return [value, undefined];\n}\n\n/**\n * Helper for targeting rules in a style block generated by polished modules that need !important-level specificity. Can optionally specify a rule (or rules) to target specific rules.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...important(cover())\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${important(cover())}\n * `\n *\n * // CSS as JS Output\n *\n * div: {\n * 'position': 'absolute !important',\n * 'top': '0 !important',\n * 'right: '0 !important',\n * 'bottom': '0 !important',\n * 'left: '0 !important'\n * }\n */\nfunction important(styleBlock, rules) {\n if (typeof styleBlock !== 'object' || styleBlock === null) {\n throw new PolishedError(75, typeof styleBlock);\n }\n var newStyleBlock = {};\n Object.keys(styleBlock).forEach(function (key) {\n if (typeof styleBlock[key] === 'object' && styleBlock[key] !== null) {\n newStyleBlock[key] = important(styleBlock[key], rules);\n } else if (!rules || rules && (rules === key || rules.indexOf(key) >= 0)) {\n newStyleBlock[key] = styleBlock[key] + \" !important\";\n } else {\n newStyleBlock[key] = styleBlock[key];\n }\n });\n return newStyleBlock;\n}\n\nvar ratioNames = {\n minorSecond: 1.067,\n majorSecond: 1.125,\n minorThird: 1.2,\n majorThird: 1.25,\n perfectFourth: 1.333,\n augFourth: 1.414,\n perfectFifth: 1.5,\n minorSixth: 1.6,\n goldenSection: 1.618,\n majorSixth: 1.667,\n minorSeventh: 1.778,\n majorSeventh: 1.875,\n octave: 2,\n majorTenth: 2.5,\n majorEleventh: 2.667,\n majorTwelfth: 3,\n doubleOctave: 4\n};\nfunction getRatio(ratioName) {\n return ratioNames[ratioName];\n}\n\n/**\n * Establish consistent measurements and spacial relationships throughout your projects by incrementing an em or rem value up or down a defined scale. We provide a list of commonly used scales as pre-defined variables.\n * @example\n * // Styles as object usage\n * const styles = {\n * // Increment two steps up the default scale\n * 'fontSize': modularScale(2)\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * // Increment two steps up the default scale\n * fontSize: ${modularScale(2)}\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * 'fontSize': '1.77689em'\n * }\n */\nfunction modularScale(steps, base, ratio) {\n if (base === void 0) {\n base = '1em';\n }\n if (ratio === void 0) {\n ratio = 1.333;\n }\n if (typeof steps !== 'number') {\n throw new PolishedError(42);\n }\n if (typeof ratio === 'string' && !ratioNames[ratio]) {\n throw new PolishedError(43);\n }\n var _ref = typeof base === 'string' ? getValueAndUnit(base) : [base, ''],\n realBase = _ref[0],\n unit = _ref[1];\n var realRatio = typeof ratio === 'string' ? getRatio(ratio) : ratio;\n if (typeof realBase === 'string') {\n throw new PolishedError(44, base);\n }\n return \"\" + realBase * Math.pow(realRatio, steps) + (unit || '');\n}\n\n/**\n * Convert pixel value to rems. The default base value is 16px, but can be changed by passing a\n * second argument to the function.\n * @function\n * @param {string|number} pxval\n * @param {string|number} [base='16px']\n * @example\n * // Styles as object usage\n * const styles = {\n * 'height': rem('16px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * height: ${rem('16px')}\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * 'height': '1rem'\n * }\n */\nvar rem = pixelsto('rem');\nvar rem$1 = rem;\n\nvar defaultFontSize = 16;\nfunction convertBase(base) {\n var deconstructedValue = getValueAndUnit(base);\n if (deconstructedValue[1] === 'px') {\n return parseFloat(base);\n }\n if (deconstructedValue[1] === '%') {\n return parseFloat(base) / 100 * defaultFontSize;\n }\n throw new PolishedError(78, deconstructedValue[1]);\n}\nfunction getBaseFromDoc() {\n /* eslint-disable */\n /* istanbul ignore next */\n if (typeof document !== 'undefined' && document.documentElement !== null) {\n var rootFontSize = getComputedStyle(document.documentElement).fontSize;\n return rootFontSize ? convertBase(rootFontSize) : defaultFontSize;\n }\n /* eslint-enable */\n /* istanbul ignore next */\n return defaultFontSize;\n}\n\n/**\n * Convert rem values to px. By default, the base value is pulled from the font-size property on the root element (if it is set in % or px). It defaults to 16px if not found on the root. You can also override the base value by providing your own base in % or px.\n * @example\n * // Styles as object usage\n * const styles = {\n * 'height': remToPx('1.6rem')\n * 'height': remToPx('1.6rem', '10px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * height: ${remToPx('1.6rem')}\n * height: ${remToPx('1.6rem', '10px')}\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * 'height': '25.6px',\n * 'height': '16px',\n * }\n */\nfunction remToPx(value, base) {\n var deconstructedValue = getValueAndUnit(value);\n if (deconstructedValue[1] !== 'rem' && deconstructedValue[1] !== '') {\n throw new PolishedError(77, deconstructedValue[1]);\n }\n var newBase = base ? convertBase(base) : getBaseFromDoc();\n return deconstructedValue[0] * newBase + \"px\";\n}\n\nvar functionsMap$3 = {\n back: 'cubic-bezier(0.600, -0.280, 0.735, 0.045)',\n circ: 'cubic-bezier(0.600, 0.040, 0.980, 0.335)',\n cubic: 'cubic-bezier(0.550, 0.055, 0.675, 0.190)',\n expo: 'cubic-bezier(0.950, 0.050, 0.795, 0.035)',\n quad: 'cubic-bezier(0.550, 0.085, 0.680, 0.530)',\n quart: 'cubic-bezier(0.895, 0.030, 0.685, 0.220)',\n quint: 'cubic-bezier(0.755, 0.050, 0.855, 0.060)',\n sine: 'cubic-bezier(0.470, 0.000, 0.745, 0.715)'\n};\n\n/**\n * String to represent common easing functions as demonstrated here: (github.com/jaukia/easie).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'transitionTimingFunction': easeIn('quad')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * transitionTimingFunction: ${easeIn('quad')};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'transitionTimingFunction': 'cubic-bezier(0.550, 0.085, 0.680, 0.530)',\n * }\n */\nfunction easeIn(functionName) {\n return functionsMap$3[functionName.toLowerCase().trim()];\n}\n\nvar functionsMap$2 = {\n back: 'cubic-bezier(0.680, -0.550, 0.265, 1.550)',\n circ: 'cubic-bezier(0.785, 0.135, 0.150, 0.860)',\n cubic: 'cubic-bezier(0.645, 0.045, 0.355, 1.000)',\n expo: 'cubic-bezier(1.000, 0.000, 0.000, 1.000)',\n quad: 'cubic-bezier(0.455, 0.030, 0.515, 0.955)',\n quart: 'cubic-bezier(0.770, 0.000, 0.175, 1.000)',\n quint: 'cubic-bezier(0.860, 0.000, 0.070, 1.000)',\n sine: 'cubic-bezier(0.445, 0.050, 0.550, 0.950)'\n};\n\n/**\n * String to represent common easing functions as demonstrated here: (github.com/jaukia/easie).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'transitionTimingFunction': easeInOut('quad')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * transitionTimingFunction: ${easeInOut('quad')};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'transitionTimingFunction': 'cubic-bezier(0.455, 0.030, 0.515, 0.955)',\n * }\n */\nfunction easeInOut(functionName) {\n return functionsMap$2[functionName.toLowerCase().trim()];\n}\n\nvar functionsMap$1 = {\n back: 'cubic-bezier(0.175, 0.885, 0.320, 1.275)',\n cubic: 'cubic-bezier(0.215, 0.610, 0.355, 1.000)',\n circ: 'cubic-bezier(0.075, 0.820, 0.165, 1.000)',\n expo: 'cubic-bezier(0.190, 1.000, 0.220, 1.000)',\n quad: 'cubic-bezier(0.250, 0.460, 0.450, 0.940)',\n quart: 'cubic-bezier(0.165, 0.840, 0.440, 1.000)',\n quint: 'cubic-bezier(0.230, 1.000, 0.320, 1.000)',\n sine: 'cubic-bezier(0.390, 0.575, 0.565, 1.000)'\n};\n\n/**\n * String to represent common easing functions as demonstrated here: (github.com/jaukia/easie).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'transitionTimingFunction': easeOut('quad')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * transitionTimingFunction: ${easeOut('quad')};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'transitionTimingFunction': 'cubic-bezier(0.250, 0.460, 0.450, 0.940)',\n * }\n */\nfunction easeOut(functionName) {\n return functionsMap$1[functionName.toLowerCase().trim()];\n}\n\n/**\n * Returns a CSS calc formula for linear interpolation of a property between two values. Accepts optional minScreen (defaults to '320px') and maxScreen (defaults to '1200px').\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * fontSize: between('20px', '100px', '400px', '1000px'),\n * fontSize: between('20px', '100px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * fontSize: ${between('20px', '100px', '400px', '1000px')};\n * fontSize: ${between('20px', '100px')}\n * `\n *\n * // CSS as JS Output\n *\n * h1: {\n * 'fontSize': 'calc(-33.33333333333334px + 13.333333333333334vw)',\n * 'fontSize': 'calc(-9.090909090909093px + 9.090909090909092vw)'\n * }\n */\nfunction between(fromSize, toSize, minScreen, maxScreen) {\n if (minScreen === void 0) {\n minScreen = '320px';\n }\n if (maxScreen === void 0) {\n maxScreen = '1200px';\n }\n var _getValueAndUnit = getValueAndUnit(fromSize),\n unitlessFromSize = _getValueAndUnit[0],\n fromSizeUnit = _getValueAndUnit[1];\n var _getValueAndUnit2 = getValueAndUnit(toSize),\n unitlessToSize = _getValueAndUnit2[0],\n toSizeUnit = _getValueAndUnit2[1];\n var _getValueAndUnit3 = getValueAndUnit(minScreen),\n unitlessMinScreen = _getValueAndUnit3[0],\n minScreenUnit = _getValueAndUnit3[1];\n var _getValueAndUnit4 = getValueAndUnit(maxScreen),\n unitlessMaxScreen = _getValueAndUnit4[0],\n maxScreenUnit = _getValueAndUnit4[1];\n if (typeof unitlessMinScreen !== 'number' || typeof unitlessMaxScreen !== 'number' || !minScreenUnit || !maxScreenUnit || minScreenUnit !== maxScreenUnit) {\n throw new PolishedError(47);\n }\n if (typeof unitlessFromSize !== 'number' || typeof unitlessToSize !== 'number' || fromSizeUnit !== toSizeUnit) {\n throw new PolishedError(48);\n }\n if (fromSizeUnit !== minScreenUnit || toSizeUnit !== maxScreenUnit) {\n throw new PolishedError(76);\n }\n var slope = (unitlessFromSize - unitlessToSize) / (unitlessMinScreen - unitlessMaxScreen);\n var base = unitlessToSize - slope * unitlessMaxScreen;\n return \"calc(\" + base.toFixed(2) + (fromSizeUnit || '') + \" + \" + (100 * slope).toFixed(2) + \"vw)\";\n}\n\n/**\n * CSS to contain a float (credit to CSSMojo).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...clearFix(),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${clearFix()}\n * `\n *\n * // CSS as JS Output\n *\n * '&::after': {\n * 'clear': 'both',\n * 'content': '\"\"',\n * 'display': 'table'\n * }\n */\nfunction clearFix(parent) {\n var _ref;\n if (parent === void 0) {\n parent = '&';\n }\n var pseudoSelector = parent + \"::after\";\n return _ref = {}, _ref[pseudoSelector] = {\n clear: 'both',\n content: '\"\"',\n display: 'table'\n }, _ref;\n}\n\n/**\n * CSS to fully cover an area. Can optionally be passed an offset to act as a \"padding\".\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...cover()\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${cover()}\n * `\n *\n * // CSS as JS Output\n *\n * div: {\n * 'position': 'absolute',\n * 'top': '0',\n * 'right: '0',\n * 'bottom': '0',\n * 'left: '0'\n * }\n */\nfunction cover(offset) {\n if (offset === void 0) {\n offset = 0;\n }\n return {\n position: 'absolute',\n top: offset,\n right: offset,\n bottom: offset,\n left: offset\n };\n}\n\n/**\n * CSS to represent truncated text with an ellipsis. You can optionally pass a max-width and number of lines before truncating.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...ellipsis('250px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${ellipsis('250px')}\n * `\n *\n * // CSS as JS Output\n *\n * div: {\n * 'display': 'inline-block',\n * 'maxWidth': '250px',\n * 'overflow': 'hidden',\n * 'textOverflow': 'ellipsis',\n * 'whiteSpace': 'nowrap',\n * 'wordWrap': 'normal'\n * }\n */\nfunction ellipsis(width, lines) {\n if (lines === void 0) {\n lines = 1;\n }\n var styles = {\n display: 'inline-block',\n maxWidth: width || '100%',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n wordWrap: 'normal'\n };\n return lines > 1 ? _extends({}, styles, {\n WebkitBoxOrient: 'vertical',\n WebkitLineClamp: lines,\n display: '-webkit-box',\n whiteSpace: 'normal'\n }) : styles;\n}\n\nfunction _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== \"undefined\" && o[Symbol.iterator] || o[\"@@iterator\"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === \"number\") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(o); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }\n/**\n * Returns a set of media queries that resizes a property (or set of properties) between a provided fromSize and toSize. Accepts optional minScreen (defaults to '320px') and maxScreen (defaults to '1200px') to constrain the interpolation.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...fluidRange(\n * {\n * prop: 'padding',\n * fromSize: '20px',\n * toSize: '100px',\n * },\n * '400px',\n * '1000px',\n * )\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${fluidRange(\n * {\n * prop: 'padding',\n * fromSize: '20px',\n * toSize: '100px',\n * },\n * '400px',\n * '1000px',\n * )}\n * `\n *\n * // CSS as JS Output\n *\n * div: {\n * \"@media (min-width: 1000px)\": Object {\n * \"padding\": \"100px\",\n * },\n * \"@media (min-width: 400px)\": Object {\n * \"padding\": \"calc(-33.33333333333334px + 13.333333333333334vw)\",\n * },\n * \"padding\": \"20px\",\n * }\n */\nfunction fluidRange(cssProp, minScreen, maxScreen) {\n if (minScreen === void 0) {\n minScreen = '320px';\n }\n if (maxScreen === void 0) {\n maxScreen = '1200px';\n }\n if (!Array.isArray(cssProp) && typeof cssProp !== 'object' || cssProp === null) {\n throw new PolishedError(49);\n }\n if (Array.isArray(cssProp)) {\n var mediaQueries = {};\n var fallbacks = {};\n for (var _iterator = _createForOfIteratorHelperLoose(cssProp), _step; !(_step = _iterator()).done;) {\n var _extends2, _extends3;\n var obj = _step.value;\n if (!obj.prop || !obj.fromSize || !obj.toSize) {\n throw new PolishedError(50);\n }\n fallbacks[obj.prop] = obj.fromSize;\n mediaQueries[\"@media (min-width: \" + minScreen + \")\"] = _extends({}, mediaQueries[\"@media (min-width: \" + minScreen + \")\"], (_extends2 = {}, _extends2[obj.prop] = between(obj.fromSize, obj.toSize, minScreen, maxScreen), _extends2));\n mediaQueries[\"@media (min-width: \" + maxScreen + \")\"] = _extends({}, mediaQueries[\"@media (min-width: \" + maxScreen + \")\"], (_extends3 = {}, _extends3[obj.prop] = obj.toSize, _extends3));\n }\n return _extends({}, fallbacks, mediaQueries);\n } else {\n var _ref, _ref2, _ref3;\n if (!cssProp.prop || !cssProp.fromSize || !cssProp.toSize) {\n throw new PolishedError(51);\n }\n return _ref3 = {}, _ref3[cssProp.prop] = cssProp.fromSize, _ref3[\"@media (min-width: \" + minScreen + \")\"] = (_ref = {}, _ref[cssProp.prop] = between(cssProp.fromSize, cssProp.toSize, minScreen, maxScreen), _ref), _ref3[\"@media (min-width: \" + maxScreen + \")\"] = (_ref2 = {}, _ref2[cssProp.prop] = cssProp.toSize, _ref2), _ref3;\n }\n}\n\nvar dataURIRegex = /^\\s*data:([a-z]+\\/[a-z-]+(;[a-z-]+=[a-z-]+)?)?(;charset=[a-z0-9-]+)?(;base64)?,[a-z0-9!$&',()*+,;=\\-._~:@/?%\\s]*\\s*$/i;\nvar formatHintMap = {\n woff: 'woff',\n woff2: 'woff2',\n ttf: 'truetype',\n otf: 'opentype',\n eot: 'embedded-opentype',\n svg: 'svg',\n svgz: 'svg'\n};\nfunction generateFormatHint(format, formatHint) {\n if (!formatHint) return '';\n return \" format(\\\"\" + formatHintMap[format] + \"\\\")\";\n}\nfunction isDataURI(fontFilePath) {\n return !!fontFilePath.replace(/\\s+/g, ' ').match(dataURIRegex);\n}\nfunction generateFileReferences(fontFilePath, fileFormats, formatHint) {\n if (isDataURI(fontFilePath)) {\n return \"url(\\\"\" + fontFilePath + \"\\\")\" + generateFormatHint(fileFormats[0], formatHint);\n }\n var fileFontReferences = fileFormats.map(function (format) {\n return \"url(\\\"\" + fontFilePath + \".\" + format + \"\\\")\" + generateFormatHint(format, formatHint);\n });\n return fileFontReferences.join(', ');\n}\nfunction generateLocalReferences(localFonts) {\n var localFontReferences = localFonts.map(function (font) {\n return \"local(\\\"\" + font + \"\\\")\";\n });\n return localFontReferences.join(', ');\n}\nfunction generateSources(fontFilePath, localFonts, fileFormats, formatHint) {\n var fontReferences = [];\n if (localFonts) fontReferences.push(generateLocalReferences(localFonts));\n if (fontFilePath) {\n fontReferences.push(generateFileReferences(fontFilePath, fileFormats, formatHint));\n }\n return fontReferences.join(', ');\n}\n\n/**\n * CSS for a @font-face declaration. Defaults to check for local copies of the font on the user's machine. You can disable this by passing `null` to localFonts.\n *\n * @example\n * // Styles as object basic usage\n * const styles = {\n * ...fontFace({\n * 'fontFamily': 'Sans-Pro',\n * 'fontFilePath': 'path/to/file'\n * })\n * }\n *\n * // styled-components basic usage\n * const GlobalStyle = createGlobalStyle`${\n * fontFace({\n * 'fontFamily': 'Sans-Pro',\n * 'fontFilePath': 'path/to/file'\n * }\n * )}`\n *\n * // CSS as JS Output\n *\n * '@font-face': {\n * 'fontFamily': 'Sans-Pro',\n * 'src': 'url(\"path/to/file.eot\"), url(\"path/to/file.woff2\"), url(\"path/to/file.woff\"), url(\"path/to/file.ttf\"), url(\"path/to/file.svg\")',\n * }\n */\n\nfunction fontFace(_ref) {\n var fontFamily = _ref.fontFamily,\n fontFilePath = _ref.fontFilePath,\n fontStretch = _ref.fontStretch,\n fontStyle = _ref.fontStyle,\n fontVariant = _ref.fontVariant,\n fontWeight = _ref.fontWeight,\n _ref$fileFormats = _ref.fileFormats,\n fileFormats = _ref$fileFormats === void 0 ? ['eot', 'woff2', 'woff', 'ttf', 'svg'] : _ref$fileFormats,\n _ref$formatHint = _ref.formatHint,\n formatHint = _ref$formatHint === void 0 ? false : _ref$formatHint,\n _ref$localFonts = _ref.localFonts,\n localFonts = _ref$localFonts === void 0 ? [fontFamily] : _ref$localFonts,\n unicodeRange = _ref.unicodeRange,\n fontDisplay = _ref.fontDisplay,\n fontVariationSettings = _ref.fontVariationSettings,\n fontFeatureSettings = _ref.fontFeatureSettings;\n // Error Handling\n if (!fontFamily) throw new PolishedError(55);\n if (!fontFilePath && !localFonts) {\n throw new PolishedError(52);\n }\n if (localFonts && !Array.isArray(localFonts)) {\n throw new PolishedError(53);\n }\n if (!Array.isArray(fileFormats)) {\n throw new PolishedError(54);\n }\n var fontFaceDeclaration = {\n '@font-face': {\n fontFamily: fontFamily,\n src: generateSources(fontFilePath, localFonts, fileFormats, formatHint),\n unicodeRange: unicodeRange,\n fontStretch: fontStretch,\n fontStyle: fontStyle,\n fontVariant: fontVariant,\n fontWeight: fontWeight,\n fontDisplay: fontDisplay,\n fontVariationSettings: fontVariationSettings,\n fontFeatureSettings: fontFeatureSettings\n }\n };\n\n // Removes undefined fields for cleaner css object.\n return JSON.parse(JSON.stringify(fontFaceDeclaration));\n}\n\n/**\n * CSS to hide text to show a background image in a SEO-friendly way.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'backgroundImage': 'url(logo.png)',\n * ...hideText(),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * backgroundImage: url(logo.png);\n * ${hideText()};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'backgroundImage': 'url(logo.png)',\n * 'textIndent': '101%',\n * 'overflow': 'hidden',\n * 'whiteSpace': 'nowrap',\n * }\n */\nfunction hideText() {\n return {\n textIndent: '101%',\n overflow: 'hidden',\n whiteSpace: 'nowrap'\n };\n}\n\n/**\n * CSS to hide content visually but remain accessible to screen readers.\n * from [HTML5 Boilerplate](https://github.com/h5bp/html5-boilerplate/blob/9a176f57af1cfe8ec70300da4621fb9b07e5fa31/src/css/main.css#L121)\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...hideVisually(),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${hideVisually()};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'border': '0',\n * 'clip': 'rect(0 0 0 0)',\n * 'height': '1px',\n * 'margin': '-1px',\n * 'overflow': 'hidden',\n * 'padding': '0',\n * 'position': 'absolute',\n * 'whiteSpace': 'nowrap',\n * 'width': '1px',\n * }\n */\nfunction hideVisually() {\n return {\n border: '0',\n clip: 'rect(0 0 0 0)',\n height: '1px',\n margin: '-1px',\n overflow: 'hidden',\n padding: '0',\n position: 'absolute',\n whiteSpace: 'nowrap',\n width: '1px'\n };\n}\n\n/**\n * Generates a media query to target HiDPI devices.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * [hiDPI(1.5)]: {\n * width: 200px;\n * }\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${hiDPI(1.5)} {\n * width: 200px;\n * }\n * `\n *\n * // CSS as JS Output\n *\n * '@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n * only screen and (min--moz-device-pixel-ratio: 1.5),\n * only screen and (-o-min-device-pixel-ratio: 1.5/1),\n * only screen and (min-resolution: 144dpi),\n * only screen and (min-resolution: 1.5dppx)': {\n * 'width': '200px',\n * }\n */\nfunction hiDPI(ratio) {\n if (ratio === void 0) {\n ratio = 1.3;\n }\n return \"\\n @media only screen and (-webkit-min-device-pixel-ratio: \" + ratio + \"),\\n only screen and (min--moz-device-pixel-ratio: \" + ratio + \"),\\n only screen and (-o-min-device-pixel-ratio: \" + ratio + \"/1),\\n only screen and (min-resolution: \" + Math.round(ratio * 96) + \"dpi),\\n only screen and (min-resolution: \" + ratio + \"dppx)\\n \";\n}\n\nfunction constructGradientValue(literals) {\n var template = '';\n for (var _len = arguments.length, substitutions = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n substitutions[_key - 1] = arguments[_key];\n }\n for (var i = 0; i < literals.length; i += 1) {\n template += literals[i];\n if (i === substitutions.length - 1 && substitutions[i]) {\n var definedValues = substitutions.filter(function (substitute) {\n return !!substitute;\n });\n // Adds leading coma if properties preceed color-stops\n if (definedValues.length > 1) {\n template = template.slice(0, -1);\n template += \", \" + substitutions[i];\n // No trailing space if color-stops is the only param provided\n } else if (definedValues.length === 1) {\n template += \"\" + substitutions[i];\n }\n } else if (substitutions[i]) {\n template += substitutions[i] + \" \";\n }\n }\n return template.trim();\n}\n\nvar _templateObject$1;\n/**\n * CSS for declaring a linear gradient, including a fallback background-color. The fallback is either the first color-stop or an explicitly passed fallback color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...linearGradient({\n colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],\n toDirection: 'to top right',\n fallback: '#FFF',\n })\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${linearGradient({\n colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],\n toDirection: 'to top right',\n fallback: '#FFF',\n })}\n *`\n *\n * // CSS as JS Output\n *\n * div: {\n * 'backgroundColor': '#FFF',\n * 'backgroundImage': 'linear-gradient(to top right, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%)',\n * }\n */\nfunction linearGradient(_ref) {\n var colorStops = _ref.colorStops,\n fallback = _ref.fallback,\n _ref$toDirection = _ref.toDirection,\n toDirection = _ref$toDirection === void 0 ? '' : _ref$toDirection;\n if (!colorStops || colorStops.length < 2) {\n throw new PolishedError(56);\n }\n return {\n backgroundColor: fallback || colorStops[0].replace(/,\\s+/g, ',').split(' ')[0].replace(/,(?=\\S)/g, ', '),\n backgroundImage: constructGradientValue(_templateObject$1 || (_templateObject$1 = _taggedTemplateLiteralLoose([\"linear-gradient(\", \"\", \")\"])), toDirection, colorStops.join(', ').replace(/,(?=\\S)/g, ', '))\n };\n}\n\n/**\n * CSS to normalize abnormalities across browsers (normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css)\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...normalize(),\n * }\n *\n * // styled-components usage\n * const GlobalStyle = createGlobalStyle`${normalize()}`\n *\n * // CSS as JS Output\n *\n * html {\n * lineHeight: 1.15,\n * textSizeAdjust: 100%,\n * } ...\n */\nfunction normalize() {\n var _ref;\n return [(_ref = {\n html: {\n lineHeight: '1.15',\n textSizeAdjust: '100%'\n },\n body: {\n margin: '0'\n },\n main: {\n display: 'block'\n },\n h1: {\n fontSize: '2em',\n margin: '0.67em 0'\n },\n hr: {\n boxSizing: 'content-box',\n height: '0',\n overflow: 'visible'\n },\n pre: {\n fontFamily: 'monospace, monospace',\n fontSize: '1em'\n },\n a: {\n backgroundColor: 'transparent'\n },\n 'abbr[title]': {\n borderBottom: 'none',\n textDecoration: 'underline'\n }\n }, _ref[\"b,\\n strong\"] = {\n fontWeight: 'bolder'\n }, _ref[\"code,\\n kbd,\\n samp\"] = {\n fontFamily: 'monospace, monospace',\n fontSize: '1em'\n }, _ref.small = {\n fontSize: '80%'\n }, _ref[\"sub,\\n sup\"] = {\n fontSize: '75%',\n lineHeight: '0',\n position: 'relative',\n verticalAlign: 'baseline'\n }, _ref.sub = {\n bottom: '-0.25em'\n }, _ref.sup = {\n top: '-0.5em'\n }, _ref.img = {\n borderStyle: 'none'\n }, _ref[\"button,\\n input,\\n optgroup,\\n select,\\n textarea\"] = {\n fontFamily: 'inherit',\n fontSize: '100%',\n lineHeight: '1.15',\n margin: '0'\n }, _ref[\"button,\\n input\"] = {\n overflow: 'visible'\n }, _ref[\"button,\\n select\"] = {\n textTransform: 'none'\n }, _ref[\"button,\\n html [type=\\\"button\\\"],\\n [type=\\\"reset\\\"],\\n [type=\\\"submit\\\"]\"] = {\n WebkitAppearance: 'button'\n }, _ref[\"button::-moz-focus-inner,\\n [type=\\\"button\\\"]::-moz-focus-inner,\\n [type=\\\"reset\\\"]::-moz-focus-inner,\\n [type=\\\"submit\\\"]::-moz-focus-inner\"] = {\n borderStyle: 'none',\n padding: '0'\n }, _ref[\"button:-moz-focusring,\\n [type=\\\"button\\\"]:-moz-focusring,\\n [type=\\\"reset\\\"]:-moz-focusring,\\n [type=\\\"submit\\\"]:-moz-focusring\"] = {\n outline: '1px dotted ButtonText'\n }, _ref.fieldset = {\n padding: '0.35em 0.625em 0.75em'\n }, _ref.legend = {\n boxSizing: 'border-box',\n color: 'inherit',\n display: 'table',\n maxWidth: '100%',\n padding: '0',\n whiteSpace: 'normal'\n }, _ref.progress = {\n verticalAlign: 'baseline'\n }, _ref.textarea = {\n overflow: 'auto'\n }, _ref[\"[type=\\\"checkbox\\\"],\\n [type=\\\"radio\\\"]\"] = {\n boxSizing: 'border-box',\n padding: '0'\n }, _ref[\"[type=\\\"number\\\"]::-webkit-inner-spin-button,\\n [type=\\\"number\\\"]::-webkit-outer-spin-button\"] = {\n height: 'auto'\n }, _ref['[type=\"search\"]'] = {\n WebkitAppearance: 'textfield',\n outlineOffset: '-2px'\n }, _ref['[type=\"search\"]::-webkit-search-decoration'] = {\n WebkitAppearance: 'none'\n }, _ref['::-webkit-file-upload-button'] = {\n WebkitAppearance: 'button',\n font: 'inherit'\n }, _ref.details = {\n display: 'block'\n }, _ref.summary = {\n display: 'list-item'\n }, _ref.template = {\n display: 'none'\n }, _ref['[hidden]'] = {\n display: 'none'\n }, _ref), {\n 'abbr[title]': {\n textDecoration: 'underline dotted'\n }\n }];\n}\n\nvar _templateObject;\n/**\n * CSS for declaring a radial gradient, including a fallback background-color. The fallback is either the first color-stop or an explicitly passed fallback color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...radialGradient({\n * colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],\n * extent: 'farthest-corner at 45px 45px',\n * position: 'center',\n * shape: 'ellipse',\n * })\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${radialGradient({\n * colorStops: ['#00FFFF 0%', 'rgba(0, 0, 255, 0) 50%', '#0000FF 95%'],\n * extent: 'farthest-corner at 45px 45px',\n * position: 'center',\n * shape: 'ellipse',\n * })}\n *`\n *\n * // CSS as JS Output\n *\n * div: {\n * 'backgroundColor': '#00FFFF',\n * 'backgroundImage': 'radial-gradient(center ellipse farthest-corner at 45px 45px, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%)',\n * }\n */\nfunction radialGradient(_ref) {\n var colorStops = _ref.colorStops,\n _ref$extent = _ref.extent,\n extent = _ref$extent === void 0 ? '' : _ref$extent,\n fallback = _ref.fallback,\n _ref$position = _ref.position,\n position = _ref$position === void 0 ? '' : _ref$position,\n _ref$shape = _ref.shape,\n shape = _ref$shape === void 0 ? '' : _ref$shape;\n if (!colorStops || colorStops.length < 2) {\n throw new PolishedError(57);\n }\n return {\n backgroundColor: fallback || colorStops[0].split(' ')[0],\n backgroundImage: constructGradientValue(_templateObject || (_templateObject = _taggedTemplateLiteralLoose([\"radial-gradient(\", \"\", \"\", \"\", \")\"])), position, shape, extent, colorStops.join(', '))\n };\n}\n\n/**\n * A helper to generate a retina background image and non-retina\n * background image. The retina background image will output to a HiDPI media query. The mixin uses\n * a _2x.png filename suffix by default.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...retinaImage('my-img')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${retinaImage('my-img')}\n * `\n *\n * // CSS as JS Output\n * div {\n * backgroundImage: 'url(my-img.png)',\n * '@media only screen and (-webkit-min-device-pixel-ratio: 1.3),\n * only screen and (min--moz-device-pixel-ratio: 1.3),\n * only screen and (-o-min-device-pixel-ratio: 1.3/1),\n * only screen and (min-resolution: 144dpi),\n * only screen and (min-resolution: 1.5dppx)': {\n * backgroundImage: 'url(my-img_2x.png)',\n * }\n * }\n */\nfunction retinaImage(filename, backgroundSize, extension, retinaFilename, retinaSuffix) {\n var _ref;\n if (extension === void 0) {\n extension = 'png';\n }\n if (retinaSuffix === void 0) {\n retinaSuffix = '_2x';\n }\n if (!filename) {\n throw new PolishedError(58);\n }\n // Replace the dot at the beginning of the passed extension if one exists\n var ext = extension.replace(/^\\./, '');\n var rFilename = retinaFilename ? retinaFilename + \".\" + ext : \"\" + filename + retinaSuffix + \".\" + ext;\n return _ref = {\n backgroundImage: \"url(\" + filename + \".\" + ext + \")\"\n }, _ref[hiDPI()] = _extends({\n backgroundImage: \"url(\" + rFilename + \")\"\n }, backgroundSize ? {\n backgroundSize: backgroundSize\n } : {}), _ref;\n}\n\n/* eslint-disable key-spacing */\nvar functionsMap = {\n easeInBack: 'cubic-bezier(0.600, -0.280, 0.735, 0.045)',\n easeInCirc: 'cubic-bezier(0.600, 0.040, 0.980, 0.335)',\n easeInCubic: 'cubic-bezier(0.550, 0.055, 0.675, 0.190)',\n easeInExpo: 'cubic-bezier(0.950, 0.050, 0.795, 0.035)',\n easeInQuad: 'cubic-bezier(0.550, 0.085, 0.680, 0.530)',\n easeInQuart: 'cubic-bezier(0.895, 0.030, 0.685, 0.220)',\n easeInQuint: 'cubic-bezier(0.755, 0.050, 0.855, 0.060)',\n easeInSine: 'cubic-bezier(0.470, 0.000, 0.745, 0.715)',\n easeOutBack: 'cubic-bezier(0.175, 0.885, 0.320, 1.275)',\n easeOutCubic: 'cubic-bezier(0.215, 0.610, 0.355, 1.000)',\n easeOutCirc: 'cubic-bezier(0.075, 0.820, 0.165, 1.000)',\n easeOutExpo: 'cubic-bezier(0.190, 1.000, 0.220, 1.000)',\n easeOutQuad: 'cubic-bezier(0.250, 0.460, 0.450, 0.940)',\n easeOutQuart: 'cubic-bezier(0.165, 0.840, 0.440, 1.000)',\n easeOutQuint: 'cubic-bezier(0.230, 1.000, 0.320, 1.000)',\n easeOutSine: 'cubic-bezier(0.390, 0.575, 0.565, 1.000)',\n easeInOutBack: 'cubic-bezier(0.680, -0.550, 0.265, 1.550)',\n easeInOutCirc: 'cubic-bezier(0.785, 0.135, 0.150, 0.860)',\n easeInOutCubic: 'cubic-bezier(0.645, 0.045, 0.355, 1.000)',\n easeInOutExpo: 'cubic-bezier(1.000, 0.000, 0.000, 1.000)',\n easeInOutQuad: 'cubic-bezier(0.455, 0.030, 0.515, 0.955)',\n easeInOutQuart: 'cubic-bezier(0.770, 0.000, 0.175, 1.000)',\n easeInOutQuint: 'cubic-bezier(0.860, 0.000, 0.070, 1.000)',\n easeInOutSine: 'cubic-bezier(0.445, 0.050, 0.550, 0.950)'\n};\n/* eslint-enable key-spacing */\n\nfunction getTimingFunction(functionName) {\n return functionsMap[functionName];\n}\n\n/**\n * String to represent common easing functions as demonstrated here: (github.com/jaukia/easie).\n *\n * @deprecated - This will be deprecated in v5 in favor of `easeIn`, `easeOut`, `easeInOut`.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * 'transitionTimingFunction': timingFunctions('easeInQuad')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * transitionTimingFunction: ${timingFunctions('easeInQuad')};\n * `\n *\n * // CSS as JS Output\n *\n * 'div': {\n * 'transitionTimingFunction': 'cubic-bezier(0.550, 0.085, 0.680, 0.530)',\n * }\n */\n\nfunction timingFunctions(timingFunction) {\n return getTimingFunction(timingFunction);\n}\n\nvar getBorderWidth = function getBorderWidth(pointingDirection, height, width) {\n var fullWidth = \"\" + width[0] + (width[1] || '');\n var halfWidth = \"\" + width[0] / 2 + (width[1] || '');\n var fullHeight = \"\" + height[0] + (height[1] || '');\n var halfHeight = \"\" + height[0] / 2 + (height[1] || '');\n switch (pointingDirection) {\n case 'top':\n return \"0 \" + halfWidth + \" \" + fullHeight + \" \" + halfWidth;\n case 'topLeft':\n return fullWidth + \" \" + fullHeight + \" 0 0\";\n case 'left':\n return halfHeight + \" \" + fullWidth + \" \" + halfHeight + \" 0\";\n case 'bottomLeft':\n return fullWidth + \" 0 0 \" + fullHeight;\n case 'bottom':\n return fullHeight + \" \" + halfWidth + \" 0 \" + halfWidth;\n case 'bottomRight':\n return \"0 0 \" + fullWidth + \" \" + fullHeight;\n case 'right':\n return halfHeight + \" 0 \" + halfHeight + \" \" + fullWidth;\n case 'topRight':\n default:\n return \"0 \" + fullWidth + \" \" + fullHeight + \" 0\";\n }\n};\nvar getBorderColor = function getBorderColor(pointingDirection, foregroundColor) {\n switch (pointingDirection) {\n case 'top':\n case 'bottomRight':\n return {\n borderBottomColor: foregroundColor\n };\n case 'right':\n case 'bottomLeft':\n return {\n borderLeftColor: foregroundColor\n };\n case 'bottom':\n case 'topLeft':\n return {\n borderTopColor: foregroundColor\n };\n case 'left':\n case 'topRight':\n return {\n borderRightColor: foregroundColor\n };\n default:\n throw new PolishedError(59);\n }\n};\n\n/**\n * CSS to represent triangle with any pointing direction with an optional background color.\n *\n * @example\n * // Styles as object usage\n *\n * const styles = {\n * ...triangle({ pointingDirection: 'right', width: '100px', height: '100px', foregroundColor: 'red' })\n * }\n *\n *\n * // styled-components usage\n * const div = styled.div`\n * ${triangle({ pointingDirection: 'right', width: '100px', height: '100px', foregroundColor: 'red' })}\n *\n *\n * // CSS as JS Output\n *\n * div: {\n * 'borderColor': 'transparent transparent transparent red',\n * 'borderStyle': 'solid',\n * 'borderWidth': '50px 0 50px 100px',\n * 'height': '0',\n * 'width': '0',\n * }\n */\nfunction triangle(_ref) {\n var pointingDirection = _ref.pointingDirection,\n height = _ref.height,\n width = _ref.width,\n foregroundColor = _ref.foregroundColor,\n _ref$backgroundColor = _ref.backgroundColor,\n backgroundColor = _ref$backgroundColor === void 0 ? 'transparent' : _ref$backgroundColor;\n var widthAndUnit = getValueAndUnit(width);\n var heightAndUnit = getValueAndUnit(height);\n if (isNaN(heightAndUnit[0]) || isNaN(widthAndUnit[0])) {\n throw new PolishedError(60);\n }\n return _extends({\n width: '0',\n height: '0',\n borderColor: backgroundColor\n }, getBorderColor(pointingDirection, foregroundColor), {\n borderStyle: 'solid',\n borderWidth: getBorderWidth(pointingDirection, heightAndUnit, widthAndUnit)\n });\n}\n\n/**\n * Provides an easy way to change the `wordWrap` property.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...wordWrap('break-word')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${wordWrap('break-word')}\n * `\n *\n * // CSS as JS Output\n *\n * const styles = {\n * overflowWrap: 'break-word',\n * wordWrap: 'break-word',\n * wordBreak: 'break-all',\n * }\n */\nfunction wordWrap(wrap) {\n if (wrap === void 0) {\n wrap = 'break-word';\n }\n var wordBreak = wrap === 'break-word' ? 'break-all' : wrap;\n return {\n overflowWrap: wrap,\n wordWrap: wrap,\n wordBreak: wordBreak\n };\n}\n\nfunction colorToInt(color) {\n return Math.round(color * 255);\n}\nfunction convertToInt(red, green, blue) {\n return colorToInt(red) + \",\" + colorToInt(green) + \",\" + colorToInt(blue);\n}\nfunction hslToRgb(hue, saturation, lightness, convert) {\n if (convert === void 0) {\n convert = convertToInt;\n }\n if (saturation === 0) {\n // achromatic\n return convert(lightness, lightness, lightness);\n }\n\n // formulae from https://en.wikipedia.org/wiki/HSL_and_HSV\n var huePrime = (hue % 360 + 360) % 360 / 60;\n var chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;\n var secondComponent = chroma * (1 - Math.abs(huePrime % 2 - 1));\n var red = 0;\n var green = 0;\n var blue = 0;\n if (huePrime >= 0 && huePrime < 1) {\n red = chroma;\n green = secondComponent;\n } else if (huePrime >= 1 && huePrime < 2) {\n red = secondComponent;\n green = chroma;\n } else if (huePrime >= 2 && huePrime < 3) {\n green = chroma;\n blue = secondComponent;\n } else if (huePrime >= 3 && huePrime < 4) {\n green = secondComponent;\n blue = chroma;\n } else if (huePrime >= 4 && huePrime < 5) {\n red = secondComponent;\n blue = chroma;\n } else if (huePrime >= 5 && huePrime < 6) {\n red = chroma;\n blue = secondComponent;\n }\n var lightnessModification = lightness - chroma / 2;\n var finalRed = red + lightnessModification;\n var finalGreen = green + lightnessModification;\n var finalBlue = blue + lightnessModification;\n return convert(finalRed, finalGreen, finalBlue);\n}\n\nvar namedColorMap = {\n aliceblue: 'f0f8ff',\n antiquewhite: 'faebd7',\n aqua: '00ffff',\n aquamarine: '7fffd4',\n azure: 'f0ffff',\n beige: 'f5f5dc',\n bisque: 'ffe4c4',\n black: '000',\n blanchedalmond: 'ffebcd',\n blue: '0000ff',\n blueviolet: '8a2be2',\n brown: 'a52a2a',\n burlywood: 'deb887',\n cadetblue: '5f9ea0',\n chartreuse: '7fff00',\n chocolate: 'd2691e',\n coral: 'ff7f50',\n cornflowerblue: '6495ed',\n cornsilk: 'fff8dc',\n crimson: 'dc143c',\n cyan: '00ffff',\n darkblue: '00008b',\n darkcyan: '008b8b',\n darkgoldenrod: 'b8860b',\n darkgray: 'a9a9a9',\n darkgreen: '006400',\n darkgrey: 'a9a9a9',\n darkkhaki: 'bdb76b',\n darkmagenta: '8b008b',\n darkolivegreen: '556b2f',\n darkorange: 'ff8c00',\n darkorchid: '9932cc',\n darkred: '8b0000',\n darksalmon: 'e9967a',\n darkseagreen: '8fbc8f',\n darkslateblue: '483d8b',\n darkslategray: '2f4f4f',\n darkslategrey: '2f4f4f',\n darkturquoise: '00ced1',\n darkviolet: '9400d3',\n deeppink: 'ff1493',\n deepskyblue: '00bfff',\n dimgray: '696969',\n dimgrey: '696969',\n dodgerblue: '1e90ff',\n firebrick: 'b22222',\n floralwhite: 'fffaf0',\n forestgreen: '228b22',\n fuchsia: 'ff00ff',\n gainsboro: 'dcdcdc',\n ghostwhite: 'f8f8ff',\n gold: 'ffd700',\n goldenrod: 'daa520',\n gray: '808080',\n green: '008000',\n greenyellow: 'adff2f',\n grey: '808080',\n honeydew: 'f0fff0',\n hotpink: 'ff69b4',\n indianred: 'cd5c5c',\n indigo: '4b0082',\n ivory: 'fffff0',\n khaki: 'f0e68c',\n lavender: 'e6e6fa',\n lavenderblush: 'fff0f5',\n lawngreen: '7cfc00',\n lemonchiffon: 'fffacd',\n lightblue: 'add8e6',\n lightcoral: 'f08080',\n lightcyan: 'e0ffff',\n lightgoldenrodyellow: 'fafad2',\n lightgray: 'd3d3d3',\n lightgreen: '90ee90',\n lightgrey: 'd3d3d3',\n lightpink: 'ffb6c1',\n lightsalmon: 'ffa07a',\n lightseagreen: '20b2aa',\n lightskyblue: '87cefa',\n lightslategray: '789',\n lightslategrey: '789',\n lightsteelblue: 'b0c4de',\n lightyellow: 'ffffe0',\n lime: '0f0',\n limegreen: '32cd32',\n linen: 'faf0e6',\n magenta: 'f0f',\n maroon: '800000',\n mediumaquamarine: '66cdaa',\n mediumblue: '0000cd',\n mediumorchid: 'ba55d3',\n mediumpurple: '9370db',\n mediumseagreen: '3cb371',\n mediumslateblue: '7b68ee',\n mediumspringgreen: '00fa9a',\n mediumturquoise: '48d1cc',\n mediumvioletred: 'c71585',\n midnightblue: '191970',\n mintcream: 'f5fffa',\n mistyrose: 'ffe4e1',\n moccasin: 'ffe4b5',\n navajowhite: 'ffdead',\n navy: '000080',\n oldlace: 'fdf5e6',\n olive: '808000',\n olivedrab: '6b8e23',\n orange: 'ffa500',\n orangered: 'ff4500',\n orchid: 'da70d6',\n palegoldenrod: 'eee8aa',\n palegreen: '98fb98',\n paleturquoise: 'afeeee',\n palevioletred: 'db7093',\n papayawhip: 'ffefd5',\n peachpuff: 'ffdab9',\n peru: 'cd853f',\n pink: 'ffc0cb',\n plum: 'dda0dd',\n powderblue: 'b0e0e6',\n purple: '800080',\n rebeccapurple: '639',\n red: 'f00',\n rosybrown: 'bc8f8f',\n royalblue: '4169e1',\n saddlebrown: '8b4513',\n salmon: 'fa8072',\n sandybrown: 'f4a460',\n seagreen: '2e8b57',\n seashell: 'fff5ee',\n sienna: 'a0522d',\n silver: 'c0c0c0',\n skyblue: '87ceeb',\n slateblue: '6a5acd',\n slategray: '708090',\n slategrey: '708090',\n snow: 'fffafa',\n springgreen: '00ff7f',\n steelblue: '4682b4',\n tan: 'd2b48c',\n teal: '008080',\n thistle: 'd8bfd8',\n tomato: 'ff6347',\n turquoise: '40e0d0',\n violet: 'ee82ee',\n wheat: 'f5deb3',\n white: 'fff',\n whitesmoke: 'f5f5f5',\n yellow: 'ff0',\n yellowgreen: '9acd32'\n};\n\n/**\n * Checks if a string is a CSS named color and returns its equivalent hex value, otherwise returns the original color.\n * @private\n */\nfunction nameToHex(color) {\n if (typeof color !== 'string') return color;\n var normalizedColorName = color.toLowerCase();\n return namedColorMap[normalizedColorName] ? \"#\" + namedColorMap[normalizedColorName] : color;\n}\n\nvar hexRegex = /^#[a-fA-F0-9]{6}$/;\nvar hexRgbaRegex = /^#[a-fA-F0-9]{8}$/;\nvar reducedHexRegex = /^#[a-fA-F0-9]{3}$/;\nvar reducedRgbaHexRegex = /^#[a-fA-F0-9]{4}$/;\nvar rgbRegex = /^rgb\\(\\s*(\\d{1,3})\\s*(?:,)?\\s*(\\d{1,3})\\s*(?:,)?\\s*(\\d{1,3})\\s*\\)$/i;\nvar rgbaRegex = /^rgb(?:a)?\\(\\s*(\\d{1,3})\\s*(?:,)?\\s*(\\d{1,3})\\s*(?:,)?\\s*(\\d{1,3})\\s*(?:,|\\/)\\s*([-+]?\\d*[.]?\\d+[%]?)\\s*\\)$/i;\nvar hslRegex = /^hsl\\(\\s*(\\d{0,3}[.]?[0-9]+(?:deg)?)\\s*(?:,)?\\s*(\\d{1,3}[.]?[0-9]?)%\\s*(?:,)?\\s*(\\d{1,3}[.]?[0-9]?)%\\s*\\)$/i;\nvar hslaRegex = /^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;\n\n/**\n * Returns an RgbColor or RgbaColor object. This utility function is only useful\n * if want to extract a color component. With the color util `toColorString` you\n * can convert a RgbColor or RgbaColor object back to a string.\n *\n * @example\n * // Assigns `{ red: 255, green: 0, blue: 0 }` to color1\n * const color1 = parseToRgb('rgb(255, 0, 0)');\n * // Assigns `{ red: 92, green: 102, blue: 112, alpha: 0.75 }` to color2\n * const color2 = parseToRgb('hsla(210, 10%, 40%, 0.75)');\n */\nfunction parseToRgb(color) {\n if (typeof color !== 'string') {\n throw new PolishedError(3);\n }\n var normalizedColor = nameToHex(color);\n if (normalizedColor.match(hexRegex)) {\n return {\n red: parseInt(\"\" + normalizedColor[1] + normalizedColor[2], 16),\n green: parseInt(\"\" + normalizedColor[3] + normalizedColor[4], 16),\n blue: parseInt(\"\" + normalizedColor[5] + normalizedColor[6], 16)\n };\n }\n if (normalizedColor.match(hexRgbaRegex)) {\n var alpha = parseFloat((parseInt(\"\" + normalizedColor[7] + normalizedColor[8], 16) / 255).toFixed(2));\n return {\n red: parseInt(\"\" + normalizedColor[1] + normalizedColor[2], 16),\n green: parseInt(\"\" + normalizedColor[3] + normalizedColor[4], 16),\n blue: parseInt(\"\" + normalizedColor[5] + normalizedColor[6], 16),\n alpha: alpha\n };\n }\n if (normalizedColor.match(reducedHexRegex)) {\n return {\n red: parseInt(\"\" + normalizedColor[1] + normalizedColor[1], 16),\n green: parseInt(\"\" + normalizedColor[2] + normalizedColor[2], 16),\n blue: parseInt(\"\" + normalizedColor[3] + normalizedColor[3], 16)\n };\n }\n if (normalizedColor.match(reducedRgbaHexRegex)) {\n var _alpha = parseFloat((parseInt(\"\" + normalizedColor[4] + normalizedColor[4], 16) / 255).toFixed(2));\n return {\n red: parseInt(\"\" + normalizedColor[1] + normalizedColor[1], 16),\n green: parseInt(\"\" + normalizedColor[2] + normalizedColor[2], 16),\n blue: parseInt(\"\" + normalizedColor[3] + normalizedColor[3], 16),\n alpha: _alpha\n };\n }\n var rgbMatched = rgbRegex.exec(normalizedColor);\n if (rgbMatched) {\n return {\n red: parseInt(\"\" + rgbMatched[1], 10),\n green: parseInt(\"\" + rgbMatched[2], 10),\n blue: parseInt(\"\" + rgbMatched[3], 10)\n };\n }\n var rgbaMatched = rgbaRegex.exec(normalizedColor.substring(0, 50));\n if (rgbaMatched) {\n return {\n red: parseInt(\"\" + rgbaMatched[1], 10),\n green: parseInt(\"\" + rgbaMatched[2], 10),\n blue: parseInt(\"\" + rgbaMatched[3], 10),\n alpha: parseFloat(\"\" + rgbaMatched[4]) > 1 ? parseFloat(\"\" + rgbaMatched[4]) / 100 : parseFloat(\"\" + rgbaMatched[4])\n };\n }\n var hslMatched = hslRegex.exec(normalizedColor);\n if (hslMatched) {\n var hue = parseInt(\"\" + hslMatched[1], 10);\n var saturation = parseInt(\"\" + hslMatched[2], 10) / 100;\n var lightness = parseInt(\"\" + hslMatched[3], 10) / 100;\n var rgbColorString = \"rgb(\" + hslToRgb(hue, saturation, lightness) + \")\";\n var hslRgbMatched = rgbRegex.exec(rgbColorString);\n if (!hslRgbMatched) {\n throw new PolishedError(4, normalizedColor, rgbColorString);\n }\n return {\n red: parseInt(\"\" + hslRgbMatched[1], 10),\n green: parseInt(\"\" + hslRgbMatched[2], 10),\n blue: parseInt(\"\" + hslRgbMatched[3], 10)\n };\n }\n var hslaMatched = hslaRegex.exec(normalizedColor.substring(0, 50));\n if (hslaMatched) {\n var _hue = parseInt(\"\" + hslaMatched[1], 10);\n var _saturation = parseInt(\"\" + hslaMatched[2], 10) / 100;\n var _lightness = parseInt(\"\" + hslaMatched[3], 10) / 100;\n var _rgbColorString = \"rgb(\" + hslToRgb(_hue, _saturation, _lightness) + \")\";\n var _hslRgbMatched = rgbRegex.exec(_rgbColorString);\n if (!_hslRgbMatched) {\n throw new PolishedError(4, normalizedColor, _rgbColorString);\n }\n return {\n red: parseInt(\"\" + _hslRgbMatched[1], 10),\n green: parseInt(\"\" + _hslRgbMatched[2], 10),\n blue: parseInt(\"\" + _hslRgbMatched[3], 10),\n alpha: parseFloat(\"\" + hslaMatched[4]) > 1 ? parseFloat(\"\" + hslaMatched[4]) / 100 : parseFloat(\"\" + hslaMatched[4])\n };\n }\n throw new PolishedError(5);\n}\n\nfunction rgbToHsl(color) {\n // make sure rgb are contained in a set of [0, 255]\n var red = color.red / 255;\n var green = color.green / 255;\n var blue = color.blue / 255;\n var max = Math.max(red, green, blue);\n var min = Math.min(red, green, blue);\n var lightness = (max + min) / 2;\n if (max === min) {\n // achromatic\n if (color.alpha !== undefined) {\n return {\n hue: 0,\n saturation: 0,\n lightness: lightness,\n alpha: color.alpha\n };\n } else {\n return {\n hue: 0,\n saturation: 0,\n lightness: lightness\n };\n }\n }\n var hue;\n var delta = max - min;\n var saturation = lightness > 0.5 ? delta / (2 - max - min) : delta / (max + min);\n switch (max) {\n case red:\n hue = (green - blue) / delta + (green < blue ? 6 : 0);\n break;\n case green:\n hue = (blue - red) / delta + 2;\n break;\n default:\n // blue case\n hue = (red - green) / delta + 4;\n break;\n }\n hue *= 60;\n if (color.alpha !== undefined) {\n return {\n hue: hue,\n saturation: saturation,\n lightness: lightness,\n alpha: color.alpha\n };\n }\n return {\n hue: hue,\n saturation: saturation,\n lightness: lightness\n };\n}\n\n/**\n * Returns an HslColor or HslaColor object. This utility function is only useful\n * if want to extract a color component. With the color util `toColorString` you\n * can convert a HslColor or HslaColor object back to a string.\n *\n * @example\n * // Assigns `{ hue: 0, saturation: 1, lightness: 0.5 }` to color1\n * const color1 = parseToHsl('rgb(255, 0, 0)');\n * // Assigns `{ hue: 128, saturation: 1, lightness: 0.5, alpha: 0.75 }` to color2\n * const color2 = parseToHsl('hsla(128, 100%, 50%, 0.75)');\n */\nfunction parseToHsl(color) {\n // Note: At a later stage we can optimize this function as right now a hsl\n // color would be parsed converted to rgb values and converted back to hsl.\n return rgbToHsl(parseToRgb(color));\n}\n\n/**\n * Reduces hex values if possible e.g. #ff8866 to #f86\n * @private\n */\nvar reduceHexValue = function reduceHexValue(value) {\n if (value.length === 7 && value[1] === value[2] && value[3] === value[4] && value[5] === value[6]) {\n return \"#\" + value[1] + value[3] + value[5];\n }\n return value;\n};\nvar reduceHexValue$1 = reduceHexValue;\n\nfunction numberToHex(value) {\n var hex = value.toString(16);\n return hex.length === 1 ? \"0\" + hex : hex;\n}\n\nfunction colorToHex(color) {\n return numberToHex(Math.round(color * 255));\n}\nfunction convertToHex(red, green, blue) {\n return reduceHexValue$1(\"#\" + colorToHex(red) + colorToHex(green) + colorToHex(blue));\n}\nfunction hslToHex(hue, saturation, lightness) {\n return hslToRgb(hue, saturation, lightness, convertToHex);\n}\n\n/**\n * Returns a string value for the color. The returned result is the smallest possible hex notation.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: hsl(359, 0.75, 0.4),\n * background: hsl({ hue: 360, saturation: 0.75, lightness: 0.4 }),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${hsl(359, 0.75, 0.4)};\n * background: ${hsl({ hue: 360, saturation: 0.75, lightness: 0.4 })};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#b3191c\";\n * background: \"#b3191c\";\n * }\n */\nfunction hsl(value, saturation, lightness) {\n if (typeof value === 'number' && typeof saturation === 'number' && typeof lightness === 'number') {\n return hslToHex(value, saturation, lightness);\n } else if (typeof value === 'object' && saturation === undefined && lightness === undefined) {\n return hslToHex(value.hue, value.saturation, value.lightness);\n }\n throw new PolishedError(1);\n}\n\n/**\n * Returns a string value for the color. The returned result is the smallest possible rgba or hex notation.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: hsla(359, 0.75, 0.4, 0.7),\n * background: hsla({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0,7 }),\n * background: hsla(359, 0.75, 0.4, 1),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${hsla(359, 0.75, 0.4, 0.7)};\n * background: ${hsla({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0,7 })};\n * background: ${hsla(359, 0.75, 0.4, 1)};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"rgba(179,25,28,0.7)\";\n * background: \"rgba(179,25,28,0.7)\";\n * background: \"#b3191c\";\n * }\n */\nfunction hsla(value, saturation, lightness, alpha) {\n if (typeof value === 'number' && typeof saturation === 'number' && typeof lightness === 'number' && typeof alpha === 'number') {\n return alpha >= 1 ? hslToHex(value, saturation, lightness) : \"rgba(\" + hslToRgb(value, saturation, lightness) + \",\" + alpha + \")\";\n } else if (typeof value === 'object' && saturation === undefined && lightness === undefined && alpha === undefined) {\n return value.alpha >= 1 ? hslToHex(value.hue, value.saturation, value.lightness) : \"rgba(\" + hslToRgb(value.hue, value.saturation, value.lightness) + \",\" + value.alpha + \")\";\n }\n throw new PolishedError(2);\n}\n\n/**\n * Returns a string value for the color. The returned result is the smallest possible hex notation.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: rgb(255, 205, 100),\n * background: rgb({ red: 255, green: 205, blue: 100 }),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${rgb(255, 205, 100)};\n * background: ${rgb({ red: 255, green: 205, blue: 100 })};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#ffcd64\";\n * background: \"#ffcd64\";\n * }\n */\nfunction rgb(value, green, blue) {\n if (typeof value === 'number' && typeof green === 'number' && typeof blue === 'number') {\n return reduceHexValue$1(\"#\" + numberToHex(value) + numberToHex(green) + numberToHex(blue));\n } else if (typeof value === 'object' && green === undefined && blue === undefined) {\n return reduceHexValue$1(\"#\" + numberToHex(value.red) + numberToHex(value.green) + numberToHex(value.blue));\n }\n throw new PolishedError(6);\n}\n\n/**\n * Returns a string value for the color. The returned result is the smallest possible rgba or hex notation.\n *\n * Can also be used to fade a color by passing a hex value or named CSS color along with an alpha value.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: rgba(255, 205, 100, 0.7),\n * background: rgba({ red: 255, green: 205, blue: 100, alpha: 0.7 }),\n * background: rgba(255, 205, 100, 1),\n * background: rgba('#ffffff', 0.4),\n * background: rgba('black', 0.7),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${rgba(255, 205, 100, 0.7)};\n * background: ${rgba({ red: 255, green: 205, blue: 100, alpha: 0.7 })};\n * background: ${rgba(255, 205, 100, 1)};\n * background: ${rgba('#ffffff', 0.4)};\n * background: ${rgba('black', 0.7)};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"rgba(255,205,100,0.7)\";\n * background: \"rgba(255,205,100,0.7)\";\n * background: \"#ffcd64\";\n * background: \"rgba(255,255,255,0.4)\";\n * background: \"rgba(0,0,0,0.7)\";\n * }\n */\nfunction rgba(firstValue, secondValue, thirdValue, fourthValue) {\n if (typeof firstValue === 'string' && typeof secondValue === 'number') {\n var rgbValue = parseToRgb(firstValue);\n return \"rgba(\" + rgbValue.red + \",\" + rgbValue.green + \",\" + rgbValue.blue + \",\" + secondValue + \")\";\n } else if (typeof firstValue === 'number' && typeof secondValue === 'number' && typeof thirdValue === 'number' && typeof fourthValue === 'number') {\n return fourthValue >= 1 ? rgb(firstValue, secondValue, thirdValue) : \"rgba(\" + firstValue + \",\" + secondValue + \",\" + thirdValue + \",\" + fourthValue + \")\";\n } else if (typeof firstValue === 'object' && secondValue === undefined && thirdValue === undefined && fourthValue === undefined) {\n return firstValue.alpha >= 1 ? rgb(firstValue.red, firstValue.green, firstValue.blue) : \"rgba(\" + firstValue.red + \",\" + firstValue.green + \",\" + firstValue.blue + \",\" + firstValue.alpha + \")\";\n }\n throw new PolishedError(7);\n}\n\nvar isRgb = function isRgb(color) {\n return typeof color.red === 'number' && typeof color.green === 'number' && typeof color.blue === 'number' && (typeof color.alpha !== 'number' || typeof color.alpha === 'undefined');\n};\nvar isRgba = function isRgba(color) {\n return typeof color.red === 'number' && typeof color.green === 'number' && typeof color.blue === 'number' && typeof color.alpha === 'number';\n};\nvar isHsl = function isHsl(color) {\n return typeof color.hue === 'number' && typeof color.saturation === 'number' && typeof color.lightness === 'number' && (typeof color.alpha !== 'number' || typeof color.alpha === 'undefined');\n};\nvar isHsla = function isHsla(color) {\n return typeof color.hue === 'number' && typeof color.saturation === 'number' && typeof color.lightness === 'number' && typeof color.alpha === 'number';\n};\n\n/**\n * Converts a RgbColor, RgbaColor, HslColor or HslaColor object to a color string.\n * This util is useful in case you only know on runtime which color object is\n * used. Otherwise we recommend to rely on `rgb`, `rgba`, `hsl` or `hsla`.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: toColorString({ red: 255, green: 205, blue: 100 }),\n * background: toColorString({ red: 255, green: 205, blue: 100, alpha: 0.72 }),\n * background: toColorString({ hue: 240, saturation: 1, lightness: 0.5 }),\n * background: toColorString({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0.72 }),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${toColorString({ red: 255, green: 205, blue: 100 })};\n * background: ${toColorString({ red: 255, green: 205, blue: 100, alpha: 0.72 })};\n * background: ${toColorString({ hue: 240, saturation: 1, lightness: 0.5 })};\n * background: ${toColorString({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0.72 })};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#ffcd64\";\n * background: \"rgba(255,205,100,0.72)\";\n * background: \"#00f\";\n * background: \"rgba(179,25,25,0.72)\";\n * }\n */\n\nfunction toColorString(color) {\n if (typeof color !== 'object') throw new PolishedError(8);\n if (isRgba(color)) return rgba(color);\n if (isRgb(color)) return rgb(color);\n if (isHsla(color)) return hsla(color);\n if (isHsl(color)) return hsl(color);\n throw new PolishedError(8);\n}\n\n// Type definitions taken from https://github.com/gcanti/flow-static-land/blob/master/src/Fun.js\n// eslint-disable-next-line no-unused-vars\n// eslint-disable-next-line no-unused-vars\n// eslint-disable-next-line no-redeclare\nfunction curried(f, length, acc) {\n return function fn() {\n // eslint-disable-next-line prefer-rest-params\n var combined = acc.concat(Array.prototype.slice.call(arguments));\n return combined.length >= length ? f.apply(this, combined) : curried(f, length, combined);\n };\n}\n\n// eslint-disable-next-line no-redeclare\nfunction curry(f) {\n // eslint-disable-line no-redeclare\n return curried(f, f.length, []);\n}\n\n/**\n * Changes the hue of the color. Hue is a number between 0 to 360. The first\n * argument for adjustHue is the amount of degrees the color is rotated around\n * the color wheel, always producing a positive hue value.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: adjustHue(180, '#448'),\n * background: adjustHue('180', 'rgba(101,100,205,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${adjustHue(180, '#448')};\n * background: ${adjustHue('180', 'rgba(101,100,205,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#888844\";\n * background: \"rgba(136,136,68,0.7)\";\n * }\n */\nfunction adjustHue(degree, color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n hue: hslColor.hue + parseFloat(degree)\n }));\n}\n\n// prettier-ignore\nvar curriedAdjustHue = curry /* ::<number | string, string, string> */(adjustHue);\nvar curriedAdjustHue$1 = curriedAdjustHue;\n\n/**\n * Returns the complement of the provided color. This is identical to adjustHue(180, <color>).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: complement('#448'),\n * background: complement('rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${complement('#448')};\n * background: ${complement('rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#884\";\n * background: \"rgba(153,153,153,0.7)\";\n * }\n */\nfunction complement(color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n hue: (hslColor.hue + 180) % 360\n }));\n}\n\nfunction guard(lowerBoundary, upperBoundary, value) {\n return Math.max(lowerBoundary, Math.min(upperBoundary, value));\n}\n\n/**\n * Returns a string value for the darkened color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: darken(0.2, '#FFCD64'),\n * background: darken('0.2', 'rgba(255,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${darken(0.2, '#FFCD64')};\n * background: ${darken('0.2', 'rgba(255,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#ffbd31\";\n * background: \"rgba(255,189,49,0.7)\";\n * }\n */\nfunction darken(amount, color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n lightness: guard(0, 1, hslColor.lightness - parseFloat(amount))\n }));\n}\n\n// prettier-ignore\nvar curriedDarken = curry /* ::<number | string, string, string> */(darken);\nvar curriedDarken$1 = curriedDarken;\n\n/**\n * Decreases the intensity of a color. Its range is between 0 to 1. The first\n * argument of the desaturate function is the amount by how much the color\n * intensity should be decreased.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: desaturate(0.2, '#CCCD64'),\n * background: desaturate('0.2', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${desaturate(0.2, '#CCCD64')};\n * background: ${desaturate('0.2', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#b8b979\";\n * background: \"rgba(184,185,121,0.7)\";\n * }\n */\nfunction desaturate(amount, color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n saturation: guard(0, 1, hslColor.saturation - parseFloat(amount))\n }));\n}\n\n// prettier-ignore\nvar curriedDesaturate = curry /* ::<number | string, string, string> */(desaturate);\nvar curriedDesaturate$1 = curriedDesaturate;\n\n/**\n * Returns a number (float) representing the luminance of a color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: getLuminance('#CCCD64') >= getLuminance('#0000ff') ? '#CCCD64' : '#0000ff',\n * background: getLuminance('rgba(58, 133, 255, 1)') >= getLuminance('rgba(255, 57, 149, 1)') ?\n * 'rgba(58, 133, 255, 1)' :\n * 'rgba(255, 57, 149, 1)',\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${getLuminance('#CCCD64') >= getLuminance('#0000ff') ? '#CCCD64' : '#0000ff'};\n * background: ${getLuminance('rgba(58, 133, 255, 1)') >= getLuminance('rgba(255, 57, 149, 1)') ?\n * 'rgba(58, 133, 255, 1)' :\n * 'rgba(255, 57, 149, 1)'};\n *\n * // CSS in JS Output\n *\n * div {\n * background: \"#CCCD64\";\n * background: \"rgba(58, 133, 255, 1)\";\n * }\n */\nfunction getLuminance(color) {\n if (color === 'transparent') return 0;\n var rgbColor = parseToRgb(color);\n var _Object$keys$map = Object.keys(rgbColor).map(function (key) {\n var channel = rgbColor[key] / 255;\n return channel <= 0.03928 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);\n }),\n r = _Object$keys$map[0],\n g = _Object$keys$map[1],\n b = _Object$keys$map[2];\n return parseFloat((0.2126 * r + 0.7152 * g + 0.0722 * b).toFixed(3));\n}\n\n/**\n * Returns the contrast ratio between two colors based on\n * [W3's recommended equation for calculating contrast](http://www.w3.org/TR/WCAG20/#contrast-ratiodef).\n *\n * @example\n * const contrastRatio = getContrast('#444', '#fff');\n */\nfunction getContrast(color1, color2) {\n var luminance1 = getLuminance(color1);\n var luminance2 = getLuminance(color2);\n return parseFloat((luminance1 > luminance2 ? (luminance1 + 0.05) / (luminance2 + 0.05) : (luminance2 + 0.05) / (luminance1 + 0.05)).toFixed(2));\n}\n\n/**\n * Converts the color to a grayscale, by reducing its saturation to 0.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: grayscale('#CCCD64'),\n * background: grayscale('rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${grayscale('#CCCD64')};\n * background: ${grayscale('rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#999\";\n * background: \"rgba(153,153,153,0.7)\";\n * }\n */\nfunction grayscale(color) {\n if (color === 'transparent') return color;\n return toColorString(_extends({}, parseToHsl(color), {\n saturation: 0\n }));\n}\n\n/**\n * Converts a HslColor or HslaColor object to a color string.\n * This util is useful in case you only know on runtime which color object is\n * used. Otherwise we recommend to rely on `hsl` or `hsla`.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: hslToColorString({ hue: 240, saturation: 1, lightness: 0.5 }),\n * background: hslToColorString({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0.72 }),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${hslToColorString({ hue: 240, saturation: 1, lightness: 0.5 })};\n * background: ${hslToColorString({ hue: 360, saturation: 0.75, lightness: 0.4, alpha: 0.72 })};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#00f\";\n * background: \"rgba(179,25,25,0.72)\";\n * }\n */\nfunction hslToColorString(color) {\n if (typeof color === 'object' && typeof color.hue === 'number' && typeof color.saturation === 'number' && typeof color.lightness === 'number') {\n if (color.alpha && typeof color.alpha === 'number') {\n return hsla({\n hue: color.hue,\n saturation: color.saturation,\n lightness: color.lightness,\n alpha: color.alpha\n });\n }\n return hsl({\n hue: color.hue,\n saturation: color.saturation,\n lightness: color.lightness\n });\n }\n throw new PolishedError(45);\n}\n\n/**\n * Inverts the red, green and blue values of a color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: invert('#CCCD64'),\n * background: invert('rgba(101,100,205,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${invert('#CCCD64')};\n * background: ${invert('rgba(101,100,205,0.7)')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#33329b\";\n * background: \"rgba(154,155,50,0.7)\";\n * }\n */\nfunction invert(color) {\n if (color === 'transparent') return color;\n // parse color string to rgb\n var value = parseToRgb(color);\n return toColorString(_extends({}, value, {\n red: 255 - value.red,\n green: 255 - value.green,\n blue: 255 - value.blue\n }));\n}\n\n/**\n * Returns a string value for the lightened color.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: lighten(0.2, '#CCCD64'),\n * background: lighten('0.2', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${lighten(0.2, '#FFCD64')};\n * background: ${lighten('0.2', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#e5e6b1\";\n * background: \"rgba(229,230,177,0.7)\";\n * }\n */\nfunction lighten(amount, color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n lightness: guard(0, 1, hslColor.lightness + parseFloat(amount))\n }));\n}\n\n// prettier-ignore\nvar curriedLighten = curry /* ::<number | string, string, string> */(lighten);\nvar curriedLighten$1 = curriedLighten;\n\n/**\n * Determines which contrast guidelines have been met for two colors.\n * Based on the [contrast calculations recommended by W3](https://www.w3.org/WAI/WCAG21/Understanding/contrast-enhanced.html).\n *\n * @example\n * const scores = meetsContrastGuidelines('#444', '#fff');\n */\nfunction meetsContrastGuidelines(color1, color2) {\n var contrastRatio = getContrast(color1, color2);\n return {\n AA: contrastRatio >= 4.5,\n AALarge: contrastRatio >= 3,\n AAA: contrastRatio >= 7,\n AAALarge: contrastRatio >= 4.5\n };\n}\n\n/**\n * Mixes the two provided colors together by calculating the average of each of the RGB components weighted to the first color by the provided weight.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: mix(0.5, '#f00', '#00f')\n * background: mix(0.25, '#f00', '#00f')\n * background: mix('0.5', 'rgba(255, 0, 0, 0.5)', '#00f')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${mix(0.5, '#f00', '#00f')};\n * background: ${mix(0.25, '#f00', '#00f')};\n * background: ${mix('0.5', 'rgba(255, 0, 0, 0.5)', '#00f')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#7f007f\";\n * background: \"#3f00bf\";\n * background: \"rgba(63, 0, 191, 0.75)\";\n * }\n */\nfunction mix(weight, color, otherColor) {\n if (color === 'transparent') return otherColor;\n if (otherColor === 'transparent') return color;\n if (weight === 0) return otherColor;\n var parsedColor1 = parseToRgb(color);\n var color1 = _extends({}, parsedColor1, {\n alpha: typeof parsedColor1.alpha === 'number' ? parsedColor1.alpha : 1\n });\n var parsedColor2 = parseToRgb(otherColor);\n var color2 = _extends({}, parsedColor2, {\n alpha: typeof parsedColor2.alpha === 'number' ? parsedColor2.alpha : 1\n });\n\n // The formula is copied from the original Sass implementation:\n // http://sass-lang.com/documentation/Sass/Script/Functions.html#mix-instance_method\n var alphaDelta = color1.alpha - color2.alpha;\n var x = parseFloat(weight) * 2 - 1;\n var y = x * alphaDelta === -1 ? x : x + alphaDelta;\n var z = 1 + x * alphaDelta;\n var weight1 = (y / z + 1) / 2.0;\n var weight2 = 1 - weight1;\n var mixedColor = {\n red: Math.floor(color1.red * weight1 + color2.red * weight2),\n green: Math.floor(color1.green * weight1 + color2.green * weight2),\n blue: Math.floor(color1.blue * weight1 + color2.blue * weight2),\n alpha: color1.alpha * parseFloat(weight) + color2.alpha * (1 - parseFloat(weight))\n };\n return rgba(mixedColor);\n}\n\n// prettier-ignore\nvar curriedMix = curry /* ::<number | string, string, string, string> */(mix);\nvar mix$1 = curriedMix;\n\n/**\n * Increases the opacity of a color. Its range for the amount is between 0 to 1.\n *\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: opacify(0.1, 'rgba(255, 255, 255, 0.9)');\n * background: opacify(0.2, 'hsla(0, 0%, 100%, 0.5)'),\n * background: opacify('0.5', 'rgba(255, 0, 0, 0.2)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${opacify(0.1, 'rgba(255, 255, 255, 0.9)')};\n * background: ${opacify(0.2, 'hsla(0, 0%, 100%, 0.5)')},\n * background: ${opacify('0.5', 'rgba(255, 0, 0, 0.2)')},\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#fff\";\n * background: \"rgba(255,255,255,0.7)\";\n * background: \"rgba(255,0,0,0.7)\";\n * }\n */\nfunction opacify(amount, color) {\n if (color === 'transparent') return color;\n var parsedColor = parseToRgb(color);\n var alpha = typeof parsedColor.alpha === 'number' ? parsedColor.alpha : 1;\n var colorWithAlpha = _extends({}, parsedColor, {\n alpha: guard(0, 1, (alpha * 100 + parseFloat(amount) * 100) / 100)\n });\n return rgba(colorWithAlpha);\n}\n\n// prettier-ignore\nvar curriedOpacify = curry /* ::<number | string, string, string> */(opacify);\nvar curriedOpacify$1 = curriedOpacify;\n\nvar defaultReturnIfLightColor = '#000';\nvar defaultReturnIfDarkColor = '#fff';\n\n/**\n * Returns black or white (or optional passed colors) for best\n * contrast depending on the luminosity of the given color.\n * When passing custom return colors, strict mode ensures that the\n * return color always meets or exceeds WCAG level AA or greater. If this test\n * fails, the default return color (black or white) is returned in place of the\n * custom return color. You can optionally turn off strict mode.\n *\n * Follows [W3C specs for readability](https://www.w3.org/TR/WCAG20-TECHS/G18.html).\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * color: readableColor('#000'),\n * color: readableColor('black', '#001', '#ff8'),\n * color: readableColor('white', '#001', '#ff8'),\n * color: readableColor('red', '#333', '#ddd', true)\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * color: ${readableColor('#000')};\n * color: ${readableColor('black', '#001', '#ff8')};\n * color: ${readableColor('white', '#001', '#ff8')};\n * color: ${readableColor('red', '#333', '#ddd', true)};\n * `\n *\n * // CSS in JS Output\n * element {\n * color: \"#fff\";\n * color: \"#ff8\";\n * color: \"#001\";\n * color: \"#000\";\n * }\n */\nfunction readableColor(color, returnIfLightColor, returnIfDarkColor, strict) {\n if (returnIfLightColor === void 0) {\n returnIfLightColor = defaultReturnIfLightColor;\n }\n if (returnIfDarkColor === void 0) {\n returnIfDarkColor = defaultReturnIfDarkColor;\n }\n if (strict === void 0) {\n strict = true;\n }\n var isColorLight = getLuminance(color) > 0.179;\n var preferredReturnColor = isColorLight ? returnIfLightColor : returnIfDarkColor;\n if (!strict || getContrast(color, preferredReturnColor) >= 4.5) {\n return preferredReturnColor;\n }\n return isColorLight ? defaultReturnIfLightColor : defaultReturnIfDarkColor;\n}\n\n/**\n * Converts a RgbColor or RgbaColor object to a color string.\n * This util is useful in case you only know on runtime which color object is\n * used. Otherwise we recommend to rely on `rgb` or `rgba`.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: rgbToColorString({ red: 255, green: 205, blue: 100 }),\n * background: rgbToColorString({ red: 255, green: 205, blue: 100, alpha: 0.72 }),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${rgbToColorString({ red: 255, green: 205, blue: 100 })};\n * background: ${rgbToColorString({ red: 255, green: 205, blue: 100, alpha: 0.72 })};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#ffcd64\";\n * background: \"rgba(255,205,100,0.72)\";\n * }\n */\nfunction rgbToColorString(color) {\n if (typeof color === 'object' && typeof color.red === 'number' && typeof color.green === 'number' && typeof color.blue === 'number') {\n if (typeof color.alpha === 'number') {\n return rgba({\n red: color.red,\n green: color.green,\n blue: color.blue,\n alpha: color.alpha\n });\n }\n return rgb({\n red: color.red,\n green: color.green,\n blue: color.blue\n });\n }\n throw new PolishedError(46);\n}\n\n/**\n * Increases the intensity of a color. Its range is between 0 to 1. The first\n * argument of the saturate function is the amount by how much the color\n * intensity should be increased.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: saturate(0.2, '#CCCD64'),\n * background: saturate('0.2', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${saturate(0.2, '#FFCD64')};\n * background: ${saturate('0.2', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#e0e250\";\n * background: \"rgba(224,226,80,0.7)\";\n * }\n */\nfunction saturate(amount, color) {\n if (color === 'transparent') return color;\n var hslColor = parseToHsl(color);\n return toColorString(_extends({}, hslColor, {\n saturation: guard(0, 1, hslColor.saturation + parseFloat(amount))\n }));\n}\n\n// prettier-ignore\nvar curriedSaturate = curry /* ::<number | string, string, string> */(saturate);\nvar curriedSaturate$1 = curriedSaturate;\n\n/**\n * Sets the hue of a color to the provided value. The hue range can be\n * from 0 and 359.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: setHue(42, '#CCCD64'),\n * background: setHue('244', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${setHue(42, '#CCCD64')};\n * background: ${setHue('244', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#cdae64\";\n * background: \"rgba(107,100,205,0.7)\";\n * }\n */\nfunction setHue(hue, color) {\n if (color === 'transparent') return color;\n return toColorString(_extends({}, parseToHsl(color), {\n hue: parseFloat(hue)\n }));\n}\n\n// prettier-ignore\nvar curriedSetHue = curry /* ::<number | string, string, string> */(setHue);\nvar curriedSetHue$1 = curriedSetHue;\n\n/**\n * Sets the lightness of a color to the provided value. The lightness range can be\n * from 0 and 1.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: setLightness(0.2, '#CCCD64'),\n * background: setLightness('0.75', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${setLightness(0.2, '#CCCD64')};\n * background: ${setLightness('0.75', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#4d4d19\";\n * background: \"rgba(223,224,159,0.7)\";\n * }\n */\nfunction setLightness(lightness, color) {\n if (color === 'transparent') return color;\n return toColorString(_extends({}, parseToHsl(color), {\n lightness: parseFloat(lightness)\n }));\n}\n\n// prettier-ignore\nvar curriedSetLightness = curry /* ::<number | string, string, string> */(setLightness);\nvar curriedSetLightness$1 = curriedSetLightness;\n\n/**\n * Sets the saturation of a color to the provided value. The saturation range can be\n * from 0 and 1.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: setSaturation(0.2, '#CCCD64'),\n * background: setSaturation('0.75', 'rgba(204,205,100,0.7)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${setSaturation(0.2, '#CCCD64')};\n * background: ${setSaturation('0.75', 'rgba(204,205,100,0.7)')};\n * `\n *\n * // CSS in JS Output\n * element {\n * background: \"#adad84\";\n * background: \"rgba(228,229,76,0.7)\";\n * }\n */\nfunction setSaturation(saturation, color) {\n if (color === 'transparent') return color;\n return toColorString(_extends({}, parseToHsl(color), {\n saturation: parseFloat(saturation)\n }));\n}\n\n// prettier-ignore\nvar curriedSetSaturation = curry /* ::<number | string, string, string> */(setSaturation);\nvar curriedSetSaturation$1 = curriedSetSaturation;\n\n/**\n * Shades a color by mixing it with black. `shade` can produce\n * hue shifts, where as `darken` manipulates the luminance channel and therefore\n * doesn't produce hue shifts.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: shade(0.25, '#00f')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${shade(0.25, '#00f')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#00003f\";\n * }\n */\n\nfunction shade(percentage, color) {\n if (color === 'transparent') return color;\n return mix$1(parseFloat(percentage), 'rgb(0, 0, 0)', color);\n}\n\n// prettier-ignore\nvar curriedShade = curry /* ::<number | string, string, string> */(shade);\nvar curriedShade$1 = curriedShade;\n\n/**\n * Tints a color by mixing it with white. `tint` can produce\n * hue shifts, where as `lighten` manipulates the luminance channel and therefore\n * doesn't produce hue shifts.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: tint(0.25, '#00f')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${tint(0.25, '#00f')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"#bfbfff\";\n * }\n */\n\nfunction tint(percentage, color) {\n if (color === 'transparent') return color;\n return mix$1(parseFloat(percentage), 'rgb(255, 255, 255)', color);\n}\n\n// prettier-ignore\nvar curriedTint = curry /* ::<number | string, string, string> */(tint);\nvar curriedTint$1 = curriedTint;\n\n/**\n * Decreases the opacity of a color. Its range for the amount is between 0 to 1.\n *\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * background: transparentize(0.1, '#fff'),\n * background: transparentize(0.2, 'hsl(0, 0%, 100%)'),\n * background: transparentize('0.5', 'rgba(255, 0, 0, 0.8)'),\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * background: ${transparentize(0.1, '#fff')};\n * background: ${transparentize(0.2, 'hsl(0, 0%, 100%)')};\n * background: ${transparentize('0.5', 'rgba(255, 0, 0, 0.8)')};\n * `\n *\n * // CSS in JS Output\n *\n * element {\n * background: \"rgba(255,255,255,0.9)\";\n * background: \"rgba(255,255,255,0.8)\";\n * background: \"rgba(255,0,0,0.3)\";\n * }\n */\nfunction transparentize(amount, color) {\n if (color === 'transparent') return color;\n var parsedColor = parseToRgb(color);\n var alpha = typeof parsedColor.alpha === 'number' ? parsedColor.alpha : 1;\n var colorWithAlpha = _extends({}, parsedColor, {\n alpha: guard(0, 1, +(alpha * 100 - parseFloat(amount) * 100).toFixed(2) / 100)\n });\n return rgba(colorWithAlpha);\n}\n\n// prettier-ignore\nvar curriedTransparentize = curry /* ::<number | string, string, string> */(transparentize);\nvar curriedTransparentize$1 = curriedTransparentize;\n\n/**\n * Shorthand for easily setting the animation property. Allows either multiple arrays with animations\n * or a single animation spread over the arguments.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...animation(['rotate', '1s', 'ease-in-out'], ['colorchange', '2s'])\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${animation(['rotate', '1s', 'ease-in-out'], ['colorchange', '2s'])}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'animation': 'rotate 1s ease-in-out, colorchange 2s'\n * }\n * @example\n * // Styles as object usage\n * const styles = {\n * ...animation('rotate', '1s', 'ease-in-out')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${animation('rotate', '1s', 'ease-in-out')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'animation': 'rotate 1s ease-in-out'\n * }\n */\nfunction animation() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n // Allow single or multiple animations passed\n var multiMode = Array.isArray(args[0]);\n if (!multiMode && args.length > 8) {\n throw new PolishedError(64);\n }\n var code = args.map(function (arg) {\n if (multiMode && !Array.isArray(arg) || !multiMode && Array.isArray(arg)) {\n throw new PolishedError(65);\n }\n if (Array.isArray(arg) && arg.length > 8) {\n throw new PolishedError(66);\n }\n return Array.isArray(arg) ? arg.join(' ') : arg;\n }).join(', ');\n return {\n animation: code\n };\n}\n\n/**\n * Shorthand that accepts any number of backgroundImage values as parameters for creating a single background statement.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...backgroundImages('url(\"/image/background.jpg\")', 'linear-gradient(red, green)')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${backgroundImages('url(\"/image/background.jpg\")', 'linear-gradient(red, green)')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'backgroundImage': 'url(\"/image/background.jpg\"), linear-gradient(red, green)'\n * }\n */\nfunction backgroundImages() {\n for (var _len = arguments.length, properties = new Array(_len), _key = 0; _key < _len; _key++) {\n properties[_key] = arguments[_key];\n }\n return {\n backgroundImage: properties.join(', ')\n };\n}\n\n/**\n * Shorthand that accepts any number of background values as parameters for creating a single background statement.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...backgrounds('url(\"/image/background.jpg\")', 'linear-gradient(red, green)', 'center no-repeat')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${backgrounds('url(\"/image/background.jpg\")', 'linear-gradient(red, green)', 'center no-repeat')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'background': 'url(\"/image/background.jpg\"), linear-gradient(red, green), center no-repeat'\n * }\n */\nfunction backgrounds() {\n for (var _len = arguments.length, properties = new Array(_len), _key = 0; _key < _len; _key++) {\n properties[_key] = arguments[_key];\n }\n return {\n background: properties.join(', ')\n };\n}\n\nvar sideMap = ['top', 'right', 'bottom', 'left'];\n\n/**\n * Shorthand for the border property that splits out individual properties for use with tools like Fela and Styletron. A side keyword can optionally be passed to target only one side's border properties.\n *\n * @example\n * // Styles as object usage\n * const styles = {\n * ...border('1px', 'solid', 'red')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${border('1px', 'solid', 'red')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderColor': 'red',\n * 'borderStyle': 'solid',\n * 'borderWidth': `1px`,\n * }\n *\n * // Styles as object usage\n * const styles = {\n * ...border('top', '1px', 'solid', 'red')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${border('top', '1px', 'solid', 'red')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderTopColor': 'red',\n * 'borderTopStyle': 'solid',\n * 'borderTopWidth': `1px`,\n * }\n */\n\nfunction border(sideKeyword) {\n for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n values[_key - 1] = arguments[_key];\n }\n if (typeof sideKeyword === 'string' && sideMap.indexOf(sideKeyword) >= 0) {\n var _ref;\n return _ref = {}, _ref[\"border\" + capitalizeString(sideKeyword) + \"Width\"] = values[0], _ref[\"border\" + capitalizeString(sideKeyword) + \"Style\"] = values[1], _ref[\"border\" + capitalizeString(sideKeyword) + \"Color\"] = values[2], _ref;\n } else {\n values.unshift(sideKeyword);\n return {\n borderWidth: values[0],\n borderStyle: values[1],\n borderColor: values[2]\n };\n }\n}\n\n/**\n * Shorthand that accepts up to four values, including null to skip a value, and maps them to their respective directions.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...borderColor('red', 'green', 'blue', 'yellow')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${borderColor('red', 'green', 'blue', 'yellow')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderTopColor': 'red',\n * 'borderRightColor': 'green',\n * 'borderBottomColor': 'blue',\n * 'borderLeftColor': 'yellow'\n * }\n */\nfunction borderColor() {\n for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {\n values[_key] = arguments[_key];\n }\n return directionalProperty.apply(void 0, ['borderColor'].concat(values));\n}\n\n/**\n * Shorthand that accepts a value for side and a value for radius and applies the radius value to both corners of the side.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...borderRadius('top', '5px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${borderRadius('top', '5px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderTopRightRadius': '5px',\n * 'borderTopLeftRadius': '5px',\n * }\n */\nfunction borderRadius(side, radius) {\n var uppercaseSide = capitalizeString(side);\n if (!radius && radius !== 0) {\n throw new PolishedError(62);\n }\n if (uppercaseSide === 'Top' || uppercaseSide === 'Bottom') {\n var _ref;\n return _ref = {}, _ref[\"border\" + uppercaseSide + \"RightRadius\"] = radius, _ref[\"border\" + uppercaseSide + \"LeftRadius\"] = radius, _ref;\n }\n if (uppercaseSide === 'Left' || uppercaseSide === 'Right') {\n var _ref2;\n return _ref2 = {}, _ref2[\"borderTop\" + uppercaseSide + \"Radius\"] = radius, _ref2[\"borderBottom\" + uppercaseSide + \"Radius\"] = radius, _ref2;\n }\n throw new PolishedError(63);\n}\n\n/**\n * Shorthand that accepts up to four values, including null to skip a value, and maps them to their respective directions.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...borderStyle('solid', 'dashed', 'dotted', 'double')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${borderStyle('solid', 'dashed', 'dotted', 'double')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderTopStyle': 'solid',\n * 'borderRightStyle': 'dashed',\n * 'borderBottomStyle': 'dotted',\n * 'borderLeftStyle': 'double'\n * }\n */\nfunction borderStyle() {\n for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {\n values[_key] = arguments[_key];\n }\n return directionalProperty.apply(void 0, ['borderStyle'].concat(values));\n}\n\n/**\n * Shorthand that accepts up to four values, including null to skip a value, and maps them to their respective directions.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...borderWidth('12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${borderWidth('12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'borderTopWidth': '12px',\n * 'borderRightWidth': '24px',\n * 'borderBottomWidth': '36px',\n * 'borderLeftWidth': '48px'\n * }\n */\nfunction borderWidth() {\n for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {\n values[_key] = arguments[_key];\n }\n return directionalProperty.apply(void 0, ['borderWidth'].concat(values));\n}\n\nfunction generateSelectors(template, state) {\n var stateSuffix = state ? \":\" + state : '';\n return template(stateSuffix);\n}\n\n/**\n * Function helper that adds an array of states to a template of selectors. Used in textInputs and buttons.\n * @private\n */\nfunction statefulSelectors(states, template, stateMap) {\n if (!template) throw new PolishedError(67);\n if (states.length === 0) return generateSelectors(template, null);\n var selectors = [];\n for (var i = 0; i < states.length; i += 1) {\n if (stateMap && stateMap.indexOf(states[i]) < 0) {\n throw new PolishedError(68);\n }\n selectors.push(generateSelectors(template, states[i]));\n }\n selectors = selectors.join(',');\n return selectors;\n}\n\nvar stateMap$1 = [undefined, null, 'active', 'focus', 'hover'];\nfunction template$1(state) {\n return \"button\" + state + \",\\n input[type=\\\"button\\\"]\" + state + \",\\n input[type=\\\"reset\\\"]\" + state + \",\\n input[type=\\\"submit\\\"]\" + state;\n}\n\n/**\n * Populates selectors that target all buttons. You can pass optional states to append to the selectors.\n * @example\n * // Styles as object usage\n * const styles = {\n * [buttons('active')]: {\n * 'border': 'none'\n * }\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * > ${buttons('active')} {\n * border: none;\n * }\n * `\n *\n * // CSS in JS Output\n *\n * 'button:active,\n * 'input[type=\"button\"]:active,\n * 'input[type=\\\"reset\\\"]:active,\n * 'input[type=\\\"submit\\\"]:active: {\n * 'border': 'none'\n * }\n */\nfunction buttons() {\n for (var _len = arguments.length, states = new Array(_len), _key = 0; _key < _len; _key++) {\n states[_key] = arguments[_key];\n }\n return statefulSelectors(states, template$1, stateMap$1);\n}\n\n/**\n * Shorthand that accepts up to four values, including null to skip a value, and maps them to their respective directions.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...margin('12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${margin('12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'marginTop': '12px',\n * 'marginRight': '24px',\n * 'marginBottom': '36px',\n * 'marginLeft': '48px'\n * }\n */\nfunction margin() {\n for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {\n values[_key] = arguments[_key];\n }\n return directionalProperty.apply(void 0, ['margin'].concat(values));\n}\n\n/**\n * Shorthand that accepts up to four values, including null to skip a value, and maps them to their respective directions.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...padding('12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${padding('12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'paddingTop': '12px',\n * 'paddingRight': '24px',\n * 'paddingBottom': '36px',\n * 'paddingLeft': '48px'\n * }\n */\nfunction padding() {\n for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {\n values[_key] = arguments[_key];\n }\n return directionalProperty.apply(void 0, ['padding'].concat(values));\n}\n\nvar positionMap = ['absolute', 'fixed', 'relative', 'static', 'sticky'];\n\n/**\n * Shorthand accepts up to five values, including null to skip a value, and maps them to their respective directions. The first value can optionally be a position keyword.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...position('12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${position('12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'top': '12px',\n * 'right': '24px',\n * 'bottom': '36px',\n * 'left': '48px'\n * }\n *\n * // Styles as object usage\n * const styles = {\n * ...position('absolute', '12px', '24px', '36px', '48px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${position('absolute', '12px', '24px', '36px', '48px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'position': 'absolute',\n * 'top': '12px',\n * 'right': '24px',\n * 'bottom': '36px',\n * 'left': '48px'\n * }\n */\nfunction position(firstValue) {\n for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n values[_key - 1] = arguments[_key];\n }\n if (positionMap.indexOf(firstValue) >= 0 && firstValue) {\n return _extends({}, directionalProperty.apply(void 0, [''].concat(values)), {\n position: firstValue\n });\n } else {\n return directionalProperty.apply(void 0, ['', firstValue].concat(values));\n }\n}\n\n/**\n * Shorthand to set the height and width properties in a single statement.\n * @example\n * // Styles as object usage\n * const styles = {\n * ...size('300px', '250px')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${size('300px', '250px')}\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'height': '300px',\n * 'width': '250px',\n * }\n */\nfunction size(height, width) {\n if (width === void 0) {\n width = height;\n }\n return {\n height: height,\n width: width\n };\n}\n\nvar stateMap = [undefined, null, 'active', 'focus', 'hover'];\nfunction template(state) {\n return \"input[type=\\\"color\\\"]\" + state + \",\\n input[type=\\\"date\\\"]\" + state + \",\\n input[type=\\\"datetime\\\"]\" + state + \",\\n input[type=\\\"datetime-local\\\"]\" + state + \",\\n input[type=\\\"email\\\"]\" + state + \",\\n input[type=\\\"month\\\"]\" + state + \",\\n input[type=\\\"number\\\"]\" + state + \",\\n input[type=\\\"password\\\"]\" + state + \",\\n input[type=\\\"search\\\"]\" + state + \",\\n input[type=\\\"tel\\\"]\" + state + \",\\n input[type=\\\"text\\\"]\" + state + \",\\n input[type=\\\"time\\\"]\" + state + \",\\n input[type=\\\"url\\\"]\" + state + \",\\n input[type=\\\"week\\\"]\" + state + \",\\n input:not([type])\" + state + \",\\n textarea\" + state;\n}\n\n/**\n * Populates selectors that target all text inputs. You can pass optional states to append to the selectors.\n * @example\n * // Styles as object usage\n * const styles = {\n * [textInputs('active')]: {\n * 'border': 'none'\n * }\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * > ${textInputs('active')} {\n * border: none;\n * }\n * `\n *\n * // CSS in JS Output\n *\n * 'input[type=\"color\"]:active,\n * input[type=\"date\"]:active,\n * input[type=\"datetime\"]:active,\n * input[type=\"datetime-local\"]:active,\n * input[type=\"email\"]:active,\n * input[type=\"month\"]:active,\n * input[type=\"number\"]:active,\n * input[type=\"password\"]:active,\n * input[type=\"search\"]:active,\n * input[type=\"tel\"]:active,\n * input[type=\"text\"]:active,\n * input[type=\"time\"]:active,\n * input[type=\"url\"]:active,\n * input[type=\"week\"]:active,\n * input:not([type]):active,\n * textarea:active': {\n * 'border': 'none'\n * }\n */\nfunction textInputs() {\n for (var _len = arguments.length, states = new Array(_len), _key = 0; _key < _len; _key++) {\n states[_key] = arguments[_key];\n }\n return statefulSelectors(states, template, stateMap);\n}\n\n/**\n * Accepts any number of transition values as parameters for creating a single transition statement. You may also pass an array of properties as the first parameter that you would like to apply the same transition values to (second parameter).\n * @example\n * // Styles as object usage\n * const styles = {\n * ...transitions('opacity 1.0s ease-in 0s', 'width 2.0s ease-in 2s'),\n * ...transitions(['color', 'background-color'], '2.0s ease-in 2s')\n * }\n *\n * // styled-components usage\n * const div = styled.div`\n * ${transitions('opacity 1.0s ease-in 0s', 'width 2.0s ease-in 2s')};\n * ${transitions(['color', 'background-color'], '2.0s ease-in 2s'),};\n * `\n *\n * // CSS as JS Output\n *\n * div {\n * 'transition': 'opacity 1.0s ease-in 0s, width 2.0s ease-in 2s'\n * 'transition': 'color 2.0s ease-in 2s, background-color 2.0s ease-in 2s',\n * }\n */\nfunction transitions() {\n for (var _len = arguments.length, properties = new Array(_len), _key = 0; _key < _len; _key++) {\n properties[_key] = arguments[_key];\n }\n if (Array.isArray(properties[0]) && properties.length === 2) {\n var value = properties[1];\n if (typeof value !== 'string') {\n throw new PolishedError(61);\n }\n var transitionsString = properties[0].map(function (property) {\n return property + \" \" + value;\n }).join(', ');\n return {\n transition: transitionsString\n };\n } else {\n return {\n transition: properties.join(', ')\n };\n }\n}\n\nexport { curriedAdjustHue$1 as adjustHue, animation, backgroundImages, backgrounds, between, border, borderColor, borderRadius, borderStyle, borderWidth, buttons, clearFix, complement, cover, cssVar, curriedDarken$1 as darken, curriedDesaturate$1 as desaturate, directionalProperty, easeIn, easeInOut, easeOut, ellipsis, em$1 as em, fluidRange, fontFace, getContrast, getLuminance, getValueAndUnit, grayscale, hiDPI, hideText, hideVisually, hsl, hslToColorString, hsla, important, invert, curriedLighten$1 as lighten, linearGradient, margin, math, meetsContrastGuidelines, mix$1 as mix, modularScale, normalize, curriedOpacify$1 as opacify, padding, parseToHsl, parseToRgb, position, radialGradient, readableColor, rem$1 as rem, remToPx, retinaImage, rgb, rgbToColorString, rgba, curriedSaturate$1 as saturate, curriedSetHue$1 as setHue, curriedSetLightness$1 as setLightness, curriedSetSaturation$1 as setSaturation, curriedShade$1 as shade, size, stripUnit, textInputs, timingFunctions, curriedTint$1 as tint, toColorString, transitions, curriedTransparentize$1 as transparentize, triangle, wordWrap };\n","import { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport type { SimpleRouteJson } from \"../types\"\nimport { transparentize } from \"polished\"\n\nexport const COLORS = [\n \"blue\",\n \"orange\",\n \"purple\",\n \"cyan\",\n \"magenta\",\n \"yellowgreen\",\n \"darkgoldenrod\",\n \"deeppink\",\n]\n\nexport const getColorMap = (\n srj: SimpleRouteJson,\n connMap?: ConnectivityMap,\n) => {\n const colorMap: Record<string, string> = {}\n for (let i = 0; i < srj.connections.length; i++) {\n const connection = srj.connections[i]\n const netName = connMap?.getNetConnectedToId(connection.name)\n\n if (netName && !colorMap[netName]) {\n colorMap[netName] =\n `hsl(${(i * 300) / srj.connections.length}, 100%, 50%)`\n }\n\n colorMap[connection.name] =\n (netName ? colorMap[netName] : null) ??\n `hsl(${(i * 340) / srj.connections.length}, 100%, 50%)`\n }\n return colorMap\n}\n\nexport const safeTransparentize = (color: string, amount: number) => {\n try {\n return transparentize(amount, color)\n } catch (e) {\n console.error(e)\n return color\n }\n}\n\nexport const createColorMapFromStrings = (strings: string[]) => {\n const colorMap: Record<string, string> = {}\n for (let i = 0; i < strings.length; i++) {\n colorMap[strings[i]] = `hsl(${(i * 300) / strings.length}, 100%, 50%)`\n }\n return colorMap\n}\n","export const mapLayerNameToZ = (layerName: string, layerCount: number) => {\n if (layerName === \"top\") return 0\n if (layerName === \"bottom\") return layerCount - 1\n return parseInt(layerName.slice(5))\n}\n","import { CapacityMeshNode } from \"lib/types/capacity-mesh-types\"\n\n/**\n * Calculate the capacity of a node based on its width\n *\n * This capacity corresponds to how many vias the node can fit, tuned for two\n * layers.\n *\n * @param nodeOrWidth The node or width to calculate capacity for\n * @param maxCapacityFactor Optional multiplier to adjust capacity\n * @returns The calculated capacity\n */\nexport const getTunedTotalCapacity1 = (\n nodeOrWidth: CapacityMeshNode | { width: number },\n maxCapacityFactor = 1,\n) => {\n const VIA_DIAMETER = 0.6\n const TRACE_WIDTH = 0.15\n const obstacleMargin = 0.2\n\n const width = \"width\" in nodeOrWidth ? nodeOrWidth.width : nodeOrWidth\n const viaLengthAcross = width / (VIA_DIAMETER / 2 + obstacleMargin)\n\n return (viaLengthAcross / 2) ** 1.1 * maxCapacityFactor\n}\n\n/**\n * Calculate the optimal subdivision depth to reach a target minimum capacity\n * @param initialWidth The initial width of the top-level node\n * @param targetMinCapacity The minimum capacity target (default 0.5)\n * @param maxDepth Maximum allowed depth (default 10)\n * @returns The optimal capacity depth\n */\nexport const calculateOptimalCapacityDepth = (\n initialWidth: number,\n targetMinCapacity = 0.5,\n maxDepth = 16,\n): number => {\n let depth = 0\n let width = initialWidth\n\n // Calculate capacity at each subdivision level until we reach target or max depth\n while (depth < maxDepth) {\n const capacity = getTunedTotalCapacity1({ width })\n\n // If capacity is below target, we've gone far enough\n if (capacity <= targetMinCapacity) {\n break\n }\n\n // Move to next subdivision level (each level divides width by 2)\n width /= 2\n depth++\n }\n\n // Return depth + 1 to account for the fact that we want to subdivide\n // until the smallest nodes have capacity <= targetMinCapacity\n return Math.max(1, depth)\n}\n","import { Obstacle } from \"lib/types\"\n\nexport type BucketCoordinate = `${number}x${number}`\n\nexport class ObstacleSpatialHashIndex {\n buckets: Map<BucketCoordinate, [Obstacle, number][]>\n CELL_SIZE = 0.4\n\n constructor(public obstacles: Obstacle[]) {\n this.buckets = new Map()\n // for (const obstacle of obstacles) {\n for (let i = 0; i < obstacles.length; i++) {\n const obstacle = obstacles[i]\n const nodeMinX = obstacle.center.x - obstacle.width / 2\n const nodeMinY = obstacle.center.y - obstacle.height / 2\n const nodeMaxX = obstacle.center.x + obstacle.width / 2\n const nodeMaxY = obstacle.center.y + obstacle.height / 2\n for (let x = nodeMinX; x <= nodeMaxX; x += this.CELL_SIZE) {\n for (let y = nodeMinY; y <= nodeMaxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey)\n if (!bucket) {\n this.buckets.set(bucketKey, [[obstacle, i]])\n } else {\n bucket.push([obstacle, i])\n }\n }\n }\n }\n }\n\n getBucketKey(x: number, y: number): BucketCoordinate {\n return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`\n }\n\n getNodesInArea(\n centerX: number,\n centerY: number,\n width: number,\n height: number,\n ): Obstacle[] {\n const obstacles: Obstacle[] = []\n const alreadyAddedObstacles = new Set<number>()\n const minX = centerX - width / 2\n const minY = centerY - height / 2\n const maxX = centerX + width / 2\n const maxY = centerY + height / 2\n for (let x = minX; x <= maxX; x += this.CELL_SIZE) {\n for (let y = minY; y <= maxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey) || []\n for (const obstacleWithIndex of bucket) {\n if (alreadyAddedObstacles.has(obstacleWithIndex[1])) continue\n alreadyAddedObstacles.add(obstacleWithIndex[1])\n obstacles.push(obstacleWithIndex[0])\n }\n }\n }\n return obstacles\n }\n}\n\nexport const ObstacleTree = ObstacleSpatialHashIndex\n","interface Target {\n x: number\n y: number\n bounds: {\n minX: number\n minY: number\n maxX: number\n maxY: number\n }\n connectionName: string\n availableZ: number[]\n}\n\nexport type BucketCoordinate = `${number}x${number}`\n\nexport class TargetTree {\n buckets: Map<BucketCoordinate, [Target, number][]>\n CELL_SIZE = 5\n\n constructor(public targets: Target[]) {\n this.buckets = new Map()\n for (let i = 0; i < targets.length; i++) {\n const target = targets[i]\n const targetBucketMinX =\n Math.floor(target.bounds.minX / this.CELL_SIZE) * this.CELL_SIZE\n const targetBucketMinY =\n Math.floor(target.bounds.minY / this.CELL_SIZE) * this.CELL_SIZE\n const targetMaxX = target.bounds.maxX\n const targetMaxY = target.bounds.maxY\n for (let x = targetBucketMinX; x <= targetMaxX; x += this.CELL_SIZE) {\n for (let y = targetBucketMinY; y <= targetMaxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey)\n if (!bucket) {\n this.buckets.set(bucketKey, [[target, i]])\n } else {\n bucket.push([target, i])\n }\n }\n }\n }\n }\n\n getBucketKey(x: number, y: number): BucketCoordinate {\n return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`\n }\n\n getTargetsInArea(\n centerX: number,\n centerY: number,\n width: number,\n height: number,\n ): Target[] {\n const targets: Target[] = []\n const alreadyAddedTargets = new Set<number>()\n const minX =\n Math.floor((centerX - width / 2) / this.CELL_SIZE) * this.CELL_SIZE\n const minY =\n Math.floor((centerY - height / 2) / this.CELL_SIZE) * this.CELL_SIZE\n const maxX = centerX + width / 2\n const maxY = centerY + height / 2\n for (let x = minX; x <= maxX; x += this.CELL_SIZE) {\n for (let y = minY; y <= maxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey) || []\n for (const targetWithIndex of bucket) {\n if (alreadyAddedTargets.has(targetWithIndex[1])) continue\n alreadyAddedTargets.add(targetWithIndex[1])\n targets.push(targetWithIndex[0])\n }\n }\n }\n return targets\n }\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n CapacityMeshNodeId,\n Obstacle,\n SimpleRouteJson,\n} from \"../../types\"\nimport { COLORS } from \"../colors\"\nimport { isPointInRect } from \"lib/utils/isPointInRect\"\nimport { doRectsOverlap } from \"lib/utils/doRectsOverlap\"\nimport { mapLayerNameToZ } from \"lib/utils/mapLayerNameToZ\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\nimport { ObstacleSpatialHashIndex } from \"lib/data-structures/ObstacleTree\"\nimport { TargetTree } from \"lib/data-structures/TargetTree\"\n\ninterface CapacityMeshNodeSolverOptions {\n capacityDepth?: number\n}\n\ninterface Target {\n x: number\n y: number\n bounds: {\n minX: number\n minY: number\n maxX: number\n maxY: number\n }\n connectionName: string\n availableZ: number[]\n}\n\nexport class CapacityMeshNodeSolver extends BaseSolver {\n unfinishedNodes: CapacityMeshNode[]\n finishedNodes: CapacityMeshNode[]\n\n nodeToXYOverlappingObstaclesMap: Map<CapacityMeshNodeId, Obstacle[]>\n layerCount: number\n\n // targetObstacleMap: Record<string, { obstacle: Obstacle, node: CapacityMeshNode }>\n\n MAX_DEPTH = 4\n\n targets: Target[]\n targetTree: TargetTree\n obstacleTree: ObstacleSpatialHashIndex\n\n constructor(\n public srj: SimpleRouteJson,\n public opts: CapacityMeshNodeSolverOptions = {},\n ) {\n super()\n this.MAX_DEPTH = opts?.capacityDepth ?? this.MAX_DEPTH\n this.MAX_ITERATIONS = 100_000\n this.layerCount = srj.layerCount ?? 2\n\n for (const obstacle of srj.obstacles) {\n if (!obstacle.zLayers) {\n const zLayers: number[] = []\n for (const layer of obstacle.layers) {\n zLayers.push(mapLayerNameToZ(layer, srj.layerCount))\n }\n obstacle.zLayers = zLayers\n }\n }\n\n const boundsCenter = {\n x: (srj.bounds.minX + srj.bounds.maxX) / 2,\n y: (srj.bounds.minY + srj.bounds.maxY) / 2,\n }\n const boundsSize = {\n width: srj.bounds.maxX - srj.bounds.minX,\n height: srj.bounds.maxY - srj.bounds.minY,\n }\n const maxWidthHeight = Math.max(boundsSize.width, boundsSize.height)\n this.unfinishedNodes = [\n {\n capacityMeshNodeId: this.getNextNodeId(),\n center: boundsCenter,\n width: maxWidthHeight,\n height: maxWidthHeight,\n layer: \"top\",\n availableZ: [0, 1],\n _depth: 0,\n _containsTarget: true,\n _containsObstacle: true,\n _completelyInsideObstacle: false,\n },\n ]\n this.finishedNodes = []\n this.nodeToXYOverlappingObstaclesMap = new Map()\n this.obstacleTree = new ObstacleSpatialHashIndex(this.srj.obstacles)\n this.targets = this.computeTargets()\n this.targetTree = new TargetTree(this.targets)\n }\n\n computeTargets(): Target[] {\n const targets: Target[] = []\n for (const conn of this.srj.connections) {\n for (const ptc of conn.pointsToConnect) {\n const obstacles = this.obstacleTree\n .getNodesInArea(ptc.x, ptc.y, 0.01, 0.01)\n .filter((o) =>\n o.zLayers!.some((z) => (ptc.layer === \"top\" ? z === 0 : z === 1)),\n )\n\n let bounds: {\n minX: number\n minY: number\n maxX: number\n maxY: number\n } = {\n minX: ptc.x - 0.005,\n minY: ptc.y - 0.005,\n maxX: ptc.x + 0.005,\n maxY: ptc.y + 0.005,\n }\n if (obstacles.length > 0) {\n bounds = {\n minX: Math.min(...obstacles.map((o) => o.center.x - o.width / 2)),\n minY: Math.min(...obstacles.map((o) => o.center.y - o.height / 2)),\n maxX: Math.max(...obstacles.map((o) => o.center.x + o.width / 2)),\n maxY: Math.max(...obstacles.map((o) => o.center.y + o.height / 2)),\n }\n }\n const target = {\n ...ptc,\n connectionName: conn.name,\n availableZ: ptc.layer === \"top\" ? [0] : [1],\n bounds,\n }\n targets.push(target)\n }\n }\n return targets\n }\n\n _nextNodeCounter = 0\n getNextNodeId(): string {\n return `cn${this._nextNodeCounter++}`\n }\n\n getCapacityFromDepth(depth: number): number {\n return (this.MAX_DEPTH - depth + 1) ** 2\n }\n\n getTargetIfNodeContainsTarget(node: CapacityMeshNode): Target | null {\n const nearbyTargets =\n node.width > this.targetTree.CELL_SIZE * 4\n ? this.targets\n : this.targetTree.getTargetsInArea(\n node.center.x,\n node.center.y,\n node.width,\n node.height,\n )\n for (const target of nearbyTargets) {\n if (\n // Check if the node and target bounds overlap\n target.bounds.minX <= node.center.x + node.width / 2 &&\n target.bounds.maxX >= node.center.x - node.width / 2 &&\n target.bounds.minY <= node.center.y + node.height / 2 &&\n target.bounds.maxY >= node.center.y - node.height / 2 &&\n target.availableZ.some((z) => node.availableZ.includes(z))\n ) {\n return target\n }\n }\n return null\n }\n\n getXYOverlappingObstacles(node: CapacityMeshNode): Obstacle[] {\n const cachedObstacles = this.nodeToXYOverlappingObstaclesMap.get(\n node.capacityMeshNodeId,\n )\n if (cachedObstacles) {\n return cachedObstacles\n }\n const overlappingObstacles: Obstacle[] = []\n\n // Compute node bounds\n const nodeLeft = node.center.x - node.width / 2\n const nodeRight = node.center.x + node.width / 2\n const nodeTop = node.center.y - node.height / 2\n const nodeBottom = node.center.y + node.height / 2\n\n const obstacles = node._parent\n ? this.getXYOverlappingObstacles(node._parent)\n : this.srj.obstacles\n for (const obstacle of obstacles) {\n const obsLeft = obstacle.center.x - obstacle.width / 2\n const obsRight = obstacle.center.x + obstacle.width / 2\n const obsTop = obstacle.center.y - obstacle.height / 2\n const obsBottom = obstacle.center.y + obstacle.height / 2\n\n // Check for intersection.\n if (\n nodeRight >= obsLeft &&\n nodeLeft <= obsRight &&\n nodeBottom >= obsTop &&\n nodeTop <= obsBottom\n ) {\n overlappingObstacles.push(obstacle)\n continue\n }\n\n // Check if the node is completely within the obstacle\n if (\n nodeLeft >= obsLeft &&\n nodeRight <= obsRight &&\n nodeTop >= obsTop &&\n nodeBottom <= obsBottom\n ) {\n // Node is completely inside the obstacle\n overlappingObstacles.push(obstacle)\n continue\n }\n\n // Check if obstacle is completely within node\n if (\n obsLeft >= nodeLeft &&\n obsRight <= nodeRight &&\n obsTop >= nodeTop &&\n obsBottom <= nodeBottom\n ) {\n overlappingObstacles.push(obstacle)\n }\n }\n\n this.nodeToXYOverlappingObstaclesMap.set(\n node.capacityMeshNodeId,\n overlappingObstacles,\n )\n\n return overlappingObstacles\n }\n\n getXYZOverlappingObstacles(node: CapacityMeshNode): Obstacle[] {\n const xyOverlappingObstacles = this.getXYOverlappingObstacles(node)\n\n // For each obstacle, check if it has any overlap in the z-axis\n const xyzOverlappingObstacles: Obstacle[] = []\n for (const obstacle of xyOverlappingObstacles) {\n if (node.availableZ.some((z) => obstacle.zLayers!.includes(z))) {\n xyzOverlappingObstacles.push(obstacle)\n }\n }\n\n return xyzOverlappingObstacles\n }\n\n /**\n * Checks if the given mesh node overlaps with any obstacle.\n * We treat both obstacles and nodes as axis‐aligned rectangles.\n */\n doesNodeOverlapObstacle(node: CapacityMeshNode): boolean {\n const overlappingObstacles = this.getXYZOverlappingObstacles(node)\n\n if (overlappingObstacles.length > 0) {\n return true\n }\n\n // Compute node bounds\n const nodeLeft = node.center.x - node.width / 2\n const nodeRight = node.center.x + node.width / 2\n const nodeTop = node.center.y - node.height / 2\n const nodeBottom = node.center.y + node.height / 2\n\n // If node is outside the bounds, we consider it to contain an obstacle\n if (\n nodeLeft < this.srj.bounds.minX ||\n nodeRight > this.srj.bounds.maxX ||\n nodeTop < this.srj.bounds.minY ||\n nodeBottom > this.srj.bounds.maxY\n ) {\n return true\n }\n return false\n }\n\n /**\n * Checks if the entire node is contained within any obstacle.\n */\n isNodeCompletelyInsideObstacle(node: CapacityMeshNode): boolean {\n const overlappingObstacles = this.getXYZOverlappingObstacles(node)\n\n // Compute node bounds\n const nodeLeft = node.center.x - node.width / 2\n const nodeRight = node.center.x + node.width / 2\n const nodeTop = node.center.y - node.height / 2\n const nodeBottom = node.center.y + node.height / 2\n\n for (const obstacle of overlappingObstacles) {\n const obsLeft = obstacle.center.x - obstacle.width / 2\n const obsRight = obstacle.center.x + obstacle.width / 2\n const obsTop = obstacle.center.y - obstacle.height / 2\n const obsBottom = obstacle.center.y + obstacle.height / 2\n\n // Check if the node's bounds are completely inside the obstacle's bounds.\n if (\n nodeLeft >= obsLeft &&\n nodeRight <= obsRight &&\n nodeTop >= obsTop &&\n nodeBottom <= obsBottom\n ) {\n return true\n }\n }\n\n // if (\n // nodeRight < this.srj.bounds.minX ||\n // nodeLeft > this.srj.bounds.maxX ||\n // nodeBottom < this.srj.bounds.minY ||\n // nodeTop > this.srj.bounds.maxY\n // ) {\n // return true\n // }\n\n return false\n }\n\n getChildNodes(parent: CapacityMeshNode): CapacityMeshNode[] {\n if (parent._depth === this.MAX_DEPTH) return []\n const childNodes: CapacityMeshNode[] = []\n\n const childNodeSize = { width: parent.width / 2, height: parent.height / 2 }\n\n const childNodePositions = [\n {\n x: parent.center.x - childNodeSize.width / 2,\n y: parent.center.y - childNodeSize.height / 2,\n },\n {\n x: parent.center.x + childNodeSize.width / 2,\n y: parent.center.y - childNodeSize.height / 2,\n },\n {\n x: parent.center.x - childNodeSize.width / 2,\n y: parent.center.y + childNodeSize.height / 2,\n },\n {\n x: parent.center.x + childNodeSize.width / 2,\n y: parent.center.y + childNodeSize.height / 2,\n },\n ]\n\n for (const position of childNodePositions) {\n const childNode: CapacityMeshNode = {\n capacityMeshNodeId: this.getNextNodeId(),\n center: position,\n width: childNodeSize.width,\n height: childNodeSize.height,\n layer: parent.layer,\n availableZ: [0, 1],\n _depth: (parent._depth ?? 0) + 1,\n _parent: parent,\n }\n childNode._containsObstacle = this.doesNodeOverlapObstacle(childNode)\n\n const target = this.getTargetIfNodeContainsTarget(childNode)\n\n if (target) {\n childNode._targetConnectionName = target.connectionName\n childNode.availableZ = target.availableZ\n childNode._containsTarget = true\n }\n\n if (childNode._containsObstacle) {\n childNode._completelyInsideObstacle =\n this.isNodeCompletelyInsideObstacle(childNode)\n }\n if (childNode._completelyInsideObstacle && !childNode._containsTarget)\n continue\n childNodes.push(childNode)\n }\n\n return childNodes\n }\n\n shouldNodeBeXYSubdivided(node: CapacityMeshNode) {\n if (node._depth! >= this.MAX_DEPTH) return false\n if (node._containsTarget) return true\n if (node._containsObstacle && !node._completelyInsideObstacle) return true\n return false\n }\n\n _step() {\n const nextNode = this.unfinishedNodes.pop()\n if (!nextNode) {\n this.solved = true\n return\n }\n\n const newNodes = this.getChildNodes(nextNode)\n\n const finishedNewNodes: CapacityMeshNode[] = []\n const unfinishedNewNodes: CapacityMeshNode[] = []\n\n for (const newNode of newNodes) {\n const shouldBeSubdivided = this.shouldNodeBeXYSubdivided(newNode)\n if (shouldBeSubdivided) {\n unfinishedNewNodes.push(newNode)\n } else if (!shouldBeSubdivided && !newNode._containsObstacle) {\n finishedNewNodes.push(newNode)\n } else if (!shouldBeSubdivided && newNode._containsTarget) {\n finishedNewNodes.push(newNode)\n }\n }\n\n this.unfinishedNodes.push(...unfinishedNewNodes)\n this.finishedNodes.push(...finishedNewNodes)\n }\n\n /**\n * Creates a GraphicsObject to visualize the mesh, its nodes, obstacles, and connection points.\n *\n * - Mesh nodes are rendered as rectangles.\n * - Nodes that have an obstacle intersection are outlined in red.\n * - Other nodes are outlined in green.\n * - Lines are drawn from a node to its parent.\n * - Obstacles are drawn as semi-transparent red rectangles.\n * - Points for each connection’s pointsToConnect are drawn in a unique color.\n */\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Capacity Mesh Visualization\",\n }\n\n // Draw obstacles\n for (const obstacle of this.srj.obstacles) {\n graphics.rects!.push({\n center: obstacle.center,\n width: obstacle.width,\n height: obstacle.height,\n fill:\n obstacle.zLayers?.length === 1 && obstacle.zLayers?.includes(1)\n ? \"rgba(0,0,255,0.3)\"\n : \"rgba(255,0,0,0.3)\",\n stroke: \"red\",\n label: [\"obstacle\", `z: ${obstacle.zLayers!.join(\",\")}`].join(\"\\n\"),\n })\n }\n\n // Draw mesh nodes (both finished and unfinished)\n const allNodes = [...this.finishedNodes, ...this.unfinishedNodes]\n for (const node of allNodes) {\n const lowestZ = Math.min(...node.availableZ)\n const isNextToBeProcessed =\n this.unfinishedNodes.length > 0 &&\n node === this.unfinishedNodes[this.unfinishedNodes.length - 1]\n\n graphics.rects!.push({\n center: {\n x: node.center.x + lowestZ * node.width * 0.05,\n y: node.center.y - lowestZ * node.width * 0.05,\n },\n width: Math.max(node.width - 2, node.width * 0.8),\n height: Math.max(node.height - 2, node.height * 0.8),\n fill: node._containsObstacle\n ? \"rgba(255,0,0,0.1)\"\n : ({\n \"0,1\": \"rgba(0,0,0,0.1)\",\n \"0\": \"rgba(0,200,200, 0.1)\",\n \"1\": \"rgba(0,0,200, 0.1)\",\n }[node.availableZ.join(\",\")] ?? \"rgba(0,200,200,0.1)\"),\n stroke: isNextToBeProcessed ? \"rgba(255,165,0,0.5)\" : undefined,\n label: [\n node.capacityMeshNodeId,\n `availableZ: ${node.availableZ.join(\",\")}`,\n `target? ${node._containsTarget ?? false}`,\n `obs? ${node._containsObstacle ?? false}`,\n `${node.width.toFixed(2)}x${node.height.toFixed(2)}`,\n `capacity: ${getTunedTotalCapacity1(node).toFixed(2)}`,\n ].join(\"\\n\"),\n })\n }\n graphics.rects!.sort((a, b) => a.center.y - b.center.y)\n\n // Draw connection points (each connection gets a unique color).\n this.srj.connections.forEach((connection, index) => {\n const color = COLORS[index % COLORS.length]\n for (const pt of connection.pointsToConnect) {\n graphics.points!.push({\n x: pt.x,\n y: pt.y,\n label: `conn-${index} (${pt.layer})`,\n color,\n })\n }\n })\n\n return graphics\n }\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n CapacityMeshNodeId,\n Obstacle,\n SimpleRouteJson,\n} from \"../../types\"\nimport { COLORS } from \"../colors\"\nimport { isPointInRect } from \"lib/utils/isPointInRect\"\nimport { doRectsOverlap } from \"lib/utils/doRectsOverlap\"\nimport { CapacityMeshNodeSolver } from \"./CapacityMeshNodeSolver1\"\nimport { mapLayerNameToZ } from \"lib/utils/mapLayerNameToZ\"\n\ninterface CapacityMeshNodeSolverOptions {\n capacityDepth?: number\n}\n\ninterface Target {\n x: number\n y: number\n connectionName: string\n availableZ: number[]\n}\n\nexport class CapacityMeshNodeSolver2_NodeUnderObstacle extends CapacityMeshNodeSolver {\n VIA_DIAMETER = 0.6\n OBSTACLE_MARGIN = 0.1\n\n constructor(\n public srj: SimpleRouteJson,\n public opts: CapacityMeshNodeSolverOptions = {},\n ) {\n super(srj, opts)\n }\n\n isNodeCompletelyOutsideBounds(node: CapacityMeshNode): boolean {\n return (\n node.center.x + node.width / 2 < this.srj.bounds.minX ||\n node.center.x - node.width / 2 > this.srj.bounds.maxX ||\n node.center.y + node.height / 2 < this.srj.bounds.minY ||\n node.center.y - node.height / 2 > this.srj.bounds.maxY\n )\n }\n\n isNodePartiallyOutsideBounds(node: CapacityMeshNode): boolean {\n return (\n node.center.x - node.width / 2 < this.srj.bounds.minX ||\n node.center.x + node.width / 2 > this.srj.bounds.maxX ||\n node.center.y - node.height / 2 < this.srj.bounds.minY ||\n node.center.y + node.height / 2 > this.srj.bounds.maxY\n )\n }\n createChildNodeAtPosition(\n parent: CapacityMeshNode,\n opts: {\n center: { x: number; y: number }\n width: number\n height: number\n availableZ: number[]\n _depth?: number\n },\n ): CapacityMeshNode {\n const childNode: CapacityMeshNode = {\n capacityMeshNodeId: this.getNextNodeId(),\n center: opts.center,\n width: opts.width,\n height: opts.height,\n layer: parent.layer,\n availableZ: opts.availableZ,\n _depth: opts._depth ?? (parent._depth ?? 0) + 1,\n _parent: parent,\n }\n\n const overlappingObstacles = this.getXYZOverlappingObstacles(childNode)\n\n childNode._containsObstacle =\n overlappingObstacles.length > 0 ||\n this.isNodePartiallyOutsideBounds(childNode)\n\n const target = this.getTargetIfNodeContainsTarget(childNode)\n\n if (target) {\n childNode._targetConnectionName = target.connectionName\n childNode._containsTarget = true\n }\n\n if (childNode._containsObstacle) {\n childNode._completelyInsideObstacle =\n this.isNodeCompletelyInsideObstacle(childNode)\n }\n // childNode._shouldBeInGraph =\n // (!isOutsideBounds && !childNode._completelyInsideObstacle) || childNode._\n\n return childNode\n }\n\n getZSubdivisionChildNodes(node: CapacityMeshNode): CapacityMeshNode[] {\n if (node.availableZ.length === 1) return []\n\n const childNodes: CapacityMeshNode[] = []\n\n // TODO when we have more than 2 layers, we need to handle other\n // variations, you always want to prioritize having larger contiguous\n // z-blocks\n const otherZBlocks = [[0], [1]]\n\n for (const zBlock of otherZBlocks) {\n const childNode = this.createChildNodeAtPosition(node, {\n center: { ...node.center },\n width: node.width,\n height: node.height,\n availableZ: zBlock,\n // z-subdivision doesn't count towards depth, should be same as parent\n _depth: node._depth!,\n })\n\n if (this.isNodeCompletelyOutsideBounds(childNode)) {\n continue\n }\n\n childNodes.push(childNode)\n }\n\n return childNodes\n }\n\n getChildNodes(parent: CapacityMeshNode): CapacityMeshNode[] {\n if (parent._depth! >= this.MAX_DEPTH) return []\n const childNodes: CapacityMeshNode[] = []\n\n const childNodeSize = { width: parent.width / 2, height: parent.height / 2 }\n\n const childNodePositions = [\n {\n x: parent.center.x - childNodeSize.width / 2,\n y: parent.center.y - childNodeSize.height / 2,\n },\n {\n x: parent.center.x + childNodeSize.width / 2,\n y: parent.center.y - childNodeSize.height / 2,\n },\n {\n x: parent.center.x - childNodeSize.width / 2,\n y: parent.center.y + childNodeSize.height / 2,\n },\n {\n x: parent.center.x + childNodeSize.width / 2,\n y: parent.center.y + childNodeSize.height / 2,\n },\n ]\n\n for (const position of childNodePositions) {\n const childNode = this.createChildNodeAtPosition(parent, {\n center: position,\n width: childNodeSize.width,\n height: childNodeSize.height,\n availableZ: parent.availableZ,\n })\n if (this.isNodeCompletelyOutsideBounds(childNode)) {\n continue\n }\n childNodes.push(childNode)\n }\n\n return childNodes\n }\n\n shouldNodeBeXYSubdivided(node: CapacityMeshNode) {\n if (node._depth! >= this.MAX_DEPTH) return false\n if (node._containsTarget) return true\n if (node.availableZ.length === 1 && node._depth! <= this.MAX_DEPTH)\n return true\n if (node._containsObstacle && !node._completelyInsideObstacle) return true\n return false\n }\n\n _step() {\n const nextNode = this.unfinishedNodes.pop()\n if (!nextNode) {\n this.solved = true\n return\n }\n\n const childNodes = this.getChildNodes(nextNode)\n\n const finishedNewNodes: CapacityMeshNode[] = []\n const unfinishedNewNodes: CapacityMeshNode[] = []\n\n for (const childNode of childNodes) {\n const shouldBeXYSubdivided = this.shouldNodeBeXYSubdivided(childNode)\n const shouldBeZSubdivided =\n childNode.availableZ.length > 1 &&\n !shouldBeXYSubdivided &&\n (childNode._containsObstacle ||\n childNode.width < this.VIA_DIAMETER + this.OBSTACLE_MARGIN)\n if (shouldBeXYSubdivided) {\n unfinishedNewNodes.push(childNode)\n } else if (\n !shouldBeXYSubdivided &&\n !childNode._containsObstacle &&\n !shouldBeZSubdivided\n ) {\n finishedNewNodes.push(childNode)\n } else if (!shouldBeXYSubdivided && childNode._containsTarget) {\n if (shouldBeZSubdivided) {\n const zSubNodes = this.getZSubdivisionChildNodes(childNode)\n finishedNewNodes.push(\n ...zSubNodes.filter(\n (n) => n._containsTarget || !n._containsObstacle,\n ),\n )\n } else {\n finishedNewNodes.push(childNode)\n }\n } else if (shouldBeZSubdivided) {\n finishedNewNodes.push(\n ...this.getZSubdivisionChildNodes(childNode).filter(\n (zSubNode) => !zSubNode._containsObstacle,\n ),\n )\n }\n }\n\n this.unfinishedNodes.push(...unfinishedNewNodes)\n this.finishedNodes.push(...finishedNewNodes)\n }\n}\n","import type { CapacityMeshEdge, CapacityMeshNodeId } from \"../../types\"\n\nexport function getNodeEdgeMap(\n edges: CapacityMeshEdge[],\n): Map<CapacityMeshNodeId, CapacityMeshEdge[]> {\n const nodeEdgeMap = new Map<CapacityMeshNodeId, CapacityMeshEdge[]>()\n\n for (const edge of edges) {\n for (const nodeId of edge.nodeIds) {\n nodeEdgeMap.set(nodeId, [...(nodeEdgeMap.get(nodeId) ?? []), edge])\n }\n }\n\n return nodeEdgeMap\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n CapacityMeshNodeId,\n CapacityPath,\n} from \"../../types\"\nimport type { NodePortSegment } from \"../../types/capacity-edges-to-port-segments-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { getNodeEdgeMap } from \"./getNodeEdgeMap\"\nimport { safeTransparentize } from \"../colors\"\n\n/**\n * Each Node is a square. The capacity paths indicate the nodes the trace will\n * travel through. We want to find the \"Port Segment\" that each capacity path\n * will take for each node.\n */\nexport class CapacityEdgeToPortSegmentSolver extends BaseSolver {\n nodes: CapacityMeshNode[]\n edges: CapacityMeshEdge[]\n capacityPaths: CapacityPath[]\n\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n nodeEdgeMap: Map<CapacityMeshNodeId, CapacityMeshEdge[]>\n\n unprocessedNodeIds: CapacityMeshNodeId[]\n\n nodePortSegments: Map<CapacityMeshNodeId, NodePortSegment[]>\n colorMap: Record<string, string>\n\n constructor({\n nodes,\n edges,\n capacityPaths,\n colorMap,\n }: {\n nodes: CapacityMeshNode[]\n edges: CapacityMeshEdge[]\n capacityPaths: CapacityPath[]\n colorMap?: Record<string, string>\n }) {\n super()\n this.nodes = nodes\n this.edges = edges\n this.nodeMap = new Map(nodes.map((node) => [node.capacityMeshNodeId, node]))\n this.nodeEdgeMap = getNodeEdgeMap(edges)\n this.capacityPaths = capacityPaths\n this.colorMap = colorMap ?? {}\n\n // We will be evaluating capacity paths\n this.unprocessedNodeIds = [\n ...new Set(capacityPaths.flatMap((path) => path.nodeIds)),\n ]\n this.nodePortSegments = new Map()\n }\n\n step() {\n const nodeId = this.unprocessedNodeIds.pop()\n if (!nodeId) {\n this.solved = true\n return\n }\n\n const pathsGoingThroughNode: Array<{\n path: CapacityPath\n indexOfNodeInPath: number\n }> = []\n for (const path of this.capacityPaths) {\n const indexOfNodeInPath = path.nodeIds.indexOf(nodeId)\n if (indexOfNodeInPath !== -1) {\n pathsGoingThroughNode.push({ path, indexOfNodeInPath })\n }\n }\n\n const node = this.nodeMap.get(nodeId)!\n const nodePortSegments: NodePortSegment[] = []\n\n for (const { path, indexOfNodeInPath } of pathsGoingThroughNode) {\n const entryNodeId = path.nodeIds[indexOfNodeInPath - 1]\n const exitNodeId = path.nodeIds[indexOfNodeInPath + 1]\n\n for (const adjNodeId of [entryNodeId, exitNodeId]) {\n const adjNode = this.nodeMap.get(adjNodeId)!\n if (!adjNode) continue\n const segment = findOverlappingSegment(node, adjNode)\n\n const mutuallyAvailableZ = adjNode.availableZ.filter((z) =>\n node.availableZ.includes(z),\n )\n\n if (mutuallyAvailableZ.length === 0) continue\n\n const portSegment: NodePortSegment = {\n capacityMeshNodeId: nodeId,\n start: segment.start,\n end: segment.end,\n connectionNames: [path.connectionName],\n availableZ: mutuallyAvailableZ,\n }\n\n nodePortSegments.push(portSegment)\n }\n }\n\n // Combine overlapping or adjacent segments on the same edge.\n const combinedSegments = combineSegments(nodePortSegments)\n this.nodePortSegments.set(nodeId, combinedSegments)\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n this.nodePortSegments.forEach((segments, nodeId) => {\n const node = this.nodeMap.get(nodeId)!\n segments.forEach((segment) => {\n const isVertical = segment.start.x === segment.end.x\n const THICKNESS = 0.05\n for (let i = 0; i < segment.connectionNames.length; i++) {\n const offset = {\n x: 0.05 * Math.max(...segment.availableZ),\n y: 0.05 * Math.max(...segment.availableZ),\n }\n const trueSegmentCenter = {\n x: (segment.start.x + segment.end.x) / 2,\n y: (segment.start.y + segment.end.y) / 2,\n }\n const segmentCenter = {\n x: trueSegmentCenter.x + offset.x,\n y: trueSegmentCenter.y + offset.y,\n }\n if (offset.x > 0) {\n // small dashed line to show the true center\n graphics.lines!.push({\n points: [trueSegmentCenter, segmentCenter],\n strokeColor: \"rgba(0, 0, 0, 0.25)\",\n strokeDash: \"5 5\",\n })\n }\n graphics.points!.push({\n x: segmentCenter.x,\n y: segmentCenter.y,\n label: `${nodeId}: ${segment.connectionNames.join(\", \")}\\navailableZ: ${segment.availableZ.join(\",\")}\\nnodePortSegmentId: ${segment.nodePortSegmentId!}`,\n })\n graphics.lines!.push({\n points: [segment.start, segment.end],\n strokeColor: safeTransparentize(\n this.colorMap[segment.connectionNames[i]],\n 0.6,\n ),\n })\n }\n })\n })\n return graphics\n }\n}\n\nfunction findOverlappingSegment(\n node: CapacityMeshNode,\n adjNode: CapacityMeshNode,\n): { start: { x: number; y: number }; end: { x: number; y: number } } {\n // Find overlapping ranges in x and y dimensions\n const xOverlap = {\n start: Math.max(\n node.center.x - node.width / 2,\n adjNode.center.x - adjNode.width / 2,\n ),\n end: Math.min(\n node.center.x + node.width / 2,\n adjNode.center.x + adjNode.width / 2,\n ),\n }\n\n const yOverlap = {\n start: Math.max(\n node.center.y - node.height / 2,\n adjNode.center.y - adjNode.height / 2,\n ),\n end: Math.min(\n node.center.y + node.height / 2,\n adjNode.center.y + adjNode.height / 2,\n ),\n }\n\n const xRange = xOverlap.end - xOverlap.start\n const yRange = yOverlap.end - yOverlap.start\n\n // If the x-range is smaller then the nodes touch vertically (common vertical edge).\n if (xRange < yRange) {\n // They are horizontally adjacent: shared vertical edge.\n const x = (xOverlap.start + xOverlap.end) / 2\n return {\n start: { x, y: yOverlap.start },\n end: { x, y: yOverlap.end },\n }\n } else {\n // Otherwise, they are vertically adjacent: shared horizontal edge.\n const y = (yOverlap.start + yOverlap.end) / 2\n return {\n start: { x: xOverlap.start, y },\n end: { x: xOverlap.end, y },\n }\n }\n}\n\nconst EPSILON = 1e-9 // Adjust threshold as needed\n\nfunction coordsAreEqual(\n p1: { x: number; y: number },\n p2: { x: number; y: number },\n): boolean {\n return Math.abs(p1.x - p2.x) < EPSILON && Math.abs(p1.y - p2.y) < EPSILON\n}\n\n// Helper to compare availableZ arrays (order matters for equality check here)\nfunction availableZAreEqual(zA1: number[], zA2: number[]): boolean {\n if (zA1.length !== zA2.length) {\n return false\n }\n // Assuming they are sorted or order matters for distinction\n for (let i = 0; i < zA1.length; i++) {\n if (zA1[i] !== zA2[i]) {\n return false\n }\n }\n return true\n}\n\n/**\n * Given a list of segments on a node, merge segments that are geometrically\n * identical (same start/end points, potentially swapped) AND share the exact\n * same availableZ list. Combines only their connection names.\n */\nfunction combineSegments(segments: NodePortSegment[]): NodePortSegment[] {\n const mergedSegments: NodePortSegment[] = []\n // Create copies to avoid modifying the original array during iteration\n // Sort availableZ consistently within each segment copy first\n const remainingSegments = segments.map((s) => ({\n ...s,\n connectionNames: [...s.connectionNames],\n availableZ: [...s.availableZ].sort((a, b) => a - b), // Ensure Z is sorted for comparison\n }))\n\n while (remainingSegments.length > 0) {\n const segmentUnderTest = remainingSegments.pop()!\n let foundMatch = false\n\n for (let i = 0; i < mergedSegments.length; i++) {\n const mergedSegment = mergedSegments[i]\n\n // Check 1: Geometric match (allowing for start/end swap)\n const geometryMatch =\n (coordsAreEqual(mergedSegment.start, segmentUnderTest.start) &&\n coordsAreEqual(mergedSegment.end, segmentUnderTest.end)) ||\n (coordsAreEqual(mergedSegment.start, segmentUnderTest.end) &&\n coordsAreEqual(mergedSegment.end, segmentUnderTest.start))\n\n // Check 2: availableZ match\n const zMatch = availableZAreEqual(\n mergedSegment.availableZ,\n segmentUnderTest.availableZ,\n )\n\n if (geometryMatch && zMatch) {\n // --- Merge Logic ---\n // Combine connection names (ensuring uniqueness)\n const currentConnections = new Set(mergedSegment.connectionNames)\n segmentUnderTest.connectionNames.forEach((cn) =>\n currentConnections.add(cn),\n )\n mergedSegment.connectionNames = Array.from(currentConnections)\n\n // DO NOT merge availableZ - they must be identical to reach here.\n\n foundMatch = true\n break // Found a match for segmentUnderTest, move to next remaining\n }\n }\n\n if (!foundMatch) {\n // If no suitable match was found (different geometry OR different availableZ),\n // add the segmentUnderTest as a new distinct merged segment.\n mergedSegments.push(segmentUnderTest)\n }\n }\n return mergedSegments\n}\n","import { BaseSolver } from \"../BaseSolver\"\nimport type { NodePortSegment } from \"../../types/capacity-edges-to-port-segments-types\"\nimport type { GraphicsObject, Line } from \"graphics-debug\"\nimport type { NodeWithPortPoints } from \"../../types/high-density-types\"\nimport type { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\n\nexport interface SegmentWithAssignedPoints extends NodePortSegment {\n assignedPoints?: {\n connectionName: string\n point: { x: number; y: number; z: number }\n }[]\n}\n\n/**\n * CapacitySegmentToPointSolver:\n *\n * In each step, the solver iterates over all unsolved segments (segments\n * without points assigned for each connection). For each segment:\n *\n * - If there is only one connection, it assigns the center as the point.\n * - If there are two connections, it attempts to determine the ordering using\n * other segments within the node. If no ordering can be determined, it does nothing.\n *\n * If an iteration produces no new assignments, the solver picks the segment with\n * the fewest connections and assigns points evenly spaced along the segment,\n * ordering them alphabetically.\n */\nexport class CapacitySegmentToPointSolver extends BaseSolver {\n unsolvedSegments: SegmentWithAssignedPoints[]\n solvedSegments: (NodePortSegment & {\n assignedPoints: {\n connectionName: string\n point: { x: number; y: number; z: number }\n }[]\n })[]\n nodeMap: Record<string, CapacityMeshNode>\n colorMap: Record<string, string>\n\n // We use an extra property on segments to remember assigned points.\n // Each segment will get an added property \"assignedPoints\" which is an array of:\n // { connectionName: string, point: {x: number, y: number } }\n // This is a temporary extension used by the solver.\n constructor({\n segments,\n colorMap,\n nodes,\n }: {\n segments: NodePortSegment[]\n colorMap?: Record<string, string>\n /**\n * This isn't used by the algorithm, but allows associating metadata\n * for the result datatype (the center, width, height of the node)\n */\n nodes: CapacityMeshNode[]\n }) {\n super()\n this.MAX_ITERATIONS = 100_000\n this.unsolvedSegments = segments\n this.solvedSegments = []\n this.colorMap = colorMap ?? {}\n this.nodeMap = Object.fromEntries(\n nodes.map((node) => [node.capacityMeshNodeId, node]),\n )\n }\n\n /**\n * Perform one iteration step.\n */\n _step() {\n let updated = false\n // unsolved segments: segments without complete assignments.\n const unsolved = [...this.unsolvedSegments]\n\n // Iterate over unsolved segments.\n for (const seg of unsolved) {\n const n = seg.connectionNames.length\n // Already processed? Skip if assignedPoints exists for all connections.\n if (\"assignedPoints\" in seg && seg.assignedPoints?.length === n) continue\n\n if (n === 1) {\n // For a single connection, assign the center of the segment.\n const center = {\n x: (seg.start.x + seg.end.x) / 2,\n y: (seg.start.y + seg.end.y) / 2,\n z: seg.availableZ[0],\n }\n ;(seg as any).assignedPoints = [\n { connectionName: seg.connectionNames[0], point: center },\n ]\n // Move seg from unsolvedSegments to solvedSegments.\n this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(seg), 1)\n this.solvedSegments.push(seg as any)\n updated = true\n }\n }\n\n // If no segments were updated in this iteration, perform a fallback.\n if (!updated && unsolved.length > 0) {\n // Choose the unsolved segment with the fewest connections.\n let candidate = unsolved[0]\n for (const seg of unsolved) {\n if (seg.connectionNames.length < candidate.connectionNames.length) {\n candidate = seg\n }\n }\n // Fallback: assign points evenly spaced along the segment,\n // after sorting connection names alphabetically.\n const sortedConnections = [...candidate.connectionNames].sort()\n const dx = candidate.end.x - candidate.start.x\n const dy = candidate.end.y - candidate.start.y\n const n = sortedConnections.length\n const points: { x: number; y: number; z: number }[] = []\n // Evenly space positions using fractions of the segment distance.\n for (let i = 1; i <= n; i++) {\n const fraction = i / (n + 1)\n points.push({\n x: candidate.start.x + dx * fraction,\n y: candidate.start.y + dy * fraction,\n z: candidate.availableZ[0],\n })\n }\n ;(candidate as any).assignedPoints = sortedConnections.map(\n (conn, idx) => ({\n connectionName: conn,\n point: points[idx],\n }),\n )\n // Move candidate from unsolvedSegments to solvedSegments.\n this.unsolvedSegments.splice(this.unsolvedSegments.indexOf(candidate), 1)\n this.solvedSegments.push(candidate as any)\n updated = true\n }\n\n // If all segments have been assigned points, mark solved.\n if (this.unsolvedSegments.length === 0) {\n this.solved = true\n }\n }\n\n /**\n * Return the assigned points for each segment.\n */\n getNodesWithPortPoints(): NodeWithPortPoints[] {\n if (!this.solved) {\n throw new Error(\n \"CapacitySegmentToPointSolver not solved, can't give port points yet\",\n )\n }\n const map = new Map<string, NodeWithPortPoints>()\n for (const seg of this.solvedSegments) {\n const nodeId = seg.capacityMeshNodeId\n const node = this.nodeMap[nodeId]\n if (!map.has(nodeId)) {\n map.set(nodeId, {\n capacityMeshNodeId: nodeId,\n portPoints: [],\n center: node.center,\n width: node.width,\n height: node.height,\n })\n }\n map.get(nodeId)!.portPoints.push(\n ...seg.assignedPoints.map((ap) => ({\n ...ap.point,\n connectionName: ap.connectionName,\n })),\n )\n }\n return Array.from(map.values())\n }\n\n /**\n * Return a GraphicsObject that visualizes the segments with assigned points.\n */\n visualize(): GraphicsObject {\n const graphics: Required<GraphicsObject> = {\n points: [],\n lines: this.solvedSegments.map((seg) => ({\n points: [seg.start, seg.end],\n step: 4,\n })),\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Capacity Segment to Point Solver\",\n }\n\n // Add points for each assigned point on solved segments\n for (let i = 0; i < this.solvedSegments.length; i++) {\n const seg = this.solvedSegments[i]\n for (let j = 0; j < seg.assignedPoints.length; j++) {\n const ap = seg.assignedPoints[j]\n\n // Calculate the true position and the offset position (if z != 0)\n const truePoint = {\n x: ap.point.x,\n y: ap.point.y,\n }\n\n const offsetPoint = {\n x: ap.point.x + ap.point.z * 0.05,\n y: ap.point.y + ap.point.z * 0.05,\n }\n\n // Add a dashed line to show the true position if there's an offset\n if (ap.point.z !== 0) {\n graphics.lines.push({\n points: [truePoint, offsetPoint],\n strokeColor: \"rgba(0, 0, 0, 0.25)\",\n strokeDash: \"5 5\",\n step: 4,\n })\n }\n\n // Add the point with label\n graphics.points.push({\n x: offsetPoint.x,\n y: offsetPoint.y,\n label: [\n `${seg.capacityMeshNodeId}-${ap.connectionName}`,\n `z: ${seg.availableZ.join(\",\")}`,\n `nodePortSegmentId: ${seg.nodePortSegmentId}`,\n ].join(\"\\n\"),\n color: this.colorMap[ap.connectionName],\n step: 4,\n })\n }\n }\n\n // Add a dashed line connecting the assignment points with the same\n // connection name within the same node\n const dashedLines: Line[] = []\n const nodeConnections: Record<\n CapacityMeshNodeId,\n Record<string, { x: number; y: number }[]>\n > = {}\n for (const seg of this.solvedSegments) {\n const nodeId = seg.capacityMeshNodeId\n if (!nodeConnections[nodeId]) {\n nodeConnections[nodeId] = {}\n }\n for (const ap of seg.assignedPoints) {\n if (!nodeConnections[nodeId][ap.connectionName]) {\n nodeConnections[nodeId][ap.connectionName] = []\n }\n nodeConnections[nodeId][ap.connectionName].push({\n x: ap.point.x,\n y: ap.point.y,\n })\n }\n }\n for (const nodeId in nodeConnections) {\n for (const conn in nodeConnections[nodeId]) {\n const points = nodeConnections[nodeId][conn]\n if (points.length > 1) {\n dashedLines.push({\n points,\n step: 4,\n strokeDash: \"5 5\",\n strokeColor: this.colorMap[conn] || \"#000\",\n } as Line)\n }\n }\n }\n graphics.lines.push(...(dashedLines as any))\n\n return graphics\n }\n}\n","import type { Point } from \"./common\"\n\n/**\n * Returns true if the two lines intersect.\n */\nexport function doesLineIntersectLine(\n [a1, a2]: [Point, Point],\n [b1, b2]: [Point, Point],\n {\n lineThickness = 0,\n }: {\n lineThickness?: number\n } = {},\n): boolean {\n if (lineThickness === 0) {\n return doSegmentsIntersect(a1, a2, b1, b2)\n }\n const minDist = segmentsDistance(a1, a2, b1, b2)\n return minDist <= lineThickness\n}\n\n/**\n * Returns true if the two segments intersect.\n */\nexport function doSegmentsIntersect(\n p1: Point,\n q1: Point,\n p2: Point,\n q2: Point,\n): boolean {\n const o1 = orientation(p1, q1, p2)\n const o2 = orientation(p1, q1, q2)\n const o3 = orientation(p2, q2, p1)\n const o4 = orientation(p2, q2, q1)\n\n // General case\n if (o1 !== o2 && o3 !== o4) {\n return true\n }\n\n // Special Cases\n if (o1 === 0 && onSegment(p1, p2, q1)) return true\n if (o2 === 0 && onSegment(p1, q2, q1)) return true\n if (o3 === 0 && onSegment(p2, p1, q2)) return true\n if (o4 === 0 && onSegment(p2, q1, q2)) return true\n\n return false\n}\n\n/**\n * Returns 0 if the points are colinear, 1 if they are clockwise, and 2 if they are counterclockwise.\n */\nexport function orientation(p: Point, q: Point, r: Point): number {\n const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)\n if (val === 0) return 0 // colinear\n return val > 0 ? 1 : 2 // clock or counterclock wise\n}\n\n/**\n * Returns true if q is on the segment p->r.\n */\nexport function onSegment(p: Point, q: Point, r: Point): boolean {\n return (\n q.x <= Math.max(p.x, r.x) &&\n q.x >= Math.min(p.x, r.x) &&\n q.y <= Math.max(p.y, r.y) &&\n q.y >= Math.min(p.y, r.y)\n )\n}\n\n/**\n * Returns the minimum distance between two segments.\n */\nfunction segmentsDistance(a1: Point, a2: Point, b1: Point, b2: Point): number {\n // Handle degenerate cases: segments of zero length\n if (a1.x === a2.x && a1.y === a2.y) {\n return pointToSegmentDistance(a1, b1, b2)\n }\n if (b1.x === b2.x && b1.y === b2.y) {\n return pointToSegmentDistance(b1, a1, a2)\n }\n\n // Check if segments intersect\n if (doSegmentsIntersect(a1, a2, b1, b2)) {\n return 0\n }\n\n // Compute the minimum distance between the segments\n const distances = [\n pointToSegmentDistance(a1, b1, b2),\n pointToSegmentDistance(a2, b1, b2),\n pointToSegmentDistance(b1, a1, a2),\n pointToSegmentDistance(b2, a1, a2),\n ]\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance between a point and a segment.\n */\nexport function pointToSegmentDistance(p: Point, v: Point, w: Point): number {\n const l2 = (w.x - v.x) ** 2 + (w.y - v.y) ** 2\n if (l2 === 0) return distance(p, v)\n\n let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2\n t = Math.max(0, Math.min(1, t))\n\n const projection = {\n x: v.x + t * (w.x - v.x),\n y: v.y + t * (w.y - v.y),\n }\n\n return distance(p, projection)\n}\n\n/**\n * Returns the distance between two points.\n */\nexport function distance(p1: Point, p2: Point): number {\n const dx = p1.x - p2.x\n const dy = p1.y - p2.y\n return Math.sqrt(dx * dx + dy * dy)\n}\n","import type { Point } from \"./common\"\n\nexport type Box = { center: Point; width: number; height: number }\nexport type BoxSet = Box[]\n\nexport type GridCell = { boxes: Box[] }\n\nexport function getBoundingBox(box: Box) {\n const halfWidth = box.width / 2\n const halfHeight = box.height / 2\n return {\n minX: box.center.x - halfWidth,\n maxX: box.center.x + halfWidth,\n minY: box.center.y - halfHeight,\n maxY: box.center.y + halfHeight,\n }\n}\n\nexport function computeDistanceBetweenBoxes(\n boxA: Box,\n boxB: Box,\n): { distance: number; pointA: Point; pointB: Point } {\n const a = getBoundingBox(boxA)\n const b = getBoundingBox(boxB)\n\n const dx = Math.max(a.minX - b.maxX, b.minX - a.maxX, 0)\n const dy = Math.max(a.minY - b.maxY, b.minY - a.maxY, 0)\n\n const pointA: Point = { x: 0, y: 0 }\n const pointB: Point = { x: 0, y: 0 }\n\n if (dx === 0 && dy === 0) {\n // Boxes overlap\n return { distance: 0, pointA: boxA.center, pointB: boxB.center }\n }\n\n // Compute the closest points on the edges\n pointA.x = clamp(boxA.center.x, b.minX, b.maxX)\n pointA.y = clamp(boxA.center.y, b.minY, b.maxY)\n\n pointB.x = clamp(boxB.center.x, a.minX, a.maxX)\n pointB.y = clamp(boxB.center.y, a.minY, a.maxY)\n\n const distance = Math.hypot(pointA.x - pointB.x, pointA.y - pointB.y)\n return { distance, pointA, pointB }\n}\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value))\n}\n\nexport function findNearestPointsBetweenBoxSets(\n boxSetA: BoxSet,\n boxSetB: BoxSet,\n): { pointA: Point; pointB: Point; distance: number } {\n let minDistance = Number.POSITIVE_INFINITY\n let nearestPointA: Point = { x: 0, y: 0 }\n let nearestPointB: Point = { x: 0, y: 0 }\n\n for (const boxA of boxSetA) {\n for (const boxB of boxSetB) {\n const { distance, pointA, pointB } = computeDistanceBetweenBoxes(\n boxA,\n boxB,\n )\n if (distance < minDistance) {\n minDistance = distance\n nearestPointA = pointA\n nearestPointB = pointB\n }\n }\n }\n\n return {\n pointA: nearestPointA,\n pointB: nearestPointB,\n distance: minDistance,\n }\n}\n","import type { Point } from \"./common\"\nimport {\n distance,\n doSegmentsIntersect,\n pointToSegmentDistance,\n} from \"./line-intersections\"\nimport { clamp } from \"./nearest-box\"\n\n/**\n * Returns the minimum distance between two line segments.\n */\nexport function segmentToSegmentMinDistance(\n a: Point,\n b: Point,\n u: Point,\n v: Point,\n): number {\n // Handle degenerate cases: segments of zero length\n if (a.x === b.x && a.y === b.y) {\n return pointToSegmentDistance(a, u, v)\n }\n if (u.x === v.x && u.y === v.y) {\n return pointToSegmentDistance(u, a, b)\n }\n\n // Check if segments intersect\n if (doSegmentsIntersect(a, b, u, v)) {\n return 0\n }\n\n // Compute the minimum distance between the segments\n const distances = [\n pointToSegmentDistance(a, u, v),\n pointToSegmentDistance(b, u, v),\n pointToSegmentDistance(u, a, b),\n pointToSegmentDistance(v, a, b),\n ]\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance from a line segment to a bounding box.\n */\nexport function segmentToBoundsMinDistance(\n a: Point,\n b: Point,\n bounds: { minX: number; minY: number; maxX: number; maxY: number },\n): number {\n // Check if segment intersects with the bounds\n // Create the four edges of the bounds\n const topLeft = { x: bounds.minX, y: bounds.minY }\n const topRight = { x: bounds.maxX, y: bounds.minY }\n const bottomLeft = { x: bounds.minX, y: bounds.maxY }\n const bottomRight = { x: bounds.maxX, y: bounds.maxY }\n\n // Check if segment intersects with any of the bounds edges\n if (\n doSegmentsIntersect(a, b, topLeft, topRight) ||\n doSegmentsIntersect(a, b, topRight, bottomRight) ||\n doSegmentsIntersect(a, b, bottomRight, bottomLeft) ||\n doSegmentsIntersect(a, b, bottomLeft, topLeft)\n ) {\n return 0\n }\n\n // Check if segment is entirely inside the bounds\n if (\n a.x >= bounds.minX &&\n a.x <= bounds.maxX &&\n a.y >= bounds.minY &&\n a.y <= bounds.maxY &&\n b.x >= bounds.minX &&\n b.x <= bounds.maxX &&\n b.y >= bounds.minY &&\n b.y <= bounds.maxY\n ) {\n return 0\n }\n\n // If not intersecting, calculate the minimum distance\n const distances = [\n pointToSegmentDistance(topLeft, a, b),\n pointToSegmentDistance(topRight, a, b),\n pointToSegmentDistance(bottomLeft, a, b),\n pointToSegmentDistance(bottomRight, a, b),\n ]\n\n // If one of the segment endpoints is inside the bounds, we need to consider its distance to the bounds as 0\n if (\n a.x >= bounds.minX &&\n a.x <= bounds.maxX &&\n a.y >= bounds.minY &&\n a.y <= bounds.maxY\n ) {\n return 0\n }\n\n if (\n b.x >= bounds.minX &&\n b.x <= bounds.maxX &&\n b.y >= bounds.minY &&\n b.y <= bounds.maxY\n ) {\n return 0\n }\n\n // Calculate distances from segment endpoints to bounds if outside\n if (\n a.x < bounds.minX ||\n a.x > bounds.maxX ||\n a.y < bounds.minY ||\n a.y > bounds.maxY\n ) {\n const closestX = clamp(a.x, bounds.minX, bounds.maxX)\n const closestY = clamp(a.y, bounds.minY, bounds.maxY)\n distances.push(distance(a, { x: closestX, y: closestY }))\n }\n\n if (\n b.x < bounds.minX ||\n b.x > bounds.maxX ||\n b.y < bounds.minY ||\n b.y > bounds.maxY\n ) {\n const closestX = clamp(b.x, bounds.minX, bounds.maxX)\n const closestY = clamp(b.y, bounds.minY, bounds.maxY)\n distances.push(distance(b, { x: closestX, y: closestY }))\n }\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance from a line segment to a box.\n */\nexport function segmentToBoxMinDistance(\n a: Point,\n b: Point,\n box: { center: Point; width: number; height: number },\n): number {\n const halfWidth = box.width / 2\n const halfHeight = box.height / 2\n const bounds = {\n minX: box.center.x - halfWidth,\n maxX: box.center.x + halfWidth,\n minY: box.center.y - halfHeight,\n maxY: box.center.y + halfHeight,\n }\n\n return segmentToBoundsMinDistance(a, b, bounds)\n}\n\n/**\n * Returns the minimum distance from a line segment to a circle.\n */\nexport function segmentToCircleMinDistance(\n a: Point,\n b: Point,\n circle: { x: number; y: number; radius: number },\n): number {\n // Calculate the distance from the circle center to the line segment\n const circleCenter = { x: circle.x, y: circle.y }\n\n // Handle degenerate case: segment of zero length (point to circle)\n if (a.x === b.x && a.y === b.y) {\n return Math.max(0, distance(a, circleCenter) - circle.radius)\n }\n\n // Vector from a to b\n const ab = { x: b.x - a.x, y: b.y - a.y }\n // Vector from a to circle center\n const ac = { x: circleCenter.x - a.x, y: circleCenter.y - a.y }\n\n // Length of segment ab squared\n const abLengthSq = ab.x * ab.x + ab.y * ab.y\n\n // Calculate projection of ac onto ab, normalized by the length of ab\n const t = Math.max(0, Math.min(1, (ab.x * ac.x + ab.y * ac.y) / abLengthSq))\n\n // Find the closest point on the segment to the circle center\n const closestPoint = {\n x: a.x + t * ab.x,\n y: a.y + t * ab.y,\n }\n\n // Calculate distance from closest point to circle center\n const distToCenter = distance(closestPoint, circleCenter)\n\n // Return the distance to the circle (subtract radius from distance to center)\n return Math.max(0, distToCenter - circle.radius)\n}\n","export type Node = {\n x: number\n y: number\n z: number\n\n g: number\n h: number\n f: number\n\n parent: Node | null\n}\n\nexport class SingleRouteCandidatePriorityQueue {\n private heap: Node[] = []\n\n constructor(nodes: Node[]) {\n this.heap = []\n\n for (const node of nodes) {\n this.enqueue(node)\n }\n }\n\n private getLeftChildIndex(parentIndex: number): number {\n return 2 * parentIndex + 1\n }\n\n private getRightChildIndex(parentIndex: number): number {\n return 2 * parentIndex + 2\n }\n\n private getParentIndex(childIndex: number) {\n return Math.floor((childIndex - 1) / 2)\n }\n\n private hasLeftChild(index: number): boolean {\n return this.getLeftChildIndex(index) < this.heap.length\n }\n\n private hasRightChild(index: number): boolean {\n return this.getRightChildIndex(index) < this.heap.length\n }\n\n private hasParent(index: number): boolean {\n return this.getParentIndex(index) >= 0\n }\n\n private leftChild(index: number): Node {\n return this.heap[this.getLeftChildIndex(index)]\n }\n\n private rightChild(index: number): Node {\n return this.heap[this.getRightChildIndex(index)]\n }\n\n private parent(index: number): Node {\n return this.heap[this.getParentIndex(index)]\n }\n\n private swap(i: number, j: number) {\n const temp = this.heap[i]\n this.heap[i] = this.heap[j]\n this.heap[j] = temp\n }\n\n // Removing an element will remove the\n // top element with highest priority then\n // heapifyDown will be called\n dequeue(): Node | null {\n if (this.heap.length === 0) {\n return null\n }\n const item = this.heap[0]\n this.heap[0] = this.heap[this.heap.length - 1]\n this.heap.pop()\n this.heapifyDown()\n return item\n }\n\n peek(): Node | null {\n if (this.heap.length === 0) {\n return null\n }\n return this.heap[0]\n }\n\n enqueue(item: Node) {\n this.heap.push(item)\n this.heapifyUp()\n }\n\n heapifyUp() {\n let index = this.heap.length - 1\n while (this.hasParent(index) && this.parent(index).f > this.heap[index].f) {\n this.swap(this.getParentIndex(index), index)\n index = this.getParentIndex(index)\n }\n }\n\n heapifyDown() {\n let index = 0\n while (this.hasLeftChild(index)) {\n let smallerChildIndex = this.getLeftChildIndex(index)\n if (\n this.hasRightChild(index) &&\n this.rightChild(index).f < this.leftChild(index).f\n ) {\n smallerChildIndex = this.getRightChildIndex(index)\n }\n if (this.heap[index].f < this.heap[smallerChildIndex].f) {\n break\n } else {\n this.swap(index, smallerChildIndex)\n }\n index = smallerChildIndex\n }\n }\n}\n","import { BaseSolver } from \"../BaseSolver\"\nimport type { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport {\n distance,\n pointToSegmentDistance,\n doSegmentsIntersect,\n} from \"@tscircuit/math-utils\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { HighDensityHyperParameters } from \"./HighDensityHyperParameters\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport {\n Node,\n SingleRouteCandidatePriorityQueue,\n} from \"lib/data-structures/SingleRouteCandidatePriorityQueue\"\n\nexport type FutureConnection = {\n connectionName: string\n points: { x: number; y: number; z: number }[]\n}\n\nexport class SingleHighDensityRouteSolver extends BaseSolver {\n obstacleRoutes: HighDensityIntraNodeRoute[]\n bounds: { minX: number; maxX: number; minY: number; maxY: number }\n boundsSize: { width: number; height: number }\n boundsCenter: { x: number; y: number }\n A: { x: number; y: number; z: number }\n B: { x: number; y: number; z: number }\n straightLineDistance: number\n\n viaDiameter: number\n traceThickness: number\n obstacleMargin: number\n layerCount: number\n minCellSize = 0.05\n cellStep = 0.05\n GREEDY_MULTIPLER = 1.1\n numRoutes: number\n\n VIA_PENALTY_FACTOR = 0.3\n CELL_SIZE_FACTOR: number\n\n exploredNodes: Set<string>\n\n candidates: SingleRouteCandidatePriorityQueue\n\n connectionName: string\n solvedPath: HighDensityIntraNodeRoute | null = null\n\n futureConnections: FutureConnection[]\n hyperParameters: Partial<HighDensityHyperParameters>\n\n connMap?: ConnectivityMap\n\n /** For debugging/animating the exploration */\n debug_exploredNodesOrdered: string[]\n debug_nodesTooCloseToObstacle: Set<string>\n debug_nodePathToParentIntersectsObstacle: Set<string>\n\n debugEnabled = true\n\n initialNodeGridOffset: { x: number; y: number }\n\n constructor(opts: {\n connectionName: string\n obstacleRoutes: HighDensityIntraNodeRoute[]\n minDistBetweenEnteringPoints: number\n bounds: { minX: number; maxX: number; minY: number; maxY: number }\n A: { x: number; y: number; z: number }\n B: { x: number; y: number; z: number }\n viaDiameter?: number\n traceThickness?: number\n obstacleMargin?: number\n layerCount?: number\n futureConnections?: FutureConnection[]\n hyperParameters?: Partial<HighDensityHyperParameters>\n connMap?: ConnectivityMap\n }) {\n super()\n this.bounds = opts.bounds\n this.connMap = opts.connMap\n this.hyperParameters = opts.hyperParameters ?? {}\n this.CELL_SIZE_FACTOR = this.hyperParameters.CELL_SIZE_FACTOR ?? 1\n this.boundsSize = {\n width: this.bounds.maxX - this.bounds.minX,\n height: this.bounds.maxY - this.bounds.minY,\n }\n this.boundsCenter = {\n x: (this.bounds.minX + this.bounds.maxX) / 2,\n y: (this.bounds.minY + this.bounds.maxY) / 2,\n }\n this.connectionName = opts.connectionName\n this.obstacleRoutes = opts.obstacleRoutes\n this.A = opts.A\n this.B = opts.B\n this.viaDiameter = opts.viaDiameter ?? 0.6\n this.traceThickness = opts.traceThickness ?? 0.15\n this.obstacleMargin = opts.obstacleMargin ?? 0.2\n this.layerCount = opts.layerCount ?? 2\n this.exploredNodes = new Set()\n this.straightLineDistance = distance(this.A, this.B)\n this.futureConnections = opts.futureConnections ?? []\n this.MAX_ITERATIONS = 5000\n\n this.debug_exploredNodesOrdered = []\n this.debug_nodesTooCloseToObstacle = new Set()\n this.debug_nodePathToParentIntersectsObstacle = new Set()\n this.numRoutes = this.obstacleRoutes.length + this.futureConnections.length\n const bestRowOrColumnCount = Math.ceil(5 * (this.numRoutes + 1))\n let numXCells = this.boundsSize.width / this.cellStep\n let numYCells = this.boundsSize.height / this.cellStep\n\n while (numXCells * numYCells > bestRowOrColumnCount ** 2) {\n if (this.cellStep * 2 > opts.minDistBetweenEnteringPoints) {\n break\n }\n this.cellStep *= 2\n numXCells = this.boundsSize.width / this.cellStep\n numYCells = this.boundsSize.height / this.cellStep\n }\n\n this.cellStep *= this.CELL_SIZE_FACTOR\n\n if (\n this.futureConnections &&\n this.futureConnections.length === 0 &&\n this.obstacleRoutes.length === 0\n ) {\n this.handleSimpleCases()\n }\n\n const initialNodePosition = {\n x: Math.round(opts.A.x / (this.cellStep / 2)) * (this.cellStep / 2),\n y: Math.round(opts.A.y / (this.cellStep / 2)) * (this.cellStep / 2),\n }\n this.initialNodeGridOffset = {\n x:\n initialNodePosition.x -\n Math.round(opts.A.x / this.cellStep) * this.cellStep,\n y:\n initialNodePosition.y -\n Math.round(opts.A.y / this.cellStep) * this.cellStep,\n }\n this.candidates = new SingleRouteCandidatePriorityQueue([\n {\n ...opts.A,\n ...initialNodePosition,\n z: opts.A.z ?? 0,\n g: 0,\n h: 0,\n f: 0,\n parent: {\n ...opts.A,\n z: opts.A.z ?? 0,\n g: 0,\n h: 0,\n f: 0,\n parent: null,\n },\n },\n ])\n }\n\n handleSimpleCases() {\n this.solved = true\n const { A, B } = this\n const route =\n A.z === B.z\n ? [A, B]\n : [\n A,\n { ...this.boundsCenter, z: this.A.z },\n {\n ...this.boundsCenter,\n z: B.z,\n },\n B,\n ]\n this.solvedPath = {\n connectionName: this.connectionName,\n route,\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: this.A.z === this.B.z ? [] : [this.boundsCenter],\n }\n }\n\n get viaPenaltyDistance() {\n return this.cellStep + this.straightLineDistance * this.VIA_PENALTY_FACTOR\n }\n\n isNodeTooCloseToObstacle(node: Node, margin?: number, isVia?: boolean) {\n margin ??= this.obstacleMargin\n\n if (isVia && node.parent) {\n const viasInMyRoute = this.getViasInNodePath(node.parent)\n for (const via of viasInMyRoute) {\n if (distance(node, via) < this.viaDiameter / 2 + margin) {\n return true\n }\n }\n }\n\n for (const route of this.obstacleRoutes) {\n const connectedToObstacle = this.connMap?.areIdsConnected?.(\n this.connectionName,\n route.connectionName,\n )\n\n if (!connectedToObstacle) {\n const pointPairs = getSameLayerPointPairs(route)\n for (const pointPair of pointPairs) {\n if (\n (isVia || pointPair.z === node.z) &&\n pointToSegmentDistance(node, pointPair.A, pointPair.B) <\n this.traceThickness + margin\n ) {\n return true\n }\n }\n }\n for (const via of route.vias) {\n if (\n distance(node, via) <\n this.viaDiameter / 2 + this.traceThickness / 2 + margin\n ) {\n return true\n }\n }\n }\n\n return false\n }\n\n isNodeTooCloseToEdge(node: Node, isVia?: boolean) {\n const margin = isVia\n ? this.viaDiameter / 2 + this.obstacleMargin / 2\n : this.obstacleMargin / 2\n const tooClose =\n node.x < this.bounds.minX + margin ||\n node.x > this.bounds.maxX - margin ||\n node.y < this.bounds.minY + margin ||\n node.y > this.bounds.maxY - margin\n if (tooClose && !isVia) {\n // If it's close to B or A it's an exception\n if (\n distance(node, this.B) < margin * 2 ||\n distance(node, this.A) < margin * 2\n ) {\n return false\n }\n }\n return tooClose\n }\n\n doesPathToParentIntersectObstacle(node: Node) {\n const parent = node.parent\n if (!parent) return false\n for (const route of this.obstacleRoutes) {\n const obstacleIsConnectedToNewPath = this.connMap?.areIdsConnected?.(\n this.connectionName,\n route.connectionName,\n )\n if (obstacleIsConnectedToNewPath) continue\n for (const pointPair of getSameLayerPointPairs(route)) {\n if (pointPair.z !== node.z) continue\n if (doSegmentsIntersect(node, parent, pointPair.A, pointPair.B)) {\n return true\n }\n }\n }\n return false\n }\n\n computeH(node: Node) {\n return (\n distance(node, this.B) +\n // via penalty\n Math.abs(node.z - this.B.z) * this.viaPenaltyDistance\n )\n }\n\n computeG(node: Node) {\n return (\n (node.parent?.g ?? 0) +\n (node.z === 0 ? 0 : this.viaPenaltyDistance) +\n distance(node, node.parent!)\n )\n }\n\n computeF(g: number, h: number) {\n return g + h * this.GREEDY_MULTIPLER\n }\n\n getNodeKey(node: Node) {\n return `${Math.round(node.x / this.cellStep) * this.cellStep},${Math.round(node.y / this.cellStep) * this.cellStep},${node.z}`\n }\n\n getNeighbors(node: Node) {\n const neighbors: Node[] = []\n\n const { maxX, minX, maxY, minY } = this.bounds\n\n for (let x = -1; x <= 1; x++) {\n for (let y = -1; y <= 1; y++) {\n if (x === 0 && y === 0) continue\n\n const neighbor = {\n ...node,\n parent: node,\n x: clamp(node.x + x * this.cellStep, minX, maxX),\n y: clamp(node.y + y * this.cellStep, minY, maxY),\n }\n\n const neighborKey = this.getNodeKey(neighbor)\n\n if (this.exploredNodes.has(neighborKey)) {\n continue\n }\n\n if (this.isNodeTooCloseToObstacle(neighbor)) {\n this.debug_nodesTooCloseToObstacle.add(neighborKey)\n this.exploredNodes.add(neighborKey)\n continue\n }\n\n if (this.isNodeTooCloseToEdge(neighbor, false)) {\n this.exploredNodes.add(neighborKey)\n continue\n }\n\n if (this.doesPathToParentIntersectObstacle(neighbor)) {\n this.debug_nodePathToParentIntersectsObstacle.add(neighborKey)\n this.exploredNodes.add(neighborKey)\n continue\n }\n\n neighbor.g = this.computeG(neighbor)\n neighbor.h = this.computeH(neighbor)\n neighbor.f = this.computeF(neighbor.g, neighbor.h)\n\n neighbors.push(neighbor)\n }\n }\n\n const viaNeighbor = {\n ...node,\n parent: node,\n z: node.z === 0 ? this.layerCount - 1 : 0,\n }\n\n if (\n !this.exploredNodes.has(this.getNodeKey(viaNeighbor)) &&\n !this.isNodeTooCloseToObstacle(\n viaNeighbor,\n this.viaDiameter / 2 + this.obstacleMargin / 2,\n true,\n ) &&\n !this.isNodeTooCloseToEdge(viaNeighbor, true)\n ) {\n viaNeighbor.g = this.computeG(viaNeighbor)\n viaNeighbor.h = this.computeH(viaNeighbor)\n viaNeighbor.f = this.computeF(viaNeighbor.g, viaNeighbor.h)\n\n neighbors.push(viaNeighbor)\n }\n\n return neighbors\n }\n\n getNodePath(node: Node) {\n const path: Node[] = []\n while (node) {\n path.push(node)\n node = node.parent!\n }\n return path\n }\n\n getViasInNodePath(node: Node) {\n const path = this.getNodePath(node)\n const vias: { x: number; y: number }[] = []\n for (let i = 0; i < path.length - 1; i++) {\n if (path[i].z !== path[i + 1].z) {\n vias.push({ x: path[i].x, y: path[i].y })\n }\n }\n return vias\n }\n\n setSolvedPath(node: Node) {\n const path = this.getNodePath(node)\n path.reverse()\n\n const vias: { x: number; y: number }[] = []\n for (let i = 0; i < path.length - 1; i++) {\n if (path[i].z !== path[i + 1].z) {\n vias.push({ x: path[i].x, y: path[i].y })\n }\n }\n\n this.solvedPath = {\n connectionName: this.connectionName,\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n route: path\n .map((node) => ({ x: node.x, y: node.y, z: node.z }))\n .concat([this.B]),\n vias,\n }\n }\n\n computeProgress(currentNode: Node, goalDist: number, isOnLayer: boolean) {\n if (!isOnLayer) goalDist += this.viaPenaltyDistance\n const goalDistPercent = 1 - goalDist / this.straightLineDistance\n\n // This is a perfectly acceptable progress metric\n // return Math.max(this.progress || 0, goalDistPercent)\n\n // Linearize because it typically gets harder towards the end\n return Math.max(\n this.progress || 0,\n // 0.112 = ~90% -> 50%\n // ~25% -> 2%\n // ~99% -> 94%\n // ~95% -> 72%\n (2 / Math.PI) *\n Math.atan((0.112 * goalDistPercent) / (1 - goalDistPercent)),\n )\n }\n\n _step() {\n let currentNode = this.candidates.dequeue()\n let currentNodeKey = currentNode ? this.getNodeKey(currentNode) : undefined\n\n while (\n currentNode &&\n currentNodeKey &&\n this.exploredNodes.has(currentNodeKey)\n ) {\n currentNode = this.candidates.dequeue()\n currentNodeKey = currentNode ? this.getNodeKey(currentNode) : undefined\n }\n\n if (!currentNode || !currentNodeKey) {\n this.failed = true\n return\n }\n this.exploredNodes.add(currentNodeKey)\n this.debug_exploredNodesOrdered.push(currentNodeKey)\n\n const goalDist = distance(currentNode, this.B)\n\n this.progress = this.computeProgress(\n currentNode,\n goalDist,\n currentNode.z === this.B.z,\n )\n\n if (\n goalDist <= this.cellStep * Math.SQRT2 &&\n currentNode.z === this.B.z &&\n // Make sure the last segment doesn't intersect an obstacle\n !this.doesPathToParentIntersectObstacle({\n ...currentNode,\n parent: currentNode,\n x: this.B.x,\n y: this.B.y,\n })\n ) {\n this.solved = true\n this.setSolvedPath(currentNode)\n }\n\n const neighbors = this.getNeighbors(currentNode)\n for (const neighbor of neighbors) {\n this.candidates.enqueue(neighbor)\n }\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n\n // Display the input port points (from nodeWithPortPoints via A and B)\n graphics.points!.push({\n x: this.A.x,\n y: this.A.y,\n label: `Input A\\nz: ${this.A.z}`,\n color: \"orange\",\n })\n graphics.points!.push({\n x: this.B.x,\n y: this.B.y,\n label: `Input B\\nz: ${this.B.z}`,\n color: \"orange\",\n })\n\n // Draw circles at future connection points\n // if (\"FUTURE_CONNECTION_PROXIMITY_VD\" in this) {\n // for (const futureConnection of this.futureConnections) {\n // for (const point of futureConnection.points) {\n // graphics.circles!.push({\n // center: point,\n // radius:\n // (this.viaDiameter *\n // (this.FUTURE_CONNECTION_PROXIMITY_VD as number)) /\n // 2,\n // // strokeColor: \"rgba(0, 255, 0, 0.3)\",\n // stroke: \"rgba(0,255,0,0.1)\",\n // label: `Future Connection: ${futureConnection.connectionName}`,\n // })\n // }\n // }\n // // Draw circles around obstacle route points\n // for (const route of this.obstacleRoutes) {\n // for (const point of [\n // route.route[0],\n // route.route[route.route.length - 1],\n // ]) {\n // graphics.circles!.push({\n // center: point,\n // radius:\n // (this.viaDiameter *\n // (this.FUTURE_CONNECTION_PROXIMITY_VD as number)) /\n // 2,\n // stroke: \"rgba(255,0,0,0.1)\",\n // label: \"Obstacle Route Point\",\n // })\n // }\n // }\n // }\n\n // Draw a line representing the direct connection between the input port points\n graphics.lines!.push({\n points: [this.A, this.B],\n strokeColor: \"rgba(255, 0, 0, 0.5)\",\n label: \"Direct Input Connection\",\n })\n\n // Show any obstacle routes as background references\n for (\n let routeIndex = 0;\n routeIndex < this.obstacleRoutes.length;\n routeIndex++\n ) {\n const route = this.obstacleRoutes[routeIndex]\n for (let i = 0; i < route.route.length - 1; i++) {\n const z = route.route[i].z\n graphics.lines!.push({\n points: [route.route[i], route.route[i + 1]],\n strokeColor:\n z === 0 ? \"rgba(255, 0, 0, 0.75)\" : \"rgba(255, 128, 0, 0.25)\",\n strokeWidth: route.traceThickness,\n label: \"Obstacle Route\",\n layer: `obstacle${routeIndex.toString()}`,\n })\n }\n }\n\n // Optionally, visualize explored nodes for debugging purposes\n for (let i = 0; i < this.debug_exploredNodesOrdered.length; i++) {\n const nodeKey = this.debug_exploredNodesOrdered[i]\n const [x, y, z] = nodeKey.split(\",\").map(Number)\n if (this.debug_nodesTooCloseToObstacle.has(nodeKey)) continue\n if (this.debug_nodePathToParentIntersectsObstacle.has(nodeKey)) continue\n graphics.rects!.push({\n center: {\n x: x + this.initialNodeGridOffset.x + (z * this.cellStep) / 20,\n y: y + this.initialNodeGridOffset.y + (z * this.cellStep) / 20,\n },\n fill:\n z === 0\n ? `rgba(255,0,255,${0.3 - (i / this.debug_exploredNodesOrdered.length) * 0.2})`\n : `rgba(0,0,255,${0.3 - (i / this.debug_exploredNodesOrdered.length) * 0.2})`,\n width: this.cellStep * 0.9,\n height: this.cellStep * 0.9,\n label: `Explored (z=${z})`,\n })\n }\n\n // Visualize the next node to be explored\n if (this.candidates.peek()) {\n const nextNode = this.candidates.peek()!\n graphics.rects!.push({\n center: {\n x: nextNode.x + (nextNode.z * this.cellStep) / 20,\n y: nextNode.y + (nextNode.z * this.cellStep) / 20,\n },\n fill: \"rgba(0, 255, 0, 0.8)\",\n width: this.cellStep * 0.9,\n height: this.cellStep * 0.9,\n label: `Next (z=${nextNode.z})`,\n })\n }\n\n // Visualize vias from obstacle routes\n for (const route of this.obstacleRoutes) {\n for (const via of route.vias) {\n graphics.circles!.push({\n center: {\n x: via.x,\n y: via.y,\n },\n radius: this.viaDiameter / 2,\n fill: \"rgba(255, 0, 0, 0.5)\",\n label: \"Via\",\n })\n }\n }\n // If a solved route exists, display it along with via markers\n if (this.solvedPath) {\n graphics.lines!.push({\n points: this.solvedPath.route,\n strokeColor: \"green\",\n label: \"Solved Route\",\n })\n for (const via of this.solvedPath.vias) {\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2,\n fill: \"green\",\n label: \"Via\",\n })\n }\n }\n\n return graphics\n }\n}\n\nfunction getSameLayerPointPairs(route: HighDensityIntraNodeRoute) {\n const pointPairs: {\n z: number\n A: { x: number; y: number; z: number }\n B: { x: number; y: number; z: number }\n }[] = []\n\n for (let i = 0; i < route.route.length - 1; i++) {\n if (route.route[i].z === route.route[i + 1].z) {\n pointPairs.push({\n z: route.route[i].z,\n A: route.route[i],\n B: route.route[i + 1],\n })\n }\n }\n\n return pointPairs\n}\n\nfunction clamp(value: number, min: number, max: number) {\n return Math.max(min, Math.min(value, max))\n}\n","import { distance } from \"@tscircuit/math-utils\"\nimport { SingleHighDensityRouteSolver } from \"./SingleHighDensityRouteSolver\"\nimport { Node } from \"lib/data-structures/SingleRouteCandidatePriorityQueue\"\n\nexport class SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost extends SingleHighDensityRouteSolver {\n FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR = 2\n FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR = 1\n FUTURE_CONNECTION_PROXIMITY_VD = 10\n MISALIGNED_DIST_PENALTY_FACTOR = 5\n VIA_PENALTY_FACTOR_2 = 1\n FLIP_TRACE_ALIGNMENT_DIRECTION = false\n\n constructor(\n opts: ConstructorParameters<typeof SingleHighDensityRouteSolver>[0],\n ) {\n super(opts)\n for (const key in opts.hyperParameters) {\n // @ts-ignore\n this[key] = opts.hyperParameters[key]\n }\n\n // Ratio of available space determines via penalty\n const viasThatCanFitHorz = this.boundsSize.width / this.viaDiameter\n this.VIA_PENALTY_FACTOR =\n 0.3 * (viasThatCanFitHorz / this.numRoutes) * this.VIA_PENALTY_FACTOR_2\n }\n\n getClosestFutureConnectionPoint(node: Node) {\n let minDist = Infinity\n let closestPoint = null\n\n for (const futureConnection of this.futureConnections) {\n for (const point of futureConnection.points) {\n const dist =\n distance(node, point) +\n (node.z !== point.z ? this.viaPenaltyDistance : 0)\n if (dist < minDist) {\n minDist = dist\n closestPoint = point\n }\n }\n }\n\n return closestPoint\n }\n\n /**\n * Rapidly approaches 0 as the goal distance approaches 0\n */\n diminishCloseToGoal(node: Node) {\n const goalDist = distance(node, this.B)\n return 1 - Math.exp((-goalDist / this.straightLineDistance) * 5)\n }\n\n getFutureConnectionPenalty(node: Node, isVia: boolean) {\n let futureConnectionPenalty = 0\n const closestFuturePoint = this.getClosestFutureConnectionPoint(node)\n const goalDist = distance(node, this.B)\n if (closestFuturePoint) {\n const distToFuturePoint = distance(node, closestFuturePoint)\n if (goalDist <= distToFuturePoint) return 0\n const maxDist = this.viaDiameter * this.FUTURE_CONNECTION_PROXIMITY_VD\n const distRatio = distToFuturePoint / maxDist\n const maxPenalty = isVia\n ? this.straightLineDistance *\n this.FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR\n : this.straightLineDistance *\n this.FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR\n futureConnectionPenalty = maxPenalty * Math.exp(-distRatio * 5)\n }\n return futureConnectionPenalty\n }\n\n computeH(node: Node) {\n const goalDist = distance(node, this.B) ** 1.6\n const goalDistRatio = goalDist / this.straightLineDistance\n\n // Base cost from original function\n const baseCost =\n goalDist + (node.z !== this.B.z ? this.viaPenaltyDistance : 0)\n\n return (\n baseCost +\n this.getFutureConnectionPenalty(node, node.z !== node.parent?.z)\n )\n }\n\n computeG(node: Node) {\n const dx = Math.abs(node.x - node.parent!.x)\n const dy = Math.abs(node.y - node.parent!.y)\n const dist = Math.sqrt(dx ** 2 + dy ** 2)\n\n const misalignedDist = !this.FLIP_TRACE_ALIGNMENT_DIRECTION\n ? node.z === 0\n ? dy\n : dx\n : node.z === 0\n ? dx\n : dy\n\n // Base cost from original function\n const baseCost =\n (node.parent?.g ?? 0) +\n (node.z === node.parent?.z ? 0 : this.viaPenaltyDistance) +\n dist +\n misalignedDist * this.MISALIGNED_DIST_PENALTY_FACTOR\n\n return (\n baseCost +\n this.getFutureConnectionPenalty(node, node.z !== node.parent?.z)\n )\n }\n}\n","export function seededRandom(seed: number) {\n // Use a simple hash to initialize both state variables\n let s = seed\n for (let i = 0; i < 10; i++) {\n s = (s * 16807) % 2147483647\n }\n let state0 = s\n\n // Use a different hash for the second state\n s = (seed * 69069 + 1) % 2147483647\n for (let i = 0; i < 10; i++) {\n s = (s * 48271) % 2147483647\n }\n let state1 = s\n\n // Return the function that generates random numbers\n return () => {\n // xorshift128+ algorithm produces much better randomness than LCG\n let s1 = state0\n const s0 = state1\n\n state0 = s0\n s1 ^= s1 << 23\n s1 ^= s1 >>> 17\n s1 ^= s0\n s1 ^= s0 >>> 26\n state1 = s1\n\n // Generate a number between 0 and 1\n const result = (state0 + state1) / 4294967296\n return result - Math.floor(result)\n }\n}\n\nexport function cloneAndShuffleArray<T>(arr: T[], seed: number): T[] {\n if (seed === 0) return arr\n const random = seededRandom(seed)\n // if (arr.length === 2) {\n // console.log(random(), seed)\n // if (random() > 0.5) return arr.slice()\n // return [arr[1], arr[0]]\n // }\n const shuffled = arr.slice() // Copy the array\n for (let i = 0; i < shuffled.length; i++) {\n const i1 = Math.floor(random() * shuffled.length)\n const i2 = Math.floor(random() * (i + 1))\n ;[shuffled[i1], shuffled[i2]] = [shuffled[i2], shuffled[i1]]\n }\n return shuffled\n}\n","import { NodeWithPortPoints } from \"lib/types/high-density-types\"\n\nexport function getBoundsFromNodeWithPortPoints(\n nodeWithPortPoints: NodeWithPortPoints,\n): { minX: number; maxX: number; minY: number; maxY: number } {\n const bounds = {\n minX: nodeWithPortPoints.center.x - nodeWithPortPoints.width / 2,\n maxX: nodeWithPortPoints.center.x + nodeWithPortPoints.width / 2,\n minY: nodeWithPortPoints.center.y - nodeWithPortPoints.height / 2,\n maxY: nodeWithPortPoints.center.y + nodeWithPortPoints.height / 2,\n }\n\n // Sometimes port points may be outside the node- this happens when there's\n // a \"leap\" to the final target or at the end or beginning of a trace when\n // we're wrapping up\n for (const pt of nodeWithPortPoints.portPoints) {\n if (pt.x < bounds.minX) {\n bounds.minX = pt.x\n }\n if (pt.x > bounds.maxX) {\n bounds.maxX = pt.x\n }\n if (pt.y < bounds.minY) {\n bounds.minY = pt.y\n }\n if (pt.y > bounds.maxY) {\n bounds.maxY = pt.y\n }\n }\n\n return bounds\n}\n","import { NodeWithPortPoints } from \"lib/types/high-density-types\"\n\nexport const getMinDistBetweenEnteringPoints = (node: NodeWithPortPoints) => {\n let minDist = Infinity\n const points = node.portPoints\n\n // Compare each point with every other point\n for (let i = 0; i < points.length; i++) {\n for (let j = i + 1; j < points.length; j++) {\n if (points[i].z !== points[j].z) {\n continue\n }\n const p1 = points[i]\n const p2 = points[j]\n\n // Calculate Euclidean distance between points\n const dist = Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2)\n\n minDist = Math.min(minDist, dist)\n }\n }\n\n return minDist === Infinity ? 0 : minDist\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport type {\n HighDensityIntraNodeRoute,\n NodeWithPortPoints,\n} from \"../../types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { SingleHighDensityRouteSolver } from \"./SingleHighDensityRouteSolver\"\nimport { safeTransparentize } from \"../colors\"\nimport { SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost } from \"./SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost\"\nimport { HighDensityHyperParameters } from \"./HighDensityHyperParameters\"\nimport { cloneAndShuffleArray } from \"lib/utils/cloneAndShuffleArray\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport { getBoundsFromNodeWithPortPoints } from \"lib/utils/getBoundsFromNodeWithPortPoints\"\nimport { getMinDistBetweenEnteringPoints } from \"lib/utils/getMinDistBetweenEnteringPoints\"\n\nexport class IntraNodeRouteSolver extends BaseSolver {\n nodeWithPortPoints: NodeWithPortPoints\n colorMap: Record<string, string>\n unsolvedConnections: {\n connectionName: string\n points: { x: number; y: number; z: number }[]\n }[]\n\n totalConnections: number\n solvedRoutes: HighDensityIntraNodeRoute[]\n failedSubSolvers: SingleHighDensityRouteSolver[]\n hyperParameters: Partial<HighDensityHyperParameters>\n minDistBetweenEnteringPoints: number\n\n activeSubSolver: SingleHighDensityRouteSolver | null = null\n connMap?: ConnectivityMap\n\n // Legacy compat\n get failedSolvers() {\n return this.failedSubSolvers\n }\n\n // Legacy compat\n get activeSolver() {\n return this.activeSubSolver\n }\n\n constructor(params: {\n nodeWithPortPoints: NodeWithPortPoints\n colorMap?: Record<string, string>\n hyperParameters?: Partial<HighDensityHyperParameters>\n connMap?: ConnectivityMap\n }) {\n const { nodeWithPortPoints, colorMap } = params\n super()\n this.nodeWithPortPoints = nodeWithPortPoints\n this.colorMap = colorMap ?? {}\n this.solvedRoutes = []\n this.hyperParameters = params.hyperParameters ?? {}\n this.failedSubSolvers = []\n this.connMap = params.connMap\n const unsolvedConnectionsMap: Map<\n string,\n { x: number; y: number; z: number }[]\n > = new Map()\n for (const { connectionName, x, y, z } of nodeWithPortPoints.portPoints) {\n unsolvedConnectionsMap.set(connectionName, [\n ...(unsolvedConnectionsMap.get(connectionName) ?? []),\n { x, y, z: z ?? 0 },\n ])\n }\n this.unsolvedConnections = Array.from(\n unsolvedConnectionsMap.entries().map(([connectionName, points]) => ({\n connectionName,\n points,\n })),\n )\n\n if (this.hyperParameters.SHUFFLE_SEED) {\n this.unsolvedConnections = cloneAndShuffleArray(\n this.unsolvedConnections,\n this.hyperParameters.SHUFFLE_SEED ?? 0,\n )\n\n // Shuffle the starting and ending points of each connection (some\n // algorithms are biased towards the start or end of a trace)\n this.unsolvedConnections = this.unsolvedConnections.map(\n ({ points, ...rest }, i) => ({\n ...rest,\n points: cloneAndShuffleArray(\n points,\n i * 7117 + (this.hyperParameters.SHUFFLE_SEED ?? 0),\n ),\n }),\n )\n }\n\n this.totalConnections = this.unsolvedConnections.length\n this.MAX_ITERATIONS = 1_000 * this.totalConnections ** 1.5\n\n this.minDistBetweenEnteringPoints = getMinDistBetweenEnteringPoints(\n this.nodeWithPortPoints,\n )\n\n // const {\n // numEntryExitLayerChanges,\n // numSameLayerCrossings,\n // numTransitionPairCrossings,\n // numTransitions,\n // } = getIntraNodeCrossings(this.nodeWithPortPoints)\n\n // if (this.nodeWithPortPoints.portPoints.length === 4) {\n\n // }\n\n // if (\n // numSameLayerCrossings === 0 &&\n // numTransitions === 0 &&\n // numEntryExitLayerChanges === 0\n // ) {\n // this.handleSimpleNoCrossingsCase()\n // }\n }\n\n // handleSimpleNoCrossingsCase() {\n // // TODO check to make sure there are no crossings due to trace width\n // this.solved = true\n // this.solvedRoutes = this.unsolvedConnections.map(\n // ({ connectionName, points }) => ({\n // connectionName,\n // route: points,\n // traceThickness: 0.1, // TODO load from hyperParameters\n // viaDiameter: 0.6,\n // vias: [],\n // }),\n // )\n // this.unsolvedConnections = []\n // }\n\n computeProgress() {\n return (\n (this.solvedRoutes.length + (this.activeSubSolver?.progress || 0)) /\n this.totalConnections\n )\n }\n\n _step() {\n if (this.activeSubSolver) {\n this.activeSubSolver.step()\n this.progress = this.computeProgress()\n if (this.activeSubSolver.solved) {\n this.solvedRoutes.push(this.activeSubSolver.solvedPath!)\n this.activeSubSolver = null\n } else if (this.activeSubSolver.failed) {\n this.failedSubSolvers.push(this.activeSubSolver)\n this.activeSubSolver = null\n this.error = this.failedSubSolvers.map((s) => s.error).join(\"\\n\")\n this.failed = true\n }\n return\n }\n\n const unsolvedConnection = this.unsolvedConnections.pop()\n this.progress = this.computeProgress()\n if (!unsolvedConnection) {\n this.solved = this.failedSubSolvers.length === 0\n return\n }\n if (unsolvedConnection.points.length === 1) {\n return\n }\n if (unsolvedConnection.points.length === 2) {\n const [A, B] = unsolvedConnection.points\n if (A.x === B.x && A.y === B.y && A.z === B.z) {\n return\n }\n }\n const { connectionName, points } = unsolvedConnection\n this.activeSubSolver =\n new SingleHighDensityRouteSolver6_VertHorzLayer_FutureCost({\n connectionName,\n minDistBetweenEnteringPoints: this.minDistBetweenEnteringPoints,\n bounds: getBoundsFromNodeWithPortPoints(this.nodeWithPortPoints),\n A: { x: points[0].x, y: points[0].y, z: points[0].z },\n B: {\n x: points[points.length - 1].x,\n y: points[points.length - 1].y,\n z: points[points.length - 1].z,\n },\n obstacleRoutes: this.solvedRoutes,\n futureConnections: this.unsolvedConnections,\n layerCount: 2,\n hyperParameters: this.hyperParameters,\n connMap: this.connMap,\n })\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n\n // Draw node bounds\n // graphics.rects!.push({\n // center: {\n // x: this.nodeWithPortPoints.center.x,\n // y: this.nodeWithPortPoints.center.y,\n // },\n // width: this.nodeWithPortPoints.width,\n // height: this.nodeWithPortPoints.height,\n // stroke: \"gray\",\n // fill: \"transparent\",\n // })\n\n // Visualize input nodeWithPortPoints\n for (const pt of this.nodeWithPortPoints.portPoints) {\n graphics.points!.push({\n x: pt.x,\n y: pt.y,\n label: [pt.connectionName, `layer: ${pt.z}`].join(\"\\n\"),\n color: this.colorMap[pt.connectionName] ?? \"blue\",\n })\n }\n\n // Visualize solvedRoutes\n for (\n let routeIndex = 0;\n routeIndex < this.solvedRoutes.length;\n routeIndex++\n ) {\n const route = this.solvedRoutes[routeIndex]\n if (route.route.length > 0) {\n const routeColor = this.colorMap[route.connectionName] ?? \"blue\"\n\n // Draw route segments between points\n for (let i = 0; i < route.route.length - 1; i++) {\n const p1 = route.route[i]\n const p2 = route.route[i + 1]\n\n graphics.lines!.push({\n points: [p1, p2],\n strokeColor:\n p1.z === 0\n ? safeTransparentize(routeColor, 0.2)\n : safeTransparentize(routeColor, 0.8),\n layer: `route-layer-${p1.z}`,\n step: routeIndex,\n strokeWidth: route.traceThickness,\n })\n }\n\n // Draw vias\n for (const via of route.vias) {\n graphics.circles!.push({\n center: { x: via.x, y: via.y },\n radius: route.viaDiameter / 2,\n fill: safeTransparentize(routeColor, 0.5),\n layer: \"via\",\n step: routeIndex,\n })\n }\n }\n }\n\n // Draw border around the node\n const bounds = getBoundsFromNodeWithPortPoints(this.nodeWithPortPoints)\n const { minX, minY, maxX, maxY } = bounds\n\n // Draw the four sides of the border with thin red lines\n graphics.lines!.push({\n points: [\n { x: minX, y: minY },\n { x: maxX, y: minY },\n { x: maxX, y: maxY },\n { x: minX, y: maxY },\n { x: minX, y: minY },\n ],\n strokeColor: \"rgba(255, 0, 0, 0.25)\",\n strokeDash: \"4 4\",\n layer: \"border\",\n })\n\n return graphics\n }\n}\n","import { GraphicsObject } from \"graphics-debug\"\nimport { BaseSolver } from \"./BaseSolver\"\n\nexport type SupervisedSolver<T extends BaseSolver> = {\n hyperParameters: any\n solver: T\n h: number\n g: number\n f: number\n}\n\nexport type HyperParameterDef = {\n name: string\n possibleValues: Array<any>\n}\n\n/**\n * The HyperParameterSupervisorSolver is a solver that solves a problem by\n * running competing solvers with different hyperparameters.\n *\n * As solvers make progress, the supervisor will allow the best solvers to run\n * for more iterations, prioritizing the solvers that are working the best.\n */\nexport class HyperParameterSupervisorSolver<\n T extends BaseSolver,\n> extends BaseSolver {\n GREEDY_MULTIPLIER = 1.2\n MIN_SUBSTEPS = 1\n\n supervisedSolvers?: Array<SupervisedSolver<T>>\n\n getHyperParameterDefs(): Array<HyperParameterDef> {\n throw new Error(\"Not implemented\")\n }\n\n getCombinationDefs(): Array<Array<string>> | null {\n return null\n }\n\n getHyperParameterCombinations(\n hyperParameterDefs?: Array<HyperParameterDef>,\n ): Array<Record<string, any>> {\n if (!hyperParameterDefs) {\n hyperParameterDefs = this.getHyperParameterDefs()\n }\n const combinations: Array<Record<string, any>> = []\n // Base case - no more hyperparameters to combine\n if (hyperParameterDefs.length === 0) {\n return [{}]\n }\n\n // Take first hyperparameter definition\n const [currentDef, ...remainingDefs] = hyperParameterDefs\n\n // Get combinations for remaining hyperparameters\n const subCombinations = this.getHyperParameterCombinations(remainingDefs)\n\n // For each possible value of current hyperparameter,\n // combine with all sub-combinations\n currentDef.possibleValues.forEach((value) => {\n subCombinations.forEach((subCombo) => {\n combinations.push({\n ...subCombo,\n ...value,\n })\n })\n })\n\n return combinations\n }\n\n initializeSolvers() {\n const hyperParameterDefs = this.getHyperParameterDefs()\n\n const combinationDefs = this.getCombinationDefs() ?? [\n hyperParameterDefs.map((def) => def.name),\n ]\n\n this.supervisedSolvers = []\n for (const combinationDef of combinationDefs) {\n const hyperParameterCombinations = this.getHyperParameterCombinations(\n hyperParameterDefs.filter((hpd) => combinationDef.includes(hpd.name)),\n )\n\n for (const hyperParameters of hyperParameterCombinations) {\n const solver = this.generateSolver(hyperParameters)\n this.supervisedSolvers.push({\n hyperParameters,\n solver,\n h: 0,\n g: 0,\n f: 0,\n })\n }\n }\n }\n\n generateSolver(hyperParameters: any): T {\n throw new Error(\"Not implemented\")\n }\n\n computeG(solver: T) {\n return solver.iterations / solver.MAX_ITERATIONS\n }\n\n computeH(solver: T) {\n return 1 - (solver.progress || 0)\n }\n\n computeF(g: number, h: number) {\n return g + h * this.GREEDY_MULTIPLIER\n }\n\n getSupervisedSolverWithBestFitness(): SupervisedSolver<T> | null {\n let bestFitness = Infinity\n let bestSolver: SupervisedSolver<T> | null = null\n for (const supervisedSolver of this.supervisedSolvers ?? []) {\n if (supervisedSolver.solver.solved) {\n return supervisedSolver\n }\n if (supervisedSolver.solver.failed) {\n continue\n }\n const fitness = supervisedSolver.f\n if (fitness < bestFitness) {\n bestFitness = fitness\n bestSolver = supervisedSolver\n }\n }\n return bestSolver\n }\n\n _step() {\n if (!this.supervisedSolvers) this.initializeSolvers()\n\n const supervisedSolver = this.getSupervisedSolverWithBestFitness()\n\n if (!supervisedSolver) {\n this.failed = true\n this.error = \"All solvers failed\"\n return\n }\n\n for (let i = 0; i < this.MIN_SUBSTEPS; i++) {\n supervisedSolver.solver.step()\n }\n\n supervisedSolver.g = this.computeG(supervisedSolver.solver)\n supervisedSolver.h = this.computeH(supervisedSolver.solver)\n supervisedSolver.f = this.computeF(supervisedSolver.g, supervisedSolver.h)\n\n if (supervisedSolver.solver.solved) {\n this.solved = true\n this.onSolve?.(supervisedSolver)\n }\n }\n\n onSolve(solver: SupervisedSolver<T>) {}\n\n visualize(): GraphicsObject {\n const bestSupervisedSolver = this.getSupervisedSolverWithBestFitness()\n let graphics: GraphicsObject = {\n lines: [],\n circles: [],\n points: [],\n rects: [],\n }\n\n if (bestSupervisedSolver) {\n graphics = bestSupervisedSolver.solver.visualize()\n }\n return graphics\n }\n}\n","interface Point {\n x: number\n y: number\n}\n\nexport const findCircleLineIntersections = (\n circle: Point & { r: number },\n line: { p1: Point; p2: Point },\n) => {\n const cx = circle.x\n const cy = circle.y\n const r = circle.r\n\n const x1 = line.p1.x\n const y1 = line.p1.y\n const x2 = line.p2.x\n const y2 = line.p2.y\n\n // Check if line is vertical\n if (Math.abs(x2 - x1) < 0.001) {\n const x = x1\n\n // Calculate discriminant\n const a = r * r - (x - cx) ** 2\n\n if (a < 0) return [] // No intersection\n\n if (Math.abs(a) < 0.001) {\n // One intersection\n const y = cy\n // Check if this point is within the line segment\n if (y >= Math.min(y1, y2) && y <= Math.max(y1, y2)) {\n return [{ x, y }]\n }\n return []\n }\n\n // Two intersections\n const y_1 = cy + Math.sqrt(a)\n const y_2 = cy - Math.sqrt(a)\n\n const points: Point[] = []\n if (y_1 >= Math.min(y1, y2) && y_1 <= Math.max(y1, y2)) {\n points.push({ x, y: y_1 })\n }\n if (y_2 >= Math.min(y1, y2) && y_2 <= Math.max(y1, y2)) {\n points.push({ x, y: y_2 })\n }\n\n return points\n }\n\n // Line is not vertical\n const m = (y2 - y1) / (x2 - x1)\n const b = y1 - m * x1\n\n // Substitute line equation into circle equation\n const A = 1 + m * m\n const B = 2 * (m * b - m * cy - cx)\n const C = cx * cx + (b - cy) * (b - cy) - r * r\n\n // Calculate discriminant\n const discriminant = B * B - 4 * A * C\n\n if (discriminant < 0) return [] // No intersection\n\n if (Math.abs(discriminant) < 0.001) {\n // One intersection\n const x = -B / (2 * A)\n const y = m * x + b\n\n // Check if this point is within the line segment\n if (\n x >= Math.min(x1, x2) &&\n x <= Math.max(x1, x2) &&\n y >= Math.min(y1, y2) &&\n y <= Math.max(y1, y2)\n ) {\n return [{ x, y }]\n }\n return []\n }\n\n // Two intersections\n const x_1 = (-B + Math.sqrt(discriminant)) / (2 * A)\n const x_2 = (-B - Math.sqrt(discriminant)) / (2 * A)\n const y_1 = m * x_1 + b\n const y_2 = m * x_2 + b\n\n const points: Point[] = []\n if (\n x_1 >= Math.min(x1, x2) &&\n x_1 <= Math.max(x1, x2) &&\n y_1 >= Math.min(y1, y2) &&\n y_1 <= Math.max(y1, y2)\n ) {\n points.push({ x: x_1, y: y_1 })\n }\n if (\n x_2 >= Math.min(x1, x2) &&\n x_2 <= Math.max(x1, x2) &&\n y_2 >= Math.min(y1, y2) &&\n y_2 <= Math.max(y1, y2)\n ) {\n points.push({ x: x_2, y: y_2 })\n }\n\n return points\n}\n","import { BaseSolver } from \"lib/solvers/BaseSolver\"\nimport {\n NodeWithPortPoints,\n HighDensityIntraNodeRoute,\n} from \"lib/types/high-density-types\"\nimport {\n distance,\n pointToSegmentDistance,\n doSegmentsIntersect,\n} from \"@tscircuit/math-utils\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { getIntraNodeCrossings } from \"lib/utils/getIntraNodeCrossings\"\nimport { findCircleLineIntersections } from \"./findCircleLineIntersections\"\n\ntype Point = { x: number; y: number; z?: number }\ntype Route = {\n startPort: Point\n endPort: Point\n connectionName: string\n}\n\nexport class TwoCrossingRoutesHighDensitySolver extends BaseSolver {\n // Input parameters\n nodeWithPortPoints: NodeWithPortPoints\n routes: Route[]\n\n // Configuration parameters\n viaDiameter: number\n traceThickness: number\n obstacleMargin: number\n layerCount: number = 2\n\n debugViaPositions: {\n via1: Point\n via2: Point\n }[]\n\n // Solution state\n solvedRoutes: HighDensityIntraNodeRoute[] = []\n\n // Bounds\n bounds: { minX: number; maxX: number; minY: number; maxY: number }\n\n constructor(params: {\n nodeWithPortPoints: NodeWithPortPoints\n viaDiameter?: number\n traceThickness?: number\n obstacleMargin?: number\n layerCount?: number\n }) {\n super()\n\n this.nodeWithPortPoints = params.nodeWithPortPoints\n this.viaDiameter = params?.viaDiameter ?? 0.6\n this.traceThickness = params?.traceThickness ?? 0.15\n this.obstacleMargin = params?.obstacleMargin ?? 0.1\n this.layerCount = params?.layerCount ?? 2\n this.debugViaPositions = []\n\n // Extract routes from the node data\n this.routes = this.extractRoutesFromNode()\n\n // Calculate bounds\n this.bounds = this.calculateBounds()\n\n if (this.routes.length !== 2) {\n this.failed = true\n return\n }\n\n const [routeA, routeB] = this.routes\n const routeAStartsAndEndsOnSameLayer =\n routeA.startPort.z === routeA.endPort.z\n if (!routeAStartsAndEndsOnSameLayer) {\n this.failed = true\n return\n }\n\n const routeBStartsAndEndsOnSameLayer =\n routeB.startPort.z === routeB.endPort.z\n if (!routeBStartsAndEndsOnSameLayer) {\n this.failed = true\n return\n }\n\n const routesAreSameLayer = routeA.startPort.z === routeB.startPort.z\n if (!routesAreSameLayer) {\n this.failed = true\n return\n }\n\n // TODO check to make sure the lines cross\n }\n\n /**\n * Extract routes that need to be connected from the node data\n */\n private extractRoutesFromNode(): Route[] {\n const routes: Route[] = []\n const connectedPorts = this.nodeWithPortPoints.portPoints!\n\n // Group ports by connection name\n const connectionGroups = new Map<string, Point[]>()\n\n for (const connectedPort of connectedPorts) {\n const { connectionName } = connectedPort\n if (!connectionGroups.has(connectionName)) {\n connectionGroups.set(connectionName, [])\n }\n connectionGroups.get(connectionName)?.push(connectedPort)\n }\n\n // Create routes for each connection (assuming each connection has exactly 2 points)\n for (const [connectionName, points] of connectionGroups.entries()) {\n if (points.length === 2) {\n routes.push({\n startPort: { ...points[0], z: points[0].z ?? 0 },\n endPort: { ...points[1], z: points[1].z ?? 0 },\n connectionName,\n })\n }\n }\n\n return routes\n }\n\n /**\n * Calculate the bounding box of the node\n */\n private calculateBounds() {\n return {\n minX:\n this.nodeWithPortPoints.center.x - this.nodeWithPortPoints.width / 2,\n maxX:\n this.nodeWithPortPoints.center.x + this.nodeWithPortPoints.width / 2,\n minY:\n this.nodeWithPortPoints.center.y - this.nodeWithPortPoints.height / 2,\n maxY:\n this.nodeWithPortPoints.center.y + this.nodeWithPortPoints.height / 2,\n }\n }\n\n /**\n * Check if two routes are crossing\n */\n private doRoutesCross(routeA: Route, routeB: Route): boolean {\n return doSegmentsIntersect(\n routeA.startPort,\n routeA.endPort,\n routeB.startPort,\n routeB.endPort,\n )\n }\n\n private calculateViaPositions(\n routeA: Route,\n routeB: Route,\n ): {\n via1: Point\n via2: Point\n } | null {\n // Define outer box as the bounds where all points lie\n const outerBox = {\n width: this.bounds.maxX - this.bounds.minX,\n height: this.bounds.maxY - this.bounds.minY,\n x: this.bounds.minX,\n y: this.bounds.minY,\n }\n\n // Define inner box with padding of obstacleMargin\n const innerBox = {\n width: outerBox.width - 2 * this.obstacleMargin - this.viaDiameter,\n height: outerBox.height - 2 * this.obstacleMargin - this.viaDiameter,\n x: outerBox.x + this.obstacleMargin + this.viaDiameter / 2,\n y: outerBox.y + this.obstacleMargin + this.viaDiameter / 2,\n }\n\n // Define the K1 parameter (minimum distance from A/B to C/D)\n // We'll use viaDiameter + obstacleMargin as the minimum distance\n const K1 = this.viaDiameter + this.obstacleMargin\n\n // Get points A and B from the routeB\n const pointA = routeB.startPort\n const pointB = routeB.endPort\n\n // Get the inner box corners\n const corners = [\n { x: innerBox.x, y: innerBox.y }, // Top-left (0)\n { x: innerBox.x + innerBox.width, y: innerBox.y }, // Top-right (1)\n { x: innerBox.x + innerBox.width, y: innerBox.y + innerBox.height }, // Bottom-right (2)\n { x: innerBox.x, y: innerBox.y + innerBox.height }, // Bottom-left (3)\n ]\n\n // Calculate distance between two points\n const distanceBetween = (p1: Point, p2: Point): number => {\n return distance(p1, p2)\n }\n\n // Find all valid candidate points\n const candidatePoints: Array<\n Point & { type: string; index?: number; circle?: number; edge?: number }\n > = []\n\n // 1. First check which corners are valid (outside both K1 circles)\n corners.forEach((corner, index) => {\n if (\n distanceBetween(corner, pointA) >= K1 &&\n distanceBetween(corner, pointB) >= K1\n ) {\n candidatePoints.push({ ...corner, type: \"corner\", index })\n }\n })\n\n // 2. Find intersections of K1 circles with the inner box edges\n // Define the 4 edges of the inner box\n const edges = [\n { p1: corners[0], p2: corners[1] }, // top\n { p1: corners[1], p2: corners[2] }, // right\n { p1: corners[2], p2: corners[3] }, // bottom\n { p1: corners[3], p2: corners[0] }, // left\n ]\n\n // Find intersections for both circles with all edges\n ;[pointA, pointB].forEach((circleCenter, circleIndex) => {\n edges.forEach((edge, edgeIndex) => {\n const intersections = findCircleLineIntersections(\n { ...circleCenter, r: K1 },\n edge,\n )\n\n // For each intersection, check if it's also outside the other circle\n intersections.forEach((point) => {\n const otherCircle = circleIndex === 0 ? pointB : pointA\n if (distanceBetween(point, otherCircle) >= K1) {\n candidatePoints.push({\n ...point,\n type: \"intersection\",\n circle: circleIndex,\n edge: edgeIndex,\n })\n }\n })\n })\n })\n\n // If we have fewer than 2 candidate points, relax the constraints\n if (candidatePoints.length < 2) {\n // Try with smaller K1\n const relaxedK1 = K1 * 0.8 // Reduce by 20%\n corners.forEach((corner, index) => {\n if (\n distanceBetween(corner, pointA) >= relaxedK1 &&\n distanceBetween(corner, pointB) >= relaxedK1 &&\n !candidatePoints.some((p) => p.x === corner.x && p.y === corner.y)\n ) {\n candidatePoints.push({ ...corner, type: \"relaxed_corner\", index })\n }\n })\n\n // If still not enough, add corners sorted by distance\n if (candidatePoints.length < 2) {\n // Sort corners by their distance from A and B\n const sortedCorners = [...corners].sort((a, b) => {\n const aMinDist = Math.min(\n distanceBetween(a, pointA),\n distanceBetween(a, pointB),\n )\n const bMinDist = Math.min(\n distanceBetween(b, pointA),\n distanceBetween(b, pointB),\n )\n return bMinDist - aMinDist // Larger distances first\n })\n\n // Add corners not already in candidatePoints\n for (const corner of sortedCorners) {\n if (\n !candidatePoints.some((p) => p.x === corner.x && p.y === corner.y)\n ) {\n candidatePoints.push({ ...corner, type: \"forced_corner\" })\n if (candidatePoints.length >= 2) break\n }\n }\n }\n }\n\n // If still fewer than 2 candidates, return null\n if (candidatePoints.length < 2) {\n return null\n }\n\n // Find the pair of points with maximum distance between them\n let maxDist = 0\n let optimalPair = [\n candidatePoints[0],\n candidatePoints[candidatePoints.length > 1 ? 1 : 0],\n ]\n\n for (let i = 0; i < candidatePoints.length; i++) {\n for (let j = i + 1; j < candidatePoints.length; j++) {\n const dist = distanceBetween(candidatePoints[i], candidatePoints[j])\n if (dist > maxDist) {\n maxDist = dist\n optimalPair = [candidatePoints[i], candidatePoints[j]]\n }\n }\n }\n\n let via1 = { x: optimalPair[0].x, y: optimalPair[0].y }\n let via2 = { x: optimalPair[1].x, y: optimalPair[1].y }\n\n const via1DistToStart = distance(via1, routeA.startPort)\n const via2DistToStart = distance(via2, routeA.startPort)\n\n if (via2DistToStart < via1DistToStart) {\n ;[via1, via2] = [via2, via1]\n }\n\n return {\n via1,\n via2,\n }\n }\n\n /**\n * Create a route with properly placed vias\n */\n private createRoute(\n start: Point,\n end: Point,\n via1: Point,\n via2: Point,\n connectionName: string,\n ): HighDensityIntraNodeRoute {\n const middleZ = start.z === 0 ? 1 : 0\n\n // Create the route path with layer transitions\n const route = [\n { x: start.x, y: start.y, z: start.z ?? 0 },\n { x: via1.x, y: via1.y, z: start.z ?? 0 },\n { x: via1.x, y: via1.y, z: middleZ }, // Via transition to layer 1\n { x: via2.x, y: via2.y, z: middleZ }, // Stay on layer 1\n { x: via2.x, y: via2.y, z: end.z ?? 0 }, // Via transition back\n { x: end.x, y: end.y, z: end.z ?? 0 },\n ]\n\n return {\n connectionName,\n route,\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [via1, via2],\n }\n }\n\n /**\n * Try to solve with routeA going over and routeB staying on layer 0\n */\n private trySolveAOverB(routeA: Route, routeB: Route): boolean {\n const viaPositions = this.calculateViaPositions(routeA, routeB)\n if (viaPositions) {\n this.debugViaPositions.push(viaPositions)\n } else {\n return false\n }\n\n const { via1, via2 } = this.optimizeViaPositions(viaPositions)\n\n // if (\n // distance(via1, via2) <\n // this.viaDiameter + this.traceThickness + this.obstacleMargin * 2\n // ) {\n // return false\n // }\n\n // Create route for A that goes over B using vias\n const routeASolution = this.createRoute(\n routeA.startPort,\n routeA.endPort,\n via1,\n via2,\n routeA.connectionName,\n )\n\n // Calculate orthogonal line through the middle segment of route A\n const midSegmentStart = { x: via1.x, y: via1.y, z: 1 }\n const midSegmentEnd = { x: via2.x, y: via2.y, z: 1 }\n\n // Calculate the orthogonal points for route B\n const orthogonalPoints =\n this.calculateShortestOrthogonalRoutePoints(\n routeB.startPort,\n routeB.endPort,\n midSegmentStart,\n midSegmentEnd,\n routeA.startPort,\n routeA.endPort,\n ) ??\n this.calculateConservativeOrthogonalRoutePoints(\n routeB.startPort,\n routeB.endPort,\n midSegmentStart,\n midSegmentEnd,\n routeA.startPort,\n routeA.endPort,\n )\n\n // Create route for B that navigates around the vias\n const routeBSolution: HighDensityIntraNodeRoute = {\n connectionName: routeB.connectionName,\n route: orthogonalPoints as any,\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [],\n }\n\n this.solvedRoutes.push(routeASolution, routeBSolution)\n return true\n }\n\n private optimizeViaPositions(viaPositions: { via1: Point; via2: Point }): {\n via1: Point\n via2: Point\n } {\n const { via1, via2 } = viaPositions\n\n // Calculate the minimum required distance between vias\n const minRequiredDistance =\n (this.viaDiameter + this.traceThickness + this.obstacleMargin) * 2\n\n // Calculate current distance between vias\n const currentDistance = distance(via1, via2)\n\n // If vias are already closer than or equal to the minimum required distance, return as is\n if (currentDistance <= minRequiredDistance) {\n return viaPositions\n }\n\n // Calculate the direction vector from viaA to viaB\n const dirX = via2.x - via1.x\n const dirY = via2.y - via1.y\n\n // Normalize the direction vector\n const dirLength = Math.sqrt(dirX * dirX + dirY * dirY)\n const normDirX = dirX / dirLength\n const normDirY = dirY / dirLength\n\n // Calculate the midpoint of the current vias\n const midpointX = (via1.x + via2.x) / 2\n const midpointY = (via1.y + via2.y) / 2\n\n // Calculate new positions that are minRequiredDistance apart\n // Move each via half the distance towards the midpoint\n const moveDistance = (currentDistance - minRequiredDistance) / 2\n\n const newVia1 = {\n x: via1.x + normDirX * moveDistance,\n y: via1.y + normDirY * moveDistance,\n }\n\n const newVia2 = {\n x: via2.x - normDirX * moveDistance,\n y: via2.y - normDirY * moveDistance,\n }\n\n return {\n via1: newVia1,\n via2: newVia2,\n }\n }\n\n /**\n * Calculate the orthogonal route points for the second route\n */\n private calculateConservativeOrthogonalRoutePoints(\n start: Point,\n end: Point,\n via1: Point,\n via2: Point,\n otherRouteStart: Point,\n otherRouteEnd: Point,\n ): Point[] | null {\n // Define the inner edge box which is obstacleMargin away from outer box\n const outerBox = {\n width: this.bounds.maxX - this.bounds.minX,\n height: this.bounds.maxY - this.bounds.minY,\n x: this.bounds.minX,\n y: this.bounds.minY,\n }\n\n const innerEdgeBox = {\n width: outerBox.width - 2 * this.obstacleMargin - this.traceThickness,\n height: outerBox.height - 2 * this.obstacleMargin - this.traceThickness,\n x: outerBox.x + this.obstacleMargin + this.traceThickness / 2,\n y: outerBox.y + this.obstacleMargin + this.traceThickness / 2,\n }\n\n // Calculate the orthogonal line to the mid segment\n // First get the direction vector of mid segment\n const midSegmentDX = via2.x - via1.x\n const midSegmentDY = via2.y - via1.y\n\n // Calculate orthogonal vector (rotate by 90 degrees)\n const orthDX = -midSegmentDY\n const orthDY = midSegmentDX\n\n // Normalize the orthogonal vector\n const orthLength = Math.sqrt(orthDX * orthDX + orthDY * orthDY)\n const normOrthDX = orthDX / orthLength\n const normOrthDY = orthDY / orthLength\n\n // Calculate the midpoint of the mid segment\n const midpointX = (via1.x + via2.x) / 2\n const midpointY = (via1.y + via2.y) / 2\n\n // Calculate the orthogonal line that passes through the midpoint\n // Line equation: (x, y) = (midpointX, midpointY) + t * (normOrthDX, normOrthDY)\n\n // Function to calculate intersections with the innerEdgeBox\n const calculateIntersections = (): Point[] => {\n const intersections: Point[] = []\n\n // Check intersection with left edge\n const leftT = (innerEdgeBox.x - midpointX) / normOrthDX\n const leftY = midpointY + leftT * normOrthDY\n if (\n leftY >= innerEdgeBox.y &&\n leftY <= innerEdgeBox.y + innerEdgeBox.height\n ) {\n intersections.push({ x: innerEdgeBox.x, y: leftY })\n }\n\n // Check intersection with right edge\n const rightT =\n (innerEdgeBox.x + innerEdgeBox.width - midpointX) / normOrthDX\n const rightY = midpointY + rightT * normOrthDY\n if (\n rightY >= innerEdgeBox.y &&\n rightY <= innerEdgeBox.y + innerEdgeBox.height\n ) {\n intersections.push({\n x: innerEdgeBox.x + innerEdgeBox.width,\n y: rightY,\n })\n }\n\n // Check intersection with top edge\n const topT = (innerEdgeBox.y - midpointY) / normOrthDY\n const topX = midpointX + topT * normOrthDX\n if (\n topX >= innerEdgeBox.x &&\n topX <= innerEdgeBox.x + innerEdgeBox.width\n ) {\n intersections.push({ x: topX, y: innerEdgeBox.y })\n }\n\n // Check intersection with bottom edge\n const bottomT =\n (innerEdgeBox.y + innerEdgeBox.height - midpointY) / normOrthDY\n const bottomX = midpointX + bottomT * normOrthDX\n if (\n bottomX >= innerEdgeBox.x &&\n bottomX <= innerEdgeBox.x + innerEdgeBox.width\n ) {\n intersections.push({\n x: bottomX,\n y: innerEdgeBox.y + innerEdgeBox.height,\n })\n }\n\n return intersections\n }\n\n const intersections = calculateIntersections()\n\n // If we don't have at least 2 intersections, return direct route\n if (intersections.length < 2) {\n return [\n { x: start.x, y: start.y, z: start.z ?? 0 },\n { x: end.x, y: end.y, z: end.z ?? 0 },\n ]\n }\n\n // Sort intersections by distance from start point\n const sortedIntersections = [...intersections].sort((a, b) => {\n const distA = distance(a, start)\n const distB = distance(b, start)\n return distA - distB\n })\n\n // Choose the closest intersection to the start and the closest to the end\n let middlePoint1 = sortedIntersections[0]\n let middlePoint2 = sortedIntersections[intersections.length - 1]\n\n if (\n doSegmentsIntersect(start, middlePoint1, otherRouteStart, via1) ||\n doSegmentsIntersect(end, middlePoint2, otherRouteEnd, via2)\n ) {\n ;[middlePoint1, middlePoint2] = [middlePoint2, middlePoint1]\n }\n\n // Create the route with 4 points\n return [\n { x: start.x, y: start.y, z: start.z ?? 0 },\n { x: middlePoint1.x, y: middlePoint1.y, z: start.z ?? 0 },\n { x: middlePoint2.x, y: middlePoint2.y, z: start.z ?? 0 },\n { x: end.x, y: end.y, z: end.z ?? 0 },\n ]\n }\n\n private calculateShortestOrthogonalRoutePoints(\n start: Point,\n end: Point,\n via1: Point,\n via2: Point,\n otherRouteStart: Point,\n otherRouteEnd: Point,\n ): Point[] | null {\n const midSegmentCenter = {\n x: (via1.x + via2.x) / 2,\n y: (via1.y + via2.y) / 2,\n }\n\n const midSegmentDirection = {\n x: via2.x - via1.x,\n y: via2.y - via1.y,\n }\n\n const midSegmentLength = distance(via1, via2)\n const normOrthDX = midSegmentDirection.y / midSegmentLength\n const normOrthDY = midSegmentDirection.x / midSegmentLength\n\n // Travel orthogonal to the mid segment by the length of the mid segment to\n // get two points\n let orthogonalPoint1 = {\n x: midSegmentCenter.x + (midSegmentLength / 2) * normOrthDY,\n y: midSegmentCenter.y - (midSegmentLength / 2) * normOrthDX,\n }\n\n let orthogonalPoint2 = {\n x: midSegmentCenter.x - (midSegmentLength / 2) * normOrthDY,\n y: midSegmentCenter.y + (midSegmentLength / 2) * normOrthDX,\n }\n\n if (distance(orthogonalPoint2, start) < distance(orthogonalPoint1, start)) {\n ;[orthogonalPoint1, orthogonalPoint2] = [\n orthogonalPoint2,\n orthogonalPoint1,\n ]\n }\n\n // Make sure we're not too close to the other route, or the mid segment\n // start or end (which has vias)\n // TODO - i haven't done this because we need a good test case/fixture -seve\n\n if (\n doSegmentsIntersect(start, orthogonalPoint1, otherRouteStart, via1) ||\n doSegmentsIntersect(end, orthogonalPoint2, otherRouteEnd, via2)\n ) {\n ;[orthogonalPoint1, orthogonalPoint2] = [\n orthogonalPoint2,\n orthogonalPoint1,\n ]\n }\n\n if (\n doSegmentsIntersect(start, orthogonalPoint2, otherRouteStart, via1) ||\n doSegmentsIntersect(end, orthogonalPoint1, otherRouteEnd, via2)\n ) {\n return null\n }\n\n return [\n { x: start.x, y: start.y, z: start.z ?? 0 },\n { x: orthogonalPoint1.x, y: orthogonalPoint1.y, z: start.z ?? 0 },\n { x: orthogonalPoint2.x, y: orthogonalPoint2.y, z: start.z ?? 0 },\n { x: end.x, y: end.y, z: end.z ?? 0 },\n ]\n }\n\n /**\n * Main step method that attempts to solve the two crossing routes\n */\n _step() {\n // Check if we have exactly two routes\n if (this.routes.length !== 2) {\n this.failed = true\n return\n }\n\n const [routeA, routeB] = this.routes\n\n // Check if routes are actually crossing\n if (!this.doRoutesCross(routeA, routeB)) {\n // Routes don't cross, create simple direct connections\n const routeASolution: HighDensityIntraNodeRoute = {\n connectionName: routeA.connectionName,\n route: [\n {\n x: routeA.startPort.x,\n y: routeA.startPort.y,\n z: routeA.startPort.z ?? 0,\n },\n {\n x: routeA.endPort.x,\n y: routeA.endPort.y,\n z: routeA.endPort.z ?? 0,\n },\n ],\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [],\n }\n\n const routeBSolution: HighDensityIntraNodeRoute = {\n connectionName: routeB.connectionName,\n route: [\n {\n x: routeB.startPort.x,\n y: routeB.startPort.y,\n z: routeB.startPort.z ?? 0,\n },\n {\n x: routeB.endPort.x,\n y: routeB.endPort.y,\n z: routeB.endPort.z ?? 0,\n },\n ],\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [],\n }\n\n this.solvedRoutes.push(routeASolution, routeBSolution)\n this.solved = true\n return\n }\n\n // Try having route A go over route B\n if (this.trySolveAOverB(routeA, routeB)) {\n this.solved = true\n return\n }\n\n // If that fails, try having route B go over route A\n if (this.trySolveAOverB(routeB, routeA)) {\n this.solved = true\n return\n }\n\n // If both approaches fail, mark as failed\n this.failed = true\n }\n\n /**\n * Visualization for debugging\n */\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n\n // Draw PCB bounds\n graphics.rects!.push({\n center: {\n x: (this.bounds.minX + this.bounds.maxX) / 2,\n y: (this.bounds.minY + this.bounds.maxY) / 2,\n },\n width: this.bounds.maxX - this.bounds.minX,\n height: this.bounds.maxY - this.bounds.minY,\n stroke: \"rgba(0, 0, 0, 0.5)\",\n fill: \"rgba(240, 240, 240, 0.1)\",\n label: \"PCB Bounds\",\n })\n\n // Draw original routes\n for (const route of this.routes) {\n // Draw endpoints\n graphics.points!.push({\n x: route.startPort.x,\n y: route.startPort.y,\n label: `${route.connectionName} start`,\n color: \"orange\",\n })\n\n graphics.points!.push({\n x: route.endPort.x,\n y: route.endPort.y,\n label: `${route.connectionName} end`,\n color: \"orange\",\n })\n\n // Draw direct connection line\n graphics.lines!.push({\n points: [route.startPort, route.endPort],\n strokeColor: \"rgba(255, 0, 0, 0.5)\",\n label: `${route.connectionName} direct`,\n })\n }\n\n // Draw debug via positions (even if solution failed)\n for (let i = 0; i < this.debugViaPositions.length; i++) {\n const { via1, via2 } = this.debugViaPositions[i]\n\n // Draw computed vias (using different colors for different attempts)\n const colors = [\"rgba(255, 165, 0, 0.7)\", \"rgba(128, 0, 128, 0.7)\"] // orange, purple\n const color = colors[i % colors.length]\n\n graphics.circles!.push({\n center: via1,\n radius: this.viaDiameter / 2,\n fill: color,\n stroke: \"rgba(0, 0, 0, 0.5)\",\n label: `Computed Via A (attempt ${i + 1})`,\n })\n\n graphics.circles!.push({\n center: via2,\n radius: this.viaDiameter / 2,\n fill: color,\n stroke: \"rgba(0, 0, 0, 0.5)\",\n label: `Computed Via B (attempt ${i + 1})`,\n })\n\n // Draw safety margins around vias\n const safetyMargin = this.viaDiameter / 2 + this.obstacleMargin\n graphics.circles!.push({\n center: via1,\n radius: safetyMargin,\n stroke: color,\n fill: \"rgba(0, 0, 0, 0)\",\n label: \"Safety Margin\",\n })\n\n graphics.circles!.push({\n center: via2,\n radius: safetyMargin,\n stroke: color,\n fill: \"rgba(0, 0, 0, 0)\",\n label: \"Safety Margin\",\n })\n\n // Draw potential route through vias\n graphics.lines!.push({\n points: [\n this.routes[i % 2].startPort,\n via1,\n via2,\n this.routes[i % 2].endPort,\n ],\n strokeColor: `${color.substring(0, color.lastIndexOf(\",\"))}, 0.3)`,\n strokeDash: [5, 5],\n label: `Potential Route (attempt ${i + 1})`,\n })\n }\n\n // Draw solved routes if available\n for (let si = 0; si < this.solvedRoutes.length; si++) {\n const route = this.solvedRoutes[si]\n const routeColor =\n si % 2 === 0 ? \"rgba(0, 255, 0, 0.75)\" : \"rgba(255, 0, 255, 0.75)\"\n for (let i = 0; i < route.route.length - 1; i++) {\n const pointA = route.route[i]\n const pointB = route.route[i + 1]\n\n graphics.lines!.push({\n points: [pointA, pointB],\n strokeColor: routeColor,\n strokeDash: pointA.z === 1 ? [0.2, 0.2] : undefined,\n strokeWidth: route.traceThickness,\n label: `${route.connectionName} z=${pointA.z}`,\n })\n }\n\n // Draw vias in solved routes\n for (const via of route.vias) {\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2,\n fill: \"rgba(0, 0, 255, 0.8)\",\n stroke: \"black\",\n label: \"Solved Via\",\n })\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2 + this.obstacleMargin,\n fill: \"rgba(0, 0, 255, 0.3)\",\n stroke: \"black\",\n label: \"Via Margin\",\n })\n }\n }\n\n return graphics\n }\n\n /**\n * Get the solved routes\n */\n getSolvedRoutes(): HighDensityIntraNodeRoute[] {\n return this.solvedRoutes\n }\n}\n","interface Point {\n x: number\n y: number\n}\n\n/**\n * Finds the optimal position that is closest to the average of points A, B, and C,\n * while maintaining a minimum distance of radius from each point and staying within bounds.\n *\n * https://claude.ai/artifacts/b61d2619-0d39-45e7-b02b-ebdcb645f07e\n */\nexport function findClosestPointToABCWithinBounds(\n A: Point,\n B: Point,\n C: Point,\n radius: number,\n bounds: { minX: number; minY: number; maxX: number; maxY: number },\n) {\n // Calculate the average point (center of mass)\n const avgPoint = {\n x: (A.x + B.x + C.x) / 3,\n y: (A.y + B.y + C.y) / 3,\n }\n\n // Function to calculate distance between two points\n const distance = (p1: Point, p2: Point) => {\n return Math.sqrt((p2.x - p1.x) ** 2 + (p2.y - p1.y) ** 2)\n }\n\n // Function to check if a point satisfies all constraints\n const isValidPoint = (point: Point) => {\n // Check distance constraints\n const distToA = distance(point, A)\n const distToB = distance(point, B)\n const distToC = distance(point, C)\n\n // Check bounds constraints\n const withinBounds =\n point.x >= bounds.minX &&\n point.x <= bounds.maxX &&\n point.y >= bounds.minY &&\n point.y <= bounds.maxY\n\n return (\n distToA >= radius &&\n distToB >= radius &&\n distToC >= radius &&\n withinBounds\n )\n }\n\n // Function to check if a point is on the boundary\n const isOnBoundary = (point: Point) => {\n const epsilon = 1e-6\n return (\n Math.abs(point.x - bounds.minX) < epsilon ||\n Math.abs(point.x - bounds.maxX) < epsilon ||\n Math.abs(point.y - bounds.minY) < epsilon ||\n Math.abs(point.y - bounds.maxY) < epsilon\n )\n }\n\n // First check if average point satisfies all constraints\n if (isValidPoint(avgPoint)) {\n return avgPoint\n }\n\n // Next, check all the standard candidates based on circles and intersections\n const pointOnCircle = (center: Point, constraint: Point, r: number) => {\n const vx = center.x - constraint.x\n const vy = center.y - constraint.y\n const dist = Math.sqrt(vx * vx + vy * vy)\n\n if (dist < 1e-10) {\n return { x: constraint.x + r, y: constraint.y }\n }\n\n return {\n x: constraint.x + (vx / dist) * r,\n y: constraint.y + (vy / dist) * r,\n }\n }\n\n const findCircleIntersections = (c1: Point, c2: Point, r: number) => {\n const dx = c2.x - c1.x\n const dy = c2.y - c1.y\n const dist = Math.sqrt(dx * dx + dy * dy)\n\n if (dist > 2 * r - 1e-10 || dist < 1e-10) {\n return []\n }\n\n const a = (dist * dist) / (2 * dist)\n const h = Math.sqrt(Math.max(0, r * r - a * a))\n\n const midX = c1.x + (dx * a) / dist\n const midY = c1.y + (dy * a) / dist\n\n const intersection1 = {\n x: midX + (h * dy) / dist,\n y: midY - (h * dx) / dist,\n }\n\n const intersection2 = {\n x: midX - (h * dy) / dist,\n y: midY + (h * dx) / dist,\n }\n\n const result = []\n const epsilon = 1e-6\n\n if (\n Math.abs(distance(intersection1, c1) - r) < epsilon &&\n Math.abs(distance(intersection1, c2) - r) < epsilon\n ) {\n result.push(intersection1)\n }\n\n if (\n Math.abs(distance(intersection2, c1) - r) < epsilon &&\n Math.abs(distance(intersection2, c2) - r) < epsilon\n ) {\n result.push(intersection2)\n }\n\n return result\n }\n\n // Get all standard candidates\n const candidateA = pointOnCircle(avgPoint, A, radius)\n const candidateB = pointOnCircle(avgPoint, B, radius)\n const candidateC = pointOnCircle(avgPoint, C, radius)\n\n const intersectionsAB = findCircleIntersections(A, B, radius)\n const intersectionsBC = findCircleIntersections(B, C, radius)\n const intersectionsCA = findCircleIntersections(C, A, radius)\n\n const allCandidates = [\n candidateA,\n candidateB,\n candidateC,\n ...intersectionsAB,\n ...intersectionsBC,\n ...intersectionsCA,\n ]\n\n // Filter to valid candidates\n const validCandidates = allCandidates.filter(isValidPoint)\n\n // If we have valid interior candidates, use them\n if (validCandidates.length > 0) {\n // Separate interior and boundary points\n const interiorCandidates = validCandidates.filter((p) => !isOnBoundary(p))\n\n if (interiorCandidates.length > 0) {\n // Sort by distance to average\n interiorCandidates.sort(\n (a, b) => distance(a, avgPoint) - distance(b, avgPoint),\n )\n return interiorCandidates[0]\n }\n }\n\n // No valid interior candidates from standard points, now do a grid search\n // We'll do a systematic grid search to find interior points\n const gridStep = 5 // 5px grid\n let bestPoint = null\n let bestDistance = Infinity\n\n for (let x = bounds.minX + 1; x < bounds.maxX; x += gridStep) {\n for (let y = bounds.minY + 1; y < bounds.maxY; y += gridStep) {\n const point = { x, y }\n if (isValidPoint(point)) {\n const dist = distance(point, avgPoint)\n if (dist < bestDistance) {\n bestDistance = dist\n bestPoint = point\n }\n }\n }\n }\n\n // If we found a valid interior point in the grid search, return it\n if (bestPoint !== null) {\n return bestPoint\n }\n\n // If all interior methods failed, check boundary points\n // Sample points along the boundary\n const numSamples = 100 // More samples for better accuracy\n const boundaryPoints = []\n\n for (let i = 0; i <= numSamples; i++) {\n const t = i / numSamples\n\n // Top edge\n boundaryPoints.push({\n x: bounds.minX + t * (bounds.maxX - bounds.minX),\n y: bounds.minY,\n })\n\n // Right edge\n boundaryPoints.push({\n x: bounds.maxX,\n y: bounds.minY + t * (bounds.maxY - bounds.minY),\n })\n\n // Bottom edge\n boundaryPoints.push({\n x: bounds.maxX - t * (bounds.maxX - bounds.minX),\n y: bounds.maxY,\n })\n\n // Left edge\n boundaryPoints.push({\n x: bounds.minX,\n y: bounds.maxY - t * (bounds.maxY - bounds.minY),\n })\n }\n\n // Find valid boundary points\n const validBoundaryPoints = boundaryPoints.filter(isValidPoint)\n\n if (validBoundaryPoints.length > 0) {\n // Sort by distance to average\n validBoundaryPoints.sort(\n (a, b) => distance(a, avgPoint) - distance(b, avgPoint),\n )\n return validBoundaryPoints[0]\n }\n\n // If we get here, no valid point exists that satisfies all constraints\n // Find the point that minimizes constraint violations\n let minViolation = Infinity\n let leastBadPoint = { x: bounds.minX, y: bounds.minY }\n\n for (const point of [...allCandidates, ...boundaryPoints]) {\n // Only consider points within bounds\n if (\n point.x >= bounds.minX &&\n point.x <= bounds.maxX &&\n point.y >= bounds.minY &&\n point.y <= bounds.maxY\n ) {\n const violationA = Math.max(0, radius - distance(point, A))\n const violationB = Math.max(0, radius - distance(point, B))\n const violationC = Math.max(0, radius - distance(point, C))\n\n const totalViolation = violationA + violationB + violationC\n\n if (totalViolation < minViolation) {\n minViolation = totalViolation\n leastBadPoint = point\n }\n }\n }\n\n return leastBadPoint\n}\n","interface Point {\n x: number\n y: number\n}\n\ninterface Circle {\n center: Point\n radius: number\n}\n\n/**\n * Finds the tangent points and their intersection for the shortest path from C to A\n * that touches the circle Q at points B and D.\n *\n * E is the point where you're guaranteed to be able to get around the circle\n * without intersecting it if you travel from A to E to C\n *\n * @param A First observation point\n * @param C Second observation point\n * @param Q Circle definition with center and radius\n * @returns Object containing points B, D, and E\n */\nexport function findPointToGetAroundCircle(\n A: Point,\n C: Point,\n Q: Circle,\n): { B: Point; D: Point; E: Point } {\n // Compute point B (tangent from C to circle Q)\n const B = computeTangentPoint(C, A, Q.center, Q.radius)\n\n // Compute point D (tangent from A to circle Q)\n const D = computeTangentPoint(A, C, Q.center, Q.radius)\n\n // Check if B and D are valid (not too close to C and A respectively)\n const distBC = distance(B, C)\n const distAD = distance(A, D)\n const minDistThreshold = 1e-6\n\n const BIsValid = distBC > minDistThreshold\n const DIsValid = distAD > minDistThreshold\n\n // Compute point E using a robust approach\n let E: Point\n\n if (!BIsValid || !DIsValid) {\n // Fallback: Use the midpoint between A and C but ensure it's outside the circle\n const midAC = {\n x: (A.x + C.x) / 2,\n y: (A.y + C.y) / 2,\n }\n\n const distFromCenter = distance(midAC, Q.center)\n if (distFromCenter < Q.radius * 1.1) {\n // Too close to circle, move away from center\n const dirFromCenter = {\n x: (midAC.x - Q.center.x) / distFromCenter,\n y: (midAC.y - Q.center.y) / distFromCenter,\n }\n\n E = {\n x: Q.center.x + dirFromCenter.x * Q.radius * 1.2,\n y: Q.center.y + dirFromCenter.y * Q.radius * 1.2,\n }\n } else {\n // Midpoint is far enough from circle\n E = midAC\n }\n } else {\n // B and D are valid, use midpoint between B and D as a robust solution\n E = {\n x: (B.x + D.x) / 2,\n y: (B.y + D.y) / 2,\n }\n\n // Check if the midpoint is a reasonable solution\n const distBE = distance(B, E)\n const distDE = distance(D, E)\n\n if (Math.abs(distBE - distDE) > Math.min(distBE, distDE) * 0.5) {\n // The midpoint is significantly closer to one point than the other\n // Use a weighted average instead\n const distAB = distance(A, B)\n const distCD = distance(C, D)\n const totalDist = distAB + distCD\n\n if (totalDist > minDistThreshold) {\n // Weight based on distances from A to B and C to D\n const weightB = distCD / totalDist\n const weightD = distAB / totalDist\n\n E = {\n x: B.x * weightB + D.x * weightD,\n y: B.y * weightB + D.y * weightD,\n }\n }\n }\n\n // Final safety check: make sure E is outside the circle\n const distEToCenter = distance(E, Q.center)\n if (distEToCenter < Q.radius * 1.05) {\n // E is too close to the circle, adjust it\n const dirFromCenter = {\n x: (E.x - Q.center.x) / distEToCenter,\n y: (E.y - Q.center.y) / distEToCenter,\n }\n\n E = {\n x: Q.center.x + dirFromCenter.x * Q.radius * 1.2,\n y: Q.center.y + dirFromCenter.y * Q.radius * 1.2,\n }\n }\n }\n\n return { B, D, E }\n}\n\n/**\n * Computes the tangent point from an observation point to a circle\n *\n * @param observationPoint The point from which the tangent is drawn\n * @param referencePoint A reference point that helps determine which side of the circle to choose\n * @param circleCenter The center of the circle\n * @param radius The radius of the circle\n * @returns The tangent point on the circle\n */\nfunction computeTangentPoint(\n observationPoint: Point,\n referencePoint: Point,\n circleCenter: Point,\n radius: number,\n): Point {\n // Vector from observation point to circle center\n const CQ = [\n circleCenter.x - observationPoint.x,\n circleCenter.y - observationPoint.y,\n ]\n const CQLength = Math.sqrt(CQ[0] * CQ[0] + CQ[1] * CQ[1])\n\n // Check if tangent is possible (point is inside or on the circle)\n if (CQLength <= radius) {\n // Instead of returning the observation point, find a point on the circle\n // in the direction away from the circle center\n if (CQLength < 1e-8) {\n // If observation point is at circle center, move in direction of reference point\n const refVec = [\n referencePoint.x - observationPoint.x,\n referencePoint.y - observationPoint.y,\n ]\n const refLength = Math.sqrt(refVec[0] * refVec[0] + refVec[1] * refVec[1])\n\n if (refLength < 1e-8) {\n // If reference point is also at circle center, use arbitrary direction\n return {\n x: circleCenter.x + radius,\n y: circleCenter.y,\n }\n }\n\n return {\n x: circleCenter.x + (refVec[0] / refLength) * radius,\n y: circleCenter.y + (refVec[1] / refLength) * radius,\n }\n }\n\n // Move away from circle center along the same line\n const CQUnit = [CQ[0] / CQLength, CQ[1] / CQLength]\n return {\n x: circleCenter.x - CQUnit[0] * radius,\n y: circleCenter.y - CQUnit[1] * radius,\n }\n }\n\n // Vector from observation point to reference point (to determine which side of the circle)\n const CR = [\n referencePoint.x - observationPoint.x,\n referencePoint.y - observationPoint.y,\n ]\n\n // Calculate the distance from observation point to the tangent point\n const d = Math.sqrt(CQLength * CQLength - radius * radius)\n\n // Normalize CQ to get the unit vector in that direction\n const CQUnit = [CQ[0] / CQLength, CQ[1] / CQLength]\n\n // Calculate two possible perpendicular unit vectors\n const perp1 = [-CQUnit[1], CQUnit[0]]\n const perp2 = [CQUnit[1], -CQUnit[0]]\n\n // Choose the perpendicular that forms an angle closer to CR\n const dot1 = CR[0] * perp1[0] + CR[1] * perp1[1]\n const dot2 = CR[0] * perp2[0] + CR[1] * perp2[1]\n const perp = dot1 > dot2 ? perp1 : perp2\n\n // Calculate the sine and cosine of the angle from CQ to the tangent line\n const sinTheta = radius / CQLength\n const cosTheta = d / CQLength\n\n // Unit vector in the direction of the tangent point\n const unitToTangent = [\n CQUnit[0] * cosTheta + perp[0] * sinTheta,\n CQUnit[1] * cosTheta + perp[1] * sinTheta,\n ]\n\n // Calculate the tangent point\n return {\n x: observationPoint.x + d * unitToTangent[0],\n y: observationPoint.y + d * unitToTangent[1],\n }\n}\n\n/**\n * Helper function to calculate the Euclidean distance between two points\n */\nfunction distance(p1: Point, p2: Point): number {\n const dx = p2.x - p1.x\n const dy = p2.y - p1.y\n return Math.sqrt(dx * dx + dy * dy)\n}\n","interface Point {\n x: number\n y: number\n}\n\ninterface Bounds {\n minX: number\n maxX: number\n minY: number\n maxY: number\n}\n\ninterface SidePercentages {\n left: number\n top: number\n right: number\n bottom: number\n}\n\n// Keep a small epsilon for floating point comparisons\nconst EPSILON = 1e-9 // Using a slightly smaller epsilon can sometimes help precision\n\n/**\n * Calculates the percentage of each side traversed when going from point A to point B\n * along the rectangle boundary.\n * Assumes traversal is always in the 'forward' direction along the perimeter (clockwise conceptually).\n */\nfunction calculateSegmentTraversal(\n startPoint: Point,\n endPoint: Point,\n bounds: Bounds,\n): SidePercentages {\n const startAngle = pointToAngle(startPoint, bounds)\n let endAngle = pointToAngle(endPoint, bounds)\n\n // Handle angle wrap-around (e.g., traversing past the 2π point)\n // If the end angle is less than the start angle, it means we crossed the 0/2π boundary\n if (endAngle < startAngle) {\n endAngle += 2 * Math.PI\n }\n\n // Use the existing helper, which calculates percentages based on a start and end angle\n // Ensure the end angle is strictly greater for non-zero traversal\n if (Math.abs(endAngle - startAngle) < EPSILON) {\n return { left: 0, top: 0, right: 0, bottom: 0 } // No movement\n }\n\n return calculateSidePercentages(startAngle, endAngle, bounds)\n}\n\n/**\n * Calculates the total percentage of each side traversed when going sequentially\n * from A to B, and then from B to C along a rectangle boundary.\n */\nexport function calculateTraversalPercentages(\n A: Point,\n B: Point,\n C: Point,\n bounds: Bounds,\n): SidePercentages {\n // Calculate traversal percentages for the segment A -> B\n const percentagesAB = calculateSegmentTraversal(A, B, bounds)\n\n // Calculate traversal percentages for the segment B -> C\n const percentagesBC = calculateSegmentTraversal(B, C, bounds)\n\n // Sum the percentages from both segments\n // Use Math.min to cap at 1.0 in case of tiny floating point overflows\n const totalPercentages: SidePercentages = {\n left: Math.min(1.0, percentagesAB.left + percentagesBC.left),\n top: Math.min(1.0, percentagesAB.top + percentagesBC.top),\n right: Math.min(1.0, percentagesAB.right + percentagesBC.right),\n bottom: Math.min(1.0, percentagesAB.bottom + percentagesBC.bottom),\n }\n\n // Optional: Clean up near-zero values resulting from floating point inaccuracies\n for (const key in totalPercentages) {\n if (Math.abs(totalPercentages[key as keyof SidePercentages]) < EPSILON) {\n totalPercentages[key as keyof SidePercentages] = 0\n }\n }\n\n return totalPercentages\n}\n\n/**\n * Converts a point on the rectangle boundary to an angle (0 to 2π, clockwise from top-left).\n * Updated to be slightly more robust with epsilon checks.\n */\nfunction pointToAngle(point: Point, bounds: Bounds): number {\n const width = bounds.maxX - bounds.minX\n const height = bounds.maxY - bounds.minY\n // Avoid division by zero if width or height is zero\n if (width < EPSILON && height < EPSILON) return 0\n const perimeter = 2 * (width + height)\n if (perimeter < EPSILON) return 0 // Avoid division by zero for degenerate rectangles\n\n let distance = 0\n\n // Check sides using epsilon comparisons\n if (\n Math.abs(point.y - bounds.maxY) < EPSILON &&\n point.x >= bounds.minX - EPSILON &&\n point.x <= bounds.maxX + EPSILON\n ) {\n // Top side (y is maxY)\n // Ensure x is clamped within bounds for distance calculation robustness\n distance = Math.max(0, Math.min(width, point.x - bounds.minX))\n } else if (\n Math.abs(point.x - bounds.maxX) < EPSILON &&\n point.y >= bounds.minY - EPSILON &&\n point.y <= bounds.maxY + EPSILON\n ) {\n // Right side (x is maxX)\n // Ensure y is clamped within bounds\n distance = width + Math.max(0, Math.min(height, bounds.maxY - point.y))\n } else if (\n Math.abs(point.y - bounds.minY) < EPSILON &&\n point.x >= bounds.minX - EPSILON &&\n point.x <= bounds.maxX + EPSILON\n ) {\n // Bottom side (y is minY)\n // Ensure x is clamped within bounds\n distance =\n width + height + Math.max(0, Math.min(width, bounds.maxX - point.x))\n } else if (\n Math.abs(point.x - bounds.minX) < EPSILON &&\n point.y >= bounds.minY - EPSILON &&\n point.y <= bounds.maxY + EPSILON\n ) {\n // Left side (x is minX)\n // Ensure y is clamped within bounds\n distance =\n width +\n height +\n width +\n Math.max(0, Math.min(height, point.y - bounds.minY))\n } else {\n // Point might be slightly off boundary due to precision, try snapping it?\n // Or throw error as before. For now, let's log a warning and try snapping.\n // console.warn(\n // \"Point does not lie exactly on the boundary, attempting to snap.\",\n // { point, bounds },\n // )\n // Simple snap: Find closest side point (more complex logic could be added here)\n // For simplicity, we'll re-call with snapped points if needed, or just throw.\n // Let's stick to the original error for now if it's significantly off.\n throw new Error(\n `Point (${point.x}, ${point.y}) does not lie on the boundary defined by ${JSON.stringify(bounds)}`,\n )\n // Alternative: Add logic here to find the closest point on the boundary and use that.\n }\n\n // Ensure distance doesn't exceed perimeter due to float issues\n distance = Math.max(0, Math.min(perimeter, distance))\n\n // Convert distance to angle (0 to 2π)\n // Handle perimeter being zero\n return perimeter > EPSILON ? (distance / perimeter) * (2 * Math.PI) : 0\n}\n\n/**\n * Calculate percentages of each side traversed based on start and end angles (endAngle >= startAngle).\n * This function remains largely the same but benefits from corrected inputs.\n */\nfunction calculateSidePercentages(\n startAngle: number,\n endAngle: number,\n bounds: Bounds,\n): SidePercentages {\n const width = bounds.maxX - bounds.minX\n const height = bounds.maxY - bounds.minY\n // Avoid division by zero if width or height is zero\n if (width < EPSILON && height < EPSILON)\n return { left: 0, top: 0, right: 0, bottom: 0 }\n const perimeter = 2 * (width + height)\n if (perimeter < EPSILON) return { left: 0, top: 0, right: 0, bottom: 0 }\n\n // Define angle ranges for each side (clockwise from top-left = 0)\n // Ensure denominator is non-zero\n const angleTopEnd = (width / perimeter) * (2 * Math.PI)\n const angleRightEnd = ((width + height) / perimeter) * (2 * Math.PI)\n const angleBottomEnd = ((width + width + height) / perimeter) * (2 * Math.PI)\n const angleLeftEnd = 2 * Math.PI // Full circle\n\n const sides = [\n { name: \"top\", start: 0, end: angleTopEnd, length: width },\n { name: \"right\", start: angleTopEnd, end: angleRightEnd, length: height },\n {\n name: \"bottom\",\n start: angleRightEnd,\n end: angleBottomEnd,\n length: width,\n },\n { name: \"left\", start: angleBottomEnd, end: angleLeftEnd, length: height }, // Ends at 2PI\n ]\n\n const result: SidePercentages = { left: 0, top: 0, right: 0, bottom: 0 }\n const totalAngleTraversal = endAngle - startAngle\n\n if (totalAngleTraversal < EPSILON) return result // No traversal\n\n for (const side of sides) {\n const sideAngleRange = side.end - side.start\n\n // Skip calculation if side length (and thus angle range) is effectively zero\n if (sideAngleRange < EPSILON || side.length < EPSILON) continue\n\n // Calculate overlap\n const overlapStart = Math.max(startAngle, side.start)\n const overlapEnd = Math.min(endAngle, side.end)\n\n if (overlapStart < overlapEnd - EPSILON) {\n // Check overlap is significant\n const traversedAngleOnSide = overlapEnd - overlapStart\n\n // Percentage calculation: (traversed angle on side) / (total angle range of side)\n // This gives the fraction *of the side* that was covered by this segment traversal.\n const percentage = traversedAngleOnSide / sideAngleRange\n\n // Add percentage, ensuring it's non-negative\n result[side.name as keyof SidePercentages] += Math.max(0, percentage)\n }\n }\n\n // Normalize results slightly in case of FP inaccuracies summing up\n for (const key in result) {\n result[key as keyof SidePercentages] = Math.max(\n 0,\n Math.min(1.0, result[key as keyof SidePercentages]),\n )\n }\n\n return result\n}\n","import { BaseSolver } from \"lib/solvers/BaseSolver\"\nimport {\n NodeWithPortPoints,\n HighDensityIntraNodeRoute,\n} from \"lib/types/high-density-types\"\nimport {\n distance,\n pointToSegmentDistance,\n doSegmentsIntersect,\n clamp,\n} from \"@tscircuit/math-utils\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { getIntraNodeCrossings } from \"lib/utils/getIntraNodeCrossings\"\nimport { findCircleLineIntersections } from \"./findCircleLineIntersections\"\nimport { findClosestPointToABCWithinBounds } from \"lib/utils/findClosestPointToABCWithinBounds\"\nimport { calculatePerpendicularPointsAtDistance } from \"lib/utils/calculatePointsAtDistance\"\nimport { snapToNearestBound } from \"lib/utils/snapToNearestBound\"\nimport { findPointToGetAroundCircle } from \"lib/utils/findPointToGetAroundCircle\"\nimport { calculateTraversalPercentages } from \"./calculateSideTraversal\"\n\ntype Point = { x: number; y: number; z?: number }\ntype Route = {\n A: Point\n B: Point\n connectionName: string\n}\n\nexport class SingleTransitionCrossingRouteSolver extends BaseSolver {\n // Input parameters\n nodeWithPortPoints: NodeWithPortPoints\n routes: Route[]\n\n // Configuration parameters\n viaDiameter: number\n traceThickness: number\n obstacleMargin: number\n layerCount: number = 2\n\n debugViaPositions: {\n via: Point\n }[]\n\n // Solution state\n solvedRoutes: HighDensityIntraNodeRoute[] = []\n\n // Bounds\n bounds: { minX: number; maxX: number; minY: number; maxY: number }\n\n constructor(params: {\n nodeWithPortPoints: NodeWithPortPoints\n viaDiameter?: number\n traceThickness?: number\n obstacleMargin?: number\n layerCount?: number\n }) {\n super()\n\n this.nodeWithPortPoints = params.nodeWithPortPoints\n this.viaDiameter = params?.viaDiameter ?? 0.6\n this.traceThickness = params?.traceThickness ?? 0.15\n this.obstacleMargin = params?.obstacleMargin ?? 0.1\n this.layerCount = params?.layerCount ?? 2\n this.debugViaPositions = []\n\n // Extract routes from the node data\n this.routes = this.extractRoutesFromNode()\n\n // Calculate bounds\n this.bounds = this.calculateBounds()\n\n if (this.routes.length !== 2) {\n this.failed = true\n return\n }\n\n const [routeA, routeB] = this.routes\n\n // Check if one route has a layer transition and the other doesn't\n const routeAHasTransition = routeA.A.z !== routeA.B.z\n const routeBHasTransition = routeB.A.z !== routeB.B.z\n\n // We need exactly one route with a transition\n if (\n (routeAHasTransition && routeBHasTransition) ||\n (!routeAHasTransition && !routeBHasTransition)\n ) {\n this.failed = true\n return\n }\n }\n\n /**\n * Extract routes that need to be connected from the node data\n */\n private extractRoutesFromNode(): Route[] {\n const routes: Route[] = []\n const connectedPorts = this.nodeWithPortPoints.portPoints!\n\n // Group ports by connection name\n const connectionGroups = new Map<string, Point[]>()\n\n for (const connectedPort of connectedPorts) {\n const { connectionName } = connectedPort\n if (!connectionGroups.has(connectionName)) {\n connectionGroups.set(connectionName, [])\n }\n connectionGroups.get(connectionName)?.push(connectedPort)\n }\n\n // Create routes for each connection (assuming each connection has exactly 2 points)\n for (const [connectionName, points] of connectionGroups.entries()) {\n if (points.length === 2) {\n routes.push({\n A: { ...points[0], z: points[0].z ?? 0 },\n B: { ...points[1], z: points[1].z ?? 0 },\n connectionName,\n })\n }\n }\n\n return routes\n }\n\n /**\n * Calculate the bounding box of the node\n */\n private calculateBounds() {\n return {\n minX:\n this.nodeWithPortPoints.center.x - this.nodeWithPortPoints.width / 2,\n maxX:\n this.nodeWithPortPoints.center.x + this.nodeWithPortPoints.width / 2,\n minY:\n this.nodeWithPortPoints.center.y - this.nodeWithPortPoints.height / 2,\n maxY:\n this.nodeWithPortPoints.center.y + this.nodeWithPortPoints.height / 2,\n }\n }\n\n /**\n * Check if two routes are crossing\n */\n private doRoutesCross(routeA: Route, routeB: Route): boolean {\n // For this specific solver, we want to check if the 2D projections intersect\n // (ignoring z values)\n return doSegmentsIntersect(routeA.A, routeA.B, routeB.A, routeB.B)\n }\n\n private calculateViaPosition(\n transitionRoute: Route,\n flatRoute: Route,\n ): Point | null {\n const flatRouteZ = flatRoute.A.z\n const ntrP1 =\n transitionRoute.A.z !== flatRouteZ ? transitionRoute.A : transitionRoute.B\n\n // ntrP1 is always on the opposite layer as the flat route, the trace must always\n // weave between ntrP1 and the via\n // The via must also be far enough from the flat route\n const marginFromBorderWithTrace =\n this.obstacleMargin * 2 + this.viaDiameter / 2 + this.traceThickness\n const marginFromBorderWithoutTrace =\n this.obstacleMargin + this.viaDiameter / 2\n\n const A = flatRoute.A\n const B = ntrP1\n const C = flatRoute.B\n\n const sideTraversal = calculateTraversalPercentages(A, B, C, this.bounds)\n\n const viaBounds = {\n minX:\n this.bounds.minX +\n (sideTraversal.left > 0.5\n ? marginFromBorderWithTrace\n : marginFromBorderWithoutTrace),\n minY:\n this.bounds.minY +\n (sideTraversal.bottom > 0.5\n ? marginFromBorderWithTrace\n : marginFromBorderWithoutTrace),\n maxX:\n this.bounds.maxX -\n (sideTraversal.right > 0.5\n ? marginFromBorderWithTrace\n : marginFromBorderWithoutTrace),\n maxY:\n this.bounds.maxY -\n (sideTraversal.top > 0.5\n ? marginFromBorderWithTrace\n : marginFromBorderWithoutTrace),\n }\n\n if (viaBounds.maxY < viaBounds.minY) {\n viaBounds.minY = (viaBounds.minY + viaBounds.maxY) / 2\n viaBounds.maxY = viaBounds.minY\n }\n\n if (viaBounds.maxX < viaBounds.minX) {\n viaBounds.minX = (viaBounds.minX + viaBounds.maxX) / 2\n viaBounds.maxX = viaBounds.minX\n }\n\n return findClosestPointToABCWithinBounds(\n A,\n B,\n C,\n marginFromBorderWithTrace,\n viaBounds,\n )\n }\n /**\n * Create a single transition route with properly placed via\n */\n private createTransitionRoute(\n start: Point,\n end: Point,\n via: Point,\n connectionName: string,\n ): HighDensityIntraNodeRoute {\n // Create the route path with layer transition at the via\n const route = [\n { x: start.x, y: start.y, z: start.z ?? 0 },\n { x: via.x, y: via.y, z: start.z ?? 0 },\n { x: via.x, y: via.y, z: end.z ?? 0 },\n { x: end.x, y: end.y, z: end.z ?? 0 },\n ]\n\n return {\n connectionName,\n route,\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [via],\n }\n }\n\n /**\n * Create the non-transition route\n */\n private createFlatRoute(\n flatStart: Point,\n flatEnd: Point,\n via: Point,\n otherRouteStart: Point,\n otherRouteEnd: Point,\n flatRouteConnectionName: string,\n ): HighDensityIntraNodeRoute {\n const ntrP1 =\n otherRouteStart.z !== flatStart.z ? otherRouteStart : otherRouteEnd\n // We need to navigate around the via\n\n const middle = (a: Point, b: Point) => {\n return {\n x: (a.x + b.x) / 2,\n y: (a.y + b.y) / 2,\n }\n }\n\n const middleWithMargin = (\n a: Point,\n aMargin: number,\n b: Point,\n bMargin: number,\n ) => {\n const dx = b.x - a.x\n const dy = b.y - a.y\n\n const effectiveA = {\n x: a.x + dx * aMargin,\n y: a.y + dy * aMargin,\n }\n\n const effectiveB = {\n x: b.x - dx * bMargin,\n y: b.y - dy * bMargin,\n }\n\n return middle(effectiveA, effectiveB)\n }\n\n const traceBounds = {\n maxX: this.bounds.maxX - this.obstacleMargin - this.traceThickness / 2,\n maxY: this.bounds.maxY - this.obstacleMargin - this.traceThickness / 2,\n minX: this.bounds.minX + this.obstacleMargin + this.traceThickness / 2,\n minY: this.bounds.minY + this.obstacleMargin + this.traceThickness / 2,\n }\n\n const minDistFromViaToTrace =\n this.viaDiameter / 2 + this.traceThickness / 2 + this.obstacleMargin\n const p2 = middleWithMargin(\n via,\n this.viaDiameter,\n otherRouteStart.z !== flatStart.z ? otherRouteStart : otherRouteEnd,\n this.traceThickness,\n )\n const p1 = findPointToGetAroundCircle(flatStart, p2, {\n center: { x: via.x, y: via.y },\n radius: minDistFromViaToTrace,\n }).E\n const p3 = findPointToGetAroundCircle(p2, flatEnd, {\n center: { x: via.x, y: via.y },\n radius: minDistFromViaToTrace,\n }).E\n\n // Determine if we need p1 or if we can just go from flatStart to p2 without\n // intersecting the via\n const p1IsNeeded =\n pointToSegmentDistance(via, flatStart, p2) < minDistFromViaToTrace\n const p3IsNeeded =\n pointToSegmentDistance(via, p2, flatEnd) < minDistFromViaToTrace\n\n // We need to navigate around the via\n return {\n connectionName: flatRouteConnectionName,\n route: [\n { x: flatStart.x, y: flatStart.y, z: flatStart.z ?? 0 },\n ...(p1IsNeeded ? [{ x: p1.x, y: p1.y, z: flatStart.z ?? 0 }] : []),\n { x: p2.x, y: p2.y, z: flatStart.z ?? 0 },\n ...(p3IsNeeded ? [{ x: p3.x, y: p3.y, z: flatStart.z ?? 0 }] : []),\n { x: flatEnd.x, y: flatEnd.y, z: flatEnd.z ?? 0 },\n ],\n traceThickness: this.traceThickness,\n viaDiameter: this.viaDiameter,\n vias: [],\n }\n }\n\n /**\n * Try to solve with one route having a transition and the other staying flat\n */\n private trySolve(): boolean {\n const [routeA, routeB] = this.routes\n\n // Determine which route has the transition\n const routeAHasTransition = routeA.A.z !== routeA.B.z\n\n const transitionRoute = routeAHasTransition ? routeA : routeB\n const flatRoute = routeAHasTransition ? routeB : routeA\n\n const viaPosition = this.calculateViaPosition(transitionRoute, flatRoute)\n if (viaPosition) {\n this.debugViaPositions.push({ via: viaPosition })\n } else {\n return false\n }\n\n // Create transition route with via\n const transitionRouteSolution = this.createTransitionRoute(\n transitionRoute.A,\n transitionRoute.B,\n viaPosition,\n transitionRoute.connectionName,\n )\n\n // Create flat route\n const flatRouteSolution = this.createFlatRoute(\n flatRoute.A,\n flatRoute.B,\n viaPosition,\n transitionRoute.A,\n transitionRoute.B,\n flatRoute.connectionName,\n )\n\n this.solvedRoutes.push(transitionRouteSolution, flatRouteSolution)\n return true\n }\n\n /**\n * Main step method that attempts to solve the routes\n */\n _step() {\n // Check if routes are actually crossing\n if (!this.doRoutesCross(this.routes[0], this.routes[1])) {\n this.failed = true\n this.error =\n \"Can only solve routes that have a single transition crossing\"\n return\n }\n\n // Try to solve\n if (this.trySolve()) {\n this.solved = true\n return\n }\n\n // If approach fails, mark as failed\n this.failed = true\n }\n\n /**\n * Visualization for debugging\n */\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n\n // Draw PCB bounds\n graphics.rects!.push({\n center: {\n x: (this.bounds.minX + this.bounds.maxX) / 2,\n y: (this.bounds.minY + this.bounds.maxY) / 2,\n },\n width: this.bounds.maxX - this.bounds.minX,\n height: this.bounds.maxY - this.bounds.minY,\n stroke: \"rgba(0, 0, 0, 0.5)\",\n fill: \"rgba(240, 240, 240, 0.1)\",\n label: \"PCB Bounds\",\n })\n\n // Draw original routes\n for (const route of this.routes) {\n // Draw endpoints\n graphics.points!.push({\n x: route.A.x,\n y: route.A.y,\n label: `${route.connectionName} start (z=${route.A.z})`,\n color: \"orange\",\n })\n\n graphics.points!.push({\n x: route.B.x,\n y: route.B.y,\n label: `${route.connectionName} end (z=${route.B.z})`,\n color: \"orange\",\n })\n\n // Draw direct connection line\n graphics.lines!.push({\n points: [route.A, route.B],\n strokeColor: \"rgba(255, 0, 0, 0.5)\",\n label: `${route.connectionName} direct`,\n })\n }\n\n // Draw debug via positions (even if solution failed)\n for (let i = 0; i < this.debugViaPositions.length; i++) {\n const { via } = this.debugViaPositions[i]\n\n // Draw computed via\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2,\n fill: \"rgba(255, 165, 0, 0.7)\",\n stroke: \"rgba(0, 0, 0, 0.5)\",\n label: `Computed Via (attempt ${i + 1})`,\n })\n\n // Draw safety margin around via\n const safetyMargin = this.viaDiameter / 2 + this.obstacleMargin\n graphics.circles!.push({\n center: via,\n radius: safetyMargin,\n stroke: \"rgba(255, 165, 0, 0.7)\",\n fill: \"rgba(0, 0, 0, 0)\",\n label: \"Safety Margin\",\n })\n }\n\n // Draw solved routes if available\n for (let si = 0; si < this.solvedRoutes.length; si++) {\n const route = this.solvedRoutes[si]\n const routeColor =\n si % 2 === 0 ? \"rgba(0, 255, 0, 0.75)\" : \"rgba(255, 0, 255, 0.75)\"\n for (let i = 0; i < route.route.length - 1; i++) {\n const pointA = route.route[i]\n const pointB = route.route[i + 1]\n\n graphics.lines!.push({\n points: [pointA, pointB],\n strokeColor: routeColor,\n strokeDash: pointA.z !== route.route[0].z ? [0.2, 0.2] : undefined,\n strokeWidth: route.traceThickness,\n label: `${route.connectionName} z=${pointA.z}`,\n })\n }\n\n // Draw vias in solved routes\n for (const via of route.vias) {\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2,\n fill: \"rgba(0, 0, 255, 0.8)\",\n stroke: \"black\",\n label: \"Solved Via\",\n })\n graphics.circles!.push({\n center: via,\n radius: this.viaDiameter / 2 + this.obstacleMargin,\n fill: \"rgba(0, 0, 255, 0.3)\",\n stroke: \"black\",\n label: \"Via Margin\",\n })\n }\n }\n\n return graphics\n }\n\n /**\n * Get the solved routes\n */\n getSolvedRoutes(): HighDensityIntraNodeRoute[] {\n return this.solvedRoutes\n }\n}\n","import {\n HighDensityIntraNodeRoute,\n NodeWithPortPoints,\n} from \"lib/types/high-density-types\"\nimport { IntraNodeRouteSolver } from \"../HighDensitySolver/IntraNodeSolver\"\nimport {\n HyperParameterSupervisorSolver,\n SupervisedSolver,\n} from \"../HyperParameterSupervisorSolver\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport { TwoCrossingRoutesHighDensitySolver } from \"../HighDensitySolver/TwoRouteHighDensitySolver/TwoCrossingRoutesHighDensitySolver\"\nimport { SingleTransitionCrossingRouteSolver } from \"../HighDensitySolver/TwoRouteHighDensitySolver/SingleTransitionCrossingRouteSolver\"\n\nexport class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver<\n IntraNodeRouteSolver | TwoCrossingRoutesHighDensitySolver\n> {\n constructorParams: ConstructorParameters<typeof IntraNodeRouteSolver>[0]\n solvedRoutes: HighDensityIntraNodeRoute[] = []\n nodeWithPortPoints: NodeWithPortPoints\n\n constructor(opts: ConstructorParameters<typeof IntraNodeRouteSolver>[0]) {\n super()\n this.nodeWithPortPoints = opts.nodeWithPortPoints\n this.constructorParams = opts\n this.MAX_ITERATIONS = 250_000\n this.GREEDY_MULTIPLIER = 5\n this.MIN_SUBSTEPS = 100\n }\n\n getCombinationDefs() {\n return [\n [\"closedFormTwoTrace\"],\n [\"majorCombinations\", \"orderings6\", \"cellSizeFactor\"],\n [\"noVias\"],\n [\"orderings50\"],\n [\"flipTraceAlignmentDirection\", \"orderings6\"],\n ]\n }\n\n getHyperParameterDefs() {\n return [\n {\n name: \"majorCombinations\",\n possibleValues: [\n {\n FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: 2,\n FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: 1,\n FUTURE_CONNECTION_PROXIMITY_VD: 10,\n MISALIGNED_DIST_PENALTY_FACTOR: 5,\n },\n {\n FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: 1,\n FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: 0.5,\n FUTURE_CONNECTION_PROXIMITY_VD: 5,\n MISALIGNED_DIST_PENALTY_FACTOR: 2,\n },\n {\n FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: 10,\n FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: 1,\n FUTURE_CONNECTION_PROXIMITY_VD: 5,\n MISALIGNED_DIST_PENALTY_FACTOR: 10,\n VIA_PENALTY_FACTOR_2: 1,\n },\n ],\n },\n {\n name: \"orderings6\",\n possibleValues: [\n {\n SHUFFLE_SEED: 0,\n },\n {\n SHUFFLE_SEED: 1,\n },\n {\n SHUFFLE_SEED: 2,\n },\n {\n SHUFFLE_SEED: 3,\n },\n {\n SHUFFLE_SEED: 4,\n },\n {\n SHUFFLE_SEED: 5,\n },\n ],\n },\n {\n name: \"cellSizeFactor\",\n possibleValues: [\n {\n CELL_SIZE_FACTOR: 0.5,\n },\n {\n CELL_SIZE_FACTOR: 1,\n },\n ],\n },\n {\n name: \"flipTraceAlignmentDirection\",\n possibleValues: [\n {\n FLIP_TRACE_ALIGNMENT_DIRECTION: true,\n },\n ],\n },\n {\n name: \"noVias\",\n possibleValues: [\n {\n CELL_SIZE_FACTOR: 2,\n VIA_PENALTY_FACTOR_2: 10,\n },\n ],\n },\n {\n name: \"orderings50\",\n possibleValues: Array.from({ length: 50 }, (_, i) => ({\n SHUFFLE_SEED: 100 + i,\n })),\n },\n {\n name: \"closedFormTwoTrace\",\n possibleValues: [\n {\n CLOSED_FORM_TWO_TRACE_SAME_LAYER: true,\n },\n {\n CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING: true,\n },\n ],\n },\n ]\n }\n\n computeG(solver: IntraNodeRouteSolver) {\n return (\n solver.iterations / 10_000 // + solver.hyperParameters.SHUFFLE_SEED! * 0.05\n )\n }\n\n computeH(solver: IntraNodeRouteSolver) {\n return 1 - (solver.progress || 0)\n }\n\n generateSolver(hyperParameters: any): IntraNodeRouteSolver {\n if (hyperParameters.CLOSED_FORM_TWO_TRACE_SAME_LAYER) {\n return new TwoCrossingRoutesHighDensitySolver({\n nodeWithPortPoints: this.nodeWithPortPoints,\n }) as any\n }\n if (hyperParameters.CLOSED_FORM_TWO_TRACE_TRANSITION_CROSSING) {\n return new SingleTransitionCrossingRouteSolver({\n nodeWithPortPoints: this.nodeWithPortPoints,\n }) as any\n }\n return new IntraNodeRouteSolver({\n ...this.constructorParams,\n hyperParameters,\n })\n }\n\n onSolve(solver: SupervisedSolver<IntraNodeRouteSolver>) {\n this.solvedRoutes = solver.solver.solvedRoutes\n }\n}\n","interface RoutePoint {\n x: number\n y: number\n z: number\n}\n\ninterface MergedSegment {\n points: { x: number; y: number }[]\n z: number\n connectionName: string\n color: string\n}\n\n/**\n * Merges consecutive route points with the same z-coordinate into segments\n * @param route Array of route points\n * @param connectionName Name of the connection\n * @param color Color for the segment\n * @returns Array of merged segments\n */\nexport function mergeRouteSegments(\n route: RoutePoint[],\n connectionName: string,\n color: string,\n): MergedSegment[] {\n const segments: MergedSegment[] = []\n let currentSegment: MergedSegment | null = null\n\n for (let i = 0; i < route.length; i++) {\n const point = route[i]\n\n if (!currentSegment) {\n currentSegment = {\n points: [{ x: point.x, y: point.y }],\n z: point.z,\n connectionName,\n color,\n }\n } else if (currentSegment.z === point.z) {\n currentSegment.points.push({ x: point.x, y: point.y })\n } else {\n segments.push(currentSegment)\n currentSegment = {\n points: [{ x: point.x, y: point.y }],\n z: point.z,\n connectionName,\n color,\n }\n }\n\n // Add final segment if we're at the last point\n if (i === route.length - 1 && currentSegment) {\n segments.push(currentSegment)\n }\n }\n\n return segments\n}\n","import type {\n HighDensityIntraNodeRoute,\n NodeWithPortPoints,\n} from \"../../types/high-density-types\"\nimport type { GraphicsObject } from \"graphics-debug\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { safeTransparentize } from \"../colors\"\nimport { IntraNodeRouteSolver } from \"./IntraNodeSolver\"\nimport { HyperSingleIntraNodeSolver } from \"../HyperHighDensitySolver/HyperSingleIntraNodeSolver\"\nimport { combineVisualizations } from \"lib/utils/combineVisualizations\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport { mergeRouteSegments } from \"lib/utils/mergeRouteSegments\"\n\nexport class HighDensitySolver extends BaseSolver {\n unsolvedNodePortPoints: NodeWithPortPoints[]\n routes: HighDensityIntraNodeRoute[]\n colorMap: Record<string, string>\n\n // Defaults as specified: viaDiameter of 0.6 and traceThickness of 0.15\n readonly defaultViaDiameter = 0.6\n readonly defaultTraceThickness = 0.15\n\n failedSolvers: (IntraNodeRouteSolver | HyperSingleIntraNodeSolver)[]\n activeSubSolver: IntraNodeRouteSolver | HyperSingleIntraNodeSolver | null =\n null\n connMap?: ConnectivityMap\n\n constructor({\n nodePortPoints,\n colorMap,\n connMap,\n }: {\n nodePortPoints: NodeWithPortPoints[]\n colorMap?: Record<string, string>\n connMap?: ConnectivityMap\n }) {\n super()\n this.unsolvedNodePortPoints = nodePortPoints\n this.colorMap = colorMap ?? {}\n this.connMap = connMap\n this.routes = []\n this.failedSolvers = []\n this.MAX_ITERATIONS = 1e6\n }\n\n /**\n * Each iteration, pop an unsolved node and attempt to find the routes inside\n * of it.\n */\n _step() {\n if (this.activeSubSolver) {\n this.activeSubSolver.step()\n if (this.activeSubSolver.solved) {\n this.routes.push(...this.activeSubSolver.solvedRoutes)\n this.activeSubSolver = null\n } else if (this.activeSubSolver.failed) {\n this.failedSolvers.push(this.activeSubSolver)\n this.activeSubSolver = null\n }\n return\n }\n if (this.unsolvedNodePortPoints.length === 0) {\n this.solved = true\n return\n }\n const node = this.unsolvedNodePortPoints.pop()!\n\n this.activeSubSolver = new HyperSingleIntraNodeSolver({\n nodeWithPortPoints: node,\n colorMap: this.colorMap,\n connMap: this.connMap,\n })\n }\n\n visualize(): GraphicsObject {\n let graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n for (const route of this.routes) {\n // Merge segments based on z-coordinate\n const mergedSegments = mergeRouteSegments(\n route.route,\n route.connectionName,\n this.colorMap[route.connectionName],\n )\n\n // Add merged segments to graphics\n for (const segment of mergedSegments) {\n graphics.lines!.push({\n points: segment.points,\n label: segment.connectionName,\n strokeColor:\n segment.z === 0\n ? segment.color\n : safeTransparentize(segment.color, 0.75),\n strokeWidth: route.traceThickness,\n strokeDash: segment.z !== 0 ? \"10, 5\" : undefined,\n })\n }\n for (const via of route.vias) {\n graphics.circles!.push({\n center: via,\n radius: route.viaDiameter / 2,\n fill: this.colorMap[route.connectionName],\n label: `${route.connectionName} via`,\n })\n }\n }\n for (const solver of this.failedSolvers) {\n const node = solver.nodeWithPortPoints\n // Group port points by connectionName\n const connectionGroups: Record<\n string,\n { x: number; y: number; z: number }[]\n > = {}\n for (const pt of node.portPoints) {\n if (!connectionGroups[pt.connectionName]) {\n connectionGroups[pt.connectionName] = []\n }\n connectionGroups[pt.connectionName].push({ x: pt.x, y: pt.y, z: pt.z })\n }\n\n for (const [connectionName, points] of Object.entries(connectionGroups)) {\n for (let i = 0; i < points.length - 1; i++) {\n const start = points[i]\n const end = points[i + 1]\n graphics.lines!.push({\n points: [start, end],\n strokeColor: \"red\",\n strokeDash: \"10, 5\",\n })\n }\n }\n }\n if (this.activeSubSolver) {\n graphics = combineVisualizations(\n graphics,\n this.activeSubSolver.visualize(),\n )\n }\n return graphics\n }\n}\n","type NodeId = string\n\nexport function findConnectedNetworks(\n connections: Array<NodeId[]>,\n): Record<string, string[]> {\n const networks: Map<string, Set<string>> = new Map()\n let netCounter = 0\n\n function getOrCreateNetwork(nodeId: string): Set<string> {\n for (const [, network] of networks) {\n if (network.has(nodeId)) {\n return network\n }\n }\n const newNetwork = new Set<string>()\n networks.set(`connectivity_net${netCounter++}`, newNetwork)\n return newNetwork\n }\n\n for (const connection of connections) {\n let network: Set<string> | null = null\n\n for (const nodeId of connection) {\n if (!network) {\n network = getOrCreateNetwork(nodeId)\n } else if (!network.has(nodeId)) {\n const existingNetwork = getOrCreateNetwork(nodeId)\n if (existingNetwork !== network) {\n // Merge networks\n for (const node of existingNetwork) {\n network.add(node)\n }\n networks.delete(\n Array.from(networks.entries()).find(\n ([, net]) => net === existingNetwork,\n )![0],\n )\n }\n }\n network.add(nodeId)\n }\n }\n\n return Object.fromEntries(\n Array.from(networks.entries()).map(([netId, connectedNodes]) => [\n netId,\n Array.from(connectedNodes),\n ]),\n )\n}\n","export class ConnectivityMap {\n netMap: Record<string, string[]>\n\n idToNetMap: Record<string, string>\n\n constructor(netMap: Record<string, string[]>) {\n this.netMap = netMap\n this.idToNetMap = {}\n for (const [netId, ids] of Object.entries(netMap)) {\n for (const id of ids) {\n this.idToNetMap[id] = netId\n }\n }\n }\n\n addConnections(connections: string[][]) {\n for (const connection of connections) {\n const existingNets = new Set<string>()\n\n // Find all existing nets for the connection\n for (const id of connection) {\n const existingNetId = this.idToNetMap[id]\n if (existingNetId) {\n existingNets.add(existingNetId)\n }\n }\n\n let targetNetId: string\n\n if (existingNets.size === 0) {\n // If no existing nets found, create a new one\n targetNetId = `connectivity_net${Object.keys(this.netMap).length}`\n this.netMap[targetNetId] = []\n } else if (existingNets.size === 1) {\n // If only one existing net found, use it\n targetNetId =\n existingNets.values().next().value ??\n `connectivity_net${Object.keys(this.netMap).length}`\n } else {\n // If multiple nets found, merge them\n targetNetId =\n existingNets.values().next().value ??\n `connectivity_net${Object.keys(this.netMap).length}`\n for (const netId of existingNets) {\n if (netId !== targetNetId) {\n this.netMap[targetNetId].push(...this.netMap[netId])\n\n // we could delete the net, but setting it to reference the other net\n // will make sure any usage of the old netId will still work\n this.netMap[netId] = this.netMap[targetNetId]\n for (const id of this.netMap[targetNetId]) {\n this.idToNetMap[id] = targetNetId\n }\n }\n }\n }\n\n // Add all ids to the target net\n for (const id of connection) {\n if (!this.netMap[targetNetId].includes(id)) {\n this.netMap[targetNetId].push(id)\n }\n this.idToNetMap[id] = targetNetId\n }\n }\n }\n\n getIdsConnectedToNet(netId: string): string[] {\n return this.netMap[netId] || []\n }\n\n getNetConnectedToId(id: string): string | undefined {\n return this.idToNetMap[id]\n }\n\n areIdsConnected(id1: string, id2: string): boolean {\n if (id1 === id2) return true\n const netId1 = this.getNetConnectedToId(id1)\n if (!netId1) return false\n const netId2 = this.getNetConnectedToId(id2)\n if (!netId2) return false\n return netId1 === netId2 || netId2 === id1 || netId2 === id1\n }\n\n areAllIdsConnected(ids: string[]): boolean {\n const netId = this.getNetConnectedToId(ids[0])\n for (const id of ids) {\n const nextNetId = this.getNetConnectedToId(id)\n if (nextNetId === undefined) {\n return false\n }\n if (nextNetId !== netId) {\n return false\n }\n }\n return true\n }\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getSourcePortConnectivityMapFromCircuitJson = (\n circuitJson: AnyCircuitElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push([\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ])\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnyCircuitElement } from \"circuit-json\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\n\nexport const getFullConnectivityMapFromCircuitJson = (\n circuitJson: AnyCircuitElement[],\n) => {\n const connections: string[][] = []\n\n for (const element of circuitJson) {\n if (element.type === \"source_trace\") {\n connections.push(\n [\n element.source_trace_id,\n ...(element.connected_source_port_ids ?? []),\n ...(element.connected_source_net_ids ?? []),\n ].filter(Boolean),\n )\n } else if (element.type === \"pcb_port\") {\n const { pcb_port_id, source_port_id } = element\n if (source_port_id && pcb_port_id) {\n connections.push([source_port_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_smtpad\") {\n const { pcb_smtpad_id, pcb_port_id } = element\n if (pcb_port_id && pcb_smtpad_id) {\n connections.push([pcb_smtpad_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_plated_hole\") {\n const { pcb_plated_hole_id, pcb_port_id } = element\n if (pcb_port_id && pcb_plated_hole_id) {\n connections.push([pcb_plated_hole_id, pcb_port_id])\n }\n } else if (element.type === \"pcb_trace\") {\n const { pcb_trace_id, source_trace_id } = element\n if (source_trace_id && pcb_trace_id) {\n connections.push([pcb_trace_id, source_trace_id])\n }\n }\n }\n\n const netMap = findConnectedNetworks(connections)\n\n return new ConnectivityMap(netMap)\n}\n","import type { AnyCircuitElement, PCBPort, PCBTrace } from \"circuit-json\"\nimport { ConnectivityMap } from \"./ConnectivityMap\"\nimport { doesLineIntersectLine } from \"@tscircuit/math-utils\"\nimport { findConnectedNetworks } from \"./findConnectedNetworks\"\n\n/**\n * A PCB Connectivity Map is a connectivity map that has analyzed what traces and ports are actually connected on the\n * PCB.\n *\n * This is useful for determining how to route a trace on the PCB. For example, you may want to determine where the\n * nearest connected net point is to connect an unrouted pin.\n */\nexport class PcbConnectivityMap {\n circuitJson: AnyCircuitElement[]\n traceIdToElm: Map<string, PCBTrace>\n portIdToElm: Map<string, PCBPort>\n connMap: ConnectivityMap\n\n constructor(circuitJson?: AnyCircuitElement[]) {\n this.circuitJson = circuitJson || []\n this.traceIdToElm = new Map()\n this.portIdToElm = new Map()\n if (circuitJson) {\n this._buildTraceMap()\n this._buildPortMap()\n this.connMap = this._buildTraceConnectivityMap()\n } else {\n this.connMap = new ConnectivityMap({})\n }\n }\n\n private _buildPortMap() {\n for (const element of this.circuitJson) {\n if (element.type === \"pcb_port\") {\n this.portIdToElm.set(element.pcb_port_id, element as PCBPort)\n }\n }\n }\n\n private _buildTraceMap() {\n for (const element of this.circuitJson) {\n if (element.type === \"pcb_trace\") {\n this.traceIdToElm.set(element.pcb_trace_id, element as PCBTrace)\n }\n }\n }\n\n private _buildTraceConnectivityMap(): ConnectivityMap {\n const connections: string[][] = []\n const traceIds = Array.from(this.traceIdToElm.keys())\n\n for (let i = 0; i < traceIds.length; i++) {\n for (let j = i + 1; j < traceIds.length; j++) {\n const trace1 = this.traceIdToElm.get(traceIds[i])!\n const trace2 = this.traceIdToElm.get(traceIds[j])!\n if (this._arePcbTracesConnected(trace1, trace2)) {\n connections.push([traceIds[i], traceIds[j]])\n }\n }\n }\n\n for (const port of this.portIdToElm.values()) {\n for (const trace of this.traceIdToElm.values()) {\n for (const rp of trace.route) {\n if (rp.route_type === \"wire\") {\n if (rp.start_pcb_port_id === port.pcb_port_id) {\n connections.push([port.pcb_port_id, trace.pcb_trace_id])\n } else if (rp.end_pcb_port_id === port.pcb_port_id) {\n connections.push([trace.pcb_trace_id, port.pcb_port_id])\n }\n }\n }\n }\n }\n\n return new ConnectivityMap(findConnectedNetworks(connections))\n }\n\n addTrace(trace: PCBTrace) {\n this.traceIdToElm.set(trace.pcb_trace_id, trace)\n const connections: string[][] = []\n for (const rp of trace.route) {\n if (rp.route_type === \"wire\") {\n if (rp.start_pcb_port_id) {\n connections.push([rp.start_pcb_port_id, trace.pcb_trace_id])\n }\n if (rp.end_pcb_port_id) {\n connections.push([rp.end_pcb_port_id, trace.pcb_trace_id])\n }\n }\n }\n\n this.connMap.addConnections(connections)\n }\n\n _arePcbTracesConnected(trace1: PCBTrace, trace2: PCBTrace): boolean {\n for (let i = 0; i < trace1.route.length - 1; i++) {\n const segment1A = trace1.route[i]\n const segment1B = trace1.route[i + 1]\n if (segment1A.route_type !== \"wire\") continue\n if (segment1B.route_type !== \"wire\") continue\n for (let j = 0; j < trace2.route.length - 1; j++) {\n const segment2A = trace2.route[j]\n const segment2B = trace2.route[j + 1]\n\n if (segment2A.route_type !== \"wire\") continue\n if (segment2B.route_type !== \"wire\") continue\n\n // Check if lines are overlapping\n const isOverlapping = doesLineIntersectLine(\n [segment1A, segment1B],\n [segment2A, segment2B],\n {\n lineThickness: (segment1A.width + segment2A.width) / 2,\n },\n )\n if (isOverlapping) {\n return true\n }\n }\n }\n return false\n }\n\n areTracesConnected(traceId1: string, traceId2: string): boolean {\n return this.connMap.areIdsConnected(traceId1, traceId2)\n }\n\n getAllTracesConnectedToTrace(traceId: string): PCBTrace[] {\n const netId = this.connMap.getNetConnectedToId(traceId)\n return netId\n ? this.connMap\n .getIdsConnectedToNet(netId)\n .filter((id) => this.traceIdToElm.has(id))\n .map((id) => this.traceIdToElm.get(id) as PCBTrace)\n : []\n }\n\n getAllTracesConnectedToPort(portId: string): PCBTrace[] {\n const netId = this.connMap.getNetConnectedToId(portId)\n return netId\n ? this.connMap\n .getIdsConnectedToNet(netId)\n .filter((id) => this.traceIdToElm.has(id))\n .map((id) => this.traceIdToElm.get(id) as PCBTrace)\n : []\n }\n}\n","import { SimpleRouteJson } from \"lib/types\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\n\nexport const getConnectivityMapFromSimpleRouteJson = (srj: SimpleRouteJson) => {\n const connMap = new ConnectivityMap({})\n for (const connection of srj.connections) {\n for (const point of connection.pointsToConnect) {\n if (\"pcb_port_id\" in point && point.pcb_port_id) {\n connMap.addConnections([[connection.name, point.pcb_port_id as string]])\n }\n }\n }\n for (const obstacle of srj.obstacles) {\n connMap.addConnections([obstacle.connectedTo])\n }\n return connMap\n}\n","type Point = { x: number; y: number }\n\nexport class KDNode {\n point: Point\n left: KDNode | null = null\n right: KDNode | null = null\n\n constructor(point: Point) {\n this.point = point\n }\n}\n\nclass KDTree {\n root: KDNode | null = null\n\n constructor(points: Point[]) {\n if (points.length > 0) {\n this.root = this.buildTree(points, 0)\n }\n }\n\n private buildTree(points: Point[], depth: number): KDNode {\n const axis = depth % 2 === 0 ? \"x\" : \"y\"\n\n // Sort points by the current axis\n points.sort((a, b) => a[axis] - b[axis])\n\n // Choose median as the pivot element\n const medianIndex = Math.floor(points.length / 2)\n const node = new KDNode(points[medianIndex])\n\n // Recursively build left and right subtrees\n if (medianIndex > 0) {\n node.left = this.buildTree(points.slice(0, medianIndex), depth + 1)\n }\n\n if (medianIndex < points.length - 1) {\n node.right = this.buildTree(points.slice(medianIndex + 1), depth + 1)\n }\n\n return node\n }\n\n // Find the nearest neighbor to a query point\n findNearestNeighbor(queryPoint: Point): Point {\n if (!this.root) {\n throw new Error(\"Tree is empty\")\n }\n\n const best: Point = this.root.point\n const bestDistance = this.distance(queryPoint, best)\n\n this.nearestNeighborSearch(this.root, queryPoint, 0, best, bestDistance)\n\n return best\n }\n\n private nearestNeighborSearch(\n node: KDNode | null,\n queryPoint: Point,\n depth: number,\n best: Point,\n bestDistance: number,\n ): Point {\n if (!node) {\n return best\n }\n\n const axis = depth % 2 ? \"x\" : \"y\"\n const currentDistance = this.distance(queryPoint, node.point)\n\n if (currentDistance < bestDistance) {\n best = node.point\n bestDistance = currentDistance\n }\n\n // Determine which subtree to search first\n const axisDiff = queryPoint[axis] - node.point[axis]\n const firstBranch = axisDiff <= 0 ? node.left : node.right\n const secondBranch = axisDiff <= 0 ? node.right : node.left\n\n // Recursively search the first branch\n best = this.nearestNeighborSearch(\n firstBranch,\n queryPoint,\n depth + 1,\n best,\n bestDistance,\n )\n bestDistance = this.distance(queryPoint, best)\n\n // Check if we need to search the second branch\n if (Math.abs(axisDiff) < bestDistance) {\n best = this.nearestNeighborSearch(\n secondBranch,\n queryPoint,\n depth + 1,\n best,\n bestDistance,\n )\n }\n\n return best\n }\n\n // Find k nearest neighbors\n findKNearestNeighbors(queryPoint: Point, k: number): Point[] {\n if (!this.root) {\n return []\n }\n\n const neighbors: Array<{ point: Point; distance: number }> = []\n\n this.kNearestNeighborSearch(this.root, queryPoint, 0, neighbors, k)\n\n return neighbors\n .sort((a, b) => a.distance - b.distance)\n .slice(0, k)\n .map((n) => n.point)\n }\n\n private kNearestNeighborSearch(\n node: KDNode | null,\n queryPoint: Point,\n depth: number,\n neighbors: Array<{ point: Point; distance: number }>,\n k: number,\n ): void {\n if (!node) {\n return\n }\n\n const axis = depth % 2 ? \"x\" : \"y\"\n const currentDistance = this.distance(queryPoint, node.point)\n\n // Add current node to neighbors\n neighbors.push({ point: node.point, distance: currentDistance })\n\n // Determine which subtree to search first\n const axisDiff = queryPoint[axis] - node.point[axis]\n const firstBranch = axisDiff <= 0 ? node.left : node.right\n const secondBranch = axisDiff <= 0 ? node.right : node.left\n\n // Recursively search the first branch\n this.kNearestNeighborSearch(\n firstBranch,\n queryPoint,\n depth + 1,\n neighbors,\n k,\n )\n\n // Get the kth distance if we have k neighbors\n let kthDistance = Infinity\n if (neighbors.length >= k) {\n neighbors.sort((a, b) => a.distance - b.distance)\n kthDistance = neighbors[k - 1]?.distance || Infinity\n }\n\n // Search the other branch if necessary\n if (Math.abs(axisDiff) < kthDistance || neighbors.length < k) {\n this.kNearestNeighborSearch(\n secondBranch,\n queryPoint,\n depth + 1,\n neighbors,\n k,\n )\n }\n }\n\n // Calculate Euclidean distance between two points\n private distance(a: Point, b: Point): number {\n return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2)\n }\n}\n\n// Disjoint Set (Union-Find) data structure for Kruskal's algorithm\nexport class DisjointSet {\n private parent: Map<string, string> = new Map()\n private rank: Map<string, number> = new Map()\n\n constructor(points: Point[]) {\n // Initialize each point as a separate set\n for (const point of points) {\n const key = this.pointToKey(point)\n this.parent.set(key, key)\n this.rank.set(key, 0)\n }\n }\n\n private pointToKey(point: Point): string {\n return `${point.x},${point.y}`\n }\n\n find(point: Point): string {\n const key = this.pointToKey(point)\n if (!this.parent.has(key)) {\n throw new Error(`Point ${key} not found in DisjointSet`)\n }\n\n let root = key\n while (root !== this.parent.get(root)) {\n root = this.parent.get(root)!\n }\n\n // Path compression\n let current = key\n while (current !== root) {\n const next = this.parent.get(current)!\n this.parent.set(current, root)\n current = next\n }\n\n return root\n }\n\n union(pointA: Point, pointB: Point): boolean {\n const rootA = this.find(pointA)\n const rootB = this.find(pointB)\n\n if (rootA === rootB) {\n return false // Already in the same set\n }\n\n // Union by rank\n const rankA = this.rank.get(rootA) || 0\n const rankB = this.rank.get(rootB) || 0\n\n if (rankA < rankB) {\n this.parent.set(rootA, rootB)\n } else if (rankA > rankB) {\n this.parent.set(rootB, rootA)\n } else {\n this.parent.set(rootB, rootA)\n this.rank.set(rootA, rankA + 1)\n }\n\n return true\n }\n}\n\n// Edge representation for Kruskal's algorithm\ninterface Edge<T extends Point> {\n from: T\n to: T\n weight: number\n}\n\n// Main function to build a minimum spanning tree using Kruskal's algorithm\nexport function buildMinimumSpanningTree<T extends Point>(\n points: T[],\n): Edge<T>[] {\n if (points.length <= 1) {\n return []\n }\n\n // Build KD-Tree for efficient nearest neighbor search\n const kdTree = new KDTree(points)\n\n // Generate edges with k-nearest neighbors for each point\n // This is an optimization to avoid generating all possible n(n-1)/2 edges\n const edges: Edge<T>[] = []\n const k = Math.min(10, points.length - 1) // Consider k nearest neighbors\n\n for (const point of points) {\n const neighbors = kdTree.findKNearestNeighbors(point, k + 1) // +1 because it includes the point itself\n\n for (const neighbor of neighbors) {\n // Skip self\n if (point.x === neighbor.x && point.y === neighbor.y) {\n continue\n }\n\n const distance = Math.sqrt(\n (point.x - neighbor.x) ** 2 + (point.y - neighbor.y) ** 2,\n )\n\n edges.push({\n from: point,\n to: neighbor as T,\n weight: distance,\n })\n }\n }\n\n // Sort edges by weight (distance)\n edges.sort((a, b) => a.weight - b.weight)\n\n // Apply Kruskal's algorithm\n const disjointSet = new DisjointSet(points)\n const mstEdges: Edge<T>[] = []\n\n for (const edge of edges) {\n if (disjointSet.union(edge.from, edge.to)) {\n mstEdges.push(edge)\n\n // MST has n-1 edges for n points\n if (mstEdges.length === points.length - 1) {\n break\n }\n }\n }\n\n return mstEdges\n}\n","import { SimpleRouteConnection, SimpleRouteJson } from \"lib/types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { buildMinimumSpanningTree } from \"./buildMinimumSpanningTree\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { seededRandom } from \"lib/utils/cloneAndShuffleArray\"\n\n/**\n * Converts a net containing many points to connect into an array of point pair\n * connections.\n *\n * For example, a connection with 3 pointsToConnect could be turned into 2\n * connections of 2 points each.\n *\n * Where we create the minimum number of pairs, we're using a minimum spanning\n * tree (MST).\n *\n * Sometimes it can be used to add additional traces to help make sure we\n * distribute load effectively. In this version we don't do that!\n */\nexport class NetToPointPairsSolver extends BaseSolver {\n unprocessedConnections: Array<SimpleRouteConnection>\n newConnections: Array<SimpleRouteConnection>\n\n constructor(\n public ogSrj: SimpleRouteJson,\n public colorMap: Record<string, string> = {},\n ) {\n super()\n this.unprocessedConnections = [...ogSrj.connections]\n this.newConnections = []\n }\n\n _step() {\n if (this.unprocessedConnections.length === 0) {\n this.solved = true\n return\n }\n const connection = this.unprocessedConnections.pop()!\n if (connection.pointsToConnect.length === 2) {\n this.newConnections.push(connection)\n return\n }\n\n const edges = buildMinimumSpanningTree(connection.pointsToConnect)\n\n for (let i = 0; i < edges.length; i++) {\n const edge = edges[i]\n this.newConnections.push({\n pointsToConnect: [edge.from, edge.to],\n name: `${connection.name}_mst${i}`,\n })\n }\n }\n\n getNewSimpleRouteJson(): SimpleRouteJson {\n return {\n ...this.ogSrj,\n connections: this.newConnections,\n }\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Net To Point Pairs Visualization\",\n }\n\n // Draw unprocessed connections in red\n this.unprocessedConnections.forEach((connection) => {\n // Draw points\n connection.pointsToConnect.forEach((point) => {\n graphics.points!.push({\n x: point.x,\n y: point.y,\n color: \"red\",\n label: connection.name,\n })\n })\n\n // Draw lines connecting all points in the connection\n const fullyConnectedEdgeCount = connection.pointsToConnect.length ** 2\n const random = seededRandom(0)\n const alreadyPlacedEdges = new Set<string>()\n for (\n let i = 0;\n i <\n Math.max(\n fullyConnectedEdgeCount,\n connection.pointsToConnect.length * 2,\n );\n i++\n ) {\n const a = Math.floor(random() * connection.pointsToConnect.length)\n const b = Math.floor(random() * connection.pointsToConnect.length)\n if (alreadyPlacedEdges.has(`${a}-${b}`)) continue\n alreadyPlacedEdges.add(`${a}-${b}`)\n graphics.lines!.push({\n points: [\n connection.pointsToConnect[a],\n connection.pointsToConnect[b],\n ],\n strokeColor: \"rgba(255,0,0,0.25)\",\n })\n }\n })\n\n // Draw processed connections with appropriate colors\n this.newConnections.forEach((connection) => {\n const color = this.colorMap?.[connection.name] || \"blue\"\n\n // Draw points\n connection.pointsToConnect.forEach((point) => {\n graphics.points!.push({\n x: point.x,\n y: point.y,\n color: color,\n label: connection.name,\n })\n })\n\n // Draw lines connecting all points in the connection\n for (let i = 0; i < connection.pointsToConnect.length - 1; i++) {\n for (let j = i + 1; j < connection.pointsToConnect.length; j++) {\n graphics.lines!.push({\n points: [\n connection.pointsToConnect[i],\n connection.pointsToConnect[j],\n ],\n strokeColor: color,\n })\n }\n }\n })\n\n return graphics\n }\n}\n","export type LayerName =\n | \"top\"\n | \"bottom\"\n | \"inner1\"\n | \"inner2\"\n | \"inner3\"\n | \"inner4\"\n | \"inner5\"\n | \"inner6\"\n\nexport const mapZToLayerName = (z: number, layerCount: number): LayerName => {\n if (z < 0 || z >= layerCount) {\n throw new Error(`Invalid z \"${z}\" for layer count: ${layerCount}`)\n }\n\n if (z === 0) return \"top\"\n if (z === layerCount - 1) return \"bottom\"\n return `inner${z}` as any\n}\n","import { SimplifiedPcbTraces } from \"lib/types\"\nimport { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { mapZToLayerName } from \"./mapZToLayerName\"\n\ntype Point = { x: number; y: number; z: number }\n\nexport const convertHdRouteToSimplifiedRoute = (\n hdRoute: HighDensityIntraNodeRoute,\n layerCount: number,\n): SimplifiedPcbTraces[number][\"route\"] => {\n const result: SimplifiedPcbTraces[number][\"route\"] = []\n if (hdRoute.route.length === 0) return result\n\n let currentLayerPoints: Point[] = []\n let currentZ = hdRoute.route[0].z\n\n // Add all points to their respective layer segments\n for (let i = 0; i < hdRoute.route.length; i++) {\n const point = hdRoute.route[i]\n\n // If we're changing layers, process the current layer's points\n // and add a via if one exists at this position\n if (point.z !== currentZ) {\n // Add all wire segments for the current layer\n const layerName = mapZToLayerName(currentZ, layerCount)\n for (const layerPoint of currentLayerPoints) {\n result.push({\n route_type: \"wire\",\n x: layerPoint.x,\n y: layerPoint.y,\n width: hdRoute.traceThickness,\n layer: layerName,\n })\n }\n\n // Check if a via exists at this position\n const viaExists = hdRoute.vias.some(\n (via) =>\n Math.abs(via.x - point.x) < 0.001 &&\n Math.abs(via.y - point.y) < 0.001,\n )\n\n // Add a via if one exists\n if (viaExists) {\n const fromLayer = mapZToLayerName(currentZ, layerCount)\n const toLayer = mapZToLayerName(point.z, layerCount)\n\n result.push({\n route_type: \"via\",\n x: point.x,\n y: point.y,\n from_layer: fromLayer,\n to_layer: toLayer,\n })\n }\n\n // Start a new layer\n currentLayerPoints = [point]\n currentZ = point.z\n } else {\n // Continue on the same layer\n currentLayerPoints.push(point)\n }\n }\n\n // Add the final layer's wire segments\n const layerName = mapZToLayerName(currentZ, layerCount)\n for (const layerPoint of currentLayerPoints) {\n result.push({\n route_type: \"wire\",\n x: layerPoint.x,\n y: layerPoint.y,\n width: hdRoute.traceThickness,\n layer: layerName,\n })\n }\n\n return result\n}\n","import { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { distance } from \"@tscircuit/math-utils\"\n\nexport class SingleHighDensityRouteStitchSolver extends BaseSolver {\n mergedHdRoute: HighDensityIntraNodeRoute\n remainingHdRoutes: HighDensityIntraNodeRoute[]\n start: { x: number; y: number; z: number }\n end: { x: number; y: number; z: number }\n\n constructor(opts: {\n connectionName?: string\n hdRoutes: HighDensityIntraNodeRoute[]\n start: { x: number; y: number; z: number }\n end: { x: number; y: number; z: number }\n }) {\n super()\n this.remainingHdRoutes = [...opts.hdRoutes]\n this.mergedHdRoute = {\n connectionName: opts.connectionName ?? opts.hdRoutes[0].connectionName,\n route: [\n {\n x: opts.start.x,\n y: opts.start.y,\n z: opts.start.z,\n },\n ],\n vias: [],\n viaDiameter: opts.hdRoutes?.[0]?.viaDiameter ?? 0.6,\n traceThickness: opts.hdRoutes?.[0]?.traceThickness ?? 0.15,\n }\n this.start = opts.start\n this.end = opts.end\n }\n\n _step() {\n if (this.remainingHdRoutes.length === 0) {\n // Add the end point to the merged route\n this.mergedHdRoute.route.push({\n x: this.end.x,\n y: this.end.y,\n z: this.end.z,\n })\n this.solved = true\n return\n }\n\n const lastMergedPoint =\n this.mergedHdRoute.route[this.mergedHdRoute.route.length - 1]\n\n // Find the next logical route to merge\n // 1. We need to check both the first and last points of the remaining routes\n // 2. If the last point is closest, we need to reverse the hd route before merging\n // 3. After merging, we remove it from the remaining routes\n\n let closestRouteIndex = 0\n let matchedOn: \"first\" | \"last\" = \"first\"\n let closestDistance = Infinity\n for (let i = 0; i < this.remainingHdRoutes.length; i++) {\n const hdRoute = this.remainingHdRoutes[i]\n const lastPointInCandidate = hdRoute.route[hdRoute.route.length - 1]\n const firstPointInCandidate = hdRoute.route[0]\n const distToFirst = distance(lastMergedPoint, firstPointInCandidate)\n const distToLast = distance(lastMergedPoint, lastPointInCandidate)\n if (distToFirst < closestDistance) {\n closestDistance = distToFirst\n closestRouteIndex = i\n matchedOn = \"first\"\n }\n if (distToLast < closestDistance) {\n closestDistance = distToLast\n closestRouteIndex = i\n matchedOn = \"last\"\n }\n }\n\n const hdRouteToMerge = this.remainingHdRoutes[closestRouteIndex]\n this.remainingHdRoutes.splice(closestRouteIndex, 1)\n\n if (matchedOn === \"first\") {\n this.mergedHdRoute.route.push(...hdRouteToMerge.route)\n } else {\n this.mergedHdRoute.route.push(...[...hdRouteToMerge.route].reverse())\n }\n\n this.mergedHdRoute.vias.push(...hdRouteToMerge.vias)\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n points: [],\n lines: [],\n circles: [],\n title: \"Single High Density Route Stitch Solver\",\n }\n\n // Visualize start and end points\n graphics.points?.push(\n {\n x: this.start.x,\n y: this.start.y,\n color: \"green\",\n label: \"Start\",\n },\n {\n x: this.end.x,\n y: this.end.y,\n color: \"red\",\n label: \"End\",\n },\n )\n\n // Visualize the merged HD route in green\n if (this.mergedHdRoute && this.mergedHdRoute.route.length > 1) {\n graphics.lines?.push({\n points: this.mergedHdRoute.route.map((point) => ({\n x: point.x,\n y: point.y,\n })),\n strokeColor: \"green\",\n })\n\n // Add points for the merged route\n for (const point of this.mergedHdRoute.route) {\n graphics.points?.push({\n x: point.x,\n y: point.y,\n color: \"green\",\n })\n }\n\n // Visualize vias in the merged route\n for (const via of this.mergedHdRoute.vias) {\n graphics.circles?.push({\n center: { x: via.x, y: via.y },\n radius: this.mergedHdRoute.viaDiameter / 2,\n fill: \"green\",\n })\n }\n }\n\n // Visualize all remaining HD routes\n const colorList = Array.from(\n { length: this.remainingHdRoutes.length },\n (_, i) => `hsl(${(i * 360) / this.remainingHdRoutes.length}, 100%, 50%)`,\n )\n for (const [i, hdRoute] of this.remainingHdRoutes.entries()) {\n if (hdRoute.route.length > 1) {\n // Create a line for the route\n graphics.lines?.push({\n points: hdRoute.route.map((point) => ({ x: point.x, y: point.y })),\n strokeColor: colorList[i],\n })\n }\n\n // Add points for each route node\n for (let pi = 0; pi < hdRoute.route.length; pi++) {\n const point = hdRoute.route[pi]\n graphics.points?.push({\n x: point.x + ((i % 2) - 0.5) / 500 + ((pi % 8) - 4) / 1000,\n y: point.y + ((i % 2) - 0.5) / 500 + ((pi % 8) - 4) / 1000,\n color: colorList[i],\n label: `Route ${i} ${point === hdRoute.route[0] ? \"First\" : point === hdRoute.route[hdRoute.route.length - 1] ? \"Last\" : \"\"}`,\n })\n }\n\n // Visualize vias\n for (const via of hdRoute.vias) {\n graphics.circles?.push({\n center: { x: via.x, y: via.y },\n radius: hdRoute.viaDiameter / 2,\n fill: colorList[i],\n })\n }\n }\n\n return graphics\n }\n}\n","import { SimpleRouteConnection } from \"lib/types\"\nimport { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { mapLayerNameToZ } from \"lib/utils/mapLayerNameToZ\"\nimport { SingleHighDensityRouteStitchSolver } from \"./SingleHighDensityRouteStitchSolver\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { safeTransparentize } from \"../colors\"\n\nexport type UnsolvedRoute = {\n connectionName: string\n hdRoutes: HighDensityIntraNodeRoute[]\n start: { x: number; y: number; z: number }\n end: { x: number; y: number; z: number }\n}\n\nexport class MultipleHighDensityRouteStitchSolver extends BaseSolver {\n unsolvedRoutes: UnsolvedRoute[]\n activeSolver: SingleHighDensityRouteStitchSolver | null = null\n mergedHdRoutes: HighDensityIntraNodeRoute[] = []\n\n constructor(opts: {\n connections: SimpleRouteConnection[]\n hdRoutes: HighDensityIntraNodeRoute[]\n layerCount: number\n }) {\n super()\n this.unsolvedRoutes = opts.connections.map((c) => ({\n connectionName: c.name,\n hdRoutes: opts.hdRoutes.filter((r) => r.connectionName === c.name),\n start: {\n ...c.pointsToConnect[0],\n z: mapLayerNameToZ(c.pointsToConnect[0].layer, opts.layerCount),\n },\n end: {\n ...c.pointsToConnect[1],\n z: mapLayerNameToZ(c.pointsToConnect[1].layer, opts.layerCount),\n },\n }))\n this.MAX_ITERATIONS = 100e3\n }\n\n _step() {\n if (this.activeSolver) {\n this.activeSolver.step()\n if (this.activeSolver.solved) {\n this.mergedHdRoutes.push(this.activeSolver.mergedHdRoute)\n this.activeSolver = null\n } else if (this.activeSolver.failed) {\n this.failed = true\n this.error = this.activeSolver.error\n }\n return\n }\n\n const unsolvedRoute = this.unsolvedRoutes.pop()\n\n if (!unsolvedRoute) {\n this.solved = true\n return\n }\n\n this.activeSolver = new SingleHighDensityRouteStitchSolver({\n connectionName: unsolvedRoute.connectionName,\n hdRoutes: unsolvedRoute.hdRoutes,\n start: unsolvedRoute.start,\n end: unsolvedRoute.end,\n })\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n points: [],\n lines: [],\n circles: [],\n title: \"Multiple High Density Route Stitch Solver\",\n }\n\n // Visualize the active solver if one exists\n if (this.activeSolver) {\n // Combine visualizations from the active solver\n const activeSolverGraphics = this.activeSolver.visualize()\n\n // Merge points\n if (activeSolverGraphics.points?.length) {\n graphics.points?.push(...activeSolverGraphics.points)\n }\n\n // Merge lines\n if (activeSolverGraphics.lines?.length) {\n graphics.lines?.push(...activeSolverGraphics.lines)\n }\n\n // Merge circles\n if (activeSolverGraphics.circles?.length) {\n graphics.circles?.push(...activeSolverGraphics.circles)\n }\n\n // Merge rects if they exist\n if (activeSolverGraphics.rects?.length) {\n graphics.rects = activeSolverGraphics.rects\n }\n }\n\n // Visualize all merged HD routes that have been solved\n for (const [i, mergedRoute] of this.mergedHdRoutes.entries()) {\n const solvedColor = `hsl(120, 100%, ${40 + ((i * 10) % 40)}%)` // Different shades of green\n\n // Visualize the route path\n if (mergedRoute.route.length > 1) {\n graphics.lines?.push({\n points: mergedRoute.route.map((point) => ({\n x: point.x,\n y: point.y,\n })),\n strokeColor: solvedColor,\n strokeWidth: mergedRoute.traceThickness,\n })\n }\n\n // Visualize route points\n for (const point of mergedRoute.route) {\n graphics.points?.push({\n x: point.x,\n y: point.y,\n color: solvedColor,\n })\n }\n\n // Visualize vias in the merged route\n for (const via of mergedRoute.vias) {\n graphics.circles?.push({\n center: { x: via.x, y: via.y },\n radius: mergedRoute.viaDiameter / 2,\n fill: solvedColor,\n })\n }\n }\n\n // Visualize all remaining unsolved routes - start/end points only\n const colorList = Array.from(\n { length: this.unsolvedRoutes.length },\n (_, i) => `hsl(${(i * 360) / this.unsolvedRoutes.length}, 100%, 50%)`,\n )\n for (const [i, unsolvedRoute] of this.unsolvedRoutes.entries()) {\n // Add start and end points for unsolved connections\n graphics.points?.push(\n {\n x: unsolvedRoute.start.x,\n y: unsolvedRoute.start.y,\n color: colorList[i],\n label: `${unsolvedRoute.connectionName} Start`,\n },\n {\n x: unsolvedRoute.end.x,\n y: unsolvedRoute.end.y,\n color: colorList[i],\n label: `${unsolvedRoute.connectionName} End`,\n },\n )\n\n // Add a light dashed line between start and end to show pending connections\n graphics.lines?.push({\n points: [\n { x: unsolvedRoute.start.x, y: unsolvedRoute.start.y },\n { x: unsolvedRoute.end.x, y: unsolvedRoute.end.y },\n ],\n strokeColor: colorList[i],\n strokeDash: \"2 2\",\n })\n\n // Visualize HD routes associated with unsolved routes (faded)\n for (const hdRoute of unsolvedRoute.hdRoutes) {\n if (hdRoute.route.length > 1) {\n graphics.lines?.push({\n points: hdRoute.route.map((point) => ({ x: point.x, y: point.y })),\n strokeColor: safeTransparentize(colorList[i], 0.5),\n strokeDash: \"10 5\",\n })\n }\n\n // Visualize vias\n for (const via of hdRoute.vias) {\n graphics.circles?.push({\n center: { x: via.x, y: via.y },\n radius: hdRoute.viaDiameter / 2,\n fill: colorList[i],\n })\n }\n }\n }\n\n return graphics\n }\n}\n","import { Rect, Line, Circle, Point } from \"graphics-debug\"\nimport { SimpleRouteJson } from \"../../lib/types/srj-types\"\nimport { getColorMap, safeTransparentize } from \"lib/solvers/colors\"\nimport { mapZToLayerName } from \"lib/utils/mapZToLayerName\"\nimport { mapLayerNameToZ } from \"lib/utils/mapLayerNameToZ\"\n\nexport const convertSrjToGraphicsObject = (srj: SimpleRouteJson) => {\n const lines: Line[] = []\n const circles: Circle[] = []\n const points: Point[] = []\n\n const colorMap: Record<string, string> = getColorMap(srj)\n const layerCount = 2\n\n // Add points for each connection's pointsToConnect\n if (srj.connections) {\n for (const connection of srj.connections) {\n for (const point of connection.pointsToConnect) {\n points.push({\n x: point.x,\n y: point.y,\n color: colorMap[connection.name]!,\n layer:\n point.layer ??\n (\"z\" in point\n ? mapZToLayerName(point.z as number, layerCount)\n : \"top\"),\n label: `${connection.name} (${point.layer})`,\n })\n }\n }\n }\n\n // Process each trace\n if (srj.traces) {\n for (const trace of srj.traces) {\n for (let j = 0; j < trace.route.length - 1; j++) {\n const routePoint = trace.route[j]\n const nextRoutePoint = trace.route[j + 1]\n\n if (routePoint.route_type === \"via\") {\n // Add a circle for the via\n circles.push({\n center: { x: routePoint.x, y: routePoint.y },\n radius: 0.3, // 0.6 via diameter\n fill: \"blue\",\n stroke: \"none\",\n layer: \"z0,1\",\n })\n } else if (\n routePoint.route_type === \"wire\" &&\n nextRoutePoint.route_type === \"wire\" &&\n nextRoutePoint.layer === routePoint.layer\n ) {\n // Create a line between consecutive wire segments on the same layer\n lines.push({\n points: [\n { x: routePoint.x, y: routePoint.y },\n { x: nextRoutePoint.x, y: nextRoutePoint.y },\n ],\n layer: `z${mapLayerNameToZ(routePoint.layer, layerCount)}`,\n strokeWidth: 0.15,\n strokeColor: safeTransparentize(\n {\n top: \"red\",\n bottom: \"blue\",\n inner1: \"green\",\n inner2: \"yellow\",\n }[routePoint.layer]!,\n 0.5,\n ),\n // For some reason this is too small, likely a graphics-debug bug\n // strokeWidth: 0.15,\n })\n }\n }\n }\n }\n\n return {\n rects: srj.obstacles.map(\n (o) =>\n ({\n center: o.center,\n width: o.width,\n height: o.height,\n fill: \"rgba(255,0,0,0.5)\",\n layer: `z${o.layers.map(mapLayerNameToZ).join(\",\")}`,\n }) as Rect,\n ),\n circles,\n lines,\n points,\n }\n}\n","import { CapacityMeshNodeId } from \"lib/types\"\n\nexport function getNodesNearNode(params: {\n nodeId: CapacityMeshNodeId\n nodeIdToSegmentIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n segmentIdToNodeIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n hops: number\n}): CapacityMeshNodeId[] {\n const { nodeId, nodeIdToSegmentIds, segmentIdToNodeIds, hops } = params\n\n if (hops === 0) return [nodeId]\n\n const visitedNodes = new Set<CapacityMeshNodeId>([nodeId])\n const exploreQueue: Array<{\n nodeId: CapacityMeshNodeId\n remainingHops: number\n }> = [{ nodeId: nodeId, remainingHops: hops }]\n\n while (exploreQueue.length > 0) {\n const { nodeId: node, remainingHops } = exploreQueue.shift()!\n\n if (remainingHops === 0) continue\n\n const segments = nodeIdToSegmentIds.get(node) || []\n for (const segmentId of segments) {\n const adjacentNodeIds = segmentIdToNodeIds.get(segmentId) || []\n for (const adjacentNodeId of adjacentNodeIds) {\n if (!visitedNodes.has(adjacentNodeId)) {\n visitedNodes.add(adjacentNodeId)\n exploreQueue.push({\n nodeId: adjacentNodeId,\n remainingHops: remainingHops - 1,\n })\n }\n }\n }\n }\n\n return Array.from(visitedNodes)\n}\n","import { SegmentPointId } from \"./types\"\n\nexport const createPointModificationsHash = (\n pointModifications: Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >,\n) => {\n return Array.from(pointModifications.entries())\n .map(\n ([id, { x, y, z }]) =>\n `${id}(${x?.toFixed(3) ?? \"\"},${y?.toFixed(3) ?? \"\"},${z ?? \"\"})`,\n )\n .sort()\n .join(\"&\")\n}\n\nexport const createFullPointModificationsHash = (\n originalPoints: Map<SegmentPointId, { x: number; y: number; z: number }>,\n pointModifications: Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >,\n) => {\n return Array.from(originalPoints.entries())\n .map(([id, originalPoint]) => {\n const mods = pointModifications.get(id)\n const finalPoint = {\n x: mods?.x !== undefined ? mods.x : originalPoint.x,\n y: mods?.y !== undefined ? mods.y : originalPoint.y,\n z: mods?.z !== undefined ? mods.z : originalPoint.z,\n }\n return `${id}(${finalPoint.x.toFixed(3)},${finalPoint.y.toFixed(3)},${finalPoint.z})`\n })\n .sort()\n .join(\"&\")\n}\n","export const hasZRangeOverlap = (\n A_z1: number,\n A_z2: number,\n B_z1: number,\n B_z2: number,\n) => {\n const Amin = Math.min(A_z1, A_z2)\n const Amax = Math.max(A_z1, A_z2)\n const Bmin = Math.min(B_z1, B_z2)\n const Bmax = Math.max(B_z1, B_z2)\n return Amin <= Bmax && Amax >= Bmin\n}\n","import { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\nimport {\n UnravelSection,\n UnravelIssue,\n UnravelTransitionViaIssue,\n SegmentPoint,\n SegmentPointId,\n UnravelSameLayerCrossingIssue,\n UnravelSingleTransitionCrossingIssue,\n UnravelDoubleTransitionCrossingIssue,\n} from \"./types\"\nimport { getIntraNodeCrossingsFromSegments } from \"lib/utils/getIntraNodeCrossingsFromSegments\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\nimport { getLogProbability } from \"./getLogProbability\"\nimport { doSegmentsIntersect } from \"@tscircuit/math-utils\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport { hasZRangeOverlap } from \"./hasZRangeOverlap\"\n\nexport const getIssuesInSection = (\n section: UnravelSection,\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>,\n pointModifications: Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >,\n connMap?: ConnectivityMap,\n): UnravelIssue[] => {\n const issues: UnravelIssue[] = []\n\n const points: Map<SegmentPointId, { x: number; y: number; z: number }> =\n new Map(section.originalPointMap)\n for (const [segmentPointId, modPoint] of pointModifications.entries()) {\n const ogPoint = points.get(segmentPointId)!\n points.set(segmentPointId, {\n x: modPoint.x ?? ogPoint.x,\n y: modPoint.y ?? ogPoint.y,\n z: modPoint.z ?? ogPoint.z,\n })\n }\n\n for (const nodeId of section.allNodeIds) {\n const node = nodeMap.get(nodeId)\n if (!node) continue\n\n const nodeSegmentPairs = section.segmentPairsInNode.get(nodeId)!\n\n // If there's a Z transition within the pair, there's a transition_via issue\n for (const pair of nodeSegmentPairs) {\n const A = points.get(pair[0])!\n const B = points.get(pair[1])!\n if (A.z !== B.z) {\n issues.push({\n type: \"transition_via\",\n segmentPoints: pair,\n capacityMeshNodeId: nodeId,\n probabilityOfFailure: 0,\n })\n }\n }\n\n // Find crossing issues\n for (let i = 0; i < nodeSegmentPairs.length; i++) {\n for (let j = i + 1; j < nodeSegmentPairs.length; j++) {\n if (\n connMap?.areIdsConnected(\n nodeSegmentPairs[i][0],\n nodeSegmentPairs[i][1],\n )\n ) {\n continue\n }\n\n const pair1 = nodeSegmentPairs[i]\n const pair2 = nodeSegmentPairs[j]\n\n const A = points.get(pair1[0])!\n const B = points.get(pair1[1])!\n const C = points.get(pair2[0])!\n const D = points.get(pair2[1])!\n\n // Are the lines ever on the same layer? Is there any risk of overlap?\n if (!hasZRangeOverlap(A.z, B.z, C.z, D.z)) continue\n\n const areCrossing = doSegmentsIntersect(A, B, C, D)\n const isSameLayer = A.z === B.z && C.z === D.z && A.z === C.z\n if (areCrossing) {\n if (isSameLayer) {\n issues.push({\n type: \"same_layer_crossing\",\n segmentPoints: [pair1, pair2],\n capacityMeshNodeId: nodeId,\n crossingLine1: pair1,\n crossingLine2: pair2,\n probabilityOfFailure: 0,\n } as UnravelSameLayerCrossingIssue)\n } else if (A.z === B.z && C.z !== D.z) {\n issues.push({\n type: \"single_transition_crossing\",\n segmentPoints: [pair1, pair2],\n capacityMeshNodeId: nodeId,\n sameLayerCrossingLine: pair1,\n transitionCrossingLine: pair2,\n probabilityOfFailure: 0,\n } as UnravelSingleTransitionCrossingIssue)\n } else if (A.z !== B.z && C.z === D.z) {\n issues.push({\n type: \"single_transition_crossing\",\n segmentPoints: [pair1, pair2],\n capacityMeshNodeId: nodeId,\n sameLayerCrossingLine: pair2,\n transitionCrossingLine: pair1,\n probabilityOfFailure: 0,\n } as UnravelSingleTransitionCrossingIssue)\n } else if (A.z !== B.z && C.z !== D.z) {\n issues.push({\n type: \"double_transition_crossing\",\n segmentPoints: [pair1, pair2],\n capacityMeshNodeId: nodeId,\n crossingLine1: pair1,\n crossingLine2: pair2,\n probabilityOfFailure: 0,\n } as UnravelDoubleTransitionCrossingIssue)\n }\n }\n }\n }\n }\n\n return issues\n}\n","export const getLogProbability = (probability: number) => {\n const K = -2.3\n return 1 - Math.exp(probability * K)\n}\n","import { SegmentPointId, UnravelOperation } from \"./types\"\n\n/**\n * Applies an operation to the point modifications map\n * @param pointModifications The current point modifications map\n * @param operation The operation to apply\n * @param getPointInCandidate Function to get the current point values (with any existing modifications)\n * @returns The modified point modifications map\n */\nexport const applyOperationToPointModifications = (\n pointModifications: Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >,\n operation: UnravelOperation,\n getPointInCandidate: (segmentPointId: SegmentPointId) => {\n x: number\n y: number\n z: number\n segmentId: string\n },\n) => {\n if (operation.type === \"change_layer\") {\n for (const segmentPointId of operation.segmentPointIds) {\n const existingMods = pointModifications.get(segmentPointId) || {}\n pointModifications.set(segmentPointId, {\n ...existingMods,\n z: operation.newZ,\n })\n }\n } else if (operation.type === \"swap_position_on_segment\") {\n const [ASpId, BSpId] = operation.segmentPointIds\n const A = getPointInCandidate(ASpId)\n const B = getPointInCandidate(BSpId)\n\n const existingModsA = pointModifications.get(ASpId) || {}\n const existingModsB = pointModifications.get(BSpId) || {}\n\n pointModifications.set(ASpId, {\n ...existingModsA,\n x: B.x,\n y: B.y,\n })\n\n pointModifications.set(BSpId, {\n ...existingModsB,\n x: A.x,\n y: A.y,\n })\n } else if (operation.type === \"combined\") {\n // For combined operations, recursively apply each operation\n for (const subOperation of operation.operations) {\n // Apply each sub-operation directly to the modifications\n applyOperationToPointModifications(\n pointModifications,\n subOperation,\n getPointInCandidate,\n )\n }\n }\n}\n","import { CapacityMeshNodeId } from \"lib/types\"\nimport { SegmentWithAssignedPoints } from \"../CapacityMeshSolver/CapacitySegmentToPointSolver\"\nimport {\n SegmentId,\n SegmentPoint,\n SegmentPointId,\n SegmentPointMap,\n} from \"./types\"\n\nexport type SegmentPointMapAndReverseMaps = {\n segmentPointMap: SegmentPointMap\n nodeToSegmentPointMap: Map<CapacityMeshNodeId, SegmentPointId[]>\n segmentToSegmentPointMap: Map<SegmentId, SegmentPointId[]>\n}\n\nexport const createSegmentPointMap = (\n dedupedSegments: SegmentWithAssignedPoints[],\n segmentIdToNodeIds: Map<SegmentId, CapacityMeshNodeId[]>,\n): SegmentPointMapAndReverseMaps => {\n const segmentPointMap: SegmentPointMap = new Map()\n const nodeToSegmentPointMap: Map<CapacityMeshNodeId, SegmentPointId[]> =\n new Map()\n const segmentToSegmentPointMap: Map<SegmentId, SegmentPointId[]> = new Map()\n\n const segmentPoints: SegmentPoint[] = []\n let highestSegmentPointId = 0\n for (const segment of dedupedSegments) {\n for (const point of segment.assignedPoints!) {\n const sp = {\n segmentPointId: `SP${highestSegmentPointId++}`,\n segmentId: segment.nodePortSegmentId!,\n capacityMeshNodeIds: segmentIdToNodeIds.get(\n segment.nodePortSegmentId!,\n )!,\n connectionName: point.connectionName,\n x: point.point.x,\n y: point.point.y,\n z: point.point.z,\n directlyConnectedSegmentPointIds: [],\n }\n\n segmentPointMap.set(sp.segmentPointId, sp)\n for (const nodeId of sp.capacityMeshNodeIds) {\n nodeToSegmentPointMap.set(nodeId, [\n ...(nodeToSegmentPointMap.get(nodeId) ?? []),\n sp.segmentPointId,\n ])\n }\n\n segmentToSegmentPointMap.set(segment.nodePortSegmentId!, [\n ...(segmentToSegmentPointMap.get(segment.nodePortSegmentId!) ?? []),\n sp.segmentPointId,\n ])\n\n segmentPoints.push(sp)\n }\n }\n\n return {\n segmentPointMap,\n nodeToSegmentPointMap,\n segmentToSegmentPointMap,\n }\n}\n","import { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { SegmentWithAssignedPoints } from \"../CapacityMeshSolver/CapacitySegmentToPointSolver\"\nimport {\n UnravelSection,\n UnravelCandidate,\n SegmentPoint,\n SegmentPointId,\n SegmentId,\n UnravelOperation,\n UnravelIssue,\n SegmentPointMap,\n} from \"./types\"\nimport { getNodesNearNode } from \"./getNodesNearNode\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport {\n createFullPointModificationsHash,\n createPointModificationsHash,\n} from \"./createPointModificationsHash\"\nimport { getIssuesInSection } from \"./getIssuesInSection\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\nimport { getLogProbability } from \"./getLogProbability\"\nimport { applyOperationToPointModifications } from \"./applyOperationToPointModifications\"\nimport {\n createSegmentPointMap,\n SegmentPointMapAndReverseMaps,\n} from \"./createSegmentPointMap\"\n\n/**\n * The UntangleSectionSolver optimizes a section of connected capacity nodes\n * with their deduplicated segments.\n *\n * The section always has a \"root\" node. From the root node, MUTABLE_HOPS are\n * taken to reach other nodes that are mutable. One additional hop is taken to\n * have all the impacted nodes in section. So a section is composed of mutable\n * and immutable nodes.\n *\n * The goal of the solver is to perform operations on the mutable nodes of the\n * section to lower the overall cost of the section.\n *\n * The untangle phase will perform \"operations\" on segments based on \"issues\"\n *\n * An \"issue\" is anything that increases the cost of the node:\n * - Anything that causes a via (e.g. layer transition)\n * - Any time two traces cross on the same layer\n *\n * An operation is a change to a segment. There are two main operations:\n * - Change layer\n * - Change point order on segment\n *\n * This solver works by exploring different paths of operations. When an\n * operation is performed, new issues are created. Each path has a cost, and\n * a set of neighbors representing next operations to perform.\n *\n */\nexport class UnravelSectionSolver extends BaseSolver {\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n dedupedSegments: SegmentWithAssignedPoints[]\n dedupedSegmentMap: Map<SegmentId, SegmentWithAssignedPoints>\n\n MUTABLE_HOPS = 1\n\n unravelSection: UnravelSection\n\n candidates: UnravelCandidate[] = []\n\n lastProcessedCandidate: UnravelCandidate | null = null\n bestCandidate: UnravelCandidate | null = null\n originalCandidate: UnravelCandidate\n\n rootNodeId: CapacityMeshNodeId\n nodeIdToSegmentIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n segmentIdToNodeIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n colorMap: Record<string, string>\n tunedNodeCapacityMap: Map<CapacityMeshNodeId, number>\n MAX_CANDIDATES = 500\n iterationsSinceImprovement = 0\n\n selectedCandidateIndex: number | \"best\" | \"original\" | null = null\n\n queuedOrExploredCandidatePointModificationHashes: Set<string> = new Set()\n\n constructor(params: {\n rootNodeId: CapacityMeshNodeId\n colorMap?: Record<string, string>\n MUTABLE_HOPS?: number\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n dedupedSegments: SegmentWithAssignedPoints[]\n dedupedSegmentMap?: Map<SegmentId, SegmentWithAssignedPoints>\n nodeIdToSegmentIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n segmentIdToNodeIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n segmentPointMap?: SegmentPointMap\n nodeToSegmentPointMap?: Map<CapacityMeshNodeId, SegmentPointId[]>\n segmentToSegmentPointMap?: Map<SegmentId, SegmentPointId[]>\n }) {\n super()\n\n this.MUTABLE_HOPS = params.MUTABLE_HOPS ?? this.MUTABLE_HOPS\n this.MAX_ITERATIONS = 50_000\n\n this.nodeMap = params.nodeMap\n this.dedupedSegments = params.dedupedSegments\n if (params.dedupedSegmentMap) {\n this.dedupedSegmentMap = params.dedupedSegmentMap\n } else {\n this.dedupedSegmentMap = new Map()\n for (const segment of this.dedupedSegments) {\n this.dedupedSegmentMap.set(segment.nodePortSegmentId!, segment)\n }\n }\n this.nodeIdToSegmentIds = params.nodeIdToSegmentIds\n this.segmentIdToNodeIds = params.segmentIdToNodeIds\n this.rootNodeId = params.rootNodeId\n this.colorMap = params.colorMap ?? {}\n this.unravelSection = this.createUnravelSection({\n segmentPointMap: params.segmentPointMap!,\n nodeToSegmentPointMap: params.nodeToSegmentPointMap!,\n segmentToSegmentPointMap: params.segmentToSegmentPointMap!,\n })\n this.tunedNodeCapacityMap = new Map()\n for (const nodeId of this.unravelSection.allNodeIds) {\n this.tunedNodeCapacityMap.set(\n nodeId,\n getTunedTotalCapacity1(this.nodeMap.get(nodeId)!),\n )\n }\n this.originalCandidate = this.createInitialCandidate()\n this.candidates = [this.originalCandidate]\n }\n\n createUnravelSection(\n largeSpMaps?: SegmentPointMapAndReverseMaps,\n ): UnravelSection {\n const mutableNodeIds = getNodesNearNode({\n nodeId: this.rootNodeId,\n nodeIdToSegmentIds: this.nodeIdToSegmentIds,\n segmentIdToNodeIds: this.segmentIdToNodeIds,\n hops: this.MUTABLE_HOPS,\n })\n const allSectionNodeIds = getNodesNearNode({\n nodeId: this.rootNodeId,\n nodeIdToSegmentIds: this.nodeIdToSegmentIds,\n segmentIdToNodeIds: this.segmentIdToNodeIds,\n hops: this.MUTABLE_HOPS + 1,\n })\n const immutableNodeIds = Array.from(\n new Set(allSectionNodeIds).difference(new Set(mutableNodeIds)),\n )\n\n if (!largeSpMaps?.segmentPointMap) {\n largeSpMaps = createSegmentPointMap(\n this.dedupedSegments,\n this.segmentIdToNodeIds,\n )\n }\n\n const segmentPointsInNode = new Map<CapacityMeshNodeId, SegmentPointId[]>()\n for (const nodeId of allSectionNodeIds) {\n segmentPointsInNode.set(\n nodeId,\n largeSpMaps.nodeToSegmentPointMap.get(nodeId)!,\n )\n }\n\n const sectionPointMap = new Map<SegmentPointId, SegmentPoint>()\n for (const nodeId of allSectionNodeIds) {\n for (const segmentPointId of segmentPointsInNode.get(nodeId)!) {\n const point = largeSpMaps.segmentPointMap.get(segmentPointId)!\n sectionPointMap.set(segmentPointId, point)\n }\n }\n\n const segmentPoints = Array.from(sectionPointMap.values())\n\n const segmentPointsInSegment = new Map<SegmentId, SegmentPointId[]>()\n for (const segmentPoint of segmentPoints) {\n segmentPointsInSegment.set(segmentPoint.segmentId, [\n ...(segmentPointsInSegment.get(segmentPoint.segmentId) ?? []),\n segmentPoint.segmentPointId,\n ])\n }\n\n // Second pass: set neighboring segment point ids\n for (const [nodeId, segmentPoints] of segmentPointsInNode.entries()) {\n for (let i = 0; i < segmentPoints.length; i++) {\n const A = largeSpMaps.segmentPointMap.get(segmentPoints[i])!\n for (let j = i + 1; j < segmentPoints.length; j++) {\n const B = largeSpMaps.segmentPointMap.get(segmentPoints[j])!\n\n if (B.segmentPointId === A.segmentPointId) continue\n if (B.segmentId === A.segmentId) continue\n if (B.connectionName !== A.connectionName) continue\n if (B.directlyConnectedSegmentPointIds.includes(A.segmentPointId))\n continue\n\n A.directlyConnectedSegmentPointIds.push(B.segmentPointId)\n B.directlyConnectedSegmentPointIds.push(A.segmentPointId)\n }\n }\n }\n\n const segmentPairsInNode = new Map<\n CapacityMeshNodeId,\n Array<[SegmentPointId, SegmentPointId]>\n >()\n for (const nodeId of allSectionNodeIds) {\n segmentPairsInNode.set(nodeId, [])\n }\n\n for (const A of segmentPoints) {\n for (const nodeId of A.capacityMeshNodeIds) {\n const segmentPairs = segmentPairsInNode.get(nodeId)\n if (!segmentPairs) continue\n for (const BId of A.directlyConnectedSegmentPointIds) {\n const B = largeSpMaps.segmentPointMap.get(BId)!\n if (B.segmentPointId === A.segmentPointId) continue\n if (!B.capacityMeshNodeIds.some((nId) => nId === nodeId)) continue\n if (\n !segmentPairs.some(\n ([a, b]) =>\n (a === A.segmentPointId && b === B.segmentPointId) ||\n (a === B.segmentPointId && b === A.segmentPointId),\n )\n ) {\n segmentPairs.push([A.segmentPointId, B.segmentPointId])\n }\n }\n }\n }\n\n const mutableSegmentIds = new Set<string>()\n for (const nodeId of mutableNodeIds) {\n for (const segmentId of this.nodeIdToSegmentIds.get(nodeId)!) {\n const allNodeIdsWithSegment = this.segmentIdToNodeIds.get(segmentId)!\n if (\n allNodeIdsWithSegment.every(\n (nodeId) => !this.nodeMap.get(nodeId)!._containsTarget,\n )\n ) {\n mutableSegmentIds.add(segmentId)\n }\n }\n }\n\n return {\n allNodeIds: allSectionNodeIds,\n mutableNodeIds,\n immutableNodeIds,\n mutableSegmentIds,\n segmentPairsInNode,\n segmentPointMap: sectionPointMap,\n segmentPointsInNode,\n segmentPointsInSegment,\n originalPointMap: sectionPointMap,\n }\n }\n\n createInitialCandidate(): UnravelCandidate {\n const pointModifications = new Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >()\n const issues = getIssuesInSection(\n this.unravelSection,\n this.nodeMap,\n pointModifications,\n )\n const g = this.computeG({\n issues,\n originalCandidate: {} as any,\n operationsPerformed: 0,\n operation: {} as any,\n })\n return {\n pointModifications,\n issues,\n g,\n h: 0,\n f: g,\n operationsPerformed: 0,\n candidateHash: createPointModificationsHash(pointModifications),\n // candidateFullHash: createFullPointModificationsHash(\n // this.unravelSection.segmentPointMap,\n // pointModifications,\n // ),\n }\n }\n\n get nextCandidate(): UnravelCandidate | null {\n return this.candidates[0] ?? null\n }\n\n getPointInCandidate(\n candidate: UnravelCandidate,\n segmentPointId: SegmentPointId,\n ): { x: number; y: number; z: number; segmentId: string } {\n const originalPoint =\n this.unravelSection.segmentPointMap.get(segmentPointId)!\n const modifications = candidate.pointModifications.get(segmentPointId)\n\n return {\n x: modifications?.x ?? originalPoint.x,\n y: modifications?.y ?? originalPoint.y,\n z: modifications?.z ?? originalPoint.z,\n segmentId: originalPoint.segmentId,\n }\n }\n\n getOperationsForIssue(\n candidate: UnravelCandidate,\n issue: UnravelIssue,\n ): UnravelOperation[] {\n const operations: UnravelOperation[] = []\n\n if (issue.type === \"transition_via\") {\n // When there's a transition via, we attempt to change the layer of either\n // end to match the other end\n const [APointId, BPointId] = issue.segmentPoints\n const pointA = this.getPointInCandidate(candidate, APointId)\n const pointB = this.getPointInCandidate(candidate, BPointId)\n\n const aAvailableZ = this.dedupedSegmentMap.get(\n pointA.segmentId,\n )!.availableZ\n const bAvailableZ = this.dedupedSegmentMap.get(\n pointB.segmentId,\n )!.availableZ\n\n if (\n this.unravelSection.mutableSegmentIds.has(pointA.segmentId) &&\n aAvailableZ.includes(pointB.z)\n ) {\n operations.push({\n type: \"change_layer\",\n newZ: pointB.z,\n segmentPointIds: [APointId],\n })\n }\n if (\n this.unravelSection.mutableSegmentIds.has(pointB.segmentId) &&\n bAvailableZ.includes(pointA.z)\n ) {\n operations.push({\n type: \"change_layer\",\n newZ: pointA.z,\n segmentPointIds: [BPointId],\n })\n }\n }\n\n if (issue.type === \"same_layer_crossing\") {\n // For a same-layer crossing, we should try all the following:\n // 1. Swap the points on each segment (for each shared segment, if any)\n // 2. Change the layer of each segment entirely to remove the crossing\n // 3. Change the layer of each point individually to make it a transition\n // crossing\n\n // 1. SWAP POINTS\n const [APointId, BPointId] = issue.crossingLine1\n const [CPointId, DPointId] = issue.crossingLine2\n\n const sharedSegments: Array<[SegmentPointId, SegmentPointId]> = []\n const A = this.unravelSection.segmentPointMap.get(APointId)!\n const B = this.unravelSection.segmentPointMap.get(BPointId)!\n const C = this.unravelSection.segmentPointMap.get(CPointId)!\n const D = this.unravelSection.segmentPointMap.get(DPointId)!\n\n if (A.segmentId === C.segmentId) {\n sharedSegments.push([APointId, CPointId])\n }\n if (A.segmentId === D.segmentId) {\n sharedSegments.push([APointId, DPointId])\n }\n if (B.segmentId === C.segmentId) {\n sharedSegments.push([BPointId, CPointId])\n }\n if (B.segmentId === D.segmentId) {\n sharedSegments.push([BPointId, DPointId])\n }\n\n for (const [EPointId, FPointId] of sharedSegments) {\n operations.push({\n type: \"swap_position_on_segment\",\n segmentPointIds: [EPointId, FPointId],\n })\n }\n\n // 2. CHANGE LAYER OF EACH SEGMENT ENTIRELY TO REMOVE CROSSING\n const Amutable = this.unravelSection.mutableSegmentIds.has(A.segmentId)\n const Bmutable = this.unravelSection.mutableSegmentIds.has(B.segmentId)\n const Cmutable = this.unravelSection.mutableSegmentIds.has(C.segmentId)\n const Dmutable = this.unravelSection.mutableSegmentIds.has(D.segmentId)\n\n // Get availableZ for each segment\n const aSegment = this.dedupedSegmentMap.get(A.segmentId)!\n const bSegment = this.dedupedSegmentMap.get(B.segmentId)!\n const cSegment = this.dedupedSegmentMap.get(C.segmentId)!\n const dSegment = this.dedupedSegmentMap.get(D.segmentId)!\n\n // Function to check if a new Z level is available for all segments\n const isNewZAvailableForAll = (segmentObjects: any[], newZ: number) => {\n return segmentObjects.every((seg) => seg.availableZ.includes(newZ))\n }\n\n // Only propose layer changes if both segments can use the target layer\n if (Amutable && Bmutable) {\n const newZ = A.z === 0 ? 1 : 0\n if (isNewZAvailableForAll([aSegment, bSegment], newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [APointId, BPointId],\n })\n }\n }\n\n if (Cmutable && Dmutable) {\n const newZ = C.z === 0 ? 1 : 0\n if (isNewZAvailableForAll([cSegment, dSegment], newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [CPointId, DPointId],\n })\n }\n }\n\n // 3. CHANGE LAYER OF EACH POINT INDIVIDUALLY TO MAKE TRANSITION CROSSING\n if (Amutable) {\n const newZ = A.z === 0 ? 1 : 0\n if (aSegment.availableZ.includes(newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [APointId],\n })\n }\n }\n\n if (Bmutable) {\n const newZ = B.z === 0 ? 1 : 0\n if (bSegment.availableZ.includes(newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [BPointId],\n })\n }\n }\n\n if (Cmutable) {\n const newZ = C.z === 0 ? 1 : 0\n if (cSegment.availableZ.includes(newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [CPointId],\n })\n }\n }\n\n if (Dmutable) {\n const newZ = D.z === 0 ? 1 : 0\n if (dSegment.availableZ.includes(newZ)) {\n operations.push({\n type: \"change_layer\",\n newZ,\n segmentPointIds: [DPointId],\n })\n }\n }\n }\n\n // TODO single_transition_crossing\n // TODO double_transition_crossing\n // TODO same_layer_trace_imbalance_with_low_capacity\n\n return operations\n }\n\n computeG(params: {\n issues: UnravelIssue[]\n originalCandidate: UnravelCandidate\n operationsPerformed: number\n operation: UnravelOperation\n }): number {\n const { issues, originalCandidate, operationsPerformed, operation } = params\n\n const nodeProblemCounts = new Map<\n CapacityMeshNodeId,\n {\n numTransitionCrossings: number\n numSameLayerCrossings: number\n numEntryExitLayerChanges: number\n }\n >()\n\n for (const issue of issues) {\n if (!nodeProblemCounts.has(issue.capacityMeshNodeId)) {\n nodeProblemCounts.set(issue.capacityMeshNodeId, {\n numTransitionCrossings: 0,\n numSameLayerCrossings: 0,\n numEntryExitLayerChanges: 0,\n })\n }\n\n const nodeProblemCount = nodeProblemCounts.get(issue.capacityMeshNodeId)!\n\n if (issue.type === \"transition_via\") {\n nodeProblemCount.numTransitionCrossings++\n } else if (issue.type === \"same_layer_crossing\") {\n nodeProblemCount.numSameLayerCrossings++\n } else if (\n issue.type === \"double_transition_crossing\" ||\n issue.type === \"single_transition_crossing\"\n ) {\n nodeProblemCount.numEntryExitLayerChanges++\n } else if (\n issue.type === \"same_layer_trace_imbalance_with_low_capacity\"\n ) {\n // TODO\n }\n }\n\n let cost = 0\n\n for (const [\n nodeId,\n {\n numEntryExitLayerChanges,\n numSameLayerCrossings,\n numTransitionCrossings,\n },\n ] of nodeProblemCounts) {\n const estNumVias =\n numSameLayerCrossings * 0.82 +\n numEntryExitLayerChanges * 0.41 +\n numTransitionCrossings * 0.2\n\n const estUsedCapacity = (estNumVias / 2) ** 1.1\n\n const totalCapacity = this.tunedNodeCapacityMap.get(nodeId)!\n\n const estPf = estUsedCapacity / totalCapacity\n\n cost += getLogProbability(estPf)\n }\n\n return cost\n }\n\n getUnexploredNeighborByApplyingOperation(\n currentCandidate: UnravelCandidate,\n operation: UnravelOperation,\n ): UnravelCandidate | null {\n const pointModifications = new Map<\n SegmentPointId,\n { x?: number; y?: number; z?: number }\n >(currentCandidate.pointModifications)\n\n applyOperationToPointModifications(\n pointModifications,\n operation,\n (segmentPointId) =>\n this.getPointInCandidate(currentCandidate, segmentPointId),\n )\n\n const candidateHash = createPointModificationsHash(pointModifications)\n\n if (\n this.queuedOrExploredCandidatePointModificationHashes.has(candidateHash)\n ) {\n return null\n }\n\n const issues: UnravelIssue[] = getIssuesInSection(\n this.unravelSection,\n this.nodeMap,\n pointModifications,\n )\n\n const operationsPerformed = currentCandidate.operationsPerformed + 1\n\n const g = this.computeG({\n issues,\n originalCandidate: currentCandidate,\n operationsPerformed,\n operation,\n })\n\n return {\n issues,\n g,\n h: 0,\n f: g,\n pointModifications,\n candidateHash,\n\n // TODO PERFORMANCE allow disabling this\n // candidateFullHash: createFullPointModificationsHash(\n // this.unravelSection.segmentPointMap,\n // pointModifications,\n // ),\n\n operationsPerformed,\n }\n }\n\n getNeighborOperationsForCandidate(\n candidate: UnravelCandidate,\n ): UnravelOperation[] {\n return candidate.issues.flatMap((issue) =>\n this.getOperationsForIssue(candidate, issue),\n )\n }\n\n getNeighbors(candidate: UnravelCandidate): UnravelCandidate[] {\n const neighbors: UnravelCandidate[] = []\n\n const operations = this.getNeighborOperationsForCandidate(candidate)\n for (const operation of operations) {\n const neighbor = this.getUnexploredNeighborByApplyingOperation(\n candidate,\n operation,\n )\n if (!neighbor) continue\n neighbors.push(neighbor)\n }\n\n return neighbors\n }\n\n _step() {\n const candidate = this.candidates.shift()\n this.iterationsSinceImprovement++\n if (!candidate) {\n this.solved = true\n return\n }\n this.lastProcessedCandidate = candidate\n\n if (candidate.f < (this.bestCandidate?.f ?? Infinity)) {\n this.bestCandidate = candidate\n this.iterationsSinceImprovement = 0\n // TODO, only works if we start computing f\n // if (candidate.f <= 0.00001) {\n // this.solved = true\n // return\n // }\n }\n\n this.getNeighbors(candidate).forEach((neighbor) => {\n const isPartialHashExplored =\n this.queuedOrExploredCandidatePointModificationHashes.has(\n neighbor.candidateHash,\n )\n // const isFullHashExplored =\n // neighbor.candidateFullHash &&\n // this.queuedOrExploredCandidatePointModificationHashes.has(\n // neighbor.candidateFullHash,\n // )\n\n // if (isPartialHashExplored || isFullHashExplored) return\n if (isPartialHashExplored) return\n this.queuedOrExploredCandidatePointModificationHashes.add(\n neighbor.candidateHash,\n )\n // if (neighbor.candidateFullHash) {\n // this.queuedOrExploredCandidatePointModificationHashes.add(\n // neighbor.candidateFullHash,\n // )\n // }\n this.candidates.push(neighbor)\n })\n this.candidates.sort((a, b) => a.f - b.f)\n this.candidates.length = Math.min(\n this.candidates.length,\n this.MAX_CANDIDATES,\n )\n }\n\n visualize(): GraphicsObject {\n const graphics: Required<GraphicsObject> = {\n points: [],\n lines: [],\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Unravel Section Solver\",\n }\n\n // Get the candidate to visualize\n let candidate: UnravelCandidate | null = null\n if (this.selectedCandidateIndex !== null) {\n if (this.selectedCandidateIndex === \"best\") {\n candidate = this.bestCandidate\n } else if (this.selectedCandidateIndex === \"original\") {\n candidate = this.originalCandidate\n } else {\n candidate = this.candidates[this.selectedCandidateIndex]\n }\n } else {\n candidate = this.lastProcessedCandidate || this.candidates[0]\n }\n if (!candidate) return graphics\n\n // Create a map of segment points with modifications applied\n const modifiedSegmentPoints = new Map<string, SegmentPoint>()\n for (const [segmentPointId, segmentPoint] of this.unravelSection\n .segmentPointMap) {\n // Create a copy of the original point\n const modifiedPoint = { ...segmentPoint }\n\n // Apply any modifications from the candidate\n const modification = candidate.pointModifications.get(segmentPointId)\n if (modification) {\n if (modification.x !== undefined) modifiedPoint.x = modification.x\n if (modification.y !== undefined) modifiedPoint.y = modification.y\n if (modification.z !== undefined) modifiedPoint.z = modification.z\n }\n\n modifiedSegmentPoints.set(segmentPointId, modifiedPoint)\n }\n\n // Visualize all segment points with modifications applied\n for (const [segmentPointId, segmentPoint] of modifiedSegmentPoints) {\n graphics.points.push({\n x: segmentPoint.x,\n y: segmentPoint.y,\n label: `${segmentPointId}\\nSegment: ${segmentPoint.segmentId} ${this.unravelSection.mutableSegmentIds.has(segmentPoint.segmentId) ? \"MUTABLE\" : \"IMMUTABLE\"}\\nLayer: ${segmentPoint.z}`,\n color: this.colorMap[segmentPoint.connectionName] || \"#000\",\n })\n }\n\n // Visualize nodes\n for (const nodeId of this.unravelSection.allNodeIds) {\n const node = this.nodeMap.get(nodeId)!\n const isMutable = this.unravelSection.mutableNodeIds.includes(nodeId)\n\n graphics.rects.push({\n center: node.center,\n label: `${nodeId}\\n${node.width.toFixed(2)}x${node.height.toFixed(2)}\\n${isMutable ? \"MUTABLE\" : \"IMMUTABLE\"}`,\n color: isMutable ? \"green\" : \"red\",\n width: node.width / 8,\n height: node.height / 8,\n })\n }\n\n // Connect segment points that belong to the same segment\n for (const [segmentId, segmentPointIds] of this.unravelSection\n .segmentPointsInSegment) {\n if (segmentPointIds.length <= 1) continue\n\n const points = segmentPointIds.map(\n (spId) => modifiedSegmentPoints.get(spId)!,\n )\n\n // Connect points in order\n for (let i = 0; i < points.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: points[i].x, y: points[i].y },\n { x: points[i + 1].x, y: points[i + 1].y },\n ],\n strokeColor: this.colorMap[segmentId] || \"#000\",\n })\n }\n }\n\n // Connect directly connected segment points (points with the same connection name)\n for (const [segmentPointId, segmentPoint] of modifiedSegmentPoints) {\n for (const connectedPointId of segmentPoint.directlyConnectedSegmentPointIds) {\n // Only process each connection once (when the current point's ID is less than the connected point's ID)\n if (segmentPointId < connectedPointId) {\n const connectedPoint = modifiedSegmentPoints.get(connectedPointId)!\n if (!connectedPoint) continue\n\n // Determine line style based on layer (z) values\n const sameLayer = segmentPoint.z === connectedPoint.z\n const commonLayer = segmentPoint.z\n\n let strokeDash: string | undefined\n if (sameLayer) {\n strokeDash = commonLayer === 0 ? undefined : \"10 5\" // top layer: solid, bottom layer: long dash\n } else {\n strokeDash = \"3 3 10\" // transition between layers: mixed dash pattern\n }\n\n graphics.lines.push({\n points: [\n { x: segmentPoint.x, y: segmentPoint.y },\n { x: connectedPoint.x, y: connectedPoint.y },\n ],\n strokeDash,\n strokeColor: this.colorMap[segmentPoint.connectionName] || \"#000\",\n })\n }\n }\n }\n\n // Visualize issues\n for (const issue of candidate.issues) {\n const node = this.nodeMap.get(issue.capacityMeshNodeId)!\n\n if (issue.type === \"transition_via\") {\n // Highlight via issues\n for (const segmentPointId of issue.segmentPoints) {\n const segmentPoint = modifiedSegmentPoints.get(segmentPointId)!\n graphics.circles.push({\n center: { x: segmentPoint.x, y: segmentPoint.y },\n radius: node.width / 16,\n stroke: \"#ff0000\",\n fill: \"rgba(255, 0, 0, 0.2)\",\n label: `Via Issue\\n${segmentPointId}\\nLayer: ${segmentPoint.z}`,\n })\n }\n } else if (issue.type === \"same_layer_crossing\") {\n // Highlight crossing issues\n for (const [sp1Id, sp2Id] of [\n issue.crossingLine1,\n issue.crossingLine2,\n ]) {\n const sp1 = modifiedSegmentPoints.get(sp1Id)!\n const sp2 = modifiedSegmentPoints.get(sp2Id)!\n\n graphics.lines.push({\n points: [\n { x: sp1.x, y: sp1.y },\n { x: sp2.x, y: sp2.y },\n ],\n strokeColor: \"rgba(255,0,0,0.2)\",\n strokeWidth: node.width / 32,\n })\n }\n }\n }\n\n // Highlight modified points\n for (const [segmentPointId, modification] of candidate.pointModifications) {\n const modifiedPoint = modifiedSegmentPoints.get(segmentPointId)!\n const originalPoint =\n this.unravelSection.segmentPointMap.get(segmentPointId)!\n\n graphics.circles.push({\n center: { x: modifiedPoint.x, y: modifiedPoint.y },\n radius: 0.05,\n stroke: \"#0000ff\",\n fill: \"rgba(0, 0, 255, 0.2)\",\n label: `${segmentPointId}\\nOriginal: (${originalPoint.x.toFixed(2)}, ${originalPoint.y.toFixed(2)}, ${originalPoint.z})\\nNew: (${modifiedPoint.x.toFixed(2)}, ${modifiedPoint.y.toFixed(2)}, ${modifiedPoint.z})`,\n })\n }\n\n return graphics\n }\n}\n","import { NodePortSegment } from \"lib/types/capacity-edges-to-port-segments-types\"\nimport { SegmentWithAssignedPoints } from \"../CapacityMeshSolver/CapacitySegmentToPointSolver\"\n\n/**\n * Deduplicates segments with the same start and end points.\n * Assigns a unique ID to each unique segment and ensures all segments with the same\n * start/end points share the same ID.\n * @param assignedSegments The segments to deduplicate\n * @returns Deduplicated segments with unique IDs\n */\nexport const getDedupedSegments = (\n assignedSegments: NodePortSegment[],\n): SegmentWithAssignedPoints[] => {\n const dedupedSegments: SegmentWithAssignedPoints[] = []\n type SegKey = `${number}-${number}-${number}-${number}-${string}`\n const dedupedSegPointMap: Map<SegKey, NodePortSegment> = new Map()\n let highestSegmentId = -1\n\n for (const seg of assignedSegments) {\n // Check if there's another segment with the same start and end and availableZ\n const segKey: SegKey = `${seg.start.x}-${seg.start.y}-${seg.end.x}-${seg.end.y}-${seg.availableZ.join(\",\")}`\n const existingSeg = dedupedSegPointMap.get(segKey)\n\n if (!existingSeg) {\n highestSegmentId++\n seg.nodePortSegmentId = `SEG${highestSegmentId}`\n dedupedSegPointMap.set(segKey, seg)\n dedupedSegments.push(seg)\n continue\n }\n\n seg.nodePortSegmentId = existingSeg.nodePortSegmentId\n }\n\n return dedupedSegments\n}\n","import { CapacityMeshNode } from \"lib/types\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\n\nexport const calculateNodeProbabilityOfFailure = (\n node: CapacityMeshNode,\n numSameLayerCrossings: number,\n numEntryExitLayerChanges: number,\n numTransitionCrossings: number,\n): number => {\n if (node?._containsTarget) return 0\n\n // Number of traces through the node\n const totalCapacity = getTunedTotalCapacity1(node)\n\n // Estimated number of vias based on crossings\n const estNumVias =\n numSameLayerCrossings * 0.82 +\n numEntryExitLayerChanges * 0.41 +\n numTransitionCrossings * 0.2\n\n const estUsedCapacity = (estNumVias / 2) ** 1.1\n\n // We could refine this with actual trace capacity\n const approxProb = estUsedCapacity / totalCapacity\n\n // Bounded probability calculation\n return approxProb\n}\n","import { doSegmentsIntersect } from \"@tscircuit/math-utils\"\nimport { SegmentPoint } from \"lib/solvers/UnravelSolver/types\"\n\nexport const getIntraNodeCrossingsFromSegmentPoints = (\n segmentPoints: SegmentPoint[],\n) => {\n // Count the number of crossings\n let numSameLayerCrossings = 0\n let numEntryExitLayerChanges = 0\n let numTransitionCrossings = 0\n\n // Group segment points by connection name\n const connectionGroups = new Map<string, SegmentPoint[]>()\n\n for (const point of segmentPoints) {\n if (!connectionGroups.has(point.connectionName)) {\n connectionGroups.set(point.connectionName, [])\n }\n connectionGroups.get(point.connectionName)!.push(point)\n }\n\n const pointPairs: {\n points: { x: number; y: number; z: number }[]\n z: number\n connectionName: string\n }[] = []\n\n const transitionPairPoints: {\n points: { x: number; y: number; z: number }[]\n connectionName: string\n }[] = []\n\n // Process each connection group\n for (const [connectionName, points] of connectionGroups.entries()) {\n if (points.length < 2) continue\n\n // For simplicity, we'll just connect the first point to all others in the group\n // This assumes a simple connection pattern\n const firstPoint = points[0]\n\n for (let i = 1; i < points.length; i++) {\n const secondPoint = points[i]\n\n const pointPair = {\n connectionName,\n z: firstPoint.z,\n points: [firstPoint, secondPoint],\n }\n\n if (firstPoint.z !== secondPoint.z) {\n numEntryExitLayerChanges++\n transitionPairPoints.push({\n connectionName,\n points: [firstPoint, secondPoint],\n })\n } else {\n pointPairs.push(pointPair)\n }\n }\n }\n\n // Check for same layer crossings\n for (let i = 0; i < pointPairs.length; i++) {\n for (let j = i + 1; j < pointPairs.length; j++) {\n const pair1 = pointPairs[i]\n const pair2 = pointPairs[j]\n\n if (\n pair1.z === pair2.z &&\n doSegmentsIntersect(\n pair1.points[0],\n pair1.points[1],\n pair2.points[0],\n pair2.points[1],\n )\n ) {\n numSameLayerCrossings++\n }\n }\n }\n\n // Check for transition crossings\n for (let i = 0; i < transitionPairPoints.length; i++) {\n for (let j = i + 1; j < transitionPairPoints.length; j++) {\n const pair1 = transitionPairPoints[i]\n const pair2 = transitionPairPoints[j]\n\n if (\n doSegmentsIntersect(\n pair1.points[0],\n pair1.points[1],\n pair2.points[0],\n pair2.points[1],\n )\n ) {\n numTransitionCrossings++\n }\n }\n }\n\n // Check for crossings between transition pairs and regular pairs\n for (let i = 0; i < transitionPairPoints.length; i++) {\n for (let j = 0; j < pointPairs.length; j++) {\n const pair1 = transitionPairPoints[i]\n const pair2 = pointPairs[j]\n\n if (\n doSegmentsIntersect(\n pair1.points[0],\n pair1.points[1],\n pair2.points[0],\n pair2.points[1],\n )\n ) {\n numTransitionCrossings++\n }\n }\n }\n\n return {\n numSameLayerCrossings,\n numEntryExitLayerChanges,\n numTransitionCrossings,\n }\n}\n","import { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\nimport { SegmentWithAssignedPoints } from \"../CapacityMeshSolver/CapacitySegmentToPointSolver\"\nimport { UnravelSectionSolver } from \"./UnravelSectionSolver\"\nimport { getIntraNodeCrossings } from \"lib/utils/getIntraNodeCrossings\"\nimport { NodePortSegment } from \"lib/types/capacity-edges-to-port-segments-types\"\nimport { getDedupedSegments } from \"./getDedupedSegments\"\nimport { getIntraNodeCrossingsFromSegments } from \"lib/utils/getIntraNodeCrossingsFromSegments\"\nimport { calculateNodeProbabilityOfFailure } from \"./calculateCrossingProbabilityOfFailure\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { NodeWithPortPoints } from \"lib/types/high-density-types\"\nimport {\n PointModificationsMap,\n SegmentId,\n SegmentPoint,\n SegmentPointId,\n SegmentPointMap,\n} from \"./types\"\nimport { createSegmentPointMap } from \"./createSegmentPointMap\"\nimport { getIntraNodeCrossingsFromSegmentPoints } from \"lib/utils/getIntraNodeCrossingsFromSegmentPoints\"\nimport { getNodesNearNode } from \"./getNodesNearNode\"\n\nexport class UnravelMultiSectionSolver extends BaseSolver {\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n dedupedSegmentMap: Map<SegmentId, SegmentWithAssignedPoints>\n dedupedSegments: SegmentWithAssignedPoints[]\n nodeIdToSegmentIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n segmentIdToNodeIds: Map<CapacityMeshNodeId, CapacityMeshNodeId[]>\n nodeToSegmentPointMap: Map<CapacityMeshNodeId, SegmentPointId[]>\n segmentToSegmentPointMap: Map<SegmentId, SegmentPointId[]>\n colorMap: Record<string, string>\n tunedNodeCapacityMap: Map<CapacityMeshNodeId, number>\n\n MAX_NODE_ATTEMPTS = 2\n\n MUTABLE_HOPS = 1\n\n ACCEPTABLE_PF = 0.05\n\n /**\n * Probability of failure for each node\n */\n nodePfMap: Map<CapacityMeshNodeId, number>\n\n attemptsToFixNode: Map<CapacityMeshNodeId, number>\n\n activeSolver: UnravelSectionSolver | null = null\n\n segmentPointMap: SegmentPointMap\n\n constructor({\n assignedSegments,\n colorMap,\n nodes,\n }: {\n assignedSegments: NodePortSegment[]\n colorMap?: Record<string, string>\n /**\n * This isn't used by the algorithm, but allows associating metadata\n * for the result datatype (the center, width, height of the node)\n */\n nodes: CapacityMeshNode[]\n }) {\n super()\n\n this.MAX_ITERATIONS = 100_000\n\n this.dedupedSegments = getDedupedSegments(assignedSegments)\n this.dedupedSegmentMap = new Map()\n for (const segment of this.dedupedSegments) {\n this.dedupedSegmentMap.set(segment.nodePortSegmentId!, segment)\n }\n this.nodeMap = new Map()\n for (const node of nodes) {\n this.nodeMap.set(node.capacityMeshNodeId, node)\n }\n\n this.nodeIdToSegmentIds = new Map()\n this.segmentIdToNodeIds = new Map()\n this.attemptsToFixNode = new Map()\n\n for (const segment of assignedSegments) {\n this.segmentIdToNodeIds.set(segment.nodePortSegmentId!, [\n ...(this.segmentIdToNodeIds.get(segment.nodePortSegmentId!) ?? []),\n segment.capacityMeshNodeId,\n ])\n this.nodeIdToSegmentIds.set(segment.capacityMeshNodeId, [\n ...(this.nodeIdToSegmentIds.get(segment.capacityMeshNodeId) ?? []),\n segment.nodePortSegmentId!,\n ])\n }\n\n this.colorMap = colorMap ?? {}\n\n // Compute tuned capacity for each node\n this.tunedNodeCapacityMap = new Map()\n for (const [nodeId, node] of this.nodeMap) {\n this.tunedNodeCapacityMap.set(nodeId, getTunedTotalCapacity1(node))\n }\n\n const { segmentPointMap, nodeToSegmentPointMap, segmentToSegmentPointMap } =\n createSegmentPointMap(this.dedupedSegments, this.segmentIdToNodeIds)\n\n this.segmentPointMap = segmentPointMap\n this.nodeToSegmentPointMap = nodeToSegmentPointMap\n this.segmentToSegmentPointMap = segmentToSegmentPointMap\n\n this.nodePfMap = this.computeInitialPfMap()\n }\n\n computeInitialPfMap() {\n const pfMap = new Map<CapacityMeshNodeId, number>()\n\n for (const [nodeId, node] of this.nodeMap.entries()) {\n pfMap.set(nodeId, this.computeNodePf(node))\n }\n\n return pfMap\n }\n\n computeNodePf(node: CapacityMeshNode) {\n const {\n numSameLayerCrossings,\n numEntryExitLayerChanges,\n numTransitionCrossings,\n } = getIntraNodeCrossingsFromSegmentPoints(\n (this.nodeToSegmentPointMap.get(node.capacityMeshNodeId) ?? []).map(\n (segPointId) => this.segmentPointMap.get(segPointId)!,\n ),\n )\n\n const probabilityOfFailure = calculateNodeProbabilityOfFailure(\n node,\n numSameLayerCrossings,\n numEntryExitLayerChanges,\n numTransitionCrossings,\n )\n\n return probabilityOfFailure\n }\n\n _step() {\n if (this.iterations >= this.MAX_ITERATIONS - 1) {\n this.solved = true\n return\n }\n if (!this.activeSolver) {\n // Find the node with the highest probability of failure\n let highestPfNodeId = null\n let highestPf = 0\n for (const [nodeId, pf] of this.nodePfMap.entries()) {\n const pfReduced =\n pf *\n (1 -\n (this.attemptsToFixNode.get(nodeId) ?? 0) / this.MAX_NODE_ATTEMPTS)\n if (pfReduced > highestPf) {\n highestPf = pf\n highestPfNodeId = nodeId\n }\n }\n\n if (!highestPfNodeId || highestPf < this.ACCEPTABLE_PF) {\n this.solved = true\n return\n }\n\n this.attemptsToFixNode.set(\n highestPfNodeId,\n (this.attemptsToFixNode.get(highestPfNodeId) ?? 0) + 1,\n )\n this.activeSolver = new UnravelSectionSolver({\n dedupedSegments: this.dedupedSegments,\n dedupedSegmentMap: this.dedupedSegmentMap,\n nodeMap: this.nodeMap,\n nodeIdToSegmentIds: this.nodeIdToSegmentIds,\n segmentIdToNodeIds: this.segmentIdToNodeIds,\n colorMap: this.colorMap,\n rootNodeId: highestPfNodeId,\n MUTABLE_HOPS: this.MUTABLE_HOPS,\n segmentPointMap: this.segmentPointMap,\n nodeToSegmentPointMap: this.nodeToSegmentPointMap,\n segmentToSegmentPointMap: this.segmentToSegmentPointMap,\n })\n }\n\n this.activeSolver.step()\n\n const { bestCandidate, originalCandidate, lastProcessedCandidate } =\n this.activeSolver\n\n // const giveUpFactor =\n // 1 + 4 * (1 - Math.min(1, this.activeSolver.iterations / 40))\n // const shouldEarlyStop =\n // lastProcessedCandidate &&\n // lastProcessedCandidate!.g > bestCandidate!.g * giveUpFactor\n const shouldEarlyStop = this.activeSolver.iterationsSinceImprovement > 200\n\n if (this.activeSolver.solved || shouldEarlyStop) {\n // Incorporate the changes from the active solver\n\n const foundBetterSolution =\n bestCandidate && bestCandidate.g < originalCandidate!.g\n\n if (foundBetterSolution) {\n // Modify the points using the pointModifications of the candidate\n for (const [\n segmentPointId,\n pointModification,\n ] of bestCandidate.pointModifications.entries()) {\n const segmentPoint = this.segmentPointMap.get(segmentPointId)!\n segmentPoint.x = pointModification.x ?? segmentPoint.x\n segmentPoint.y = pointModification.y ?? segmentPoint.y\n segmentPoint.z = pointModification.z ?? segmentPoint.z\n }\n\n // HACK: This is time consuming but there is a bug where sometimes the\n // UnravelSectionSolver accidentally mutates immutable nodes, so we\n // need to go to even more neighbors to be sure we have the updated\n // Pf values. If that bug gets fixed, you can use this.activeSolver.section.allNodeIds\n const possiblyImpactedNodeIds = getNodesNearNode({\n hops: this.activeSolver.MUTABLE_HOPS + 2,\n nodeId: this.activeSolver.rootNodeId,\n nodeIdToSegmentIds: this.nodeIdToSegmentIds,\n segmentIdToNodeIds: this.segmentIdToNodeIds,\n })\n\n // Update node failure probabilities\n for (const nodeId of possiblyImpactedNodeIds) {\n // for (const nodeId of this.nodeMap.keys()) {\n this.nodePfMap.set(\n nodeId,\n this.computeNodePf(this.nodeMap.get(nodeId)!),\n )\n }\n }\n\n this.activeSolver = null\n }\n }\n\n visualize(): GraphicsObject {\n if (this.activeSolver) {\n return this.activeSolver.visualize()\n }\n\n const graphics: Required<GraphicsObject> = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Unravel Multi Section Solver\",\n }\n\n // Visualize nodes\n for (const [nodeId, node] of this.nodeMap.entries()) {\n const probabilityOfFailure = this.nodePfMap.get(nodeId) || 0\n // Color based on probability of failure - red for high, gradient to green for low\n const pf = Math.min(probabilityOfFailure, 1) // Cap at 1\n const red = Math.floor(255 * pf)\n const green = Math.floor(255 * (1 - pf))\n const color = `rgb(${red}, ${green}, 0)`\n\n if ((this.attemptsToFixNode.get(nodeId) ?? 0) === 0 && pf === 0) {\n continue\n }\n\n graphics.rects.push({\n center: node.center,\n label: [\n nodeId,\n `${node.width.toFixed(2)}x${node.height.toFixed(2)}`,\n `Pf: ${probabilityOfFailure.toFixed(3)}`,\n ].join(\"\\n\"),\n color,\n width: node.width / 8,\n height: node.height / 8,\n })\n }\n\n // Visualize segment points\n for (const segmentPoint of this.segmentPointMap.values()) {\n const segment = this.dedupedSegmentMap.get(segmentPoint.segmentId)\n graphics.points.push({\n x: segmentPoint.x,\n y: segmentPoint.y,\n label: [\n segmentPoint.segmentPointId,\n segmentPoint.segmentId,\n `z: ${segmentPoint.z}`,\n `segment.availableZ: ${segment?.availableZ.join(\",\")}`,\n ].join(\"\\n\"),\n color: this.colorMap[segmentPoint.connectionName] || \"#000\",\n })\n }\n\n // Connect segment points that belong to the same segment\n // Group points by segment ID\n const pointsBySegment = new Map<string, SegmentPoint[]>()\n for (const point of this.segmentPointMap.values()) {\n if (!pointsBySegment.has(point.segmentId)) {\n pointsBySegment.set(point.segmentId, [])\n }\n pointsBySegment.get(point.segmentId)!.push(point)\n }\n\n // Connect points in each segment\n for (const [segmentId, points] of pointsBySegment.entries()) {\n if (points.length < 2) continue\n\n // Sort points by some logical order (this approximates the correct ordering)\n const sortedPoints = [...points].sort((a, b) =>\n a.x !== b.x ? a.x - b.x : a.y - b.y,\n )\n\n // Connect adjacent points in the sorted order\n for (let i = 0; i < sortedPoints.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: sortedPoints[i].x, y: sortedPoints[i].y },\n { x: sortedPoints[i + 1].x, y: sortedPoints[i + 1].y },\n ],\n strokeColor: this.colorMap[segmentId] || \"#000\",\n })\n }\n }\n\n // Connect points with the same connection name that share a node\n const processedConnections = new Set<string>()\n const allPoints = Array.from(this.segmentPointMap.values())\n\n for (let i = 0; i < allPoints.length; i++) {\n const point1 = allPoints[i]\n for (let j = i + 1; j < allPoints.length; j++) {\n const point2 = allPoints[j]\n\n // Skip if they have different connection names or are in the same segment\n if (\n point1.connectionName !== point2.connectionName ||\n point1.segmentId === point2.segmentId\n ) {\n continue\n }\n\n // Check if they share a node\n const hasSharedNode = point1.capacityMeshNodeIds.some((nodeId) =>\n point2.capacityMeshNodeIds.includes(nodeId),\n )\n\n if (hasSharedNode) {\n const connectionKey = `${point1.segmentPointId}-${point2.segmentPointId}`\n if (processedConnections.has(connectionKey)) continue\n processedConnections.add(connectionKey)\n\n // Determine line style based on layer (z) values\n const sameLayer = point1.z === point2.z\n const layer = point1.z\n\n let strokeDash: string | undefined\n if (sameLayer) {\n strokeDash = layer === 0 ? undefined : \"10 5\" // Solid for layer 0, long dash for other layers\n } else {\n strokeDash = \"3 3 10\" // Mixed dash for transitions between layers\n }\n\n graphics.lines.push({\n points: [\n { x: point1.x, y: point1.y },\n { x: point2.x, y: point2.y },\n ],\n strokeDash,\n strokeColor: this.colorMap[point1.connectionName] || \"#666\",\n })\n }\n }\n }\n return graphics\n }\n\n getNodesWithPortPoints(): NodeWithPortPoints[] {\n if (!this.solved) {\n throw new Error(\n \"CapacitySegmentToPointSolver not solved, can't give port points yet\",\n )\n }\n const nodeWithPortPointsMap = new Map<string, NodeWithPortPoints>()\n for (const segment of this.dedupedSegments) {\n const segId = segment.nodePortSegmentId!\n for (const nodeId of this.segmentIdToNodeIds.get(segId)!) {\n const node = this.nodeMap.get(nodeId)!\n if (!nodeWithPortPointsMap.has(nodeId)) {\n nodeWithPortPointsMap.set(nodeId, {\n capacityMeshNodeId: nodeId,\n portPoints: [],\n center: node.center,\n width: node.width,\n height: node.height,\n })\n }\n }\n }\n\n for (const segmentPoint of this.segmentPointMap.values()) {\n for (const nodeId of segmentPoint.capacityMeshNodeIds) {\n const nodeWithPortPoints = nodeWithPortPointsMap.get(nodeId)\n if (nodeWithPortPoints) {\n nodeWithPortPoints.portPoints.push({\n x: segmentPoint.x,\n y: segmentPoint.y,\n z: segmentPoint.z,\n connectionName: segmentPoint.connectionName,\n })\n }\n }\n }\n\n return Array.from(nodeWithPortPointsMap.values())\n }\n}\n","import { Rect } from \"graphics-debug\"\nimport { CapacityMeshNode } from \"lib/types\"\n\nexport const createRectFromCapacityNode = (\n node: CapacityMeshNode,\n opts: {\n rectMargin?: number\n zOffset?: number\n } = {},\n): Rect => {\n const lowestZ = Math.min(...node.availableZ)\n return {\n center:\n !opts.rectMargin || opts.zOffset\n ? {\n x: node.center.x + lowestZ * node.width * (opts.zOffset ?? 0.05),\n y: node.center.y - lowestZ * node.width * (opts.zOffset ?? 0.05),\n }\n : node.center,\n width: opts.rectMargin\n ? node.width - opts.rectMargin * 2\n : Math.max(node.width - 0.5, node.width * 0.8),\n height: opts.rectMargin\n ? node.height - opts.rectMargin * 2\n : Math.max(node.height - 0.5, node.height * 0.8),\n fill: node._containsObstacle\n ? \"rgba(255,0,0,0.1)\"\n : ({\n \"0,1\": \"rgba(0,0,0,0.1)\",\n \"0\": \"rgba(0,200,200, 0.1)\",\n \"1\": \"rgba(0,0,200, 0.1)\",\n }[node.availableZ.join(\",\")] ?? \"rgba(0,200,200,0.1)\"),\n layer: `z${node.availableZ.join(\",\")}`,\n label: [\n node.capacityMeshNodeId,\n `availableZ: ${node.availableZ.join(\",\")}`,\n `${node._containsTarget ? \"containsTarget\" : \"\"}`,\n `${node._containsObstacle ? \"containsObstacle\" : \"\"}`,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n }\n}\n","import { BaseSolver } from \"../BaseSolver\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n CapacityMeshNodeId,\n CapacityPath,\n SimpleRouteConnection,\n SimpleRouteJson,\n} from \"../../types\"\nimport { getNodeEdgeMap } from \"../CapacityMeshSolver/getNodeEdgeMap\"\nimport { distance } from \"@tscircuit/math-utils\"\nimport { CapacityHyperParameters } from \"../CapacityHyperParameters\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { safeTransparentize } from \"../colors\"\nimport { createRectFromCapacityNode } from \"lib/utils/createRectFromCapacityNode\"\n\nexport type Candidate = {\n prevCandidate: Candidate | null\n node: CapacityMeshNode\n f: number\n g: number\n h: number\n}\n\nexport class CapacityPathingSolver extends BaseSolver {\n connectionsWithNodes: Array<{\n connection: SimpleRouteConnection\n nodes: CapacityMeshNode[]\n path?: CapacityMeshNode[]\n straightLineDistance: number\n }>\n\n usedNodeCapacityMap: Map<CapacityMeshNodeId, number>\n\n simpleRouteJson: SimpleRouteJson\n nodes: CapacityMeshNode[]\n edges: CapacityMeshEdge[]\n GREEDY_MULTIPLIER = 1.1\n\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n nodeEdgeMap: Map<CapacityMeshNodeId, CapacityMeshEdge[]>\n connectionNameToGoalNodeIds: Map<string, CapacityMeshNodeId[]>\n colorMap: Record<string, string>\n maxDepthOfNodes: number\n\n activeCandidateStraightLineDistance?: number\n\n debug_lastNodeCostMap: Map<\n CapacityMeshNodeId,\n {\n g: number\n h: number\n f: number\n }\n >\n\n hyperParameters: Partial<CapacityHyperParameters>\n\n constructor({\n simpleRouteJson,\n nodes,\n edges,\n colorMap,\n MAX_ITERATIONS = 1e6,\n hyperParameters = {},\n }: {\n simpleRouteJson: SimpleRouteJson\n nodes: CapacityMeshNode[]\n edges: CapacityMeshEdge[]\n colorMap?: Record<string, string>\n MAX_ITERATIONS?: number\n hyperParameters?: Partial<CapacityHyperParameters>\n }) {\n super()\n this.MAX_ITERATIONS = MAX_ITERATIONS\n this.simpleRouteJson = simpleRouteJson\n this.nodes = nodes\n this.edges = edges\n this.colorMap = colorMap ?? {}\n const { connectionsWithNodes, connectionNameToGoalNodeIds } =\n this.getConnectionsWithNodes()\n this.connectionsWithNodes = connectionsWithNodes\n this.connectionNameToGoalNodeIds = connectionNameToGoalNodeIds\n this.hyperParameters = hyperParameters\n this.usedNodeCapacityMap = new Map(\n this.nodes.map((node) => [node.capacityMeshNodeId, 0]),\n )\n this.nodeMap = new Map(\n this.nodes.map((node) => [node.capacityMeshNodeId, node]),\n )\n this.nodeEdgeMap = getNodeEdgeMap(this.edges)\n this.maxDepthOfNodes = Math.max(\n ...this.nodes.map((node) => node._depth ?? 0),\n )\n this.debug_lastNodeCostMap = new Map()\n }\n\n getTotalCapacity(node: CapacityMeshNode): number {\n const depth = node._depth ?? 0\n return (this.maxDepthOfNodes - depth + 1) ** 2\n }\n\n getConnectionsWithNodes() {\n const connectionsWithNodes: Array<{\n connection: SimpleRouteConnection\n nodes: CapacityMeshNode[]\n pathFound: boolean\n straightLineDistance: number\n }> = []\n const nodesWithTargets = this.nodes.filter((node) => node._containsTarget)\n const connectionNameToGoalNodeIds = new Map<string, CapacityMeshNodeId[]>()\n\n for (const connection of this.simpleRouteJson.connections) {\n const nodesForConnection: CapacityMeshNode[] = []\n for (const point of connection.pointsToConnect) {\n let closestNode = this.nodes[0]\n let minDistance = Number.MAX_VALUE\n\n for (const node of nodesWithTargets) {\n const distance = Math.sqrt(\n (node.center.x - point.x) ** 2 + (node.center.y - point.y) ** 2,\n )\n if (distance < minDistance) {\n minDistance = distance\n closestNode = node\n }\n }\n nodesForConnection.push(closestNode)\n }\n if (nodesForConnection.length < 2) {\n throw new Error(\n `Not enough nodes for connection \"${connection.name}\", only ${nodesForConnection.length} found`,\n )\n }\n connectionNameToGoalNodeIds.set(\n connection.name,\n nodesForConnection.map((n) => n.capacityMeshNodeId),\n )\n connectionsWithNodes.push({\n connection,\n nodes: nodesForConnection,\n pathFound: false,\n straightLineDistance: distance(\n nodesForConnection[0].center,\n nodesForConnection[nodesForConnection.length - 1].center,\n ),\n })\n }\n\n connectionsWithNodes.sort(\n (a, b) => a.straightLineDistance - b.straightLineDistance,\n )\n return { connectionsWithNodes, connectionNameToGoalNodeIds }\n }\n\n currentConnectionIndex = 0\n\n candidates?: Array<Candidate> | null\n visitedNodes?: Set<CapacityMeshNodeId> | null\n\n computeG(\n prevCandidate: Candidate,\n node: CapacityMeshNode,\n endGoal: CapacityMeshNode,\n ) {\n return (\n prevCandidate.g + this.getDistanceBetweenNodes(prevCandidate.node, node)\n )\n }\n\n computeH(\n prevCandidate: Candidate,\n node: CapacityMeshNode,\n endGoal: CapacityMeshNode,\n ) {\n return this.getDistanceBetweenNodes(node, endGoal)\n }\n\n getBacktrackedPath(candidate: Candidate) {\n const path: CapacityMeshNode[] = []\n let currentCandidate = candidate\n while (currentCandidate) {\n path.push(currentCandidate.node)\n currentCandidate = currentCandidate.prevCandidate!\n }\n return path\n }\n\n getNeighboringNodes(node: CapacityMeshNode) {\n return this.nodeEdgeMap\n .get(node.capacityMeshNodeId)!\n .flatMap((edge): CapacityMeshNodeId[] =>\n edge.nodeIds.filter((n) => n !== node.capacityMeshNodeId),\n )\n .map((n) => this.nodeMap.get(n)!)\n }\n\n getCapacityPaths() {\n const capacityPaths: CapacityPath[] = []\n for (const connection of this.connectionsWithNodes) {\n const path = connection.path\n if (path) {\n capacityPaths.push({\n capacityPathId: connection.connection.name,\n connectionName: connection.connection.name,\n nodeIds: path.map((node) => node.capacityMeshNodeId),\n })\n }\n }\n return capacityPaths\n }\n\n doesNodeHaveCapacityForTrace(\n node: CapacityMeshNode,\n prevNode: CapacityMeshNode,\n ) {\n const usedCapacity =\n this.usedNodeCapacityMap.get(node.capacityMeshNodeId) ?? 0\n const totalCapacity = this.getTotalCapacity(node)\n\n // Single layer nodes can't safely have multiple traces because there's no\n // way to cross over two traces without a via\n if (\n node.availableZ.length === 1 &&\n !node._containsTarget &&\n usedCapacity > 0\n )\n return false\n\n let additionalCapacityRequirement = 0\n if (node.availableZ.length > 1 && prevNode.availableZ.length === 1) {\n additionalCapacityRequirement += 0.5\n }\n\n return usedCapacity + additionalCapacityRequirement < totalCapacity\n }\n\n canTravelThroughObstacle(node: CapacityMeshNode, connectionName: string) {\n const goalNodeIds = this.connectionNameToGoalNodeIds.get(connectionName)\n\n return goalNodeIds?.includes(node.capacityMeshNodeId) ?? false\n }\n\n getDistanceBetweenNodes(A: CapacityMeshNode, B: CapacityMeshNode) {\n return Math.sqrt(\n (A.center.x - B.center.x) ** 2 + (A.center.y - B.center.y) ** 2,\n )\n }\n\n reduceCapacityAlongPath(nextConnection: {\n path?: CapacityMeshNode[]\n }) {\n for (const node of nextConnection.path ?? []) {\n this.usedNodeCapacityMap.set(\n node.capacityMeshNodeId,\n this.usedNodeCapacityMap.get(node.capacityMeshNodeId)! + 1,\n )\n }\n }\n\n isConnectedToEndGoal(node: CapacityMeshNode, endGoal: CapacityMeshNode) {\n return this.nodeEdgeMap\n .get(node.capacityMeshNodeId)!\n .some((edge) => edge.nodeIds.includes(endGoal.capacityMeshNodeId))\n }\n\n _step() {\n const nextConnection =\n this.connectionsWithNodes[this.currentConnectionIndex]\n if (!nextConnection) {\n this.solved = true\n return\n }\n const [start, end] = nextConnection.nodes\n if (!this.candidates) {\n this.candidates = [{ prevCandidate: null, node: start, f: 0, g: 0, h: 0 }]\n this.debug_lastNodeCostMap = new Map()\n this.visitedNodes = new Set([start.capacityMeshNodeId])\n this.activeCandidateStraightLineDistance = distance(\n start.center,\n end.center,\n )\n }\n\n this.candidates.sort((a, b) => a.f - b.f)\n const currentCandidate = this.candidates.shift()\n if (!currentCandidate) {\n // TODO Track failed paths, make sure solver doesn't think it solved\n console.error(\n `Ran out of candidates on connection ${nextConnection.connection.name}`,\n )\n this.currentConnectionIndex++\n this.candidates = null\n this.visitedNodes = null\n this.failed = true\n return\n }\n if (this.isConnectedToEndGoal(currentCandidate.node, end)) {\n nextConnection.path = this.getBacktrackedPath({\n prevCandidate: currentCandidate,\n node: end,\n f: 0,\n g: 0,\n h: 0,\n })\n\n this.reduceCapacityAlongPath(nextConnection)\n\n this.currentConnectionIndex++\n this.candidates = null\n this.visitedNodes = null\n return\n }\n\n const neighborNodes = this.getNeighboringNodes(currentCandidate.node)\n for (const neighborNode of neighborNodes) {\n if (this.visitedNodes?.has(neighborNode.capacityMeshNodeId)) {\n continue\n }\n if (\n !this.doesNodeHaveCapacityForTrace(neighborNode, currentCandidate.node)\n ) {\n continue\n }\n const connectionName =\n this.connectionsWithNodes[this.currentConnectionIndex].connection.name\n if (\n neighborNode._containsObstacle &&\n !this.canTravelThroughObstacle(neighborNode, connectionName)\n ) {\n continue\n }\n const g = this.computeG(currentCandidate, neighborNode, end)\n const h = this.computeH(currentCandidate, neighborNode, end)\n const f = g + h * this.GREEDY_MULTIPLIER\n\n this.debug_lastNodeCostMap.set(neighborNode.capacityMeshNodeId, {\n f,\n g,\n h,\n })\n\n const newCandidate = {\n prevCandidate: currentCandidate,\n node: neighborNode,\n f,\n g,\n h,\n }\n this.candidates.push(newCandidate)\n }\n this.visitedNodes!.add(currentCandidate.node.capacityMeshNodeId)\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n }\n\n // Visualize each solved connection path (draw a line through each node's center)\n if (this.connectionsWithNodes) {\n for (let i = 0; i < this.connectionsWithNodes.length; i++) {\n const conn = this.connectionsWithNodes[i]\n if (conn.path && conn.path.length > 0) {\n const pathPoints = conn.path.map(\n ({ center: { x, y }, width, availableZ }) => ({\n // slight offset to allow viewing overlapping paths\n x: x + ((i % 10) + (i % 19)) * (0.005 * width),\n y: y + ((i % 10) + (i % 19)) * (0.005 * width),\n availableZ,\n }),\n )\n graphics.lines!.push({\n points: pathPoints,\n strokeColor: this.colorMap[conn.connection.name],\n })\n for (let u = 0; u < pathPoints.length; u++) {\n const point = pathPoints[u]\n graphics.points!.push({\n x: point.x,\n y: point.y,\n label: [\n `conn: ${conn.connection.name}`,\n `node: ${conn.path[u].capacityMeshNodeId}`,\n `z: ${point.availableZ.join(\",\")}`,\n ].join(\"\\n\"),\n })\n }\n }\n }\n }\n\n for (const node of this.nodes) {\n const nodeCosts = this.debug_lastNodeCostMap.get(node.capacityMeshNodeId)\n graphics.rects!.push({\n ...createRectFromCapacityNode(node, {\n rectMargin: 0.025,\n zOffset: 0.01,\n }),\n label: [\n `${node.capacityMeshNodeId}`,\n `${this.usedNodeCapacityMap.get(node.capacityMeshNodeId)}/${this.getTotalCapacity(node).toFixed(2)}`,\n `${node.width.toFixed(2)}x${node.height.toFixed(2)}`,\n `g: ${nodeCosts?.g !== undefined ? nodeCosts.g.toFixed(2) : \"?\"}`,\n `h: ${nodeCosts?.h !== undefined ? nodeCosts.h.toFixed(2) : \"?\"}`,\n `f: ${nodeCosts?.f !== undefined ? nodeCosts.f.toFixed(2) : \"?\"}`,\n `z: ${node.availableZ.join(\", \")}`,\n ].join(\"\\n\"),\n })\n }\n\n // Visualize connection points from each connection as circles\n if (this.connectionsWithNodes) {\n for (const conn of this.connectionsWithNodes) {\n if (conn.connection?.pointsToConnect) {\n for (const point of conn.connection.pointsToConnect) {\n graphics.points!.push({\n x: point.x,\n y: point.y,\n label: [`pointsToConnect ${conn.connection.name}`].join(\"\\n\"),\n })\n }\n }\n }\n }\n\n // Draw a dashed line from the start node to the end node\n const nextConnection =\n this.connectionsWithNodes[this.currentConnectionIndex]\n if (nextConnection) {\n const [start, end] = nextConnection.connection.pointsToConnect\n graphics.lines!.push({\n points: [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ],\n strokeColor: \"red\",\n strokeDash: \"10 5\",\n })\n }\n\n // Visualize backtracked path of highest ranked candidate\n if (this.candidates) {\n // Get top 10 candidates\n const topCandidates = this.candidates.slice(0, 5)\n const connectionName =\n this.connectionsWithNodes[this.currentConnectionIndex].connection.name\n\n // Add paths for each candidate with decreasing opacity\n topCandidates.forEach((candidate, index) => {\n const opacity = 0.5 * (1 - index / 5) // Opacity decreases from 0.5 to 0.05\n const backtrackedPath = this.getBacktrackedPath(candidate)\n graphics.lines!.push({\n points: backtrackedPath.map(({ center: { x, y } }) => ({ x, y })),\n strokeColor: safeTransparentize(\n this.colorMap[connectionName] ?? \"red\",\n 1 - opacity,\n ),\n })\n })\n }\n\n return graphics\n }\n}\n","import type { CapacityMeshNode } from \"lib/types\"\nimport { CapacityPathingSolver, type Candidate } from \"./CapacityPathingSolver\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\n\nexport class CapacityPathingSolver5 extends CapacityPathingSolver {\n NEGATIVE_CAPACITY_PENALTY_FACTOR = 1\n REDUCED_CAPACITY_PENALTY_FACTOR = 1\n\n constructor(...args: ConstructorParameters<typeof CapacityPathingSolver>) {\n super(...args)\n this.GREEDY_MULTIPLIER = 2.5\n }\n\n get maxCapacityFactor() {\n return this.hyperParameters.MAX_CAPACITY_FACTOR ?? 1\n }\n\n getTotalCapacity(node: CapacityMeshNode): number {\n return getTunedTotalCapacity1(node, this.maxCapacityFactor)\n }\n\n /**\n * Penalty you pay for using this node\n */\n getNodeCapacityPenalty(node: CapacityMeshNode): number {\n // return 0.05\n\n const MAX_PENALTY = node.width + node.height\n const MIN_PENALTY = 0.05\n\n const START_PENALIZING_CAPACITY_WHEN_IT_DROPS_BELOW = 2\n\n const totalCapacity = this.getTotalCapacity(node)\n const usedCapacity =\n this.usedNodeCapacityMap.get(node.capacityMeshNodeId) ?? 0\n const remainingCapacity = totalCapacity - usedCapacity\n\n if (remainingCapacity > START_PENALIZING_CAPACITY_WHEN_IT_DROPS_BELOW) {\n return MIN_PENALTY\n }\n\n const penalty =\n (MAX_PENALTY - MIN_PENALTY) *\n Math.max(\n 1,\n (START_PENALIZING_CAPACITY_WHEN_IT_DROPS_BELOW - remainingCapacity) /\n (MAX_PENALTY - MIN_PENALTY),\n ) +\n MIN_PENALTY\n\n return penalty\n // const penalty =\n // (MAX_PENALTY - MIN_PENALTY) *\n // (remainingCapacity / START_PENALIZING_CAPACITY_WHEN_IT_DROPS_BELOW)\n\n // return penalty\n // if (node.availableZ.length === 1) {\n // return 0\n // }\n\n // const dist = this.activeCandidateStraightLineDistance!\n\n // if (remainingCapacity <= 0) {\n // // | Total Cap | Remaining Cap | Remaining Cap Ratio | PenaltySLD |\n // // | 1 | 0 | (-( 0) + 1) / 1 | 1^2 = 1 |\n // // | 1 | -1 | (-(-1) + 1) / 1 | 2^2 = 4 |\n // // | 1 | -2 | (-(-2) + 1) / 1 | 3^2 = 9 |\n // // | 2 | 0 | (-( 0) + 1) / 2 | 0.5^2 = 0.25 |\n // // | 2 | -1 | (-(-1) + 1) / 2 | 1^2 = 1 |\n // // | 2 | -2 | (-(-2) + 1) / 2 | 2^2 = 4 |\n // // | 2 | -3 | (-(-3) + 1) / 2 | 3^2 = 9 |\n // // | 3 | 0 | (-( 0) + 1) / 3 | 0.333^2= 0.111|\n // // | 3 | -1 | (-(-1) + 1) / 3 | 0.666^2= 0.444|\n // // | 3 | -2 | (-(-2) + 1) / 3 | 1^2 = 1 |\n // // | 3 | -3 | (-(-3) + 1) / 3 | 2^2 = 4 |\n // const penalty =\n // ((-remainingCapacity + 1) / totalCapacity) *\n // dist *\n // (this.NEGATIVE_CAPACITY_PENALTY_FACTOR / 4)\n\n // return penalty ** 2\n // }\n\n // This node still has capacity, but penalize as we reduce the capacity\n // return (\n // ((1 / remainingCapacity) * dist * this.REDUCED_CAPACITY_PENALTY_FACTOR) /\n // 8\n // )\n }\n\n /**\n * We're rewarding travel into big nodes.\n *\n * To minimize shortest path, you'd want to comment this out.\n */\n getDistanceBetweenNodes(A: CapacityMeshNode, B: CapacityMeshNode) {\n const dx = A.center.x - B.center.x\n const dy = A.center.y - B.center.y\n\n return Math.sqrt(dx ** 2 + dy ** 2)\n\n // REWARD BIG NODE TRAVEL\n // const szx = Math.max(A.width, B.width)\n // const szy = Math.max(A.height, B.height)\n\n // const dist = Math.sqrt(dx ** 2 + dy ** 2) / (szx * szy)\n\n // return dist\n }\n\n computeG(\n prevCandidate: Candidate,\n node: CapacityMeshNode,\n endGoal: CapacityMeshNode,\n ) {\n return (\n prevCandidate.g +\n this.getDistanceBetweenNodes(prevCandidate.node, node) +\n this.getNodeCapacityPenalty(node)\n )\n }\n\n computeH(\n prevCandidate: Candidate,\n node: CapacityMeshNode,\n endGoal: CapacityMeshNode,\n ) {\n return (\n this.getDistanceBetweenNodes(node, endGoal) +\n this.getNodeCapacityPenalty(node)\n )\n }\n}\n","import { CapacityMeshNode } from \"lib/types/capacity-mesh-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { getTunedTotalCapacity1 } from \"lib/utils/getTunedTotalCapacity1\"\n\nexport class StrawSolver extends BaseSolver {\n multiLayerNodes: CapacityMeshNode[]\n\n strawNodes: CapacityMeshNode[]\n skippedNodes: CapacityMeshNode[]\n\n unprocessedNodes: CapacityMeshNode[]\n strawSize: number\n\n nodeIdCounter: number\n\n constructor(params: {\n nodes: CapacityMeshNode[]\n strawSize?: number\n }) {\n super()\n this.MAX_ITERATIONS = 100e3\n this.strawSize = params.strawSize ?? 0.5\n this.multiLayerNodes = []\n this.strawNodes = []\n this.skippedNodes = []\n this.nodeIdCounter = 0\n this.unprocessedNodes = []\n for (const node of params.nodes) {\n if (node.availableZ.length === 1) {\n this.unprocessedNodes.push(node)\n } else {\n this.multiLayerNodes.push(node)\n }\n }\n }\n\n getCapacityOfMultiLayerNodesWithinBounds(bounds: {\n minX: number\n maxX: number\n minY: number\n maxY: number\n }): number {\n let totalCapacity = 0\n\n for (const node of this.multiLayerNodes) {\n // Calculate node bounds\n const nodeMinX = node.center.x - node.width / 2\n const nodeMaxX = node.center.x + node.width / 2\n const nodeMinY = node.center.y - node.height / 2\n const nodeMaxY = node.center.y + node.height / 2\n\n // Calculate overlap area\n const overlapMinX = Math.max(bounds.minX, nodeMinX)\n const overlapMaxX = Math.min(bounds.maxX, nodeMaxX)\n const overlapMinY = Math.max(bounds.minY, nodeMinY)\n const overlapMaxY = Math.min(bounds.maxY, nodeMaxY)\n\n // If there's an overlap\n if (overlapMinX < overlapMaxX && overlapMinY < overlapMaxY) {\n const overlapWidth = overlapMaxX - overlapMinX\n const overlapHeight = overlapMaxY - overlapMinY\n const overlapArea = overlapWidth * overlapHeight\n const nodeArea = node.width * node.height\n\n // Calculate proportion of node that overlaps\n const proportion = overlapArea / nodeArea\n\n // Add proportional capacity to total\n totalCapacity += getTunedTotalCapacity1(node) * proportion\n }\n }\n\n return totalCapacity\n }\n\n getSurroundingCapacities(node: CapacityMeshNode): {\n leftSurroundingCapacity: number\n rightSurroundingCapacity: number\n topSurroundingCapacity: number\n bottomSurroundingCapacity: number\n } {\n const searchDistance = Math.min(node.width, node.height)\n\n const leftSurroundingCapacity =\n this.getCapacityOfMultiLayerNodesWithinBounds({\n minX: node.center.x - node.width / 2 - searchDistance,\n maxX: node.center.x - node.width / 2,\n minY: node.center.y - node.height / 2,\n maxY: node.center.y + node.height / 2,\n })\n\n const rightSurroundingCapacity =\n this.getCapacityOfMultiLayerNodesWithinBounds({\n minX: node.center.x + node.width / 2,\n maxX: node.center.x + node.width / 2 + searchDistance,\n minY: node.center.y - node.height / 2,\n maxY: node.center.y + node.height / 2,\n })\n\n const topSurroundingCapacity =\n this.getCapacityOfMultiLayerNodesWithinBounds({\n minX: node.center.x - node.width / 2,\n maxX: node.center.x + node.width / 2,\n minY: node.center.y - node.height / 2 - searchDistance,\n maxY: node.center.y - node.height / 2,\n })\n\n const bottomSurroundingCapacity =\n this.getCapacityOfMultiLayerNodesWithinBounds({\n minX: node.center.x - node.width / 2,\n maxX: node.center.x + node.width / 2,\n minY: node.center.y + node.height / 2,\n maxY: node.center.y + node.height / 2 + searchDistance,\n })\n\n return {\n leftSurroundingCapacity,\n rightSurroundingCapacity,\n topSurroundingCapacity,\n bottomSurroundingCapacity,\n }\n }\n /**\n * Creates straw nodes from a single-layer node based on surrounding capacities\n */\n createStrawsForNode(node: CapacityMeshNode): CapacityMeshNode[] {\n const result: CapacityMeshNode[] = []\n const {\n leftSurroundingCapacity,\n rightSurroundingCapacity,\n topSurroundingCapacity,\n bottomSurroundingCapacity,\n } = this.getSurroundingCapacities(node)\n\n // Decide whether to create horizontal or vertical straws\n const horizontalCapacity =\n leftSurroundingCapacity + rightSurroundingCapacity\n const verticalCapacity = topSurroundingCapacity + bottomSurroundingCapacity\n\n // Layer-specific preferred direction\n // Layer 0 (top) prefers horizontal traces, Layer 1 (bottom) prefers vertical\n const layerPrefersFactor = 1 // node.availableZ[0] === 0 ? 1.3 : 0.7\n\n const effectiveHorizontalCapacity = horizontalCapacity * layerPrefersFactor\n\n // Create straws based on dimensions and surrounding capacity\n if (effectiveHorizontalCapacity > verticalCapacity) {\n // Create horizontal straws\n const numStraws = Math.floor(node.height / this.strawSize)\n const strawHeight = node.height / numStraws\n\n for (let i = 0; i < numStraws; i++) {\n const strawCenterY =\n node.center.y - node.height / 2 + i * strawHeight + strawHeight / 2\n\n result.push({\n capacityMeshNodeId: `${node.capacityMeshNodeId}_straw${i}`,\n center: { x: node.center.x, y: strawCenterY },\n width: node.width,\n height: strawHeight,\n layer: node.layer,\n availableZ: [...node.availableZ],\n _depth: node._depth,\n _strawNode: true,\n _strawParentCapacityMeshNodeId: node.capacityMeshNodeId,\n })\n }\n } else {\n // Create vertical straws\n const numStraws = Math.floor(node.width / this.strawSize)\n const strawWidth = node.width / numStraws\n\n for (let i = 0; i < numStraws; i++) {\n const strawCenterX =\n node.center.x - node.width / 2 + i * strawWidth + strawWidth / 2\n\n result.push({\n capacityMeshNodeId: `${node.capacityMeshNodeId}_straw${i}`,\n center: { x: strawCenterX, y: node.center.y },\n width: strawWidth,\n height: node.height,\n layer: node.layer,\n availableZ: [...node.availableZ],\n _depth: node._depth,\n _strawNode: true,\n _strawParentCapacityMeshNodeId: node.capacityMeshNodeId,\n })\n }\n }\n\n return result\n }\n\n getResultNodes(): CapacityMeshNode[] {\n return [...this.multiLayerNodes, ...this.strawNodes, ...this.skippedNodes]\n }\n\n _step() {\n const rootNode = this.unprocessedNodes.pop()\n\n if (!rootNode) {\n this.solved = true\n return\n }\n\n // Skip nodes that are too small to subdivide\n if (rootNode.width < this.strawSize && rootNode.height < this.strawSize) {\n this.skippedNodes.push(rootNode)\n return\n }\n\n // Skip target nodes (keep them intact)\n if (rootNode._containsTarget) {\n this.skippedNodes.push(rootNode)\n return\n }\n\n // Create straws for this node\n const strawNodes = this.createStrawsForNode(rootNode)\n this.strawNodes.push(...strawNodes)\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n rects: [],\n lines: [],\n points: [],\n circles: [],\n title: \"Straw Solver\",\n }\n\n // Draw unprocessed nodes\n for (const node of this.unprocessedNodes) {\n graphics.rects!.push({\n center: node.center,\n width: node.width,\n height: node.height,\n fill: \"rgba(200, 200, 200, 0.5)\",\n stroke: \"rgba(0, 0, 0, 0.5)\",\n label: `${node.capacityMeshNodeId}\\nUnprocessed\\n${node.width}x${node.height}`,\n })\n }\n\n // Draw straw nodes with different colors based on layer\n for (const node of this.strawNodes) {\n const color =\n node.availableZ[0] === 0\n ? \"rgba(0, 150, 255, 0.5)\"\n : \"rgba(255, 100, 0, 0.5)\"\n\n graphics.rects!.push({\n center: node.center,\n width: node.width,\n height: node.height,\n fill: color,\n stroke: \"rgba(0, 0, 0, 0.5)\",\n label: `${node.capacityMeshNodeId}\\nLayer: ${node.availableZ[0]}\\n${node.width}x${node.height}`,\n layer: `z${node.availableZ.join(\",\")}`,\n })\n }\n\n // Draw multi-layer nodes\n for (const node of this.multiLayerNodes) {\n graphics.rects!.push({\n center: node.center,\n width: node.width * 0.9,\n height: node.height * 0.9,\n fill: \"rgba(100, 255, 100, 0.5)\",\n stroke: \"rgba(0, 0, 0, 0.5)\",\n layer: `z${node.availableZ.join(\",\")}`,\n label: `${node.capacityMeshNodeId}\\nLayers: ${node.availableZ.join(\",\")}\\n${node.width}x${node.height}`,\n })\n }\n\n return graphics\n }\n}\n","import { CapacityMeshNode } from \"../types\"\n\nexport function areNodesBordering(\n node1: CapacityMeshNode,\n node2: CapacityMeshNode,\n): boolean {\n const n1Left = node1.center.x - node1.width / 2\n const n1Right = node1.center.x + node1.width / 2\n const n1Top = node1.center.y - node1.height / 2\n const n1Bottom = node1.center.y + node1.height / 2\n\n const n2Left = node2.center.x - node2.width / 2\n const n2Right = node2.center.x + node2.width / 2\n const n2Top = node2.center.y - node2.height / 2\n const n2Bottom = node2.center.y + node2.height / 2\n\n const epsilon = 0.001\n\n const shareVerticalBorder =\n (Math.abs(n1Right - n2Left) < epsilon ||\n Math.abs(n1Left - n2Right) < epsilon) &&\n Math.min(n1Bottom, n2Bottom) - Math.max(n1Top, n2Top) >= epsilon\n\n const shareHorizontalBorder =\n (Math.abs(n1Bottom - n2Top) < epsilon ||\n Math.abs(n1Top - n2Bottom) < epsilon) &&\n Math.min(n1Right, n2Right) - Math.max(n1Left, n2Left) >= epsilon\n\n return shareVerticalBorder || shareHorizontalBorder\n}\n","import { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\n\nexport type BucketCoordinate = `${number}x${number}`\n\nexport class CapacityNodeTree {\n buckets: Map<BucketCoordinate, CapacityMeshNode[]>\n CELL_SIZE = 0.4\n\n constructor(public nodes: CapacityMeshNode[]) {\n this.buckets = new Map()\n for (const node of nodes) {\n const nodeMinX = node.center.x - node.width / 2\n const nodeMinY = node.center.y - node.height / 2\n const nodeMaxX = node.center.x + node.width / 2\n const nodeMaxY = node.center.y + node.height / 2\n for (let x = nodeMinX; x <= nodeMaxX; x += this.CELL_SIZE) {\n for (let y = nodeMinY; y <= nodeMaxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey)\n if (!bucket) {\n this.buckets.set(bucketKey, [node])\n } else {\n bucket.push(node)\n }\n }\n }\n }\n }\n\n getBucketKey(x: number, y: number): BucketCoordinate {\n return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`\n }\n\n getNodesInArea(\n centerX: number,\n centerY: number,\n width: number,\n height: number,\n ) {\n const nodes: CapacityMeshNode[] = []\n const alreadyAddedNodes = new Set<CapacityMeshNodeId>()\n const minX = centerX - width / 2\n const minY = centerY - height / 2\n const maxX = centerX + width / 2\n const maxY = centerY + height / 2\n for (let x = minX; x <= maxX; x += this.CELL_SIZE) {\n for (let y = minY; y <= maxY; y += this.CELL_SIZE) {\n const bucketKey = this.getBucketKey(x, y)\n const bucket = this.buckets.get(bucketKey) || []\n for (const node of bucket) {\n if (alreadyAddedNodes.has(node.capacityMeshNodeId)) continue\n alreadyAddedNodes.add(node.capacityMeshNodeId)\n nodes.push(node)\n }\n }\n }\n return nodes\n }\n}\n","import { CapacityMeshNode, CapacityMeshNodeId } from \"lib/types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { areNodesBordering } from \"lib/utils/areNodesBordering\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { createRectFromCapacityNode } from \"lib/utils/createRectFromCapacityNode\"\nimport { CapacityNodeTree } from \"lib/data-structures/CapacityNodeTree\"\n\nconst EPSILON = 0.005\n\n/**\n * Merges same layer nodes into larger nodes. Pre-processing stage necessary\n * for \"strawing\".\n */\nexport class SingleLayerNodeMergerSolver extends BaseSolver {\n nodeMap: Map<CapacityMeshNodeId, CapacityMeshNode>\n currentBatchNodeIds: CapacityMeshNodeId[]\n\n absorbedNodeIds: Set<CapacityMeshNodeId>\n\n nextBatchNodeIds: CapacityMeshNodeId[]\n batchHadModifications: boolean\n\n hasComputedAdjacentNodeIds: boolean = false\n\n newNodes: CapacityMeshNode[]\n constructor(nodes: CapacityMeshNode[]) {\n super()\n this.nodeMap = new Map()\n this.MAX_ITERATIONS = 100_000\n // TODO we probably don't need this map because we only care about\n // nodes that need to be absorbed or processed\n for (const node of nodes) {\n this.nodeMap.set(node.capacityMeshNodeId, node)\n }\n this.newNodes = []\n this.absorbedNodeIds = new Set()\n const unprocessedNodesWithArea: Array<[CapacityMeshNode, number]> = []\n for (const node of nodes) {\n if (node.availableZ.length > 1) {\n this.newNodes.push(node)\n this.absorbedNodeIds.add(node.capacityMeshNodeId)\n } else {\n unprocessedNodesWithArea.push([node, node.width * node.height])\n }\n }\n unprocessedNodesWithArea.sort((a, b) => a[1] - b[1])\n for (const [node, area] of unprocessedNodesWithArea) {\n const unprocessedNode = {\n ...node,\n center: { ...node.center },\n }\n this.nodeMap.set(node.capacityMeshNodeId, unprocessedNode)\n }\n this.currentBatchNodeIds = unprocessedNodesWithArea.map(\n ([node]) => node.capacityMeshNodeId,\n )\n this.nextBatchNodeIds = []\n this.batchHadModifications = false\n }\n\n computeAdjacentNodeIdsForFirstBatch(nodes: CapacityMeshNode[]) {\n const nodeTrees = [\n new CapacityNodeTree(nodes.filter((n) => n.availableZ[0] === 0)),\n new CapacityNodeTree(nodes.filter((n) => n.availableZ[0] === 1)),\n ]\n for (const node of nodes) {\n const adjacentNodes: CapacityMeshNode[] = []\n const z = node.availableZ[0]\n\n const nodesInArea = nodeTrees[z].getNodesInArea(\n node.center.x,\n node.center.y,\n node.width * 4,\n node.height * 4,\n )\n\n for (const unprocessedNode of nodesInArea) {\n if (\n unprocessedNode._containsTarget &&\n unprocessedNode._targetConnectionName !== node._targetConnectionName\n )\n continue\n // if (this.absorbedNodeIds.has(unprocessedNode.capacityMeshNodeId))\n // continue\n if (unprocessedNode.capacityMeshNodeId === node.capacityMeshNodeId)\n continue\n if (!areNodesBordering(node, unprocessedNode)) continue\n\n adjacentNodes.push(unprocessedNode)\n }\n\n node._adjacentNodeIds = adjacentNodes.map((n) => n.capacityMeshNodeId)\n }\n }\n\n // getAdjacentSameLayerUnprocessedNodes1(rootNode: CapacityMeshNode) {\n // const adjacentNodes: CapacityMeshNode[] = []\n // for (const unprocessedNodeId of this.currentBatchNodeIds) {\n // const unprocessedNode = this.nodeMap.get(unprocessedNodeId)!\n // if (!areNodesBordering(rootNode, unprocessedNode)) continue\n // if (unprocessedNode.availableZ[0] !== rootNode.availableZ[0]) continue\n // if (\n // unprocessedNode._containsTarget &&\n // unprocessedNode._targetConnectionName !== rootNode._targetConnectionName\n // )\n // continue\n // if (this.absorbedNodeIds.has(unprocessedNodeId)) continue\n // adjacentNodes.push(unprocessedNode)\n // }\n // return adjacentNodes\n // }\n\n getAdjacentSameLayerUnprocessedNodes(rootNode: CapacityMeshNode) {\n return this.getAdjacentSameLayerUnprocessedNodes2(rootNode)\n }\n\n getAdjacentSameLayerUnprocessedNodes2(rootNode: CapacityMeshNode) {\n const adjacentNodes: CapacityMeshNode[] = []\n const unprocessedAdjNodes: CapacityMeshNode[] = Array.from(\n new Set(\n (rootNode._adjacentNodeIds ?? []).map((a) => this.nodeMap.get(a)!),\n ),\n )\n\n unprocessedAdjNodes.sort((a, b) => a.width * a.height - b.width * b.height)\n\n for (const unprocessedNode of unprocessedAdjNodes) {\n if (this.absorbedNodeIds.has(unprocessedNode.capacityMeshNodeId)) continue\n adjacentNodes.push(unprocessedNode)\n }\n\n return adjacentNodes\n }\n\n _step() {\n if (!this.hasComputedAdjacentNodeIds) {\n this.computeAdjacentNodeIdsForFirstBatch(\n this.currentBatchNodeIds.map((id) => this.nodeMap.get(id)!),\n )\n this.hasComputedAdjacentNodeIds = true\n }\n let rootNodeId = this.currentBatchNodeIds.pop()\n while (rootNodeId && this.absorbedNodeIds.has(rootNodeId)) {\n rootNodeId = this.currentBatchNodeIds.pop()\n }\n\n if (!rootNodeId) {\n if (this.batchHadModifications) {\n this.currentBatchNodeIds = this.nextBatchNodeIds.sort((a, b) => {\n const A = this.nodeMap.get(a)!\n const B = this.nodeMap.get(b)!\n return A.width * A.height - B.width * B.height\n })\n this.nextBatchNodeIds = []\n this.batchHadModifications = false\n return\n }\n\n this.solved = true\n this.newNodes.push(\n ...this.nextBatchNodeIds.map((id) => this.nodeMap.get(id)!),\n )\n return\n }\n\n const rootNode = this.nodeMap.get(rootNodeId)!\n let rootNodeHasGrown = false\n\n const adjacentNodes = this.getAdjacentSameLayerUnprocessedNodes(rootNode)\n\n if (adjacentNodes.length === 0) {\n this.nextBatchNodeIds.push(rootNodeId)\n return\n }\n\n const absorbAdjacentNodeIds = (nodesToAbsorb: CapacityMeshNode[]) => {\n for (const adjNode of nodesToAbsorb) {\n this.absorbedNodeIds.add(adjNode.capacityMeshNodeId)\n }\n\n rootNode._adjacentNodeIds = Array.from(\n new Set(\n [\n ...(rootNode._adjacentNodeIds ?? []),\n ...nodesToAbsorb.flatMap((n) => n._adjacentNodeIds ?? []),\n ].filter((id) => !this.absorbedNodeIds.has(id)),\n ),\n )\n }\n\n // Handle adjacent nodes to the LEFT\n const adjacentNodesToLeft = adjacentNodes.filter(\n (adjNode) =>\n adjNode.center.x < rootNode.center.x &&\n Math.abs(adjNode.center.y - rootNode.center.y) < rootNode.height / 2,\n )\n\n if (adjacentNodesToLeft.length > 0) {\n const { width: leftAdjNodeWidth, height: leftAdjNodeHeight } =\n adjacentNodesToLeft[0]\n const leftAdjNodesAreAllSameSize = adjacentNodesToLeft.every(\n (adjNode) =>\n adjNode.width === leftAdjNodeWidth &&\n adjNode.height === leftAdjNodeHeight,\n )\n\n const leftAdjNodesTakeUpEntireHeight =\n Math.abs(\n adjacentNodesToLeft.reduce((acc, adjNode) => {\n return acc + adjNode.height\n }, 0) - rootNode.height,\n ) < EPSILON\n\n if (leftAdjNodesTakeUpEntireHeight && leftAdjNodesAreAllSameSize) {\n rootNode.width += leftAdjNodeWidth\n rootNode.center.x = rootNode.center.x - leftAdjNodeWidth / 2\n\n absorbAdjacentNodeIds(adjacentNodesToLeft)\n\n rootNodeHasGrown = true\n }\n }\n\n // Handle adjacent nodes to the RIGHT\n const adjacentNodesToRight = adjacentNodes.filter(\n (adjNode) =>\n adjNode.center.x > rootNode.center.x &&\n Math.abs(adjNode.center.y - rootNode.center.y) < rootNode.height / 2,\n )\n\n if (adjacentNodesToRight.length > 0 && !rootNodeHasGrown) {\n const { width: rightAdjNodeWidth, height: rightAdjNodeHeight } =\n adjacentNodesToRight[0]\n const rightAdjNodesAreAllSameSize = adjacentNodesToRight.every(\n (adjNode) =>\n adjNode.width === rightAdjNodeWidth &&\n adjNode.height === rightAdjNodeHeight,\n )\n\n const rightAdjNodesTakeUpEntireHeight =\n Math.abs(\n adjacentNodesToRight.reduce((acc, adjNode) => {\n return acc + adjNode.height\n }, 0) - rootNode.height,\n ) < EPSILON\n\n if (rightAdjNodesTakeUpEntireHeight && rightAdjNodesAreAllSameSize) {\n rootNode.width += rightAdjNodeWidth\n rootNode.center.x = rootNode.center.x + rightAdjNodeWidth / 2\n\n absorbAdjacentNodeIds(adjacentNodesToRight)\n\n rootNodeHasGrown = true\n }\n }\n\n // Handle adjacent nodes to the TOP\n const adjacentNodesToTop = adjacentNodes.filter(\n (adjNode) =>\n adjNode.center.y > rootNode.center.y &&\n Math.abs(adjNode.center.x - rootNode.center.x) < rootNode.width / 2,\n )\n\n if (adjacentNodesToTop.length > 0 && !rootNodeHasGrown) {\n const { width: topAdjNodeWidth, height: topAdjNodeHeight } =\n adjacentNodesToTop[0]\n const topAdjNodesAreAllSameSize = adjacentNodesToTop.every(\n (adjNode) =>\n adjNode.width === topAdjNodeWidth &&\n adjNode.height === topAdjNodeHeight,\n )\n\n const topAdjNodesTakeUpEntireWidth =\n Math.abs(\n adjacentNodesToTop.reduce((acc, adjNode) => {\n return acc + adjNode.width\n }, 0) - rootNode.width,\n ) < EPSILON\n\n if (topAdjNodesTakeUpEntireWidth && topAdjNodesAreAllSameSize) {\n rootNode.height += topAdjNodeHeight\n rootNode.center.y = rootNode.center.y + topAdjNodeHeight / 2\n\n absorbAdjacentNodeIds(adjacentNodesToTop)\n\n rootNodeHasGrown = true\n }\n }\n\n // Handle adjacent nodes to the BOTTOM\n const adjacentNodesToBottom = adjacentNodes.filter(\n (adjNode) =>\n adjNode.center.y < rootNode.center.y &&\n Math.abs(adjNode.center.x - rootNode.center.x) < rootNode.width / 2,\n )\n\n if (adjacentNodesToBottom.length > 0 && !rootNodeHasGrown) {\n const { width: bottomAdjNodeWidth, height: bottomAdjNodeHeight } =\n adjacentNodesToBottom[0]\n const bottomAdjNodesAreAllSameSize = adjacentNodesToBottom.every(\n (adjNode) =>\n adjNode.width === bottomAdjNodeWidth &&\n adjNode.height === bottomAdjNodeHeight,\n )\n\n const bottomAdjNodesTakeUpEntireWidth =\n Math.abs(\n adjacentNodesToBottom.reduce((acc, adjNode) => {\n return acc + adjNode.width\n }, 0) - rootNode.width,\n ) < EPSILON\n\n if (bottomAdjNodesTakeUpEntireWidth && bottomAdjNodesAreAllSameSize) {\n rootNode.height += bottomAdjNodeHeight\n rootNode.center.y = rootNode.center.y - bottomAdjNodeHeight / 2\n\n absorbAdjacentNodeIds(adjacentNodesToBottom)\n\n rootNodeHasGrown = true\n }\n }\n\n if (rootNodeHasGrown) {\n this.batchHadModifications = true\n this.currentBatchNodeIds.push(rootNodeId)\n } else {\n this.nextBatchNodeIds.unshift(rootNodeId)\n // this.processedNodeIds.add(rootNodeId)\n // this.newNodes.push(rootNode)\n }\n }\n\n visualize(): GraphicsObject {\n const graphics = {\n circles: [],\n lines: [],\n points: [],\n rects: [],\n coordinateSystem: \"cartesian\",\n title: \"Same Layer Node Merger\",\n } as Required<GraphicsObject>\n\n for (const node of this.newNodes) {\n graphics.rects.push(createRectFromCapacityNode(node))\n }\n\n const nextNodeIdInBatch =\n this.currentBatchNodeIds[this.currentBatchNodeIds.length - 1]\n let adjacentNodes: CapacityMeshNode[] | undefined\n if (nextNodeIdInBatch) {\n adjacentNodes = this.getAdjacentSameLayerUnprocessedNodes(\n this.nodeMap.get(nextNodeIdInBatch)!,\n )\n }\n\n // Visualize unprocessed nodes with a different style\n for (const nodeId of this.currentBatchNodeIds) {\n const node = this.nodeMap.get(nodeId)\n if (this.absorbedNodeIds.has(nodeId)) continue\n if (node) {\n const rect = createRectFromCapacityNode(node, {\n rectMargin: 0.01,\n })\n if (nodeId === nextNodeIdInBatch) {\n rect.stroke = \"rgba(0, 255, 0, 0.8)\" // Green for next node in batch\n } else if (\n adjacentNodes?.some(\n (adjNode) => adjNode.capacityMeshNodeId === nodeId,\n )\n ) {\n rect.stroke = \"rgba(128, 0, 128, 0.8)\" // Purple for adjacent nodes\n } else {\n rect.stroke = \"rgba(255, 165, 0, 0.8)\" // Orange border for other nodes\n }\n rect.layer = `z${node.availableZ.join(\",\")}`\n rect.label = `${rect.label}\\n(unprocessed)`\n graphics.rects.push(rect)\n }\n }\n\n // Visualize next batch nodes with a different style\n for (const nodeId of this.nextBatchNodeIds) {\n const node = this.nodeMap.get(nodeId)\n if (this.absorbedNodeIds.has(nodeId)) continue\n if (node) {\n const rect = createRectFromCapacityNode(node, {\n rectMargin: 0.01,\n })\n rect.layer = `z${node.availableZ.join(\",\")}`\n rect.stroke = \"rgba(0, 217, 255, 0.8)\" // Green border\n rect.label = `${rect.label}\\nx: ${node.center.x}, y: ${node.center.y}\\n${node.width}x${node.height}\\n(next batch)`\n graphics.rects.push(rect)\n }\n }\n\n return graphics\n }\n}\n","import { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { Obstacle } from \"lib/types\"\nimport { calculate45DegreePaths } from \"lib/utils/calculate45DegreePaths\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\n\ninterface Point {\n x: number\n y: number\n z: number\n}\n\nexport class SingleSimplifiedPathSolver extends BaseSolver {\n newRoute: HighDensityIntraNodeRoute[\"route\"]\n newVias: HighDensityIntraNodeRoute[\"vias\"]\n\n headIndex = 0\n tailIndex = 0\n\n inputRoute: HighDensityIntraNodeRoute\n otherHdRoutes: HighDensityIntraNodeRoute[]\n obstacles: Obstacle[]\n connMap: ConnectivityMap\n colorMap: Record<string, string>\n\n constructor(params: {\n inputRoute: HighDensityIntraNodeRoute\n otherHdRoutes: HighDensityIntraNodeRoute[]\n obstacles: Obstacle[]\n connMap: ConnectivityMap\n colorMap: Record<string, string>\n }) {\n super()\n\n this.inputRoute = params.inputRoute\n this.otherHdRoutes = params.otherHdRoutes\n this.obstacles = params.obstacles\n this.connMap = params.connMap\n this.colorMap = params.colorMap\n\n this.newRoute = [this.inputRoute.route[0]]\n this.newVias = []\n }\n\n getConstructorParams() {\n return {\n inputRoute: this.inputRoute,\n otherHdRoutes: this.otherHdRoutes,\n obstacles: this.obstacles,\n connMap: this.connMap.netMap,\n colorMap: this.colorMap,\n }\n }\n\n get simplifiedRoute(): HighDensityIntraNodeRoute {\n return {\n connectionName: this.inputRoute.connectionName,\n traceThickness: this.inputRoute.traceThickness,\n viaDiameter: this.inputRoute.viaDiameter,\n route: this.newRoute,\n vias: this.newVias,\n }\n }\n\n isValidPath(pointsInRoute: Point[]): boolean {\n // check that the segments don't intersect with any obstacles or other\n // routes or vias\n throw new Error(\"Not implemented\")\n }\n\n _step() {\n // Each iteration, we're going to increase the head and make sure that\n // there's a compatible simplified path from the tail to the head\n // If there isn't a compatible simplified path, we add a segment to the new\n // route from [tail, tail + (head - tail) / 2] then start our next iteration\n // at tail = tail + Math.ceil((head - tail) / 2)\n // If there is a Z change between the tail and the head, we stop the\n // simplification for that segment (add to newRoute and newVias, set tail to\n // head)\n throw new Error(\"Not implemented\")\n }\n\n getVisualsForNewRouteAndObstacles() {\n const graphics: Required<GraphicsObject> = {\n lines: [],\n points: [],\n circles: [],\n rects: [],\n coordinateSystem: \"cartesian\",\n title: \"Simplified Path Solver\",\n }\n\n // Visualize the original route in red\n for (let i = 0; i < this.inputRoute.route.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: this.inputRoute.route[i].x, y: this.inputRoute.route[i].y },\n {\n x: this.inputRoute.route[i + 1].x,\n y: this.inputRoute.route[i + 1].y,\n },\n ],\n strokeColor: \"rgba(255, 0, 0, 0.8)\",\n strokeDash: this.inputRoute.route[i].z === 1 ? \"5, 5\" : undefined,\n layer: `z${this.inputRoute.route[i].z.toString()}`,\n })\n }\n\n // Visualize the simplified route in green\n for (let i = 0; i < this.newRoute.length; i++) {\n if (i < this.newRoute.length - 1) {\n graphics.lines.push({\n points: [\n { x: this.newRoute[i].x, y: this.newRoute[i].y },\n { x: this.newRoute[i + 1].x, y: this.newRoute[i + 1].y },\n ],\n strokeWidth: 0.15,\n strokeColor: \"rgba(0, 255, 0, 0.8)\",\n strokeDash: this.newRoute[i].z === 1 ? [0.4, 0.4] : undefined,\n layer: `z${this.newRoute[i].z.toString()}`,\n })\n }\n graphics.points.push({\n x: this.newRoute[i].x,\n y: this.newRoute[i].y,\n color: \"rgba(0, 255, 0, 0.8)\",\n label: `z: ${this.newRoute[i].z}`,\n layer: `z${this.newRoute[i].z.toString()}`,\n })\n }\n\n // // Visualize vias\n for (const via of this.newVias) {\n graphics.circles.push({\n center: via,\n radius: this.inputRoute.viaDiameter / 2,\n fill: \"rgba(0, 0, 255, 0.5)\",\n })\n }\n\n // Visualize obstacles\n for (const obstacle of this.obstacles) {\n graphics.rects.push({\n center: obstacle.center,\n width: obstacle.width,\n height: obstacle.height,\n fill: obstacle.layers?.includes(\"top\")\n ? \"rgba(255, 0, 0, 0.3)\"\n : obstacle.layers?.includes(\"bottom\")\n ? \"rgba(0, 0, 255, 0.3)\"\n : \"rgba(128, 128, 128, 0.3)\",\n })\n }\n\n // Visualize other routes as obstacles (in purple)\n for (const route of this.otherHdRoutes) {\n for (let i = 0; i < route.route.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: route.route[i].x, y: route.route[i].y },\n { x: route.route[i + 1].x, y: route.route[i + 1].y },\n ],\n strokeWidth: 0.15,\n strokeColor:\n route.route[i].z === 0\n ? \"rgba(255, 0, 255, 0.5)\" // top layer (purple)\n : route.route[i].z === 1\n ? \"rgba(128, 0, 128, 0.5)\" // inner layer (darker purple)\n : \"rgba(0, 0, 255, 0.5)\", // bottom layer (blue)\n layer: `z${route.route[i].z.toString()}`,\n })\n }\n }\n\n if (\"filteredObstaclePathSegments\" in this) {\n const filteredObstaclePathSegments = this\n .filteredObstaclePathSegments as Array<[Point, Point]>\n for (const [start, end] of filteredObstaclePathSegments) {\n graphics.lines.push({\n points: [start, end],\n })\n }\n }\n\n return graphics\n }\n}\n","interface Point {\n x: number\n y: number\n}\n\nexport const calculate45DegreePaths = (\n pointA: Point,\n pointB: Point,\n): Array<Array<Point>> => {\n const result: Array<Array<Point>> = []\n const dx = Math.abs(pointB.x - pointA.x)\n const dy = Math.abs(pointB.y - pointA.y)\n const signX = pointB.x > pointA.x ? 1 : -1\n const signY = pointB.y > pointA.y ? 1 : -1\n\n // Path 1: Horizontal then 45 degrees\n const midPoint1: Point = {\n x: pointB.x - signX * Math.abs(pointB.y - pointA.y),\n y: pointA.y,\n }\n // Check if midpoint is within bounds\n if (\n (midPoint1.x - pointA.x) * signX >= 0 &&\n (midPoint1.x - pointB.x) * signX <= 0\n ) {\n result.push([pointA, midPoint1, pointB])\n }\n\n // Path 2: Vertical then 45 degrees\n const midPoint2: Point = {\n x: pointA.x,\n y: pointB.y - signY * Math.abs(pointB.x - pointA.x),\n }\n // Check if midpoint is within bounds\n if (\n (midPoint2.y - pointA.y) * signY >= 0 &&\n (midPoint2.y - pointB.y) * signY <= 0\n ) {\n result.push([pointA, midPoint2, pointB])\n }\n\n // // Calculate 45-degree points\n const minDist = Math.min(dx, dy)\n\n // // Path 3: 45 degrees then horizontal\n const midPoint3: Point = {\n x: pointA.x + signX * minDist,\n y: pointA.y + signY * minDist,\n }\n // Check if midpoint is within bounds\n if (\n (midPoint3.x - pointA.x) * signX >= 0 &&\n (midPoint3.x - pointB.x) * signX <= 0 &&\n (midPoint3.y - pointA.y) * signY >= 0 &&\n (midPoint3.y - pointB.y) * signY <= 0\n ) {\n result.push([pointA, midPoint3, pointB])\n }\n\n return result\n}\n","interface Point {\n x: number\n y: number\n}\n\n/**\n * Calculates the minimum distance between two line segments.\n * @param A1 First point of the first line segment\n * @param A2 Second point of the first line segment\n * @param B1 First point of the second line segment\n * @param B2 Second point of the second line segment\n * @returns The minimum distance between the two line segments\n */\nexport function minimumDistanceBetweenSegments(\n A1: Point,\n A2: Point,\n B1: Point,\n B2: Point,\n): number {\n // Check if segments intersect\n if (segmentsIntersect(A1, A2, B1, B2)) {\n return 0\n }\n\n // Calculate distances from each endpoint to the other segment\n const distA1 = pointToSegmentDistance(A1, B1, B2)\n const distA2 = pointToSegmentDistance(A2, B1, B2)\n const distB1 = pointToSegmentDistance(B1, A1, A2)\n const distB2 = pointToSegmentDistance(B2, A1, A2)\n\n // Return the minimum of the four distances\n return Math.min(distA1, distA2, distB1, distB2)\n}\n\n/**\n * Calculates the distance from a point to a line segment.\n * @param P The point\n * @param Q1 First point of the line segment\n * @param Q2 Second point of the line segment\n * @returns The minimum distance from point P to the line segment Q1Q2\n */\nfunction pointToSegmentDistance(P: Point, Q1: Point, Q2: Point): number {\n const v = { x: Q2.x - Q1.x, y: Q2.y - Q1.y }\n const w = { x: P.x - Q1.x, y: P.y - Q1.y }\n\n // Calculate squared length of the segment\n const c1 = dotProduct(w, v)\n if (c1 <= 0) {\n // Point is behind Q1\n return distance(P, Q1)\n }\n\n const c2 = dotProduct(v, v)\n if (c2 <= c1) {\n // Point is beyond Q2\n return distance(P, Q2)\n }\n\n // Point projects onto the segment\n const b = c1 / c2\n const Pb = {\n x: Q1.x + b * v.x,\n y: Q1.y + b * v.y,\n }\n return distance(P, Pb)\n}\n\n/**\n * Calculates the dot product of two vectors.\n */\nfunction dotProduct(\n v1: { x: number; y: number },\n v2: { x: number; y: number },\n): number {\n return v1.x * v2.x + v1.y * v2.y\n}\n\n/**\n * Calculates the Euclidean distance between two points.\n */\nfunction distance(p1: Point, p2: Point): number {\n const dx = p2.x - p1.x\n const dy = p2.y - p1.y\n return Math.sqrt(dx * dx + dy * dy)\n}\n\n/**\n * Determines the orientation of triplet (p, q, r).\n * @returns 0 if collinear, 1 if clockwise, 2 if counterclockwise\n */\nfunction orientation(p: Point, q: Point, r: Point): number {\n const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)\n if (val === 0) return 0 // collinear\n return val > 0 ? 1 : 2 // clockwise or counterclockwise\n}\n\n/**\n * Checks if point q lies on segment pr.\n */\nfunction onSegment(p: Point, q: Point, r: Point): boolean {\n return (\n q.x <= Math.max(p.x, r.x) &&\n q.x >= Math.min(p.x, r.x) &&\n q.y <= Math.max(p.y, r.y) &&\n q.y >= Math.min(p.y, r.y)\n )\n}\n\n/**\n * Checks if two line segments intersect.\n */\nfunction segmentsIntersect(\n A1: Point,\n A2: Point,\n B1: Point,\n B2: Point,\n): boolean {\n // Find the four orientations needed for general case\n const o1 = orientation(A1, A2, B1)\n const o2 = orientation(A1, A2, B2)\n const o3 = orientation(B1, B2, A1)\n const o4 = orientation(B1, B2, A2)\n\n // General case\n if (o1 !== o2 && o3 !== o4) return true\n\n // Special Cases\n // A1, A2 and B1 are collinear and B1 lies on segment A1A2\n if (o1 === 0 && onSegment(A1, B1, A2)) return true\n\n // A1, A2 and B2 are collinear and B2 lies on segment A1A2\n if (o2 === 0 && onSegment(A1, B2, A2)) return true\n\n // B1, B2 and A1 are collinear and A1 lies on segment B1B2\n if (o3 === 0 && onSegment(B1, A1, B2)) return true\n\n // B1, B2 and A2 are collinear and A2 lies on segment B1B2\n if (o4 === 0 && onSegment(B1, A2, B2)) return true\n\n return false // Doesn't fall in any of the above cases\n}\n","interface Point {\n x: number\n y: number\n z: number\n}\n\ntype Segment = [Point, Point]\n\ntype SegmentWithId = [Point, Point, string]\n\nconst getSegmentBounds = (segment: Segment) => {\n return {\n minX: Math.min(segment[0].x, segment[1].x),\n maxX: Math.max(segment[0].x, segment[1].x),\n minY: Math.min(segment[0].y, segment[1].y),\n maxY: Math.max(segment[0].y, segment[1].y),\n }\n}\nexport type BucketCoordinate = `${number}x${number}`\n\nexport class SegmentTree {\n buckets: Map<BucketCoordinate, SegmentWithId[]>\n CELL_SIZE = 0.4\n SEGMENT_MARGIN = 0.4 // traceThickness + obstacleMargin\n\n constructor(public segments: Segment[]) {\n this.buckets = new Map()\n const segmentsById = new Map<string, Segment>() // Avoid adding duplicates if input has them\n\n for (const segment of segments) {\n const segmentKey = this.getSegmentKey(segment)\n if (segmentsById.has(segmentKey)) continue // Skip duplicates in input\n segmentsById.set(segmentKey, segment)\n\n const bounds = getSegmentBounds(segment)\n\n // Calculate min/max integer indices covered by the segment's bounds\n const minIndexX = Math.floor(bounds.minX / this.CELL_SIZE)\n const maxIndexX = Math.floor(bounds.maxX / this.CELL_SIZE)\n const minIndexY = Math.floor(bounds.minY / this.CELL_SIZE)\n const maxIndexY = Math.floor(bounds.maxY / this.CELL_SIZE)\n\n // Iterate through the integer indices\n for (let ix = minIndexX; ix <= maxIndexX; ix++) {\n for (let iy = minIndexY; iy <= maxIndexY; iy++) {\n const bucketKey = `${ix}x${iy}` as BucketCoordinate // Construct key from indices\n const bucket = this.buckets.get(bucketKey)\n const segmentWithId: SegmentWithId = [\n segment[0],\n segment[1],\n segmentKey,\n ]\n\n if (!bucket) {\n this.buckets.set(bucketKey, [segmentWithId])\n } else {\n // Optional: Check if segment already in this specific bucket if constructor might be called multiple times\n // or if input segments could be complex overlaps. Usually not needed if input is processed once.\n bucket.push(segmentWithId)\n }\n }\n }\n }\n }\n\n getBucketKey(x: number, y: number): BucketCoordinate {\n return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`\n }\n\n getSegmentKey(segment: Segment): string {\n return `${segment[0].x}-${segment[0].y}-${segment[0].z}-${segment[1].x}-${segment[1].y}-${segment[1].z}`\n }\n\n getSegmentsThatCouldIntersect(A: Point, B: Point): SegmentWithId[] {\n const segments: SegmentWithId[] = []\n const alreadyAddedSegments = new Set<string>()\n\n // Calculate the margined bounding box of the query segment\n const minX = Math.min(A.x, B.x) - this.SEGMENT_MARGIN\n const minY = Math.min(A.y, B.y) - this.SEGMENT_MARGIN\n const maxX = Math.max(A.x, B.x) + this.SEGMENT_MARGIN\n const maxY = Math.max(A.y, B.y) + this.SEGMENT_MARGIN\n\n // Calculate min/max integer indices covered by the margined query bounds\n const minIndexX = Math.floor(minX / this.CELL_SIZE)\n const maxIndexX = Math.floor(maxX / this.CELL_SIZE)\n const minIndexY = Math.floor(minY / this.CELL_SIZE)\n const maxIndexY = Math.floor(maxY / this.CELL_SIZE)\n\n // Iterate through the integer indices\n for (let ix = minIndexX; ix <= maxIndexX; ix++) {\n for (let iy = minIndexY; iy <= maxIndexY; iy++) {\n const bucketKey = `${ix}x${iy}` as BucketCoordinate // Construct key from indices\n const bucket = this.buckets.get(bucketKey)\n\n if (bucket) {\n // Check if bucket exists\n for (const segment of bucket) {\n const key = segment[2] // The segment key is stored at index 2\n if (!alreadyAddedSegments.has(key)) {\n alreadyAddedSegments.add(key)\n segments.push(segment)\n }\n }\n }\n }\n }\n return segments\n }\n}\n","import {\n doSegmentsIntersect,\n pointToSegmentDistance,\n} from \"@tscircuit/math-utils\"\nimport { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { Obstacle } from \"lib/types\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { SingleSimplifiedPathSolver } from \"./SingleSimplifiedPathSolver\"\nimport { calculate45DegreePaths } from \"lib/utils/calculate45DegreePaths\"\nimport { minimumDistanceBetweenSegments } from \"lib/utils/minimumDistanceBetweenSegments\"\nimport { SegmentTree } from \"lib/data-structures/SegmentTree\"\nimport {\n segmentToBoxMinDistance,\n computeDistanceBetweenBoxes,\n segmentToBoundsMinDistance,\n} from \"@tscircuit/math-utils\"\n\ninterface Point {\n x: number\n y: number\n z: number\n}\n\ninterface PathSegment {\n start: Point\n end: Point\n length: number\n startDistance: number\n endDistance: number\n}\n\nexport class SingleSimplifiedPathSolver5 extends SingleSimplifiedPathSolver {\n private pathSegments: PathSegment[] = []\n private totalPathLength: number = 0\n private headDistanceAlongPath: number = 0\n private tailDistanceAlongPath: number = 0\n private minStepSize: number = 0.25 // Default step size, can be adjusted\n private lastValidPath: Point[] | null = null // Store the current valid path\n private lastValidPathHeadDistance: number = 0\n\n /** Amount the step size is reduced when the step isn't possible */\n STEP_SIZE_REDUCTION_FACTOR = 0.25\n maxStepSize = 4\n currentStepSize = this.maxStepSize\n lastHeadMoveDistance = 0\n\n cachedValidPathSegments: Set<string>\n\n filteredObstacles: Obstacle[] = []\n filteredObstaclePathSegments: Array<[Point, Point]> = []\n filteredVias: Array<{ x: number; y: number; diameter: number }> = []\n\n segmentTree!: SegmentTree\n\n OBSTACLE_MARGIN = 0.1\n TRACE_THICKNESS = 0.15\n\n TAIL_JUMP_RATIO: number = 0.8\n\n constructor(\n params: ConstructorParameters<typeof SingleSimplifiedPathSolver>[0],\n ) {\n super(params)\n\n this.cachedValidPathSegments = new Set()\n\n // Handle empty or single-point routes\n if (this.inputRoute.route.length <= 1) {\n this.newRoute = [...this.inputRoute.route]\n this.solved = true\n return\n }\n\n const bounds = this.inputRoute.route.reduce(\n (acc, point) => {\n acc.minX = Math.min(acc.minX, point.x)\n acc.maxX = Math.max(acc.maxX, point.x)\n acc.minY = Math.min(acc.minY, point.y)\n acc.maxY = Math.max(acc.maxY, point.y)\n return acc\n },\n { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity },\n )\n const boundsBox = {\n center: {\n x: (bounds.minX + bounds.maxX) / 2,\n y: (bounds.minY + bounds.maxY) / 2,\n },\n width: bounds.maxX - bounds.minX,\n height: bounds.maxY - bounds.minY,\n }\n\n this.filteredObstacles = this.obstacles\n .filter(\n (obstacle) =>\n !obstacle.connectedTo.some((id) =>\n this.connMap.areIdsConnected(this.inputRoute.connectionName, id),\n ),\n )\n .filter((obstacle) => {\n if (\n obstacle.connectedTo.some((obsId) =>\n this.connMap.areIdsConnected(this.inputRoute.connectionName, obsId),\n )\n ) {\n return false\n }\n\n const { distance } = computeDistanceBetweenBoxes(boundsBox, obstacle)\n\n if (distance < this.OBSTACLE_MARGIN + 0.5) {\n return true\n }\n\n return false\n })\n\n this.filteredObstaclePathSegments = this.otherHdRoutes.flatMap(\n (hdRoute) => {\n if (\n this.connMap.areIdsConnected(\n this.inputRoute.connectionName,\n hdRoute.connectionName,\n )\n ) {\n return []\n }\n\n const route = hdRoute.route\n const segments: Array<[Point, Point]> = []\n for (let i = 0; i < route.length - 1; i++) {\n const start = route[i]\n const end = route[i + 1]\n\n const minX = Math.min(start.x, end.x)\n const maxX = Math.max(start.x, end.x)\n const minY = Math.min(start.y, end.y)\n const maxY = Math.max(start.y, end.y)\n\n if (\n minX <= bounds.maxX &&\n maxX >= bounds.minX &&\n minY <= bounds.maxY &&\n maxY >= bounds.minY\n ) {\n segments.push([start, end])\n }\n }\n\n return segments\n },\n )\n this.segmentTree = new SegmentTree(this.filteredObstaclePathSegments)\n\n this.filteredVias = this.otherHdRoutes.flatMap((hdRoute) => {\n if (\n this.connMap.areIdsConnected(\n this.inputRoute.connectionName,\n hdRoute.connectionName,\n )\n ) {\n return []\n }\n\n const vias = hdRoute.vias\n const filteredVias: Array<{ x: number; y: number; diameter: number }> = []\n for (const via of vias) {\n const margin =\n this.OBSTACLE_MARGIN +\n this.TRACE_THICKNESS / 2 +\n hdRoute.viaDiameter / 2\n const minX = via.x - margin\n const maxX = via.x + margin\n const minY = via.y - margin\n const maxY = via.y + margin\n\n if (\n minX <= bounds.maxX &&\n maxX >= bounds.minX &&\n minY <= bounds.maxY &&\n maxY >= bounds.minY\n ) {\n filteredVias.push({ ...via, diameter: hdRoute.viaDiameter })\n }\n }\n return filteredVias\n })\n\n // Compute path segments and total length\n this.computePathSegments()\n }\n\n // Compute the path segments and their distances\n private computePathSegments() {\n let cumulativeDistance = 0\n\n for (let i = 0; i < this.inputRoute.route.length - 1; i++) {\n const start = this.inputRoute.route[i]\n const end = this.inputRoute.route[i + 1]\n\n // Calculate segment length using Euclidean distance\n const length =\n Math.sqrt((end.x - start.x) ** 2 + (end.y - start.y) ** 2) + i / 10000\n\n this.pathSegments.push({\n start,\n end,\n length,\n startDistance: cumulativeDistance,\n endDistance: cumulativeDistance + length,\n })\n\n cumulativeDistance += length\n }\n\n this.totalPathLength = cumulativeDistance\n }\n\n // Helper to check if two points are the same\n private arePointsEqual(p1: Point, p2: Point): boolean {\n return p1.x === p2.x && p1.y === p2.y && p1.z === p2.z\n }\n\n // Get point at a specific distance along the path\n private getPointAtDistance(distance: number): Point {\n // Ensure distance is within bounds\n distance = Math.max(0, Math.min(distance, this.totalPathLength))\n\n // Find the segment that contains this distance\n const segment = this.pathSegments.find(\n (seg) => distance >= seg.startDistance && distance <= seg.endDistance,\n )\n\n if (!segment) {\n // Fallback to last point if segment not found\n return this.inputRoute.route[this.inputRoute.route.length - 1]\n }\n\n // Calculate interpolation factor (between 0 and 1)\n const factor = (distance - segment.startDistance) / segment.length\n\n // Interpolate the point\n return {\n x: segment.start.x + factor * (segment.end.x - segment.start.x),\n y: segment.start.y + factor * (segment.end.y - segment.start.y),\n z: factor < 0.5 ? segment.start.z : segment.end.z, // Z doesn't interpolate - use the segment's start z value\n }\n }\n\n // Find nearest index in the original route for a given distance\n private getNearestIndexForDistance(distance: number): number {\n if (distance <= 0) return 0\n if (distance >= this.totalPathLength)\n return this.inputRoute.route.length - 1\n\n // Find the segment that contains this distance\n const segmentIndex = this.pathSegments.findIndex(\n (seg) => distance >= seg.startDistance && distance <= seg.endDistance,\n )\n\n if (segmentIndex === -1) return 0\n\n // If closer to the end of the segment, return the next index\n const segment = this.pathSegments[segmentIndex]\n const midDistance = (segment.startDistance + segment.endDistance) / 2\n\n return distance > midDistance ? segmentIndex + 1 : segmentIndex\n }\n\n // Check if a path segment is valid\n isValidPathSegment(start: Point, end: Point): boolean {\n // Check if the segment intersects with any obstacle\n for (const obstacle of this.filteredObstacles) {\n if (!obstacle.zLayers?.includes(start.z)) {\n continue\n }\n\n const distToObstacle = segmentToBoxMinDistance(start, end, obstacle)\n\n // Check if the line might intersect with this obstacle's borders\n if (distToObstacle < this.OBSTACLE_MARGIN + this.TRACE_THICKNESS / 2) {\n return false\n }\n }\n\n // Check if the segment intersects with any other route\n const segmentsThatCouldIntersect =\n this.segmentTree.getSegmentsThatCouldIntersect(start, end)\n for (const [otherSegA, otherSegB, segId] of segmentsThatCouldIntersect) {\n // Only check intersection if we're on the same layer\n if (otherSegA.z === start.z && otherSegB.z === start.z) {\n const distBetweenSegments = minimumDistanceBetweenSegments(\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n { x: otherSegA.x, y: otherSegA.y },\n { x: otherSegB.x, y: otherSegB.y },\n )\n if (distBetweenSegments < this.OBSTACLE_MARGIN + this.TRACE_THICKNESS) {\n return false\n }\n }\n }\n\n for (const via of this.filteredVias) {\n if (\n pointToSegmentDistance(via, start, end) <\n this.OBSTACLE_MARGIN + via.diameter / 2 + this.TRACE_THICKNESS / 2\n ) {\n return false\n }\n }\n\n return true\n }\n\n // Check if a path with multiple points is valid\n isValidPath(pointsInRoute: Point[]): boolean {\n if (pointsInRoute.length < 2) return true\n\n // Check for layer changes - we don't allow simplifying across layer changes\n for (let i = 0; i < pointsInRoute.length - 1; i++) {\n if (pointsInRoute[i].z !== pointsInRoute[i + 1].z) {\n return false\n }\n }\n\n // Check each segment of the path\n for (let i = 0; i < pointsInRoute.length - 1; i++) {\n if (!this.isValidPathSegment(pointsInRoute[i], pointsInRoute[i + 1])) {\n return false\n }\n }\n\n return true\n }\n\n // Find a valid 45-degree path between two points\n private find45DegreePath(start: Point, end: Point): Point[] | null {\n // Skip if points are the same\n if (this.arePointsEqual(start, end)) {\n return [start]\n }\n\n // Skip 45-degree check if we're on different layers\n if (start.z !== end.z) {\n return null\n }\n\n // Calculate potential 45-degree paths\n const possiblePaths = calculate45DegreePaths(\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n )\n\n // Check each path for validity\n for (const path of possiblePaths) {\n // Convert the 2D points to 3D points with the correct z value\n const fullPath = path.map((p) => ({ x: p.x, y: p.y, z: start.z }))\n\n // Check if this path is valid\n if (this.isValidPath(fullPath)) {\n return fullPath\n }\n }\n\n // No valid 45-degree path found\n return null\n }\n\n // Add a path to the result, skipping the first point if it's already added\n private addPathToResult(path: Point[]) {\n if (path.length === 0) return\n\n for (let i = 0; i < path.length; i++) {\n // Skip the first point if it's already added\n if (\n i === 0 &&\n this.newRoute.length > 0 &&\n this.arePointsEqual(this.newRoute[this.newRoute.length - 1], path[i])\n ) {\n continue\n }\n this.newRoute.push(path[i])\n }\n this.currentStepSize = this.maxStepSize\n }\n\n moveHead(distance: number) {\n this.lastHeadMoveDistance = distance\n this.headDistanceAlongPath = Math.min(\n this.headDistanceAlongPath + distance,\n this.totalPathLength,\n )\n }\n\n stepBackAndReduceStepSize() {\n this.headDistanceAlongPath = Math.max(\n this.tailDistanceAlongPath,\n this.headDistanceAlongPath - this.lastHeadMoveDistance,\n )\n this.currentStepSize = Math.max(\n this.minStepSize,\n this.currentStepSize * this.STEP_SIZE_REDUCTION_FACTOR,\n )\n }\n\n _step() {\n const tailHasReachedEnd = this.tailDistanceAlongPath >= this.totalPathLength\n const headHasReachedEnd = this.headDistanceAlongPath >= this.totalPathLength\n\n if (tailHasReachedEnd) {\n // Make sure to add the last point if needed\n const lastPoint = this.inputRoute.route[this.inputRoute.route.length - 1]\n if (\n this.newRoute.length === 0 ||\n !this.arePointsEqual(this.newRoute[this.newRoute.length - 1], lastPoint)\n ) {\n // TODO find path from tail to end w/ 45 degree paths\n this.newRoute.push(lastPoint)\n }\n this.solved = true\n return\n }\n\n if (headHasReachedEnd) {\n const tailPoint = this.getPointAtDistance(this.tailDistanceAlongPath)\n const endPoint = this.inputRoute.route[this.inputRoute.route.length - 1]\n\n // Try to find a valid 45-degree path\n const path45 = this.find45DegreePath(tailPoint, endPoint)\n\n if (path45) {\n // Add the path to the result\n this.addPathToResult(path45)\n this.solved = true\n return\n } else {\n // No valid 45-degree path to the end,\n // add the current path if any and continue with normal advance\n if (this.lastValidPath) {\n this.addPathToResult(this.lastValidPath)\n this.lastValidPath = null\n this.tailDistanceAlongPath = this.lastValidPathHeadDistance\n } else {\n this.newRoute.push(endPoint)\n this.solved = true\n }\n }\n }\n\n // Increment head distance but don't go past the end of the path\n this.moveHead(this.currentStepSize)\n\n // Get the points between tail and head distances\n const tailPoint = this.getPointAtDistance(this.tailDistanceAlongPath)\n const headPoint = this.getPointAtDistance(this.headDistanceAlongPath)\n\n // Check for layer changes between tail and head\n const tailIndex = this.getNearestIndexForDistance(\n this.tailDistanceAlongPath,\n )\n const headIndex = this.getNearestIndexForDistance(\n this.headDistanceAlongPath,\n )\n\n // If there's a potential layer change in this segment\n let layerChangeBtwHeadAndTail = false\n let layerChangeAtDistance = -1\n\n for (let i = tailIndex; i < headIndex; i++) {\n if (\n i + 1 < this.inputRoute.route.length &&\n this.inputRoute.route[i].z !== this.inputRoute.route[i + 1].z\n ) {\n layerChangeBtwHeadAndTail = true\n // Find the segment with the layer change\n const changeSegmentIndex = i\n layerChangeAtDistance =\n this.pathSegments[changeSegmentIndex].startDistance\n break\n }\n }\n\n if (\n layerChangeBtwHeadAndTail &&\n this.lastHeadMoveDistance > this.minStepSize\n ) {\n this.stepBackAndReduceStepSize()\n return\n }\n\n // If there's a layer change, handle it\n // Inside the _step method, within the layer change handling block:\n if (layerChangeBtwHeadAndTail && layerChangeAtDistance > 0) {\n // Get the point *after* the layer change from the original route.\n // This point's XY coordinates define the via location.\n const indexAfterLayerChange =\n this.getNearestIndexForDistance(layerChangeAtDistance) + 1\n const pointAfterChange = this.inputRoute.route[indexAfterLayerChange]\n const viaLocation = { x: pointAfterChange.x, y: pointAfterChange.y }\n\n // 1. Add the last valid path found *before* the layer change.\n if (this.lastValidPath) {\n this.addPathToResult(this.lastValidPath)\n this.lastValidPath = null // Clear it after adding\n }\n\n // 2. Ensure the route connects *exactly* to the via location on the *previous* layer.\n const lastPointInNewRoute = this.newRoute[this.newRoute.length - 1]\n if (\n lastPointInNewRoute.x !== viaLocation.x ||\n lastPointInNewRoute.y !== viaLocation.y\n ) {\n // Add a point explicitly connecting to the via XY on the layer we are *leaving*.\n this.newRoute.push({\n x: viaLocation.x,\n y: viaLocation.y,\n z: lastPointInNewRoute.z, // Use the Z of the layer we are leaving\n })\n }\n // If the last point was already at the via location, its Z is correct, so we don't need an else.\n\n // 3. Add the via itself.\n this.newVias.push(viaLocation)\n\n // 4. Add the point *after* the layer change, starting the segment on the *new* layer.\n // Ensure this point also uses the precise via location and the *new* Z coordinate.\n this.newRoute.push({\n x: viaLocation.x,\n y: viaLocation.y,\n z: pointAfterChange.z, // Use the Z of the layer we are entering\n })\n\n // 5. Reset state for the next segment.\n this.currentStepSize = this.maxStepSize\n\n // Update tail to the start of the segment *after* the layer change point\n const segmentIndexAfterChange = this.pathSegments.findIndex(\n (seg) => seg.start === pointAfterChange,\n )\n\n if (segmentIndexAfterChange !== -1) {\n this.tailDistanceAlongPath =\n this.pathSegments[segmentIndexAfterChange].startDistance\n this.headDistanceAlongPath = this.tailDistanceAlongPath // Reset head to tail\n this.lastValidPath = null // Ensure lastValidPath is clear\n this.lastValidPathHeadDistance = this.tailDistanceAlongPath\n } else if (indexAfterLayerChange < this.inputRoute.route.length) {\n // Fallback if the exact segment wasn't found but index is valid\n // This might happen due to floating point comparisons if getPointAtDistance was used previously\n console.warn(\n \"Fallback used for tailDistanceAlongPath after layer change\",\n )\n const segment = this.pathSegments.find(\n (seg) => seg.start === this.inputRoute.route[indexAfterLayerChange],\n )\n if (segment) {\n this.tailDistanceAlongPath = segment.startDistance\n this.headDistanceAlongPath = this.tailDistanceAlongPath\n this.lastValidPath = null\n this.lastValidPathHeadDistance = this.tailDistanceAlongPath\n } else {\n console.error(\n \"Could not find segment start after layer change, path might be incomplete.\",\n )\n this.solved = true // Prevent infinite loop\n }\n } else {\n // Layer change occurred at the very last point/segment.\n console.warn(\"Layer change occurred at the end of the path.\")\n // The last point on the new layer is already added. We are done.\n this.solved = true\n }\n\n return // End the step after handling the layer change\n }\n\n // Try to find a valid 45-degree path from tail to head\n const path45 = this.find45DegreePath(tailPoint, headPoint)\n\n if (!path45 && this.lastHeadMoveDistance > this.minStepSize) {\n this.stepBackAndReduceStepSize()\n return\n }\n\n if (!path45 && !this.lastValidPath) {\n const oldTailPoint = this.getPointAtDistance(this.tailDistanceAlongPath)\n\n // Move tail and head forward by stepSize\n this.tailDistanceAlongPath += this.minStepSize\n this.moveHead(this.minStepSize)\n\n const newTailIndex = this.getNearestIndexForDistance(\n this.tailDistanceAlongPath,\n )\n const newTailPoint = this.inputRoute.route[newTailIndex]\n const lastRoutePoint =\n this.inputRoute.route[this.inputRoute.route.length - 1]\n\n // Add the segment from old tail to new tail\n if (\n !this.arePointsEqual(oldTailPoint, newTailPoint) &&\n !this.arePointsEqual(newTailPoint, lastRoutePoint)\n ) {\n this.newRoute.push(newTailPoint)\n }\n\n return\n }\n\n if (path45) {\n // Valid 45-degree path found, store it and continue expanding\n this.lastValidPath = path45\n this.lastValidPathHeadDistance = this.headDistanceAlongPath\n return\n }\n\n // No valid path found, use the last valid path and reset\n if (this.lastValidPath) {\n this.addPathToResult(this.lastValidPath)\n this.lastValidPath = null\n this.tailDistanceAlongPath = this.lastValidPathHeadDistance\n this.moveHead(this.minStepSize)\n }\n }\n\n visualize(): GraphicsObject {\n const graphics = this.getVisualsForNewRouteAndObstacles()\n\n // Highlight current head and tail positions\n const tailPoint = this.getPointAtDistance(this.tailDistanceAlongPath)\n const headPoint = this.getPointAtDistance(this.headDistanceAlongPath)\n\n graphics.points.push({\n x: tailPoint.x,\n y: tailPoint.y,\n color: \"yellow\",\n label: [\"Tail\", `z: ${tailPoint.z}`].join(\"\\n\"),\n })\n\n graphics.points.push({\n x: headPoint.x,\n y: headPoint.y,\n color: \"orange\",\n label: [\"Head\", `z: ${headPoint.z}`].join(\"\\n\"),\n })\n\n const tentativeHead = this.getPointAtDistance(\n this.headDistanceAlongPath + this.currentStepSize,\n )\n graphics.points.push({\n x: tentativeHead.x,\n y: tentativeHead.y,\n color: \"red\",\n label: [\"Tentative Head\", `z: ${tentativeHead.z}`].join(\"\\n\"),\n })\n\n // Add visualization of the path segments\n let distance = 0\n while (distance < this.totalPathLength) {\n const point = this.getPointAtDistance(distance)\n graphics.circles.push({\n center: {\n x: point.x,\n y: point.y,\n },\n radius: 0.05,\n fill: \"rgba(100, 100, 100, 0.5)\",\n })\n distance += this.totalPathLength / 20 // Show 20 markers along the path\n }\n\n // Visualize the current prospective 45-degree path from tail to head\n if (this.lastValidPath && this.lastValidPath.length > 1) {\n // Draw the path in a bright cyan color to make it stand out\n for (let i = 0; i < this.lastValidPath.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: this.lastValidPath[i].x, y: this.lastValidPath[i].y },\n {\n x: this.lastValidPath[i + 1].x,\n y: this.lastValidPath[i + 1].y,\n },\n ],\n strokeColor: \"rgba(0, 255, 255, 0.9)\", // Bright cyan\n strokeDash: \"3, 3\", // Dashed line to indicate it's a prospective path\n })\n }\n }\n\n return graphics\n }\n}\n","import { HighDensityIntraNodeRoute } from \"lib/types/high-density-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { Obstacle } from \"lib/types\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { combineVisualizations } from \"lib/utils/combineVisualizations\"\nimport { SingleSimplifiedPathSolver5 } from \"./SingleSimplifiedPathSolver5_Deg45\"\nimport { SingleSimplifiedPathSolver } from \"./SingleSimplifiedPathSolver\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\n\nexport class MultiSimplifiedPathSolver extends BaseSolver {\n simplifiedHdRoutes: HighDensityIntraNodeRoute[]\n\n currentUnsimplifiedHdRouteIndex = 0\n\n activeSubSolver: SingleSimplifiedPathSolver | null = null\n\n unsimplifiedHdRoutes: HighDensityIntraNodeRoute[]\n obstacles: Obstacle[]\n connMap: ConnectivityMap\n colorMap: Record<string, string>\n\n constructor(params: {\n unsimplifiedHdRoutes: HighDensityIntraNodeRoute[]\n obstacles: Obstacle[]\n connMap?: ConnectivityMap\n colorMap?: Record<string, string>\n }) {\n super()\n this.MAX_ITERATIONS = 100e6\n\n this.unsimplifiedHdRoutes = params.unsimplifiedHdRoutes\n this.obstacles = params.obstacles\n this.connMap = params.connMap || new ConnectivityMap({})\n this.colorMap = params.colorMap || {}\n\n this.simplifiedHdRoutes = []\n }\n\n _step() {\n const hdRoute =\n this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex]\n if (!this.activeSubSolver) {\n if (!hdRoute) {\n this.solved = true\n return\n }\n\n this.activeSubSolver = new SingleSimplifiedPathSolver5({\n inputRoute: hdRoute,\n otherHdRoutes: this.unsimplifiedHdRoutes\n .slice(this.currentUnsimplifiedHdRouteIndex + 1)\n .concat(this.simplifiedHdRoutes),\n obstacles: this.obstacles,\n connMap: this.connMap,\n colorMap: this.colorMap,\n })\n this.currentUnsimplifiedHdRouteIndex++\n return\n }\n\n this.activeSubSolver.step()\n if (this.activeSubSolver.solved) {\n this.simplifiedHdRoutes.push(this.activeSubSolver.simplifiedRoute)\n this.activeSubSolver = null\n }\n }\n\n visualize(): GraphicsObject {\n if (this.activeSubSolver) {\n return this.activeSubSolver.visualize()\n }\n\n const graphics: Required<GraphicsObject> = {\n lines: [],\n points: [],\n circles: [],\n rects: [],\n coordinateSystem: \"cartesian\",\n title: \"Multi Simplified Path Solver\",\n }\n\n // Visualize the original unsimplified routes in red with transparency\n for (const route of this.unsimplifiedHdRoutes) {\n if (\n this.simplifiedHdRoutes.some(\n (r) => r.connectionName === route.connectionName,\n )\n ) {\n continue\n }\n\n for (let i = 0; i < route.route.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: route.route[i].x, y: route.route[i].y },\n { x: route.route[i + 1].x, y: route.route[i + 1].y },\n ],\n strokeColor:\n route.route[i].z === 1\n ? \"rgba(0, 0, 255, 0.4)\"\n : \"rgba(255, 0, 0, 0.4)\",\n strokeWidth: 0.15,\n strokeDash: route.route[i].z === 1 ? [0.5, 0.5] : undefined,\n })\n }\n\n // Draw vias for unsimplified routes\n for (const via of route.vias || []) {\n graphics.circles.push({\n center: via,\n radius: route.viaDiameter / 2 || 0.3, // Default radius if viaDiameter not specified\n fill: \"rgba(0, 0, 255, 0.4)\",\n })\n }\n }\n\n // Visualize the simplified routes with colors from colorMap or gray if not found\n for (const route of this.simplifiedHdRoutes) {\n const routeColor =\n this.colorMap?.[route.connectionName] || \"rgba(128, 128, 128, 0.8)\"\n\n // Draw the route lines\n for (let i = 0; i < route.route.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: route.route[i].x, y: route.route[i].y },\n { x: route.route[i + 1].x, y: route.route[i + 1].y },\n ],\n strokeWidth: 0.15,\n strokeColor: routeColor,\n strokeDash: route.route[i].z === 1 ? [0.5, 0.5] : undefined,\n step: 1,\n })\n }\n\n // Visualize vias\n for (const via of route.vias || []) {\n graphics.circles.push({\n center: via,\n radius: route.viaDiameter / 2,\n fill: \"rgba(0, 0, 255, 0.5)\",\n step: 1,\n })\n }\n }\n\n // Visualize the original unsimplified routes in red\n for (const route of this.unsimplifiedHdRoutes) {\n // Draw the route lines\n for (let i = 0; i < route.route.length - 1; i++) {\n graphics.lines.push({\n points: [\n { x: route.route[i].x, y: route.route[i].y },\n { x: route.route[i + 1].x, y: route.route[i + 1].y },\n ],\n strokeWidth: 0.15,\n strokeColor: \"rgba(255, 0, 0, 0.2)\",\n strokeDash: [0.5, 0.5],\n step: 0,\n layer: `z${route.route[i].z.toString()}`,\n })\n }\n\n // Add small circles at each point of the original route\n for (const point of route.vias) {\n graphics.circles.push({\n center: { x: point.x, y: point.y },\n radius: route.viaDiameter / 2,\n fill: \"rgba(255, 0, 0, 0.2)\",\n step: 0,\n })\n }\n }\n\n // Visualize obstacles\n for (const obstacle of this.obstacles) {\n graphics.rects.push({\n center: obstacle.center,\n width: obstacle.width,\n height: obstacle.height,\n fill: obstacle.layers?.includes(\"top\")\n ? \"rgba(255, 0, 0, 0.3)\"\n : obstacle.layers?.includes(\"bottom\")\n ? \"rgba(0, 0, 255, 0.3)\"\n : \"rgba(128, 128, 128, 0.3)\",\n })\n }\n\n // Highlight the current route being processed\n if (\n this.currentUnsimplifiedHdRouteIndex < this.unsimplifiedHdRoutes.length\n ) {\n const currentRoute =\n this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex]\n\n // Add a label to the first point of the current route\n if (currentRoute.route.length > 0) {\n graphics.circles.push({\n center: {\n x: currentRoute.route[0].x,\n y: currentRoute.route[0].y,\n },\n radius: 0.2,\n fill: \"yellow\",\n label: \"Current\",\n })\n }\n }\n\n return graphics\n }\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n} from \"../../types/capacity-mesh-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { distance } from \"@tscircuit/math-utils\"\nimport { areNodesBordering } from \"lib/utils/areNodesBordering\"\n\nexport class CapacityMeshEdgeSolver extends BaseSolver {\n public edges: Array<CapacityMeshEdge>\n\n constructor(public nodes: CapacityMeshNode[]) {\n super()\n this.edges = []\n }\n\n getNextCapacityMeshEdgeId() {\n return `ce${this.edges.length}`\n }\n\n step() {\n this.edges = []\n for (let i = 0; i < this.nodes.length; i++) {\n for (let j = i + 1; j < this.nodes.length; j++) {\n const strawNodesWithSameParent =\n this.nodes[i]._strawNode &&\n this.nodes[j]._strawNode &&\n this.nodes[i]._strawParentCapacityMeshNodeId ===\n this.nodes[j]._strawParentCapacityMeshNodeId\n if (\n !strawNodesWithSameParent &&\n areNodesBordering(this.nodes[i], this.nodes[j]) &&\n this.doNodesHaveSharedLayer(this.nodes[i], this.nodes[j])\n ) {\n this.edges.push({\n capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),\n nodeIds: [\n this.nodes[i].capacityMeshNodeId,\n this.nodes[j].capacityMeshNodeId,\n ],\n })\n }\n }\n }\n\n this.handleTargetNodes()\n\n this.solved = true\n }\n\n handleTargetNodes() {\n // If a target node is not connected to any other node, then it is \"inside\n // an obstacle\" (this is the case almost 100% of the time when we place\n // targets inside of PCB pads)\n // To fix this we connect it to the nearest nodes without obstacles\n const targetNodes = this.nodes.filter((node) => node._containsTarget)\n for (const targetNode of targetNodes) {\n const hasEdge = this.edges.some((edge) =>\n edge.nodeIds.includes(targetNode.capacityMeshNodeId),\n )\n if (hasEdge) continue\n\n let nearestNode: CapacityMeshNode | null = null\n let nearestDistance = Infinity\n for (const node of this.nodes) {\n if (node._containsObstacle) continue\n if (node._containsTarget) continue\n const dist = distance(targetNode.center, node.center)\n if (dist < nearestDistance) {\n nearestDistance = dist\n nearestNode = node\n }\n }\n if (nearestNode) {\n this.edges.push({\n capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),\n nodeIds: [\n targetNode.capacityMeshNodeId,\n nearestNode.capacityMeshNodeId,\n ],\n })\n }\n }\n }\n\n doNodesHaveSharedLayer(\n node1: CapacityMeshNode,\n node2: CapacityMeshNode,\n ): boolean {\n return node1.availableZ.some((z) => node2.availableZ.includes(z))\n }\n\n visualize(): GraphicsObject {\n const graphics: GraphicsObject = {\n lines: [],\n points: [],\n rects: this.nodes.map((node) => {\n const lowestZ = Math.min(...node.availableZ)\n return {\n width: Math.max(node.width - 2, node.width * 0.8),\n height: Math.max(node.height - 2, node.height * 0.8),\n center: {\n x: node.center.x + lowestZ * node.width * 0.05,\n y: node.center.y - lowestZ * node.width * 0.05,\n },\n fill: node._containsObstacle\n ? \"rgba(255,0,0,0.1)\"\n : ({\n \"0,1\": \"rgba(0,0,0,0.1)\",\n \"0\": \"rgba(0,200,200, 0.1)\",\n \"1\": \"rgba(0,0,200, 0.1)\",\n }[node.availableZ.join(\",\")] ?? \"rgba(0,200,200,0.1)\"),\n label: [\n node.capacityMeshNodeId,\n `availableZ: ${node.availableZ.join(\",\")}`,\n `target? ${node._containsTarget ?? false}`,\n `obs? ${node._containsObstacle ?? false}`,\n ].join(\"\\n\"),\n }\n }),\n circles: [],\n }\n for (const edge of this.edges) {\n const node1 = this.nodes.find(\n (node) => node.capacityMeshNodeId === edge.nodeIds[0],\n )\n const node2 = this.nodes.find(\n (node) => node.capacityMeshNodeId === edge.nodeIds[1],\n )\n if (node1?.center && node2?.center) {\n const lowestZ1 = Math.min(...node1.availableZ)\n const lowestZ2 = Math.min(...node2.availableZ)\n const nodeCenter1Adj = {\n x: node1.center.x + lowestZ1 * node1.width * 0.05,\n y: node1.center.y - lowestZ1 * node1.width * 0.05,\n }\n const nodeCenter2Adj = {\n x: node2.center.x + lowestZ2 * node2.width * 0.05,\n y: node2.center.y - lowestZ2 * node2.width * 0.05,\n }\n graphics.lines!.push({\n points: [nodeCenter1Adj, nodeCenter2Adj],\n strokeDash:\n node1.availableZ.join(\",\") === node2.availableZ.join(\",\")\n ? undefined\n : \"10 5\",\n })\n }\n }\n return graphics\n }\n}\n","import type { GraphicsObject } from \"graphics-debug\"\nimport type {\n CapacityMeshEdge,\n CapacityMeshNode,\n} from \"../../types/capacity-mesh-types\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { distance } from \"@tscircuit/math-utils\"\nimport { areNodesBordering } from \"lib/utils/areNodesBordering\"\nimport { CapacityMeshEdgeSolver } from \"./CapacityMeshEdgeSolver\"\nimport { CapacityNodeTree } from \"lib/data-structures/CapacityNodeTree\"\n\nexport class CapacityMeshEdgeSolver2_NodeTreeOptimization extends CapacityMeshEdgeSolver {\n step() {\n this.edges = []\n const edgeSet = new Set<string>()\n\n const nodeTree = new CapacityNodeTree(this.nodes)\n\n for (let i = 0; i < this.nodes.length; i++) {\n const A = this.nodes[i]\n const maybeAdjNodes = nodeTree.getNodesInArea(\n A.center.x,\n A.center.y,\n A.width * 2,\n A.height * 2,\n )\n\n for (const B of maybeAdjNodes) {\n const areBordering = areNodesBordering(A, B)\n if (!areBordering) continue\n const strawNodesWithSameParent =\n A._strawNode &&\n B._strawNode &&\n A._strawParentCapacityMeshNodeId === B._strawParentCapacityMeshNodeId\n if (\n !strawNodesWithSameParent &&\n this.doNodesHaveSharedLayer(A, B) &&\n !edgeSet.has(`${A.capacityMeshNodeId}-${B.capacityMeshNodeId}`)\n ) {\n edgeSet.add(`${A.capacityMeshNodeId}-${B.capacityMeshNodeId}`)\n edgeSet.add(`${B.capacityMeshNodeId}-${A.capacityMeshNodeId}`)\n this.edges.push({\n capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),\n nodeIds: [A.capacityMeshNodeId, B.capacityMeshNodeId],\n })\n }\n }\n }\n\n this.handleTargetNodes()\n\n this.solved = true\n }\n}\n","import { doSegmentsIntersect } from \"@tscircuit/math-utils\" // Assuming this is available and correct\n\n// --- Interfaces and Types (Unchanged) ---\n\ninterface Point {\n x: number\n y: number\n z: number // Kept for type compatibility, but calculations focus on X/Y\n}\n\ntype Point2D = { x: number; y: number } // Use Point2D for clarity in calculations\n\ntype Segment = [Point, Point]\n\nexport type HighDensityIntraNodeRoute = {\n connectionName: string // Assuming this is unique per route\n traceThickness: number\n viaDiameter: number // Now used in conflict calculation\n route: Array<{ x: number; y: number; z: number }>\n vias: Array<{ x: number; y: number }> // Will be indexed\n}\nexport type HighDensityRoute = HighDensityIntraNodeRoute\n\n// --- Utility Functions (Unchanged) ---\n\nconst getSegmentBounds = (segment: Segment) => {\n return {\n minX: Math.min(segment[0].x, segment[1].x),\n maxX: Math.max(segment[0].x, segment[1].x),\n minY: Math.min(segment[0].y, segment[1].y),\n maxY: Math.max(segment[0].y, segment[1].y),\n }\n}\n\nexport type BucketCoordinate = `${number}x${number}`\n\n// --- Geometry Helper Functions (Unchanged, but ensure Point2D compatibility) ---\n\nfunction computeDistSq(p1: Point2D, p2: Point2D): number {\n const dx = p1.x - p2.x\n const dy = p1.y - p2.y\n return dx * dx + dy * dy\n}\n\nfunction pointToSegmentDistanceSq(p: Point2D, a: Point2D, b: Point2D): number {\n const l2 = computeDistSq(a, b)\n if (l2 === 0) return computeDistSq(p, a) // Segment is a point\n let t = ((p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y)) / l2\n t = Math.max(0, Math.min(1, t))\n const projection = {\n x: a.x + t * (b.x - a.x),\n y: a.y + t * (b.y - a.y),\n }\n return computeDistSq(p, projection)\n}\n\nfunction segmentToSegmentDistanceSq(\n a: Point, // Keep Point for compatibility if doSegmentsIntersect needs z\n b: Point,\n c: Point,\n d: Point,\n): number {\n // Use the provided (or assumed imported) intersection function\n if (doSegmentsIntersect(a, b, c, d)) {\n return 0\n }\n // Convert to Point2D for distance calculations\n const pA = { x: a.x, y: a.y }\n const pB = { x: b.x, y: b.y }\n const pC = { x: c.x, y: c.y }\n const pD = { x: d.x, y: d.y }\n\n return Math.min(\n pointToSegmentDistanceSq(pA, pC, pD),\n pointToSegmentDistanceSq(pB, pC, pD),\n pointToSegmentDistanceSq(pC, pA, pB),\n pointToSegmentDistanceSq(pD, pA, pB),\n )\n}\n\n// --- New Interfaces for Bucket Contents ---\ninterface StoredSegment {\n segmentId: string\n segment: [Point, Point] // Keep original Point type if needed by other parts\n parentRoute: HighDensityRoute\n}\n\ninterface StoredVia {\n viaId: string // Unique identifier for the via within its route\n x: number\n y: number\n parentRoute: HighDensityRoute\n}\n\n// --- Updated Spatial Index Class ---\n\nexport class HighDensityRouteSpatialIndex {\n private segmentBuckets: Map<BucketCoordinate, StoredSegment[]>\n private viaBuckets: Map<BucketCoordinate, StoredVia[]> // New: Store vias\n private routes: Map<string, HighDensityRoute>\n private CELL_SIZE: number\n\n constructor(routes: HighDensityRoute[], cellSize: number = 1.0) {\n // console.time(\"HighDensityRouteSpatialIndex Constructor\");\n this.segmentBuckets = new Map()\n this.viaBuckets = new Map() // Initialize via buckets\n this.routes = new Map()\n this.CELL_SIZE = cellSize\n const epsilon = 1e-9 // For segment boundary checks\n\n for (const route of routes) {\n if (!route || !route.connectionName) {\n console.warn(\"Skipping route with missing data:\", route)\n continue\n }\n if (this.routes.has(route.connectionName)) {\n console.warn(\n `Skipping duplicate route connectionName: ${route.connectionName}`,\n )\n continue\n }\n this.routes.set(route.connectionName, route)\n\n // --- Index Segments ---\n if (route.route && route.route.length >= 2) {\n for (let i = 0; i < route.route.length - 1; i++) {\n const p1 = route.route[i]\n const p2 = route.route[i + 1]\n // Skip zero-length segments\n if (p1.x === p2.x && p1.y === p2.y) continue\n\n const segment: Segment = [p1, p2]\n const bounds = getSegmentBounds(segment)\n\n const segmentInfo: StoredSegment = {\n segmentId: `${route.connectionName}-seg-${i}`,\n segment: segment,\n parentRoute: route,\n }\n\n const minIndexX = Math.floor(bounds.minX / this.CELL_SIZE)\n const maxIndexX = Math.floor((bounds.maxX + epsilon) / this.CELL_SIZE)\n const minIndexY = Math.floor(bounds.minY / this.CELL_SIZE)\n const maxIndexY = Math.floor((bounds.maxY + epsilon) / this.CELL_SIZE)\n\n for (let ix = minIndexX; ix <= maxIndexX; ix++) {\n for (let iy = minIndexY; iy <= maxIndexY; iy++) {\n const bucketKey = `${ix}x${iy}` as BucketCoordinate\n let bucketList = this.segmentBuckets.get(bucketKey)\n if (!bucketList) {\n bucketList = []\n this.segmentBuckets.set(bucketKey, bucketList)\n }\n bucketList.push(segmentInfo)\n }\n }\n }\n }\n\n // --- Index Vias ---\n if (route.vias && route.vias.length > 0) {\n for (let i = 0; i < route.vias.length; i++) {\n const via = route.vias[i]\n if (via === undefined || via === null) continue // Basic check\n\n const storedVia: StoredVia = {\n viaId: `${route.connectionName}-via-${i}`,\n x: via.x,\n y: via.y,\n parentRoute: route,\n }\n\n // Vias belong to a single bucket\n const ix = Math.floor(via.x / this.CELL_SIZE)\n const iy = Math.floor(via.y / this.CELL_SIZE)\n const bucketKey = `${ix}x${iy}` as BucketCoordinate\n\n let bucketList = this.viaBuckets.get(bucketKey)\n if (!bucketList) {\n bucketList = []\n this.viaBuckets.set(bucketKey, bucketList)\n }\n bucketList.push(storedVia)\n }\n }\n }\n // console.timeEnd(\"HighDensityRouteSpatialIndex Constructor\");\n }\n\n /**\n * Finds routes that potentially conflict with a given line segment within a margin.\n * Checks both segments and vias.\n * @param segmentStart Start point of the query segment.\n * @param segmentEnd End point of the query segment.\n * @param margin The minimum required clearance distance from the query segment's centerline.\n * @returns An array of conflicting routes and their minimum distance to the segment.\n */\n getConflictingRoutesForSegment(\n segmentStart: Point, // Keep Point for original Z data if needed elsewhere\n segmentEnd: Point,\n margin: number, // Minimum required clearance\n ): Array<{ conflictingRoute: HighDensityRoute; distance: number }> {\n const querySegment: Segment = [segmentStart, segmentEnd]\n const bounds = getSegmentBounds(querySegment)\n\n // --- Define search area including margin for both segments and vias ---\n // Need to consider the maximum possible radius (trace/2 or via/2) + margin\n // For simplicity, just use the provided margin for bucket search.\n // Precise checks will use item-specific sizes.\n const searchMinX = bounds.minX - margin\n const searchMinY = bounds.minY - margin\n const searchMaxX = bounds.maxX + margin\n const searchMaxY = bounds.maxY + margin\n const epsilon = 1e-9\n\n const minIndexX = Math.floor(searchMinX / this.CELL_SIZE)\n const maxIndexX = Math.floor((searchMaxX + epsilon) / this.CELL_SIZE)\n const minIndexY = Math.floor(searchMinY / this.CELL_SIZE)\n const maxIndexY = Math.floor((searchMaxY + epsilon) / this.CELL_SIZE)\n\n // Use a map to store the minimum squared distance found *per route*\n const conflictingRouteData = new Map<\n string,\n { route: HighDensityRoute; minDistSq: number }\n >()\n const checkedSegments = new Set<string>() // Store segmentId\n const checkedVias = new Set<string>() // Store viaId\n\n const queryP1: Point2D = { x: segmentStart.x, y: segmentStart.y }\n const queryP2: Point2D = { x: segmentEnd.x, y: segmentEnd.y }\n\n for (let ix = minIndexX; ix <= maxIndexX; ix++) {\n for (let iy = minIndexY; iy <= maxIndexY; iy++) {\n const bucketKey = `${ix}x${iy}` as BucketCoordinate\n\n // --- Check Segments in Bucket ---\n const segmentBucketList = this.segmentBuckets.get(bucketKey)\n if (segmentBucketList) {\n for (const segmentInfo of segmentBucketList) {\n if (checkedSegments.has(segmentInfo.segmentId)) continue\n checkedSegments.add(segmentInfo.segmentId)\n\n const route = segmentInfo.parentRoute\n const [p1, p2] = segmentInfo.segment // Original points\n\n // Required separation distance from query centerline to segment edge\n const requiredSeparation = margin + route.traceThickness / 2\n const requiredSeparationSq = requiredSeparation * requiredSeparation\n\n // Use original points for segmentToSegmentDistanceSq if it relies on the Point type\n const distSq = segmentToSegmentDistanceSq(\n segmentStart,\n segmentEnd,\n p1,\n p2,\n )\n\n if (distSq < requiredSeparationSq) {\n // Use < for strict clearance\n const routeName = route.connectionName\n const existing = conflictingRouteData.get(routeName)\n if (!existing || distSq < existing.minDistSq) {\n conflictingRouteData.set(routeName, {\n route,\n minDistSq: distSq,\n })\n }\n }\n }\n }\n\n // --- Check Vias in Bucket ---\n const viaBucketList = this.viaBuckets.get(bucketKey)\n if (viaBucketList) {\n for (const viaInfo of viaBucketList) {\n if (checkedVias.has(viaInfo.viaId)) continue\n checkedVias.add(viaInfo.viaId)\n\n const route = viaInfo.parentRoute\n const viaPoint: Point2D = { x: viaInfo.x, y: viaInfo.y }\n\n // Required separation distance from query centerline to via edge\n const requiredSeparation = margin + route.viaDiameter / 2\n const requiredSeparationSq = requiredSeparation * requiredSeparation\n\n // Calculate distance from via center to the query segment\n const distSq = pointToSegmentDistanceSq(viaPoint, queryP1, queryP2)\n\n if (distSq < requiredSeparationSq) {\n // Use < for strict clearance\n const routeName = route.connectionName\n const existing = conflictingRouteData.get(routeName)\n if (!existing || distSq < existing.minDistSq) {\n conflictingRouteData.set(routeName, {\n route,\n minDistSq: distSq,\n })\n }\n }\n }\n }\n }\n }\n\n // --- Convert map to results ---\n const results: Array<{\n conflictingRoute: HighDensityRoute\n distance: number\n }> = []\n for (const data of conflictingRouteData.values()) {\n // Distance reported is centerline-to-centerline (or point)\n results.push({\n conflictingRoute: data.route,\n distance: Math.sqrt(data.minDistSq),\n })\n }\n\n return results\n }\n\n /**\n * Finds routes that pass near a given point within a margin.\n * Checks both segments and vias.\n * @param point The query point {x, y}. Z is ignored.\n * @param margin The minimum required clearance distance from the query point.\n * @returns An array of conflicting routes and their minimum distance to the point.\n */\n getConflictingRoutesNearPoint(\n point: Point2D,\n margin: number, // Minimum required clearance\n ): Array<{ conflictingRoute: HighDensityRoute; distance: number }> {\n // --- Define search area ---\n const searchMinX = point.x - margin\n const searchMinY = point.y - margin\n const searchMaxX = point.x + margin\n const searchMaxY = point.y + margin\n const epsilon = 1e-9\n\n const minIndexX = Math.floor(searchMinX / this.CELL_SIZE)\n const maxIndexX = Math.floor((searchMaxX + epsilon) / this.CELL_SIZE) // Epsilon might not be strictly needed for point queries but harmless\n const minIndexY = Math.floor(searchMinY / this.CELL_SIZE)\n const maxIndexY = Math.floor((searchMaxY + epsilon) / this.CELL_SIZE)\n\n const conflictingRouteData = new Map<\n string,\n { route: HighDensityRoute; minDistSq: number }\n >()\n const checkedSegments = new Set<string>()\n const checkedVias = new Set<string>()\n\n for (let ix = minIndexX; ix <= maxIndexX; ix++) {\n for (let iy = minIndexY; iy <= maxIndexY; iy++) {\n const bucketKey = `${ix}x${iy}` as BucketCoordinate\n\n // --- Check Segments ---\n const segmentBucketList = this.segmentBuckets.get(bucketKey)\n if (segmentBucketList) {\n for (const segmentInfo of segmentBucketList) {\n if (checkedSegments.has(segmentInfo.segmentId)) continue\n checkedSegments.add(segmentInfo.segmentId)\n\n const route = segmentInfo.parentRoute\n // Convert segment points to Point2D for distance calculation\n const p1: Point2D = {\n x: segmentInfo.segment[0].x,\n y: segmentInfo.segment[0].y,\n }\n const p2: Point2D = {\n x: segmentInfo.segment[1].x,\n y: segmentInfo.segment[1].y,\n }\n\n const requiredSeparation = margin + route.traceThickness / 2\n const requiredSeparationSq = requiredSeparation * requiredSeparation\n\n const distSq = pointToSegmentDistanceSq(point, p1, p2)\n\n if (distSq < requiredSeparationSq) {\n // Use < for strict clearance\n const routeName = route.connectionName\n const existing = conflictingRouteData.get(routeName)\n if (!existing || distSq < existing.minDistSq) {\n conflictingRouteData.set(routeName, {\n route,\n minDistSq: distSq,\n })\n }\n }\n }\n }\n\n // --- Check Vias ---\n const viaBucketList = this.viaBuckets.get(bucketKey)\n if (viaBucketList) {\n for (const viaInfo of viaBucketList) {\n if (checkedVias.has(viaInfo.viaId)) continue\n checkedVias.add(viaInfo.viaId)\n\n const route = viaInfo.parentRoute\n const viaPoint: Point2D = { x: viaInfo.x, y: viaInfo.y }\n\n const requiredSeparation = margin + route.viaDiameter / 2\n const requiredSeparationSq = requiredSeparation * requiredSeparation\n\n const distSq = computeDistSq(point, viaPoint) // Point-to-point distance\n\n if (distSq < requiredSeparationSq) {\n // Use < for strict clearance\n const routeName = route.connectionName\n const existing = conflictingRouteData.get(routeName)\n if (!existing || distSq < existing.minDistSq) {\n conflictingRouteData.set(routeName, {\n route,\n minDistSq: distSq,\n })\n }\n }\n }\n }\n }\n }\n\n // --- Convert map to results ---\n const results: Array<{\n conflictingRoute: HighDensityRoute\n distance: number\n }> = []\n for (const data of conflictingRouteData.values()) {\n // Distance reported is point-to-segment-centerline or point-to-via-center\n results.push({\n conflictingRoute: data.route,\n distance: Math.sqrt(data.minDistSq),\n })\n }\n\n return results\n }\n}\n","import { ObstacleSpatialHashIndex } from \"lib/data-structures/ObstacleTree\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport {\n HighDensityRoute,\n HighDensityRouteSpatialIndex,\n} from \"lib/data-structures/HighDensityRouteSpatialIndex\"\nimport { segmentToBoxMinDistance } from \"@tscircuit/math-utils\"\nimport { GraphicsObject } from \"graphics-debug\"\n\ninterface RouteSection {\n startIndex: number\n endIndex: number\n z: number\n points: HighDensityRoute[\"route\"]\n}\n\nexport class SingleRouteUselessViaRemovalSolver extends BaseSolver {\n obstacleSHI: ObstacleSpatialHashIndex\n hdRouteSHI: HighDensityRouteSpatialIndex\n unsimplifiedRoute: HighDensityRoute\n\n routeSections: Array<RouteSection>\n\n currentSectionIndex: number\n\n TRACE_THICKNESS = 0.15\n OBSTACLE_MARGIN = 0.1\n\n constructor(params: {\n obstacleSHI: ObstacleSpatialHashIndex\n hdRouteSHI: HighDensityRouteSpatialIndex\n unsimplifiedRoute: HighDensityRoute\n }) {\n super()\n this.currentSectionIndex = 1\n this.obstacleSHI = params.obstacleSHI\n this.hdRouteSHI = params.hdRouteSHI\n this.unsimplifiedRoute = params.unsimplifiedRoute\n\n this.routeSections = this.breakRouteIntoSections(this.unsimplifiedRoute)\n }\n\n breakRouteIntoSections(route: HighDensityRoute) {\n const routeSections: this[\"routeSections\"] = []\n const routePoints = route.route\n if (routePoints.length === 0) return []\n\n let currentSection = {\n startIndex: 0,\n endIndex: -1,\n z: routePoints[0].z,\n points: [routePoints[0]],\n }\n for (let i = 1; i < routePoints.length; i++) {\n if (routePoints[i].z === currentSection.z) {\n currentSection.points.push(routePoints[i])\n } else {\n currentSection.endIndex = i - 1\n routeSections.push(currentSection)\n currentSection = {\n startIndex: i,\n endIndex: -1,\n z: routePoints[i].z,\n points: [routePoints[i]],\n }\n }\n }\n currentSection.endIndex = routePoints.length - 1\n routeSections.push(currentSection)\n\n return routeSections\n }\n\n _step() {\n // We skip the first/last segment (since it's connected to the destination)\n if (this.currentSectionIndex >= this.routeSections.length - 1) {\n this.solved = true\n return\n }\n\n const prevSection = this.routeSections[this.currentSectionIndex - 1]\n const currentSection = this.routeSections[this.currentSectionIndex]\n const nextSection = this.routeSections[this.currentSectionIndex + 1]\n // console.log({\n // routeSections: this.routeSections,\n // prevSection,\n // currentSection,\n // nextSection,\n // })\n\n if (prevSection.z !== nextSection.z) {\n // We only remove vias where there is a middle section that can be\n // replaced by the layer of adjacent sections, if the adjacent sections\n // don't have matching layers, a more complex algo is needed\n this.currentSectionIndex++\n return\n }\n\n const targetZ = prevSection.z\n\n if (this.canSectionMoveToLayer({ currentSection, targetZ })) {\n currentSection.z = targetZ\n currentSection.points = currentSection.points.map((p) => ({\n ...p,\n z: targetZ,\n }))\n this.currentSectionIndex += 2\n return\n }\n\n this.currentSectionIndex++\n return\n }\n\n canSectionMoveToLayer({\n currentSection,\n targetZ,\n }: {\n currentSection: RouteSection\n targetZ: number\n }): boolean {\n // Evaluate if the section layer can be changed without hitting anything\n for (let i = 0; i < currentSection.points.length - 1; i++) {\n const A = { ...currentSection.points[i], z: targetZ }\n const B = { ...currentSection.points[i + 1], z: targetZ }\n\n const conflictingRoutes = this.hdRouteSHI.getConflictingRoutesForSegment(\n A,\n B,\n this.TRACE_THICKNESS,\n )\n\n for (const { conflictingRoute, distance } of conflictingRoutes) {\n if (\n conflictingRoute.connectionName ===\n this.unsimplifiedRoute.connectionName\n )\n continue\n // TODO connMap test\n if (distance < this.TRACE_THICKNESS + conflictingRoute.traceThickness) {\n return false\n }\n }\n\n const segmentBox = {\n centerX: (A.x + B.x) / 2,\n centerY: (A.y + B.y) / 2,\n width: Math.abs(A.x - B.x),\n height: Math.abs(A.y - B.y),\n }\n\n // Obstacle check\n const obstacles = this.obstacleSHI.getNodesInArea(\n segmentBox.centerX,\n segmentBox.centerY,\n segmentBox.width,\n segmentBox.height,\n )\n\n for (const obstacle of obstacles) {\n // TODO connMap test\n const distToObstacle = segmentToBoxMinDistance(A, B, obstacle)\n\n if (distToObstacle < this.TRACE_THICKNESS + this.OBSTACLE_MARGIN) {\n return false\n }\n }\n }\n\n return true\n }\n\n getOptimizedHdRoute(): HighDensityRoute {\n // TODO reconstruct the route from segments, we will need to recompute the\n // vias\n const route = this.routeSections.flatMap((section) => section.points)\n const vias: HighDensityRoute[\"vias\"] = []\n for (let i = 0; i < route.length - 1; i++) {\n if (route[i].z !== route[i + 1].z) {\n vias.push({\n x: route[i].x,\n y: route[i].y,\n })\n }\n }\n return {\n connectionName: this.unsimplifiedRoute.connectionName,\n route,\n traceThickness: this.unsimplifiedRoute.traceThickness,\n vias,\n viaDiameter: this.unsimplifiedRoute.viaDiameter,\n }\n }\n visualize(): GraphicsObject {\n const graphics: Required<GraphicsObject> = {\n circles: [],\n lines: [],\n points: [],\n rects: [],\n coordinateSystem: \"cartesian\",\n title: \"Single Route Useless Via Removal Solver\",\n }\n\n // Draw the sections, draw the active section in orange\n\n for (let i = 0; i < this.routeSections.length; i++) {\n const section = this.routeSections[i]\n graphics.lines.push({\n points: section.points,\n strokeWidth: this.TRACE_THICKNESS,\n strokeColor:\n i === this.currentSectionIndex\n ? \"orange\"\n : section.z === 0\n ? \"red\"\n : \"blue\",\n })\n }\n\n return graphics\n }\n}\n","import { ObstacleSpatialHashIndex } from \"lib/data-structures/ObstacleTree\"\nimport { SegmentTree } from \"lib/data-structures/SegmentTree\"\nimport { BaseSolver } from \"../BaseSolver\"\nimport { HighDensityRoute } from \"lib/types/high-density-types\"\nimport { Obstacle } from \"lib/types\"\nimport { GraphicsObject } from \"graphics-debug\"\nimport { mapZToLayerName } from \"lib/utils/mapZToLayerName\"\nimport { HighDensityRouteSpatialIndex } from \"lib/data-structures/HighDensityRouteSpatialIndex\"\nimport { SingleRouteUselessViaRemovalSolver } from \"./SingleRouteUselessViaRemovalSolver\"\n\nexport interface UselessViaRemovalSolverInput {\n unsimplifiedHdRoutes: HighDensityRoute[]\n obstacles: Obstacle[]\n colorMap: Record<string, string>\n layerCount: number\n}\n\nexport class UselessViaRemovalSolver extends BaseSolver {\n unsimplifiedHdRoutes: HighDensityRoute[]\n optimizedHdRoutes: HighDensityRoute[]\n unprocessedRoutes: HighDensityRoute[]\n\n activeSubSolver?: SingleRouteUselessViaRemovalSolver | null | undefined = null\n\n obstacleSHI: ObstacleSpatialHashIndex | null = null\n hdRouteSHI: HighDensityRouteSpatialIndex | null = null\n\n constructor(private input: UselessViaRemovalSolverInput) {\n super()\n this.unsimplifiedHdRoutes = input.unsimplifiedHdRoutes\n this.optimizedHdRoutes = []\n this.unprocessedRoutes = [...input.unsimplifiedHdRoutes]\n\n this.obstacleSHI = new ObstacleSpatialHashIndex(input.obstacles)\n this.hdRouteSHI = new HighDensityRouteSpatialIndex(\n this.unsimplifiedHdRoutes,\n )\n }\n\n _step() {\n if (this.activeSubSolver) {\n this.activeSubSolver.step()\n if (this.activeSubSolver.solved) {\n this.optimizedHdRoutes.push(this.activeSubSolver.getOptimizedHdRoute())\n this.activeSubSolver = null\n } else if (this.activeSubSolver.failed || this.activeSubSolver.error) {\n this.error = this.activeSubSolver.error\n this.failed = true\n }\n return\n }\n\n const unprocessedRoute = this.unprocessedRoutes.shift()\n if (!unprocessedRoute) {\n this.solved = true\n return\n }\n\n this.activeSubSolver = new SingleRouteUselessViaRemovalSolver({\n hdRouteSHI: this.hdRouteSHI!,\n obstacleSHI: this.obstacleSHI!,\n unsimplifiedRoute: unprocessedRoute,\n })\n }\n\n getOptimizedHdRoutes(): HighDensityRoute[] | null {\n return this.optimizedHdRoutes\n }\n\n visualize(): GraphicsObject {\n const visualization: Required<GraphicsObject> = {\n lines: [],\n points: [],\n rects: [],\n circles: [],\n coordinateSystem: \"cartesian\",\n title: \"Useless Via Removal Solver\",\n }\n\n // Display each optimized route\n for (const route of this.optimizedHdRoutes) {\n // Skip routes with no points\n if (route.route.length === 0) continue\n\n const color = this.input.colorMap[route.connectionName] || \"#888888\"\n\n // Add lines connecting route points on the same layer\n for (let i = 0; i < route.route.length - 1; i++) {\n const current = route.route[i]\n const next = route.route[i + 1]\n\n // Only draw segments that are on the same layer\n if (current.z === next.z) {\n visualization.lines.push({\n points: [\n { x: current.x, y: current.y },\n { x: next.x, y: next.y },\n ],\n strokeColor: current.z === 0 ? \"red\" : \"blue\",\n strokeWidth: route.traceThickness,\n label: `${route.connectionName} (z=${current.z})`,\n })\n }\n }\n\n // Add circles for vias\n for (const via of route.vias) {\n visualization.circles.push({\n center: { x: via.x, y: via.y },\n radius: route.viaDiameter / 2,\n fill: \"rgba(255, 0, 255, 0.5)\",\n label: `${route.connectionName} via`,\n })\n }\n }\n\n if (this.activeSubSolver) {\n visualization.lines.push(\n ...(this.activeSubSolver.visualize().lines ?? []),\n )\n }\n\n return visualization\n }\n}\n","import type { GraphicsObject, Line } from \"graphics-debug\"\nimport { combineVisualizations } from \"../utils/combineVisualizations\"\nimport type {\n CapacityMeshNode,\n SimpleRouteJson,\n SimplifiedPcbTrace,\n SimplifiedPcbTraces,\n TraceId,\n} from \"../types\"\nimport { BaseSolver } from \"./BaseSolver\"\nimport { CapacityMeshEdgeSolver } from \"./CapacityMeshSolver/CapacityMeshEdgeSolver\"\nimport { CapacityMeshNodeSolver } from \"./CapacityMeshSolver/CapacityMeshNodeSolver1\"\nimport { CapacityMeshNodeSolver2_NodeUnderObstacle } from \"./CapacityMeshSolver/CapacityMeshNodeSolver2_NodesUnderObstacles\"\nimport { CapacityPathingSolver } from \"./CapacityPathingSolver/CapacityPathingSolver\"\nimport { CapacityEdgeToPortSegmentSolver } from \"./CapacityMeshSolver/CapacityEdgeToPortSegmentSolver\"\nimport { getColorMap } from \"./colors\"\nimport { CapacitySegmentToPointSolver } from \"./CapacityMeshSolver/CapacitySegmentToPointSolver\"\nimport { HighDensitySolver } from \"./HighDensitySolver/HighDensitySolver\"\nimport type { NodePortSegment } from \"../types/capacity-edges-to-port-segments-types\"\nimport { CapacityPathingSolver2_AvoidLowCapacity } from \"./CapacityPathingSolver/CapacityPathingSolver2_AvoidLowCapacity\"\nimport { CapacityPathingSolver3_FlexibleNegativeCapacity_AvoidLowCapacity } from \"./CapacityPathingSolver/CapacityPathingSolver3_FlexibleNegativeCapacity_AvoidLowCapacity\"\nimport { CapacityPathingSolver4_FlexibleNegativeCapacity } from \"./CapacityPathingSolver/CapacityPathingSolver4_FlexibleNegativeCapacity_AvoidLowCapacity_FixedDistanceCost\"\nimport { ConnectivityMap } from \"circuit-json-to-connectivity-map\"\nimport { getConnectivityMapFromSimpleRouteJson } from \"lib/utils/getConnectivityMapFromSimpleRouteJson\"\nimport { CapacityNodeTargetMerger } from \"./CapacityNodeTargetMerger/CapacityNodeTargetMerger\"\nimport { CapacitySegmentPointOptimizer } from \"./CapacitySegmentPointOptimizer/CapacitySegmentPointOptimizer\"\nimport { calculateOptimalCapacityDepth } from \"../utils/getTunedTotalCapacity1\"\nimport { NetToPointPairsSolver } from \"./NetToPointPairsSolver/NetToPointPairsSolver\"\nimport { convertHdRouteToSimplifiedRoute } from \"lib/utils/convertHdRouteToSimplifiedRoute\"\nimport { mergeRouteSegments } from \"lib/utils/mergeRouteSegments\"\nimport { mapLayerNameToZ } from \"lib/utils/mapLayerNameToZ\"\nimport { MultipleHighDensityRouteStitchSolver } from \"./RouteStitchingSolver/MultipleHighDensityRouteStitchSolver\"\nimport { convertSrjToGraphicsObject } from \"tests/fixtures/convertSrjToGraphicsObject\"\nimport { UnravelMultiSectionSolver } from \"./UnravelSolver/UnravelMultiSectionSolver\"\nimport { CapacityPathingSolver5 } from \"./CapacityPathingSolver/CapacityPathingSolver5\"\nimport { StrawSolver } from \"./StrawSolver/StrawSolver\"\nimport { SingleLayerNodeMergerSolver } from \"./SingleLayerNodeMerger/SingleLayerNodeMergerSolver\"\nimport { CapacityNodeTargetMerger2 } from \"./CapacityNodeTargetMerger/CapacityNodeTargetMerger2\"\nimport { SingleSimplifiedPathSolver } from \"./SimplifiedPathSolver/SingleSimplifiedPathSolver\"\nimport { MultiSimplifiedPathSolver } from \"./SimplifiedPathSolver/MultiSimplifiedPathSolver\"\nimport {\n HighDensityIntraNodeRoute,\n HighDensityRoute,\n} from \"lib/types/high-density-types\"\nimport { CapacityMeshEdgeSolver2_NodeTreeOptimization } from \"./CapacityMeshSolver/CapacityMeshEdgeSolver2_NodeTreeOptimization\"\nimport { UselessViaRemovalSolver } from \"./UselessViaRemovalSolver/UselessViaRemovalSolver\"\n\ninterface CapacityMeshSolverOptions {\n capacityDepth?: number\n targetMinCapacity?: number\n}\n\ntype PipelineStep<T extends new (...args: any[]) => BaseSolver> = {\n solverName: string\n solverClass: T\n getConstructorParams: (\n instance: AutoroutingPipelineSolver,\n ) => ConstructorParameters<T>\n onSolved?: (instance: AutoroutingPipelineSolver) => void\n}\n\nfunction definePipelineStep<\n T extends new (\n ...args: any[]\n ) => BaseSolver,\n const P extends ConstructorParameters<T>,\n>(\n solverName: keyof AutoroutingPipelineSolver,\n solverClass: T,\n getConstructorParams: (instance: AutoroutingPipelineSolver) => P,\n opts: {\n onSolved?: (instance: AutoroutingPipelineSolver) => void\n } = {},\n): PipelineStep<T> {\n return {\n solverName,\n solverClass,\n getConstructorParams,\n onSolved: opts.onSolved,\n }\n}\n\nexport class AutoroutingPipelineSolver extends BaseSolver {\n netToPointPairsSolver?: NetToPointPairsSolver\n nodeSolver?: CapacityMeshNodeSolver\n nodeTargetMerger?: CapacityNodeTargetMerger\n edgeSolver?: CapacityMeshEdgeSolver\n pathingSolver?: CapacityPathingSolver\n edgeToPortSegmentSolver?: CapacityEdgeToPortSegmentSolver\n colorMap: Record<string, string>\n segmentToPointSolver?: CapacitySegmentToPointSolver\n unravelMultiSectionSolver?: UnravelMultiSectionSolver\n segmentToPointOptimizer?: CapacitySegmentPointOptimizer\n highDensityRouteSolver?: HighDensitySolver\n highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver\n singleLayerNodeMerger?: SingleLayerNodeMergerSolver\n strawSolver?: StrawSolver\n uselessViaRemovalSolver?: UselessViaRemovalSolver\n multiSimplifiedPathSolver?: MultiSimplifiedPathSolver\n\n startTimeOfPhase: Record<string, number>\n endTimeOfPhase: Record<string, number>\n timeSpentOnPhase: Record<string, number>\n\n activeSubSolver?: BaseSolver | null = null\n connMap: ConnectivityMap\n srjWithPointPairs?: SimpleRouteJson\n capacityNodes: CapacityMeshNode[] | null = null\n\n pipelineDef = [\n definePipelineStep(\n \"netToPointPairsSolver\",\n NetToPointPairsSolver,\n (cms) => [cms.srj, cms.colorMap],\n {\n onSolved: (cms) => {\n cms.srjWithPointPairs =\n cms.netToPointPairsSolver?.getNewSimpleRouteJson()\n cms.colorMap = getColorMap(cms.srjWithPointPairs!, this.connMap)\n cms.connMap = getConnectivityMapFromSimpleRouteJson(\n cms.srjWithPointPairs!,\n )\n },\n },\n ),\n definePipelineStep(\n \"nodeSolver\",\n CapacityMeshNodeSolver2_NodeUnderObstacle,\n (cms) => [\n cms.netToPointPairsSolver?.getNewSimpleRouteJson() || cms.srj,\n cms.opts,\n ],\n {\n onSolved: (cms) => {\n cms.capacityNodes = cms.nodeSolver?.finishedNodes!\n },\n },\n ),\n // definePipelineStep(\"nodeTargetMerger\", CapacityNodeTargetMerger, (cms) => [\n // cms.nodeSolver?.finishedNodes || [],\n // cms.srj.obstacles,\n // cms.connMap,\n // ]),\n // definePipelineStep(\"nodeTargetMerger\", CapacityNodeTargetMerger2, (cms) => [\n // cms.nodeSolver?.finishedNodes || [],\n // cms.srj.obstacles,\n // cms.connMap,\n // cms.colorMap,\n // cms.srj.connections,\n // ]),\n definePipelineStep(\n \"singleLayerNodeMerger\",\n SingleLayerNodeMergerSolver,\n (cms) => [cms.nodeSolver?.finishedNodes!],\n {\n onSolved: (cms) => {\n cms.capacityNodes = cms.singleLayerNodeMerger?.newNodes!\n },\n },\n ),\n definePipelineStep(\n \"strawSolver\",\n StrawSolver,\n (cms) => [{ nodes: cms.singleLayerNodeMerger?.newNodes! }],\n {\n onSolved: (cms) => {\n cms.capacityNodes = cms.strawSolver?.getResultNodes()!\n },\n },\n ),\n definePipelineStep(\n \"edgeSolver\",\n CapacityMeshEdgeSolver2_NodeTreeOptimization,\n (cms) => [cms.capacityNodes!],\n ),\n definePipelineStep(\"pathingSolver\", CapacityPathingSolver5, (cms) => [\n {\n simpleRouteJson: cms.srjWithPointPairs!,\n nodes: cms.capacityNodes!,\n edges: cms.edgeSolver?.edges || [],\n colorMap: cms.colorMap,\n hyperParameters: {\n MAX_CAPACITY_FACTOR: 1,\n },\n },\n ]),\n definePipelineStep(\n \"edgeToPortSegmentSolver\",\n CapacityEdgeToPortSegmentSolver,\n (cms) => [\n {\n nodes: cms.capacityNodes!,\n edges: cms.edgeSolver?.edges || [],\n capacityPaths: cms.pathingSolver?.getCapacityPaths() || [],\n colorMap: cms.colorMap,\n },\n ],\n ),\n definePipelineStep(\n \"segmentToPointSolver\",\n CapacitySegmentToPointSolver,\n (cms) => {\n const allSegments: NodePortSegment[] = []\n if (cms.edgeToPortSegmentSolver?.nodePortSegments) {\n cms.edgeToPortSegmentSolver.nodePortSegments.forEach((segs) => {\n allSegments.push(...segs)\n })\n }\n return [\n {\n segments: allSegments,\n colorMap: cms.colorMap,\n nodes: cms.capacityNodes!,\n },\n ]\n },\n ),\n // definePipelineStep(\n // \"segmentToPointOptimizer\",\n // CapacitySegmentPointOptimizer,\n // (cms) => [\n // {\n // assignedSegments: cms.segmentToPointSolver?.solvedSegments || [],\n // colorMap: cms.colorMap,\n // nodes: cms.nodeTargetMerger?.newNodes || [],\n // },\n // ],\n // ),\n definePipelineStep(\n \"unravelMultiSectionSolver\",\n UnravelMultiSectionSolver,\n (cms) => [\n {\n assignedSegments: cms.segmentToPointSolver?.solvedSegments || [],\n colorMap: cms.colorMap,\n nodes: cms.capacityNodes!,\n },\n ],\n ),\n definePipelineStep(\"highDensityRouteSolver\", HighDensitySolver, (cms) => [\n {\n nodePortPoints:\n cms.unravelMultiSectionSolver?.getNodesWithPortPoints() ??\n cms.segmentToPointOptimizer?.getNodesWithPortPoints() ??\n [],\n colorMap: cms.colorMap,\n connMap: cms.connMap,\n },\n ]),\n definePipelineStep(\n \"highDensityStitchSolver\",\n MultipleHighDensityRouteStitchSolver,\n (cms) => [\n {\n connections: cms.srjWithPointPairs!.connections,\n hdRoutes: cms.highDensityRouteSolver!.routes,\n layerCount: cms.srj.layerCount,\n },\n ],\n ),\n definePipelineStep(\n \"uselessViaRemovalSolver\",\n UselessViaRemovalSolver,\n (cms) => [\n {\n unsimplifiedHdRoutes: cms.highDensityStitchSolver!.mergedHdRoutes,\n obstacles: cms.srj.obstacles,\n colorMap: cms.colorMap,\n layerCount: cms.srj.layerCount,\n },\n ],\n ),\n definePipelineStep(\n \"multiSimplifiedPathSolver\",\n MultiSimplifiedPathSolver,\n (cms) => [\n {\n unsimplifiedHdRoutes:\n cms.uselessViaRemovalSolver?.getOptimizedHdRoutes() ||\n cms.highDensityStitchSolver!.mergedHdRoutes,\n obstacles: cms.srj.obstacles,\n connMap: cms.connMap,\n colorMap: cms.colorMap,\n },\n ],\n ),\n ]\n\n constructor(\n public srj: SimpleRouteJson,\n public opts: CapacityMeshSolverOptions = {},\n ) {\n super()\n this.MAX_ITERATIONS = 1e6\n\n // If capacityDepth is not provided, calculate it automatically\n if (opts.capacityDepth === undefined) {\n // Calculate max width/height from bounds for initial node size\n const boundsWidth = srj.bounds.maxX - srj.bounds.minX\n const boundsHeight = srj.bounds.maxY - srj.bounds.minY\n const maxWidthHeight = Math.max(boundsWidth, boundsHeight)\n\n // Use the calculateOptimalCapacityDepth function to determine the right depth\n const targetMinCapacity = opts.targetMinCapacity ?? 0.5\n opts.capacityDepth = calculateOptimalCapacityDepth(\n maxWidthHeight,\n targetMinCapacity,\n )\n }\n\n this.connMap = getConnectivityMapFromSimpleRouteJson(srj)\n this.colorMap = getColorMap(srj, this.connMap)\n this.startTimeOfPhase = {}\n this.endTimeOfPhase = {}\n this.timeSpentOnPhase = {}\n }\n\n currentPipelineStepIndex = 0\n _step() {\n const pipelineStepDef = this.pipelineDef[this.currentPipelineStepIndex]\n if (!pipelineStepDef) {\n this.solved = true\n return\n }\n\n if (this.activeSubSolver) {\n this.activeSubSolver.step()\n if (this.activeSubSolver.solved) {\n this.endTimeOfPhase[pipelineStepDef.solverName] = performance.now()\n this.timeSpentOnPhase[pipelineStepDef.solverName] =\n this.endTimeOfPhase[pipelineStepDef.solverName] -\n this.startTimeOfPhase[pipelineStepDef.solverName]\n pipelineStepDef.onSolved?.(this)\n this.activeSubSolver = null\n this.currentPipelineStepIndex++\n } else if (this.activeSubSolver.failed) {\n this.error = this.activeSubSolver?.error\n this.failed = true\n this.activeSubSolver = null\n }\n return\n }\n\n const constructorParams = pipelineStepDef.getConstructorParams(this)\n // @ts-ignore\n this.activeSubSolver = new pipelineStepDef.solverClass(...constructorParams)\n ;(this as any)[pipelineStepDef.solverName] = this.activeSubSolver\n this.timeSpentOnPhase[pipelineStepDef.solverName] = 0\n this.startTimeOfPhase[pipelineStepDef.solverName] = performance.now()\n }\n\n solveUntilPhase(phase: string) {\n while (this.getCurrentPhase() !== phase) {\n this.step()\n }\n }\n\n getCurrentPhase(): string {\n return this.pipelineDef[this.currentPipelineStepIndex]?.solverName ?? \"none\"\n }\n\n visualize(): GraphicsObject {\n if (!this.solved && this.activeSubSolver)\n return this.activeSubSolver.visualize()\n const netToPPSolver = this.netToPointPairsSolver?.visualize()\n const nodeViz = this.nodeSolver?.visualize()\n const nodeTargetMergerViz = this.nodeTargetMerger?.visualize()\n const singleLayerNodeMergerViz = this.singleLayerNodeMerger?.visualize()\n const strawSolverViz = this.strawSolver?.visualize()\n const edgeViz = this.edgeSolver?.visualize()\n const pathingViz = this.pathingSolver?.visualize()\n const edgeToPortSegmentViz = this.edgeToPortSegmentSolver?.visualize()\n const segmentToPointViz = this.segmentToPointSolver?.visualize()\n const segmentOptimizationViz =\n this.unravelMultiSectionSolver?.visualize() ??\n this.segmentToPointOptimizer?.visualize()\n const highDensityViz = this.highDensityRouteSolver?.visualize()\n const highDensityStitchViz = this.highDensityStitchSolver?.visualize()\n const uselessViaRemovalViz = this.uselessViaRemovalSolver?.visualize()\n const simplifiedPathSolverViz = this.multiSimplifiedPathSolver?.visualize()\n const problemViz = {\n points: [\n ...this.srj.connections.flatMap((c) =>\n c.pointsToConnect.map((p) => ({\n ...p,\n label: `${c.name} ${p.pcb_port_id ?? \"\"}`,\n })),\n ),\n ],\n rects: [\n ...(this.srj.obstacles ?? []).map((o) => ({\n ...o,\n fill: o.layers?.includes(\"top\")\n ? \"rgba(255,0,0,0.25)\"\n : o.layers?.includes(\"bottom\")\n ? \"rgba(0,0,255,0.25)\"\n : \"rgba(255,0,0,0.25)\",\n label: o.layers?.join(\", \"),\n })),\n ],\n lines: [\n {\n points: [\n // Add five points representing the bounds of the PCB\n {\n x: this.srj.bounds?.minX ?? -50,\n y: this.srj.bounds?.minY ?? -50,\n },\n { x: this.srj.bounds?.maxX ?? 50, y: this.srj.bounds?.minY ?? -50 },\n { x: this.srj.bounds?.maxX ?? 50, y: this.srj.bounds?.maxY ?? 50 },\n { x: this.srj.bounds?.minX ?? -50, y: this.srj.bounds?.maxY ?? 50 },\n {\n x: this.srj.bounds?.minX ?? -50,\n y: this.srj.bounds?.minY ?? -50,\n }, // Close the rectangle\n ],\n strokeColor: \"rgba(255,0,0,0.25)\",\n },\n ],\n } as GraphicsObject\n const visualizations = [\n problemViz,\n netToPPSolver,\n nodeViz,\n nodeTargetMergerViz,\n singleLayerNodeMergerViz,\n strawSolverViz,\n edgeViz,\n pathingViz,\n edgeToPortSegmentViz,\n segmentToPointViz,\n segmentOptimizationViz,\n highDensityViz ? combineVisualizations(problemViz, highDensityViz) : null,\n highDensityStitchViz,\n uselessViaRemovalViz,\n simplifiedPathSolverViz,\n this.solved\n ? combineVisualizations(\n problemViz,\n convertSrjToGraphicsObject(this.getOutputSimpleRouteJson()),\n )\n : null,\n ].filter(Boolean) as GraphicsObject[]\n // return visualizations[visualizations.length - 1]\n return combineVisualizations(...visualizations)\n }\n\n /**\n * A lightweight version of the visualize method that can be used to stream\n * progress\n *\n * We return the most relevant graphic for the stage:\n * 1. netToPointPairs output\n * 2. Capacity Planning Output\n * 3. High Density Route Solver Output, max 200 lines\n */\n preview(): GraphicsObject {\n if (this.highDensityRouteSolver) {\n const lines: Line[] = []\n for (let i = this.highDensityRouteSolver.routes.length - 1; i >= 0; i--) {\n const route = this.highDensityRouteSolver.routes[i]\n lines.push({\n points: route.route.map((n) => ({\n x: n.x,\n y: n.y,\n })),\n strokeColor: this.colorMap[route.connectionName],\n })\n if (lines.length > 200) break\n }\n return { lines }\n }\n\n if (this.pathingSolver) {\n const lines: Line[] = []\n for (const connection of this.pathingSolver.connectionsWithNodes) {\n if (!connection.path) continue\n lines.push({\n points: connection.path.map((n) => ({\n x: n.center.x,\n y: n.center.y,\n })),\n strokeColor: this.colorMap[connection.connection.name],\n })\n }\n return { lines }\n }\n\n // This output is good as-is\n if (this.netToPointPairsSolver) {\n return this.netToPointPairsSolver?.visualize()\n }\n\n return {}\n }\n\n /**\n * Get original connection name from connection name with MST suffix\n * @param mstConnectionName The MST-suffixed connection name (e.g. \"connection1_mst0\")\n * @returns The original connection name (e.g. \"connection1\")\n */\n private getOriginalConnectionName(mstConnectionName: string): string {\n // MST connections are named like \"connection_mst0\", so extract the original name\n const match = mstConnectionName.match(/^(.+?)_mst\\d+$/)\n return match ? match[1] : mstConnectionName\n }\n\n _getOutputHdRoutes(): HighDensityRoute[] {\n return (\n this.multiSimplifiedPathSolver?.simplifiedHdRoutes ??\n this.uselessViaRemovalSolver?.getOptimizedHdRoutes() ??\n this.highDensityStitchSolver!.mergedHdRoutes\n )\n }\n\n /**\n * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces\n */\n getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces {\n if (!this.solved || !this.highDensityRouteSolver) {\n throw new Error(\"Cannot get output before solving is complete\")\n }\n\n const traces: SimplifiedPcbTraces = []\n const allHdRoutes = this._getOutputHdRoutes()\n\n for (const connection of this.netToPointPairsSolver?.newConnections ?? []) {\n const netConnection = this.srj.connections.find(\n (c) => c.name === connection.netConnectionName,\n )\n\n // Find all the hdRoutes that correspond to this connection\n const hdRoutes = allHdRoutes.filter(\n (r) => r.connectionName === connection.name,\n )\n\n for (let i = 0; i < hdRoutes.length; i++) {\n const hdRoute = hdRoutes[i]\n const simplifiedPcbTrace: SimplifiedPcbTrace = {\n type: \"pcb_trace\",\n pcb_trace_id: `${connection.name}_${i}`,\n connection_name: this.getOriginalConnectionName(connection.name),\n route: convertHdRouteToSimplifiedRoute(hdRoute, this.srj.layerCount),\n }\n\n traces.push(simplifiedPcbTrace)\n }\n }\n\n return traces\n }\n\n getOutputSimpleRouteJson(): SimpleRouteJson {\n return {\n ...this.srj,\n traces: this.getOutputSimplifiedPcbTraces(),\n }\n }\n}\n\n/** @deprecated Use AutoroutingPipelineSolver instead */\nexport const CapacityMeshSolver = AutoroutingPipelineSolver\nexport type CapacityMeshSolver = AutoroutingPipelineSolver\n"],"mappings":"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","names":["t","e","t","t","_isNativeReflectConstruct","_wrapNativeSuper","t","PolishedError","pxtoFactory","reduceHexValue","isRgb","isRgba","isHsl","isHsla","distance","clamp","node","y_1","y_2","points","intersections","distance","distance","CQUnit","EPSILON","distance","distance","layerName","segmentPoints","nodeId","distance","EPSILON","pointToSegmentDistance","distance","orientation","onSegment","distance","tailPoint","path45","getSegmentBounds","distance"]}
|